src/Zone.cpp
author David Anderson <danderson@mozilla.com>
Wed Jul 25 01:30:33 2012 -0700 (2012-07-25)
changeset 92 e3974e7360e9
parent 86 32ad0523b309
child 129 86b368a4d80d
permissions -rw-r--r--
Add GCC/Linux support.
     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_MetaEnvironment] = allocateMap(MapKind_MetaEnvironment, sizeof(Map))) == NULL)
    82         return false;
    83     if ((maps_[MapKind_Module] = allocateMap(MapKind_Module, sizeof(Map))) == NULL)
    84         return false;
    85     if ((maps_[MapKind_Function] = allocateMap(MapKind_Function, sizeof(Map))) == NULL)
    86         return false;
    87     if ((maps_[MapKind_String] = allocateMap(MapKind_String, sizeof(Map))) == NULL)
    88         return false;
    89     if ((maps_[MapKind_Native] = allocateMap(MapKind_Native, sizeof(Map))) == NULL)
    90         return false;
    91     if ((maps_[MapKind_FreeRegion] = allocateMap(MapKind_FreeRegion, sizeof(Map))) == NULL)
    92         return false;
    93     if ((maps_[MapKind_EnvironmentSlotDescriptorArray] =
    94          allocateMap(MapKind_EnvironmentSlotDescriptorArray, sizeof(Map))) == NULL)
    95     {
    96         return false;
    97     }
    98 
    99     types_ = new TypeManager(this);
   100     if (!types_ || !types_->initialize())
   101         return false;
   102 
   103     // Create the cached array maps for generic arrays. This is for the API
   104     // version of Invoke(), which needs to make arrays very quickly from C++.
   105     {
   106         // Generic "cell" array (contents do not matter, just non-gc things).
   107         Local<Type> type(this, types_->getPrimitive(PrimitiveType_Int32));
   108         if (!type)
   109             return false;
   110 
   111         type = types_->unsafeArray(type, Type::UNKNOWN_SIZE, false);
   112         if (!type)
   113             return false;
   114 
   115         Local<ArrayMap> contained(this);
   116         genericArrayMap_ = ArrayMap::New(this, type, contained);
   117         if (!genericArrayMap_)
   118             return false;
   119 
   120         type = types_->getPrimitive(PrimitiveType_Char);
   121         if (!type)
   122             return false;
   123 
   124         type = types_->unsafeArray(type, Type::UNKNOWN_SIZE, false);
   125         if (!type)
   126             return false;
   127 
   128         charArrayMap_ = ArrayMap::New(this, type, contained);
   129         if (!charArrayMap_)
   130             return false;
   131     }
   132 
   133     return true;
   134 }
   135 
   136 Map *
   137 Zone::allocateMap(MapKind kind, size_t bytes, MapKind parent)
   138 {
   139     assert(maps_[parent]);
   140     Map *map = heap_.allocateMap(kind, bytes);
   141     if (!map)
   142         return NULL;
   143     map->init(maps_[parent]);
   144     return map;
   145 }
   146 
   147 void
   148 Zone::accept(VirtualObjectVisitor *visitor)
   149 {
   150     for (unsigned i = 0; i < MapKinds_Total; i++)
   151         visitor->visit(maps_[i].address());
   152     visitor->visit(charArrayMap_.address());
   153     visitor->visit(genericArrayMap_.address());
   154     types()->accept(visitor);
   155 
   156     Local<Object> *local = lastLocalRoot_;
   157     while (local) {
   158         visitor->visit(local->address());
   159         local = local->prev();
   160     }
   161 
   162     globalRoots_->accept(visitor);
   163     rootScopes_.accept(visitor);
   164 
   165     stack_.accept(visitor);
   166 }
   167 
   168 String *
   169 Zone::makeSymbol(const char *str, size_t length)
   170 {
   171     return symbols_->add(str, length);
   172 }
   173 
   174 String *
   175 Zone::makeSymbol(const char *str)
   176 {
   177     return makeSymbol(str, strlen(str));
   178 }
   179 
   180 bool
   181 Zone::hasPendingException()
   182 {
   183     return hasPendingException_;
   184 }
   185 
   186 void
   187 Zone::reportOutOfMemory()
   188 {
   189     
   190 }
   191 
   192 void
   193 Zone::reportError(Message message, ...)
   194 {
   195     va_list ap;
   196     va_start(ap, message);
   197     reportErrorVA(message, ap);
   198     va_end(ap);
   199 }
   200 
   201 #if defined(_MSC_VER)
   202 # define VA_COPY(to, from)  to = from
   203 #else
   204 # define VA_COPY(to, from)  va_copy(to, from)
   205 #endif
   206 
   207 static char *
   208 BuildErrorMessage(const char *format, va_list ap)
   209 {
   210     va_list use;
   211     VA_COPY(use, ap);
   212 
   213     // We over-allocate and zero terminate ahead of time, since LIBCRT's
   214     // version of vsnprintf is screwy.
   215     size_t size = 255;
   216     char *buffer = (char *)calloc(size + 1, 1);
   217     if (!buffer)
   218         return NULL;
   219 
   220     for (;;) {
   221         int r = vsnprintf(buffer, size, format, use);
   222 
   223         if (r > -1 && size_t(r) < size)
   224             return buffer;
   225        
   226 #if defined(_MSC_VER)
   227         if (r < 0)
   228             size *= 2;
   229 #else
   230         if (r > -1)
   231             size = size_t(r) + 1;
   232         else
   233             size *= 2;
   234 #endif
   235 
   236         free(buffer);
   237         if ((buffer = (char *)calloc(size + 1, 1)) == NULL)
   238             return NULL;
   239 
   240         VA_COPY(use, ap);
   241     }
   242 }
   243 
   244 void
   245 Zone::reportErrorVA(Message message, va_list ap)
   246 {
   247     char *report = BuildErrorMessage(Messages[message].format, ap);
   248     if (!report) {
   249         reportOutOfMemory();
   250         return;
   251     }
   252 
   253     if (reporter_) {
   254         // Reporters can re-enter. When we start having actual exception
   255         // objects that can be caught and inspected, this code will have to
   256         // save and restore the exception state.
   257         reporter_->onUncaughtException(report);
   258     }
   259 
   260     hasPendingException_ = true;
   261 
   262     free(report);
   263 }
   264 
   265 void
   266 Zone::beginCompilationErrors(const char *file)
   267 {
   268     if (reporter_)
   269         reporter_->beginCompilationErrors(file);
   270 }
   271 
   272 void
   273 Zone::reportCompilationError(Message message, unsigned line, unsigned col, va_list ap)
   274 {
   275     char *report = BuildErrorMessage(Messages[message].format, ap);
   276     if (!report) {
   277         reportOutOfMemory();
   278         return;
   279     }
   280 
   281     if (reporter_) {
   282         // Reporters can re-enter. When we start having actual exception
   283         // objects that can be caught and inspected, this code will have to
   284         // save and restore the exception state.
   285         reporter_->reportCompilationError(report, line, col);
   286     }
   287 
   288     free(report);
   289 }
   290 
   291 void
   292 Zone::endCompilationErrors()
   293 {
   294     if (reporter_)
   295         reporter_->endCompilationErrors();
   296 }
   297 
   298 void
   299 Zone::installErrorReporter(Ke::IMessageReporter *reporter)
   300 {
   301     reporter_ = reporter;
   302 }
   303 
   304 void
   305 ZoneAllocatorPolicy::reportOutOfMemory()
   306 {
   307     ZONE()->reportOutOfMemory();
   308 }
   309 
   310 void
   311 ZoneAllocatorPolicy::reportAllocationOverflow()
   312 {
   313     ZONE()->reportError(Message_AllocationOverflow);
   314 }