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