1 /*
2     SuperCollider real time audio synthesis system
3     Copyright (c) 2002 James McCartney. All rights reserved.
4     http://www.audiosynth.com
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19 */
20 
21 
22 #include "Opcodes.h"
23 #include "PyrInterpreter.h"
24 #include "PyrPrimitive.h"
25 #include "PyrPrimitiveProto.h"
26 #include "PyrMathPrim.h"
27 #include "PyrListPrim.h"
28 #include "PyrKernel.h"
29 #include "PyrMessage.h"
30 #include "PyrParseNode.h"
31 #include "PyrSignal.h"
32 #include "PyrSched.h"
33 #include "SC_InlineUnaryOp.h"
34 #include "SC_InlineBinaryOp.h"
35 #include "PyrKernelProto.h"
36 #include "PyrSymbolTable.h"
37 #include <math.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <signal.h>
41 
42 #include <boost/chrono.hpp>
43 
44 #include <float.h>
45 #define kBigBigFloat DBL_MAX
46 #define kSmallSmallFloat DBL_MIN
47 
48 
49 #include <new>
50 #include "InitAlloc.h"
51 #include "function_attributes.h"
52 
53 #ifdef __clang__
54 #    pragma clang diagnostic ignored "-Warray-bounds"
55 #endif
56 
57 
58 // void tellPlugInsAboutToRun();
59 double timeNow();
60 
61 
timeseed()62 int32 timeseed() {
63     using namespace std::chrono;
64 
65     high_resolution_clock::time_point now = high_resolution_clock::now();
66     high_resolution_clock::duration since_epoch = now.time_since_epoch();
67 
68     seconds secs = duration_cast<seconds>(since_epoch);
69     nanoseconds nanosecs = since_epoch - secs;
70 
71     int_least64_t seed = secs.count() ^ nanosecs.count();
72 
73     return (int32)seed;
74 }
75 
76 VMGlobals gVMGlobals;
77 VMGlobals* gMainVMGlobals = &gVMGlobals;
78 
79 void debugf(char* fmt, ...);
80 
81 #define DEBUGINTERPRETER 0
82 #define METHODMETER 0
83 #define BCSTAT 0
84 #define CHECK_MAX_STACK_USE 0
85 
86 
87 #if CHECK_MAX_STACK_USE
88 int gMaxStackDepth = 0;
89 #endif
90 
91 unsigned char* dumpOneByteCode(PyrBlock* theBlock, PyrClass* theClass, unsigned char* ip);
92 void dumpSlotOneWord(const char* tagstr, PyrSlot* slot);
93 // bool checkAllObjChecksum(PyrObject* obj);
94 
95 bool gTraceInterpreter = false;
96 // bool gTraceInterpreter = true;
97 
98 
99 const char* byteCodeString(int code);
100 
101 extern int gNumClasses;
102 extern PyrClass* gClassList;
103 
104 // runInterpreter has 7 call sites:
105 //	compileLibrary (4)
106 // 	runLibrary
107 // 	interpretCmdLine
108 
109 static void endInterpreter(VMGlobals* g);
110 
111 
runInterpreter(VMGlobals * g,PyrSymbol * selector,int numArgsPushed)112 SCLANG_DLLEXPORT_C void runInterpreter(VMGlobals* g, PyrSymbol* selector, int numArgsPushed) {
113     // postfl("->runInterpreter\n");
114 #ifdef GC_SANITYCHECK
115     g->gc->SanityCheck();
116 #endif
117     // postfl(" >initInterpreter\n");
118 
119     if (initInterpreter(g, selector, numArgsPushed)) {
120 #ifdef GC_SANITYCHECK
121         g->gc->SanityCheck();
122 #endif
123         //        if (strcmp(selector->name, "tick") != 0) post("%s %d  execMethod %d\n", selector->name, numArgsPushed,
124         //        g->execMethod);
125         // post("->Interpret thread %p\n", g->thread);
126         if (g->execMethod)
127             Interpret(g);
128             // post("<-Interpret thread %p\n", g->thread);
129 #ifdef GC_SANITYCHECK
130         g->gc->SanityCheck();
131 #endif
132     }
133 
134     // postfl(" >endInterpreter\n");
135     endInterpreter(g);
136 #ifdef GC_SANITYCHECK
137     g->gc->SanityCheck();
138 #endif
139     // postfl("<-runInterpreter\n");
140     // dumpGCStats(g->gc);
141 }
142 
143 static bool initAwakeMessage(VMGlobals* g);
144 
runAwakeMessage(VMGlobals * g)145 void runAwakeMessage(VMGlobals* g) {
146     if (initAwakeMessage(g)) {
147         if (g->execMethod)
148             Interpret(g);
149     }
150     endInterpreter(g);
151 }
152 
153 void initPyrThread(VMGlobals* g, PyrThread* thread, PyrSlot* func, int stacksize, PyrInt32Array* rgenArray,
154                    double beats, double seconds, PyrSlot* clock, bool runGC);
155 int32 timeseed();
156 
newPyrProcess(VMGlobals * g,PyrClass * procclassobj)157 PyrProcess* newPyrProcess(VMGlobals* g, PyrClass* procclassobj) {
158     PyrGC* gc = g->gc;
159     PyrProcess* proc = (PyrProcess*)instantiateObject(gc, procclassobj, 0, true, false);
160 
161     PyrObject* sysSchedulerQueue = newPyrArray(gc, 4096, 0, false);
162     sysSchedulerQueue->size = 1;
163     SetInt(sysSchedulerQueue->slots + 0, 0); // stability count
164     SetObject(&proc->sysSchedulerQueue, sysSchedulerQueue);
165 
166     PyrObject* classVars = newPyrArray(gc, gNumClassVars, 0, false);
167     classVars->size = gNumClassVars;
168     nilSlots(classVars->slots, gNumClassVars);
169     SetObject(&proc->classVars, classVars);
170     g->classvars = classVars;
171 
172     // fill class vars from prototypes:
173     PyrClass* classobj = gClassList;
174     while (classobj) {
175         if (IsObj(&classobj->cprototype)) {
176             int numClassVars = slotRawObject(&classobj->cprototype)->size;
177             if (numClassVars > 0) {
178                 memcpy(g->classvars->slots + slotRawInt(&classobj->classVarIndex),
179                        slotRawObject(&classobj->cprototype)->slots, numClassVars * sizeof(PyrSlot));
180             }
181         }
182         classobj = slotRawClass(&classobj->nextclass);
183     }
184 
185     SetNil(&proc->nowExecutingPath);
186 
187     class_thread = getsym("Thread")->u.classobj;
188     if (class_thread) {
189         SetNil(&proc->curThread);
190         PyrThread* thread = (PyrThread*)instantiateObject(gc, class_thread, 0, true, false);
191         // SetObject(&threadsArray->slots[0], thread);
192         SetObject(&proc->mainThread, thread);
193         PyrInt32Array* rgenArray = newPyrInt32Array(gc, 4, 0, false);
194         rgenArray->size = 4;
195         rgenArray->i[0] = 0;
196         rgenArray->i[1] = 0;
197         rgenArray->i[2] = 0;
198         rgenArray->i[3] = 0;
199         ((RGen*)(rgenArray->i))->init(timeseed());
200 
201         PyrSlot clockSlot;
202         SetObject(&clockSlot, s_systemclock->u.classobj);
203         initPyrThread(g, thread, &o_nil, EVALSTACKDEPTH, rgenArray, 0., 0., &clockSlot, false);
204         // postfl("elapsedTime %.6f\n", elapsedTime());
205     } else {
206         error("Class Thread not found.\n");
207     }
208 
209     PyrSymbol* contextsym = getsym("functionCompileContext");
210     size_t index = slotRawInt(&class_interpreter->classIndex) + contextsym->u.index;
211     PyrMethod* meth = gRowTable[index];
212     if (!meth || slotRawSymbol(&meth->name) != contextsym) {
213         error("compile context method 'functionCompileContext' not found.\n");
214         // SetNil(&proc->interpreter);
215     } else {
216         PyrObject* proto;
217         PyrFrame* frame;
218         PyrMethodRaw* methraw;
219 
220         PyrInterpreter* interpreter = (PyrInterpreter*)instantiateObject(gc, class_interpreter, 0, true, false);
221         SetObject(&proc->interpreter, interpreter);
222         proto = slotRawObject(&meth->prototypeFrame);
223 
224         methraw = METHRAW(meth);
225         frame = (PyrFrame*)gc->New(methraw->frameSize, 0, obj_slot, false);
226         frame->classptr = class_frame;
227         frame->size = FRAMESIZE + proto->size; /// <- IS THIS WRONG ??
228         SetObject(&frame->method, meth);
229         SetObject(&frame->homeContext, frame);
230         SetInt(&frame->caller, 0);
231         SetNil(&frame->context);
232         SetPtr(&frame->ip, nullptr);
233         SetObject(&frame->vars[0], interpreter);
234 
235         SetObject(&interpreter->context, frame);
236     }
237 
238     return proc;
239 }
240 
241 
242 #if BCSTAT
243 int prevop = 0;
244 int bcstat[256];
245 int bcpair[256][256];
246 
247 void clearbcstat();
clearbcstat()248 void clearbcstat() {
249     int i, j;
250     for (i = 0; i < 256; ++i) {
251         bcstat[i] = 0;
252         for (j = 0; j < 256; ++j) {
253             bcpair[i][j] = 0;
254         }
255     }
256 }
257 
258 void dumpbcstat();
dumpbcstat()259 void dumpbcstat() {
260     FILE* file;
261     int i, j, k, total;
262 
263     file = fopen("bcstat", "w");
264     if (file) {
265         fprintf(file, "----------\n");
266         total = 0;
267         for (i = 0; i < 256; ++i) {
268             total += bcstat[i];
269             if (bcstat[i])
270                 fprintf(file, "%3d %8d  %-32s\n", i, bcstat[i], byteCodeString(i));
271         }
272         fprintf(file, "\ntotal %d\n", total);
273         fprintf(file, "-----cur,next-----\n");
274         for (i = 0, k = 0; i < 256; ++i) {
275             for (j = 0; j < 256; j++) {
276                 if (bcpair[i][j] > 0) {
277                     fprintf(file, "%4d %3d %3d %8d %-32s %-32s\n", k++, i, j, bcpair[i][j], byteCodeString(i),
278                             byteCodeString(j));
279                 }
280             }
281         }
282         fprintf(file, "-----cur,prev-----\n");
283         for (i = 0, k = 0; i < 256; ++i) {
284             for (j = 0; j < 256; j++) {
285                 if (bcpair[j][i] > 0) {
286                     fprintf(file, "%4d %3d %3d %8d %-32s %-32s\n", k++, i, j, bcpair[j][i], byteCodeString(i),
287                             byteCodeString(j));
288                 }
289             }
290         }
291     }
292     fclose(file);
293 }
294 #endif
295 
296 void initPatterns();
297 void initThreads();
298 void initGUI();
299 
300 #ifndef _WIN32
301 bool running = true;
handleSigUsr1(int param)302 static void handleSigUsr1(int param) {
303     printf("handleSigUsr1()...\n");
304     running = false;
305 }
306 #endif
307 
initRuntime(VMGlobals * g,int poolSize,AllocPool * inPool)308 bool initRuntime(VMGlobals* g, int poolSize, AllocPool* inPool) {
309     /*
310         create a GC environment
311         create a vmachine instance of main
312         initialize VMGlobals
313     */
314 
315     PyrClass* class_main = s_main->u.classobj;
316 
317     if (!class_main) {
318         error("Class 'Main' not defined.\n");
319         return false;
320     }
321     if (!isSubclassOf(class_main, class_process)) {
322         error("Class Main is not a subclass of Process.\n");
323         return false;
324     }
325 
326     // create GC environment, process
327     g->allocPool = inPool;
328     g->gc = (PyrGC*)g->allocPool->Alloc(sizeof(PyrGC));
329     new (g->gc) PyrGC(g, g->allocPool, class_main, poolSize);
330     g->thread = slotRawThread(&g->process->mainThread);
331     SetObject(&g->receiver, g->process);
332 
333     // these will be set up when the run method is called
334     g->method = nullptr;
335     g->block = nullptr;
336     g->frame = nullptr;
337     g->ip = nullptr;
338 
339     // initialize process random number generator
340     g->rgen = (RGen*)(slotRawObject(&g->thread->randData)->slots);
341 
342     initThreads();
343     initPatterns();
344     initUniqueMethods();
345     initGUI();
346 #ifdef GC_SANITYCHECK
347     g->gc->SanityCheck();
348 #endif
349     // tellPlugInsAboutToRun();
350 
351 #ifndef _WIN32
352     signal(SIGUSR1, handleSigUsr1);
353 #endif
354 
355     assert((g->gc->SanityCheck()));
356 #ifdef GC_SANITYCHECK
357     g->gc->SanityCheck();
358 #endif
359 
360     return true;
361 }
362 
initAwakeMessage(VMGlobals * g)363 static bool initAwakeMessage(VMGlobals* g) {
364     // post("initAwakeMessage %p %p\n", g->thread, slotRawThread(&g->process->mainThread));
365     slotCopy(&g->process->curThread, &g->process->mainThread); //??
366     g->thread = slotRawThread(&g->process->mainThread); //??
367 
368     // these will be set up when the run method is called
369     g->method = nullptr;
370     g->block = nullptr;
371     g->frame = nullptr;
372     g->ip = nullptr;
373     g->execMethod = 0;
374 
375     // set process as the receiver
376     PyrSlot* slot = g->sp - 3;
377     slotCopy(&g->receiver, slot);
378 
379     SetFloat(&g->thread->beats, slotRawFloat(&slot[1]));
380     SetFloat(&g->thread->seconds, slotRawFloat(&slot[2]));
381     slotCopy(&g->thread->clock, &slot[3]);
382     g->gc->GCWrite(g->thread, slot + 3);
383 
384     // start it
385     sendMessage(g, s_awake, 4);
386 
387     return g->method != nullptr;
388 }
389 
initInterpreter(VMGlobals * g,PyrSymbol * selector,int numArgsPushed)390 bool initInterpreter(VMGlobals* g, PyrSymbol* selector, int numArgsPushed) {
391     slotCopy(&g->process->curThread, &g->process->mainThread);
392     g->thread = slotRawThread(&g->process->mainThread);
393 
394     // these will be set up when the run method is called
395 #if TAILCALLOPTIMIZE
396     g->tailCall = 0;
397 #endif
398     g->method = nullptr;
399     g->block = nullptr;
400     g->frame = nullptr;
401     g->ip = nullptr;
402     g->execMethod = 0;
403     double elapsed = elapsedTime();
404     SetFloat(&g->thread->beats, elapsed);
405     SetFloat(&g->thread->seconds, elapsed);
406     SetObject(&g->thread->clock, s_systemclock->u.classobj);
407     g->gc->GCWrite(g->thread, s_systemclock->u.classobj);
408 
409     // set process as the receiver
410     PyrSlot* slot = g->sp - numArgsPushed + 1;
411     slotCopy(&g->receiver, slot);
412 
413     // start it
414     sendMessage(g, selector, numArgsPushed);
415 
416     return g->method != nullptr;
417 }
418 
419 
endInterpreter(VMGlobals * g)420 static void endInterpreter(VMGlobals* g) {
421     slotCopy(&g->result, g->sp);
422     //	dumpObjectSlot(&g->result);
423     g->gc->Stack()->size = 0;
424     g->sp = g->gc->Stack()->slots - 1;
425     g->gc->LazyCollect();
426 }
427 
428 
StoreToImmutableA(VMGlobals * g,PyrSlot * & sp,unsigned char * & ip)429 static void StoreToImmutableA(VMGlobals* g, PyrSlot*& sp, unsigned char*& ip) {
430     // only the value is on the stack
431     slotCopy(sp + 1, sp); // copy value up one
432     slotCopy(sp, &g->receiver); // put receiver in place
433     sp++;
434     g->sp = sp;
435     g->ip = ip;
436     post("StoreToImmutableA\n");
437     dumpObjectSlot(sp - 1);
438     dumpObjectSlot(sp);
439     sendMessage(g, getsym("immutableError"), 2);
440     sp = g->sp;
441     ip = g->ip;
442 }
443 
StoreToImmutableB(VMGlobals * g,PyrSlot * & sp,unsigned char * & ip)444 void StoreToImmutableB(VMGlobals* g, PyrSlot*& sp, unsigned char*& ip) {
445     // receiver and value are on the stack.
446     sp++;
447     g->sp = sp;
448     g->ip = ip;
449     post("StoreToImmutableB\n");
450     dumpObjectSlot(sp - 1);
451     dumpObjectSlot(sp);
452     PyrSymbol* selector = getsym("immutableError");
453     sendMessage(g, selector, 2);
454     sp = g->sp;
455     ip = g->ip;
456 }
457 
458 
459 void dumpByteCodes(PyrBlock* theBlock);
460 
handlePushClassVar(VMGlobals * g,PyrSlot * & sp,unsigned char * & ip,unsigned char op2)461 static inline void handlePushClassVar(VMGlobals* g, PyrSlot*& sp, unsigned char*& ip, unsigned char op2) {
462     unsigned char op3 = ip[1];
463     ++ip; // get class var index
464     slotCopy(++sp, &g->classvars->slots[(op2 << 8) | op3]);
465 }
466 
handleStoreInstVar(VMGlobals * g,PyrSlot * & sp,unsigned char * & ip,unsigned int index)467 static inline void handleStoreInstVar(VMGlobals* g, PyrSlot*& sp, unsigned char*& ip, unsigned int index) {
468     PyrObject* obj = slotRawObject(&g->receiver);
469     if (obj->IsImmutable())
470         StoreToImmutableA(g, sp, ip);
471     else {
472         PyrSlot* slot = obj->slots + index;
473         slotCopy(slot, sp--);
474         g->gc->GCWrite(obj, slot);
475     }
476 }
477 
handleSendSpecialUnaryArithMsg(VMGlobals * g,PyrSlot * & sp,unsigned char * & ip,unsigned char op1)478 static inline void handleSendSpecialUnaryArithMsg(VMGlobals* g, PyrSlot*& sp, unsigned char*& ip, unsigned char op1) {
479     g->sp = sp;
480     g->ip = ip;
481     g->primitiveIndex = op1 & 15;
482     doSpecialUnaryArithMsg(g, -1);
483     sp = g->sp;
484     ip = g->ip;
485 }
486 
handleSendSpecialBinaryArithMsg(VMGlobals * g,PyrSlot * & sp,unsigned char * & ip,unsigned char op1)487 static inline void handleSendSpecialBinaryArithMsg(VMGlobals* g, PyrSlot*& sp, unsigned char*& ip, unsigned char op1) {
488     g->sp = sp;
489     g->ip = ip;
490     g->primitiveIndex = op1 & 15;
491     doSpecialBinaryArithMsg(g, 2, false);
492     sp = g->sp;
493     ip = g->ip;
494 }
495 
checkStackOverflow(VMGlobals * g,PyrSlot * sp)496 static inline bool checkStackOverflow(VMGlobals* g, PyrSlot* sp) {
497     PyrObject* stack = g->gc->Stack();
498     int depth = sp - stack->slots;
499     return depth < slotRawInt(&g->thread->stackSize);
500 }
501 
checkStackDepth(VMGlobals * g,PyrSlot * sp)502 static inline void checkStackDepth(VMGlobals* g, PyrSlot* sp) {
503 #if CHECK_MAX_STACK_USE
504     int stackDepth = sp - g->sp + 1;
505     if (stackDepth > gMaxStackDepth) {
506         gMaxStackDepth = stackDepth;
507         printf("gMaxStackDepth %d\n", gMaxStackDepth);
508     }
509 #endif
510 }
511 
512 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
513 #    define LABELS_AS_VALUES
514 #endif
515 
516 #ifdef LABELS_AS_VALUES
517 #    define dispatch_opcode                                                                                            \
518         op1 = ip[1];                                                                                                   \
519         ++ip;                                                                                                          \
520         checkStackDepth(g, sp);                                                                                        \
521         assert(checkStackOverflow(g, sp));                                                                             \
522         goto* opcode_labels[op1]
523 #else
524 #    define dispatch_opcode break
525 #endif
526 
527 #if defined(__GNUC__)
528 #    define LIKELY(x) __builtin_expect((x), 1)
529 #    define UNLIKELY(x) __builtin_expect((x), 0)
530 #else
531 #    define LIKELY(x) x
532 #    define UNLIKELY(x) x
533 #endif
534 
535 #if defined(__GNUC__) && !defined(__clang__)
536 // gcc manual:
537 // Note: When compiling a program using computed gotos, a GCC extension, you may get better run-time performance if
538 //       you disable the global common subexpression elimination pass by adding -fno-gcse to the command line.
539 #    pragma GCC push_options
540 #    pragma GCC optimize("-fno-gcse")
541 #endif
542 
Interpret(VMGlobals * g)543 HOT void Interpret(VMGlobals* g) {
544     // byte code values
545     unsigned char* ip;
546     unsigned char op1;
547 
548     // interpreter globals
549     int numArgsPushed, numKeyArgsPushed;
550     PyrSymbol* selector;
551     PyrClass* classobj;
552 
553     // temporary variables used in the interpreter
554     PyrSlot* slot;
555     PyrSlot* sp;
556 
557 #ifdef LABELS_AS_VALUES
558     static void* opcode_labels[] = {
559         &&handle_op_0,   &&handle_op_1,   &&handle_op_2,   &&handle_op_3,   &&handle_op_4,   &&handle_op_5,
560         &&handle_op_6,   &&handle_op_7,   &&handle_op_8,   &&handle_op_9,   &&handle_op_10,  &&handle_op_11,
561         &&handle_op_12,  &&handle_op_13,  &&handle_op_14,  &&handle_op_15,  &&handle_op_16,  &&handle_op_17,
562         &&handle_op_18,  &&handle_op_19,  &&handle_op_20,  &&handle_op_21,  &&handle_op_22,  &&handle_op_23,
563         &&handle_op_24,  &&handle_op_25,  &&handle_op_26,  &&handle_op_27,  &&handle_op_28,  &&handle_op_29,
564         &&handle_op_30,  &&handle_op_31,  &&handle_op_32,  &&handle_op_33,  &&handle_op_34,  &&handle_op_35,
565         &&handle_op_36,  &&handle_op_37,  &&handle_op_38,  &&handle_op_39,  &&handle_op_40,  &&handle_op_41,
566         &&handle_op_42,  &&handle_op_43,  &&handle_op_44,  &&handle_op_45,  &&handle_op_46,  &&handle_op_47,
567         &&handle_op_48,  &&handle_op_49,  &&handle_op_50,  &&handle_op_51,  &&handle_op_52,  &&handle_op_53,
568         &&handle_op_54,  &&handle_op_55,  &&handle_op_56,  &&handle_op_57,  &&handle_op_58,  &&handle_op_59,
569         &&handle_op_60,  &&handle_op_61,  &&handle_op_62,  &&handle_op_63,  &&handle_op_64,  &&handle_op_65,
570         &&handle_op_66,  &&handle_op_67,  &&handle_op_68,  &&handle_op_69,  &&handle_op_70,  &&handle_op_71,
571         &&handle_op_72,  &&handle_op_73,  &&handle_op_74,  &&handle_op_75,  &&handle_op_76,  &&handle_op_77,
572         &&handle_op_78,  &&handle_op_79,  &&handle_op_80,  &&handle_op_81,  &&handle_op_82,  &&handle_op_83,
573         &&handle_op_84,  &&handle_op_85,  &&handle_op_86,  &&handle_op_87,  &&handle_op_88,  &&handle_op_89,
574         &&handle_op_90,  &&handle_op_91,  &&handle_op_92,  &&handle_op_93,  &&handle_op_94,  &&handle_op_95,
575         &&handle_op_96,  &&handle_op_97,  &&handle_op_98,  &&handle_op_99,  &&handle_op_100, &&handle_op_101,
576         &&handle_op_102, &&handle_op_103, &&handle_op_104, &&handle_op_105, &&handle_op_106, &&handle_op_107,
577         &&handle_op_108, &&handle_op_109, &&handle_op_110, &&handle_op_111, &&handle_op_112, &&handle_op_113,
578         &&handle_op_114, &&handle_op_115, &&handle_op_116, &&handle_op_117, &&handle_op_118, &&handle_op_119,
579         &&handle_op_120, &&handle_op_121, &&handle_op_122, &&handle_op_123, &&handle_op_124, &&handle_op_125,
580         &&handle_op_126, &&handle_op_127, &&handle_op_128, &&handle_op_129, &&handle_op_130, &&handle_op_131,
581         &&handle_op_132, &&handle_op_133, &&handle_op_134, &&handle_op_135, &&handle_op_136, &&handle_op_137,
582         &&handle_op_138, &&handle_op_139, &&handle_op_140, &&handle_op_141, &&handle_op_142, &&handle_op_143,
583         &&handle_op_144, &&handle_op_145, &&handle_op_146, &&handle_op_147, &&handle_op_148, &&handle_op_149,
584         &&handle_op_150, &&handle_op_151, &&handle_op_152, &&handle_op_153, &&handle_op_154, &&handle_op_155,
585         &&handle_op_156, &&handle_op_157, &&handle_op_158, &&handle_op_159, &&handle_op_160, &&handle_op_161,
586         &&handle_op_162, &&handle_op_163, &&handle_op_164, &&handle_op_165, &&handle_op_166, &&handle_op_167,
587         &&handle_op_168, &&handle_op_169, &&handle_op_170, &&handle_op_171, &&handle_op_172, &&handle_op_173,
588         &&handle_op_174, &&handle_op_175, &&handle_op_176, &&handle_op_177, &&handle_op_178, &&handle_op_179,
589         &&handle_op_180, &&handle_op_181, &&handle_op_182, &&handle_op_183, &&handle_op_184, &&handle_op_185,
590         &&handle_op_186, &&handle_op_187, &&handle_op_188, &&handle_op_189, &&handle_op_190, &&handle_op_191,
591         &&handle_op_192, &&handle_op_193, &&handle_op_194, &&handle_op_195, &&handle_op_196, &&handle_op_197,
592         &&handle_op_198, &&handle_op_199, &&handle_op_200, &&handle_op_201, &&handle_op_202, &&handle_op_203,
593         &&handle_op_204, &&handle_op_205, &&handle_op_206, &&handle_op_207, &&handle_op_208, &&handle_op_209,
594         &&handle_op_210, &&handle_op_211, &&handle_op_212, &&handle_op_213, &&handle_op_214, &&handle_op_215,
595         &&handle_op_216, &&handle_op_217, &&handle_op_218, &&handle_op_219, &&handle_op_220, &&handle_op_221,
596         &&handle_op_222, &&handle_op_223, &&handle_op_224, &&handle_op_225, &&handle_op_226, &&handle_op_227,
597         &&handle_op_228, &&handle_op_229, &&handle_op_230, &&handle_op_231, &&handle_op_232, &&handle_op_233,
598         &&handle_op_234, &&handle_op_235, &&handle_op_236, &&handle_op_237, &&handle_op_238, &&handle_op_239,
599         &&handle_op_240, &&handle_op_241, &&handle_op_242, &&handle_op_243, &&handle_op_244, &&handle_op_245,
600         &&handle_op_246, &&handle_op_247, &&handle_op_248, &&handle_op_249, &&handle_op_250, &&handle_op_251,
601         &&handle_op_252, &&handle_op_253, &&handle_op_254, &&handle_op_255
602     };
603 
604 #endif
605 
606 #if 0
607 	unsigned char *bzero;
608 	PyrSlot *szero;
609 	char str[80];
610 #endif
611 
612 
613 #if BCSTAT
614     // clearbcstat();
615     op1 = 0;
616     prevop = 0;
617 #endif
618 
619 #if 0
620 	bzero = g->ip;
621 	szero = g->sp;
622 	//SetSymbol(g->sp, getsym("STACK TOP")); // just for debugging
623 	//g->sp++; // just for debugging
624 #endif
625 
626     // Codewarrior puts them in registers. take advantage..
627     sp = g->sp;
628     ip = g->ip;
629 
630     numKeyArgsPushed = 0;
631 
632     if (setjmp(g->escapeInterpreter) != 0) {
633         return;
634     }
635 #ifndef _WIN32
636     while (running) { // not going to indent body to save line space
637 #else
638     while (true) {
639 #endif
640 
641         checkStackDepth(g, sp);
642 
643 #if BCSTAT
644         prevop = op1;
645 #endif
646 
647         op1 = ip[1];
648         ++ip;
649 
650         assert(checkStackOverflow(g, sp));
651 
652 #if BCSTAT
653         ++bcstat[op1];
654         ++bcpair[prevop][op1];
655         prevop = op1;
656 #endif
657         // printf("op1 %d\n", op1);
658         // postfl("sp %p   frame %p  caller %p  ip %p\n", sp, g->frame, g->frame->caller.uof,
659         // slotRawInt(&g->frame->caller.uof->ip)); postfl("sp %p   frame %p   diff %d    caller %p\n", sp, g->frame,
660         // ((int)sp - (int)g->frame)>>3, g->frame->caller.uof);
661 #if DEBUGINTERPRETER
662         if (gTraceInterpreter) {
663             // DumpStack(g, sp);
664             if (FrameSanity(g->frame, "dbgint")) {
665                 // Debugger();
666             }
667             // g->gc->SanityCheck();
668             // assert(g->gc->SanityCheck());
669             g->sp = sp;
670             g->ip = ip;
671             g->gc->FullCollection();
672             sp = g->sp;
673             ip = g->ip;
674             postfl("[%3d] %20s-%-16s  ", (sp - g->gc->Stack()->slots) + 1,
675                    slotRawSymbol(&slotRawClass(&g->method->ownerclass)->name)->name,
676                    slotRawSymbol(&g->method->name)->name);
677             dumpOneByteCode(g->block, NULL, ip);
678         }
679 #endif
680 #ifdef GC_SANITYCHECK
681         //	gcLinkSanity(g->gc);
682         g->gc->SanityCheck();
683 //	do_check_pool(pyr_pool_runtime);
684 //	do_check_pool(pyr_pool_compile);
685 #endif
686 #if METHODMETER
687         if (gTraceInterpreter) {
688             slotRawInt(&g->method->byteMeter)++;
689         }
690 #endif
691 
692         switch (op1) {
693         case 0: //	push class
694         handle_op_0 : {
695             int op2 = ip[1];
696             ++ip; // get literal index
697             classobj = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2])->u.classobj;
698             if (classobj) {
699                 ++sp;
700                 SetObject(sp, classobj);
701             } else {
702                 postfl("Execution warning: Class '%s' not found\n",
703                        slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2])->name);
704                 slotCopy(++sp, &gSpecialValues[svNil]);
705             }
706             dispatch_opcode;
707         }
708         case 1: // opExtended, opPushInstVar
709         handle_op_1 : {
710             int op2 = ip[1];
711             ++ip; // get inst var index
712             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[op2]);
713             dispatch_opcode;
714         }
715         case 2: // opExtended, opPushTempVar
716         handle_op_2 : {
717             int op2 = ip[1]; // get temp var level
718             int op3 = ip[2]; // get temp var index
719             ip += 2;
720             PyrFrame* tframe = g->frame;
721             for (; op2--; tframe = slotRawFrame(&tframe->context)) { /* noop */
722             }
723             slotCopy(++sp, &tframe->vars[op3]);
724             dispatch_opcode;
725         }
726         case 3: // opExtended, opPushTempZeroVar
727         handle_op_3 : {
728             int op2 = ip[1];
729             ++ip; // get temp var index
730             slotCopy(++sp, &g->frame->vars[op2]);
731             dispatch_opcode;
732         }
733         case 4: // opExtended, opPushLiteral
734         handle_op_4 : {
735             int op2 = ip[1];
736             ++ip; // get literal index
737             // push a block as a closure if it is one
738             slot = slotRawObject(&g->block->selectors)->slots + op2;
739             if (IsObj(slot) && slotRawObject(slot)->classptr == gSpecialClasses[op_class_fundef]->u.classobj) {
740                 // push a closure
741                 g->sp = sp; // gc may push the stack
742                 PyrClosure* closure = (PyrClosure*)g->gc->New(2 * sizeof(PyrSlot), 0, obj_notindexed, true);
743                 sp = g->sp;
744                 closure->classptr = gSpecialClasses[op_class_func]->u.classobj;
745                 closure->size = 2;
746                 slotCopy(&closure->block, slot);
747                 if (IsNil(&slotRawBlock(slot)->contextDef)) {
748                     slotCopy(&closure->context, &slotRawInterpreter(&g->process->interpreter)->context);
749                 } else {
750                     SetObject(&closure->context, g->frame);
751                 }
752                 ++sp;
753                 SetObject(sp, closure);
754             } else {
755                 slotCopy(++sp, slot);
756             }
757             dispatch_opcode;
758         }
759         case 5: // opExtended, opPushClassVar
760         handle_op_5 : {
761             int op2 = ip[1]; // get class
762             int op3 = ip[2]; // get class var index
763             ip += 2;
764             slotCopy(++sp, &g->classvars->slots[(op2 << 8) | op3]);
765             dispatch_opcode;
766         }
767         case 6: // opExtended, opPushSpecialValue == push a special class
768         handle_op_6 : {
769             int op2 = ip[1];
770             ++ip; // get class name index
771             classobj = gSpecialClasses[op2]->u.classobj;
772             if (classobj) {
773                 ++sp;
774                 SetObject(sp, classobj);
775             } else {
776                 slotCopy(++sp, &gSpecialValues[svNil]);
777             }
778             dispatch_opcode;
779         }
780         case 7: // opExtended, opStoreInstVar
781         handle_op_7 : {
782             int op2 = ip[1];
783             ++ip; // get inst var index
784             PyrObject* obj = slotRawObject(&g->receiver);
785             if (obj->IsImmutable()) {
786                 StoreToImmutableA(g, sp, ip);
787             } else {
788                 slot = obj->slots + op2;
789                 slotCopy(slot, sp);
790                 g->gc->GCWrite(obj, slot);
791             }
792             dispatch_opcode;
793         }
794         case 8: // opExtended, opStoreTempVar
795         handle_op_8 : {
796             int op2 = ip[1]; // get temp var level
797             int op3 = ip[2]; // get temp var index
798             ip += 2;
799             PyrFrame* tframe = g->frame;
800             for (; op2--; tframe = slotRawFrame(&tframe->context)) { /* noop */
801             }
802             slot = tframe->vars + op3;
803             slotCopy(slot, sp);
804             g->gc->GCWrite(tframe, slot);
805             dispatch_opcode;
806         }
807         case 9: // opExtended, opStoreClassVar
808         handle_op_9 : {
809             int op2 = ip[1]; // get index of class name literal
810             int op3 = ip[2]; // get class var index
811             ip += 2;
812             slotCopy(&g->classvars->slots[(op2 << 8) | op3], sp);
813             g->gc->GCWrite(g->classvars, sp);
814             dispatch_opcode;
815         }
816         case 10: // opExtended, opSendMsg
817         handle_op_10 : {
818             numArgsPushed = ip[1]; // get num args
819             numKeyArgsPushed = ip[2]; // get num keyword args
820             int op3 = ip[3]; // get selector index
821             ip += 3;
822             selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op3]);
823 
824             slot = sp - numArgsPushed + 1;
825 
826             if (numKeyArgsPushed)
827                 goto key_class_lookup;
828             else
829                 goto class_lookup;
830         }
831         case 11: // opExtended, opSendSuper
832         handle_op_11 : {
833             numArgsPushed = ip[1]; // get num args
834             numKeyArgsPushed = ip[2]; // get num keyword args
835             int op3 = ip[3]; // get selector index
836             ip += 3;
837             selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op3]);
838 
839             slot = g->sp - numArgsPushed + 1;
840             classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj;
841 
842             if (numKeyArgsPushed)
843                 goto key_msg_lookup;
844             else
845                 goto msg_lookup;
846         }
847 
848         case 12: // opExtended, opSendSpecialMsg
849         handle_op_12 : {
850             numArgsPushed = ip[1]; // get num args
851             numKeyArgsPushed = ip[2]; // get num keyword args
852             int op3 = ip[3]; // get selector index
853             ip += 3;
854 
855             selector = gSpecialSelectors[op3];
856             slot = sp - numArgsPushed + 1;
857 
858             if (numKeyArgsPushed)
859                 goto key_class_lookup;
860             else
861                 goto class_lookup;
862         }
863 
864         case 13: // opExtended, opSendSpecialUnaryArithMsg
865         handle_op_13 : {
866             int op2 = ip[1];
867             ++ip; // get selector index
868             g->sp = sp;
869             g->ip = ip;
870             g->primitiveIndex = op2;
871             doSpecialUnaryArithMsg(g, -1);
872 #if TAILCALLOPTIMIZE
873             g->tailCall = 0;
874 #endif
875             sp = g->sp;
876             ip = g->ip;
877             dispatch_opcode;
878         }
879         case 14: // opExtended, opSendSpecialBinaryArithMsg
880         handle_op_14 : {
881             int op2 = ip[1];
882             ++ip; // get selector index
883             g->sp = sp;
884             g->ip = ip;
885             g->primitiveIndex = op2;
886             doSpecialBinaryArithMsg(g, 2, false);
887             sp = g->sp;
888             ip = g->ip;
889             dispatch_opcode;
890         }
891         case 15: // opExtended, opSpecialOpcode (none yet)
892         handle_op_15 : {
893             int op2 = ip[1];
894             ++ip; // get extended special opcode
895             switch (op2) {
896             case opgProcess: // push thisProcess
897                 ++sp;
898                 SetObject(sp, g->process);
899                 break;
900             case opgThread: // push thisProcess
901                 ++sp;
902                 SetObject(sp, g->thread);
903                 break;
904             case opgMethod: // push thisMethod
905                 ++sp;
906                 SetObject(sp, g->method);
907                 break;
908             case opgFunctionDef: // push thisFunctionDef
909                 ++sp;
910                 SetObject(sp, g->block);
911                 break;
912             case opgFunction: { // push thisFunc
913                 // push a closure
914                 g->sp = sp; // gc may push the stack
915                 PyrClosure* closure = (PyrClosure*)g->gc->New(2 * sizeof(PyrSlot), 0, obj_notindexed, true);
916                 sp = g->sp;
917                 closure->classptr = gSpecialClasses[op_class_func]->u.classobj;
918                 closure->size = 2;
919                 SetObject(&closure->block, g->block);
920                 SetObject(&closure->context, slotRawFrame(&g->frame->context));
921                 ++sp;
922                 SetObject(sp, closure);
923                 break;
924             }
925             default:
926                 slotCopy(++sp, &gSpecialValues[svNil]);
927                 break;
928             }
929             dispatch_opcode;
930         }
931         // opPushInstVar, 0..15
932         case 16:
933         handle_op_16:
934             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[0]);
935             dispatch_opcode;
936         case 17:
937         handle_op_17:
938             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[1]);
939             dispatch_opcode;
940         case 18:
941         handle_op_18:
942             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[2]);
943             dispatch_opcode;
944         case 19:
945         handle_op_19:
946             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[3]);
947             dispatch_opcode;
948         case 20:
949         handle_op_20:
950             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[4]);
951             dispatch_opcode;
952         case 21:
953         handle_op_21:
954             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[5]);
955             dispatch_opcode;
956         case 22:
957         handle_op_22:
958             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[6]);
959             dispatch_opcode;
960         case 23:
961         handle_op_23:
962             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[7]);
963             dispatch_opcode;
964         case 24:
965         handle_op_24:
966             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[8]);
967             dispatch_opcode;
968         case 25:
969         handle_op_25:
970             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[9]);
971             dispatch_opcode;
972         case 26:
973         handle_op_26:
974             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[10]);
975             dispatch_opcode;
976         case 27:
977         handle_op_27:
978             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[11]);
979             dispatch_opcode;
980         case 28:
981         handle_op_28:
982             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[12]);
983             dispatch_opcode;
984         case 29:
985         handle_op_29:
986             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[13]);
987             dispatch_opcode;
988         case 30:
989         handle_op_30:
990             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[14]);
991             dispatch_opcode;
992         case 31:
993         handle_op_31:
994             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[15]);
995             dispatch_opcode;
996 
997         case 32: // JumpIfTrue
998         handle_op_32:
999             // cannot compare with o_false because it is NaN
1000             if (IsTrue(sp)) {
1001                 int jmplen = (ip[1] << 8) | ip[2];
1002                 ip += jmplen + 2;
1003             } else if (IsFalse(sp)) {
1004                 ip += 2;
1005             } else {
1006                 numArgsPushed = 1;
1007                 selector = gSpecialSelectors[opmNonBooleanError];
1008                 slot = sp;
1009 
1010                 goto class_lookup;
1011             }
1012             --sp;
1013             dispatch_opcode;
1014 
1015         // opPushTempVar, levels 1..7
1016         case 33:
1017         handle_op_33:
1018             slotCopy(++sp, &slotRawFrame(&g->frame->context)->vars[ip[1]]);
1019             ++ip;
1020             dispatch_opcode;
1021         case 34:
1022         handle_op_34:
1023             slotCopy(++sp, &slotRawFrame(&slotRawFrame(&g->frame->context)->context)->vars[ip[1]]);
1024             ++ip;
1025             dispatch_opcode;
1026         case 35:
1027         handle_op_35:
1028             slotCopy(++sp,
1029                      &slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)->vars[ip[1]]);
1030             ++ip;
1031             dispatch_opcode;
1032         case 36:
1033         handle_op_36:
1034             slotCopy(++sp,
1035                      &slotRawFrame(
1036                           &slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)->context)
1037                           ->vars[ip[1]]);
1038             ++ip;
1039             dispatch_opcode;
1040         case 37:
1041         handle_op_37:
1042             slotCopy(
1043                 ++sp,
1044                 &slotRawFrame(
1045                      &slotRawFrame(
1046                           &slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)->context)
1047                           ->context)
1048                      ->vars[ip[1]]);
1049             ++ip;
1050             dispatch_opcode;
1051         case 38:
1052         handle_op_38:
1053             slotCopy(++sp,
1054                      &slotRawFrame(
1055                           &slotRawFrame(
1056                                &slotRawFrame(
1057                                     &slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)
1058                                          ->context)
1059                                     ->context)
1060                                ->context)
1061                           ->vars[ip[1]]);
1062             ++ip;
1063             dispatch_opcode;
1064         case 39:
1065         handle_op_39:
1066             slotCopy(
1067                 ++sp,
1068                 &slotRawFrame(
1069                      &slotRawFrame(
1070                           &slotRawFrame(
1071                                &slotRawFrame(
1072                                     &slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)
1073                                          ->context)
1074                                     ->context)
1075                                ->context)
1076                           ->context)
1077                      ->vars[ip[1]]);
1078             ++ip;
1079             dispatch_opcode;
1080 
1081         // push literal constants.
1082         case 40:
1083         handle_op_40 : {
1084             int ival = ip[1];
1085             ip += 1;
1086             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1087             dispatch_opcode;
1088         }
1089         case 41:
1090         handle_op_41 : {
1091             int ival = (ip[1] << 8) | ip[2];
1092             ip += 2;
1093             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1094             dispatch_opcode;
1095         }
1096         case 42:
1097         handle_op_42 : {
1098             int ival = (ip[1] << 16) | (ip[2] << 8) | ip[3];
1099             ip += 3;
1100             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1101             dispatch_opcode;
1102         }
1103         case 43:
1104         handle_op_43 : {
1105             int ival = (ip[1] << 24) | (ip[2] << 16) | (ip[3] << 8) | ip[4];
1106             ip += 4;
1107             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1108             dispatch_opcode;
1109         }
1110         // push integers.
1111         case 44:
1112         handle_op_44 : {
1113             int ival = (int32)(ip[1] << 24) >> 24;
1114             ip += 1;
1115             ++sp;
1116             SetInt(sp, ival);
1117             dispatch_opcode;
1118         }
1119         case 45:
1120         handle_op_45 : {
1121             int ival = (int32)((ip[1] << 24) | (ip[2] << 16)) >> 16;
1122             ip += 2;
1123             ++sp;
1124             SetInt(sp, ival);
1125             dispatch_opcode;
1126         }
1127         case 46:
1128         handle_op_46 : {
1129             int ival = (int32)((ip[1] << 24) | (ip[2] << 16) | (ip[3] << 8)) >> 8;
1130             ip += 3;
1131             ++sp;
1132             SetInt(sp, ival);
1133             dispatch_opcode;
1134         }
1135         case 47:
1136         handle_op_47 : {
1137             int ival = (int32)((ip[1] << 24) | (ip[2] << 16) | (ip[3] << 8) | ip[4]);
1138             ip += 4;
1139             ++sp;
1140             SetInt(sp, ival);
1141             dispatch_opcode;
1142         }
1143 
1144         // opPushTempZeroVar
1145         case 48:
1146         handle_op_48:
1147             slotCopy(++sp, &g->frame->vars[0]);
1148             dispatch_opcode;
1149         case 49:
1150         handle_op_49:
1151             slotCopy(++sp, &g->frame->vars[1]);
1152             dispatch_opcode;
1153         case 50:
1154         handle_op_50:
1155             slotCopy(++sp, &g->frame->vars[2]);
1156             dispatch_opcode;
1157         case 51:
1158         handle_op_51:
1159             slotCopy(++sp, &g->frame->vars[3]);
1160             dispatch_opcode;
1161         case 52:
1162         handle_op_52:
1163             slotCopy(++sp, &g->frame->vars[4]);
1164             dispatch_opcode;
1165         case 53:
1166         handle_op_53:
1167             slotCopy(++sp, &g->frame->vars[5]);
1168             dispatch_opcode;
1169         case 54:
1170         handle_op_54:
1171             slotCopy(++sp, &g->frame->vars[6]);
1172             dispatch_opcode;
1173         case 55:
1174         handle_op_55:
1175             slotCopy(++sp, &g->frame->vars[7]);
1176             dispatch_opcode;
1177         case 56:
1178         handle_op_56:
1179             slotCopy(++sp, &g->frame->vars[8]);
1180             dispatch_opcode;
1181         case 57:
1182         handle_op_57:
1183             slotCopy(++sp, &g->frame->vars[9]);
1184             dispatch_opcode;
1185         case 58:
1186         handle_op_58:
1187             slotCopy(++sp, &g->frame->vars[10]);
1188             dispatch_opcode;
1189         case 59:
1190         handle_op_59:
1191             slotCopy(++sp, &g->frame->vars[11]);
1192             dispatch_opcode;
1193         case 60:
1194         handle_op_60:
1195             slotCopy(++sp, &g->frame->vars[12]);
1196             dispatch_opcode;
1197         case 61:
1198         handle_op_61:
1199             slotCopy(++sp, &g->frame->vars[13]);
1200             dispatch_opcode;
1201         case 62:
1202         handle_op_62:
1203             slotCopy(++sp, &g->frame->vars[14]);
1204             dispatch_opcode;
1205         case 63:
1206         handle_op_63:
1207             slotCopy(++sp, &g->frame->vars[15]);
1208             dispatch_opcode;
1209 
1210         // case opPushLiteral
1211         case 64:
1212         handle_op_64:
1213             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[0]);
1214             dispatch_opcode;
1215         case 65:
1216         handle_op_65:
1217             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[1]);
1218             dispatch_opcode;
1219         case 66:
1220         handle_op_66:
1221             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[2]);
1222             dispatch_opcode;
1223         case 67:
1224         handle_op_67:
1225             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[3]);
1226             dispatch_opcode;
1227         case 68:
1228         handle_op_68:
1229             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[4]);
1230             dispatch_opcode;
1231         case 69:
1232         handle_op_69:
1233             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[5]);
1234             dispatch_opcode;
1235         case 70:
1236         handle_op_70:
1237             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[6]);
1238             dispatch_opcode;
1239         case 71:
1240         handle_op_71:
1241             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[7]);
1242             dispatch_opcode;
1243         case 72:
1244         handle_op_72:
1245             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[8]);
1246             dispatch_opcode;
1247         case 73:
1248         handle_op_73:
1249             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[9]);
1250             dispatch_opcode;
1251         case 74:
1252         handle_op_74:
1253             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[10]);
1254             dispatch_opcode;
1255         case 75:
1256         handle_op_75:
1257             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[11]);
1258             dispatch_opcode;
1259         case 76:
1260         handle_op_76:
1261             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[12]);
1262             dispatch_opcode;
1263         case 77:
1264         handle_op_77:
1265             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[13]);
1266             dispatch_opcode;
1267         case 78:
1268         handle_op_78:
1269             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[14]);
1270             dispatch_opcode;
1271         case 79:
1272         handle_op_79:
1273             slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[15]);
1274             dispatch_opcode;
1275 
1276         // opPushClassVar
1277         case 80:
1278         handle_op_80:
1279             handlePushClassVar(g, sp, ip, 0);
1280             dispatch_opcode;
1281         case 81:
1282         handle_op_81:
1283             handlePushClassVar(g, sp, ip, 1);
1284             dispatch_opcode;
1285         case 82:
1286         handle_op_82:
1287             handlePushClassVar(g, sp, ip, 2);
1288             dispatch_opcode;
1289         case 83:
1290         handle_op_83:
1291             handlePushClassVar(g, sp, ip, 3);
1292             dispatch_opcode;
1293         case 84:
1294         handle_op_84:
1295             handlePushClassVar(g, sp, ip, 4);
1296             dispatch_opcode;
1297         case 85:
1298         handle_op_85:
1299             handlePushClassVar(g, sp, ip, 5);
1300             dispatch_opcode;
1301         case 86:
1302         handle_op_86:
1303             handlePushClassVar(g, sp, ip, 6);
1304             dispatch_opcode;
1305         case 87:
1306         handle_op_87:
1307             handlePushClassVar(g, sp, ip, 7);
1308             dispatch_opcode;
1309         case 88:
1310         handle_op_88:
1311             handlePushClassVar(g, sp, ip, 8);
1312             dispatch_opcode;
1313         case 89:
1314         handle_op_89:
1315             handlePushClassVar(g, sp, ip, 9);
1316             dispatch_opcode;
1317         case 90:
1318         handle_op_90:
1319             handlePushClassVar(g, sp, ip, 10);
1320             dispatch_opcode;
1321         case 91:
1322         handle_op_91:
1323             handlePushClassVar(g, sp, ip, 11);
1324             dispatch_opcode;
1325         case 92:
1326         handle_op_92:
1327             handlePushClassVar(g, sp, ip, 12);
1328             dispatch_opcode;
1329         case 93:
1330         handle_op_93:
1331             handlePushClassVar(g, sp, ip, 13);
1332             dispatch_opcode;
1333         case 94:
1334         handle_op_94:
1335             handlePushClassVar(g, sp, ip, 14);
1336             dispatch_opcode;
1337         case 95:
1338         handle_op_95:
1339             handlePushClassVar(g, sp, ip, 15);
1340             dispatch_opcode;
1341 
1342         // opPushSpecialValue
1343         case 96:
1344         handle_op_96:
1345             slotCopy(++sp, &g->receiver);
1346             dispatch_opcode;
1347         case 97: // push one and subtract
1348         handle_op_97:
1349             if (IsInt(sp)) {
1350                 SetRaw(sp, slotRawInt(sp) - 1);
1351 #if TAILCALLOPTIMIZE
1352                 g->tailCall = 0;
1353 #endif
1354             } else {
1355                 slotCopy(++sp, &gSpecialValues[svOne]);
1356                 g->sp = sp;
1357                 g->ip = ip;
1358                 g->primitiveIndex = opSub;
1359                 prSubNum(g, -1);
1360                 sp = g->sp;
1361                 ip = g->ip;
1362             }
1363             dispatch_opcode;
1364         case 98:
1365         handle_op_98:
1366             slotCopy(++sp, &gSpecialValues[svNegOne]);
1367             dispatch_opcode;
1368         case 99:
1369         handle_op_99:
1370             slotCopy(++sp, &gSpecialValues[svZero]);
1371             dispatch_opcode;
1372         case 100:
1373         handle_op_100:
1374             slotCopy(++sp, &gSpecialValues[svOne]);
1375             dispatch_opcode;
1376         case 101:
1377         handle_op_101:
1378             slotCopy(++sp, &gSpecialValues[svTwo]);
1379             dispatch_opcode;
1380         case 102:
1381         handle_op_102:
1382             slotCopy(++sp, &gSpecialValues[svFHalf]);
1383             dispatch_opcode;
1384         case 103:
1385         handle_op_103:
1386             slotCopy(++sp, &gSpecialValues[svFNegOne]);
1387             dispatch_opcode;
1388         case 104:
1389         handle_op_104:
1390             slotCopy(++sp, &gSpecialValues[svFZero]);
1391             dispatch_opcode;
1392         case 105:
1393         handle_op_105:
1394             slotCopy(++sp, &gSpecialValues[svFOne]);
1395             dispatch_opcode;
1396         case 106:
1397         handle_op_106:
1398             slotCopy(++sp, &gSpecialValues[svFTwo]);
1399             dispatch_opcode;
1400         case 107: // push one and add
1401         handle_op_107:
1402             if (IsInt(sp)) {
1403                 SetRaw(sp, slotRawInt(sp) + 1);
1404 #if TAILCALLOPTIMIZE
1405                 g->tailCall = 0;
1406 #endif
1407             } else {
1408                 slotCopy(++sp, &gSpecialValues[svOne]);
1409                 g->sp = sp;
1410                 g->ip = ip;
1411                 g->primitiveIndex = opAdd;
1412                 prAddNum(g, -1);
1413                 sp = g->sp;
1414                 ip = g->ip;
1415             }
1416             dispatch_opcode;
1417         case 108:
1418         handle_op_108:
1419             slotCopy(++sp, &gSpecialValues[svTrue]);
1420             dispatch_opcode;
1421         case 109:
1422         handle_op_109:
1423             slotCopy(++sp, &gSpecialValues[svFalse]);
1424             dispatch_opcode;
1425         case 110:
1426         handle_op_110:
1427             slotCopy(++sp, &gSpecialValues[svNil]);
1428             dispatch_opcode;
1429         case 111:
1430         handle_op_111:
1431             slotCopy(++sp, &gSpecialValues[svInf]);
1432             dispatch_opcode;
1433 
1434         // opStoreInstVar, 0..15
1435         case 112:
1436         handle_op_112:
1437             handleStoreInstVar(g, sp, ip, 0);
1438             dispatch_opcode;
1439         case 113:
1440         handle_op_113:
1441             handleStoreInstVar(g, sp, ip, 1);
1442             dispatch_opcode;
1443         case 114:
1444         handle_op_114:
1445             handleStoreInstVar(g, sp, ip, 2);
1446             dispatch_opcode;
1447         case 115:
1448         handle_op_115:
1449             handleStoreInstVar(g, sp, ip, 3);
1450             dispatch_opcode;
1451         case 116:
1452         handle_op_116:
1453             handleStoreInstVar(g, sp, ip, 4);
1454             dispatch_opcode;
1455         case 117:
1456         handle_op_117:
1457             handleStoreInstVar(g, sp, ip, 5);
1458             dispatch_opcode;
1459         case 118:
1460         handle_op_118:
1461             handleStoreInstVar(g, sp, ip, 6);
1462             dispatch_opcode;
1463         case 119:
1464         handle_op_119:
1465             handleStoreInstVar(g, sp, ip, 7);
1466             dispatch_opcode;
1467         case 120:
1468         handle_op_120:
1469             handleStoreInstVar(g, sp, ip, 8);
1470             dispatch_opcode;
1471         case 121:
1472         handle_op_121:
1473             handleStoreInstVar(g, sp, ip, 9);
1474             dispatch_opcode;
1475         case 122:
1476         handle_op_122:
1477             handleStoreInstVar(g, sp, ip, 10);
1478             dispatch_opcode;
1479         case 123:
1480         handle_op_123:
1481             handleStoreInstVar(g, sp, ip, 11);
1482             dispatch_opcode;
1483         case 124:
1484         handle_op_124:
1485             handleStoreInstVar(g, sp, ip, 12);
1486             dispatch_opcode;
1487         case 125:
1488         handle_op_125:
1489             handleStoreInstVar(g, sp, ip, 13);
1490             dispatch_opcode;
1491         case 126:
1492         handle_op_126:
1493             handleStoreInstVar(g, sp, ip, 14);
1494             dispatch_opcode;
1495         case 127:
1496         handle_op_127:
1497             handleStoreInstVar(g, sp, ip, 15);
1498             dispatch_opcode;
1499 
1500         // opStoreTempVar
1501         case 128:
1502         handle_op_128 : {
1503             int op3 = ip[1];
1504             ++ip; // get temp var index
1505             PyrFrame* tframe = g->frame; // zero level
1506             slot = tframe->vars + op3;
1507             slotCopy(slot, sp--);
1508             g->gc->GCWrite(tframe, slot);
1509             dispatch_opcode;
1510         }
1511 
1512         case 129:
1513         handle_op_129 : {
1514             int op3 = ip[1];
1515             ++ip; // get temp var index
1516             PyrFrame* tframe = slotRawFrame(&g->frame->context); // one level
1517             slot = tframe->vars + op3;
1518             slotCopy(slot, sp--);
1519             g->gc->GCWrite(tframe, slot);
1520             dispatch_opcode;
1521         }
1522 
1523         case 130:
1524         handle_op_130 : {
1525             int op3 = ip[1];
1526             ++ip; // get temp var index
1527             PyrFrame* tframe = slotRawFrame(&slotRawFrame(&g->frame->context)->context); // two levels
1528             slot = tframe->vars + op3;
1529             slotCopy(slot, sp--);
1530             g->gc->GCWrite(tframe, slot);
1531             dispatch_opcode;
1532         }
1533 
1534         case 131:
1535         handle_op_131 : {
1536             int op3 = ip[1];
1537             ++ip; // get temp var index
1538             PyrFrame* tframe =
1539                 slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context); // three levels
1540             slot = tframe->vars + op3;
1541             slotCopy(slot, sp--);
1542             g->gc->GCWrite(tframe, slot);
1543             dispatch_opcode;
1544         }
1545 
1546         case 132:
1547         handle_op_132 : {
1548             int op3 = ip[1];
1549             ++ip; // get temp var index
1550             PyrFrame* tframe =
1551                 slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)
1552                                   ->context); // four levels
1553             slot = tframe->vars + op3;
1554             slotCopy(slot, sp--);
1555             g->gc->GCWrite(tframe, slot);
1556             dispatch_opcode;
1557         }
1558 
1559         case 133:
1560         case 134:
1561         case 135:
1562         handle_op_133:
1563         handle_op_134:
1564         handle_op_135 : {
1565             int op2 = op1 & 15;
1566             int op3 = ip[1];
1567             ++ip; // get temp var index
1568             PyrFrame* tframe = g->frame;
1569             for (; op2--; tframe = slotRawFrame(&tframe->context)) { /* noop */
1570             }
1571             slot = tframe->vars + op3;
1572             slotCopy(slot, sp);
1573             g->gc->GCWrite(tframe, slot);
1574             dispatch_opcode;
1575         }
1576 
1577         case 136: // push inst var, send special selector
1578         handle_op_136 : {
1579             int op2 = ip[1]; // get inst var index
1580             int op3 = ip[2]; // get selector
1581             ip += 2;
1582 
1583             slotCopy(++sp, &slotRawObject(&g->receiver)->slots[op2]);
1584 
1585             numArgsPushed = 1;
1586             selector = gSpecialSelectors[op3];
1587             slot = sp;
1588 
1589             goto class_lookup;
1590         }
1591 
1592         case 137: // push all args, send msg
1593         handle_op_137 : {
1594             numArgsPushed = METHRAW(g->block)->numargs;
1595             PyrSlot* pslot = g->frame->vars - 1;
1596             for (int m = 0; m < numArgsPushed; ++m)
1597                 *++sp = *++pslot;
1598 
1599             int op2 = ip[1];
1600             ++ip; // get selector index
1601             selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
1602             slot = sp - numArgsPushed + 1;
1603 
1604             goto class_lookup;
1605         }
1606         case 138: // push all but first arg, send msg
1607         handle_op_138 : {
1608             numArgsPushed = METHRAW(g->block)->numargs;
1609             PyrSlot* pslot = g->frame->vars;
1610             for (int m = 0; m < numArgsPushed - 1; ++m)
1611                 *++sp = *++pslot;
1612 
1613             int op2 = ip[1];
1614             ++ip; // get selector index
1615             selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
1616             slot = sp - numArgsPushed + 1;
1617 
1618             goto class_lookup;
1619         }
1620 
1621         case 139: // push all args, send special
1622         handle_op_139 : {
1623             numArgsPushed = METHRAW(g->block)->numargs;
1624             PyrSlot* pslot = g->frame->vars - 1;
1625             for (int m = 0; m < numArgsPushed; ++m)
1626                 *++sp = *++pslot;
1627 
1628             int op2 = ip[1];
1629             ++ip; // get selector
1630             selector = gSpecialSelectors[op2];
1631             slot = sp - numArgsPushed + 1;
1632 
1633             goto class_lookup;
1634         }
1635 
1636         case 140: // push all but first arg, send special
1637         handle_op_140 : {
1638             numArgsPushed = METHRAW(g->block)->numargs;
1639             PyrSlot* pslot = g->frame->vars;
1640             for (int m = 0; m < numArgsPushed - 1; ++m)
1641                 *++sp = *++pslot;
1642 
1643             int op2 = ip[1];
1644             ++ip; // get selector
1645             selector = gSpecialSelectors[op2];
1646             slot = sp - numArgsPushed + 1;
1647 
1648             goto class_lookup;
1649         }
1650 
1651         case 141: // one arg pushed, push all but first arg, send msg
1652         handle_op_141 : {
1653             numArgsPushed = METHRAW(g->block)->numargs + 1;
1654             PyrSlot* pslot = g->frame->vars;
1655             for (int m = 0; m < numArgsPushed - 2; ++m)
1656                 *++sp = *++pslot;
1657 
1658             int op2 = ip[1];
1659             ++ip; // get selector index
1660             selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
1661             slot = sp - numArgsPushed + 1;
1662 
1663             goto class_lookup;
1664         }
1665 
1666         case 142: // one arg pushed, push all but first arg, send special
1667         handle_op_142 : {
1668             numArgsPushed = METHRAW(g->block)->numargs + 1;
1669             PyrSlot* pslot = g->frame->vars;
1670             for (int m = 0; m < numArgsPushed - 2; ++m)
1671                 *++sp = *++pslot;
1672 
1673             int op2 = ip[1];
1674             ++ip; // get selector
1675             selector = gSpecialSelectors[op2];
1676             slot = sp - numArgsPushed + 1;
1677 
1678             goto class_lookup;
1679         }
1680 
1681         case 143: // loop byte codes
1682         handle_op_143 : {
1683             // this is major cheating to speed up often used looping methods
1684             // these byte codes are specific to their method and should only be used there.
1685             int op2 = ip[1];
1686             ++ip; // get which one
1687             switch (op2) {
1688             // Integer-do : 143 0, 143 1
1689             case 0: {
1690                 PyrSlot* vars = g->frame->vars;
1691                 if (slotRawInt(&vars[2]) < slotRawInt(&g->receiver)) {
1692                     slotCopy(++sp, &vars[1]); // push function
1693                     slotCopy(++sp, &vars[2]); // push i
1694                     slotCopy(++sp, &vars[2]); // push i
1695                     // SendSpecialMsg value
1696                     numArgsPushed = 3;
1697                     selector = gSpecialSelectors[opmValue];
1698                     slot = sp - 2;
1699 
1700                     goto class_lookup;
1701                 } else {
1702                     slotCopy(++sp, &g->receiver);
1703                     g->sp = sp;
1704                     g->ip = ip;
1705                     returnFromMethod(g);
1706                     sp = g->sp;
1707                     ip = g->ip;
1708                 }
1709                 dispatch_opcode;
1710             }
1711             case 1:
1712                 --sp; // Drop
1713                 SetRaw(&g->frame->vars[2], slotRawInt(&g->frame->vars[2]) + 1); // inc i
1714                 ip -= 4;
1715                 dispatch_opcode;
1716 
1717             // Integer-reverseDo : 143 2, 143 3, 143 4
1718             case 2:
1719                 SetRaw(&g->frame->vars[2], slotRawInt(&g->receiver) - 1);
1720                 dispatch_opcode;
1721             case 3: {
1722                 PyrSlot* vars = g->frame->vars;
1723                 if (slotRawInt(&vars[2]) >= 0) {
1724                     slotCopy(++sp, &vars[1]); // push function
1725                     slotCopy(++sp, &vars[2]); // push i
1726                     slotCopy(++sp, &vars[3]); // push j
1727                     // SendSpecialMsg value
1728                     numArgsPushed = 3;
1729                     selector = gSpecialSelectors[opmValue];
1730                     slot = sp - 2;
1731 
1732                     goto class_lookup;
1733                 } else {
1734                     slotCopy(++sp, &g->receiver);
1735                     g->sp = sp;
1736                     g->ip = ip;
1737                     returnFromMethod(g);
1738                     sp = g->sp;
1739                     ip = g->ip;
1740                 }
1741                 dispatch_opcode;
1742             }
1743             case 4: {
1744                 --sp; // Drop
1745                 PyrSlot* vars = g->frame->vars;
1746                 SetRaw(&vars[2], slotRawInt(&vars[2]) - 1); // dec i
1747                 SetRaw(&vars[3], slotRawInt(&vars[3]) + 1); // inc j
1748                 ip -= 4;
1749                 dispatch_opcode;
1750             }
1751             // Integer-for : 143 5, 143 6, 143 16
1752             case 5: {
1753                 PyrSlot* vars = g->frame->vars;
1754                 int tag = GetTag(&vars[1]);
1755 
1756                 if (tag != tagInt) {
1757                     if (IsFloat(&vars[1])) {
1758                         // coerce to int
1759                         SetInt(&vars[1], (int32)(slotRawFloat(&vars[1])));
1760                     } else {
1761                         error("Integer-for : endval not a SimpleNumber.\n");
1762 
1763                         slotCopy(++sp, &g->receiver);
1764                         numArgsPushed = 1;
1765                         selector = gSpecialSelectors[opmPrimitiveFailed];
1766                         slot = sp;
1767 
1768                         goto class_lookup;
1769                     }
1770                 }
1771 
1772                 if (slotRawInt(&g->receiver) <= slotRawInt(&vars[1])) {
1773                     SetRaw(&vars[5], 1);
1774                 } else {
1775                     SetRaw(&vars[5], -1);
1776                 }
1777                 slotCopy(&vars[3], &g->receiver);
1778 
1779                 dispatch_opcode;
1780             }
1781             case 6: {
1782                 PyrSlot* vars = g->frame->vars;
1783                 if ((slotRawInt(&vars[5]) > 0 && slotRawInt(&vars[3]) <= slotRawInt(&vars[1]))
1784                     || (slotRawInt(&vars[5]) < 0 && slotRawInt(&vars[3]) >= slotRawInt(&vars[1]))) {
1785                     slotCopy(++sp, &vars[2]); // push function
1786                     slotCopy(++sp, &vars[3]); // push i
1787                     slotCopy(++sp, &vars[4]); // push j
1788                     // SendSpecialMsg value
1789                     numArgsPushed = 3;
1790                     selector = gSpecialSelectors[opmValue];
1791                     slot = sp - 2;
1792 
1793                     goto class_lookup;
1794                 } else {
1795                     slotCopy(++sp, &g->receiver);
1796                     g->sp = sp;
1797                     g->ip = ip;
1798                     returnFromMethod(g);
1799                     sp = g->sp;
1800                     ip = g->ip;
1801                 }
1802                 dispatch_opcode;
1803             }
1804 
1805             // Integer-forBy : 143 7, 143 8, 143 9
1806             case 7: {
1807                 PyrSlot* vars = g->frame->vars;
1808                 // Detect case of a zero-valued stepval argument, which
1809                 // would result in an infinite loop.
1810                 if ((IsFloat(vars + 2) && slotRawFloat(&vars[2]) == 0.0)
1811                     || (IsInt(vars + 2) && slotRawInt(&vars[2]) == 0)) {
1812                     error("Integer-forBy: zero-valued stepval argument.\n");
1813                     slotCopy(++sp, &g->receiver);
1814                     numArgsPushed = 1;
1815                     selector = gSpecialSelectors[opmPrimitiveFailed];
1816                     slot = sp;
1817 
1818                     goto class_lookup;
1819                 }
1820                 // If any argument is floating point we cast all arguments
1821                 // to floating point, including the accumulator. This avoids
1822                 // potential infinite loops due to integer truncation.
1823                 if (IsFloat(vars + 1) || IsFloat(vars + 2)) {
1824                     if (IsInt(vars + 1)) {
1825                         SetFloat(&vars[1], (double)(slotRawInt(&vars[1])));
1826                     }
1827                     if (IsInt(vars + 2)) {
1828                         SetFloat(&vars[2], (double)(slotRawInt(&vars[2])));
1829                     }
1830                     SetFloat(&vars[4], (double)(slotRawInt(&g->receiver)));
1831                 } else {
1832                     int tag = GetTag(&vars[1]);
1833                     if ((tag != tagInt) || NotInt(&vars[2])) {
1834                         error("Integer-forBy : endval or stepval not an Integer or Float.\n");
1835 
1836                         slotCopy(++sp, &g->receiver);
1837                         numArgsPushed = 1;
1838                         selector = gSpecialSelectors[opmPrimitiveFailed];
1839                         slot = sp;
1840 
1841                         goto class_lookup;
1842                     }
1843                     slotCopy(&vars[4], &g->receiver);
1844                 }
1845                 dispatch_opcode;
1846             }
1847             case 8: {
1848                 PyrSlot* vars = g->frame->vars;
1849                 bool continueForBy = false;
1850                 if (IsFloat(vars + 4)) {
1851                     continueForBy = (slotRawFloat(&vars[2]) >= 0.0 && slotRawFloat(&vars[4]) <= slotRawFloat(&vars[1]))
1852                         || (slotRawFloat(&vars[2]) < 0.0 && slotRawFloat(&vars[4]) >= slotRawFloat(&vars[1]));
1853                 } else {
1854                     continueForBy = (slotRawInt(&vars[2]) >= 0 && slotRawInt(&vars[4]) <= slotRawInt(&vars[1]))
1855                         || (slotRawInt(&vars[2]) < 0 && slotRawInt(&vars[4]) >= slotRawInt(&vars[1]));
1856                 }
1857                 if (continueForBy) {
1858                     slotCopy(++sp, &vars[3]); // push function
1859                     slotCopy(++sp, &vars[4]); // push i
1860                     slotCopy(++sp, &vars[5]); // push j
1861                     // SendSpecialMsg value
1862                     numArgsPushed = 3;
1863                     selector = gSpecialSelectors[opmValue];
1864                     slot = sp - 2;
1865 
1866                     goto class_lookup;
1867                 } else {
1868                     slotCopy(++sp, &g->receiver);
1869                     g->sp = sp;
1870                     g->ip = ip;
1871                     returnFromMethod(g);
1872                     sp = g->sp;
1873                     ip = g->ip;
1874                 }
1875                 dispatch_opcode;
1876             }
1877             case 9: {
1878                 --sp; // Drop
1879                 PyrSlot* vars = g->frame->vars;
1880                 if (IsFloat(vars + 4)) {
1881                     SetRaw(&vars[4], slotRawFloat(&vars[4]) + slotRawFloat(&vars[2]));
1882                 } else {
1883                     SetRaw(&vars[4], slotRawInt(&vars[4]) + slotRawInt(&vars[2])); // inc i
1884                 }
1885                 SetRaw(&vars[5], slotRawInt(&vars[5]) + 1); // inc j
1886                 ip -= 4;
1887                 dispatch_opcode;
1888             }
1889             // ArrayedCollection-do : 143 10, 143 1
1890             case 10: {
1891                 // 0 this, 1 func, 2 i
1892                 PyrSlot* vars = g->frame->vars;
1893 
1894                 if (slotRawInt(&vars[2]) < slotRawObject(&g->receiver)->size) {
1895                     slotCopy(++sp, &vars[1]); // push function
1896                     getIndexedSlot(slotRawObject(&g->receiver), ++sp, slotRawInt(&vars[2])); // push this.at(i)
1897                     slotCopy(++sp, &vars[2]); // push i
1898                     // SendSpecialMsg value
1899                     numArgsPushed = 3;
1900                     selector = gSpecialSelectors[opmValue];
1901                     slot = sp - 2;
1902 
1903                     goto class_lookup;
1904                 } else {
1905                     slotCopy(++sp, &g->receiver);
1906                     g->sp = sp;
1907                     g->ip = ip;
1908                     returnFromMethod(g);
1909                     sp = g->sp;
1910                     ip = g->ip;
1911                 }
1912                 dispatch_opcode;
1913             }
1914 
1915             // ArrayedCollection-reverseDo : 143 11, 143 12, 143 4
1916             case 11:
1917                 SetRaw(&g->frame->vars[2], slotRawObject(&g->receiver)->size - 1);
1918                 dispatch_opcode;
1919             case 12: {
1920                 PyrSlot* vars = g->frame->vars;
1921                 if (slotRawInt(&vars[2]) >= 0) {
1922                     slotCopy(++sp, &vars[1]); // push function
1923                     getIndexedSlot(slotRawObject(&g->receiver), ++sp, slotRawInt(&vars[2])); // push this.at(i)
1924                     slotCopy(++sp, &vars[3]); // push j
1925                     // SendSpecialMsg value
1926                     numArgsPushed = 3;
1927                     selector = gSpecialSelectors[opmValue];
1928                     slot = sp - 2;
1929 
1930                     goto class_lookup; // class_lookup:
1931                 } else {
1932                     slotCopy(++sp, &g->receiver);
1933                     g->sp = sp;
1934                     g->ip = ip;
1935                     returnFromMethod(g);
1936                     sp = g->sp;
1937                     ip = g->ip;
1938                 }
1939                 dispatch_opcode;
1940             }
1941 
1942             // Dictionary-keysValuesArrayDo
1943             case 13: {
1944                 PyrSlot* vars = g->frame->vars;
1945 
1946                 if (IsNil(&vars[1])) {
1947                     error("Dictionary-keysValuesArrayDo: first argument should not be nil.\n");
1948 
1949                     slotCopy(++sp, &g->receiver);
1950                     numArgsPushed = 0;
1951                     selector = gSpecialSelectors[opmPrimitiveFailed];
1952                     slot = sp;
1953 
1954                     goto class_lookup;
1955                 }
1956 
1957                 int m = slotRawInt(&vars[3]);
1958                 PyrObject* obj = slotRawObject(&vars[1]);
1959 
1960 
1961                 if (m < obj->size) {
1962                     slot = obj->slots + m; // key
1963                     while (IsNil(slot)) {
1964                         m += 2;
1965                         if (m >= obj->size) {
1966                             SetRaw(&vars[3], m);
1967                             goto keysValuesArrayDo_return;
1968                         }
1969                         slot = obj->slots + m; // key
1970                     }
1971                     SetRaw(&vars[3], m);
1972                     slotCopy(++sp, &vars[2]); // function
1973                     slotCopy(++sp, &slot[0]); // key
1974                     slotCopy(++sp, &slot[1]); // val
1975                     slotCopy(++sp, &vars[4]); // j
1976                     SetRaw(&vars[4], slotRawInt(&vars[4]) + 1);
1977 
1978                     // SendSpecialMsg value
1979                     numArgsPushed = 4;
1980                     selector = gSpecialSelectors[opmValue];
1981                     slot = sp - 3;
1982 
1983                     goto class_lookup; // class_lookup:
1984                 } else {
1985                 keysValuesArrayDo_return:
1986                     slotCopy(++sp, &g->receiver);
1987                     g->sp = sp;
1988                     g->ip = ip;
1989                     returnFromMethod(g);
1990                     sp = g->sp;
1991                     ip = g->ip;
1992                 }
1993                 dispatch_opcode;
1994             }
1995             case 14:
1996                 --sp; // Drop
1997                 SetRaw(&g->frame->vars[3], slotRawInt(&g->frame->vars[3]) + 2); // inc i
1998                 ip -= 4;
1999                 dispatch_opcode;
2000             case 15:
2001                 // unused opcode.
2002                 break;
2003 
2004             case 16: {
2005                 --sp; // Drop
2006                 PyrSlot* vars = g->frame->vars;
2007                 SetRaw(&vars[3], slotRawInt(&vars[3]) + slotRawInt(&vars[5])); // inc i by stepval
2008                 SetRaw(&vars[4], slotRawInt(&vars[4]) + 1); // inc j
2009                 ip -= 4;
2010                 dispatch_opcode;
2011             }
2012 
2013             // Float-do : 143 17, 143 18
2014             case 17: {
2015                 PyrSlot* vars = g->frame->vars;
2016                 if (slotRawFloat(&vars[2]) + 0.5 < slotRawFloat(&g->receiver)) {
2017                     slotCopy(++sp, &vars[1]); // push function
2018                     slotCopy(++sp, &vars[2]); // push i
2019                     slotCopy(++sp, &vars[2]); // push i
2020                     // SendSpecialMsg value
2021                     numArgsPushed = 3;
2022                     selector = gSpecialSelectors[opmValue];
2023                     slot = sp - 2;
2024 
2025                     goto class_lookup;
2026                 } else {
2027                     slotCopy(++sp, &g->receiver);
2028                     g->sp = sp;
2029                     g->ip = ip;
2030                     returnFromMethod(g);
2031                     sp = g->sp;
2032                     ip = g->ip;
2033                 }
2034                 dispatch_opcode;
2035             }
2036             case 18: {
2037                 --sp; // Drop
2038                 SetRaw(&g->frame->vars[2], slotRawFloat(&g->frame->vars[2]) + 1.0); // inc i
2039                 ip -= 4;
2040                 dispatch_opcode;
2041             }
2042 
2043             // Float-reverseDo : 143 19, 143 20, 143 21
2044             case 19: {
2045                 SetFloat(&g->frame->vars[2], slotRawFloat(&g->receiver) - 1.0);
2046                 dispatch_opcode;
2047             }
2048             case 20: {
2049                 PyrSlot* vars = g->frame->vars;
2050                 if (slotRawFloat(&vars[2]) + 0.5 >= 0.0) {
2051                     slotCopy(++sp, &vars[1]); // push function
2052                     slotCopy(++sp, &vars[2]); // push i
2053                     slotCopy(++sp, &vars[3]); // push j
2054                     // SendSpecialMsg value
2055                     numArgsPushed = 3;
2056                     selector = gSpecialSelectors[opmValue];
2057                     slot = sp - 2;
2058 
2059                     goto class_lookup;
2060                 } else {
2061                     slotCopy(++sp, &g->receiver);
2062                     g->sp = sp;
2063                     g->ip = ip;
2064                     returnFromMethod(g);
2065                     sp = g->sp;
2066                     ip = g->ip;
2067                 }
2068                 dispatch_opcode;
2069             }
2070             case 21: {
2071                 --sp; // Drop
2072                 PyrSlot* vars = g->frame->vars;
2073                 SetRaw(&vars[2], slotRawFloat(&vars[2]) - 1.0); // dec i
2074                 SetRaw(&vars[3], slotRawFloat(&vars[3]) - 1.0); // inc j
2075                 ip -= 4;
2076                 dispatch_opcode;
2077             }
2078             case 22: // ? question mark method
2079                 --sp;
2080                 if (IsNil(sp)) {
2081                     *sp = *(sp + 1);
2082                 }
2083                 dispatch_opcode;
2084             case 23: // if not nil push this and jump. used to implement ??
2085                 if (NotNil(sp)) {
2086                     int jmplen = (ip[1] << 8) | ip[2];
2087                     ip += jmplen + 2;
2088                 } else {
2089                     --sp;
2090                     ip += 2;
2091                 }
2092                 dispatch_opcode;
2093             case 24: // ifNil
2094                 if (NotNil(sp)) {
2095                     int jmplen = (ip[1] << 8) | ip[2];
2096                     ip += jmplen + 2;
2097                 } else {
2098                     ip += 2;
2099                 }
2100                 --sp;
2101                 dispatch_opcode;
2102             case 25: // ifNotNil
2103                 if (IsNil(sp)) {
2104                     int jmplen = (ip[1] << 8) | ip[2];
2105                     ip += jmplen + 2;
2106                 } else {
2107                     ip += 2;
2108                 }
2109                 --sp;
2110                 dispatch_opcode;
2111             case 26: // ifNotNilPushNil
2112                 if (NotNil(sp)) {
2113                     int jmplen = (ip[1] << 8) | ip[2];
2114                     ip += jmplen + 2;
2115                     slotCopy(sp, &gSpecialValues[svNil]);
2116                 } else {
2117                     ip += 2;
2118                     --sp;
2119                 }
2120                 dispatch_opcode;
2121             case 27: // ifNilPushNil
2122                 if (IsNil(sp)) {
2123                     int jmplen = (ip[1] << 8) | ip[2];
2124                     ip += jmplen + 2;
2125                 } else {
2126                     ip += 2;
2127                     --sp;
2128                 }
2129                 dispatch_opcode;
2130             case 28: { // switch
2131                 PyrObject* obj = slotRawObject(sp);
2132                 op2 = 1 + arrayAtIdentityHashInPairs(obj, (sp - 1));
2133                 sp -= 2;
2134                 ip += slotRawInt(&obj->slots[op2]);
2135                 dispatch_opcode;
2136             }
2137             // Number-forSeries : 143 29, 143 30, 143 31
2138             case 29: {
2139                 PyrSlot* vars = g->frame->vars;
2140                 // 0 receiver, 1 step, 2 last, 3 function, 4 i, 5 j
2141                 if (IsInt(vars + 0) && (IsInt(vars + 1) || IsNil(vars + 1)) && (IsInt(vars + 2) || IsNil(vars + 2))) {
2142                     if (IsNil(vars + 1)) {
2143                         if (IsNil(vars + 2))
2144                             SetInt(vars + 2, 0x7FFFFFFF);
2145                         if (slotRawInt(&vars[0]) < slotRawInt(&vars[2]))
2146                             SetInt(vars + 1, 1);
2147                         else
2148                             SetInt(vars + 1, -1);
2149                     } else {
2150                         if (IsNil(vars + 2)) {
2151                             if (slotRawInt(&vars[1]) < slotRawInt(&vars[0]))
2152                                 SetInt(vars + 2, 0x80000000);
2153                             else
2154                                 SetInt(vars + 2, 0x7FFFFFFF);
2155                         }
2156                         SetInt(vars + 1, slotRawInt(&vars[1]) - slotRawInt(&vars[0]));
2157                     }
2158                     slotCopy(&vars[4], &vars[0]);
2159                 } else {
2160                     if (IsInt(vars + 0)) {
2161                         SetFloat(&vars[4], slotRawInt(&vars[0]));
2162                     } else if (IsFloat(vars + 0)) {
2163                         SetFloat(&vars[4], slotRawFloat(&vars[0]));
2164                     } else {
2165                     bailFromNumberSeries:
2166                         error("Number-forSeries : first, second or last not an Integer or Float.\n");
2167 
2168                         slotCopy(++sp, &g->receiver);
2169                         numArgsPushed = 1;
2170                         selector = gSpecialSelectors[opmPrimitiveFailed];
2171                         slot = sp;
2172 
2173                         goto class_lookup;
2174                     }
2175 
2176                     if (IsNil(vars + 1)) {
2177                         if (IsNil(vars + 2))
2178                             SetFloat(vars + 2, kBigBigFloat);
2179                         else if (IsInt(vars + 2))
2180                             SetFloat(&vars[2], slotRawInt(&vars[2]));
2181                         else if (!IsFloat(vars + 2))
2182                             goto bailFromNumberSeries;
2183 
2184                         if (slotRawFloat(&vars[4]) < slotRawFloat(&vars[2]))
2185                             SetFloat(vars + 1, 1.);
2186                         else
2187                             SetFloat(vars + 1, -1.);
2188                     } else {
2189                         if (IsInt(vars + 1))
2190                             SetFloat(&vars[1], slotRawInt(&vars[1]));
2191                         else if (!IsFloat(vars + 1))
2192                             goto bailFromNumberSeries;
2193 
2194                         if (IsNil(vars + 2)) {
2195                             if (slotRawFloat(&vars[1]) < slotRawFloat(&vars[4]))
2196                                 SetFloat(vars + 2, kSmallSmallFloat);
2197                             else
2198                                 SetFloat(vars + 2, kBigBigFloat);
2199                         } else if (IsInt(vars + 2))
2200                             SetFloat(&vars[2], slotRawInt(&vars[2]));
2201                         else if (!IsFloat(vars + 2))
2202                             goto bailFromNumberSeries;
2203                         SetFloat(vars + 1, slotRawFloat(&vars[1]) - slotRawFloat(&vars[4]));
2204                     }
2205                 }
2206                 dispatch_opcode;
2207             }
2208             case 30: {
2209                 PyrSlot* vars = g->frame->vars;
2210                 int tag = GetTag(&vars[1]);
2211                 if (tag == tagInt) {
2212                     if ((slotRawInt(&vars[1]) >= 0 && slotRawInt(&vars[4]) <= slotRawInt(&vars[2]))
2213                         || (slotRawInt(&vars[1]) < 0 && slotRawInt(&vars[4]) >= slotRawInt(&vars[2]))) {
2214                         slotCopy(++sp, &vars[3]); // push function
2215                         slotCopy(++sp, &vars[4]); // push i
2216                         slotCopy(++sp, &vars[5]); // push j
2217                         // SendSpecialMsg value
2218                         numArgsPushed = 3;
2219                         selector = gSpecialSelectors[opmValue];
2220                         slot = sp - 2;
2221 
2222                         goto class_lookup;
2223                     } else {
2224                         slotCopy(++sp, &g->receiver);
2225                         g->sp = sp;
2226                         g->ip = ip;
2227                         returnFromMethod(g);
2228                         sp = g->sp;
2229                         ip = g->ip;
2230                     }
2231                 } else {
2232                     if ((slotRawFloat(&vars[1]) >= 0. && slotRawFloat(&vars[4]) <= slotRawFloat(&vars[2]))
2233                         || (slotRawFloat(&vars[1]) < 0. && slotRawFloat(&vars[4]) >= slotRawFloat(&vars[2]))) {
2234                         slotCopy(++sp, &vars[3]); // push function
2235                         slotCopy(++sp, &vars[4]); // push i
2236                         slotCopy(++sp, &vars[5]); // push j
2237                         // SendSpecialMsg value
2238                         numArgsPushed = 3;
2239                         selector = gSpecialSelectors[opmValue];
2240                         slot = sp - 2;
2241 
2242                         goto class_lookup;
2243                     } else {
2244                         slotCopy(++sp, &g->receiver);
2245                         g->sp = sp;
2246                         g->ip = ip;
2247                         returnFromMethod(g);
2248                         sp = g->sp;
2249                         ip = g->ip;
2250                     }
2251                 }
2252                 dispatch_opcode;
2253             }
2254             case 31: {
2255                 --sp; // Drop
2256                 PyrSlot* vars = g->frame->vars;
2257 
2258                 int tag = GetTag(&vars[1]);
2259                 if (tag == tagInt) {
2260                     SetRaw(&vars[4], slotRawInt(&vars[4]) + slotRawInt(&vars[1])); // inc i
2261                 } else {
2262                     SetRaw(&vars[4], slotRawFloat(&vars[4]) + slotRawFloat(&vars[1])); // inc i
2263                 }
2264                 SetRaw(&vars[5], slotRawInt(&vars[5]) + 1); // inc j
2265                 ip -= 4;
2266                 dispatch_opcode;
2267             }
2268             }
2269             dispatch_opcode;
2270         }
2271 
2272 
2273         // opStoreClassVar
2274         case 144:
2275         case 145:
2276         case 146:
2277         case 147:
2278         case 148:
2279         case 149:
2280         case 150:
2281         case 151:
2282         case 152:
2283         case 153:
2284         case 154:
2285         case 155:
2286         case 156:
2287         case 157:
2288         case 158:
2289         case 159:
2290         handle_op_144:
2291         handle_op_145:
2292         handle_op_146:
2293         handle_op_147:
2294         handle_op_148:
2295         handle_op_149:
2296         handle_op_150:
2297         handle_op_151:
2298         handle_op_152:
2299         handle_op_153:
2300         handle_op_154:
2301         handle_op_155:
2302         handle_op_156:
2303         handle_op_157:
2304         handle_op_158:
2305         handle_op_159 : {
2306             int op2 = op1 & 15;
2307             int op3 = ip[1];
2308             ++ip; // get class var index
2309             slotCopy(&g->classvars->slots[(op2 << 8) | op3], sp--);
2310             g->gc->GCWrite(g->classvars, (sp + 1));
2311             dispatch_opcode;
2312         }
2313 
2314         // opSendMsg
2315         case 160:
2316         handle_op_160 : {
2317             // special case for this as only arg
2318             int op2 = ip[1];
2319             ++ip; // get selector index
2320             slotCopy(++sp, &g->receiver);
2321             numArgsPushed = 1;
2322             selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2323             slot = sp;
2324 
2325             goto class_lookup;
2326         }
2327 
2328         case 161:
2329         case 162:
2330         case 163:
2331         case 164:
2332         case 165:
2333         case 166:
2334         case 167:
2335         case 168:
2336         case 169:
2337         case 170:
2338         case 171:
2339         case 172:
2340         case 173:
2341         case 174:
2342         case 175:
2343         handle_op_161:
2344         handle_op_162:
2345         handle_op_163:
2346         handle_op_164:
2347         handle_op_165:
2348         handle_op_166:
2349         handle_op_167:
2350         handle_op_168:
2351         handle_op_169:
2352         handle_op_170:
2353         handle_op_171:
2354         handle_op_172:
2355         handle_op_173:
2356         handle_op_174:
2357         handle_op_175 : {
2358             int op2 = ip[1];
2359             ++ip; // get selector index
2360             numArgsPushed = op1 & 15;
2361             selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2362             slot = sp - numArgsPushed + 1;
2363 
2364             goto class_lookup;
2365         }
2366 
2367         case 176: // opcTailCallReturnFromFunction
2368         handle_op_176:
2369 #if TAILCALLOPTIMIZE
2370             g->tailCall = 2;
2371 #endif
2372             dispatch_opcode;
2373         // opSuperMsg
2374         case 177:
2375         handle_op_177 : {
2376             // special case for this as only arg
2377             int op2 = ip[1];
2378             ++ip; // get selector index
2379             slotCopy(++sp, &g->receiver);
2380             numArgsPushed = 1;
2381             selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2382             slot = sp;
2383             classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj;
2384 
2385             goto msg_lookup;
2386         }
2387 
2388         case 178:
2389         case 179:
2390         case 180:
2391         case 181:
2392         case 182:
2393         case 183:
2394         case 184:
2395         case 185:
2396         case 186:
2397         case 187:
2398         case 188:
2399         case 189:
2400         case 190:
2401         case 191:
2402 
2403         handle_op_178:
2404         handle_op_179:
2405         handle_op_180:
2406         handle_op_181:
2407         handle_op_182:
2408         handle_op_183:
2409         handle_op_184:
2410         handle_op_185:
2411         handle_op_186:
2412         handle_op_187:
2413         handle_op_188:
2414         handle_op_189:
2415         handle_op_190:
2416         handle_op_191 : {
2417             int op2 = ip[1];
2418             ++ip; // get selector index
2419             numArgsPushed = op1 & 15;
2420             selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2421             slot = sp - numArgsPushed + 1;
2422             classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj;
2423 
2424             goto msg_lookup;
2425         }
2426 
2427         // opSendSpecialMsg
2428         case 192:
2429         handle_op_192 : {
2430             slotCopy(++sp, &g->receiver);
2431             int op2 = ip[1];
2432             ++ip; // get selector index
2433             numArgsPushed = 1;
2434             selector = gSpecialSelectors[op2];
2435             slot = sp;
2436 
2437             goto class_lookup;
2438         }
2439 
2440         case 193:
2441         case 194:
2442         case 195:
2443         case 196:
2444         case 197:
2445         case 198:
2446         case 199:
2447         case 200:
2448         case 201:
2449         case 202:
2450         case 203:
2451         case 204:
2452         case 205:
2453         case 206:
2454         case 207:
2455 
2456         handle_op_193:
2457         handle_op_194:
2458         handle_op_195:
2459         handle_op_196:
2460         handle_op_197:
2461         handle_op_198:
2462         handle_op_199:
2463         handle_op_200:
2464         handle_op_201:
2465         handle_op_202:
2466         handle_op_203:
2467         handle_op_204:
2468         handle_op_205:
2469         handle_op_206:
2470         handle_op_207 : {
2471             int op2 = ip[1];
2472             ++ip; // get selector index
2473             numArgsPushed = op1 & 15;
2474             selector = gSpecialSelectors[op2];
2475             slot = sp - numArgsPushed + 1;
2476 
2477             goto class_lookup;
2478         }
2479 
2480         // opSendSpecialUnaryArithMsg
2481         case 208: // opNeg
2482         handle_op_208:
2483             if (IsFloat(sp)) {
2484                 SetFloat(sp, -slotRawFloat(sp));
2485 #if TAILCALLOPTIMIZE
2486                 g->tailCall = 0;
2487 #endif
2488             } else if (IsInt(sp)) {
2489                 SetRaw(sp, -slotRawInt(sp));
2490 #if TAILCALLOPTIMIZE
2491                 g->tailCall = 0;
2492 #endif
2493             } else
2494                 handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2495             dispatch_opcode;
2496         case 209: // opNot
2497         handle_op_209:
2498             if (IsTrue(sp)) {
2499                 SetTagRaw(sp, tagFalse);
2500 #if TAILCALLOPTIMIZE
2501                 g->tailCall = 0;
2502 #endif
2503             } else if (IsFalse(sp)) {
2504                 SetTagRaw(sp, tagTrue);
2505 #if TAILCALLOPTIMIZE
2506                 g->tailCall = 0;
2507 #endif
2508             } else
2509                 handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2510             dispatch_opcode;
2511         case 210: // opIsNil
2512         handle_op_210:
2513             if (IsNil(sp)) {
2514                 SetTagRaw(sp, tagTrue);
2515             } else {
2516                 slotCopy(sp, &gSpecialValues[svFalse]);
2517             }
2518 #if TAILCALLOPTIMIZE
2519             g->tailCall = 0;
2520 #endif
2521             dispatch_opcode;
2522         case 211: // opNotNil
2523         handle_op_211:
2524             if (NotNil(sp)) {
2525                 slotCopy(sp, &gSpecialValues[svTrue]);
2526             } else {
2527                 SetTagRaw(sp, tagFalse);
2528             }
2529 #if TAILCALLOPTIMIZE
2530             g->tailCall = 0;
2531 #endif
2532             dispatch_opcode;
2533 
2534         case 212:
2535         handle_op_212:
2536             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2537             dispatch_opcode;
2538         case 213:
2539         handle_op_213:
2540             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2541             dispatch_opcode;
2542         case 214:
2543         handle_op_214:
2544             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2545             dispatch_opcode;
2546         case 215:
2547         handle_op_215:
2548             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2549             dispatch_opcode;
2550         case 216:
2551         handle_op_216:
2552             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2553             dispatch_opcode;
2554         case 217:
2555         handle_op_217:
2556             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2557             dispatch_opcode;
2558         case 218:
2559         handle_op_218:
2560             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2561             dispatch_opcode;
2562         case 219:
2563         handle_op_219:
2564             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2565             dispatch_opcode;
2566         case 220:
2567         handle_op_220:
2568             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2569             dispatch_opcode;
2570         case 221:
2571         handle_op_221:
2572             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2573             dispatch_opcode;
2574         case 222:
2575         handle_op_222:
2576             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2577             dispatch_opcode;
2578         case 223:
2579         handle_op_223:
2580             handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2581             dispatch_opcode;
2582 
2583 
2584         // opSendSpecialBinaryArithMsg
2585         case 224: // add
2586         handle_op_224:
2587             if (IsInt(sp - 1)) {
2588                 if (IsInt(sp)) {
2589                     --sp;
2590                     SetRaw(sp, slotRawInt(sp) + slotRawInt(sp + 1));
2591 #if TAILCALLOPTIMIZE
2592                     g->tailCall = 0;
2593 #endif
2594                 } else {
2595                     g->sp = sp;
2596                     g->ip = ip;
2597                     g->primitiveIndex = opAdd;
2598                     prAddInt(g, -1);
2599                     sp = g->sp;
2600                     ip = g->ip;
2601                 }
2602             } else {
2603                 g->sp = sp;
2604                 g->ip = ip;
2605                 g->primitiveIndex = opAdd;
2606                 prAddNum(g, -1);
2607                 sp = g->sp;
2608                 ip = g->ip;
2609             }
2610             dispatch_opcode;
2611         case 225: // subtract
2612         handle_op_225:
2613             if (IsInt(sp - 1)) {
2614                 if (IsInt(sp)) {
2615                     --sp;
2616                     SetRaw(sp, slotRawInt(sp) - slotRawInt(sp + 1));
2617 #if TAILCALLOPTIMIZE
2618                     g->tailCall = 0;
2619 #endif
2620                 } else {
2621                     g->sp = sp;
2622                     g->ip = ip;
2623                     g->primitiveIndex = opSub;
2624                     prSubInt(g, -1);
2625                     sp = g->sp;
2626                     ip = g->ip;
2627                 }
2628             } else {
2629                 g->sp = sp;
2630                 g->ip = ip;
2631                 g->primitiveIndex = opSub;
2632                 prSubNum(g, -1);
2633                 sp = g->sp;
2634                 ip = g->ip;
2635             }
2636             dispatch_opcode;
2637         case 226: // multiply
2638         handle_op_226:
2639             if (IsInt(sp - 1)) {
2640                 if (IsInt(sp)) {
2641                     --sp;
2642                     SetRaw(sp, slotRawInt(sp) * slotRawInt(sp + 1));
2643 #if TAILCALLOPTIMIZE
2644                     g->tailCall = 0;
2645 #endif
2646                 } else {
2647                     g->sp = sp;
2648                     g->ip = ip;
2649                     g->primitiveIndex = opMul;
2650                     prMulInt(g, -1);
2651                     sp = g->sp;
2652                     ip = g->ip;
2653                 }
2654             } else {
2655                 g->sp = sp;
2656                 g->ip = ip;
2657                 g->primitiveIndex = opMul;
2658                 prMulNum(g, -1);
2659                 sp = g->sp;
2660                 ip = g->ip;
2661             }
2662             dispatch_opcode;
2663 
2664         case 227:
2665         handle_op_227:
2666             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2667             dispatch_opcode;
2668         case 228:
2669         handle_op_228:
2670             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2671             dispatch_opcode;
2672         case 229:
2673         handle_op_229:
2674             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2675             dispatch_opcode;
2676         case 230:
2677         handle_op_230:
2678             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2679             dispatch_opcode;
2680         case 231:
2681         handle_op_231:
2682             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2683             dispatch_opcode;
2684         case 232:
2685         handle_op_232:
2686             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2687             dispatch_opcode;
2688         case 233:
2689         handle_op_233:
2690             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2691             dispatch_opcode;
2692         case 234:
2693         handle_op_234:
2694             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2695             dispatch_opcode;
2696         case 235:
2697         handle_op_235:
2698             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2699             dispatch_opcode;
2700         case 236:
2701         handle_op_236:
2702             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2703             dispatch_opcode;
2704         case 237:
2705         handle_op_237:
2706             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2707             dispatch_opcode;
2708         case 238:
2709         handle_op_238:
2710             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2711             dispatch_opcode;
2712         case 239:
2713         handle_op_239:
2714             handleSendSpecialBinaryArithMsg(g, sp, ip, op1);
2715             dispatch_opcode;
2716 
2717         // opSpecialOpcodes
2718         case 240:
2719         handle_op_240:
2720             --sp;
2721             dispatch_opcode; // opDrop
2722         case 241:
2723         handle_op_241:
2724             ++sp;
2725             *sp = sp[-1];
2726             dispatch_opcode; // opDup
2727         case 242: // opcFunctionReturn
2728         handle_op_242:
2729             g->sp = sp;
2730             g->ip = ip;
2731             returnFromBlock(g);
2732             sp = g->sp;
2733             ip = g->ip;
2734             dispatch_opcode;
2735         case 243: // opcReturn
2736         handle_op_243:
2737             g->sp = sp;
2738             g->ip = ip;
2739             returnFromMethod(g);
2740             sp = g->sp;
2741             ip = g->ip;
2742             dispatch_opcode;
2743         case 244: // opcReturnSelf
2744         handle_op_244:
2745             slotCopy(++sp, &g->receiver);
2746             g->sp = sp;
2747             g->ip = ip;
2748             returnFromMethod(g);
2749             sp = g->sp;
2750             ip = g->ip;
2751             dispatch_opcode;
2752         case 245: // opcReturnTrue
2753         handle_op_245:
2754             slotCopy(++sp, &gSpecialValues[svTrue]);
2755             g->sp = sp;
2756             g->ip = ip;
2757             returnFromMethod(g);
2758             sp = g->sp;
2759             ip = g->ip;
2760             dispatch_opcode;
2761         case 246: // opcReturnFalse
2762         handle_op_246:
2763             slotCopy(++sp, &gSpecialValues[svFalse]);
2764             g->sp = sp;
2765             g->ip = ip;
2766             returnFromMethod(g);
2767             sp = g->sp;
2768             ip = g->ip;
2769             dispatch_opcode;
2770         case 247: // opcReturnNil
2771         handle_op_247:
2772             slotCopy(++sp, &gSpecialValues[svNil]);
2773             g->sp = sp;
2774             g->ip = ip;
2775             returnFromMethod(g);
2776             sp = g->sp;
2777             ip = g->ip;
2778             dispatch_opcode;
2779 
2780         case 248: // opcJumpIfFalse
2781         handle_op_248:
2782             // cannot compare with o_false because it is NaN
2783             if (IsFalse(sp)) {
2784                 int jmplen = (ip[1] << 8) | ip[2];
2785                 ip += jmplen + 2;
2786             } else if (IsTrue(sp)) {
2787                 ip += 2;
2788             } else {
2789                 numArgsPushed = 1;
2790                 selector = gSpecialSelectors[opmNonBooleanError];
2791                 slot = sp;
2792 
2793                 goto class_lookup;
2794             }
2795             --sp;
2796             dispatch_opcode;
2797         case 249: // opcJumpIfFalsePushNil
2798         handle_op_249:
2799             if (IsFalse(sp)) {
2800                 int jmplen = (ip[1] << 8) | ip[2];
2801                 ip += jmplen + 2;
2802                 slotCopy(sp, &gSpecialValues[svNil]);
2803             } else if (IsTrue(sp)) {
2804                 --sp;
2805                 ip += 2;
2806             } else {
2807                 numArgsPushed = 1;
2808                 selector = gSpecialSelectors[opmNonBooleanError];
2809                 slot = sp;
2810 
2811                 goto class_lookup;
2812             }
2813             dispatch_opcode;
2814         case 250: // opcJumpIfFalsePushFalse
2815         handle_op_250:
2816             if (IsFalse(sp)) {
2817                 int jmplen = (ip[1] << 8) | ip[2];
2818                 ip += jmplen + 2;
2819                 //*sp = r_false;
2820             } else if (IsTrue(sp)) {
2821                 --sp;
2822                 ip += 2;
2823             } else {
2824                 numArgsPushed = 1;
2825                 selector = gSpecialSelectors[opmNonBooleanError];
2826                 slot = sp;
2827 
2828                 goto class_lookup;
2829             }
2830             dispatch_opcode;
2831         case 251: // opcJumpIfTruePushTrue
2832         handle_op_251:
2833             if (IsFalse(sp)) {
2834                 --sp;
2835                 ip += 2;
2836             } else if (IsTrue(sp)) {
2837                 int jmplen = (ip[1] << 8) | ip[2];
2838                 ip += jmplen + 2;
2839                 slotCopy(sp, &gSpecialValues[svTrue]);
2840             } else {
2841                 numArgsPushed = 1;
2842                 selector = gSpecialSelectors[opmNonBooleanError];
2843                 slot = sp;
2844 
2845                 goto class_lookup;
2846             }
2847             dispatch_opcode;
2848         case 252: // opcJumpFwd
2849         handle_op_252 : {
2850             int jmplen = (ip[1] << 8) | ip[2];
2851             ip += jmplen + 2;
2852             dispatch_opcode;
2853         }
2854         case 253: // opcJumpBak
2855         handle_op_253 : {
2856             --sp; // also drops the stack. This saves an opcode in the while loop
2857                   // which is the only place this opcode is used.
2858             int jmplen = (ip[1] << 8) | ip[2];
2859             ip -= jmplen;
2860 
2861             // assert(g->gc->SanityCheck());
2862             dispatch_opcode;
2863         }
2864         case 254: // opcSpecialBinaryOpWithAdverb
2865         handle_op_254 : {
2866             int op2 = ip[1];
2867             ++ip; // get selector index
2868             g->sp = sp;
2869             g->ip = ip;
2870             g->primitiveIndex = op2;
2871             doSpecialBinaryArithMsg(g, 3, false);
2872             sp = g->sp;
2873             ip = g->ip;
2874             dispatch_opcode;
2875         }
2876         case 255: // opcTailCallReturnFromMethod
2877         handle_op_255:
2878 #if TAILCALLOPTIMIZE
2879             g->tailCall = 1;
2880 #endif
2881             dispatch_opcode;
2882 
2883             ////////////////////////////////////
2884 
2885         class_lookup:
2886             // normal class lookup
2887             classobj = classOfSlot(slot);
2888 
2889             // message sends handled here:
2890         msg_lookup : {
2891             size_t index = slotRawInt(&classobj->classIndex) + selector->u.index;
2892             PyrMethod* meth = nullptr;
2893             if (UNLIKELY((selector->flags & sym_Class) != 0)) {
2894                 // You have sent a message which is a class name. This is a bad thing.
2895                 // There are two cases. It is either an illegitimate classname like
2896                 // 1 FooBaz: 2
2897                 // in which case selector->u.index == 0 and you get a message or it is a real one like
2898                 // 1 Object: 2
2899                 // in which case selector->u.index isn't pointing to a method and you get a segfault. So...
2900                 meth = nullptr;
2901             } else {
2902                 meth = gRowTable[index];
2903             }
2904 
2905             // and now if meth is null, bail out just like if I don't understand it
2906             if (UNLIKELY(meth == nullptr || (slotRawSymbol(&meth->name) != selector))) {
2907                 g->sp = sp;
2908                 g->ip = ip;
2909                 doesNotUnderstand(g, selector, numArgsPushed);
2910                 sp = g->sp;
2911                 ip = g->ip;
2912             } else {
2913                 PyrMethodRaw* methraw = METHRAW(meth);
2914                 switch (methraw->methType) {
2915                 case methNormal: /* normal msg send */
2916                     g->sp = sp;
2917                     g->ip = ip;
2918                     executeMethod(g, meth, numArgsPushed);
2919                     sp = g->sp;
2920                     ip = g->ip;
2921                     break;
2922                 case methReturnSelf: /* return self */
2923                     sp -= numArgsPushed - 1;
2924                     break;
2925                 case methReturnLiteral: /* return literal */
2926                     sp -= numArgsPushed - 1;
2927                     slotCopy(sp, &meth->selectors); /* in this case selectors is just a single value */
2928                     break;
2929                 case methReturnArg: /* return an argument */
2930                     sp -= numArgsPushed - 1;
2931                     index = methraw->specialIndex; // zero is index of the first argument
2932                     if (index < numArgsPushed) {
2933                         slotCopy(sp, sp + index);
2934                     } else {
2935                         slotCopy(sp, &slotRawObject(&meth->prototypeFrame)->slots[index]);
2936                     }
2937                     break;
2938                 case methReturnInstVar: /* return inst var */
2939                     sp -= numArgsPushed - 1;
2940                     index = methraw->specialIndex;
2941                     slotCopy(sp, &slotRawObject(slot)->slots[index]);
2942                     break;
2943                 case methAssignInstVar: { /* assign inst var */
2944                     sp -= numArgsPushed - 1;
2945                     index = methraw->specialIndex;
2946                     PyrObject* obj = slotRawObject(slot);
2947                     if (obj->IsImmutable()) {
2948                         StoreToImmutableB(g, sp, ip);
2949                     } else {
2950                         if (numArgsPushed >= 2) {
2951                             slotCopy(&obj->slots[index], sp + 1);
2952                             g->gc->GCWrite(obj, sp + 1);
2953                         } else {
2954                             slotCopy(&obj->slots[index], &gSpecialValues[svNil]);
2955                         }
2956                         slotCopy(sp, slot);
2957                     }
2958                     break;
2959                 }
2960                 case methReturnClassVar: /* return class var */
2961                     sp -= numArgsPushed - 1;
2962                     slotCopy(sp, &g->classvars->slots[methraw->specialIndex]);
2963                     break;
2964                 case methAssignClassVar: /* assign class var */
2965                     sp -= numArgsPushed - 1;
2966                     if (numArgsPushed >= 2) {
2967                         slotCopy(&g->classvars->slots[methraw->specialIndex], sp + 1);
2968                         g->gc->GCWrite(g->classvars, sp + 1);
2969                     } else
2970                         slotCopy(&g->classvars->slots[methraw->specialIndex], &gSpecialValues[svNil]);
2971                     slotCopy(sp, slot);
2972                     break;
2973                 case methRedirect: /* send a different selector to self */
2974                     if (numArgsPushed < methraw->numargs) { // not enough args pushed
2975                         /* push default arg values */
2976                         PyrSlot* qslot;
2977                         int m, mmax;
2978                         qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
2979                         for (m = 0, mmax = methraw->numargs - numArgsPushed; m < mmax; ++m)
2980                             slotCopy(++sp, ++qslot);
2981                         numArgsPushed = methraw->numargs;
2982                     }
2983                     selector = slotRawSymbol(&meth->selectors);
2984                     goto msg_lookup;
2985                 case methRedirectSuper: /* send a different selector to self */
2986                     if (numArgsPushed < methraw->numargs) { // not enough args pushed
2987                         /* push default arg values */
2988                         PyrSlot* qslot;
2989                         int m, mmax;
2990                         qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
2991                         for (m = 0, mmax = methraw->numargs - numArgsPushed; m < mmax; ++m)
2992                             slotCopy(++sp, ++qslot);
2993                         numArgsPushed = methraw->numargs;
2994                     }
2995                     selector = slotRawSymbol(&meth->selectors);
2996                     classobj = slotRawSymbol(&slotRawClass(&meth->ownerclass)->superclass)->u.classobj;
2997                     goto msg_lookup;
2998                 case methForwardInstVar: /* forward to an instance variable */
2999                     if (numArgsPushed < methraw->numargs) { // not enough args pushed
3000                         /* push default arg values */
3001                         PyrSlot* qslot;
3002                         int m, mmax;
3003                         qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
3004                         for (m = 0, mmax = methraw->numargs - numArgsPushed; m < mmax; ++m)
3005                             slotCopy(++sp, ++qslot);
3006                         numArgsPushed = methraw->numargs;
3007                     }
3008                     selector = slotRawSymbol(&meth->selectors);
3009                     index = methraw->specialIndex;
3010                     slotCopy(slot, &slotRawObject(slot)->slots[index]);
3011 
3012                     classobj = classOfSlot(slot);
3013 
3014                     goto msg_lookup;
3015                 case methForwardClassVar: /* forward to an instance variable */
3016                     if (numArgsPushed < methraw->numargs) { // not enough args pushed
3017                         /* push default arg values */
3018                         PyrSlot* qslot;
3019                         int m, mmax;
3020                         qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
3021                         for (m = 0, mmax = methraw->numargs - numArgsPushed; m < mmax; ++m)
3022                             slotCopy(++sp, ++qslot);
3023                         numArgsPushed = methraw->numargs;
3024                     }
3025                     selector = slotRawSymbol(&meth->selectors);
3026                     slotCopy(slot, &g->classvars->slots[methraw->specialIndex]);
3027 
3028                     classobj = classOfSlot(slot);
3029 
3030                     goto msg_lookup;
3031                 case methPrimitive: /* primitive */
3032                     g->sp = sp;
3033                     g->ip = ip;
3034                     doPrimitive(g, meth, numArgsPushed);
3035                     sp = g->sp;
3036                     ip = g->ip;
3037                     break;
3038                 } // switch (meth->methType)
3039             } // end handle message
3040 #if TAILCALLOPTIMIZE
3041             g->tailCall = 0;
3042 #endif
3043             dispatch_opcode;
3044         }
3045             ////////////////////////////////////
3046 
3047         key_class_lookup:
3048             // normal class lookup
3049             classobj = classOfSlot(slot);
3050 
3051             // message sends handled here:
3052         key_msg_lookup : {
3053             size_t index = slotRawInt(&classobj->classIndex) + selector->u.index;
3054             PyrMethod* meth = gRowTable[index];
3055 
3056             if (UNLIKELY(slotRawSymbol(&meth->name) != selector)) {
3057                 g->sp = sp;
3058                 g->ip = ip;
3059                 doesNotUnderstandWithKeys(g, selector, numArgsPushed, numKeyArgsPushed);
3060                 sp = g->sp;
3061                 ip = g->ip;
3062             } else {
3063                 PyrMethodRaw* methraw;
3064                 methraw = METHRAW(meth);
3065                 switch (methraw->methType) {
3066                 case methNormal: /* normal msg send */
3067                     g->sp = sp;
3068                     g->ip = ip;
3069                     executeMethodWithKeys(g, meth, numArgsPushed, numKeyArgsPushed);
3070                     sp = g->sp;
3071                     ip = g->ip;
3072                     break;
3073                 case methReturnSelf: /* return self */
3074                     sp -= numArgsPushed - 1;
3075                     break;
3076                 case methReturnLiteral: /* return literal */
3077                     sp -= numArgsPushed - 1;
3078                     slotCopy(sp, &meth->selectors); /* in this case selectors is just a single value */
3079                     break;
3080                 case methReturnArg: /* return an argument */
3081                     g->sp = sp;
3082                     numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
3083                     numKeyArgsPushed = 0;
3084                     sp = g->sp;
3085                     sp -= numArgsPushed - 1;
3086                     index = methraw->specialIndex; // zero is index of the first argument
3087                     if (index < numArgsPushed) {
3088                         slotCopy(sp, sp + index);
3089                     } else {
3090                         slotCopy(sp, &slotRawObject(&meth->prototypeFrame)->slots[index]);
3091                     }
3092                     break;
3093                 case methReturnInstVar: /* return inst var */
3094                     sp -= numArgsPushed - 1;
3095                     index = methraw->specialIndex;
3096                     slotCopy(sp, &slotRawObject(slot)->slots[index]);
3097                     break;
3098                 case methAssignInstVar: { /* assign inst var */
3099                     sp -= numArgsPushed - 1;
3100                     numArgsPushed -= numKeyArgsPushed << 1;
3101                     index = methraw->specialIndex;
3102                     PyrObject* obj = slotRawObject(slot);
3103                     if (obj->IsImmutable()) {
3104                         StoreToImmutableB(g, sp, ip);
3105                     } else {
3106                         if (numArgsPushed >= 2) {
3107                             slotCopy(&obj->slots[index], sp + 1);
3108                             g->gc->GCWrite(obj, sp + 1);
3109                         } else
3110                             slotCopy(&obj->slots[index], &gSpecialValues[svNil]);
3111                         slotCopy(sp, slot);
3112                     }
3113                     break;
3114                 }
3115                 case methReturnClassVar: /* return class var */
3116                     sp -= numArgsPushed - 1;
3117                     slotCopy(sp, &g->classvars->slots[methraw->specialIndex]);
3118                     break;
3119                 case methAssignClassVar: /* assign class var */
3120                     sp -= numArgsPushed - 1;
3121                     if (numArgsPushed >= 2) {
3122                         slotCopy(&g->classvars->slots[methraw->specialIndex], sp + 1);
3123                         g->gc->GCWrite(g->classvars, sp + 1);
3124                     } else
3125                         slotCopy(&g->classvars->slots[methraw->specialIndex], &gSpecialValues[svNil]);
3126                     slotCopy(sp, slot);
3127                     break;
3128                 case methRedirect: /* send a different selector to self, e.g. this.subclassResponsibility */
3129                     g->sp = sp;
3130                     numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
3131                     numKeyArgsPushed = 0;
3132                     sp = g->sp;
3133                     selector = slotRawSymbol(&meth->selectors);
3134 
3135                     goto msg_lookup;
3136                 case methRedirectSuper: /* send a different selector to super */
3137                     g->sp = sp;
3138                     numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
3139                     numKeyArgsPushed = 0;
3140                     sp = g->sp;
3141                     selector = slotRawSymbol(&meth->selectors);
3142 
3143                     classobj = slotRawSymbol(&slotRawClass(&meth->ownerclass)->superclass)->u.classobj;
3144 
3145                     goto msg_lookup;
3146                 case methForwardInstVar: /* forward to an instance variable */
3147                     g->sp = sp;
3148                     numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
3149                     numKeyArgsPushed = 0;
3150                     sp = g->sp;
3151                     selector = slotRawSymbol(&meth->selectors);
3152                     index = methraw->specialIndex;
3153                     slotCopy(slot, &slotRawObject(slot)->slots[index]);
3154 
3155                     classobj = classOfSlot(slot);
3156 
3157                     goto msg_lookup;
3158                 case methForwardClassVar: /* forward to an instance variable */
3159                     g->sp = sp;
3160                     numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
3161                     numKeyArgsPushed = 0;
3162                     sp = g->sp;
3163                     selector = slotRawSymbol(&meth->selectors);
3164                     slotCopy(slot, &g->classvars->slots[methraw->specialIndex]);
3165 
3166                     classobj = classOfSlot(slot);
3167 
3168                     goto msg_lookup;
3169                 case methPrimitive: /* primitive */
3170                     g->sp = sp;
3171                     g->ip = ip;
3172                     doPrimitiveWithKeys(g, meth, numArgsPushed, numKeyArgsPushed);
3173                     sp = g->sp;
3174                     ip = g->ip;
3175                     break;
3176                 } // switch (meth->methType)
3177             } // end handle message
3178             numKeyArgsPushed = 0;
3179 #if TAILCALLOPTIMIZE
3180             g->tailCall = 0;
3181 #endif
3182             dispatch_opcode;
3183         }
3184         } // switch(op1)
3185     } // end while(running)
3186 #ifndef _WIN32
3187     running = true; // reset the signal
3188 #endif
3189     g->sp = sp;
3190     g->ip = ip;
3191 }
3192 
3193 
3194 #if defined(__GNUC__) && !defined(__clang__)
3195 #    pragma GCC pop_options
3196 #endif
3197 
3198 
3199 void DumpSimpleBackTrace(VMGlobals* g);
3200 void DumpSimpleBackTrace(VMGlobals* g) {
3201     int i;
3202     PyrFrame* frame;
3203 
3204     post("CALL STACK:\n");
3205     // print the variables and arguments for the most recent frames in the
3206     // call graph
3207     frame = g->frame;
3208 
3209     for (i = 0; i < 16; ++i) {
3210         char str[256];
3211         slotOneWord(&frame->method, str);
3212         post("%s ip %d\n", str,
3213              (char*)slotRawPtr(&frame->ip) - (char*)slotRawObject(&slotRawMethod(&frame->method)->code)->slots);
3214         frame = slotRawFrame(&frame->caller);
3215         if (!frame)
3216             break;
3217     }
3218     if (frame) {
3219         post("...\n");
3220     }
3221     // DumpStack(g, g->sp);
3222 }
3223 
3224 void DumpBackTrace(VMGlobals* g) {
3225     int i;
3226     PyrFrame* frame;
3227 
3228     post("CALL STACK:\n");
3229     // print the variables and arguments for the most recent frames in the
3230     // call graph
3231     frame = g->frame;
3232 
3233     for (i = 0; i < 16; ++i) {
3234         if (FrameSanity(frame, "DumpBackTrace")) {
3235             post("FRAME CORRUPTED\n");
3236             return;
3237         }
3238         DumpFrame(frame);
3239         frame = slotRawFrame(&frame->caller);
3240         if (!frame)
3241             break;
3242     }
3243     if (frame) {
3244         post("...\n");
3245     }
3246     // DumpStack(g, g->sp);
3247 }
3248 
3249 void DumpDetailedFrame(PyrFrame* frame);
3250 void DumpDetailedBackTrace(VMGlobals* g);
3251 void DumpDetailedBackTrace(VMGlobals* g) {
3252     int i;
3253     PyrFrame* frame;
3254 
3255     post("CALL STACK:\n");
3256     // print the variables and arguments for the most recent frames in the
3257     // call graph
3258     frame = g->frame;
3259 
3260     for (i = 0; i < 16; ++i) {
3261         if (FrameSanity(frame, "DumpDetailedBackTrace")) {
3262             post("FRAME CORRUPTED\n");
3263             return;
3264         }
3265         DumpDetailedFrame(frame);
3266         frame = slotRawFrame(&frame->caller);
3267         if (!frame)
3268             break;
3269     }
3270     if (frame) {
3271         post("...\n");
3272     }
3273     // DumpStack(g, g->sp);
3274 }
3275 
3276 void DumpStack(VMGlobals* g, PyrSlot* sp) {
3277     PyrSlot* slot;
3278     char str[128];
3279 #if BCSTAT
3280     dumpbcstat();
3281 #endif
3282     postfl("STACK:\n");
3283     slot = sp - 64;
3284     if (slot < g->gc->Stack()->slots)
3285         slot = g->gc->Stack()->slots;
3286     for (size_t i = slot - g->gc->Stack()->slots; slot <= sp; slot++, ++i) {
3287         slotString(slot, str);
3288         post("   %2d  %s\n", i, str);
3289     }
3290 }
3291