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