Split ArrayType from Type.
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"
32 #include "Structures.h"
37 // An ObjectVisitor is used for traversing object references in the heap. Since
38 // this pattern must be lightning fast, we avoid virtual dispatch by forcing
39 // visitors to compose themselves with the visiting logic.
41 class ObjectVisitor : public T
44 void visitField(Object *obj, size_t offset) {
45 this->visit(reinterpret_cast<Object **>(Address(obj) + offset));
48 size_t iterateType(Object *obj) {
49 visitField(obj, Type::offsetOfName());
53 size_t iterateArrayType(Object *obj) {
55 visitField(obj, ArrayType::offsetOfContained());
56 visitField(obj, ArrayType::offsetOfNewMap());
57 return sizeof(ArrayType);
60 size_t iterateStructType(Object *obj) {
62 visitField(obj, StructType::offsetOfFields());
63 visitField(obj, StructType::offsetOfNewMap());
64 return sizeof(StructType);
67 size_t iterateFunctionType(Object *obj) {
69 visitField(obj, FunctionType::offsetOfReturnType());
70 visitField(obj, FunctionType::offsetOfParameters());
71 visitField(obj, FunctionType::offsetOfDefaults());
72 return sizeof(FunctionType);
75 size_t iterateFixedArray(FixedArray *array) {
76 unsigned length = array->length();
77 Object **ptr = reinterpret_cast<Object **>(array + 1);
78 for (unsigned i = 0; i < length; i++)
80 return array->objSize();
83 size_t iterateByteArray(ByteArray *array) {
84 return array->objSize();
87 size_t iterateCode(Object *obj) {
88 visitField(obj, Code::offsetOfModule());
89 visitField(obj, Code::offsetOfBytecode());
90 visitField(obj, Code::offsetOfLocals());
91 visitField(obj, Code::offsetOfObjects());
92 visitField(obj, Code::offsetOfSafepoints());
93 visitField(obj, Code::offsetOfSourceMap());
94 visitField(obj, Code::offsetOfStrings());
98 size_t iterateReference(Object *obj) {
99 visitField(obj, Reference::offsetOfBase());
100 return sizeof(Reference);
103 size_t iterateModule(Object *obj) {
104 visitField(obj, Module::offsetOfFile());
105 visitField(obj, Module::offsetOfGlobals());
106 visitField(obj, Module::offsetOfCode());
107 return sizeof(Module);
110 size_t iterateFunction(Object *obj) {
111 visitField(obj, Function::offsetOfCode());
112 visitField(obj, Function::offsetOfType());
113 visitField(obj, Function::offsetOfName());
114 return sizeof(Function);
117 size_t iterateDescriptor(Object *obj) {
118 visitField(obj, Descriptor::offsetOfName());
119 visitField(obj, Descriptor::offsetOfType());
120 return sizeof(Descriptor);
123 size_t iterateNative(Object *obj) {
124 visitField(obj, Native::offsetOfType());
125 return sizeof(Native);
128 size_t iterateString(Object *obj) {
129 return String::cast(obj)->objSize();
132 size_t iterateArray(Array *array, ArrayMap *map) {
133 if (!map->type()->fixedLength() || map->type()->contained()->isTraceable())
134 visitField(array, Array::offsetOfElements());
135 return array->objSize(map);
138 size_t iterateBox(Box *obj) {
139 visitField(obj, Box::offsetOfType());
140 if (obj->type()->isTraceable())
141 visitField(obj, Box::offsetOfObj());
145 size_t iterateArrayMap(ArrayMap *map) {
146 visitField(map, ArrayMap::offsetOfType());
147 return sizeof(ArrayMap);
150 size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
151 unsigned length = env->length();
152 EnvironmentSlotDescriptor *desc = env->slots();
153 for (unsigned i = 0; i < length; i++)
154 this->visit(desc->type.addr());
155 return env->objSize();
158 size_t iterateEnvironmentMap(EnvironmentMap *map) {
159 visitField(map, EnvironmentMap::offsetOfSlots());
160 return map->objSize();
163 size_t iterateStructMap(StructMap *map) {
164 visitField(map, StructMap::offsetOfType());
165 visitField(map, StructMap::offsetOfComposed());
166 return map->objSize();
169 size_t iterateEnvironment(Environment *env) {
170 EnvironmentMap *map = env->map();
171 const unsigned *offsets = map->traceOffsets();
172 unsigned noffsets = map->traceOffsetCount();
173 for (unsigned i = 0; i < noffsets; i++)
174 visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
175 return env->objSize();
178 size_t iterateStruct(Struct *obj) {
179 StructMap *map = obj->map();
180 const unsigned *offsets = map->traceOffsets();
181 unsigned noffsets = map->traceOffsetCount();
182 for (unsigned i = 0; i < noffsets; i++)
183 visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
184 return obj->objSize();
188 size_t iterateObject(Object *obj) {
189 visitField(obj, Object::offsetOfMap());
190 return iterate(obj, obj->map());
193 size_t iterateObject(Object *obj, Map *map) {
194 switch (map->kind()) {
196 return iterateType(obj);
198 case MapKind_ArrayType:
199 return iterateArrayType(obj);
201 case MapKind_FunctionType:
202 return iterateFunctionType(obj);
204 case MapKind_StructType:
205 return iterateStructType(obj);
207 case MapKind_FixedArray:
208 return iterateFixedArray(FixedArray::cast(obj));
210 case MapKind_ByteArray:
211 return iterateByteArray(ByteArray::cast(obj));
214 return iterateCode(obj);
216 case MapKind_Reference:
217 return iterateReference(obj);
220 return iterateModule(obj);
222 case MapKind_Function:
223 return iterateFunction(obj);
225 case MapKind_Descriptor:
226 return iterateDescriptor(obj);
229 return iterateString(obj);
232 return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
235 return iterateBox(Box::cast(obj));
238 return iterateStruct(Struct::cast(obj));
240 case MapKind_EnvironmentSlotDescriptorArray:
241 return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
243 case MapKind_Environment:
244 return iterateEnvironment(Environment::cast(obj));
247 return iterateNative(obj);
249 case MapKind_MetaArray:
250 return iterateArrayMap(ArrayMap::cast(obj));
252 case MapKind_MetaEnvironment:
253 return iterateEnvironmentMap(EnvironmentMap::cast(obj));
255 case MapKind_MetaStruct:
256 return iterateStructMap(StructMap::cast(obj));
259 assert(map->kind() == MapKind_Meta);
265 size_t iterate(Object *obj) {
266 return Align(iterateObject(obj), kObjectAlignment);
269 size_t iterate(Object *obj, Map *map) {
270 return Align(iterateObject(obj, map), kObjectAlignment);
275 SizeOfObjectRaw(Object *obj, Map *map)
277 switch (map->kind()) {
281 case MapKind_ArrayType:
282 return sizeof(ArrayType);
284 case MapKind_FunctionType:
285 return sizeof(FunctionType);
287 case MapKind_StructType:
288 return sizeof(StructType);
290 case MapKind_FixedArray:
291 return FixedArray::cast(obj)->objSize();
293 case MapKind_ByteArray:
294 return ByteArray::cast(obj)->objSize();
299 case MapKind_Reference:
300 return sizeof(Reference);
303 return sizeof(Module);
305 case MapKind_Descriptor:
306 return sizeof(Descriptor);
308 case MapKind_Function:
309 return sizeof(Function);
312 return String::cast(obj)->objSize();
315 return sizeof(Native);
318 return Align(Array::cast(obj)->objSize(ArrayMap::cast(map)), kObjectAlignment);
324 return Struct::cast(obj)->objSize();
326 case MapKind_EnvironmentSlotDescriptorArray:
327 return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
329 case MapKind_Environment:
330 return Environment::cast(obj)->objSize();
332 case MapKind_MetaArray:
333 return sizeof(ArrayMap);
335 case MapKind_MetaEnvironment:
336 return EnvironmentMap::cast(obj)->objSize();
338 case MapKind_MetaStruct:
339 return StructMap::cast(obj)->objSize();
341 case MapKind_FreeRegion:
342 return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
345 assert(map->kind() == MapKind_Meta);
351 SizeOfObject(Object *obj, Map *map)
353 return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
356 class ObjectSizeEvaluator
359 size_t operator()(Object *obj, Map *map) {
360 return SizeOfObject(obj, map);
366 #endif // _include_jc_object_visitor_h_