1.1 --- a/src/Zone.cpp Mon Jun 10 00:46:29 2013 +0100
1.2 +++ b/src/Zone.cpp Mon Jun 10 01:04:43 2013 +0100
1.3 @@ -1,368 +1,368 @@
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 -#include <stdlib.h>
1.23 -#include "Zone.h"
1.24 -#include "StringPool.h"
1.25 -#include "TypeManager.h"
1.26 -#include "GlobalRoots.h"
1.27 -#include "AllocatorPolicies.h"
1.28 -#include "Array.h"
1.29 -#include "NativeTable.h"
1.30 -#include "Packages.h"
1.31 -#include "Spaces-inl.h"
1.32 -#include "Heap-inl.h"
1.33 -
1.34 -using namespace ke;
1.35 -
1.36 -Zone *ke::SingleThreadedZone;
1.37 -
1.38 -void * const NullAddress::Sentinel = NULL;
1.39 -
1.40 -Zone::Zone()
1.41 - : stack_(thisFromCtor()),
1.42 - heap_(thisFromCtor()),
1.43 - types_(NULL),
1.44 - symbols_(NULL),
1.45 - globalRoots_(NULL),
1.46 - nativeTable_(NULL),
1.47 - packages_(NULL),
1.48 - lastLocalRoot_(NULL),
1.49 - specialRoots_(NULL),
1.50 - hasPendingException_(false),
1.51 - reporter_(NULL)
1.52 -{
1.53 -}
1.54 -
1.55 -Zone::~Zone()
1.56 -{
1.57 - delete nativeTable_;
1.58 - delete types_;
1.59 - delete symbols_;
1.60 - delete packages_;
1.61 - delete globalRoots_;
1.62 -}
1.63 -
1.64 -bool
1.65 -Zone::initialize()
1.66 -{
1.67 - if (!stack_.initialize())
1.68 - return false;
1.69 - if (!heap_.initialize())
1.70 - return false;
1.71 -
1.72 - symbols_ = new StringPool(this);
1.73 - if (!symbols_ || !symbols_->initialize())
1.74 - return false;
1.75 -
1.76 - globalRoots_ = new GlobalRoots(this);
1.77 - if (!globalRoots_ || !globalRoots_->initialize())
1.78 - return false;
1.79 -
1.80 - nativeTable_ = new NativeTable(this);
1.81 - if (!nativeTable_ || !nativeTable_->initialize())
1.82 - return false;
1.83 -
1.84 - packages_ = new PackageCache(this);
1.85 - if (!packages_ || !packages_->initialize())
1.86 - return false;
1.87 -
1.88 - MapKind maps[] =
1.89 - {
1.90 - MapKind_Type,
1.91 - MapKind_ArrayType,
1.92 - MapKind_FunctionType,
1.93 - MapKind_StructType,
1.94 - MapKind_ReferenceType,
1.95 - MapKind_EnumType,
1.96 - MapKind_FixedArray,
1.97 - MapKind_ByteArray,
1.98 - MapKind_Code,
1.99 - MapKind_Reference,
1.100 - MapKind_MetaArray,
1.101 - MapKind_MetaStruct,
1.102 - MapKind_MetaEnvironment,
1.103 - MapKind_Module,
1.104 - MapKind_Function,
1.105 - MapKind_String,
1.106 - MapKind_Native,
1.107 - MapKind_Descriptor,
1.108 - MapKind_Box,
1.109 - MapKind_List,
1.110 - MapKind_Package,
1.111 - MapKind_FreeRegion,
1.112 - MapKind_EnvironmentSlotDescriptorArray
1.113 - };
1.114 -
1.115 - maps_[MapKind_Meta] = heap_.metaMap();
1.116 - for (size_t i = 0; i < sizeof(maps) / sizeof(maps[0]); i++) {
1.117 - if ((maps_[maps[i]] = allocateMap(maps[i], sizeof(Map))) == NULL)
1.118 - return false;
1.119 - }
1.120 -
1.121 - types_ = new TypeManager(this);
1.122 - if (!types_ || !types_->initialize())
1.123 - return false;
1.124 -
1.125 - // Create the cached array maps for generic arrays. This is for the API
1.126 - // version of Invoke(), which needs to make arrays very quickly from C++.
1.127 - {
1.128 - // Generic "cell" array (contents do not matter, just non-gc things).
1.129 - Local<Type> type(this, types_->getPrimitive(PrimitiveType_Int32));
1.130 - if (!type)
1.131 - return false;
1.132 -
1.133 - type = types_->newExternalArray(type);
1.134 - if (!type)
1.135 - return false;
1.136 -
1.137 - // :TODO:
1.138 -#if 0
1.139 - externalGenericArrayMap_ = ArrayMap::Attach(this, type);
1.140 - if (!externalGenericArrayMap_)
1.141 - return false;
1.142 -#endif
1.143 -
1.144 - type = types_->getPrimitive(PrimitiveType_Char);
1.145 - if (!type)
1.146 - return false;
1.147 -
1.148 - type = types_->newExternalArray(type);
1.149 - if (!type)
1.150 - return false;
1.151 -
1.152 - // :TODO:
1.153 -#if 0
1.154 - externalCharArrayMap_ = ArrayMap::Attach(this, type);
1.155 - if (!externalCharArrayMap_)
1.156 - return false;
1.157 -#endif
1.158 - }
1.159 -
1.160 - return true;
1.161 -}
1.162 -
1.163 -Map *
1.164 -Zone::allocateMap(MapKind kind, size_t bytes, MapKind parent)
1.165 -{
1.166 - assert(maps_[parent]);
1.167 - Map *map = heap_.allocateMap(kind, bytes);
1.168 - if (!map)
1.169 - return NULL;
1.170 - map->init(maps_[parent]);
1.171 - return map;
1.172 -}
1.173 -
1.174 -void
1.175 -Zone::accept(VirtualObjectVisitor *visitor)
1.176 -{
1.177 - for (unsigned i = 0; i < MapKinds_Total; i++)
1.178 - visitor->visit(maps_[i].address());
1.179 - visitor->visit(externalCharArrayMap_.address());
1.180 - visitor->visit(externalGenericArrayMap_.address());
1.181 - types()->accept(visitor);
1.182 -
1.183 - Local<Object> *local = lastLocalRoot_;
1.184 - while (local) {
1.185 - visitor->visit(local->address());
1.186 - local = local->prev();
1.187 - }
1.188 -
1.189 - globalRoots_->accept(visitor);
1.190 - rootScopes_.accept(visitor);
1.191 - nativeTable_->accept(visitor);
1.192 - packages_->accept(visitor);
1.193 -
1.194 - stack_.accept(visitor);
1.195 -}
1.196 -
1.197 -void
1.198 -Zone::sweepWeakRoots()
1.199 -{
1.200 - symbols_->sweep();
1.201 - types()->sweep();
1.202 -}
1.203 -
1.204 -String *
1.205 -Zone::makeSymbol(const char *str, size_t length)
1.206 -{
1.207 - return symbols_->add(str, length);
1.208 -}
1.209 -
1.210 -String *
1.211 -Zone::makeSymbol(const char *str)
1.212 -{
1.213 - return makeSymbol(str, strlen(str));
1.214 -}
1.215 -
1.216 -bool
1.217 -Zone::hasPendingException()
1.218 -{
1.219 - return hasPendingException_;
1.220 -}
1.221 -
1.222 -void
1.223 -Zone::reportOutOfMemory()
1.224 -{
1.225 -
1.226 -}
1.227 -
1.228 -void
1.229 -Zone::reportError(Message message, ...)
1.230 -{
1.231 - va_list ap;
1.232 - va_start(ap, message);
1.233 - reportErrorVA(message, ap);
1.234 - va_end(ap);
1.235 -}
1.236 -
1.237 -#if defined(_MSC_VER)
1.238 -# define VA_COPY(to, from) to = from
1.239 -#else
1.240 -# define VA_COPY(to, from) va_copy(to, from)
1.241 -#endif
1.242 -
1.243 -char *
1.244 -ke::BuildErrorMessage(const char *format, va_list ap)
1.245 -{
1.246 - va_list use;
1.247 - VA_COPY(use, ap);
1.248 -
1.249 - // We over-allocate and zero terminate ahead of time, since LIBCRT's
1.250 - // version of vsnprintf is screwy.
1.251 - size_t size = 255;
1.252 - char *buffer = (char *)calloc(size + 1, 1);
1.253 - if (!buffer)
1.254 - return NULL;
1.255 -
1.256 - for (;;) {
1.257 - int r = vsnprintf(buffer, size, format, use);
1.258 -
1.259 - if (r > -1 && size_t(r) < size)
1.260 - return buffer;
1.261 -
1.262 -#if defined(_MSC_VER)
1.263 - if (r < 0)
1.264 - size *= 2;
1.265 -#else
1.266 - if (r > -1)
1.267 - size = size_t(r) + 1;
1.268 - else
1.269 - size *= 2;
1.270 -#endif
1.271 -
1.272 - free(buffer);
1.273 - if ((buffer = (char *)calloc(size + 1, 1)) == NULL)
1.274 - return NULL;
1.275 -
1.276 - VA_COPY(use, ap);
1.277 - }
1.278 -}
1.279 -
1.280 -void
1.281 -ke::FreeErrorMessage(const char *message)
1.282 -{
1.283 - free((void *)message);
1.284 -}
1.285 -
1.286 -void
1.287 -Zone::reportErrorVA(Message message, va_list ap)
1.288 -{
1.289 - char *report = BuildErrorMessage(Messages[message].format, ap);
1.290 - if (!report) {
1.291 - reportOutOfMemory();
1.292 - return;
1.293 - }
1.294 -
1.295 - if (reporter_) {
1.296 - // Reporters can re-enter. When we start having actual exception
1.297 - // objects that can be caught and inspected, this code will have to
1.298 - // save and restore the exception state.
1.299 - reporter_->onUncaughtException(report);
1.300 - }
1.301 -
1.302 - hasPendingException_ = true;
1.303 -
1.304 - FreeErrorMessage(report);
1.305 -}
1.306 -
1.307 -void
1.308 -Zone::installErrorReporter(Ke::IMessageReporter *reporter)
1.309 -{
1.310 - reporter_ = reporter;
1.311 -}
1.312 -
1.313 -void
1.314 -ZoneAllocatorPolicy::reportOutOfMemory()
1.315 -{
1.316 - ZONE()->reportOutOfMemory();
1.317 -}
1.318 -
1.319 -void
1.320 -ZoneAllocatorPolicy::reportAllocationOverflow()
1.321 -{
1.322 - ZONE()->reportAllocationOverflow();
1.323 -}
1.324 -
1.325 -void
1.326 -Zone::reportAllocationOverflow()
1.327 -{
1.328 - reportError(Message_AllocationOverflow);
1.329 -}
1.330 -
1.331 -void
1.332 -Zone::clearPendingException()
1.333 -{
1.334 - hasPendingException_ = false;
1.335 -}
1.336 -
1.337 -void
1.338 -Zone::setPublicFunctionListener(Ke::IPublicFunctionListener *listener)
1.339 -{
1.340 - publicFunctionListener_ = listener;
1.341 -}
1.342 -
1.343 -void *
1.344 -Zone::malloc(size_t size)
1.345 -{
1.346 - void *ptr = ::malloc(size);
1.347 - if (!ptr)
1.348 - reportOutOfMemory();
1.349 - return ptr;
1.350 -}
1.351 -
1.352 -void *
1.353 -Zone::realloc(void *ptr, size_t size)
1.354 -{
1.355 - ptr = ::realloc(ptr, size);
1.356 - if (!ptr)
1.357 - reportOutOfMemory();
1.358 - return ptr;
1.359 -}
1.360 -
1.361 -AutoRooted::AutoRooted(Zone *zone)
1.362 - : zone_(zone),
1.363 - prev_(*zone->lastSpecialRoot())
1.364 -{
1.365 - *zone->lastSpecialRoot() = this;
1.366 -}
1.367 -
1.368 -AutoRooted::~AutoRooted()
1.369 -{
1.370 - *zone_->lastSpecialRoot() = prev_;
1.371 -}
1.372 +/* vim: set ts=4 sw=4 tw=99 et:
1.373 + *
1.374 + * Copyright (C) 2012 David Anderson
1.375 + *
1.376 + * This file is part of JITCraft.
1.377 + *
1.378 + * JITCraft is free software: you can redistribute it and/or modify it under
1.379 + * the terms of the GNU General Public License as published by the Free
1.380 + * Software Foundation, either version 3 of the License, or (at your option)
1.381 + * any later version.
1.382 + *
1.383 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
1.384 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.385 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.386 + *
1.387 + * You should have received a copy of the GNU General Public License along with
1.388 + * JITCraft. If not, see http://www.gnu.org/licenses/.
1.389 + */
1.390 +#include <stdlib.h>
1.391 +#include "Zone.h"
1.392 +#include "StringPool.h"
1.393 +#include "TypeManager.h"
1.394 +#include "GlobalRoots.h"
1.395 +#include "AllocatorPolicies.h"
1.396 +#include "Array.h"
1.397 +#include "NativeTable.h"
1.398 +#include "Packages.h"
1.399 +#include "Spaces-inl.h"
1.400 +#include "Heap-inl.h"
1.401 +
1.402 +using namespace ke;
1.403 +
1.404 +Zone *ke::SingleThreadedZone;
1.405 +
1.406 +void * const NullAddress::Sentinel = NULL;
1.407 +
1.408 +Zone::Zone()
1.409 + : stack_(thisFromCtor()),
1.410 + heap_(thisFromCtor()),
1.411 + types_(NULL),
1.412 + symbols_(NULL),
1.413 + globalRoots_(NULL),
1.414 + nativeTable_(NULL),
1.415 + packages_(NULL),
1.416 + lastLocalRoot_(NULL),
1.417 + specialRoots_(NULL),
1.418 + hasPendingException_(false),
1.419 + reporter_(NULL)
1.420 +{
1.421 +}
1.422 +
1.423 +Zone::~Zone()
1.424 +{
1.425 + delete nativeTable_;
1.426 + delete types_;
1.427 + delete symbols_;
1.428 + delete packages_;
1.429 + delete globalRoots_;
1.430 +}
1.431 +
1.432 +bool
1.433 +Zone::initialize()
1.434 +{
1.435 + if (!stack_.initialize())
1.436 + return false;
1.437 + if (!heap_.initialize())
1.438 + return false;
1.439 +
1.440 + symbols_ = new StringPool(this);
1.441 + if (!symbols_ || !symbols_->initialize())
1.442 + return false;
1.443 +
1.444 + globalRoots_ = new GlobalRoots(this);
1.445 + if (!globalRoots_ || !globalRoots_->initialize())
1.446 + return false;
1.447 +
1.448 + nativeTable_ = new NativeTable(this);
1.449 + if (!nativeTable_ || !nativeTable_->initialize())
1.450 + return false;
1.451 +
1.452 + packages_ = new PackageCache(this);
1.453 + if (!packages_ || !packages_->initialize())
1.454 + return false;
1.455 +
1.456 + MapKind maps[] =
1.457 + {
1.458 + MapKind_Type,
1.459 + MapKind_ArrayType,
1.460 + MapKind_FunctionType,
1.461 + MapKind_StructType,
1.462 + MapKind_ReferenceType,
1.463 + MapKind_EnumType,
1.464 + MapKind_FixedArray,
1.465 + MapKind_ByteArray,
1.466 + MapKind_Code,
1.467 + MapKind_Reference,
1.468 + MapKind_MetaArray,
1.469 + MapKind_MetaStruct,
1.470 + MapKind_MetaEnvironment,
1.471 + MapKind_Module,
1.472 + MapKind_Function,
1.473 + MapKind_String,
1.474 + MapKind_Native,
1.475 + MapKind_Descriptor,
1.476 + MapKind_Box,
1.477 + MapKind_List,
1.478 + MapKind_Package,
1.479 + MapKind_FreeRegion,
1.480 + MapKind_EnvironmentSlotDescriptorArray
1.481 + };
1.482 +
1.483 + maps_[MapKind_Meta] = heap_.metaMap();
1.484 + for (size_t i = 0; i < sizeof(maps) / sizeof(maps[0]); i++) {
1.485 + if ((maps_[maps[i]] = allocateMap(maps[i], sizeof(Map))) == NULL)
1.486 + return false;
1.487 + }
1.488 +
1.489 + types_ = new TypeManager(this);
1.490 + if (!types_ || !types_->initialize())
1.491 + return false;
1.492 +
1.493 + // Create the cached array maps for generic arrays. This is for the API
1.494 + // version of Invoke(), which needs to make arrays very quickly from C++.
1.495 + {
1.496 + // Generic "cell" array (contents do not matter, just non-gc things).
1.497 + Local<Type> type(this, types_->getPrimitive(PrimitiveType_Int32));
1.498 + if (!type)
1.499 + return false;
1.500 +
1.501 + type = types_->newExternalArray(type);
1.502 + if (!type)
1.503 + return false;
1.504 +
1.505 + // :TODO:
1.506 +#if 0
1.507 + externalGenericArrayMap_ = ArrayMap::Attach(this, type);
1.508 + if (!externalGenericArrayMap_)
1.509 + return false;
1.510 +#endif
1.511 +
1.512 + type = types_->getPrimitive(PrimitiveType_Char);
1.513 + if (!type)
1.514 + return false;
1.515 +
1.516 + type = types_->newExternalArray(type);
1.517 + if (!type)
1.518 + return false;
1.519 +
1.520 + // :TODO:
1.521 +#if 0
1.522 + externalCharArrayMap_ = ArrayMap::Attach(this, type);
1.523 + if (!externalCharArrayMap_)
1.524 + return false;
1.525 +#endif
1.526 + }
1.527 +
1.528 + return true;
1.529 +}
1.530 +
1.531 +Map *
1.532 +Zone::allocateMap(MapKind kind, size_t bytes, MapKind parent)
1.533 +{
1.534 + assert(maps_[parent]);
1.535 + Map *map = heap_.allocateMap(kind, bytes);
1.536 + if (!map)
1.537 + return NULL;
1.538 + map->init(maps_[parent]);
1.539 + return map;
1.540 +}
1.541 +
1.542 +void
1.543 +Zone::accept(VirtualObjectVisitor *visitor)
1.544 +{
1.545 + for (unsigned i = 0; i < MapKinds_Total; i++)
1.546 + visitor->visit(maps_[i].address());
1.547 + visitor->visit(externalCharArrayMap_.address());
1.548 + visitor->visit(externalGenericArrayMap_.address());
1.549 + types()->accept(visitor);
1.550 +
1.551 + Local<Object> *local = lastLocalRoot_;
1.552 + while (local) {
1.553 + visitor->visit(local->address());
1.554 + local = local->prev();
1.555 + }
1.556 +
1.557 + globalRoots_->accept(visitor);
1.558 + rootScopes_.accept(visitor);
1.559 + nativeTable_->accept(visitor);
1.560 + packages_->accept(visitor);
1.561 +
1.562 + stack_.accept(visitor);
1.563 +}
1.564 +
1.565 +void
1.566 +Zone::sweepWeakRoots()
1.567 +{
1.568 + symbols_->sweep();
1.569 + types()->sweep();
1.570 +}
1.571 +
1.572 +String *
1.573 +Zone::makeSymbol(const char *str, size_t length)
1.574 +{
1.575 + return symbols_->add(str, length);
1.576 +}
1.577 +
1.578 +String *
1.579 +Zone::makeSymbol(const char *str)
1.580 +{
1.581 + return makeSymbol(str, strlen(str));
1.582 +}
1.583 +
1.584 +bool
1.585 +Zone::hasPendingException()
1.586 +{
1.587 + return hasPendingException_;
1.588 +}
1.589 +
1.590 +void
1.591 +Zone::reportOutOfMemory()
1.592 +{
1.593 +
1.594 +}
1.595 +
1.596 +void
1.597 +Zone::reportError(Message message, ...)
1.598 +{
1.599 + va_list ap;
1.600 + va_start(ap, message);
1.601 + reportErrorVA(message, ap);
1.602 + va_end(ap);
1.603 +}
1.604 +
1.605 +#if defined(_MSC_VER)
1.606 +# define VA_COPY(to, from) to = from
1.607 +#else
1.608 +# define VA_COPY(to, from) va_copy(to, from)
1.609 +#endif
1.610 +
1.611 +char *
1.612 +ke::BuildErrorMessage(const char *format, va_list ap)
1.613 +{
1.614 + va_list use;
1.615 + VA_COPY(use, ap);
1.616 +
1.617 + // We over-allocate and zero terminate ahead of time, since LIBCRT's
1.618 + // version of vsnprintf is screwy.
1.619 + size_t size = 255;
1.620 + char *buffer = (char *)calloc(size + 1, 1);
1.621 + if (!buffer)
1.622 + return NULL;
1.623 +
1.624 + for (;;) {
1.625 + int r = vsnprintf(buffer, size, format, use);
1.626 +
1.627 + if (r > -1 && size_t(r) < size)
1.628 + return buffer;
1.629 +
1.630 +#if defined(_MSC_VER)
1.631 + if (r < 0)
1.632 + size *= 2;
1.633 +#else
1.634 + if (r > -1)
1.635 + size = size_t(r) + 1;
1.636 + else
1.637 + size *= 2;
1.638 +#endif
1.639 +
1.640 + free(buffer);
1.641 + if ((buffer = (char *)calloc(size + 1, 1)) == NULL)
1.642 + return NULL;
1.643 +
1.644 + VA_COPY(use, ap);
1.645 + }
1.646 +}
1.647 +
1.648 +void
1.649 +ke::FreeErrorMessage(const char *message)
1.650 +{
1.651 + free((void *)message);
1.652 +}
1.653 +
1.654 +void
1.655 +Zone::reportErrorVA(Message message, va_list ap)
1.656 +{
1.657 + char *report = BuildErrorMessage(Messages[message].format, ap);
1.658 + if (!report) {
1.659 + reportOutOfMemory();
1.660 + return;
1.661 + }
1.662 +
1.663 + if (reporter_) {
1.664 + // Reporters can re-enter. When we start having actual exception
1.665 + // objects that can be caught and inspected, this code will have to
1.666 + // save and restore the exception state.
1.667 + reporter_->onUncaughtException(report);
1.668 + }
1.669 +
1.670 + hasPendingException_ = true;
1.671 +
1.672 + FreeErrorMessage(report);
1.673 +}
1.674 +
1.675 +void
1.676 +Zone::installErrorReporter(Ke::IMessageReporter *reporter)
1.677 +{
1.678 + reporter_ = reporter;
1.679 +}
1.680 +
1.681 +void
1.682 +ZoneAllocatorPolicy::reportOutOfMemory()
1.683 +{
1.684 + ZONE()->reportOutOfMemory();
1.685 +}
1.686 +
1.687 +void
1.688 +ZoneAllocatorPolicy::reportAllocationOverflow()
1.689 +{
1.690 + ZONE()->reportAllocationOverflow();
1.691 +}
1.692 +
1.693 +void
1.694 +Zone::reportAllocationOverflow()
1.695 +{
1.696 + reportError(Message_AllocationOverflow);
1.697 +}
1.698 +
1.699 +void
1.700 +Zone::clearPendingException()
1.701 +{
1.702 + hasPendingException_ = false;
1.703 +}
1.704 +
1.705 +void
1.706 +Zone::setPublicFunctionListener(Ke::IPublicFunctionListener *listener)
1.707 +{
1.708 + publicFunctionListener_ = listener;
1.709 +}
1.710 +
1.711 +void *
1.712 +Zone::malloc(size_t size)
1.713 +{
1.714 + void *ptr = ::malloc(size);
1.715 + if (!ptr)
1.716 + reportOutOfMemory();
1.717 + return ptr;
1.718 +}
1.719 +
1.720 +void *
1.721 +Zone::realloc(void *ptr, size_t size)
1.722 +{
1.723 + ptr = ::realloc(ptr, size);
1.724 + if (!ptr)
1.725 + reportOutOfMemory();
1.726 + return ptr;
1.727 +}
1.728 +
1.729 +AutoRooted::AutoRooted(Zone *zone)
1.730 + : zone_(zone),
1.731 + prev_(*zone->lastSpecialRoot())
1.732 +{
1.733 + *zone->lastSpecialRoot() = this;
1.734 +}
1.735 +
1.736 +AutoRooted::~AutoRooted()
1.737 +{
1.738 + *zone_->lastSpecialRoot() = prev_;
1.739 +}