src/Interpreter.cpp
author David Anderson <dvander@alliedmods.net>
Sat Nov 17 20:11:05 2012 -0800 (2012-11-17)
changeset 206 3a896e9b57e2
parent 196 9904633b1dfc
child 207 04ce04a54936
permissions -rw-r--r--
Add test for |do|.
dvander@39
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@39
     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
 */
danderson@91
    19
#include <string.h>
dvander@0
    20
#include "Interpreter.h"
dvander@0
    21
#include "Modules.h"
dvander@0
    22
#include "Zone.h"
dvander@0
    23
#include "Types.h"
dvander@12
    24
#include "Array.h"
dvander@14
    25
#include "Reference.h"
dvander@69
    26
#include "Strings.h"
dvander@85
    27
#include "Environments.h"
dvander@147
    28
#include "Structures.h"
dvander@195
    29
#include "NativeTable.h"
dvander@28
    30
#include "Heap-inl.h"
dvander@0
    31
dvander@59
    32
using namespace ke;
dvander@0
    33
dvander@0
    34
#define PUSH_I32(top, value)    \
dvander@0
    35
    do {                        \
dvander@0
    36
        top.sp->i32 = value;    \
dvander@0
    37
        top.sp++;               \
dvander@0
    38
   } while (0)
dvander@0
    39
dvander@4
    40
#define PUSH_F(top, value)      \
dvander@4
    41
    do {                        \
dvander@4
    42
        top.sp->f = value;      \
dvander@4
    43
        top.sp++;               \
dvander@4
    44
   } while (0)
dvander@4
    45
dvander@0
    46
static inline int
dvander@0
    47
POP_I32(Top &top)
dvander@0
    48
{
dvander@0
    49
    int value = top.sp[-1].i32;
dvander@0
    50
    top.sp--;
dvander@0
    51
    return value;
dvander@0
    52
}
dvander@0
    53
dvander@4
    54
static inline float
dvander@4
    55
POP_F(Top &top)
dvander@4
    56
{
dvander@4
    57
    float value = top.sp[-1].f;
dvander@4
    58
    top.sp--;
dvander@4
    59
    return value;
dvander@4
    60
}
dvander@4
    61
dvander@77
    62
// Pawn's original semantics specify some kind of floor operation, so
dvander@77
    63
// (8 / -3 == -3) and (-8 / 3 == -1). The SourcePawn 1 compiler (spcomp) uses
dvander@77
    64
// the upstream algorithm when constant folding. However the SourcePawn 1 JIT
dvander@77
    65
// does not. My guess is that Borja freaked out seeing the 13-instruction x86
dvander@77
    66
// sequence necessary to get this functionality (I vaguely recall a thread
dvander@77
    67
// where we discussed this with Mark Peter? But the ITB forums are gone...),
dvander@77
    68
// and we just decided to break the damn thing. So SP1 was inconsistent, but
dvander@77
    69
// we are not. And for completeness, we assert that the C compiler does the
dvander@77
    70
// right thing, since C89 leaves it unspecified.
dvander@77
    71
STATIC_ASSERT(8 / -3 == -2);
dvander@77
    72
STATIC_ASSERT(-8 / 3 == -2);
dvander@77
    73
dvander@0
    74
static inline bool
dvander@14
    75
PushNewRef(Zone *zone, Top &top, void *location, Heap::Tenure tenure)
dvander@14
    76
{
dvander@14
    77
    Reference *ref = Reference::NewStack(zone, location, tenure);
dvander@14
    78
    if (!ref)
dvander@14
    79
        return false;
dvander@14
    80
    top.sp->ref = ref;
dvander@14
    81
    top.sp++;
dvander@14
    82
    return true;
dvander@14
    83
}
dvander@14
    84
dvander@178
    85
static bool CopyStruct(Zone *zone, Handle<Struct> left, Handle<Struct> right);
dvander@155
    86
dvander@179
    87
static bool
dvander@179
    88
ChangeArrayLength(Zone *zone, Handle<Array> source, Handle<Array> dest)
dvander@179
    89
{
dvander@179
    90
    return true;
dvander@179
    91
}
dvander@179
    92
dvander@152
    93
// Even though this function can fail, we immediately bail out, so it doesn't
dvander@152
    94
// matter if we've leaving things unrooted.
dvander@21
    95
static bool
dvander@179
    96
CopyArray(Zone *zone, Handle<Array> dest, Handle<Array> source)
dvander@21
    97
{
dvander@178
    98
    if (source->length() != dest->length()) {
dvander@179
    99
        if (!ChangeArrayLength(zone, source, dest))
dvander@179
   100
            return false;
dvander@178
   101
    }
dvander@178
   102
dvander@187
   103
    Local<Type> contained(zone, source->type()->contained());
dvander@187
   104
    if (contained->isArray() && contained->isFixedLength()) {
dvander@155
   105
        assert(dest->type()->contained()->isArray());
dvander@155
   106
        assert(source->length() == dest->length());
dvander@155
   107
dvander@178
   108
        Local<Array> left(zone);
dvander@178
   109
        Local<Array> right(zone);
dvander@155
   110
        for (unsigned i = 0; i < source->length(); i++) {
dvander@179
   111
            left = Array::cast(dest->readObject(i));
dvander@179
   112
            right = Array::cast(source->readObject(i));
dvander@155
   113
            if (!CopyArray(zone, left, right))
dvander@155
   114
                return false;
dvander@155
   115
        }
dvander@187
   116
        return true;
dvander@187
   117
    }
dvander@187
   118
    
dvander@187
   119
    if (contained->isStruct()) {
dvander@187
   120
        assert(dest->type()->contained() == contained);
dvander@155
   121
        assert(source->length() == dest->length());
dvander@21
   122
dvander@178
   123
        Local<Struct> left(zone);
dvander@178
   124
        Local<Struct> right(zone);
dvander@155
   125
        for (unsigned i = 0; i < source->length(); i++) {
dvander@179
   126
            left = Struct::cast(dest->readObject(i));
dvander@179
   127
            right = Struct::cast(source->readObject(i));
dvander@155
   128
            if (!CopyStruct(zone, left, right))
dvander@155
   129
                return false;
dvander@155
   130
        }
dvander@187
   131
        return true;
dvander@187
   132
    }
dvander@155
   133
dvander@187
   134
    if (contained->isTraceable()) {
dvander@187
   135
        for (unsigned i = 0; i < source->length(); i++)
dvander@187
   136
            dest->writeObject(zone, i, source->readObject(i));
dvander@187
   137
        return true;
dvander@155
   138
    }
dvander@187
   139
dvander@187
   140
    assert(contained->pod() == dest->type()->contained()->pod());
dvander@187
   141
    assert(contained->pod() == PrimitiveType_Char
dvander@187
   142
           ? source->length() <= dest->length()
dvander@187
   143
           : source->length() == dest->length());
dvander@187
   144
dvander@188
   145
    assert(dest->length());
dvander@188
   146
    memcpy(dest->bytes(), source->bytes(), source->length() * Array::SizeForElement(dest->type()));
dvander@21
   147
    return true;
dvander@21
   148
}
dvander@21
   149
dvander@152
   150
static void
dvander@157
   151
GetElement(Array *array, int index, LocalSlot *vp)
dvander@157
   152
{
dvander@157
   153
    if (array->type()->contained()->isTraceable()) {
dvander@157
   154
        vp->obj = array->readObject(index);
dvander@157
   155
        return;
dvander@157
   156
    }
dvander@157
   157
dvander@157
   158
    switch (array->type()->contained()->pod()) {
dvander@157
   159
      case PrimitiveType_Float:
dvander@157
   160
        vp->f = array->readFloat(index);
dvander@157
   161
        break;
dvander@157
   162
dvander@157
   163
      case PrimitiveType_Char:
dvander@157
   164
        vp->i32 = array->readChar(index);
dvander@157
   165
        break;
dvander@157
   166
dvander@157
   167
      default:
dvander@157
   168
        assert(array->type()->contained()->pod() == PrimitiveType_Int32);
dvander@157
   169
        vp->i32 = array->readInt32(index);
dvander@157
   170
        break;
dvander@157
   171
    }
dvander@157
   172
}
dvander@157
   173
dvander@157
   174
static void
dvander@157
   175
SetElement(Zone *zone, Array *array, int index, const LocalSlot &v)
dvander@157
   176
{
dvander@157
   177
    if (array->type()->contained()->isTraceable()) {
dvander@157
   178
        array->writeObject(zone, index, v.obj);
dvander@157
   179
        return;
dvander@157
   180
    }
dvander@157
   181
dvander@157
   182
    switch (array->type()->contained()->pod()) {
dvander@157
   183
      case PrimitiveType_Float:
dvander@157
   184
        array->writeFloat(index, v.f);
dvander@157
   185
        break;
dvander@157
   186
dvander@157
   187
      case PrimitiveType_Char:
dvander@157
   188
        array->writeChar(index, v.i32);
dvander@157
   189
        break;
dvander@157
   190
dvander@157
   191
      default:
dvander@157
   192
        assert(array->type()->contained()->pod() == PrimitiveType_Int32);
dvander@157
   193
        array->writeInt32(index, v.i32);
dvander@157
   194
        break;
dvander@157
   195
    }
dvander@157
   196
}
dvander@157
   197
dvander@157
   198
static void
dvander@196
   199
FetchField(Struct *obj, Descriptor *desc, LocalSlot *vp)
dvander@152
   200
{
dvander@152
   201
    // :TODO: assert no GC.
dvander@152
   202
    if (desc->type()->isTraceable()) {
dvander@152
   203
        vp->obj = obj->get<Object *>(desc);
dvander@157
   204
        return;
dvander@157
   205
    }
dvander@152
   206
dvander@157
   207
    switch (desc->type()->pod()) {
dvander@157
   208
      case PrimitiveType_Float:
dvander@157
   209
        vp->f = obj->get<float>(desc);
dvander@157
   210
        break;
dvander@157
   211
dvander@157
   212
      default:
dvander@157
   213
        assert(desc->type()->pod() == PrimitiveType_Int32);
dvander@157
   214
        vp->i32 = obj->get<int>(desc);
dvander@157
   215
        break;
dvander@152
   216
    }
dvander@152
   217
}
dvander@152
   218
dvander@152
   219
static void
dvander@152
   220
GetField(Struct *obj, unsigned index, LocalSlot *vp)
dvander@152
   221
{
dvander@195
   222
    StructType *type = StructType::cast(obj->map()->type());
dvander@195
   223
    Descriptor *desc = Descriptor::cast(type->fields()->at(index));
dvander@196
   224
    FetchField(obj, desc, vp);
dvander@195
   225
}
dvander@195
   226
dvander@195
   227
static void
dvander@195
   228
GetGlobal(Zone *zone, Handle<Struct> obj, Handle<String> name, LocalSlot *vp)
dvander@195
   229
{
dvander@195
   230
    Local<StructType> type(zone, StructType::cast(obj->map()->type()));
dvander@195
   231
    Local<Descriptor> desc(zone, type->lookupField(name, NULL));
dvander@196
   232
    FetchField(obj, desc, vp);
dvander@152
   233
}
dvander@152
   234
dvander@152
   235
static void
dvander@196
   236
StoreField(Zone *zone, Struct *obj, Descriptor *desc, const LocalSlot &v)
dvander@152
   237
{
dvander@152
   238
    // :TODO: assert no GC.
dvander@152
   239
    if (desc->type()->isTraceable()) {
dvander@152
   240
        obj->set(zone, desc, v.obj);
dvander@157
   241
        return;
dvander@157
   242
    }
dvander@152
   243
dvander@157
   244
    switch (desc->type()->pod()) {
dvander@157
   245
      case PrimitiveType_Float:
dvander@157
   246
        obj->set<float>(desc, v.f);
dvander@157
   247
        break;
dvander@157
   248
dvander@157
   249
      default:
dvander@157
   250
        assert(desc->type()->pod() == PrimitiveType_Int32);
dvander@157
   251
        obj->set<int>(desc, v.i32);
dvander@157
   252
        break;
dvander@152
   253
    }
dvander@152
   254
}
dvander@152
   255
dvander@152
   256
static void
dvander@152
   257
SetField(Zone *zone, Struct *obj, unsigned index, const LocalSlot &v)
dvander@152
   258
{
dvander@195
   259
    StructType *type = StructType::cast(obj->map()->type());
dvander@195
   260
    Descriptor *desc = Descriptor::cast(type->fields()->at(index));
dvander@196
   261
    StoreField(zone, obj, desc, v);
dvander@195
   262
}
dvander@195
   263
dvander@195
   264
static void
dvander@195
   265
SetGlobal(Zone *zone, Handle<Struct> obj, Handle<String> name, LocalSlot &v)
dvander@195
   266
{
dvander@195
   267
    Local<StructType> type(zone, StructType::cast(obj->map()->type()));
dvander@195
   268
    Local<Descriptor> desc(zone, type->lookupField(name, NULL));
dvander@196
   269
    StoreField(zone, obj, desc, v);
dvander@152
   270
}
dvander@152
   271
dvander@152
   272
// Even though this function can fail, we immediately bail out, so it doesn't
dvander@152
   273
// matter if we've leaving things unrooted.
dvander@152
   274
static bool
dvander@178
   275
CopyStruct(Zone *zone, Handle<Struct> left, Handle<Struct> right)
dvander@152
   276
{
dvander@152
   277
    assert(left->map()->type() == right->map()->type());
dvander@152
   278
dvander@195
   279
    Local<StructType> type(zone, StructType::cast(left->map()->type()));
dvander@178
   280
    Local<Struct> leftStruct(zone);
dvander@178
   281
    Local<Struct> rightStruct(zone);
dvander@178
   282
    Local<Array> leftArray(zone);
dvander@178
   283
    Local<Array> rightArray(zone);
dvander@152
   284
    for (unsigned i = 0; i < type->fields()->length(); i++) {
dvander@152
   285
        Descriptor *desc = Descriptor::cast(type->fields()->at(i));
dvander@152
   286
dvander@152
   287
        LocalSlot rval;
dvander@196
   288
        FetchField(right, desc, &rval);
dvander@152
   289
dvander@152
   290
        // If the field is a struct, we need to deep-copy.
dvander@152
   291
        if (desc->type()->isStruct()) {
dvander@152
   292
            LocalSlot lval;
dvander@152
   293
dvander@196
   294
            FetchField(left, desc, &lval);
dvander@178
   295
            leftStruct = Struct::cast(lval.obj);
dvander@178
   296
            rightStruct = Struct::cast(rval.obj);
dvander@178
   297
            if (!CopyStruct(zone, leftStruct, rightStruct))
dvander@152
   298
                return false;
dvander@152
   299
        } else if (desc->type()->isArray()) {
dvander@152
   300
            LocalSlot lval;
dvander@152
   301
dvander@196
   302
            FetchField(left, desc, &lval);
dvander@178
   303
            leftArray = Array::cast(lval.obj);
dvander@178
   304
            rightArray = Array::cast(rval.obj);
dvander@178
   305
            if (!CopyArray(zone, leftArray, rightArray))
dvander@152
   306
                return false;
dvander@152
   307
        } else {
dvander@196
   308
            StoreField(zone, left, desc, rval);
dvander@152
   309
        }
dvander@152
   310
    }
dvander@152
   311
dvander@152
   312
    return true;
dvander@152
   313
}
dvander@152
   314
dvander@68
   315
static bool
dvander@68
   316
InvokeNative(Zone *zone, Handle<Native> native, void *identity, LocalSlot *args, unsigned argc,
dvander@68
   317
             int *result)
dvander@68
   318
{
dvander@68
   319
    NativeArgs guard;
dvander@68
   320
dvander@195
   321
    void *address = zone->nativeTable()->address(native->index());
dvander@195
   322
    if (!address) {
dvander@195
   323
        Local<String> name(zone, zone->nativeTable()->name(native->index()));
dvander@195
   324
        zone->reportError(Message_NativeNotBound, name->chars());
dvander@195
   325
        return false;
dvander@195
   326
    }
dvander@195
   327
dvander@68
   328
    if (!zone->stack().pushNativeFrame(native, guard, argc + 1))
dvander@68
   329
        return false;
dvander@68
   330
dvander@68
   331
    intptr_t *cells = guard.args();
dvander@68
   332
dvander@68
   333
    // params[0] == argc, in ISPE
dvander@68
   334
    cells[0] = argc;
dvander@68
   335
dvander@68
   336
    // Pass the formal arguments.
dvander@195
   337
    Local<FunctionType> type(zone, native->type());
dvander@68
   338
    Local<Type> param(zone);
dvander@68
   339
    for (unsigned i = 0; i < type->parameters()->length(); i++) {
dvander@68
   340
        param = type->parameterAt(i);
dvander@68
   341
        
dvander@68
   342
        // For floats, we rely on the aliasing of |i32| and |f|.
dvander@68
   343
        LocalSlot &arg = args[-int(i) - 1];
dvander@68
   344
        if (param->isInt32() || param->isFloat()) {
dvander@68
   345
            cells[i + 1] = arg.i32;
dvander@68
   346
        } else if (param->isReference()) {
dvander@68
   347
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
dvander@68
   348
        } else {
dvander@68
   349
            assert(param->isArray());
dvander@188
   350
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->bytes());
dvander@68
   351
        }
dvander@68
   352
    }
dvander@68
   353
dvander@68
   354
    // For variadic arguments, the compiler left either arrays or references.
dvander@68
   355
    for (unsigned i = type->parameters()->length(); i < argc; i++) {
dvander@68
   356
        LocalSlot &arg = args[-int(i) - 1];
dvander@68
   357
dvander@68
   358
        if (arg.obj->is(MapKind_Reference)) {
dvander@68
   359
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
dvander@68
   360
        } else {
dvander@68
   361
            assert(arg.obj->is(MapKind_Array));
dvander@188
   362
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->bytes());
dvander@68
   363
        }
dvander@68
   364
    }
dvander@68
   365
dvander@68
   366
    typedef intptr_t (*INVOKE)(void *, intptr_t *);
dvander@195
   367
    INVOKE invoke = (INVOKE)address;
dvander@68
   368
    *result = invoke(identity, cells);
dvander@68
   369
dvander@69
   370
    return !zone->hasPendingException();
dvander@68
   371
}
dvander@68
   372
dvander@0
   373
bool
dvander@59
   374
ke::Interpret(Zone *zone, Frame *entryFrame, LocalSlot *result)
dvander@0
   375
{
dvander@42
   376
    Top &top = *zone->stack().top();
dvander@69
   377
    if (!entryFrame)
dvander@69
   378
        entryFrame = top.fp;
dvander@69
   379
dvander@47
   380
    LocalSlot *locals = entryFrame->locals();
dvander@0
   381
dvander@0
   382
    for (;;) {
dvander@0
   383
        Opcode op = Opcode(*top.pc);
dvander@174
   384
dvander@174
   385
        if (OpcodeInfo[op].nuses > 0)
dvander@174
   386
            assert(top.sp - OpcodeInfo[op].nuses >= top.fp->stackBase());
dvander@174
   387
dvander@0
   388
        switch (op) {
dvander@0
   389
dvander@0
   390
case OP_NOP:
dvander@0
   391
    break;
dvander@0
   392
dvander@0
   393
case OP_INT:
dvander@0
   394
    PUSH_I32(top, READ_INT32(top.pc));
dvander@0
   395
    break;
dvander@0
   396
dvander@4
   397
case OP_FLOAT:
dvander@4
   398
    PUSH_F(top, READ_FLOAT(top.pc));
dvander@4
   399
    break;
dvander@4
   400
dvander@0
   401
case OP_RETURN:
dvander@72
   402
case OP_RETURNVOID:
dvander@72
   403
case OP_STOP:
dvander@0
   404
{
dvander@72
   405
    if (op == OP_RETURN)
dvander@72
   406
        *result = *--top.sp;
dvander@72
   407
dvander@69
   408
    if (top.fp == entryFrame)
dvander@69
   409
        goto done;
dvander@0
   410
dvander@72
   411
    // This must not GC.
dvander@65
   412
    zone->stack().popInlineFrame();
dvander@47
   413
    locals = top.fp->locals();
dvander@72
   414
dvander@72
   415
    if (op == OP_RETURN)
dvander@72
   416
        *top.sp++ = *result;
dvander@72
   417
dvander@0
   418
    top.pc += OpcodeInfo[*top.pc].length;
dvander@0
   419
    continue;
dvander@0
   420
}
dvander@0
   421
dvander@80
   422
case OP_POP:
dvander@80
   423
{
dvander@80
   424
    top.sp--;
dvander@80
   425
    break;
dvander@80
   426
}
dvander@80
   427
dvander@0
   428
case OP_JT:
dvander@0
   429
{
dvander@0
   430
    int value = POP_I32(top);
dvander@0
   431
    if (value) {
dvander@0
   432
        top.pc += READ_INT32(top.pc);
dvander@0
   433
        continue;
dvander@0
   434
    }
dvander@0
   435
    break;
dvander@0
   436
}
dvander@0
   437
dvander@0
   438
case OP_JF:
dvander@0
   439
{
dvander@0
   440
    int value = POP_I32(top);
dvander@0
   441
    if (!value) {
dvander@0
   442
        top.pc += READ_INT32(top.pc);
dvander@0
   443
        continue;
dvander@0
   444
    }
dvander@0
   445
    break;
dvander@0
   446
}
dvander@0
   447
dvander@0
   448
case OP_JUMP:
dvander@0
   449
    top.pc += READ_INT32(top.pc);
dvander@0
   450
    continue;
dvander@0
   451
dvander@0
   452
case OP_GETLOCAL:
dvander@0
   453
{
dvander@195
   454
    unsigned slot = READ_UINT32(top.pc);
dvander@195
   455
    assert(slot < top.fp->code()->nlocals());
dvander@0
   456
    *top.sp++ = locals[slot];
dvander@0
   457
    break;
dvander@0
   458
}
dvander@0
   459
dvander@0
   460
case OP_SETLOCAL:
dvander@0
   461
{
dvander@195
   462
    unsigned slot = READ_UINT32(top.pc);
dvander@195
   463
    assert(slot < top.fp->code()->nlocals());
dvander@0
   464
    locals[slot] = top.sp[-1];
dvander@0
   465
    break;
dvander@0
   466
}
dvander@0
   467
dvander@0
   468
case OP_ADD:
dvander@0
   469
{
dvander@77
   470
    top.sp[-2].i32 = top.sp[-2].i32 + top.sp[-1].i32;
dvander@77
   471
    top.sp--;
dvander@0
   472
    break;
dvander@0
   473
}
dvander@0
   474
dvander@0
   475
case OP_SUB:
dvander@0
   476
{
dvander@77
   477
    top.sp[-2].i32 = top.sp[-2].i32 - top.sp[-1].i32;
dvander@77
   478
    top.sp--;
dvander@0
   479
    break;
dvander@0
   480
}
dvander@0
   481
dvander@0
   482
case OP_MUL:
dvander@0
   483
{
dvander@77
   484
    top.sp[-2].i32 = top.sp[-2].i32 * top.sp[-1].i32;
dvander@77
   485
    top.sp--;
dvander@0
   486
    break;
dvander@0
   487
}
dvander@0
   488
dvander@0
   489
case OP_DIV:
dvander@0
   490
{
dvander@77
   491
    if (top.sp[-1].i32 == 0) {
dvander@69
   492
        zone->reportError(Message_IntegerDivideByZero);
dvander@69
   493
        goto error;
dvander@69
   494
    }
dvander@77
   495
    top.sp[-2].i32 = top.sp[-2].i32 / top.sp[-1].i32;
dvander@77
   496
    top.sp--;
dvander@0
   497
    break;
dvander@0
   498
}
dvander@0
   499
dvander@82
   500
case OP_MOD:
dvander@82
   501
{
dvander@82
   502
    if (top.sp[-1].i32 == 0) {
dvander@82
   503
        zone->reportError(Message_IntegerDivideByZero);
dvander@82
   504
        goto error;
dvander@82
   505
    }
dvander@82
   506
    top.sp[-2].i32 = top.sp[-2].i32 % top.sp[-1].i32;
dvander@82
   507
    top.sp--;
dvander@82
   508
    break;
dvander@82
   509
}
dvander@82
   510
dvander@74
   511
case OP_LT:
dvander@74
   512
{
dvander@74
   513
    top.sp[-2].i32 = top.sp[-2].i32 < top.sp[-1].i32;
dvander@74
   514
    top.sp--;
dvander@74
   515
    break;
dvander@74
   516
}
dvander@74
   517
dvander@74
   518
case OP_LE:
dvander@74
   519
{
dvander@74
   520
    top.sp[-2].i32 = top.sp[-2].i32 <= top.sp[-1].i32;
dvander@74
   521
    top.sp--;
dvander@74
   522
    break;
dvander@74
   523
}
dvander@74
   524
dvander@74
   525
case OP_GT:
dvander@74
   526
{
dvander@74
   527
    top.sp[-2].i32 = top.sp[-2].i32 > top.sp[-1].i32;
dvander@74
   528
    top.sp--;
dvander@74
   529
    break;
dvander@74
   530
}
dvander@74
   531
dvander@74
   532
case OP_GE:
dvander@74
   533
{
dvander@74
   534
    top.sp[-2].i32 = top.sp[-2].i32 >= top.sp[-1].i32;
dvander@74
   535
    top.sp--;
dvander@74
   536
    break;
dvander@74
   537
}
dvander@74
   538
dvander@74
   539
case OP_EQ:
dvander@74
   540
{
dvander@74
   541
    top.sp[-2].i32 = (top.sp[-2].i32 == top.sp[-1].i32);
dvander@74
   542
    top.sp--;
dvander@74
   543
    break;
dvander@74
   544
}
dvander@74
   545
dvander@74
   546
case OP_NE:
dvander@74
   547
{
dvander@74
   548
    top.sp[-2].i32 = (top.sp[-2].i32 != top.sp[-1].i32);
dvander@74
   549
    top.sp--;
dvander@74
   550
    break;
dvander@74
   551
}
dvander@74
   552
dvander@4
   553
case OP_ADD_F:
dvander@4
   554
{
dvander@77
   555
    top.sp[-2].f = top.sp[-2].f + top.sp[-1].f;
dvander@77
   556
    top.sp--;
dvander@4
   557
    break;
dvander@4
   558
}
dvander@4
   559
dvander@4
   560
case OP_SUB_F:
dvander@4
   561
{
dvander@77
   562
    top.sp[-2].f = top.sp[-2].f - top.sp[-1].f;
dvander@77
   563
    top.sp--;
dvander@4
   564
    break;
dvander@4
   565
}
dvander@4
   566
dvander@4
   567
case OP_MUL_F:
dvander@4
   568
{
dvander@77
   569
    top.sp[-2].f = top.sp[-2].f * top.sp[-1].f;
dvander@77
   570
    top.sp--;
dvander@4
   571
    break;
dvander@4
   572
}
dvander@4
   573
dvander@4
   574
case OP_DIV_F:
dvander@4
   575
{
dvander@77
   576
    top.sp[-2].f = top.sp[-2].f / top.sp[-1].f;
dvander@77
   577
    top.sp--;
dvander@4
   578
    break;
dvander@4
   579
}
dvander@4
   580
dvander@74
   581
case OP_LT_F:
dvander@74
   582
{
dvander@74
   583
    top.sp[-2].f = top.sp[-2].f < top.sp[-1].f;
dvander@74
   584
    top.sp--;
dvander@74
   585
    break;
dvander@74
   586
}
dvander@74
   587
dvander@74
   588
case OP_LE_F:
dvander@74
   589
{
dvander@74
   590
    top.sp[-2].f = top.sp[-2].f <= top.sp[-1].f;
dvander@74
   591
    top.sp--;
dvander@74
   592
    break;
dvander@74
   593
}
dvander@74
   594
dvander@74
   595
case OP_GT_F:
dvander@74
   596
{
dvander@74
   597
    top.sp[-2].f = top.sp[-2].f > top.sp[-1].f;
dvander@74
   598
    top.sp--;
dvander@74
   599
    break;
dvander@74
   600
}
dvander@74
   601
dvander@74
   602
case OP_GE_F:
dvander@74
   603
{
dvander@74
   604
    top.sp[-2].f = top.sp[-2].f >= top.sp[-1].f;
dvander@74
   605
    top.sp--;
dvander@74
   606
    break;
dvander@74
   607
}
dvander@74
   608
dvander@74
   609
case OP_EQ_F:
dvander@74
   610
{
dvander@74
   611
    top.sp[-2].i32 = (top.sp[-2].f == top.sp[-1].f);
dvander@74
   612
    top.sp--;
dvander@74
   613
    break;
dvander@74
   614
}
dvander@74
   615
dvander@74
   616
case OP_NE_F:
dvander@74
   617
{
dvander@74
   618
    top.sp[-2].i32 = (top.sp[-2].f != top.sp[-1].f);
dvander@74
   619
    top.sp--;
dvander@74
   620
    break;
dvander@74
   621
}
dvander@74
   622
dvander@8
   623
case OP_SHL:
dvander@8
   624
{
dvander@77
   625
    top.sp[-2].i32 = top.sp[-2].i32 << top.sp[-1].i32;
dvander@77
   626
    top.sp--;
dvander@8
   627
    break;
dvander@8
   628
}
dvander@8
   629
dvander@8
   630
case OP_SHR:
dvander@8
   631
{
dvander@77
   632
    top.sp[-2].i32 = top.sp[-2].i32 >> top.sp[-1].i32;
dvander@77
   633
    top.sp--;
dvander@8
   634
    break;
dvander@8
   635
}
dvander@8
   636
dvander@8
   637
case OP_USHR:
dvander@8
   638
{
dvander@77
   639
    top.sp[-2].i32 = unsigned(top.sp[-2].i32) << unsigned(top.sp[-1].i32);
dvander@77
   640
    top.sp--;
dvander@8
   641
    break;
dvander@8
   642
}
dvander@8
   643
dvander@8
   644
case OP_BITAND:
dvander@8
   645
{
dvander@77
   646
    top.sp[-2].i32 = top.sp[-2].i32 & top.sp[-1].i32;
dvander@77
   647
    top.sp--;
dvander@8
   648
    break;
dvander@8
   649
}
dvander@8
   650
dvander@8
   651
case OP_BITOR:
dvander@8
   652
{
dvander@77
   653
    top.sp[-2].i32 = top.sp[-2].i32 | top.sp[-1].i32;
dvander@77
   654
    top.sp--;
dvander@8
   655
    break;
dvander@8
   656
}
dvander@8
   657
dvander@8
   658
case OP_BITXOR:
dvander@8
   659
{
dvander@77
   660
    top.sp[-2].i32 = top.sp[-2].i32 ^ top.sp[-1].i32;
dvander@77
   661
    top.sp--;
dvander@8
   662
    break;
dvander@8
   663
}
dvander@8
   664
dvander@78
   665
case OP_BITNOT:
dvander@78
   666
{
dvander@78
   667
    top.sp[-1].i32 = ~top.sp[-1].i32;
dvander@78
   668
    break;
dvander@78
   669
}
dvander@78
   670
dvander@79
   671
case OP_NOT:
dvander@79
   672
{
dvander@79
   673
    top.sp[-1].i32 = top.sp[-1].i32 ? 0 : 1;
dvander@79
   674
    break;
dvander@79
   675
}
dvander@79
   676
dvander@79
   677
case OP_NOT_F:
dvander@79
   678
{
dvander@79
   679
    top.sp[-1].i32 = top.sp[-1].f ? 0 : 1;
dvander@79
   680
    break;
dvander@79
   681
}
dvander@79
   682
dvander@80
   683
case OP_NEG:
dvander@79
   684
{
dvander@80
   685
    top.sp[-1].i32 = -top.sp[-1].i32;
dvander@80
   686
    break;
dvander@80
   687
}
dvander@80
   688
dvander@80
   689
case OP_NEG_F:
dvander@80
   690
{
dvander@80
   691
    top.sp[-1].f = -top.sp[-1].f;
dvander@0
   692
    break;
dvander@79
   693
}
dvander@0
   694
dvander@73
   695
case OP_CALL:
dvander@0
   696
{
dvander@195
   697
    Local<Function> newFun(zone, Function::cast(top.sp[-1].obj));
dvander@73
   698
    top.sp--;
dvander@73
   699
dvander@69
   700
    if (!zone->stack().pushInlineFrame(newFun))
dvander@69
   701
        goto error;
dvander@0
   702
dvander@47
   703
    locals = top.fp->locals();
dvander@0
   704
    continue;
dvander@0
   705
}
dvander@0
   706
dvander@0
   707
case OP_GETARG:
dvander@0
   708
{
dvander@0
   709
    unsigned slot = READ_UINT32(top.pc);
dvander@47
   710
    *top.sp++ = top.fp->arg(slot);
dvander@0
   711
    break;
dvander@0
   712
}
dvander@0
   713
dvander@0
   714
case OP_SETARG:
dvander@0
   715
{
dvander@0
   716
    unsigned slot = READ_UINT32(top.pc);
dvander@174
   717
    top.fp->arg(slot) = top.sp[-1];
dvander@0
   718
    break;
dvander@0
   719
}
dvander@0
   720
dvander@158
   721
case OP_GETELEM:
dvander@0
   722
{
dvander@158
   723
    Array *array = Array::cast(top.sp[-2].obj);
dvander@0
   724
    int index = top.sp[-1].i32;
dvander@158
   725
dvander@155
   726
    if (index < 0 || unsigned(index) >= array->length()) {
dvander@155
   727
        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
dvander@69
   728
        goto error;
dvander@69
   729
    }
dvander@0
   730
dvander@157
   731
    GetElement(array, index, &top.sp[-2]);
dvander@21
   732
    top.sp--;
dvander@21
   733
    break;
dvander@21
   734
}
dvander@21
   735
dvander@157
   736
case OP_SETELEM:
dvander@0
   737
{
dvander@157
   738
    Array *array = Array::cast(top.sp[-3].obj);
dvander@0
   739
    int index = top.sp[-2].i32;
dvander@158
   740
dvander@158
   741
    if (index < 0 || unsigned(index) >= array->length()) {
dvander@158
   742
        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
dvander@158
   743
        goto error;
dvander@158
   744
    }
dvander@158
   745
dvander@157
   746
    SetElement(zone, array, index, top.sp[-1]);
dvander@7
   747
    top.sp[-3] = top.sp[-1];
dvander@7
   748
    top.sp -= 2;
dvander@7
   749
    break;
dvander@7
   750
}
dvander@7
   751
dvander@4
   752
case OP_CVT_I2F:
dvander@4
   753
{
dvander@4
   754
    int ival = POP_I32(top);
dvander@4
   755
    float fval = (float)ival;
dvander@4
   756
    PUSH_F(top, fval);
dvander@4
   757
    break;
dvander@4
   758
}
dvander@4
   759
dvander@185
   760
case OP_NEWFIXED:
dvander@12
   761
{
dvander@85
   762
    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
dvander@85
   763
    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
dvander@187
   764
    Array *array = Array::NewFixed(zone, map, tenure);
dvander@185
   765
    if (!array)
dvander@185
   766
        goto error;
dvander@185
   767
    top.sp->obj = array;
dvander@185
   768
    top.sp++;
dvander@185
   769
    break;
dvander@185
   770
}
dvander@185
   771
dvander@185
   772
case OP_NEWEMPTY:
dvander@185
   773
{
dvander@185
   774
    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
dvander@185
   775
    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
dvander@187
   776
    Array *array = Array::NewEmpty(zone, map, tenure);
dvander@187
   777
    if (!array)
dvander@187
   778
        goto error;
dvander@187
   779
    top.sp->obj = array;
dvander@187
   780
    top.sp++;
dvander@187
   781
    break;
dvander@187
   782
}
dvander@187
   783
dvander@187
   784
case OP_NEWSIZED:
dvander@187
   785
{
dvander@187
   786
    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
dvander@187
   787
    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
dvander@187
   788
    assert(map->type()->levels() < MAX_ARRAY_DEPTH);
dvander@187
   789
dvander@187
   790
    int dims[MAX_ARRAY_DEPTH];
dvander@187
   791
    for (unsigned i = map->type()->levels() - 1; i < map->type()->levels(); i--)
dvander@187
   792
        dims[i] = POP_I32(top);
dvander@187
   793
dvander@187
   794
    Array *array = Array::NewSized(zone, map, dims, tenure);
dvander@69
   795
    if (!array)
dvander@69
   796
        goto error;
dvander@12
   797
    top.sp->obj = array;
dvander@12
   798
    top.sp++;
dvander@12
   799
    break;
dvander@12
   800
}
dvander@12
   801
dvander@147
   802
case OP_NEWSTRUCT:
dvander@147
   803
{
dvander@147
   804
    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
dvander@147
   805
    Local<StructMap> map(zone, StructMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
dvander@147
   806
    top.sp->obj = Struct::New(zone, map, tenure);
dvander@147
   807
    if (!top.sp->obj)
dvander@147
   808
        goto error;
dvander@147
   809
    top.sp++;
dvander@147
   810
    break;
dvander@147
   811
}
dvander@147
   812
dvander@12
   813
case OP_SAVELIFO:
dvander@10
   814
{
dvander@10
   815
    unsigned slot = READ_UINT32(top.pc);
dvander@42
   816
    locals[slot].address = zone->heap().lifoPosition();
dvander@12
   817
    break;
dvander@12
   818
}
dvander@12
   819
dvander@12
   820
case OP_UNWINDLIFO:
dvander@12
   821
{
dvander@12
   822
    unsigned slot = READ_UINT32(top.pc);
dvander@42
   823
    zone->heap().unwindLifo(locals[slot].address);
dvander@10
   824
    break;
dvander@10
   825
}
dvander@10
   826
dvander@14
   827
case OP_VARREF_LIFO:
dvander@14
   828
{
dvander@14
   829
    unsigned slot = READ_UINT32(top.pc);
dvander@69
   830
    if (!PushNewRef(zone, top, &locals[slot], Heap::Tenure_Stack))
dvander@69
   831
        goto error;
dvander@14
   832
    break;
dvander@14
   833
}
dvander@14
   834
dvander@14
   835
case OP_ARGREF_LIFO:
dvander@14
   836
{
dvander@14
   837
    unsigned slot = READ_UINT32(top.pc);
dvander@69
   838
    if (!PushNewRef(zone, top, &top.fp->arg(slot), Heap::Tenure_Stack))
dvander@69
   839
        goto error;
dvander@14
   840
    break;
dvander@14
   841
}
dvander@14
   842
dvander@16
   843
case OP_SLOTREF_LIFO:
dvander@16
   844
{
dvander@42
   845
    Reference *ref = Reference::NewStack(zone, top.sp[-1], Heap::Tenure_Stack);
dvander@69
   846
    if (!ref)
dvander@69
   847
        goto error;
dvander@16
   848
    top.sp[-1].ref = ref;
dvander@16
   849
    break;
dvander@16
   850
}
dvander@16
   851
dvander@14
   852
case OP_GETREF_I:
dvander@14
   853
{
dvander@14
   854
    top.sp[-1].i32 = top.sp[-1].ref->getInt();
dvander@14
   855
    break;
dvander@14
   856
}
dvander@14
   857
dvander@14
   858
case OP_SETREF_I:
dvander@14
   859
{
dvander@14
   860
    top.sp[-2].ref->setInt(top.sp[-1].i32);
dvander@14
   861
    top.sp[-2].i32 = top.sp[-1].i32;
dvander@23
   862
    top.sp--;
dvander@14
   863
    break;
dvander@14
   864
}
dvander@14
   865
dvander@14
   866
case OP_GETREF_F:
dvander@14
   867
{
dvander@14
   868
    top.sp[-1].f = top.sp[-1].ref->getFloat();
dvander@14
   869
    break;
dvander@14
   870
}
dvander@14
   871
dvander@14
   872
case OP_SETREF_F:
dvander@14
   873
{
dvander@14
   874
    top.sp[-2].ref->setFloat(top.sp[-1].f);
dvander@14
   875
    top.sp[-2].f = top.sp[-1].f;
dvander@14
   876
    break;
dvander@14
   877
}
dvander@14
   878
dvander@21
   879
case OP_OBJECT:
dvander@21
   880
{
dvander@47
   881
    top.sp->obj = top.fp->code()->object(READ_UINT32(top.pc));
dvander@21
   882
    top.sp++;
dvander@21
   883
    break;
dvander@21
   884
}
dvander@21
   885
dvander@152
   886
case OP_COPYARRAY:
dvander@21
   887
{
dvander@21
   888
    // Note for this assignment opcode, we return the left-hand side, not the
dvander@21
   889
    // right, since in this case the result of the expression could be different.
dvander@178
   890
    Local<Array> left(zone, Array::cast(top.sp[-2].array));
dvander@178
   891
    Local<Array> right(zone, Array::cast(top.sp[-1].array));
dvander@178
   892
    if (!CopyArray(zone, left, right))
dvander@69
   893
        goto error;
dvander@21
   894
    top.sp--;
dvander@21
   895
    break;
dvander@21
   896
}
dvander@21
   897
dvander@22
   898
case OP_DUP:
dvander@22
   899
{
dvander@23
   900
    top.sp++;
dvander@23
   901
    top.sp[-1] = top.sp[-2];
dvander@22
   902
    break;
dvander@22
   903
}
dvander@22
   904
dvander@22
   905
case OP_DUP2:
dvander@22
   906
{
dvander@23
   907
    top.sp += 2;
dvander@23
   908
    top.sp[-2] = top.sp[-4];
dvander@23
   909
    top.sp[-1] = top.sp[-3];
dvander@23
   910
    break;
dvander@23
   911
}
dvander@23
   912
dvander@23
   913
case OP_SWAP:
dvander@23
   914
{
dvander@23
   915
    LocalSlot slot = top.sp[-2];
dvander@23
   916
    top.sp[-2] = top.sp[-1];
dvander@23
   917
    top.sp[-1] = slot;
dvander@23
   918
    break;
dvander@23
   919
}
dvander@23
   920
dvander@23
   921
case OP_ROLL3:
dvander@23
   922
{
dvander@23
   923
    LocalSlot slot = top.sp[-3];
dvander@23
   924
    top.sp[-3] = top.sp[-2];
dvander@23
   925
    top.sp[-2] = top.sp[-1];
dvander@23
   926
    top.sp[-1] = slot;
dvander@23
   927
    break;
dvander@23
   928
}
dvander@23
   929
dvander@23
   930
case OP_PICK2:
dvander@23
   931
{
dvander@23
   932
    top.sp++;
dvander@23
   933
    top.sp[-1] = top.sp[-3];
dvander@23
   934
    break;
dvander@23
   935
}
dvander@23
   936
dvander@23
   937
case OP_PICK3:
dvander@23
   938
{
dvander@23
   939
    top.sp++;
dvander@23
   940
    top.sp[-1] = top.sp[-4];
dvander@22
   941
    break;
dvander@22
   942
}
dvander@22
   943
dvander@68
   944
case OP_CALLNATIVE:
dvander@68
   945
{
dvander@195
   946
    unsigned argc = READ_UINT32(top.pc);
dvander@68
   947
dvander@195
   948
    Local<Native> native(zone, Native::cast(top.sp[-1].obj));
dvander@195
   949
    top.sp--;
dvander@68
   950
dvander@68
   951
    int result;
dvander@68
   952
    void *nativeIdentity = top.fp->code()->module()->nativeIdentity();
dvander@69
   953
    if (!InvokeNative(zone, native, nativeIdentity, top.sp, argc, &result))
dvander@69
   954
        goto error;
dvander@68
   955
dvander@68
   956
    top.sp -= argc;
dvander@68
   957
    PUSH_I32(top, result);
dvander@68
   958
    break;
dvander@68
   959
}
dvander@68
   960
dvander@142
   961
case OP_BITS_I2F:
dvander@142
   962
case OP_BITS_F2I:
dvander@142
   963
{
dvander@142
   964
    // Because the stack is a union, these are actually no-ops in the
dvander@142
   965
    // interpreter.
dvander@142
   966
    break;
dvander@142
   967
}
dvander@142
   968
dvander@143
   969
case OP_TRUE:
dvander@143
   970
{
dvander@143
   971
    top.sp++;
dvander@143
   972
    top.sp[-1].i32 = 1;
dvander@143
   973
    break;
dvander@143
   974
}
dvander@143
   975
dvander@143
   976
case OP_FALSE:
dvander@143
   977
{
dvander@143
   978
    top.sp++;
dvander@143
   979
    top.sp[-1].i32 = 0;
dvander@143
   980
    break;
dvander@143
   981
}
dvander@143
   982
dvander@152
   983
case OP_GETFIELD:
dvander@152
   984
{
dvander@152
   985
    Struct *obj = Struct::cast(top.sp[-1].obj);
dvander@152
   986
    GetField(obj, READ_UINT32(top.pc), &top.sp[-1]);
dvander@152
   987
    break;
dvander@152
   988
}
dvander@152
   989
dvander@152
   990
case OP_SETFIELD:
dvander@152
   991
{
dvander@152
   992
    Struct *obj = Struct::cast(top.sp[-2].obj);
dvander@152
   993
    SetField(zone, obj, READ_UINT32(top.pc), top.sp[-1]);
dvander@152
   994
    top.sp[-2] = top.sp[-1];
dvander@152
   995
    top.sp--;
dvander@152
   996
    break;
dvander@152
   997
}
dvander@152
   998
dvander@152
   999
case OP_COPYSTRUCT:
dvander@152
  1000
{
dvander@178
  1001
    Local<Struct> left(zone, Struct::cast(top.sp[-2].obj));
dvander@178
  1002
    Local<Struct> right(zone, Struct::cast(top.sp[-1].obj));
dvander@178
  1003
    if (!CopyStruct(zone, left, right))
dvander@152
  1004
        goto error;
dvander@152
  1005
    top.sp[-2].obj = top.sp[-1].obj;
dvander@152
  1006
    top.sp--;
dvander@152
  1007
    break;
dvander@152
  1008
}
dvander@152
  1009
dvander@172
  1010
case OP_TABLESWITCH:
dvander@172
  1011
{
dvander@172
  1012
    int value = top.sp[-1].i32;
dvander@172
  1013
    int low = READ_TABLESWITCH_LOW(top.pc);
dvander@172
  1014
    int high = READ_TABLESWITCH_HIGH(top.pc);
dvander@172
  1015
dvander@172
  1016
    top.sp--;
dvander@172
  1017
dvander@172
  1018
    unsigned index = unsigned(value - low);
dvander@172
  1019
    unsigned tablesize = TableSwitchEntries(low, high);
dvander@172
  1020
    if (index < tablesize) {
dvander@172
  1021
        top.pc += OP_TABLESWITCH_LENGTH + OP_JUMP_LENGTH;
dvander@172
  1022
        top.pc += index * OP_JUMP_LENGTH;
dvander@172
  1023
        continue;
dvander@172
  1024
    }
dvander@172
  1025
    break;
dvander@172
  1026
}
dvander@172
  1027
dvander@194
  1028
case OP_SIZEOF:
dvander@194
  1029
{
dvander@194
  1030
    Array *array = Array::cast(top.sp[-1].obj);
dvander@194
  1031
    top.sp[-1].i32 = array->length();
dvander@194
  1032
    break;
dvander@194
  1033
}
dvander@194
  1034
dvander@195
  1035
case OP_PUBLIC:
dvander@195
  1036
{
dvander@195
  1037
    Local<Function> fun(zone, Function::cast(top.sp[-1].obj));
dvander@195
  1038
    zone->registerPublic(fun);
dvander@195
  1039
    top.sp--;
dvander@195
  1040
    break;
dvander@195
  1041
}
dvander@195
  1042
dvander@195
  1043
case OP_SETGLOBAL:
dvander@195
  1044
{
dvander@195
  1045
    Local<Code> code(zone, top.fp->code());
dvander@195
  1046
    Local<Struct> obj(zone, code->module()->globals());
dvander@195
  1047
    Local<String> name(zone, String::cast(code->strings()->at(READ_UINT32(top.pc))));
dvander@195
  1048
    SetGlobal(zone, obj, name, top.sp[-1]);
dvander@195
  1049
    break;
dvander@195
  1050
}
dvander@195
  1051
dvander@195
  1052
case OP_GETGLOBAL:
dvander@195
  1053
{
dvander@195
  1054
    Local<Code> code(zone, top.fp->code());
dvander@195
  1055
    Local<Struct> obj(zone, code->module()->globals());
dvander@195
  1056
    Local<String> name(zone, String::cast(code->strings()->at(READ_UINT32(top.pc))));
dvander@195
  1057
    GetGlobal(zone, obj, name, top.sp);
dvander@195
  1058
    top.sp++;
dvander@195
  1059
    break;
dvander@195
  1060
}
dvander@195
  1061
dvander@0
  1062
default:
dvander@0
  1063
    assert(false);
dvander@0
  1064
    return false;
dvander@0
  1065
dvander@0
  1066
        }
dvander@0
  1067
dvander@0
  1068
        top.pc += OpcodeInfo[op].length;
dvander@174
  1069
        assert(top.sp >= top.fp->stackBase());
dvander@0
  1070
    }
dvander@0
  1071
dvander@69
  1072
done:
dvander@0
  1073
    return true;
dvander@69
  1074
dvander@69
  1075
error:
dvander@69
  1076
    // Unwind frames until we can continue.
dvander@69
  1077
    while (top.fp != entryFrame)
dvander@69
  1078
        zone->stack().popInlineFrame();
dvander@69
  1079
    return false;
dvander@0
  1080
}