scide: implement selectionLength for openDocument
[supercollider.git] / lang / LangSource / PyrInterpreter3.cpp
blob606625688e54b61360e6f5a3c901da167efa6707
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
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.
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.
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
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>
42 #ifdef SC_WIN32
43 # include "SC_Win32Utils.h"
44 #else
45 # include <sys/time.h>
46 #endif
48 #include <float.h>
49 #define kBigBigFloat DBL_MAX
50 #define kSmallSmallFloat DBL_MIN
53 #include <new>
54 #include "InitAlloc.h"
55 #include "function_attributes.h"
57 //void tellPlugInsAboutToRun();
58 double timeNow();
61 int32 timeseed()
63 struct timeval tv;
64 gettimeofday(&tv, 0);
65 return tv.tv_sec ^ tv.tv_usec;
68 VMGlobals gVMGlobals;
69 VMGlobals *gMainVMGlobals = &gVMGlobals;
71 extern PyrObject *gSynth;
73 void debugf(char *fmt, ...) ;
75 #define DEBUGINTERPRETER 0
76 #define METHODMETER 0
77 #define BCSTAT 0
78 #define CHECK_MAX_STACK_USE 0
81 #if CHECK_MAX_STACK_USE
82 int gMaxStackDepth = 0;
83 #endif
85 unsigned char* dumpOneByteCode(PyrBlock *theBlock, PyrClass* theClass, unsigned char *ip);
86 void dumpSlotOneWord(const char *tagstr, PyrSlot *slot);
87 //bool checkAllObjChecksum(PyrObject* obj);
89 bool gTraceInterpreter = false;
90 //bool gTraceInterpreter = true;
93 const char* byteCodeString(int code);
95 extern int gNumClasses;
96 extern PyrClass *gClassList;
98 // runInterpreter has 7 call sites:
99 // compileLibrary (4)
100 // runLibrary
101 // interpretCmdLine
103 static void endInterpreter(VMGlobals *g);
106 SC_DLLEXPORT_C void runInterpreter(VMGlobals *g, PyrSymbol *selector, int numArgsPushed)
108 //postfl("->runInterpreter\n");
109 #ifdef GC_SANITYCHECK
110 g->gc->SanityCheck();
111 #endif
112 //postfl(" >initInterpreter\n");
114 if (initInterpreter(g, selector, numArgsPushed)) {
115 #ifdef GC_SANITYCHECK
116 g->gc->SanityCheck();
117 #endif
118 // if (strcmp(selector->name, "tick") != 0) post("%s %d execMethod %d\n", selector->name, numArgsPushed, g->execMethod);
119 //post("->Interpret thread %p\n", g->thread);
120 if (g->execMethod) Interpret(g);
121 //post("<-Interpret thread %p\n", g->thread);
122 #ifdef GC_SANITYCHECK
123 g->gc->SanityCheck();
124 #endif
127 //postfl(" >endInterpreter\n");
128 endInterpreter(g);
129 #ifdef GC_SANITYCHECK
130 g->gc->SanityCheck();
131 #endif
132 //postfl("<-runInterpreter\n");
133 //dumpGCStats(g->gc);
136 static bool initAwakeMessage(VMGlobals *g);
138 void runAwakeMessage(VMGlobals *g)
140 if (initAwakeMessage(g)) {
141 if (g->execMethod) Interpret(g);
143 endInterpreter(g);
146 void initPyrThread(VMGlobals *g, PyrThread *thread, PyrSlot *func, int stacksize, PyrInt32Array* rgenArray,
147 double beats, double seconds, PyrSlot* clock, bool collect);
148 int32 timeseed();
150 PyrProcess* newPyrProcess(VMGlobals *g, PyrClass *procclassobj)
152 PyrGC* gc = g->gc;
153 PyrProcess * proc = (PyrProcess*)instantiateObject(gc, procclassobj, 0, true, false);
155 PyrObject *sysSchedulerQueue = newPyrArray(gc, 4096, 0, false);
156 sysSchedulerQueue->size = 1;
157 SetInt(sysSchedulerQueue->slots + 0, 0); // stability count
158 SetObject(&proc->sysSchedulerQueue, sysSchedulerQueue);
160 PyrObject *classVars = newPyrArray(gc, gNumClassVars, 0, false);
161 classVars->size = gNumClassVars;
162 nilSlots(classVars->slots, gNumClassVars);
163 SetObject(&proc->classVars, classVars);
164 g->classvars = classVars;
166 // fill class vars from prototypes:
167 PyrClass * classobj = gClassList;
168 while (classobj) {
169 if (IsObj(&classobj->cprototype)) {
170 int numClassVars = slotRawObject(&classobj->cprototype)->size;
171 if (numClassVars > 0) {
172 memcpy(g->classvars->slots + slotRawInt(&classobj->classVarIndex), slotRawObject(&classobj->cprototype)->slots, numClassVars * sizeof(PyrSlot));
175 classobj = slotRawClass(&classobj->nextclass);
178 SetNil(&proc->nowExecutingPath);
180 class_thread = getsym("Thread")->u.classobj;
181 if (class_thread) {
182 SetNil(&proc->curThread);
183 PyrThread * thread = (PyrThread*)instantiateObject(gc, class_thread, 0, true, false);
184 //SetObject(&threadsArray->slots[0], thread);
185 SetObject(&proc->mainThread, thread);
186 PyrInt32Array *rgenArray = newPyrInt32Array(gc, 4, 0, false);
187 rgenArray->size = 4;
188 rgenArray->i[0] = 0;
189 rgenArray->i[1] = 0;
190 rgenArray->i[2] = 0;
191 rgenArray->i[3] = 0;
192 ((RGen*)(rgenArray->i))->init(timeseed());
194 PyrSlot clockSlot;
195 SetObject(&clockSlot, s_systemclock->u.classobj);
196 initPyrThread(g, thread, &o_nil, EVALSTACKDEPTH, rgenArray, 0., 0., &clockSlot, false);
197 //postfl("elapsedTime %.6f\n", elapsedTime());
198 } else {
199 error("Class Thread not found.\n");
202 PyrSymbol * contextsym = getsym("functionCompileContext");
203 size_t index = slotRawInt(&class_interpreter->classIndex) + contextsym->u.index;
204 PyrMethod * meth = gRowTable[index];
205 if (!meth || slotRawSymbol(&meth->name) != contextsym) {
206 error("compile context method 'functionCompileContext' not found.\n");
207 //SetNil(&proc->interpreter);
208 } else {
209 PyrObject *proto;
210 PyrFrame *frame;
211 PyrMethodRaw *methraw;
213 PyrInterpreter * interpreter = (PyrInterpreter*)instantiateObject(gc, class_interpreter, 0, true, false);
214 SetObject(&proc->interpreter, interpreter);
215 proto = slotRawObject(&meth->prototypeFrame);
217 methraw = METHRAW(meth);
218 frame = (PyrFrame*)gc->New(methraw->frameSize, 0, obj_slot, false);
219 frame->classptr = class_frame;
220 frame->size = FRAMESIZE + proto->size; /// <- IS THIS WRONG ??
221 SetObject(&frame->method, meth);
222 SetObject(&frame->homeContext, frame);
223 SetInt(&frame->caller, 0);
224 SetNil(&frame->context);
225 SetPtr(&frame->ip, 0);
226 SetObject(&frame->vars[0], interpreter);
228 SetObject(&interpreter->context, frame);
231 return proc;
235 #if BCSTAT
236 int prevop = 0;
237 int bcstat[256];
238 int bcpair[256][256];
240 void clearbcstat();
241 void clearbcstat()
243 int i, j;
244 for (i=0; i<256; ++i) {
245 bcstat[i] = 0;
246 for (j=0; j<256; ++j) {
247 bcpair[i][j] = 0;
252 void dumpbcstat();
253 void dumpbcstat()
255 FILE *file;
256 int i, j, k, total;
258 file = fopen("bcstat", "w");
259 if (file) {
260 fprintf(file, "----------\n");
261 total = 0;
262 for (i=0; i<256; ++i) {
263 total += bcstat[i];
264 if (bcstat[i]) fprintf(file, "%3d %8d %-32s\n", i, bcstat[i], byteCodeString(i));
266 fprintf(file, "\ntotal %d\n", total);
267 fprintf(file, "-----cur,next-----\n");
268 for (i=0, k=0; i<256; ++i) {
269 for (j=0; j<256; j++) {
270 if (bcpair[i][j] > 0) {
271 fprintf(file, "%4d %3d %3d %8d %-32s %-32s\n", k++, i, j, bcpair[i][j], byteCodeString(i), byteCodeString(j));
275 fprintf(file, "-----cur,prev-----\n");
276 for (i=0, k=0; i<256; ++i) {
277 for (j=0; j<256; j++) {
278 if (bcpair[j][i] > 0) {
279 fprintf(file, "%4d %3d %3d %8d %-32s %-32s\n", k++, i, j, bcpair[j][i], byteCodeString(i), byteCodeString(j));
284 fclose(file);
286 #endif
288 void initPatterns();
289 void initThreads();
290 void initGUI();
292 #ifndef SC_WIN32
293 bool running = true;
294 static void handleSigUsr1(int param)
296 printf("handleSigUsr1()...\n");
297 running = false;
299 #endif
301 bool initRuntime(VMGlobals *g, int poolSize, AllocPool *inPool)
304 create a GC environment
305 create a vmachine instance of main
306 initialize VMGlobals
309 PyrClass * class_main = s_main->u.classobj;
311 if (!class_main) { error("Class 'Main' not defined.\n"); return false; }
312 if (!isSubclassOf(class_main, class_process)) {
313 error("Class Main is not a subclass of Process.\n");
314 return false;
317 // create GC environment, process
318 g->allocPool = inPool;
319 g->gc = (PyrGC*)g->allocPool->Alloc(sizeof(PyrGC));
320 new (g->gc) PyrGC(g, g->allocPool, class_main, poolSize);
321 g->thread = slotRawThread(&g->process->mainThread);
322 SetObject(&g->receiver, g->process);
324 // these will be set up when the run method is called
325 g->method = NULL;
326 g->block = NULL;
327 g->frame = NULL;
328 g->ip = NULL;
330 // initialize process random number generator
331 g->rgen = (RGen*)(slotRawObject(&g->thread->randData)->slots);
333 //initUGenFuncs();
334 signal_init_globs();
335 initThreads();
336 initPatterns();
337 initUniqueMethods();
338 initGUI();
339 #ifdef GC_SANITYCHECK
340 g->gc->SanityCheck();
341 #endif
342 //tellPlugInsAboutToRun();
344 #ifndef SC_WIN32
345 signal(SIGUSR1,handleSigUsr1);
346 #endif
348 assert((g->gc->SanityCheck()));
349 #ifdef GC_SANITYCHECK
350 g->gc->SanityCheck();
351 #endif
353 return true;
356 static bool initAwakeMessage(VMGlobals *g)
358 //post("initAwakeMessage %p %p\n", g->thread, slotRawThread(&g->process->mainThread));
359 slotCopy(&g->process->curThread, &g->process->mainThread); //??
360 g->thread = slotRawThread(&g->process->mainThread); //??
362 // these will be set up when the run method is called
363 g->method = NULL;
364 g->block = NULL;
365 g->frame = NULL;
366 g->ip = NULL;
367 g->execMethod = 0;
369 // set process as the receiver
370 PyrSlot *slot = g->sp - 3;
371 slotCopy(&g->receiver, slot);
373 SetFloat(&g->thread->beats, slotRawFloat(&slot[1]));
374 SetFloat(&g->thread->seconds, slotRawFloat(&slot[2]));
375 slotCopy(&g->thread->clock, &slot[3]);
376 g->gc->GCWrite(g->thread, slot+3);
378 // start it
379 sendMessage(g, s_awake, 4);
381 return g->method != NULL;
384 bool initInterpreter(VMGlobals *g, PyrSymbol *selector, int numArgsPushed)
386 slotCopy(&g->process->curThread, &g->process->mainThread);
387 g->thread = slotRawThread(&g->process->mainThread);
389 // these will be set up when the run method is called
390 #if TAILCALLOPTIMIZE
391 g->tailCall = 0;
392 #endif
393 g->method = NULL;
394 g->block = NULL;
395 g->frame = NULL;
396 g->ip = NULL;
397 g->execMethod = 0;
398 double elapsed = elapsedTime();
399 SetFloat(&g->thread->beats, elapsed);
400 SetFloat(&g->thread->seconds, elapsed);
401 SetObject(&g->thread->clock, s_systemclock->u.classobj);
402 g->gc->GCWrite(g->thread, s_systemclock->u.classobj);
404 // set process as the receiver
405 PyrSlot *slot = g->sp - numArgsPushed + 1;
406 slotCopy(&g->receiver, slot);
408 // start it
409 sendMessage(g, selector, numArgsPushed);
411 return g->method != NULL;
415 static void endInterpreter(VMGlobals *g)
417 slotCopy(&g->result, g->sp);
418 // dumpObjectSlot(&g->result);
419 g->gc->Stack()->size = 0;
420 g->sp = g->gc->Stack()->slots - 1;
421 g->gc->LazyCollect();
425 static void StoreToImmutableA(VMGlobals *g, PyrSlot *& sp, unsigned char *& ip)
427 // only the value is on the stack
428 slotCopy(sp + 1, sp); // copy value up one
429 slotCopy(sp, &g->receiver); // put receiver in place
430 sp++;
431 g->sp = sp;
432 g->ip = ip;
433 post("StoreToImmutableA\n");
434 dumpObjectSlot(sp-1);
435 dumpObjectSlot(sp);
436 sendMessage(g, getsym("immutableError"), 2);
437 sp = g->sp;
438 ip = g->ip;
441 void StoreToImmutableB(VMGlobals *g, PyrSlot *& sp, unsigned char *& ip)
443 // receiver and value are on the stack.
444 sp++;
445 g->sp = sp;
446 g->ip = ip;
447 post("StoreToImmutableB\n");
448 dumpObjectSlot(sp-1);
449 dumpObjectSlot(sp);
450 PyrSymbol *selector = getsym("immutableError");
451 sendMessage(g, selector, 2);
452 sp = g->sp;
453 ip = g->ip;
457 void dumpByteCodes(PyrBlock *theBlock);
459 static inline void handlePushClassVar(VMGlobals* g, PyrSlot *& sp, unsigned char *& ip, unsigned char op2)
461 unsigned char op3 = ip[1]; ++ip; // get class var index
462 slotCopy(++sp, &g->classvars->slots[(op2<<8)|op3]);
465 static inline void handleStoreInstVar(VMGlobals* g, PyrSlot *& sp, unsigned char *& ip, unsigned int index)
467 PyrObject* obj = slotRawObject(&g->receiver);
468 if (obj->IsImmutable())
469 StoreToImmutableA(g, sp, ip);
470 else {
471 PyrSlot * slot = obj->slots + index;
472 slotCopy(slot, sp--);
473 g->gc->GCWrite(obj, slot);
477 static inline void handleSendSpecialUnaryArithMsg(VMGlobals* g, PyrSlot *& sp, unsigned char *& ip, unsigned char op1)
479 g->sp = sp; g->ip = ip;
480 g->primitiveIndex = op1 & 15;
481 doSpecialUnaryArithMsg(g, -1);
482 sp = g->sp; ip = g->ip;
485 static inline void handleSendSpecialBinaryArithMsg(VMGlobals* g, PyrSlot *& sp, unsigned char *& ip, unsigned char op1)
487 g->sp = sp; g->ip = ip;
488 g->primitiveIndex = op1 & 15;
489 doSpecialBinaryArithMsg(g, 2, false);
490 sp = g->sp; ip = g->ip;
493 static inline bool checkStackOverflow(VMGlobals* g, PyrSlot * sp)
495 PyrObject * stack = g->gc->Stack();
496 int depth = sp - stack->slots;
497 return depth < slotRawInt(&g->thread->stackSize);
500 static inline void checkStackDepth(VMGlobals* g, PyrSlot * sp)
502 #if CHECK_MAX_STACK_USE
503 int stackDepth = sp - g->sp + 1;
504 if (stackDepth > gMaxStackDepth) {
505 gMaxStackDepth = stackDepth;
506 printf("gMaxStackDepth %d\n", gMaxStackDepth);
508 #endif
511 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
512 #define LABELS_AS_VALUES
513 #endif
515 #ifdef LABELS_AS_VALUES
516 #define dispatch_opcode \
517 op1 = ip[1]; \
518 ++ip; \
519 checkStackDepth(g, sp); \
520 assert(checkStackOverflow(g, sp)); \
521 goto *opcode_labels[op1]
522 #else
523 #define dispatch_opcode break
524 #endif
526 #if defined(__GNUC__)
527 #define LIKELY(x) __builtin_expect((x),1)
528 #define UNLIKELY(x) __builtin_expect((x),0)
529 #else
530 #define LIKELY(x) x
531 #define UNLIKELY(x) x
532 #endif
535 HOT void Interpret(VMGlobals *g)
537 // byte code values
538 unsigned char *ip;
539 unsigned char op1;
540 size_t index;
541 int op2, op3, tag;
542 // interpreter globals
544 // temporary variables used in the interpreter
545 int ival, jmplen, numArgsPushed, numKeyArgsPushed;
546 PyrFrame *tframe;
547 PyrSymbol *selector;
548 PyrClass *classobj;
549 PyrSlot *slot, *vars;
550 PyrSlot *sp, *pslot;
551 PyrObject *obj;
552 PyrClosure *closure;
553 PyrMethod *meth;
554 int m,mmax;
556 #ifdef LABELS_AS_VALUES
557 static void * opcode_labels[] = {
558 &&handle_op_0,
559 &&handle_op_1,
560 &&handle_op_2,
561 &&handle_op_3,
562 &&handle_op_4,
563 &&handle_op_5,
564 &&handle_op_6,
565 &&handle_op_7,
566 &&handle_op_8,
567 &&handle_op_9,
568 &&handle_op_10,
569 &&handle_op_11,
570 &&handle_op_12,
571 &&handle_op_13,
572 &&handle_op_14,
573 &&handle_op_15,
574 &&handle_op_16,
575 &&handle_op_17,
576 &&handle_op_18,
577 &&handle_op_19,
578 &&handle_op_20,
579 &&handle_op_21,
580 &&handle_op_22,
581 &&handle_op_23,
582 &&handle_op_24,
583 &&handle_op_25,
584 &&handle_op_26,
585 &&handle_op_27,
586 &&handle_op_28,
587 &&handle_op_29,
588 &&handle_op_30,
589 &&handle_op_31,
590 &&handle_op_32,
591 &&handle_op_33,
592 &&handle_op_34,
593 &&handle_op_35,
594 &&handle_op_36,
595 &&handle_op_37,
596 &&handle_op_38,
597 &&handle_op_39,
598 &&handle_op_40,
599 &&handle_op_41,
600 &&handle_op_42,
601 &&handle_op_43,
602 &&handle_op_44,
603 &&handle_op_45,
604 &&handle_op_46,
605 &&handle_op_47,
606 &&handle_op_48,
607 &&handle_op_49,
608 &&handle_op_50,
609 &&handle_op_51,
610 &&handle_op_52,
611 &&handle_op_53,
612 &&handle_op_54,
613 &&handle_op_55,
614 &&handle_op_56,
615 &&handle_op_57,
616 &&handle_op_58,
617 &&handle_op_59,
618 &&handle_op_60,
619 &&handle_op_61,
620 &&handle_op_62,
621 &&handle_op_63,
622 &&handle_op_64,
623 &&handle_op_65,
624 &&handle_op_66,
625 &&handle_op_67,
626 &&handle_op_68,
627 &&handle_op_69,
628 &&handle_op_70,
629 &&handle_op_71,
630 &&handle_op_72,
631 &&handle_op_73,
632 &&handle_op_74,
633 &&handle_op_75,
634 &&handle_op_76,
635 &&handle_op_77,
636 &&handle_op_78,
637 &&handle_op_79,
638 &&handle_op_80,
639 &&handle_op_81,
640 &&handle_op_82,
641 &&handle_op_83,
642 &&handle_op_84,
643 &&handle_op_85,
644 &&handle_op_86,
645 &&handle_op_87,
646 &&handle_op_88,
647 &&handle_op_89,
648 &&handle_op_90,
649 &&handle_op_91,
650 &&handle_op_92,
651 &&handle_op_93,
652 &&handle_op_94,
653 &&handle_op_95,
654 &&handle_op_96,
655 &&handle_op_97,
656 &&handle_op_98,
657 &&handle_op_99,
658 &&handle_op_100,
659 &&handle_op_101,
660 &&handle_op_102,
661 &&handle_op_103,
662 &&handle_op_104,
663 &&handle_op_105,
664 &&handle_op_106,
665 &&handle_op_107,
666 &&handle_op_108,
667 &&handle_op_109,
668 &&handle_op_110,
669 &&handle_op_111,
670 &&handle_op_112,
671 &&handle_op_113,
672 &&handle_op_114,
673 &&handle_op_115,
674 &&handle_op_116,
675 &&handle_op_117,
676 &&handle_op_118,
677 &&handle_op_119,
678 &&handle_op_120,
679 &&handle_op_121,
680 &&handle_op_122,
681 &&handle_op_123,
682 &&handle_op_124,
683 &&handle_op_125,
684 &&handle_op_126,
685 &&handle_op_127,
686 &&handle_op_128,
687 &&handle_op_129,
688 &&handle_op_130,
689 &&handle_op_131,
690 &&handle_op_132,
691 &&handle_op_133,
692 &&handle_op_134,
693 &&handle_op_135,
694 &&handle_op_136,
695 &&handle_op_137,
696 &&handle_op_138,
697 &&handle_op_139,
698 &&handle_op_140,
699 &&handle_op_141,
700 &&handle_op_142,
701 &&handle_op_143,
702 &&handle_op_144,
703 &&handle_op_145,
704 &&handle_op_146,
705 &&handle_op_147,
706 &&handle_op_148,
707 &&handle_op_149,
708 &&handle_op_150,
709 &&handle_op_151,
710 &&handle_op_152,
711 &&handle_op_153,
712 &&handle_op_154,
713 &&handle_op_155,
714 &&handle_op_156,
715 &&handle_op_157,
716 &&handle_op_158,
717 &&handle_op_159,
718 &&handle_op_160,
719 &&handle_op_161,
720 &&handle_op_162,
721 &&handle_op_163,
722 &&handle_op_164,
723 &&handle_op_165,
724 &&handle_op_166,
725 &&handle_op_167,
726 &&handle_op_168,
727 &&handle_op_169,
728 &&handle_op_170,
729 &&handle_op_171,
730 &&handle_op_172,
731 &&handle_op_173,
732 &&handle_op_174,
733 &&handle_op_175,
734 &&handle_op_176,
735 &&handle_op_177,
736 &&handle_op_178,
737 &&handle_op_179,
738 &&handle_op_180,
739 &&handle_op_181,
740 &&handle_op_182,
741 &&handle_op_183,
742 &&handle_op_184,
743 &&handle_op_185,
744 &&handle_op_186,
745 &&handle_op_187,
746 &&handle_op_188,
747 &&handle_op_189,
748 &&handle_op_190,
749 &&handle_op_191,
750 &&handle_op_192,
751 &&handle_op_193,
752 &&handle_op_194,
753 &&handle_op_195,
754 &&handle_op_196,
755 &&handle_op_197,
756 &&handle_op_198,
757 &&handle_op_199,
758 &&handle_op_200,
759 &&handle_op_201,
760 &&handle_op_202,
761 &&handle_op_203,
762 &&handle_op_204,
763 &&handle_op_205,
764 &&handle_op_206,
765 &&handle_op_207,
766 &&handle_op_208,
767 &&handle_op_209,
768 &&handle_op_210,
769 &&handle_op_211,
770 &&handle_op_212,
771 &&handle_op_213,
772 &&handle_op_214,
773 &&handle_op_215,
774 &&handle_op_216,
775 &&handle_op_217,
776 &&handle_op_218,
777 &&handle_op_219,
778 &&handle_op_220,
779 &&handle_op_221,
780 &&handle_op_222,
781 &&handle_op_223,
782 &&handle_op_224,
783 &&handle_op_225,
784 &&handle_op_226,
785 &&handle_op_227,
786 &&handle_op_228,
787 &&handle_op_229,
788 &&handle_op_230,
789 &&handle_op_231,
790 &&handle_op_232,
791 &&handle_op_233,
792 &&handle_op_234,
793 &&handle_op_235,
794 &&handle_op_236,
795 &&handle_op_237,
796 &&handle_op_238,
797 &&handle_op_239,
798 &&handle_op_240,
799 &&handle_op_241,
800 &&handle_op_242,
801 &&handle_op_243,
802 &&handle_op_244,
803 &&handle_op_245,
804 &&handle_op_246,
805 &&handle_op_247,
806 &&handle_op_248,
807 &&handle_op_249,
808 &&handle_op_250,
809 &&handle_op_251,
810 &&handle_op_252,
811 &&handle_op_253,
812 &&handle_op_254,
813 &&handle_op_255
816 #endif
818 #if 0
819 unsigned char *bzero;
820 PyrSlot *szero;
821 char str[80];
822 #endif
825 #if BCSTAT
826 //clearbcstat();
827 op1 = 0;
828 prevop = 0;
829 #endif
831 #if 0
832 bzero = g->ip;
833 szero = g->sp;
834 //SetSymbol(g->sp, getsym("STACK TOP")); // just for debugging
835 //g->sp++; // just for debugging
836 #endif
838 // Codewarrior puts them in registers. take advantage..
839 sp = g->sp;
840 ip = g->ip;
842 numKeyArgsPushed = 0;
844 if (setjmp(g->escapeInterpreter) != 0) {
845 return;
847 #ifndef SC_WIN32
848 while (running) { // not going to indent body to save line space
849 #else
850 while (true) {
851 #endif
853 checkStackDepth(g, sp);
855 #if BCSTAT
856 prevop = op1;
857 #endif
859 op1 = ip[1];
860 ++ip;
862 assert(checkStackOverflow(g, sp));
864 #if BCSTAT
865 ++bcstat[op1];
866 ++bcpair[prevop][op1];
867 prevop = op1;
868 #endif
869 //printf("op1 %d\n", op1);
870 //postfl("sp %p frame %p caller %p ip %p\n", sp, g->frame, g->frame->caller.uof, slotRawInt(&g->frame->caller.uof->ip));
871 //postfl("sp %p frame %p diff %d caller %p\n", sp, g->frame, ((int)sp - (int)g->frame)>>3, g->frame->caller.uof);
872 #if DEBUGINTERPRETER
873 if (gTraceInterpreter) {
874 //DumpStack(g, sp);
875 if (FrameSanity(g->frame, "dbgint")) {
876 //Debugger();
878 //g->gc->SanityCheck();
879 //assert(g->gc->SanityCheck());
880 g->sp = sp; g->ip = ip;
881 g->gc->FullCollection();
882 sp = g->sp; ip = g->ip;
883 postfl("[%3d] %20s-%-16s ",
884 (sp - g->gc->Stack()->slots) + 1,
885 slotRawSymbol(&slotRawClass(&g->method->ownerclass)->name)->name, slotRawSymbol(&g->method->name)->name);
886 dumpOneByteCode(g->block, NULL, ip);
888 #endif
889 #ifdef GC_SANITYCHECK
890 // gcLinkSanity(g->gc);
891 g->gc->SanityCheck();
892 // do_check_pool(pyr_pool_runtime);
893 // do_check_pool(pyr_pool_compile);
894 #endif
895 #if METHODMETER
896 if (gTraceInterpreter) {
897 slotRawInt(&g->method->byteMeter)++;
899 #endif
901 switch (op1) {
902 case 0 : // push class
903 handle_op_0:
904 op2 = ip[1]; ++ip; // get literal index
905 classobj = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2])->u.classobj;
906 if (classobj) {
907 ++sp; SetObject(sp, classobj);
908 } else {
909 postfl("Execution warning: Class '%s' not found\n", slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2])->name);
910 slotCopy(++sp, &gSpecialValues[svNil]);
912 dispatch_opcode;
913 case 1 : // opExtended, opPushInstVar
914 handle_op_1:
915 op2 = ip[1]; ++ip; // get inst var index
916 slotCopy(++sp, &slotRawObject(&g->receiver)->slots[op2]);
917 dispatch_opcode;
918 case 2 : // opExtended, opPushTempVar
919 handle_op_2:
920 op2 = ip[1]; // get temp var level
921 op3 = ip[2]; // get temp var index
922 ip += 2;
923 for (tframe = g->frame; --op2; tframe = slotRawFrame(&tframe->context)) { /* noop */ }
924 slotCopy(++sp, &tframe->vars[op3]);
925 dispatch_opcode;
926 case 3 : // opExtended, opPushTempZeroVar
927 handle_op_3:
928 op2 = ip[1]; ++ip; // get temp var index
929 slotCopy(++sp, &g->frame->vars[op2]);
930 dispatch_opcode;
931 case 4 : // opExtended, opPushLiteral
932 handle_op_4:
933 op2 = ip[1]; ++ip; // get literal index
934 // push a block as a closure if it is one
935 slot = slotRawObject(&g->block->selectors)->slots + op2;
936 if (IsObj(slot) && slotRawObject(slot)->classptr == gSpecialClasses[op_class_fundef]->u.classobj) {
937 // push a closure
938 g->sp = sp; // gc may push the stack
939 closure = (PyrClosure*)g->gc->New(2*sizeof(PyrSlot), 0, obj_notindexed, true);
940 sp = g->sp;
941 closure->classptr = gSpecialClasses[op_class_func]->u.classobj;
942 closure->size = 2;
943 slotCopy(&closure->block, slot);
944 if (IsNil(&slotRawBlock(slot)->contextDef)) {
945 slotCopy(&closure->context, &slotRawInterpreter(&g->process->interpreter)->context);
946 } else {
947 SetObject(&closure->context, g->frame);
949 ++sp; SetObject(sp, closure);
950 } else {
951 slotCopy(++sp, slot);
953 dispatch_opcode;
954 case 5 : // opExtended, opPushClassVar
955 handle_op_5:
956 op2 = ip[1]; // get class
957 op3 = ip[2]; // get class var index
958 ip += 2;
959 slotCopy(++sp, &g->classvars->slots[(op2<<8)|op3]);
960 dispatch_opcode;
961 case 6 : // opExtended, opPushSpecialValue == push a special class
962 handle_op_6:
963 op2 = ip[1]; ++ip; // get class name index
964 classobj = gSpecialClasses[op2]->u.classobj;
965 if (classobj) {
966 ++sp; SetObject(sp, classobj);
967 } else {
968 slotCopy(++sp, &gSpecialValues[svNil]);
970 dispatch_opcode;
971 case 7 : // opExtended, opStoreInstVar
972 handle_op_7:
973 op2 = ip[1]; ++ip; // get inst var index
974 obj = slotRawObject(&g->receiver);
975 if (obj->IsImmutable()) { StoreToImmutableA(g, sp, ip); }
976 else {
977 slot = obj->slots + op2;
978 slotCopy(slot, sp);
979 g->gc->GCWrite(obj, slot);
981 dispatch_opcode;
982 case 8 : // opExtended, opStoreTempVar
983 handle_op_8:
984 op2 = ip[1]; // get temp var level
985 op3 = ip[2]; // get temp var index
986 ip += 2;
987 for (tframe = g->frame; op2--; tframe = slotRawFrame(&tframe->context)) { /* noop */ }
988 slot = tframe->vars + op3;
989 slotCopy(slot, sp);
990 g->gc->GCWrite(tframe, slot);
991 dispatch_opcode;
992 case 9 : // opExtended, opStoreClassVar
993 handle_op_9:
994 op2 = ip[1]; // get index of class name literal
995 op3 = ip[2]; // get class var index
996 ip += 2;
997 slotCopy(&g->classvars->slots[(op2<<8)|op3], sp);
998 g->gc->GCWrite(g->classvars, sp);
999 dispatch_opcode;
1000 case 10 : // opExtended, opSendMsg
1001 handle_op_10:
1002 numArgsPushed = ip[1]; // get num args
1003 numKeyArgsPushed = ip[2]; // get num keyword args
1004 op3 = ip[3]; // get selector index
1005 ip += 3;
1006 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op3]);
1008 slot = sp - numArgsPushed + 1;
1010 if (numKeyArgsPushed) goto key_class_lookup;
1011 else goto class_lookup;
1013 case 11 : // opExtended, opSendSuper
1014 handle_op_11:
1015 numArgsPushed = ip[1]; // get num args
1016 numKeyArgsPushed = ip[2]; // get num keyword args
1017 op3 = ip[3]; // get selector index
1018 ip += 3;
1019 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op3]);
1021 slot = g->sp - numArgsPushed + 1;
1022 classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj;
1024 if (numKeyArgsPushed) goto key_msg_lookup;
1025 else goto msg_lookup;
1027 case 12 : // opExtended, opSendSpecialMsg
1028 handle_op_12:
1029 numArgsPushed = ip[1]; // get num args
1030 numKeyArgsPushed = ip[2]; // get num keyword args
1031 op3 = ip[3]; // get selector index
1032 ip += 3;
1034 selector = gSpecialSelectors[op3];
1035 slot = sp - numArgsPushed + 1;
1037 if (numKeyArgsPushed) goto key_class_lookup;
1038 else goto class_lookup;
1040 case 13 : // opExtended, opSendSpecialUnaryArithMsg
1041 handle_op_13:
1042 op2 = ip[1]; ++ip; // get selector index
1043 g->sp = sp; g->ip = ip;
1044 g->primitiveIndex = op2;
1045 doSpecialUnaryArithMsg(g, -1);
1046 #if TAILCALLOPTIMIZE
1047 g->tailCall = 0;
1048 #endif
1049 sp = g->sp; ip = g->ip;
1050 dispatch_opcode;
1051 case 14 : // opExtended, opSendSpecialBinaryArithMsg
1052 handle_op_14:
1053 op2 = ip[1]; ++ip; // get selector index
1054 g->sp = sp; g->ip = ip;
1055 g->primitiveIndex = op2;
1056 doSpecialBinaryArithMsg(g, 2, false);
1057 sp = g->sp; ip = g->ip;
1058 dispatch_opcode;
1059 case 15 : // opExtended, opSpecialOpcode (none yet)
1060 handle_op_15:
1061 op2 = ip[1]; ++ip; // get extended special opcode
1062 switch (op2) {
1063 case opgProcess : // push thisProcess
1064 ++sp; SetObject(sp, g->process); break;
1065 case opgThread : // push thisProcess
1066 ++sp; SetObject(sp, g->thread); break;
1067 case opgMethod : // push thisMethod
1068 ++sp; SetObject(sp, g->method); break;
1069 case opgFunctionDef : // push thisFunctionDef
1070 ++sp; SetObject(sp, g->block); break;
1071 case opgFunction : // push thisFunc
1072 // push a closure
1073 g->sp = sp; // gc may push the stack
1074 closure = (PyrClosure*)g->gc->New(2*sizeof(PyrSlot), 0, obj_notindexed, true);
1075 sp = g->sp;
1076 closure->classptr = gSpecialClasses[op_class_func]->u.classobj;
1077 closure->size = 2;
1078 SetObject(&closure->block, g->block);
1079 SetObject(&closure->context, slotRawFrame(&g->frame->context));
1080 ++sp; SetObject(sp, closure);
1081 break;
1082 default :
1083 slotCopy(++sp, &gSpecialValues[svNil]); break;
1085 dispatch_opcode;
1086 // opPushInstVar, 0..15
1087 case 16 : handle_op_16: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 0]); dispatch_opcode;
1088 case 17 : handle_op_17: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 1]); dispatch_opcode;
1089 case 18 : handle_op_18: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 2]); dispatch_opcode;
1090 case 19 : handle_op_19: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 3]); dispatch_opcode;
1091 case 20 : handle_op_20: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 4]); dispatch_opcode;
1092 case 21 : handle_op_21: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 5]); dispatch_opcode;
1093 case 22 : handle_op_22: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 6]); dispatch_opcode;
1094 case 23 : handle_op_23: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 7]); dispatch_opcode;
1095 case 24 : handle_op_24: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 8]); dispatch_opcode;
1096 case 25 : handle_op_25: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 9]); dispatch_opcode;
1097 case 26 : handle_op_26: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[10]); dispatch_opcode;
1098 case 27 : handle_op_27: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[11]); dispatch_opcode;
1099 case 28 : handle_op_28: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[12]); dispatch_opcode;
1100 case 29 : handle_op_29: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[13]); dispatch_opcode;
1101 case 30 : handle_op_30: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[14]); dispatch_opcode;
1102 case 31 : handle_op_31: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[15]); dispatch_opcode;
1104 case 32 : // JumpIfTrue
1105 handle_op_32:
1106 // cannot compare with o_false because it is NaN
1107 if ( IsTrue(sp) ) {
1108 jmplen = (ip[1]<<8) | ip[2];
1109 ip += jmplen + 2;
1110 } else if ( IsFalse(sp)) {
1111 ip+=2;
1112 } else {
1113 numArgsPushed = 1;
1114 selector = gSpecialSelectors[opmNonBooleanError];
1115 slot = sp;
1117 goto class_lookup;
1119 --sp;
1120 dispatch_opcode;
1122 // opPushTempVar, levels 1..7
1123 case 33 : handle_op_33:
1124 slotCopy(++sp, &slotRawFrame(&g->frame->context)->vars[ip[1]]); ++ip; dispatch_opcode;
1125 case 34 : handle_op_34:
1126 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&g->frame->context)->context)->vars[ip[1]]); ++ip; dispatch_opcode;
1127 case 35 : handle_op_35:
1128 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)->vars[ip[1]]);
1129 ++ip; dispatch_opcode;
1130 case 36 : handle_op_36:
1131 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)->
1132 context)->vars[ip[1]]); ++ip; dispatch_opcode;
1133 case 37 : handle_op_37:
1134 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->
1135 context)->context)->context)->context)->vars[ip[1]]); ++ip; dispatch_opcode;
1136 case 38 : handle_op_38:
1137 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->
1138 context)->context)->context)->context)->context)->vars[ip[1]]); ++ip; dispatch_opcode;
1139 case 39 : handle_op_39:
1140 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->
1141 context)->context)->context)->context)->context)->context)->vars[ip[1]]); ++ip; dispatch_opcode;
1143 // push literal constants.
1144 case 40 :
1145 handle_op_40:
1146 ival = ip[1];
1147 ip+=1;
1148 slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1149 dispatch_opcode;
1150 case 41 :
1151 handle_op_41:
1152 ival = (ip[1] << 8) | ip[2];
1153 ip+=2;
1154 slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1155 dispatch_opcode;
1156 case 42 :
1157 handle_op_42:
1158 ival = (ip[1] << 16) | (ip[2] << 8) | ip[3];
1159 ip+=3;
1160 slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1161 dispatch_opcode;
1162 case 43 :
1163 handle_op_43:
1164 ival = (ip[1] << 24) | (ip[2] << 16) | (ip[3] << 8) | ip[4];
1165 ip+=4;
1166 slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1167 dispatch_opcode;
1169 // push integers.
1170 case 44 :
1171 handle_op_44:
1172 ival = (int32)(ip[1] << 24) >> 24;
1173 ip+=1;
1174 ++sp; SetInt(sp, ival);
1175 dispatch_opcode;
1176 case 45 :
1177 handle_op_45:
1178 ival = (int32)((ip[1] << 24) | (ip[2] << 16)) >> 16;
1179 ip+=2;
1180 ++sp; SetInt(sp, ival);
1181 dispatch_opcode;
1182 case 46 :
1183 handle_op_46:
1184 ival = (int32)((ip[1] << 24) | (ip[2] << 16) | (ip[3] << 8)) >> 8;
1185 ip+=3;
1186 ++sp; SetInt(sp, ival);
1187 dispatch_opcode;
1188 case 47 :
1189 handle_op_47:
1190 ival = (int32)((ip[1] << 24) | (ip[2] << 16) | (ip[3] << 8) | ip[4]);
1191 ip+=4;
1192 ++sp; SetInt(sp, ival);
1193 dispatch_opcode;
1196 // opPushTempZeroVar
1197 case 48 : handle_op_48: slotCopy(++sp, &g->frame->vars[ 0]); dispatch_opcode;
1198 case 49 : handle_op_49: slotCopy(++sp, &g->frame->vars[ 1]); dispatch_opcode;
1199 case 50 : handle_op_50: slotCopy(++sp, &g->frame->vars[ 2]); dispatch_opcode;
1200 case 51 : handle_op_51: slotCopy(++sp, &g->frame->vars[ 3]); dispatch_opcode;
1201 case 52 : handle_op_52: slotCopy(++sp, &g->frame->vars[ 4]); dispatch_opcode;
1202 case 53 : handle_op_53: slotCopy(++sp, &g->frame->vars[ 5]); dispatch_opcode;
1203 case 54 : handle_op_54: slotCopy(++sp, &g->frame->vars[ 6]); dispatch_opcode;
1204 case 55 : handle_op_55: slotCopy(++sp, &g->frame->vars[ 7]); dispatch_opcode;
1205 case 56 : handle_op_56: slotCopy(++sp, &g->frame->vars[ 8]); dispatch_opcode;
1206 case 57 : handle_op_57: slotCopy(++sp, &g->frame->vars[ 9]); dispatch_opcode;
1207 case 58 : handle_op_58: slotCopy(++sp, &g->frame->vars[10]); dispatch_opcode;
1208 case 59 : handle_op_59: slotCopy(++sp, &g->frame->vars[11]); dispatch_opcode;
1209 case 60 : handle_op_60: slotCopy(++sp, &g->frame->vars[12]); dispatch_opcode;
1210 case 61 : handle_op_61: slotCopy(++sp, &g->frame->vars[13]); dispatch_opcode;
1211 case 62 : handle_op_62: slotCopy(++sp, &g->frame->vars[14]); dispatch_opcode;
1212 case 63 : handle_op_63: slotCopy(++sp, &g->frame->vars[15]); dispatch_opcode;
1214 // case opPushLiteral
1215 case 64 : handle_op_64: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 0]); dispatch_opcode;
1216 case 65 : handle_op_65: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 1]); dispatch_opcode;
1217 case 66 : handle_op_66: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 2]); dispatch_opcode;
1218 case 67 : handle_op_67: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 3]); dispatch_opcode;
1219 case 68 : handle_op_68: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 4]); dispatch_opcode;
1220 case 69 : handle_op_69: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 5]); dispatch_opcode;
1221 case 70 : handle_op_70: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 6]); dispatch_opcode;
1222 case 71 : handle_op_71: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 7]); dispatch_opcode;
1223 case 72 : handle_op_72: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 8]); dispatch_opcode;
1224 case 73 : handle_op_73: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 9]); dispatch_opcode;
1225 case 74 : handle_op_74: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[10]); dispatch_opcode;
1226 case 75 : handle_op_75: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[11]); dispatch_opcode;
1227 case 76 : handle_op_76: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[12]); dispatch_opcode;
1228 case 77 : handle_op_77: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[13]); dispatch_opcode;
1229 case 78 : handle_op_78: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[14]); dispatch_opcode;
1230 case 79 : handle_op_79: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[15]); dispatch_opcode;
1232 // opPushClassVar
1233 case 80: handle_op_80:
1234 handlePushClassVar(g, sp, ip, 0); dispatch_opcode;
1235 case 81: handle_op_81:
1236 handlePushClassVar(g, sp, ip, 1); dispatch_opcode;
1237 case 82: handle_op_82:
1238 handlePushClassVar(g, sp, ip, 2); dispatch_opcode;
1239 case 83: handle_op_83:
1240 handlePushClassVar(g, sp, ip, 3); dispatch_opcode;
1241 case 84: handle_op_84:
1242 handlePushClassVar(g, sp, ip, 4); dispatch_opcode;
1243 case 85: handle_op_85:
1244 handlePushClassVar(g, sp, ip, 5); dispatch_opcode;
1245 case 86: handle_op_86:
1246 handlePushClassVar(g, sp, ip, 6); dispatch_opcode;
1247 case 87: handle_op_87:
1248 handlePushClassVar(g, sp, ip, 7); dispatch_opcode;
1249 case 88: handle_op_88:
1250 handlePushClassVar(g, sp, ip, 8); dispatch_opcode;
1251 case 89: handle_op_89:
1252 handlePushClassVar(g, sp, ip, 9); dispatch_opcode;
1253 case 90: handle_op_90:
1254 handlePushClassVar(g, sp, ip, 10); dispatch_opcode;
1255 case 91: handle_op_91:
1256 handlePushClassVar(g, sp, ip, 11); dispatch_opcode;
1257 case 92: handle_op_92:
1258 handlePushClassVar(g, sp, ip, 12); dispatch_opcode;
1259 case 93: handle_op_93:
1260 handlePushClassVar(g, sp, ip, 13); dispatch_opcode;
1261 case 94: handle_op_94:
1262 handlePushClassVar(g, sp, ip, 14); dispatch_opcode;
1263 case 95: handle_op_95:
1264 handlePushClassVar(g, sp, ip, 15); dispatch_opcode;
1266 // opPushSpecialValue
1267 case 96 : handle_op_96: slotCopy(++sp, &g->receiver); dispatch_opcode;
1268 case 97 : // push one and subtract
1269 handle_op_97:
1270 if (IsInt(sp)) {
1271 SetRaw(sp, slotRawInt(sp) - 1);
1272 #if TAILCALLOPTIMIZE
1273 g->tailCall = 0;
1274 #endif
1275 } else {
1276 slotCopy(++sp, &gSpecialValues[svOne]);
1277 g->sp = sp; g->ip = ip;
1278 g->primitiveIndex = opSub;
1279 prSubNum(g, -1);
1280 sp = g->sp; ip = g->ip;
1282 dispatch_opcode;
1283 case 98 : handle_op_98: slotCopy(++sp, &gSpecialValues[svNegOne]); dispatch_opcode;
1284 case 99 : handle_op_99: slotCopy(++sp, &gSpecialValues[svZero]); dispatch_opcode;
1285 case 100 : handle_op_100: slotCopy(++sp, &gSpecialValues[svOne]); dispatch_opcode;
1286 case 101 : handle_op_101: slotCopy(++sp, &gSpecialValues[svTwo]); dispatch_opcode;
1287 case 102 : handle_op_102: slotCopy(++sp, &gSpecialValues[svFHalf]); dispatch_opcode;
1288 case 103 : handle_op_103: slotCopy(++sp, &gSpecialValues[svFNegOne]); dispatch_opcode;
1289 case 104 : handle_op_104: slotCopy(++sp, &gSpecialValues[svFZero]); dispatch_opcode;
1290 case 105 : handle_op_105: slotCopy(++sp, &gSpecialValues[svFOne]); dispatch_opcode;
1291 case 106 : handle_op_106: slotCopy(++sp, &gSpecialValues[svFTwo]); dispatch_opcode;
1292 case 107 : // push one and add
1293 handle_op_107:
1294 if (IsInt(sp)) {
1295 SetRaw(sp, slotRawInt(sp) + 1);
1296 #if TAILCALLOPTIMIZE
1297 g->tailCall = 0;
1298 #endif
1299 } else {
1300 slotCopy(++sp, &gSpecialValues[svOne]);
1301 g->sp = sp; g->ip = ip;
1302 g->primitiveIndex = opAdd;
1303 prAddNum(g, -1);
1304 sp = g->sp; ip = g->ip;
1306 dispatch_opcode;
1307 case 108 : handle_op_108: slotCopy(++sp, &gSpecialValues[svTrue]); dispatch_opcode;
1308 case 109 : handle_op_109: slotCopy(++sp, &gSpecialValues[svFalse]); dispatch_opcode;
1309 case 110 : handle_op_110: slotCopy(++sp, &gSpecialValues[svNil]); dispatch_opcode;
1310 case 111 : handle_op_111: slotCopy(++sp, &gSpecialValues[svInf]); dispatch_opcode;
1312 // opStoreInstVar, 0..15
1313 case 112 : handle_op_112:
1314 handleStoreInstVar(g, sp, ip, 0); dispatch_opcode;
1315 case 113 : handle_op_113:
1316 handleStoreInstVar(g, sp, ip, 1); dispatch_opcode;
1317 case 114 : handle_op_114:
1318 handleStoreInstVar(g, sp, ip, 2); dispatch_opcode;
1319 case 115 : handle_op_115:
1320 handleStoreInstVar(g, sp, ip, 3); dispatch_opcode;
1321 case 116 : handle_op_116:
1322 handleStoreInstVar(g, sp, ip, 4); dispatch_opcode;
1323 case 117 : handle_op_117:
1324 handleStoreInstVar(g, sp, ip, 5); dispatch_opcode;
1325 case 118 : handle_op_118:
1326 handleStoreInstVar(g, sp, ip, 6); dispatch_opcode;
1327 case 119 : handle_op_119:
1328 handleStoreInstVar(g, sp, ip, 7); dispatch_opcode;
1329 case 120 : handle_op_120:
1330 handleStoreInstVar(g, sp, ip, 8); dispatch_opcode;
1331 case 121 : handle_op_121:
1332 handleStoreInstVar(g, sp, ip, 9); dispatch_opcode;
1333 case 122 : handle_op_122:
1334 handleStoreInstVar(g, sp, ip, 10); dispatch_opcode;
1335 case 123 : handle_op_123:
1336 handleStoreInstVar(g, sp, ip, 11); dispatch_opcode;
1337 case 124 : handle_op_124:
1338 handleStoreInstVar(g, sp, ip, 12); dispatch_opcode;
1339 case 125 : handle_op_125:
1340 handleStoreInstVar(g, sp, ip, 13); dispatch_opcode;
1341 case 126 : handle_op_126:
1342 handleStoreInstVar(g, sp, ip, 14); dispatch_opcode;
1343 case 127 : handle_op_127:
1344 handleStoreInstVar(g, sp, ip, 15); dispatch_opcode;
1346 // opStoreTempVar
1347 case 128 :
1348 handle_op_128:
1349 op3 = ip[1]; ++ip; // get temp var index
1350 tframe = g->frame; // zero level
1351 slot = tframe->vars + op3;
1352 slotCopy(slot, sp--);
1353 g->gc->GCWrite(tframe, slot);
1354 dispatch_opcode;
1356 case 129 :
1357 handle_op_129:
1358 op3 = ip[1]; ++ip; // get temp var index
1359 tframe = slotRawFrame(&g->frame->context); // one level
1360 slot = tframe->vars + op3;
1361 slotCopy(slot, sp--);
1362 g->gc->GCWrite(tframe, slot);
1363 dispatch_opcode;
1365 case 130 :
1366 handle_op_130:
1367 op3 = ip[1]; ++ip; // get temp var index
1368 tframe = slotRawFrame(&slotRawFrame(&g->frame->context)->context); // two levels
1369 slot = tframe->vars + op3;
1370 slotCopy(slot, sp--);
1371 g->gc->GCWrite(tframe, slot);
1372 dispatch_opcode;
1374 case 131 :
1375 handle_op_131:
1376 op3 = ip[1]; ++ip; // get temp var index
1377 tframe = slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context); // three levels
1378 slot = tframe->vars + op3;
1379 slotCopy(slot, sp--);
1380 g->gc->GCWrite(tframe, slot);
1381 dispatch_opcode;
1383 case 132 :
1384 handle_op_132:
1385 op3 = ip[1]; ++ip; // get temp var index
1386 tframe = slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)->context); // four levels
1387 slot = tframe->vars + op3;
1388 slotCopy(slot, sp--);
1389 g->gc->GCWrite(tframe, slot);
1390 dispatch_opcode;
1392 case 133 : case 134 : case 135 :
1393 handle_op_133:
1394 handle_op_134:
1395 handle_op_135:
1396 op2 = op1 & 15;
1397 op3 = ip[1]; ++ip; // get temp var index
1398 for (tframe = g->frame; op2--; tframe = slotRawFrame(&tframe->context)) { /* noop */ }
1399 slot = tframe->vars + op3;
1400 slotCopy(slot, sp);
1401 g->gc->GCWrite(tframe, slot);
1402 dispatch_opcode;
1404 case 136 : // push inst var, send special selector
1405 handle_op_136:
1406 op2 = ip[1]; // get inst var index
1407 op3 = ip[2]; // get selector
1408 ip+=2;
1410 slotCopy(++sp, &slotRawObject(&g->receiver)->slots[op2]);
1412 numArgsPushed = 1;
1413 selector = gSpecialSelectors[op3];
1414 slot = sp;
1416 goto class_lookup;
1418 case 137 : // push all args, send msg
1419 handle_op_137:
1420 numArgsPushed = METHRAW(g->block)->numargs;
1421 pslot = g->frame->vars - 1;
1422 for (m=0,mmax=numArgsPushed; m<mmax; ++m) *++sp = *++pslot;
1424 op2 = ip[1]; ++ip; // get selector index
1425 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
1426 slot = sp - numArgsPushed + 1;
1428 goto class_lookup;
1430 case 138 : // push all but first arg, send msg
1431 handle_op_138:
1432 numArgsPushed = METHRAW(g->block)->numargs;
1433 pslot = g->frame->vars;
1434 for (m=0,mmax=numArgsPushed-1; m<mmax; ++m) *++sp = *++pslot;
1436 op2 = ip[1]; ++ip; // get selector index
1437 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
1438 slot = sp - numArgsPushed + 1;
1440 goto class_lookup;
1442 case 139 : // push all args, send special
1443 handle_op_139:
1444 numArgsPushed = METHRAW(g->block)->numargs;
1445 pslot = g->frame->vars - 1;
1446 for (m=0,mmax=numArgsPushed; m<mmax; ++m) *++sp = *++pslot;
1448 op2 = ip[1]; ++ip; // get selector
1449 selector = gSpecialSelectors[op2];
1450 slot = sp - numArgsPushed + 1;
1452 goto class_lookup;
1454 case 140 : // push all but first arg, send special
1455 handle_op_140:
1456 numArgsPushed = METHRAW(g->block)->numargs;
1457 pslot = g->frame->vars;
1458 for (m=0,mmax=numArgsPushed-1; m<mmax; ++m) *++sp = *++pslot;
1460 op2 = ip[1]; ++ip; // get selector
1461 selector = gSpecialSelectors[op2];
1462 slot = sp - numArgsPushed + 1;
1464 goto class_lookup;
1466 case 141 : // one arg pushed, push all but first arg, send msg
1467 handle_op_141:
1468 numArgsPushed = METHRAW(g->block)->numargs + 1;
1469 pslot = g->frame->vars;
1470 for (m=0,mmax=numArgsPushed-2; m<mmax; ++m) *++sp = *++pslot;
1472 op2 = ip[1]; ++ip; // get selector index
1473 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
1474 slot = sp - numArgsPushed + 1;
1476 goto class_lookup;
1478 case 142 : // one arg pushed, push all but first arg, send special
1479 handle_op_142:
1480 numArgsPushed = METHRAW(g->block)->numargs + 1;
1481 pslot = g->frame->vars;
1482 for (m=0,mmax=numArgsPushed-2; m<mmax; ++m) *++sp = *++pslot;
1484 op2 = ip[1]; ++ip; // get selector
1485 selector = gSpecialSelectors[op2];
1486 slot = sp - numArgsPushed + 1;
1488 goto class_lookup;
1490 case 143 : // loop byte codes
1491 handle_op_143:
1492 // this is major cheating to speed up often used looping methods
1493 // these byte codes are specific to their method and should only be used there.
1494 op2 = ip[1]; ++ip; // get which one
1495 switch (op2) {
1496 // Integer-do : 143 0, 143 1
1497 case 0 :
1498 vars = g->frame->vars;
1499 if (slotRawInt(&vars[2]) < slotRawInt(&g->receiver)) {
1500 slotCopy(++sp, &vars[1]); // push function
1501 slotCopy(++sp, &vars[2]); // push i
1502 slotCopy(++sp, &vars[2]); // push i
1503 // SendSpecialMsg value
1504 numArgsPushed = 3;
1505 selector = gSpecialSelectors[opmValue];
1506 slot = sp - 2;
1508 goto class_lookup;
1509 } else {
1510 slotCopy(++sp, &g->receiver);
1511 g->sp = sp; g->ip = ip;
1512 returnFromMethod(g);
1513 sp = g->sp; ip = g->ip;
1515 dispatch_opcode;
1516 case 1 :
1517 -- sp ; // Drop
1518 SetRaw(&g->frame->vars[2], slotRawInt(&g->frame->vars[2]) + 1); // inc i
1519 ip -= 4;
1520 dispatch_opcode;
1522 // Integer-reverseDo : 143 2, 143 3, 143 4
1523 case 2 :
1524 SetRaw(&g->frame->vars[2], slotRawInt(&g->receiver) - 1);
1525 dispatch_opcode;
1526 case 3 :
1527 vars = g->frame->vars;
1528 if (slotRawInt(&vars[2]) >= 0) {
1529 slotCopy(++sp, &vars[1]); // push function
1530 slotCopy(++sp, &vars[2]); // push i
1531 slotCopy(++sp, &vars[3]); // push j
1532 // SendSpecialMsg value
1533 numArgsPushed = 3;
1534 selector = gSpecialSelectors[opmValue];
1535 slot = sp - 2;
1537 goto class_lookup;
1538 } else {
1539 slotCopy(++sp, &g->receiver);
1540 g->sp = sp; g->ip = ip;
1541 returnFromMethod(g);
1542 sp = g->sp; ip = g->ip;
1544 dispatch_opcode;
1545 case 4 :
1546 -- sp ; // Drop
1547 vars = g->frame->vars;
1548 SetRaw(&vars[2], slotRawInt(&vars[2]) - 1); // dec i
1549 SetRaw(&vars[3], slotRawInt(&vars[3]) + 1); // inc j
1550 ip -= 4;
1551 dispatch_opcode;
1553 // Integer-for : 143 5, 143 6, 143 16
1554 case 5 :
1555 vars = g->frame->vars;
1556 tag = GetTag(&vars[1]);
1558 if (tag != tagInt) {
1559 if (IsFloat(&vars[1])) {
1560 // coerce to int
1561 SetInt(&vars[1], (int32)(slotRawFloat(&vars[1])));
1562 } else {
1563 error("Integer-for : endval not a SimpleNumber.\n");
1565 slotCopy(++sp, &g->receiver);
1566 numArgsPushed = 1;
1567 selector = gSpecialSelectors[opmPrimitiveFailed];
1568 slot = sp;
1570 goto class_lookup;
1574 if (slotRawInt(&g->receiver) <= slotRawInt(&vars[1])) {
1575 SetRaw(&vars[5], 1);
1576 } else {
1577 SetRaw(&vars[5], -1);
1579 slotCopy(&vars[3], &g->receiver);
1581 dispatch_opcode;
1582 case 6 :
1583 vars = g->frame->vars;
1584 if ((slotRawInt(&vars[5]) > 0 && slotRawInt(&vars[3]) <= slotRawInt(&vars[1]))
1585 || (slotRawInt(&vars[5]) < 0 && slotRawInt(&vars[3]) >= slotRawInt(&vars[1])))
1587 slotCopy(++sp, &vars[2]); // push function
1588 slotCopy(++sp, &vars[3]); // push i
1589 slotCopy(++sp, &vars[4]); // push j
1590 // SendSpecialMsg value
1591 numArgsPushed = 3;
1592 selector = gSpecialSelectors[opmValue];
1593 slot = sp - 2;
1595 goto class_lookup;
1596 } else {
1597 slotCopy(++sp, &g->receiver);
1598 g->sp = sp; g->ip = ip;
1599 returnFromMethod(g);
1600 sp = g->sp; ip = g->ip;
1602 dispatch_opcode;
1604 // Integer-forBy : 143 7, 143 8, 143 9
1605 case 7 :
1606 vars = g->frame->vars;
1607 if (IsFloat(vars+1)) {
1608 SetInt(&vars[1], (int32)(slotRawFloat(&vars[1])));
1610 if (IsFloat(vars+2)) {
1611 SetInt(&vars[2], (int32)(slotRawFloat(&vars[2])));
1613 tag = GetTag(&vars[1]);
1614 if ((tag != tagInt)
1615 || NotInt(&vars[2])) {
1616 error("Integer-forBy : endval or stepval not an Integer.\n");
1618 slotCopy(++sp, &g->receiver);
1619 numArgsPushed = 1;
1620 selector = gSpecialSelectors[opmPrimitiveFailed];
1621 slot = sp;
1623 goto class_lookup;
1625 slotCopy(&vars[4], &g->receiver);
1626 dispatch_opcode;
1627 case 8 :
1628 vars = g->frame->vars;
1629 if ((slotRawInt(&vars[2]) >= 0 && slotRawInt(&vars[4]) <= slotRawInt(&vars[1]))
1630 || (slotRawInt(&vars[2]) < 0 && slotRawInt(&vars[4]) >= slotRawInt(&vars[1]))) {
1631 slotCopy(++sp, &vars[3]); // push function
1632 slotCopy(++sp, &vars[4]); // push i
1633 slotCopy(++sp, &vars[5]); // push j
1634 // SendSpecialMsg value
1635 numArgsPushed = 3;
1636 selector = gSpecialSelectors[opmValue];
1637 slot = sp - 2;
1639 goto class_lookup;
1640 } else {
1641 slotCopy(++sp, &g->receiver);
1642 g->sp = sp; g->ip = ip;
1643 returnFromMethod(g);
1644 sp = g->sp; ip = g->ip;
1646 dispatch_opcode;
1647 case 9 :
1648 --sp ; // Drop
1649 vars = g->frame->vars;
1650 SetRaw(&vars[4], slotRawInt(&vars[4]) + slotRawInt(&vars[2])); // inc i
1651 SetRaw(&vars[5], slotRawInt(&vars[5]) + 1); // inc j
1652 ip -= 4;
1653 dispatch_opcode;
1655 // ArrayedCollection-do : 143 10, 143 1
1656 case 10 :
1657 // 0 this, 1 func, 2 i
1658 vars = g->frame->vars;
1660 if (slotRawInt(&vars[2]) < slotRawObject(&g->receiver)->size) {
1661 slotCopy(++sp, &vars[1]); // push function
1662 getIndexedSlot(slotRawObject(&g->receiver), ++sp, slotRawInt(&vars[2])); // push this.at(i)
1663 slotCopy(++sp, &vars[2]); // push i
1664 // SendSpecialMsg value
1665 numArgsPushed = 3;
1666 selector = gSpecialSelectors[opmValue];
1667 slot = sp - 2;
1669 goto class_lookup;
1670 } else {
1671 slotCopy(++sp, &g->receiver);
1672 g->sp = sp; g->ip = ip;
1673 returnFromMethod(g);
1674 sp = g->sp; ip = g->ip;
1676 dispatch_opcode;
1678 // ArrayedCollection-reverseDo : 143 11, 143 12, 143 4
1679 case 11 :
1680 SetRaw(&g->frame->vars[2], slotRawObject(&g->receiver)->size - 1);
1681 dispatch_opcode;
1682 case 12 :
1683 vars = g->frame->vars;
1684 if (slotRawInt(&vars[2]) >= 0) {
1685 slotCopy(++sp, &vars[1]); // push function
1686 getIndexedSlot(slotRawObject(&g->receiver), ++sp, slotRawInt(&vars[2])); // push this.at(i)
1687 slotCopy(++sp, &vars[3]); // push j
1688 // SendSpecialMsg value
1689 numArgsPushed = 3;
1690 selector = gSpecialSelectors[opmValue];
1691 slot = sp - 2;
1693 goto class_lookup; // class_lookup:
1694 } else {
1695 slotCopy(++sp, &g->receiver);
1696 g->sp = sp; g->ip = ip;
1697 returnFromMethod(g);
1698 sp = g->sp; ip = g->ip;
1700 dispatch_opcode;
1702 // Dictionary-keysValuesArrayDo
1703 case 13 :
1704 vars = g->frame->vars;
1705 m = slotRawInt(&vars[3]);
1706 obj = slotRawObject(&vars[1]);
1707 if ( m < obj->size ) {
1708 slot = obj->slots + m; // key
1709 while (IsNil(slot)) {
1710 m += 2;
1711 if ( m >= obj->size ) {
1712 SetRaw(&vars[3], m);
1713 goto keysValuesArrayDo_return;
1715 slot = obj->slots + m; // key
1717 SetRaw(&vars[3], m);
1718 slotCopy(++sp, &vars[2]); // function
1719 slotCopy(++sp, &slot[0]); // key
1720 slotCopy(++sp, &slot[1]); // val
1721 slotCopy(++sp, &vars[4]); // j
1722 SetRaw(&vars[4], slotRawInt(&vars[4]) + 1);
1724 // SendSpecialMsg value
1725 numArgsPushed = 4;
1726 selector = gSpecialSelectors[opmValue];
1727 slot = sp - 3;
1729 goto class_lookup; // class_lookup:
1730 } else {
1731 keysValuesArrayDo_return:
1732 slotCopy(++sp, &g->receiver);
1733 g->sp = sp; g->ip = ip;
1734 returnFromMethod(g);
1735 sp = g->sp; ip = g->ip;
1737 dispatch_opcode;
1738 case 14 :
1739 -- sp; // Drop
1740 SetRaw(&g->frame->vars[3], slotRawInt(&g->frame->vars[3]) + 2); // inc i
1741 ip -= 4;
1742 dispatch_opcode;
1743 case 15 :
1744 // unused opcode.
1745 break;
1747 case 16 :
1748 -- sp ; // Drop
1749 vars = g->frame->vars;
1750 SetRaw(&vars[3], slotRawInt(&vars[3]) + slotRawInt(&vars[5])); // inc i by stepval
1751 SetRaw(&vars[4], slotRawInt(&vars[4]) + 1); // inc j
1752 ip -= 4;
1753 dispatch_opcode;
1755 // Float-do : 143 17, 143 18
1756 case 17 :
1757 vars = g->frame->vars;
1758 if (slotRawFloat(&vars[2]) + 0.5 < slotRawFloat(&g->receiver)) {
1759 slotCopy(++sp, &vars[1]); // push function
1760 slotCopy(++sp, &vars[2]); // push i
1761 slotCopy(++sp, &vars[2]); // push i
1762 // SendSpecialMsg value
1763 numArgsPushed = 3;
1764 selector = gSpecialSelectors[opmValue];
1765 slot = sp - 2;
1767 goto class_lookup;
1768 } else {
1769 slotCopy(++sp, &g->receiver);
1770 g->sp = sp; g->ip = ip;
1771 returnFromMethod(g);
1772 sp = g->sp; ip = g->ip;
1774 dispatch_opcode;
1775 case 18 :
1776 -- sp ; // Drop
1777 SetRaw(&g->frame->vars[2], slotRawFloat(&g->frame->vars[2]) + 1.0); // inc i
1778 ip -= 4;
1779 dispatch_opcode;
1781 // Float-reverseDo : 143 19, 143 20, 143 21
1782 case 19 :
1783 SetFloat(&g->frame->vars[2], slotRawFloat(&g->receiver) - 1.0);
1784 dispatch_opcode;
1785 case 20 :
1786 vars = g->frame->vars;
1787 if (slotRawFloat(&vars[2]) + 0.5 >= 0.0) {
1788 slotCopy(++sp, &vars[1]); // push function
1789 slotCopy(++sp, &vars[2]); // push i
1790 slotCopy(++sp, &vars[3]); // push j
1791 // SendSpecialMsg value
1792 numArgsPushed = 3;
1793 selector = gSpecialSelectors[opmValue];
1794 slot = sp - 2;
1796 goto class_lookup;
1797 } else {
1798 slotCopy(++sp, &g->receiver);
1799 g->sp = sp; g->ip = ip;
1800 returnFromMethod(g);
1801 sp = g->sp; ip = g->ip;
1803 dispatch_opcode;
1804 case 21 :
1805 -- sp ; // Drop
1806 vars = g->frame->vars;
1807 SetRaw(&g->frame->vars[2], slotRawFloat(&g->frame->vars[2]) - 1.0); // dec i
1808 SetRaw(&g->frame->vars[3], slotRawFloat(&g->frame->vars[3]) - 1.0); // inc j
1809 ip -= 4;
1810 dispatch_opcode;
1811 case 22 : // ? question mark method
1812 --sp;
1813 if (IsNil(sp)) {
1814 *sp = *(sp+1);
1816 dispatch_opcode;
1817 case 23 : // if not nil push this and jump. used to implement ??
1818 if (NotNil(sp)) {
1819 jmplen = (ip[1]<<8) | ip[2];
1820 ip += jmplen + 2;
1821 } else {
1822 --sp;
1823 ip+=2;
1825 dispatch_opcode;
1826 case 24 : // ifNil
1827 if ( NotNil(sp) ) {
1828 jmplen = (ip[1]<<8) | ip[2];
1829 ip += jmplen + 2;
1830 } else {
1831 ip+=2;
1833 --sp;
1834 dispatch_opcode;
1835 case 25 : // ifNotNil
1836 if ( IsNil(sp) ) {
1837 jmplen = (ip[1]<<8) | ip[2];
1838 ip += jmplen + 2;
1839 } else {
1840 ip+=2;
1842 --sp;
1843 dispatch_opcode;
1844 case 26 : // ifNotNilPushNil
1845 if ( NotNil(sp) ) {
1846 jmplen = (ip[1]<<8) | ip[2];
1847 ip += jmplen + 2;
1848 slotCopy(sp, &gSpecialValues[svNil]);
1849 } else {
1850 ip+=2;
1851 --sp;
1853 dispatch_opcode;
1854 case 27 : // ifNilPushNil
1855 if ( IsNil(sp) ) {
1856 jmplen = (ip[1]<<8) | ip[2];
1857 ip += jmplen + 2;
1858 } else {
1859 ip+=2;
1860 --sp;
1862 dispatch_opcode;
1863 case 28 : // switch
1864 obj = slotRawObject(sp);
1865 op2 = 1 + arrayAtIdentityHashInPairs(obj, (sp-1));
1866 sp-=2;
1867 ip += slotRawInt(&obj->slots[op2]);
1868 dispatch_opcode;
1870 // Number-forSeries : 143 29, 143 30, 143 31
1871 case 29 :
1872 vars = g->frame->vars;
1873 // 0 receiver, 1 step, 2 last, 3 function, 4 i, 5 j
1874 if (IsInt(vars+0) && (IsInt(vars+1) || IsNil(vars+1)) && (IsInt(vars+2) || IsNil(vars+2))) {
1875 if (IsNil(vars+1)) {
1876 if (IsNil(vars+2)) SetInt(vars+2, 0x7FFFFFFF);
1877 if (slotRawInt(&vars[0]) < slotRawInt(&vars[2])) SetInt(vars+1, 1);
1878 else SetInt(vars+1, -1);
1879 } else {
1880 if (IsNil(vars+2)) {
1881 if (slotRawInt(&vars[1]) < slotRawInt(&vars[0])) SetInt(vars+2, 0x80000000);
1882 else SetInt(vars+2, 0x7FFFFFFF);
1884 SetInt(vars+1, slotRawInt(&vars[1]) - slotRawInt(&vars[0]));
1886 slotCopy(&vars[4], &vars[0]);
1887 } else {
1888 if (IsInt(vars+0)) {
1889 SetFloat(&vars[4], slotRawInt(&vars[0]));
1890 } else if (IsFloat(vars+0)) {
1891 SetFloat(&vars[4], slotRawFloat(&vars[0]));
1892 } else {
1893 bailFromNumberSeries:
1894 error("Number-forSeries : first, second or last not an Integer or Float.\n");
1896 slotCopy(++sp, &g->receiver);
1897 numArgsPushed = 1;
1898 selector = gSpecialSelectors[opmPrimitiveFailed];
1899 slot = sp;
1901 goto class_lookup;
1904 if (IsNil(vars+1)) {
1905 if (IsNil(vars+2)) SetFloat(vars+2, kBigBigFloat);
1906 else if (IsInt(vars+2)) SetFloat(&vars[2], slotRawInt(&vars[2]));
1907 else if (!IsFloat(vars+2)) goto bailFromNumberSeries;
1909 if (slotRawFloat(&vars[4]) < slotRawFloat(&vars[2])) SetFloat(vars+1, 1.);
1910 else SetFloat(vars+1, -1.);
1911 } else {
1912 if (IsInt(vars+1)) SetFloat(&vars[1], slotRawInt(&vars[1]));
1913 else if (!IsFloat(vars+1)) goto bailFromNumberSeries;
1915 if (IsNil(vars+2)) {
1916 if (slotRawFloat(&vars[1]) < slotRawFloat(&vars[4])) SetFloat(vars+2, kSmallSmallFloat);
1917 else SetFloat(vars+2, kBigBigFloat);
1919 else if (IsInt(vars+2)) SetFloat(&vars[2], slotRawInt(&vars[2]));
1920 else if (!IsFloat(vars+2)) goto bailFromNumberSeries;
1921 SetFloat(vars+1, slotRawFloat(&vars[1]) - slotRawFloat(&vars[4]));
1924 dispatch_opcode;
1925 case 30 :
1926 vars = g->frame->vars;
1927 tag = GetTag(&vars[1]);
1928 if (tag == tagInt) {
1929 if ((slotRawInt(&vars[1]) >= 0 && slotRawInt(&vars[4]) <= slotRawInt(&vars[2]))
1930 || (slotRawInt(&vars[1]) < 0 && slotRawInt(&vars[4]) >= slotRawInt(&vars[2]))) {
1931 slotCopy(++sp, &vars[3]); // push function
1932 slotCopy(++sp, &vars[4]); // push i
1933 slotCopy(++sp, &vars[5]); // push j
1934 // SendSpecialMsg value
1935 numArgsPushed = 3;
1936 selector = gSpecialSelectors[opmValue];
1937 slot = sp - 2;
1939 goto class_lookup;
1940 } else {
1941 slotCopy(++sp, &g->receiver);
1942 g->sp = sp; g->ip = ip;
1943 returnFromMethod(g);
1944 sp = g->sp; ip = g->ip;
1946 } else {
1947 if ((slotRawFloat(&vars[1]) >= 0. && slotRawFloat(&vars[4]) <= slotRawFloat(&vars[2]))
1948 || (slotRawFloat(&vars[1]) < 0. && slotRawFloat(&vars[4]) >= slotRawFloat(&vars[2]))) {
1949 slotCopy(++sp, &vars[3]); // push function
1950 slotCopy(++sp, &vars[4]); // push i
1951 slotCopy(++sp, &vars[5]); // push j
1952 // SendSpecialMsg value
1953 numArgsPushed = 3;
1954 selector = gSpecialSelectors[opmValue];
1955 slot = sp - 2;
1957 goto class_lookup;
1958 } else {
1959 slotCopy(++sp, &g->receiver);
1960 g->sp = sp; g->ip = ip;
1961 returnFromMethod(g);
1962 sp = g->sp; ip = g->ip;
1965 dispatch_opcode;
1966 case 31 :
1967 -- sp ; // Drop
1968 vars = g->frame->vars;
1970 tag = GetTag(&vars[1]);
1971 if (tag == tagInt) {
1972 SetRaw(&vars[4], slotRawInt(&vars[4]) + slotRawInt(&vars[1])); // inc i
1973 } else {
1974 SetRaw(&vars[4], slotRawFloat(&vars[4]) + slotRawFloat(&vars[1])); // inc i
1976 SetRaw(&vars[5], slotRawInt(&vars[5]) + 1); // inc j
1977 ip -= 4;
1978 dispatch_opcode;
1980 dispatch_opcode;
1983 // opStoreClassVar
1984 case 144 : case 145 : case 146 : case 147 :
1985 case 148 : case 149 : case 150 : case 151 :
1986 case 152 : case 153 : case 154 : case 155 :
1987 case 156 : case 157 : case 158 : case 159 :
1988 handle_op_144: handle_op_145: handle_op_146: handle_op_147:
1989 handle_op_148: handle_op_149: handle_op_150: handle_op_151:
1990 handle_op_152: handle_op_153: handle_op_154: handle_op_155:
1991 handle_op_156: handle_op_157: handle_op_158: handle_op_159:
1993 op2 = op1 & 15;
1994 op3 = ip[1]; ++ip; // get class var index
1995 slotCopy(&g->classvars->slots[(op2<<8)|op3], sp--);
1996 g->gc->GCWrite(g->classvars, (sp+1));
1997 dispatch_opcode;
1999 // opSendMsg
2000 case 160 :
2001 handle_op_160:
2002 // special case for this as only arg
2003 op2 = ip[1]; ++ip; // get selector index
2004 slotCopy(++sp, &g->receiver);
2005 numArgsPushed = 1;
2006 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2007 slot = sp;
2009 goto class_lookup;
2011 case 161 : case 162 : case 163 :
2012 case 164 : case 165 : case 166 : case 167 :
2013 case 168 : case 169 : case 170 : case 171 :
2014 case 172 : case 173 : case 174 : case 175 :
2015 handle_op_161: handle_op_162: handle_op_163:
2016 handle_op_164: handle_op_165: handle_op_166: handle_op_167:
2017 handle_op_168: handle_op_169: handle_op_170: handle_op_171:
2018 handle_op_172: handle_op_173: handle_op_174: handle_op_175:
2020 op2 = ip[1]; ++ip; // get selector index
2021 numArgsPushed = op1 & 15;
2022 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2023 slot = sp - numArgsPushed + 1;
2025 goto class_lookup;
2027 case 176 : // opcTailCallReturnFromFunction
2028 handle_op_176:
2029 #if TAILCALLOPTIMIZE
2030 g->tailCall = 2;
2031 #endif
2032 dispatch_opcode;
2033 // opSuperMsg
2034 case 177 :
2035 handle_op_177:
2036 // special case for this as only arg
2037 op2 = ip[1]; ++ip; // get selector index
2038 slotCopy(++sp, &g->receiver);
2039 numArgsPushed = 1;
2040 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2041 slot = sp;
2042 classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj;
2044 goto msg_lookup;
2046 case 178 : case 179 :
2047 case 180 : case 181 : case 182 : case 183 :
2048 case 184 : case 185 : case 186 : case 187 :
2049 case 188 : case 189 : case 190 : case 191 :
2051 handle_op_178: handle_op_179:
2052 handle_op_180: handle_op_181: handle_op_182: handle_op_183:
2053 handle_op_184: handle_op_185: handle_op_186: handle_op_187:
2054 handle_op_188: handle_op_189: handle_op_190: handle_op_191:
2056 op2 = ip[1]; ++ip; // get selector index
2057 numArgsPushed = op1 & 15;
2058 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2059 slot = sp - numArgsPushed + 1;
2060 classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj;
2062 goto msg_lookup;
2064 // opSendSpecialMsg
2065 case 192 :
2066 handle_op_192:
2067 slotCopy(++sp, &g->receiver);
2068 op2 = ip[1]; ++ip; // get selector index
2069 numArgsPushed = 1;
2070 selector = gSpecialSelectors[op2];
2071 slot = sp;
2073 goto class_lookup;
2075 case 193 : case 194 : case 195 :
2076 case 196 : case 197 : case 198 : case 199 :
2077 case 200 : case 201 : case 202 : case 203 :
2078 case 204 : case 205 : case 206 : case 207 :
2080 handle_op_193: handle_op_194: handle_op_195:
2081 handle_op_196: handle_op_197: handle_op_198: handle_op_199:
2082 handle_op_200: handle_op_201: handle_op_202: handle_op_203:
2083 handle_op_204: handle_op_205: handle_op_206: handle_op_207:
2085 op2 = ip[1]; ++ip; // get selector index
2086 numArgsPushed = op1 & 15;
2087 selector = gSpecialSelectors[op2];
2088 slot = sp - numArgsPushed + 1;
2090 goto class_lookup;
2092 // opSendSpecialUnaryArithMsg
2093 case 208 : // opNeg
2094 handle_op_208:
2095 if (IsFloat(sp)) {
2096 SetFloat(sp, -slotRawFloat(sp));
2097 #if TAILCALLOPTIMIZE
2098 g->tailCall = 0;
2099 #endif
2100 } else if (IsInt(sp)) {
2101 SetRaw(sp, -slotRawInt(sp));
2102 #if TAILCALLOPTIMIZE
2103 g->tailCall = 0;
2104 #endif
2105 } else
2106 handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2107 dispatch_opcode;
2108 case 209 : // opNot
2109 handle_op_209:
2110 if (IsTrue(sp)) {
2111 SetTagRaw(sp, tagFalse);
2112 #if TAILCALLOPTIMIZE
2113 g->tailCall = 0;
2114 #endif
2115 } else if (IsFalse(sp)) {
2116 SetTagRaw(sp, tagTrue);
2117 #if TAILCALLOPTIMIZE
2118 g->tailCall = 0;
2119 #endif
2120 } else
2121 handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2122 dispatch_opcode;
2123 case 210 : // opIsNil
2124 handle_op_210:
2125 if (IsNil(sp)) {
2126 SetTagRaw(sp, tagTrue);
2127 } else {
2128 slotCopy(sp, &gSpecialValues[svFalse]);
2130 #if TAILCALLOPTIMIZE
2131 g->tailCall = 0;
2132 #endif
2133 dispatch_opcode;
2134 case 211 : // opNotNil
2135 handle_op_211:
2136 if (NotNil(sp)) {
2137 slotCopy(sp, &gSpecialValues[svTrue]);
2138 } else {
2139 SetTagRaw(sp, tagFalse);
2141 #if TAILCALLOPTIMIZE
2142 g->tailCall = 0;
2143 #endif
2144 dispatch_opcode;
2146 case 212 : handle_op_212:
2147 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2148 case 213 : handle_op_213:
2149 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2150 case 214 : handle_op_214:
2151 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2152 case 215 : handle_op_215:
2153 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2154 case 216 : handle_op_216:
2155 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2156 case 217 : handle_op_217:
2157 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2158 case 218 : handle_op_218:
2159 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2160 case 219 : handle_op_219:
2161 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2162 case 220 : handle_op_220:
2163 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2164 case 221 : handle_op_221:
2165 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2166 case 222 : handle_op_222:
2167 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2168 case 223 : handle_op_223:
2169 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2172 // opSendSpecialBinaryArithMsg
2173 case 224 : // add
2174 handle_op_224:
2175 if (IsInt(sp - 1)) {
2176 if (IsInt(sp)) {
2177 --sp; SetRaw(sp, slotRawInt(sp) + slotRawInt(sp + 1));
2178 #if TAILCALLOPTIMIZE
2179 g->tailCall = 0;
2180 #endif
2181 } else {
2182 g->sp = sp; g->ip = ip;
2183 g->primitiveIndex = opAdd;
2184 prAddInt(g, -1);
2185 sp = g->sp; ip = g->ip;
2187 } else {
2188 g->sp = sp; g->ip = ip;
2189 g->primitiveIndex = opAdd;
2190 prAddNum(g, -1);
2191 sp = g->sp; ip = g->ip;
2193 dispatch_opcode;
2194 case 225 : // subtract
2195 handle_op_225:
2196 if (IsInt(sp - 1)) {
2197 if (IsInt(sp)) {
2198 --sp; SetRaw(sp, slotRawInt(sp) - slotRawInt(sp + 1));
2199 #if TAILCALLOPTIMIZE
2200 g->tailCall = 0;
2201 #endif
2202 } else {
2203 g->sp = sp; g->ip = ip;
2204 g->primitiveIndex = opSub;
2205 prSubInt(g, -1);
2206 sp = g->sp; ip = g->ip;
2208 } else {
2209 g->sp = sp; g->ip = ip;
2210 g->primitiveIndex = opSub;
2211 prSubNum(g, -1);
2212 sp = g->sp; ip = g->ip;
2214 dispatch_opcode;
2215 case 226 : // multiply
2216 handle_op_226:
2217 if (IsInt(sp - 1)) {
2218 if (IsInt(sp)) {
2219 --sp; SetRaw(sp, slotRawInt(sp) * slotRawInt(sp + 1));
2220 #if TAILCALLOPTIMIZE
2221 g->tailCall = 0;
2222 #endif
2223 } else {
2224 g->sp = sp; g->ip = ip;
2225 g->primitiveIndex = opMul;
2226 prMulInt(g, -1);
2227 sp = g->sp; ip = g->ip;
2229 } else {
2230 g->sp = sp; g->ip = ip;
2231 g->primitiveIndex = opMul;
2232 prMulNum(g, -1);
2233 sp = g->sp; ip = g->ip;
2235 dispatch_opcode;
2237 case 227 : handle_op_227:
2238 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2239 case 228 : handle_op_228:
2240 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2241 case 229 : handle_op_229:
2242 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2243 case 230 : handle_op_230:
2244 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2245 case 231 : handle_op_231:
2246 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2247 case 232 : handle_op_232:
2248 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2249 case 233 : handle_op_233:
2250 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2251 case 234 : handle_op_234:
2252 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2253 case 235 : handle_op_235:
2254 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2255 case 236 : handle_op_236:
2256 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2257 case 237 : handle_op_237:
2258 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2259 case 238 : handle_op_238:
2260 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2261 case 239 : handle_op_239:
2262 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2264 // opSpecialOpcodes
2265 case 240 :
2266 handle_op_240:
2267 --sp; dispatch_opcode; // opDrop
2268 case 241 :
2269 handle_op_241:
2270 ++sp; *sp = sp[-1]; dispatch_opcode; // opDup
2271 case 242 : // opcFunctionReturn
2272 handle_op_242:
2273 g->sp = sp; g->ip = ip;
2274 returnFromBlock(g);
2275 sp = g->sp; ip = g->ip;
2276 dispatch_opcode;
2277 case 243 : // opcReturn
2278 handle_op_243:
2279 g->sp = sp; g->ip = ip;
2280 returnFromMethod(g);
2281 sp = g->sp; ip = g->ip;
2282 dispatch_opcode;
2283 case 244 : // opcReturnSelf
2284 handle_op_244:
2285 slotCopy(++sp, &g->receiver);
2286 g->sp = sp; g->ip = ip;
2287 returnFromMethod(g);
2288 sp = g->sp; ip = g->ip;
2289 dispatch_opcode;
2290 case 245 : // opcReturnTrue
2291 handle_op_245:
2292 slotCopy(++sp, &gSpecialValues[svTrue]);
2293 g->sp = sp; g->ip = ip;
2294 returnFromMethod(g);
2295 sp = g->sp; ip = g->ip;
2296 dispatch_opcode;
2297 case 246 : // opcReturnFalse
2298 handle_op_246:
2299 slotCopy(++sp, &gSpecialValues[svFalse]);
2300 g->sp = sp; g->ip = ip;
2301 returnFromMethod(g);
2302 sp = g->sp; ip = g->ip;
2303 dispatch_opcode;
2304 case 247 : // opcReturnNil
2305 handle_op_247:
2306 slotCopy(++sp, &gSpecialValues[svNil]);
2307 g->sp = sp; g->ip = ip;
2308 returnFromMethod(g);
2309 sp = g->sp; ip = g->ip;
2310 dispatch_opcode;
2312 case 248 : // opcJumpIfFalse
2313 handle_op_248:
2314 // cannot compare with o_false because it is NaN
2315 if ( IsFalse(sp) ) {
2316 jmplen = (ip[1]<<8) | ip[2];
2317 ip += jmplen + 2;
2318 } else if ( IsTrue(sp)) {
2319 ip+=2;
2320 } else {
2321 numArgsPushed = 1;
2322 selector = gSpecialSelectors[opmNonBooleanError];
2323 slot = sp;
2325 goto class_lookup;
2327 --sp;
2328 dispatch_opcode;
2329 case 249 : // opcJumpIfFalsePushNil
2330 handle_op_249:
2331 if ( IsFalse(sp)) {
2332 jmplen = (ip[1]<<8) | ip[2];
2333 ip += jmplen + 2;
2334 slotCopy(sp, &gSpecialValues[svNil]);
2335 } else if ( IsTrue(sp)) {
2336 --sp;
2337 ip+=2;
2338 } else {
2339 numArgsPushed = 1;
2340 selector = gSpecialSelectors[opmNonBooleanError];
2341 slot = sp;
2343 goto class_lookup;
2345 dispatch_opcode;
2346 case 250 : // opcJumpIfFalsePushFalse
2347 handle_op_250:
2348 if (IsFalse(sp)) {
2349 jmplen = (ip[1]<<8) | ip[2];
2350 ip += jmplen + 2;
2351 //*sp = r_false;
2352 } else if (IsTrue(sp)) {
2353 --sp;
2354 ip+=2;
2355 } else {
2356 numArgsPushed = 1;
2357 selector = gSpecialSelectors[opmNonBooleanError];
2358 slot = sp;
2360 goto class_lookup;
2362 dispatch_opcode;
2363 case 251 : // opcJumpIfTruePushTrue
2364 handle_op_251:
2365 if (IsFalse(sp)) {
2366 --sp;
2367 ip+=2;
2368 } else if (IsTrue(sp)) {
2369 jmplen = (ip[1]<<8) | ip[2];
2370 ip += jmplen + 2;
2371 slotCopy(sp, &gSpecialValues[svTrue]);
2372 } else {
2373 numArgsPushed = 1;
2374 selector = gSpecialSelectors[opmNonBooleanError];
2375 slot = sp;
2377 goto class_lookup;
2379 dispatch_opcode;
2380 case 252 : // opcJumpFwd
2381 handle_op_252:
2382 jmplen = (ip[1]<<8) | ip[2];
2383 ip += jmplen + 2;
2384 dispatch_opcode;
2385 case 253 : // opcJumpBak
2386 handle_op_253:
2387 --sp; // also drops the stack. This saves an opcode in the while loop
2388 // which is the only place this opcode is used.
2389 jmplen = (ip[1]<<8) | ip[2];
2390 ip -= jmplen;
2392 //assert(g->gc->SanityCheck());
2393 dispatch_opcode;
2394 case 254 : // opcSpecialBinaryOpWithAdverb
2395 handle_op_254:
2396 op2 = ip[1]; ++ip; // get selector index
2397 g->sp = sp; g->ip = ip;
2398 g->primitiveIndex = op2;
2399 doSpecialBinaryArithMsg(g, 3, false);
2400 sp = g->sp; ip = g->ip;
2401 dispatch_opcode;
2402 case 255 : // opcTailCallReturnFromMethod
2403 handle_op_255:
2404 #if TAILCALLOPTIMIZE
2405 g->tailCall = 1;
2406 #endif
2407 dispatch_opcode;
2409 ////////////////////////////////////
2411 class_lookup:
2412 // normal class lookup
2413 classobj = classOfSlot(slot);
2415 // message sends handled here:
2416 msg_lookup:
2417 index = slotRawInt(&classobj->classIndex) + selector->u.index;
2418 meth = gRowTable[index];
2420 if (UNLIKELY(slotRawSymbol(&meth->name) != selector)) {
2421 g->sp = sp; g->ip = ip;
2422 doesNotUnderstand(g, selector, numArgsPushed);
2423 sp = g->sp; ip = g->ip;
2424 } else {
2425 PyrMethodRaw *methraw;
2426 methraw = METHRAW(meth);
2427 switch (methraw->methType) {
2428 case methNormal : /* normal msg send */
2429 g->sp = sp; g->ip = ip;
2430 executeMethod(g, meth, numArgsPushed);
2431 sp = g->sp; ip = g->ip;
2432 break;
2433 case methReturnSelf : /* return self */
2434 sp -= numArgsPushed - 1;
2435 break;
2436 case methReturnLiteral : /* return literal */
2437 sp -= numArgsPushed - 1;
2438 slotCopy(sp, &meth->selectors); /* in this case selectors is just a single value */
2439 break;
2440 case methReturnArg : /* return an argument */
2441 sp -= numArgsPushed - 1;
2442 index = methraw->specialIndex; // zero is index of the first argument
2443 if (index < numArgsPushed) {
2444 slotCopy(sp, sp + index);
2445 } else {
2446 slotCopy(sp, &slotRawObject(&meth->prototypeFrame)->slots[index]);
2448 break;
2449 case methReturnInstVar : /* return inst var */
2450 sp -= numArgsPushed - 1;
2451 index = methraw->specialIndex;
2452 slotCopy(sp, &slotRawObject(slot)->slots[index]);
2453 break;
2454 case methAssignInstVar : /* assign inst var */
2455 sp -= numArgsPushed - 1;
2456 index = methraw->specialIndex;
2457 obj = slotRawObject(slot);
2458 if (obj->IsImmutable()) { StoreToImmutableB(g, sp, ip); }
2459 else {
2460 if (numArgsPushed >= 2) {
2461 slotCopy(&obj->slots[index], sp + 1);
2462 g->gc->GCWrite(obj, sp + 1);
2463 } else {
2464 slotCopy(&obj->slots[index], &gSpecialValues[svNil]);
2466 slotCopy(sp, slot);
2468 break;
2469 case methReturnClassVar : /* return class var */
2470 sp -= numArgsPushed - 1;
2471 slotCopy(sp, &g->classvars->slots[methraw->specialIndex]);
2472 break;
2473 case methAssignClassVar : /* assign class var */
2474 sp -= numArgsPushed - 1;
2475 if (numArgsPushed >= 2) {
2476 slotCopy(&g->classvars->slots[methraw->specialIndex], sp + 1);
2477 g->gc->GCWrite(g->classvars, sp + 1);
2478 } else
2479 slotCopy(&g->classvars->slots[methraw->specialIndex], &gSpecialValues[svNil]);
2480 slotCopy(sp, slot);
2481 break;
2482 case methRedirect : /* send a different selector to self */
2483 if (numArgsPushed < methraw->numargs) { // not enough args pushed
2484 /* push default arg values */
2485 PyrSlot *qslot;
2486 int m, mmax;
2487 qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
2488 for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++sp, ++qslot);
2489 numArgsPushed = methraw->numargs;
2491 selector = slotRawSymbol(&meth->selectors);
2492 goto msg_lookup;
2493 case methRedirectSuper : /* send a different selector to self */
2494 if (numArgsPushed < methraw->numargs) { // not enough args pushed
2495 /* push default arg values */
2496 PyrSlot *qslot;
2497 int m, mmax;
2498 qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
2499 for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++sp, ++qslot);
2500 numArgsPushed = methraw->numargs;
2502 selector = slotRawSymbol(&meth->selectors);
2503 classobj = slotRawSymbol(&slotRawClass(&meth->ownerclass)->superclass)->u.classobj;
2504 goto msg_lookup;
2505 case methForwardInstVar : /* forward to an instance variable */
2506 if (numArgsPushed < methraw->numargs) { // not enough args pushed
2507 /* push default arg values */
2508 PyrSlot *qslot;
2509 int m, mmax;
2510 qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
2511 for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++sp, ++qslot);
2512 numArgsPushed = methraw->numargs;
2514 selector = slotRawSymbol(&meth->selectors);
2515 index = methraw->specialIndex;
2516 slotCopy(slot, &slotRawObject(slot)->slots[index]);
2518 classobj = classOfSlot(slot);
2520 goto msg_lookup;
2521 case methForwardClassVar : /* forward to an instance variable */
2522 if (numArgsPushed < methraw->numargs) { // not enough args pushed
2523 /* push default arg values */
2524 PyrSlot *qslot;
2525 int m, mmax;
2526 qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
2527 for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++sp, ++qslot);
2528 numArgsPushed = methraw->numargs;
2530 selector = slotRawSymbol(&meth->selectors);
2531 slotCopy(slot, &g->classvars->slots[methraw->specialIndex]);
2533 classobj = classOfSlot(slot);
2535 goto msg_lookup;
2536 case methPrimitive : /* primitive */
2537 g->sp = sp; g->ip = ip;
2538 doPrimitive(g, meth, numArgsPushed);
2539 sp = g->sp; ip = g->ip;
2540 break;
2541 } // switch (meth->methType)
2542 } // end handle message
2543 #if TAILCALLOPTIMIZE
2544 g->tailCall = 0;
2545 #endif
2546 dispatch_opcode;
2548 ////////////////////////////////////
2550 key_class_lookup:
2551 // normal class lookup
2552 classobj = classOfSlot(slot);
2554 // message sends handled here:
2555 key_msg_lookup:
2556 index = slotRawInt(&classobj->classIndex) + selector->u.index;
2557 meth = gRowTable[index];
2559 if (UNLIKELY(slotRawSymbol(&meth->name) != selector)) {
2560 g->sp = sp; g->ip = ip;
2561 doesNotUnderstandWithKeys(g, selector, numArgsPushed, numKeyArgsPushed);
2562 sp = g->sp; ip = g->ip;
2563 } else {
2564 PyrMethodRaw *methraw;
2565 methraw = METHRAW(meth);
2566 switch (methraw->methType) {
2567 case methNormal : /* normal msg send */
2568 g->sp = sp; g->ip = ip;
2569 executeMethodWithKeys(g, meth, numArgsPushed, numKeyArgsPushed);
2570 sp = g->sp; ip = g->ip;
2571 break;
2572 case methReturnSelf : /* return self */
2573 sp -= numArgsPushed - 1;
2574 break;
2575 case methReturnLiteral : /* return literal */
2576 sp -= numArgsPushed - 1;
2577 slotCopy(sp, &meth->selectors); /* in this case selectors is just a single value */
2578 break;
2579 case methReturnArg : /* return an argument */
2580 g->sp = sp;
2581 numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
2582 numKeyArgsPushed = 0;
2583 sp = g->sp;
2584 sp -= numArgsPushed - 1;
2585 index = methraw->specialIndex; // zero is index of the first argument
2586 if (index < numArgsPushed) {
2587 slotCopy(sp, sp + index);
2588 } else {
2589 slotCopy(sp, &slotRawObject(&meth->prototypeFrame)->slots[index]);
2591 break;
2592 case methReturnInstVar : /* return inst var */
2593 sp -= numArgsPushed - 1;
2594 index = methraw->specialIndex;
2595 slotCopy(sp, &slotRawObject(slot)->slots[index]);
2596 break;
2597 case methAssignInstVar : /* assign inst var */
2598 sp -= numArgsPushed - 1;
2599 numArgsPushed -= numKeyArgsPushed << 1;
2600 index = methraw->specialIndex;
2601 obj = slotRawObject(slot);
2602 if (obj->IsImmutable()) { StoreToImmutableB(g, sp, ip); }
2603 else {
2604 if (numArgsPushed >= 2) {
2605 slotCopy(&obj->slots[index], sp + 1);
2606 g->gc->GCWrite(obj, sp + 1);
2607 } else
2608 slotCopy(&obj->slots[index], &gSpecialValues[svNil]);
2609 slotCopy(sp, slot);
2611 break;
2612 case methReturnClassVar : /* return class var */
2613 sp -= numArgsPushed - 1;
2614 slotCopy(sp, &g->classvars->slots[methraw->specialIndex]);
2615 break;
2616 case methAssignClassVar : /* assign class var */
2617 sp -= numArgsPushed - 1;
2618 if (numArgsPushed >= 2) {
2619 slotCopy(&g->classvars->slots[methraw->specialIndex], sp + 1);
2620 g->gc->GCWrite(g->classvars, sp + 1);
2621 } else
2622 slotCopy(&g->classvars->slots[methraw->specialIndex], &gSpecialValues[svNil]);
2623 slotCopy(sp, slot);
2624 break;
2625 case methRedirect : /* send a different selector to self, e.g. this.subclassResponsibility */
2626 g->sp = sp;
2627 numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
2628 numKeyArgsPushed = 0;
2629 sp = g->sp;
2630 selector = slotRawSymbol(&meth->selectors);
2632 goto msg_lookup;
2633 case methRedirectSuper : /* send a different selector to super */
2634 g->sp = sp;
2635 numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
2636 numKeyArgsPushed = 0;
2637 sp = g->sp;
2638 selector = slotRawSymbol(&meth->selectors);
2640 classobj = slotRawSymbol(&slotRawClass(&meth->ownerclass)->superclass)->u.classobj;
2642 goto msg_lookup;
2643 case methForwardInstVar : /* forward to an instance variable */
2644 g->sp = sp;
2645 numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
2646 numKeyArgsPushed = 0;
2647 sp = g->sp;
2648 selector = slotRawSymbol(&meth->selectors);
2649 index = methraw->specialIndex;
2650 slotCopy(slot, &slotRawObject(slot)->slots[index]);
2652 classobj = classOfSlot(slot);
2654 goto msg_lookup;
2655 case methForwardClassVar : /* forward to an instance variable */
2656 g->sp = sp;
2657 numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
2658 numKeyArgsPushed = 0;
2659 sp = g->sp;
2660 selector = slotRawSymbol(&meth->selectors);
2661 slotCopy(slot, &g->classvars->slots[methraw->specialIndex]);
2663 classobj = classOfSlot(slot);
2665 goto msg_lookup;
2666 case methPrimitive : /* primitive */
2667 g->sp = sp; g->ip = ip;
2668 doPrimitiveWithKeys(g, meth, numArgsPushed, numKeyArgsPushed);
2669 sp = g->sp; ip = g->ip;
2670 break;
2671 } // switch (meth->methType)
2672 } // end handle message
2673 numKeyArgsPushed = 0;
2674 #if TAILCALLOPTIMIZE
2675 g->tailCall = 0;
2676 #endif
2677 dispatch_opcode;
2678 } // switch(op1)
2679 } // end while(running)
2680 #ifndef SC_WIN32
2681 running = true; // reset the signal
2682 #endif
2683 g->sp = sp; g->ip = ip;
2686 void DumpSimpleBackTrace(VMGlobals *g);
2687 void DumpSimpleBackTrace(VMGlobals *g)
2689 int i;
2690 PyrFrame *frame;
2692 post("CALL STACK:\n");
2693 // print the variables and arguments for the most recent frames in the
2694 // call graph
2695 frame = g->frame;
2697 for (i=0; i<16; ++i) {
2698 char str[256];
2699 slotOneWord(&frame->method, str);
2700 post("%s ip %d\n", str, (char*)slotRawPtr(&frame->ip) - (char*)slotRawObject(&slotRawMethod(&frame->method)->code)->slots);
2701 frame = slotRawFrame(&frame->caller);
2702 if (!frame) break;
2704 if (frame) { post("...\n"); }
2705 //DumpStack(g, g->sp);
2708 void DumpBackTrace(VMGlobals *g)
2710 int i;
2711 PyrFrame *frame;
2713 post("CALL STACK:\n");
2714 // print the variables and arguments for the most recent frames in the
2715 // call graph
2716 frame = g->frame;
2718 for (i=0; i<16; ++i) {
2719 if (FrameSanity(frame, "DumpBackTrace")) {
2720 post("FRAME CORRUPTED\n");
2721 return;
2723 DumpFrame(frame);
2724 frame = slotRawFrame(&frame->caller);
2725 if (!frame) break;
2727 if (frame) { post("...\n"); }
2728 //DumpStack(g, g->sp);
2731 void DumpDetailedFrame(PyrFrame *frame);
2732 void DumpDetailedBackTrace(VMGlobals *g);
2733 void DumpDetailedBackTrace(VMGlobals *g)
2735 int i;
2736 PyrFrame *frame;
2738 post("CALL STACK:\n");
2739 // print the variables and arguments for the most recent frames in the
2740 // call graph
2741 frame = g->frame;
2743 for (i=0; i<16; ++i) {
2744 if (FrameSanity(frame, "DumpDetailedBackTrace")) {
2745 post("FRAME CORRUPTED\n");
2746 return;
2748 DumpDetailedFrame(frame);
2749 frame = slotRawFrame(&frame->caller);
2750 if (!frame) break;
2752 if (frame) { post("...\n"); }
2753 //DumpStack(g, g->sp);
2756 void DumpStack(VMGlobals *g, PyrSlot *sp)
2758 PyrSlot *slot;
2759 char str[128];
2760 #if BCSTAT
2761 dumpbcstat();
2762 #endif
2763 postfl("STACK:\n");
2764 slot = sp - 64;
2765 if (slot < g->gc->Stack()->slots) slot = g->gc->Stack()->slots;
2766 for (size_t i=slot - g->gc->Stack()->slots; slot<=sp; slot++, ++i) {
2767 slotString(slot, str);
2768 post(" %2d %s\n", i, str);