jitcraft/ObjectVisitor.h
author David Anderson <dvander@alliedmods.net>
Thu Jul 12 00:38:00 2012 -0700 (2012-07-12)
changeset 70 1aec996cde2d
parent 68 b40b0e18a918
child 72 40746ab0a30b
permissions -rw-r--r--
Add support for line and file information in backtraces.
     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 
    32 namespace ke {
    33 
    34 // An ObjectVisitor is used for traversing object references in the heap. Since
    35 // this pattern must be lightning fast, we avoid virtual dispatch by forcing
    36 // visitors to compose themselves with the visiting logic.
    37 template <typename T>
    38 class ObjectVisitor : public T
    39 {
    40   private:
    41     void visitField(Object *obj, size_t offset) {
    42         this->visit(reinterpret_cast<Object **>(Address(obj) + offset));
    43     }
    44 
    45     size_t iterateType(Object *obj) {
    46         visitField(obj, Type::offsetOfContained());
    47         visitField(obj, Type::offsetOfReturnType());
    48         visitField(obj, Type::offsetOfParameters());
    49         visitField(obj, Type::offsetOfTag());
    50         return sizeof(Type);
    51     }
    52 
    53     size_t iterateFixedArray(FixedArray *array) {
    54         unsigned length = array->length();
    55         Object **ptr = reinterpret_cast<Object **>(array + 1);
    56         for (unsigned i = 0; i < length; i++)
    57             this->visit(ptr + i);
    58         return FixedArray::SizeFor(length);
    59     }
    60 
    61     size_t iterateByteArray(ByteArray *array) {
    62         return ByteArray::SizeFor(array->length());
    63     }
    64 
    65     size_t iterateCode(Object *obj) {
    66         visitField(obj, Code::offsetOfModule());
    67         visitField(obj, Code::offsetOfBytecode());
    68         visitField(obj, Code::offsetOfLocals());
    69         visitField(obj, Code::offsetOfObjects());
    70         visitField(obj, Code::offsetOfSafepoints());
    71         visitField(obj, Code::offsetOfSourceMap());
    72         return sizeof(Code);
    73     }
    74 
    75     size_t iterateReference(Object *obj) {
    76         visitField(obj, Reference::offsetOfBase());
    77         return sizeof(Reference);
    78     }
    79 
    80     size_t iterateModule(Object *obj) {
    81         visitField(obj, Module::offsetOfFunctions());
    82         visitField(obj, Module::offsetOfPublics());
    83         visitField(obj, Module::offsetOfNatives());
    84         visitField(obj, Module::offsetOfFile());
    85         return sizeof(Module);
    86     }
    87 
    88     size_t iterateFunction(Object *obj) {
    89         visitField(obj, Function::offsetOfCode());
    90         visitField(obj, Function::offsetOfType());
    91         visitField(obj, Function::offsetOfName());
    92         return sizeof(Function);
    93     }
    94 
    95     size_t iterateNative(Object *obj) {
    96         visitField(obj, Native::offsetOfType());
    97         visitField(obj, Native::offsetOfName());
    98         return sizeof(Native);
    99     }
   100 
   101     size_t iterateString(Object *obj) {
   102         return String::SizeFor(String::cast(obj)->length());
   103     }
   104 
   105     size_t iterateArray(Array *array, ArrayMap *map) {
   106         if (map->type()->isArray()) {
   107             unsigned length = array->nelements();
   108             Object **vec = array->objVec();
   109             for (unsigned i = 0; i < length; i++)
   110                 this->visit(vec + i);
   111         }
   112         return Array::SizeOf(array);
   113     }
   114 
   115     size_t iterateArrayMap(ArrayMap *map) {
   116         visitField(map, ArrayMap::offsetOfType());
   117         visitField(map, ArrayMap::offsetOfContained());
   118         return sizeof(ArrayMap);
   119     }
   120 
   121   public:
   122     size_t iterate(Object *obj) {
   123         visitField(obj, Object::offsetOfMap());
   124         return iterate(obj, obj->map());
   125     }
   126 
   127     size_t iterate(Object *obj, Map *map) {
   128         switch (map->kind()) {
   129           case MapKind_Type:
   130             return iterateType(obj);
   131 
   132           case MapKind_FixedArray:
   133             return iterateFixedArray(FixedArray::cast(obj));
   134 
   135           case MapKind_ByteArray:
   136             return iterateByteArray(ByteArray::cast(obj));
   137 
   138           case MapKind_Code:
   139             return iterateCode(obj);
   140 
   141           case MapKind_Reference:
   142             return iterateReference(obj);
   143 
   144           case MapKind_Module:
   145             return iterateModule(obj);
   146 
   147           case MapKind_Function:
   148             return iterateFunction(obj);
   149 
   150           case MapKind_String:
   151             return iterateString(obj);
   152 
   153           case MapKind_Array:
   154             return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
   155 
   156           case MapKind_Native:
   157             return iterateNative(obj);
   158 
   159           case MapKind_MetaArray:
   160             return iterateArrayMap(ArrayMap::cast(obj));
   161 
   162           default:
   163             assert(map->kind() == MapKind_Meta);
   164             return sizeof(Map);
   165         }
   166     }
   167 };
   168 
   169 static inline size_t
   170 SizeOfObject(Object *obj, Map *map)
   171 {
   172     switch (map->kind()) {
   173       case MapKind_Type:
   174         return sizeof(Type);
   175 
   176       case MapKind_FixedArray:
   177         return FixedArray::SizeFor(FixedArray::cast(obj)->length());
   178 
   179       case MapKind_ByteArray:
   180         return ByteArray::SizeFor(ByteArray::cast(obj)->length());
   181 
   182       case MapKind_Code:
   183         return sizeof(Code);
   184 
   185       case MapKind_Reference:
   186         return sizeof(Reference);
   187 
   188       case MapKind_Module:
   189         return sizeof(Module);
   190 
   191       case MapKind_Function:
   192         return sizeof(Function);
   193 
   194       case MapKind_String:
   195         return String::SizeFor(String::cast(obj)->length());
   196 
   197       case MapKind_Native:
   198         return sizeof(Native);
   199 
   200       case MapKind_Array:
   201         return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
   202 
   203       case MapKind_MetaArray:
   204         return sizeof(ArrayMap);
   205 
   206       case MapKind_FreeRegion:
   207         return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
   208 
   209       default:
   210         assert(map->kind() == MapKind_Meta);
   211         return sizeof(Map);
   212     }
   213 }
   214 
   215 class ObjectSizeEvaluator
   216 {
   217   public:
   218     size_t operator()(Object *obj, Map *map) {
   219         return SizeOfObject(obj, map);
   220     }
   221 };
   222 
   223 }
   224 
   225 #endif // _include_jc_object_visitor_h_