sclang: array primitives - respect mutability when changing object.
[supercollider.git] / lang / LangSource / dumpByteCodes.cpp
blobb121e2fb0ca06a9ff63b9082598dc72363eb5bd8
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "PyrKernel.h"
22 #include "PyrParseNode.h"
23 #include "PyrSymbol.h"
24 #include "SCBase.h"
26 void numBlockTemps(PyrBlock *block, long level, long *numArgNames, long *numVarNames);
27 void numBlockTemps(PyrBlock *block, long level, long *numArgNames, long *numVarNames)
29 long i;
30 for (i=0; i<level; ++i) {
31 block = slotRawBlock(&block->contextDef);
33 *numArgNames = slotRawSymbolArray(&block->argNames) ? slotRawSymbolArray(&block->argNames)->size : 0;
34 *numVarNames = slotRawSymbolArray(&block->varNames) ? slotRawSymbolArray(&block->varNames)->size : 0;
37 unsigned char* dumpOneByteCode(PyrBlock *theBlock, PyrClass* theClass, unsigned char *ip);
38 unsigned char* dumpOneByteCode(PyrBlock *theBlock, PyrClass* theClass, unsigned char *ip)
40 PyrClass *classobj;
41 PyrBlock *block;
42 PyrSlot *slot;
43 PyrSymbol *selector;
44 char str[256];
45 long op1, op2, op3, op4, op5;
46 long i, n, ival, jmplen;
47 long numArgNames, numVarNames, numTemps;
48 unsigned char *ipbeg;
50 if (theClass == NULL) {
51 block = theBlock;
52 theClass = 0;
53 while (block) {
54 //dumpObject((PyrObject*)block);
55 //post("block->classptr %d class_method %d %d\n",
56 // block->classptr, class_method, isKindOf((PyrObject*)block, class_method));
57 //if (block->classptr == class_method) {
58 if (isKindOf((PyrObject*)block, class_method)) {
59 theClass = slotRawClass(&((PyrMethod*)block)->ownerclass);
60 break;
62 block = slotRawBlock(&block->contextDef);
64 if (theClass == NULL) {
65 theClass = s_interpreter->u.classobj;
66 //error("dumpByteCodes: no Class found.\n");
67 //return NULL;
70 ipbeg = slotRawInt8Array(&theBlock->code)->b;
71 n = ip - ipbeg;
72 op1 = *ip++;
73 post("%3d %02X", n, op1);
74 switch (op1) {
75 case 0 : // push class
76 op2 = *ip++; // get literal index
77 post(" %02X PushClassX '%s'\n", op2,
78 slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2])->name);
79 break;
80 case 1 : // Extended, PushInstVar
81 op2 = *ip++; // get inst var index
82 post(" %02X PushInstVarX '%s'\n", op2,
83 slotRawSymbolArray(&theClass->instVarNames)->symbols[op2]->name);
84 break;
85 case 2 : // Extended, PushTempVar
86 op2 = *ip++; // get temp var level
88 block = theBlock;
89 for (i=op2; i--; block = slotRawBlock(&block->contextDef)) { /* noop */ }
90 numArgNames = slotRawSymbolArray(&block->argNames) ? slotRawSymbolArray(&block->argNames)->size : 0;
91 numVarNames = slotRawSymbolArray(&block->varNames) ? slotRawSymbolArray(&block->varNames)->size : 0;
92 numTemps = numArgNames + numVarNames;
94 op3 = numTemps - *ip++ - 1; // get temp var index
95 if (op3 < numArgNames) {
96 post(" %02X %02X PushTempVarX '%s'\n", op2, op3,
97 slotRawSymbolArray(&block->argNames)->symbols[op3]->name);
98 } else {
99 post(" %02X %02X PushTempVarX '%s'\n", op2, op3,
100 slotRawSymbolArray(&block->varNames)->symbols[op3-numArgNames]->name);
102 break;
103 case 3 : // Extended, PushTempZeroVar
105 block = theBlock;
106 numArgNames = slotRawSymbolArray(&block->argNames) ? slotRawSymbolArray(&block->argNames)->size : 0;
107 numVarNames = slotRawSymbolArray(&block->varNames) ? slotRawSymbolArray(&block->varNames)->size : 0;
108 numTemps = numArgNames + numVarNames;
110 op2 = numTemps - *ip++ - 1; // get temp var index
111 if (op2 < numArgNames) {
112 post(" %02X PushTempZeroVarX '%s'\n", op2,
113 slotRawSymbolArray(&theBlock->argNames)->symbols[op2]->name);
114 } else {
115 post(" %02X PushTempZeroVarX '%s'\n", op2,
116 slotRawSymbolArray(&theBlock->varNames)->symbols[op2-numArgNames]->name);
118 break;
119 case 4 : // Extended, PushLiteral
120 op2 = *ip++; // get literal index
121 // push a block if it is one
122 slot = slotRawObject(&theBlock->selectors)->slots + op2;
123 slotString(slot, str);
124 post(" %02X PushLiteralX %s\n", op2, str);
125 break;
126 case 5 : // Extended, PushClassVar
127 op2 = *ip++; // get class var literal index
128 op3 = *ip++; // get class var index
129 post(" %02X %02X PushClassVarX\n", op2, op3);
130 break;
131 case 6 : // Extended, PushSpecialValue == push a special class
132 op2 = *ip++; // get class name index
133 classobj = gSpecialClasses[op2]->u.classobj;
134 post(" %02X PushSpecialClass '%s'\n", op2,
135 slotRawSymbol(&classobj->name)->name);
136 break;
137 case 7 : // Extended, StoreInstVar
138 op2 = *ip++; // get inst var index
139 post(" %02X StoreInstVarX '%s'\n", op2,
140 slotRawSymbolArray(&theClass->instVarNames)->symbols[op2]->name);
141 break;
142 case 8 : // Extended, StoreTempVar
143 op2 = *ip++; // get temp var level
145 block = theBlock;
146 for (i=op2; i--; block = slotRawBlock(&block->contextDef)) { /* noop */ }
147 numArgNames = slotRawSymbolArray(&block->argNames) ? slotRawSymbolArray(&block->argNames)->size : 0;
148 numVarNames = slotRawSymbolArray(&block->varNames) ? slotRawSymbolArray(&block->varNames)->size : 0;
149 numTemps = numArgNames + numVarNames;
151 op3 = *ip++; // get temp var index
152 if (op3 < numArgNames) {
153 post(" %02X %02X StoreTempVarX '%s'\n", op2, op3,
154 slotRawSymbolArray(&block->argNames)->symbols[op3]->name);
155 } else {
156 post(" %02X %02X StoreTempVarX '%s'\n", op2, op3,
157 slotRawSymbolArray(&block->varNames)->symbols[op3-numArgNames]->name);
159 break;
160 case 9 : // Extended, StoreClassVar
161 op2 = *ip++; // get class var literal index
162 op3 = *ip++; // get class var index
163 post(" %02X %02X StoreClassVarX\n", op2, op3);
164 break;
165 case 10 : // Extended, SendMsg
166 op2 = *ip++; // get num args
167 op3 = *ip++; // get num key args
168 op4 = *ip++; // get selector index
169 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op4]);
170 post(" %02X %02X %02X SendMsgX '%s'\n", op2, op3, op4, selector->name);
171 break;
172 case 11 : // Extended, SuperMsg
173 op2 = *ip++; // get num args
174 op3 = *ip++; // get num key args
175 op4 = *ip++; // get selector index
176 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op4]);
177 post(" %02X %02X %02X SuperMsgX '%s'\n", op2, op3, op4, selector->name);
178 break;
179 case 12 : // Extended, SendSpecialMsg
180 op2 = *ip++; // get num args
181 op3 = *ip++; // get num key args
182 op4 = *ip++; // get selector index
183 post(" %02X %02X %02X SendSpecialMsgX '%s'\n", op2, op3, op4,
184 gSpecialSelectors[op4]->name);
185 break;
186 case 13 : // Extended, SendSpecialUnaryArithMsg
187 op2 = *ip++; // get selector index
188 post(" %02X SendSpecialUnaryArithMsgX '%s'\n", op2,
189 gSpecialUnarySelectors[op2]->name);
190 break;
191 case 14 : // Extended, SendSpecialBinaryArithMsg
192 op2 = *ip++; // get selector index
193 post(" %02X SendSpecialBinaryArithMsgX '%s'\n", op2,
194 gSpecialBinarySelectors[op2]->name);
195 break;
196 case 15 : // Extended, SpecialOpcode (none yet)
197 op2 = *ip++; // get extended special opcode
198 switch (op2) {
199 case opgProcess : // push thisProcess
200 post(" %02X opgProcess\n", op1, op2); break;
201 case opgThread : // push thisThread
202 post(" %02X opgThread\n", op1, op2); break;
203 case opgMethod : // push thisMethod
204 post(" %02X opgMethod\n", op1, op2); break;
205 case opgFunctionDef : // push thisBlock
206 post(" %02X opgFunctionDef\n", op1, op2); break;
207 case opgFunction : // push thisClosure
208 post(" %02X opgFunction\n", op1, op2); break;
210 break;
212 // PushInstVar, 0..15
213 case 16 : case 17 : case 18 : case 19 :
214 case 20 : case 21 : case 22 : case 23 :
215 case 24 : case 25 : case 26 : case 27 :
216 case 28 : case 29 : case 30 : case 31 :
217 post(" PushInstVar '%s'\n",
218 slotRawSymbolArray(&theClass->instVarNames)->symbols[op1&15]->name);
219 break;
221 case 32 :
222 op2 = *ip++;
223 op3 = *ip++;
224 jmplen = (op2<<8) | op3;
225 post(" %02X %02X JumpIfTrue %d (%d)\n", op2, op3, jmplen, n + jmplen + 3);
226 break;
228 case 33 : case 34 : case 35 :
229 case 36 : case 37 : case 38 : case 39 :
230 op2 = op1 & 15; // get temp var level
232 block = theBlock;
233 for (i=op2; i--; block = slotRawBlock(&block->contextDef)) { /* noop */ }
234 numArgNames = slotRawSymbolArray(&block->argNames) ? slotRawSymbolArray(&block->argNames)->size : 0;
235 numVarNames = slotRawSymbolArray(&block->varNames) ? slotRawSymbolArray(&block->varNames)->size : 0;
236 numTemps = numArgNames + numVarNames;
238 op3 = numTemps - *ip++ - 1; // get temp var index
239 if (op3 >= 0 && op3 < numArgNames) {
240 post(" %02X PushTempVar '%s'\n", op3,
241 slotRawSymbolArray(&block->argNames)->symbols[op3]->name);
242 } else if (op3 >= 0) {
243 post(" %02X PushTempVar '%s'\n", op3,
244 slotRawSymbolArray(&block->varNames)->symbols[op3-numArgNames]->name);
246 break;
248 case 40 :
249 op5 = *ip++;
250 ival = op5;
251 slot = slotRawObject(&theBlock->constants)->slots + ival;
252 slotString(slot, str);
253 post(" %02X PushConstant %s\n", op5, str);
254 break;
256 case 41 :
257 op4 = *ip++;
258 op5 = *ip++;
259 ival = (op4 << 8) | op5;
260 slot = slotRawObject(&theBlock->constants)->slots + ival;
261 slotString(slot, str);
262 post(" %02X %02X PushConstant %s\n", op4, op5, str);
263 break;
265 case 42 :
266 op3 = *ip++;
267 op4 = *ip++;
268 op5 = *ip++;
269 ival = (op3 << 16) | (op4 << 8) | op5;
270 slot = slotRawObject(&theBlock->constants)->slots + ival;
271 slotString(slot, str);
272 post(" %02X %02X %02X PushConstant %s\n", op3, op4, op5, str);
273 break;
275 case 43 :
276 op2 = *ip++;
277 op3 = *ip++;
278 op4 = *ip++;
279 op5 = *ip++;
280 ival = (op2 << 24) | (op3 << 16) | (op4 << 8) | op5;
281 slot = slotRawObject(&theBlock->constants)->slots + ival;
282 slotString(slot, str);
283 post(" %02X %02X %02X %02X PushConstant %s\n", op2, op3, op4, op5, str);
284 break;
286 case 44 :
287 op5 = *ip++;
288 ival = (int32)(op5 << 24) >> 24;
289 post(" %02X PushInt %d\n", op5, ival);
290 break;
292 case 45 :
293 op4 = *ip++;
294 op5 = *ip++;
295 ival = (int32)((op4 << 24) | (op5 << 16)) >> 16;
296 post(" %02X %02X PushInt %d\n", op4, op5, ival);
297 break;
299 case 46 :
300 op3 = *ip++;
301 op4 = *ip++;
302 op5 = *ip++;
303 ival = (int32)((op3 << 24) | (op4 << 16) | (op5 << 8)) >> 8;
304 post(" %02X %02X %02X PushInt %d\n", op3, op4, op5, ival);
305 break;
307 case 47 :
308 op2 = *ip++;
309 op3 = *ip++;
310 op4 = *ip++;
311 op5 = *ip++;
312 ival = (int32)((op2 << 24) | (op3 << 16) | (op4 << 8) | op5);
313 post(" %02X %02X %02X %02X PushInt %d\n", op2, op3, op4, op5, ival);
314 break;
316 case 48 : case 49 : case 50 : case 51 :
317 case 52 : case 53 : case 54 : case 55 :
318 case 56 : case 57 : case 58 : case 59 :
319 case 60 : case 61 : case 62 : case 63 :
320 op2 = op1 & 15; // get temp var index
322 block = theBlock;
323 numArgNames = slotRawSymbolArray(&block->argNames) ? slotRawSymbolArray(&block->argNames)->size : 0;
324 numVarNames = slotRawSymbolArray(&block->varNames) ? slotRawSymbolArray(&block->varNames)->size : 0;
325 numTemps = numArgNames + numVarNames;
327 if (op2 < numArgNames) {
328 post(" PushTempZeroVar '%s'\n",
329 slotRawSymbolArray(&theBlock->argNames)->symbols[op2]->name);
330 } else {
331 post(" PushTempZeroVar '%s'\n",
332 slotRawSymbolArray(&theBlock->varNames)->symbols[op2-numArgNames]->name);
334 break;
336 case 64 : case 65 : case 66 : case 67 :
337 case 68 : case 69 : case 70 : case 71 :
338 case 72 : case 73 : case 74 : case 75 :
339 case 76 : case 77 : case 78 : case 79 :
340 op2 = op1 & 15; // get temp var level
341 slot = slotRawObject(&theBlock->constants)->slots + op2;
342 slotString(slot, str);
343 post(" PushLiteral %s\n", str);
344 break;
346 // PushClassVar
347 case 80 : case 81 : case 82 : case 83 :
348 case 84 : case 85 : case 86 : case 87 :
349 case 88 : case 89 : case 90 : case 91 :
350 case 92 : case 93 : case 94 : case 95 :
351 op2 = op1 & 15;
352 op3 = *ip++; // get class var index
353 post(" %02X %02X PushClassVar\n", op2, op3);
354 break;
356 // PushSpecialValue
357 case 96 : post(" PushSpecialValue this\n"); break;
358 case 97 : post(" PushOneAndSubtract\n"); break;
359 case 98 : post(" PushSpecialValue -1\n"); break;
360 case 99 : post(" PushSpecialValue 0\n"); break;
361 case 100 : post(" PushSpecialValue 1\n"); break;
362 case 101 : post(" PushSpecialValue 2\n"); break;
363 case 102 : post(" PushSpecialValue 0.5\n"); break;
364 case 103 : post(" PushSpecialValue -1.0\n"); break;
365 case 104 : post(" PushSpecialValue 0.0\n"); break;
366 case 105 : post(" PushSpecialValue 1.0\n"); break;
367 case 106 : post(" PushSpecialValue 2.0\n"); break;
368 case 107 : post(" PushOneAndAdd\n"); break;
369 case 108 : post(" PushSpecialValue true\n"); break;
370 case 109 : post(" PushSpecialValue false\n"); break;
371 case 110 : post(" PushSpecialValue nil\n"); break;
372 case 111 : post(" PushSpecialValue 'end'\n"); break;
374 // StoreInstVar, 0..15
375 case 112 : case 113 : case 114 : case 115 :
376 case 116 : case 117 : case 118 : case 119 :
377 case 120 : case 121 : case 122 : case 123 :
378 case 124 : case 125 : case 126 : case 127 :
379 post(" StoreInstVar '%s'\n",
380 slotRawSymbolArray(&theClass->instVarNames)->symbols[op1 & 15]->name);
381 break;
383 // StoreTempVar
384 case 128 : case 129 : case 130 : case 131 :
385 case 132 : case 133 : case 134 : case 135 :
386 op2 = op1 & 15; // get temp var level
388 block = theBlock;
389 for (i=op2; i--; block = slotRawBlock(&block->contextDef)) { /* noop */ }
390 numArgNames = slotRawSymbolArray(&block->argNames) ? slotRawSymbolArray(&block->argNames)->size : 0;
391 numVarNames = slotRawSymbolArray(&block->varNames) ? slotRawSymbolArray(&block->varNames)->size : 0;
392 numTemps = numArgNames + numVarNames;
394 op3 = *ip++; // get temp var index
395 if (op3 < numArgNames) {
396 post(" %02X StoreTempVar '%s'\n", op3,
397 slotRawSymbolArray(&block->argNames)->symbols[op3]->name);
398 } else {
399 post(" %02X StoreTempVar '%s'\n", op3,
400 slotRawSymbolArray(&block->varNames)->symbols[op3-numArgNames]->name);
402 break;
403 case 136 :
404 op2 = *ip++; // get inst var index
405 op3 = *ip++; // get selector index
406 selector = gSpecialSelectors[op3];
407 post(" %02X %02X PushInstVarAndSendSpecialMsg '%s' '%s'\n", op2, op3,
408 slotRawSymbolArray(&theClass->instVarNames)->symbols[op2]->name, selector->name);
409 break;
410 case 137 :
411 op2 = *ip++; // get selector index
412 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2]);
413 post(" %02X PushAllArgs+SendMsg '%s'\n",
414 op2, selector->name);
415 break;
416 case 138 :
417 op2 = *ip++; // get selector index
418 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2]);
419 post(" %02X PushAllButFirstArg+SendMsg '%s'\n",
420 op2, selector->name);
421 break;
422 case 139 :
423 op2 = *ip++; // get selector index
424 selector = gSpecialSelectors[op2];
425 post(" %02X PushAllArgs+SendSpecialMsg '%s'\n",
426 op2, selector->name);
427 break;
428 case 140 :
429 op2 = *ip++; // get selector index
430 selector = gSpecialSelectors[op2];
431 post(" %02X PushAllButFirstArg+SendSpecialMsg '%s'\n",
432 op2, selector->name);
433 break;
434 case 141 :
435 op2 = *ip++; // get selector index
436 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2]);
437 post(" %02X PushAllButFirstTwoArgs+SendMsg '%s'\n",
438 op2, selector->name);
439 break;
440 case 142 :
441 op2 = *ip++; // get selector index
442 selector = gSpecialSelectors[op2];
443 post(" %02X PushAllButFirstTwoArgs+SendSpecialMsg '%s'\n",
444 op2, selector->name);
445 break;
446 case 143 :
447 op2 = *ip++; // get loop opcode
448 if (op2 < 23 || op2 > 27) {
449 post(" %02X ControlOpcode\n", op2); break;
450 } else {
451 op3 = *ip++; // jump
452 op4 = *ip++; // jump
453 jmplen = ((op3 & 0xFF)<<8) | (op4 & 0xFF);
454 post(" %02X %02X %02X ControlOpcode %d (%d)\n", op2, op3, op4, jmplen, n + jmplen + 3); break;
456 break;
458 // StoreClassVar
459 case 144 : case 145 : case 146 : case 147 :
460 case 148 : case 149 : case 150 : case 151 :
461 case 152 : case 153 : case 154 : case 155 :
462 case 156 : case 157 : case 158 : case 159 :
463 op2 = op1 & 15;
464 op3 = *ip++; // get class var index
465 post(" %02X StoreClassVar\n", op3);
466 break;
468 // SendMsg
469 case 160 : case 161 : case 162 : case 163 :
470 case 164 : case 165 : case 166 : case 167 :
471 case 168 : case 169 : case 170 : case 171 :
472 case 172 : case 173 : case 174 : case 175 :
473 op2 = *ip++; // get selector index
474 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2]);
475 post(" %02X SendMsg '%s'\n", op2, selector->name);
476 break;
478 // TailCallReturnFromFunction
479 case 176 :
480 post(" TailCallReturnFromFunction\n");
481 break;
483 // SuperMsg
484 case 177 : case 178 : case 179 :
485 case 180 : case 181 : case 182 : case 183 :
486 case 184 : case 185 : case 186 : case 187 :
487 case 188 : case 189 : case 190 : case 191 :
488 op2 = *ip++; // get selector index
489 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2]);
490 post(" %02X SuperMsg '%s'\n", op2, selector->name);
491 break;
493 // SendSpecialMsg
494 case 192 : case 193 : case 194 : case 195 :
495 case 196 : case 197 : case 198 : case 199 :
496 case 200 : case 201 : case 202 : case 203 :
497 case 204 : case 205 : case 206 : case 207 :
498 op2 = *ip++; // get selector index
499 selector = gSpecialSelectors[op2];
500 post(" %02X SendSpecialMsg '%s'\n", op2, selector->name);
501 break;
503 // SendSpecialUnaryArithMsg
504 case 208 : case 209 : case 210 : case 211 :
505 case 212 : case 213 : case 214 : case 215 :
506 case 216 : case 217 : case 218 : case 219 :
507 case 220 : case 221 : case 222 : case 223 :
508 op2 = op1 & 15;
509 selector = gSpecialUnarySelectors[op2];
510 post(" SendSpecialUnaryArithMsg '%s'\n", selector->name);
511 break;
513 // SendSpecialBinaryArithMsg
514 case 224 : case 225 : case 226 : case 227 :
515 case 228 : case 229 : case 230 : case 231 :
516 case 232 : case 233 : case 234 : case 235 :
517 case 236 : case 237 : case 238 : case 239 :
518 op2 = op1 & 15;
519 selector = gSpecialBinarySelectors[op2];
520 post(" SendSpecialBinaryArithMsg '%s'\n", selector->name);
521 break;
523 // SpecialOpcodes
524 case 240 : post(" Drop\n"); break;
525 case 241 : post(" Dup\n"); break; // Dup
527 case 242 : post(" BlockReturn\n"); break; // BlockReturn
528 case 243 : post(" Return\n"); break; // Return
529 case 244 : post(" ReturnSelf\n"); break; // ReturnSelf
530 case 245 : post(" ReturnTrue\n"); break; // ReturnTrue
531 case 246 : post(" ReturnFalse\n"); break; // ReturnFalse
532 case 247 : post(" ReturnNil\n"); break; // ReturnNil
534 case 248 : // JumpIfFalse
535 op2 = *ip++;
536 op3 = *ip++;
537 jmplen = (op2<<8) | op3;
538 post(" %02X %02X JumpIfFalse %d (%d)\n", op2, op3, jmplen, n + jmplen + 3);
539 break;
540 case 249 : // JumpIfFalsePushNil
541 op2 = *ip++;
542 op3 = *ip++;
543 jmplen = ((op2 & 0xFF)<<8) | (op3 & 0xFF);
544 post(" %02X %02X JumpIfFalsePushNil %d (%d)\n", op2, op3, jmplen, n + jmplen + 3);
545 break;
546 case 250 : // JumpIfFalsePushFalse
547 op2 = *ip++;
548 op3 = *ip++;
549 jmplen = (op2<<8) | op3;
550 post(" %02X %02X JumpIfFalsePushFalse %d (%d)\n", op2, op3, jmplen, n + jmplen + 3);
551 break;
552 case 251 : // JumpIfTruePushTrue
553 op2 = *ip++;
554 op3 = *ip++;
555 jmplen = (op2<<8) | op3;
556 post(" %02X %02X JumpIfTruePushTrue %d (%d)\n", op2, op3, jmplen, n + jmplen + 3);
557 break;
558 case 252 : // JumpFwd
559 op2 = *ip++;
560 op3 = *ip++;
561 jmplen = (op2<<8) | op3;
562 post(" %02X %02X JumpFwd %d (%d)\n", op2, op3, jmplen, n + jmplen + 3);
563 break;
564 case 253 : // JumpBak
565 op2 = *ip++;
566 op3 = *ip++;
567 jmplen = (op2<<8) | op3;
568 post(" %02X %02X JumpBak %d (%d)\n", op2, op3, jmplen, n - jmplen + 1);
569 break;
570 case 254 :
571 op2 = *ip++;
572 post(" %02X SpecialBinaryOpWithAdverb\n", op2);
573 break;
574 case 255 :
575 post(" TailCallReturnFromMethod\n");
576 break;
578 return ip;
583 bool detectSendSelector(PyrBlock *theBlock, PyrClass* theClass, unsigned char **ipp, PyrSymbol *testSelector);
584 bool detectSendSelector(PyrBlock *theBlock, PyrClass* theClass, unsigned char **ipp, PyrSymbol *testSelector)
586 PyrBlock *block;
587 PyrSymbol *selector = 0;
588 long op1, op2, op3, op4, op5, op6;
589 unsigned char *ip = *ipp;
590 if (theClass == NULL) {
591 block = theBlock;
592 theClass = 0;
593 while (block) {
594 if (isKindOf((PyrObject*)block, class_method)) {
595 theClass = slotRawClass(&((PyrMethod*)block)->ownerclass);
596 break;
598 block = slotRawBlock(&block->contextDef);
600 if (theClass == NULL) {
601 theClass = s_interpreter->u.classobj;
604 op1 = *ip++;
605 switch (op1) {
606 case 0 : // push class
607 op2 = *ip++; // get literal index
608 break;
609 case 1 : // Extended, PushInstVar
610 op2 = *ip++; // get inst var index
611 break;
612 case 2 : // Extended, PushTempVar
613 op2 = *ip++; // get temp var level
614 op3 = *ip++; // get temp var index
615 break;
616 case 3 : // Extended, PushTempZeroVar
617 op2 = *ip++; // get temp var level
618 break;
619 case 4 : // Extended, PushLiteral
620 op2 = *ip++; // get literal index
621 break;
622 case 5 : // Extended, PushClassVar
623 op2 = *ip++; // get class var literal index
624 op3 = *ip++; // get class var index
625 break;
626 case 6 : // Extended, PushSpecialValue == push a special class
627 op2 = *ip++; // get class name index
628 break;
629 case 7 : // Extended, StoreInstVar
630 op2 = *ip++; // get inst var index
631 break;
632 case 8 : // Extended, StoreTempVar
633 op2 = *ip++; // get temp var level
634 op3 = *ip++; // get class var index
635 break;
636 case 9 : // Extended, StoreClassVar
637 op2 = *ip++; // get class var literal index
638 op3 = *ip++; // get class var index
639 break;
640 case 10 : // Extended, SendMsg
641 op2 = *ip++; // get num args
642 op3 = *ip++; // get num key args
643 op4 = *ip++; // get selector index
644 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op4]);
645 break;
646 case 11 : // Extended, SuperMsg
647 op2 = *ip++; // get num args
648 op3 = *ip++; // get num key args
649 op4 = *ip++; // get selector index
650 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op4]);
651 break;
652 case 12 : // Extended, SendSpecialMsg
653 op2 = *ip++; // get num args
654 op3 = *ip++; // get num key args
655 op4 = *ip++; // get selector index
656 selector = gSpecialSelectors[op4];
657 break;
658 case 13 : // Extended, SendSpecialUnaryArithMsg
659 op2 = *ip++; // get selector index
660 selector = gSpecialUnarySelectors[op2];
661 break;
662 case 14 : // Extended, SendSpecialBinaryArithMsg
663 op2 = *ip++; // get selector index
664 selector = gSpecialBinarySelectors[op2];
665 break;
666 case 15 : // Extended, SpecialOpcode (none yet)
667 op2 = *ip++; // get extended special opcode
668 break;
670 // PushInstVar, 0..15
671 case 16 : case 17 : case 18 : case 19 :
672 case 20 : case 21 : case 22 : case 23 :
673 case 24 : case 25 : case 26 : case 27 :
674 case 28 : case 29 : case 30 : case 31 :
675 break;
676 case 32 : case 33 : case 34 : case 35 :
677 case 36 : case 37 : case 38 : case 39 :
678 case 40 : case 41 : case 42 : case 43 :
679 case 44 : case 45 : case 46 : case 47 :
680 op2 = op1 & 15; // get temp var level
681 op3 = *ip++; // get num key args
682 break;
684 case 48 : case 49 : case 50 : case 51 :
685 case 52 : case 53 : case 54 : case 55 :
686 case 56 : case 57 : case 58 : case 59 :
687 case 60 : case 61 : case 62 : case 63 :
688 break;
690 case 64 : case 65 : case 66 : case 67 :
691 case 68 : case 69 : case 70 : case 71 :
692 case 72 : case 73 : case 74 : case 75 :
693 case 76 : case 77 : case 78 : case 79 :
694 break;
696 // PushClassVar
697 case 80 : case 81 : case 82 : case 83 :
698 case 84 : case 85 : case 86 : case 87 :
699 case 88 : case 89 : case 90 : case 91 :
700 case 92 : case 93 : case 94 : case 95 :
701 op2 = op1 & 15;
702 op3 = *ip++; // get class var index
703 break;
705 // PushSpecialValue
706 case 96 : case 97 : case 98 : case 99 :
707 case 100 : case 101 : case 102 : case 103 :
708 case 104 : case 105 : case 106 : case 107 :
709 case 108 : case 109 : case 110 : case 111 :
710 break;
712 // StoreInstVar, 0..15
713 case 112 : case 113 : case 114 : case 115 :
714 case 116 : case 117 : case 118 : case 119 :
715 case 120 : case 121 : case 122 : case 123 :
716 case 124 : case 125 : case 126 : case 127 :
717 break;
719 // StoreTempVar
720 case 128 : case 129 : case 130 : case 131 :
721 case 132 : case 133 : case 134 : case 135 :
722 op2 = op1 & 15; // get temp var level
723 op3 = *ip++; // get class var index
724 break;
725 case 136 :
726 op2 = *ip++; // get inst var index
727 op3 = *ip++; // get selector index
728 selector = gSpecialSelectors[op3];
729 break;
730 case 137 :
731 op2 = *ip++; // get selector index
732 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2]);
733 break;
734 case 138 :
735 op2 = *ip++; // get selector index
736 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2]);
737 break;
738 case 139 :
739 op2 = *ip++; // get selector index
740 selector = gSpecialSelectors[op2];
741 break;
742 case 140 :
743 op2 = *ip++; // get selector index
744 selector = gSpecialSelectors[op2];
745 break;
746 case 141 :
747 op2 = *ip++; // get selector index
748 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2]);
749 break;
750 case 142 :
751 op2 = *ip++; // get selector index
752 selector = gSpecialSelectors[op2];
753 break;
754 case 143 :
755 op2 = *ip++; // get selector index
756 break;
758 // StoreClassVar
759 case 144 : case 145 : case 146 : case 147 :
760 case 148 : case 149 : case 150 : case 151 :
761 case 152 : case 153 : case 154 : case 155 :
762 case 156 : case 157 : case 158 : case 159 :
763 op2 = op1 & 15;
764 op3 = *ip++; // get class var index
765 break;
767 // SendMsg
768 case 160 : case 161 : case 162 : case 163 :
769 case 164 : case 165 : case 166 : case 167 :
770 case 168 : case 169 : case 170 : case 171 :
771 case 172 : case 173 : case 174 : case 175 :
772 op2 = *ip++; // get selector index
773 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2]);
774 break;
776 // SuperMsg
777 case 176 : case 177 : case 178 : case 179 :
778 case 180 : case 181 : case 182 : case 183 :
779 case 184 : case 185 : case 186 : case 187 :
780 case 188 : case 189 : case 190 : case 191 :
781 op2 = *ip++; // get selector index
782 selector = slotRawSymbol(&slotRawObject(&theBlock->selectors)->slots[op2]);
783 break;
785 // SendSpecialMsg
786 case 192 : case 193 : case 194 : case 195 :
787 case 196 : case 197 : case 198 : case 199 :
788 case 200 : case 201 : case 202 : case 203 :
789 case 204 : case 205 : case 206 : case 207 :
790 op2 = *ip++; // get selector index
791 selector = gSpecialSelectors[op2];
792 break;
794 // SendSpecialUnaryArithMsg
795 case 208 : case 209 : case 210 : case 211 :
796 case 212 : case 213 : case 214 : case 215 :
797 case 216 : case 217 : case 218 : case 219 :
798 case 220 : case 221 : case 222 : case 223 :
799 op2 = op1 & 15;
800 selector = gSpecialUnarySelectors[op2];
801 break;
803 // SendSpecialBinaryArithMsg
804 case 224 : case 225 : case 226 : case 227 :
805 case 228 : case 229 : case 230 : case 231 :
806 case 232 : case 233 : case 234 : case 235 :
807 case 236 : case 237 : case 238 : case 239 :
808 op2 = op1 & 15;
809 selector = gSpecialBinarySelectors[op2];
810 break;
812 // SpecialOpcodes
813 case 240 : case 241 : case 242 : case 243 :
814 case 244 : case 245 : case 246 : case 247 :
815 break;
817 case 248 : // JumpIfFalse
818 case 249 : // JumpIfFalsePushNil
819 case 250 : // JumpIfFalsePushFalse
820 case 251 : // JumpIfTruePushTrue
821 case 252 : // JumpFwd
822 case 253 : // JumpBak
823 op2 = *ip++;
824 op3 = *ip++;
825 break;
826 case 254 : // PushPosInt
827 case 255 : // PushNegInt
828 op2 = *ip++;
829 if (op2 & 0x80) {
830 op3 = *ip++;
831 if (op3 & 0x80) {
832 op4 = *ip++;
833 if (op4 & 0x80) {
834 op5 = *ip++;
835 if (op5 & 0x80) {
836 op6 = *ip++;
841 break;
844 *ipp = ip;
845 return testSelector == selector;
850 void dumpByteCodes(PyrBlock *theBlock);
851 void dumpByteCodes(PyrBlock *theBlock)
853 PyrClass *theClass;
854 PyrBlock *block;
855 long size;
856 unsigned char *ip, *ipbeg, *ipend;
858 if (slotRawInt8Array(&theBlock->code) == NULL) {
859 post("Code empty.\n");
860 return;
862 block = theBlock;
863 theClass = 0;
864 while (block) {
865 if (isKindOf((PyrObject*)block, class_method)) {
866 theClass = slotRawClass(&((PyrMethod*)block)->ownerclass);
867 break;
869 block = slotRawBlock(&block->contextDef);
871 if (theClass == NULL) {
872 theClass = s_interpreter->u.classobj;
875 ip = ipbeg = slotRawInt8Array(&theBlock->code)->b;
876 size = slotRawInt8Array(&theBlock->code)->size;
877 ipend = ip + size;
878 post("BYTECODES: (%d)\n", size);
879 while (ip<ipend) {
880 ip = dumpOneByteCode(theBlock, theClass, ip);
884 bool detectSendSelectorIn(PyrBlock *theBlock, PyrSymbol *testSelector);
885 bool detectSendSelectorIn(PyrBlock *theBlock, PyrSymbol *testSelector)
887 PyrClass *theClass;
888 PyrBlock *block;
889 PyrSymbol *selector;
890 long size;
891 unsigned char *ip, *ipbeg, *ipend;
893 if (slotRawInt8Array(&theBlock->code) == NULL) {
894 PyrMethodRaw* methraw = METHRAW(theBlock);
895 switch (methraw->methType) {
896 case methRedirect :
897 case methRedirectSuper :
898 case methForwardInstVar :
899 case methForwardClassVar :
900 selector = slotRawSymbol(&theBlock->selectors);
901 return selector == testSelector;
902 default :
903 return false;
906 block = theBlock;
907 theClass = 0;
908 while (block) {
909 if (isKindOf((PyrObject*)block, class_method)) {
910 theClass = slotRawClass(&((PyrMethod*)block)->ownerclass);
911 break;
913 block = slotRawBlock(&block->contextDef);
915 if (theClass == NULL) {
916 theClass = s_interpreter->u.classobj;
919 ip = ipbeg = slotRawInt8Array(&theBlock->code)->b;
920 size = slotRawInt8Array(&theBlock->code)->size;
921 ipend = ip + size;
922 bool res = false;
923 while (ip<ipend) {
924 if ((res = detectSendSelector(theBlock, theClass, &ip, testSelector))) break;
926 return res;
930 const char* byteCodeString(int code);
931 const char* byteCodeString(int code)
933 switch (code) {
934 case 0 : return "PushClassX";
935 case 1 : return "PushInstVarX";
936 case 2 : return "PushTempVarX";
937 case 3 : return "PushTempZeroVarX";
938 case 4 : return "PushLiteralX";
939 case 5 : return "PushClassVarX";
940 case 6 : return "PushSpecialClass";
941 case 7 : return "StoreInstVarX";
942 case 8 : return "StoreTempVarX";
943 case 9 : return "StoreClassVarX";
944 case 10 : return "SendMsgX";
945 case 11 : return "SuperMsgX";
946 case 12 : return "SendSpecialMsgX";
947 case 13 : return "SendSpecialUnaryArithMsgX";
948 case 14 : return "SendSpecialBinaryArithMsgX";
949 case 15 : return "PushGlobal";
951 case 16 : case 17 : case 18 : case 19 :
952 case 20 : case 21 : case 22 : case 23 :
953 case 24 : case 25 : case 26 : case 27 :
954 case 28 : case 29 : case 30 : case 31 :
955 return "PushInstVar";
957 case 32 : case 33 : case 34 : case 35 :
958 case 36 : case 37 : case 38 : case 39 :
959 case 40 : case 41 : case 42 : case 43 :
960 case 44 : case 45 : case 46 : case 47 :
961 return "PushTempVar";
963 case 48 : case 49 : case 50 : case 51 :
964 case 52 : case 53 : case 54 : case 55 :
965 case 56 : case 57 : case 58 : case 59 :
966 case 60 : case 61 : case 62 : case 63 :
967 return "PushTempZeroVar";
969 case 64 : case 65 : case 66 : case 67 :
970 case 68 : case 69 : case 70 : case 71 :
971 case 72 : case 73 : case 74 : case 75 :
972 case 76 : case 77 : case 78 : case 79 :
973 return "PushLiteral";
975 case 80 : case 81 : case 82 : case 83 :
976 case 84 : case 85 : case 86 : case 87 :
977 case 88 : case 89 : case 90 : case 91 :
978 case 92 : case 93 : case 94 : case 95 :
979 return "PushClassVar";
981 case 96 : return "PushSpecialValue this";
982 case 97 : return "PushOneAndSubtract";
983 case 98 : return "PushSpecialValue -1";
984 case 99 : return "PushSpecialValue 0";
985 case 100 : return "PushSpecialValue 1";
986 case 101 : return "PushSpecialValue 2";
987 case 102 : return "PushSpecialValue 0.5";
988 case 103 : return "PushSpecialValue -1.0";
989 case 104 : return "PushSpecialValue 0.0";
990 case 105 : return "PushSpecialValue 1.0";
991 case 106 : return "PushSpecialValue 2.0";
992 case 107 : return "PushOneAndAdd";
993 case 108 : return "PushSpecialValue true";
994 case 109 : return "PushSpecialValue false";
995 case 110 : return "PushSpecialValue nil";
996 case 111 : return "PushSpecialValue 'end'";
998 case 112 : case 113 : case 114 : case 115 :
999 case 116 : case 117 : case 118 : case 119 :
1000 case 120 : case 121 : case 122 : case 123 :
1001 case 124 : case 125 : case 126 : case 127 :
1002 return "StoreInstVar";
1004 case 128 : case 129 : case 130 : case 131 :
1005 return "StoreTempVar";
1007 case 132 : return "PushInstVarAndSendNext";
1008 case 133 : return "PushInstVarAndSendPrNext";
1009 case 134 : return "PushInstVarAndSendDemandThisNode";
1010 case 135 : return "PushInstVarAndSendSpecialMsg";
1012 case 136 : case 137 : case 138 : case 139 :
1013 case 140 : case 141 : case 142 : case 143 :
1014 return "UndefinedOpcode";
1016 case 144 : case 145 : case 146 : case 147 :
1017 case 148 : case 149 : case 150 : case 151 :
1018 case 152 : case 153 : case 154 : case 155 :
1019 case 156 : case 157 : case 158 : case 159 :
1020 return "StoreClassVar";
1022 case 160 : case 161 : case 162 : case 163 :
1023 case 164 : case 165 : case 166 : case 167 :
1024 case 168 : case 169 : case 170 : case 171 :
1025 case 172 : case 173 : case 174 : case 175 :
1026 return "SendMsg";
1028 case 176 :
1029 return "TailCallReturnFromFunction";
1031 case 177 : case 178 : case 179 :
1032 case 180 : case 181 : case 182 : case 183 :
1033 case 184 : case 185 : case 186 : case 187 :
1034 case 188 : case 189 : case 190 : case 191 :
1035 return "SuperMsg";
1037 case 192 : case 193 : case 194 : case 195 :
1038 case 196 : case 197 : case 198 : case 199 :
1039 case 200 : case 201 : case 202 : case 203 :
1040 case 204 : case 205 : case 206 : case 207 :
1041 return "SendSpecialMsg";
1043 case 208 : case 209 : case 210 : case 211 :
1044 case 212 : case 213 : case 214 : case 215 :
1045 case 216 : case 217 : case 218 : case 219 :
1046 case 220 : case 221 : case 222 : case 223 :
1047 return "SendSpecialUnaryArithMsg";
1049 case 224 : case 225 : case 226 : case 227 :
1050 case 228 : case 229 : case 230 : case 231 :
1051 case 232 : case 233 : case 234 : case 235 :
1052 case 236 : case 237 : case 238 : case 239 :
1053 return "SendSpecialBinaryArithMsg";
1055 // SpecialOpcodes
1056 case 240 : return "Drop";
1057 case 241 : return "Dup"; // Dup
1059 case 242 : return "BlockReturn"; // BlockReturn
1060 case 243 : return "Return"; // Return
1061 case 244 : return "ReturnSelf"; // ReturnSelf
1062 case 245 : return "ReturnTrue"; // ReturnTrue
1063 case 246 : return "ReturnFalse"; // ReturnFalse
1064 case 247 : return "ReturnNil"; // ReturnNil
1066 case 248 : return "JumpIfFalse"; // JumpIfFalse
1067 case 249 : return "JumpIfFalsePushNil"; // JumpIfFalsePushNil
1069 case 250 : return "JumpIfFalsePushFalse"; // JumpIfFalsePushFalse
1070 case 251 : return "JumpIfTruePushTrue"; // JumpIfTruePushTrue
1071 case 252 : return "JumpFwd"; // JumpFwd
1072 case 253 : return "JumpBak"; // JumpBak
1073 case 254 : return "PushPosInt"; // PushPosInt
1074 case 255 : return "TailCallReturnFromMethod"; // TailCallReturnFromMethod
1076 return "unknown opcode";