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