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.
dvander@45
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@45
     2
 *
dvander@45
     3
 * Copyright (C) 2012 David Anderson
dvander@45
     4
 *
dvander@45
     5
 * This file is part of JITCraft.
dvander@45
     6
 *
dvander@45
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@45
     8
 * the terms of the GNU General Public License as published by the Free
dvander@45
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@45
    10
 * any later version.
dvander@45
    11
 * 
dvander@45
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@45
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@45
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@45
    15
 *
dvander@45
    16
 * You should have received a copy of the GNU General Public License along with
dvander@45
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@45
    18
 */
dvander@45
    19
#ifndef _include_jc_object_visitor_h_
dvander@45
    20
#define _include_jc_object_visitor_h_
dvander@45
    21
dvander@45
    22
#include "Objects.h"
dvander@45
    23
#include "Types.h"
dvander@45
    24
#include "FixedArray.h"
dvander@45
    25
#include "Code.h"
dvander@45
    26
#include "Reference.h"
dvander@45
    27
#include "Modules.h"
dvander@45
    28
#include "Functions.h"
dvander@45
    29
#include "Array.h"
dvander@45
    30
dvander@45
    31
namespace jc {
dvander@45
    32
dvander@45
    33
// An ObjectVisitor is used for traversing object references in the heap. Since
dvander@45
    34
// this pattern must be lightning fast, we avoid virtual dispatch by forcing
dvander@45
    35
// visitors to compose themselves with the visiting logic.
dvander@45
    36
template <typename T>
dvander@45
    37
class ObjectVisitor : public T
dvander@45
    38
{
dvander@45
    39
  private:
dvander@45
    40
    void visitField(Object *obj, size_t offset) {
dvander@45
    41
        this->visit(reinterpret_cast<Object **>(Address(obj) + offset));
dvander@45
    42
    }
dvander@45
    43
dvander@45
    44
    size_t iterateType(Object *obj) {
dvander@45
    45
        visitField(obj, Type::offsetOfContained());
dvander@45
    46
        visitField(obj, Type::offsetOfReturnType());
dvander@45
    47
        visitField(obj, Type::offsetOfParameters());
dvander@45
    48
        return sizeof(Type);
dvander@45
    49
    }
dvander@45
    50
dvander@45
    51
    size_t iterateFixedArray(FixedArray *array) {
dvander@45
    52
        unsigned length = array->length();
dvander@45
    53
        Object **ptr = reinterpret_cast<Object **>(array + 1);
dvander@45
    54
        for (unsigned i = 0; i < length; i++)
dvander@45
    55
            this->visit(ptr + i);
dvander@45
    56
        return FixedArray::SizeFor(length);
dvander@45
    57
    }
dvander@45
    58
dvander@45
    59
    size_t iterateByteArray(ByteArray *array) {
dvander@45
    60
        return ByteArray::SizeFor(array->length());
dvander@45
    61
    }
dvander@45
    62
dvander@45
    63
    size_t iterateCode(Object *obj) {
dvander@45
    64
        visitField(obj, Code::offsetOfModule());
dvander@45
    65
        visitField(obj, Code::offsetOfBytecode());
dvander@45
    66
        visitField(obj, Code::offsetOfLocals());
dvander@45
    67
        visitField(obj, Code::offsetOfObjects());
dvander@53
    68
        visitField(obj, Code::offsetOfSafepoints());
dvander@45
    69
        return sizeof(Code);
dvander@45
    70
    }
dvander@45
    71
dvander@45
    72
    size_t iterateReference(Object *obj) {
dvander@45
    73
        visitField(obj, Reference::offsetOfBase());
dvander@45
    74
        return sizeof(Reference);
dvander@45
    75
    }
dvander@45
    76
dvander@45
    77
    size_t iterateModule(Object *obj) {
dvander@45
    78
        visitField(obj, Module::offsetOfFunctions());
dvander@45
    79
        return sizeof(Module);
dvander@45
    80
    }
dvander@45
    81
dvander@45
    82
    size_t iterateFunction(Object *obj) {
dvander@52
    83
        visitField(obj, Function::offsetOfModule());
dvander@52
    84
        visitField(obj, Function::offsetOfCode());
dvander@52
    85
        visitField(obj, Function::offsetOfType());
dvander@45
    86
        return sizeof(Function);
dvander@45
    87
    }
dvander@45
    88
dvander@45
    89
    size_t iterateArray(Array *array, ArrayMap *map) {
dvander@45
    90
        if (map->type()->isArray()) {
dvander@45
    91
            unsigned length = array->nelements();
dvander@45
    92
            Object **vec = array->objVec();
dvander@45
    93
            for (unsigned i = 0; i < length; i++)
dvander@45
    94
                this->visit(vec + i);
dvander@45
    95
        }
dvander@45
    96
        return Array::SizeOf(array);
dvander@45
    97
    }
dvander@45
    98
dvander@45
    99
    size_t iterateArrayMap(ArrayMap *map) {
dvander@52
   100
        visitField(map, ArrayMap::offsetOfType());
dvander@52
   101
        visitField(map, ArrayMap::offsetOfContained());
dvander@45
   102
        return sizeof(ArrayMap);
dvander@45
   103
    }
dvander@45
   104
dvander@45
   105
  public:
dvander@52
   106
    size_t iterate(Object *obj) {
dvander@52
   107
        visitField(obj, Object::offsetOfMap());
dvander@52
   108
        return iterate(obj, obj->map());
dvander@52
   109
    }
dvander@52
   110
dvander@45
   111
    size_t iterate(Object *obj, Map *map) {
dvander@45
   112
        switch (map->kind()) {
dvander@45
   113
          case MapKind_Type:
dvander@45
   114
            return iterateType(obj);
dvander@45
   115
dvander@45
   116
          case MapKind_FixedArray:
dvander@45
   117
            return iterateFixedArray(FixedArray::cast(obj));
dvander@45
   118
dvander@45
   119
          case MapKind_ByteArray:
dvander@53
   120
            return Align(iterateByteArray(ByteArray::cast(obj)), kObjectAlignment);
dvander@45
   121
dvander@45
   122
          case MapKind_Code:
dvander@45
   123
            return iterateCode(obj);
dvander@45
   124
dvander@45
   125
          case MapKind_Reference:
dvander@45
   126
            return iterateReference(obj);
dvander@45
   127
dvander@45
   128
          case MapKind_Module:
dvander@45
   129
            return iterateModule(obj);
dvander@45
   130
dvander@45
   131
          case MapKind_Function:
dvander@45
   132
            return iterateFunction(obj);
dvander@45
   133
dvander@45
   134
          case MapKind_Array:
dvander@53
   135
            return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
dvander@45
   136
dvander@45
   137
          case MapKind_MetaArray:
dvander@52
   138
            return iterateArrayMap(ArrayMap::cast(obj));
dvander@45
   139
dvander@45
   140
          default:
dvander@45
   141
            assert(map->kind() == MapKind_Meta);
dvander@52
   142
            return sizeof(Map);
dvander@45
   143
        }
dvander@45
   144
    }
dvander@45
   145
};
dvander@45
   146
dvander@53
   147
static inline size_t
dvander@53
   148
SizeOfObject(Object *obj, Map *map)
dvander@53
   149
{
dvander@53
   150
    switch (map->kind()) {
dvander@53
   151
      case MapKind_Type:
dvander@53
   152
        return sizeof(Type);
dvander@53
   153
dvander@53
   154
      case MapKind_FixedArray:
dvander@53
   155
        return FixedArray::SizeFor(FixedArray::cast(obj)->length());
dvander@53
   156
dvander@53
   157
      case MapKind_ByteArray:
dvander@53
   158
        return Align(ByteArray::SizeFor(ByteArray::cast(obj)->length()), kObjectAlignment);
dvander@53
   159
dvander@53
   160
      case MapKind_Code:
dvander@53
   161
        return sizeof(Code);
dvander@53
   162
dvander@53
   163
      case MapKind_Reference:
dvander@53
   164
        return sizeof(Reference);
dvander@53
   165
dvander@53
   166
      case MapKind_Module:
dvander@53
   167
        return sizeof(Module);
dvander@53
   168
dvander@53
   169
      case MapKind_Function:
dvander@53
   170
        return sizeof(Function);
dvander@53
   171
dvander@53
   172
      case MapKind_Array:
dvander@53
   173
        return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
dvander@53
   174
dvander@53
   175
      case MapKind_MetaArray:
dvander@53
   176
        return sizeof(ArrayMap);
dvander@53
   177
dvander@53
   178
      case MapKind_FreeRegion:
dvander@53
   179
        return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
dvander@53
   180
dvander@53
   181
      default:
dvander@53
   182
        assert(map->kind() == MapKind_Meta);
dvander@53
   183
        return sizeof(Map);
dvander@53
   184
    }
dvander@53
   185
}
dvander@53
   186
dvander@53
   187
class ObjectSizeEvaluator
dvander@53
   188
{
dvander@53
   189
  public:
dvander@53
   190
    size_t operator()(Object *obj, Map *map) {
dvander@53
   191
        return SizeOfObject(obj, map);
dvander@53
   192
    }
dvander@53
   193
};
dvander@53
   194
dvander@45
   195
}
dvander@45
   196
dvander@45
   197
#endif // _include_jc_object_visitor_h_