1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/ObjectVisitor.h Tue Jul 24 23:53:34 2012 -0700
1.3 @@ -0,0 +1,269 @@
1.4 +/* vim: set ts=4 sw=4 tw=99 et:
1.5 + *
1.6 + * Copyright (C) 2012 David Anderson
1.7 + *
1.8 + * This file is part of JITCraft.
1.9 + *
1.10 + * JITCraft is free software: you can redistribute it and/or modify it under
1.11 + * the terms of the GNU General Public License as published by the Free
1.12 + * Software Foundation, either version 3 of the License, or (at your option)
1.13 + * any later version.
1.14 + *
1.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
1.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License along with
1.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
1.21 + */
1.22 +#ifndef _include_jc_object_visitor_h_
1.23 +#define _include_jc_object_visitor_h_
1.24 +
1.25 +#include "Objects.h"
1.26 +#include "Types.h"
1.27 +#include "FixedArray.h"
1.28 +#include "Code.h"
1.29 +#include "Reference.h"
1.30 +#include "Modules.h"
1.31 +#include "Functions.h"
1.32 +#include "Array.h"
1.33 +#include "Strings.h"
1.34 +#include "Environments.h"
1.35 +
1.36 +namespace ke {
1.37 +
1.38 +// An ObjectVisitor is used for traversing object references in the heap. Since
1.39 +// this pattern must be lightning fast, we avoid virtual dispatch by forcing
1.40 +// visitors to compose themselves with the visiting logic.
1.41 +template <typename T>
1.42 +class ObjectVisitor : public T
1.43 +{
1.44 + private:
1.45 + void visitField(Object *obj, size_t offset) {
1.46 + this->visit(reinterpret_cast<Object **>(Address(obj) + offset));
1.47 + }
1.48 +
1.49 + size_t iterateType(Object *obj) {
1.50 + visitField(obj, Type::offsetOfContained());
1.51 + visitField(obj, Type::offsetOfReturnType());
1.52 + visitField(obj, Type::offsetOfParameters());
1.53 + visitField(obj, Type::offsetOfTag());
1.54 + return sizeof(Type);
1.55 + }
1.56 +
1.57 + size_t iterateFixedArray(FixedArray *array) {
1.58 + unsigned length = array->length();
1.59 + Object **ptr = reinterpret_cast<Object **>(array + 1);
1.60 + for (unsigned i = 0; i < length; i++)
1.61 + this->visit(ptr + i);
1.62 + return FixedArray::SizeFor(length);
1.63 + }
1.64 +
1.65 + size_t iterateByteArray(ByteArray *array) {
1.66 + return ByteArray::SizeFor(array->length());
1.67 + }
1.68 +
1.69 + size_t iterateCode(Object *obj) {
1.70 + visitField(obj, Code::offsetOfModule());
1.71 + visitField(obj, Code::offsetOfBytecode());
1.72 + visitField(obj, Code::offsetOfLocals());
1.73 + visitField(obj, Code::offsetOfObjects());
1.74 + visitField(obj, Code::offsetOfSafepoints());
1.75 + visitField(obj, Code::offsetOfSourceMap());
1.76 + return sizeof(Code);
1.77 + }
1.78 +
1.79 + size_t iterateReference(Object *obj) {
1.80 + visitField(obj, Reference::offsetOfBase());
1.81 + return sizeof(Reference);
1.82 + }
1.83 +
1.84 + size_t iterateModule(Object *obj) {
1.85 + visitField(obj, Module::offsetOfFunctions());
1.86 + visitField(obj, Module::offsetOfPublics());
1.87 + visitField(obj, Module::offsetOfNatives());
1.88 + visitField(obj, Module::offsetOfFile());
1.89 + visitField(obj, Module::offsetOfEnvironment());
1.90 + visitField(obj, Module::offsetOfCode());
1.91 + return sizeof(Module);
1.92 + }
1.93 +
1.94 + size_t iterateFunction(Object *obj) {
1.95 + visitField(obj, Function::offsetOfCode());
1.96 + visitField(obj, Function::offsetOfType());
1.97 + visitField(obj, Function::offsetOfName());
1.98 + return sizeof(Function);
1.99 + }
1.100 +
1.101 + size_t iterateNative(Object *obj) {
1.102 + visitField(obj, Native::offsetOfType());
1.103 + visitField(obj, Native::offsetOfName());
1.104 + return sizeof(Native);
1.105 + }
1.106 +
1.107 + size_t iterateString(Object *obj) {
1.108 + return String::SizeFor(String::cast(obj)->length());
1.109 + }
1.110 +
1.111 + size_t iterateArray(Array *array, ArrayMap *map) {
1.112 + assert(map->type()->isArray());
1.113 + if (map->contained()) {
1.114 + unsigned length = array->nelements();
1.115 + Object **vec = array->objVec();
1.116 + for (unsigned i = 0; i < length; i++)
1.117 + this->visit(vec + i);
1.118 + }
1.119 + return Array::SizeOf(array);
1.120 + }
1.121 +
1.122 + size_t iterateArrayMap(ArrayMap *map) {
1.123 + visitField(map, ArrayMap::offsetOfType());
1.124 + visitField(map, ArrayMap::offsetOfContained());
1.125 + return sizeof(ArrayMap);
1.126 + }
1.127 +
1.128 + size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
1.129 + unsigned length = env->length();
1.130 + EnvironmentSlotDescriptor *desc = env->slots();
1.131 + for (unsigned i = 0; i < length; i++)
1.132 + this->visit(desc->type.addr());
1.133 + return env->size();
1.134 + }
1.135 +
1.136 + size_t iterateEnvironmentMap(EnvironmentMap *map) {
1.137 + visitField(map, EnvironmentMap::offsetOfSlots());
1.138 + return map->size();
1.139 + }
1.140 +
1.141 + size_t iterateEnvironment(Environment *env) {
1.142 + EnvironmentMap *map = env->map();
1.143 + const unsigned *offsets = map->traceOffsets();
1.144 + unsigned noffsets = map->traceOffsetCount();
1.145 + for (unsigned i = 0; i < noffsets; i++)
1.146 + visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
1.147 + return env->size();
1.148 + }
1.149 +
1.150 + public:
1.151 + size_t iterate(Object *obj) {
1.152 + visitField(obj, Object::offsetOfMap());
1.153 + return iterate(obj, obj->map());
1.154 + }
1.155 +
1.156 + size_t iterate(Object *obj, Map *map) {
1.157 + switch (map->kind()) {
1.158 + case MapKind_Type:
1.159 + return iterateType(obj);
1.160 +
1.161 + case MapKind_FixedArray:
1.162 + return iterateFixedArray(FixedArray::cast(obj));
1.163 +
1.164 + case MapKind_ByteArray:
1.165 + return iterateByteArray(ByteArray::cast(obj));
1.166 +
1.167 + case MapKind_Code:
1.168 + return iterateCode(obj);
1.169 +
1.170 + case MapKind_Reference:
1.171 + return iterateReference(obj);
1.172 +
1.173 + case MapKind_Module:
1.174 + return iterateModule(obj);
1.175 +
1.176 + case MapKind_Function:
1.177 + return iterateFunction(obj);
1.178 +
1.179 + case MapKind_String:
1.180 + return iterateString(obj);
1.181 +
1.182 + case MapKind_Array:
1.183 + return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
1.184 +
1.185 + case MapKind_EnvironmentSlotDescriptorArray:
1.186 + return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
1.187 +
1.188 + case MapKind_Environment:
1.189 + return iterateEnvironment(Environment::cast(obj));
1.190 +
1.191 + case MapKind_Native:
1.192 + return iterateNative(obj);
1.193 +
1.194 + case MapKind_MetaArray:
1.195 + return iterateArrayMap(ArrayMap::cast(obj));
1.196 +
1.197 + case MapKind_MetaEnvironment:
1.198 + return iterateEnvironmentMap(EnvironmentMap::cast(obj));
1.199 +
1.200 + default:
1.201 + assert(map->kind() == MapKind_Meta);
1.202 + return sizeof(Map);
1.203 + }
1.204 + }
1.205 +};
1.206 +
1.207 +static inline size_t
1.208 +SizeOfObject(Object *obj, Map *map)
1.209 +{
1.210 + switch (map->kind()) {
1.211 + case MapKind_Type:
1.212 + return sizeof(Type);
1.213 +
1.214 + case MapKind_FixedArray:
1.215 + return FixedArray::SizeFor(FixedArray::cast(obj)->length());
1.216 +
1.217 + case MapKind_ByteArray:
1.218 + return ByteArray::SizeFor(ByteArray::cast(obj)->length());
1.219 +
1.220 + case MapKind_Code:
1.221 + return sizeof(Code);
1.222 +
1.223 + case MapKind_Reference:
1.224 + return sizeof(Reference);
1.225 +
1.226 + case MapKind_Module:
1.227 + return sizeof(Module);
1.228 +
1.229 + case MapKind_Function:
1.230 + return sizeof(Function);
1.231 +
1.232 + case MapKind_String:
1.233 + return String::SizeFor(String::cast(obj)->length());
1.234 +
1.235 + case MapKind_Native:
1.236 + return sizeof(Native);
1.237 +
1.238 + case MapKind_Array:
1.239 + return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
1.240 +
1.241 + case MapKind_EnvironmentSlotDescriptorArray:
1.242 + return EnvironmentSlotDescriptorArray::cast(obj)->size();
1.243 +
1.244 + case MapKind_Environment:
1.245 + return Environment::cast(obj)->size();
1.246 +
1.247 + case MapKind_MetaArray:
1.248 + return sizeof(ArrayMap);
1.249 +
1.250 + case MapKind_MetaEnvironment:
1.251 + return EnvironmentMap::cast(obj)->size();
1.252 +
1.253 + case MapKind_FreeRegion:
1.254 + return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
1.255 +
1.256 + default:
1.257 + assert(map->kind() == MapKind_Meta);
1.258 + return sizeof(Map);
1.259 + }
1.260 +}
1.261 +
1.262 +class ObjectSizeEvaluator
1.263 +{
1.264 + public:
1.265 + size_t operator()(Object *obj, Map *map) {
1.266 + return SizeOfObject(obj, map);
1.267 + }
1.268 +};
1.269 +
1.270 +}
1.271 +
1.272 +#endif // _include_jc_object_visitor_h_