jitcraft/Interpreter.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jul 11 01:12:54 2012 -0700 (2012-07-11)
changeset 69 dfce0539a77d
parent 68 b40b0e18a918
child 72 40746ab0a30b
permissions -rw-r--r--
Added error reporting API and fixed all known error paths.
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
 */
dvander@0
    19
#include "Interpreter.h"
dvander@0
    20
#include "Modules.h"
dvander@0
    21
#include "Zone.h"
dvander@0
    22
#include "Types.h"
dvander@12
    23
#include "Array.h"
dvander@14
    24
#include "Reference.h"
dvander@69
    25
#include "Strings.h"
dvander@28
    26
#include "Heap-inl.h"
dvander@0
    27
dvander@59
    28
using namespace ke;
dvander@0
    29
dvander@0
    30
#define PUSH_I32(top, value)    \
dvander@0
    31
    do {                        \
dvander@0
    32
        top.sp->i32 = value;    \
dvander@0
    33
        top.sp++;               \
dvander@0
    34
   } while (0)
dvander@0
    35
dvander@4
    36
#define PUSH_F(top, value)      \
dvander@4
    37
    do {                        \
dvander@4
    38
        top.sp->f = value;      \
dvander@4
    39
        top.sp++;               \
dvander@4
    40
   } while (0)
dvander@4
    41
dvander@0
    42
static inline int
dvander@0
    43
POP_I32(Top &top)
dvander@0
    44
{
dvander@0
    45
    int value = top.sp[-1].i32;
dvander@0
    46
    top.sp--;
dvander@0
    47
    return value;
dvander@0
    48
}
dvander@0
    49
dvander@4
    50
static inline float
dvander@4
    51
POP_F(Top &top)
dvander@4
    52
{
dvander@4
    53
    float value = top.sp[-1].f;
dvander@4
    54
    top.sp--;
dvander@4
    55
    return value;
dvander@4
    56
}
dvander@4
    57
dvander@0
    58
static inline bool
dvander@14
    59
PushNewRef(Zone *zone, Top &top, void *location, Heap::Tenure tenure)
dvander@14
    60
{
dvander@14
    61
    Reference *ref = Reference::NewStack(zone, location, tenure);
dvander@14
    62
    if (!ref)
dvander@14
    63
        return false;
dvander@14
    64
    top.sp->ref = ref;
dvander@14
    65
    top.sp++;
dvander@14
    66
    return true;
dvander@14
    67
}
dvander@14
    68
dvander@12
    69
// Generate an array with completely static sizes.
dvander@12
    70
static Array *
dvander@27
    71
GenerateArray(Zone *zone, Handle<ArrayMap> map)
dvander@0
    72
{
dvander@12
    73
    assert(map->type()->elements() != -1);
dvander@0
    74
dvander@43
    75
    Local<Array> array(zone, Array::New(zone, map, map->type()->elements(), Heap::Tenure_Stack));
dvander@12
    76
    if (!array)
dvander@0
    77
        return NULL;
dvander@0
    78
dvander@12
    79
    if (map->type()->levels() == 1)
dvander@12
    80
        return array;
dvander@0
    81
dvander@27
    82
    Local<ArrayMap> contained(zone, map->contained());
dvander@43
    83
    Local<Array> sub(zone);
dvander@12
    84
    for (unsigned i = 0; i < unsigned(map->type()->elements()); i++) {
dvander@43
    85
        sub = GenerateArray(zone, contained);
dvander@12
    86
        if (!sub)
dvander@0
    87
            return NULL;
dvander@12
    88
        array->writeObject(zone, i, sub);
dvander@0
    89
    }
dvander@0
    90
dvander@12
    91
    return array;
dvander@0
    92
}
dvander@0
    93
dvander@21
    94
static bool
dvander@21
    95
CopyArray(Zone *zone, Array *source, Array *dest)
dvander@21
    96
{
dvander@21
    97
    assert(source->type()->levels() == 1);
dvander@21
    98
    assert(dest->type()->levels() == 1);
dvander@21
    99
    assert(source->type()->contained()->primitive() ==
dvander@21
   100
           dest->type()->contained()->primitive());
dvander@21
   101
    assert(source->nelements() >= dest->nelements());
dvander@21
   102
    assert(dest->elementSize() == source->elementSize());
dvander@21
   103
dvander@21
   104
    memcpy(source->vec(), dest->vec(), dest->nelements() * dest->elementSize());
dvander@21
   105
    return true;
dvander@21
   106
}
dvander@21
   107
dvander@68
   108
static bool
dvander@68
   109
InvokeNative(Zone *zone, Handle<Native> native, void *identity, LocalSlot *args, unsigned argc,
dvander@68
   110
             int *result)
dvander@68
   111
{
dvander@68
   112
    NativeArgs guard;
dvander@68
   113
dvander@68
   114
    if (!zone->stack().pushNativeFrame(native, guard, argc + 1))
dvander@68
   115
        return false;
dvander@68
   116
dvander@68
   117
    intptr_t *cells = guard.args();
dvander@68
   118
dvander@68
   119
    // params[0] == argc, in ISPE
dvander@68
   120
    cells[0] = argc;
dvander@68
   121
dvander@68
   122
    // Pass the formal arguments.
dvander@68
   123
    Local<Type> type(zone, native->type());
dvander@68
   124
    Local<Type> param(zone);
dvander@68
   125
    for (unsigned i = 0; i < type->parameters()->length(); i++) {
dvander@68
   126
        param = type->parameterAt(i);
dvander@68
   127
        
dvander@68
   128
        // For floats, we rely on the aliasing of |i32| and |f|.
dvander@68
   129
        LocalSlot &arg = args[-int(i) - 1];
dvander@68
   130
        if (param->isInt32() || param->isFloat()) {
dvander@68
   131
            cells[i + 1] = arg.i32;
dvander@68
   132
        } else if (param->isReference()) {
dvander@68
   133
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
dvander@68
   134
        } else {
dvander@68
   135
            assert(param->isArray());
dvander@68
   136
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->vec());
dvander@68
   137
        }
dvander@68
   138
    }
dvander@68
   139
dvander@68
   140
    // For variadic arguments, the compiler left either arrays or references.
dvander@68
   141
    for (unsigned i = type->parameters()->length(); i < argc; i++) {
dvander@68
   142
        LocalSlot &arg = args[-int(i) - 1];
dvander@68
   143
dvander@68
   144
        if (arg.obj->is(MapKind_Reference)) {
dvander@68
   145
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
dvander@68
   146
        } else {
dvander@68
   147
            assert(arg.obj->is(MapKind_Array));
dvander@68
   148
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->vec());
dvander@68
   149
        }
dvander@68
   150
    }
dvander@68
   151
dvander@68
   152
    typedef intptr_t (*INVOKE)(void *, intptr_t *);
dvander@68
   153
    INVOKE invoke = (INVOKE)native->function();
dvander@68
   154
    *result = invoke(identity, cells);
dvander@68
   155
dvander@69
   156
    return !zone->hasPendingException();
dvander@68
   157
}
dvander@68
   158
dvander@0
   159
bool
dvander@59
   160
ke::Interpret(Zone *zone, Frame *entryFrame, LocalSlot *result)
dvander@0
   161
{
dvander@42
   162
    Top &top = *zone->stack().top();
dvander@69
   163
    if (!entryFrame)
dvander@69
   164
        entryFrame = top.fp;
dvander@69
   165
dvander@47
   166
    LocalSlot *locals = entryFrame->locals();
dvander@0
   167
dvander@0
   168
    for (;;) {
dvander@0
   169
        Opcode op = Opcode(*top.pc);
dvander@0
   170
        switch (op) {
dvander@0
   171
dvander@0
   172
case OP_NOP:
dvander@0
   173
    break;
dvander@0
   174
dvander@0
   175
case OP_INT:
dvander@0
   176
    PUSH_I32(top, READ_INT32(top.pc));
dvander@0
   177
    break;
dvander@0
   178
dvander@4
   179
case OP_FLOAT:
dvander@4
   180
    PUSH_F(top, READ_FLOAT(top.pc));
dvander@4
   181
    break;
dvander@4
   182
dvander@0
   183
case OP_RETURN:
dvander@0
   184
{
dvander@4
   185
    *result = *--top.sp;
dvander@69
   186
    if (top.fp == entryFrame)
dvander@69
   187
        goto done;
dvander@0
   188
dvander@65
   189
    zone->stack().popInlineFrame();
dvander@47
   190
    locals = top.fp->locals();
dvander@4
   191
    *top.sp++ = *result;
dvander@0
   192
    top.pc += OpcodeInfo[*top.pc].length;
dvander@0
   193
    continue;
dvander@0
   194
}
dvander@0
   195
dvander@0
   196
#define RELATIONAL_JUMP(op)                 \
dvander@0
   197
    {                                       \
dvander@0
   198
        int right = POP_I32(top);           \
dvander@0
   199
        int left = POP_I32(top);            \
dvander@0
   200
        if (left op right) {                \
dvander@0
   201
            top.pc += READ_INT32(top.pc);   \
dvander@0
   202
            continue;                       \
dvander@0
   203
        }                                   \
dvander@0
   204
    }
dvander@0
   205
dvander@0
   206
case OP_JL:
dvander@0
   207
    RELATIONAL_JUMP(<);
dvander@0
   208
    break;
dvander@0
   209
dvander@0
   210
case OP_JLE:
dvander@0
   211
    RELATIONAL_JUMP(<=);
dvander@0
   212
    break;
dvander@0
   213
dvander@0
   214
case OP_JG:
dvander@0
   215
    RELATIONAL_JUMP(>);
dvander@0
   216
    break;
dvander@0
   217
dvander@0
   218
case OP_JGE:
dvander@0
   219
    RELATIONAL_JUMP(>=);
dvander@0
   220
    break;
dvander@0
   221
dvander@0
   222
case OP_JEQ:
dvander@0
   223
    RELATIONAL_JUMP(==);
dvander@0
   224
    break;
dvander@0
   225
dvander@0
   226
case OP_JNE:
dvander@0
   227
    RELATIONAL_JUMP(!=);
dvander@0
   228
    break;
dvander@0
   229
dvander@0
   230
case OP_JT:
dvander@0
   231
{
dvander@0
   232
    int value = POP_I32(top);
dvander@0
   233
    if (value) {
dvander@0
   234
        top.pc += READ_INT32(top.pc);
dvander@0
   235
        continue;
dvander@0
   236
    }
dvander@0
   237
    break;
dvander@0
   238
}
dvander@0
   239
dvander@0
   240
case OP_JF:
dvander@0
   241
{
dvander@0
   242
    int value = POP_I32(top);
dvander@0
   243
    if (!value) {
dvander@0
   244
        top.pc += READ_INT32(top.pc);
dvander@0
   245
        continue;
dvander@0
   246
    }
dvander@0
   247
    break;
dvander@0
   248
}
dvander@0
   249
dvander@0
   250
case OP_JUMP:
dvander@0
   251
    top.pc += READ_INT32(top.pc);
dvander@0
   252
    continue;
dvander@0
   253
dvander@0
   254
case OP_GETLOCAL:
dvander@0
   255
{
dvander@0
   256
    int slot = READ_INT32(top.pc);
dvander@0
   257
    *top.sp++ = locals[slot];
dvander@0
   258
    break;
dvander@0
   259
}
dvander@0
   260
dvander@0
   261
case OP_SETLOCAL:
dvander@0
   262
{
dvander@0
   263
    int slot = READ_INT32(top.pc);
dvander@0
   264
    locals[slot] = top.sp[-1];
dvander@0
   265
    break;
dvander@0
   266
}
dvander@0
   267
dvander@0
   268
case OP_ADD:
dvander@0
   269
{
dvander@0
   270
    int right = POP_I32(top);
dvander@0
   271
    int left = POP_I32(top);
dvander@0
   272
    int result = left + right;
dvander@0
   273
    PUSH_I32(top, result);
dvander@0
   274
    break;
dvander@0
   275
}
dvander@0
   276
dvander@0
   277
case OP_SUB:
dvander@0
   278
{
dvander@0
   279
    int right = POP_I32(top);
dvander@0
   280
    int left = POP_I32(top);
dvander@0
   281
    int result = left - right;
dvander@0
   282
    PUSH_I32(top, result);
dvander@0
   283
    break;
dvander@0
   284
}
dvander@0
   285
dvander@0
   286
case OP_MUL:
dvander@0
   287
{
dvander@0
   288
    int right = POP_I32(top);
dvander@0
   289
    int left = POP_I32(top);
dvander@0
   290
    int result = left * right;
dvander@22
   291
    PUSH_I32(top, result);
dvander@0
   292
    break;
dvander@0
   293
}
dvander@0
   294
dvander@0
   295
case OP_DIV:
dvander@0
   296
{
dvander@0
   297
    int right = POP_I32(top);
dvander@0
   298
    int left = POP_I32(top);
dvander@69
   299
    if (!right) {
dvander@69
   300
        zone->reportError(Message_IntegerDivideByZero);
dvander@69
   301
        goto error;
dvander@69
   302
    }
dvander@0
   303
    int result = left / right;
dvander@0
   304
    PUSH_I32(top, result);
dvander@0
   305
    break;
dvander@0
   306
}
dvander@0
   307
dvander@4
   308
case OP_ADD_F:
dvander@4
   309
{
dvander@4
   310
    float right = POP_F(top);
dvander@4
   311
    float left = POP_F(top);
dvander@4
   312
    float result = left + right;
dvander@4
   313
    PUSH_F(top, result);
dvander@4
   314
    break;
dvander@4
   315
}
dvander@4
   316
dvander@4
   317
case OP_SUB_F:
dvander@4
   318
{
dvander@4
   319
    float right = POP_F(top);
dvander@4
   320
    float left = POP_F(top);
dvander@4
   321
    float result = left - right;
dvander@4
   322
    PUSH_F(top, result);
dvander@4
   323
    break;
dvander@4
   324
}
dvander@4
   325
dvander@4
   326
case OP_MUL_F:
dvander@4
   327
{
dvander@4
   328
    float right = POP_F(top);
dvander@4
   329
    float left = POP_F(top);
dvander@4
   330
    float result = left * right;
dvander@4
   331
    PUSH_F(top, result);
dvander@4
   332
    break;
dvander@4
   333
}
dvander@4
   334
dvander@4
   335
case OP_DIV_F:
dvander@4
   336
{
dvander@4
   337
    float right = POP_F(top);
dvander@4
   338
    float left = POP_F(top);
dvander@4
   339
    float result = left / right;
dvander@4
   340
    PUSH_F(top, result);
dvander@4
   341
    break;
dvander@4
   342
}
dvander@4
   343
dvander@8
   344
case OP_SHL:
dvander@8
   345
{
dvander@8
   346
    int right = POP_I32(top);
dvander@8
   347
    int left = POP_I32(top);
dvander@8
   348
    int result = left << right;
dvander@8
   349
    PUSH_I32(top, result);
dvander@8
   350
    break;
dvander@8
   351
}
dvander@8
   352
dvander@8
   353
case OP_SHR:
dvander@8
   354
{
dvander@8
   355
    int right = POP_I32(top);
dvander@8
   356
    int left = POP_I32(top);
dvander@8
   357
    int result = left >> right;
dvander@8
   358
    PUSH_I32(top, result);
dvander@8
   359
    break;
dvander@8
   360
}
dvander@8
   361
dvander@8
   362
case OP_USHR:
dvander@8
   363
{
dvander@8
   364
    int right = POP_I32(top);
dvander@8
   365
    int left = POP_I32(top);
dvander@8
   366
    int result = unsigned(left) >> unsigned(right);
dvander@8
   367
    PUSH_I32(top, result);
dvander@8
   368
    break;
dvander@8
   369
}
dvander@8
   370
dvander@8
   371
case OP_BITAND:
dvander@8
   372
{
dvander@8
   373
    int right = POP_I32(top);
dvander@8
   374
    int left = POP_I32(top);
dvander@8
   375
    int result = left & right;
dvander@8
   376
    PUSH_I32(top, result);
dvander@8
   377
    break;
dvander@8
   378
}
dvander@8
   379
dvander@8
   380
case OP_BITOR:
dvander@8
   381
{
dvander@8
   382
    int right = POP_I32(top);
dvander@8
   383
    int left = POP_I32(top);
dvander@8
   384
    int result = left | right;
dvander@8
   385
    PUSH_I32(top, result);
dvander@8
   386
    break;
dvander@8
   387
}
dvander@8
   388
dvander@8
   389
case OP_BITXOR:
dvander@8
   390
{
dvander@8
   391
    int right = POP_I32(top);
dvander@8
   392
    int left = POP_I32(top);
dvander@8
   393
    int result = left ^ right;
dvander@8
   394
    PUSH_I32(top, result);
dvander@8
   395
    break;
dvander@8
   396
}
dvander@8
   397
dvander@0
   398
case OP_POP:
dvander@0
   399
    top.sp--;
dvander@0
   400
    break;
dvander@0
   401
dvander@0
   402
case OP_STOP:
dvander@0
   403
    assert(false);
dvander@0
   404
    break;
dvander@0
   405
dvander@0
   406
case OP_CALLGLOBAL:
dvander@0
   407
{
dvander@53
   408
    zone->heap().reclaim();
dvander@46
   409
    unsigned index = READ_UINT32(top.pc);
dvander@47
   410
    Local<Function> newFun(zone, top.fp->code()->module()->getFunction(index));
dvander@69
   411
    if (!zone->stack().pushInlineFrame(newFun))
dvander@69
   412
        goto error;
dvander@0
   413
dvander@47
   414
    locals = top.fp->locals();
dvander@0
   415
    continue;
dvander@0
   416
}
dvander@0
   417
dvander@0
   418
case OP_GETARG:
dvander@0
   419
{
dvander@0
   420
    unsigned slot = READ_UINT32(top.pc);
dvander@47
   421
    *top.sp++ = top.fp->arg(slot);
dvander@0
   422
    break;
dvander@0
   423
}
dvander@0
   424
dvander@0
   425
case OP_SETARG:
dvander@0
   426
{
dvander@0
   427
    unsigned slot = READ_UINT32(top.pc);
dvander@47
   428
    top.fp->arg(slot) = *--top.sp;
dvander@0
   429
    break;
dvander@0
   430
}
dvander@0
   431
dvander@19
   432
case OP_BOUNDS:
dvander@0
   433
{
dvander@12
   434
    Array *array = top.sp[-2].array;
dvander@0
   435
    int index = top.sp[-1].i32;
dvander@69
   436
    if (index < 0 || unsigned(index) >= array->nelements()) {
dvander@69
   437
        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->nelements());
dvander@69
   438
        goto error;
dvander@69
   439
    }
dvander@0
   440
    break;
dvander@0
   441
}
dvander@0
   442
dvander@6
   443
case OP_GETARRAY_I:
dvander@0
   444
{
dvander@12
   445
    Array *array = top.sp[-2].array;
dvander@0
   446
    int index = top.sp[-1].i32;
dvander@0
   447
    top.sp[-2].i32 = array->readInt32(index);
dvander@0
   448
    top.sp--;
dvander@0
   449
    break;
dvander@0
   450
}
dvander@0
   451
dvander@7
   452
case OP_GETARRAY_F:
dvander@7
   453
{
dvander@12
   454
    Array *array = top.sp[-2].array;
dvander@7
   455
    int index = top.sp[-1].i32;
dvander@7
   456
    top.sp[-2].f = array->readFloat(index);
dvander@7
   457
    top.sp--;
dvander@7
   458
    break;
dvander@7
   459
}
dvander@7
   460
dvander@21
   461
case OP_GETARRAY_C:
dvander@21
   462
{
dvander@21
   463
    Array *array = top.sp[-2].array;
dvander@21
   464
    int index = top.sp[-1].i32;
dvander@21
   465
    top.sp[-2].i32 = array->readChar(index);
dvander@21
   466
    top.sp--;
dvander@21
   467
    break;
dvander@21
   468
}
dvander@21
   469
dvander@6
   470
case OP_SETARRAY_I:
dvander@0
   471
{
dvander@12
   472
    Array *array = top.sp[-3].array;
dvander@0
   473
    int index = top.sp[-2].i32;
dvander@0
   474
    array->writeInt32(index, top.sp[-1].i32);
dvander@0
   475
    top.sp[-3] = top.sp[-1];
dvander@0
   476
    top.sp -= 2;
dvander@0
   477
    break;
dvander@0
   478
}
dvander@0
   479
dvander@7
   480
case OP_SETARRAY_F:
dvander@7
   481
{
dvander@12
   482
    Array *array = top.sp[-3].array;
dvander@7
   483
    int index = top.sp[-2].i32;
dvander@7
   484
    array->writeFloat(index, top.sp[-1].f);
dvander@7
   485
    top.sp[-3] = top.sp[-1];
dvander@7
   486
    top.sp -= 2;
dvander@7
   487
    break;
dvander@7
   488
}
dvander@7
   489
dvander@21
   490
case OP_SETARRAY_C:
dvander@21
   491
{
dvander@21
   492
    Array *array = top.sp[-3].array;
dvander@21
   493
    int index = top.sp[-2].i32;
dvander@21
   494
    array->writeChar(index, top.sp[-1].i32);
dvander@21
   495
    top.sp[-3] = top.sp[-1];
dvander@21
   496
    top.sp -= 2;
dvander@21
   497
    break;
dvander@21
   498
}
dvander@21
   499
dvander@19
   500
case OP_GETARRAY_O:
dvander@0
   501
{
dvander@12
   502
    Array *array = top.sp[-2].array;
dvander@0
   503
    int index = top.sp[-1].i32;
dvander@12
   504
    top.sp[-2].array = Array::cast(array->readObject(index));
dvander@0
   505
    top.sp--;
dvander@0
   506
    break;
dvander@0
   507
}
dvander@0
   508
dvander@4
   509
case OP_CVT_I2F:
dvander@4
   510
{
dvander@4
   511
    int ival = POP_I32(top);
dvander@4
   512
    float fval = (float)ival;
dvander@4
   513
    PUSH_F(top, fval);
dvander@4
   514
    break;
dvander@4
   515
}
dvander@4
   516
dvander@19
   517
case OP_NEWARRAY_LIFO:
dvander@12
   518
{
dvander@47
   519
    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc))));
dvander@42
   520
    Array *array = GenerateArray(zone, map);
dvander@69
   521
    if (!array)
dvander@69
   522
        goto error;
dvander@12
   523
    top.sp->obj = array;
dvander@12
   524
    top.sp++;
dvander@12
   525
    break;
dvander@12
   526
}
dvander@12
   527
dvander@12
   528
case OP_SAVELIFO:
dvander@10
   529
{
dvander@10
   530
    unsigned slot = READ_UINT32(top.pc);
dvander@42
   531
    locals[slot].address = zone->heap().lifoPosition();
dvander@12
   532
    break;
dvander@12
   533
}
dvander@12
   534
dvander@12
   535
case OP_UNWINDLIFO:
dvander@12
   536
{
dvander@12
   537
    unsigned slot = READ_UINT32(top.pc);
dvander@42
   538
    zone->heap().unwindLifo(locals[slot].address);
dvander@10
   539
    break;
dvander@10
   540
}
dvander@10
   541
dvander@14
   542
case OP_VARREF_LIFO:
dvander@14
   543
{
dvander@14
   544
    unsigned slot = READ_UINT32(top.pc);
dvander@69
   545
    if (!PushNewRef(zone, top, &locals[slot], Heap::Tenure_Stack))
dvander@69
   546
        goto error;
dvander@14
   547
    break;
dvander@14
   548
}
dvander@14
   549
dvander@14
   550
case OP_ARGREF_LIFO:
dvander@14
   551
{
dvander@14
   552
    unsigned slot = READ_UINT32(top.pc);
dvander@69
   553
    if (!PushNewRef(zone, top, &top.fp->arg(slot), Heap::Tenure_Stack))
dvander@69
   554
        goto error;
dvander@14
   555
    break;
dvander@14
   556
}
dvander@14
   557
dvander@17
   558
case OP_ARRAYREF_LIFO:
dvander@17
   559
{
dvander@42
   560
    Local<Array> array(zone, top.sp[-2].array);
dvander@42
   561
    Local<Reference> ref(zone, Reference::NewArray(zone, array, top.sp[-1].i32, Heap::Tenure_Stack));
dvander@69
   562
    if (!ref)
dvander@69
   563
        goto error;
dvander@17
   564
    top.sp[-2].ref = ref;
dvander@17
   565
    top.sp--;
dvander@17
   566
    break;
dvander@17
   567
}
dvander@17
   568
dvander@16
   569
case OP_SLOTREF_LIFO:
dvander@16
   570
{
dvander@42
   571
    Reference *ref = Reference::NewStack(zone, top.sp[-1], Heap::Tenure_Stack);
dvander@69
   572
    if (!ref)
dvander@69
   573
        goto error;
dvander@16
   574
    top.sp[-1].ref = ref;
dvander@16
   575
    break;
dvander@16
   576
}
dvander@16
   577
dvander@14
   578
case OP_GETREF_I:
dvander@14
   579
{
dvander@14
   580
    top.sp[-1].i32 = top.sp[-1].ref->getInt();
dvander@14
   581
    break;
dvander@14
   582
}
dvander@14
   583
dvander@14
   584
case OP_SETREF_I:
dvander@14
   585
{
dvander@14
   586
    top.sp[-2].ref->setInt(top.sp[-1].i32);
dvander@14
   587
    top.sp[-2].i32 = top.sp[-1].i32;
dvander@23
   588
    top.sp--;
dvander@14
   589
    break;
dvander@14
   590
}
dvander@14
   591
dvander@14
   592
case OP_GETREF_F:
dvander@14
   593
{
dvander@14
   594
    top.sp[-1].f = top.sp[-1].ref->getFloat();
dvander@14
   595
    break;
dvander@14
   596
}
dvander@14
   597
dvander@14
   598
case OP_SETREF_F:
dvander@14
   599
{
dvander@14
   600
    top.sp[-2].ref->setFloat(top.sp[-1].f);
dvander@14
   601
    top.sp[-2].f = top.sp[-1].f;
dvander@14
   602
    break;
dvander@14
   603
}
dvander@14
   604
dvander@21
   605
case OP_OBJECT:
dvander@21
   606
{
dvander@47
   607
    top.sp->obj = top.fp->code()->object(READ_UINT32(top.pc));
dvander@21
   608
    top.sp++;
dvander@21
   609
    break;
dvander@21
   610
}
dvander@21
   611
dvander@21
   612
case OP_ARRAYCOPY:
dvander@21
   613
{
dvander@21
   614
    // Note for this assignment opcode, we return the left-hand side, not the
dvander@21
   615
    // right, since in this case the result of the expression could be different.
dvander@69
   616
    if (!CopyArray(zone, top.sp[-2].array, top.sp[-1].array))
dvander@69
   617
        goto error;
dvander@21
   618
    top.sp--;
dvander@21
   619
    break;
dvander@21
   620
}
dvander@21
   621
dvander@22
   622
case OP_DUP:
dvander@22
   623
{
dvander@23
   624
    top.sp++;
dvander@23
   625
    top.sp[-1] = top.sp[-2];
dvander@22
   626
    break;
dvander@22
   627
}
dvander@22
   628
dvander@22
   629
case OP_DUP2:
dvander@22
   630
{
dvander@23
   631
    top.sp += 2;
dvander@23
   632
    top.sp[-2] = top.sp[-4];
dvander@23
   633
    top.sp[-1] = top.sp[-3];
dvander@23
   634
    break;
dvander@23
   635
}
dvander@23
   636
dvander@23
   637
case OP_SWAP:
dvander@23
   638
{
dvander@23
   639
    LocalSlot slot = top.sp[-2];
dvander@23
   640
    top.sp[-2] = top.sp[-1];
dvander@23
   641
    top.sp[-1] = slot;
dvander@23
   642
    break;
dvander@23
   643
}
dvander@23
   644
dvander@23
   645
case OP_ROLL3:
dvander@23
   646
{
dvander@23
   647
    LocalSlot slot = top.sp[-3];
dvander@23
   648
    top.sp[-3] = top.sp[-2];
dvander@23
   649
    top.sp[-2] = top.sp[-1];
dvander@23
   650
    top.sp[-1] = slot;
dvander@23
   651
    break;
dvander@23
   652
}
dvander@23
   653
dvander@23
   654
case OP_PICK2:
dvander@23
   655
{
dvander@23
   656
    top.sp++;
dvander@23
   657
    top.sp[-1] = top.sp[-3];
dvander@23
   658
    break;
dvander@23
   659
}
dvander@23
   660
dvander@23
   661
case OP_PICK3:
dvander@23
   662
{
dvander@23
   663
    top.sp++;
dvander@23
   664
    top.sp[-1] = top.sp[-4];
dvander@22
   665
    break;
dvander@22
   666
}
dvander@22
   667
dvander@68
   668
case OP_CALLNATIVE:
dvander@68
   669
{
dvander@68
   670
    unsigned index = READ_UINT32(top.pc);
dvander@68
   671
    unsigned argc = READ_UINT32(top.pc + 4);
dvander@68
   672
dvander@68
   673
    Local<Native> native(zone, Native::cast(top.fp->code()->module()->natives()->at(index)));
dvander@68
   674
    if (!native->function()) {
dvander@69
   675
        zone->reportError(Message_NativeNotBound, native->name()->chars());
dvander@69
   676
        goto error;
dvander@68
   677
    }
dvander@68
   678
dvander@68
   679
    int result;
dvander@68
   680
    void *nativeIdentity = top.fp->code()->module()->nativeIdentity();
dvander@69
   681
    if (!InvokeNative(zone, native, nativeIdentity, top.sp, argc, &result))
dvander@69
   682
        goto error;
dvander@68
   683
dvander@68
   684
    top.sp -= argc;
dvander@68
   685
    PUSH_I32(top, result);
dvander@68
   686
    break;
dvander@68
   687
}
dvander@68
   688
dvander@0
   689
default:
dvander@0
   690
    assert(false);
dvander@0
   691
    return false;
dvander@0
   692
dvander@0
   693
        }
dvander@0
   694
dvander@0
   695
        top.pc += OpcodeInfo[op].length;
dvander@0
   696
    }
dvander@0
   697
dvander@69
   698
done:
dvander@0
   699
    return true;
dvander@69
   700
dvander@69
   701
error:
dvander@69
   702
    // Unwind frames until we can continue.
dvander@69
   703
    while (top.fp != entryFrame)
dvander@69
   704
        zone->stack().popInlineFrame();
dvander@69
   705
    return false;
dvander@0
   706
}