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@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@45: visitField(obj, Type::offsetOfContained()); dvander@45: visitField(obj, Type::offsetOfReturnType()); dvander@45: visitField(obj, Type::offsetOfParameters()); dvander@54: visitField(obj, Type::offsetOfTag()); dvander@45: return sizeof(Type); 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@45: return FixedArray::SizeFor(length); dvander@45: } dvander@45: dvander@45: size_t iterateByteArray(ByteArray *array) { dvander@45: return ByteArray::SizeFor(array->length()); 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@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@45: visitField(obj, Module::offsetOfFunctions()); dvander@64: visitField(obj, Module::offsetOfPublics()); dvander@68: visitField(obj, Module::offsetOfNatives()); dvander@70: visitField(obj, Module::offsetOfFile()); dvander@85: visitField(obj, Module::offsetOfEnvironment()); 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@68: size_t iterateNative(Object *obj) { dvander@68: visitField(obj, Native::offsetOfType()); dvander@68: visitField(obj, Native::offsetOfName()); dvander@68: return sizeof(Native); dvander@68: } dvander@68: dvander@54: size_t iterateString(Object *obj) { dvander@54: return String::SizeFor(String::cast(obj)->length()); dvander@54: } dvander@54: dvander@45: size_t iterateArray(Array *array, ArrayMap *map) { dvander@72: assert(map->type()->isArray()); dvander@72: if (map->contained()) { dvander@45: unsigned length = array->nelements(); dvander@45: Object **vec = array->objVec(); dvander@45: for (unsigned i = 0; i < length; i++) dvander@45: this->visit(vec + i); dvander@45: } dvander@45: return Array::SizeOf(array); dvander@45: } dvander@45: dvander@45: size_t iterateArrayMap(ArrayMap *map) { dvander@52: visitField(map, ArrayMap::offsetOfType()); dvander@52: visitField(map, ArrayMap::offsetOfContained()); 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@85: return env->size(); dvander@85: } dvander@85: dvander@85: size_t iterateEnvironmentMap(EnvironmentMap *map) { dvander@85: visitField(map, EnvironmentMap::offsetOfSlots()); dvander@85: return map->size(); dvander@85: } dvander@85: 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@85: return env->size(); dvander@85: } dvander@85: dvander@45: public: dvander@52: size_t iterate(Object *obj) { dvander@52: visitField(obj, Object::offsetOfMap()); dvander@52: return iterate(obj, obj->map()); dvander@52: } dvander@52: dvander@45: size_t iterate(Object *obj, Map *map) { dvander@45: switch (map->kind()) { dvander@45: case MapKind_Type: dvander@45: return iterateType(obj); dvander@45: 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@54: case MapKind_String: dvander@54: return iterateString(obj); dvander@54: dvander@45: case MapKind_Array: dvander@53: return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment); dvander@45: 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@45: default: dvander@45: assert(map->kind() == MapKind_Meta); dvander@52: return sizeof(Map); dvander@45: } dvander@45: } dvander@45: }; dvander@45: dvander@53: static inline size_t dvander@53: SizeOfObject(Object *obj, Map *map) dvander@53: { dvander@53: switch (map->kind()) { dvander@53: case MapKind_Type: dvander@53: return sizeof(Type); dvander@53: dvander@53: case MapKind_FixedArray: dvander@53: return FixedArray::SizeFor(FixedArray::cast(obj)->length()); dvander@53: dvander@53: case MapKind_ByteArray: dvander@54: return ByteArray::SizeFor(ByteArray::cast(obj)->length()); 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@53: case MapKind_Function: dvander@53: return sizeof(Function); dvander@53: dvander@54: case MapKind_String: dvander@54: return String::SizeFor(String::cast(obj)->length()); dvander@54: dvander@68: case MapKind_Native: dvander@68: return sizeof(Native); dvander@68: dvander@53: case MapKind_Array: dvander@53: return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment); dvander@53: dvander@85: case MapKind_EnvironmentSlotDescriptorArray: dvander@85: return EnvironmentSlotDescriptorArray::cast(obj)->size(); dvander@85: dvander@85: case MapKind_Environment: dvander@85: return Environment::cast(obj)->size(); dvander@85: dvander@53: case MapKind_MetaArray: dvander@53: return sizeof(ArrayMap); dvander@53: dvander@85: case MapKind_MetaEnvironment: dvander@85: return EnvironmentMap::cast(obj)->size(); dvander@85: 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@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_