src/ObjectVisitor.h
author David Anderson <dvander@alliedmods.net>
Tue Dec 25 17:02:07 2012 -0800 (2012-12-25)
changeset 239 572668ef742b
parent 238 e9bec7549c28
child 247 7721042bdb67
permissions -rw-r--r--
More const preparation: allow type casts to follow qualification.
     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         visitField(obj, Type::offsetOfRoot());
    50         return sizeof(Type);
    51     }
    52 
    53     size_t iterateEnumType(Object *obj) {
    54         visitField(obj, EnumType::offsetOfName());
    55         return sizeof(EnumType);
    56     }
    57 
    58     size_t iterateReferenceType(Object *obj) {
    59         iterateType(obj);
    60         visitField(obj, ReferenceType::offsetOfContained());
    61         return sizeof(ReferenceType);
    62     }
    63 
    64     size_t iterateArrayType(Object *obj) {
    65         iterateType(obj);
    66         visitField(obj, ArrayType::offsetOfContained());
    67         visitField(obj, ArrayType::offsetOfNewMap());
    68         return sizeof(ArrayType);
    69     }
    70 
    71     size_t iterateStructType(Object *obj) {
    72         iterateType(obj);
    73         visitField(obj, StructType::offsetOfFields());
    74         visitField(obj, StructType::offsetOfNewMap());
    75         visitField(obj, StructType::offsetOfName());
    76         return sizeof(StructType);
    77     }
    78 
    79     size_t iterateFunctionType(Object *obj) {
    80         iterateType(obj);
    81         visitField(obj, FunctionType::offsetOfReturnType());
    82         visitField(obj, FunctionType::offsetOfParameters());      
    83         visitField(obj, FunctionType::offsetOfDefaults());
    84         visitField(obj, FunctionType::offsetOfName());
    85         return sizeof(FunctionType);
    86     }
    87 
    88     size_t iterateFixedArray(FixedArray *array) {
    89         unsigned length = array->length();
    90         Object **ptr = reinterpret_cast<Object **>(array + 1);
    91         for (unsigned i = 0; i < length; i++)
    92             this->visit(ptr + i);
    93         return array->objSize();
    94     }
    95 
    96     size_t iterateByteArray(ByteArray *array) {
    97         return array->objSize();
    98     }
    99 
   100     size_t iterateCode(Object *obj) {
   101         visitField(obj, Code::offsetOfModule());
   102         visitField(obj, Code::offsetOfBytecode());
   103         visitField(obj, Code::offsetOfLocals());
   104         visitField(obj, Code::offsetOfObjects());
   105         visitField(obj, Code::offsetOfSafepoints());
   106         visitField(obj, Code::offsetOfSourceMap());
   107         visitField(obj, Code::offsetOfStrings());
   108         return sizeof(Code);
   109     }
   110 
   111     size_t iterateReference(Object *obj) {
   112         visitField(obj, Reference::offsetOfBase());
   113         return sizeof(Reference);
   114     }
   115 
   116     size_t iterateModule(Object *obj) {
   117         visitField(obj, Module::offsetOfFile());
   118         visitField(obj, Module::offsetOfGlobals());
   119         visitField(obj, Module::offsetOfCode());
   120         return sizeof(Module);
   121     }
   122 
   123     size_t iterateFunction(Object *obj) {
   124         visitField(obj, Function::offsetOfCode());
   125         visitField(obj, Function::offsetOfType());
   126         visitField(obj, Function::offsetOfName());
   127         return sizeof(Function);
   128     }
   129 
   130     size_t iterateDescriptor(Object *obj) {
   131         visitField(obj, Descriptor::offsetOfName());
   132         visitField(obj, Descriptor::offsetOfType());
   133         return sizeof(Descriptor);
   134     }
   135 
   136     size_t iterateNative(Object *obj) {
   137         visitField(obj, Native::offsetOfType());
   138         return sizeof(Native);
   139     }
   140 
   141     size_t iterateString(Object *obj) {
   142         return String::cast(obj)->objSize();
   143     }
   144 
   145     size_t iterateArray(Array *array, ArrayMap *map) {
   146         if (!map->type()->hasInlineElements())
   147             visitField(array, Array::offsetOfElements());
   148         return array->objSize(map);
   149     }
   150 
   151     size_t iterateBox(Box *obj) {
   152         visitField(obj, Box::offsetOfType());
   153         if (obj->type()->isTraceable())
   154             visitField(obj, Box::offsetOfObj());
   155         return sizeof(Box);
   156     }
   157 
   158     size_t iterateArrayMap(ArrayMap *map) {
   159         visitField(map, ArrayMap::offsetOfType());
   160         return sizeof(ArrayMap);
   161     }
   162 
   163     size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
   164         unsigned length = env->length();
   165         EnvironmentSlotDescriptor *desc = env->slots();
   166         for (unsigned i = 0; i < length; i++)
   167             this->visit(desc->type.addr());
   168         return env->objSize();
   169     }
   170 
   171     size_t iterateEnvironmentMap(EnvironmentMap *map) {
   172         visitField(map, EnvironmentMap::offsetOfSlots());
   173         return map->objSize();
   174     }
   175 
   176     size_t iterateStructMap(StructMap *map) {
   177         visitField(map, StructMap::offsetOfType());
   178         visitField(map, StructMap::offsetOfComposed());
   179         return map->objSize();
   180     }
   181 
   182     size_t iterateEnvironment(Environment *env) {
   183         EnvironmentMap *map = env->map();
   184         const unsigned *offsets = map->traceOffsets();
   185         unsigned noffsets = map->traceOffsetCount();
   186         for (unsigned i = 0; i < noffsets; i++)
   187             visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
   188         return env->objSize();
   189     }
   190 
   191     size_t iterateStruct(Struct *obj) {
   192         StructMap *map = obj->map();
   193         const unsigned *offsets = map->traceOffsets();
   194         unsigned noffsets = map->traceOffsetCount();
   195         for (unsigned i = 0; i < noffsets; i++)
   196             visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
   197         return obj->objSize();
   198     }
   199 
   200   private:
   201     size_t iterateObject(Object *obj) {
   202         visitField(obj, Object::offsetOfMap());
   203         return iterate(obj, obj->map());
   204     }
   205 
   206     size_t iterateObject(Object *obj, Map *map) {
   207         switch (map->kind()) {
   208           case MapKind_Type:
   209             return iterateType(obj);
   210 
   211           case MapKind_ReferenceType:
   212             return iterateReferenceType(obj);
   213 
   214           case MapKind_ArrayType:
   215             return iterateArrayType(obj);
   216 
   217           case MapKind_EnumType:
   218             return iterateEnumType(obj);
   219 
   220           case MapKind_FunctionType:
   221             return iterateFunctionType(obj);
   222 
   223           case MapKind_StructType:
   224             return iterateStructType(obj);
   225 
   226           case MapKind_FixedArray:
   227             return iterateFixedArray(FixedArray::cast(obj));
   228 
   229           case MapKind_ByteArray:
   230             return iterateByteArray(ByteArray::cast(obj));
   231 
   232           case MapKind_Code:
   233             return iterateCode(obj);
   234 
   235           case MapKind_Reference:
   236             return iterateReference(obj);
   237 
   238           case MapKind_Module:
   239             return iterateModule(obj);
   240 
   241           case MapKind_Function:
   242             return iterateFunction(obj);
   243 
   244           case MapKind_Descriptor:
   245             return iterateDescriptor(obj);
   246 
   247           case MapKind_String:
   248             return iterateString(obj);
   249 
   250           case MapKind_Array:
   251             return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
   252 
   253           case MapKind_Box:
   254             return iterateBox(Box::cast(obj));
   255 
   256           case MapKind_Struct:
   257             return iterateStruct(Struct::cast(obj));
   258 
   259           case MapKind_EnvironmentSlotDescriptorArray:
   260             return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
   261 
   262           case MapKind_Environment:
   263             return iterateEnvironment(Environment::cast(obj));
   264 
   265           case MapKind_Native:
   266             return iterateNative(obj);
   267 
   268           case MapKind_MetaArray:
   269             return iterateArrayMap(ArrayMap::cast(obj));
   270 
   271           case MapKind_MetaEnvironment:
   272             return iterateEnvironmentMap(EnvironmentMap::cast(obj));
   273 
   274           case MapKind_MetaStruct:
   275             return iterateStructMap(StructMap::cast(obj));
   276 
   277           default:
   278             assert(map->kind() == MapKind_Meta);
   279             return sizeof(Map);
   280         }
   281     }
   282 
   283   public:
   284     size_t iterate(Object *obj) {
   285         return Align(iterateObject(obj), kObjectAlignment);
   286     }
   287 
   288     size_t iterate(Object *obj, Map *map) {
   289         return Align(iterateObject(obj, map), kObjectAlignment);
   290     }
   291 };
   292 
   293 static inline size_t
   294 SizeOfObjectRaw(Object *obj, Map *map)
   295 {
   296     switch (map->kind()) {
   297       case MapKind_Type:
   298         return sizeof(Type);
   299 
   300       case MapKind_ReferenceType:
   301         return sizeof(ReferenceType);
   302 
   303       case MapKind_ArrayType:
   304         return sizeof(ArrayType);
   305 
   306       case MapKind_EnumType:
   307         return sizeof(EnumType);
   308 
   309       case MapKind_FunctionType:
   310         return sizeof(FunctionType);
   311 
   312       case MapKind_StructType:
   313         return sizeof(StructType);
   314 
   315       case MapKind_FixedArray:
   316         return FixedArray::cast(obj)->objSize();
   317 
   318       case MapKind_ByteArray:
   319         return ByteArray::cast(obj)->objSize();
   320 
   321       case MapKind_Code:
   322         return sizeof(Code);
   323 
   324       case MapKind_Reference:
   325         return sizeof(Reference);
   326 
   327       case MapKind_Module:
   328         return sizeof(Module);
   329 
   330       case MapKind_Descriptor:
   331         return sizeof(Descriptor);
   332 
   333       case MapKind_Function:
   334         return sizeof(Function);
   335 
   336       case MapKind_String:
   337         return String::cast(obj)->objSize();
   338 
   339       case MapKind_Native:
   340         return sizeof(Native);
   341 
   342       case MapKind_Array:
   343         return Align(Array::cast(obj)->objSize(ArrayMap::cast(map)), kObjectAlignment);
   344 
   345       case MapKind_Box:
   346         return sizeof(Box);
   347 
   348       case MapKind_Struct:
   349         return Struct::cast(obj)->objSize();
   350 
   351       case MapKind_EnvironmentSlotDescriptorArray:
   352         return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
   353 
   354       case MapKind_Environment:
   355         return Environment::cast(obj)->objSize();
   356 
   357       case MapKind_MetaArray:
   358         return sizeof(ArrayMap);
   359 
   360       case MapKind_MetaEnvironment:
   361         return EnvironmentMap::cast(obj)->objSize();
   362 
   363       case MapKind_MetaStruct:
   364         return StructMap::cast(obj)->objSize();
   365 
   366       case MapKind_FreeRegion:
   367         return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
   368 
   369       default:
   370         assert(map->kind() == MapKind_Meta);
   371         return sizeof(Map);
   372     }
   373 }
   374 
   375 static inline size_t
   376 SizeOfObject(Object *obj, Map *map)
   377 {
   378     return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
   379 }
   380 
   381 class ObjectSizeEvaluator
   382 {
   383   public:
   384     size_t operator()(Object *obj, Map *map) {
   385         return SizeOfObject(obj, map);
   386     }
   387 };
   388 
   389 }
   390 
   391 #endif // _include_jc_object_visitor_h_