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"
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 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);
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
->obj_flags
& obj_immutable
)
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
527 void Interpret(VMGlobals
*g
)
532 int op2
, op3
, index
, tag
;
533 // interpreter globals
535 // temporary variables used in the interpreter
536 int ival
, jmplen
, numArgsPushed
, numKeyArgsPushed
;
540 PyrSlot
*slot
, *vars
;
547 #ifdef LABELS_AS_VALUES
548 static void * opcode_labels
[] = {
810 unsigned char *bzero
;
825 //SetSymbol(g->sp, getsym("STACK TOP")); // just for debugging
826 //g->sp++; // just for debugging
829 // Codewarrior puts them in registers. take advantage..
833 numKeyArgsPushed
= 0;
835 if (setjmp(g
->escapeInterpreter
) != 0) {
839 while (running
) { // not going to indent body to save line space
844 checkStackDepth(g
, sp
);
853 assert(checkStackOverflow(g
, sp
));
857 ++bcpair
[prevop
][op1
];
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);
864 if (gTraceInterpreter
) {
866 if (FrameSanity(g
->frame
, "dbgint")) {
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
);
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);
887 if (gTraceInterpreter
) {
888 slotRawInt(&g
->method
->byteMeter
)++;
893 case 0 : // push class
895 op2
= ip
[1]; ++ip
; // get literal index
896 classobj
= slotRawSymbol(&slotRawObject(&g
->block
->selectors
)->slots
[op2
])->u
.classobj
;
898 ++sp
; SetObject(sp
, classobj
);
900 postfl("Execution warning: Class '%s' not found\n", slotRawSymbol(&slotRawObject(&g
->block
->selectors
)->slots
[op2
])->name
);
901 slotCopy(++sp
, &gSpecialValues
[svNil
]);
904 case 1 : // opExtended, opPushInstVar
906 op2
= ip
[1]; ++ip
; // get inst var index
907 slotCopy(++sp
, &slotRawObject(&g
->receiver
)->slots
[op2
]);
909 case 2 : // opExtended, opPushTempVar
911 op2
= ip
[1]; // get temp var level
912 op3
= ip
[2]; // get temp var index
914 for (tframe
= g
->frame
; --op2
; tframe
= slotRawFrame(&tframe
->context
)) { /* noop */ }
915 slotCopy(++sp
, &tframe
->vars
[op3
]);
917 case 3 : // opExtended, opPushTempZeroVar
919 op2
= ip
[1]; ++ip
; // get temp var index
920 slotCopy(++sp
, &g
->frame
->vars
[op2
]);
922 case 4 : // opExtended, opPushLiteral
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
) {
929 g
->sp
= sp
; // gc may push the stack
930 closure
= (PyrClosure
*)g
->gc
->New(2*sizeof(PyrSlot
), 0, obj_notindexed
, true);
932 closure
->classptr
= gSpecialClasses
[op_class_func
]->u
.classobj
;
934 slotCopy(&closure
->block
, slot
);
935 if (IsNil(&slotRawBlock(slot
)->contextDef
)) {
936 slotCopy(&closure
->context
, &slotRawInterpreter(&g
->process
->interpreter
)->context
);
938 SetObject(&closure
->context
, g
->frame
);
940 ++sp
; SetObject(sp
, closure
);
942 slotCopy(++sp
, slot
);
945 case 5 : // opExtended, opPushClassVar
947 op2
= ip
[1]; // get class
948 op3
= ip
[2]; // get class var index
950 slotCopy(++sp
, &g
->classvars
->slots
[(op2
<<8)|op3
]);
952 case 6 : // opExtended, opPushSpecialValue == push a special class
954 op2
= ip
[1]; ++ip
; // get class name index
955 classobj
= gSpecialClasses
[op2
]->u
.classobj
;
957 ++sp
; SetObject(sp
, classobj
);
959 slotCopy(++sp
, &gSpecialValues
[svNil
]);
962 case 7 : // opExtended, opStoreInstVar
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
); }
968 slot
= obj
->slots
+ op2
;
970 g
->gc
->GCWrite(obj
, slot
);
973 case 8 : // opExtended, opStoreTempVar
975 op2
= ip
[1]; // get temp var level
976 op3
= ip
[2]; // get temp var index
978 for (tframe
= g
->frame
; op2
--; tframe
= slotRawFrame(&tframe
->context
)) { /* noop */ }
979 slot
= tframe
->vars
+ op3
;
981 g
->gc
->GCWrite(tframe
, slot
);
983 case 9 : // opExtended, opStoreClassVar
985 op2
= ip
[1]; // get index of class name literal
986 op3
= ip
[2]; // get class var index
988 slotCopy(&g
->classvars
->slots
[(op2
<<8)|op3
], sp
);
989 g
->gc
->GCWrite(g
->classvars
, sp
);
991 case 10 : // opExtended, opSendMsg
993 numArgsPushed
= ip
[1]; // get num args
994 numKeyArgsPushed
= ip
[2]; // get num keyword args
995 op3
= ip
[3]; // get selector index
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
1006 numArgsPushed
= ip
[1]; // get num args
1007 numKeyArgsPushed
= ip
[2]; // get num keyword args
1008 op3
= ip
[3]; // get selector index
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
1020 numArgsPushed
= ip
[1]; // get num args
1021 numKeyArgsPushed
= ip
[2]; // get num keyword args
1022 op3
= ip
[3]; // get selector index
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
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
1040 sp
= g
->sp
; ip
= g
->ip
;
1042 case 14 : // opExtended, opSendSpecialBinaryArithMsg
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
;
1050 case 15 : // opExtended, opSpecialOpcode (none yet)
1052 op2
= ip
[1]; ++ip
; // get extended special opcode
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
1064 g
->sp
= sp
; // gc may push the stack
1065 closure
= (PyrClosure
*)g
->gc
->New(2*sizeof(PyrSlot
), 0, obj_notindexed
, true);
1067 closure
->classptr
= gSpecialClasses
[op_class_func
]->u
.classobj
;
1069 SetObject(&closure
->block
, g
->block
);
1070 SetObject(&closure
->context
, slotRawFrame(&g
->frame
->context
));
1071 ++sp
; SetObject(sp
, closure
);
1074 slotCopy(++sp
, &gSpecialValues
[svNil
]); break;
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
1097 // cannot compare with o_false because it is NaN
1099 jmplen
= (ip
[1]<<8) | ip
[2];
1101 } else if ( IsFalse(sp
)) {
1105 selector
= gSpecialSelectors
[opmNonBooleanError
];
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.
1139 slotCopy(++sp
, &slotRawObject(&g
->block
->constants
)->slots
[ival
]);
1143 ival
= (ip
[1] << 8) | ip
[2];
1145 slotCopy(++sp
, &slotRawObject(&g
->block
->constants
)->slots
[ival
]);
1149 ival
= (ip
[1] << 16) | (ip
[2] << 8) | ip
[3];
1151 slotCopy(++sp
, &slotRawObject(&g
->block
->constants
)->slots
[ival
]);
1155 ival
= (ip
[1] << 24) | (ip
[2] << 16) | (ip
[3] << 8) | ip
[4];
1157 slotCopy(++sp
, &slotRawObject(&g
->block
->constants
)->slots
[ival
]);
1163 ival
= (int32
)(ip
[1] << 24) >> 24;
1165 ++sp
; SetInt(sp
, ival
);
1169 ival
= (int32
)((ip
[1] << 24) | (ip
[2] << 16)) >> 16;
1171 ++sp
; SetInt(sp
, ival
);
1175 ival
= (int32
)((ip
[1] << 24) | (ip
[2] << 16) | (ip
[3] << 8)) >> 8;
1177 ++sp
; SetInt(sp
, ival
);
1181 ival
= (int32
)((ip
[1] << 24) | (ip
[2] << 16) | (ip
[3] << 8) | ip
[4]);
1183 ++sp
; SetInt(sp
, ival
);
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
;
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
1262 SetRaw(sp
, slotRawInt(sp
) - 1);
1263 #if TAILCALLOPTIMIZE
1267 slotCopy(++sp
, &gSpecialValues
[svOne
]);
1268 g
->sp
= sp
; g
->ip
= ip
;
1269 g
->primitiveIndex
= opSub
;
1271 sp
= g
->sp
; ip
= g
->ip
;
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
1286 SetRaw(sp
, slotRawInt(sp
) + 1);
1287 #if TAILCALLOPTIMIZE
1291 slotCopy(++sp
, &gSpecialValues
[svOne
]);
1292 g
->sp
= sp
; g
->ip
= ip
;
1293 g
->primitiveIndex
= opAdd
;
1295 sp
= g
->sp
; ip
= g
->ip
;
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
;
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
);
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
);
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
);
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
);
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
);
1383 case 133 : case 134 : case 135 :
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
;
1392 g
->gc
->GCWrite(tframe
, slot
);
1395 case 136 : // push inst var, send special selector
1397 op2
= ip
[1]; // get inst var index
1398 op3
= ip
[2]; // get selector
1401 slotCopy(++sp
, &slotRawObject(&g
->receiver
)->slots
[op2
]);
1404 selector
= gSpecialSelectors
[op3
];
1409 case 137 : // push all args, send msg
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;
1421 case 138 : // push all but first arg, send msg
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;
1433 case 139 : // push all args, send special
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;
1445 case 140 : // push all but first arg, send special
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;
1457 case 141 : // one arg pushed, push all but first arg, send msg
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;
1469 case 142 : // one arg pushed, push all but first arg, send special
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;
1481 case 143 : // loop byte codes
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
1487 // Integer-do : 143 0, 143 1
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
1496 selector
= gSpecialSelectors
[opmValue
];
1501 slotCopy(++sp
, &g
->receiver
);
1502 g
->sp
= sp
; g
->ip
= ip
;
1503 returnFromMethod(g
);
1504 sp
= g
->sp
; ip
= g
->ip
;
1509 SetRaw(&g
->frame
->vars
[2], slotRawInt(&g
->frame
->vars
[2]) + 1); // inc i
1513 // Integer-reverseDo : 143 2, 143 3, 143 4
1515 SetRaw(&g
->frame
->vars
[2], slotRawInt(&g
->receiver
) - 1);
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
1525 selector
= gSpecialSelectors
[opmValue
];
1530 slotCopy(++sp
, &g
->receiver
);
1531 g
->sp
= sp
; g
->ip
= ip
;
1532 returnFromMethod(g
);
1533 sp
= g
->sp
; ip
= g
->ip
;
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
1544 // Integer-for : 143 5, 143 6, 143 16
1546 vars
= g
->frame
->vars
;
1547 tag
= GetTag(&vars
[1]);
1549 if (tag
!= tagInt
) {
1550 if (IsFloat(&vars
[1])) {
1552 SetInt(&vars
[1], (int32
)(slotRawFloat(&vars
[1])));
1554 error("Integer-for : endval not a SimpleNumber.\n");
1556 slotCopy(++sp
, &g
->receiver
);
1558 selector
= gSpecialSelectors
[opmPrimitiveFailed
];
1565 if (slotRawInt(&g
->receiver
) <= slotRawInt(&vars
[1])) {
1566 SetRaw(&vars
[5], 1);
1568 SetRaw(&vars
[5], -1);
1570 slotCopy(&vars
[3], &g
->receiver
);
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
1583 selector
= gSpecialSelectors
[opmValue
];
1588 slotCopy(++sp
, &g
->receiver
);
1589 g
->sp
= sp
; g
->ip
= ip
;
1590 returnFromMethod(g
);
1591 sp
= g
->sp
; ip
= g
->ip
;
1595 // Integer-forBy : 143 7, 143 8, 143 9
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]);
1606 || NotInt(&vars
[2])) {
1607 error("Integer-forBy : endval or stepval not an Integer.\n");
1609 slotCopy(++sp
, &g
->receiver
);
1611 selector
= gSpecialSelectors
[opmPrimitiveFailed
];
1616 slotCopy(&vars
[4], &g
->receiver
);
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
1627 selector
= gSpecialSelectors
[opmValue
];
1632 slotCopy(++sp
, &g
->receiver
);
1633 g
->sp
= sp
; g
->ip
= ip
;
1634 returnFromMethod(g
);
1635 sp
= g
->sp
; ip
= g
->ip
;
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
1646 // ArrayedCollection-do : 143 10, 143 1
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
1657 selector
= gSpecialSelectors
[opmValue
];
1662 slotCopy(++sp
, &g
->receiver
);
1663 g
->sp
= sp
; g
->ip
= ip
;
1664 returnFromMethod(g
);
1665 sp
= g
->sp
; ip
= g
->ip
;
1669 // ArrayedCollection-reverseDo : 143 11, 143 12, 143 4
1671 SetRaw(&g
->frame
->vars
[2], slotRawObject(&g
->receiver
)->size
- 1);
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
1681 selector
= gSpecialSelectors
[opmValue
];
1684 goto class_lookup
; // class_lookup:
1686 slotCopy(++sp
, &g
->receiver
);
1687 g
->sp
= sp
; g
->ip
= ip
;
1688 returnFromMethod(g
);
1689 sp
= g
->sp
; ip
= g
->ip
;
1693 // Dictionary-keysValuesArrayDo
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
)) {
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
1717 selector
= gSpecialSelectors
[opmValue
];
1720 goto class_lookup
; // class_lookup:
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
;
1731 SetRaw(&g
->frame
->vars
[3], slotRawInt(&g
->frame
->vars
[3]) + 2); // inc i
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
1746 // Float-do : 143 17, 143 18
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
1755 selector
= gSpecialSelectors
[opmValue
];
1760 slotCopy(++sp
, &g
->receiver
);
1761 g
->sp
= sp
; g
->ip
= ip
;
1762 returnFromMethod(g
);
1763 sp
= g
->sp
; ip
= g
->ip
;
1768 SetRaw(&g
->frame
->vars
[2], slotRawFloat(&g
->frame
->vars
[2]) + 1.0); // inc i
1772 // Float-reverseDo : 143 19, 143 20, 143 21
1774 SetFloat(&g
->frame
->vars
[2], slotRawFloat(&g
->receiver
) - 1.0);
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
1784 selector
= gSpecialSelectors
[opmValue
];
1789 slotCopy(++sp
, &g
->receiver
);
1790 g
->sp
= sp
; g
->ip
= ip
;
1791 returnFromMethod(g
);
1792 sp
= g
->sp
; ip
= g
->ip
;
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
1802 case 22 : // ? question mark method
1808 case 23 : // if not nil push this and jump. used to implement ??
1810 jmplen
= (ip
[1]<<8) | ip
[2];
1819 jmplen
= (ip
[1]<<8) | ip
[2];
1826 case 25 : // ifNotNil
1828 jmplen
= (ip
[1]<<8) | ip
[2];
1835 case 26 : // ifNotNilPushNil
1837 jmplen
= (ip
[1]<<8) | ip
[2];
1839 slotCopy(sp
, &gSpecialValues
[svNil
]);
1845 case 27 : // ifNilPushNil
1847 jmplen
= (ip
[1]<<8) | ip
[2];
1855 obj
= slotRawObject(sp
);
1856 op2
= 1 + arrayAtIdentityHashInPairs(obj
, (sp
-1));
1858 ip
+= slotRawInt(&obj
->slots
[op2
]);
1861 // Number-forSeries : 143 29, 143 30, 143 31
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);
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]);
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]));
1884 bailFromNumberSeries
:
1885 error("Number-forSeries : first, second or last not an Integer or Float.\n");
1887 slotCopy(++sp
, &g
->receiver
);
1889 selector
= gSpecialSelectors
[opmPrimitiveFailed
];
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.);
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]));
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
1927 selector
= gSpecialSelectors
[opmValue
];
1932 slotCopy(++sp
, &g
->receiver
);
1933 g
->sp
= sp
; g
->ip
= ip
;
1934 returnFromMethod(g
);
1935 sp
= g
->sp
; ip
= g
->ip
;
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
1945 selector
= gSpecialSelectors
[opmValue
];
1950 slotCopy(++sp
, &g
->receiver
);
1951 g
->sp
= sp
; g
->ip
= ip
;
1952 returnFromMethod(g
);
1953 sp
= g
->sp
; ip
= g
->ip
;
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
1965 SetRaw(&vars
[4], slotRawFloat(&vars
[4]) + slotRawFloat(&vars
[1])); // inc i
1967 SetRaw(&vars
[5], slotRawInt(&vars
[5]) + 1); // inc j
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
:
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));
1993 // special case for this as only arg
1994 op2
= ip
[1]; ++ip
; // get selector index
1995 slotCopy(++sp
, &g
->receiver
);
1997 selector
= slotRawSymbol(&slotRawObject(&g
->block
->selectors
)->slots
[op2
]);
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;
2018 case 176 : // opcTailCallReturnFromFunction
2020 #if TAILCALLOPTIMIZE
2027 // special case for this as only arg
2028 op2
= ip
[1]; ++ip
; // get selector index
2029 slotCopy(++sp
, &g
->receiver
);
2031 selector
= slotRawSymbol(&slotRawObject(&g
->block
->selectors
)->slots
[op2
]);
2033 classobj
= slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->superclass
)->u
.classobj
;
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
;
2058 slotCopy(++sp
, &g
->receiver
);
2059 op2
= ip
[1]; ++ip
; // get selector index
2061 selector
= gSpecialSelectors
[op2
];
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;
2083 // opSendSpecialUnaryArithMsg
2087 SetFloat(sp
, -slotRawFloat(sp
));
2088 #if TAILCALLOPTIMIZE
2091 } else if (IsInt(sp
)) {
2092 SetRaw(sp
, -slotRawInt(sp
));
2093 #if TAILCALLOPTIMIZE
2097 handleSendSpecialUnaryArithMsg(g
, sp
, ip
, op1
);
2102 SetTagRaw(sp
, tagFalse
);
2103 #if TAILCALLOPTIMIZE
2106 } else if (IsFalse(sp
)) {
2107 SetTagRaw(sp
, tagTrue
);
2108 #if TAILCALLOPTIMIZE
2112 handleSendSpecialUnaryArithMsg(g
, sp
, ip
, op1
);
2114 case 210 : // opIsNil
2117 SetTagRaw(sp
, tagTrue
);
2119 slotCopy(sp
, &gSpecialValues
[svFalse
]);
2121 #if TAILCALLOPTIMIZE
2125 case 211 : // opNotNil
2128 slotCopy(sp
, &gSpecialValues
[svTrue
]);
2130 SetTagRaw(sp
, tagFalse
);
2132 #if TAILCALLOPTIMIZE
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
2166 if (IsInt(sp
- 1)) {
2168 --sp
; SetRaw(sp
, slotRawInt(sp
) + slotRawInt(sp
+ 1));
2169 #if TAILCALLOPTIMIZE
2173 g
->sp
= sp
; g
->ip
= ip
;
2174 g
->primitiveIndex
= opAdd
;
2176 sp
= g
->sp
; ip
= g
->ip
;
2179 g
->sp
= sp
; g
->ip
= ip
;
2180 g
->primitiveIndex
= opAdd
;
2182 sp
= g
->sp
; ip
= g
->ip
;
2185 case 225 : // subtract
2187 if (IsInt(sp
- 1)) {
2189 --sp
; SetRaw(sp
, slotRawInt(sp
) - slotRawInt(sp
+ 1));
2190 #if TAILCALLOPTIMIZE
2194 g
->sp
= sp
; g
->ip
= ip
;
2195 g
->primitiveIndex
= opSub
;
2197 sp
= g
->sp
; ip
= g
->ip
;
2200 g
->sp
= sp
; g
->ip
= ip
;
2201 g
->primitiveIndex
= opSub
;
2203 sp
= g
->sp
; ip
= g
->ip
;
2206 case 226 : // multiply
2208 if (IsInt(sp
- 1)) {
2210 --sp
; SetRaw(sp
, slotRawInt(sp
) * slotRawInt(sp
+ 1));
2211 #if TAILCALLOPTIMIZE
2215 g
->sp
= sp
; g
->ip
= ip
;
2216 g
->primitiveIndex
= opMul
;
2218 sp
= g
->sp
; ip
= g
->ip
;
2221 g
->sp
= sp
; g
->ip
= ip
;
2222 g
->primitiveIndex
= opMul
;
2224 sp
= g
->sp
; ip
= g
->ip
;
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
;
2258 --sp
; dispatch_opcode
; // opDrop
2261 ++sp
; *sp
= sp
[-1]; dispatch_opcode
; // opDup
2262 case 242 : // opcFunctionReturn
2264 g
->sp
= sp
; g
->ip
= ip
;
2266 sp
= g
->sp
; ip
= g
->ip
;
2268 case 243 : // opcReturn
2270 g
->sp
= sp
; g
->ip
= ip
;
2271 returnFromMethod(g
);
2272 sp
= g
->sp
; ip
= g
->ip
;
2274 case 244 : // opcReturnSelf
2276 slotCopy(++sp
, &g
->receiver
);
2277 g
->sp
= sp
; g
->ip
= ip
;
2278 returnFromMethod(g
);
2279 sp
= g
->sp
; ip
= g
->ip
;
2281 case 245 : // opcReturnTrue
2283 slotCopy(++sp
, &gSpecialValues
[svTrue
]);
2284 g
->sp
= sp
; g
->ip
= ip
;
2285 returnFromMethod(g
);
2286 sp
= g
->sp
; ip
= g
->ip
;
2288 case 246 : // opcReturnFalse
2290 slotCopy(++sp
, &gSpecialValues
[svFalse
]);
2291 g
->sp
= sp
; g
->ip
= ip
;
2292 returnFromMethod(g
);
2293 sp
= g
->sp
; ip
= g
->ip
;
2295 case 247 : // opcReturnNil
2297 slotCopy(++sp
, &gSpecialValues
[svNil
]);
2298 g
->sp
= sp
; g
->ip
= ip
;
2299 returnFromMethod(g
);
2300 sp
= g
->sp
; ip
= g
->ip
;
2303 case 248 : // opcJumpIfFalse
2305 // cannot compare with o_false because it is NaN
2306 if ( IsFalse(sp
) ) {
2307 jmplen
= (ip
[1]<<8) | ip
[2];
2309 } else if ( IsTrue(sp
)) {
2313 selector
= gSpecialSelectors
[opmNonBooleanError
];
2320 case 249 : // opcJumpIfFalsePushNil
2323 jmplen
= (ip
[1]<<8) | ip
[2];
2325 slotCopy(sp
, &gSpecialValues
[svNil
]);
2326 } else if ( IsTrue(sp
)) {
2331 selector
= gSpecialSelectors
[opmNonBooleanError
];
2337 case 250 : // opcJumpIfFalsePushFalse
2340 jmplen
= (ip
[1]<<8) | ip
[2];
2343 } else if (IsTrue(sp
)) {
2348 selector
= gSpecialSelectors
[opmNonBooleanError
];
2354 case 251 : // opcJumpIfTruePushTrue
2359 } else if (IsTrue(sp
)) {
2360 jmplen
= (ip
[1]<<8) | ip
[2];
2362 slotCopy(sp
, &gSpecialValues
[svTrue
]);
2365 selector
= gSpecialSelectors
[opmNonBooleanError
];
2371 case 252 : // opcJumpFwd
2373 jmplen
= (ip
[1]<<8) | ip
[2];
2376 case 253 : // opcJumpBak
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];
2383 //assert(g->gc->SanityCheck());
2385 case 254 : // opcSpecialBinaryOpWithAdverb
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
;
2393 case 255 : // opcTailCallReturnFromMethod
2395 #if TAILCALLOPTIMIZE
2400 ////////////////////////////////////
2403 // normal class lookup
2404 classobj
= classOfSlot(slot
);
2406 // message sends handled here:
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
;
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
;
2424 case methReturnSelf
: /* return self */
2425 sp
-= numArgsPushed
- 1;
2427 case methReturnLiteral
: /* return literal */
2428 sp
-= numArgsPushed
- 1;
2429 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
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
);
2437 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
2440 case methReturnInstVar
: /* return inst var */
2441 sp
-= numArgsPushed
- 1;
2442 index
= methraw
->specialIndex
;
2443 slotCopy(sp
, &slotRawObject(slot
)->slots
[index
]);
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
); }
2451 if (numArgsPushed
>= 2) {
2452 slotCopy(&obj
->slots
[index
], sp
+ 1);
2453 g
->gc
->GCWrite(obj
, sp
+ 1);
2455 slotCopy(&obj
->slots
[index
], &gSpecialValues
[svNil
]);
2460 case methReturnClassVar
: /* return class var */
2461 sp
-= numArgsPushed
- 1;
2462 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
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);
2470 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], &gSpecialValues
[svNil
]);
2473 case methRedirect
: /* send a different selector to self */
2474 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
2475 /* push default arg values */
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
);
2484 case methRedirectSuper
: /* send a different selector to self */
2485 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
2486 /* push default arg values */
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
;
2496 case methForwardInstVar
: /* forward to an instance variable */
2497 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
2498 /* push default arg values */
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
);
2512 case methForwardClassVar
: /* forward to an instance variable */
2513 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
2514 /* push default arg values */
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
);
2527 case methPrimitive
: /* primitive */
2528 g
->sp
= sp
; g
->ip
= ip
;
2529 doPrimitive(g
, meth
, numArgsPushed
);
2530 sp
= g
->sp
; ip
= g
->ip
;
2532 } // switch (meth->methType)
2533 } // end handle message
2534 #if TAILCALLOPTIMIZE
2539 ////////////////////////////////////
2542 // normal class lookup
2543 classobj
= classOfSlot(slot
);
2545 // message sends handled here:
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
;
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
;
2563 case methReturnSelf
: /* return self */
2564 sp
-= numArgsPushed
- 1;
2566 case methReturnLiteral
: /* return literal */
2567 sp
-= numArgsPushed
- 1;
2568 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
2570 case methReturnArg
: /* return an argument */
2572 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
2573 numKeyArgsPushed
= 0;
2575 sp
-= numArgsPushed
- 1;
2576 index
= methraw
->specialIndex
; // zero is index of the first argument
2577 if (index
< numArgsPushed
) {
2578 slotCopy(sp
, sp
+ index
);
2580 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
2583 case methReturnInstVar
: /* return inst var */
2584 sp
-= numArgsPushed
- 1;
2585 index
= methraw
->specialIndex
;
2586 slotCopy(sp
, &slotRawObject(slot
)->slots
[index
]);
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
); }
2595 if (numArgsPushed
>= 2) {
2596 slotCopy(&obj
->slots
[index
], sp
+ 1);
2597 g
->gc
->GCWrite(obj
, sp
+ 1);
2599 slotCopy(&obj
->slots
[index
], &gSpecialValues
[svNil
]);
2603 case methReturnClassVar
: /* return class var */
2604 sp
-= numArgsPushed
- 1;
2605 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
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);
2613 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], &gSpecialValues
[svNil
]);
2616 case methRedirect
: /* send a different selector to self, e.g. this.subclassResponsibility */
2618 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
2619 numKeyArgsPushed
= 0;
2621 selector
= slotRawSymbol(&meth
->selectors
);
2624 case methRedirectSuper
: /* send a different selector to super */
2626 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
2627 numKeyArgsPushed
= 0;
2629 selector
= slotRawSymbol(&meth
->selectors
);
2631 classobj
= slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->superclass
)->u
.classobj
;
2634 case methForwardInstVar
: /* forward to an instance variable */
2636 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
2637 numKeyArgsPushed
= 0;
2639 selector
= slotRawSymbol(&meth
->selectors
);
2640 index
= methraw
->specialIndex
;
2641 slotCopy(slot
, &slotRawObject(slot
)->slots
[index
]);
2643 classobj
= classOfSlot(slot
);
2646 case methForwardClassVar
: /* forward to an instance variable */
2648 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
2649 numKeyArgsPushed
= 0;
2651 selector
= slotRawSymbol(&meth
->selectors
);
2652 slotCopy(slot
, &g
->classvars
->slots
[methraw
->specialIndex
]);
2654 classobj
= classOfSlot(slot
);
2657 case methPrimitive
: /* primitive */
2658 g
->sp
= sp
; g
->ip
= ip
;
2659 doPrimitiveWithKeys(g
, meth
, numArgsPushed
, numKeyArgsPushed
);
2660 sp
= g
->sp
; ip
= g
->ip
;
2662 } // switch (meth->methType)
2663 } // end handle message
2664 numKeyArgsPushed
= 0;
2665 #if TAILCALLOPTIMIZE
2670 } // end while(running)
2672 running
= true; // reset the signal
2674 g
->sp
= sp
; g
->ip
= ip
;
2677 void DumpSimpleBackTrace(VMGlobals
*g
);
2678 void DumpSimpleBackTrace(VMGlobals
*g
)
2683 post("CALL STACK:\n");
2684 // print the variables and arguments for the most recent frames in the
2688 for (i
=0; i
<16; ++i
) {
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
);
2695 if (frame
) { post("...\n"); }
2696 //DumpStack(g, g->sp);
2699 void DumpBackTrace(VMGlobals
*g
)
2704 post("CALL STACK:\n");
2705 // print the variables and arguments for the most recent frames in the
2709 for (i
=0; i
<16; ++i
) {
2710 if (FrameSanity(frame
, "DumpBackTrace")) {
2711 post("FRAME CORRUPTED\n");
2715 frame
= slotRawFrame(&frame
->caller
);
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
)
2729 post("CALL STACK:\n");
2730 // print the variables and arguments for the most recent frames in the
2734 for (i
=0; i
<16; ++i
) {
2735 if (FrameSanity(frame
, "DumpDetailedBackTrace")) {
2736 post("FRAME CORRUPTED\n");
2739 DumpDetailedFrame(frame
);
2740 frame
= slotRawFrame(&frame
->caller
);
2743 if (frame
) { post("...\n"); }
2744 //DumpStack(g, g->sp);
2747 void DumpStack(VMGlobals
*g
, PyrSlot
*sp
)
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
);