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