src/ObjectVisitor.h
author David Anderson <dvander@alliedmods.net>
Sat Dec 22 23:18:57 2012 -0800 (2012-12-22)
changeset 233 bbb498ccb4ac
parent 222 0cde1379b29f
child 234 26e3035cdffc
permissions -rw-r--r--
Re-add enum support.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #ifndef _include_jc_object_visitor_h_
    20 #define _include_jc_object_visitor_h_
    21 
    22 #include "Objects.h"
    23 #include "Types.h"
    24 #include "FixedArray.h"
    25 #include "Code.h"
    26 #include "Reference.h"
    27 #include "Modules.h"
    28 #include "Functions.h"
    29 #include "Array.h"
    30 #include "Strings.h"
    31 #include "Environments.h"
    32 #include "Structures.h"
    33 #include "Box.h"
    34 
    35 namespace ke {
    36 
    37 // An ObjectVisitor is used for traversing object references in the heap. Since
    38 // this pattern must be lightning fast, we avoid virtual dispatch by forcing
    39 // visitors to compose themselves with the visiting logic.
    40 template <typename T>
    41 class ObjectVisitor : public T
    42 {
    43   private:
    44     void visitField(Object *obj, size_t offset) {
    45         this->visit(reinterpret_cast<Object **>(Address(obj) + offset));
    46     }
    47 
    48     size_t iterateType(Object *obj) {
    49         return sizeof(Type);
    50     }
    51 
    52     size_t iterateEnumType(Object *obj) {
    53         visitField(obj, EnumType::offsetOfName());
    54         return sizeof(EnumType);
    55     }
    56 
    57     size_t iterateReferenceType(Object *obj) {
    58         iterateType(obj);
    59         visitField(obj, ReferenceType::offsetOfContained());
    60         return sizeof(ReferenceType);
    61     }
    62 
    63     size_t iterateArrayType(Object *obj) {
    64         iterateType(obj);
    65         visitField(obj, ArrayType::offsetOfContained());
    66         visitField(obj, ArrayType::offsetOfNewMap());
    67         return sizeof(ArrayType);
    68     }
    69 
    70     size_t iterateStructType(Object *obj) {
    71         iterateType(obj);
    72         visitField(obj, StructType::offsetOfFields());
    73         visitField(obj, StructType::offsetOfNewMap());
    74         visitField(obj, StructType::offsetOfName());
    75         return sizeof(StructType);
    76     }
    77 
    78     size_t iterateFunctionType(Object *obj) {
    79         iterateType(obj);
    80         visitField(obj, FunctionType::offsetOfReturnType());
    81         visitField(obj, FunctionType::offsetOfParameters());      
    82         visitField(obj, FunctionType::offsetOfDefaults());
    83         visitField(obj, FunctionType::offsetOfName());
    84         return sizeof(FunctionType);
    85     }
    86 
    87     size_t iterateFixedArray(FixedArray *array) {
    88         unsigned length = array->length();
    89         Object **ptr = reinterpret_cast<Object **>(array + 1);
    90         for (unsigned i = 0; i < length; i++)
    91             this->visit(ptr + i);
    92         return array->objSize();
    93     }
    94 
    95     size_t iterateByteArray(ByteArray *array) {
    96         return array->objSize();
    97     }
    98 
    99     size_t iterateCode(Object *obj) {
   100         visitField(obj, Code::offsetOfModule());
   101         visitField(obj, Code::offsetOfBytecode());
   102         visitField(obj, Code::offsetOfLocals());
   103         visitField(obj, Code::offsetOfObjects());
   104         visitField(obj, Code::offsetOfSafepoints());
   105         visitField(obj, Code::offsetOfSourceMap());
   106         visitField(obj, Code::offsetOfStrings());
   107         return sizeof(Code);
   108     }
   109 
   110     size_t iterateReference(Object *obj) {
   111         visitField(obj, Reference::offsetOfBase());
   112         return sizeof(Reference);
   113     }
   114 
   115     size_t iterateModule(Object *obj) {
   116         visitField(obj, Module::offsetOfFile());
   117         visitField(obj, Module::offsetOfGlobals());
   118         visitField(obj, Module::offsetOfCode());
   119         return sizeof(Module);
   120     }
   121 
   122     size_t iterateFunction(Object *obj) {
   123         visitField(obj, Function::offsetOfCode());
   124         visitField(obj, Function::offsetOfType());
   125         visitField(obj, Function::offsetOfName());
   126         return sizeof(Function);
   127     }
   128 
   129     size_t iterateDescriptor(Object *obj) {
   130         visitField(obj, Descriptor::offsetOfName());
   131         visitField(obj, Descriptor::offsetOfType());
   132         return sizeof(Descriptor);
   133     }
   134 
   135     size_t iterateNative(Object *obj) {
   136         visitField(obj, Native::offsetOfType());
   137         return sizeof(Native);
   138     }
   139 
   140     size_t iterateString(Object *obj) {
   141         return String::cast(obj)->objSize();
   142     }
   143 
   144     size_t iterateArray(Array *array, ArrayMap *map) {
   145         if (!map->type()->fixedLength() || map->type()->contained()->isTraceable())
   146             visitField(array, Array::offsetOfElements());
   147         return array->objSize(map);
   148     }
   149 
   150     size_t iterateBox(Box *obj) {
   151         visitField(obj, Box::offsetOfType());
   152         if (obj->type()->isTraceable())
   153             visitField(obj, Box::offsetOfObj());
   154         return sizeof(Box);
   155     }
   156 
   157     size_t iterateArrayMap(ArrayMap *map) {
   158         visitField(map, ArrayMap::offsetOfType());
   159         return sizeof(ArrayMap);
   160     }
   161 
   162     size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
   163         unsigned length = env->length();
   164         EnvironmentSlotDescriptor *desc = env->slots();
   165         for (unsigned i = 0; i < length; i++)
   166             this->visit(desc->type.addr());
   167         return env->objSize();
   168     }
   169 
   170     size_t iterateEnvironmentMap(EnvironmentMap *map) {
   171         visitField(map, EnvironmentMap::offsetOfSlots());
   172         return map->objSize();
   173     }
   174 
   175     size_t iterateStructMap(StructMap *map) {
   176         visitField(map, StructMap::offsetOfType());
   177         visitField(map, StructMap::offsetOfComposed());
   178         return map->objSize();
   179     }
   180 
   181     size_t iterateEnvironment(Environment *env) {
   182         EnvironmentMap *map = env->map();
   183         const unsigned *offsets = map->traceOffsets();
   184         unsigned noffsets = map->traceOffsetCount();
   185         for (unsigned i = 0; i < noffsets; i++)
   186             visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
   187         return env->objSize();
   188     }
   189 
   190     size_t iterateStruct(Struct *obj) {
   191         StructMap *map = obj->map();
   192         const unsigned *offsets = map->traceOffsets();
   193         unsigned noffsets = map->traceOffsetCount();
   194         for (unsigned i = 0; i < noffsets; i++)
   195             visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
   196         return obj->objSize();
   197     }
   198 
   199   private:
   200     size_t iterateObject(Object *obj) {
   201         visitField(obj, Object::offsetOfMap());
   202         return iterate(obj, obj->map());
   203     }
   204 
   205     size_t iterateObject(Object *obj, Map *map) {
   206         switch (map->kind()) {
   207           case MapKind_Type:
   208             return iterateType(obj);
   209 
   210           case MapKind_ReferenceType:
   211             return iterateReferenceType(obj);
   212 
   213           case MapKind_ArrayType:
   214             return iterateArrayType(obj);
   215 
   216           case MapKind_EnumType:
   217             return iterateEnumType(obj);
   218 
   219           case MapKind_FunctionType:
   220             return iterateFunctionType(obj);
   221 
   222           case MapKind_StructType:
   223             return iterateStructType(obj);
   224 
   225           case MapKind_FixedArray:
   226             return iterateFixedArray(FixedArray::cast(obj));
   227 
   228           case MapKind_ByteArray:
   229             return iterateByteArray(ByteArray::cast(obj));
   230 
   231           case MapKind_Code:
   232             return iterateCode(obj);
   233 
   234           case MapKind_Reference:
   235             return iterateReference(obj);
   236 
   237           case MapKind_Module:
   238             return iterateModule(obj);
   239 
   240           case MapKind_Function:
   241             return iterateFunction(obj);
   242 
   243           case MapKind_Descriptor:
   244             return iterateDescriptor(obj);
   245 
   246           case MapKind_String:
   247             return iterateString(obj);
   248 
   249           case MapKind_Array:
   250             return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
   251 
   252           case MapKind_Box:
   253             return iterateBox(Box::cast(obj));
   254 
   255           case MapKind_Struct:
   256             return iterateStruct(Struct::cast(obj));
   257 
   258           case MapKind_EnvironmentSlotDescriptorArray:
   259             return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
   260 
   261           case MapKind_Environment:
   262             return iterateEnvironment(Environment::cast(obj));
   263 
   264           case MapKind_Native:
   265             return iterateNative(obj);
   266 
   267           case MapKind_MetaArray:
   268             return iterateArrayMap(ArrayMap::cast(obj));
   269 
   270           case MapKind_MetaEnvironment:
   271             return iterateEnvironmentMap(EnvironmentMap::cast(obj));
   272 
   273           case MapKind_MetaStruct:
   274             return iterateStructMap(StructMap::cast(obj));
   275 
   276           default:
   277             assert(map->kind() == MapKind_Meta);
   278             return sizeof(Map);
   279         }
   280     }
   281 
   282   public:
   283     size_t iterate(Object *obj) {
   284         return Align(iterateObject(obj), kObjectAlignment);
   285     }
   286 
   287     size_t iterate(Object *obj, Map *map) {
   288         return Align(iterateObject(obj, map), kObjectAlignment);
   289     }
   290 };
   291 
   292 static inline size_t
   293 SizeOfObjectRaw(Object *obj, Map *map)
   294 {
   295     switch (map->kind()) {
   296       case MapKind_Type:
   297         return sizeof(Type);
   298 
   299       case MapKind_ReferenceType:
   300         return sizeof(ReferenceType);
   301 
   302       case MapKind_ArrayType:
   303         return sizeof(ArrayType);
   304 
   305       case MapKind_EnumType:
   306         return sizeof(EnumType);
   307 
   308       case MapKind_FunctionType:
   309         return sizeof(FunctionType);
   310 
   311       case MapKind_StructType:
   312         return sizeof(StructType);
   313 
   314       case MapKind_FixedArray:
   315         return FixedArray::cast(obj)->objSize();
   316 
   317       case MapKind_ByteArray:
   318         return ByteArray::cast(obj)->objSize();
   319 
   320       case MapKind_Code:
   321         return sizeof(Code);
   322 
   323       case MapKind_Reference:
   324         return sizeof(Reference);
   325 
   326       case MapKind_Module:
   327         return sizeof(Module);
   328 
   329       case MapKind_Descriptor:
   330         return sizeof(Descriptor);
   331 
   332       case MapKind_Function:
   333         return sizeof(Function);
   334 
   335       case MapKind_String:
   336         return String::cast(obj)->objSize();
   337 
   338       case MapKind_Native:
   339         return sizeof(Native);
   340 
   341       case MapKind_Array:
   342         return Align(Array::cast(obj)->objSize(ArrayMap::cast(map)), kObjectAlignment);
   343 
   344       case MapKind_Box:
   345         return sizeof(Box);
   346 
   347       case MapKind_Struct:
   348         return Struct::cast(obj)->objSize();
   349 
   350       case MapKind_EnvironmentSlotDescriptorArray:
   351         return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
   352 
   353       case MapKind_Environment:
   354         return Environment::cast(obj)->objSize();
   355 
   356       case MapKind_MetaArray:
   357         return sizeof(ArrayMap);
   358 
   359       case MapKind_MetaEnvironment:
   360         return EnvironmentMap::cast(obj)->objSize();
   361 
   362       case MapKind_MetaStruct:
   363         return StructMap::cast(obj)->objSize();
   364 
   365       case MapKind_FreeRegion:
   366         return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
   367 
   368       default:
   369         assert(map->kind() == MapKind_Meta);
   370         return sizeof(Map);
   371     }
   372 }
   373 
   374 static inline size_t
   375 SizeOfObject(Object *obj, Map *map)
   376 {
   377     return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
   378 }
   379 
   380 class ObjectSizeEvaluator
   381 {
   382   public:
   383     size_t operator()(Object *obj, Map *map) {
   384         return SizeOfObject(obj, map);
   385     }
   386 };
   387 
   388 }
   389 
   390 #endif // _include_jc_object_visitor_h_