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