More const preparation: allow type casts to follow qualification.
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::offsetOfRoot());
53 size_t iterateEnumType(Object *obj) {
54 visitField(obj, EnumType::offsetOfName());
55 return sizeof(EnumType);
58 size_t iterateReferenceType(Object *obj) {
60 visitField(obj, ReferenceType::offsetOfContained());
61 return sizeof(ReferenceType);
64 size_t iterateArrayType(Object *obj) {
66 visitField(obj, ArrayType::offsetOfContained());
67 visitField(obj, ArrayType::offsetOfNewMap());
68 return sizeof(ArrayType);
71 size_t iterateStructType(Object *obj) {
73 visitField(obj, StructType::offsetOfFields());
74 visitField(obj, StructType::offsetOfNewMap());
75 visitField(obj, StructType::offsetOfName());
76 return sizeof(StructType);
79 size_t iterateFunctionType(Object *obj) {
81 visitField(obj, FunctionType::offsetOfReturnType());
82 visitField(obj, FunctionType::offsetOfParameters());
83 visitField(obj, FunctionType::offsetOfDefaults());
84 visitField(obj, FunctionType::offsetOfName());
85 return sizeof(FunctionType);
88 size_t iterateFixedArray(FixedArray *array) {
89 unsigned length = array->length();
90 Object **ptr = reinterpret_cast<Object **>(array + 1);
91 for (unsigned i = 0; i < length; i++)
93 return array->objSize();
96 size_t iterateByteArray(ByteArray *array) {
97 return array->objSize();
100 size_t iterateCode(Object *obj) {
101 visitField(obj, Code::offsetOfModule());
102 visitField(obj, Code::offsetOfBytecode());
103 visitField(obj, Code::offsetOfLocals());
104 visitField(obj, Code::offsetOfObjects());
105 visitField(obj, Code::offsetOfSafepoints());
106 visitField(obj, Code::offsetOfSourceMap());
107 visitField(obj, Code::offsetOfStrings());
111 size_t iterateReference(Object *obj) {
112 visitField(obj, Reference::offsetOfBase());
113 return sizeof(Reference);
116 size_t iterateModule(Object *obj) {
117 visitField(obj, Module::offsetOfFile());
118 visitField(obj, Module::offsetOfGlobals());
119 visitField(obj, Module::offsetOfCode());
120 return sizeof(Module);
123 size_t iterateFunction(Object *obj) {
124 visitField(obj, Function::offsetOfCode());
125 visitField(obj, Function::offsetOfType());
126 visitField(obj, Function::offsetOfName());
127 return sizeof(Function);
130 size_t iterateDescriptor(Object *obj) {
131 visitField(obj, Descriptor::offsetOfName());
132 visitField(obj, Descriptor::offsetOfType());
133 return sizeof(Descriptor);
136 size_t iterateNative(Object *obj) {
137 visitField(obj, Native::offsetOfType());
138 return sizeof(Native);
141 size_t iterateString(Object *obj) {
142 return String::cast(obj)->objSize();
145 size_t iterateArray(Array *array, ArrayMap *map) {
146 if (!map->type()->hasInlineElements())
147 visitField(array, Array::offsetOfElements());
148 return array->objSize(map);
151 size_t iterateBox(Box *obj) {
152 visitField(obj, Box::offsetOfType());
153 if (obj->type()->isTraceable())
154 visitField(obj, Box::offsetOfObj());
158 size_t iterateArrayMap(ArrayMap *map) {
159 visitField(map, ArrayMap::offsetOfType());
160 return sizeof(ArrayMap);
163 size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
164 unsigned length = env->length();
165 EnvironmentSlotDescriptor *desc = env->slots();
166 for (unsigned i = 0; i < length; i++)
167 this->visit(desc->type.addr());
168 return env->objSize();
171 size_t iterateEnvironmentMap(EnvironmentMap *map) {
172 visitField(map, EnvironmentMap::offsetOfSlots());
173 return map->objSize();
176 size_t iterateStructMap(StructMap *map) {
177 visitField(map, StructMap::offsetOfType());
178 visitField(map, StructMap::offsetOfComposed());
179 return map->objSize();
182 size_t iterateEnvironment(Environment *env) {
183 EnvironmentMap *map = env->map();
184 const unsigned *offsets = map->traceOffsets();
185 unsigned noffsets = map->traceOffsetCount();
186 for (unsigned i = 0; i < noffsets; i++)
187 visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
188 return env->objSize();
191 size_t iterateStruct(Struct *obj) {
192 StructMap *map = obj->map();
193 const unsigned *offsets = map->traceOffsets();
194 unsigned noffsets = map->traceOffsetCount();
195 for (unsigned i = 0; i < noffsets; i++)
196 visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
197 return obj->objSize();
201 size_t iterateObject(Object *obj) {
202 visitField(obj, Object::offsetOfMap());
203 return iterate(obj, obj->map());
206 size_t iterateObject(Object *obj, Map *map) {
207 switch (map->kind()) {
209 return iterateType(obj);
211 case MapKind_ReferenceType:
212 return iterateReferenceType(obj);
214 case MapKind_ArrayType:
215 return iterateArrayType(obj);
217 case MapKind_EnumType:
218 return iterateEnumType(obj);
220 case MapKind_FunctionType:
221 return iterateFunctionType(obj);
223 case MapKind_StructType:
224 return iterateStructType(obj);
226 case MapKind_FixedArray:
227 return iterateFixedArray(FixedArray::cast(obj));
229 case MapKind_ByteArray:
230 return iterateByteArray(ByteArray::cast(obj));
233 return iterateCode(obj);
235 case MapKind_Reference:
236 return iterateReference(obj);
239 return iterateModule(obj);
241 case MapKind_Function:
242 return iterateFunction(obj);
244 case MapKind_Descriptor:
245 return iterateDescriptor(obj);
248 return iterateString(obj);
251 return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
254 return iterateBox(Box::cast(obj));
257 return iterateStruct(Struct::cast(obj));
259 case MapKind_EnvironmentSlotDescriptorArray:
260 return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
262 case MapKind_Environment:
263 return iterateEnvironment(Environment::cast(obj));
266 return iterateNative(obj);
268 case MapKind_MetaArray:
269 return iterateArrayMap(ArrayMap::cast(obj));
271 case MapKind_MetaEnvironment:
272 return iterateEnvironmentMap(EnvironmentMap::cast(obj));
274 case MapKind_MetaStruct:
275 return iterateStructMap(StructMap::cast(obj));
278 assert(map->kind() == MapKind_Meta);
284 size_t iterate(Object *obj) {
285 return Align(iterateObject(obj), kObjectAlignment);
288 size_t iterate(Object *obj, Map *map) {
289 return Align(iterateObject(obj, map), kObjectAlignment);
294 SizeOfObjectRaw(Object *obj, Map *map)
296 switch (map->kind()) {
300 case MapKind_ReferenceType:
301 return sizeof(ReferenceType);
303 case MapKind_ArrayType:
304 return sizeof(ArrayType);
306 case MapKind_EnumType:
307 return sizeof(EnumType);
309 case MapKind_FunctionType:
310 return sizeof(FunctionType);
312 case MapKind_StructType:
313 return sizeof(StructType);
315 case MapKind_FixedArray:
316 return FixedArray::cast(obj)->objSize();
318 case MapKind_ByteArray:
319 return ByteArray::cast(obj)->objSize();
324 case MapKind_Reference:
325 return sizeof(Reference);
328 return sizeof(Module);
330 case MapKind_Descriptor:
331 return sizeof(Descriptor);
333 case MapKind_Function:
334 return sizeof(Function);
337 return String::cast(obj)->objSize();
340 return sizeof(Native);
343 return Align(Array::cast(obj)->objSize(ArrayMap::cast(map)), kObjectAlignment);
349 return Struct::cast(obj)->objSize();
351 case MapKind_EnvironmentSlotDescriptorArray:
352 return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
354 case MapKind_Environment:
355 return Environment::cast(obj)->objSize();
357 case MapKind_MetaArray:
358 return sizeof(ArrayMap);
360 case MapKind_MetaEnvironment:
361 return EnvironmentMap::cast(obj)->objSize();
363 case MapKind_MetaStruct:
364 return StructMap::cast(obj)->objSize();
366 case MapKind_FreeRegion:
367 return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
370 assert(map->kind() == MapKind_Meta);
376 SizeOfObject(Object *obj, Map *map)
378 return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
381 class ObjectSizeEvaluator
384 size_t operator()(Object *obj, Map *map) {
385 return SizeOfObject(obj, map);
391 #endif // _include_jc_object_visitor_h_