src/Interpreter.cpp
author Asher Baker <asherkin@gmail.com>
Mon Jun 10 01:04:43 2013 +0100 (2013-06-10)
changeset 263 ba85a47ee414
parent 256 3c184218462d
permissions -rw-r--r--
Normalise line endings.
asherkin@263
     1
/* vim: set ts=4 sw=4 tw=99 et:
asherkin@263
     2
 *
asherkin@263
     3
 * Copyright (C) 2012 David Anderson
asherkin@263
     4
 *
asherkin@263
     5
 * This file is part of JITCraft.
asherkin@263
     6
 *
asherkin@263
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
asherkin@263
     8
 * the terms of the GNU General Public License as published by the Free
asherkin@263
     9
 * Software Foundation, either version 3 of the License, or (at your option)
asherkin@263
    10
 * any later version.
asherkin@263
    11
 * 
asherkin@263
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
asherkin@263
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
asherkin@263
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
asherkin@263
    15
 *
asherkin@263
    16
 * You should have received a copy of the GNU General Public License along with
asherkin@263
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
asherkin@263
    18
 */
asherkin@263
    19
#include <string.h>
asherkin@263
    20
#include "Interpreter.h"
asherkin@263
    21
#include "Modules.h"
asherkin@263
    22
#include "Zone.h"
asherkin@263
    23
#include "Types.h"
asherkin@263
    24
#include "Array.h"
asherkin@263
    25
#include "Reference.h"
asherkin@263
    26
#include "Strings.h"
asherkin@263
    27
#include "Environments.h"
asherkin@263
    28
#include "Structures.h"
asherkin@263
    29
#include "NativeTable.h"
asherkin@263
    30
#include "Packages.h"
asherkin@263
    31
#include "Heap-inl.h"
asherkin@263
    32
asherkin@263
    33
using namespace ke;
asherkin@263
    34
asherkin@263
    35
#define PUSH_I32(top, value)    \
asherkin@263
    36
    do {                        \
asherkin@263
    37
        top.sp->i32 = value;    \
asherkin@263
    38
        top.sp++;               \
asherkin@263
    39
   } while (0)
asherkin@263
    40
asherkin@263
    41
#define PUSH_F(top, value)      \
asherkin@263
    42
    do {                        \
asherkin@263
    43
        top.sp->f = value;      \
asherkin@263
    44
        top.sp++;               \
asherkin@263
    45
   } while (0)
asherkin@263
    46
asherkin@263
    47
static inline int
asherkin@263
    48
POP_I32(Top &top)
asherkin@263
    49
{
asherkin@263
    50
    int value = top.sp[-1].i32;
asherkin@263
    51
    top.sp--;
asherkin@263
    52
    return value;
asherkin@263
    53
}
asherkin@263
    54
asherkin@263
    55
static inline float
asherkin@263
    56
POP_F(Top &top)
asherkin@263
    57
{
asherkin@263
    58
    float value = top.sp[-1].f;
asherkin@263
    59
    top.sp--;
asherkin@263
    60
    return value;
asherkin@263
    61
}
asherkin@263
    62
asherkin@263
    63
// Pawn's original semantics specify some kind of floor operation, so
asherkin@263
    64
// (8 / -3 == -3) and (-8 / 3 == -1). The SourcePawn 1 compiler (spcomp) uses
asherkin@263
    65
// the upstream algorithm when constant folding. However the SourcePawn 1 JIT
asherkin@263
    66
// does not. My guess is that Borja freaked out seeing the 13-instruction x86
asherkin@263
    67
// sequence necessary to get this functionality (I vaguely recall a thread
asherkin@263
    68
// where we discussed this with Mark Peter? But the ITB forums are gone...),
asherkin@263
    69
// and we just decided to break the damn thing. So SP1 was inconsistent, but
asherkin@263
    70
// we are not. And for completeness, we assert that the C compiler does the
asherkin@263
    71
// right thing, since C89 leaves it unspecified.
asherkin@263
    72
STATIC_ASSERT(8 / -3 == -2);
asherkin@263
    73
STATIC_ASSERT(-8 / 3 == -2);
asherkin@263
    74
asherkin@263
    75
static inline bool
asherkin@263
    76
PushNewRef(Zone *zone, Top &top, void *location, Heap::Tenure tenure)
asherkin@263
    77
{
asherkin@263
    78
    Reference *ref = Reference::NewStack(zone, location, tenure);
asherkin@263
    79
    if (!ref)
asherkin@263
    80
        return false;
asherkin@263
    81
    top.sp->ref = ref;
asherkin@263
    82
    top.sp++;
asherkin@263
    83
    return true;
asherkin@263
    84
}
asherkin@263
    85
asherkin@263
    86
static void
asherkin@263
    87
GetElement(Array *array, int index, LocalSlot *vp)
asherkin@263
    88
{
asherkin@263
    89
    if (array->type()->contained()->isTraceable()) {
asherkin@263
    90
        vp->obj = array->readObject(index);
asherkin@263
    91
        return;
asherkin@263
    92
    }
asherkin@263
    93
asherkin@263
    94
    switch (array->type()->contained()->pod()) {
asherkin@263
    95
      case PrimitiveType_Float:
asherkin@263
    96
        vp->f = array->readFloat(index);
asherkin@263
    97
        break;
asherkin@263
    98
asherkin@263
    99
      case PrimitiveType_Char:
asherkin@263
   100
        vp->i32 = array->readChar(index);
asherkin@263
   101
        break;
asherkin@263
   102
asherkin@263
   103
      default:
asherkin@263
   104
        assert(array->type()->contained()->pod() == PrimitiveType_Int32);
asherkin@263
   105
        vp->i32 = array->readInt32(index);
asherkin@263
   106
        break;
asherkin@263
   107
    }
asherkin@263
   108
}
asherkin@263
   109
asherkin@263
   110
static void
asherkin@263
   111
SetElement(Zone *zone, Array *array, int index, const LocalSlot &v)
asherkin@263
   112
{
asherkin@263
   113
    if (array->type()->contained()->isTraceable()) {
asherkin@263
   114
        array->writeObject(zone, index, v.obj);
asherkin@263
   115
        return;
asherkin@263
   116
    }
asherkin@263
   117
asherkin@263
   118
    switch (array->type()->contained()->pod()) {
asherkin@263
   119
      case PrimitiveType_Float:
asherkin@263
   120
        array->writeFloat(index, v.f);
asherkin@263
   121
        break;
asherkin@263
   122
asherkin@263
   123
      case PrimitiveType_Char:
asherkin@263
   124
        array->writeChar(index, v.i32);
asherkin@263
   125
        break;
asherkin@263
   126
asherkin@263
   127
      default:
asherkin@263
   128
        assert(array->type()->contained()->pod() == PrimitiveType_Int32);
asherkin@263
   129
        array->writeInt32(index, v.i32);
asherkin@263
   130
        break;
asherkin@263
   131
    }
asherkin@263
   132
}
asherkin@263
   133
asherkin@263
   134
static void
asherkin@263
   135
FetchField(Struct *obj, Descriptor *desc, LocalSlot *vp)
asherkin@263
   136
{
asherkin@263
   137
    // :TODO: assert no GC.
asherkin@263
   138
    if (desc->type()->isTraceable()) {
asherkin@263
   139
        vp->obj = obj->get<Object *>(desc);
asherkin@263
   140
        return;
asherkin@263
   141
    }
asherkin@263
   142
asherkin@263
   143
    switch (desc->type()->pod()) {
asherkin@263
   144
      case PrimitiveType_Float:
asherkin@263
   145
        vp->f = obj->get<float>(desc);
asherkin@263
   146
        break;
asherkin@263
   147
asherkin@263
   148
      default:
asherkin@263
   149
        assert(desc->type()->pod() == PrimitiveType_Int32);
asherkin@263
   150
        vp->i32 = obj->get<int>(desc);
asherkin@263
   151
        break;
asherkin@263
   152
    }
asherkin@263
   153
}
asherkin@263
   154
asherkin@263
   155
static void
asherkin@263
   156
GetField(Struct *obj, unsigned index, LocalSlot *vp)
asherkin@263
   157
{
asherkin@263
   158
    StructType *type = StructType::cast(obj->map()->type());
asherkin@263
   159
    Descriptor *desc = Descriptor::cast(type->fields()->at(index));
asherkin@263
   160
    FetchField(obj, desc, vp);
asherkin@263
   161
}
asherkin@263
   162
asherkin@263
   163
static void
asherkin@263
   164
GetGlobal(Zone *zone, Handle<Struct> obj, Handle<String> name, LocalSlot *vp)
asherkin@263
   165
{
asherkin@263
   166
    Local<StructType> type(zone, StructType::cast(obj->map()->type()));
asherkin@263
   167
    Local<Descriptor> desc(zone, type->lookupField(name, NULL));
asherkin@263
   168
    FetchField(obj, desc, vp);
asherkin@263
   169
}
asherkin@263
   170
asherkin@263
   171
static void
asherkin@263
   172
StoreField(Zone *zone, Struct *obj, Descriptor *desc, const LocalSlot &v)
asherkin@263
   173
{
asherkin@263
   174
    // :TODO: assert no GC.
asherkin@263
   175
    if (desc->type()->isTraceable()) {
asherkin@263
   176
        obj->set(zone, desc, v.obj);
asherkin@263
   177
        return;
asherkin@263
   178
    }
asherkin@263
   179
asherkin@263
   180
    switch (desc->type()->pod()) {
asherkin@263
   181
      case PrimitiveType_Float:
asherkin@263
   182
        obj->set<float>(desc, v.f);
asherkin@263
   183
        break;
asherkin@263
   184
asherkin@263
   185
      default:
asherkin@263
   186
        assert(desc->type()->pod() == PrimitiveType_Int32);
asherkin@263
   187
        obj->set<int>(desc, v.i32);
asherkin@263
   188
        break;
asherkin@263
   189
    }
asherkin@263
   190
}
asherkin@263
   191
asherkin@263
   192
static void
asherkin@263
   193
SetField(Zone *zone, Struct *obj, unsigned index, const LocalSlot &v)
asherkin@263
   194
{
asherkin@263
   195
    StructType *type = StructType::cast(obj->map()->type());
asherkin@263
   196
    Descriptor *desc = Descriptor::cast(type->fields()->at(index));
asherkin@263
   197
    StoreField(zone, obj, desc, v);
asherkin@263
   198
}
asherkin@263
   199
asherkin@263
   200
static void
asherkin@263
   201
SetGlobal(Zone *zone, Handle<Struct> obj, Handle<String> name, LocalSlot &v)
asherkin@263
   202
{
asherkin@263
   203
    Local<StructType> type(zone, StructType::cast(obj->map()->type()));
asherkin@263
   204
    Local<Descriptor> desc(zone, type->lookupField(name, NULL));
asherkin@263
   205
    StoreField(zone, obj, desc, v);
asherkin@263
   206
}
asherkin@263
   207
asherkin@263
   208
static bool
asherkin@263
   209
InvokeNative(Zone *zone, Handle<Native> native, void *identity, LocalSlot *args, unsigned argc,
asherkin@263
   210
             int *result)
asherkin@263
   211
{
asherkin@263
   212
    NativeArgs guard;
asherkin@263
   213
asherkin@263
   214
    void *address = zone->nativeTable()->address(native->index());
asherkin@263
   215
    if (!address) {
asherkin@263
   216
        Local<String> name(zone, zone->nativeTable()->name(native->index()));
asherkin@263
   217
        zone->reportError(Message_NativeNotBound, name->chars());
asherkin@263
   218
        return false;
asherkin@263
   219
    }
asherkin@263
   220
asherkin@263
   221
    if (!zone->stack().pushNativeFrame(native, guard, argc + 1))
asherkin@263
   222
        return false;
asherkin@263
   223
asherkin@263
   224
    intptr_t *cells = guard.args();
asherkin@263
   225
asherkin@263
   226
    // params[0] == argc, in ISPE
asherkin@263
   227
    cells[0] = argc;
asherkin@263
   228
asherkin@263
   229
    // Pass the formal arguments.
asherkin@263
   230
    Local<FunctionType> type(zone, native->type());
asherkin@263
   231
    Local<Type> param(zone);
asherkin@263
   232
    for (unsigned i = 0; i < type->parameters()->length(); i++) {
asherkin@263
   233
        param = type->parameterAt(i);
asherkin@263
   234
        
asherkin@263
   235
        // For floats, we rely on the aliasing of |i32| and |f|.
asherkin@263
   236
        LocalSlot &arg = args[-int(i) - 1];
asherkin@263
   237
        if (param->isInt32() || param->isFloat()) {
asherkin@263
   238
            cells[i + 1] = arg.i32;
asherkin@263
   239
        } else if (param->isReference()) {
asherkin@263
   240
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
asherkin@263
   241
        } else {
asherkin@263
   242
            assert(param->isArray());
asherkin@263
   243
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->bytes());
asherkin@263
   244
        }
asherkin@263
   245
    }
asherkin@263
   246
asherkin@263
   247
    // For variadic arguments, the compiler left either arrays or references.
asherkin@263
   248
    for (unsigned i = type->parameters()->length(); i < argc; i++) {
asherkin@263
   249
        LocalSlot &arg = args[-int(i) - 1];
asherkin@263
   250
asherkin@263
   251
        if (arg.obj->is(MapKind_Reference)) {
asherkin@263
   252
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
asherkin@263
   253
        } else {
asherkin@263
   254
            assert(arg.obj->is(MapKind_Array));
asherkin@263
   255
            cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->bytes());
asherkin@263
   256
        }
asherkin@263
   257
    }
asherkin@263
   258
asherkin@263
   259
    typedef intptr_t (*INVOKE)(void *, intptr_t *);
asherkin@263
   260
    INVOKE invoke = (INVOKE)address;
asherkin@263
   261
    *result = invoke(identity, cells);
asherkin@263
   262
asherkin@263
   263
    return !zone->hasPendingException();
asherkin@263
   264
}
asherkin@263
   265
asherkin@263
   266
bool
asherkin@263
   267
ke::Interpret(Zone *zone, Frame *entryFrame, LocalSlot *result)
asherkin@263
   268
{
asherkin@263
   269
    Top &top = *zone->stack().top();
asherkin@263
   270
    if (!entryFrame)
asherkin@263
   271
        entryFrame = top.fp;
asherkin@263
   272
asherkin@263
   273
    LocalSlot *locals = entryFrame->locals();
asherkin@263
   274
asherkin@263
   275
    for (;;) {
asherkin@263
   276
        Opcode op = Opcode(*top.pc);
asherkin@263
   277
asherkin@263
   278
        if (OpcodeInfo[op].nuses > 0)
asherkin@263
   279
            assert(top.sp - OpcodeInfo[op].nuses >= top.fp->stackBase());
asherkin@263
   280
asherkin@263
   281
        switch (op) {
asherkin@263
   282
asherkin@263
   283
case OP_NOP:
asherkin@263
   284
    break;
asherkin@263
   285
asherkin@263
   286
case OP_INT:
asherkin@263
   287
    PUSH_I32(top, READ_INT32(top.pc));
asherkin@263
   288
    break;
asherkin@263
   289
asherkin@263
   290
case OP_FLOAT:
asherkin@263
   291
    PUSH_F(top, READ_FLOAT(top.pc));
asherkin@263
   292
    break;
asherkin@263
   293
asherkin@263
   294
case OP_RETURN:
asherkin@263
   295
case OP_RETURNVOID:
asherkin@263
   296
case OP_STOP:
asherkin@263
   297
{
asherkin@263
   298
    if (op == OP_RETURN)
asherkin@263
   299
        *result = *--top.sp;
asherkin@263
   300
asherkin@263
   301
    if (top.fp == entryFrame)
asherkin@263
   302
        goto done;
asherkin@263
   303
asherkin@263
   304
    // This must not GC.
asherkin@263
   305
    zone->stack().popInlineFrame();
asherkin@263
   306
    locals = top.fp->locals();
asherkin@263
   307
asherkin@263
   308
    if (op == OP_RETURN)
asherkin@263
   309
        *top.sp++ = *result;
asherkin@263
   310
asherkin@263
   311
    top.pc += OpcodeInfo[*top.pc].length;
asherkin@263
   312
    continue;
asherkin@263
   313
}
asherkin@263
   314
asherkin@263
   315
case OP_POP:
asherkin@263
   316
{
asherkin@263
   317
    top.sp--;
asherkin@263
   318
    break;
asherkin@263
   319
}
asherkin@263
   320
asherkin@263
   321
case OP_JT:
asherkin@263
   322
{
asherkin@263
   323
    int value = POP_I32(top);
asherkin@263
   324
    if (value) {
asherkin@263
   325
        top.pc += READ_INT32(top.pc);
asherkin@263
   326
        continue;
asherkin@263
   327
    }
asherkin@263
   328
    break;
asherkin@263
   329
}
asherkin@263
   330
asherkin@263
   331
case OP_JF:
asherkin@263
   332
{
asherkin@263
   333
    int value = POP_I32(top);
asherkin@263
   334
    if (!value) {
asherkin@263
   335
        top.pc += READ_INT32(top.pc);
asherkin@263
   336
        continue;
asherkin@263
   337
    }
asherkin@263
   338
    break;
asherkin@263
   339
}
asherkin@263
   340
asherkin@263
   341
case OP_JUMP:
asherkin@263
   342
{
asherkin@263
   343
    top.pc += READ_INT32(top.pc);
asherkin@263
   344
    continue;
asherkin@263
   345
}
asherkin@263
   346
asherkin@263
   347
case OP_BREAK:
asherkin@263
   348
case OP_CONTINUE:
asherkin@263
   349
{
asherkin@263
   350
    top.fp->leaveLoop(zone);
asherkin@263
   351
    top.pc += READ_INT32(top.pc);
asherkin@263
   352
    continue;
asherkin@263
   353
}
asherkin@263
   354
asherkin@263
   355
case OP_GETLOCAL:
asherkin@263
   356
{
asherkin@263
   357
    unsigned slot = READ_UINT32(top.pc);
asherkin@263
   358
    assert(slot < top.fp->code()->nlocals());
asherkin@263
   359
    *top.sp++ = locals[slot];
asherkin@263
   360
    break;
asherkin@263
   361
}
asherkin@263
   362
asherkin@263
   363
case OP_SETLOCAL:
asherkin@263
   364
{
asherkin@263
   365
    unsigned slot = READ_UINT32(top.pc);
asherkin@263
   366
    assert(slot < top.fp->code()->nlocals());
asherkin@263
   367
    locals[slot] = top.sp[-1];
asherkin@263
   368
    break;
asherkin@263
   369
}
asherkin@263
   370
asherkin@263
   371
case OP_ADD:
asherkin@263
   372
{
asherkin@263
   373
    top.sp[-2].i32 = top.sp[-2].i32 + top.sp[-1].i32;
asherkin@263
   374
    top.sp--;
asherkin@263
   375
    break;
asherkin@263
   376
}
asherkin@263
   377
asherkin@263
   378
case OP_SUB:
asherkin@263
   379
{
asherkin@263
   380
    top.sp[-2].i32 = top.sp[-2].i32 - top.sp[-1].i32;
asherkin@263
   381
    top.sp--;
asherkin@263
   382
    break;
asherkin@263
   383
}
asherkin@263
   384
asherkin@263
   385
case OP_MUL:
asherkin@263
   386
{
asherkin@263
   387
    top.sp[-2].i32 = top.sp[-2].i32 * top.sp[-1].i32;
asherkin@263
   388
    top.sp--;
asherkin@263
   389
    break;
asherkin@263
   390
}
asherkin@263
   391
asherkin@263
   392
case OP_DIV:
asherkin@263
   393
{
asherkin@263
   394
    if (top.sp[-1].i32 == 0) {
asherkin@263
   395
        zone->reportError(Message_IntegerDivideByZero);
asherkin@263
   396
        goto error;
asherkin@263
   397
    }
asherkin@263
   398
    top.sp[-2].i32 = top.sp[-2].i32 / top.sp[-1].i32;
asherkin@263
   399
    top.sp--;
asherkin@263
   400
    break;
asherkin@263
   401
}
asherkin@263
   402
asherkin@263
   403
case OP_MOD:
asherkin@263
   404
{
asherkin@263
   405
    if (top.sp[-1].i32 == 0) {
asherkin@263
   406
        zone->reportError(Message_IntegerDivideByZero);
asherkin@263
   407
        goto error;
asherkin@263
   408
    }
asherkin@263
   409
    top.sp[-2].i32 = top.sp[-2].i32 % top.sp[-1].i32;
asherkin@263
   410
    top.sp--;
asherkin@263
   411
    break;
asherkin@263
   412
}
asherkin@263
   413
asherkin@263
   414
case OP_LT:
asherkin@263
   415
{
asherkin@263
   416
    top.sp[-2].i32 = top.sp[-2].i32 < top.sp[-1].i32;
asherkin@263
   417
    top.sp--;
asherkin@263
   418
    break;
asherkin@263
   419
}
asherkin@263
   420
asherkin@263
   421
case OP_LE:
asherkin@263
   422
{
asherkin@263
   423
    top.sp[-2].i32 = top.sp[-2].i32 <= top.sp[-1].i32;
asherkin@263
   424
    top.sp--;
asherkin@263
   425
    break;
asherkin@263
   426
}
asherkin@263
   427
asherkin@263
   428
case OP_GT:
asherkin@263
   429
{
asherkin@263
   430
    top.sp[-2].i32 = top.sp[-2].i32 > top.sp[-1].i32;
asherkin@263
   431
    top.sp--;
asherkin@263
   432
    break;
asherkin@263
   433
}
asherkin@263
   434
asherkin@263
   435
case OP_GE:
asherkin@263
   436
{
asherkin@263
   437
    top.sp[-2].i32 = top.sp[-2].i32 >= top.sp[-1].i32;
asherkin@263
   438
    top.sp--;
asherkin@263
   439
    break;
asherkin@263
   440
}
asherkin@263
   441
asherkin@263
   442
case OP_EQ:
asherkin@263
   443
{
asherkin@263
   444
    top.sp[-2].i32 = (top.sp[-2].i32 == top.sp[-1].i32);
asherkin@263
   445
    top.sp--;
asherkin@263
   446
    break;
asherkin@263
   447
}
asherkin@263
   448
asherkin@263
   449
case OP_NE:
asherkin@263
   450
{
asherkin@263
   451
    top.sp[-2].i32 = (top.sp[-2].i32 != top.sp[-1].i32);
asherkin@263
   452
    top.sp--;
asherkin@263
   453
    break;
asherkin@263
   454
}
asherkin@263
   455
asherkin@263
   456
case OP_ADD_F:
asherkin@263
   457
{
asherkin@263
   458
    top.sp[-2].f = top.sp[-2].f + top.sp[-1].f;
asherkin@263
   459
    top.sp--;
asherkin@263
   460
    break;
asherkin@263
   461
}
asherkin@263
   462
asherkin@263
   463
case OP_SUB_F:
asherkin@263
   464
{
asherkin@263
   465
    top.sp[-2].f = top.sp[-2].f - top.sp[-1].f;
asherkin@263
   466
    top.sp--;
asherkin@263
   467
    break;
asherkin@263
   468
}
asherkin@263
   469
asherkin@263
   470
case OP_MUL_F:
asherkin@263
   471
{
asherkin@263
   472
    top.sp[-2].f = top.sp[-2].f * top.sp[-1].f;
asherkin@263
   473
    top.sp--;
asherkin@263
   474
    break;
asherkin@263
   475
}
asherkin@263
   476
asherkin@263
   477
case OP_DIV_F:
asherkin@263
   478
{
asherkin@263
   479
    top.sp[-2].f = top.sp[-2].f / top.sp[-1].f;
asherkin@263
   480
    top.sp--;
asherkin@263
   481
    break;
asherkin@263
   482
}
asherkin@263
   483
asherkin@263
   484
case OP_LT_F:
asherkin@263
   485
{
asherkin@263
   486
    top.sp[-2].f = top.sp[-2].f < top.sp[-1].f;
asherkin@263
   487
    top.sp--;
asherkin@263
   488
    break;
asherkin@263
   489
}
asherkin@263
   490
asherkin@263
   491
case OP_LE_F:
asherkin@263
   492
{
asherkin@263
   493
    top.sp[-2].f = top.sp[-2].f <= top.sp[-1].f;
asherkin@263
   494
    top.sp--;
asherkin@263
   495
    break;
asherkin@263
   496
}
asherkin@263
   497
asherkin@263
   498
case OP_GT_F:
asherkin@263
   499
{
asherkin@263
   500
    top.sp[-2].f = top.sp[-2].f > top.sp[-1].f;
asherkin@263
   501
    top.sp--;
asherkin@263
   502
    break;
asherkin@263
   503
}
asherkin@263
   504
asherkin@263
   505
case OP_GE_F:
asherkin@263
   506
{
asherkin@263
   507
    top.sp[-2].f = top.sp[-2].f >= top.sp[-1].f;
asherkin@263
   508
    top.sp--;
asherkin@263
   509
    break;
asherkin@263
   510
}
asherkin@263
   511
asherkin@263
   512
case OP_EQ_F:
asherkin@263
   513
{
asherkin@263
   514
    top.sp[-2].i32 = (top.sp[-2].f == top.sp[-1].f);
asherkin@263
   515
    top.sp--;
asherkin@263
   516
    break;
asherkin@263
   517
}
asherkin@263
   518
asherkin@263
   519
case OP_NE_F:
asherkin@263
   520
{
asherkin@263
   521
    top.sp[-2].i32 = (top.sp[-2].f != top.sp[-1].f);
asherkin@263
   522
    top.sp--;
asherkin@263
   523
    break;
asherkin@263
   524
}
asherkin@263
   525
asherkin@263
   526
case OP_SHL:
asherkin@263
   527
{
asherkin@263
   528
    top.sp[-2].i32 = top.sp[-2].i32 << top.sp[-1].i32;
asherkin@263
   529
    top.sp--;
asherkin@263
   530
    break;
asherkin@263
   531
}
asherkin@263
   532
asherkin@263
   533
case OP_SHR:
asherkin@263
   534
{
asherkin@263
   535
    top.sp[-2].i32 = top.sp[-2].i32 >> top.sp[-1].i32;
asherkin@263
   536
    top.sp--;
asherkin@263
   537
    break;
asherkin@263
   538
}
asherkin@263
   539
asherkin@263
   540
case OP_USHR:
asherkin@263
   541
{
asherkin@263
   542
    top.sp[-2].i32 = unsigned(top.sp[-2].i32) >> unsigned(top.sp[-1].i32);
asherkin@263
   543
    top.sp--;
asherkin@263
   544
    break;
asherkin@263
   545
}
asherkin@263
   546
asherkin@263
   547
case OP_BITAND:
asherkin@263
   548
{
asherkin@263
   549
    top.sp[-2].i32 = top.sp[-2].i32 & top.sp[-1].i32;
asherkin@263
   550
    top.sp--;
asherkin@263
   551
    break;
asherkin@263
   552
}
asherkin@263
   553
asherkin@263
   554
case OP_BITOR:
asherkin@263
   555
{
asherkin@263
   556
    top.sp[-2].i32 = top.sp[-2].i32 | top.sp[-1].i32;
asherkin@263
   557
    top.sp--;
asherkin@263
   558
    break;
asherkin@263
   559
}
asherkin@263
   560
asherkin@263
   561
case OP_BITXOR:
asherkin@263
   562
{
asherkin@263
   563
    top.sp[-2].i32 = top.sp[-2].i32 ^ top.sp[-1].i32;
asherkin@263
   564
    top.sp--;
asherkin@263
   565
    break;
asherkin@263
   566
}
asherkin@263
   567
asherkin@263
   568
case OP_BITNOT:
asherkin@263
   569
{
asherkin@263
   570
    top.sp[-1].i32 = ~top.sp[-1].i32;
asherkin@263
   571
    break;
asherkin@263
   572
}
asherkin@263
   573
asherkin@263
   574
case OP_NOT:
asherkin@263
   575
{
asherkin@263
   576
    top.sp[-1].i32 = top.sp[-1].i32 ? 0 : 1;
asherkin@263
   577
    break;
asherkin@263
   578
}
asherkin@263
   579
asherkin@263
   580
case OP_NOT_F:
asherkin@263
   581
{
asherkin@263
   582
    top.sp[-1].i32 = top.sp[-1].f ? 0 : 1;
asherkin@263
   583
    break;
asherkin@263
   584
}
asherkin@263
   585
asherkin@263
   586
case OP_NEG:
asherkin@263
   587
{
asherkin@263
   588
    top.sp[-1].i32 = -top.sp[-1].i32;
asherkin@263
   589
    break;
asherkin@263
   590
}
asherkin@263
   591
asherkin@263
   592
case OP_NEG_F:
asherkin@263
   593
{
asherkin@263
   594
    top.sp[-1].f = -top.sp[-1].f;
asherkin@263
   595
    break;
asherkin@263
   596
}
asherkin@263
   597
asherkin@263
   598
case OP_CALL:
asherkin@263
   599
{
asherkin@263
   600
    Local<Function> newFun(zone, Function::cast(top.sp[-1].obj));
asherkin@263
   601
    top.sp--;
asherkin@263
   602
asherkin@263
   603
    if (!zone->stack().pushInlineFrame(newFun))
asherkin@263
   604
        goto error;
asherkin@263
   605
asherkin@263
   606
    locals = top.fp->locals();
asherkin@263
   607
    continue;
asherkin@263
   608
}
asherkin@263
   609
asherkin@263
   610
case OP_GETARG:
asherkin@263
   611
{
asherkin@263
   612
    unsigned slot = READ_UINT32(top.pc);
asherkin@263
   613
    *top.sp++ = top.fp->arg(slot);
asherkin@263
   614
    break;
asherkin@263
   615
}
asherkin@263
   616
asherkin@263
   617
case OP_SETARG:
asherkin@263
   618
{
asherkin@263
   619
    unsigned slot = READ_UINT32(top.pc);
asherkin@263
   620
    top.fp->arg(slot) = top.sp[-1];
asherkin@263
   621
    break;
asherkin@263
   622
}
asherkin@263
   623
asherkin@263
   624
case OP_GETELEM:
asherkin@263
   625
{
asherkin@263
   626
    Array *array = Array::cast(top.sp[-2].obj);
asherkin@263
   627
    int index = top.sp[-1].i32;
asherkin@263
   628
asherkin@263
   629
    if (index < 0 || unsigned(index) >= array->length()) {
asherkin@263
   630
        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
asherkin@263
   631
        goto error;
asherkin@263
   632
    }
asherkin@263
   633
asherkin@263
   634
    GetElement(array, index, &top.sp[-2]);
asherkin@263
   635
    top.sp--;
asherkin@263
   636
    break;
asherkin@263
   637
}
asherkin@263
   638
asherkin@263
   639
case OP_SETELEM:
asherkin@263
   640
{
asherkin@263
   641
    Array *array = Array::cast(top.sp[-3].obj);
asherkin@263
   642
    int index = top.sp[-2].i32;
asherkin@263
   643
asherkin@263
   644
    if (index < 0 || unsigned(index) >= array->length()) {
asherkin@263
   645
        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
asherkin@263
   646
        goto error;
asherkin@263
   647
    }
asherkin@263
   648
asherkin@263
   649
    SetElement(zone, array, index, top.sp[-1]);
asherkin@263
   650
    top.sp[-3] = top.sp[-1];
asherkin@263
   651
    top.sp -= 2;
asherkin@263
   652
    break;
asherkin@263
   653
}
asherkin@263
   654
asherkin@263
   655
case OP_CVT_I2F:
asherkin@263
   656
{
asherkin@263
   657
    int ival = POP_I32(top);
asherkin@263
   658
    float fval = (float)ival;
asherkin@263
   659
    PUSH_F(top, fval);
asherkin@263
   660
    break;
asherkin@263
   661
}
asherkin@263
   662
asherkin@263
   663
case OP_CVT_I2B:
asherkin@263
   664
{
asherkin@263
   665
    top.sp[-1].i32 = !!top.sp[-1].i32;
asherkin@263
   666
    break;
asherkin@263
   667
}
asherkin@263
   668
asherkin@263
   669
case OP_DUPARRAY:
asherkin@263
   670
{
asherkin@263
   671
    Local<Array> src(zone, Array::cast(top.sp[-1].obj));
asherkin@263
   672
    top.sp[-1].obj = Array::DeepCopy(zone, src, Heap::Tenure_Default);
asherkin@263
   673
    if (!top.sp[-1].obj)
asherkin@263
   674
        goto error;
asherkin@263
   675
    break;
asherkin@263
   676
}
asherkin@263
   677
asherkin@263
   678
case OP_NEWFIXED:
asherkin@263
   679
{
asherkin@263
   680
    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
asherkin@263
   681
    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
asherkin@263
   682
    Array *array = Array::NewFixed(zone, map, tenure);
asherkin@263
   683
    if (!array)
asherkin@263
   684
        goto error;
asherkin@263
   685
    top.sp->obj = array;
asherkin@263
   686
    top.sp++;
asherkin@263
   687
    break;
asherkin@263
   688
}
asherkin@263
   689
asherkin@263
   690
case OP_NEWEMPTY:
asherkin@263
   691
{
asherkin@263
   692
    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
asherkin@263
   693
    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
asherkin@263
   694
    Array *array = Array::NewEmpty(zone, map, tenure);
asherkin@263
   695
    if (!array)
asherkin@263
   696
        goto error;
asherkin@263
   697
    top.sp->obj = array;
asherkin@263
   698
    top.sp++;
asherkin@263
   699
    break;
asherkin@263
   700
}
asherkin@263
   701
asherkin@263
   702
case OP_NEWSIZED:
asherkin@263
   703
{
asherkin@263
   704
    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
asherkin@263
   705
    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
asherkin@263
   706
    assert(map->type()->levels() < MAX_ARRAY_DEPTH);
asherkin@263
   707
asherkin@263
   708
    int dims[MAX_ARRAY_DEPTH];
asherkin@263
   709
    for (unsigned i = map->type()->levels() - 1; i < map->type()->levels(); i--)
asherkin@263
   710
        dims[i] = POP_I32(top);
asherkin@263
   711
asherkin@263
   712
    Array *array = Array::NewSized(zone, map, dims, tenure);
asherkin@263
   713
    if (!array)
asherkin@263
   714
        goto error;
asherkin@263
   715
    top.sp->obj = array;
asherkin@263
   716
    top.sp++;
asherkin@263
   717
    break;
asherkin@263
   718
}
asherkin@263
   719
asherkin@263
   720
case OP_NEWSTRUCT:
asherkin@263
   721
{
asherkin@263
   722
    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
asherkin@263
   723
    Local<StructMap> map(zone, StructMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
asherkin@263
   724
    top.sp->obj = Struct::New(zone, map, tenure);
asherkin@263
   725
    if (!top.sp->obj)
asherkin@263
   726
        goto error;
asherkin@263
   727
    top.sp++;
asherkin@263
   728
    break;
asherkin@263
   729
}
asherkin@263
   730
asherkin@263
   731
case OP_SAVELIFO:
asherkin@263
   732
{
asherkin@263
   733
    unsigned slot = READ_UINT32(top.pc);
asherkin@263
   734
    locals[slot].address = zone->heap().lifoPosition();
asherkin@263
   735
    break;
asherkin@263
   736
}
asherkin@263
   737
asherkin@263
   738
case OP_UNWINDLIFO:
asherkin@263
   739
{
asherkin@263
   740
    unsigned slot = READ_UINT32(top.pc);
asherkin@263
   741
    zone->heap().unwindLifo(locals[slot].address);
asherkin@263
   742
    break;
asherkin@263
   743
}
asherkin@263
   744
asherkin@263
   745
case OP_VARREF_LIFO:
asherkin@263
   746
{
asherkin@263
   747
    unsigned slot = READ_UINT32(top.pc);
asherkin@263
   748
    if (!PushNewRef(zone, top, &locals[slot], Heap::Tenure_Stack))
asherkin@263
   749
        goto error;
asherkin@263
   750
    break;
asherkin@263
   751
}
asherkin@263
   752
asherkin@263
   753
case OP_ARGREF_LIFO:
asherkin@263
   754
{
asherkin@263
   755
    unsigned slot = READ_UINT32(top.pc);
asherkin@263
   756
    if (!PushNewRef(zone, top, &top.fp->arg(slot), Heap::Tenure_Stack))
asherkin@263
   757
        goto error;
asherkin@263
   758
    break;
asherkin@263
   759
}
asherkin@263
   760
asherkin@263
   761
case OP_SLOTREF_LIFO:
asherkin@263
   762
{
asherkin@263
   763
    Reference *ref = Reference::NewStack(zone, top.sp[-1], Heap::Tenure_Stack);
asherkin@263
   764
    if (!ref)
asherkin@263
   765
        goto error;
asherkin@263
   766
    top.sp[-1].ref = ref;
asherkin@263
   767
    break;
asherkin@263
   768
}
asherkin@263
   769
asherkin@263
   770
case OP_GETREF_I:
asherkin@263
   771
{
asherkin@263
   772
    top.sp[-1].i32 = top.sp[-1].ref->getInt();
asherkin@263
   773
    break;
asherkin@263
   774
}
asherkin@263
   775
asherkin@263
   776
case OP_SETREF_I:
asherkin@263
   777
{
asherkin@263
   778
    top.sp[-2].ref->setInt(top.sp[-1].i32);
asherkin@263
   779
    top.sp[-2].i32 = top.sp[-1].i32;
asherkin@263
   780
    top.sp--;
asherkin@263
   781
    break;
asherkin@263
   782
}
asherkin@263
   783
asherkin@263
   784
case OP_GETREF_F:
asherkin@263
   785
{
asherkin@263
   786
    top.sp[-1].f = top.sp[-1].ref->getFloat();
asherkin@263
   787
    break;
asherkin@263
   788
}
asherkin@263
   789
asherkin@263
   790
case OP_SETREF_F:
asherkin@263
   791
{
asherkin@263
   792
    top.sp[-2].ref->setFloat(top.sp[-1].f);
asherkin@263
   793
    top.sp[-2].f = top.sp[-1].f;
asherkin@263
   794
    break;
asherkin@263
   795
}
asherkin@263
   796
asherkin@263
   797
case OP_OBJECT:
asherkin@263
   798
{
asherkin@263
   799
    top.sp->obj = top.fp->code()->object(READ_UINT32(top.pc));
asherkin@263
   800
    top.sp++;
asherkin@263
   801
    break;
asherkin@263
   802
}
asherkin@263
   803
asherkin@263
   804
case OP_COPYARRAY:
asherkin@263
   805
{
asherkin@263
   806
    // Note for this assignment opcode, we return the left-hand side, not the
asherkin@263
   807
    // right, since in this case the result of the expression could be different.
asherkin@263
   808
    Local<Array> left(zone, Array::cast(top.sp[-2].array));
asherkin@263
   809
    Local<Array> right(zone, Array::cast(top.sp[-1].array));
asherkin@263
   810
    if (!Array::ShallowCopy(zone, left, right))
asherkin@263
   811
        goto error;
asherkin@263
   812
    top.sp--;
asherkin@263
   813
    break;
asherkin@263
   814
}
asherkin@263
   815
asherkin@263
   816
case OP_DUP:
asherkin@263
   817
{
asherkin@263
   818
    top.sp++;
asherkin@263
   819
    top.sp[-1] = top.sp[-2];
asherkin@263
   820
    break;
asherkin@263
   821
}
asherkin@263
   822
asherkin@263
   823
case OP_DUP2:
asherkin@263
   824
{
asherkin@263
   825
    top.sp += 2;
asherkin@263
   826
    top.sp[-2] = top.sp[-4];
asherkin@263
   827
    top.sp[-1] = top.sp[-3];
asherkin@263
   828
    break;
asherkin@263
   829
}
asherkin@263
   830
asherkin@263
   831
case OP_SWAP:
asherkin@263
   832
{
asherkin@263
   833
    LocalSlot slot = top.sp[-2];
asherkin@263
   834
    top.sp[-2] = top.sp[-1];
asherkin@263
   835
    top.sp[-1] = slot;
asherkin@263
   836
    break;
asherkin@263
   837
}
asherkin@263
   838
asherkin@263
   839
case OP_ROLL3:
asherkin@263
   840
{
asherkin@263
   841
    LocalSlot slot = top.sp[-3];
asherkin@263
   842
    top.sp[-3] = top.sp[-2];
asherkin@263
   843
    top.sp[-2] = top.sp[-1];
asherkin@263
   844
    top.sp[-1] = slot;
asherkin@263
   845
    break;
asherkin@263
   846
}
asherkin@263
   847
asherkin@263
   848
case OP_PICK2:
asherkin@263
   849
{
asherkin@263
   850
    top.sp++;
asherkin@263
   851
    top.sp[-1] = top.sp[-3];
asherkin@263
   852
    break;
asherkin@263
   853
}
asherkin@263
   854
asherkin@263
   855
case OP_PICK3:
asherkin@263
   856
{
asherkin@263
   857
    top.sp++;
asherkin@263
   858
    top.sp[-1] = top.sp[-4];
asherkin@263
   859
    break;
asherkin@263
   860
}
asherkin@263
   861
asherkin@263
   862
case OP_CALLNATIVE:
asherkin@263
   863
{
asherkin@263
   864
    unsigned argc = READ_UINT32(top.pc);
asherkin@263
   865
asherkin@263
   866
    Local<Native> native(zone, Native::cast(top.sp[-1].obj));
asherkin@263
   867
    top.sp--;
asherkin@263
   868
asherkin@263
   869
    int result;
asherkin@263
   870
    void *nativeIdentity = top.fp->code()->module()->parent()->getNativeIdentity();
asherkin@263
   871
    if (!InvokeNative(zone, native, nativeIdentity, top.sp, argc, &result))
asherkin@263
   872
        goto error;
asherkin@263
   873
asherkin@263
   874
    top.sp -= argc;
asherkin@263
   875
    PUSH_I32(top, result);
asherkin@263
   876
    break;
asherkin@263
   877
}
asherkin@263
   878
asherkin@263
   879
case OP_BITCAST:
asherkin@263
   880
{
asherkin@263
   881
    // Because the stack is a union, this is a no-op.
asherkin@263
   882
    break;
asherkin@263
   883
}
asherkin@263
   884
asherkin@263
   885
case OP_TRUE:
asherkin@263
   886
{
asherkin@263
   887
    top.sp++;
asherkin@263
   888
    top.sp[-1].i32 = 1;
asherkin@263
   889
    break;
asherkin@263
   890
}
asherkin@263
   891
asherkin@263
   892
case OP_FALSE:
asherkin@263
   893
{
asherkin@263
   894
    top.sp++;
asherkin@263
   895
    top.sp[-1].i32 = 0;
asherkin@263
   896
    break;
asherkin@263
   897
}
asherkin@263
   898
asherkin@263
   899
case OP_GETFIELD:
asherkin@263
   900
{
asherkin@263
   901
    Struct *obj;
asherkin@263
   902
    if (top.sp[-1].obj->is(MapKind_Module))
asherkin@263
   903
        obj = Module::cast(top.sp[-1].obj)->globals();
asherkin@263
   904
    else
asherkin@263
   905
        obj = Struct::cast(top.sp[-1].obj);
asherkin@263
   906
    GetField(obj, READ_UINT32(top.pc), &top.sp[-1]);
asherkin@263
   907
    break;
asherkin@263
   908
}
asherkin@263
   909
asherkin@263
   910
case OP_SETFIELD:
asherkin@263
   911
{
asherkin@263
   912
    Struct *obj = Struct::cast(top.sp[-2].obj);
asherkin@263
   913
    SetField(zone, obj, READ_UINT32(top.pc), top.sp[-1]);
asherkin@263
   914
    top.sp[-2] = top.sp[-1];
asherkin@263
   915
    top.sp--;
asherkin@263
   916
    break;
asherkin@263
   917
}
asherkin@263
   918
asherkin@263
   919
case OP_COPYSTRUCT:
asherkin@263
   920
{
asherkin@263
   921
    Local<Struct> left(zone, Struct::cast(top.sp[-2].obj));
asherkin@263
   922
    Local<Struct> right(zone, Struct::cast(top.sp[-1].obj));
asherkin@263
   923
    if (!Struct::Copy(zone, left, right))
asherkin@263
   924
        goto error;
asherkin@263
   925
    top.sp[-2].obj = top.sp[-1].obj;
asherkin@263
   926
    top.sp--;
asherkin@263
   927
    break;
asherkin@263
   928
}
asherkin@263
   929
asherkin@263
   930
case OP_TABLESWITCH:
asherkin@263
   931
{
asherkin@263
   932
    int value = top.sp[-1].i32;
asherkin@263
   933
    int low = READ_TABLESWITCH_LOW(top.pc);
asherkin@263
   934
    int high = READ_TABLESWITCH_HIGH(top.pc);
asherkin@263
   935
asherkin@263
   936
    top.sp--;
asherkin@263
   937
asherkin@263
   938
    unsigned index = unsigned(value - low);
asherkin@263
   939
    unsigned tablesize = TableSwitchEntries(low, high);
asherkin@263
   940
    if (index < tablesize) {
asherkin@263
   941
        top.pc += OP_TABLESWITCH_LENGTH + OP_JUMP_LENGTH;
asherkin@263
   942
        top.pc += index * OP_JUMP_LENGTH;
asherkin@263
   943
        continue;
asherkin@263
   944
    }
asherkin@263
   945
    break;
asherkin@263
   946
}
asherkin@263
   947
asherkin@263
   948
case OP_SIZEOF:
asherkin@263
   949
{
asherkin@263
   950
    Array *array = Array::cast(top.sp[-1].obj);
asherkin@263
   951
    top.sp[-1].i32 = array->length();
asherkin@263
   952
    break;
asherkin@263
   953
}
asherkin@263
   954
asherkin@263
   955
case OP_PUBLIC:
asherkin@263
   956
{
asherkin@263
   957
    Local<Function> fun(zone, Function::cast(top.sp[-1].obj));
asherkin@263
   958
    zone->registerPublic(fun);
asherkin@263
   959
    top.sp--;
asherkin@263
   960
    break;
asherkin@263
   961
}
asherkin@263
   962
asherkin@263
   963
case OP_SETGLOBAL:
asherkin@263
   964
{
asherkin@263
   965
    Local<Code> code(zone, top.fp->code());
asherkin@263
   966
    Local<Struct> obj(zone, code->module()->globals());
asherkin@263
   967
    Local<String> name(zone, String::cast(code->strings()->at(READ_UINT32(top.pc))));
asherkin@263
   968
    SetGlobal(zone, obj, name, top.sp[-1]);
asherkin@263
   969
    break;
asherkin@263
   970
}
asherkin@263
   971
asherkin@263
   972
case OP_GETGLOBAL:
asherkin@263
   973
{
asherkin@263
   974
    Local<Code> code(zone, top.fp->code());
asherkin@263
   975
    Local<Struct> obj(zone, code->module()->globals());
asherkin@263
   976
    Local<String> name(zone, String::cast(code->strings()->at(READ_UINT32(top.pc))));
asherkin@263
   977
    GetGlobal(zone, obj, name, top.sp);
asherkin@263
   978
    top.sp++;
asherkin@263
   979
    break;
asherkin@263
   980
}
asherkin@263
   981
asherkin@263
   982
case OP_ENTERLOOP:
asherkin@263
   983
{
asherkin@263
   984
    top.fp->enterLoop(zone);
asherkin@263
   985
    break;
asherkin@263
   986
}
asherkin@263
   987
asherkin@263
   988
case OP_LEAVELOOP:
asherkin@263
   989
{
asherkin@263
   990
    top.fp->leaveLoop(zone);
asherkin@263
   991
    break;
asherkin@263
   992
}
asherkin@263
   993
asherkin@263
   994
case OP_DEPARRAY:
asherkin@263
   995
{
asherkin@263
   996
    Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->object(READ_UINT32(top.pc))));
asherkin@263
   997
    Local<Array> array(zone, Array::cast(top.sp[-2].obj));
asherkin@263
   998
    int index = top.sp[-1].i32;
asherkin@263
   999
asherkin@263
  1000
    // We allow taking 0-length dependent arrays.
asherkin@263
  1001
    if (index < 0 || unsigned(index) > array->length()) {
asherkin@263
  1002
        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
asherkin@263
  1003
        goto error;
asherkin@263
  1004
    }
asherkin@263
  1005
asherkin@263
  1006
    top.sp[-2].obj = DependentArray::New(zone, array, map, index);
asherkin@263
  1007
    if (!top.sp[-2].obj)
asherkin@263
  1008
        goto error;
asherkin@263
  1009
asherkin@263
  1010
    top.sp--;
asherkin@263
  1011
    break;
asherkin@263
  1012
}
asherkin@263
  1013
asherkin@263
  1014
case OP_IMPORT:
asherkin@263
  1015
{
asherkin@263
  1016
    unsigned index = READ_UINT32(top.pc);
asherkin@263
  1017
asherkin@263
  1018
    top.sp++;
asherkin@263
  1019
    top.sp[-1].obj = top.fp->code()->module()->getImportAt(index);
asherkin@263
  1020
    break;
asherkin@263
  1021
}
asherkin@263
  1022
asherkin@263
  1023
default:
asherkin@263
  1024
    assert(false);
asherkin@263
  1025
    return false;
asherkin@263
  1026
asherkin@263
  1027
        }
asherkin@263
  1028
asherkin@263
  1029
        top.pc += OpcodeInfo[op].length;
asherkin@263
  1030
        assert(top.sp >= top.fp->stackBase());
asherkin@263
  1031
    }
asherkin@263
  1032
asherkin@263
  1033
done:
asherkin@263
  1034
    return true;
asherkin@263
  1035
asherkin@263
  1036
error:
asherkin@263
  1037
    // Unwind frames until we can continue.
asherkin@263
  1038
    while (top.fp != entryFrame)
asherkin@263
  1039
        zone->stack().popInlineFrame();
asherkin@263
  1040
    return false;
asherkin@263
  1041
}