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