src/ObjectVisitor.h
author David Anderson <dvander@alliedmods.net>
Sun Jan 06 13:52:21 2013 -0800 (2013-01-06)
changeset 256 3c184218462d
parent 251 ca99a81745fe
child 261 219b49bf4a03
permissions -rw-r--r--
Initial implementation of module imports.
     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         visitField(obj, Module::offsetOfImports());
   129         return sizeof(Module);
   130     }
   131 
   132     size_t iteratePackage(Object *obj) {
   133         visitImportable(obj);
   134         visitField(obj, Package::offsetOfContents());
   135         return sizeof(Package);
   136     }
   137 
   138     size_t iterateFunction(Object *obj) {
   139         visitField(obj, Function::offsetOfCode());
   140         visitField(obj, Function::offsetOfType());
   141         visitField(obj, Function::offsetOfName());
   142         return sizeof(Function);
   143     }
   144 
   145     size_t iterateDescriptor(Object *obj) {
   146         visitField(obj, Descriptor::offsetOfName());
   147         visitField(obj, Descriptor::offsetOfType());
   148         return sizeof(Descriptor);
   149     }
   150 
   151     size_t iterateNative(Object *obj) {
   152         visitField(obj, Native::offsetOfType());
   153         return sizeof(Native);
   154     }
   155 
   156     size_t iterateString(Object *obj) {
   157         return String::cast(obj)->objSize();
   158     }
   159 
   160     size_t iterateArray(Array *array, ArrayMap *map) {
   161         if (!map->type()->hasInlineElements())
   162             visitField(array, Array::offsetOfElements());
   163         return array->objSize(map);
   164     }
   165 
   166     size_t iterateDependentArray(Object *array) {
   167         visitField(array, DependentArray::offsetOfRoot());
   168         return sizeof(DependentArray);
   169     }
   170 
   171     size_t iterateBox(Box *obj) {
   172         visitField(obj, Box::offsetOfType());
   173         if (obj->type()->isTraceable())
   174             visitField(obj, Box::offsetOfObj());
   175         return sizeof(Box);
   176     }
   177 
   178     size_t iterateArrayMap(ArrayMap *map) {
   179         visitField(map, ArrayMap::offsetOfType());
   180         return sizeof(ArrayMap);
   181     }
   182 
   183     size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
   184         unsigned length = env->length();
   185         EnvironmentSlotDescriptor *desc = env->slots();
   186         for (unsigned i = 0; i < length; i++)
   187             this->visit(desc->type.addr());
   188         return env->objSize();
   189     }
   190 
   191     size_t iterateEnvironmentMap(EnvironmentMap *map) {
   192         visitField(map, EnvironmentMap::offsetOfSlots());
   193         return map->objSize();
   194     }
   195 
   196     size_t iterateStructMap(StructMap *map) {
   197         visitField(map, StructMap::offsetOfType());
   198         visitField(map, StructMap::offsetOfComposed());
   199         return map->objSize();
   200     }
   201 
   202     size_t iterateEnvironment(Environment *env) {
   203         EnvironmentMap *map = env->map();
   204         const unsigned *offsets = map->traceOffsets();
   205         unsigned noffsets = map->traceOffsetCount();
   206         for (unsigned i = 0; i < noffsets; i++)
   207             visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
   208         return env->objSize();
   209     }
   210 
   211     size_t iterateStruct(Struct *obj) {
   212         StructMap *map = obj->map();
   213         const unsigned *offsets = map->traceOffsets();
   214         unsigned noffsets = map->traceOffsetCount();
   215         for (unsigned i = 0; i < noffsets; i++)
   216             visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
   217         return Struct::SizeFor(map);
   218     }
   219 
   220     size_t iterateList(Object *obj) {
   221         visitField(obj, List<Object>::offsetOfArray());
   222         return sizeof(List<Object>);
   223     }
   224 
   225   private:
   226     size_t iterateObject(Object *obj) {
   227         visitField(obj, Object::offsetOfMap());
   228         return iterate(obj, obj->map());
   229     }
   230 
   231     size_t iterateObject(Object *obj, Map *map) {
   232         switch (map->kind()) {
   233           case MapKind_Type:
   234             return iterateType(obj);
   235 
   236           case MapKind_ReferenceType:
   237             return iterateReferenceType(obj);
   238 
   239           case MapKind_ArrayType:
   240             return iterateArrayType(obj);
   241 
   242           case MapKind_EnumType:
   243             return iterateEnumType(obj);
   244 
   245           case MapKind_FunctionType:
   246             return iterateFunctionType(obj);
   247 
   248           case MapKind_StructType:
   249             return iterateStructType(obj);
   250 
   251           case MapKind_FixedArray:
   252             return iterateFixedArray(FixedArray::cast(obj));
   253 
   254           case MapKind_ByteArray:
   255             return iterateByteArray(ByteArray::cast(obj));
   256 
   257           case MapKind_Code:
   258             return iterateCode(obj);
   259 
   260           case MapKind_Reference:
   261             return iterateReference(obj);
   262 
   263           case MapKind_Module:
   264             return iterateModule(obj);
   265 
   266           case MapKind_Package:
   267             return iteratePackage(obj);
   268 
   269           case MapKind_Function:
   270             return iterateFunction(obj);
   271 
   272           case MapKind_Descriptor:
   273             return iterateDescriptor(obj);
   274 
   275           case MapKind_String:
   276             return iterateString(obj);
   277 
   278           case MapKind_Array:
   279             return iterateArray(Array::cast(obj), ArrayMap::cast(map));
   280 
   281           case MapKind_DependentArray:
   282             return iterateDependentArray(obj);
   283 
   284           case MapKind_Box:
   285             return iterateBox(Box::cast(obj));
   286 
   287           case MapKind_Struct:
   288             return iterateStruct(Struct::cast(obj));
   289 
   290           case MapKind_List:
   291             return iterateList(obj);
   292 
   293           case MapKind_EnvironmentSlotDescriptorArray:
   294             return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
   295 
   296           case MapKind_Environment:
   297             return iterateEnvironment(Environment::cast(obj));
   298 
   299           case MapKind_Native:
   300             return iterateNative(obj);
   301 
   302           case MapKind_MetaArray:
   303             return iterateArrayMap(ArrayMap::cast(obj));
   304 
   305           case MapKind_MetaEnvironment:
   306             return iterateEnvironmentMap(EnvironmentMap::cast(obj));
   307 
   308           case MapKind_MetaStruct:
   309             return iterateStructMap(StructMap::cast(obj));
   310 
   311           default:
   312             assert(map->kind() == MapKind_Meta);
   313             return sizeof(Map);
   314         }
   315     }
   316 
   317   public:
   318     size_t iterate(Object *obj) {
   319         return Align(iterateObject(obj), kObjectAlignment);
   320     }
   321 
   322     size_t iterate(Object *obj, Map *map) {
   323         return Align(iterateObject(obj, map), kObjectAlignment);
   324     }
   325 };
   326 
   327 static inline size_t
   328 SizeOfObjectRaw(Object *obj, Map *map)
   329 {
   330     switch (map->kind()) {
   331       case MapKind_Type:
   332         return sizeof(Type);
   333 
   334       case MapKind_ReferenceType:
   335         return sizeof(ReferenceType);
   336 
   337       case MapKind_ArrayType:
   338         return sizeof(ArrayType);
   339 
   340       case MapKind_EnumType:
   341         return sizeof(EnumType);
   342 
   343       case MapKind_FunctionType:
   344         return sizeof(FunctionType);
   345 
   346       case MapKind_StructType:
   347         return sizeof(StructType);
   348 
   349       case MapKind_FixedArray:
   350         return FixedArray::cast(obj)->objSize();
   351 
   352       case MapKind_ByteArray:
   353         return ByteArray::cast(obj)->objSize();
   354 
   355       case MapKind_Code:
   356         return sizeof(Code);
   357 
   358       case MapKind_Reference:
   359         return sizeof(Reference);
   360 
   361       case MapKind_Module:
   362         return sizeof(Module);
   363 
   364       case MapKind_Package:
   365         return sizeof(Package);
   366 
   367       case MapKind_Descriptor:
   368         return sizeof(Descriptor);
   369 
   370       case MapKind_Function:
   371         return sizeof(Function);
   372 
   373       case MapKind_String:
   374         return String::cast(obj)->objSize();
   375 
   376       case MapKind_Native:
   377         return sizeof(Native);
   378 
   379       case MapKind_Array:
   380         return Array::cast(obj)->objSize(ArrayMap::cast(map));
   381 
   382        case MapKind_DependentArray:
   383         return sizeof(DependentArray);
   384 
   385       case MapKind_Box:
   386         return sizeof(Box);
   387 
   388       case MapKind_List:
   389         return sizeof(List<Object>);
   390 
   391       case MapKind_Struct:
   392         return Struct::SizeFor(StructMap::cast(map));
   393 
   394       case MapKind_EnvironmentSlotDescriptorArray:
   395         return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
   396 
   397       case MapKind_Environment:
   398         return Environment::cast(obj)->objSize();
   399 
   400       case MapKind_MetaArray:
   401         return sizeof(ArrayMap);
   402 
   403       case MapKind_MetaEnvironment:
   404         return EnvironmentMap::cast(obj)->objSize();
   405 
   406       case MapKind_MetaStruct:
   407         return StructMap::cast(obj)->objSize();
   408 
   409       case MapKind_FreeRegion:
   410         return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
   411 
   412       default:
   413         assert(map->kind() == MapKind_Meta);
   414         return sizeof(Map);
   415     }
   416 }
   417 
   418 static inline size_t
   419 SizeOfObject(Object *obj, Map *map)
   420 {
   421     return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
   422 }
   423 
   424 class ObjectSizeEvaluator
   425 {
   426   public:
   427     size_t operator()(Object *obj, Map *map) {
   428         return SizeOfObject(obj, map);
   429     }
   430 };
   431 
   432 }
   433 
   434 #endif // _include_jc_object_visitor_h_