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 #include <atomic>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <math.h>
25 #include <limits.h>
26 #include "GC.h"
27 #include "PyrMessage.h"
28 #include "PyrInterpreter.h"
29 #include "PyrSymbolTable.h"
30 #include "PyrObjectProto.h"
31 #include "PyrKernelProto.h"
32 #include "PyrLexer.h"
33 #include "InitAlloc.h"
34 #include "Hash.h"
35 #include "SC_Constants.h"
36 #include "SC_Alloca.h"
37 #include "SC_Lock.h"
38
39 #include <set>
40 #include <limits>
41
42 #include <memory>
43 #include <boost/range/irange.hpp>
44
45 #define BOOST_THREAD_VERSION 4
46 #define BOOST_THREAD_PROVIDES_EXECUTORS
47
48 #include <boost/thread/future.hpp>
49 #include <boost/thread/executor.hpp>
50 #include <boost/thread/executors/basic_thread_pool.hpp>
51
52 #ifdef _MSC_VER
53 # include <future>
54 #endif
55
56 #if 0 // not yet
57 # include <parallel/algorithm>
58 #endif
59
60
61 PyrClass* gClassList = nullptr;
62 int gNumSelectors = 0;
63 int gNumClasses = 0;
64 int gNumClassVars = 0;
65 int gFormatElemSize[NUMOBJFORMATS];
66 int gFormatElemCapc[NUMOBJFORMATS];
67 int gFormatElemTag[NUMOBJFORMATS];
68 PyrMethod* gNullMethod; // used to fill row table
69 PyrClass* gTagClassTable[16];
70
71 PyrClass* class_object;
72 PyrClass* class_dict;
73 PyrClass* class_array;
74 PyrClass *class_list, *class_method, *class_fundef, *class_frame, *class_class;
75 PyrClass *class_symbol, *class_nil;
76 PyrClass *class_boolean, *class_true, *class_false;
77 PyrClass *class_int, *class_char, *class_float, *class_complex;
78 PyrClass* class_rawptr;
79 PyrClass* class_string;
80 PyrClass *class_magnitude, *class_number, *class_collection, *class_ordered_collection;
81 PyrClass* class_arrayed_collection;
82 PyrClass* class_sequenceable_collection;
83 PyrClass* class_simple_number;
84 PyrClass* class_rawarray;
85 PyrClass* class_signal;
86 PyrClass* class_wavetable;
87 PyrClass* class_floatarray;
88 PyrClass* class_int8array;
89 PyrClass* class_int16array;
90 PyrClass* class_int32array;
91 PyrClass* class_symbolarray;
92 PyrClass* class_doublearray;
93 PyrClass *class_func, *class_absfunc;
94 PyrClass* class_stream;
95 PyrClass* class_process;
96 PyrClass* class_interpreter;
97 PyrClass* class_thread;
98 PyrClass* class_routine;
99 PyrClass* class_finalizer;
100 PyrClass* class_server_shm_interface;
101
102 PyrSymbol* s_none;
103 PyrSymbol* s_object;
104 PyrSymbol* s_bag;
105 PyrSymbol* s_set;
106 PyrSymbol* s_identityset;
107 PyrSymbol* s_dictionary;
108 PyrSymbol* s_identitydictionary;
109 PyrSymbol* s_linkedlist;
110 PyrSymbol* s_sortedlist;
111 PyrSymbol* s_array;
112 PyrSymbol *s_list, *s_method, *s_fundef, *s_frame, *s_class;
113 PyrSymbol *s_symbol, *s_nil;
114 PyrSymbol *s_boolean, *s_true, *s_false;
115 PyrSymbol *s_int, *s_char, *s_color, *s_float, *s_complex;
116 PyrSymbol* s_rawptr;
117 PyrSymbol* s_string;
118 PyrSymbol *s_magnitude, *s_number, *s_collection, *s_ordered_collection;
119 PyrSymbol* s_arrayed_collection;
120 PyrSymbol* s_sequenceable_collection;
121 PyrSymbol* s_simple_number;
122 PyrSymbol* s_signal;
123 PyrSymbol* s_wavetable;
124
125 PyrSymbol* s_rawarray;
126 PyrSymbol* s_int8array;
127 PyrSymbol* s_int16array;
128 PyrSymbol* s_int32array;
129 PyrSymbol* s_symbolarray;
130 PyrSymbol* s_doublearray;
131 PyrSymbol* s_floatarray;
132 PyrSymbol* s_rect;
133 PyrSymbol *s_func, *s_absfunc;
134 PyrSymbol* s_stream;
135 PyrSymbol* s_process;
136 PyrSymbol* s_main;
137 PyrSymbol* s_thread;
138 PyrSymbol* s_routine;
139 PyrSymbol* s_task;
140 PyrSymbol* s_prstart;
141 PyrSymbol* s_interpreter;
142 PyrSymbol* s_finalizer;
143 PyrSymbol* s_awake;
144 PyrSymbol* s_systemclock;
145 PyrSymbol* s_server_shm_interface;
146 PyrSymbol *s_interpretCmdLine, *s_interpretPrintCmdLine;
147
148 PyrSymbol* s_doesNotUnderstand;
149 PyrSymbol *s_curProcess, *s_curMethod, *s_curBlock, *s_curClosure, *s_curThread;
150 PyrSymbol *s_run, *s_stop, *s_tick;
151 PyrSymbol* s_startup;
152 PyrSymbol* s_next;
153 PyrSymbol* s_env;
154 PyrSymbol *s_new, *s_ref, *s_value, *s_at, *s_put;
155 PyrSymbol *s_performList, *s_superPerformList;
156 PyrSymbol *s_series, *s_copyseries, *s_putseries;
157 PyrSymbol *s_envirGet, *s_envirPut;
158 PyrSymbol *s_synth, *s_environment, *s_event;
159 PyrSymbol* s_shutdown;
160 PyrSymbol *s_super, *s_this;
161
162 PyrSlot o_nil, o_true, o_false;
163 PyrSlot o_fhalf, o_fnegone, o_fzero, o_fone, o_ftwo, o_inf;
164 PyrSlot o_negone, o_zero, o_one, o_two;
165 PyrSlot o_none;
166 PyrSlot o_emptyarray, o_onenilarray, o_argnamethis;
167
168
initSymbols()169 void initSymbols() {
170 // basic keywords
171 s_new = getsym("new");
172 s_none = getsym("__none");
173 /* Dummy symbol for null superclass or primitive. Prefixed with
174 * `__` to avoid collisions with possible method and primitive names.
175 */
176 s_this = getsym("this");
177 s_super = getsym("super");
178 s_curProcess = getsym("thisProcess");
179 s_curThread = getsym("thisThread");
180 s_curMethod = getsym("thisMethod");
181 s_curBlock = getsym("thisFunctionDef");
182 s_curClosure = getsym("thisFunction");
183
184 // classes
185 s_object = getsym("Object");
186 s_ref = getsym("Ref");
187 s_dictionary = getsym("Dictionary");
188 s_bag = getsym("Bag");
189 s_set = getsym("Set");
190 s_identityset = getsym("IdentitySet");
191 s_identitydictionary = getsym("IdentityDictionary");
192 s_linkedlist = getsym("LinkedList");
193 s_sortedlist = getsym("SortedList");
194 s_array = getsym("Array");
195 s_list = getsym("List");
196 s_method = getsym("Method");
197 s_fundef = getsym("FunctionDef");
198 s_frame = getsym("Frame");
199 s_class = getsym("Class");
200 s_symbol = getsym("Symbol");
201 s_nil = getsym("Nil");
202 s_true = getsym("True");
203 s_false = getsym("False");
204 s_int = getsym("Integer");
205 s_float = getsym("Float");
206 s_char = getsym("Char");
207 s_color = getsym("Color");
208 s_rawptr = getsym("RawPointer");
209 s_string = getsym("String");
210 s_magnitude = getsym("Magnitude");
211 s_number = getsym("Number");
212 s_simple_number = getsym("SimpleNumber");
213 s_collection = getsym("Collection");
214 s_arrayed_collection = getsym("ArrayedCollection");
215 s_sequenceable_collection = getsym("SequenceableCollection");
216 s_boolean = getsym("Boolean");
217 s_signal = getsym("Signal");
218 s_wavetable = getsym("Wavetable");
219 s_rawarray = getsym("RawArray");
220 s_int8array = getsym("Int8Array");
221 s_int16array = getsym("Int16Array");
222 s_int32array = getsym("Int32Array");
223 s_symbolarray = getsym("SymbolArray");
224 s_floatarray = getsym("FloatArray");
225 s_doublearray = getsym("DoubleArray");
226 s_complex = getsym("Complex");
227 s_rect = getsym("Rect");
228 s_absfunc = getsym("AbstractFunction");
229 s_func = getsym("Function");
230 s_stream = getsym("Stream");
231 s_process = getsym("Process");
232 s_main = getsym("Main");
233 s_thread = getsym("Thread");
234 s_routine = getsym("Routine");
235 s_task = getsym("Task");
236 s_interpreter = getsym("Interpreter");
237 s_finalizer = getsym("Finalizer");
238 s_systemclock = getsym("SystemClock");
239 s_server_shm_interface = getsym("ServerShmInterface");
240 s_env = getsym("Env");
241 s_synth = getsym("Synth");
242 s_environment = getsym("Environment");
243 s_event = getsym("Event");
244
245 // interpreter
246 s_interpretCmdLine = getsym("interpretCmdLine");
247 s_interpretPrintCmdLine = getsym("interpretPrintCmdLine");
248
249 s_doesNotUnderstand = getsym("doesNotUnderstand");
250
251 s_startup = getsym("startup");
252 s_awake = getsym("awake");
253 s_shutdown = getsym("shutdown");
254
255 // methods
256 s_run = getsym("run");
257 s_stop = getsym("stop");
258 s_tick = getsym("tick");
259 s_next = getsym("next");
260 s_value = getsym("value");
261 s_performList = getsym("performList");
262 s_superPerformList = getsym("superPerformList");
263 s_at = getsym("at");
264 s_put = getsym("put");
265 s_prstart = getsym("prStart");
266 s_series = getsym("prSimpleNumberSeries");
267 s_copyseries = getsym("copySeries");
268 s_putseries = getsym("putSeries");
269
270 s_envirGet = getsym("envirGet");
271 s_envirPut = getsym("envirPut");
272
273 // set special value slots
274 SetSymbol(&o_none, s_none);
275
276 SetNil(&o_nil);
277 SetFalse(&o_false);
278 SetTrue(&o_true);
279
280 SetInt(&o_negone, -1);
281 SetInt(&o_zero, 0);
282 SetInt(&o_one, 1);
283 SetInt(&o_two, 2);
284
285 SetFloat(&o_fhalf, .5);
286 SetFloat(&o_fnegone, -1.);
287 SetFloat(&o_fzero, 0.);
288 SetFloat(&o_fone, 1.);
289 SetFloat(&o_ftwo, 2.);
290 SetFloat(&o_inf, std::numeric_limits<double>::infinity());
291
292 slotCopy(&gSpecialValues[svNil], &o_nil);
293 slotCopy(&gSpecialValues[svFalse], &o_false);
294 slotCopy(&gSpecialValues[svTrue], &o_true);
295
296 slotCopy(&gSpecialValues[svNegOne], &o_negone);
297 slotCopy(&gSpecialValues[svZero], &o_zero);
298 slotCopy(&gSpecialValues[svOne], &o_one);
299 slotCopy(&gSpecialValues[svTwo], &o_two);
300
301 slotCopy(&gSpecialValues[svFHalf], &o_fhalf);
302 slotCopy(&gSpecialValues[svFNegOne], &o_fnegone);
303 slotCopy(&gSpecialValues[svFZero], &o_fzero);
304 slotCopy(&gSpecialValues[svFOne], &o_fone);
305 slotCopy(&gSpecialValues[svFTwo], &o_ftwo);
306 slotCopy(&gSpecialValues[svInf], &o_inf);
307
308
309 gFormatElemSize[obj_notindexed] = sizeof(PyrSlot);
310 gFormatElemSize[obj_slot] = sizeof(PyrSlot);
311 gFormatElemSize[obj_double] = sizeof(double);
312 gFormatElemSize[obj_float] = sizeof(float);
313 gFormatElemSize[obj_int32] = sizeof(int32);
314 gFormatElemSize[obj_int16] = sizeof(int16);
315 gFormatElemSize[obj_int8] = sizeof(int8);
316 gFormatElemSize[obj_char] = sizeof(char);
317 gFormatElemSize[obj_symbol] = sizeof(PyrSymbol*);
318
319 gFormatElemCapc[obj_notindexed] = sizeof(PyrSlot) / sizeof(PyrSlot);
320 gFormatElemCapc[obj_slot] = sizeof(PyrSlot) / sizeof(PyrSlot);
321 gFormatElemCapc[obj_double] = sizeof(PyrSlot) / sizeof(double);
322 gFormatElemCapc[obj_float] = sizeof(PyrSlot) / sizeof(float);
323 gFormatElemCapc[obj_int32] = sizeof(PyrSlot) / sizeof(int32);
324 gFormatElemCapc[obj_int16] = sizeof(PyrSlot) / sizeof(int16);
325 gFormatElemCapc[obj_int8] = sizeof(PyrSlot) / sizeof(int8);
326 gFormatElemCapc[obj_char] = sizeof(PyrSlot) / sizeof(char);
327 gFormatElemCapc[obj_symbol] = sizeof(PyrSlot) / sizeof(PyrSymbol*);
328
329 gFormatElemTag[obj_notindexed] = -1;
330 gFormatElemTag[obj_slot] = -1;
331 gFormatElemTag[obj_double] = 0;
332 gFormatElemTag[obj_float] = 0;
333 gFormatElemTag[obj_int32] = tagInt;
334 gFormatElemTag[obj_int16] = tagInt;
335 gFormatElemTag[obj_int8] = tagInt;
336 gFormatElemTag[obj_char] = tagChar;
337 gFormatElemTag[obj_symbol] = tagSym;
338 }
339
slotSymString(PyrSlot * slot)340 const char* slotSymString(PyrSlot* slot) {
341 switch (GetTag(slot)) {
342 case tagObj:
343 return slotRawSymbol(&slotRawObject(slot)->classptr->name)->name;
344 case tagInt:
345 return "Integer";
346 case tagChar:
347 return "Char";
348 case tagSym:
349 return slotRawSymbol(slot)->name;
350 case tagNil:
351 return "Nil";
352 case tagFalse:
353 return "False";
354 case tagTrue:
355 return "True";
356 default:
357 return "<float>";
358 }
359 }
360
newClassObj(PyrClass * classObjSuperClass,PyrSymbol * className,PyrSymbol * superClassName,int numInstVars,int numClassVars,int numConsts,int numInstMethods,int instFormat,int instFlags)361 PyrClass* newClassObj(PyrClass* classObjSuperClass, PyrSymbol* className, PyrSymbol* superClassName, int numInstVars,
362 int numClassVars, int numConsts, int numInstMethods, int instFormat, int instFlags) {
363 PyrClass *classobj, *superclassobj;
364 PyrObject* array;
365 PyrSymbolArray* symarray;
366 int classFlags;
367
368 /*{
369 int c;
370 c = className->name[0];
371 if (!(c >= 'A' && c <= 'Z')) Debugger();
372 }*/
373 // pyrmalloc:
374 // lifetime: kill upon recompiling library
375 classobj = (PyrClass*)pyr_pool_runtime->Alloc(sizeof(PyrClass));
376 MEMFAIL(classobj);
377 classobj->size = (sizeof(PyrClass) - sizeof(PyrObjectHdr)) / sizeof(PyrSlot);
378 classobj->prev = classobj->next = nullptr;
379 classobj->obj_flags = obj_immutable;
380 classobj->obj_format = obj_notindexed;
381 classobj->gc_color = obj_permanent;
382 classobj->obj_sizeclass = LOG2CEIL(classobj->size);
383 classobj->classptr = classObjSuperClass;
384
385
386 // append to the list of classes
387 if (gClassList)
388 SetObject(&classobj->nextclass, gClassList);
389 else
390 SetNil(&classobj->nextclass);
391
392 gClassList = classobj;
393
394 className->u.classobj = classobj;
395 // postfl("> '%s' %d %d\n", className->name, className, classobj);
396
397 SetSymbol(&classobj->name, className);
398 if (superClassName) {
399 SetSymbol(&classobj->superclass, superClassName);
400 superclassobj = superClassName->u.classobj;
401 } else {
402 SetSymbol(&classobj->superclass, s_none);
403 superclassobj = nullptr;
404 }
405
406 SetInt(&classobj->subclasses, 0); // to be filled with subclasses later
407 // in the meantime it is used as a tally of subclasses so that its allocation
408 // size can be known
409
410 if (numInstMethods) {
411 array = newPyrArray(nullptr, numInstMethods, obj_permanent | obj_immutable, false);
412 SetObject(&classobj->methods, array);
413 } else {
414 SetNil(&classobj->methods);
415 }
416
417 if (numInstVars) {
418 symarray = newPyrSymbolArray(nullptr, numInstVars, obj_permanent | obj_immutable, false);
419 SetObject(&classobj->instVarNames, symarray);
420
421 array = newPyrArray(nullptr, numInstVars, obj_permanent | obj_immutable, false);
422 SetObject(&classobj->iprototype, array);
423 nilSlots(array->slots, numInstVars);
424 } else {
425 SetNil(&classobj->instVarNames);
426 SetNil(&classobj->iprototype);
427 }
428
429 if (numClassVars) {
430 symarray = newPyrSymbolArray(nullptr, numClassVars, obj_permanent | obj_immutable, false);
431 SetObject(&classobj->classVarNames, symarray);
432
433 array = newPyrArray(nullptr, numClassVars, obj_permanent | obj_immutable, false);
434 SetObject(&classobj->cprototype, array);
435 nilSlots(array->slots, numClassVars);
436 } else {
437 SetNil(&classobj->classVarNames);
438 SetNil(&classobj->cprototype);
439 }
440
441 if (numConsts) {
442 symarray = newPyrSymbolArray(nullptr, numConsts, obj_permanent | obj_immutable, false);
443 SetObject(&classobj->constNames, symarray);
444
445 array = newPyrArray(nullptr, numConsts, obj_permanent | obj_immutable, false);
446 SetObject(&classobj->constValues, array);
447 nilSlots(array->slots, numConsts);
448 } else {
449 SetNil(&classobj->constNames);
450 SetNil(&classobj->constValues);
451 }
452
453 classFlags = 0;
454 if (instFormat != obj_notindexed) {
455 classFlags |= classHasIndexableInstances;
456 }
457
458 SetInt(&classobj->instanceFormat, instFormat);
459 SetInt(&classobj->instanceFlags, instFlags);
460 SetInt(&classobj->classIndex, -1);
461 SetInt(&classobj->classFlags, classFlags);
462 SetInt(&classobj->maxSubclassIndex, 0);
463 SetNil(&classobj->filenameSym);
464 SetInt(&classobj->charPos, 0);
465 SetInt(&classobj->classVarIndex, gNumClassVars);
466 // if (numClassVars) post("%16s %4d %4d\n", className->name, gNumClassVars, numClassVars);
467 gNumClassVars += numClassVars;
468 return classobj;
469 }
470
reallocClassObj(PyrClass * classobj,int numInstVars,int numClassVars,int numConsts,int numMethods,int instFormat,int instFlags)471 void reallocClassObj(PyrClass* classobj, int numInstVars, int numClassVars, int numConsts, int numMethods,
472 int instFormat, int instFlags) {
473 PyrObject* array;
474 PyrSymbolArray* symarray;
475 PyrClass* superclassobj;
476
477 freePyrSlot(&classobj->methods);
478 freePyrSlot(&classobj->instVarNames);
479 freePyrSlot(&classobj->classVarNames);
480 freePyrSlot(&classobj->iprototype);
481 freePyrSlot(&classobj->cprototype);
482
483 freePyrSlot(&classobj->constNames);
484 freePyrSlot(&classobj->constValues);
485
486 if (numMethods) {
487 array = newPyrArray(nullptr, numMethods, obj_permanent | obj_immutable, false);
488 SetObject(&classobj->methods, array);
489 } else {
490 SetNil(&classobj->methods);
491 }
492
493 if (numInstVars) {
494 // post("reallocClassObj %s numInstVars %d\n", slotRawSymbol(&classobj->name)->name, numInstVars);
495 symarray = newPyrSymbolArray(nullptr, numInstVars, obj_permanent | obj_immutable, false);
496 SetObject(&classobj->instVarNames, symarray);
497
498 array = newPyrArray(nullptr, numInstVars, obj_permanent | obj_immutable, false);
499 SetObject(&classobj->iprototype, array);
500 nilSlots(array->slots, numInstVars);
501 } else {
502 SetNil(&classobj->instVarNames);
503 SetNil(&classobj->iprototype);
504 }
505
506 if (numClassVars) {
507 // post("reallocClassObj %s numClassVars %d\n", slotRawSymbol(&classobj->name)->name, numClassVars);
508 symarray = newPyrSymbolArray(nullptr, numClassVars, obj_permanent | obj_immutable, false);
509 SetObject(&classobj->classVarNames, symarray);
510 nilSlots(array->slots, numClassVars);
511
512 array = newPyrArray(nullptr, numClassVars, obj_permanent | obj_immutable, false);
513 SetObject(&classobj->cprototype, array);
514 nilSlots(array->slots, numClassVars);
515 } else {
516 SetNil(&classobj->classVarNames);
517 SetNil(&classobj->cprototype);
518 }
519
520 if (numConsts) {
521 // post("reallocClassObj %s numConsts %d\n", slotRawSymbol(&classobj->name)->name, numConsts);
522 symarray = newPyrSymbolArray(nullptr, numConsts, obj_permanent | obj_immutable, false);
523 SetObject(&classobj->constNames, symarray);
524
525 array = newPyrArray(nullptr, numConsts, obj_permanent | obj_immutable, false);
526 SetObject(&classobj->constValues, array);
527 nilSlots(array->slots, numConsts);
528 } else {
529 SetNil(&classobj->constNames);
530 SetNil(&classobj->constValues);
531 }
532
533 superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
534
535 SetInt(&classobj->instanceFormat, instFormat);
536 SetInt(&classobj->instanceFlags, instFlags);
537 SetInt(&classobj->classIndex, -1);
538 }
539
540 void fixClassArrays(PyrClass* classobj);
fixClassArrays(PyrClass * classobj)541 void fixClassArrays(PyrClass* classobj) {
542 if (IsObj(&classobj->methods))
543 slotRawObject(&classobj->methods)->classptr = class_array;
544 if (IsObj(&classobj->instVarNames))
545 slotRawObject(&classobj->instVarNames)->classptr = class_symbolarray;
546 if (IsObj(&classobj->classVarNames))
547 slotRawObject(&classobj->classVarNames)->classptr = class_symbolarray;
548 if (IsObj(&classobj->iprototype))
549 slotRawObject(&classobj->iprototype)->classptr = class_array;
550 if (IsObj(&classobj->cprototype))
551 slotRawObject(&classobj->cprototype)->classptr = class_array;
552 }
553
numInstVars(PyrClass * classobj)554 int numInstVars(PyrClass* classobj) {
555 int res;
556 if (IsNil(&classobj->instVarNames))
557 res = 0;
558 else
559 res = slotRawObject(&classobj->instVarNames)->size;
560 return res;
561 }
562
numClassVars(PyrClass * classobj)563 int numClassVars(PyrClass* classobj) {
564 int res;
565 if (IsNil(&classobj->classVarNames))
566 res = 0;
567 else
568 res = slotRawObject(&classobj->classVarNames)->size;
569 return res;
570 }
571
572
573 void objAddIndexedSlotGrow(PyrSlot* arraySlot, PyrSlot* addSlot);
objAddIndexedSlotGrow(PyrSlot * arraySlot,PyrSlot * addSlot)574 void objAddIndexedSlotGrow(PyrSlot* arraySlot, PyrSlot* addSlot) {
575 PyrObject* obj;
576 if (IsNil(arraySlot)) {
577 PyrObject* newobj = (PyrObject*)newPyrArray(nullptr, 1, obj_permanent | obj_immutable, false);
578 SetObject(arraySlot, newobj);
579 obj = newobj;
580 } else {
581 obj = slotRawObject(arraySlot);
582 if (obj->size >= ARRAYMAXINDEXSIZE(obj)) {
583 // post("objAddIndexedSlotGrow\n");
584 PyrObject* newobj = (PyrObject*)newPyrArray(nullptr, obj->size * 2, obj_permanent | obj_immutable, false);
585 memcpy(newobj->slots, obj->slots, obj->size * sizeof(PyrSlot));
586 newobj->size = obj->size;
587 SetObject(arraySlot, newobj);
588 pyr_pool_runtime->Free((void*)obj);
589 obj = newobj;
590 }
591 }
592 slotCopy(&obj->slots[obj->size++], addSlot);
593 }
594
addMethod(PyrClass * classobj,PyrMethod * method)595 void addMethod(PyrClass* classobj, PyrMethod* method) {
596 PyrSlot slot;
597 SetObject(&slot, method);
598 objAddIndexedSlotGrow(&classobj->methods, &slot);
599 }
600
601
classFindDirectMethod(PyrClass * classobj,PyrSymbol * name)602 PyrMethod* classFindDirectMethod(PyrClass* classobj, PyrSymbol* name) {
603 PyrMethod* method;
604 PyrSlot* methods;
605 int i, numMethods;
606 if (IsNil(&classobj->methods))
607 return nullptr;
608 methods = slotRawObject(&classobj->methods)->slots;
609 numMethods = slotRawObject(&classobj->methods)->size;
610 for (i = 0; i < numMethods; ++i) {
611 method = slotRawMethod(&methods[i]);
612 if (slotRawSymbol(&method->name) == name)
613 break;
614 }
615 if (i >= numMethods)
616 method = nullptr;
617 return method;
618 }
619
numSuperInstVars(PyrClass * superclassobj)620 int numSuperInstVars(PyrClass* superclassobj) {
621 int superinstvars = 0;
622 if (superclassobj) {
623 if (IsObj(&superclassobj->iprototype)) {
624 superinstvars = slotRawObject(&superclassobj->iprototype)->size;
625 }
626 }
627 return superinstvars;
628 }
629
classFindInstVar(PyrClass * classobj,PyrSymbol * name,int * index)630 bool classFindInstVar(PyrClass* classobj, PyrSymbol* name, int* index) {
631 PyrSymbolArray* ivnames;
632 PyrSymbol* ivname;
633 int i;
634 if (NotNil(&classobj->instVarNames)) {
635 ivnames = slotRawSymbolArray(&classobj->instVarNames);
636 if (ivnames) {
637 for (i = 0; i < ivnames->size; ++i) {
638 ivname = ivnames->symbols[i];
639 if (ivname == name) {
640 // numsupervars = numSuperInstVars(slotRawSymbol(&classobj->superclass)->u.classobj);
641 //*index = numsupervars + i;
642 *index = i;
643 return true;
644 }
645 }
646 }
647 }
648 return false;
649 }
650
instVarOffset(const char * classname,const char * instvarname)651 int instVarOffset(const char* classname, const char* instvarname) {
652 PyrSymbol *instvarsymbol, *classsymbol;
653 PyrClass* classobj;
654 int index;
655 char c;
656
657 classsymbol = getsym(classname);
658 instvarsymbol = getsym(instvarname);
659
660 c = classname[0];
661 if (!(c >= 'A' && c <= 'Z'))
662 return -1;
663
664 classobj = classsymbol->u.classobj;
665 if (!classobj)
666 return -1;
667 if (!classFindInstVar(classobj, instvarsymbol, &index))
668 return -1;
669 return index;
670 }
671
classVarOffset(const char * classname,const char * classvarname,PyrClass ** classobj)672 int classVarOffset(const char* classname, const char* classvarname, PyrClass** classobj) {
673 PyrSymbol *classvarsymbol, *classsymbol;
674 int index;
675 char c;
676
677 classsymbol = getsym(classname);
678 classvarsymbol = getsym(classvarname);
679
680 c = classname[0];
681 if (!(c >= 'A' && c <= 'Z'))
682 return -1;
683
684 *classobj = classsymbol->u.classobj;
685 if (!*classobj)
686 return -1;
687 if (!classFindClassVar(classobj, classvarsymbol, &index))
688 return -1;
689 return index;
690 }
691
classFindClassVar(PyrClass ** classobj,PyrSymbol * name,int * index)692 bool classFindClassVar(PyrClass** classobj, PyrSymbol* name, int* index) {
693 PyrSymbolArray* cvnames;
694 PyrSymbol* cvname;
695 int i, j;
696 char* classname;
697 PyrClass* localclassobj = *classobj;
698 // if this is a Metaclass then we need to search its normal Class for
699 // the class vars
700 classname = slotRawSymbol(&localclassobj->name)->name;
701 if (strncmp(classname, "Meta_", 5) == 0) {
702 localclassobj = getsym(classname + 5)->u.classobj;
703 }
704 for (j = 0; localclassobj; ++j) {
705 if (NotNil(&localclassobj->classVarNames)) {
706 cvnames = slotRawSymbolArray(&localclassobj->classVarNames);
707 if (cvnames) {
708 for (i = 0; i < cvnames->size; ++i) {
709 cvname = cvnames->symbols[i];
710 if (cvname == name) {
711 *classobj = localclassobj;
712 *index = i;
713 return true;
714 }
715 }
716 }
717 }
718 if (IsSym(&localclassobj->superclass)) {
719 localclassobj = slotRawSymbol(&localclassobj->superclass)->u.classobj;
720 } else {
721 localclassobj = nullptr;
722 }
723 }
724 return false;
725 }
726
classFindConst(PyrClass ** classobj,PyrSymbol * name,int * index)727 bool classFindConst(PyrClass** classobj, PyrSymbol* name, int* index) {
728 PyrSymbolArray* knames;
729 PyrSymbol* kname;
730 int i, j;
731 char* classname;
732 PyrClass* localclassobj = *classobj;
733 // if this is a Metaclass then we need to search its normal Class for
734 // the class vars
735 classname = slotRawSymbol(&localclassobj->name)->name;
736 if (strncmp(classname, "Meta_", 5) == 0) {
737 localclassobj = getsym(classname + 5)->u.classobj;
738 }
739 for (j = 0; localclassobj; ++j) {
740 if (NotNil(&localclassobj->constNames)) {
741 knames = slotRawSymbolArray(&localclassobj->constNames);
742 if (knames) {
743 for (i = 0; i < knames->size; ++i) {
744 kname = knames->symbols[i];
745 if (kname == name) {
746 *classobj = localclassobj;
747 *index = i;
748 return true;
749 }
750 }
751 }
752 }
753 if (IsSym(&localclassobj->superclass)) {
754 localclassobj = slotRawSymbol(&localclassobj->superclass)->u.classobj;
755 } else {
756 localclassobj = nullptr;
757 }
758 }
759 return false;
760 }
761
762 struct compareByName {
operator ()compareByName763 bool operator()(PyrClass* lhs, PyrClass* rhs) const {
764 return strcmp(slotRawSymbol(&lhs->name)->name, slotRawSymbol(&rhs->name)->name) < 0;
765 }
766 };
767
768
769 template <class T> class pyr_pool_compile_allocator {
770 public:
771 typedef std::size_t size_type;
772 typedef std::ptrdiff_t difference_type;
773 typedef T* pointer;
774 typedef const T* const_pointer;
775 typedef T& reference;
776 typedef const T& const_reference;
777 typedef T value_type;
778
779 template <class U> struct rebind { typedef pyr_pool_compile_allocator<U> other; };
780
pyr_pool_compile_allocator(void)781 pyr_pool_compile_allocator(void) {}
782
pyr_pool_compile_allocator(pyr_pool_compile_allocator<U> const &)783 template <class U> pyr_pool_compile_allocator(pyr_pool_compile_allocator<U> const&) {}
784
address(reference x) const785 pointer address(reference x) const { return &x; }
786
address(const_reference x) const787 const_pointer address(const_reference x) const { return &x; }
788
allocate(size_type n,const void * hint=nullptr)789 pointer allocate(size_type n, const void* hint = nullptr) {
790 return (pointer)pyr_pool_compile->Alloc(n * sizeof(T));
791 }
792
deallocate(pointer p,size_type n)793 void deallocate(pointer p, size_type n) { pyr_pool_compile->Free(p); }
794
construct(pointer p,const T & val)795 void construct(pointer p, const T& val) { ::new (p) T(val); }
796
destroy(pointer p)797 void destroy(pointer p) { p->~T(); }
798 };
799
800
801 /* sort list of classes:
802 * we fill a binary search tree
803 *
804 */
sortClasses(PyrClass * aClassList)805 static PyrClass* sortClasses(PyrClass* aClassList) {
806 typedef std::set<PyrClass*, compareByName, pyr_pool_compile_allocator<PyrClass*>> classSetType;
807 classSetType classSet;
808
809 PyrClass* insertHead = aClassList;
810 do {
811 assert(classSet.find(insertHead) == classSet.end());
812 classSet.insert(insertHead);
813 insertHead = slotRawClass(&insertHead->nextclass);
814 } while (insertHead);
815
816 classSetType::iterator it = classSet.begin();
817 PyrClass* sortedClasses = *it;
818 ++it;
819
820 PyrClass* lastClass = sortedClasses;
821 for (; it != classSet.end(); ++it) {
822 PyrClass* current = *it;
823 SetObject(&lastClass->nextclass, (PyrObject*)current);
824 lastClass = current;
825 }
826 SetNil(&lastClass->nextclass);
827 return sortedClasses;
828 }
829
830
buildClassTree()831 void buildClassTree() {
832 // after all classes are compiled this function builds the tree and
833 // indexes the classes
834
835 // count subclasses
836 // postfl("count subclasses\n");
837 PyrClass* classobj = gClassList;
838 while (classobj) {
839 PyrClass* superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
840 if (superclassobj) {
841 // postfl(" superclassobj %s\n", slotRawSymbol(&superclassobj->name)->name);
842 SetRaw(&superclassobj->subclasses, slotRawInt(&superclassobj->subclasses) + 1);
843 }
844 classobj = slotRawClass(&classobj->nextclass);
845 }
846 // allocate subclass arrays
847 // postfl("allocate subclass arrays\n");
848 classobj = gClassList;
849 while (classobj) {
850 int numSubclasses;
851 numSubclasses = slotRawInt(&classobj->subclasses);
852 // postfl(" %s %d\n", slotRawSymbol(&classobj->name)->name, numSubclasses);
853 if (numSubclasses) {
854 SetObject(&classobj->subclasses,
855 (PyrObject*)newPyrArray(nullptr, numSubclasses, obj_permanent | obj_immutable, false));
856 slotRawObject(&classobj->subclasses)->size = 0;
857 } else {
858 SetNil(&classobj->subclasses);
859 }
860 classobj = slotRawClass(&classobj->nextclass);
861 }
862 // fill in subclass arrays
863 // postfl("fill in subclass arrays\n");
864 classobj = gClassList;
865 while (classobj) {
866 // postfl(" %s\n", slotRawSymbol(&classobj->name)->name);
867 PyrClass* superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
868 if (superclassobj) {
869 objAddIndexedObject(slotRawObject(&superclassobj->subclasses), (PyrObject*)classobj);
870 // postfl(" superclassobj %s %d\n", slotRawSymbol(&superclassobj->name)->name,
871 // slotRawObject(&superclassobj->subclasses)->size);
872 }
873 classobj = slotRawClass(&classobj->nextclass);
874 }
875
876 // alpha sort the classes via insertion sort
877 gClassList = sortClasses(gClassList);
878 }
879
indexClassTree(PyrClass * classobj,int numSuperMethods)880 void indexClassTree(PyrClass* classobj, int numSuperMethods) {
881 int i, numMethods;
882
883 if (!classobj)
884 return;
885
886 SetInt(&classobj->classIndex, gNumClasses);
887 gNumClasses++;
888
889 if (IsObj(&classobj->methods)) {
890 PyrObject* methods = slotRawObject(&classobj->methods);
891 numMethods = methods->size;
892 } else
893 numMethods = 0;
894
895 numMethods = numSuperMethods + numMethods;
896 if (IsObj(&classobj->subclasses)) {
897 PyrObject* subclasses = slotRawObject(&classobj->subclasses);
898 for (i = 0; i < subclasses->size; ++i)
899 indexClassTree(slotRawClass(&subclasses->slots[i]), numMethods);
900 }
901 SetInt(&classobj->maxSubclassIndex, gNumClasses - 1);
902 }
903
904 void findDiscrepancy();
findDiscrepancy()905 void findDiscrepancy() {
906 PyrClass *classobjA, *classobjB;
907
908 classobjA = gClassList;
909 while (classobjA) {
910 classobjB = slotRawClass(&classobjA->nextclass);
911 ;
912 while (classobjB) {
913 if (slotRawSymbol(&classobjA->name) == slotRawSymbol(&classobjB->name)) {
914 post("duplicate %s\n", slotRawSymbol(&classobjA->name)->name);
915 }
916 classobjB = slotRawClass(&classobjB->nextclass);
917 }
918 classobjA = slotRawClass(&classobjA->nextclass);
919 }
920 }
921
922
indent(int n)923 static void indent(int n) {
924 for (int i = 0; i < n; ++i) {
925 post(" ");
926 }
927 }
928
postClassTree(PyrClass * classobj,int level)929 void postClassTree(PyrClass* classobj, int level) {
930 PyrObject* subclasses;
931 int i;
932
933 // post("%4d ", slotRawInt(&classobj->classIndex));
934 indent(level);
935 post("%s\n", slotRawSymbol(&classobj->name)->name);
936
937 if (classobj == class_class) {
938 indent(level + 1);
939 post(" [.. all metaclasses ..]\n");
940 } else {
941 if (IsNil(&classobj->subclasses))
942 return; // FIXME: can we initialize subclasses with a NULL pointer?
943 subclasses = slotRawObject(&classobj->subclasses);
944 if (subclasses) {
945 // determine if can put on one line
946 bool oneline = subclasses->size <= 5;
947 for (i = 0; oneline && i < subclasses->size; ++i) {
948 PyrClass* subclassobj = slotRawClass(&subclasses->slots[i]);
949 if (IsObj(&subclassobj->subclasses))
950 // FIXME: shall we do a null-pointer check?
951 oneline = false;
952 }
953 if (oneline) {
954 indent(level + 1);
955 post("[");
956 for (i = 0; i < subclasses->size; ++i) {
957 PyrClass* subclassobj = slotRawClass(&subclasses->slots[i]);
958 post(" %s", slotRawSymbol(&subclassobj->name)->name);
959 }
960 post(" ]\n");
961 } else {
962 indent(level);
963 post("[\n");
964 for (i = 0; i < subclasses->size; ++i) {
965 postClassTree(slotRawClass(&subclasses->slots[i]), level + 1);
966 }
967 indent(level);
968 post("]\n");
969 }
970 }
971 }
972 }
973
974
setSelectorFlags()975 void setSelectorFlags() {
976 int i;
977
978 PyrClass* classobj = gClassList;
979 while (classobj) {
980 if (IsObj(&classobj->methods)) {
981 PyrObject* methods = slotRawObject(&classobj->methods);
982 for (i = 0; i < methods->size; ++i) {
983 PyrMethod* method = slotRawMethod(&methods->slots[i]);
984 slotRawSymbol(&method->name)->flags |= sym_Selector;
985 // if (method->methType == methRedirect) {
986 // post("rd: %3d %s:%s\n", k++, slotRawSymbol(&classobj->name)->name,
987 // slotRawSymbol(&method->name)->name);
988 //}
989 }
990 }
991 classobj = slotRawClass(&classobj->nextclass);
992 }
993 // count selectors
994 gNumSelectors = 0;
995 SymbolTable* symbolTable = gMainVMGlobals->symbolTable;
996 for (int i = 0; i < symbolTable->TableSize(); ++i) {
997 PyrSymbol* sym = symbolTable->Get(i);
998 if (sym && (sym->flags & sym_Selector)) {
999 sym->u.index = gNumSelectors++;
1000 }
1001 }
1002 // post("gNumSelectors %d\n", gNumSelectors);
1003 }
1004
1005 // the chunky stuff can be commented back in for implementing a better
1006 // compression scheme. The Q&D method works fine for my small class tree for now.
1007
1008 typedef struct {
1009 PyrSymbol* selector;
1010 int minClassIndex;
1011 int maxClassIndex;
1012 int rowWidth;
1013 // int largestChunk;
1014 // int chunkOffset;
1015 int selectorIndex;
1016 int population;
1017 int rowOffset;
1018 } ColumnDescriptor;
1019
1020 int compareColDescs(const void* va, const void* vb);
compareColDescs(const void * va,const void * vb)1021 int compareColDescs(const void* va, const void* vb) {
1022 ColumnDescriptor* a = (ColumnDescriptor*)va;
1023 ColumnDescriptor* b = (ColumnDescriptor*)vb;
1024 int diff;
1025 // diff = b->largestChunk - a->largestChunk;
1026 // if (diff != 0) return diff;
1027 diff = b->rowWidth - a->rowWidth;
1028 if (diff != 0)
1029 return diff;
1030 // diff = b->chunkOffset - a->chunkOffset;
1031 diff = b->minClassIndex - a->minClassIndex;
1032 return diff;
1033 }
1034
1035 #define CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME 0
1036 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1037 double elapsedTime();
1038 #endif
1039
1040 #ifdef _MSC_VER
1041 static size_t fillClassRows(const PyrClass* classobj, PyrMethod** bigTable);
1042 #else
1043 static size_t fillClassRows(const PyrClass* classobj, PyrMethod** bigTable, boost::basic_thread_pool& pool);
1044 #endif
1045
1046
binsortClassRows(PyrMethod const ** bigTable,const ColumnDescriptor * sels,size_t numSelectors,size_t begin,size_t end)1047 static void binsortClassRows(PyrMethod const** bigTable, const ColumnDescriptor* sels, size_t numSelectors,
1048 size_t begin, size_t end) {
1049 // bin sort the class rows to the new ordering
1050 // post("reorder rows\n");
1051 const int allocaThreshold = 16384;
1052 PyrMethod** temprow = (numSelectors < allocaThreshold) ? (PyrMethod**)alloca(numSelectors * sizeof(PyrMethod*))
1053 : (PyrMethod**)malloc(numSelectors * sizeof(PyrMethod*));
1054
1055 for (int j = begin; j < end; ++j) {
1056 PyrMethod const** row = bigTable + j * numSelectors;
1057 memcpy(temprow, row, numSelectors * sizeof(PyrMethod*));
1058
1059 #pragma GCC ivdep
1060 for (int i = 0; i < numSelectors; ++i)
1061 row[i] = temprow[sels[i].selectorIndex];
1062 }
1063
1064 if (numSelectors >= allocaThreshold)
1065 free(temprow);
1066 }
1067
prepareColumnTable(ColumnDescriptor * sels,int numSelectors)1068 static ColumnDescriptor* prepareColumnTable(ColumnDescriptor* sels, int numSelectors) {
1069 // fill selector table
1070 // post("fill selector table\n");
1071 SymbolTable* symbolTable = gMainVMGlobals->symbolTable;
1072
1073 int selectorTableIndex = 0;
1074 for (int i : boost::irange(0, symbolTable->TableSize())) {
1075 PyrSymbol* sym = symbolTable->Get(i);
1076 if (sym && (sym->flags & sym_Selector))
1077 sels[selectorTableIndex++].selector = sym;
1078 }
1079 assert(selectorTableIndex == numSelectors);
1080
1081 for (int i = 0; i < numSelectors; ++i) {
1082 // postfl("%3d %s\n", i, sels[i].selector->name);
1083 sels[i].minClassIndex = INT_MAX;
1084 sels[i].maxClassIndex = 0;
1085 // sels[i].largestChunk = 0;
1086 // sels[i].chunkOffset = 0;
1087 sels[i].selectorIndex = i;
1088 sels[i].population = 0;
1089 }
1090 return sels;
1091 }
1092
1093
calcRowStats(PyrMethod const * const * bigTable,ColumnDescriptor * sels,int numClasses,int numSelectors,int begin,int end)1094 static void calcRowStats(PyrMethod const* const* bigTable, ColumnDescriptor* sels, int numClasses, int numSelectors,
1095 int begin, int end) {
1096 // chunkSize = 0;
1097 // chunkOffset = 0;
1098 for (int classIndex = 0; classIndex < numClasses; ++classIndex) {
1099 for (int selectorIndex = begin; selectorIndex < end; ++selectorIndex) {
1100 PyrMethod const* method = bigTable[classIndex * numSelectors + selectorIndex];
1101 if (method) {
1102 // classobj = method->ownerclass.uoc;
1103 if (classIndex > sels[selectorIndex].maxClassIndex)
1104 sels[selectorIndex].maxClassIndex = classIndex;
1105
1106 if (classIndex < sels[selectorIndex].minClassIndex)
1107 sels[selectorIndex].minClassIndex = classIndex;
1108
1109 sels[selectorIndex].population++;
1110 // if (chunkSize == 0) chunkOffset = j;
1111 // chunkSize++;
1112 // postfl(" %8s %3d %3d %3d %3d\n", slotRawSymbol(&classobj->name)->name, i, j,
1113 // chunkSize, slotRawInt(&classobj->classIndex));
1114 //} else {
1115 // if (chunkSize > sels[i].largestChunk) {
1116 // sels[i].largestChunk = chunkSize;
1117 // sels[i].chunkOffset = chunkOffset;
1118 //}
1119 // chunkSize = 0;
1120 }
1121 }
1122 }
1123
1124 for (int i = begin; i < end; ++i)
1125 sels[i].rowWidth = sels[i].maxClassIndex - sels[i].minClassIndex + 1;
1126 }
1127
buildBigMethodMatrix()1128 void buildBigMethodMatrix() {
1129 PyrMethod **bigTable, **row;
1130 PyrClass** classes;
1131 int j, k;
1132 int popSum, widthSum;
1133 int rowOffset, freeIndex;
1134 int rowTableSize;
1135 int bigTableSize;
1136 const size_t numSelectors = gNumSelectors;
1137 const size_t numClasses = gNumClasses;
1138 // post("allocate arrays\n");
1139
1140 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1141 double t0 = elapsedTime();
1142 #endif
1143
1144 const int hw_concurrency = SC_Thread::hardware_concurrency();
1145 const int cpuCount = hw_concurrency > 0 ? hw_concurrency : 1;
1146 const int helperThreadCount = cpuCount > 1 ? cpuCount - 1 : 1;
1147 boost::basic_thread_pool pool(helperThreadCount);
1148
1149 // pyrmalloc:
1150 // lifetime: kill after compile
1151 bigTableSize = numSelectors * numClasses;
1152 // post("bigTableSize %d %d %d\n", bigTableSize, numSelectors, numClasses);
1153 ColumnDescriptor* sels = (ColumnDescriptor*)pyr_pool_compile->Alloc(numSelectors * sizeof(ColumnDescriptor));
1154 MEMFAIL(sels);
1155 #ifdef _MSC_VER
1156 auto filledSelectorsFuture = std::async(std::launch::deferred, std::bind(&prepareColumnTable, sels, numSelectors));
1157 #else
1158 auto filledSelectorsFuture = boost::async(pool, std::bind(&prepareColumnTable, sels, numSelectors));
1159 #endif
1160
1161 classes = (PyrClass**)pyr_pool_compile->Alloc(numClasses * sizeof(PyrClass*));
1162 MEMFAIL(classes);
1163
1164 auto fillClassIndices = [](PyrClass** classes) {
1165 PyrClass* classobj = gClassList;
1166 while (classobj) {
1167 classes[slotRawInt(&classobj->classIndex)] = classobj;
1168 classobj = slotRawClass(&classobj->nextclass);
1169 }
1170 return classes;
1171 };
1172 #ifdef _MSC_VER
1173 auto filledClassIndices = std::async(std::launch::deferred, fillClassIndices, classes);
1174 #else
1175 auto filledClassIndices = boost::async(pool, fillClassIndices, classes);
1176 #endif
1177
1178 bigTable = (PyrMethod**)pyr_pool_compile->Alloc(bigTableSize * sizeof(PyrMethod*));
1179 MEMFAIL(bigTable);
1180
1181 #ifndef _MSC_VER
1182 pool.try_executing_one();
1183 #endif
1184 filledClassIndices.wait();
1185 #ifdef _MSC_VER
1186 size_t numentries = fillClassRows(class_object, bigTable);
1187 #else
1188 size_t numentries = fillClassRows(class_object, bigTable, pool);
1189 #endif
1190 post("\tnumentries = %lu / %d = %.2g\n", numentries, bigTableSize, (double)numentries / (double)bigTableSize);
1191
1192
1193 ColumnDescriptor* filledSelectors = filledSelectorsFuture.get();
1194 #ifdef _MSC_VER
1195 std::vector<std::future<void>> columnDescriptorsWithStats;
1196 #else
1197 std::vector<boost::future<void>> columnDescriptorsWithStats;
1198 #endif
1199 size_t selectorsPerJob = numSelectors / cpuCount / 2;
1200 for (size_t beginSelectorIndex : boost::irange(selectorsPerJob, numSelectors, selectorsPerJob)) {
1201 size_t endSelectorIndex = std::min(beginSelectorIndex + selectorsPerJob, numSelectors);
1202 #ifdef _MSC_VER
1203 auto future = std::async(std::launch::deferred, calcRowStats, bigTable, filledSelectors, numClasses,
1204 numSelectors, beginSelectorIndex, endSelectorIndex);
1205 #else
1206 auto future = boost::async(pool, calcRowStats, bigTable, filledSelectors, numClasses, numSelectors,
1207 beginSelectorIndex, endSelectorIndex);
1208 #endif
1209 columnDescriptorsWithStats.push_back(std::move(future));
1210 }
1211
1212 calcRowStats(bigTable, filledSelectors, numClasses, numSelectors, 0, std::min(selectorsPerJob, numSelectors));
1213
1214 for (auto& future : columnDescriptorsWithStats) {
1215 #ifdef _MSC_VER
1216 future.wait();
1217 #else
1218 while (!future.is_ready())
1219 pool.schedule_one_or_yield();
1220 #endif
1221 }
1222
1223 // post("qsort\n");
1224 // sort rows by largest chunk, then by width, then by chunk offset
1225
1226 #if 0 // not yet
1227 __gnu_parallel::sort(sels, sels + numSelectors, [](ColumnDescriptor const & rhs, ColumnDescriptor const & lhs) {
1228 return compareColDescs(&rhs, &lhs) < 0;
1229 });
1230 #else
1231 std::sort(sels, sels + numSelectors,
1232 [](ColumnDescriptor const& rhs, ColumnDescriptor const& lhs) { return compareColDescs(&rhs, &lhs) < 0; });
1233 #endif
1234
1235 // bin sort the class rows to the new ordering
1236 // post("reorder rows\n");
1237 #ifdef _MSC_VER
1238 std::vector<std::future<void>> binsortedClassRowFuture;
1239 #else
1240 std::vector<boost::future<void>> binsortedClassRowFuture;
1241 #endif
1242 size_t classesPerJob = numClasses / cpuCount / 2;
1243 for (size_t beginClassIndex : boost::irange(classesPerJob, numClasses, classesPerJob)) {
1244 size_t endClassIndex = std::min(beginClassIndex + classesPerJob, numClasses);
1245 #ifdef _MSC_VER
1246 auto future = std::async(std::launch::deferred, binsortClassRows, (PyrMethod const**)bigTable, sels,
1247 numSelectors, beginClassIndex, endClassIndex);
1248 #else
1249 auto future = boost::async(pool, binsortClassRows, (PyrMethod const**)bigTable, sels, numSelectors,
1250 beginClassIndex, endClassIndex);
1251 #endif
1252 binsortedClassRowFuture.push_back(std::move(future));
1253 }
1254
1255 binsortClassRows((PyrMethod const**)bigTable, sels, numSelectors, 0, std::min(classesPerJob, numClasses));
1256
1257 for (auto& future : binsortedClassRowFuture) {
1258 #ifdef _MSC_VER
1259 future.wait();
1260 #else
1261 while (!future.is_ready())
1262 pool.schedule_one_or_yield();
1263 #endif
1264 }
1265
1266 // post("calc row offsets %d\n", numSelectors);
1267 widthSum = 0;
1268 popSum = 0;
1269 freeIndex = 0;
1270 rowOffset = -1;
1271 for (int i = 0; i < numSelectors; ++i) {
1272 widthSum += sels[i].rowWidth;
1273 popSum += sels[i].population;
1274 rowOffset = sc_max(rowOffset + 1, freeIndex - sels[i].minClassIndex);
1275 freeIndex = rowOffset + sels[i].maxClassIndex + 1;
1276 sels[i].rowOffset = rowOffset;
1277 sels[i].selector->u.index = rowOffset;
1278 // post("%3d %24s %3d %5d %5d\n", i, sels[i].selector->name,
1279 // sels[i].rowWidth, rowOffset, freeIndex);
1280 }
1281 // post("alloc row table %d\n", freeIndex);
1282 rowTableSize = (freeIndex + numClasses) * sizeof(PyrMethod*);
1283 gRowTable = (PyrMethod**)pyr_pool_runtime->Alloc(rowTableSize);
1284 MEMFAIL(gRowTable);
1285
1286 // having the method ptr always be valid saves a branch in SendMessage()
1287 for (int i = 0; i < freeIndex + numClasses; ++i)
1288 gRowTable[i] = gNullMethod;
1289
1290 // post("fill compressed table\n");
1291 //{ FILE* fp;
1292 // newPyrMethod
1293 // fp = fopen("meth table", "w");
1294 for (int i = 0; i < numSelectors; ++i) {
1295 int offset, maxwidth;
1296 offset = sels[i].rowOffset + sels[i].minClassIndex;
1297 maxwidth = offset + sels[i].rowWidth;
1298 row = bigTable + sels[i].minClassIndex * numSelectors + i;
1299 PyrMethod** table = gRowTable;
1300 for (j = offset, k = 0; j < maxwidth; ++j, k += numSelectors) {
1301 if (row[k])
1302 table[j] = row[k];
1303 }
1304 }
1305 // fclose(fp);
1306 //}
1307
1308 for (int i = 0; i < freeIndex + numClasses; ++i)
1309 assert(gRowTable[i]);
1310
1311
1312 // post("freeIndex %d\n", freeIndex);
1313 // post("widthSum %d\n", widthSum);
1314 // post("popSum %d\n", popSum);
1315
1316 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1317 post("building table took %.3g seconds\n", elapsedTime() - t0);
1318 {
1319 int numFilled = 0;
1320 for (int i = 0; i < rowTableSize / sizeof(PyrMethod*); ++i) {
1321 if (gRowTable[i] != gNullMethod)
1322 numFilled++;
1323 }
1324 post("Filled %d of %d = %f percent\n", numFilled, rowTableSize / sizeof(PyrMethod*),
1325 100. * (double)numFilled / (rowTableSize / sizeof(PyrMethod*)));
1326 }
1327 #endif
1328 post("\t%d method selectors, %d classes\n", numSelectors, numClasses);
1329 post("\tmethod table size %d bytes, ", rowTableSize);
1330 post("big table size %d\n", numSelectors * numClasses * sizeof(PyrMethod*));
1331 // postfl("%p %p %p\n", classes, bigTable, sels);
1332 /*
1333 // not necessary since the entire pool will be freed..
1334 pyr_pool_compile->Free(classes);
1335 pyr_pool_compile->Free(bigTable);
1336 pyr_pool_compile->Free(sels);
1337 */
1338 }
1339
1340 #ifdef _MSC_VER
fillClassRow(const PyrClass * classobj,PyrMethod ** bigTable)1341 static size_t fillClassRow(const PyrClass* classobj, PyrMethod** bigTable)
1342 #else
1343 static size_t fillClassRow(const PyrClass* classobj, PyrMethod** bigTable, boost::basic_thread_pool& pool)
1344 #endif
1345 {
1346 size_t count = 0;
1347
1348 PyrMethod** myrow = bigTable + slotRawInt(&classobj->classIndex) * gNumSelectors;
1349 PyrClass* superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
1350 if (superclassobj) {
1351 PyrMethod** superrow = bigTable + slotRawInt(&superclassobj->classIndex) * gNumSelectors;
1352
1353 #pragma GCC ivdep
1354 for (int i = 0; i != gNumSelectors; ++i) {
1355 myrow[i] = superrow[i];
1356 if (superrow[i])
1357 ++count;
1358 }
1359
1360 } else {
1361 memset(myrow, 0, gNumSelectors * sizeof(PyrMethod*));
1362 }
1363
1364 if (IsObj(&classobj->methods)) {
1365 PyrObject* methods = const_cast<PyrObject*>(slotRawObject(&classobj->methods));
1366 // postfl(" %d\n", methods->size);
1367 for (int i = 0; i < methods->size; ++i) {
1368 PyrMethod* method = slotRawMethod(&methods->slots[i]);
1369 int selectorIndex = slotRawSymbol(&method->name)->u.index;
1370
1371 if (myrow[selectorIndex] == nullptr)
1372 ++count;
1373
1374 myrow[selectorIndex] = method;
1375 }
1376 }
1377
1378 size_t result = count;
1379
1380 if (IsObj(&classobj->subclasses)) {
1381 const PyrObject* subclasses = slotRawObject(&classobj->subclasses);
1382 int numSubclasses = subclasses->size;
1383
1384 if (numSubclasses) {
1385 #ifdef _MSC_VER
1386 if (numSubclasses <= 2) {
1387 for (int subClassIndex : boost::irange(0, numSubclasses))
1388 result += fillClassRow(slotRawClass(&subclasses->slots[subClassIndex]), bigTable);
1389 } else {
1390 typedef std::vector<std::future<size_t>> VectorOfFutures;
1391
1392 VectorOfFutures subclassResults;
1393 for (int subClassIndex : boost::irange(1, numSubclasses)) {
1394 auto subclassResult = std::async(std::launch::deferred, fillClassRow,
1395 slotRawClass(&subclasses->slots[subClassIndex]), bigTable);
1396 subclassResults.emplace_back(std::move(subclassResult));
1397 }
1398
1399 result += fillClassRow(slotRawClass(&subclasses->slots[0]), bigTable);
1400
1401 for (auto& subclassResult : subclassResults) {
1402 result += subclassResult.get();
1403 }
1404 }
1405 #else
1406 if (numSubclasses <= 2) {
1407 for (int subClassIndex : boost::irange(0, numSubclasses))
1408 result += fillClassRow(slotRawClass(&subclasses->slots[subClassIndex]), bigTable, pool);
1409 } else {
1410 typedef std::vector<boost::future<size_t>> VectorOfFutures;
1411
1412 VectorOfFutures subclassResults;
1413 for (int subClassIndex : boost::irange(1, numSubclasses)) {
1414 auto subclassResult =
1415 boost::async(pool, fillClassRow, slotRawClass(&subclasses->slots[subClassIndex]), bigTable,
1416 boost::ref(pool));
1417 subclassResults.emplace_back(std::move(subclassResult));
1418 }
1419
1420 result += fillClassRow(slotRawClass(&subclasses->slots[0]), bigTable, pool);
1421
1422 for (auto& subclassResult : subclassResults) {
1423 while (!subclassResult.is_ready())
1424 pool.schedule_one_or_yield();
1425
1426 result += subclassResult.get();
1427 }
1428 }
1429 #endif
1430 }
1431 }
1432
1433 return result;
1434 }
1435
1436 #ifdef _MSC_VER
fillClassRows(const PyrClass * classobj,PyrMethod ** bigTable)1437 static size_t fillClassRows(const PyrClass* classobj, PyrMethod** bigTable) { return fillClassRow(classobj, bigTable); }
1438 #else
fillClassRows(const PyrClass * classobj,PyrMethod ** bigTable,boost::basic_thread_pool & pool)1439 static size_t fillClassRows(const PyrClass* classobj, PyrMethod** bigTable, boost::basic_thread_pool& pool) {
1440 return fillClassRow(classobj, bigTable, pool);
1441 }
1442 #endif
1443
funcFindArg(PyrBlock * func,PyrSymbol * name,int * index)1444 bool funcFindArg(PyrBlock* func, PyrSymbol* name, int* index) {
1445 int i;
1446 for (i = 0; i < slotRawSymbolArray(&func->argNames)->size; ++i) {
1447 if (slotRawSymbolArray(&func->argNames)->symbols[i] == name) {
1448 *index = i;
1449 return true;
1450 }
1451 }
1452 return false;
1453 }
1454
funcFindVar(PyrBlock * func,PyrSymbol * name,int * index)1455 bool funcFindVar(PyrBlock* func, PyrSymbol* name, int* index) {
1456 int i;
1457 for (i = 0; i < slotRawSymbolArray(&func->varNames)->size; ++i) {
1458 if (slotRawSymbolArray(&func->varNames)->symbols[i] == name) {
1459 *index = i;
1460 return true;
1461 }
1462 }
1463 return false;
1464 }
1465
makeIntrinsicClass(PyrSymbol * className,PyrSymbol * superClassName,int numInstVars,int numClassVars)1466 PyrClass* makeIntrinsicClass(PyrSymbol* className, PyrSymbol* superClassName, int numInstVars, int numClassVars) {
1467 PyrClass* superClass = nullptr;
1468 PyrClass* metaSuperClass = nullptr;
1469 PyrSymbol* metaClassName = nullptr;
1470 PyrSymbol* metaSuperClassName = nullptr;
1471 PyrClass* classobj = nullptr;
1472 PyrClass* metaclassobj = nullptr;
1473 int superInstVars;
1474
1475 // postfl("makeIntrinsicClass '%s'\n", className->name);
1476 if (superClassName) {
1477 superClass = superClassName->u.classobj;
1478 if (!superClass) {
1479 error("Can't find superclass '%s' of '%s'\n", superClassName->name, className->name);
1480 return nullptr;
1481 }
1482 metaSuperClassName = getmetasym(superClassName->name);
1483 metaSuperClass = metaSuperClassName->u.classobj;
1484 superInstVars = numSuperInstVars(superClass);
1485 } else {
1486 // else it must be Object and so has no superclass
1487 metaSuperClassName = nullptr;
1488 superInstVars = 0;
1489 }
1490
1491 metaClassName = getmetasym(className->name);
1492 metaClassName->flags |= sym_MetaClass;
1493 metaclassobj =
1494 newClassObj(class_class, metaClassName, metaSuperClassName, classClassNumInstVars, 0, 0, 0, obj_notindexed, 0);
1495 SetInt(&metaclassobj->classFlags, slotRawInt(&metaclassobj->classFlags) | classIsIntrinsic);
1496
1497 if (metaSuperClassName && classClassNumInstVars) {
1498 memcpy(slotRawObject(&metaclassobj->iprototype)->slots, slotRawObject(&metaSuperClass->iprototype)->slots,
1499 sizeof(PyrSlot) * classClassNumInstVars);
1500 memcpy(slotRawSymbolArray(&metaclassobj->instVarNames)->symbols,
1501 slotRawSymbolArray(&metaSuperClass->instVarNames)->symbols, sizeof(PyrSymbol*) * classClassNumInstVars);
1502 slotRawObject(&metaclassobj->iprototype)->size = classClassNumInstVars;
1503 slotRawObject(&metaclassobj->instVarNames)->size = classClassNumInstVars;
1504 // dumpObject((PyrObject*)metaclassobj);
1505 }
1506
1507 classobj = newClassObj(metaclassobj, className, superClassName, numInstVars + superInstVars, numClassVars, 0, 0,
1508 obj_notindexed, 0);
1509 SetInt(&classobj->classFlags, slotRawInt(&classobj->classFlags) | classIsIntrinsic);
1510
1511 // postfl("%s:%s : %d\n", className->name, superClassName->name, superInstVars);
1512 if (superClass && superInstVars) {
1513 memcpy(slotRawObject(&classobj->iprototype)->slots, slotRawObject(&superClass->iprototype)->slots,
1514 sizeof(PyrSlot) * superInstVars);
1515 memcpy(slotRawSymbolArray(&classobj->instVarNames)->symbols,
1516 slotRawSymbolArray(&superClass->instVarNames)->symbols, sizeof(PyrSymbol*) * superInstVars);
1517 slotRawObject(&classobj->iprototype)->size = superInstVars;
1518 slotRawObject(&classobj->instVarNames)->size = superInstVars;
1519 }
1520
1521 return classobj;
1522 }
1523
addIntrinsicVar(PyrClass * classobj,const char * varName,PyrSlot * slot)1524 void addIntrinsicVar(PyrClass* classobj, const char* varName, PyrSlot* slot) {
1525 // postfl("%s %s %d\n", slotRawSymbol(&classobj->name)->name, varName,
1526 // slotRawObject(&classobj->instVarNames)->size);
1527 objAddIndexedSymbol(slotRawSymbolArray(&classobj->instVarNames), getsym(varName));
1528 objAddIndexedSlot(slotRawObject(&classobj->iprototype), slot);
1529 }
1530
1531 void addIntrinsicClassVar(PyrClass* classobj, const char* varName, PyrSlot* slot);
addIntrinsicClassVar(PyrClass * classobj,const char * varName,PyrSlot * slot)1532 void addIntrinsicClassVar(PyrClass* classobj, const char* varName, PyrSlot* slot) {
1533 // postfl("%s %s %d\n", slotRawSymbol(&classobj->name)->name, varName,
1534 // slotRawObject(&classobj->instVarNames)->size);
1535 objAddIndexedSymbol(slotRawSymbolArray(&classobj->classVarNames), getsym(varName));
1536 objAddIndexedSlot(slotRawObject(&classobj->cprototype), slot);
1537 }
1538
initClasses()1539 void initClasses() {
1540 PyrClass* class_object_meta;
1541 PyrMethodRaw* methraw;
1542
1543 // BOOTSTRAP THE OBJECT HIERARCHY
1544
1545 gNumClassVars = 0;
1546 gClassList = nullptr;
1547 gNullMethod = newPyrMethod();
1548 SetSymbol(&gNullMethod->name, (PyrSymbol*)nullptr);
1549 methraw = METHRAW(gNullMethod);
1550 methraw->methType = methNormal;
1551
1552 // build intrinsic classes
1553 class_class = nullptr;
1554 class_object = makeIntrinsicClass(s_object, nullptr, 0, 4);
1555 class_class = makeIntrinsicClass(s_class, s_object, classClassNumInstVars, 1);
1556
1557 // now fix class_class ptrs that were just previously installed erroneously
1558 class_object->classptr->classptr = class_class;
1559 class_class->classptr->classptr = class_class;
1560 class_object_meta = class_object->classptr;
1561 class_object_meta->superclass = class_class->name;
1562
1563 addIntrinsicClassVar(class_object, "dependantsDictionary", &o_nil);
1564 addIntrinsicClassVar(class_object, "currentEnvironment", &o_nil);
1565 addIntrinsicClassVar(class_object, "topEnvironment", &o_nil);
1566 addIntrinsicClassVar(class_object, "uniqueMethods", &o_nil);
1567
1568 // declare varNames for Class
1569
1570 addIntrinsicVar(class_class, "name", &o_nil);
1571 addIntrinsicVar(class_class, "nextclass", &o_nil);
1572 addIntrinsicVar(class_class, "superclass", &o_nil);
1573 addIntrinsicVar(class_class, "subclasses", &o_nil);
1574 addIntrinsicVar(class_class, "methods", &o_nil);
1575
1576 addIntrinsicVar(class_class, "instVarNames", &o_nil);
1577 addIntrinsicVar(class_class, "classVarNames", &o_nil);
1578 addIntrinsicVar(class_class, "iprototype", &o_nil);
1579 addIntrinsicVar(class_class, "cprototype", &o_nil);
1580
1581 addIntrinsicVar(class_class, "constNames", &o_nil);
1582 addIntrinsicVar(class_class, "constValues", &o_nil);
1583
1584 addIntrinsicVar(class_class, "instanceFormat", &o_nil);
1585 addIntrinsicVar(class_class, "instanceFlags", &o_zero);
1586 addIntrinsicVar(class_class, "classIndex", &o_zero);
1587 addIntrinsicVar(class_class, "classFlags", &o_zero);
1588 addIntrinsicVar(class_class, "maxSubclassIndex", &o_zero);
1589 addIntrinsicVar(class_class, "filenameSymbol", &o_nil);
1590 addIntrinsicVar(class_class, "charPos", &o_zero);
1591 addIntrinsicVar(class_class, "classVarIndex", &o_zero);
1592
1593 addIntrinsicClassVar(class_class, "classesInited", &o_nil);
1594
1595 // class_object_meta's inst var names need to be copied from class_class
1596 // because class_class didn't exist when it was created
1597 memcpy(slotRawObject(&class_object_meta->iprototype)->slots, slotRawObject(&class_class->iprototype)->slots,
1598 sizeof(PyrSlot) * classClassNumInstVars);
1599 memcpy(slotRawSymbolArray(&class_object_meta->instVarNames)->symbols,
1600 slotRawSymbolArray(&class_class->instVarNames)->symbols, sizeof(PyrSymbol*) * classClassNumInstVars);
1601
1602 memcpy(slotRawObject(&class_class->classptr->iprototype)->slots, slotRawObject(&class_class->iprototype)->slots,
1603 sizeof(PyrSlot) * classClassNumInstVars);
1604 memcpy(slotRawSymbolArray(&class_class->classptr->instVarNames)->symbols,
1605 slotRawSymbolArray(&class_class->instVarNames)->symbols, sizeof(PyrSymbol*) * classClassNumInstVars);
1606
1607
1608 // OK the next thing I need is arrays..
1609 class_collection = makeIntrinsicClass(s_collection, s_object, 0, 0);
1610 class_sequenceable_collection = makeIntrinsicClass(s_sequenceable_collection, s_collection, 0, 0);
1611
1612 class_arrayed_collection = makeIntrinsicClass(s_arrayed_collection, s_sequenceable_collection, 0, 0);
1613 class_array = makeIntrinsicClass(s_array, s_arrayed_collection, 0, 0);
1614 SetInt(&class_array->instanceFormat, obj_slot);
1615 SetInt(&class_array->classFlags, slotRawInt(&class_array->classFlags) | classHasIndexableInstances);
1616
1617 // now fix array classptrs in already created classes
1618 fixClassArrays(class_class);
1619 fixClassArrays(class_class->classptr);
1620 fixClassArrays(class_object_meta);
1621 fixClassArrays(class_collection);
1622 fixClassArrays(class_sequenceable_collection);
1623 fixClassArrays(class_arrayed_collection);
1624 fixClassArrays(class_array);
1625
1626 class_fundef = makeIntrinsicClass(s_fundef, s_object, 10, 0);
1627 // declare varNames for Block
1628
1629 addIntrinsicVar(class_fundef, "raw1", &o_nil);
1630 addIntrinsicVar(class_fundef, "raw2", &o_nil);
1631 addIntrinsicVar(class_fundef, "code", &o_nil);
1632 addIntrinsicVar(class_fundef, "selectors", &o_nil);
1633 addIntrinsicVar(class_fundef, "constants", &o_nil);
1634
1635 addIntrinsicVar(class_fundef, "prototypeFrame", &o_nil);
1636 addIntrinsicVar(class_fundef, "context", &o_nil);
1637 addIntrinsicVar(class_fundef, "argNames", &o_nil);
1638 addIntrinsicVar(class_fundef, "varNames", &o_nil);
1639 addIntrinsicVar(class_fundef, "sourceCode", &o_nil);
1640
1641 class_method = makeIntrinsicClass(s_method, s_fundef, 5, 0);
1642 addIntrinsicVar(class_method, "ownerClass", &o_nil);
1643 addIntrinsicVar(class_method, "name", &o_nil);
1644 addIntrinsicVar(class_method, "primitiveName", &o_nil);
1645 addIntrinsicVar(class_method, "filenameSymbol", &o_nil);
1646 addIntrinsicVar(class_method, "charPos", &o_zero);
1647 // addIntrinsicVar(class_method, "byteMeter", &o_zero);
1648 // addIntrinsicVar(class_method, "callMeter", &o_zero);
1649
1650 class_frame = makeIntrinsicClass(s_frame, s_object, 0, 0);
1651 SetInt(&class_frame->classFlags, slotRawInt(&class_frame->classFlags) | classHasIndexableInstances);
1652 // addIntrinsicVar(class_frame, "method", &o_nil);
1653 // addIntrinsicVar(class_frame, "caller", &o_nil);
1654 // addIntrinsicVar(class_frame, "context", &o_nil);
1655 // addIntrinsicVar(class_frame, "homeContext", &o_nil);
1656 // addIntrinsicVar(class_frame, "ip", &o_nil);
1657
1658 class_process = makeIntrinsicClass(s_process, s_object, 6, 0);
1659 addIntrinsicVar(class_process, "classVars", &o_nil);
1660 addIntrinsicVar(class_process, "interpreter", &o_nil);
1661 addIntrinsicVar(class_process, "curThread", &o_nil);
1662 addIntrinsicVar(class_process, "mainThread", &o_nil);
1663 addIntrinsicVar(class_process, "schedulerQueue", &o_nil);
1664 addIntrinsicVar(class_process, "nowExecutingPath", &o_nil);
1665
1666 class_interpreter = makeIntrinsicClass(s_interpreter, s_object, 29, 0);
1667 addIntrinsicVar(class_interpreter, "cmdLine", &o_nil);
1668 addIntrinsicVar(class_interpreter, "context", &o_nil);
1669 for (int i = 0; i < 26; ++i) {
1670 char name[2];
1671 name[0] = 'a' + i;
1672 name[1] = 0;
1673 addIntrinsicVar(class_interpreter, name, &o_nil);
1674 }
1675 addIntrinsicVar(class_interpreter, "codeDump", &o_nil);
1676 addIntrinsicVar(class_interpreter, "preProcessor", &o_nil);
1677
1678 class_absfunc = makeIntrinsicClass(s_absfunc, s_object, 0, 0);
1679 class_stream = makeIntrinsicClass(s_stream, s_absfunc, 0, 0);
1680
1681 class_thread = makeIntrinsicClass(s_thread, s_stream, 27, 0);
1682 addIntrinsicVar(class_thread, "state", &o_nil);
1683 addIntrinsicVar(class_thread, "func", &o_nil);
1684 addIntrinsicVar(class_thread, "stack", &o_nil);
1685 addIntrinsicVar(class_thread, "method", &o_nil);
1686 addIntrinsicVar(class_thread, "block", &o_nil);
1687 addIntrinsicVar(class_thread, "frame", &o_nil);
1688 addIntrinsicVar(class_thread, "ip", &o_zero);
1689 addIntrinsicVar(class_thread, "sp", &o_zero);
1690 addIntrinsicVar(class_thread, "numpop", &o_zero);
1691 addIntrinsicVar(class_thread, "receiver", &o_nil);
1692 addIntrinsicVar(class_thread, "numArgsPushed", &o_zero);
1693 addIntrinsicVar(class_thread, "parent", &o_nil);
1694 addIntrinsicVar(class_thread, "terminalValue", &o_nil);
1695
1696 addIntrinsicVar(class_thread, "primitiveError", &o_zero);
1697 addIntrinsicVar(class_thread, "primitiveIndex", &o_zero);
1698 addIntrinsicVar(class_thread, "randData", &o_zero);
1699 addIntrinsicVar(class_thread, "beats", &o_fzero);
1700 addIntrinsicVar(class_thread, "seconds", &o_fzero);
1701 addIntrinsicVar(class_thread, "clock", &o_nil);
1702 addIntrinsicVar(class_thread, "nextBeat", &o_nil);
1703 addIntrinsicVar(class_thread, "endBeat", &o_nil);
1704 addIntrinsicVar(class_thread, "endValue", &o_nil);
1705
1706 addIntrinsicVar(class_thread, "environment", &o_nil);
1707 addIntrinsicVar(class_thread, "exceptionHandler", &o_nil);
1708 addIntrinsicVar(class_thread, "threadPlayer", &o_nil);
1709
1710 addIntrinsicVar(class_thread, "executingPath", &o_nil);
1711 addIntrinsicVar(class_thread, "oldExecutingPath", &o_nil);
1712
1713 class_finalizer = makeIntrinsicClass(s_finalizer, s_object, 2, 0);
1714 addIntrinsicVar(class_finalizer, "cFunction", &o_nil);
1715 addIntrinsicVar(class_finalizer, "object", &o_nil);
1716
1717 class_routine = makeIntrinsicClass(s_routine, s_thread, 0, 0);
1718
1719 class_symbol = makeIntrinsicClass(s_symbol, s_object, 0, 0);
1720 class_nil = makeIntrinsicClass(s_nil, s_object, 0, 0);
1721
1722 class_boolean = makeIntrinsicClass(s_boolean, s_object, 0, 0);
1723 class_true = makeIntrinsicClass(s_true, s_boolean, 0, 0);
1724 class_false = makeIntrinsicClass(s_false, s_boolean, 0, 0);
1725
1726 class_magnitude = makeIntrinsicClass(s_magnitude, s_object, 0, 0);
1727 class_char = makeIntrinsicClass(s_char, s_magnitude, 0, 0);
1728 class_number = makeIntrinsicClass(s_number, s_magnitude, 0, 0);
1729 class_simple_number = makeIntrinsicClass(s_simple_number, s_number, 0, 0);
1730 class_int = makeIntrinsicClass(s_int, s_simple_number, 0, 0);
1731 class_float = makeIntrinsicClass(s_float, s_simple_number, 0, 0);
1732
1733 class_rawptr = makeIntrinsicClass(s_rawptr, s_object, 0, 0);
1734
1735 /*
1736 class_complex = makeIntrinsicClass(s_complex, s_number, 2, 0);
1737 addIntrinsicVar(class_complex, "real", &o_nil);
1738 addIntrinsicVar(class_complex, "imag", &o_nil);
1739 */
1740
1741 class_rawarray = makeIntrinsicClass(s_rawarray, s_arrayed_collection, 0, 0);
1742 // SetInt(&class_rawarray->instanceFormat, obj_int8);
1743 // slotRawInt(&class_rawarray->classFlags) |= classHasIndexableInstances;
1744 class_int8array = makeIntrinsicClass(s_int8array, s_rawarray, 0, 0);
1745 SetInt(&class_int8array->instanceFormat, obj_int8);
1746 SetInt(&class_int8array->classFlags, slotRawInt(&class_int8array->classFlags) | classHasIndexableInstances);
1747 class_int16array = makeIntrinsicClass(s_int16array, s_rawarray, 0, 0);
1748 SetInt(&class_int16array->instanceFormat, obj_int16);
1749 SetInt(&class_int16array->classFlags, slotRawInt(&class_int16array->classFlags) | classHasIndexableInstances);
1750 class_int32array = makeIntrinsicClass(s_int32array, s_rawarray, 0, 0);
1751 SetInt(&class_int32array->instanceFormat, obj_int32);
1752 SetInt(&class_int32array->classFlags, slotRawInt(&class_int32array->classFlags) | classHasIndexableInstances);
1753 class_symbolarray = makeIntrinsicClass(s_symbolarray, s_rawarray, 0, 0);
1754 SetInt(&class_symbolarray->instanceFormat, obj_symbol);
1755 SetInt(&class_symbolarray->classFlags, slotRawInt(&class_symbolarray->classFlags) | classHasIndexableInstances);
1756 class_string = makeIntrinsicClass(s_string, s_rawarray, 0, 1);
1757 addIntrinsicClassVar(class_string, "unixCmdActions", &o_nil);
1758 SetInt(&class_string->instanceFormat, obj_char);
1759 SetInt(&class_string->classFlags, slotRawInt(&class_string->classFlags) | classHasIndexableInstances);
1760 class_floatarray = makeIntrinsicClass(s_floatarray, s_rawarray, 0, 0);
1761 SetInt(&class_floatarray->instanceFormat, obj_float);
1762 SetInt(&class_floatarray->classFlags, slotRawInt(&class_floatarray->classFlags) | classHasIndexableInstances);
1763 class_signal = makeIntrinsicClass(s_signal, s_floatarray, 0, 0);
1764 SetInt(&class_signal->instanceFormat, obj_float);
1765 SetInt(&class_signal->classFlags, slotRawInt(&class_signal->classFlags) | classHasIndexableInstances);
1766 class_wavetable = makeIntrinsicClass(s_wavetable, s_floatarray, 0, 0);
1767 SetInt(&class_wavetable->instanceFormat, obj_float);
1768 SetInt(&class_wavetable->classFlags, slotRawInt(&class_wavetable->classFlags) | classHasIndexableInstances);
1769
1770 // addIntrinsicVar(class_signal, "rate", &o_nil);
1771 class_doublearray = makeIntrinsicClass(s_doublearray, s_rawarray, 0, 0);
1772 SetInt(&class_doublearray->instanceFormat, obj_double);
1773 SetInt(&class_doublearray->classFlags, slotRawInt(&class_doublearray->classFlags) | classHasIndexableInstances);
1774
1775 class_list = makeIntrinsicClass(s_list, s_sequenceable_collection, 1, 0);
1776 addIntrinsicVar(class_list, "array", &o_nil);
1777 // addIntrinsicVar(class_list, "size", &o_zero);
1778
1779 class_func = makeIntrinsicClass(s_func, s_absfunc, 2, 0);
1780 addIntrinsicVar(class_func, "def", &o_nil);
1781 addIntrinsicVar(class_func, "context", &o_nil);
1782
1783 class_server_shm_interface = makeIntrinsicClass(s_server_shm_interface, s_object, 2, 0);
1784 addIntrinsicVar(class_server_shm_interface, "ptr", &o_nil);
1785 addIntrinsicVar(class_server_shm_interface, "finalizer", &o_nil);
1786
1787 gTagClassTable[0] = nullptr;
1788 gTagClassTable[1] = nullptr;
1789 gTagClassTable[2] = class_int;
1790 gTagClassTable[3] = class_symbol;
1791 gTagClassTable[4] = class_char;
1792 gTagClassTable[5] = class_nil;
1793 gTagClassTable[6] = class_false;
1794 gTagClassTable[7] = class_true;
1795 gTagClassTable[8] = class_rawptr;
1796 gTagClassTable[9] = class_float;
1797 gTagClassTable[10] = class_float;
1798 gTagClassTable[11] = class_float;
1799 gTagClassTable[12] = class_float;
1800
1801 SetObject(&o_emptyarray, newPyrArray(nullptr, 0, obj_permanent | obj_immutable, false));
1802
1803 SetObject(&o_onenilarray, newPyrArray(nullptr, 1, obj_permanent | obj_immutable, false));
1804 slotRawObject(&o_onenilarray)->size = 1;
1805 SetNil(slotRawObject(&o_onenilarray)->slots);
1806
1807 SetObject(&o_argnamethis, newPyrSymbolArray(nullptr, 1, obj_permanent | obj_immutable, false));
1808 slotRawSymbolArray(&o_argnamethis)->size = 1;
1809 slotRawSymbolArray(&o_argnamethis)->symbols[0] = s_this;
1810
1811 /*
1812 post("array %p '%s'\n", class_array, class_array->name.us->name);
1813 post("o_emptyarray %p '%s'\n", slotRawObject(&o_emptyarray)->classptr,
1814 slotRawObject(&o_emptyarray)->classptr->name.us->name); post("o_argnamethis %p '%s'\n",
1815 slotRawObject(&o_argnamethis)->classptr, slotRawObject(&o_argnamethis)->classptr->name.us->name);
1816 post("o_onenilarray %p '%s'\n", slotRawObject(&o_onenilarray)->classptr,
1817 slotRawObject(&o_onenilarray)->classptr->name.us->name); dumpObjectSlot(&o_emptyarray);
1818 dumpObjectSlot(&o_argnamethis);
1819 dumpObjectSlot(&o_onenilarray);
1820 */
1821 }
1822
instantiateObject(class PyrGC * gc,PyrClass * classobj,int size,bool fill,bool runGC)1823 PyrObject* instantiateObject(class PyrGC* gc, PyrClass* classobj, int size, bool fill, bool runGC) {
1824 PyrObject *newobj, *proto;
1825 int numbytes, format, flags;
1826
1827 format = slotRawInt(&classobj->instanceFormat);
1828 flags = slotRawInt(&classobj->instanceFlags);
1829
1830 if (slotRawInt(&classobj->classFlags) & classHasIndexableInstances) {
1831 // create an indexable object
1832 numbytes = size * gFormatElemSize[format];
1833 newobj = gc->New(numbytes, flags, format, runGC);
1834 if (fill) {
1835 newobj->size = size;
1836 if (format == obj_slot) {
1837 nilSlots(newobj->slots, size);
1838 } else {
1839 memset(newobj->slots, format == obj_char ? ' ' : 0, size * gFormatElemSize[format]);
1840 }
1841 } else {
1842 newobj->size = 0;
1843 }
1844 } else {
1845 if (IsObj(&classobj->iprototype)) {
1846 proto = slotRawObject(&classobj->iprototype);
1847 size = proto->size;
1848 numbytes = size * sizeof(PyrSlot);
1849 newobj = gc->New(numbytes, flags, format, runGC);
1850 newobj->size = size;
1851 if (size) {
1852 memcpy(newobj->slots, proto->slots, numbytes);
1853 }
1854 } else {
1855 numbytes = 0;
1856 newobj = gc->New(numbytes, flags, format, runGC);
1857 newobj->size = 0;
1858 }
1859 }
1860 newobj->classptr = classobj;
1861 return newobj;
1862 }
1863
1864 PyrObject* instantiateObjectLight(class PyrGC* gc, PyrClass* classobj, int size, bool runGC);
instantiateObjectLight(class PyrGC * gc,PyrClass * classobj,int size,bool runGC)1865 PyrObject* instantiateObjectLight(class PyrGC* gc, PyrClass* classobj, int size, bool runGC) {
1866 PyrObject *newobj, *proto;
1867 int numbytes, format, flags;
1868
1869 format = slotRawInt(&classobj->instanceFormat);
1870 flags = slotRawInt(&classobj->instanceFlags);
1871
1872 if (slotRawInt(&classobj->classFlags) & classHasIndexableInstances) {
1873 numbytes = size * gFormatElemSize[format];
1874 } else {
1875 if (IsObj(&classobj->iprototype)) {
1876 proto = slotRawObject(&classobj->iprototype);
1877 size = proto->size;
1878 numbytes = size * sizeof(PyrSlot);
1879 } else {
1880 size = 0;
1881 numbytes = 0;
1882 }
1883 }
1884 newobj = gc->New(numbytes, flags, format, runGC);
1885 newobj->size = size;
1886 newobj->classptr = classobj;
1887
1888 return newobj;
1889 }
1890
copyObject(class PyrGC * gc,PyrObject * inobj,bool runGC)1891 PyrObject* copyObject(class PyrGC* gc, PyrObject* inobj, bool runGC) {
1892 PyrObject* newobj;
1893
1894 // copies are neither immutable not permanent
1895 int flags = ~(obj_immutable)&inobj->obj_flags;
1896 flags = ~(obj_permanent)&flags;
1897
1898 int elemsize = gFormatElemSize[inobj->obj_format];
1899 int numbytes = inobj->size * elemsize;
1900
1901 newobj = gc->New(numbytes, flags, inobj->obj_format, runGC);
1902
1903 newobj->size = inobj->size;
1904 newobj->classptr = inobj->classptr;
1905
1906 memcpy(newobj->slots, inobj->slots, inobj->size * elemsize);
1907 return newobj;
1908 }
1909
copyObjectRange(class PyrGC * gc,PyrObject * inobj,int start,int end,bool runGC)1910 PyrObject* copyObjectRange(class PyrGC* gc, PyrObject* inobj, int start, int end, bool runGC) {
1911 PyrObject* newobj;
1912
1913 if (start < 0)
1914 start = 0;
1915 if (end >= inobj->size)
1916 end = inobj->size - 1;
1917 int length = end - start + 1;
1918 if (length < 0)
1919 length = 0;
1920
1921 int elemsize = gFormatElemSize[inobj->obj_format];
1922 int numbytes = length * elemsize;
1923
1924 // copies are neither immutable not permanent
1925 int flags = ~(obj_immutable)&inobj->obj_flags;
1926 flags = ~(obj_permanent)&flags;
1927
1928 newobj = gc->New(numbytes, flags, inobj->obj_format, runGC);
1929 newobj->size = length;
1930 newobj->classptr = inobj->classptr;
1931
1932 if (length > 0) {
1933 memcpy(newobj->slots, (char*)(inobj->slots) + start * elemsize, length * elemsize);
1934 }
1935 return newobj;
1936 }
1937
dumpObject(PyrObject * obj)1938 void dumpObject(PyrObject* obj) {
1939 char str[256];
1940 PyrClass* classobj;
1941 int i;
1942
1943 if (obj == nullptr) {
1944 postfl("NULL object pointer\n");
1945 return;
1946 }
1947 classobj = obj->classptr;
1948 if (isKindOf(obj, class_class)) {
1949 post("class %s (%p) {\n", slotRawSymbol(&((PyrClass*)obj)->name)->name, obj);
1950 } else {
1951 // post("Instance of %s (%p) {\n", slotRawSymbol(&classobj->name)->name, obj);
1952 post("Instance of %s { (%p, gc=%02X, fmt=%02X, flg=%02X, set=%02X)\n", slotRawSymbol(&classobj->name)->name,
1953 obj, obj->gc_color, obj->obj_format, obj->obj_flags, obj->obj_sizeclass);
1954 }
1955 // flushPostBuf();
1956
1957 if (obj->obj_format == obj_notindexed) {
1958 post(" instance variables [%d]\n", obj->size);
1959 for (i = 0; i < obj->size; ++i) {
1960 slotString(obj->slots + i, str);
1961 post(" %s : %s\n", slotRawSymbolArray(&classobj->instVarNames)->symbols[i]->name, str);
1962 }
1963 } else {
1964 int maxsize;
1965 post(" indexed slots [%d]\n", obj->size);
1966 maxsize = sc_min(32, obj->size);
1967 switch (obj->obj_format) {
1968 case obj_slot:
1969 for (i = 0; i < maxsize; ++i) {
1970 slotString(obj->slots + i, str);
1971 post(" %3d : %s\n", i, str);
1972 }
1973 break;
1974 case obj_double:
1975 for (i = 0; i < maxsize; ++i) {
1976 post(" %3d : %f\n", i, slotRawFloat(&obj->slots[i]));
1977 }
1978 break;
1979 case obj_float:
1980 for (i = 0; i < maxsize; ++i) {
1981 float val;
1982 val = ((float*)(obj->slots))[i];
1983 post(" %3d : %g\n", i, val);
1984 }
1985 break;
1986 case obj_int32:
1987 for (i = 0; i < maxsize; ++i) {
1988 int32 val;
1989 val = ((int32*)(obj->slots))[i];
1990 post(" %3d : %d\n", i, val);
1991 }
1992 break;
1993 case obj_int16:
1994 for (i = 0; i < maxsize; ++i) {
1995 int16 val;
1996 val = ((int16*)(obj->slots))[i];
1997 post(" %3d : %d\n", i, val);
1998 }
1999 break;
2000 case obj_int8:
2001 for (i = 0; i < maxsize; ++i) {
2002 int8 val;
2003 val = ((int8*)(obj->slots))[i];
2004 post(" %3d : %4d %4u 0x%02X\n", i, val, val & 255, val & 255);
2005 }
2006 break;
2007 case obj_char:
2008 for (i = 0; i < maxsize; ++i) {
2009 char val;
2010 val = ((char*)(obj->slots))[i];
2011 post(" %3d : %c\n", i, val);
2012 }
2013 break;
2014 case obj_symbol:
2015 for (i = 0; i < maxsize; ++i) {
2016 PyrSymbol* sym;
2017 sym = ((PyrSymbol**)(obj->slots))[i];
2018 post(" %3d : '%s'\n", i, sym->name);
2019 }
2020 break;
2021 default:
2022 post("unknown obj_format %X\n", obj->obj_format);
2023 }
2024 if (obj->size > maxsize) {
2025 post(" ...\n");
2026 }
2027 }
2028 post("}\n");
2029 }
2030
dumpBadObject(PyrObject * obj)2031 void dumpBadObject(PyrObject* obj) {
2032 char str[128];
2033 PyrClass* classobj;
2034 int i;
2035
2036 if (obj == nullptr) {
2037 postfl("NULL object pointer\n");
2038 return;
2039 }
2040 classobj = obj->classptr;
2041 if (isKindOf(obj, class_class)) {
2042 postfl("class %s (%p) {\n", slotRawSymbol(&((PyrClass*)obj)->name)->name, obj);
2043 } else {
2044 // postfl("Instance of %s (%p) {\n", slotRawSymbol(&classobj->name)->name, obj);
2045 postfl("Instance of %s { (%p, gc=%02X, fmt=%02X, flg=%02X, set=%02X)\n",
2046 slotRawSymbol(&classobj->name)->name, obj, obj->gc_color, obj->obj_format, obj->obj_flags,
2047 obj->obj_sizeclass);
2048 }
2049 if (obj->obj_format == obj_notindexed) {
2050 postfl(" instance variables [%d]\n", obj->size);
2051 for (i = 0; i < obj->size; ++i) {
2052 slotString(obj->slots + i, str);
2053 postfl(" %s : %s\n", slotRawSymbolArray(&classobj->instVarNames)->symbols[i]->name, str);
2054 }
2055 } else {
2056 int maxsize;
2057 postfl(" indexed slots [%d]\n", obj->size);
2058 maxsize = obj->size;
2059 maxsize = sc_min(32, maxsize);
2060 switch (obj->obj_format) {
2061 case obj_slot:
2062 for (i = 0; i < maxsize; ++i) {
2063 slotString(obj->slots + i, str);
2064 postfl(" %3d : %s\n", i, str);
2065 }
2066 break;
2067 case obj_double:
2068 for (i = 0; i < maxsize; ++i) {
2069 postfl(" %3d : %f\n", i, slotRawFloat(&obj->slots[i]));
2070 }
2071 break;
2072 case obj_float:
2073 for (i = 0; i < maxsize; ++i) {
2074 float val;
2075 val = ((float*)(obj->slots))[i];
2076 postfl(" %3d : %g\n", i, val);
2077 }
2078 break;
2079 case obj_int32:
2080 for (i = 0; i < maxsize; ++i) {
2081 int32 val;
2082 val = ((int32*)(obj->slots))[i];
2083 postfl(" %3d : %d\n", i, val);
2084 }
2085 break;
2086 case obj_int16:
2087 for (i = 0; i < maxsize; ++i) {
2088 int16 val;
2089 val = ((int16*)(obj->slots))[i];
2090 postfl(" %3d : %d\n", i, val);
2091 }
2092 break;
2093 case obj_int8:
2094 for (i = 0; i < maxsize; ++i) {
2095 int8 val;
2096 val = ((int8*)(obj->slots))[i];
2097 postfl(" %3d : %4d %4u 0x%02X\n", i, val, val & 255, val & 255);
2098 }
2099 break;
2100 case obj_char:
2101 for (i = 0; i < maxsize; ++i) {
2102 char val;
2103 val = ((char*)(obj->slots))[i];
2104 postfl(" %3d : %c\n", i, val);
2105 }
2106 break;
2107 case obj_symbol:
2108 for (i = 0; i < maxsize; ++i) {
2109 PyrSymbol* sym;
2110 sym = ((PyrSymbol**)(obj->slots))[i];
2111 post(" %3d : '%s'\n", i, sym->name);
2112 }
2113 break;
2114 default:
2115 postfl("unknown obj_format %X\n", obj->obj_format);
2116 }
2117 if (obj->size > maxsize) {
2118 postfl(" ...\n");
2119 }
2120 }
2121 postfl("}\n");
2122 }
2123
dumpObjectSlot(PyrSlot * slot)2124 void dumpObjectSlot(PyrSlot* slot) {
2125 if (IsObj(slot)) {
2126 dumpObject(slotRawObject(slot));
2127 } else {
2128 dumpPyrSlot(slot);
2129 }
2130 }
2131
dumpSlotOneWord(const char * tagstr,PyrSlot * slot)2132 void dumpSlotOneWord(const char* tagstr, PyrSlot* slot) {
2133 char str[256];
2134 slotOneWord(slot, str);
2135 post("%s %s\n", tagstr, str);
2136 }
2137
2138 void CallStackSanity(VMGlobals* g, const char* tagstr);
CallStackSanity(VMGlobals * g,const char * tagstr)2139 void CallStackSanity(VMGlobals* g, const char* tagstr) {
2140 PyrFrame* frame;
2141 frame = g->frame;
2142 while (frame) {
2143 if (FrameSanity(frame, tagstr)) {
2144 DumpBackTrace(g);
2145 // Debugger();
2146 break;
2147 }
2148 frame = slotRawFrame(&frame->caller);
2149 }
2150 }
2151
2152 bool FrameSanity(PyrFrame* frame, const char* tagstr);
FrameSanity(PyrFrame * frame,const char * tagstr)2153 bool FrameSanity(PyrFrame* frame, const char* tagstr) {
2154 bool failed = false;
2155 if (frame == nullptr)
2156 return false;
2157 if (NotObj(&frame->method)) {
2158 postfl("Frame %p method tag wrong %p\n", frame, GetTag(&frame->method));
2159 failed = true;
2160 //} else if (!isKindOf((PyrObject*)slotRawObject(&frame->method)->classptr, class_fundef)) {
2161 } else if (slotRawObject(&frame->method)->classptr != class_method
2162 && slotRawObject(&frame->method)->classptr != class_fundef) {
2163 postfl("Frame %p method class wrong %p\n", frame, slotRawObject(&frame->method)->classptr);
2164 failed = true;
2165 // if (slotRawObject(&frame->method)->classptr->classptr == class_class) {
2166 postfl("class: '%s'\n", slotRawSymbol(&slotRawObject(&frame->method)->classptr->name)->name);
2167 ///} else {
2168 // postfl("not even a class\n");
2169 //}
2170 } else if (NotObj(&slotRawBlock(&frame->method)->code)) {
2171 postfl("Method %p code tag wrong %p\n", slotRawBlock(&frame->method),
2172 GetTag(&slotRawBlock(&frame->method)->code));
2173 failed = true;
2174 } else if (slotRawObject(&slotRawBlock(&frame->method)->code)->classptr != class_int8array) {
2175 postfl("Code %p class wrong %p\n", slotRawObject(&slotRawBlock(&frame->method)->code),
2176 slotRawObject(&slotRawBlock(&frame->method)->code)->classptr);
2177 postfl("class: '%s'\n",
2178 slotRawSymbol(&slotRawObject(&slotRawBlock(&frame->method)->code)->classptr->name)->name);
2179 failed = true;
2180 }
2181 /*
2182 if (frame->caller.utag != tagHFrame && frame->caller.utag != tagNil) {
2183 postfl("Frame %p caller tag wrong %p\n", frame, frame->caller.utag);
2184 failed = true;
2185 }
2186 if (frame->context.utag != tagHFrame && frame->context.utag != tagNil) {
2187 postfl("Frame %p context tag wrong %p\n", frame, frame->context.utag);
2188 failed = true;
2189 }
2190 if (frame->homeContext.utag != tagHFrame && frame->homeContext.utag != tagNil) {
2191 postfl("Frame %p homeContext tag wrong %p\n", frame, frame->homeContext.utag);
2192 failed = true;
2193 }
2194 */
2195 if (!IsPtr(&frame->ip)) {
2196 postfl("Frame %p ip tag wrong %p\n", frame, GetTag(&frame->ip));
2197 failed = true;
2198 }
2199 return failed;
2200 }
2201
DumpFrame(PyrFrame * frame)2202 void DumpFrame(PyrFrame* frame) {
2203 char str[256];
2204 int i, numargs;
2205 PyrMethod* meth;
2206 PyrMethodRaw* methraw;
2207
2208 if (FrameSanity(frame, "DumpFrame")) {
2209 post("FRAME CORRUPTED\n");
2210 return;
2211 }
2212 slotOneWord(&frame->method, str);
2213 // slotString(&frame->method, str);
2214
2215 meth = slotRawMethod(&frame->method);
2216 methraw = METHRAW(meth);
2217 if (methraw->numtemps) {
2218 post("\t%s\n", str);
2219 numargs = methraw->numargs + methraw->varargs;
2220 for (i = 0; i < methraw->numtemps; ++i) {
2221 slotOneWord(frame->vars + i, str);
2222 // slotString(frame->vars + i, str);
2223 if (i < numargs) {
2224 post("\t\targ %s = %s\n", slotRawSymbolArray(&meth->argNames)->symbols[i]->name, str);
2225 } else {
2226 post("\t\tvar %s = %s\n", slotRawSymbolArray(&meth->varNames)->symbols[i - numargs]->name, str);
2227 }
2228 }
2229 } else {
2230 post("\t%s (no arguments or variables)\n", str);
2231 }
2232 }
2233
2234 void dumpByteCodes(PyrBlock* theBlock);
2235
2236 void DumpDetailedFrame(PyrFrame* frame);
DumpDetailedFrame(PyrFrame * frame)2237 void DumpDetailedFrame(PyrFrame* frame) {
2238 char mstr[256];
2239 char str[256];
2240 int i, numargs;
2241 PyrMethod* meth;
2242 PyrMethodRaw* methraw;
2243
2244 if (FrameSanity(frame, "DumpDetailedFrame")) {
2245 post("FRAME CORRUPTED\n");
2246 return;
2247 }
2248 slotOneWord(&frame->method, mstr);
2249 // slotString(&frame->method, str);
2250
2251 meth = slotRawMethod(&frame->method);
2252 methraw = METHRAW(meth);
2253
2254 if (methraw->numtemps) {
2255 post("\t%s\n", mstr);
2256 numargs = methraw->numargs + methraw->varargs;
2257 for (i = 0; i < methraw->numtemps; ++i) {
2258 slotOneWord(frame->vars + i, str);
2259 // slotString(frame->vars + i, str);
2260 if (i < numargs) {
2261 post("\t\targ %s = %s\n", slotRawSymbolArray(&meth->argNames)->symbols[i]->name, str);
2262 } else {
2263 post("\t\tvar %s = %s\n", slotRawSymbolArray(&meth->varNames)->symbols[i - numargs]->name, str);
2264 }
2265 }
2266 } else {
2267 post("\t%s (no arguments or variables)\n", mstr);
2268 }
2269
2270 post("\t....%s details:\n", mstr);
2271 post("\t\tneedsHeapContext = %d\n", methraw->needsHeapContext);
2272 post("\t\tnumtemps = %d\n", methraw->numtemps);
2273 post("\t\tpopSize = %d\n", methraw->popSize);
2274
2275 slotString(&frame->method, str);
2276 post("\t\tmethod = %s\n", str);
2277 slotString(&frame->caller, str);
2278 post("\t\tcaller = %s\n", str);
2279 slotString(&frame->context, str);
2280 post("\t\tcontext = %s\n", str);
2281 slotString(&frame->homeContext, str);
2282 post("\t\thomeCtx = %s\n", str);
2283 slotString(&frame->ip, str);
2284 post("\t\tip = %s\n", str);
2285
2286 if (IsPtr(&frame->ip)) {
2287 post("ipoffset = %d\n", (char*)slotRawPtr(&frame->ip) - (char*)slotRawInt8Array(&meth->code)->b);
2288 dumpByteCodes(meth);
2289 }
2290 }
2291
2292
respondsTo(PyrSlot * slot,PyrSymbol * selector)2293 bool respondsTo(PyrSlot* slot, PyrSymbol* selector) {
2294 PyrClass* classobj;
2295 PyrMethod* meth;
2296 int index;
2297
2298 classobj = classOfSlot(slot);
2299
2300 index = slotRawInt(&classobj->classIndex) + selector->u.index;
2301 meth = gRowTable[index];
2302 return slotRawSymbol(&meth->name) == selector;
2303 }
2304
2305 PyrMethod* methodLookup(PyrSlot* slot, PyrSymbol* selector);
methodLookup(PyrSlot * slot,PyrSymbol * selector)2306 PyrMethod* methodLookup(PyrSlot* slot, PyrSymbol* selector) {
2307 PyrClass* classobj;
2308 PyrMethod* meth;
2309 int index;
2310
2311 classobj = classOfSlot(slot);
2312
2313 index = slotRawInt(&classobj->classIndex) + selector->u.index;
2314 meth = gRowTable[index];
2315 return meth;
2316 }
2317
2318
isSubclassOf(PyrClass * classobj,PyrClass * testclass)2319 bool isSubclassOf(PyrClass* classobj, PyrClass* testclass) {
2320 while (classobj) {
2321 if (classobj == testclass) {
2322 return true;
2323 }
2324 classobj = slotRawSymbol(&classobj->superclass)->u.classobj;
2325 }
2326 return false;
2327 }
2328
2329 /*bool isKindOf(PyrObjectHdr *obj, PyrClass *testclass)
2330 {
2331 int objClassIndex = slotRawInt(&obj->classptr->classIndex);
2332 return objClassIndex >= slotRawInt(&testclass->classIndex) && objClassIndex <=
2333 slotRawInt(&testclass->maxSubclassIndex);
2334 }*/
2335
objAddIndexedSlot(PyrObject * obj,PyrSlot * slot)2336 bool objAddIndexedSlot(PyrObject* obj, PyrSlot* slot) {
2337 if (obj->size < ARRAYMAXINDEXSIZE(obj)) {
2338 slotCopy(&obj->slots[obj->size++], slot);
2339 return true;
2340 } else {
2341 return false;
2342 }
2343 }
2344
objAddIndexedSymbol(PyrSymbolArray * obj,PyrSymbol * symbol)2345 bool objAddIndexedSymbol(PyrSymbolArray* obj, PyrSymbol* symbol) {
2346 if (obj->size < MAXINDEXSIZE((PyrObject*)obj)) {
2347 obj->symbols[obj->size++] = symbol;
2348 return true;
2349 } else {
2350 return false;
2351 }
2352 }
2353
objAddIndexedObject(PyrObject * obj,PyrObject * obj2)2354 bool objAddIndexedObject(PyrObject* obj, PyrObject* obj2) {
2355 if (obj->size < ARRAYMAXINDEXSIZE(obj)) {
2356 SetObject(obj->slots + obj->size, obj2);
2357 obj->size++;
2358 return true;
2359 } else {
2360 return false;
2361 }
2362 }
2363
fillSlots(PyrSlot * slot,int size,PyrSlot * fillslot)2364 void fillSlots(PyrSlot* slot, int size, PyrSlot* fillslot) {
2365 for (int i = 0; i != size; ++i)
2366 slotCopy(&slot[i], fillslot);
2367 }
2368
nilSlots(PyrSlot * slot,int size)2369 void nilSlots(PyrSlot* slot, int size) { fillSlots(slot, size, &o_nil); }
2370
zeroSlots(PyrSlot * slot,int size)2371 void zeroSlots(PyrSlot* slot, int size) {
2372 PyrSlot zero;
2373 SetTagRaw(&zero, 0);
2374 SetRaw(&zero, 0.0);
2375 fillSlots(slot, size, &zero);
2376 }
2377
newPyrObject(class PyrGC * gc,size_t inNumBytes,int inFlags,int inFormat,bool inRunGC)2378 PyrObject* newPyrObject(class PyrGC* gc, size_t inNumBytes, int inFlags, int inFormat, bool inRunGC) {
2379 return gc->New(inNumBytes, inFlags, inFormat, inRunGC);
2380 }
2381
newPyrArray(class PyrGC * gc,int size,int flags,bool runGC)2382 PyrObject* newPyrArray(class PyrGC* gc, int size, int flags, bool runGC) {
2383 PyrObject* array;
2384
2385 int numbytes = size * sizeof(PyrSlot);
2386 if (!gc)
2387 array = PyrGC::NewPermanent(numbytes, flags, obj_slot);
2388 else
2389 array = gc->New(numbytes, flags, obj_slot, runGC);
2390 array->classptr = class_array;
2391 return array;
2392 }
2393
newPyrSymbolArray(class PyrGC * gc,int size,int flags,bool runGC)2394 PyrSymbolArray* newPyrSymbolArray(class PyrGC* gc, int size, int flags, bool runGC) {
2395 PyrSymbolArray* array;
2396
2397 int numbytes = size * sizeof(PyrSymbol*);
2398 if (!gc)
2399 array = (PyrSymbolArray*)PyrGC::NewPermanent(numbytes, flags, obj_symbol);
2400 else
2401 array = (PyrSymbolArray*)gc->New(numbytes, flags, obj_symbol, runGC);
2402 array->classptr = class_symbolarray;
2403 return array;
2404 }
2405
newPyrInt8Array(class PyrGC * gc,int size,int flags,bool runGC)2406 PyrInt8Array* newPyrInt8Array(class PyrGC* gc, int size, int flags, bool runGC) {
2407 PyrInt8Array* array;
2408
2409 if (!gc)
2410 array = (PyrInt8Array*)PyrGC::NewPermanent(size, flags, obj_int8);
2411 else
2412 array = (PyrInt8Array*)gc->New(size, flags, obj_int8, runGC);
2413 array->classptr = class_int8array;
2414 return array;
2415 }
2416
newPyrInt32Array(class PyrGC * gc,int size,int flags,bool runGC)2417 PyrInt32Array* newPyrInt32Array(class PyrGC* gc, int size, int flags, bool runGC) {
2418 PyrInt32Array* array;
2419 int numbytes = size * sizeof(int32);
2420 if (!gc)
2421 array = (PyrInt32Array*)PyrGC::NewPermanent(numbytes, flags, obj_int32);
2422 else
2423 array = (PyrInt32Array*)gc->New(numbytes, flags, obj_int32, runGC);
2424 array->classptr = class_int32array;
2425 return array;
2426 }
2427
newPyrDoubleArray(class PyrGC * gc,int size,int flags,bool runGC)2428 PyrDoubleArray* newPyrDoubleArray(class PyrGC* gc, int size, int flags, bool runGC) {
2429 PyrDoubleArray* array;
2430
2431 int numbytes = size * sizeof(double);
2432 if (!gc)
2433 array = (PyrDoubleArray*)PyrGC::NewPermanent(numbytes, flags, obj_double);
2434 else
2435 array = (PyrDoubleArray*)gc->New(size, flags, obj_double, runGC);
2436 array->classptr = class_doublearray;
2437 return array;
2438 }
2439
newPyrString(class PyrGC * gc,const char * s,int flags,bool runGC)2440 PyrString* newPyrString(class PyrGC* gc, const char* s, int flags, bool runGC) {
2441 PyrString* string;
2442 int length = strlen(s);
2443
2444 if (!gc)
2445 string = (PyrString*)PyrGC::NewPermanent(length, flags, obj_char);
2446 else
2447 string = (PyrString*)gc->New(length, flags, obj_char, runGC);
2448 string->classptr = class_string;
2449 string->size = length;
2450 memcpy(string->s, s, length);
2451 return string;
2452 }
2453
newPyrStringN(class PyrGC * gc,int length,int flags,bool runGC)2454 PyrString* newPyrStringN(class PyrGC* gc, int length, int flags, bool runGC) {
2455 PyrString* string;
2456
2457 if (!gc)
2458 string = (PyrString*)PyrGC::NewPermanent(length, flags, obj_char);
2459 else
2460 string = (PyrString*)gc->New(length, flags, obj_char, runGC);
2461 string->classptr = class_string;
2462 string->size = length; // filled with garbage!
2463 return string;
2464 }
2465
newPyrBlock(int flags)2466 PyrBlock* newPyrBlock(int flags) {
2467 PyrBlock* block;
2468 PyrMethodRaw* methraw;
2469
2470
2471 int32 numbytes = sizeof(PyrBlock) - sizeof(PyrObjectHdr);
2472 int32 numSlots = numbytes / sizeof(PyrSlot);
2473
2474 if (!compilingCmdLine)
2475 block = (PyrBlock*)PyrGC::NewPermanent(numbytes, flags, obj_notindexed);
2476 else
2477 block = (PyrBlock*)gMainVMGlobals->gc->New(numbytes, flags, obj_notindexed, false);
2478 block->classptr = class_fundef;
2479 block->size = numSlots;
2480
2481 // clear out raw area
2482 methraw = METHRAW(block);
2483 methraw->specialIndex = 0;
2484 methraw->methType = methBlock;
2485 methraw->needsHeapContext = 0;
2486 methraw->frameSize = 0;
2487 methraw->varargs = 0;
2488 methraw->numargs = 0;
2489 methraw->numvars = 0;
2490 methraw->numtemps = 0;
2491 methraw->popSize = 0;
2492
2493 nilSlots(&block->rawData1, numSlots);
2494 return block;
2495 }
2496
scGlobals()2497 SCLANG_DLLEXPORT_C struct VMGlobals* scGlobals() { return gMainVMGlobals; }
2498
initPyrMethod(PyrMethod * method)2499 PyrMethod* initPyrMethod(PyrMethod* method) {
2500 int32 numbytes = sizeof(PyrMethod) - sizeof(PyrObjectHdr);
2501 int32 numSlots = numbytes / sizeof(PyrSlot);
2502
2503 method->classptr = class_method;
2504 method->size = 0;
2505 method->size = numSlots;
2506 SetFloat(&method->rawData1, 0.0);
2507 SetFloat(&method->rawData2, 0.0);
2508 nilSlots(&method->code, numSlots - 2);
2509 // slotCopy(&method->byteMeter, &o_zero);
2510 // slotCopy(&method->callMeter, &o_zero);
2511 // post("<- newPyrMethod %p %p\n", method, methraw);
2512 return method;
2513 }
2514
newPyrMethod()2515 PyrMethod* newPyrMethod() {
2516 int32 numbytes = sizeof(PyrMethod) - sizeof(PyrObjectHdr);
2517 PyrMethod* method = (PyrMethod*)PyrGC::NewPermanent(numbytes, obj_permanent | obj_immutable, obj_notindexed);
2518 return initPyrMethod(method);
2519 }
2520
freePyrSlot(PyrSlot * slot)2521 void freePyrSlot(PyrSlot* slot) {
2522 if (IsObj(slot)) {
2523 PyrObject* obj = slotRawObject(slot);
2524
2525 if (obj && obj->IsPermanent()) {
2526 // don't deallocate these
2527 if (obj != slotRawObject(&o_emptyarray) && obj != slotRawObject(&o_onenilarray)
2528 && obj != slotRawObject(&o_argnamethis))
2529 pyr_pool_runtime->Free((void*)obj);
2530
2531 SetNil(slot);
2532 }
2533 }
2534 }
2535
freePyrObject(PyrObject * obj)2536 void freePyrObject(PyrObject* obj) {
2537 if (obj->IsPermanent()) {
2538 pyr_pool_runtime->Free((void*)obj);
2539 }
2540 }
2541
getIndexedInt(PyrObject * obj,int index,int * value)2542 int getIndexedInt(PyrObject* obj, int index, int* value) {
2543 PyrSlot* slot;
2544 int err = errNone;
2545 if (index < 0 || index >= obj->size)
2546 return errIndexOutOfRange;
2547 switch (obj->obj_format) {
2548 case obj_slot:
2549 slot = obj->slots + index;
2550 if (IsFloat(slot)) {
2551 *value = (int)slotRawFloat(slot);
2552 } else if (IsInt(slot)) {
2553 *value = slotRawInt(slot);
2554 } else {
2555 err = errWrongType;
2556 }
2557 break;
2558 case obj_double:
2559 *value = (int)((double*)(obj->slots))[index];
2560 break;
2561 case obj_float:
2562 *value = (int)((float*)(obj->slots))[index];
2563 break;
2564 case obj_int32:
2565 *value = ((int32*)(obj->slots))[index];
2566 break;
2567 case obj_int16:
2568 *value = ((int16*)(obj->slots))[index];
2569 break;
2570 case obj_int8:
2571 *value = ((int8*)(obj->slots))[index];
2572 break;
2573 default:
2574 err = errWrongType;
2575 }
2576 return err;
2577 }
2578
getIndexedFloat(PyrObject * obj,int index,float * value)2579 int getIndexedFloat(PyrObject* obj, int index, float* value) {
2580 PyrSlot* slot;
2581 int err = errNone;
2582 if (index < 0 || index >= obj->size)
2583 return errIndexOutOfRange;
2584 switch (obj->obj_format) {
2585 case obj_slot:
2586 slot = obj->slots + index;
2587 if (IsFloat(slot)) {
2588 *value = slotRawFloat(slot);
2589 } else if (IsInt(slot)) {
2590 *value = slotRawInt(slot);
2591 } else {
2592 err = errWrongType;
2593 }
2594 break;
2595 case obj_double:
2596 *value = ((double*)(obj->slots))[index];
2597 break;
2598 case obj_float:
2599 *value = ((float*)(obj->slots))[index];
2600 break;
2601 case obj_int32:
2602 *value = ((int32*)(obj->slots))[index];
2603 break;
2604 case obj_int16:
2605 *value = ((int16*)(obj->slots))[index];
2606 break;
2607 case obj_int8:
2608 *value = ((int8*)(obj->slots))[index];
2609 break;
2610 default:
2611 err = errWrongType;
2612 }
2613 return err;
2614 }
2615
getIndexedDouble(PyrObject * obj,int index,double * value)2616 int getIndexedDouble(PyrObject* obj, int index, double* value) {
2617 PyrSlot* slot;
2618 int err = errNone;
2619 if (index < 0 || index >= obj->size)
2620 return errIndexOutOfRange;
2621 switch (obj->obj_format) {
2622 case obj_slot:
2623 slot = obj->slots + index;
2624 if (IsFloat(slot)) {
2625 *value = slotRawFloat(slot);
2626 } else if (IsInt(slot)) {
2627 *value = slotRawInt(slot);
2628 } else {
2629 err = errWrongType;
2630 }
2631 break;
2632 case obj_double:
2633 *value = ((double*)(obj->slots))[index];
2634 break;
2635 case obj_float:
2636 *value = ((float*)(obj->slots))[index];
2637 break;
2638 case obj_int32:
2639 *value = ((int32*)(obj->slots))[index];
2640 break;
2641 case obj_int16:
2642 *value = ((int16*)(obj->slots))[index];
2643 break;
2644 case obj_int8:
2645 *value = ((int8*)(obj->slots))[index];
2646 break;
2647 default:
2648 err = errWrongType;
2649 }
2650 return err;
2651 }
2652
2653
getIndexedSlot(PyrObject * obj,PyrSlot * a,int index)2654 void getIndexedSlot(PyrObject* obj, PyrSlot* a, int index) {
2655 // postfl("getIndexedSlot %s %X %d\n", slotRawSymbol(&obj->classptr->name)->name,
2656 // obj, index);
2657 switch (obj->obj_format) {
2658 case obj_slot:
2659 slotCopy(a, &obj->slots[index]);
2660 break;
2661 case obj_double:
2662 SetFloat(a, ((double*)(obj->slots))[index]);
2663 break;
2664 case obj_float:
2665 SetFloat(a, ((float*)(obj->slots))[index]);
2666 break;
2667 case obj_int32:
2668 SetInt(a, ((int32*)(obj->slots))[index]);
2669 break;
2670 case obj_int16:
2671 SetInt(a, ((int16*)(obj->slots))[index]);
2672 break;
2673 case obj_int8:
2674 SetInt(a, ((int8*)(obj->slots))[index]);
2675 break;
2676 case obj_symbol:
2677 SetSymbol(a, (PyrSymbol*)((int**)(obj->slots))[index]);
2678 break;
2679 case obj_char:
2680 SetChar(a, ((unsigned char*)(obj->slots))[index]);
2681 break;
2682 }
2683 }
2684
putIndexedSlot(VMGlobals * g,PyrObject * obj,PyrSlot * c,int index)2685 int putIndexedSlot(VMGlobals* g, PyrObject* obj, PyrSlot* c, int index) {
2686 PyrSlot* slot;
2687 switch (obj->obj_format) {
2688 case obj_slot:
2689 if (obj->IsImmutable())
2690 return errImmutableObject;
2691 slot = obj->slots + index;
2692 slotCopy(slot, c);
2693 g->gc->GCWrite(obj, slot);
2694 break;
2695 case obj_double:
2696 if (NotFloat(c)) {
2697 if (NotInt(c))
2698 return errWrongType;
2699 else {
2700 ((double*)(obj->slots))[index] = slotRawInt(c);
2701 }
2702 } else
2703 ((double*)(obj->slots))[index] = slotRawFloat(c);
2704 break;
2705 case obj_float:
2706 if (NotFloat(c)) {
2707 if (NotInt(c))
2708 return errWrongType;
2709 else {
2710 ((float*)(obj->slots))[index] = slotRawInt(c);
2711 }
2712 } else
2713 ((float*)(obj->slots))[index] = slotRawFloat(c);
2714 break;
2715 case obj_int32:
2716 if (NotInt(c))
2717 return errWrongType;
2718 ((int32*)(obj->slots))[index] = slotRawInt(c);
2719 break;
2720 case obj_int16:
2721 if (NotInt(c))
2722 return errWrongType;
2723 ((int16*)(obj->slots))[index] = slotRawInt(c);
2724 break;
2725 case obj_int8:
2726 if (NotInt(c))
2727 return errWrongType;
2728 ((int8*)(obj->slots))[index] = slotRawInt(c);
2729 break;
2730 case obj_symbol:
2731 if (NotSym(c))
2732 return errWrongType;
2733 ((PyrSymbol**)(obj->slots))[index] = slotRawSymbol(c);
2734 break;
2735 case obj_char:
2736 if (NotChar(c))
2737 return errWrongType;
2738 ((unsigned char*)(obj->slots))[index] = slotRawChar(c);
2739 break;
2740 }
2741 return errNone;
2742 }
2743
putIndexedFloat(PyrObject * obj,double val,int index)2744 int putIndexedFloat(PyrObject* obj, double val, int index) {
2745 PyrSlot* slot;
2746 switch (obj->obj_format) {
2747 case obj_slot:
2748 if (obj->IsImmutable())
2749 return errImmutableObject;
2750 slot = obj->slots + index;
2751 SetFloat(slot, val);
2752 break;
2753 case obj_double:
2754 ((double*)(obj->slots))[index] = val;
2755 break;
2756 case obj_float:
2757 ((float*)(obj->slots))[index] = (float)val;
2758 break;
2759 case obj_int32:
2760 ((int32*)(obj->slots))[index] = (int32)val;
2761 break;
2762 case obj_int16:
2763 ((int16*)(obj->slots))[index] = (int16)val;
2764 break;
2765 case obj_int8:
2766 ((int8*)(obj->slots))[index] = (int8)val;
2767 break;
2768 }
2769 return errNone;
2770 }
2771 /**
2772 * @brief obtain a vector of strings from an sclang collection of sclang strings.
2773 * @param coll The sclang collection containing strings
2774 * @return a tuple containing an int (the error code) and a vector of std:string's.
2775 * If an error occurs an empty vector is returned.
2776 */
PyrCollToVectorStdString(PyrObject * coll)2777 std::tuple<int, std::vector<std::string>> PyrCollToVectorStdString(PyrObject* coll) {
2778 std::vector<std::string> strings;
2779 for (int i = 0; i < coll->size; ++i) {
2780 PyrSlot argSlot;
2781 getIndexedSlot(coll, &argSlot, i);
2782 int error;
2783 std::string string;
2784 std::tie(error, string) = slotStrStdStrVal(&argSlot);
2785 if (error != errNone) {
2786 strings.clear();
2787 return std::make_tuple(error, strings);
2788 }
2789 strings.push_back(std::move(string));
2790 }
2791 return make_tuple(errNone, std::move(strings));
2792 }
2793
hashPtr(void * ptr)2794 static int hashPtr(void* ptr) {
2795 int32 hashed_part = int32((size_t)ptr & 0xffffffff);
2796 return Hash(hashed_part);
2797 }
2798
2799 int calcHash(PyrSlot* a);
calcHash(PyrSlot * a)2800 int calcHash(PyrSlot* a) {
2801 int hash;
2802 switch (GetTag(a)) {
2803 case tagObj:
2804 hash = hashPtr(slotRawObject(a));
2805 break;
2806 case tagInt:
2807 hash = Hash(slotRawInt(a));
2808 break;
2809 case tagChar:
2810 hash = Hash(slotRawChar(a) & 255);
2811 break;
2812 case tagSym:
2813 hash = slotRawSymbol(a)->hash;
2814 break;
2815 case tagNil:
2816 hash = 0xA5A5A5A5;
2817 break;
2818 case tagFalse:
2819 hash = 0x55AA55AA;
2820 break;
2821 case tagTrue:
2822 hash = 0x69696969;
2823 break;
2824 case tagPtr:
2825 hash = hashPtr(slotRawPtr(a));
2826 break;
2827 default:
2828 // hash for a double
2829 union {
2830 int32 i[2];
2831 double d;
2832 } u;
2833 u.d = slotRawFloat(a);
2834 hash = Hash(u.i[0] + Hash(u.i[1]));
2835 }
2836 return hash;
2837 }
2838
InstallFinalizer(VMGlobals * g,PyrObject * inObj,int slotIndex,ObjFuncPtr inFunc)2839 void InstallFinalizer(VMGlobals* g, PyrObject* inObj, int slotIndex, ObjFuncPtr inFunc) {
2840 PyrObject* finalizer = g->gc->NewFinalizer(inFunc, inObj, false);
2841 SetObject(inObj->slots + slotIndex, finalizer);
2842 g->gc->GCWriteNew(inObj, finalizer); // we know finalizer is white so we can use GCWriteNew
2843 }
2844