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:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
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)
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.
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/.
19 #ifndef _include_jc_object_visitor_h_
20 #define _include_jc_object_visitor_h_
24 #include "FixedArray.h"
26 #include "Reference.h"
28 #include "Functions.h"
31 #include "Environments.h"
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.
39 class ObjectVisitor : public T
42 void visitField(Object *obj, size_t offset) {
43 this->visit(reinterpret_cast<Object **>(Address(obj) + offset));
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());
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++)
59 return FixedArray::SizeFor(length);
62 size_t iterateByteArray(ByteArray *array) {
63 return ByteArray::SizeFor(array->length());
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());
76 size_t iterateReference(Object *obj) {
77 visitField(obj, Reference::offsetOfBase());
78 return sizeof(Reference);
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);
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);
98 size_t iterateNative(Object *obj) {
99 visitField(obj, Native::offsetOfType());
100 visitField(obj, Native::offsetOfName());
101 return sizeof(Native);
104 size_t iterateString(Object *obj) {
105 return String::SizeFor(String::cast(obj)->length());
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);
116 return Array::SizeOf(array);
119 size_t iterateArrayMap(ArrayMap *map) {
120 visitField(map, ArrayMap::offsetOfType());
121 visitField(map, ArrayMap::offsetOfContained());
122 return sizeof(ArrayMap);
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());
133 size_t iterateEnvironmentMap(EnvironmentMap *map) {
134 visitField(map, EnvironmentMap::offsetOfSlots());
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]));
148 size_t iterate(Object *obj) {
149 visitField(obj, Object::offsetOfMap());
150 return iterate(obj, obj->map());
153 size_t iterate(Object *obj, Map *map) {
154 switch (map->kind()) {
156 return iterateType(obj);
158 case MapKind_FixedArray:
159 return iterateFixedArray(FixedArray::cast(obj));
161 case MapKind_ByteArray:
162 return iterateByteArray(ByteArray::cast(obj));
165 return iterateCode(obj);
167 case MapKind_Reference:
168 return iterateReference(obj);
171 return iterateModule(obj);
173 case MapKind_Function:
174 return iterateFunction(obj);
177 return iterateString(obj);
180 return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
182 case MapKind_EnvironmentSlotDescriptorArray:
183 return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
185 case MapKind_Environment:
186 return iterateEnvironment(Environment::cast(obj));
189 return iterateNative(obj);
191 case MapKind_MetaArray:
192 return iterateArrayMap(ArrayMap::cast(obj));
194 case MapKind_MetaEnvironment:
195 return iterateEnvironmentMap(EnvironmentMap::cast(obj));
198 assert(map->kind() == MapKind_Meta);
205 SizeOfObject(Object *obj, Map *map)
207 switch (map->kind()) {
211 case MapKind_FixedArray:
212 return FixedArray::SizeFor(FixedArray::cast(obj)->length());
214 case MapKind_ByteArray:
215 return ByteArray::SizeFor(ByteArray::cast(obj)->length());
220 case MapKind_Reference:
221 return sizeof(Reference);
224 return sizeof(Module);
226 case MapKind_Function:
227 return sizeof(Function);
230 return String::SizeFor(String::cast(obj)->length());
233 return sizeof(Native);
236 return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
238 case MapKind_EnvironmentSlotDescriptorArray:
239 return EnvironmentSlotDescriptorArray::cast(obj)->size();
241 case MapKind_Environment:
242 return Environment::cast(obj)->size();
244 case MapKind_MetaArray:
245 return sizeof(ArrayMap);
247 case MapKind_MetaEnvironment:
248 return EnvironmentMap::cast(obj)->size();
250 case MapKind_FreeRegion:
251 return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
254 assert(map->kind() == MapKind_Meta);
259 class ObjectSizeEvaluator
262 size_t operator()(Object *obj, Map *map) {
263 return SizeOfObject(obj, map);
269 #endif // _include_jc_object_visitor_h_