supernova: fix for small audio vector sizes
[supercollider.git] / lang / LangSource / PyrInterpreter3.cpp
blob5ad7cd297300365855f1661304a40ec861fbf2b7
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 "bullet.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 int 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->obj_flags & obj_immutable)
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
527 void Interpret(VMGlobals *g)
529 // byte code values
530 unsigned char *ip;
531 unsigned char op1;
532 int op2, op3, index, tag;
533 // interpreter globals
535 // temporary variables used in the interpreter
536 int ival, jmplen, numArgsPushed, numKeyArgsPushed;
537 PyrFrame *tframe;
538 PyrSymbol *selector;
539 PyrClass *classobj;
540 PyrSlot *slot, *vars;
541 PyrSlot *sp, *pslot;
542 PyrObject *obj;
543 PyrClosure *closure;
544 PyrMethod *meth;
545 int m,mmax;
547 #ifdef LABELS_AS_VALUES
548 static void * opcode_labels[] = {
549 &&handle_op_0,
550 &&handle_op_1,
551 &&handle_op_2,
552 &&handle_op_3,
553 &&handle_op_4,
554 &&handle_op_5,
555 &&handle_op_6,
556 &&handle_op_7,
557 &&handle_op_8,
558 &&handle_op_9,
559 &&handle_op_10,
560 &&handle_op_11,
561 &&handle_op_12,
562 &&handle_op_13,
563 &&handle_op_14,
564 &&handle_op_15,
565 &&handle_op_16,
566 &&handle_op_17,
567 &&handle_op_18,
568 &&handle_op_19,
569 &&handle_op_20,
570 &&handle_op_21,
571 &&handle_op_22,
572 &&handle_op_23,
573 &&handle_op_24,
574 &&handle_op_25,
575 &&handle_op_26,
576 &&handle_op_27,
577 &&handle_op_28,
578 &&handle_op_29,
579 &&handle_op_30,
580 &&handle_op_31,
581 &&handle_op_32,
582 &&handle_op_33,
583 &&handle_op_34,
584 &&handle_op_35,
585 &&handle_op_36,
586 &&handle_op_37,
587 &&handle_op_38,
588 &&handle_op_39,
589 &&handle_op_40,
590 &&handle_op_41,
591 &&handle_op_42,
592 &&handle_op_43,
593 &&handle_op_44,
594 &&handle_op_45,
595 &&handle_op_46,
596 &&handle_op_47,
597 &&handle_op_48,
598 &&handle_op_49,
599 &&handle_op_50,
600 &&handle_op_51,
601 &&handle_op_52,
602 &&handle_op_53,
603 &&handle_op_54,
604 &&handle_op_55,
605 &&handle_op_56,
606 &&handle_op_57,
607 &&handle_op_58,
608 &&handle_op_59,
609 &&handle_op_60,
610 &&handle_op_61,
611 &&handle_op_62,
612 &&handle_op_63,
613 &&handle_op_64,
614 &&handle_op_65,
615 &&handle_op_66,
616 &&handle_op_67,
617 &&handle_op_68,
618 &&handle_op_69,
619 &&handle_op_70,
620 &&handle_op_71,
621 &&handle_op_72,
622 &&handle_op_73,
623 &&handle_op_74,
624 &&handle_op_75,
625 &&handle_op_76,
626 &&handle_op_77,
627 &&handle_op_78,
628 &&handle_op_79,
629 &&handle_op_80,
630 &&handle_op_81,
631 &&handle_op_82,
632 &&handle_op_83,
633 &&handle_op_84,
634 &&handle_op_85,
635 &&handle_op_86,
636 &&handle_op_87,
637 &&handle_op_88,
638 &&handle_op_89,
639 &&handle_op_90,
640 &&handle_op_91,
641 &&handle_op_92,
642 &&handle_op_93,
643 &&handle_op_94,
644 &&handle_op_95,
645 &&handle_op_96,
646 &&handle_op_97,
647 &&handle_op_98,
648 &&handle_op_99,
649 &&handle_op_100,
650 &&handle_op_101,
651 &&handle_op_102,
652 &&handle_op_103,
653 &&handle_op_104,
654 &&handle_op_105,
655 &&handle_op_106,
656 &&handle_op_107,
657 &&handle_op_108,
658 &&handle_op_109,
659 &&handle_op_110,
660 &&handle_op_111,
661 &&handle_op_112,
662 &&handle_op_113,
663 &&handle_op_114,
664 &&handle_op_115,
665 &&handle_op_116,
666 &&handle_op_117,
667 &&handle_op_118,
668 &&handle_op_119,
669 &&handle_op_120,
670 &&handle_op_121,
671 &&handle_op_122,
672 &&handle_op_123,
673 &&handle_op_124,
674 &&handle_op_125,
675 &&handle_op_126,
676 &&handle_op_127,
677 &&handle_op_128,
678 &&handle_op_129,
679 &&handle_op_130,
680 &&handle_op_131,
681 &&handle_op_132,
682 &&handle_op_133,
683 &&handle_op_134,
684 &&handle_op_135,
685 &&handle_op_136,
686 &&handle_op_137,
687 &&handle_op_138,
688 &&handle_op_139,
689 &&handle_op_140,
690 &&handle_op_141,
691 &&handle_op_142,
692 &&handle_op_143,
693 &&handle_op_144,
694 &&handle_op_145,
695 &&handle_op_146,
696 &&handle_op_147,
697 &&handle_op_148,
698 &&handle_op_149,
699 &&handle_op_150,
700 &&handle_op_151,
701 &&handle_op_152,
702 &&handle_op_153,
703 &&handle_op_154,
704 &&handle_op_155,
705 &&handle_op_156,
706 &&handle_op_157,
707 &&handle_op_158,
708 &&handle_op_159,
709 &&handle_op_160,
710 &&handle_op_161,
711 &&handle_op_162,
712 &&handle_op_163,
713 &&handle_op_164,
714 &&handle_op_165,
715 &&handle_op_166,
716 &&handle_op_167,
717 &&handle_op_168,
718 &&handle_op_169,
719 &&handle_op_170,
720 &&handle_op_171,
721 &&handle_op_172,
722 &&handle_op_173,
723 &&handle_op_174,
724 &&handle_op_175,
725 &&handle_op_176,
726 &&handle_op_177,
727 &&handle_op_178,
728 &&handle_op_179,
729 &&handle_op_180,
730 &&handle_op_181,
731 &&handle_op_182,
732 &&handle_op_183,
733 &&handle_op_184,
734 &&handle_op_185,
735 &&handle_op_186,
736 &&handle_op_187,
737 &&handle_op_188,
738 &&handle_op_189,
739 &&handle_op_190,
740 &&handle_op_191,
741 &&handle_op_192,
742 &&handle_op_193,
743 &&handle_op_194,
744 &&handle_op_195,
745 &&handle_op_196,
746 &&handle_op_197,
747 &&handle_op_198,
748 &&handle_op_199,
749 &&handle_op_200,
750 &&handle_op_201,
751 &&handle_op_202,
752 &&handle_op_203,
753 &&handle_op_204,
754 &&handle_op_205,
755 &&handle_op_206,
756 &&handle_op_207,
757 &&handle_op_208,
758 &&handle_op_209,
759 &&handle_op_210,
760 &&handle_op_211,
761 &&handle_op_212,
762 &&handle_op_213,
763 &&handle_op_214,
764 &&handle_op_215,
765 &&handle_op_216,
766 &&handle_op_217,
767 &&handle_op_218,
768 &&handle_op_219,
769 &&handle_op_220,
770 &&handle_op_221,
771 &&handle_op_222,
772 &&handle_op_223,
773 &&handle_op_224,
774 &&handle_op_225,
775 &&handle_op_226,
776 &&handle_op_227,
777 &&handle_op_228,
778 &&handle_op_229,
779 &&handle_op_230,
780 &&handle_op_231,
781 &&handle_op_232,
782 &&handle_op_233,
783 &&handle_op_234,
784 &&handle_op_235,
785 &&handle_op_236,
786 &&handle_op_237,
787 &&handle_op_238,
788 &&handle_op_239,
789 &&handle_op_240,
790 &&handle_op_241,
791 &&handle_op_242,
792 &&handle_op_243,
793 &&handle_op_244,
794 &&handle_op_245,
795 &&handle_op_246,
796 &&handle_op_247,
797 &&handle_op_248,
798 &&handle_op_249,
799 &&handle_op_250,
800 &&handle_op_251,
801 &&handle_op_252,
802 &&handle_op_253,
803 &&handle_op_254,
804 &&handle_op_255
807 #endif
809 #if 0
810 unsigned char *bzero;
811 PyrSlot *szero;
812 char str[80];
813 #endif
816 #if BCSTAT
817 //clearbcstat();
818 op1 = 0;
819 prevop = 0;
820 #endif
822 #if 0
823 bzero = g->ip;
824 szero = g->sp;
825 //SetSymbol(g->sp, getsym("STACK TOP")); // just for debugging
826 //g->sp++; // just for debugging
827 #endif
829 // Codewarrior puts them in registers. take advantage..
830 sp = g->sp;
831 ip = g->ip;
833 numKeyArgsPushed = 0;
835 if (setjmp(g->escapeInterpreter) != 0) {
836 return;
838 #ifndef SC_WIN32
839 while (running) { // not going to indent body to save line space
840 #else
841 while (true) {
842 #endif
844 checkStackDepth(g, sp);
846 #if BCSTAT
847 prevop = op1;
848 #endif
850 op1 = ip[1];
851 ++ip;
853 assert(checkStackOverflow(g, sp));
855 #if BCSTAT
856 ++bcstat[op1];
857 ++bcpair[prevop][op1];
858 prevop = op1;
859 #endif
860 //printf("op1 %d\n", op1);
861 //postfl("sp %p frame %p caller %p ip %p\n", sp, g->frame, g->frame->caller.uof, slotRawInt(&g->frame->caller.uof->ip));
862 //postfl("sp %p frame %p diff %d caller %p\n", sp, g->frame, ((int)sp - (int)g->frame)>>3, g->frame->caller.uof);
863 #if DEBUGINTERPRETER
864 if (gTraceInterpreter) {
865 //DumpStack(g, sp);
866 if (FrameSanity(g->frame, "dbgint")) {
867 //Debugger();
869 //g->gc->SanityCheck();
870 //assert(g->gc->SanityCheck());
871 g->sp = sp; g->ip = ip;
872 g->gc->FullCollection();
873 sp = g->sp; ip = g->ip;
874 postfl("[%3d] %20s-%-16s ",
875 (sp - g->gc->Stack()->slots) + 1,
876 slotRawSymbol(&slotRawClass(&g->method->ownerclass)->name)->name, slotRawSymbol(&g->method->name)->name);
877 dumpOneByteCode(g->block, NULL, ip);
879 #endif
880 #ifdef GC_SANITYCHECK
881 // gcLinkSanity(g->gc);
882 g->gc->SanityCheck();
883 // do_check_pool(pyr_pool_runtime);
884 // do_check_pool(pyr_pool_compile);
885 #endif
886 #if METHODMETER
887 if (gTraceInterpreter) {
888 slotRawInt(&g->method->byteMeter)++;
890 #endif
892 switch (op1) {
893 case 0 : // push class
894 handle_op_0:
895 op2 = ip[1]; ++ip; // get literal index
896 classobj = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2])->u.classobj;
897 if (classobj) {
898 ++sp; SetObject(sp, classobj);
899 } else {
900 postfl("Execution warning: Class '%s' not found\n", slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2])->name);
901 slotCopy(++sp, &gSpecialValues[svNil]);
903 dispatch_opcode;
904 case 1 : // opExtended, opPushInstVar
905 handle_op_1:
906 op2 = ip[1]; ++ip; // get inst var index
907 slotCopy(++sp, &slotRawObject(&g->receiver)->slots[op2]);
908 dispatch_opcode;
909 case 2 : // opExtended, opPushTempVar
910 handle_op_2:
911 op2 = ip[1]; // get temp var level
912 op3 = ip[2]; // get temp var index
913 ip += 2;
914 for (tframe = g->frame; --op2; tframe = slotRawFrame(&tframe->context)) { /* noop */ }
915 slotCopy(++sp, &tframe->vars[op3]);
916 dispatch_opcode;
917 case 3 : // opExtended, opPushTempZeroVar
918 handle_op_3:
919 op2 = ip[1]; ++ip; // get temp var index
920 slotCopy(++sp, &g->frame->vars[op2]);
921 dispatch_opcode;
922 case 4 : // opExtended, opPushLiteral
923 handle_op_4:
924 op2 = ip[1]; ++ip; // get literal index
925 // push a block as a closure if it is one
926 slot = slotRawObject(&g->block->selectors)->slots + op2;
927 if (IsObj(slot) && slotRawObject(slot)->classptr == gSpecialClasses[op_class_fundef]->u.classobj) {
928 // push a closure
929 g->sp = sp; // gc may push the stack
930 closure = (PyrClosure*)g->gc->New(2*sizeof(PyrSlot), 0, obj_notindexed, true);
931 sp = g->sp;
932 closure->classptr = gSpecialClasses[op_class_func]->u.classobj;
933 closure->size = 2;
934 slotCopy(&closure->block, slot);
935 if (IsNil(&slotRawBlock(slot)->contextDef)) {
936 slotCopy(&closure->context, &slotRawInterpreter(&g->process->interpreter)->context);
937 } else {
938 SetObject(&closure->context, g->frame);
940 ++sp; SetObject(sp, closure);
941 } else {
942 slotCopy(++sp, slot);
944 dispatch_opcode;
945 case 5 : // opExtended, opPushClassVar
946 handle_op_5:
947 op2 = ip[1]; // get class
948 op3 = ip[2]; // get class var index
949 ip += 2;
950 slotCopy(++sp, &g->classvars->slots[(op2<<8)|op3]);
951 dispatch_opcode;
952 case 6 : // opExtended, opPushSpecialValue == push a special class
953 handle_op_6:
954 op2 = ip[1]; ++ip; // get class name index
955 classobj = gSpecialClasses[op2]->u.classobj;
956 if (classobj) {
957 ++sp; SetObject(sp, classobj);
958 } else {
959 slotCopy(++sp, &gSpecialValues[svNil]);
961 dispatch_opcode;
962 case 7 : // opExtended, opStoreInstVar
963 handle_op_7:
964 op2 = ip[1]; ++ip; // get inst var index
965 obj = slotRawObject(&g->receiver);
966 if (obj->obj_flags & obj_immutable) { StoreToImmutableA(g, sp, ip); }
967 else {
968 slot = obj->slots + op2;
969 slotCopy(slot, sp);
970 g->gc->GCWrite(obj, slot);
972 dispatch_opcode;
973 case 8 : // opExtended, opStoreTempVar
974 handle_op_8:
975 op2 = ip[1]; // get temp var level
976 op3 = ip[2]; // get temp var index
977 ip += 2;
978 for (tframe = g->frame; op2--; tframe = slotRawFrame(&tframe->context)) { /* noop */ }
979 slot = tframe->vars + op3;
980 slotCopy(slot, sp);
981 g->gc->GCWrite(tframe, slot);
982 dispatch_opcode;
983 case 9 : // opExtended, opStoreClassVar
984 handle_op_9:
985 op2 = ip[1]; // get index of class name literal
986 op3 = ip[2]; // get class var index
987 ip += 2;
988 slotCopy(&g->classvars->slots[(op2<<8)|op3], sp);
989 g->gc->GCWrite(g->classvars, sp);
990 dispatch_opcode;
991 case 10 : // opExtended, opSendMsg
992 handle_op_10:
993 numArgsPushed = ip[1]; // get num args
994 numKeyArgsPushed = ip[2]; // get num keyword args
995 op3 = ip[3]; // get selector index
996 ip += 3;
997 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op3]);
999 slot = sp - numArgsPushed + 1;
1001 if (numKeyArgsPushed) goto key_class_lookup;
1002 else goto class_lookup;
1004 case 11 : // opExtended, opSendSuper
1005 handle_op_11:
1006 numArgsPushed = ip[1]; // get num args
1007 numKeyArgsPushed = ip[2]; // get num keyword args
1008 op3 = ip[3]; // get selector index
1009 ip += 3;
1010 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op3]);
1012 slot = g->sp - numArgsPushed + 1;
1013 classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj;
1015 if (numKeyArgsPushed) goto key_msg_lookup;
1016 else goto msg_lookup;
1018 case 12 : // opExtended, opSendSpecialMsg
1019 handle_op_12:
1020 numArgsPushed = ip[1]; // get num args
1021 numKeyArgsPushed = ip[2]; // get num keyword args
1022 op3 = ip[3]; // get selector index
1023 ip += 3;
1025 selector = gSpecialSelectors[op3];
1026 slot = sp - numArgsPushed + 1;
1028 if (numKeyArgsPushed) goto key_class_lookup;
1029 else goto class_lookup;
1031 case 13 : // opExtended, opSendSpecialUnaryArithMsg
1032 handle_op_13:
1033 op2 = ip[1]; ++ip; // get selector index
1034 g->sp = sp; g->ip = ip;
1035 g->primitiveIndex = op2;
1036 doSpecialUnaryArithMsg(g, -1);
1037 #if TAILCALLOPTIMIZE
1038 g->tailCall = 0;
1039 #endif
1040 sp = g->sp; ip = g->ip;
1041 dispatch_opcode;
1042 case 14 : // opExtended, opSendSpecialBinaryArithMsg
1043 handle_op_14:
1044 op2 = ip[1]; ++ip; // get selector index
1045 g->sp = sp; g->ip = ip;
1046 g->primitiveIndex = op2;
1047 doSpecialBinaryArithMsg(g, 2, false);
1048 sp = g->sp; ip = g->ip;
1049 dispatch_opcode;
1050 case 15 : // opExtended, opSpecialOpcode (none yet)
1051 handle_op_15:
1052 op2 = ip[1]; ++ip; // get extended special opcode
1053 switch (op2) {
1054 case opgProcess : // push thisProcess
1055 ++sp; SetObject(sp, g->process); break;
1056 case opgThread : // push thisProcess
1057 ++sp; SetObject(sp, g->thread); break;
1058 case opgMethod : // push thisMethod
1059 ++sp; SetObject(sp, g->method); break;
1060 case opgFunctionDef : // push thisFunctionDef
1061 ++sp; SetObject(sp, g->block); break;
1062 case opgFunction : // push thisFunc
1063 // push a closure
1064 g->sp = sp; // gc may push the stack
1065 closure = (PyrClosure*)g->gc->New(2*sizeof(PyrSlot), 0, obj_notindexed, true);
1066 sp = g->sp;
1067 closure->classptr = gSpecialClasses[op_class_func]->u.classobj;
1068 closure->size = 2;
1069 SetObject(&closure->block, g->block);
1070 SetObject(&closure->context, slotRawFrame(&g->frame->context));
1071 ++sp; SetObject(sp, closure);
1072 break;
1073 default :
1074 slotCopy(++sp, &gSpecialValues[svNil]); break;
1076 dispatch_opcode;
1077 // opPushInstVar, 0..15
1078 case 16 : handle_op_16: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 0]); dispatch_opcode;
1079 case 17 : handle_op_17: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 1]); dispatch_opcode;
1080 case 18 : handle_op_18: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 2]); dispatch_opcode;
1081 case 19 : handle_op_19: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 3]); dispatch_opcode;
1082 case 20 : handle_op_20: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 4]); dispatch_opcode;
1083 case 21 : handle_op_21: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 5]); dispatch_opcode;
1084 case 22 : handle_op_22: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 6]); dispatch_opcode;
1085 case 23 : handle_op_23: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 7]); dispatch_opcode;
1086 case 24 : handle_op_24: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 8]); dispatch_opcode;
1087 case 25 : handle_op_25: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[ 9]); dispatch_opcode;
1088 case 26 : handle_op_26: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[10]); dispatch_opcode;
1089 case 27 : handle_op_27: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[11]); dispatch_opcode;
1090 case 28 : handle_op_28: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[12]); dispatch_opcode;
1091 case 29 : handle_op_29: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[13]); dispatch_opcode;
1092 case 30 : handle_op_30: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[14]); dispatch_opcode;
1093 case 31 : handle_op_31: slotCopy(++sp, &slotRawObject(&g->receiver)->slots[15]); dispatch_opcode;
1095 case 32 : // JumpIfTrue
1096 handle_op_32:
1097 // cannot compare with o_false because it is NaN
1098 if ( IsTrue(sp) ) {
1099 jmplen = (ip[1]<<8) | ip[2];
1100 ip += jmplen + 2;
1101 } else if ( IsFalse(sp)) {
1102 ip+=2;
1103 } else {
1104 numArgsPushed = 1;
1105 selector = gSpecialSelectors[opmNonBooleanError];
1106 slot = sp;
1108 goto class_lookup;
1110 --sp;
1111 dispatch_opcode;
1113 // opPushTempVar, levels 1..7
1114 case 33 : handle_op_33:
1115 slotCopy(++sp, &slotRawFrame(&g->frame->context)->vars[ip[1]]); ++ip; dispatch_opcode;
1116 case 34 : handle_op_34:
1117 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&g->frame->context)->context)->vars[ip[1]]); ++ip; dispatch_opcode;
1118 case 35 : handle_op_35:
1119 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)->vars[ip[1]]);
1120 ++ip; dispatch_opcode;
1121 case 36 : handle_op_36:
1122 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)->
1123 context)->vars[ip[1]]); ++ip; dispatch_opcode;
1124 case 37 : handle_op_37:
1125 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->
1126 context)->context)->context)->context)->vars[ip[1]]); ++ip; dispatch_opcode;
1127 case 38 : handle_op_38:
1128 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->
1129 context)->context)->context)->context)->context)->vars[ip[1]]); ++ip; dispatch_opcode;
1130 case 39 : handle_op_39:
1131 slotCopy(++sp, &slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->
1132 context)->context)->context)->context)->context)->context)->vars[ip[1]]); ++ip; dispatch_opcode;
1134 // push literal constants.
1135 case 40 :
1136 handle_op_40:
1137 ival = ip[1];
1138 ip+=1;
1139 slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1140 dispatch_opcode;
1141 case 41 :
1142 handle_op_41:
1143 ival = (ip[1] << 8) | ip[2];
1144 ip+=2;
1145 slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1146 dispatch_opcode;
1147 case 42 :
1148 handle_op_42:
1149 ival = (ip[1] << 16) | (ip[2] << 8) | ip[3];
1150 ip+=3;
1151 slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1152 dispatch_opcode;
1153 case 43 :
1154 handle_op_43:
1155 ival = (ip[1] << 24) | (ip[2] << 16) | (ip[3] << 8) | ip[4];
1156 ip+=4;
1157 slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ival]);
1158 dispatch_opcode;
1160 // push integers.
1161 case 44 :
1162 handle_op_44:
1163 ival = (int32)(ip[1] << 24) >> 24;
1164 ip+=1;
1165 ++sp; SetInt(sp, ival);
1166 dispatch_opcode;
1167 case 45 :
1168 handle_op_45:
1169 ival = (int32)((ip[1] << 24) | (ip[2] << 16)) >> 16;
1170 ip+=2;
1171 ++sp; SetInt(sp, ival);
1172 dispatch_opcode;
1173 case 46 :
1174 handle_op_46:
1175 ival = (int32)((ip[1] << 24) | (ip[2] << 16) | (ip[3] << 8)) >> 8;
1176 ip+=3;
1177 ++sp; SetInt(sp, ival);
1178 dispatch_opcode;
1179 case 47 :
1180 handle_op_47:
1181 ival = (int32)((ip[1] << 24) | (ip[2] << 16) | (ip[3] << 8) | ip[4]);
1182 ip+=4;
1183 ++sp; SetInt(sp, ival);
1184 dispatch_opcode;
1187 // opPushTempZeroVar
1188 case 48 : handle_op_48: slotCopy(++sp, &g->frame->vars[ 0]); dispatch_opcode;
1189 case 49 : handle_op_49: slotCopy(++sp, &g->frame->vars[ 1]); dispatch_opcode;
1190 case 50 : handle_op_50: slotCopy(++sp, &g->frame->vars[ 2]); dispatch_opcode;
1191 case 51 : handle_op_51: slotCopy(++sp, &g->frame->vars[ 3]); dispatch_opcode;
1192 case 52 : handle_op_52: slotCopy(++sp, &g->frame->vars[ 4]); dispatch_opcode;
1193 case 53 : handle_op_53: slotCopy(++sp, &g->frame->vars[ 5]); dispatch_opcode;
1194 case 54 : handle_op_54: slotCopy(++sp, &g->frame->vars[ 6]); dispatch_opcode;
1195 case 55 : handle_op_55: slotCopy(++sp, &g->frame->vars[ 7]); dispatch_opcode;
1196 case 56 : handle_op_56: slotCopy(++sp, &g->frame->vars[ 8]); dispatch_opcode;
1197 case 57 : handle_op_57: slotCopy(++sp, &g->frame->vars[ 9]); dispatch_opcode;
1198 case 58 : handle_op_58: slotCopy(++sp, &g->frame->vars[10]); dispatch_opcode;
1199 case 59 : handle_op_59: slotCopy(++sp, &g->frame->vars[11]); dispatch_opcode;
1200 case 60 : handle_op_60: slotCopy(++sp, &g->frame->vars[12]); dispatch_opcode;
1201 case 61 : handle_op_61: slotCopy(++sp, &g->frame->vars[13]); dispatch_opcode;
1202 case 62 : handle_op_62: slotCopy(++sp, &g->frame->vars[14]); dispatch_opcode;
1203 case 63 : handle_op_63: slotCopy(++sp, &g->frame->vars[15]); dispatch_opcode;
1205 // case opPushLiteral
1206 case 64 : handle_op_64: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 0]); dispatch_opcode;
1207 case 65 : handle_op_65: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 1]); dispatch_opcode;
1208 case 66 : handle_op_66: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 2]); dispatch_opcode;
1209 case 67 : handle_op_67: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 3]); dispatch_opcode;
1210 case 68 : handle_op_68: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 4]); dispatch_opcode;
1211 case 69 : handle_op_69: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 5]); dispatch_opcode;
1212 case 70 : handle_op_70: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 6]); dispatch_opcode;
1213 case 71 : handle_op_71: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 7]); dispatch_opcode;
1214 case 72 : handle_op_72: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 8]); dispatch_opcode;
1215 case 73 : handle_op_73: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[ 9]); dispatch_opcode;
1216 case 74 : handle_op_74: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[10]); dispatch_opcode;
1217 case 75 : handle_op_75: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[11]); dispatch_opcode;
1218 case 76 : handle_op_76: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[12]); dispatch_opcode;
1219 case 77 : handle_op_77: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[13]); dispatch_opcode;
1220 case 78 : handle_op_78: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[14]); dispatch_opcode;
1221 case 79 : handle_op_79: slotCopy(++sp, &slotRawObject(&g->block->constants)->slots[15]); dispatch_opcode;
1223 // opPushClassVar
1224 case 80: handle_op_80:
1225 handlePushClassVar(g, sp, ip, 0); dispatch_opcode;
1226 case 81: handle_op_81:
1227 handlePushClassVar(g, sp, ip, 1); dispatch_opcode;
1228 case 82: handle_op_82:
1229 handlePushClassVar(g, sp, ip, 2); dispatch_opcode;
1230 case 83: handle_op_83:
1231 handlePushClassVar(g, sp, ip, 3); dispatch_opcode;
1232 case 84: handle_op_84:
1233 handlePushClassVar(g, sp, ip, 4); dispatch_opcode;
1234 case 85: handle_op_85:
1235 handlePushClassVar(g, sp, ip, 5); dispatch_opcode;
1236 case 86: handle_op_86:
1237 handlePushClassVar(g, sp, ip, 6); dispatch_opcode;
1238 case 87: handle_op_87:
1239 handlePushClassVar(g, sp, ip, 7); dispatch_opcode;
1240 case 88: handle_op_88:
1241 handlePushClassVar(g, sp, ip, 8); dispatch_opcode;
1242 case 89: handle_op_89:
1243 handlePushClassVar(g, sp, ip, 9); dispatch_opcode;
1244 case 90: handle_op_90:
1245 handlePushClassVar(g, sp, ip, 10); dispatch_opcode;
1246 case 91: handle_op_91:
1247 handlePushClassVar(g, sp, ip, 11); dispatch_opcode;
1248 case 92: handle_op_92:
1249 handlePushClassVar(g, sp, ip, 12); dispatch_opcode;
1250 case 93: handle_op_93:
1251 handlePushClassVar(g, sp, ip, 13); dispatch_opcode;
1252 case 94: handle_op_94:
1253 handlePushClassVar(g, sp, ip, 14); dispatch_opcode;
1254 case 95: handle_op_95:
1255 handlePushClassVar(g, sp, ip, 15); dispatch_opcode;
1257 // opPushSpecialValue
1258 case 96 : handle_op_96: slotCopy(++sp, &g->receiver); dispatch_opcode;
1259 case 97 : // push one and subtract
1260 handle_op_97:
1261 if (IsInt(sp)) {
1262 SetRaw(sp, slotRawInt(sp) - 1);
1263 #if TAILCALLOPTIMIZE
1264 g->tailCall = 0;
1265 #endif
1266 } else {
1267 slotCopy(++sp, &gSpecialValues[svOne]);
1268 g->sp = sp; g->ip = ip;
1269 g->primitiveIndex = opSub;
1270 prSubNum(g, -1);
1271 sp = g->sp; ip = g->ip;
1273 dispatch_opcode;
1274 case 98 : handle_op_98: slotCopy(++sp, &gSpecialValues[svNegOne]); dispatch_opcode;
1275 case 99 : handle_op_99: slotCopy(++sp, &gSpecialValues[svZero]); dispatch_opcode;
1276 case 100 : handle_op_100: slotCopy(++sp, &gSpecialValues[svOne]); dispatch_opcode;
1277 case 101 : handle_op_101: slotCopy(++sp, &gSpecialValues[svTwo]); dispatch_opcode;
1278 case 102 : handle_op_102: slotCopy(++sp, &gSpecialValues[svFHalf]); dispatch_opcode;
1279 case 103 : handle_op_103: slotCopy(++sp, &gSpecialValues[svFNegOne]); dispatch_opcode;
1280 case 104 : handle_op_104: slotCopy(++sp, &gSpecialValues[svFZero]); dispatch_opcode;
1281 case 105 : handle_op_105: slotCopy(++sp, &gSpecialValues[svFOne]); dispatch_opcode;
1282 case 106 : handle_op_106: slotCopy(++sp, &gSpecialValues[svFTwo]); dispatch_opcode;
1283 case 107 : // push one and add
1284 handle_op_107:
1285 if (IsInt(sp)) {
1286 SetRaw(sp, slotRawInt(sp) + 1);
1287 #if TAILCALLOPTIMIZE
1288 g->tailCall = 0;
1289 #endif
1290 } else {
1291 slotCopy(++sp, &gSpecialValues[svOne]);
1292 g->sp = sp; g->ip = ip;
1293 g->primitiveIndex = opAdd;
1294 prAddNum(g, -1);
1295 sp = g->sp; ip = g->ip;
1297 dispatch_opcode;
1298 case 108 : handle_op_108: slotCopy(++sp, &gSpecialValues[svTrue]); dispatch_opcode;
1299 case 109 : handle_op_109: slotCopy(++sp, &gSpecialValues[svFalse]); dispatch_opcode;
1300 case 110 : handle_op_110: slotCopy(++sp, &gSpecialValues[svNil]); dispatch_opcode;
1301 case 111 : handle_op_111: slotCopy(++sp, &gSpecialValues[svInf]); dispatch_opcode;
1303 // opStoreInstVar, 0..15
1304 case 112 : handle_op_112:
1305 handleStoreInstVar(g, sp, ip, 0); dispatch_opcode;
1306 case 113 : handle_op_113:
1307 handleStoreInstVar(g, sp, ip, 1); dispatch_opcode;
1308 case 114 : handle_op_114:
1309 handleStoreInstVar(g, sp, ip, 2); dispatch_opcode;
1310 case 115 : handle_op_115:
1311 handleStoreInstVar(g, sp, ip, 3); dispatch_opcode;
1312 case 116 : handle_op_116:
1313 handleStoreInstVar(g, sp, ip, 4); dispatch_opcode;
1314 case 117 : handle_op_117:
1315 handleStoreInstVar(g, sp, ip, 5); dispatch_opcode;
1316 case 118 : handle_op_118:
1317 handleStoreInstVar(g, sp, ip, 6); dispatch_opcode;
1318 case 119 : handle_op_119:
1319 handleStoreInstVar(g, sp, ip, 7); dispatch_opcode;
1320 case 120 : handle_op_120:
1321 handleStoreInstVar(g, sp, ip, 8); dispatch_opcode;
1322 case 121 : handle_op_121:
1323 handleStoreInstVar(g, sp, ip, 9); dispatch_opcode;
1324 case 122 : handle_op_122:
1325 handleStoreInstVar(g, sp, ip, 10); dispatch_opcode;
1326 case 123 : handle_op_123:
1327 handleStoreInstVar(g, sp, ip, 11); dispatch_opcode;
1328 case 124 : handle_op_124:
1329 handleStoreInstVar(g, sp, ip, 12); dispatch_opcode;
1330 case 125 : handle_op_125:
1331 handleStoreInstVar(g, sp, ip, 13); dispatch_opcode;
1332 case 126 : handle_op_126:
1333 handleStoreInstVar(g, sp, ip, 14); dispatch_opcode;
1334 case 127 : handle_op_127:
1335 handleStoreInstVar(g, sp, ip, 15); dispatch_opcode;
1337 // opStoreTempVar
1338 case 128 :
1339 handle_op_128:
1340 op3 = ip[1]; ++ip; // get temp var index
1341 tframe = g->frame; // zero level
1342 slot = tframe->vars + op3;
1343 slotCopy(slot, sp--);
1344 g->gc->GCWrite(tframe, slot);
1345 dispatch_opcode;
1347 case 129 :
1348 handle_op_129:
1349 op3 = ip[1]; ++ip; // get temp var index
1350 tframe = slotRawFrame(&g->frame->context); // one level
1351 slot = tframe->vars + op3;
1352 slotCopy(slot, sp--);
1353 g->gc->GCWrite(tframe, slot);
1354 dispatch_opcode;
1356 case 130 :
1357 handle_op_130:
1358 op3 = ip[1]; ++ip; // get temp var index
1359 tframe = slotRawFrame(&slotRawFrame(&g->frame->context)->context); // two levels
1360 slot = tframe->vars + op3;
1361 slotCopy(slot, sp--);
1362 g->gc->GCWrite(tframe, slot);
1363 dispatch_opcode;
1365 case 131 :
1366 handle_op_131:
1367 op3 = ip[1]; ++ip; // get temp var index
1368 tframe = slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context); // three levels
1369 slot = tframe->vars + op3;
1370 slotCopy(slot, sp--);
1371 g->gc->GCWrite(tframe, slot);
1372 dispatch_opcode;
1374 case 132 :
1375 handle_op_132:
1376 op3 = ip[1]; ++ip; // get temp var index
1377 tframe = slotRawFrame(&slotRawFrame(&slotRawFrame(&slotRawFrame(&g->frame->context)->context)->context)->context); // four levels
1378 slot = tframe->vars + op3;
1379 slotCopy(slot, sp--);
1380 g->gc->GCWrite(tframe, slot);
1381 dispatch_opcode;
1383 case 133 : case 134 : case 135 :
1384 handle_op_133:
1385 handle_op_134:
1386 handle_op_135:
1387 op2 = op1 & 15;
1388 op3 = ip[1]; ++ip; // get temp var index
1389 for (tframe = g->frame; op2--; tframe = slotRawFrame(&tframe->context)) { /* noop */ }
1390 slot = tframe->vars + op3;
1391 slotCopy(slot, sp);
1392 g->gc->GCWrite(tframe, slot);
1393 dispatch_opcode;
1395 case 136 : // push inst var, send special selector
1396 handle_op_136:
1397 op2 = ip[1]; // get inst var index
1398 op3 = ip[2]; // get selector
1399 ip+=2;
1401 slotCopy(++sp, &slotRawObject(&g->receiver)->slots[op2]);
1403 numArgsPushed = 1;
1404 selector = gSpecialSelectors[op3];
1405 slot = sp;
1407 goto class_lookup;
1409 case 137 : // push all args, send msg
1410 handle_op_137:
1411 numArgsPushed = METHRAW(g->block)->numargs;
1412 pslot = g->frame->vars - 1;
1413 for (m=0,mmax=numArgsPushed; m<mmax; ++m) *++sp = *++pslot;
1415 op2 = ip[1]; ++ip; // get selector index
1416 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
1417 slot = sp - numArgsPushed + 1;
1419 goto class_lookup;
1421 case 138 : // push all but first arg, send msg
1422 handle_op_138:
1423 numArgsPushed = METHRAW(g->block)->numargs;
1424 pslot = g->frame->vars;
1425 for (m=0,mmax=numArgsPushed-1; m<mmax; ++m) *++sp = *++pslot;
1427 op2 = ip[1]; ++ip; // get selector index
1428 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
1429 slot = sp - numArgsPushed + 1;
1431 goto class_lookup;
1433 case 139 : // push all args, send special
1434 handle_op_139:
1435 numArgsPushed = METHRAW(g->block)->numargs;
1436 pslot = g->frame->vars - 1;
1437 for (m=0,mmax=numArgsPushed; m<mmax; ++m) *++sp = *++pslot;
1439 op2 = ip[1]; ++ip; // get selector
1440 selector = gSpecialSelectors[op2];
1441 slot = sp - numArgsPushed + 1;
1443 goto class_lookup;
1445 case 140 : // push all but first arg, send special
1446 handle_op_140:
1447 numArgsPushed = METHRAW(g->block)->numargs;
1448 pslot = g->frame->vars;
1449 for (m=0,mmax=numArgsPushed-1; m<mmax; ++m) *++sp = *++pslot;
1451 op2 = ip[1]; ++ip; // get selector
1452 selector = gSpecialSelectors[op2];
1453 slot = sp - numArgsPushed + 1;
1455 goto class_lookup;
1457 case 141 : // one arg pushed, push all but first arg, send msg
1458 handle_op_141:
1459 numArgsPushed = METHRAW(g->block)->numargs + 1;
1460 pslot = g->frame->vars;
1461 for (m=0,mmax=numArgsPushed-2; m<mmax; ++m) *++sp = *++pslot;
1463 op2 = ip[1]; ++ip; // get selector index
1464 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
1465 slot = sp - numArgsPushed + 1;
1467 goto class_lookup;
1469 case 142 : // one arg pushed, push all but first arg, send special
1470 handle_op_142:
1471 numArgsPushed = METHRAW(g->block)->numargs + 1;
1472 pslot = g->frame->vars;
1473 for (m=0,mmax=numArgsPushed-2; m<mmax; ++m) *++sp = *++pslot;
1475 op2 = ip[1]; ++ip; // get selector
1476 selector = gSpecialSelectors[op2];
1477 slot = sp - numArgsPushed + 1;
1479 goto class_lookup;
1481 case 143 : // loop byte codes
1482 handle_op_143:
1483 // this is major cheating to speed up often used looping methods
1484 // these byte codes are specific to their method and should only be used there.
1485 op2 = ip[1]; ++ip; // get which one
1486 switch (op2) {
1487 // Integer-do : 143 0, 143 1
1488 case 0 :
1489 vars = g->frame->vars;
1490 if (slotRawInt(&vars[2]) < slotRawInt(&g->receiver)) {
1491 slotCopy(++sp, &vars[1]); // push function
1492 slotCopy(++sp, &vars[2]); // push i
1493 slotCopy(++sp, &vars[2]); // push i
1494 // SendSpecialMsg value
1495 numArgsPushed = 3;
1496 selector = gSpecialSelectors[opmValue];
1497 slot = sp - 2;
1499 goto class_lookup;
1500 } else {
1501 slotCopy(++sp, &g->receiver);
1502 g->sp = sp; g->ip = ip;
1503 returnFromMethod(g);
1504 sp = g->sp; ip = g->ip;
1506 dispatch_opcode;
1507 case 1 :
1508 -- sp ; // Drop
1509 SetRaw(&g->frame->vars[2], slotRawInt(&g->frame->vars[2]) + 1); // inc i
1510 ip -= 4;
1511 dispatch_opcode;
1513 // Integer-reverseDo : 143 2, 143 3, 143 4
1514 case 2 :
1515 SetRaw(&g->frame->vars[2], slotRawInt(&g->receiver) - 1);
1516 dispatch_opcode;
1517 case 3 :
1518 vars = g->frame->vars;
1519 if (slotRawInt(&vars[2]) >= 0) {
1520 slotCopy(++sp, &vars[1]); // push function
1521 slotCopy(++sp, &vars[2]); // push i
1522 slotCopy(++sp, &vars[3]); // push j
1523 // SendSpecialMsg value
1524 numArgsPushed = 3;
1525 selector = gSpecialSelectors[opmValue];
1526 slot = sp - 2;
1528 goto class_lookup;
1529 } else {
1530 slotCopy(++sp, &g->receiver);
1531 g->sp = sp; g->ip = ip;
1532 returnFromMethod(g);
1533 sp = g->sp; ip = g->ip;
1535 dispatch_opcode;
1536 case 4 :
1537 -- sp ; // Drop
1538 vars = g->frame->vars;
1539 SetRaw(&vars[2], slotRawInt(&vars[2]) - 1); // dec i
1540 SetRaw(&vars[3], slotRawInt(&vars[3]) + 1); // inc j
1541 ip -= 4;
1542 dispatch_opcode;
1544 // Integer-for : 143 5, 143 6, 143 16
1545 case 5 :
1546 vars = g->frame->vars;
1547 tag = GetTag(&vars[1]);
1549 if (tag != tagInt) {
1550 if (IsFloat(&vars[1])) {
1551 // coerce to int
1552 SetInt(&vars[1], (int32)(slotRawFloat(&vars[1])));
1553 } else {
1554 error("Integer-for : endval not a SimpleNumber.\n");
1556 slotCopy(++sp, &g->receiver);
1557 numArgsPushed = 1;
1558 selector = gSpecialSelectors[opmPrimitiveFailed];
1559 slot = sp;
1561 goto class_lookup;
1565 if (slotRawInt(&g->receiver) <= slotRawInt(&vars[1])) {
1566 SetRaw(&vars[5], 1);
1567 } else {
1568 SetRaw(&vars[5], -1);
1570 slotCopy(&vars[3], &g->receiver);
1572 dispatch_opcode;
1573 case 6 :
1574 vars = g->frame->vars;
1575 if ((slotRawInt(&vars[5]) > 0 && slotRawInt(&vars[3]) <= slotRawInt(&vars[1]))
1576 || (slotRawInt(&vars[5]) < 0 && slotRawInt(&vars[3]) >= slotRawInt(&vars[1])))
1578 slotCopy(++sp, &vars[2]); // push function
1579 slotCopy(++sp, &vars[3]); // push i
1580 slotCopy(++sp, &vars[4]); // push j
1581 // SendSpecialMsg value
1582 numArgsPushed = 3;
1583 selector = gSpecialSelectors[opmValue];
1584 slot = sp - 2;
1586 goto class_lookup;
1587 } else {
1588 slotCopy(++sp, &g->receiver);
1589 g->sp = sp; g->ip = ip;
1590 returnFromMethod(g);
1591 sp = g->sp; ip = g->ip;
1593 dispatch_opcode;
1595 // Integer-forBy : 143 7, 143 8, 143 9
1596 case 7 :
1597 vars = g->frame->vars;
1598 if (IsFloat(vars+1)) {
1599 SetInt(&vars[1], (int32)(slotRawFloat(&vars[1])));
1601 if (IsFloat(vars+2)) {
1602 SetInt(&vars[2], (int32)(slotRawFloat(&vars[2])));
1604 tag = GetTag(&vars[1]);
1605 if ((tag != tagInt)
1606 || NotInt(&vars[2])) {
1607 error("Integer-forBy : endval or stepval not an Integer.\n");
1609 slotCopy(++sp, &g->receiver);
1610 numArgsPushed = 1;
1611 selector = gSpecialSelectors[opmPrimitiveFailed];
1612 slot = sp;
1614 goto class_lookup;
1616 slotCopy(&vars[4], &g->receiver);
1617 dispatch_opcode;
1618 case 8 :
1619 vars = g->frame->vars;
1620 if ((slotRawInt(&vars[2]) >= 0 && slotRawInt(&vars[4]) <= slotRawInt(&vars[1]))
1621 || (slotRawInt(&vars[2]) < 0 && slotRawInt(&vars[4]) >= slotRawInt(&vars[1]))) {
1622 slotCopy(++sp, &vars[3]); // push function
1623 slotCopy(++sp, &vars[4]); // push i
1624 slotCopy(++sp, &vars[5]); // push j
1625 // SendSpecialMsg value
1626 numArgsPushed = 3;
1627 selector = gSpecialSelectors[opmValue];
1628 slot = sp - 2;
1630 goto class_lookup;
1631 } else {
1632 slotCopy(++sp, &g->receiver);
1633 g->sp = sp; g->ip = ip;
1634 returnFromMethod(g);
1635 sp = g->sp; ip = g->ip;
1637 dispatch_opcode;
1638 case 9 :
1639 --sp ; // Drop
1640 vars = g->frame->vars;
1641 SetRaw(&vars[4], slotRawInt(&vars[4]) + slotRawInt(&vars[2])); // inc i
1642 SetRaw(&vars[5], slotRawInt(&vars[5]) + 1); // inc j
1643 ip -= 4;
1644 dispatch_opcode;
1646 // ArrayedCollection-do : 143 10, 143 1
1647 case 10 :
1648 // 0 this, 1 func, 2 i
1649 vars = g->frame->vars;
1651 if (slotRawInt(&vars[2]) < slotRawObject(&g->receiver)->size) {
1652 slotCopy(++sp, &vars[1]); // push function
1653 getIndexedSlot(slotRawObject(&g->receiver), ++sp, slotRawInt(&vars[2])); // push this.at(i)
1654 slotCopy(++sp, &vars[2]); // push i
1655 // SendSpecialMsg value
1656 numArgsPushed = 3;
1657 selector = gSpecialSelectors[opmValue];
1658 slot = sp - 2;
1660 goto class_lookup;
1661 } else {
1662 slotCopy(++sp, &g->receiver);
1663 g->sp = sp; g->ip = ip;
1664 returnFromMethod(g);
1665 sp = g->sp; ip = g->ip;
1667 dispatch_opcode;
1669 // ArrayedCollection-reverseDo : 143 11, 143 12, 143 4
1670 case 11 :
1671 SetRaw(&g->frame->vars[2], slotRawObject(&g->receiver)->size - 1);
1672 dispatch_opcode;
1673 case 12 :
1674 vars = g->frame->vars;
1675 if (slotRawInt(&vars[2]) >= 0) {
1676 slotCopy(++sp, &vars[1]); // push function
1677 getIndexedSlot(slotRawObject(&g->receiver), ++sp, slotRawInt(&vars[2])); // push this.at(i)
1678 slotCopy(++sp, &vars[3]); // push j
1679 // SendSpecialMsg value
1680 numArgsPushed = 3;
1681 selector = gSpecialSelectors[opmValue];
1682 slot = sp - 2;
1684 goto class_lookup; // class_lookup:
1685 } else {
1686 slotCopy(++sp, &g->receiver);
1687 g->sp = sp; g->ip = ip;
1688 returnFromMethod(g);
1689 sp = g->sp; ip = g->ip;
1691 dispatch_opcode;
1693 // Dictionary-keysValuesArrayDo
1694 case 13 :
1695 vars = g->frame->vars;
1696 m = slotRawInt(&vars[3]);
1697 obj = slotRawObject(&vars[1]);
1698 if ( m < obj->size ) {
1699 slot = obj->slots + m; // key
1700 while (IsNil(slot)) {
1701 m += 2;
1702 if ( m >= obj->size ) {
1703 SetRaw(&vars[3], m);
1704 goto keysValuesArrayDo_return;
1706 slot = obj->slots + m; // key
1708 SetRaw(&vars[3], m);
1709 slotCopy(++sp, &vars[2]); // function
1710 slotCopy(++sp, &slot[0]); // key
1711 slotCopy(++sp, &slot[1]); // val
1712 slotCopy(++sp, &vars[4]); // j
1713 SetRaw(&vars[4], slotRawInt(&vars[4]) + 1);
1715 // SendSpecialMsg value
1716 numArgsPushed = 4;
1717 selector = gSpecialSelectors[opmValue];
1718 slot = sp - 3;
1720 goto class_lookup; // class_lookup:
1721 } else {
1722 keysValuesArrayDo_return:
1723 slotCopy(++sp, &g->receiver);
1724 g->sp = sp; g->ip = ip;
1725 returnFromMethod(g);
1726 sp = g->sp; ip = g->ip;
1728 dispatch_opcode;
1729 case 14 :
1730 -- sp; // Drop
1731 SetRaw(&g->frame->vars[3], slotRawInt(&g->frame->vars[3]) + 2); // inc i
1732 ip -= 4;
1733 dispatch_opcode;
1734 case 15 :
1735 // unused opcode.
1736 break;
1738 case 16 :
1739 -- sp ; // Drop
1740 vars = g->frame->vars;
1741 SetRaw(&vars[3], slotRawInt(&vars[3]) + slotRawInt(&vars[5])); // inc i by stepval
1742 SetRaw(&vars[4], slotRawInt(&vars[4]) + 1); // inc j
1743 ip -= 4;
1744 dispatch_opcode;
1746 // Float-do : 143 17, 143 18
1747 case 17 :
1748 vars = g->frame->vars;
1749 if (slotRawFloat(&vars[2]) + 0.5 < slotRawFloat(&g->receiver)) {
1750 slotCopy(++sp, &vars[1]); // push function
1751 slotCopy(++sp, &vars[2]); // push i
1752 slotCopy(++sp, &vars[2]); // push i
1753 // SendSpecialMsg value
1754 numArgsPushed = 3;
1755 selector = gSpecialSelectors[opmValue];
1756 slot = sp - 2;
1758 goto class_lookup;
1759 } else {
1760 slotCopy(++sp, &g->receiver);
1761 g->sp = sp; g->ip = ip;
1762 returnFromMethod(g);
1763 sp = g->sp; ip = g->ip;
1765 dispatch_opcode;
1766 case 18 :
1767 -- sp ; // Drop
1768 SetRaw(&g->frame->vars[2], slotRawFloat(&g->frame->vars[2]) + 1.0); // inc i
1769 ip -= 4;
1770 dispatch_opcode;
1772 // Float-reverseDo : 143 19, 143 20, 143 21
1773 case 19 :
1774 SetFloat(&g->frame->vars[2], slotRawFloat(&g->receiver) - 1.0);
1775 dispatch_opcode;
1776 case 20 :
1777 vars = g->frame->vars;
1778 if (slotRawFloat(&vars[2]) + 0.5 >= 0.0) {
1779 slotCopy(++sp, &vars[1]); // push function
1780 slotCopy(++sp, &vars[2]); // push i
1781 slotCopy(++sp, &vars[3]); // push j
1782 // SendSpecialMsg value
1783 numArgsPushed = 3;
1784 selector = gSpecialSelectors[opmValue];
1785 slot = sp - 2;
1787 goto class_lookup;
1788 } else {
1789 slotCopy(++sp, &g->receiver);
1790 g->sp = sp; g->ip = ip;
1791 returnFromMethod(g);
1792 sp = g->sp; ip = g->ip;
1794 dispatch_opcode;
1795 case 21 :
1796 -- sp ; // Drop
1797 vars = g->frame->vars;
1798 SetRaw(&g->frame->vars[2], slotRawFloat(&g->frame->vars[2]) - 1.0); // dec i
1799 SetRaw(&g->frame->vars[3], slotRawFloat(&g->frame->vars[3]) - 1.0); // inc j
1800 ip -= 4;
1801 dispatch_opcode;
1802 case 22 : // ? question mark method
1803 --sp;
1804 if (IsNil(sp)) {
1805 *sp = *(sp+1);
1807 dispatch_opcode;
1808 case 23 : // if not nil push this and jump. used to implement ??
1809 if (NotNil(sp)) {
1810 jmplen = (ip[1]<<8) | ip[2];
1811 ip += jmplen + 2;
1812 } else {
1813 --sp;
1814 ip+=2;
1816 dispatch_opcode;
1817 case 24 : // ifNil
1818 if ( NotNil(sp) ) {
1819 jmplen = (ip[1]<<8) | ip[2];
1820 ip += jmplen + 2;
1821 } else {
1822 ip+=2;
1824 --sp;
1825 dispatch_opcode;
1826 case 25 : // ifNotNil
1827 if ( IsNil(sp) ) {
1828 jmplen = (ip[1]<<8) | ip[2];
1829 ip += jmplen + 2;
1830 } else {
1831 ip+=2;
1833 --sp;
1834 dispatch_opcode;
1835 case 26 : // ifNotNilPushNil
1836 if ( NotNil(sp) ) {
1837 jmplen = (ip[1]<<8) | ip[2];
1838 ip += jmplen + 2;
1839 slotCopy(sp, &gSpecialValues[svNil]);
1840 } else {
1841 ip+=2;
1842 --sp;
1844 dispatch_opcode;
1845 case 27 : // ifNilPushNil
1846 if ( IsNil(sp) ) {
1847 jmplen = (ip[1]<<8) | ip[2];
1848 ip += jmplen + 2;
1849 } else {
1850 ip+=2;
1851 --sp;
1853 dispatch_opcode;
1854 case 28 : // switch
1855 obj = slotRawObject(sp);
1856 op2 = 1 + arrayAtIdentityHashInPairs(obj, (sp-1));
1857 sp-=2;
1858 ip += slotRawInt(&obj->slots[op2]);
1859 dispatch_opcode;
1861 // Number-forSeries : 143 29, 143 30, 143 31
1862 case 29 :
1863 vars = g->frame->vars;
1864 // 0 receiver, 1 step, 2 last, 3 function, 4 i, 5 j
1865 if (IsInt(vars+0) && (IsInt(vars+1) || IsNil(vars+1)) && (IsInt(vars+2) || IsNil(vars+2))) {
1866 if (IsNil(vars+1)) {
1867 if (IsNil(vars+2)) SetInt(vars+2, 0x7FFFFFFF);
1868 if (slotRawInt(&vars[0]) < slotRawInt(&vars[2])) SetInt(vars+1, 1);
1869 else SetInt(vars+1, -1);
1870 } else {
1871 if (IsNil(vars+2)) {
1872 if (slotRawInt(&vars[1]) < slotRawInt(&vars[0])) SetInt(vars+2, 0x80000000);
1873 else SetInt(vars+2, 0x7FFFFFFF);
1875 SetInt(vars+1, slotRawInt(&vars[1]) - slotRawInt(&vars[0]));
1877 slotCopy(&vars[4], &vars[0]);
1878 } else {
1879 if (IsInt(vars+0)) {
1880 SetFloat(&vars[4], slotRawInt(&vars[0]));
1881 } else if (IsFloat(vars+0)) {
1882 SetFloat(&vars[4], slotRawFloat(&vars[0]));
1883 } else {
1884 bailFromNumberSeries:
1885 error("Number-forSeries : first, second or last not an Integer or Float.\n");
1887 slotCopy(++sp, &g->receiver);
1888 numArgsPushed = 1;
1889 selector = gSpecialSelectors[opmPrimitiveFailed];
1890 slot = sp;
1892 goto class_lookup;
1895 if (IsNil(vars+1)) {
1896 if (IsNil(vars+2)) SetFloat(vars+2, kBigBigFloat);
1897 else if (IsInt(vars+2)) SetFloat(&vars[2], slotRawInt(&vars[2]));
1898 else if (!IsFloat(vars+2)) goto bailFromNumberSeries;
1900 if (slotRawFloat(&vars[4]) < slotRawFloat(&vars[2])) SetFloat(vars+1, 1.);
1901 else SetFloat(vars+1, -1.);
1902 } else {
1903 if (IsInt(vars+1)) SetFloat(&vars[1], slotRawInt(&vars[1]));
1904 else if (!IsFloat(vars+1)) goto bailFromNumberSeries;
1906 if (IsNil(vars+2)) {
1907 if (slotRawFloat(&vars[1]) < slotRawFloat(&vars[4])) SetFloat(vars+2, kSmallSmallFloat);
1908 else SetFloat(vars+2, kBigBigFloat);
1910 else if (IsInt(vars+2)) SetFloat(&vars[2], slotRawInt(&vars[2]));
1911 else if (!IsFloat(vars+2)) goto bailFromNumberSeries;
1912 SetFloat(vars+1, slotRawFloat(&vars[1]) - slotRawFloat(&vars[4]));
1915 dispatch_opcode;
1916 case 30 :
1917 vars = g->frame->vars;
1918 tag = GetTag(&vars[1]);
1919 if (tag == tagInt) {
1920 if ((slotRawInt(&vars[1]) >= 0 && slotRawInt(&vars[4]) <= slotRawInt(&vars[2]))
1921 || (slotRawInt(&vars[1]) < 0 && slotRawInt(&vars[4]) >= slotRawInt(&vars[2]))) {
1922 slotCopy(++sp, &vars[3]); // push function
1923 slotCopy(++sp, &vars[4]); // push i
1924 slotCopy(++sp, &vars[5]); // push j
1925 // SendSpecialMsg value
1926 numArgsPushed = 3;
1927 selector = gSpecialSelectors[opmValue];
1928 slot = sp - 2;
1930 goto class_lookup;
1931 } else {
1932 slotCopy(++sp, &g->receiver);
1933 g->sp = sp; g->ip = ip;
1934 returnFromMethod(g);
1935 sp = g->sp; ip = g->ip;
1937 } else {
1938 if ((slotRawFloat(&vars[1]) >= 0. && slotRawFloat(&vars[4]) <= slotRawFloat(&vars[2]))
1939 || (slotRawFloat(&vars[1]) < 0. && slotRawFloat(&vars[4]) >= slotRawFloat(&vars[2]))) {
1940 slotCopy(++sp, &vars[3]); // push function
1941 slotCopy(++sp, &vars[4]); // push i
1942 slotCopy(++sp, &vars[5]); // push j
1943 // SendSpecialMsg value
1944 numArgsPushed = 3;
1945 selector = gSpecialSelectors[opmValue];
1946 slot = sp - 2;
1948 goto class_lookup;
1949 } else {
1950 slotCopy(++sp, &g->receiver);
1951 g->sp = sp; g->ip = ip;
1952 returnFromMethod(g);
1953 sp = g->sp; ip = g->ip;
1956 dispatch_opcode;
1957 case 31 :
1958 -- sp ; // Drop
1959 vars = g->frame->vars;
1961 tag = GetTag(&vars[1]);
1962 if (tag == tagInt) {
1963 SetRaw(&vars[4], slotRawInt(&vars[4]) + slotRawInt(&vars[1])); // inc i
1964 } else {
1965 SetRaw(&vars[4], slotRawFloat(&vars[4]) + slotRawFloat(&vars[1])); // inc i
1967 SetRaw(&vars[5], slotRawInt(&vars[5]) + 1); // inc j
1968 ip -= 4;
1969 dispatch_opcode;
1971 dispatch_opcode;
1974 // opStoreClassVar
1975 case 144 : case 145 : case 146 : case 147 :
1976 case 148 : case 149 : case 150 : case 151 :
1977 case 152 : case 153 : case 154 : case 155 :
1978 case 156 : case 157 : case 158 : case 159 :
1979 handle_op_144: handle_op_145: handle_op_146: handle_op_147:
1980 handle_op_148: handle_op_149: handle_op_150: handle_op_151:
1981 handle_op_152: handle_op_153: handle_op_154: handle_op_155:
1982 handle_op_156: handle_op_157: handle_op_158: handle_op_159:
1984 op2 = op1 & 15;
1985 op3 = ip[1]; ++ip; // get class var index
1986 slotCopy(&g->classvars->slots[(op2<<8)|op3], sp--);
1987 g->gc->GCWrite(g->classvars, (sp+1));
1988 dispatch_opcode;
1990 // opSendMsg
1991 case 160 :
1992 handle_op_160:
1993 // special case for this as only arg
1994 op2 = ip[1]; ++ip; // get selector index
1995 slotCopy(++sp, &g->receiver);
1996 numArgsPushed = 1;
1997 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
1998 slot = sp;
2000 goto class_lookup;
2002 case 161 : case 162 : case 163 :
2003 case 164 : case 165 : case 166 : case 167 :
2004 case 168 : case 169 : case 170 : case 171 :
2005 case 172 : case 173 : case 174 : case 175 :
2006 handle_op_161: handle_op_162: handle_op_163:
2007 handle_op_164: handle_op_165: handle_op_166: handle_op_167:
2008 handle_op_168: handle_op_169: handle_op_170: handle_op_171:
2009 handle_op_172: handle_op_173: handle_op_174: handle_op_175:
2011 op2 = ip[1]; ++ip; // get selector index
2012 numArgsPushed = op1 & 15;
2013 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2014 slot = sp - numArgsPushed + 1;
2016 goto class_lookup;
2018 case 176 : // opcTailCallReturnFromFunction
2019 handle_op_176:
2020 #if TAILCALLOPTIMIZE
2021 g->tailCall = 2;
2022 #endif
2023 dispatch_opcode;
2024 // opSuperMsg
2025 case 177 :
2026 handle_op_177:
2027 // special case for this as only arg
2028 op2 = ip[1]; ++ip; // get selector index
2029 slotCopy(++sp, &g->receiver);
2030 numArgsPushed = 1;
2031 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2032 slot = sp;
2033 classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj;
2035 goto msg_lookup;
2037 case 178 : case 179 :
2038 case 180 : case 181 : case 182 : case 183 :
2039 case 184 : case 185 : case 186 : case 187 :
2040 case 188 : case 189 : case 190 : case 191 :
2042 handle_op_178: handle_op_179:
2043 handle_op_180: handle_op_181: handle_op_182: handle_op_183:
2044 handle_op_184: handle_op_185: handle_op_186: handle_op_187:
2045 handle_op_188: handle_op_189: handle_op_190: handle_op_191:
2047 op2 = ip[1]; ++ip; // get selector index
2048 numArgsPushed = op1 & 15;
2049 selector = slotRawSymbol(&slotRawObject(&g->block->selectors)->slots[op2]);
2050 slot = sp - numArgsPushed + 1;
2051 classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj;
2053 goto msg_lookup;
2055 // opSendSpecialMsg
2056 case 192 :
2057 handle_op_192:
2058 slotCopy(++sp, &g->receiver);
2059 op2 = ip[1]; ++ip; // get selector index
2060 numArgsPushed = 1;
2061 selector = gSpecialSelectors[op2];
2062 slot = sp;
2064 goto class_lookup;
2066 case 193 : case 194 : case 195 :
2067 case 196 : case 197 : case 198 : case 199 :
2068 case 200 : case 201 : case 202 : case 203 :
2069 case 204 : case 205 : case 206 : case 207 :
2071 handle_op_193: handle_op_194: handle_op_195:
2072 handle_op_196: handle_op_197: handle_op_198: handle_op_199:
2073 handle_op_200: handle_op_201: handle_op_202: handle_op_203:
2074 handle_op_204: handle_op_205: handle_op_206: handle_op_207:
2076 op2 = ip[1]; ++ip; // get selector index
2077 numArgsPushed = op1 & 15;
2078 selector = gSpecialSelectors[op2];
2079 slot = sp - numArgsPushed + 1;
2081 goto class_lookup;
2083 // opSendSpecialUnaryArithMsg
2084 case 208 : // opNeg
2085 handle_op_208:
2086 if (IsFloat(sp)) {
2087 SetFloat(sp, -slotRawFloat(sp));
2088 #if TAILCALLOPTIMIZE
2089 g->tailCall = 0;
2090 #endif
2091 } else if (IsInt(sp)) {
2092 SetRaw(sp, -slotRawInt(sp));
2093 #if TAILCALLOPTIMIZE
2094 g->tailCall = 0;
2095 #endif
2096 } else
2097 handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2098 dispatch_opcode;
2099 case 209 : // opNot
2100 handle_op_209:
2101 if (IsTrue(sp)) {
2102 SetTagRaw(sp, tagFalse);
2103 #if TAILCALLOPTIMIZE
2104 g->tailCall = 0;
2105 #endif
2106 } else if (IsFalse(sp)) {
2107 SetTagRaw(sp, tagTrue);
2108 #if TAILCALLOPTIMIZE
2109 g->tailCall = 0;
2110 #endif
2111 } else
2112 handleSendSpecialUnaryArithMsg(g, sp, ip, op1);
2113 dispatch_opcode;
2114 case 210 : // opIsNil
2115 handle_op_210:
2116 if (IsNil(sp)) {
2117 SetTagRaw(sp, tagTrue);
2118 } else {
2119 slotCopy(sp, &gSpecialValues[svFalse]);
2121 #if TAILCALLOPTIMIZE
2122 g->tailCall = 0;
2123 #endif
2124 dispatch_opcode;
2125 case 211 : // opNotNil
2126 handle_op_211:
2127 if (NotNil(sp)) {
2128 slotCopy(sp, &gSpecialValues[svTrue]);
2129 } else {
2130 SetTagRaw(sp, tagFalse);
2132 #if TAILCALLOPTIMIZE
2133 g->tailCall = 0;
2134 #endif
2135 dispatch_opcode;
2137 case 212 : handle_op_212:
2138 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2139 case 213 : handle_op_213:
2140 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2141 case 214 : handle_op_214:
2142 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2143 case 215 : handle_op_215:
2144 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2145 case 216 : handle_op_216:
2146 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2147 case 217 : handle_op_217:
2148 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2149 case 218 : handle_op_218:
2150 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2151 case 219 : handle_op_219:
2152 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2153 case 220 : handle_op_220:
2154 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2155 case 221 : handle_op_221:
2156 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2157 case 222 : handle_op_222:
2158 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2159 case 223 : handle_op_223:
2160 handleSendSpecialUnaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2163 // opSendSpecialBinaryArithMsg
2164 case 224 : // add
2165 handle_op_224:
2166 if (IsInt(sp - 1)) {
2167 if (IsInt(sp)) {
2168 --sp; SetRaw(sp, slotRawInt(sp) + slotRawInt(sp + 1));
2169 #if TAILCALLOPTIMIZE
2170 g->tailCall = 0;
2171 #endif
2172 } else {
2173 g->sp = sp; g->ip = ip;
2174 g->primitiveIndex = opAdd;
2175 prAddInt(g, -1);
2176 sp = g->sp; ip = g->ip;
2178 } else {
2179 g->sp = sp; g->ip = ip;
2180 g->primitiveIndex = opAdd;
2181 prAddNum(g, -1);
2182 sp = g->sp; ip = g->ip;
2184 dispatch_opcode;
2185 case 225 : // subtract
2186 handle_op_225:
2187 if (IsInt(sp - 1)) {
2188 if (IsInt(sp)) {
2189 --sp; SetRaw(sp, slotRawInt(sp) - slotRawInt(sp + 1));
2190 #if TAILCALLOPTIMIZE
2191 g->tailCall = 0;
2192 #endif
2193 } else {
2194 g->sp = sp; g->ip = ip;
2195 g->primitiveIndex = opSub;
2196 prSubInt(g, -1);
2197 sp = g->sp; ip = g->ip;
2199 } else {
2200 g->sp = sp; g->ip = ip;
2201 g->primitiveIndex = opSub;
2202 prSubNum(g, -1);
2203 sp = g->sp; ip = g->ip;
2205 dispatch_opcode;
2206 case 226 : // multiply
2207 handle_op_226:
2208 if (IsInt(sp - 1)) {
2209 if (IsInt(sp)) {
2210 --sp; SetRaw(sp, slotRawInt(sp) * slotRawInt(sp + 1));
2211 #if TAILCALLOPTIMIZE
2212 g->tailCall = 0;
2213 #endif
2214 } else {
2215 g->sp = sp; g->ip = ip;
2216 g->primitiveIndex = opMul;
2217 prMulInt(g, -1);
2218 sp = g->sp; ip = g->ip;
2220 } else {
2221 g->sp = sp; g->ip = ip;
2222 g->primitiveIndex = opMul;
2223 prMulNum(g, -1);
2224 sp = g->sp; ip = g->ip;
2226 dispatch_opcode;
2228 case 227 : handle_op_227:
2229 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2230 case 228 : handle_op_228:
2231 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2232 case 229 : handle_op_229:
2233 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2234 case 230 : handle_op_230:
2235 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2236 case 231 : handle_op_231:
2237 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2238 case 232 : handle_op_232:
2239 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2240 case 233 : handle_op_233:
2241 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2242 case 234 : handle_op_234:
2243 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2244 case 235 : handle_op_235:
2245 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2246 case 236 : handle_op_236:
2247 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2248 case 237 : handle_op_237:
2249 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2250 case 238 : handle_op_238:
2251 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2252 case 239 : handle_op_239:
2253 handleSendSpecialBinaryArithMsg(g, sp, ip, op1); dispatch_opcode;
2255 // opSpecialOpcodes
2256 case 240 :
2257 handle_op_240:
2258 --sp; dispatch_opcode; // opDrop
2259 case 241 :
2260 handle_op_241:
2261 ++sp; *sp = sp[-1]; dispatch_opcode; // opDup
2262 case 242 : // opcFunctionReturn
2263 handle_op_242:
2264 g->sp = sp; g->ip = ip;
2265 returnFromBlock(g);
2266 sp = g->sp; ip = g->ip;
2267 dispatch_opcode;
2268 case 243 : // opcReturn
2269 handle_op_243:
2270 g->sp = sp; g->ip = ip;
2271 returnFromMethod(g);
2272 sp = g->sp; ip = g->ip;
2273 dispatch_opcode;
2274 case 244 : // opcReturnSelf
2275 handle_op_244:
2276 slotCopy(++sp, &g->receiver);
2277 g->sp = sp; g->ip = ip;
2278 returnFromMethod(g);
2279 sp = g->sp; ip = g->ip;
2280 dispatch_opcode;
2281 case 245 : // opcReturnTrue
2282 handle_op_245:
2283 slotCopy(++sp, &gSpecialValues[svTrue]);
2284 g->sp = sp; g->ip = ip;
2285 returnFromMethod(g);
2286 sp = g->sp; ip = g->ip;
2287 dispatch_opcode;
2288 case 246 : // opcReturnFalse
2289 handle_op_246:
2290 slotCopy(++sp, &gSpecialValues[svFalse]);
2291 g->sp = sp; g->ip = ip;
2292 returnFromMethod(g);
2293 sp = g->sp; ip = g->ip;
2294 dispatch_opcode;
2295 case 247 : // opcReturnNil
2296 handle_op_247:
2297 slotCopy(++sp, &gSpecialValues[svNil]);
2298 g->sp = sp; g->ip = ip;
2299 returnFromMethod(g);
2300 sp = g->sp; ip = g->ip;
2301 dispatch_opcode;
2303 case 248 : // opcJumpIfFalse
2304 handle_op_248:
2305 // cannot compare with o_false because it is NaN
2306 if ( IsFalse(sp) ) {
2307 jmplen = (ip[1]<<8) | ip[2];
2308 ip += jmplen + 2;
2309 } else if ( IsTrue(sp)) {
2310 ip+=2;
2311 } else {
2312 numArgsPushed = 1;
2313 selector = gSpecialSelectors[opmNonBooleanError];
2314 slot = sp;
2316 goto class_lookup;
2318 --sp;
2319 dispatch_opcode;
2320 case 249 : // opcJumpIfFalsePushNil
2321 handle_op_249:
2322 if ( IsFalse(sp)) {
2323 jmplen = (ip[1]<<8) | ip[2];
2324 ip += jmplen + 2;
2325 slotCopy(sp, &gSpecialValues[svNil]);
2326 } else if ( IsTrue(sp)) {
2327 --sp;
2328 ip+=2;
2329 } else {
2330 numArgsPushed = 1;
2331 selector = gSpecialSelectors[opmNonBooleanError];
2332 slot = sp;
2334 goto class_lookup;
2336 dispatch_opcode;
2337 case 250 : // opcJumpIfFalsePushFalse
2338 handle_op_250:
2339 if (IsFalse(sp)) {
2340 jmplen = (ip[1]<<8) | ip[2];
2341 ip += jmplen + 2;
2342 //*sp = r_false;
2343 } else if (IsTrue(sp)) {
2344 --sp;
2345 ip+=2;
2346 } else {
2347 numArgsPushed = 1;
2348 selector = gSpecialSelectors[opmNonBooleanError];
2349 slot = sp;
2351 goto class_lookup;
2353 dispatch_opcode;
2354 case 251 : // opcJumpIfTruePushTrue
2355 handle_op_251:
2356 if (IsFalse(sp)) {
2357 --sp;
2358 ip+=2;
2359 } else if (IsTrue(sp)) {
2360 jmplen = (ip[1]<<8) | ip[2];
2361 ip += jmplen + 2;
2362 slotCopy(sp, &gSpecialValues[svTrue]);
2363 } else {
2364 numArgsPushed = 1;
2365 selector = gSpecialSelectors[opmNonBooleanError];
2366 slot = sp;
2368 goto class_lookup;
2370 dispatch_opcode;
2371 case 252 : // opcJumpFwd
2372 handle_op_252:
2373 jmplen = (ip[1]<<8) | ip[2];
2374 ip += jmplen + 2;
2375 dispatch_opcode;
2376 case 253 : // opcJumpBak
2377 handle_op_253:
2378 --sp; // also drops the stack. This saves an opcode in the while loop
2379 // which is the only place this opcode is used.
2380 jmplen = (ip[1]<<8) | ip[2];
2381 ip -= jmplen;
2383 //assert(g->gc->SanityCheck());
2384 dispatch_opcode;
2385 case 254 : // opcSpecialBinaryOpWithAdverb
2386 handle_op_254:
2387 op2 = ip[1]; ++ip; // get selector index
2388 g->sp = sp; g->ip = ip;
2389 g->primitiveIndex = op2;
2390 doSpecialBinaryArithMsg(g, 3, false);
2391 sp = g->sp; ip = g->ip;
2392 dispatch_opcode;
2393 case 255 : // opcTailCallReturnFromMethod
2394 handle_op_255:
2395 #if TAILCALLOPTIMIZE
2396 g->tailCall = 1;
2397 #endif
2398 dispatch_opcode;
2400 ////////////////////////////////////
2402 class_lookup:
2403 // normal class lookup
2404 classobj = classOfSlot(slot);
2406 // message sends handled here:
2407 msg_lookup:
2408 index = slotRawInt(&classobj->classIndex) + selector->u.index;
2409 meth = gRowTable[index];
2411 if (slotRawSymbol(&meth->name) != selector) {
2412 g->sp = sp; g->ip = ip;
2413 doesNotUnderstand(g, selector, numArgsPushed);
2414 sp = g->sp; ip = g->ip;
2415 } else {
2416 PyrMethodRaw *methraw;
2417 methraw = METHRAW(meth);
2418 switch (methraw->methType) {
2419 case methNormal : /* normal msg send */
2420 g->sp = sp; g->ip = ip;
2421 executeMethod(g, meth, numArgsPushed);
2422 sp = g->sp; ip = g->ip;
2423 break;
2424 case methReturnSelf : /* return self */
2425 sp -= numArgsPushed - 1;
2426 break;
2427 case methReturnLiteral : /* return literal */
2428 sp -= numArgsPushed - 1;
2429 slotCopy(sp, &meth->selectors); /* in this case selectors is just a single value */
2430 break;
2431 case methReturnArg : /* return an argument */
2432 sp -= numArgsPushed - 1;
2433 index = methraw->specialIndex; // zero is index of the first argument
2434 if (index < numArgsPushed) {
2435 slotCopy(sp, sp + index);
2436 } else {
2437 slotCopy(sp, &slotRawObject(&meth->prototypeFrame)->slots[index]);
2439 break;
2440 case methReturnInstVar : /* return inst var */
2441 sp -= numArgsPushed - 1;
2442 index = methraw->specialIndex;
2443 slotCopy(sp, &slotRawObject(slot)->slots[index]);
2444 break;
2445 case methAssignInstVar : /* assign inst var */
2446 sp -= numArgsPushed - 1;
2447 index = methraw->specialIndex;
2448 obj = slotRawObject(slot);
2449 if (obj->obj_flags & obj_immutable) { StoreToImmutableB(g, sp, ip); }
2450 else {
2451 if (numArgsPushed >= 2) {
2452 slotCopy(&obj->slots[index], sp + 1);
2453 g->gc->GCWrite(obj, sp + 1);
2454 } else {
2455 slotCopy(&obj->slots[index], &gSpecialValues[svNil]);
2457 slotCopy(sp, slot);
2459 break;
2460 case methReturnClassVar : /* return class var */
2461 sp -= numArgsPushed - 1;
2462 slotCopy(sp, &g->classvars->slots[methraw->specialIndex]);
2463 break;
2464 case methAssignClassVar : /* assign class var */
2465 sp -= numArgsPushed - 1;
2466 if (numArgsPushed >= 2) {
2467 slotCopy(&g->classvars->slots[methraw->specialIndex], sp + 1);
2468 g->gc->GCWrite(g->classvars, sp + 1);
2469 } else
2470 slotCopy(&g->classvars->slots[methraw->specialIndex], &gSpecialValues[svNil]);
2471 slotCopy(sp, slot);
2472 break;
2473 case methRedirect : /* send a different selector to self */
2474 if (numArgsPushed < methraw->numargs) { // not enough args pushed
2475 /* push default arg values */
2476 PyrSlot *qslot;
2477 int m, mmax;
2478 qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
2479 for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++sp, ++qslot);
2480 numArgsPushed = methraw->numargs;
2482 selector = slotRawSymbol(&meth->selectors);
2483 goto msg_lookup;
2484 case methRedirectSuper : /* send a different selector to self */
2485 if (numArgsPushed < methraw->numargs) { // not enough args pushed
2486 /* push default arg values */
2487 PyrSlot *qslot;
2488 int m, mmax;
2489 qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
2490 for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++sp, ++qslot);
2491 numArgsPushed = methraw->numargs;
2493 selector = slotRawSymbol(&meth->selectors);
2494 classobj = slotRawSymbol(&slotRawClass(&meth->ownerclass)->superclass)->u.classobj;
2495 goto msg_lookup;
2496 case methForwardInstVar : /* forward to an instance variable */
2497 if (numArgsPushed < methraw->numargs) { // not enough args pushed
2498 /* push default arg values */
2499 PyrSlot *qslot;
2500 int m, mmax;
2501 qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
2502 for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++sp, ++qslot);
2503 numArgsPushed = methraw->numargs;
2505 selector = slotRawSymbol(&meth->selectors);
2506 index = methraw->specialIndex;
2507 slotCopy(slot, &slotRawObject(slot)->slots[index]);
2509 classobj = classOfSlot(slot);
2511 goto msg_lookup;
2512 case methForwardClassVar : /* forward to an instance variable */
2513 if (numArgsPushed < methraw->numargs) { // not enough args pushed
2514 /* push default arg values */
2515 PyrSlot *qslot;
2516 int m, mmax;
2517 qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
2518 for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++sp, ++qslot);
2519 numArgsPushed = methraw->numargs;
2521 selector = slotRawSymbol(&meth->selectors);
2522 slotCopy(slot, &g->classvars->slots[methraw->specialIndex]);
2524 classobj = classOfSlot(slot);
2526 goto msg_lookup;
2527 case methPrimitive : /* primitive */
2528 g->sp = sp; g->ip = ip;
2529 doPrimitive(g, meth, numArgsPushed);
2530 sp = g->sp; ip = g->ip;
2531 break;
2532 } // switch (meth->methType)
2533 } // end handle message
2534 #if TAILCALLOPTIMIZE
2535 g->tailCall = 0;
2536 #endif
2537 dispatch_opcode;
2539 ////////////////////////////////////
2541 key_class_lookup:
2542 // normal class lookup
2543 classobj = classOfSlot(slot);
2545 // message sends handled here:
2546 key_msg_lookup:
2547 index = slotRawInt(&classobj->classIndex) + selector->u.index;
2548 meth = gRowTable[index];
2550 if (slotRawSymbol(&meth->name) != selector) {
2551 g->sp = sp; g->ip = ip;
2552 doesNotUnderstandWithKeys(g, selector, numArgsPushed, numKeyArgsPushed);
2553 sp = g->sp; ip = g->ip;
2554 } else {
2555 PyrMethodRaw *methraw;
2556 methraw = METHRAW(meth);
2557 switch (methraw->methType) {
2558 case methNormal : /* normal msg send */
2559 g->sp = sp; g->ip = ip;
2560 executeMethodWithKeys(g, meth, numArgsPushed, numKeyArgsPushed);
2561 sp = g->sp; ip = g->ip;
2562 break;
2563 case methReturnSelf : /* return self */
2564 sp -= numArgsPushed - 1;
2565 break;
2566 case methReturnLiteral : /* return literal */
2567 sp -= numArgsPushed - 1;
2568 slotCopy(sp, &meth->selectors); /* in this case selectors is just a single value */
2569 break;
2570 case methReturnArg : /* return an argument */
2571 g->sp = sp;
2572 numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
2573 numKeyArgsPushed = 0;
2574 sp = g->sp;
2575 sp -= numArgsPushed - 1;
2576 index = methraw->specialIndex; // zero is index of the first argument
2577 if (index < numArgsPushed) {
2578 slotCopy(sp, sp + index);
2579 } else {
2580 slotCopy(sp, &slotRawObject(&meth->prototypeFrame)->slots[index]);
2582 break;
2583 case methReturnInstVar : /* return inst var */
2584 sp -= numArgsPushed - 1;
2585 index = methraw->specialIndex;
2586 slotCopy(sp, &slotRawObject(slot)->slots[index]);
2587 break;
2588 case methAssignInstVar : /* assign inst var */
2589 sp -= numArgsPushed - 1;
2590 numArgsPushed -= numKeyArgsPushed << 1;
2591 index = methraw->specialIndex;
2592 obj = slotRawObject(slot);
2593 if (obj->obj_flags & obj_immutable) { StoreToImmutableB(g, sp, ip); }
2594 else {
2595 if (numArgsPushed >= 2) {
2596 slotCopy(&obj->slots[index], sp + 1);
2597 g->gc->GCWrite(obj, sp + 1);
2598 } else
2599 slotCopy(&obj->slots[index], &gSpecialValues[svNil]);
2600 slotCopy(sp, slot);
2602 break;
2603 case methReturnClassVar : /* return class var */
2604 sp -= numArgsPushed - 1;
2605 slotCopy(sp, &g->classvars->slots[methraw->specialIndex]);
2606 break;
2607 case methAssignClassVar : /* assign class var */
2608 sp -= numArgsPushed - 1;
2609 if (numArgsPushed >= 2) {
2610 slotCopy(&g->classvars->slots[methraw->specialIndex], sp + 1);
2611 g->gc->GCWrite(g->classvars, sp + 1);
2612 } else
2613 slotCopy(&g->classvars->slots[methraw->specialIndex], &gSpecialValues[svNil]);
2614 slotCopy(sp, slot);
2615 break;
2616 case methRedirect : /* send a different selector to self, e.g. this.subclassResponsibility */
2617 g->sp = sp;
2618 numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
2619 numKeyArgsPushed = 0;
2620 sp = g->sp;
2621 selector = slotRawSymbol(&meth->selectors);
2623 goto msg_lookup;
2624 case methRedirectSuper : /* send a different selector to super */
2625 g->sp = sp;
2626 numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
2627 numKeyArgsPushed = 0;
2628 sp = g->sp;
2629 selector = slotRawSymbol(&meth->selectors);
2631 classobj = slotRawSymbol(&slotRawClass(&meth->ownerclass)->superclass)->u.classobj;
2633 goto msg_lookup;
2634 case methForwardInstVar : /* forward to an instance variable */
2635 g->sp = sp;
2636 numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
2637 numKeyArgsPushed = 0;
2638 sp = g->sp;
2639 selector = slotRawSymbol(&meth->selectors);
2640 index = methraw->specialIndex;
2641 slotCopy(slot, &slotRawObject(slot)->slots[index]);
2643 classobj = classOfSlot(slot);
2645 goto msg_lookup;
2646 case methForwardClassVar : /* forward to an instance variable */
2647 g->sp = sp;
2648 numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed);
2649 numKeyArgsPushed = 0;
2650 sp = g->sp;
2651 selector = slotRawSymbol(&meth->selectors);
2652 slotCopy(slot, &g->classvars->slots[methraw->specialIndex]);
2654 classobj = classOfSlot(slot);
2656 goto msg_lookup;
2657 case methPrimitive : /* primitive */
2658 g->sp = sp; g->ip = ip;
2659 doPrimitiveWithKeys(g, meth, numArgsPushed, numKeyArgsPushed);
2660 sp = g->sp; ip = g->ip;
2661 break;
2662 } // switch (meth->methType)
2663 } // end handle message
2664 numKeyArgsPushed = 0;
2665 #if TAILCALLOPTIMIZE
2666 g->tailCall = 0;
2667 #endif
2668 dispatch_opcode;
2669 } // switch(op1)
2670 } // end while(running)
2671 #ifndef SC_WIN32
2672 running = true; // reset the signal
2673 #endif
2674 g->sp = sp; g->ip = ip;
2677 void DumpSimpleBackTrace(VMGlobals *g);
2678 void DumpSimpleBackTrace(VMGlobals *g)
2680 int i;
2681 PyrFrame *frame;
2683 post("CALL STACK:\n");
2684 // print the variables and arguments for the most recent frames in the
2685 // call graph
2686 frame = g->frame;
2688 for (i=0; i<16; ++i) {
2689 char str[256];
2690 slotOneWord(&frame->method, str);
2691 post("%s ip %d\n", str, (char*)slotRawPtr(&frame->ip) - (char*)slotRawObject(&slotRawMethod(&frame->method)->code)->slots);
2692 frame = slotRawFrame(&frame->caller);
2693 if (!frame) break;
2695 if (frame) { post("...\n"); }
2696 //DumpStack(g, g->sp);
2699 void DumpBackTrace(VMGlobals *g)
2701 int i;
2702 PyrFrame *frame;
2704 post("CALL STACK:\n");
2705 // print the variables and arguments for the most recent frames in the
2706 // call graph
2707 frame = g->frame;
2709 for (i=0; i<16; ++i) {
2710 if (FrameSanity(frame, "DumpBackTrace")) {
2711 post("FRAME CORRUPTED\n");
2712 return;
2714 DumpFrame(frame);
2715 frame = slotRawFrame(&frame->caller);
2716 if (!frame) break;
2718 if (frame) { post("...\n"); }
2719 //DumpStack(g, g->sp);
2722 void DumpDetailedFrame(PyrFrame *frame);
2723 void DumpDetailedBackTrace(VMGlobals *g);
2724 void DumpDetailedBackTrace(VMGlobals *g)
2726 int i;
2727 PyrFrame *frame;
2729 post("CALL STACK:\n");
2730 // print the variables and arguments for the most recent frames in the
2731 // call graph
2732 frame = g->frame;
2734 for (i=0; i<16; ++i) {
2735 if (FrameSanity(frame, "DumpDetailedBackTrace")) {
2736 post("FRAME CORRUPTED\n");
2737 return;
2739 DumpDetailedFrame(frame);
2740 frame = slotRawFrame(&frame->caller);
2741 if (!frame) break;
2743 if (frame) { post("...\n"); }
2744 //DumpStack(g, g->sp);
2747 void DumpStack(VMGlobals *g, PyrSlot *sp)
2749 int i;
2750 PyrSlot *slot;
2751 char str[128];
2752 #if BCSTAT
2753 dumpbcstat();
2754 #endif
2755 postfl("STACK:\n");
2756 slot = sp - 64;
2757 if (slot < g->gc->Stack()->slots) slot = g->gc->Stack()->slots;
2758 for (i=slot - g->gc->Stack()->slots; slot<=sp; slot++, ++i) {
2759 slotString(slot, str);
2760 post(" %2d %s\n", i, str);