Re-add LIFO stack optimizations.
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 iterateReferenceType(Object *obj) {
55 visitField(obj, ReferenceType::offsetOfContained());
56 return sizeof(ReferenceType);
59 size_t iterateArrayType(Object *obj) {
61 visitField(obj, ArrayType::offsetOfContained());
62 visitField(obj, ArrayType::offsetOfNewMap());
63 return sizeof(ArrayType);
66 size_t iterateStructType(Object *obj) {
68 visitField(obj, StructType::offsetOfFields());
69 visitField(obj, StructType::offsetOfNewMap());
70 return sizeof(StructType);
73 size_t iterateFunctionType(Object *obj) {
75 visitField(obj, FunctionType::offsetOfReturnType());
76 visitField(obj, FunctionType::offsetOfParameters());
77 visitField(obj, FunctionType::offsetOfDefaults());
78 return sizeof(FunctionType);
81 size_t iterateFixedArray(FixedArray *array) {
82 unsigned length = array->length();
83 Object **ptr = reinterpret_cast<Object **>(array + 1);
84 for (unsigned i = 0; i < length; i++)
86 return array->objSize();
89 size_t iterateByteArray(ByteArray *array) {
90 return array->objSize();
93 size_t iterateCode(Object *obj) {
94 visitField(obj, Code::offsetOfModule());
95 visitField(obj, Code::offsetOfBytecode());
96 visitField(obj, Code::offsetOfLocals());
97 visitField(obj, Code::offsetOfObjects());
98 visitField(obj, Code::offsetOfSafepoints());
99 visitField(obj, Code::offsetOfSourceMap());
100 visitField(obj, Code::offsetOfStrings());
104 size_t iterateReference(Object *obj) {
105 visitField(obj, Reference::offsetOfBase());
106 return sizeof(Reference);
109 size_t iterateModule(Object *obj) {
110 visitField(obj, Module::offsetOfFile());
111 visitField(obj, Module::offsetOfGlobals());
112 visitField(obj, Module::offsetOfCode());
113 return sizeof(Module);
116 size_t iterateFunction(Object *obj) {
117 visitField(obj, Function::offsetOfCode());
118 visitField(obj, Function::offsetOfType());
119 visitField(obj, Function::offsetOfName());
120 return sizeof(Function);
123 size_t iterateDescriptor(Object *obj) {
124 visitField(obj, Descriptor::offsetOfName());
125 visitField(obj, Descriptor::offsetOfType());
126 return sizeof(Descriptor);
129 size_t iterateNative(Object *obj) {
130 visitField(obj, Native::offsetOfType());
131 return sizeof(Native);
134 size_t iterateString(Object *obj) {
135 return String::cast(obj)->objSize();
138 size_t iterateArray(Array *array, ArrayMap *map) {
139 if (!map->type()->fixedLength() || map->type()->contained()->isTraceable())
140 visitField(array, Array::offsetOfElements());
141 return array->objSize(map);
144 size_t iterateBox(Box *obj) {
145 visitField(obj, Box::offsetOfType());
146 if (obj->type()->isTraceable())
147 visitField(obj, Box::offsetOfObj());
151 size_t iterateArrayMap(ArrayMap *map) {
152 visitField(map, ArrayMap::offsetOfType());
153 return sizeof(ArrayMap);
156 size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
157 unsigned length = env->length();
158 EnvironmentSlotDescriptor *desc = env->slots();
159 for (unsigned i = 0; i < length; i++)
160 this->visit(desc->type.addr());
161 return env->objSize();
164 size_t iterateEnvironmentMap(EnvironmentMap *map) {
165 visitField(map, EnvironmentMap::offsetOfSlots());
166 return map->objSize();
169 size_t iterateStructMap(StructMap *map) {
170 visitField(map, StructMap::offsetOfType());
171 visitField(map, StructMap::offsetOfComposed());
172 return map->objSize();
175 size_t iterateEnvironment(Environment *env) {
176 EnvironmentMap *map = env->map();
177 const unsigned *offsets = map->traceOffsets();
178 unsigned noffsets = map->traceOffsetCount();
179 for (unsigned i = 0; i < noffsets; i++)
180 visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
181 return env->objSize();
184 size_t iterateStruct(Struct *obj) {
185 StructMap *map = obj->map();
186 const unsigned *offsets = map->traceOffsets();
187 unsigned noffsets = map->traceOffsetCount();
188 for (unsigned i = 0; i < noffsets; i++)
189 visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
190 return obj->objSize();
194 size_t iterateObject(Object *obj) {
195 visitField(obj, Object::offsetOfMap());
196 return iterate(obj, obj->map());
199 size_t iterateObject(Object *obj, Map *map) {
200 switch (map->kind()) {
202 return iterateType(obj);
204 case MapKind_ReferenceType:
205 return iterateReferenceType(obj);
207 case MapKind_ArrayType:
208 return iterateArrayType(obj);
210 case MapKind_FunctionType:
211 return iterateFunctionType(obj);
213 case MapKind_StructType:
214 return iterateStructType(obj);
216 case MapKind_FixedArray:
217 return iterateFixedArray(FixedArray::cast(obj));
219 case MapKind_ByteArray:
220 return iterateByteArray(ByteArray::cast(obj));
223 return iterateCode(obj);
225 case MapKind_Reference:
226 return iterateReference(obj);
229 return iterateModule(obj);
231 case MapKind_Function:
232 return iterateFunction(obj);
234 case MapKind_Descriptor:
235 return iterateDescriptor(obj);
238 return iterateString(obj);
241 return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
244 return iterateBox(Box::cast(obj));
247 return iterateStruct(Struct::cast(obj));
249 case MapKind_EnvironmentSlotDescriptorArray:
250 return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
252 case MapKind_Environment:
253 return iterateEnvironment(Environment::cast(obj));
256 return iterateNative(obj);
258 case MapKind_MetaArray:
259 return iterateArrayMap(ArrayMap::cast(obj));
261 case MapKind_MetaEnvironment:
262 return iterateEnvironmentMap(EnvironmentMap::cast(obj));
264 case MapKind_MetaStruct:
265 return iterateStructMap(StructMap::cast(obj));
268 assert(map->kind() == MapKind_Meta);
274 size_t iterate(Object *obj) {
275 return Align(iterateObject(obj), kObjectAlignment);
278 size_t iterate(Object *obj, Map *map) {
279 return Align(iterateObject(obj, map), kObjectAlignment);
284 SizeOfObjectRaw(Object *obj, Map *map)
286 switch (map->kind()) {
290 case MapKind_ReferenceType:
291 return sizeof(ReferenceType);
293 case MapKind_ArrayType:
294 return sizeof(ArrayType);
296 case MapKind_FunctionType:
297 return sizeof(FunctionType);
299 case MapKind_StructType:
300 return sizeof(StructType);
302 case MapKind_FixedArray:
303 return FixedArray::cast(obj)->objSize();
305 case MapKind_ByteArray:
306 return ByteArray::cast(obj)->objSize();
311 case MapKind_Reference:
312 return sizeof(Reference);
315 return sizeof(Module);
317 case MapKind_Descriptor:
318 return sizeof(Descriptor);
320 case MapKind_Function:
321 return sizeof(Function);
324 return String::cast(obj)->objSize();
327 return sizeof(Native);
330 return Align(Array::cast(obj)->objSize(ArrayMap::cast(map)), kObjectAlignment);
336 return Struct::cast(obj)->objSize();
338 case MapKind_EnvironmentSlotDescriptorArray:
339 return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
341 case MapKind_Environment:
342 return Environment::cast(obj)->objSize();
344 case MapKind_MetaArray:
345 return sizeof(ArrayMap);
347 case MapKind_MetaEnvironment:
348 return EnvironmentMap::cast(obj)->objSize();
350 case MapKind_MetaStruct:
351 return StructMap::cast(obj)->objSize();
353 case MapKind_FreeRegion:
354 return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
357 assert(map->kind() == MapKind_Meta);
363 SizeOfObject(Object *obj, Map *map)
365 return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
368 class ObjectSizeEvaluator
371 size_t operator()(Object *obj, Map *map) {
372 return SizeOfObject(obj, map);
378 #endif // _include_jc_object_visitor_h_