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