src/ObjectVisitor.h
author David Anderson <dvander@alliedmods.net>
Sun Sep 16 21:34:10 2012 -0700 (2012-09-16)
changeset 188 bab29bcec7fe
parent 168 4d0fff61d65e
child 195 c1ba166f3fc4
permissions -rw-r--r--
Restructure Array so the elements vector can be replaced.
     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::offsetOfContained());
    50         visitField(obj, Type::offsetOfReturnType());
    51         visitField(obj, Type::offsetOfParameters());
    52         visitField(obj, Type::offsetOfName());
    53         visitField(obj, Type::offsetOfFields());
    54         visitField(obj, Type::offsetOfDefaults());
    55         visitField(obj, Type::offsetOfNewMap());
    56         return sizeof(Type);
    57     }
    58 
    59     size_t iterateFixedArray(FixedArray *array) {
    60         unsigned length = array->length();
    61         Object **ptr = reinterpret_cast<Object **>(array + 1);
    62         for (unsigned i = 0; i < length; i++)
    63             this->visit(ptr + i);
    64         return array->objSize();
    65     }
    66 
    67     size_t iterateByteArray(ByteArray *array) {
    68         return array->objSize();
    69     }
    70 
    71     size_t iterateCode(Object *obj) {
    72         visitField(obj, Code::offsetOfModule());
    73         visitField(obj, Code::offsetOfBytecode());
    74         visitField(obj, Code::offsetOfLocals());
    75         visitField(obj, Code::offsetOfObjects());
    76         visitField(obj, Code::offsetOfSafepoints());
    77         visitField(obj, Code::offsetOfSourceMap());
    78         return sizeof(Code);
    79     }
    80 
    81     size_t iterateReference(Object *obj) {
    82         visitField(obj, Reference::offsetOfBase());
    83         return sizeof(Reference);
    84     }
    85 
    86     size_t iterateModule(Object *obj) {
    87         visitField(obj, Module::offsetOfFunctions());
    88         visitField(obj, Module::offsetOfPublics());
    89         visitField(obj, Module::offsetOfNatives());
    90         visitField(obj, Module::offsetOfFile());
    91         visitField(obj, Module::offsetOfEnvironment());
    92         visitField(obj, Module::offsetOfCode());
    93         return sizeof(Module);
    94     }
    95 
    96     size_t iterateFunction(Object *obj) {
    97         visitField(obj, Function::offsetOfCode());
    98         visitField(obj, Function::offsetOfType());
    99         visitField(obj, Function::offsetOfName());
   100         return sizeof(Function);
   101     }
   102 
   103     size_t iterateDescriptor(Object *obj) {
   104         visitField(obj, Descriptor::offsetOfName());
   105         visitField(obj, Descriptor::offsetOfType());
   106         return sizeof(Descriptor);
   107     }
   108 
   109     size_t iterateNative(Object *obj) {
   110         visitField(obj, Native::offsetOfType());
   111         visitField(obj, Native::offsetOfName());
   112         return sizeof(Native);
   113     }
   114 
   115     size_t iterateString(Object *obj) {
   116         return String::cast(obj)->objSize();
   117     }
   118 
   119     size_t iterateArray(Array *array, ArrayMap *map) {
   120         if (!map->type()->fixedLength() || map->type()->contained()->isTraceable())
   121             visitField(array, Array::offsetOfElements());
   122         return array->objSize(map);
   123     }
   124 
   125     size_t iterateBox(Box *obj) {
   126         visitField(obj, Box::offsetOfType());
   127         if (obj->type()->isTraceable())
   128             visitField(obj, Box::offsetOfObj());
   129         return sizeof(Box);
   130     }
   131 
   132     size_t iterateArrayMap(ArrayMap *map) {
   133         visitField(map, ArrayMap::offsetOfType());
   134         return sizeof(ArrayMap);
   135     }
   136 
   137     size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
   138         unsigned length = env->length();
   139         EnvironmentSlotDescriptor *desc = env->slots();
   140         for (unsigned i = 0; i < length; i++)
   141             this->visit(desc->type.addr());
   142         return env->objSize();
   143     }
   144 
   145     size_t iterateEnvironmentMap(EnvironmentMap *map) {
   146         visitField(map, EnvironmentMap::offsetOfSlots());
   147         return map->objSize();
   148     }
   149 
   150     size_t iterateStructMap(StructMap *map) {
   151         visitField(map, StructMap::offsetOfType());
   152         visitField(map, StructMap::offsetOfComposed());
   153         return map->objSize();
   154     }
   155 
   156     size_t iterateEnvironment(Environment *env) {
   157         EnvironmentMap *map = env->map();
   158         const unsigned *offsets = map->traceOffsets();
   159         unsigned noffsets = map->traceOffsetCount();
   160         for (unsigned i = 0; i < noffsets; i++)
   161             visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
   162         return env->objSize();
   163     }
   164 
   165     size_t iterateStruct(Struct *obj) {
   166         StructMap *map = obj->map();
   167         const unsigned *offsets = map->traceOffsets();
   168         unsigned noffsets = map->traceOffsetCount();
   169         for (unsigned i = 0; i < noffsets; i++)
   170             visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
   171         return obj->objSize();
   172     }
   173 
   174   private:
   175     size_t iterateObject(Object *obj) {
   176         visitField(obj, Object::offsetOfMap());
   177         return iterate(obj, obj->map());
   178     }
   179 
   180     size_t iterateObject(Object *obj, Map *map) {
   181         switch (map->kind()) {
   182           case MapKind_Type:
   183             return iterateType(obj);
   184 
   185           case MapKind_FixedArray:
   186             return iterateFixedArray(FixedArray::cast(obj));
   187 
   188           case MapKind_ByteArray:
   189             return iterateByteArray(ByteArray::cast(obj));
   190 
   191           case MapKind_Code:
   192             return iterateCode(obj);
   193 
   194           case MapKind_Reference:
   195             return iterateReference(obj);
   196 
   197           case MapKind_Module:
   198             return iterateModule(obj);
   199 
   200           case MapKind_Function:
   201             return iterateFunction(obj);
   202 
   203           case MapKind_Descriptor:
   204             return iterateDescriptor(obj);
   205 
   206           case MapKind_String:
   207             return iterateString(obj);
   208 
   209           case MapKind_Array:
   210             return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
   211 
   212           case MapKind_Box:
   213             return iterateBox(Box::cast(obj));
   214 
   215           case MapKind_Struct:
   216             return iterateStruct(Struct::cast(obj));
   217 
   218           case MapKind_EnvironmentSlotDescriptorArray:
   219             return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
   220 
   221           case MapKind_Environment:
   222             return iterateEnvironment(Environment::cast(obj));
   223 
   224           case MapKind_Native:
   225             return iterateNative(obj);
   226 
   227           case MapKind_MetaArray:
   228             return iterateArrayMap(ArrayMap::cast(obj));
   229 
   230           case MapKind_MetaEnvironment:
   231             return iterateEnvironmentMap(EnvironmentMap::cast(obj));
   232 
   233           case MapKind_MetaStruct:
   234             return iterateStructMap(StructMap::cast(obj));
   235 
   236           default:
   237             assert(map->kind() == MapKind_Meta);
   238             return sizeof(Map);
   239         }
   240     }
   241 
   242   public:
   243     size_t iterate(Object *obj) {
   244         return Align(iterateObject(obj), kObjectAlignment);
   245     }
   246 
   247     size_t iterate(Object *obj, Map *map) {
   248         return Align(iterateObject(obj, map), kObjectAlignment);
   249     }
   250 };
   251 
   252 static inline size_t
   253 SizeOfObjectRaw(Object *obj, Map *map)
   254 {
   255     switch (map->kind()) {
   256       case MapKind_Type:
   257         return sizeof(Type);
   258 
   259       case MapKind_FixedArray:
   260         return FixedArray::cast(obj)->objSize();
   261 
   262       case MapKind_ByteArray:
   263         return ByteArray::cast(obj)->objSize();
   264 
   265       case MapKind_Code:
   266         return sizeof(Code);
   267 
   268       case MapKind_Reference:
   269         return sizeof(Reference);
   270 
   271       case MapKind_Module:
   272         return sizeof(Module);
   273 
   274       case MapKind_Descriptor:
   275         return sizeof(Descriptor);
   276 
   277       case MapKind_Function:
   278         return sizeof(Function);
   279 
   280       case MapKind_String:
   281         return String::cast(obj)->objSize();
   282 
   283       case MapKind_Native:
   284         return sizeof(Native);
   285 
   286       case MapKind_Array:
   287         return Align(Array::cast(obj)->objSize(ArrayMap::cast(map)), kObjectAlignment);
   288 
   289       case MapKind_Box:
   290         return sizeof(Box);
   291 
   292       case MapKind_Struct:
   293         return Struct::cast(obj)->objSize();
   294 
   295       case MapKind_EnvironmentSlotDescriptorArray:
   296         return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
   297 
   298       case MapKind_Environment:
   299         return Environment::cast(obj)->objSize();
   300 
   301       case MapKind_MetaArray:
   302         return sizeof(ArrayMap);
   303 
   304       case MapKind_MetaEnvironment:
   305         return EnvironmentMap::cast(obj)->objSize();
   306 
   307       case MapKind_MetaStruct:
   308         return StructMap::cast(obj)->objSize();
   309 
   310       case MapKind_FreeRegion:
   311         return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
   312 
   313       default:
   314         assert(map->kind() == MapKind_Meta);
   315         return sizeof(Map);
   316     }
   317 }
   318 
   319 static inline size_t
   320 SizeOfObject(Object *obj, Map *map)
   321 {
   322     return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
   323 }
   324 
   325 class ObjectSizeEvaluator
   326 {
   327   public:
   328     size_t operator()(Object *obj, Map *map) {
   329         return SizeOfObject(obj, map);
   330     }
   331 };
   332 
   333 }
   334 
   335 #endif // _include_jc_object_visitor_h_