dvander@45: /* vim: set ts=4 sw=4 tw=99 et: dvander@45: * dvander@45: * Copyright (C) 2012 David Anderson dvander@45: * dvander@45: * This file is part of JITCraft. dvander@45: * dvander@45: * JITCraft is free software: you can redistribute it and/or modify it under dvander@45: * the terms of the GNU General Public License as published by the Free dvander@45: * Software Foundation, either version 3 of the License, or (at your option) dvander@45: * any later version. dvander@45: * dvander@45: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@45: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@45: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@45: * dvander@45: * You should have received a copy of the GNU General Public License along with dvander@45: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@45: */ dvander@45: #ifndef _include_jc_object_visitor_h_ dvander@45: #define _include_jc_object_visitor_h_ dvander@45: dvander@45: #include "Objects.h" dvander@45: #include "Types.h" dvander@45: #include "FixedArray.h" dvander@45: #include "Code.h" dvander@45: #include "Reference.h" dvander@45: #include "Modules.h" dvander@45: #include "Functions.h" dvander@45: #include "Array.h" dvander@54: #include "Strings.h" dvander@85: #include "Environments.h" dvander@146: #include "Structures.h" dvander@168: #include "Box.h" dvander@45: dvander@59: namespace ke { dvander@45: dvander@45: // An ObjectVisitor is used for traversing object references in the heap. Since dvander@45: // this pattern must be lightning fast, we avoid virtual dispatch by forcing dvander@45: // visitors to compose themselves with the visiting logic. dvander@45: template dvander@45: class ObjectVisitor : public T dvander@45: { dvander@45: private: dvander@45: void visitField(Object *obj, size_t offset) { dvander@45: this->visit(reinterpret_cast(Address(obj) + offset)); dvander@45: } dvander@45: dvander@45: size_t iterateType(Object *obj) { dvander@238: visitField(obj, Type::offsetOfRoot()); dvander@195: return sizeof(Type); dvander@195: } dvander@195: dvander@233: size_t iterateEnumType(Object *obj) { dvander@233: visitField(obj, EnumType::offsetOfName()); dvander@233: return sizeof(EnumType); dvander@233: } dvander@233: dvander@222: size_t iterateReferenceType(Object *obj) { dvander@222: iterateType(obj); dvander@222: visitField(obj, ReferenceType::offsetOfContained()); dvander@222: return sizeof(ReferenceType); dvander@222: } dvander@222: dvander@209: size_t iterateArrayType(Object *obj) { dvander@209: iterateType(obj); dvander@209: visitField(obj, ArrayType::offsetOfContained()); dvander@209: visitField(obj, ArrayType::offsetOfNewMap()); dvander@209: return sizeof(ArrayType); dvander@209: } dvander@209: dvander@195: size_t iterateStructType(Object *obj) { dvander@209: iterateType(obj); dvander@195: visitField(obj, StructType::offsetOfFields()); dvander@195: visitField(obj, StructType::offsetOfNewMap()); dvander@233: visitField(obj, StructType::offsetOfName()); dvander@195: return sizeof(StructType); dvander@195: } dvander@195: dvander@195: size_t iterateFunctionType(Object *obj) { dvander@209: iterateType(obj); dvander@195: visitField(obj, FunctionType::offsetOfReturnType()); dvander@195: visitField(obj, FunctionType::offsetOfParameters()); dvander@195: visitField(obj, FunctionType::offsetOfDefaults()); dvander@233: visitField(obj, FunctionType::offsetOfName()); dvander@195: return sizeof(FunctionType); dvander@45: } dvander@45: dvander@45: size_t iterateFixedArray(FixedArray *array) { dvander@45: unsigned length = array->length(); dvander@45: Object **ptr = reinterpret_cast(array + 1); dvander@45: for (unsigned i = 0; i < length; i++) dvander@45: this->visit(ptr + i); dvander@161: return array->objSize(); dvander@45: } dvander@45: dvander@45: size_t iterateByteArray(ByteArray *array) { dvander@161: return array->objSize(); dvander@45: } dvander@45: dvander@45: size_t iterateCode(Object *obj) { dvander@45: visitField(obj, Code::offsetOfModule()); dvander@45: visitField(obj, Code::offsetOfBytecode()); dvander@45: visitField(obj, Code::offsetOfLocals()); dvander@45: visitField(obj, Code::offsetOfObjects()); dvander@53: visitField(obj, Code::offsetOfSafepoints()); dvander@70: visitField(obj, Code::offsetOfSourceMap()); dvander@195: visitField(obj, Code::offsetOfStrings()); dvander@45: return sizeof(Code); dvander@45: } dvander@45: dvander@45: size_t iterateReference(Object *obj) { dvander@45: visitField(obj, Reference::offsetOfBase()); dvander@45: return sizeof(Reference); dvander@45: } dvander@45: dvander@45: size_t iterateModule(Object *obj) { dvander@70: visitField(obj, Module::offsetOfFile()); dvander@195: visitField(obj, Module::offsetOfGlobals()); dvander@85: visitField(obj, Module::offsetOfCode()); dvander@45: return sizeof(Module); dvander@45: } dvander@45: dvander@45: size_t iterateFunction(Object *obj) { dvander@52: visitField(obj, Function::offsetOfCode()); dvander@52: visitField(obj, Function::offsetOfType()); dvander@68: visitField(obj, Function::offsetOfName()); dvander@45: return sizeof(Function); dvander@45: } dvander@45: dvander@146: size_t iterateDescriptor(Object *obj) { dvander@146: visitField(obj, Descriptor::offsetOfName()); dvander@146: visitField(obj, Descriptor::offsetOfType()); dvander@146: return sizeof(Descriptor); dvander@146: } dvander@146: dvander@68: size_t iterateNative(Object *obj) { dvander@68: visitField(obj, Native::offsetOfType()); dvander@68: return sizeof(Native); dvander@68: } dvander@68: dvander@54: size_t iterateString(Object *obj) { dvander@161: return String::cast(obj)->objSize(); dvander@54: } dvander@54: dvander@45: size_t iterateArray(Array *array, ArrayMap *map) { dvander@234: if (!map->type()->hasInlineElements()) dvander@188: visitField(array, Array::offsetOfElements()); dvander@188: return array->objSize(map); dvander@45: } dvander@45: dvander@247: size_t iterateDependentArray(Object *array) { dvander@247: visitField(array, DependentArray::offsetOfRoot()); dvander@247: return sizeof(DependentArray); dvander@247: } dvander@247: dvander@168: size_t iterateBox(Box *obj) { dvander@168: visitField(obj, Box::offsetOfType()); dvander@168: if (obj->type()->isTraceable()) dvander@168: visitField(obj, Box::offsetOfObj()); dvander@168: return sizeof(Box); dvander@168: } dvander@168: dvander@45: size_t iterateArrayMap(ArrayMap *map) { dvander@52: visitField(map, ArrayMap::offsetOfType()); dvander@45: return sizeof(ArrayMap); dvander@45: } dvander@45: dvander@85: size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) { dvander@85: unsigned length = env->length(); dvander@85: EnvironmentSlotDescriptor *desc = env->slots(); dvander@85: for (unsigned i = 0; i < length; i++) dvander@85: this->visit(desc->type.addr()); dvander@161: return env->objSize(); dvander@85: } dvander@85: dvander@85: size_t iterateEnvironmentMap(EnvironmentMap *map) { dvander@85: visitField(map, EnvironmentMap::offsetOfSlots()); dvander@161: return map->objSize(); dvander@85: } dvander@85: dvander@147: size_t iterateStructMap(StructMap *map) { dvander@147: visitField(map, StructMap::offsetOfType()); dvander@153: visitField(map, StructMap::offsetOfComposed()); dvander@161: return map->objSize(); dvander@147: } dvander@147: dvander@85: size_t iterateEnvironment(Environment *env) { dvander@85: EnvironmentMap *map = env->map(); dvander@85: const unsigned *offsets = map->traceOffsets(); dvander@85: unsigned noffsets = map->traceOffsetCount(); dvander@85: for (unsigned i = 0; i < noffsets; i++) dvander@85: visitField(env, Environment::offsetOfSlotOffset(offsets[i])); dvander@161: return env->objSize(); dvander@85: } dvander@85: dvander@147: size_t iterateStruct(Struct *obj) { dvander@147: StructMap *map = obj->map(); dvander@147: const unsigned *offsets = map->traceOffsets(); dvander@147: unsigned noffsets = map->traceOffsetCount(); dvander@147: for (unsigned i = 0; i < noffsets; i++) dvander@147: visitField(obj, Struct::offsetOfSlotOffset(offsets[i])); dvander@161: return obj->objSize(); dvander@147: } dvander@147: dvander@161: private: dvander@161: size_t iterateObject(Object *obj) { dvander@52: visitField(obj, Object::offsetOfMap()); dvander@52: return iterate(obj, obj->map()); dvander@52: } dvander@52: dvander@161: size_t iterateObject(Object *obj, Map *map) { dvander@45: switch (map->kind()) { dvander@45: case MapKind_Type: dvander@45: return iterateType(obj); dvander@45: dvander@222: case MapKind_ReferenceType: dvander@222: return iterateReferenceType(obj); dvander@222: dvander@209: case MapKind_ArrayType: dvander@209: return iterateArrayType(obj); dvander@209: dvander@233: case MapKind_EnumType: dvander@233: return iterateEnumType(obj); dvander@233: dvander@195: case MapKind_FunctionType: dvander@195: return iterateFunctionType(obj); dvander@195: dvander@195: case MapKind_StructType: dvander@195: return iterateStructType(obj); dvander@195: dvander@45: case MapKind_FixedArray: dvander@45: return iterateFixedArray(FixedArray::cast(obj)); dvander@45: dvander@45: case MapKind_ByteArray: dvander@54: return iterateByteArray(ByteArray::cast(obj)); dvander@45: dvander@45: case MapKind_Code: dvander@45: return iterateCode(obj); dvander@45: dvander@45: case MapKind_Reference: dvander@45: return iterateReference(obj); dvander@45: dvander@45: case MapKind_Module: dvander@45: return iterateModule(obj); dvander@45: dvander@45: case MapKind_Function: dvander@45: return iterateFunction(obj); dvander@45: dvander@146: case MapKind_Descriptor: dvander@146: return iterateDescriptor(obj); dvander@146: dvander@54: case MapKind_String: dvander@54: return iterateString(obj); dvander@54: dvander@45: case MapKind_Array: dvander@247: return iterateArray(Array::cast(obj), ArrayMap::cast(map)); dvander@247: dvander@247: case MapKind_DependentArray: dvander@247: return iterateDependentArray(obj); dvander@45: dvander@168: case MapKind_Box: dvander@168: return iterateBox(Box::cast(obj)); dvander@168: dvander@147: case MapKind_Struct: dvander@147: return iterateStruct(Struct::cast(obj)); dvander@147: dvander@85: case MapKind_EnvironmentSlotDescriptorArray: dvander@85: return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj)); dvander@85: dvander@85: case MapKind_Environment: dvander@85: return iterateEnvironment(Environment::cast(obj)); dvander@85: dvander@68: case MapKind_Native: dvander@68: return iterateNative(obj); dvander@68: dvander@45: case MapKind_MetaArray: dvander@52: return iterateArrayMap(ArrayMap::cast(obj)); dvander@45: dvander@85: case MapKind_MetaEnvironment: dvander@85: return iterateEnvironmentMap(EnvironmentMap::cast(obj)); dvander@85: dvander@147: case MapKind_MetaStruct: dvander@147: return iterateStructMap(StructMap::cast(obj)); dvander@147: dvander@45: default: dvander@45: assert(map->kind() == MapKind_Meta); dvander@52: return sizeof(Map); dvander@45: } dvander@45: } dvander@161: dvander@161: public: dvander@161: size_t iterate(Object *obj) { dvander@161: return Align(iterateObject(obj), kObjectAlignment); dvander@161: } dvander@161: dvander@161: size_t iterate(Object *obj, Map *map) { dvander@161: return Align(iterateObject(obj, map), kObjectAlignment); dvander@161: } dvander@45: }; dvander@45: dvander@53: static inline size_t dvander@161: SizeOfObjectRaw(Object *obj, Map *map) dvander@53: { dvander@53: switch (map->kind()) { dvander@53: case MapKind_Type: dvander@53: return sizeof(Type); dvander@53: dvander@222: case MapKind_ReferenceType: dvander@222: return sizeof(ReferenceType); dvander@222: dvander@209: case MapKind_ArrayType: dvander@209: return sizeof(ArrayType); dvander@209: dvander@233: case MapKind_EnumType: dvander@233: return sizeof(EnumType); dvander@233: dvander@195: case MapKind_FunctionType: dvander@195: return sizeof(FunctionType); dvander@195: dvander@195: case MapKind_StructType: dvander@195: return sizeof(StructType); dvander@195: dvander@53: case MapKind_FixedArray: dvander@161: return FixedArray::cast(obj)->objSize(); dvander@53: dvander@53: case MapKind_ByteArray: dvander@161: return ByteArray::cast(obj)->objSize(); dvander@53: dvander@53: case MapKind_Code: dvander@53: return sizeof(Code); dvander@53: dvander@53: case MapKind_Reference: dvander@53: return sizeof(Reference); dvander@53: dvander@53: case MapKind_Module: dvander@53: return sizeof(Module); dvander@53: dvander@146: case MapKind_Descriptor: dvander@146: return sizeof(Descriptor); dvander@146: dvander@53: case MapKind_Function: dvander@53: return sizeof(Function); dvander@53: dvander@54: case MapKind_String: dvander@161: return String::cast(obj)->objSize(); dvander@54: dvander@68: case MapKind_Native: dvander@68: return sizeof(Native); dvander@68: dvander@53: case MapKind_Array: dvander@247: return Array::cast(obj)->objSize(ArrayMap::cast(map)); dvander@247: dvander@247: case MapKind_DependentArray: dvander@248: return sizeof(DependentArray); dvander@53: dvander@168: case MapKind_Box: dvander@168: return sizeof(Box); dvander@168: dvander@147: case MapKind_Struct: dvander@161: return Struct::cast(obj)->objSize(); dvander@147: dvander@85: case MapKind_EnvironmentSlotDescriptorArray: dvander@161: return EnvironmentSlotDescriptorArray::cast(obj)->objSize(); dvander@85: dvander@85: case MapKind_Environment: dvander@161: return Environment::cast(obj)->objSize(); dvander@85: dvander@53: case MapKind_MetaArray: dvander@53: return sizeof(ArrayMap); dvander@53: dvander@85: case MapKind_MetaEnvironment: dvander@161: return EnvironmentMap::cast(obj)->objSize(); dvander@85: dvander@147: case MapKind_MetaStruct: dvander@161: return StructMap::cast(obj)->objSize(); dvander@147: dvander@53: case MapKind_FreeRegion: dvander@53: return *reinterpret_cast(reinterpret_cast
(obj + 1)); dvander@53: dvander@53: default: dvander@53: assert(map->kind() == MapKind_Meta); dvander@53: return sizeof(Map); dvander@53: } dvander@53: } dvander@53: dvander@161: static inline size_t dvander@161: SizeOfObject(Object *obj, Map *map) dvander@161: { dvander@161: return Align(SizeOfObjectRaw(obj, map), kObjectAlignment); dvander@161: } dvander@161: dvander@53: class ObjectSizeEvaluator dvander@53: { dvander@53: public: dvander@53: size_t operator()(Object *obj, Map *map) { dvander@53: return SizeOfObject(obj, map); dvander@53: } dvander@53: }; dvander@53: dvander@45: } dvander@45: dvander@45: #endif // _include_jc_object_visitor_h_