Fix gcc and clang builds.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of SourcePawn.
7 * SourcePawn 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 * SourcePawn 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 * SourcePawn. 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"
39 // An ObjectVisitor is used for traversing object references in the heap. Since
40 // this pattern must be lightning fast, we avoid virtual dispatch by forcing
41 // visitors to compose themselves with the visiting logic.
43 class ObjectVisitor : public T
46 void visitField(Object *obj, size_t offset) {
47 this->visit(reinterpret_cast<Object **>(Address(obj) + offset));
50 size_t iterateType(Object *obj) {
51 visitField(obj, Type::offsetOfRoot());
55 size_t iterateEnumType(Object *obj) {
56 visitField(obj, EnumType::offsetOfName());
57 return sizeof(EnumType);
60 size_t iterateReferenceType(Object *obj) {
62 visitField(obj, ReferenceType::offsetOfContained());
63 return sizeof(ReferenceType);
66 size_t iterateArrayType(Object *obj) {
68 visitField(obj, ArrayType::offsetOfContained());
69 visitField(obj, ArrayType::offsetOfNewMap());
70 return sizeof(ArrayType);
73 size_t iterateStructType(Object *obj) {
75 visitField(obj, StructType::offsetOfFields());
76 visitField(obj, StructType::offsetOfNewMap());
77 visitField(obj, StructType::offsetOfName());
78 return sizeof(StructType);
81 size_t iterateFunctionType(Object *obj) {
83 visitField(obj, FunctionType::offsetOfReturnType());
84 visitField(obj, FunctionType::offsetOfParameters());
85 visitField(obj, FunctionType::offsetOfDefaults());
86 visitField(obj, FunctionType::offsetOfName());
87 return sizeof(FunctionType);
90 size_t iterateFixedArray(FixedArray *array) {
91 unsigned length = array->length();
92 Object **ptr = reinterpret_cast<Object **>(array + 1);
93 for (unsigned i = 0; i < length; i++)
95 return array->objSize();
98 size_t iterateByteArray(ByteArray *array) {
99 return array->objSize();
102 size_t iterateCode(Object *obj) {
103 visitField(obj, Code::offsetOfModule());
104 visitField(obj, Code::offsetOfBytecode());
105 visitField(obj, Code::offsetOfLocals());
106 visitField(obj, Code::offsetOfObjects());
107 visitField(obj, Code::offsetOfSafepoints());
108 visitField(obj, Code::offsetOfSourceMap());
109 visitField(obj, Code::offsetOfStrings());
113 size_t iterateReference(Object *obj) {
114 visitField(obj, Reference::offsetOfBase());
115 return sizeof(Reference);
118 void visitImportable(Object *obj) {
119 visitField(obj, Package::offsetOfName());
120 visitField(obj, Package::offsetOfParent());
121 visitField(obj, Package::offsetOfPath());
124 size_t iterateModule(Object *obj) {
125 visitImportable(obj);
126 visitField(obj, Module::offsetOfGlobals());
127 visitField(obj, Module::offsetOfCode());
128 visitField(obj, Module::offsetOfImports());
129 return sizeof(Module);
132 size_t iteratePackage(Object *obj) {
133 visitImportable(obj);
134 visitField(obj, Package::offsetOfContents());
135 return sizeof(Package);
138 size_t iterateFunction(Object *obj) {
139 visitField(obj, Function::offsetOfCode());
140 visitField(obj, Function::offsetOfType());
141 visitField(obj, Function::offsetOfName());
142 return sizeof(Function);
145 size_t iterateDescriptor(Object *obj) {
146 visitField(obj, Descriptor::offsetOfName());
147 visitField(obj, Descriptor::offsetOfType());
148 return sizeof(Descriptor);
151 size_t iterateNative(Object *obj) {
152 visitField(obj, Native::offsetOfType());
153 return sizeof(Native);
156 size_t iterateString(Object *obj) {
157 return String::cast(obj)->objSize();
160 size_t iterateArray(Array *array, ArrayMap *map) {
161 if (!map->type()->hasInlineElements())
162 visitField(array, Array::offsetOfElements());
163 return array->objSize(map);
166 size_t iterateDependentArray(Object *array) {
167 visitField(array, DependentArray::offsetOfRoot());
168 return sizeof(DependentArray);
171 size_t iterateBox(Box *obj) {
172 visitField(obj, Box::offsetOfType());
173 if (obj->type()->isTraceable())
174 visitField(obj, Box::offsetOfObj());
178 size_t iterateArrayMap(ArrayMap *map) {
179 visitField(map, ArrayMap::offsetOfType());
180 return sizeof(ArrayMap);
183 size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
184 unsigned length = env->length();
185 EnvironmentSlotDescriptor *desc = env->slots();
186 for (unsigned i = 0; i < length; i++)
187 this->visit(desc->type.addr());
188 return env->objSize();
191 size_t iterateEnvironmentMap(EnvironmentMap *map) {
192 visitField(map, EnvironmentMap::offsetOfSlots());
193 return map->objSize();
196 size_t iterateStructMap(StructMap *map) {
197 visitField(map, StructMap::offsetOfType());
198 visitField(map, StructMap::offsetOfComposed());
199 return map->objSize();
202 size_t iterateEnvironment(Environment *env) {
203 EnvironmentMap *map = env->map();
204 const unsigned *offsets = map->traceOffsets();
205 unsigned noffsets = map->traceOffsetCount();
206 for (unsigned i = 0; i < noffsets; i++)
207 visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
208 return env->objSize();
211 size_t iterateStruct(Struct *obj) {
212 StructMap *map = obj->map();
213 const unsigned *offsets = map->traceOffsets();
214 unsigned noffsets = map->traceOffsetCount();
215 for (unsigned i = 0; i < noffsets; i++)
216 visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
217 return Struct::SizeFor(map);
220 size_t iterateList(Object *obj) {
221 visitField(obj, List<Object>::offsetOfArray());
222 return sizeof(List<Object>);
226 size_t iterateObject(Object *obj) {
227 visitField(obj, Object::offsetOfMap());
228 return iterate(obj, obj->map());
231 size_t iterateObject(Object *obj, Map *map) {
232 switch (map->kind()) {
234 return iterateType(obj);
236 case MapKind_ReferenceType:
237 return iterateReferenceType(obj);
239 case MapKind_ArrayType:
240 return iterateArrayType(obj);
242 case MapKind_EnumType:
243 return iterateEnumType(obj);
245 case MapKind_FunctionType:
246 return iterateFunctionType(obj);
248 case MapKind_StructType:
249 return iterateStructType(obj);
251 case MapKind_FixedArray:
252 return iterateFixedArray(FixedArray::cast(obj));
254 case MapKind_ByteArray:
255 return iterateByteArray(ByteArray::cast(obj));
258 return iterateCode(obj);
260 case MapKind_Reference:
261 return iterateReference(obj);
264 return iterateModule(obj);
266 case MapKind_Package:
267 return iteratePackage(obj);
269 case MapKind_Function:
270 return iterateFunction(obj);
272 case MapKind_Descriptor:
273 return iterateDescriptor(obj);
276 return iterateString(obj);
279 return iterateArray(Array::cast(obj), ArrayMap::cast(map));
281 case MapKind_DependentArray:
282 return iterateDependentArray(obj);
285 return iterateBox(Box::cast(obj));
288 return iterateStruct(Struct::cast(obj));
291 return iterateList(obj);
293 case MapKind_EnvironmentSlotDescriptorArray:
294 return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
296 case MapKind_Environment:
297 return iterateEnvironment(Environment::cast(obj));
300 return iterateNative(obj);
302 case MapKind_MetaArray:
303 return iterateArrayMap(ArrayMap::cast(obj));
305 case MapKind_MetaEnvironment:
306 return iterateEnvironmentMap(EnvironmentMap::cast(obj));
308 case MapKind_MetaStruct:
309 return iterateStructMap(StructMap::cast(obj));
312 assert(map->kind() == MapKind_Meta);
318 size_t iterate(Object *obj) {
319 return Align(iterateObject(obj), kObjectAlignment);
322 size_t iterate(Object *obj, Map *map) {
323 return Align(iterateObject(obj, map), kObjectAlignment);
328 SizeOfObjectRaw(Object *obj, Map *map)
330 switch (map->kind()) {
334 case MapKind_ReferenceType:
335 return sizeof(ReferenceType);
337 case MapKind_ArrayType:
338 return sizeof(ArrayType);
340 case MapKind_EnumType:
341 return sizeof(EnumType);
343 case MapKind_FunctionType:
344 return sizeof(FunctionType);
346 case MapKind_StructType:
347 return sizeof(StructType);
349 case MapKind_FixedArray:
350 return FixedArray::cast(obj)->objSize();
352 case MapKind_ByteArray:
353 return ByteArray::cast(obj)->objSize();
358 case MapKind_Reference:
359 return sizeof(Reference);
362 return sizeof(Module);
364 case MapKind_Package:
365 return sizeof(Package);
367 case MapKind_Descriptor:
368 return sizeof(Descriptor);
370 case MapKind_Function:
371 return sizeof(Function);
374 return String::cast(obj)->objSize();
377 return sizeof(Native);
380 return Array::cast(obj)->objSize(ArrayMap::cast(map));
382 case MapKind_DependentArray:
383 return sizeof(DependentArray);
389 return sizeof(List<Object>);
392 return Struct::SizeFor(StructMap::cast(map));
394 case MapKind_EnvironmentSlotDescriptorArray:
395 return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
397 case MapKind_Environment:
398 return Environment::cast(obj)->objSize();
400 case MapKind_MetaArray:
401 return sizeof(ArrayMap);
403 case MapKind_MetaEnvironment:
404 return EnvironmentMap::cast(obj)->objSize();
406 case MapKind_MetaStruct:
407 return StructMap::cast(obj)->objSize();
409 case MapKind_FreeRegion:
410 return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
413 assert(map->kind() == MapKind_Meta);
419 SizeOfObject(Object *obj, Map *map)
421 return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
424 class ObjectSizeEvaluator
427 size_t operator()(Object *obj, Map *map) {
428 return SizeOfObject(obj, map);
434 #endif // _include_jc_object_visitor_h_