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