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
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"
33 #include "SC_InlineUnaryOp.h"
34 #include "SC_InlineBinaryOp.h"
35 #include "PyrKernelProto.h"
36 #include "PyrSymbolTable.h"
43 # include "SC_Win32Utils.h"
45 # include <sys/time.h>
49 #define kBigBigFloat DBL_MAX
50 #define kSmallSmallFloat DBL_MIN
54 #include "InitAlloc.h"
55 #include "function_attributes.h"
57 //void tellPlugInsAboutToRun();
65 return tv
.tv_sec
^ tv
.tv_usec
;
69 VMGlobals
*gMainVMGlobals
= &gVMGlobals
;
71 extern PyrObject
*gSynth
;
73 void debugf(char *fmt
, ...) ;
75 #define DEBUGINTERPRETER 0
78 #define CHECK_MAX_STACK_USE 0
81 #if CHECK_MAX_STACK_USE
82 int gMaxStackDepth
= 0;
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:
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();
112 //postfl(" >initInterpreter\n");
114 if (initInterpreter(g
, selector
, numArgsPushed
)) {
115 #ifdef GC_SANITYCHECK
116 g
->gc
->SanityCheck();
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();
127 //postfl(" >endInterpreter\n");
129 #ifdef GC_SANITYCHECK
130 g
->gc
->SanityCheck();
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
);
146 void initPyrThread(VMGlobals
*g
, PyrThread
*thread
, PyrSlot
*func
, int stacksize
, PyrInt32Array
* rgenArray
,
147 double beats
, double seconds
, PyrSlot
* clock
, bool collect
);
150 PyrProcess
* newPyrProcess(VMGlobals
*g
, PyrClass
*procclassobj
)
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
;
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
;
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);
192 ((RGen
*)(rgenArray
->i
))->init(timeseed());
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());
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);
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
);
238 int bcpair
[256][256];
244 for (i
=0; i
<256; ++i
) {
246 for (j
=0; j
<256; ++j
) {
258 file
= fopen("bcstat", "w");
260 fprintf(file
, "----------\n");
262 for (i
=0; i
<256; ++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
));
294 static void handleSigUsr1(int param
)
296 printf("handleSigUsr1()...\n");
301 bool initRuntime(VMGlobals
*g
, int poolSize
, AllocPool
*inPool
)
304 create a GC environment
305 create a vmachine instance of main
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");
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
330 // initialize process random number generator
331 g
->rgen
= (RGen
*)(slotRawObject(&g
->thread
->randData
)->slots
);
339 #ifdef GC_SANITYCHECK
340 g
->gc
->SanityCheck();
342 //tellPlugInsAboutToRun();
345 signal(SIGUSR1
,handleSigUsr1
);
348 assert((g
->gc
->SanityCheck()));
349 #ifdef GC_SANITYCHECK
350 g
->gc
->SanityCheck();
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
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);
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
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
);
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
433 post("StoreToImmutableA\n");
434 dumpObjectSlot(sp
-1);
436 sendMessage(g
, getsym("immutableError"), 2);
441 void StoreToImmutableB(VMGlobals
*g
, PyrSlot
*& sp
, unsigned char *& ip
)
443 // receiver and value are on the stack.
447 post("StoreToImmutableB\n");
448 dumpObjectSlot(sp
-1);
450 PyrSymbol
*selector
= getsym("immutableError");
451 sendMessage(g
, selector
, 2);
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
);
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
);
511 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
512 #define LABELS_AS_VALUES
515 #ifdef LABELS_AS_VALUES
516 #define dispatch_opcode \
519 checkStackDepth(g, sp); \
520 assert(checkStackOverflow(g, sp)); \
521 goto *opcode_labels[op1]
523 #define dispatch_opcode break
526 #if defined(__GNUC__)
527 #define LIKELY(x) __builtin_expect((x),1)
528 #define UNLIKELY(x) __builtin_expect((x),0)
531 #define UNLIKELY(x) x
535 HOT
void Interpret(VMGlobals
*g
)
542 // interpreter globals
544 // temporary variables used in the interpreter
545 int ival
, jmplen
, numArgsPushed
, numKeyArgsPushed
;
549 PyrSlot
*slot
, *vars
;
556 #ifdef LABELS_AS_VALUES
557 static void * opcode_labels
[] = {
819 unsigned char *bzero
;
834 //SetSymbol(g->sp, getsym("STACK TOP")); // just for debugging
835 //g->sp++; // just for debugging
838 // Codewarrior puts them in registers. take advantage..
842 numKeyArgsPushed
= 0;
844 if (setjmp(g
->escapeInterpreter
) != 0) {
848 while (running
) { // not going to indent body to save line space
853 checkStackDepth(g
, sp
);
862 assert(checkStackOverflow(g
, sp
));
866 ++bcpair
[prevop
][op1
];
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);
873 if (gTraceInterpreter
) {
875 if (FrameSanity(g
->frame
, "dbgint")) {
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
);
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);
896 if (gTraceInterpreter
) {
897 slotRawInt(&g
->method
->byteMeter
)++;
902 case 0 : // push class
904 op2
= ip
[1]; ++ip
; // get literal index
905 classobj
= slotRawSymbol(&slotRawObject(&g
->block
->selectors
)->slots
[op2
])->u
.classobj
;
907 ++sp
; SetObject(sp
, classobj
);
909 postfl("Execution warning: Class '%s' not found\n", slotRawSymbol(&slotRawObject(&g
->block
->selectors
)->slots
[op2
])->name
);
910 slotCopy(++sp
, &gSpecialValues
[svNil
]);
913 case 1 : // opExtended, opPushInstVar
915 op2
= ip
[1]; ++ip
; // get inst var index
916 slotCopy(++sp
, &slotRawObject(&g
->receiver
)->slots
[op2
]);
918 case 2 : // opExtended, opPushTempVar
920 op2
= ip
[1]; // get temp var level
921 op3
= ip
[2]; // get temp var index
923 for (tframe
= g
->frame
; --op2
; tframe
= slotRawFrame(&tframe
->context
)) { /* noop */ }
924 slotCopy(++sp
, &tframe
->vars
[op3
]);
926 case 3 : // opExtended, opPushTempZeroVar
928 op2
= ip
[1]; ++ip
; // get temp var index
929 slotCopy(++sp
, &g
->frame
->vars
[op2
]);
931 case 4 : // opExtended, opPushLiteral
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
) {
938 g
->sp
= sp
; // gc may push the stack
939 closure
= (PyrClosure
*)g
->gc
->New(2*sizeof(PyrSlot
), 0, obj_notindexed
, true);
941 closure
->classptr
= gSpecialClasses
[op_class_func
]->u
.classobj
;
943 slotCopy(&closure
->block
, slot
);
944 if (IsNil(&slotRawBlock(slot
)->contextDef
)) {
945 slotCopy(&closure
->context
, &slotRawInterpreter(&g
->process
->interpreter
)->context
);
947 SetObject(&closure
->context
, g
->frame
);
949 ++sp
; SetObject(sp
, closure
);
951 slotCopy(++sp
, slot
);
954 case 5 : // opExtended, opPushClassVar
956 op2
= ip
[1]; // get class
957 op3
= ip
[2]; // get class var index
959 slotCopy(++sp
, &g
->classvars
->slots
[(op2
<<8)|op3
]);
961 case 6 : // opExtended, opPushSpecialValue == push a special class
963 op2
= ip
[1]; ++ip
; // get class name index
964 classobj
= gSpecialClasses
[op2
]->u
.classobj
;
966 ++sp
; SetObject(sp
, classobj
);
968 slotCopy(++sp
, &gSpecialValues
[svNil
]);
971 case 7 : // opExtended, opStoreInstVar
973 op2
= ip
[1]; ++ip
; // get inst var index
974 obj
= slotRawObject(&g
->receiver
);
975 if (obj
->IsImmutable()) { StoreToImmutableA(g
, sp
, ip
); }
977 slot
= obj
->slots
+ op2
;
979 g
->gc
->GCWrite(obj
, slot
);
982 case 8 : // opExtended, opStoreTempVar
984 op2
= ip
[1]; // get temp var level
985 op3
= ip
[2]; // get temp var index
987 for (tframe
= g
->frame
; op2
--; tframe
= slotRawFrame(&tframe
->context
)) { /* noop */ }
988 slot
= tframe
->vars
+ op3
;
990 g
->gc
->GCWrite(tframe
, slot
);
992 case 9 : // opExtended, opStoreClassVar
994 op2
= ip
[1]; // get index of class name literal
995 op3
= ip
[2]; // get class var index
997 slotCopy(&g
->classvars
->slots
[(op2
<<8)|op3
], sp
);
998 g
->gc
->GCWrite(g
->classvars
, sp
);
1000 case 10 : // opExtended, opSendMsg
1002 numArgsPushed
= ip
[1]; // get num args
1003 numKeyArgsPushed
= ip
[2]; // get num keyword args
1004 op3
= ip
[3]; // get selector index
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
1015 numArgsPushed
= ip
[1]; // get num args
1016 numKeyArgsPushed
= ip
[2]; // get num keyword args
1017 op3
= ip
[3]; // get selector index
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
1029 numArgsPushed
= ip
[1]; // get num args
1030 numKeyArgsPushed
= ip
[2]; // get num keyword args
1031 op3
= ip
[3]; // get selector index
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
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
1049 sp
= g
->sp
; ip
= g
->ip
;
1051 case 14 : // opExtended, opSendSpecialBinaryArithMsg
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
;
1059 case 15 : // opExtended, opSpecialOpcode (none yet)
1061 op2
= ip
[1]; ++ip
; // get extended special opcode
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
1073 g
->sp
= sp
; // gc may push the stack
1074 closure
= (PyrClosure
*)g
->gc
->New(2*sizeof(PyrSlot
), 0, obj_notindexed
, true);
1076 closure
->classptr
= gSpecialClasses
[op_class_func
]->u
.classobj
;
1078 SetObject(&closure
->block
, g
->block
);
1079 SetObject(&closure
->context
, slotRawFrame(&g
->frame
->context
));
1080 ++sp
; SetObject(sp
, closure
);
1083 slotCopy(++sp
, &gSpecialValues
[svNil
]); break;
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
1106 // cannot compare with o_false because it is NaN
1108 jmplen
= (ip
[1]<<8) | ip
[2];
1110 } else if ( IsFalse(sp
)) {
1114 selector
= gSpecialSelectors
[opmNonBooleanError
];
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.
1148 slotCopy(++sp
, &slotRawObject(&g
->block
->constants
)->slots
[ival
]);
1152 ival
= (ip
[1] << 8) | ip
[2];
1154 slotCopy(++sp
, &slotRawObject(&g
->block
->constants
)->slots
[ival
]);
1158 ival
= (ip
[1] << 16) | (ip
[2] << 8) | ip
[3];
1160 slotCopy(++sp
, &slotRawObject(&g
->block
->constants
)->slots
[ival
]);
1164 ival
= (ip
[1] << 24) | (ip
[2] << 16) | (ip
[3] << 8) | ip
[4];
1166 slotCopy(++sp
, &slotRawObject(&g
->block
->constants
)->slots
[ival
]);
1172 ival
= (int32
)(ip
[1] << 24) >> 24;
1174 ++sp
; SetInt(sp
, ival
);
1178 ival
= (int32
)((ip
[1] << 24) | (ip
[2] << 16)) >> 16;
1180 ++sp
; SetInt(sp
, ival
);
1184 ival
= (int32
)((ip
[1] << 24) | (ip
[2] << 16) | (ip
[3] << 8)) >> 8;
1186 ++sp
; SetInt(sp
, ival
);
1190 ival
= (int32
)((ip
[1] << 24) | (ip
[2] << 16) | (ip
[3] << 8) | ip
[4]);
1192 ++sp
; SetInt(sp
, ival
);
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
;
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
1271 SetRaw(sp
, slotRawInt(sp
) - 1);
1272 #if TAILCALLOPTIMIZE
1276 slotCopy(++sp
, &gSpecialValues
[svOne
]);
1277 g
->sp
= sp
; g
->ip
= ip
;
1278 g
->primitiveIndex
= opSub
;
1280 sp
= g
->sp
; ip
= g
->ip
;
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
1295 SetRaw(sp
, slotRawInt(sp
) + 1);
1296 #if TAILCALLOPTIMIZE
1300 slotCopy(++sp
, &gSpecialValues
[svOne
]);
1301 g
->sp
= sp
; g
->ip
= ip
;
1302 g
->primitiveIndex
= opAdd
;
1304 sp
= g
->sp
; ip
= g
->ip
;
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
;
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
);
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
);
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
);
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
);
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
);
1392 case 133 : case 134 : case 135 :
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
;
1401 g
->gc
->GCWrite(tframe
, slot
);
1404 case 136 : // push inst var, send special selector
1406 op2
= ip
[1]; // get inst var index
1407 op3
= ip
[2]; // get selector
1410 slotCopy(++sp
, &slotRawObject(&g
->receiver
)->slots
[op2
]);
1413 selector
= gSpecialSelectors
[op3
];
1418 case 137 : // push all args, send msg
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;
1430 case 138 : // push all but first arg, send msg
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;
1442 case 139 : // push all args, send special
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;
1454 case 140 : // push all but first arg, send special
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;
1466 case 141 : // one arg pushed, push all but first arg, send msg
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;
1478 case 142 : // one arg pushed, push all but first arg, send special
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;
1490 case 143 : // loop byte codes
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
1496 // Integer-do : 143 0, 143 1
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
1505 selector
= gSpecialSelectors
[opmValue
];
1510 slotCopy(++sp
, &g
->receiver
);
1511 g
->sp
= sp
; g
->ip
= ip
;
1512 returnFromMethod(g
);
1513 sp
= g
->sp
; ip
= g
->ip
;
1518 SetRaw(&g
->frame
->vars
[2], slotRawInt(&g
->frame
->vars
[2]) + 1); // inc i
1522 // Integer-reverseDo : 143 2, 143 3, 143 4
1524 SetRaw(&g
->frame
->vars
[2], slotRawInt(&g
->receiver
) - 1);
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
1534 selector
= gSpecialSelectors
[opmValue
];
1539 slotCopy(++sp
, &g
->receiver
);
1540 g
->sp
= sp
; g
->ip
= ip
;
1541 returnFromMethod(g
);
1542 sp
= g
->sp
; ip
= g
->ip
;
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
1553 // Integer-for : 143 5, 143 6, 143 16
1555 vars
= g
->frame
->vars
;
1556 tag
= GetTag(&vars
[1]);
1558 if (tag
!= tagInt
) {
1559 if (IsFloat(&vars
[1])) {
1561 SetInt(&vars
[1], (int32
)(slotRawFloat(&vars
[1])));
1563 error("Integer-for : endval not a SimpleNumber.\n");
1565 slotCopy(++sp
, &g
->receiver
);
1567 selector
= gSpecialSelectors
[opmPrimitiveFailed
];
1574 if (slotRawInt(&g
->receiver
) <= slotRawInt(&vars
[1])) {
1575 SetRaw(&vars
[5], 1);
1577 SetRaw(&vars
[5], -1);
1579 slotCopy(&vars
[3], &g
->receiver
);
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
1592 selector
= gSpecialSelectors
[opmValue
];
1597 slotCopy(++sp
, &g
->receiver
);
1598 g
->sp
= sp
; g
->ip
= ip
;
1599 returnFromMethod(g
);
1600 sp
= g
->sp
; ip
= g
->ip
;
1604 // Integer-forBy : 143 7, 143 8, 143 9
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]);
1615 || NotInt(&vars
[2])) {
1616 error("Integer-forBy : endval or stepval not an Integer.\n");
1618 slotCopy(++sp
, &g
->receiver
);
1620 selector
= gSpecialSelectors
[opmPrimitiveFailed
];
1625 slotCopy(&vars
[4], &g
->receiver
);
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
1636 selector
= gSpecialSelectors
[opmValue
];
1641 slotCopy(++sp
, &g
->receiver
);
1642 g
->sp
= sp
; g
->ip
= ip
;
1643 returnFromMethod(g
);
1644 sp
= g
->sp
; ip
= g
->ip
;
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
1655 // ArrayedCollection-do : 143 10, 143 1
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
1666 selector
= gSpecialSelectors
[opmValue
];
1671 slotCopy(++sp
, &g
->receiver
);
1672 g
->sp
= sp
; g
->ip
= ip
;
1673 returnFromMethod(g
);
1674 sp
= g
->sp
; ip
= g
->ip
;
1678 // ArrayedCollection-reverseDo : 143 11, 143 12, 143 4
1680 SetRaw(&g
->frame
->vars
[2], slotRawObject(&g
->receiver
)->size
- 1);
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
1690 selector
= gSpecialSelectors
[opmValue
];
1693 goto class_lookup
; // class_lookup:
1695 slotCopy(++sp
, &g
->receiver
);
1696 g
->sp
= sp
; g
->ip
= ip
;
1697 returnFromMethod(g
);
1698 sp
= g
->sp
; ip
= g
->ip
;
1702 // Dictionary-keysValuesArrayDo
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
)) {
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
1726 selector
= gSpecialSelectors
[opmValue
];
1729 goto class_lookup
; // class_lookup:
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
;
1740 SetRaw(&g
->frame
->vars
[3], slotRawInt(&g
->frame
->vars
[3]) + 2); // inc i
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
1755 // Float-do : 143 17, 143 18
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
1764 selector
= gSpecialSelectors
[opmValue
];
1769 slotCopy(++sp
, &g
->receiver
);
1770 g
->sp
= sp
; g
->ip
= ip
;
1771 returnFromMethod(g
);
1772 sp
= g
->sp
; ip
= g
->ip
;
1777 SetRaw(&g
->frame
->vars
[2], slotRawFloat(&g
->frame
->vars
[2]) + 1.0); // inc i
1781 // Float-reverseDo : 143 19, 143 20, 143 21
1783 SetFloat(&g
->frame
->vars
[2], slotRawFloat(&g
->receiver
) - 1.0);
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
1793 selector
= gSpecialSelectors
[opmValue
];
1798 slotCopy(++sp
, &g
->receiver
);
1799 g
->sp
= sp
; g
->ip
= ip
;
1800 returnFromMethod(g
);
1801 sp
= g
->sp
; ip
= g
->ip
;
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
1811 case 22 : // ? question mark method
1817 case 23 : // if not nil push this and jump. used to implement ??
1819 jmplen
= (ip
[1]<<8) | ip
[2];
1828 jmplen
= (ip
[1]<<8) | ip
[2];
1835 case 25 : // ifNotNil
1837 jmplen
= (ip
[1]<<8) | ip
[2];
1844 case 26 : // ifNotNilPushNil
1846 jmplen
= (ip
[1]<<8) | ip
[2];
1848 slotCopy(sp
, &gSpecialValues
[svNil
]);
1854 case 27 : // ifNilPushNil
1856 jmplen
= (ip
[1]<<8) | ip
[2];
1864 obj
= slotRawObject(sp
);
1865 op2
= 1 + arrayAtIdentityHashInPairs(obj
, (sp
-1));
1867 ip
+= slotRawInt(&obj
->slots
[op2
]);
1870 // Number-forSeries : 143 29, 143 30, 143 31
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);
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]);
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]));
1893 bailFromNumberSeries
:
1894 error("Number-forSeries : first, second or last not an Integer or Float.\n");
1896 slotCopy(++sp
, &g
->receiver
);
1898 selector
= gSpecialSelectors
[opmPrimitiveFailed
];
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.);
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]));
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
1936 selector
= gSpecialSelectors
[opmValue
];
1941 slotCopy(++sp
, &g
->receiver
);
1942 g
->sp
= sp
; g
->ip
= ip
;
1943 returnFromMethod(g
);
1944 sp
= g
->sp
; ip
= g
->ip
;
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
1954 selector
= gSpecialSelectors
[opmValue
];
1959 slotCopy(++sp
, &g
->receiver
);
1960 g
->sp
= sp
; g
->ip
= ip
;
1961 returnFromMethod(g
);
1962 sp
= g
->sp
; ip
= g
->ip
;
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
1974 SetRaw(&vars
[4], slotRawFloat(&vars
[4]) + slotRawFloat(&vars
[1])); // inc i
1976 SetRaw(&vars
[5], slotRawInt(&vars
[5]) + 1); // inc j
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
:
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));
2002 // special case for this as only arg
2003 op2
= ip
[1]; ++ip
; // get selector index
2004 slotCopy(++sp
, &g
->receiver
);
2006 selector
= slotRawSymbol(&slotRawObject(&g
->block
->selectors
)->slots
[op2
]);
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;
2027 case 176 : // opcTailCallReturnFromFunction
2029 #if TAILCALLOPTIMIZE
2036 // special case for this as only arg
2037 op2
= ip
[1]; ++ip
; // get selector index
2038 slotCopy(++sp
, &g
->receiver
);
2040 selector
= slotRawSymbol(&slotRawObject(&g
->block
->selectors
)->slots
[op2
]);
2042 classobj
= slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->superclass
)->u
.classobj
;
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
;
2067 slotCopy(++sp
, &g
->receiver
);
2068 op2
= ip
[1]; ++ip
; // get selector index
2070 selector
= gSpecialSelectors
[op2
];
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;
2092 // opSendSpecialUnaryArithMsg
2096 SetFloat(sp
, -slotRawFloat(sp
));
2097 #if TAILCALLOPTIMIZE
2100 } else if (IsInt(sp
)) {
2101 SetRaw(sp
, -slotRawInt(sp
));
2102 #if TAILCALLOPTIMIZE
2106 handleSendSpecialUnaryArithMsg(g
, sp
, ip
, op1
);
2111 SetTagRaw(sp
, tagFalse
);
2112 #if TAILCALLOPTIMIZE
2115 } else if (IsFalse(sp
)) {
2116 SetTagRaw(sp
, tagTrue
);
2117 #if TAILCALLOPTIMIZE
2121 handleSendSpecialUnaryArithMsg(g
, sp
, ip
, op1
);
2123 case 210 : // opIsNil
2126 SetTagRaw(sp
, tagTrue
);
2128 slotCopy(sp
, &gSpecialValues
[svFalse
]);
2130 #if TAILCALLOPTIMIZE
2134 case 211 : // opNotNil
2137 slotCopy(sp
, &gSpecialValues
[svTrue
]);
2139 SetTagRaw(sp
, tagFalse
);
2141 #if TAILCALLOPTIMIZE
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
2175 if (IsInt(sp
- 1)) {
2177 --sp
; SetRaw(sp
, slotRawInt(sp
) + slotRawInt(sp
+ 1));
2178 #if TAILCALLOPTIMIZE
2182 g
->sp
= sp
; g
->ip
= ip
;
2183 g
->primitiveIndex
= opAdd
;
2185 sp
= g
->sp
; ip
= g
->ip
;
2188 g
->sp
= sp
; g
->ip
= ip
;
2189 g
->primitiveIndex
= opAdd
;
2191 sp
= g
->sp
; ip
= g
->ip
;
2194 case 225 : // subtract
2196 if (IsInt(sp
- 1)) {
2198 --sp
; SetRaw(sp
, slotRawInt(sp
) - slotRawInt(sp
+ 1));
2199 #if TAILCALLOPTIMIZE
2203 g
->sp
= sp
; g
->ip
= ip
;
2204 g
->primitiveIndex
= opSub
;
2206 sp
= g
->sp
; ip
= g
->ip
;
2209 g
->sp
= sp
; g
->ip
= ip
;
2210 g
->primitiveIndex
= opSub
;
2212 sp
= g
->sp
; ip
= g
->ip
;
2215 case 226 : // multiply
2217 if (IsInt(sp
- 1)) {
2219 --sp
; SetRaw(sp
, slotRawInt(sp
) * slotRawInt(sp
+ 1));
2220 #if TAILCALLOPTIMIZE
2224 g
->sp
= sp
; g
->ip
= ip
;
2225 g
->primitiveIndex
= opMul
;
2227 sp
= g
->sp
; ip
= g
->ip
;
2230 g
->sp
= sp
; g
->ip
= ip
;
2231 g
->primitiveIndex
= opMul
;
2233 sp
= g
->sp
; ip
= g
->ip
;
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
;
2267 --sp
; dispatch_opcode
; // opDrop
2270 ++sp
; *sp
= sp
[-1]; dispatch_opcode
; // opDup
2271 case 242 : // opcFunctionReturn
2273 g
->sp
= sp
; g
->ip
= ip
;
2275 sp
= g
->sp
; ip
= g
->ip
;
2277 case 243 : // opcReturn
2279 g
->sp
= sp
; g
->ip
= ip
;
2280 returnFromMethod(g
);
2281 sp
= g
->sp
; ip
= g
->ip
;
2283 case 244 : // opcReturnSelf
2285 slotCopy(++sp
, &g
->receiver
);
2286 g
->sp
= sp
; g
->ip
= ip
;
2287 returnFromMethod(g
);
2288 sp
= g
->sp
; ip
= g
->ip
;
2290 case 245 : // opcReturnTrue
2292 slotCopy(++sp
, &gSpecialValues
[svTrue
]);
2293 g
->sp
= sp
; g
->ip
= ip
;
2294 returnFromMethod(g
);
2295 sp
= g
->sp
; ip
= g
->ip
;
2297 case 246 : // opcReturnFalse
2299 slotCopy(++sp
, &gSpecialValues
[svFalse
]);
2300 g
->sp
= sp
; g
->ip
= ip
;
2301 returnFromMethod(g
);
2302 sp
= g
->sp
; ip
= g
->ip
;
2304 case 247 : // opcReturnNil
2306 slotCopy(++sp
, &gSpecialValues
[svNil
]);
2307 g
->sp
= sp
; g
->ip
= ip
;
2308 returnFromMethod(g
);
2309 sp
= g
->sp
; ip
= g
->ip
;
2312 case 248 : // opcJumpIfFalse
2314 // cannot compare with o_false because it is NaN
2315 if ( IsFalse(sp
) ) {
2316 jmplen
= (ip
[1]<<8) | ip
[2];
2318 } else if ( IsTrue(sp
)) {
2322 selector
= gSpecialSelectors
[opmNonBooleanError
];
2329 case 249 : // opcJumpIfFalsePushNil
2332 jmplen
= (ip
[1]<<8) | ip
[2];
2334 slotCopy(sp
, &gSpecialValues
[svNil
]);
2335 } else if ( IsTrue(sp
)) {
2340 selector
= gSpecialSelectors
[opmNonBooleanError
];
2346 case 250 : // opcJumpIfFalsePushFalse
2349 jmplen
= (ip
[1]<<8) | ip
[2];
2352 } else if (IsTrue(sp
)) {
2357 selector
= gSpecialSelectors
[opmNonBooleanError
];
2363 case 251 : // opcJumpIfTruePushTrue
2368 } else if (IsTrue(sp
)) {
2369 jmplen
= (ip
[1]<<8) | ip
[2];
2371 slotCopy(sp
, &gSpecialValues
[svTrue
]);
2374 selector
= gSpecialSelectors
[opmNonBooleanError
];
2380 case 252 : // opcJumpFwd
2382 jmplen
= (ip
[1]<<8) | ip
[2];
2385 case 253 : // opcJumpBak
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];
2392 //assert(g->gc->SanityCheck());
2394 case 254 : // opcSpecialBinaryOpWithAdverb
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
;
2402 case 255 : // opcTailCallReturnFromMethod
2404 #if TAILCALLOPTIMIZE
2409 ////////////////////////////////////
2412 // normal class lookup
2413 classobj
= classOfSlot(slot
);
2415 // message sends handled here:
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
;
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
;
2433 case methReturnSelf
: /* return self */
2434 sp
-= numArgsPushed
- 1;
2436 case methReturnLiteral
: /* return literal */
2437 sp
-= numArgsPushed
- 1;
2438 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
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
);
2446 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
2449 case methReturnInstVar
: /* return inst var */
2450 sp
-= numArgsPushed
- 1;
2451 index
= methraw
->specialIndex
;
2452 slotCopy(sp
, &slotRawObject(slot
)->slots
[index
]);
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
); }
2460 if (numArgsPushed
>= 2) {
2461 slotCopy(&obj
->slots
[index
], sp
+ 1);
2462 g
->gc
->GCWrite(obj
, sp
+ 1);
2464 slotCopy(&obj
->slots
[index
], &gSpecialValues
[svNil
]);
2469 case methReturnClassVar
: /* return class var */
2470 sp
-= numArgsPushed
- 1;
2471 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
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);
2479 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], &gSpecialValues
[svNil
]);
2482 case methRedirect
: /* send a different selector to self */
2483 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
2484 /* push default arg values */
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
);
2493 case methRedirectSuper
: /* send a different selector to self */
2494 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
2495 /* push default arg values */
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
;
2505 case methForwardInstVar
: /* forward to an instance variable */
2506 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
2507 /* push default arg values */
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
);
2521 case methForwardClassVar
: /* forward to an instance variable */
2522 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
2523 /* push default arg values */
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
);
2536 case methPrimitive
: /* primitive */
2537 g
->sp
= sp
; g
->ip
= ip
;
2538 doPrimitive(g
, meth
, numArgsPushed
);
2539 sp
= g
->sp
; ip
= g
->ip
;
2541 } // switch (meth->methType)
2542 } // end handle message
2543 #if TAILCALLOPTIMIZE
2548 ////////////////////////////////////
2551 // normal class lookup
2552 classobj
= classOfSlot(slot
);
2554 // message sends handled here:
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
;
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
;
2572 case methReturnSelf
: /* return self */
2573 sp
-= numArgsPushed
- 1;
2575 case methReturnLiteral
: /* return literal */
2576 sp
-= numArgsPushed
- 1;
2577 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
2579 case methReturnArg
: /* return an argument */
2581 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
2582 numKeyArgsPushed
= 0;
2584 sp
-= numArgsPushed
- 1;
2585 index
= methraw
->specialIndex
; // zero is index of the first argument
2586 if (index
< numArgsPushed
) {
2587 slotCopy(sp
, sp
+ index
);
2589 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
2592 case methReturnInstVar
: /* return inst var */
2593 sp
-= numArgsPushed
- 1;
2594 index
= methraw
->specialIndex
;
2595 slotCopy(sp
, &slotRawObject(slot
)->slots
[index
]);
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
); }
2604 if (numArgsPushed
>= 2) {
2605 slotCopy(&obj
->slots
[index
], sp
+ 1);
2606 g
->gc
->GCWrite(obj
, sp
+ 1);
2608 slotCopy(&obj
->slots
[index
], &gSpecialValues
[svNil
]);
2612 case methReturnClassVar
: /* return class var */
2613 sp
-= numArgsPushed
- 1;
2614 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
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);
2622 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], &gSpecialValues
[svNil
]);
2625 case methRedirect
: /* send a different selector to self, e.g. this.subclassResponsibility */
2627 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
2628 numKeyArgsPushed
= 0;
2630 selector
= slotRawSymbol(&meth
->selectors
);
2633 case methRedirectSuper
: /* send a different selector to super */
2635 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
2636 numKeyArgsPushed
= 0;
2638 selector
= slotRawSymbol(&meth
->selectors
);
2640 classobj
= slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->superclass
)->u
.classobj
;
2643 case methForwardInstVar
: /* forward to an instance variable */
2645 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
2646 numKeyArgsPushed
= 0;
2648 selector
= slotRawSymbol(&meth
->selectors
);
2649 index
= methraw
->specialIndex
;
2650 slotCopy(slot
, &slotRawObject(slot
)->slots
[index
]);
2652 classobj
= classOfSlot(slot
);
2655 case methForwardClassVar
: /* forward to an instance variable */
2657 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
2658 numKeyArgsPushed
= 0;
2660 selector
= slotRawSymbol(&meth
->selectors
);
2661 slotCopy(slot
, &g
->classvars
->slots
[methraw
->specialIndex
]);
2663 classobj
= classOfSlot(slot
);
2666 case methPrimitive
: /* primitive */
2667 g
->sp
= sp
; g
->ip
= ip
;
2668 doPrimitiveWithKeys(g
, meth
, numArgsPushed
, numKeyArgsPushed
);
2669 sp
= g
->sp
; ip
= g
->ip
;
2671 } // switch (meth->methType)
2672 } // end handle message
2673 numKeyArgsPushed
= 0;
2674 #if TAILCALLOPTIMIZE
2679 } // end while(running)
2681 running
= true; // reset the signal
2683 g
->sp
= sp
; g
->ip
= ip
;
2686 void DumpSimpleBackTrace(VMGlobals
*g
);
2687 void DumpSimpleBackTrace(VMGlobals
*g
)
2692 post("CALL STACK:\n");
2693 // print the variables and arguments for the most recent frames in the
2697 for (i
=0; i
<16; ++i
) {
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
);
2704 if (frame
) { post("...\n"); }
2705 //DumpStack(g, g->sp);
2708 void DumpBackTrace(VMGlobals
*g
)
2713 post("CALL STACK:\n");
2714 // print the variables and arguments for the most recent frames in the
2718 for (i
=0; i
<16; ++i
) {
2719 if (FrameSanity(frame
, "DumpBackTrace")) {
2720 post("FRAME CORRUPTED\n");
2724 frame
= slotRawFrame(&frame
->caller
);
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
)
2738 post("CALL STACK:\n");
2739 // print the variables and arguments for the most recent frames in the
2743 for (i
=0; i
<16; ++i
) {
2744 if (FrameSanity(frame
, "DumpDetailedBackTrace")) {
2745 post("FRAME CORRUPTED\n");
2748 DumpDetailedFrame(frame
);
2749 frame
= slotRawFrame(&frame
->caller
);
2752 if (frame
) { post("...\n"); }
2753 //DumpStack(g, g->sp);
2756 void DumpStack(VMGlobals
*g
, PyrSlot
*sp
)
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
);