src/Zone.cpp
author David Anderson <dvander@alliedmods.net>
Sat Sep 15 18:25:54 2012 -0700 (2012-09-15)
changeset 185 10936f3a2ba3
parent 184 387d76b1e981
child 188 bab29bcec7fe
permissions -rw-r--r--
Added support for declaring empty-length arrays.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft 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)
    10  * any later version.
    11  * 
    12  * Foobar 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.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include <stdlib.h>
    20 #include "Zone.h"
    21 #include "StringPool.h"
    22 #include "TypeManager.h"
    23 #include "GlobalRoots.h"
    24 #include "AllocatorPolicies.h"
    25 #include "Array.h"
    26 #include "Spaces-inl.h"
    27 #include "Heap-inl.h"
    28 
    29 using namespace ke;
    30 
    31 Zone *ke::SingleThreadedZone;
    32 
    33 Zone::Zone()
    34   : stack_(thisFromCtor()),
    35     heap_(thisFromCtor()),
    36     types_(NULL),
    37     symbols_(NULL),
    38     globalRoots_(NULL),
    39     lastLocalRoot_(NULL),
    40     hasPendingException_(false),
    41     reporter_(NULL)
    42 {
    43 }
    44 
    45 Zone::~Zone()
    46 {
    47     delete types_;
    48     delete symbols_;
    49     delete globalRoots_;
    50 }
    51 
    52 bool
    53 Zone::initialize()
    54 {
    55     if (!stack_.initialize())
    56         return false;
    57     if (!heap_.initialize())
    58         return false;
    59 
    60     symbols_ = new StringPool(this);
    61     if (!symbols_ || !symbols_->initialize())
    62         return false;
    63 
    64     globalRoots_ = new GlobalRoots(this);
    65     if (!globalRoots_ || !globalRoots_->initialize())
    66         return false;
    67 
    68     maps_[MapKind_Meta] = heap_.metaMap();
    69     if ((maps_[MapKind_Type] = allocateMap(MapKind_Type, sizeof(Map))) == NULL)
    70         return false;
    71     if ((maps_[MapKind_FixedArray] = allocateMap(MapKind_FixedArray, sizeof(Map))) == NULL)
    72         return false;
    73     if ((maps_[MapKind_ByteArray] = allocateMap(MapKind_ByteArray, sizeof(Map))) == NULL)
    74         return false;
    75     if ((maps_[MapKind_Code] = allocateMap(MapKind_Code, sizeof(Map))) == NULL)
    76         return false;
    77     if ((maps_[MapKind_Reference] = allocateMap(MapKind_Reference, sizeof(Map))) == NULL)
    78         return false;
    79     if ((maps_[MapKind_MetaArray] = allocateMap(MapKind_MetaArray, sizeof(Map))) == NULL)
    80         return false;
    81     if ((maps_[MapKind_MetaStruct] = allocateMap(MapKind_MetaStruct, sizeof(Map))) == NULL)
    82         return false;
    83     if ((maps_[MapKind_MetaEnvironment] = allocateMap(MapKind_MetaEnvironment, sizeof(Map))) == NULL)
    84         return false;
    85     if ((maps_[MapKind_Module] = allocateMap(MapKind_Module, sizeof(Map))) == NULL)
    86         return false;
    87     if ((maps_[MapKind_Function] = allocateMap(MapKind_Function, sizeof(Map))) == NULL)
    88         return false;
    89     if ((maps_[MapKind_String] = allocateMap(MapKind_String, sizeof(Map))) == NULL)
    90         return false;
    91     if ((maps_[MapKind_Native] = allocateMap(MapKind_Native, sizeof(Map))) == NULL)
    92         return false;
    93     if ((maps_[MapKind_Descriptor] = allocateMap(MapKind_Descriptor, sizeof(Map))) == NULL)
    94         return false;
    95     if ((maps_[MapKind_Box] = allocateMap(MapKind_Box, sizeof(Map))) == NULL)
    96         return false;
    97     if ((maps_[MapKind_FreeRegion] = allocateMap(MapKind_FreeRegion, sizeof(Map))) == NULL)
    98         return false;
    99     if ((maps_[MapKind_EnvironmentSlotDescriptorArray] =
   100          allocateMap(MapKind_EnvironmentSlotDescriptorArray, sizeof(Map))) == NULL)
   101     {
   102         return false;
   103     }
   104 
   105     types_ = new TypeManager(this);
   106     if (!types_ || !types_->initialize())
   107         return false;
   108 
   109     // Create the cached array maps for generic arrays. This is for the API
   110     // version of Invoke(), which needs to make arrays very quickly from C++.
   111     {
   112         // Generic "cell" array (contents do not matter, just non-gc things).
   113         Local<Type> type(this, types_->getPrimitive(PrimitiveType_Int32));
   114         if (!type)
   115             return false;
   116 
   117         type = types_->newArray(type, Type::DYNAMIC_ARRAY_SIZE, false);
   118         if (!type)
   119             return false;
   120 
   121         genericArrayMap_ = ArrayMap::New(this, type);
   122         if (!genericArrayMap_)
   123             return false;
   124 
   125         type = types_->getPrimitive(PrimitiveType_Char);
   126         if (!type)
   127             return false;
   128 
   129         type = types_->newArray(type, Type::DYNAMIC_ARRAY_SIZE, false);
   130         if (!type)
   131             return false;
   132 
   133         charArrayMap_ = ArrayMap::New(this, type);
   134         if (!charArrayMap_)
   135             return false;
   136     }
   137 
   138     return true;
   139 }
   140 
   141 Map *
   142 Zone::allocateMap(MapKind kind, size_t bytes, MapKind parent)
   143 {
   144     assert(maps_[parent]);
   145     Map *map = heap_.allocateMap(kind, bytes);
   146     if (!map)
   147         return NULL;
   148     map->init(maps_[parent]);
   149     return map;
   150 }
   151 
   152 void
   153 Zone::accept(VirtualObjectVisitor *visitor)
   154 {
   155     for (unsigned i = 0; i < MapKinds_Total; i++)
   156         visitor->visit(maps_[i].address());
   157     visitor->visit(charArrayMap_.address());
   158     visitor->visit(genericArrayMap_.address());
   159     types()->accept(visitor);
   160 
   161     Local<Object> *local = lastLocalRoot_;
   162     while (local) {
   163         visitor->visit(local->address());
   164         local = local->prev();
   165     }
   166 
   167     globalRoots_->accept(visitor);
   168     rootScopes_.accept(visitor);
   169 
   170     stack_.accept(visitor);
   171 }
   172 
   173 String *
   174 Zone::makeSymbol(const char *str, size_t length)
   175 {
   176     return symbols_->add(str, length);
   177 }
   178 
   179 String *
   180 Zone::makeSymbol(const char *str)
   181 {
   182     return makeSymbol(str, strlen(str));
   183 }
   184 
   185 bool
   186 Zone::hasPendingException()
   187 {
   188     return hasPendingException_;
   189 }
   190 
   191 void
   192 Zone::reportOutOfMemory()
   193 {
   194     
   195 }
   196 
   197 void
   198 Zone::reportError(Message message, ...)
   199 {
   200     va_list ap;
   201     va_start(ap, message);
   202     reportErrorVA(message, ap);
   203     va_end(ap);
   204 }
   205 
   206 #if defined(_MSC_VER)
   207 # define VA_COPY(to, from)  to = from
   208 #else
   209 # define VA_COPY(to, from)  va_copy(to, from)
   210 #endif
   211 
   212 static char *
   213 BuildErrorMessage(const char *format, va_list ap)
   214 {
   215     va_list use;
   216     VA_COPY(use, ap);
   217 
   218     // We over-allocate and zero terminate ahead of time, since LIBCRT's
   219     // version of vsnprintf is screwy.
   220     size_t size = 255;
   221     char *buffer = (char *)calloc(size + 1, 1);
   222     if (!buffer)
   223         return NULL;
   224 
   225     for (;;) {
   226         int r = vsnprintf(buffer, size, format, use);
   227 
   228         if (r > -1 && size_t(r) < size)
   229             return buffer;
   230        
   231 #if defined(_MSC_VER)
   232         if (r < 0)
   233             size *= 2;
   234 #else
   235         if (r > -1)
   236             size = size_t(r) + 1;
   237         else
   238             size *= 2;
   239 #endif
   240 
   241         free(buffer);
   242         if ((buffer = (char *)calloc(size + 1, 1)) == NULL)
   243             return NULL;
   244 
   245         VA_COPY(use, ap);
   246     }
   247 }
   248 
   249 void
   250 Zone::reportErrorVA(Message message, va_list ap)
   251 {
   252     char *report = BuildErrorMessage(Messages[message].format, ap);
   253     if (!report) {
   254         reportOutOfMemory();
   255         return;
   256     }
   257 
   258     if (reporter_) {
   259         // Reporters can re-enter. When we start having actual exception
   260         // objects that can be caught and inspected, this code will have to
   261         // save and restore the exception state.
   262         reporter_->onUncaughtException(report);
   263     }
   264 
   265     hasPendingException_ = true;
   266 
   267     free(report);
   268 }
   269 
   270 void
   271 Zone::beginCompilationErrors(const char *file)
   272 {
   273     if (reporter_)
   274         reporter_->beginCompilationErrors(file);
   275 }
   276 
   277 void
   278 Zone::reportCompilationError(Message message, unsigned line, unsigned col, va_list ap)
   279 {
   280     char *report = BuildErrorMessage(Messages[message].format, ap);
   281     if (!report) {
   282         reportOutOfMemory();
   283         return;
   284     }
   285 
   286     if (reporter_) {
   287         // Reporters can re-enter. When we start having actual exception
   288         // objects that can be caught and inspected, this code will have to
   289         // save and restore the exception state.
   290         reporter_->reportCompilationError(report, line, col);
   291     }
   292 
   293     free(report);
   294 }
   295 
   296 void
   297 Zone::endCompilationErrors()
   298 {
   299     if (reporter_)
   300         reporter_->endCompilationErrors();
   301 }
   302 
   303 void
   304 Zone::installErrorReporter(Ke::IMessageReporter *reporter)
   305 {
   306     reporter_ = reporter;
   307 }
   308 
   309 void
   310 ZoneAllocatorPolicy::reportOutOfMemory()
   311 {
   312     ZONE()->reportOutOfMemory();
   313 }
   314 
   315 void
   316 ZoneAllocatorPolicy::reportAllocationOverflow()
   317 {
   318     ZONE()->reportError(Message_AllocationOverflow);
   319 }
   320 
   321 void
   322 Zone::clearPendingException()
   323 {
   324     hasPendingException_ = false;
   325 }
   326