src/ObjectVisitor.h
author David Anderson <danderson@mozilla.com>
Wed Jul 25 00:48:08 2012 -0700 (2012-07-25)
changeset 91 5f4402180204
parent 86 32ad0523b309
child 145 e9d804821c48
permissions -rw-r--r--
Added clang support. A lot of the motion here is introducing a new offsetof because clang's seems broken?
     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 
    33 namespace ke {
    34 
    35 // An ObjectVisitor is used for traversing object references in the heap. Since
    36 // this pattern must be lightning fast, we avoid virtual dispatch by forcing
    37 // visitors to compose themselves with the visiting logic.
    38 template <typename T>
    39 class ObjectVisitor : public T
    40 {
    41   private:
    42     void visitField(Object *obj, size_t offset) {
    43         this->visit(reinterpret_cast<Object **>(Address(obj) + offset));
    44     }
    45 
    46     size_t iterateType(Object *obj) {
    47         visitField(obj, Type::offsetOfContained());
    48         visitField(obj, Type::offsetOfReturnType());
    49         visitField(obj, Type::offsetOfParameters());
    50         visitField(obj, Type::offsetOfTag());
    51         return sizeof(Type);
    52     }
    53 
    54     size_t iterateFixedArray(FixedArray *array) {
    55         unsigned length = array->length();
    56         Object **ptr = reinterpret_cast<Object **>(array + 1);
    57         for (unsigned i = 0; i < length; i++)
    58             this->visit(ptr + i);
    59         return FixedArray::SizeFor(length);
    60     }
    61 
    62     size_t iterateByteArray(ByteArray *array) {
    63         return ByteArray::SizeFor(array->length());
    64     }
    65 
    66     size_t iterateCode(Object *obj) {
    67         visitField(obj, Code::offsetOfModule());
    68         visitField(obj, Code::offsetOfBytecode());
    69         visitField(obj, Code::offsetOfLocals());
    70         visitField(obj, Code::offsetOfObjects());
    71         visitField(obj, Code::offsetOfSafepoints());
    72         visitField(obj, Code::offsetOfSourceMap());
    73         return sizeof(Code);
    74     }
    75 
    76     size_t iterateReference(Object *obj) {
    77         visitField(obj, Reference::offsetOfBase());
    78         return sizeof(Reference);
    79     }
    80 
    81     size_t iterateModule(Object *obj) {
    82         visitField(obj, Module::offsetOfFunctions());
    83         visitField(obj, Module::offsetOfPublics());
    84         visitField(obj, Module::offsetOfNatives());
    85         visitField(obj, Module::offsetOfFile());
    86         visitField(obj, Module::offsetOfEnvironment());
    87         visitField(obj, Module::offsetOfCode());
    88         return sizeof(Module);
    89     }
    90 
    91     size_t iterateFunction(Object *obj) {
    92         visitField(obj, Function::offsetOfCode());
    93         visitField(obj, Function::offsetOfType());
    94         visitField(obj, Function::offsetOfName());
    95         return sizeof(Function);
    96     }
    97 
    98     size_t iterateNative(Object *obj) {
    99         visitField(obj, Native::offsetOfType());
   100         visitField(obj, Native::offsetOfName());
   101         return sizeof(Native);
   102     }
   103 
   104     size_t iterateString(Object *obj) {
   105         return String::SizeFor(String::cast(obj)->length());
   106     }
   107 
   108     size_t iterateArray(Array *array, ArrayMap *map) {
   109         assert(map->type()->isArray());
   110         if (map->contained()) {
   111             unsigned length = array->nelements();
   112             Object **vec = array->objVec();
   113             for (unsigned i = 0; i < length; i++)
   114                 this->visit(vec + i);
   115         }
   116         return Array::SizeOf(array);
   117     }
   118 
   119     size_t iterateArrayMap(ArrayMap *map) {
   120         visitField(map, ArrayMap::offsetOfType());
   121         visitField(map, ArrayMap::offsetOfContained());
   122         return sizeof(ArrayMap);
   123     }
   124 
   125     size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
   126         unsigned length = env->length();
   127         EnvironmentSlotDescriptor *desc = env->slots();
   128         for (unsigned i = 0; i < length; i++)
   129             this->visit(desc->type.addr());
   130         return env->size();
   131     }
   132 
   133     size_t iterateEnvironmentMap(EnvironmentMap *map) {
   134         visitField(map, EnvironmentMap::offsetOfSlots());
   135         return map->size();
   136     }
   137 
   138     size_t iterateEnvironment(Environment *env) {
   139         EnvironmentMap *map = env->map();
   140         const unsigned *offsets = map->traceOffsets();
   141         unsigned noffsets = map->traceOffsetCount();
   142         for (unsigned i = 0; i < noffsets; i++)
   143             visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
   144         return env->size();
   145     }
   146 
   147   public:
   148     size_t iterate(Object *obj) {
   149         visitField(obj, Object::offsetOfMap());
   150         return iterate(obj, obj->map());
   151     }
   152 
   153     size_t iterate(Object *obj, Map *map) {
   154         switch (map->kind()) {
   155           case MapKind_Type:
   156             return iterateType(obj);
   157 
   158           case MapKind_FixedArray:
   159             return iterateFixedArray(FixedArray::cast(obj));
   160 
   161           case MapKind_ByteArray:
   162             return iterateByteArray(ByteArray::cast(obj));
   163 
   164           case MapKind_Code:
   165             return iterateCode(obj);
   166 
   167           case MapKind_Reference:
   168             return iterateReference(obj);
   169 
   170           case MapKind_Module:
   171             return iterateModule(obj);
   172 
   173           case MapKind_Function:
   174             return iterateFunction(obj);
   175 
   176           case MapKind_String:
   177             return iterateString(obj);
   178 
   179           case MapKind_Array:
   180             return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
   181 
   182           case MapKind_EnvironmentSlotDescriptorArray:
   183             return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
   184 
   185           case MapKind_Environment:
   186             return iterateEnvironment(Environment::cast(obj));
   187 
   188           case MapKind_Native:
   189             return iterateNative(obj);
   190 
   191           case MapKind_MetaArray:
   192             return iterateArrayMap(ArrayMap::cast(obj));
   193 
   194           case MapKind_MetaEnvironment:
   195             return iterateEnvironmentMap(EnvironmentMap::cast(obj));
   196 
   197           default:
   198             assert(map->kind() == MapKind_Meta);
   199             return sizeof(Map);
   200         }
   201     }
   202 };
   203 
   204 static inline size_t
   205 SizeOfObject(Object *obj, Map *map)
   206 {
   207     switch (map->kind()) {
   208       case MapKind_Type:
   209         return sizeof(Type);
   210 
   211       case MapKind_FixedArray:
   212         return FixedArray::SizeFor(FixedArray::cast(obj)->length());
   213 
   214       case MapKind_ByteArray:
   215         return ByteArray::SizeFor(ByteArray::cast(obj)->length());
   216 
   217       case MapKind_Code:
   218         return sizeof(Code);
   219 
   220       case MapKind_Reference:
   221         return sizeof(Reference);
   222 
   223       case MapKind_Module:
   224         return sizeof(Module);
   225 
   226       case MapKind_Function:
   227         return sizeof(Function);
   228 
   229       case MapKind_String:
   230         return String::SizeFor(String::cast(obj)->length());
   231 
   232       case MapKind_Native:
   233         return sizeof(Native);
   234 
   235       case MapKind_Array:
   236         return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
   237 
   238       case MapKind_EnvironmentSlotDescriptorArray:
   239         return EnvironmentSlotDescriptorArray::cast(obj)->size();
   240 
   241       case MapKind_Environment:
   242         return Environment::cast(obj)->size();
   243 
   244       case MapKind_MetaArray:
   245         return sizeof(ArrayMap);
   246 
   247       case MapKind_MetaEnvironment:
   248         return EnvironmentMap::cast(obj)->size();
   249 
   250       case MapKind_FreeRegion:
   251         return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
   252 
   253       default:
   254         assert(map->kind() == MapKind_Meta);
   255         return sizeof(Map);
   256     }
   257 }
   258 
   259 class ObjectSizeEvaluator
   260 {
   261   public:
   262     size_t operator()(Object *obj, Map *map) {
   263         return SizeOfObject(obj, map);
   264     }
   265 };
   266 
   267 }
   268 
   269 #endif // _include_jc_object_visitor_h_