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 visitField(obj, EnumType::offsetOfFields());
58 return sizeof(EnumType);
61 size_t iterateReferenceType(Object *obj) {
63 visitField(obj, ReferenceType::offsetOfContained());
64 return sizeof(ReferenceType);
67 size_t iterateArrayType(Object *obj) {
69 visitField(obj, ArrayType::offsetOfContained());
70 visitField(obj, ArrayType::offsetOfNewMap());
71 return sizeof(ArrayType);
74 size_t iterateStructType(Object *obj) {
76 visitField(obj, StructType::offsetOfFields());
77 visitField(obj, StructType::offsetOfNewMap());
78 visitField(obj, StructType::offsetOfName());
79 return sizeof(StructType);
82 size_t iterateFunctionType(Object *obj) {
84 visitField(obj, FunctionType::offsetOfReturnType());
85 visitField(obj, FunctionType::offsetOfParameters());
86 visitField(obj, FunctionType::offsetOfDefaults());
87 visitField(obj, FunctionType::offsetOfName());
88 return sizeof(FunctionType);
91 size_t iterateFixedArray(FixedArray *array) {
92 unsigned length = array->length();
93 Object **ptr = reinterpret_cast<Object **>(array + 1);
94 for (unsigned i = 0; i < length; i++)
96 return array->objSize();
99 size_t iterateByteArray(ByteArray *array) {
100 return array->objSize();
103 size_t iterateCode(Object *obj) {
104 visitField(obj, Code::offsetOfModule());
105 visitField(obj, Code::offsetOfBytecode());
106 visitField(obj, Code::offsetOfLocals());
107 visitField(obj, Code::offsetOfObjects());
108 visitField(obj, Code::offsetOfSafepoints());
109 visitField(obj, Code::offsetOfSourceMap());
110 visitField(obj, Code::offsetOfStrings());
114 size_t iterateReference(Object *obj) {
115 visitField(obj, Reference::offsetOfBase());
116 return sizeof(Reference);
119 void visitImportable(Object *obj) {
120 visitField(obj, Package::offsetOfName());
121 visitField(obj, Package::offsetOfParent());
122 visitField(obj, Package::offsetOfPath());
125 size_t iterateModule(Object *obj) {
126 visitImportable(obj);
127 visitField(obj, Module::offsetOfGlobals());
128 visitField(obj, Module::offsetOfCode());
129 visitField(obj, Module::offsetOfImports());
130 return sizeof(Module);
133 size_t iteratePackage(Object *obj) {
134 visitImportable(obj);
135 visitField(obj, Package::offsetOfContents());
136 return sizeof(Package);
139 size_t iterateFunction(Object *obj) {
140 visitField(obj, Function::offsetOfCode());
141 visitField(obj, Function::offsetOfType());
142 visitField(obj, Function::offsetOfName());
143 return sizeof(Function);
146 size_t iterateDescriptor(Object *obj) {
147 visitField(obj, Descriptor::offsetOfName());
148 visitField(obj, Descriptor::offsetOfType());
149 return sizeof(Descriptor);
152 size_t iterateNative(Object *obj) {
153 visitField(obj, Native::offsetOfType());
154 return sizeof(Native);
157 size_t iterateString(Object *obj) {
158 return String::cast(obj)->objSize();
161 size_t iterateArray(Array *array, ArrayMap *map) {
162 if (!map->type()->hasInlineElements())
163 visitField(array, Array::offsetOfElements());
164 return array->objSize(map);
167 size_t iterateDependentArray(Object *array) {
168 visitField(array, DependentArray::offsetOfRoot());
169 return sizeof(DependentArray);
172 size_t iterateBox(Box *obj) {
173 visitField(obj, Box::offsetOfType());
174 if (obj->type()->isTraceable())
175 visitField(obj, Box::offsetOfObj());
179 size_t iterateArrayMap(ArrayMap *map) {
180 visitField(map, ArrayMap::offsetOfType());
181 return sizeof(ArrayMap);
184 size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
185 unsigned length = env->length();
186 EnvironmentSlotDescriptor *desc = env->slots();
187 for (unsigned i = 0; i < length; i++)
188 this->visit(desc->type.addr());
189 return env->objSize();
192 size_t iterateEnvironmentMap(EnvironmentMap *map) {
193 visitField(map, EnvironmentMap::offsetOfSlots());
194 return map->objSize();
197 size_t iterateStructMap(StructMap *map) {
198 visitField(map, StructMap::offsetOfType());
199 visitField(map, StructMap::offsetOfComposed());
200 return map->objSize();
203 size_t iterateEnvironment(Environment *env) {
204 EnvironmentMap *map = env->map();
205 const unsigned *offsets = map->traceOffsets();
206 unsigned noffsets = map->traceOffsetCount();
207 for (unsigned i = 0; i < noffsets; i++)
208 visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
209 return env->objSize();
212 size_t iterateStruct(Struct *obj) {
213 StructMap *map = obj->map();
214 const unsigned *offsets = map->traceOffsets();
215 unsigned noffsets = map->traceOffsetCount();
216 for (unsigned i = 0; i < noffsets; i++)
217 visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
218 return Struct::SizeFor(map);
221 size_t iterateList(Object *obj) {
222 visitField(obj, List<Object>::offsetOfArray());
223 return sizeof(List<Object>);
227 size_t iterateObject(Object *obj) {
228 visitField(obj, Object::offsetOfMap());
229 return iterate(obj, obj->map());
232 size_t iterateObject(Object *obj, Map *map) {
233 switch (map->kind()) {
235 return iterateType(obj);
237 case MapKind_ReferenceType:
238 return iterateReferenceType(obj);
240 case MapKind_ArrayType:
241 return iterateArrayType(obj);
243 case MapKind_EnumType:
244 return iterateEnumType(obj);
246 case MapKind_FunctionType:
247 return iterateFunctionType(obj);
249 case MapKind_StructType:
250 return iterateStructType(obj);
252 case MapKind_FixedArray:
253 return iterateFixedArray(FixedArray::cast(obj));
255 case MapKind_ByteArray:
256 return iterateByteArray(ByteArray::cast(obj));
259 return iterateCode(obj);
261 case MapKind_Reference:
262 return iterateReference(obj);
265 return iterateModule(obj);
267 case MapKind_Package:
268 return iteratePackage(obj);
270 case MapKind_Function:
271 return iterateFunction(obj);
273 case MapKind_Descriptor:
274 return iterateDescriptor(obj);
277 return iterateString(obj);
280 return iterateArray(Array::cast(obj), ArrayMap::cast(map));
282 case MapKind_DependentArray:
283 return iterateDependentArray(obj);
286 return iterateBox(Box::cast(obj));
289 return iterateStruct(Struct::cast(obj));
292 return iterateList(obj);
294 case MapKind_EnvironmentSlotDescriptorArray:
295 return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
297 case MapKind_Environment:
298 return iterateEnvironment(Environment::cast(obj));
301 return iterateNative(obj);
303 case MapKind_MetaArray:
304 return iterateArrayMap(ArrayMap::cast(obj));
306 case MapKind_MetaEnvironment:
307 return iterateEnvironmentMap(EnvironmentMap::cast(obj));
309 case MapKind_MetaStruct:
310 return iterateStructMap(StructMap::cast(obj));
313 assert(map->kind() == MapKind_Meta);
319 size_t iterate(Object *obj) {
320 return Align(iterateObject(obj), kObjectAlignment);
323 size_t iterate(Object *obj, Map *map) {
324 return Align(iterateObject(obj, map), kObjectAlignment);
329 SizeOfObjectRaw(Object *obj, Map *map)
331 switch (map->kind()) {
335 case MapKind_ReferenceType:
336 return sizeof(ReferenceType);
338 case MapKind_ArrayType:
339 return sizeof(ArrayType);
341 case MapKind_EnumType:
342 return sizeof(EnumType);
344 case MapKind_FunctionType:
345 return sizeof(FunctionType);
347 case MapKind_StructType:
348 return sizeof(StructType);
350 case MapKind_FixedArray:
351 return FixedArray::cast(obj)->objSize();
353 case MapKind_ByteArray:
354 return ByteArray::cast(obj)->objSize();
359 case MapKind_Reference:
360 return sizeof(Reference);
363 return sizeof(Module);
365 case MapKind_Package:
366 return sizeof(Package);
368 case MapKind_Descriptor:
369 return sizeof(Descriptor);
371 case MapKind_Function:
372 return sizeof(Function);
375 return String::cast(obj)->objSize();
378 return sizeof(Native);
381 return Array::cast(obj)->objSize(ArrayMap::cast(map));
383 case MapKind_DependentArray:
384 return sizeof(DependentArray);
390 return sizeof(List<Object>);
393 return Struct::SizeFor(StructMap::cast(map));
395 case MapKind_EnvironmentSlotDescriptorArray:
396 return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
398 case MapKind_Environment:
399 return Environment::cast(obj)->objSize();
401 case MapKind_MetaArray:
402 return sizeof(ArrayMap);
404 case MapKind_MetaEnvironment:
405 return EnvironmentMap::cast(obj)->objSize();
407 case MapKind_MetaStruct:
408 return StructMap::cast(obj)->objSize();
410 case MapKind_FreeRegion:
411 return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
414 assert(map->kind() == MapKind_Meta);
420 SizeOfObject(Object *obj, Map *map)
422 return Align(SizeOfObjectRaw(obj, map), kObjectAlignment);
425 class ObjectSizeEvaluator
428 size_t operator()(Object *obj, Map *map) {
429 return SizeOfObject(obj, map);
435 #endif // _include_jc_object_visitor_h_