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