Re-add enum support.
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) {
52 size_t iterateEnumType(Object *obj) {
53 visitField(obj, EnumType::offsetOfName());
54 return sizeof(EnumType);
57 size_t iterateReferenceType(Object *obj) {
59 visitField(obj, ReferenceType::offsetOfContained());
60 return sizeof(ReferenceType);
63 size_t iterateArrayType(Object *obj) {
65 visitField(obj, ArrayType::offsetOfContained());
66 visitField(obj, ArrayType::offsetOfNewMap());
67 return sizeof(ArrayType);
70 size_t iterateStructType(Object *obj) {
72 visitField(obj, StructType::offsetOfFields());
73 visitField(obj, StructType::offsetOfNewMap());
74 visitField(obj, StructType::offsetOfName());
75 return sizeof(StructType);
78 size_t iterateFunctionType(Object *obj) {
80 visitField(obj, FunctionType::offsetOfReturnType());
81 visitField(obj, FunctionType::offsetOfParameters());
82 visitField(obj, FunctionType::offsetOfDefaults());
83 visitField(obj, FunctionType::offsetOfName());
84 return sizeof(FunctionType);
87 size_t iterateFixedArray(FixedArray *array) {
88 unsigned length = array->length();
89 Object **ptr = reinterpret_cast<Object **>(array + 1);
90 for (unsigned i = 0; i < length; i++)
92 return array->objSize();
95 size_t iterateByteArray(ByteArray *array) {
96 return array->objSize();
99 size_t iterateCode(Object *obj) {
100 visitField(obj, Code::offsetOfModule());
101 visitField(obj, Code::offsetOfBytecode());
102 visitField(obj, Code::offsetOfLocals());
103 visitField(obj, Code::offsetOfObjects());
104 visitField(obj, Code::offsetOfSafepoints());
105 visitField(obj, Code::offsetOfSourceMap());
106 visitField(obj, Code::offsetOfStrings());
110 size_t iterateReference(Object *obj) {
111 visitField(obj, Reference::offsetOfBase());
112 return sizeof(Reference);
115 size_t iterateModule(Object *obj) {
116 visitField(obj, Module::offsetOfFile());
117 visitField(obj, Module::offsetOfGlobals());
118 visitField(obj, Module::offsetOfCode());
119 return sizeof(Module);
122 size_t iterateFunction(Object *obj) {
123 visitField(obj, Function::offsetOfCode());
124 visitField(obj, Function::offsetOfType());
125 visitField(obj, Function::offsetOfName());
126 return sizeof(Function);
129 size_t iterateDescriptor(Object *obj) {
130 visitField(obj, Descriptor::offsetOfName());
131 visitField(obj, Descriptor::offsetOfType());
132 return sizeof(Descriptor);
135 size_t iterateNative(Object *obj) {
136 visitField(obj, Native::offsetOfType());
137 return sizeof(Native);
140 size_t iterateString(Object *obj) {
141 return String::cast(obj)->objSize();
144 size_t iterateArray(Array *array, ArrayMap *map) {
145 if (!map->type()->fixedLength() || map->type()->contained()->isTraceable())
146 visitField(array, Array::offsetOfElements());
147 return array->objSize(map);
150 size_t iterateBox(Box *obj) {
151 visitField(obj, Box::offsetOfType());
152 if (obj->type()->isTraceable())
153 visitField(obj, Box::offsetOfObj());
157 size_t iterateArrayMap(ArrayMap *map) {
158 visitField(map, ArrayMap::offsetOfType());
159 return sizeof(ArrayMap);
162 size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
163 unsigned length = env->length();
164 EnvironmentSlotDescriptor *desc = env->slots();
165 for (unsigned i = 0; i < length; i++)
166 this->visit(desc->type.addr());
167 return env->objSize();
170 size_t iterateEnvironmentMap(EnvironmentMap *map) {
171 visitField(map, EnvironmentMap::offsetOfSlots());
172 return map->objSize();
175 size_t iterateStructMap(StructMap *map) {
176 visitField(map, StructMap::offsetOfType());
177 visitField(map, StructMap::offsetOfComposed());
178 return map->objSize();
181 size_t iterateEnvironment(Environment *env) {
182 EnvironmentMap *map = env->map();
183 const unsigned *offsets = map->traceOffsets();
184 unsigned noffsets = map->traceOffsetCount();
185 for (unsigned i = 0; i < noffsets; i++)
186 visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
187 return env->objSize();
190 size_t iterateStruct(Struct *obj) {
191 StructMap *map = obj->map();
192 const unsigned *offsets = map->traceOffsets();
193 unsigned noffsets = map->traceOffsetCount();
194 for (unsigned i = 0; i < noffsets; i++)
195 visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
196 return obj->objSize();
200 size_t iterateObject(Object *obj) {
201 visitField(obj, Object::offsetOfMap());
202 return iterate(obj, obj->map());
205 size_t iterateObject(Object *obj, Map *map) {
206 switch (map->kind()) {
208 return iterateType(obj);
210 case MapKind_ReferenceType:
211 return iterateReferenceType(obj);
213 case MapKind_ArrayType:
214 return iterateArrayType(obj);
216 case MapKind_EnumType:
217 return iterateEnumType(obj);
219 case MapKind_FunctionType:
220 return iterateFunctionType(obj);
222 case MapKind_StructType:
223 return iterateStructType(obj);
225 case MapKind_FixedArray:
226 return iterateFixedArray(FixedArray::cast(obj));
228 case MapKind_ByteArray:
229 return iterateByteArray(ByteArray::cast(obj));
232 return iterateCode(obj);
234 case MapKind_Reference:
235 return iterateReference(obj);
238 return iterateModule(obj);
240 case MapKind_Function:
241 return iterateFunction(obj);
243 case MapKind_Descriptor:
244 return iterateDescriptor(obj);
247 return iterateString(obj);
250 return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
253 return iterateBox(Box::cast(obj));
256 return iterateStruct(Struct::cast(obj));
258 case MapKind_EnvironmentSlotDescriptorArray:
259 return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
261 case MapKind_Environment:
262 return iterateEnvironment(Environment::cast(obj));
265 return iterateNative(obj);
267 case MapKind_MetaArray:
268 return iterateArrayMap(ArrayMap::cast(obj));
270 case MapKind_MetaEnvironment:
271 return iterateEnvironmentMap(EnvironmentMap::cast(obj));
273 case MapKind_MetaStruct:
274 return iterateStructMap(StructMap::cast(obj));
277 assert(map->kind() == MapKind_Meta);
283 size_t iterate(Object *obj) {
284 return Align(iterateObject(obj), kObjectAlignment);
287 size_t iterate(Object *obj, Map *map) {
288 return Align(iterateObject(obj, map), kObjectAlignment);
293 SizeOfObjectRaw(Object *obj, Map *map)
295 switch (map->kind()) {
299 case MapKind_ReferenceType:
300 return sizeof(ReferenceType);
302 case MapKind_ArrayType:
303 return sizeof(ArrayType);
305 case MapKind_EnumType:
306 return sizeof(EnumType);
308 case MapKind_FunctionType:
309 return sizeof(FunctionType);
311 case MapKind_StructType:
312 return sizeof(StructType);
314 case MapKind_FixedArray:
315 return FixedArray::cast(obj)->objSize();
317 case MapKind_ByteArray:
318 return ByteArray::cast(obj)->objSize();
323 case MapKind_Reference:
324 return sizeof(Reference);
327 return sizeof(Module);
329 case MapKind_Descriptor:
330 return sizeof(Descriptor);
332 case MapKind_Function:
333 return sizeof(Function);
336 return String::cast(obj)->objSize();
339 return sizeof(Native);
342 return Align(Array::cast(obj)->objSize(ArrayMap::cast(map)), kObjectAlignment);
348 return Struct::cast(obj)->objSize();
350 case MapKind_EnvironmentSlotDescriptorArray:
351 return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
353 case MapKind_Environment:
354 return Environment::cast(obj)->objSize();
356 case MapKind_MetaArray:
357 return sizeof(ArrayMap);
359 case MapKind_MetaEnvironment:
360 return EnvironmentMap::cast(obj)->objSize();
362 case MapKind_MetaStruct:
363 return StructMap::cast(obj)->objSize();
365 case MapKind_FreeRegion:
366 return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
369 assert(map->kind() == MapKind_Meta);
375 SizeOfObject(Object *obj, Map *map)
377 return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
380 class ObjectSizeEvaluator
383 size_t operator()(Object *obj, Map *map) {
384 return SizeOfObject(obj, map);
390 #endif // _include_jc_object_visitor_h_