src/ObjectVisitor.h
author David Anderson <dvander@alliedmods.net>
Tue Jan 01 20:08:34 2013 -0800 (2013-01-01)
changeset 255 b3cf7e052ddf
parent 251 ca99a81745fe
child 256 3c184218462d
permissions -rw-r--r--
Fix FileSystem.cpp build on GCC.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of SourcePawn.
     6  *
     7  * SourcePawn 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  * SourcePawn 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  * SourcePawn. 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 #include "Packages.h"
    35 #include "List.h"
    36 
    37 namespace ke {
    38 
    39 // An ObjectVisitor is used for traversing object references in the heap. Since
    40 // this pattern must be lightning fast, we avoid virtual dispatch by forcing
    41 // visitors to compose themselves with the visiting logic.
    42 template <typename T>
    43 class ObjectVisitor : public T
    44 {
    45   private:
    46     void visitField(Object *obj, size_t offset) {
    47         this->visit(reinterpret_cast<Object **>(Address(obj) + offset));
    48     }
    49 
    50     size_t iterateType(Object *obj) {
    51         visitField(obj, Type::offsetOfRoot());
    52         return sizeof(Type);
    53     }
    54 
    55     size_t iterateEnumType(Object *obj) {
    56         visitField(obj, EnumType::offsetOfName());
    57         return sizeof(EnumType);
    58     }
    59 
    60     size_t iterateReferenceType(Object *obj) {
    61         iterateType(obj);
    62         visitField(obj, ReferenceType::offsetOfContained());
    63         return sizeof(ReferenceType);
    64     }
    65 
    66     size_t iterateArrayType(Object *obj) {
    67         iterateType(obj);
    68         visitField(obj, ArrayType::offsetOfContained());
    69         visitField(obj, ArrayType::offsetOfNewMap());
    70         return sizeof(ArrayType);
    71     }
    72 
    73     size_t iterateStructType(Object *obj) {
    74         iterateType(obj);
    75         visitField(obj, StructType::offsetOfFields());
    76         visitField(obj, StructType::offsetOfNewMap());
    77         visitField(obj, StructType::offsetOfName());
    78         return sizeof(StructType);
    79     }
    80 
    81     size_t iterateFunctionType(Object *obj) {
    82         iterateType(obj);
    83         visitField(obj, FunctionType::offsetOfReturnType());
    84         visitField(obj, FunctionType::offsetOfParameters());      
    85         visitField(obj, FunctionType::offsetOfDefaults());
    86         visitField(obj, FunctionType::offsetOfName());
    87         return sizeof(FunctionType);
    88     }
    89 
    90     size_t iterateFixedArray(FixedArray *array) {
    91         unsigned length = array->length();
    92         Object **ptr = reinterpret_cast<Object **>(array + 1);
    93         for (unsigned i = 0; i < length; i++)
    94             this->visit(ptr + i);
    95         return array->objSize();
    96     }
    97 
    98     size_t iterateByteArray(ByteArray *array) {
    99         return array->objSize();
   100     }
   101 
   102     size_t iterateCode(Object *obj) {
   103         visitField(obj, Code::offsetOfModule());
   104         visitField(obj, Code::offsetOfBytecode());
   105         visitField(obj, Code::offsetOfLocals());
   106         visitField(obj, Code::offsetOfObjects());
   107         visitField(obj, Code::offsetOfSafepoints());
   108         visitField(obj, Code::offsetOfSourceMap());
   109         visitField(obj, Code::offsetOfStrings());
   110         return sizeof(Code);
   111     }
   112 
   113     size_t iterateReference(Object *obj) {
   114         visitField(obj, Reference::offsetOfBase());
   115         return sizeof(Reference);
   116     }
   117 
   118     void visitImportable(Object *obj) {
   119         visitField(obj, Package::offsetOfName());
   120         visitField(obj, Package::offsetOfParent());
   121         visitField(obj, Package::offsetOfPath());
   122     }
   123 
   124     size_t iterateModule(Object *obj) {
   125         visitImportable(obj);
   126         visitField(obj, Module::offsetOfGlobals());
   127         visitField(obj, Module::offsetOfCode());
   128         return sizeof(Module);
   129     }
   130 
   131     size_t iteratePackage(Object *obj) {
   132         visitImportable(obj);
   133         visitField(obj, Package::offsetOfContents());
   134         return sizeof(Package);
   135     }
   136 
   137     size_t iterateFunction(Object *obj) {
   138         visitField(obj, Function::offsetOfCode());
   139         visitField(obj, Function::offsetOfType());
   140         visitField(obj, Function::offsetOfName());
   141         return sizeof(Function);
   142     }
   143 
   144     size_t iterateDescriptor(Object *obj) {
   145         visitField(obj, Descriptor::offsetOfName());
   146         visitField(obj, Descriptor::offsetOfType());
   147         return sizeof(Descriptor);
   148     }
   149 
   150     size_t iterateNative(Object *obj) {
   151         visitField(obj, Native::offsetOfType());
   152         return sizeof(Native);
   153     }
   154 
   155     size_t iterateString(Object *obj) {
   156         return String::cast(obj)->objSize();
   157     }
   158 
   159     size_t iterateArray(Array *array, ArrayMap *map) {
   160         if (!map->type()->hasInlineElements())
   161             visitField(array, Array::offsetOfElements());
   162         return array->objSize(map);
   163     }
   164 
   165     size_t iterateDependentArray(Object *array) {
   166         visitField(array, DependentArray::offsetOfRoot());
   167         return sizeof(DependentArray);
   168     }
   169 
   170     size_t iterateBox(Box *obj) {
   171         visitField(obj, Box::offsetOfType());
   172         if (obj->type()->isTraceable())
   173             visitField(obj, Box::offsetOfObj());
   174         return sizeof(Box);
   175     }
   176 
   177     size_t iterateArrayMap(ArrayMap *map) {
   178         visitField(map, ArrayMap::offsetOfType());
   179         return sizeof(ArrayMap);
   180     }
   181 
   182     size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
   183         unsigned length = env->length();
   184         EnvironmentSlotDescriptor *desc = env->slots();
   185         for (unsigned i = 0; i < length; i++)
   186             this->visit(desc->type.addr());
   187         return env->objSize();
   188     }
   189 
   190     size_t iterateEnvironmentMap(EnvironmentMap *map) {
   191         visitField(map, EnvironmentMap::offsetOfSlots());
   192         return map->objSize();
   193     }
   194 
   195     size_t iterateStructMap(StructMap *map) {
   196         visitField(map, StructMap::offsetOfType());
   197         visitField(map, StructMap::offsetOfComposed());
   198         return map->objSize();
   199     }
   200 
   201     size_t iterateEnvironment(Environment *env) {
   202         EnvironmentMap *map = env->map();
   203         const unsigned *offsets = map->traceOffsets();
   204         unsigned noffsets = map->traceOffsetCount();
   205         for (unsigned i = 0; i < noffsets; i++)
   206             visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
   207         return env->objSize();
   208     }
   209 
   210     size_t iterateStruct(Struct *obj) {
   211         StructMap *map = obj->map();
   212         const unsigned *offsets = map->traceOffsets();
   213         unsigned noffsets = map->traceOffsetCount();
   214         for (unsigned i = 0; i < noffsets; i++)
   215             visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
   216         return obj->objSize();
   217     }
   218 
   219     size_t iterateList(Object *obj) {
   220         visitField(obj, List<Object>::offsetOfArray());
   221         return sizeof(List<Object>);
   222     }
   223 
   224   private:
   225     size_t iterateObject(Object *obj) {
   226         visitField(obj, Object::offsetOfMap());
   227         return iterate(obj, obj->map());
   228     }
   229 
   230     size_t iterateObject(Object *obj, Map *map) {
   231         switch (map->kind()) {
   232           case MapKind_Type:
   233             return iterateType(obj);
   234 
   235           case MapKind_ReferenceType:
   236             return iterateReferenceType(obj);
   237 
   238           case MapKind_ArrayType:
   239             return iterateArrayType(obj);
   240 
   241           case MapKind_EnumType:
   242             return iterateEnumType(obj);
   243 
   244           case MapKind_FunctionType:
   245             return iterateFunctionType(obj);
   246 
   247           case MapKind_StructType:
   248             return iterateStructType(obj);
   249 
   250           case MapKind_FixedArray:
   251             return iterateFixedArray(FixedArray::cast(obj));
   252 
   253           case MapKind_ByteArray:
   254             return iterateByteArray(ByteArray::cast(obj));
   255 
   256           case MapKind_Code:
   257             return iterateCode(obj);
   258 
   259           case MapKind_Reference:
   260             return iterateReference(obj);
   261 
   262           case MapKind_Module:
   263             return iterateModule(obj);
   264 
   265           case MapKind_Package:
   266             return iteratePackage(obj);
   267 
   268           case MapKind_Function:
   269             return iterateFunction(obj);
   270 
   271           case MapKind_Descriptor:
   272             return iterateDescriptor(obj);
   273 
   274           case MapKind_String:
   275             return iterateString(obj);
   276 
   277           case MapKind_Array:
   278             return iterateArray(Array::cast(obj), ArrayMap::cast(map));
   279 
   280           case MapKind_DependentArray:
   281             return iterateDependentArray(obj);
   282 
   283           case MapKind_Box:
   284             return iterateBox(Box::cast(obj));
   285 
   286           case MapKind_Struct:
   287             return iterateStruct(Struct::cast(obj));
   288 
   289           case MapKind_List:
   290             return iterateList(obj);
   291 
   292           case MapKind_EnvironmentSlotDescriptorArray:
   293             return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
   294 
   295           case MapKind_Environment:
   296             return iterateEnvironment(Environment::cast(obj));
   297 
   298           case MapKind_Native:
   299             return iterateNative(obj);
   300 
   301           case MapKind_MetaArray:
   302             return iterateArrayMap(ArrayMap::cast(obj));
   303 
   304           case MapKind_MetaEnvironment:
   305             return iterateEnvironmentMap(EnvironmentMap::cast(obj));
   306 
   307           case MapKind_MetaStruct:
   308             return iterateStructMap(StructMap::cast(obj));
   309 
   310           default:
   311             assert(map->kind() == MapKind_Meta);
   312             return sizeof(Map);
   313         }
   314     }
   315 
   316   public:
   317     size_t iterate(Object *obj) {
   318         return Align(iterateObject(obj), kObjectAlignment);
   319     }
   320 
   321     size_t iterate(Object *obj, Map *map) {
   322         return Align(iterateObject(obj, map), kObjectAlignment);
   323     }
   324 };
   325 
   326 static inline size_t
   327 SizeOfObjectRaw(Object *obj, Map *map)
   328 {
   329     switch (map->kind()) {
   330       case MapKind_Type:
   331         return sizeof(Type);
   332 
   333       case MapKind_ReferenceType:
   334         return sizeof(ReferenceType);
   335 
   336       case MapKind_ArrayType:
   337         return sizeof(ArrayType);
   338 
   339       case MapKind_EnumType:
   340         return sizeof(EnumType);
   341 
   342       case MapKind_FunctionType:
   343         return sizeof(FunctionType);
   344 
   345       case MapKind_StructType:
   346         return sizeof(StructType);
   347 
   348       case MapKind_FixedArray:
   349         return FixedArray::cast(obj)->objSize();
   350 
   351       case MapKind_ByteArray:
   352         return ByteArray::cast(obj)->objSize();
   353 
   354       case MapKind_Code:
   355         return sizeof(Code);
   356 
   357       case MapKind_Reference:
   358         return sizeof(Reference);
   359 
   360       case MapKind_Module:
   361         return sizeof(Module);
   362 
   363       case MapKind_Package:
   364         return sizeof(Package);
   365 
   366       case MapKind_Descriptor:
   367         return sizeof(Descriptor);
   368 
   369       case MapKind_Function:
   370         return sizeof(Function);
   371 
   372       case MapKind_String:
   373         return String::cast(obj)->objSize();
   374 
   375       case MapKind_Native:
   376         return sizeof(Native);
   377 
   378       case MapKind_Array:
   379         return Array::cast(obj)->objSize(ArrayMap::cast(map));
   380 
   381        case MapKind_DependentArray:
   382         return sizeof(DependentArray);
   383 
   384       case MapKind_Box:
   385         return sizeof(Box);
   386 
   387       case MapKind_List:
   388         return sizeof(List<Object>);
   389 
   390       case MapKind_Struct:
   391         return Struct::cast(obj)->objSize();
   392 
   393       case MapKind_EnvironmentSlotDescriptorArray:
   394         return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
   395 
   396       case MapKind_Environment:
   397         return Environment::cast(obj)->objSize();
   398 
   399       case MapKind_MetaArray:
   400         return sizeof(ArrayMap);
   401 
   402       case MapKind_MetaEnvironment:
   403         return EnvironmentMap::cast(obj)->objSize();
   404 
   405       case MapKind_MetaStruct:
   406         return StructMap::cast(obj)->objSize();
   407 
   408       case MapKind_FreeRegion:
   409         return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
   410 
   411       default:
   412         assert(map->kind() == MapKind_Meta);
   413         return sizeof(Map);
   414     }
   415 }
   416 
   417 static inline size_t
   418 SizeOfObject(Object *obj, Map *map)
   419 {
   420     return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
   421 }
   422 
   423 class ObjectSizeEvaluator
   424 {
   425   public:
   426     size_t operator()(Object *obj, Map *map) {
   427         return SizeOfObject(obj, map);
   428     }
   429 };
   430 
   431 }
   432 
   433 #endif // _include_jc_object_visitor_h_