src/ObjectVisitor.h
author David Anderson <dvander@alliedmods.net>
Sun Sep 02 13:06:09 2012 -0700 (2012-09-02)
changeset 177 56f7e5b0243c
parent 168 4d0fff61d65e
child 188 bab29bcec7fe
permissions -rw-r--r--
Fix bug in bytecode resizing.
     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         assert(map->type()->isArray());
   121         if (map->type()->contained()->isTraceable()) {
   122             unsigned length = array->length();
   123             Object **vec = array->objVec();
   124             for (unsigned i = 0; i < length; i++)
   125                 this->visit(vec + i);
   126         }
   127         return Array::SizeOf(array);
   128     }
   129 
   130     size_t iterateBox(Box *obj) {
   131         visitField(obj, Box::offsetOfType());
   132         if (obj->type()->isTraceable())
   133             visitField(obj, Box::offsetOfObj());
   134         return sizeof(Box);
   135     }
   136 
   137     size_t iterateArrayMap(ArrayMap *map) {
   138         visitField(map, ArrayMap::offsetOfType());
   139         return sizeof(ArrayMap);
   140     }
   141 
   142     size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
   143         unsigned length = env->length();
   144         EnvironmentSlotDescriptor *desc = env->slots();
   145         for (unsigned i = 0; i < length; i++)
   146             this->visit(desc->type.addr());
   147         return env->objSize();
   148     }
   149 
   150     size_t iterateEnvironmentMap(EnvironmentMap *map) {
   151         visitField(map, EnvironmentMap::offsetOfSlots());
   152         return map->objSize();
   153     }
   154 
   155     size_t iterateStructMap(StructMap *map) {
   156         visitField(map, StructMap::offsetOfType());
   157         visitField(map, StructMap::offsetOfComposed());
   158         return map->objSize();
   159     }
   160 
   161     size_t iterateEnvironment(Environment *env) {
   162         EnvironmentMap *map = env->map();
   163         const unsigned *offsets = map->traceOffsets();
   164         unsigned noffsets = map->traceOffsetCount();
   165         for (unsigned i = 0; i < noffsets; i++)
   166             visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
   167         return env->objSize();
   168     }
   169 
   170     size_t iterateStruct(Struct *obj) {
   171         StructMap *map = obj->map();
   172         const unsigned *offsets = map->traceOffsets();
   173         unsigned noffsets = map->traceOffsetCount();
   174         for (unsigned i = 0; i < noffsets; i++)
   175             visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
   176         return obj->objSize();
   177     }
   178 
   179   private:
   180     size_t iterateObject(Object *obj) {
   181         visitField(obj, Object::offsetOfMap());
   182         return iterate(obj, obj->map());
   183     }
   184 
   185     size_t iterateObject(Object *obj, Map *map) {
   186         switch (map->kind()) {
   187           case MapKind_Type:
   188             return iterateType(obj);
   189 
   190           case MapKind_FixedArray:
   191             return iterateFixedArray(FixedArray::cast(obj));
   192 
   193           case MapKind_ByteArray:
   194             return iterateByteArray(ByteArray::cast(obj));
   195 
   196           case MapKind_Code:
   197             return iterateCode(obj);
   198 
   199           case MapKind_Reference:
   200             return iterateReference(obj);
   201 
   202           case MapKind_Module:
   203             return iterateModule(obj);
   204 
   205           case MapKind_Function:
   206             return iterateFunction(obj);
   207 
   208           case MapKind_Descriptor:
   209             return iterateDescriptor(obj);
   210 
   211           case MapKind_String:
   212             return iterateString(obj);
   213 
   214           case MapKind_Array:
   215             return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
   216 
   217           case MapKind_Box:
   218             return iterateBox(Box::cast(obj));
   219 
   220           case MapKind_Struct:
   221             return iterateStruct(Struct::cast(obj));
   222 
   223           case MapKind_EnvironmentSlotDescriptorArray:
   224             return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
   225 
   226           case MapKind_Environment:
   227             return iterateEnvironment(Environment::cast(obj));
   228 
   229           case MapKind_Native:
   230             return iterateNative(obj);
   231 
   232           case MapKind_MetaArray:
   233             return iterateArrayMap(ArrayMap::cast(obj));
   234 
   235           case MapKind_MetaEnvironment:
   236             return iterateEnvironmentMap(EnvironmentMap::cast(obj));
   237 
   238           case MapKind_MetaStruct:
   239             return iterateStructMap(StructMap::cast(obj));
   240 
   241           default:
   242             assert(map->kind() == MapKind_Meta);
   243             return sizeof(Map);
   244         }
   245     }
   246 
   247   public:
   248     size_t iterate(Object *obj) {
   249         return Align(iterateObject(obj), kObjectAlignment);
   250     }
   251 
   252     size_t iterate(Object *obj, Map *map) {
   253         return Align(iterateObject(obj, map), kObjectAlignment);
   254     }
   255 };
   256 
   257 static inline size_t
   258 SizeOfObjectRaw(Object *obj, Map *map)
   259 {
   260     switch (map->kind()) {
   261       case MapKind_Type:
   262         return sizeof(Type);
   263 
   264       case MapKind_FixedArray:
   265         return FixedArray::cast(obj)->objSize();
   266 
   267       case MapKind_ByteArray:
   268         return ByteArray::cast(obj)->objSize();
   269 
   270       case MapKind_Code:
   271         return sizeof(Code);
   272 
   273       case MapKind_Reference:
   274         return sizeof(Reference);
   275 
   276       case MapKind_Module:
   277         return sizeof(Module);
   278 
   279       case MapKind_Descriptor:
   280         return sizeof(Descriptor);
   281 
   282       case MapKind_Function:
   283         return sizeof(Function);
   284 
   285       case MapKind_String:
   286         return String::cast(obj)->objSize();
   287 
   288       case MapKind_Native:
   289         return sizeof(Native);
   290 
   291       case MapKind_Array:
   292         return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
   293 
   294       case MapKind_Box:
   295         return sizeof(Box);
   296 
   297       case MapKind_Struct:
   298         return Struct::cast(obj)->objSize();
   299 
   300       case MapKind_EnvironmentSlotDescriptorArray:
   301         return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
   302 
   303       case MapKind_Environment:
   304         return Environment::cast(obj)->objSize();
   305 
   306       case MapKind_MetaArray:
   307         return sizeof(ArrayMap);
   308 
   309       case MapKind_MetaEnvironment:
   310         return EnvironmentMap::cast(obj)->objSize();
   311 
   312       case MapKind_MetaStruct:
   313         return StructMap::cast(obj)->objSize();
   314 
   315       case MapKind_FreeRegion:
   316         return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
   317 
   318       default:
   319         assert(map->kind() == MapKind_Meta);
   320         return sizeof(Map);
   321     }
   322 }
   323 
   324 static inline size_t
   325 SizeOfObject(Object *obj, Map *map)
   326 {
   327     return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
   328 }
   329 
   330 class ObjectSizeEvaluator
   331 {
   332   public:
   333     size_t operator()(Object *obj, Map *map) {
   334         return SizeOfObject(obj, map);
   335     }
   336 };
   337 
   338 }
   339 
   340 #endif // _include_jc_object_visitor_h_