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