1.1 --- a/src/Structures.cpp Mon Jun 10 00:46:29 2013 +0100
1.2 +++ b/src/Structures.cpp Mon Jun 10 01:04:43 2013 +0100
1.3 @@ -1,205 +1,205 @@
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 SourcePawn.
1.9 - *
1.10 - * SourcePawn 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 - * SourcePawn 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 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
1.21 - */
1.22 -#include <string.h>
1.23 -#include "Structures.h"
1.24 -#include "Zone.h"
1.25 -#include "Types.h"
1.26 -#include "Array.h"
1.27 -#include "Spaces-inl.h"
1.28 -#include "Heap-inl.h"
1.29 -
1.30 -using namespace ke;
1.31 -
1.32 -StructureBufferBuilder::StructureBufferBuilder()
1.33 - : size_(0)
1.34 -{
1.35 -}
1.36 -
1.37 -bool
1.38 -StructureBufferBuilder::add(Handle<Type> type, unsigned *offset)
1.39 -{
1.40 - *offset = size_;
1.41 -
1.42 - if (!type->isTraceable()) {
1.43 - // For now, assume the alignment of all primitive storage is 4 bytes,
1.44 - // and that all need <= 4 bytes of storage.
1.45 - assert(type->isInt32() ||
1.46 - type->isFloat() ||
1.47 - type->isBool() ||
1.48 - type->isChar() ||
1.49 - type->isEnum());
1.50 - size_ += 4;
1.51 - return true;
1.52 - }
1.53 -
1.54 - if (!offsets_.append(size_))
1.55 - return false;
1.56 -
1.57 - size_ += sizeof(Object *);
1.58 - return true;
1.59 -}
1.60 -
1.61 -Descriptor *
1.62 -Descriptor::New(Zone *zone, Handle<String> name, Handle<Type> type, Visibility visibility)
1.63 -{
1.64 - Local<Descriptor> desc(zone,
1.65 - Descriptor::cast(zone->allocate(MapKind_Descriptor, sizeof(Descriptor), Heap::Tenure_Old)));
1.66 - if (!desc)
1.67 - return NULL;
1.68 -
1.69 - desc->name_ = name;
1.70 - desc->type_ = type;
1.71 - desc->offset_ = unsigned(-1);
1.72 - desc->visibility_ = visibility;
1.73 - return desc;
1.74 -}
1.75 -
1.76 -StructMap *
1.77 -StructMap::New(Zone *zone, const StructureBufferBuilder &builder, Handle<StructType> type)
1.78 -{
1.79 - Vector<unsigned> composedIndexes;
1.80 - for (size_t i = 0; i < type->fields()->length(); i++) {
1.81 - Descriptor *desc = Descriptor::cast(type->fields()->at(i));
1.82 - if (desc->type()->isArray() || desc->type()->isStruct()) {
1.83 - if (!composedIndexes.append(i))
1.84 - return NULL;
1.85 - }
1.86 - }
1.87 -
1.88 - Local<FixedArray> composed(zone, FixedArray::New(zone, composedIndexes.length(), Heap::Tenure_Old));
1.89 - if (!composed)
1.90 - return NULL;
1.91 -
1.92 - for (size_t i = 0; i < composedIndexes.length(); i++) {
1.93 - Descriptor *desc = Descriptor::cast(type->fields()->at(composedIndexes[i]));
1.94 - composed->set(zone, i, desc);
1.95 - }
1.96 -
1.97 - size_t bytesNeeded = sizeof(StructMap) +
1.98 - (builder.traceableOffsetCount() * sizeof(unsigned));
1.99 -
1.100 - Local<StructMap> map(zone);
1.101 - map = StructMap::cast(zone->allocateMap(MapKind_Struct, bytesNeeded, MapKind_MetaStruct));
1.102 - if (!map)
1.103 - return NULL;
1.104 -
1.105 - map->structureSize_ = builder.structureSize();
1.106 - map->traceOffsetCount_ = builder.traceableOffsetCount();
1.107 - map->type_ = type;
1.108 - map->composed_ = composed;
1.109 - memcpy(const_cast<unsigned *>(map->traceOffsets()), builder.offsets(),
1.110 - sizeof(unsigned) * builder.traceableOffsetCount());
1.111 -
1.112 - return map;
1.113 -}
1.114 -
1.115 -Struct *
1.116 -Struct::New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure)
1.117 -{
1.118 - size_t bytesNeeded = SizeFor(map);
1.119 -
1.120 - Local<Struct> obj(zone, Struct::cast(zone->allocate(map, bytesNeeded, tenure)));
1.121 - if (!obj)
1.122 - return NULL;
1.123 -
1.124 - memset((Struct *)obj + 1, 0, (bytesNeeded - sizeof(Struct)));
1.125 -
1.126 - // Initialize any sub-structures. Right now, this is performed as part of
1.127 - // struct allocation, rather than inlined in bytecode, for simplicity.
1.128 - if (map->composed()) {
1.129 - Local<Descriptor> desc(zone);
1.130 - Local<Object> child(zone);
1.131 - Local<StructMap> childStructMap(zone);
1.132 - Local<ArrayMap> childArrayMap(zone);
1.133 -
1.134 - for (unsigned i = 0; i < map->composed()->length(); i++) {
1.135 - desc = Descriptor::cast(map->composed()->at(i));
1.136 -
1.137 - if (desc->type()->isStruct()) {
1.138 - childStructMap = StructMap::cast(StructType::cast(desc->type())->newMap());
1.139 - child = Struct::New(zone, childStructMap, tenure);
1.140 - } else if (desc->type()->isArray()) {
1.141 - // :TODO: don't create empty arrays for ref slots here.
1.142 - // Instead, make a separate Initialize function, so we
1.143 - // can avoid double-creating arrays for module globals.
1.144 - // (const char:x[] = "x")
1.145 - ArrayType *type = ArrayType::cast(desc->type());
1.146 - childArrayMap = ArrayMap::cast(type->newMap());
1.147 - if (type->isFixedLength())
1.148 - child = Array::NewFixed(zone, childArrayMap, tenure);
1.149 - else
1.150 - child = Array::NewEmpty(zone, childArrayMap, tenure);
1.151 - }
1.152 - if (!child)
1.153 - return NULL;
1.154 -
1.155 - obj->set(zone, desc, child);
1.156 - }
1.157 - }
1.158 -
1.159 - return obj;
1.160 -}
1.161 -
1.162 -bool
1.163 -Struct::Copy(Zone *zone, Handle<Struct> left, Handle<Struct> right)
1.164 -{
1.165 - assert(left->map()->type() == right->map()->type());
1.166 -
1.167 - Local<StructType> type(zone, StructType::cast(left->map()->type()));
1.168 - Local<Struct> leftStruct(zone);
1.169 - Local<Struct> rightStruct(zone);
1.170 - Local<Array> leftArray(zone);
1.171 - Local<Array> rightArray(zone);
1.172 - for (unsigned i = 0; i < type->fields()->length(); i++) {
1.173 - Descriptor *desc = Descriptor::cast(type->fields()->at(i));
1.174 -
1.175 - // If the field is a struct, we need to deep-copy.
1.176 - if (desc->type()->isStruct()) {
1.177 - leftStruct = Struct::cast(left->get<Object *>(desc));
1.178 - rightStruct = Struct::cast(right->get<Object *>(desc));
1.179 - if (!Struct::Copy(zone, leftStruct, rightStruct))
1.180 - return false;
1.181 - } else if (desc->type()->isArray()) {
1.182 - leftArray = Array::cast(left->get<Object *>(desc));
1.183 - rightArray = Array::cast(right->get<Object *>(desc));
1.184 - if (!Array::ShallowCopy(zone, leftArray, rightArray))
1.185 - return false;
1.186 - } else if (desc->type()->isTraceable()) {
1.187 - Object *obj = right->get<Object *>(desc);
1.188 - left->set(zone, desc, obj);
1.189 - } else {
1.190 - switch (desc->type()->pod()) {
1.191 - case PrimitiveType_Int32:
1.192 - case PrimitiveType_Char:
1.193 - case PrimitiveType_Bool:
1.194 - left->set(desc, right->get<int>(desc));
1.195 - break;
1.196 -
1.197 - case PrimitiveType_Float:
1.198 - left->set(desc, right->get<float>(desc));
1.199 - break;
1.200 -
1.201 - default:
1.202 - assert(false);
1.203 - }
1.204 - }
1.205 - }
1.206 -
1.207 - return true;
1.208 +/* vim: set ts=4 sw=4 tw=99 et:
1.209 + *
1.210 + * Copyright (C) 2012 David Anderson
1.211 + *
1.212 + * This file is part of SourcePawn.
1.213 + *
1.214 + * SourcePawn is free software: you can redistribute it and/or modify it under
1.215 + * the terms of the GNU General Public License as published by the Free
1.216 + * Software Foundation, either version 3 of the License, or (at your option)
1.217 + * any later version.
1.218 + *
1.219 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
1.220 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.221 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.222 + *
1.223 + * You should have received a copy of the GNU General Public License along with
1.224 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
1.225 + */
1.226 +#include <string.h>
1.227 +#include "Structures.h"
1.228 +#include "Zone.h"
1.229 +#include "Types.h"
1.230 +#include "Array.h"
1.231 +#include "Spaces-inl.h"
1.232 +#include "Heap-inl.h"
1.233 +
1.234 +using namespace ke;
1.235 +
1.236 +StructureBufferBuilder::StructureBufferBuilder()
1.237 + : size_(0)
1.238 +{
1.239 +}
1.240 +
1.241 +bool
1.242 +StructureBufferBuilder::add(Handle<Type> type, unsigned *offset)
1.243 +{
1.244 + *offset = size_;
1.245 +
1.246 + if (!type->isTraceable()) {
1.247 + // For now, assume the alignment of all primitive storage is 4 bytes,
1.248 + // and that all need <= 4 bytes of storage.
1.249 + assert(type->isInt32() ||
1.250 + type->isFloat() ||
1.251 + type->isBool() ||
1.252 + type->isChar() ||
1.253 + type->isEnum());
1.254 + size_ += 4;
1.255 + return true;
1.256 + }
1.257 +
1.258 + if (!offsets_.append(size_))
1.259 + return false;
1.260 +
1.261 + size_ += sizeof(Object *);
1.262 + return true;
1.263 +}
1.264 +
1.265 +Descriptor *
1.266 +Descriptor::New(Zone *zone, Handle<String> name, Handle<Type> type, Visibility visibility)
1.267 +{
1.268 + Local<Descriptor> desc(zone,
1.269 + Descriptor::cast(zone->allocate(MapKind_Descriptor, sizeof(Descriptor), Heap::Tenure_Old)));
1.270 + if (!desc)
1.271 + return NULL;
1.272 +
1.273 + desc->name_ = name;
1.274 + desc->type_ = type;
1.275 + desc->offset_ = unsigned(-1);
1.276 + desc->visibility_ = visibility;
1.277 + return desc;
1.278 +}
1.279 +
1.280 +StructMap *
1.281 +StructMap::New(Zone *zone, const StructureBufferBuilder &builder, Handle<StructType> type)
1.282 +{
1.283 + Vector<unsigned> composedIndexes;
1.284 + for (size_t i = 0; i < type->fields()->length(); i++) {
1.285 + Descriptor *desc = Descriptor::cast(type->fields()->at(i));
1.286 + if (desc->type()->isArray() || desc->type()->isStruct()) {
1.287 + if (!composedIndexes.append(i))
1.288 + return NULL;
1.289 + }
1.290 + }
1.291 +
1.292 + Local<FixedArray> composed(zone, FixedArray::New(zone, composedIndexes.length(), Heap::Tenure_Old));
1.293 + if (!composed)
1.294 + return NULL;
1.295 +
1.296 + for (size_t i = 0; i < composedIndexes.length(); i++) {
1.297 + Descriptor *desc = Descriptor::cast(type->fields()->at(composedIndexes[i]));
1.298 + composed->set(zone, i, desc);
1.299 + }
1.300 +
1.301 + size_t bytesNeeded = sizeof(StructMap) +
1.302 + (builder.traceableOffsetCount() * sizeof(unsigned));
1.303 +
1.304 + Local<StructMap> map(zone);
1.305 + map = StructMap::cast(zone->allocateMap(MapKind_Struct, bytesNeeded, MapKind_MetaStruct));
1.306 + if (!map)
1.307 + return NULL;
1.308 +
1.309 + map->structureSize_ = builder.structureSize();
1.310 + map->traceOffsetCount_ = builder.traceableOffsetCount();
1.311 + map->type_ = type;
1.312 + map->composed_ = composed;
1.313 + memcpy(const_cast<unsigned *>(map->traceOffsets()), builder.offsets(),
1.314 + sizeof(unsigned) * builder.traceableOffsetCount());
1.315 +
1.316 + return map;
1.317 +}
1.318 +
1.319 +Struct *
1.320 +Struct::New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure)
1.321 +{
1.322 + size_t bytesNeeded = SizeFor(map);
1.323 +
1.324 + Local<Struct> obj(zone, Struct::cast(zone->allocate(map, bytesNeeded, tenure)));
1.325 + if (!obj)
1.326 + return NULL;
1.327 +
1.328 + memset((Struct *)obj + 1, 0, (bytesNeeded - sizeof(Struct)));
1.329 +
1.330 + // Initialize any sub-structures. Right now, this is performed as part of
1.331 + // struct allocation, rather than inlined in bytecode, for simplicity.
1.332 + if (map->composed()) {
1.333 + Local<Descriptor> desc(zone);
1.334 + Local<Object> child(zone);
1.335 + Local<StructMap> childStructMap(zone);
1.336 + Local<ArrayMap> childArrayMap(zone);
1.337 +
1.338 + for (unsigned i = 0; i < map->composed()->length(); i++) {
1.339 + desc = Descriptor::cast(map->composed()->at(i));
1.340 +
1.341 + if (desc->type()->isStruct()) {
1.342 + childStructMap = StructMap::cast(StructType::cast(desc->type())->newMap());
1.343 + child = Struct::New(zone, childStructMap, tenure);
1.344 + } else if (desc->type()->isArray()) {
1.345 + // :TODO: don't create empty arrays for ref slots here.
1.346 + // Instead, make a separate Initialize function, so we
1.347 + // can avoid double-creating arrays for module globals.
1.348 + // (const char:x[] = "x")
1.349 + ArrayType *type = ArrayType::cast(desc->type());
1.350 + childArrayMap = ArrayMap::cast(type->newMap());
1.351 + if (type->isFixedLength())
1.352 + child = Array::NewFixed(zone, childArrayMap, tenure);
1.353 + else
1.354 + child = Array::NewEmpty(zone, childArrayMap, tenure);
1.355 + }
1.356 + if (!child)
1.357 + return NULL;
1.358 +
1.359 + obj->set(zone, desc, child);
1.360 + }
1.361 + }
1.362 +
1.363 + return obj;
1.364 +}
1.365 +
1.366 +bool
1.367 +Struct::Copy(Zone *zone, Handle<Struct> left, Handle<Struct> right)
1.368 +{
1.369 + assert(left->map()->type() == right->map()->type());
1.370 +
1.371 + Local<StructType> type(zone, StructType::cast(left->map()->type()));
1.372 + Local<Struct> leftStruct(zone);
1.373 + Local<Struct> rightStruct(zone);
1.374 + Local<Array> leftArray(zone);
1.375 + Local<Array> rightArray(zone);
1.376 + for (unsigned i = 0; i < type->fields()->length(); i++) {
1.377 + Descriptor *desc = Descriptor::cast(type->fields()->at(i));
1.378 +
1.379 + // If the field is a struct, we need to deep-copy.
1.380 + if (desc->type()->isStruct()) {
1.381 + leftStruct = Struct::cast(left->get<Object *>(desc));
1.382 + rightStruct = Struct::cast(right->get<Object *>(desc));
1.383 + if (!Struct::Copy(zone, leftStruct, rightStruct))
1.384 + return false;
1.385 + } else if (desc->type()->isArray()) {
1.386 + leftArray = Array::cast(left->get<Object *>(desc));
1.387 + rightArray = Array::cast(right->get<Object *>(desc));
1.388 + if (!Array::ShallowCopy(zone, leftArray, rightArray))
1.389 + return false;
1.390 + } else if (desc->type()->isTraceable()) {
1.391 + Object *obj = right->get<Object *>(desc);
1.392 + left->set(zone, desc, obj);
1.393 + } else {
1.394 + switch (desc->type()->pod()) {
1.395 + case PrimitiveType_Int32:
1.396 + case PrimitiveType_Char:
1.397 + case PrimitiveType_Bool:
1.398 + left->set(desc, right->get<int>(desc));
1.399 + break;
1.400 +
1.401 + case PrimitiveType_Float:
1.402 + left->set(desc, right->get<float>(desc));
1.403 + break;
1.404 +
1.405 + default:
1.406 + assert(false);
1.407 + }
1.408 + }
1.409 + }
1.410 +
1.411 + return true;
1.412 }
1.413 \ No newline at end of file