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