jitcraft/Interpreter.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jul 15 14:40:11 2012 -0700 (2012-07-15)
changeset 73 ef5492aa8d8b
parent 72 40746ab0a30b
child 74 80e29e23eb4e
permissions -rw-r--r--
Small refactoring to make callees pushed explicitly.
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@72
   184
case OP_RETURNVOID:
dvander@72
   185
case OP_STOP:
dvander@0
   186
{
dvander@72
   187
    if (op == OP_RETURN)
dvander@72
   188
        *result = *--top.sp;
dvander@72
   189
dvander@69
   190
    if (top.fp == entryFrame)
dvander@69
   191
        goto done;
dvander@0
   192
dvander@72
   193
    // This must not GC.
dvander@65
   194
    zone->stack().popInlineFrame();
dvander@47
   195
    locals = top.fp->locals();
dvander@72
   196
dvander@72
   197
    if (op == OP_RETURN)
dvander@72
   198
        *top.sp++ = *result;
dvander@72
   199
dvander@0
   200
    top.pc += OpcodeInfo[*top.pc].length;
dvander@0
   201
    continue;
dvander@0
   202
}
dvander@0
   203
dvander@0
   204
#define RELATIONAL_JUMP(op)                 \
dvander@0
   205
    {                                       \
dvander@0
   206
        int right = POP_I32(top);           \
dvander@0
   207
        int left = POP_I32(top);            \
dvander@0
   208
        if (left op right) {                \
dvander@0
   209
            top.pc += READ_INT32(top.pc);   \
dvander@0
   210
            continue;                       \
dvander@0
   211
        }                                   \
dvander@0
   212
    }
dvander@0
   213
dvander@0
   214
case OP_JL:
dvander@0
   215
    RELATIONAL_JUMP(<);
dvander@0
   216
    break;
dvander@0
   217
dvander@0
   218
case OP_JLE:
dvander@0
   219
    RELATIONAL_JUMP(<=);
dvander@0
   220
    break;
dvander@0
   221
dvander@0
   222
case OP_JG:
dvander@0
   223
    RELATIONAL_JUMP(>);
dvander@0
   224
    break;
dvander@0
   225
dvander@0
   226
case OP_JGE:
dvander@0
   227
    RELATIONAL_JUMP(>=);
dvander@0
   228
    break;
dvander@0
   229
dvander@0
   230
case OP_JEQ:
dvander@0
   231
    RELATIONAL_JUMP(==);
dvander@0
   232
    break;
dvander@0
   233
dvander@0
   234
case OP_JNE:
dvander@0
   235
    RELATIONAL_JUMP(!=);
dvander@0
   236
    break;
dvander@0
   237
dvander@0
   238
case OP_JT:
dvander@0
   239
{
dvander@0
   240
    int value = POP_I32(top);
dvander@0
   241
    if (value) {
dvander@0
   242
        top.pc += READ_INT32(top.pc);
dvander@0
   243
        continue;
dvander@0
   244
    }
dvander@0
   245
    break;
dvander@0
   246
}
dvander@0
   247
dvander@0
   248
case OP_JF:
dvander@0
   249
{
dvander@0
   250
    int value = POP_I32(top);
dvander@0
   251
    if (!value) {
dvander@0
   252
        top.pc += READ_INT32(top.pc);
dvander@0
   253
        continue;
dvander@0
   254
    }
dvander@0
   255
    break;
dvander@0
   256
}
dvander@0
   257
dvander@0
   258
case OP_JUMP:
dvander@0
   259
    top.pc += READ_INT32(top.pc);
dvander@0
   260
    continue;
dvander@0
   261
dvander@0
   262
case OP_GETLOCAL:
dvander@0
   263
{
dvander@0
   264
    int slot = READ_INT32(top.pc);
dvander@0
   265
    *top.sp++ = locals[slot];
dvander@0
   266
    break;
dvander@0
   267
}
dvander@0
   268
dvander@0
   269
case OP_SETLOCAL:
dvander@0
   270
{
dvander@0
   271
    int slot = READ_INT32(top.pc);
dvander@0
   272
    locals[slot] = top.sp[-1];
dvander@0
   273
    break;
dvander@0
   274
}
dvander@0
   275
dvander@0
   276
case OP_ADD:
dvander@0
   277
{
dvander@0
   278
    int right = POP_I32(top);
dvander@0
   279
    int left = POP_I32(top);
dvander@0
   280
    int result = left + right;
dvander@0
   281
    PUSH_I32(top, result);
dvander@0
   282
    break;
dvander@0
   283
}
dvander@0
   284
dvander@0
   285
case OP_SUB:
dvander@0
   286
{
dvander@0
   287
    int right = POP_I32(top);
dvander@0
   288
    int left = POP_I32(top);
dvander@0
   289
    int result = left - right;
dvander@0
   290
    PUSH_I32(top, result);
dvander@0
   291
    break;
dvander@0
   292
}
dvander@0
   293
dvander@0
   294
case OP_MUL:
dvander@0
   295
{
dvander@0
   296
    int right = POP_I32(top);
dvander@0
   297
    int left = POP_I32(top);
dvander@0
   298
    int result = left * right;
dvander@22
   299
    PUSH_I32(top, result);
dvander@0
   300
    break;
dvander@0
   301
}
dvander@0
   302
dvander@0
   303
case OP_DIV:
dvander@0
   304
{
dvander@0
   305
    int right = POP_I32(top);
dvander@0
   306
    int left = POP_I32(top);
dvander@69
   307
    if (!right) {
dvander@69
   308
        zone->reportError(Message_IntegerDivideByZero);
dvander@69
   309
        goto error;
dvander@69
   310
    }
dvander@0
   311
    int result = left / right;
dvander@0
   312
    PUSH_I32(top, result);
dvander@0
   313
    break;
dvander@0
   314
}
dvander@0
   315
dvander@4
   316
case OP_ADD_F:
dvander@4
   317
{
dvander@4
   318
    float right = POP_F(top);
dvander@4
   319
    float left = POP_F(top);
dvander@4
   320
    float result = left + right;
dvander@4
   321
    PUSH_F(top, result);
dvander@4
   322
    break;
dvander@4
   323
}
dvander@4
   324
dvander@4
   325
case OP_SUB_F:
dvander@4
   326
{
dvander@4
   327
    float right = POP_F(top);
dvander@4
   328
    float left = POP_F(top);
dvander@4
   329
    float result = left - right;
dvander@4
   330
    PUSH_F(top, result);
dvander@4
   331
    break;
dvander@4
   332
}
dvander@4
   333
dvander@4
   334
case OP_MUL_F:
dvander@4
   335
{
dvander@4
   336
    float right = POP_F(top);
dvander@4
   337
    float left = POP_F(top);
dvander@4
   338
    float result = left * right;
dvander@4
   339
    PUSH_F(top, result);
dvander@4
   340
    break;
dvander@4
   341
}
dvander@4
   342
dvander@4
   343
case OP_DIV_F:
dvander@4
   344
{
dvander@4
   345
    float right = POP_F(top);
dvander@4
   346
    float left = POP_F(top);
dvander@4
   347
    float result = left / right;
dvander@4
   348
    PUSH_F(top, result);
dvander@4
   349
    break;
dvander@4
   350
}
dvander@4
   351
dvander@8
   352
case OP_SHL:
dvander@8
   353
{
dvander@8
   354
    int right = POP_I32(top);
dvander@8
   355
    int left = POP_I32(top);
dvander@8
   356
    int result = left << right;
dvander@8
   357
    PUSH_I32(top, result);
dvander@8
   358
    break;
dvander@8
   359
}
dvander@8
   360
dvander@8
   361
case OP_SHR:
dvander@8
   362
{
dvander@8
   363
    int right = POP_I32(top);
dvander@8
   364
    int left = POP_I32(top);
dvander@8
   365
    int result = left >> right;
dvander@8
   366
    PUSH_I32(top, result);
dvander@8
   367
    break;
dvander@8
   368
}
dvander@8
   369
dvander@8
   370
case OP_USHR:
dvander@8
   371
{
dvander@8
   372
    int right = POP_I32(top);
dvander@8
   373
    int left = POP_I32(top);
dvander@8
   374
    int result = unsigned(left) >> unsigned(right);
dvander@8
   375
    PUSH_I32(top, result);
dvander@8
   376
    break;
dvander@8
   377
}
dvander@8
   378
dvander@8
   379
case OP_BITAND:
dvander@8
   380
{
dvander@8
   381
    int right = POP_I32(top);
dvander@8
   382
    int left = POP_I32(top);
dvander@8
   383
    int result = left & right;
dvander@8
   384
    PUSH_I32(top, result);
dvander@8
   385
    break;
dvander@8
   386
}
dvander@8
   387
dvander@8
   388
case OP_BITOR:
dvander@8
   389
{
dvander@8
   390
    int right = POP_I32(top);
dvander@8
   391
    int left = POP_I32(top);
dvander@8
   392
    int result = left | right;
dvander@8
   393
    PUSH_I32(top, result);
dvander@8
   394
    break;
dvander@8
   395
}
dvander@8
   396
dvander@8
   397
case OP_BITXOR:
dvander@8
   398
{
dvander@8
   399
    int right = POP_I32(top);
dvander@8
   400
    int left = POP_I32(top);
dvander@8
   401
    int result = left ^ right;
dvander@8
   402
    PUSH_I32(top, result);
dvander@8
   403
    break;
dvander@8
   404
}
dvander@8
   405
dvander@0
   406
case OP_POP:
dvander@0
   407
    top.sp--;
dvander@0
   408
    break;
dvander@0
   409
dvander@73
   410
case OP_CALL:
dvander@0
   411
{
dvander@53
   412
    zone->heap().reclaim();
dvander@73
   413
dvander@73
   414
    Local<Function> newFun(zone, top.sp[-1].fun);
dvander@73
   415
    top.sp--;
dvander@73
   416
dvander@69
   417
    if (!zone->stack().pushInlineFrame(newFun))
dvander@69
   418
        goto error;
dvander@0
   419
dvander@47
   420
    locals = top.fp->locals();
dvander@0
   421
    continue;
dvander@0
   422
}
dvander@0
   423
dvander@0
   424
case OP_GETARG:
dvander@0
   425
{
dvander@0
   426
    unsigned slot = READ_UINT32(top.pc);
dvander@47
   427
    *top.sp++ = top.fp->arg(slot);
dvander@0
   428
    break;
dvander@0
   429
}
dvander@0
   430
dvander@0
   431
case OP_SETARG:
dvander@0
   432
{
dvander@0
   433
    unsigned slot = READ_UINT32(top.pc);
dvander@47
   434
    top.fp->arg(slot) = *--top.sp;
dvander@0
   435
    break;
dvander@0
   436
}
dvander@0
   437
dvander@19
   438
case OP_BOUNDS:
dvander@0
   439
{
dvander@12
   440
    Array *array = top.sp[-2].array;
dvander@0
   441
    int index = top.sp[-1].i32;
dvander@69
   442
    if (index < 0 || unsigned(index) >= array->nelements()) {
dvander@69
   443
        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->nelements());
dvander@69
   444
        goto error;
dvander@69
   445
    }
dvander@0
   446
    break;
dvander@0
   447
}
dvander@0
   448
dvander@6
   449
case OP_GETARRAY_I:
dvander@0
   450
{
dvander@12
   451
    Array *array = top.sp[-2].array;
dvander@0
   452
    int index = top.sp[-1].i32;
dvander@0
   453
    top.sp[-2].i32 = array->readInt32(index);
dvander@0
   454
    top.sp--;
dvander@0
   455
    break;
dvander@0
   456
}
dvander@0
   457
dvander@7
   458
case OP_GETARRAY_F:
dvander@7
   459
{
dvander@12
   460
    Array *array = top.sp[-2].array;
dvander@7
   461
    int index = top.sp[-1].i32;
dvander@7
   462
    top.sp[-2].f = array->readFloat(index);
dvander@7
   463
    top.sp--;
dvander@7
   464
    break;
dvander@7
   465
}
dvander@7
   466
dvander@21
   467
case OP_GETARRAY_C:
dvander@21
   468
{
dvander@21
   469
    Array *array = top.sp[-2].array;
dvander@21
   470
    int index = top.sp[-1].i32;
dvander@21
   471
    top.sp[-2].i32 = array->readChar(index);
dvander@21
   472
    top.sp--;
dvander@21
   473
    break;
dvander@21
   474
}
dvander@21
   475
dvander@6
   476
case OP_SETARRAY_I:
dvander@0
   477
{
dvander@12
   478
    Array *array = top.sp[-3].array;
dvander@0
   479
    int index = top.sp[-2].i32;
dvander@0
   480
    array->writeInt32(index, top.sp[-1].i32);
dvander@0
   481
    top.sp[-3] = top.sp[-1];
dvander@0
   482
    top.sp -= 2;
dvander@0
   483
    break;
dvander@0
   484
}
dvander@0
   485
dvander@7
   486
case OP_SETARRAY_F:
dvander@7
   487
{
dvander@12
   488
    Array *array = top.sp[-3].array;
dvander@7
   489
    int index = top.sp[-2].i32;
dvander@7
   490
    array->writeFloat(index, top.sp[-1].f);
dvander@7
   491
    top.sp[-3] = top.sp[-1];
dvander@7
   492
    top.sp -= 2;
dvander@7
   493
    break;
dvander@7
   494
}
dvander@7
   495
dvander@21
   496
case OP_SETARRAY_C:
dvander@21
   497
{
dvander@21
   498
    Array *array = top.sp[-3].array;
dvander@21
   499
    int index = top.sp[-2].i32;
dvander@21
   500
    array->writeChar(index, top.sp[-1].i32);
dvander@21
   501
    top.sp[-3] = top.sp[-1];
dvander@21
   502
    top.sp -= 2;
dvander@21
   503
    break;
dvander@21
   504
}
dvander@21
   505
dvander@19
   506
case OP_GETARRAY_O:
dvander@0
   507
{
dvander@12
   508
    Array *array = top.sp[-2].array;
dvander@0
   509
    int index = top.sp[-1].i32;
dvander@12
   510
    top.sp[-2].array = Array::cast(array->readObject(index));
dvander@0
   511
    top.sp--;
dvander@0
   512
    break;
dvander@0
   513
}
dvander@0
   514
dvander@4
   515
case OP_CVT_I2F:
dvander@4
   516
{
dvander@4
   517
    int ival = POP_I32(top);
dvander@4
   518
    float fval = (float)ival;
dvander@4
   519
    PUSH_F(top, fval);
dvander@4
   520
    break;
dvander@4
   521
}
dvander@4
   522
dvander@19
   523
case OP_NEWARRAY_LIFO:
dvander@12
   524
{
dvander@47
   525
    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc))));
dvander@42
   526
    Array *array = GenerateArray(zone, map);
dvander@69
   527
    if (!array)
dvander@69
   528
        goto error;
dvander@12
   529
    top.sp->obj = array;
dvander@12
   530
    top.sp++;
dvander@12
   531
    break;
dvander@12
   532
}
dvander@12
   533
dvander@12
   534
case OP_SAVELIFO:
dvander@10
   535
{
dvander@10
   536
    unsigned slot = READ_UINT32(top.pc);
dvander@42
   537
    locals[slot].address = zone->heap().lifoPosition();
dvander@12
   538
    break;
dvander@12
   539
}
dvander@12
   540
dvander@12
   541
case OP_UNWINDLIFO:
dvander@12
   542
{
dvander@12
   543
    unsigned slot = READ_UINT32(top.pc);
dvander@42
   544
    zone->heap().unwindLifo(locals[slot].address);
dvander@10
   545
    break;
dvander@10
   546
}
dvander@10
   547
dvander@14
   548
case OP_VARREF_LIFO:
dvander@14
   549
{
dvander@14
   550
    unsigned slot = READ_UINT32(top.pc);
dvander@69
   551
    if (!PushNewRef(zone, top, &locals[slot], Heap::Tenure_Stack))
dvander@69
   552
        goto error;
dvander@14
   553
    break;
dvander@14
   554
}
dvander@14
   555
dvander@14
   556
case OP_ARGREF_LIFO:
dvander@14
   557
{
dvander@14
   558
    unsigned slot = READ_UINT32(top.pc);
dvander@69
   559
    if (!PushNewRef(zone, top, &top.fp->arg(slot), Heap::Tenure_Stack))
dvander@69
   560
        goto error;
dvander@14
   561
    break;
dvander@14
   562
}
dvander@14
   563
dvander@17
   564
case OP_ARRAYREF_LIFO:
dvander@17
   565
{
dvander@42
   566
    Local<Array> array(zone, top.sp[-2].array);
dvander@42
   567
    Local<Reference> ref(zone, Reference::NewArray(zone, array, top.sp[-1].i32, Heap::Tenure_Stack));
dvander@69
   568
    if (!ref)
dvander@69
   569
        goto error;
dvander@17
   570
    top.sp[-2].ref = ref;
dvander@17
   571
    top.sp--;
dvander@17
   572
    break;
dvander@17
   573
}
dvander@17
   574
dvander@16
   575
case OP_SLOTREF_LIFO:
dvander@16
   576
{
dvander@42
   577
    Reference *ref = Reference::NewStack(zone, top.sp[-1], Heap::Tenure_Stack);
dvander@69
   578
    if (!ref)
dvander@69
   579
        goto error;
dvander@16
   580
    top.sp[-1].ref = ref;
dvander@16
   581
    break;
dvander@16
   582
}
dvander@16
   583
dvander@14
   584
case OP_GETREF_I:
dvander@14
   585
{
dvander@14
   586
    top.sp[-1].i32 = top.sp[-1].ref->getInt();
dvander@14
   587
    break;
dvander@14
   588
}
dvander@14
   589
dvander@14
   590
case OP_SETREF_I:
dvander@14
   591
{
dvander@14
   592
    top.sp[-2].ref->setInt(top.sp[-1].i32);
dvander@14
   593
    top.sp[-2].i32 = top.sp[-1].i32;
dvander@23
   594
    top.sp--;
dvander@14
   595
    break;
dvander@14
   596
}
dvander@14
   597
dvander@14
   598
case OP_GETREF_F:
dvander@14
   599
{
dvander@14
   600
    top.sp[-1].f = top.sp[-1].ref->getFloat();
dvander@14
   601
    break;
dvander@14
   602
}
dvander@14
   603
dvander@14
   604
case OP_SETREF_F:
dvander@14
   605
{
dvander@14
   606
    top.sp[-2].ref->setFloat(top.sp[-1].f);
dvander@14
   607
    top.sp[-2].f = top.sp[-1].f;
dvander@14
   608
    break;
dvander@14
   609
}
dvander@14
   610
dvander@21
   611
case OP_OBJECT:
dvander@21
   612
{
dvander@47
   613
    top.sp->obj = top.fp->code()->object(READ_UINT32(top.pc));
dvander@21
   614
    top.sp++;
dvander@21
   615
    break;
dvander@21
   616
}
dvander@21
   617
dvander@21
   618
case OP_ARRAYCOPY:
dvander@21
   619
{
dvander@21
   620
    // Note for this assignment opcode, we return the left-hand side, not the
dvander@21
   621
    // right, since in this case the result of the expression could be different.
dvander@69
   622
    if (!CopyArray(zone, top.sp[-2].array, top.sp[-1].array))
dvander@69
   623
        goto error;
dvander@21
   624
    top.sp--;
dvander@21
   625
    break;
dvander@21
   626
}
dvander@21
   627
dvander@22
   628
case OP_DUP:
dvander@22
   629
{
dvander@23
   630
    top.sp++;
dvander@23
   631
    top.sp[-1] = top.sp[-2];
dvander@22
   632
    break;
dvander@22
   633
}
dvander@22
   634
dvander@22
   635
case OP_DUP2:
dvander@22
   636
{
dvander@23
   637
    top.sp += 2;
dvander@23
   638
    top.sp[-2] = top.sp[-4];
dvander@23
   639
    top.sp[-1] = top.sp[-3];
dvander@23
   640
    break;
dvander@23
   641
}
dvander@23
   642
dvander@23
   643
case OP_SWAP:
dvander@23
   644
{
dvander@23
   645
    LocalSlot slot = top.sp[-2];
dvander@23
   646
    top.sp[-2] = top.sp[-1];
dvander@23
   647
    top.sp[-1] = slot;
dvander@23
   648
    break;
dvander@23
   649
}
dvander@23
   650
dvander@23
   651
case OP_ROLL3:
dvander@23
   652
{
dvander@23
   653
    LocalSlot slot = top.sp[-3];
dvander@23
   654
    top.sp[-3] = top.sp[-2];
dvander@23
   655
    top.sp[-2] = top.sp[-1];
dvander@23
   656
    top.sp[-1] = slot;
dvander@23
   657
    break;
dvander@23
   658
}
dvander@23
   659
dvander@23
   660
case OP_PICK2:
dvander@23
   661
{
dvander@23
   662
    top.sp++;
dvander@23
   663
    top.sp[-1] = top.sp[-3];
dvander@23
   664
    break;
dvander@23
   665
}
dvander@23
   666
dvander@23
   667
case OP_PICK3:
dvander@23
   668
{
dvander@23
   669
    top.sp++;
dvander@23
   670
    top.sp[-1] = top.sp[-4];
dvander@22
   671
    break;
dvander@22
   672
}
dvander@22
   673
dvander@68
   674
case OP_CALLNATIVE:
dvander@68
   675
{
dvander@68
   676
    unsigned index = READ_UINT32(top.pc);
dvander@68
   677
    unsigned argc = READ_UINT32(top.pc + 4);
dvander@68
   678
dvander@68
   679
    Local<Native> native(zone, Native::cast(top.fp->code()->module()->natives()->at(index)));
dvander@68
   680
    if (!native->function()) {
dvander@69
   681
        zone->reportError(Message_NativeNotBound, native->name()->chars());
dvander@69
   682
        goto error;
dvander@68
   683
    }
dvander@68
   684
dvander@68
   685
    int result;
dvander@68
   686
    void *nativeIdentity = top.fp->code()->module()->nativeIdentity();
dvander@69
   687
    if (!InvokeNative(zone, native, nativeIdentity, top.sp, argc, &result))
dvander@69
   688
        goto error;
dvander@68
   689
dvander@68
   690
    top.sp -= argc;
dvander@68
   691
    PUSH_I32(top, result);
dvander@68
   692
    break;
dvander@68
   693
}
dvander@68
   694
dvander@73
   695
case OP_MODULE:
dvander@73
   696
{
dvander@73
   697
    top.sp++;
dvander@73
   698
    top.sp[-1].module = top.fp->code()->module();
dvander@73
   699
    break;
dvander@73
   700
}
dvander@73
   701
dvander@73
   702
case OP_GETMODULE_FN:
dvander@73
   703
{
dvander@73
   704
    top.sp[-1].fun = top.sp[-1].module->getFunction(READ_UINT32(top.pc));
dvander@73
   705
    break;
dvander@73
   706
}
dvander@73
   707
dvander@0
   708
default:
dvander@0
   709
    assert(false);
dvander@0
   710
    return false;
dvander@0
   711
dvander@0
   712
        }
dvander@0
   713
dvander@0
   714
        top.pc += OpcodeInfo[op].length;
dvander@0
   715
    }
dvander@0
   716
dvander@69
   717
done:
dvander@0
   718
    return true;
dvander@69
   719
dvander@69
   720
error:
dvander@69
   721
    // Unwind frames until we can continue.
dvander@69
   722
    while (top.fp != entryFrame)
dvander@69
   723
        zone->stack().popInlineFrame();
dvander@69
   724
    return false;
dvander@0
   725
}