supernova: fix for small audio vector sizes
[supercollider.git] / lang / LangSource / PyrObject.cpp
blob9f3dfcdeca6df0839ec381682047f29790c25e81
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <stdlib.h>
22 #include <string.h>
23 #include <math.h>
24 #include <limits.h>
25 #include "GC.h"
26 #include "PyrMessage.h"
27 #include "PyrInterpreter.h"
28 #include "PyrSymbolTable.h"
29 #include "PyrObjectProto.h"
30 #include "PyrKernelProto.h"
31 #include "PyrLexer.h"
32 #include "InitAlloc.h"
33 #include "Hash.h"
34 #include "SC_Constants.h"
35 #include "SC_Alloca.h"
37 #include <set>
39 PyrClass *gClassList = NULL;
40 int gNumSelectors = 0;
41 int gNumClasses = 0;
42 int gNumClassVars = 0;
43 int gFormatElemSize[NUMOBJFORMATS];
44 int gFormatElemCapc[NUMOBJFORMATS];
45 int gFormatElemTag[NUMOBJFORMATS];
46 PyrMethod *gNullMethod; // used to fill row table
47 PyrClass* gTagClassTable[16];
49 PyrClass *class_object;
50 PyrClass *class_dict;
51 PyrClass *class_array;
52 PyrClass *class_list, *class_method, *class_fundef, *class_frame, *class_class;
53 PyrClass *class_symbol, *class_nil;
54 PyrClass *class_boolean, *class_true, *class_false;
55 PyrClass *class_int, *class_char, *class_float, *class_complex;
56 PyrClass *class_rawptr;
57 PyrClass *class_string;
58 PyrClass *class_magnitude, *class_number, *class_collection, *class_ordered_collection;
59 PyrClass *class_arrayed_collection;
60 PyrClass *class_sequenceable_collection;
61 PyrClass *class_simple_number;
62 PyrClass *class_rawarray;
63 PyrClass *class_signal;
64 PyrClass *class_wavetable;
65 PyrClass *class_floatarray;
66 PyrClass *class_int8array;
67 PyrClass *class_int16array;
68 PyrClass *class_int32array;
69 PyrClass *class_symbolarray;
70 PyrClass *class_doublearray;
71 PyrClass *class_func, *class_absfunc;
72 PyrClass *class_stream;
73 PyrClass *class_process;
74 PyrClass *class_interpreter;
75 PyrClass *class_thread;
76 PyrClass *class_routine;
77 PyrClass *class_finalizer;
79 PyrSymbol *s_none;
80 PyrSymbol *s_object;
81 PyrSymbol *s_bag;
82 PyrSymbol *s_set;
83 PyrSymbol *s_identityset;
84 PyrSymbol *s_dictionary;
85 PyrSymbol *s_identitydictionary;
86 PyrSymbol *s_linkedlist;
87 PyrSymbol *s_sortedlist;
88 PyrSymbol *s_array;
89 PyrSymbol *s_list, *s_method, *s_fundef, *s_frame, *s_class;
90 PyrSymbol *s_symbol, *s_nil;
91 PyrSymbol *s_boolean, *s_true, *s_false;
92 PyrSymbol *s_int, *s_char, *s_color, *s_float, *s_complex;
93 PyrSymbol *s_rawptr, *s_objptr;
94 PyrSymbol *s_string;
95 PyrSymbol *s_magnitude, *s_number, *s_collection, *s_ordered_collection;
96 PyrSymbol *s_arrayed_collection;
97 PyrSymbol *s_sequenceable_collection;
98 PyrSymbol *s_simple_number;
99 PyrSymbol *s_signal;
100 PyrSymbol *s_wavetable;
102 PyrSymbol *s_rawarray;
103 PyrSymbol *s_int8array;
104 PyrSymbol *s_int16array;
105 PyrSymbol *s_int32array;
106 PyrSymbol *s_symbolarray;
107 PyrSymbol *s_doublearray;
108 PyrSymbol *s_floatarray;
109 PyrSymbol *s_point;
110 PyrSymbol *s_rect;
111 PyrSymbol *s_func, *s_absfunc;
112 PyrSymbol *s_stream;
113 PyrSymbol *s_process;
114 PyrSymbol *s_main;
115 PyrSymbol *s_thread;
116 PyrSymbol *s_routine;
117 PyrSymbol *s_task;
118 PyrSymbol *s_prstart;
119 PyrSymbol *s_interpreter;
120 PyrSymbol *s_finalizer;
121 PyrSymbol *s_awake;
122 PyrSymbol *s_appclock;
123 PyrSymbol *s_systemclock;
125 PyrSymbol *s_nocomprendo;
126 PyrSymbol *s_curProcess, *s_curMethod, *s_curBlock, *s_curClosure, *s_curThread;
127 //PyrSymbol *s_sampleRate;
128 //PyrSymbol *s_audioClock, *s_logicalClock;
129 PyrSymbol *s_run;
130 PyrSymbol *s_startup;
131 PyrSymbol *s_docmdline;
132 PyrSymbol *s_audio;
133 PyrSymbol *s_control;
134 PyrSymbol *s_scalar;
135 PyrSymbol *s_next;
136 PyrSymbol *s_env;
137 PyrSymbol *s_ugen, *s_outputproxy;
138 PyrSymbol *s_new, *s_ref, *s_value, *s_at, *s_put;
139 PyrSymbol *s_performList, *s_superPerformList;
140 PyrSymbol *s_series, *s_copyseries, *s_putseries;
141 PyrSymbol *s_envirGet, *s_envirPut;
142 PyrSymbol *s_synth, *s_spawn, *s_environment, *s_event;
143 PyrSymbol *s_hardwaresetup, *s_shutdown;
144 PyrSymbol *s_linear, *s_exponential, *s_gate;
145 PyrSymbol *s_super, *s_this;
146 PyrSlot o_nil, o_true, o_false, o_end;
147 PyrSlot o_pi, o_twopi;
148 PyrSlot o_fhalf, o_fnegone, o_fzero, o_fone, o_ftwo, o_inf;
149 PyrSlot o_negtwo, o_negone, o_zero, o_one, o_two;
150 PyrSlot o_nullframe, o_none;
151 PyrSlot o_emptyarray, o_onenilarray, o_argnamethis;
154 void initSymbols()
156 s_new = getsym("new");
157 s_ref = getsym("Ref");
158 s_none = getsym("none");
159 s_object = getsym("Object");
160 s_this = getsym("this");
161 s_super = getsym("super");
163 s_dictionary = getsym("Dictionary");
164 s_bag = getsym("Bag");
165 s_set = getsym("Set");
166 s_identityset = getsym("IdentitySet");
167 s_identitydictionary = getsym("IdentityDictionary");
168 s_linkedlist = getsym("LinkedList");
169 s_sortedlist = getsym("SortedList");
170 s_array = getsym("Array");
171 s_list = getsym("List");
172 s_method = getsym("Method");
173 s_fundef = getsym("FunctionDef");
174 s_frame = getsym("Frame");
175 s_class = getsym("Class");
176 s_symbol = getsym("Symbol");
177 s_nil = getsym("Nil");
178 s_true = getsym("True");
179 s_false = getsym("False");
180 s_int = getsym("Integer");
181 s_float = getsym("Float");
182 s_char = getsym("Char");
183 s_color = getsym("Color");
184 s_rawptr = getsym("RawPointer");
185 s_objptr = getsym("ObjectPointer");
186 s_string = getsym("String");
187 s_magnitude = getsym("Magnitude");
188 s_number = getsym("Number");
189 s_simple_number = getsym("SimpleNumber");
190 s_collection = getsym("Collection");
191 //s_ordered_collection = getsym("OrderedCollection");
192 s_arrayed_collection = getsym("ArrayedCollection");
193 s_sequenceable_collection = getsym("SequenceableCollection");
194 s_boolean = getsym("Boolean");
195 s_signal = getsym("Signal");
196 s_wavetable = getsym("Wavetable");
197 //s_signalnode = getsym("SignalNode");
198 s_rawarray = getsym("RawArray");
199 s_int8array = getsym("Int8Array");
200 s_int16array = getsym("Int16Array");
201 s_int32array = getsym("Int32Array");
202 s_symbolarray = getsym("SymbolArray");
203 s_floatarray = getsym("FloatArray");
204 s_doublearray = getsym("DoubleArray");
205 s_complex = getsym("Complex");
206 s_point = getsym("Point");
207 s_rect = getsym("Rect");
208 s_absfunc = getsym("AbstractFunction");
209 s_func = getsym("Function");
210 s_stream = getsym("Stream");
211 s_process = getsym("Process");
212 s_main = getsym("Main");
213 s_thread = getsym("Thread");
214 s_routine = getsym("Routine");
215 s_task = getsym("Task");
216 s_prstart = getsym("prStart");
217 s_interpreter = getsym("Interpreter");
218 s_finalizer = getsym("Finalizer");
219 s_awake = getsym("awake");
220 s_appclock = getsym("AppClock");
221 s_systemclock = getsym("SystemClock");
223 s_linear = getsym("linear");
224 s_exponential = getsym("exponential");
225 s_gate = getsym("gate");
227 //s_dsp = getsym("DSP");
228 //s_dspsettings = getsym("DSPSettings");
229 s_synth = getsym("Synth");
230 s_spawn = getsym("BasicSpawn");
231 s_environment = getsym("Environment");
232 s_event = getsym("Event");
233 s_hardwaresetup = getsym("hardwareSetup");
234 s_shutdown = getsym("shutdown");
236 s_nocomprendo = getsym("doesNotUnderstand");
238 s_curProcess = getsym("thisProcess");
239 s_curThread = getsym("thisThread");
240 s_curMethod = getsym("thisMethod");
241 s_curBlock = getsym("thisFunctionDef");
242 s_curClosure = getsym("thisFunction");
243 //s_sampleRate = getsym("gSR");
244 //s_logicalClock = getsym("gTime");
245 //s_audioClock = getsym("gAudioTime");
246 s_audio = getsym("audio");
247 s_control = getsym("control");
248 s_scalar = getsym("scalar");
249 s_run = getsym("run");
250 s_startup = getsym("startup");
251 s_docmdline = getsym("doCmdLine");
252 s_next = getsym("next");
253 s_value = getsym("value");
254 s_performList = getsym("performList");
255 s_superPerformList = getsym("superPerformList");
256 s_at = getsym("at");
257 s_put = getsym("put");
259 s_series = getsym("prSimpleNumberSeries");
260 s_copyseries = getsym("copySeries");
261 s_putseries = getsym("putSeries");
263 s_ugen = getsym("UGen");
264 s_outputproxy = getsym("OutputProxy");
265 s_env = getsym("Env");
267 s_envirGet = getsym("envirGet");
268 s_envirPut = getsym("envirPut");
270 SetNil(&o_nil);
271 SetFalse(&o_false);
272 SetTrue(&o_true);
274 SetFloat(&o_pi, pi);
275 SetFloat(&o_twopi, twopi);
276 SetFloat(&o_fhalf, .5);
277 SetFloat(&o_fnegone, -1.);
278 SetFloat(&o_fzero, 0.);
279 SetFloat(&o_fone, 1.);
280 SetFloat(&o_ftwo, 2.);
281 SetInt(&o_negtwo, -2);
282 SetInt(&o_negone, -1);
283 SetInt(&o_zero, 0);
284 SetInt(&o_one, 1);
285 SetInt(&o_two, 2);
286 SetSymbol(&o_none, s_none);
287 #ifdef SC_WIN32
289 double a = 0.0;
290 double b = 1.0/a;
291 SetFloat(&o_inf, b);
293 #else
294 SetFloat(&o_inf, INFINITY);
295 #endif
297 slotCopy(&gSpecialValues[svNil], &o_nil);
298 slotCopy(&gSpecialValues[svFalse], &o_false);
299 slotCopy(&gSpecialValues[svTrue], &o_true);
300 slotCopy(&gSpecialValues[svNegOne], &o_negone);
301 slotCopy(&gSpecialValues[svZero], &o_zero);
302 slotCopy(&gSpecialValues[svOne], &o_one);
303 slotCopy(&gSpecialValues[svTwo], &o_two);
304 slotCopy(&gSpecialValues[svFHalf], &o_fhalf);
305 slotCopy(&gSpecialValues[svFNegOne], &o_fnegone);
306 slotCopy(&gSpecialValues[svFZero], &o_fzero);
307 slotCopy(&gSpecialValues[svFOne], &o_fone);
308 slotCopy(&gSpecialValues[svFTwo], &o_ftwo);
309 slotCopy(&gSpecialValues[svInf], &o_inf);
311 gFormatElemSize[obj_notindexed] = sizeof(PyrSlot);
312 gFormatElemSize[obj_slot ] = sizeof(PyrSlot);
313 gFormatElemSize[obj_double] = sizeof(double);
314 gFormatElemSize[obj_float ] = sizeof(float);
315 gFormatElemSize[obj_int32 ] = sizeof(int32);
316 gFormatElemSize[obj_int16 ] = sizeof(int16);
317 gFormatElemSize[obj_int8 ] = sizeof(int8);
318 gFormatElemSize[obj_char ] = sizeof(char);
319 gFormatElemSize[obj_symbol ] = sizeof(PyrSymbol*);
321 gFormatElemCapc[obj_notindexed] = sizeof(PyrSlot) / sizeof(PyrSlot);
322 gFormatElemCapc[obj_slot ] = sizeof(PyrSlot) / sizeof(PyrSlot);
323 gFormatElemCapc[obj_double] = sizeof(PyrSlot) / sizeof(double);
324 gFormatElemCapc[obj_float ] = sizeof(PyrSlot) / sizeof(float);
325 gFormatElemCapc[obj_int32 ] = sizeof(PyrSlot) / sizeof(int32);
326 gFormatElemCapc[obj_int16 ] = sizeof(PyrSlot) / sizeof(int16);
327 gFormatElemCapc[obj_int8 ] = sizeof(PyrSlot) / sizeof(int8);
328 gFormatElemCapc[obj_char ] = sizeof(PyrSlot) / sizeof(char);
329 gFormatElemCapc[obj_symbol] = sizeof(PyrSlot) / sizeof(PyrSymbol*);
331 gFormatElemTag[obj_notindexed] = -1;
332 gFormatElemTag[obj_slot ] = -1;
333 gFormatElemTag[obj_double] = 0;
334 gFormatElemTag[obj_float ] = 0;
335 gFormatElemTag[obj_int32 ] = tagInt;
336 gFormatElemTag[obj_int16 ] = tagInt;
337 gFormatElemTag[obj_int8 ] = tagInt;
338 gFormatElemTag[obj_char ] = tagChar;
339 gFormatElemTag[obj_symbol] = tagSym;
342 const char *slotSymString(PyrSlot* slot)
344 switch (GetTag(slot)) {
345 case tagObj : return slotRawSymbol(&slotRawObject(slot)->classptr->name)->name;
346 case tagInt : return "Integer";
347 case tagChar : return "Char";
348 case tagSym : return slotRawSymbol(slot)->name;
349 case tagNil : return "Nil";
350 case tagFalse : return "False";
351 case tagTrue : return "True";
352 default : return "<float>";
356 PyrClass* newClassObj(PyrClass *classObjSuperClass,
357 PyrSymbol* className, PyrSymbol* superClassName,
358 int numInstVars, int numClassVars, int numConsts, int numInstMethods,
359 int instFormat, int instFlags)
361 PyrClass* classobj, *superclassobj;
362 PyrObject* array;
363 PyrSymbolArray *symarray;
364 int classFlags;
367 int c;
368 c = className->name[0];
369 if (!(c >= 'A' && c <= 'Z')) Debugger();
371 // pyrmalloc:
372 // lifetime: kill upon recompiling library
373 classobj = (PyrClass*)pyr_pool_runtime->Alloc(sizeof(PyrClass));
374 MEMFAIL(classobj);
375 classobj->size = (sizeof(PyrClass) - sizeof(PyrObjectHdr))/sizeof(PyrSlot);
376 classobj->prev = classobj->next = NULL;
377 classobj->obj_flags = obj_immutable ;
378 classobj->obj_format = obj_notindexed ;
379 classobj->gc_color = obj_permanent ;
380 classobj->obj_sizeclass = LOG2CEIL(classobj->size);
381 classobj->classptr = classObjSuperClass;
384 // append to the list of classes
385 if (gClassList) SetObject(&classobj->nextclass, gClassList);
386 else SetNil(&classobj->nextclass);
388 gClassList = classobj;
390 className->u.classobj = classobj;
391 //postfl("> '%s' %d %d\n", className->name, className, classobj);
393 SetSymbol(&classobj->name, className);
394 if (superClassName) {
395 SetSymbol(&classobj->superclass, superClassName);
396 superclassobj = superClassName->u.classobj;
397 } else {
398 SetSymbol(&classobj->superclass, s_none);
399 superclassobj = NULL;
402 SetInt(&classobj->subclasses, 0); // to be filled with subclasses later
403 // in the meantime it is used as a tally of subclasses so that its allocation
404 // size can be known
406 if (numInstMethods) {
407 array = newPyrArray(NULL, numInstMethods, obj_permanent | obj_immutable, false);
408 SetObject(&classobj->methods, array);
409 } else {
410 SetNil(&classobj->methods);
413 if (numInstVars) {
414 symarray = newPyrSymbolArray(NULL, numInstVars, obj_permanent | obj_immutable, false);
415 SetObject(&classobj->instVarNames, symarray);
417 array = newPyrArray(NULL, numInstVars, obj_permanent | obj_immutable, false);
418 SetObject(&classobj->iprototype, array);
419 nilSlots(array->slots, numInstVars);
420 } else {
421 SetNil(&classobj->instVarNames);
422 SetNil(&classobj->iprototype);
425 if (numClassVars) {
426 symarray = newPyrSymbolArray(NULL, numClassVars, obj_permanent | obj_immutable, false);
427 SetObject(&classobj->classVarNames, symarray);
429 array = newPyrArray(NULL, numClassVars, obj_permanent | obj_immutable, false);
430 SetObject(&classobj->cprototype, array);
431 nilSlots(array->slots, numClassVars);
432 } else {
433 SetNil(&classobj->classVarNames);
434 SetNil(&classobj->cprototype);
437 if (numConsts) {
438 symarray = newPyrSymbolArray(NULL, numConsts, obj_permanent | obj_immutable, false);
439 SetObject(&classobj->constNames, symarray);
441 array = newPyrArray(NULL, numConsts, obj_permanent | obj_immutable, false);
442 SetObject(&classobj->constValues, array);
443 nilSlots(array->slots, numConsts);
444 } else {
445 SetNil(&classobj->constNames);
446 SetNil(&classobj->constValues);
449 classFlags = 0;
450 if (instFormat != obj_notindexed) {
451 classFlags |= classHasIndexableInstances;
454 SetInt(&classobj->instanceFormat, instFormat);
455 SetInt(&classobj->instanceFlags, instFlags);
456 SetInt(&classobj->classIndex, -1);
457 SetInt(&classobj->classFlags, classFlags);
458 SetInt(&classobj->maxSubclassIndex, 0);
459 SetNil(&classobj->filenameSym);
460 SetInt(&classobj->charPos, 0);
461 SetInt(&classobj->classVarIndex, gNumClassVars);
462 //if (numClassVars) post("%16s %4d %4d\n", className->name, gNumClassVars, numClassVars);
463 gNumClassVars += numClassVars;
464 return classobj;
467 void reallocClassObj(PyrClass* classobj,
468 int numInstVars, int numClassVars, int numConsts, int numMethods,
469 int instFormat, int instFlags)
471 PyrObject* array;
472 PyrSymbolArray *symarray;
473 PyrClass *superclassobj;
475 freePyrSlot(&classobj->methods);
476 freePyrSlot(&classobj->instVarNames);
477 freePyrSlot(&classobj->classVarNames);
478 freePyrSlot(&classobj->iprototype);
479 freePyrSlot(&classobj->cprototype);
481 freePyrSlot(&classobj->constNames);
482 freePyrSlot(&classobj->constValues);
484 if (numMethods) {
485 array = newPyrArray(NULL, numMethods, obj_permanent | obj_immutable, false);
486 SetObject(&classobj->methods, array);
487 } else {
488 SetNil(&classobj->methods);
491 if (numInstVars) {
492 //post("reallocClassObj %s numInstVars %d\n", slotRawSymbol(&classobj->name)->name, numInstVars);
493 symarray = newPyrSymbolArray(NULL, numInstVars, obj_permanent | obj_immutable, false);
494 SetObject(&classobj->instVarNames, symarray);
496 array = newPyrArray(NULL, numInstVars, obj_permanent | obj_immutable, false);
497 SetObject(&classobj->iprototype, array);
498 nilSlots(array->slots, numInstVars);
499 } else {
500 SetNil(&classobj->instVarNames);
501 SetNil(&classobj->iprototype);
504 if (numClassVars) {
505 //post("reallocClassObj %s numClassVars %d\n", slotRawSymbol(&classobj->name)->name, numClassVars);
506 symarray = newPyrSymbolArray(NULL, numClassVars, obj_permanent | obj_immutable, false);
507 SetObject(&classobj->classVarNames, symarray);
508 nilSlots(array->slots, numClassVars);
510 array = newPyrArray(NULL, numClassVars, obj_permanent | obj_immutable, false);
511 SetObject(&classobj->cprototype, array);
512 nilSlots(array->slots, numClassVars);
513 } else {
514 SetNil(&classobj->classVarNames);
515 SetNil(&classobj->cprototype);
518 if (numConsts) {
519 //post("reallocClassObj %s numConsts %d\n", slotRawSymbol(&classobj->name)->name, numConsts);
520 symarray = newPyrSymbolArray(NULL, numConsts, obj_permanent | obj_immutable, false);
521 SetObject(&classobj->constNames, symarray);
523 array = newPyrArray(NULL, numConsts, obj_permanent | obj_immutable, false);
524 SetObject(&classobj->constValues, array);
525 nilSlots(array->slots, numConsts);
526 } else {
527 SetNil(&classobj->constNames);
528 SetNil(&classobj->constValues);
531 superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
533 SetInt(&classobj->instanceFormat, instFormat);
534 SetInt(&classobj->instanceFlags, instFlags);
535 SetInt(&classobj->classIndex, -1);
538 void fixClassArrays(PyrClass *classobj);
539 void fixClassArrays(PyrClass *classobj)
541 if (IsObj(&classobj->methods)) slotRawObject(&classobj->methods)->classptr = class_array;
542 if (IsObj(&classobj->instVarNames)) slotRawObject(&classobj->instVarNames)->classptr = class_symbolarray;
543 if (IsObj(&classobj->classVarNames)) slotRawObject(&classobj->classVarNames)->classptr = class_symbolarray;
544 if (IsObj(&classobj->iprototype)) slotRawObject(&classobj->iprototype)->classptr = class_array;
545 if (IsObj(&classobj->cprototype)) slotRawObject(&classobj->cprototype)->classptr = class_array;
548 int numInstVars(PyrClass* classobj)
550 int res;
551 if (IsNil(&classobj->instVarNames))
552 res = 0;
553 else
554 res = slotRawObject(&classobj->instVarNames)->size;
555 return res;
558 int numClassVars(PyrClass* classobj)
560 int res;
561 if (IsNil(&classobj->classVarNames)) res = 0;
562 else res = slotRawObject(&classobj->classVarNames)->size;
563 return res;
567 void objAddIndexedSlotGrow(PyrSlot *arraySlot, PyrSlot *addSlot);
568 void objAddIndexedSlotGrow(PyrSlot *arraySlot, PyrSlot *addSlot)
570 PyrObject *obj;
571 if (IsNil(arraySlot)) {
572 PyrObject *newobj = (PyrObject*)newPyrArray(NULL, 1, obj_permanent | obj_immutable, false);
573 SetObject(arraySlot, newobj);
574 obj = newobj;
575 } else {
576 obj = slotRawObject(arraySlot);
577 if (obj->size >= ARRAYMAXINDEXSIZE(obj)) {
578 //post("objAddIndexedSlotGrow\n");
579 PyrObject *newobj = (PyrObject*)newPyrArray(NULL, obj->size * 2, obj_permanent | obj_immutable, false);
580 memcpy(newobj->slots, obj->slots, obj->size * sizeof(PyrSlot));
581 newobj->size = obj->size;
582 SetObject(arraySlot, newobj);
583 pyr_pool_runtime->Free((void*)obj);
584 obj = newobj;
587 slotCopy(&obj->slots[obj->size++], addSlot);
590 void addMethod(PyrClass *classobj, PyrMethod *method)
592 PyrSlot slot;
593 SetObject(&slot, method);
594 objAddIndexedSlotGrow(&classobj->methods, &slot);
599 PyrMethod* classFindDirectMethod(PyrClass* classobj, PyrSymbol *name)
601 PyrMethod *method;
602 PyrSlot *methods;
603 int i, numMethods;
604 if (IsNil(&classobj->methods)) return NULL;
605 methods = slotRawObject(&classobj->methods)->slots;
606 numMethods = slotRawObject(&classobj->methods)->size;
607 for (i=0; i<numMethods; ++i) {
608 method = slotRawMethod(&methods[i]);
609 if (slotRawSymbol(&method->name) == name) break;
611 if (i>=numMethods) method = NULL;
612 return method;
615 int numSuperInstVars(PyrClass *superclassobj)
617 int superinstvars = 0;
618 if (superclassobj) {
619 if (IsObj(&superclassobj->iprototype)) {
620 superinstvars = slotRawObject(&superclassobj->iprototype)->size;
623 return superinstvars;
626 bool classFindInstVar(PyrClass* classobj, PyrSymbol *name, int *index)
628 PyrSymbolArray *ivnames;
629 PyrSymbol *ivname;
630 int i;
631 if (NotNil(&classobj->instVarNames)) {
632 ivnames = slotRawSymbolArray(&classobj->instVarNames);
633 if (ivnames) {
634 for (i=0; i<ivnames->size; ++i) {
635 ivname = ivnames->symbols[i];
636 if (ivname == name) {
637 //numsupervars = numSuperInstVars(slotRawSymbol(&classobj->superclass)->u.classobj);
638 //*index = numsupervars + i;
639 *index = i;
640 return true;
645 return false;
648 int instVarOffset(const char *classname, const char *instvarname)
650 PyrSymbol *instvarsymbol, *classsymbol;
651 PyrClass* classobj;
652 int index;
653 char c;
655 classsymbol = getsym(classname);
656 instvarsymbol = getsym(instvarname);
658 c = classname[0];
659 if (!(c >= 'A' && c <= 'Z')) return -1;
661 classobj = classsymbol->u.classobj;
662 if (!classobj) return -1;
663 if (!classFindInstVar(classobj, instvarsymbol, &index)) return -1;
664 return index;
667 int classVarOffset(const char *classname, const char *classvarname, PyrClass** classobj)
669 PyrSymbol *classvarsymbol, *classsymbol;
670 int index;
671 char c;
673 classsymbol = getsym(classname);
674 classvarsymbol = getsym(classvarname);
676 c = classname[0];
677 if (!(c >= 'A' && c <= 'Z')) return -1;
679 *classobj = classsymbol->u.classobj;
680 if (!*classobj) return -1;
681 if (!classFindClassVar(classobj, classvarsymbol, &index)) return -1;
682 return index;
685 bool classFindClassVar(PyrClass** classobj, PyrSymbol *name, int *index)
687 PyrSymbolArray *cvnames;
688 PyrSymbol *cvname;
689 int i, j;
690 char *classname;
691 PyrClass* localclassobj = *classobj;
692 // if this is a Metaclass then we need to search its normal Class for
693 // the class vars
694 classname = slotRawSymbol(&localclassobj->name)->name;
695 if (strncmp(classname, "Meta_", 5) == 0) {
696 localclassobj = getsym(classname+5)->u.classobj;
698 for (j=0; localclassobj; ++j) {
699 if (NotNil(&localclassobj->classVarNames)) {
700 cvnames = slotRawSymbolArray(&localclassobj->classVarNames);
701 if (cvnames) {
702 for (i=0; i<cvnames->size; ++i) {
703 cvname = cvnames->symbols[i];
704 if (cvname == name) {
705 *classobj = localclassobj;
706 *index = i;
707 return true;
712 if (IsSym(&localclassobj->superclass)) {
713 localclassobj = slotRawSymbol(&localclassobj->superclass)->u.classobj;
714 } else {
715 localclassobj = NULL;
718 return false;
721 bool classFindConst(PyrClass** classobj, PyrSymbol *name, int *index)
723 PyrSymbolArray *knames;
724 PyrSymbol *kname;
725 int i, j;
726 char *classname;
727 PyrClass* localclassobj = *classobj;
728 // if this is a Metaclass then we need to search its normal Class for
729 // the class vars
730 classname = slotRawSymbol(&localclassobj->name)->name;
731 if (strncmp(classname, "Meta_", 5) == 0) {
732 localclassobj = getsym(classname+5)->u.classobj;
734 for (j=0; localclassobj; ++j) {
735 if (NotNil(&localclassobj->constNames)) {
736 knames = slotRawSymbolArray(&localclassobj->constNames);
737 if (knames) {
738 for (i=0; i<knames->size; ++i) {
739 kname = knames->symbols[i];
740 if (kname == name) {
741 *classobj = localclassobj;
742 *index = i;
743 return true;
748 if (IsSym(&localclassobj->superclass)) {
749 localclassobj = slotRawSymbol(&localclassobj->superclass)->u.classobj;
750 } else {
751 localclassobj = NULL;
754 return false;
757 struct compareByName
759 bool operator()(PyrClass * lhs, PyrClass * rhs) const
761 return strcmp(slotRawSymbol(&lhs->name)->name, slotRawSymbol(&rhs->name)->name) < 0;
766 template <class T>
767 class pyr_pool_compile_allocator
769 public:
770 typedef std::size_t size_type;
771 typedef std::ptrdiff_t difference_type;
772 typedef T* pointer;
773 typedef const T* const_pointer;
774 typedef T& reference;
775 typedef const T& const_reference;
776 typedef T value_type;
778 template <class U> struct rebind
780 typedef pyr_pool_compile_allocator<U> other;
783 pyr_pool_compile_allocator(void)
786 template <class U>
787 pyr_pool_compile_allocator(pyr_pool_compile_allocator<U> const &)
790 pointer address(reference x) const
792 return &x;
795 const_pointer address(const_reference x) const
797 return &x;
800 pointer allocate(size_type n, const void* hint = 0)
802 return (pointer)pyr_pool_compile->Alloc(n*sizeof(T));
805 void deallocate(pointer p, size_type n)
807 pyr_pool_compile->Free(p);
810 void construct(pointer p, const T& val)
812 ::new(p) T(val);
815 void destroy(pointer p)
817 p->~T();
822 /* sort list of classes:
823 * we fill a binary search tree
826 static PyrClass * sortClasses(PyrClass * aClassList)
828 typedef std::set<PyrClass*, compareByName, pyr_pool_compile_allocator<PyrClass*> > classSetType;
829 classSetType classSet;
831 PyrClass * insertHead = aClassList;
832 do {
833 assert(classSet.find(insertHead) == classSet.end());
834 classSet.insert(insertHead);
835 insertHead = slotRawClass(&insertHead->nextclass);
836 } while (insertHead);
838 classSetType::iterator it = classSet.begin();
839 PyrClass * sortedClasses = *it;
840 ++it;
842 PyrClass * lastClass = sortedClasses;
843 for (; it != classSet.end(); ++it) {
844 PyrClass * current = *it;
845 SetObject(&lastClass->nextclass, (PyrObject*)current);
846 lastClass = current;
848 SetNil(&lastClass->nextclass);
849 return sortedClasses;
852 #include <boost/threadpool.hpp>
854 static int cpuCount = boost::thread::hardware_concurrency();
855 static int helperThreadCount = cpuCount - 1;
856 static boost::threadpool::fifo_pool compileThreadPool;
858 void buildClassTree()
860 // the first time we use the pool
861 compileThreadPool.size_controller().resize(helperThreadCount);
863 // after all classes are compiled this function builds the tree and
864 // indexes the classes
866 // count subclasses
867 //postfl("count subclasses\n");
868 PyrClass *classobj = gClassList;
869 while (classobj) {
870 PyrClass * superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
871 if (superclassobj) {
872 //postfl(" superclassobj %s\n", slotRawSymbol(&superclassobj->name)->name);
873 SetRaw(&superclassobj->subclasses, slotRawInt(&superclassobj->subclasses) + 1);
875 classobj = slotRawClass(&classobj->nextclass);
877 // allocate subclass arrays
878 //postfl("allocate subclass arrays\n");
879 classobj = gClassList;
880 while (classobj) {
881 int numSubclasses;
882 numSubclasses = slotRawInt(&classobj->subclasses);
883 //postfl(" %s %d\n", slotRawSymbol(&classobj->name)->name, numSubclasses);
884 if (numSubclasses) {
885 SetObject(&classobj->subclasses, (PyrObject*)newPyrArray(NULL, numSubclasses, obj_permanent | obj_immutable, false));
886 slotRawObject(&classobj->subclasses)->size = 0;
887 } else {
888 SetNil(&classobj->subclasses);
890 classobj = slotRawClass(&classobj->nextclass);
892 // fill in subclass arrays
893 //postfl("fill in subclass arrays\n");
894 classobj = gClassList;
895 while (classobj) {
896 //postfl(" %s\n", slotRawSymbol(&classobj->name)->name);
897 PyrClass *superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
898 if (superclassobj) {
899 objAddIndexedObject(slotRawObject(&superclassobj->subclasses), (PyrObject*)classobj);
900 //postfl(" superclassobj %s %d\n", slotRawSymbol(&superclassobj->name)->name,
901 // slotRawObject(&superclassobj->subclasses)->size);
903 classobj = slotRawClass(&classobj->nextclass);
906 // alpha sort the classes via insertion sort
907 gClassList = sortClasses(gClassList);
910 void indexClassTree(PyrClass *classobj, int numSuperMethods)
912 int i, numMethods;
914 if (!classobj) return;
916 SetInt(&classobj->classIndex, gNumClasses);
917 gNumClasses ++;
919 if (IsObj(&classobj->methods)) {
920 PyrObject * methods = slotRawObject(&classobj->methods);
921 numMethods = methods->size;
923 else
924 numMethods = 0;
926 numMethods = numSuperMethods + numMethods;
927 if (IsObj(&classobj->subclasses)) {
928 PyrObject * subclasses = slotRawObject(&classobj->subclasses);
929 for (i=0; i<subclasses->size; ++i)
930 indexClassTree(slotRawClass(&subclasses->slots[i]), numMethods);
932 SetInt(&classobj->maxSubclassIndex, gNumClasses - 1);
935 void findDiscrepancy();
936 void findDiscrepancy()
938 PyrClass *classobjA, *classobjB;
940 classobjA = gClassList;
941 while (classobjA) {
942 classobjB = slotRawClass(&classobjA->nextclass);;
943 while (classobjB) {
944 if (slotRawSymbol(&classobjA->name) == slotRawSymbol(&classobjB->name)) {
945 post("duplicate %s\n", slotRawSymbol(&classobjA->name)->name);
947 classobjB = slotRawClass(&classobjB->nextclass);
949 classobjA = slotRawClass(&classobjA->nextclass);
954 static void indent(int n)
956 for (int i=0; i<n; ++i) {
957 post(" ");
961 void postClassTree(PyrClass *classobj, int level)
963 PyrObject *subclasses;
964 int i;
966 //post("%4d ", slotRawInt(&classobj->classIndex));
967 indent(level);
968 post("%s\n", slotRawSymbol(&classobj->name)->name);
970 if (classobj == class_class) {
971 indent(level+1);
972 post(" [.. all metaclasses ..]\n");
973 } else {
974 if (IsNil(&classobj->subclasses))
975 return; // FIXME: can we initialize subclasses with a NULL pointer?
976 subclasses = slotRawObject(&classobj->subclasses);
977 if (subclasses) {
978 // determine if can put on one line
979 bool oneline = subclasses->size <= 5;
980 for (i=0; oneline && i<subclasses->size; ++i) {
981 PyrClass *subclassobj = slotRawClass(&subclasses->slots[i]);
982 if (IsObj(&subclassobj->subclasses))
983 // FIXME: shall we do a null-pointer check?
984 oneline = false;
986 if (oneline) {
987 indent(level+1);
988 post("[");
989 for (i=0; i<subclasses->size; ++i) {
990 PyrClass *subclassobj = slotRawClass(&subclasses->slots[i]);
991 post(" %s", slotRawSymbol(&subclassobj->name)->name);
993 post(" ]\n");
994 } else {
995 indent(level);
996 post("[\n");
997 for (i=0; i<subclasses->size; ++i) {
998 postClassTree(slotRawClass(&subclasses->slots[i]), level+1);
1000 indent(level);
1001 post("]\n");
1008 void setSelectorFlags()
1010 int i;
1012 PyrClass * classobj = gClassList;
1013 while (classobj) {
1014 if (IsObj(&classobj->methods)) {
1015 PyrObject *methods = slotRawObject(&classobj->methods);
1016 for (i=0; i<methods->size; ++i) {
1017 PyrMethod * method = slotRawMethod(&methods->slots[i]);
1018 slotRawSymbol(&method->name)->flags |= sym_Selector;
1019 //if (method->methType == methRedirect) {
1020 // post("rd: %3d %s:%s\n", k++, slotRawSymbol(&classobj->name)->name,
1021 // slotRawSymbol(&method->name)->name);
1025 classobj = slotRawClass(&classobj->nextclass);
1027 // count selectors
1028 gNumSelectors = 0;
1029 SymbolTable* symbolTable = gMainVMGlobals->symbolTable;
1030 for (int i=0; i<symbolTable->TableSize(); ++i) {
1031 PyrSymbol *sym = symbolTable->Get(i);
1032 if (sym && (sym->flags & sym_Selector)) {
1033 sym->u.index = gNumSelectors++;
1036 //post("gNumSelectors %d\n", gNumSelectors);
1039 // the chunky stuff can be commented back in for implementing a better
1040 // compression scheme. The Q&D method works fine for my small class tree for now.
1042 typedef struct {
1043 PyrSymbol *selector;
1044 int minClassIndex;
1045 int maxClassIndex;
1046 int rowWidth;
1047 //int largestChunk;
1048 //int chunkOffset;
1049 int selectorIndex;
1050 int population;
1051 int rowOffset;
1052 } ColumnDescriptor;
1054 int compareColDescs(const void *va, const void *vb);
1055 int compareColDescs(const void *va, const void *vb)
1057 ColumnDescriptor *a = (ColumnDescriptor*)va;
1058 ColumnDescriptor *b = (ColumnDescriptor*)vb;
1059 int diff;
1060 //diff = b->largestChunk - a->largestChunk;
1061 //if (diff != 0) return diff;
1062 diff = b->rowWidth - a->rowWidth;
1063 if (diff != 0) return diff;
1064 //diff = b->chunkOffset - a->chunkOffset;
1065 diff = b->minClassIndex - a->minClassIndex;
1066 return diff;
1069 #define CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME 0
1070 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1071 double elapsedTime();
1072 #endif
1074 static size_t fillClassRow(PyrClass *classobj, PyrMethod** bigTable);
1077 static void updateSelectorRowWidth(ColumnDescriptor* sels, size_t begin, size_t end)
1079 for (int i=begin; i<end; ++i) {
1080 //if (chunkSize > sels[i].largestChunk) {
1081 // sels[i].largestChunk = chunkSize;
1082 // sels[i].chunkOffset = chunkOffset;
1084 sels[i].rowWidth = sels[i].maxClassIndex - sels[i].minClassIndex + 1;
1088 static void binsortClassRows(PyrMethod ** bigTable, const ColumnDescriptor* sels, size_t numSelectors, size_t begin, size_t end)
1090 // bin sort the class rows to the new ordering
1091 //post("reorder rows\n");
1092 const int allocaThreshold = 4096;
1094 PyrMethod** temprow = (numSelectors < allocaThreshold) ? (PyrMethod**)alloca(numSelectors * sizeof(PyrMethod*))
1095 : (PyrMethod**)malloc(numSelectors * sizeof(PyrMethod*));
1097 for (int j=begin; j<end; ++j) {
1098 PyrMethod** row = bigTable + j * numSelectors;
1099 memcpy(temprow, row, numSelectors * sizeof(PyrMethod*));
1100 for (int i=0; i<numSelectors; ++i)
1101 row[i] = temprow[sels[i].selectorIndex];
1104 if (numSelectors >= allocaThreshold)
1105 free(temprow);
1108 static void prepareColumnTable(ColumnDescriptor * sels, int numSelectors)
1110 // fill selector table
1111 //post("fill selector table\n");
1112 SymbolTable* symbolTable = gMainVMGlobals->symbolTable;
1113 for (int i=0, j=0; i<symbolTable->TableSize(); ++i) {
1114 PyrSymbol *sym = symbolTable->Get(i);
1115 if (sym && (sym->flags & sym_Selector))
1116 sels[j++].selector = sym;
1119 for (int i=0; i<numSelectors; ++i) {
1120 //postfl("%3d %s\n", i, sels[i].selector->name);
1121 sels[i].minClassIndex = INT_MAX;
1122 sels[i].maxClassIndex = 0;
1123 //sels[i].largestChunk = 0;
1124 //sels[i].chunkOffset = 0;
1125 sels[i].selectorIndex = i;
1126 sels[i].population = 0;
1130 static void calcRowStats(PyrMethod** bigTable, ColumnDescriptor * sels, int numClasses, int numSelectors, int begin, int end)
1132 //chunkSize = 0;
1133 //chunkOffset = 0;
1134 PyrMethod** methodPtr = bigTable;
1135 for (int j=0; j<numClasses; ++j) {
1136 for (int i=begin; i<end; ++i) {
1137 PyrMethod* method = bigTable[j * numSelectors + i];
1138 if (method) {
1139 //classobj = method->ownerclass.uoc;
1140 if (j > sels[i].maxClassIndex) {
1141 sels[i].maxClassIndex = j;
1143 if (j < sels[i].minClassIndex) {
1144 sels[i].minClassIndex = j;
1146 sels[i].population ++;
1147 //if (chunkSize == 0) chunkOffset = j;
1148 //chunkSize++;
1149 //postfl(" %8s %3d %3d %3d %3d\n", slotRawSymbol(&classobj->name)->name, i, j,
1150 // chunkSize, slotRawInt(&classobj->classIndex));
1151 //} else {
1152 //if (chunkSize > sels[i].largestChunk) {
1153 // sels[i].largestChunk = chunkSize;
1154 // sels[i].chunkOffset = chunkOffset;
1156 //chunkSize = 0;
1163 void buildBigMethodMatrix()
1165 PyrMethod **bigTable, **temprow, **row;
1166 PyrClass *classobj, **classes;
1167 int i, j, k;
1168 int popSum, widthSum;
1169 int rowOffset, freeIndex;
1170 int rowTableSize;
1171 int bigTableSize;
1172 const int numSelectors = gNumSelectors;
1173 const int numClasses = gNumClasses;
1174 //post("allocate arrays\n");
1176 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1177 double t0 = elapsedTime();
1178 #endif
1180 // pyrmalloc:
1181 // lifetime: kill after compile
1182 bigTableSize = numSelectors * numClasses;
1183 //post("bigTableSize %d %d %d\n", bigTableSize, numSelectors, numClasses);
1184 ColumnDescriptor *sels = (ColumnDescriptor*)pyr_pool_compile->Alloc(numSelectors * sizeof(ColumnDescriptor));
1185 MEMFAIL(sels);
1186 if (helperThreadCount)
1187 compileThreadPool.schedule(boost::bind(&prepareColumnTable, sels, numSelectors));
1188 else
1189 prepareColumnTable(sels, numSelectors);
1191 bigTable = (PyrMethod**)pyr_pool_compile->Alloc(bigTableSize * sizeof(PyrMethod*));
1192 MEMFAIL(bigTable);
1193 classes = (PyrClass**)pyr_pool_compile->Alloc(numClasses * sizeof(PyrClass*));
1194 MEMFAIL(classes);
1196 classobj = gClassList;
1197 while (classobj) {
1198 classes[slotRawInt(&classobj->classIndex)] = classobj;
1199 classobj = slotRawClass(&classobj->nextclass);
1202 size_t numentries = fillClassRow(class_object, bigTable);
1203 post("\tnumentries = %lu / %d = %.2g\n", numentries, bigTableSize, (double)numentries/(double)bigTableSize);
1205 // no need to wait for the theadpool, because it is done in fillClassRow
1207 // calc row stats
1208 //post("calc row stats\n");
1209 const int classesPerThread = numClasses/cpuCount;
1210 const int selectorsPerThread = numSelectors/cpuCount;
1211 for (i = 0; i != helperThreadCount; ++i)
1212 compileThreadPool.schedule(boost::bind(&calcRowStats, bigTable, sels, numClasses, numSelectors,
1213 selectorsPerThread * i, selectorsPerThread * (i+1)));
1215 calcRowStats(bigTable, sels, numClasses, numSelectors, helperThreadCount*selectorsPerThread, numSelectors);
1216 if (helperThreadCount) compileThreadPool.wait();
1218 for (i = 0; i != helperThreadCount; ++i)
1219 compileThreadPool.schedule(boost::bind(&updateSelectorRowWidth, sels,
1220 selectorsPerThread * i, selectorsPerThread * (i+1)));
1222 updateSelectorRowWidth(sels, helperThreadCount*selectorsPerThread, numSelectors);
1223 if (helperThreadCount) compileThreadPool.wait();
1225 //post("qsort\n");
1226 // sort rows by largest chunk, then by width, then by chunk offset
1227 //qsort(sels, numSelectors, sizeof(ColumnDescriptor), (std::_compare_function)compareColDescs);
1228 qsort(sels, numSelectors, sizeof(ColumnDescriptor), compareColDescs);
1230 // bin sort the class rows to the new ordering
1231 //post("reorder rows\n");
1232 for (i = 0; i != helperThreadCount; ++i)
1233 compileThreadPool.schedule(boost::bind(&binsortClassRows, bigTable, sels, numSelectors,
1234 classesPerThread * i, classesPerThread * (i+1)));
1236 binsortClassRows(bigTable, sels, numSelectors, helperThreadCount*classesPerThread, numClasses);
1237 if (helperThreadCount) compileThreadPool.wait();
1239 //post("calc row offsets %d\n", numSelectors);
1240 widthSum = 0;
1241 popSum = 0;
1242 freeIndex = 0;
1243 rowOffset = -1;
1244 for (i=0; i<numSelectors; ++i) {
1245 widthSum += sels[i].rowWidth;
1246 popSum += sels[i].population;
1247 rowOffset = sc_max(rowOffset+1, freeIndex - sels[i].minClassIndex);
1248 freeIndex = rowOffset + sels[i].maxClassIndex + 1;
1249 sels[i].rowOffset = rowOffset;
1250 sels[i].selector->u.index = rowOffset;
1251 //post("%3d %24s %3d %5d %5d\n", i, sels[i].selector->name,
1252 // sels[i].rowWidth, rowOffset, freeIndex);
1254 //post("alloc row table %d\n", freeIndex);
1255 rowTableSize = (freeIndex + numClasses) * sizeof(PyrMethod*);
1256 gRowTable = (PyrMethod**)pyr_pool_runtime->Alloc(rowTableSize);
1257 MEMFAIL(gRowTable);
1259 // having the method ptr always be valid saves a branch in SendMessage()
1260 for (i=0; i<freeIndex + numClasses; ++i)
1261 gRowTable[i] = gNullMethod;
1263 //post("fill compressed table\n");
1264 //{ FILE* fp;
1265 // newPyrMethod
1266 //fp = fopen("meth table", "w");
1267 for (i=0; i<numSelectors; ++i) {
1268 int offset, maxwidth;
1269 offset = sels[i].rowOffset + sels[i].minClassIndex;
1270 maxwidth = offset + sels[i].rowWidth;
1271 row = bigTable + sels[i].minClassIndex * numSelectors + i;
1272 PyrMethod ** table = gRowTable;
1273 for (j=offset,k=0; j<maxwidth; ++j, k+=numSelectors) {
1274 if (row[k])
1275 table[j] = row[k];
1278 //fclose(fp);
1281 for (i=0; i<freeIndex + numClasses; ++i)
1282 assert(gRowTable[i]);
1285 //post("freeIndex %d\n", freeIndex);
1286 //post("widthSum %d\n", widthSum);
1287 //post("popSum %d\n", popSum);
1289 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1290 post("building table took %.3g seconds\n", elapsedTime() - t0);
1292 int numFilled = 0;
1293 for (i=0; i<rowTableSize/sizeof(PyrMethod*); ++i) {
1294 if (gRowTable[i] != gNullMethod) numFilled++;
1296 post("Filled %d of %d = %f percent\n", numFilled, rowTableSize/sizeof(PyrMethod*),
1297 100. * (double)numFilled/(rowTableSize/sizeof(PyrMethod*)));
1299 #endif
1300 post("\t%d method selectors, %d classes\n", numSelectors, numClasses);
1301 post("\tmethod table size %d bytes, ", rowTableSize);
1302 post("big table size %d\n", numSelectors * numClasses * sizeof(PyrMethod*));
1303 //postfl("%p %p %p\n", classes, bigTable, sels);
1305 // not necessary since the entire pool will be freed..
1306 pyr_pool_compile->Free(classes);
1307 pyr_pool_compile->Free(bigTable);
1308 pyr_pool_compile->Free(sels);
1310 compileThreadPool.size_controller().resize(0); // terminate threads
1313 #include <boost/atomic.hpp>
1315 static void fillClassRowSubClasses(PyrObject * subclasses, int begin, int end, PyrMethod** bigTable, boost::atomic<size_t> * rCount);
1317 static void fillClassRow(PyrClass *classobj, PyrMethod** bigTable, boost::atomic<size_t> * rCount)
1319 size_t count = 0;
1321 PyrMethod ** myrow = bigTable + slotRawInt(&classobj->classIndex) * gNumSelectors;
1322 PyrClass* superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
1323 if (superclassobj) {
1324 PyrMethod ** superrow = bigTable + slotRawInt(&superclassobj->classIndex) * gNumSelectors;
1326 for (int i = 0; i != gNumSelectors; ++i) {
1327 myrow[i] = superrow[i];
1328 if (superrow[i])
1329 ++count;
1331 } else {
1332 memset(myrow, 0, gNumSelectors * sizeof(PyrMethod*));
1335 if (IsObj(&classobj->methods)) {
1336 PyrObject * methods = slotRawObject(&classobj->methods);
1337 //postfl(" %d\n", methods->size);
1338 for (int i=0; i<methods->size; ++i) {
1339 PyrMethod* method = slotRawMethod(&methods->slots[i]);
1340 int selectorIndex = slotRawSymbol(&method->name)->u.index;
1342 if (myrow[selectorIndex] == 0)
1343 ++count;
1345 myrow[selectorIndex] = method;
1349 *rCount += count;
1351 if (IsObj(&classobj->subclasses)) {
1352 PyrObject * subclasses = slotRawObject(&classobj->subclasses);
1353 size_t numSubclasses = subclasses->size;
1355 if (numSubclasses > 4*cpuCount) {
1356 int subclassesPerThread = numSubclasses / cpuCount;
1357 for (int i = 0; i != helperThreadCount; ++i)
1358 compileThreadPool.schedule(boost::bind(&fillClassRowSubClasses, subclasses,
1359 subclassesPerThread * i, subclassesPerThread * (i+1),
1360 bigTable, rCount));
1361 fillClassRowSubClasses(subclasses, subclassesPerThread * helperThreadCount, numSubclasses, bigTable, rCount);
1363 else
1364 fillClassRowSubClasses(subclasses, 0, numSubclasses, bigTable, rCount);
1368 static void fillClassRowSubClasses(PyrObject * subclasses, int begin, int end, PyrMethod** bigTable, boost::atomic<size_t> * rCount)
1370 for (int i = begin; i != end; ++i)
1371 fillClassRow(slotRawClass(&subclasses->slots[i]), bigTable, rCount);
1375 static size_t fillClassRow(PyrClass *classobj, PyrMethod** bigTable)
1377 boost::atomic<size_t> ret (0);
1379 fillClassRow(classobj, bigTable, &ret);
1380 if (helperThreadCount) compileThreadPool.wait();
1381 return ret.load(boost::memory_order_acquire);
1385 bool funcFindArg(PyrBlock* func, PyrSymbol *name, int *index)
1387 int i;
1388 for (i=0; i<slotRawSymbolArray(&func->argNames)->size; ++i) {
1389 if (slotRawSymbolArray(&func->argNames)->symbols[i] == name) {
1390 *index = i;
1391 return true;
1394 return false;
1397 bool funcFindVar(PyrBlock* func, PyrSymbol *name, int *index)
1399 int i;
1400 for (i=0; i<slotRawSymbolArray(&func->varNames)->size; ++i) {
1401 if (slotRawSymbolArray(&func->varNames)->symbols[i] == name) {
1402 *index = i;
1403 return true;
1406 return false;
1409 PyrClass* makeIntrinsicClass(PyrSymbol *className, PyrSymbol *superClassName,
1410 int numInstVars, int numClassVars)
1412 PyrClass *superClass = NULL;
1413 PyrClass *metaSuperClass = NULL;
1414 PyrSymbol *metaClassName = NULL;
1415 PyrSymbol *metaSuperClassName = NULL;
1416 PyrClass *classobj = NULL;
1417 PyrClass *metaclassobj = NULL;
1418 int superInstVars;
1420 //postfl("makeIntrinsicClass '%s'\n", className->name);
1421 if (superClassName) {
1422 superClass = superClassName->u.classobj;
1423 if (!superClass) {
1424 error("Can't find superclass '%s' of '%s'\n", superClassName->name,
1425 className->name);
1426 return NULL;
1428 metaSuperClassName = getmetasym(superClassName->name);
1429 metaSuperClass = metaSuperClassName->u.classobj;
1430 superInstVars = numSuperInstVars(superClass);
1431 } else {
1432 // else it must be Object and so has no superclass
1433 metaSuperClassName = NULL;
1434 superInstVars = 0;
1437 metaClassName = getmetasym(className->name);
1438 metaClassName->flags |= sym_MetaClass;
1439 metaclassobj = newClassObj( class_class,
1440 metaClassName, metaSuperClassName,
1441 classClassNumInstVars, 0, 0, 0, obj_notindexed, 0);
1442 SetInt(&metaclassobj->classFlags, slotRawInt(&metaclassobj->classFlags) | classIsIntrinsic);
1444 if (metaSuperClassName && classClassNumInstVars) {
1445 memcpy(slotRawObject(&metaclassobj->iprototype)->slots, slotRawObject(&metaSuperClass->iprototype)->slots,
1446 sizeof(PyrSlot) * classClassNumInstVars);
1447 memcpy(slotRawSymbolArray(&metaclassobj->instVarNames)->symbols,
1448 slotRawSymbolArray(&metaSuperClass->instVarNames)->symbols,
1449 sizeof(PyrSymbol*) * classClassNumInstVars);
1450 slotRawObject(&metaclassobj->iprototype)->size = classClassNumInstVars;
1451 slotRawObject(&metaclassobj->instVarNames)->size = classClassNumInstVars;
1452 //dumpObject((PyrObject*)metaclassobj);
1455 classobj = newClassObj(metaclassobj,
1456 className, superClassName,
1457 numInstVars + superInstVars, numClassVars, 0, 0, obj_notindexed, 0);
1458 SetInt(&classobj->classFlags, slotRawInt(&classobj->classFlags) | classIsIntrinsic);
1460 //postfl("%s:%s : %d\n", className->name, superClassName->name, superInstVars);
1461 if (superClass && superInstVars) {
1462 memcpy(slotRawObject(&classobj->iprototype)->slots, slotRawObject(&superClass->iprototype)->slots,
1463 sizeof(PyrSlot) * superInstVars);
1464 memcpy(slotRawSymbolArray(&classobj->instVarNames)->symbols,
1465 slotRawSymbolArray(&superClass->instVarNames)->symbols,
1466 sizeof(PyrSymbol*) * superInstVars);
1467 slotRawObject(&classobj->iprototype)->size = superInstVars;
1468 slotRawObject(&classobj->instVarNames)->size = superInstVars;
1471 return classobj;
1474 void addIntrinsicVar(PyrClass *classobj, const char *varName, PyrSlot *slot)
1476 //postfl("%s %s %d\n", slotRawSymbol(&classobj->name)->name, varName,
1477 // slotRawObject(&classobj->instVarNames)->size);
1478 objAddIndexedSymbol(slotRawSymbolArray(&classobj->instVarNames), getsym(varName));
1479 objAddIndexedSlot(slotRawObject(&classobj->iprototype), slot);
1482 void addIntrinsicClassVar(PyrClass *classobj, const char *varName, PyrSlot *slot);
1483 void addIntrinsicClassVar(PyrClass *classobj, const char *varName, PyrSlot *slot)
1485 //postfl("%s %s %d\n", slotRawSymbol(&classobj->name)->name, varName,
1486 // slotRawObject(&classobj->instVarNames)->size);
1487 objAddIndexedSymbol(slotRawSymbolArray(&classobj->classVarNames), getsym(varName));
1488 objAddIndexedSlot(slotRawObject(&classobj->cprototype), slot);
1491 void initClasses()
1493 PyrClass *class_object_meta;
1494 PyrMethodRaw *methraw;
1496 // BOOTSTRAP THE OBJECT HIERARCHY
1498 gNumClassVars = 0;
1499 gClassList = NULL;
1500 gNullMethod = newPyrMethod();
1501 SetSymbol(&gNullMethod->name, (PyrSymbol*)NULL);
1502 methraw = METHRAW(gNullMethod);
1503 methraw->methType = methNormal;
1505 // build intrinsic classes
1506 class_class = NULL;
1507 class_object = makeIntrinsicClass(s_object, 0, 0, 4);
1508 class_class = makeIntrinsicClass(s_class, s_object, classClassNumInstVars, 1);
1510 // now fix class_class ptrs that were just previously installed erroneously
1511 class_object->classptr->classptr = class_class;
1512 class_class->classptr->classptr = class_class;
1513 class_object_meta = class_object->classptr;
1514 class_object_meta->superclass = class_class->name;
1516 addIntrinsicClassVar(class_object, "dependantsDictionary", &o_nil);
1517 addIntrinsicClassVar(class_object, "currentEnvironment", &o_nil);
1518 addIntrinsicClassVar(class_object, "topEnvironment", &o_nil);
1519 addIntrinsicClassVar(class_object, "uniqueMethods", &o_nil);
1521 // declare varNames for Class
1523 addIntrinsicVar(class_class, "name", &o_nil);
1524 addIntrinsicVar(class_class, "nextclass", &o_nil);
1525 addIntrinsicVar(class_class, "superclass", &o_nil);
1526 addIntrinsicVar(class_class, "subclasses", &o_nil);
1527 addIntrinsicVar(class_class, "methods", &o_nil);
1529 addIntrinsicVar(class_class, "instVarNames", &o_nil);
1530 addIntrinsicVar(class_class, "classVarNames", &o_nil);
1531 addIntrinsicVar(class_class, "iprototype", &o_nil);
1532 addIntrinsicVar(class_class, "cprototype", &o_nil);
1534 addIntrinsicVar(class_class, "constNames", &o_nil);
1535 addIntrinsicVar(class_class, "constValues", &o_nil);
1537 addIntrinsicVar(class_class, "instanceFormat", &o_nil);
1538 addIntrinsicVar(class_class, "instanceFlags", &o_zero);
1539 addIntrinsicVar(class_class, "classIndex", &o_zero);
1540 addIntrinsicVar(class_class, "classFlags", &o_zero);
1541 addIntrinsicVar(class_class, "maxSubclassIndex", &o_zero);
1542 addIntrinsicVar(class_class, "filenameSymbol", &o_nil);
1543 addIntrinsicVar(class_class, "charPos", &o_zero);
1544 addIntrinsicVar(class_class, "classVarIndex", &o_zero);
1546 addIntrinsicClassVar(class_class, "classesInited", &o_nil);
1548 // class_object_meta's inst var names need to be copied from class_class
1549 // because class_class didn't exist when it was created
1550 memcpy(slotRawObject(&class_object_meta->iprototype)->slots, slotRawObject(&class_class->iprototype)->slots,
1551 sizeof(PyrSlot) * classClassNumInstVars);
1552 memcpy(slotRawSymbolArray(&class_object_meta->instVarNames)->symbols,
1553 slotRawSymbolArray(&class_class->instVarNames)->symbols,
1554 sizeof(PyrSymbol*) * classClassNumInstVars);
1556 memcpy(slotRawObject(&class_class->classptr->iprototype)->slots, slotRawObject(&class_class->iprototype)->slots,
1557 sizeof(PyrSlot) * classClassNumInstVars);
1558 memcpy(slotRawSymbolArray(&class_class->classptr->instVarNames)->symbols,
1559 slotRawSymbolArray(&class_class->instVarNames)->symbols,
1560 sizeof(PyrSymbol*) * classClassNumInstVars);
1563 // OK the next thing I need is arrays..
1564 class_collection = makeIntrinsicClass(s_collection, s_object, 0, 0);
1565 class_sequenceable_collection = makeIntrinsicClass(s_sequenceable_collection, s_collection, 0, 0);
1567 class_arrayed_collection = makeIntrinsicClass(s_arrayed_collection, s_sequenceable_collection, 0, 0);
1568 class_array = makeIntrinsicClass(s_array, s_arrayed_collection, 0, 0);
1569 SetInt(&class_array->instanceFormat, obj_slot);
1570 SetInt(&class_array->classFlags, slotRawInt(&class_array->classFlags) | classHasIndexableInstances);
1572 // now fix array classptrs in already created classes
1573 fixClassArrays(class_class);
1574 fixClassArrays(class_class->classptr);
1575 fixClassArrays(class_object_meta);
1576 fixClassArrays(class_collection);
1577 fixClassArrays(class_sequenceable_collection);
1578 fixClassArrays(class_arrayed_collection);
1579 fixClassArrays(class_array);
1581 class_fundef = makeIntrinsicClass(s_fundef, s_object, 10, 0);
1582 // declare varNames for Block
1584 addIntrinsicVar(class_fundef, "raw1", &o_nil);
1585 addIntrinsicVar(class_fundef, "raw2", &o_nil);
1586 addIntrinsicVar(class_fundef, "code", &o_nil);
1587 addIntrinsicVar(class_fundef, "selectors", &o_nil);
1588 addIntrinsicVar(class_fundef, "constants", &o_nil);
1590 addIntrinsicVar(class_fundef, "prototypeFrame", &o_nil);
1591 addIntrinsicVar(class_fundef, "context", &o_nil);
1592 addIntrinsicVar(class_fundef, "argNames", &o_nil);
1593 addIntrinsicVar(class_fundef, "varNames", &o_nil);
1594 addIntrinsicVar(class_fundef, "sourceCode", &o_nil);
1596 class_method = makeIntrinsicClass(s_method, s_fundef, 5, 0);
1597 addIntrinsicVar(class_method, "ownerClass", &o_nil);
1598 addIntrinsicVar(class_method, "name", &o_nil);
1599 addIntrinsicVar(class_method, "primitiveName", &o_nil);
1600 addIntrinsicVar(class_method, "filenameSymbol", &o_nil);
1601 addIntrinsicVar(class_method, "charPos", &o_zero);
1602 //addIntrinsicVar(class_method, "byteMeter", &o_zero);
1603 //addIntrinsicVar(class_method, "callMeter", &o_zero);
1605 class_frame = makeIntrinsicClass(s_frame, s_object, 0, 0);
1606 SetInt(&class_frame->classFlags, slotRawInt(&class_frame->classFlags) | classHasIndexableInstances);
1607 //addIntrinsicVar(class_frame, "method", &o_nil);
1608 //addIntrinsicVar(class_frame, "caller", &o_nil);
1609 //addIntrinsicVar(class_frame, "context", &o_nil);
1610 //addIntrinsicVar(class_frame, "homeContext", &o_nil);
1611 //addIntrinsicVar(class_frame, "ip", &o_nil);
1613 class_process = makeIntrinsicClass(s_process, s_object, 6, 0);
1614 addIntrinsicVar(class_process, "classVars", &o_nil);
1615 addIntrinsicVar(class_process, "interpreter", &o_nil);
1616 addIntrinsicVar(class_process, "curThread", &o_nil);
1617 addIntrinsicVar(class_process, "mainThread", &o_nil);
1618 addIntrinsicVar(class_process, "schedulerQueue", &o_nil);
1619 addIntrinsicVar(class_process, "nowExecutingPath", &o_nil);
1621 class_interpreter = makeIntrinsicClass(s_interpreter, s_object, 29, 0);
1622 addIntrinsicVar(class_interpreter, "cmdLine", &o_nil);
1623 addIntrinsicVar(class_interpreter, "context", &o_nil);
1624 for (int i=0; i<26; ++i) {
1625 char name[2];
1626 name[0] = 'a' + i;
1627 name[1] = 0;
1628 addIntrinsicVar(class_interpreter, name, &o_nil);
1630 addIntrinsicVar(class_interpreter, "codeDump", &o_nil);
1631 addIntrinsicVar(class_interpreter, "preProcessor", &o_nil);
1633 class_absfunc = makeIntrinsicClass(s_absfunc, s_object, 0, 0);
1634 class_stream = makeIntrinsicClass(s_stream, s_absfunc, 0, 0);
1636 class_thread = makeIntrinsicClass(s_thread, s_stream, 26, 0);
1637 addIntrinsicVar(class_thread, "state", &o_nil);
1638 addIntrinsicVar(class_thread, "func", &o_nil);
1639 addIntrinsicVar(class_thread, "stack", &o_nil);
1640 addIntrinsicVar(class_thread, "method", &o_nil);
1641 addIntrinsicVar(class_thread, "block", &o_nil);
1642 addIntrinsicVar(class_thread, "frame", &o_nil);
1643 addIntrinsicVar(class_thread, "ip", &o_zero);
1644 addIntrinsicVar(class_thread, "sp", &o_zero);
1645 addIntrinsicVar(class_thread, "numpop", &o_zero);
1646 addIntrinsicVar(class_thread, "receiver", &o_nil);
1647 addIntrinsicVar(class_thread, "numArgsPushed", &o_zero);
1648 addIntrinsicVar(class_thread, "parent", &o_nil);
1649 addIntrinsicVar(class_thread, "terminalValue", &o_nil);
1651 addIntrinsicVar(class_thread, "primitiveError", &o_zero);
1652 addIntrinsicVar(class_thread, "primitiveIndex", &o_zero);
1653 addIntrinsicVar(class_thread, "randData", &o_zero);
1654 addIntrinsicVar(class_thread, "beats", &o_fzero);
1655 addIntrinsicVar(class_thread, "seconds", &o_fzero);
1656 addIntrinsicVar(class_thread, "clock", &o_nil);
1657 addIntrinsicVar(class_thread, "nextBeat", &o_nil);
1658 addIntrinsicVar(class_thread, "endBeat", &o_nil);
1659 addIntrinsicVar(class_thread, "endValue", &o_nil);
1661 addIntrinsicVar(class_thread, "environment", &o_nil);
1662 addIntrinsicVar(class_thread, "exceptionHandler", &o_nil);
1664 addIntrinsicVar(class_thread, "executingPath", &o_nil);
1665 addIntrinsicVar(class_thread, "oldExecutingPath", &o_nil);
1667 class_finalizer = makeIntrinsicClass(s_finalizer, s_object, 2, 0);
1668 addIntrinsicVar(class_finalizer, "cFunction", &o_nil);
1669 addIntrinsicVar(class_finalizer, "object", &o_nil);
1671 class_routine = makeIntrinsicClass(s_routine, s_thread, 0, 0);
1673 class_symbol = makeIntrinsicClass(s_symbol, s_object, 0, 0);
1674 class_nil = makeIntrinsicClass(s_nil, s_object, 0, 0);
1676 class_boolean = makeIntrinsicClass(s_boolean, s_object, 0, 0);
1677 class_true = makeIntrinsicClass(s_true, s_boolean, 0, 0);
1678 class_false = makeIntrinsicClass(s_false, s_boolean, 0, 0);
1680 class_magnitude = makeIntrinsicClass(s_magnitude, s_object, 0, 0);
1681 class_char = makeIntrinsicClass(s_char, s_magnitude, 0, 0);
1682 class_number = makeIntrinsicClass(s_number, s_magnitude, 0, 0);
1683 class_simple_number = makeIntrinsicClass(s_simple_number, s_number, 0, 0);
1684 class_int = makeIntrinsicClass(s_int, s_simple_number, 0, 0);
1685 class_float = makeIntrinsicClass(s_float, s_simple_number, 0, 0);
1687 class_rawptr = makeIntrinsicClass(s_rawptr, s_object, 0, 0);
1690 class_complex = makeIntrinsicClass(s_complex, s_number, 2, 0);
1691 addIntrinsicVar(class_complex, "real", &o_nil);
1692 addIntrinsicVar(class_complex, "imag", &o_nil);
1695 class_rawarray = makeIntrinsicClass(s_rawarray, s_arrayed_collection, 0, 0);
1696 //SetInt(&class_rawarray->instanceFormat, obj_int8);
1697 //slotRawInt(&class_rawarray->classFlags) |= classHasIndexableInstances;
1698 class_int8array = makeIntrinsicClass(s_int8array, s_rawarray, 0, 0);
1699 SetInt(&class_int8array->instanceFormat, obj_int8);
1700 SetInt(&class_int8array->classFlags, slotRawInt(&class_int8array->classFlags) | classHasIndexableInstances);
1701 class_int16array = makeIntrinsicClass(s_int16array, s_rawarray, 0, 0);
1702 SetInt(&class_int16array->instanceFormat, obj_int16);
1703 SetInt(&class_int16array->classFlags, slotRawInt(&class_int16array->classFlags) | classHasIndexableInstances);
1704 class_int32array = makeIntrinsicClass(s_int32array, s_rawarray, 0, 0);
1705 SetInt(&class_int32array->instanceFormat, obj_int32);
1706 SetInt(&class_int32array->classFlags, slotRawInt(&class_int32array->classFlags) | classHasIndexableInstances);
1707 class_symbolarray = makeIntrinsicClass(s_symbolarray, s_rawarray, 0, 0);
1708 SetInt(&class_symbolarray->instanceFormat, obj_symbol);
1709 SetInt(&class_symbolarray->classFlags, slotRawInt(&class_symbolarray->classFlags) | classHasIndexableInstances);
1710 class_string = makeIntrinsicClass(s_string, s_rawarray, 0, 1);
1711 addIntrinsicClassVar(class_string, "unixCmdActions", &o_nil);
1712 SetInt(&class_string->instanceFormat, obj_char);
1713 SetInt(&class_string->classFlags, slotRawInt(&class_string->classFlags) | classHasIndexableInstances);
1714 class_floatarray = makeIntrinsicClass(s_floatarray, s_rawarray, 0, 0);
1715 SetInt(&class_floatarray->instanceFormat, obj_float);
1716 SetInt(&class_floatarray->classFlags, slotRawInt(&class_floatarray->classFlags) | classHasIndexableInstances);
1717 class_signal = makeIntrinsicClass(s_signal, s_floatarray, 0, 0);
1718 SetInt(&class_signal->instanceFormat, obj_float);
1719 SetInt(&class_signal->classFlags, slotRawInt(&class_signal->classFlags) | classHasIndexableInstances);
1720 class_wavetable = makeIntrinsicClass(s_wavetable, s_floatarray, 0, 0);
1721 SetInt(&class_wavetable->instanceFormat, obj_float);
1722 SetInt(&class_wavetable->classFlags, slotRawInt(&class_wavetable->classFlags) | classHasIndexableInstances);
1724 //addIntrinsicVar(class_signal, "rate", &o_nil);
1725 class_doublearray = makeIntrinsicClass(s_doublearray, s_rawarray, 0, 0);
1726 SetInt(&class_doublearray->instanceFormat, obj_double);
1727 SetInt(&class_doublearray->classFlags, slotRawInt(&class_doublearray->classFlags) | classHasIndexableInstances);
1729 class_list = makeIntrinsicClass(s_list, s_sequenceable_collection, 1, 0);
1730 addIntrinsicVar(class_list, "array", &o_nil);
1731 //addIntrinsicVar(class_list, "size", &o_zero);
1733 class_func = makeIntrinsicClass(s_func, s_absfunc, 2, 0);
1734 addIntrinsicVar(class_func, "def", &o_nil);
1735 addIntrinsicVar(class_func, "context", &o_nil);
1737 gTagClassTable[ 0] = NULL;
1738 gTagClassTable[ 1] = NULL;
1739 gTagClassTable[ 2] = class_int;
1740 gTagClassTable[ 3] = class_symbol;
1741 gTagClassTable[ 4] = class_char;
1742 gTagClassTable[ 5] = class_nil;
1743 gTagClassTable[ 6] = class_false;
1744 gTagClassTable[ 7] = class_true;
1745 gTagClassTable[ 8] = class_rawptr;
1746 gTagClassTable[ 9] = class_float;
1747 gTagClassTable[10] = class_float;
1748 gTagClassTable[11] = class_float;
1749 gTagClassTable[12] = class_float;
1751 SetObject(&o_emptyarray, newPyrArray(NULL, 0, obj_permanent | obj_immutable, false));
1753 SetObject(&o_onenilarray, newPyrArray(NULL, 1, obj_permanent | obj_immutable, false));
1754 slotRawObject(&o_onenilarray)->size = 1;
1755 SetNil(slotRawObject(&o_onenilarray)->slots);
1757 SetObject(&o_argnamethis, newPyrSymbolArray(NULL, 1, obj_permanent | obj_immutable, false));
1758 slotRawSymbolArray(&o_argnamethis)->size = 1;
1759 slotRawSymbolArray(&o_argnamethis)->symbols[0] = s_this;
1762 post("array %p '%s'\n", class_array, class_array->name.us->name);
1763 post("o_emptyarray %p '%s'\n", slotRawObject(&o_emptyarray)->classptr, slotRawObject(&o_emptyarray)->classptr->name.us->name);
1764 post("o_argnamethis %p '%s'\n", slotRawObject(&o_argnamethis)->classptr, slotRawObject(&o_argnamethis)->classptr->name.us->name);
1765 post("o_onenilarray %p '%s'\n", slotRawObject(&o_onenilarray)->classptr, slotRawObject(&o_onenilarray)->classptr->name.us->name);
1766 dumpObjectSlot(&o_emptyarray);
1767 dumpObjectSlot(&o_argnamethis);
1768 dumpObjectSlot(&o_onenilarray);
1772 PyrObject* instantiateObject(class PyrGC *gc, PyrClass* classobj, int size,
1773 bool fill, bool collect)
1775 PyrObject *newobj, *proto;
1776 int numbytes, format, flags;
1778 format = slotRawInt(&classobj->instanceFormat);
1779 flags = slotRawInt(&classobj->instanceFlags);
1781 if (slotRawInt(&classobj->classFlags) & classHasIndexableInstances) {
1782 // create an indexable object
1783 numbytes = size * gFormatElemSize[format];
1784 newobj = gc->New(numbytes, flags, format, collect);
1785 if (fill) {
1786 newobj->size = size;
1787 if (format == obj_slot) {
1788 nilSlots(newobj->slots, size);
1789 } else {
1790 memset(newobj->slots, format == obj_char ? ' ' : 0, size * gFormatElemSize[format]);
1792 } else {
1793 newobj->size = 0;
1795 } else {
1796 if (IsObj(&classobj->iprototype)) {
1797 proto = slotRawObject(&classobj->iprototype);
1798 size = proto->size;
1799 numbytes = size * sizeof(PyrSlot);
1800 newobj = gc->New(numbytes, flags, format, collect);
1801 newobj->size = size;
1802 if (size) {
1803 memcpy(newobj->slots, proto->slots, numbytes);
1805 } else {
1806 numbytes = 0;
1807 newobj = gc->New(numbytes, flags, format, collect);
1808 newobj->size = 0;
1811 newobj->classptr = classobj;
1812 return newobj;
1815 PyrObject* instantiateObjectLight(class PyrGC *gc, PyrClass* classobj, int size, bool collect);
1816 PyrObject* instantiateObjectLight(class PyrGC *gc, PyrClass* classobj, int size, bool collect)
1818 PyrObject *newobj, *proto;
1819 int numbytes, format, flags;
1821 format = slotRawInt(&classobj->instanceFormat);
1822 flags = slotRawInt(&classobj->instanceFlags);
1824 if (slotRawInt(&classobj->classFlags) & classHasIndexableInstances) {
1825 numbytes = size * gFormatElemSize[format];
1826 } else {
1827 if (IsObj(&classobj->iprototype)) {
1828 proto = slotRawObject(&classobj->iprototype);
1829 size = proto->size;
1830 numbytes = size * sizeof(PyrSlot);
1831 } else {
1832 size = 0;
1833 numbytes = 0;
1836 newobj = gc->New(numbytes, flags, format, collect);
1837 newobj->size = size;
1838 newobj->classptr = classobj;
1840 return newobj;
1843 PyrObject* copyObject(class PyrGC *gc, PyrObject *inobj, bool collect)
1845 PyrObject *newobj;
1847 int flags = ~(obj_immutable) & inobj->obj_flags;
1849 int elemsize = gFormatElemSize[inobj->obj_format];
1850 int numbytes = inobj->size * elemsize;
1852 newobj = gc->New(numbytes, flags, inobj->obj_format, collect);
1854 newobj->size = inobj->size;
1855 newobj->classptr = inobj->classptr;
1857 memcpy(newobj->slots, inobj->slots, inobj->size * elemsize);
1858 return newobj;
1861 PyrObject* copyObjectRange(class PyrGC *gc, PyrObject *inobj, int start, int end, bool collect)
1863 PyrObject *newobj;
1865 if (start < 0) start = 0;
1866 if (end >= inobj->size) end = inobj->size - 1;
1867 int length = end - start + 1;
1868 if (length < 0) length = 0;
1870 int elemsize = gFormatElemSize[inobj->obj_format];
1871 int numbytes = length * elemsize;
1873 int flags = ~(obj_immutable) & inobj->obj_flags;
1875 newobj = gc->New(numbytes, flags, inobj->obj_format, collect);
1876 newobj->size = length;
1877 newobj->classptr = inobj->classptr;
1879 if (length > 0) {
1880 memcpy(newobj->slots, (char*)(inobj->slots) + start * elemsize, length * elemsize);
1882 return newobj;
1885 void dumpObject(PyrObject *obj)
1887 char str[256];
1888 PyrClass *classobj;
1889 int i;
1891 if (obj == NULL) {
1892 postfl("NULL object pointer\n");
1893 return;
1895 classobj = obj->classptr;
1896 if (isKindOf(obj, class_class)) {
1897 post("class %s (%p) {\n", slotRawSymbol(&((PyrClass*)obj)->name)->name, obj);
1898 } else {
1899 //post("Instance of %s (%p) {\n", slotRawSymbol(&classobj->name)->name, obj);
1900 post("Instance of %s { (%p, gc=%02X, fmt=%02X, flg=%02X, set=%02X)\n",
1901 slotRawSymbol(&classobj->name)->name, obj, obj->gc_color, obj->obj_format, obj->obj_flags,
1902 obj->obj_sizeclass);
1904 //flushPostBuf();
1906 if (obj->obj_format == obj_notindexed) {
1907 post(" instance variables [%d]\n", obj->size);
1908 for (i=0; i<obj->size; ++i) {
1909 slotString(obj->slots + i, str);
1910 post(" %s : %s\n", slotRawSymbolArray(&classobj->instVarNames)->symbols[i]->name, str);
1912 } else {
1913 int maxsize;
1914 post(" indexed slots [%d]\n", obj->size);
1915 maxsize = sc_min(32, obj->size);
1916 switch (obj->obj_format) {
1917 case obj_slot :
1918 for (i=0; i<maxsize; ++i) {
1919 slotString(obj->slots + i, str);
1920 post(" %3d : %s\n", i, str);
1922 break;
1923 case obj_double :
1924 for (i=0; i<maxsize; ++i) {
1925 post(" %3d : %f\n", i, slotRawFloat(&obj->slots[i]));
1927 break;
1928 case obj_float :
1929 for (i=0; i<maxsize; ++i) {
1930 float val;
1931 val = ((float*)(obj->slots))[i];
1932 post(" %3d : %g\n", i, val);
1934 break;
1935 case obj_int32 :
1936 for (i=0; i<maxsize; ++i) {
1937 int32 val;
1938 val = ((int32*)(obj->slots))[i];
1939 post(" %3d : %d\n", i, val);
1941 break;
1942 case obj_int16 :
1943 for (i=0; i<maxsize; ++i) {
1944 int16 val;
1945 val = ((int16*)(obj->slots))[i];
1946 post(" %3d : %d\n", i, val);
1948 break;
1949 case obj_int8 :
1950 for (i=0; i<maxsize; ++i) {
1951 int8 val;
1952 val = ((int8*)(obj->slots))[i];
1953 post(" %3d : %4d %4u 0x%02X\n", i, val, val&255, val&255);
1955 break;
1956 case obj_char :
1957 for (i=0; i<maxsize; ++i) {
1958 char val;
1959 val = ((char*)(obj->slots))[i];
1960 post(" %3d : %c\n", i, val);
1962 break;
1963 case obj_symbol :
1964 for (i=0; i<maxsize; ++i) {
1965 PyrSymbol* sym;
1966 sym = ((PyrSymbol**)(obj->slots))[i];
1967 post(" %3d : '%s'\n", i, sym->name);
1969 break;
1970 default :
1971 post("unknown obj_format %X\n", obj->obj_format);
1973 if (obj->size > maxsize) {
1974 post(" ...\n");
1977 post("}\n");
1980 void dumpBadObject(PyrObject *obj)
1982 char str[128];
1983 PyrClass *classobj;
1984 int i;
1986 if (obj == NULL) {
1987 postfl("NULL object pointer\n");
1988 return;
1990 classobj = obj->classptr;
1991 if (isKindOf(obj, class_class)) {
1992 postfl("class %s (%p) {\n", slotRawSymbol(&((PyrClass*)obj)->name)->name, obj);
1993 } else {
1994 //postfl("Instance of %s (%p) {\n", slotRawSymbol(&classobj->name)->name, obj);
1995 postfl("Instance of %s { (%p, gc=%02X, fmt=%02X, flg=%02X, set=%02X)\n",
1996 slotRawSymbol(&classobj->name)->name, obj, obj->gc_color, obj->obj_format, obj->obj_flags,
1997 obj->obj_sizeclass);
1999 if (obj->obj_format == obj_notindexed) {
2000 postfl(" instance variables [%d]\n", obj->size);
2001 for (i=0; i<obj->size; ++i) {
2002 slotString(obj->slots + i, str);
2003 postfl(" %s : %s\n", slotRawSymbolArray(&classobj->instVarNames)->symbols[i]->name, str);
2005 } else {
2006 int maxsize;
2007 postfl(" indexed slots [%d]\n", obj->size);
2008 maxsize = obj->size;
2009 maxsize = sc_min(32, maxsize);
2010 switch (obj->obj_format) {
2011 case obj_slot :
2012 for (i=0; i<maxsize; ++i) {
2013 slotString(obj->slots + i, str);
2014 postfl(" %3d : %s\n", i, str);
2016 break;
2017 case obj_double :
2018 for (i=0; i<maxsize; ++i) {
2019 postfl(" %3d : %f\n", i, slotRawFloat(&obj->slots[i]));
2021 break;
2022 case obj_float :
2023 for (i=0; i<maxsize; ++i) {
2024 float val;
2025 val = ((float*)(obj->slots))[i];
2026 postfl(" %3d : %g\n", i, val);
2028 break;
2029 case obj_int32 :
2030 for (i=0; i<maxsize; ++i) {
2031 int32 val;
2032 val = ((int32*)(obj->slots))[i];
2033 postfl(" %3d : %d\n", i, val);
2035 break;
2036 case obj_int16 :
2037 for (i=0; i<maxsize; ++i) {
2038 int16 val;
2039 val = ((int16*)(obj->slots))[i];
2040 postfl(" %3d : %d\n", i, val);
2042 break;
2043 case obj_int8 :
2044 for (i=0; i<maxsize; ++i) {
2045 int8 val;
2046 val = ((int8*)(obj->slots))[i];
2047 postfl(" %3d : %4d %4u 0x%02X\n", i, val, val&255, val&255);
2049 break;
2050 case obj_char :
2051 for (i=0; i<maxsize; ++i) {
2052 char val;
2053 val = ((char*)(obj->slots))[i];
2054 postfl(" %3d : %c\n", i, val);
2056 break;
2057 case obj_symbol :
2058 for (i=0; i<maxsize; ++i) {
2059 PyrSymbol* sym;
2060 sym = ((PyrSymbol**)(obj->slots))[i];
2061 post(" %3d : '%s'\n", i, sym->name);
2063 break;
2064 default :
2065 postfl("unknown obj_format %X\n", obj->obj_format);
2067 if (obj->size > maxsize) {
2068 postfl(" ...\n");
2071 postfl("}\n");
2074 void dumpObjectSlot(PyrSlot *slot)
2076 if (IsObj(slot)) {
2077 dumpObject(slotRawObject(slot));
2078 } else {
2079 dumpPyrSlot(slot);
2083 void dumpSlotOneWord(const char *tagstr, PyrSlot *slot)
2085 char str[256];
2086 slotOneWord(slot, str);
2087 post("%s %s\n", tagstr, str);
2090 void CallStackSanity(VMGlobals *g, const char *tagstr);
2091 void CallStackSanity(VMGlobals *g, const char *tagstr)
2093 PyrFrame *frame;
2094 frame = g->frame;
2095 while (frame) {
2096 if (FrameSanity(frame, tagstr)) {
2097 DumpBackTrace(g);
2098 //Debugger();
2099 break;
2101 frame = slotRawFrame(&frame->caller);
2105 bool FrameSanity(PyrFrame *frame, const char *tagstr);
2106 bool FrameSanity(PyrFrame *frame, const char *tagstr)
2108 bool failed = false;
2109 if (frame==NULL) return false;
2110 if (NotObj(&frame->method)) {
2111 postfl("Frame %p method tag wrong %p\n", frame, GetTag(&frame->method));
2112 failed = true;
2113 //} else if (!isKindOf((PyrObject*)slotRawObject(&frame->method)->classptr, class_fundef)) {
2114 } else if (slotRawObject(&frame->method)->classptr != class_method && slotRawObject(&frame->method)->classptr != class_fundef) {
2115 postfl("Frame %p method class wrong %p\n", frame, slotRawObject(&frame->method)->classptr);
2116 failed = true;
2117 //if (slotRawObject(&frame->method)->classptr->classptr == class_class) {
2118 postfl("class: '%s'\n", slotRawSymbol(&slotRawObject(&frame->method)->classptr->name)->name);
2119 ///} else {
2120 // postfl("not even a class\n");
2122 } else if (NotObj(&slotRawBlock(&frame->method)->code)) {
2123 postfl("Method %p code tag wrong %p\n", slotRawBlock(&frame->method), GetTag(&slotRawBlock(&frame->method)->code));
2124 failed = true;
2125 } else if (slotRawObject(&slotRawBlock(&frame->method)->code)->classptr != class_int8array) {
2126 postfl("Code %p class wrong %p\n", slotRawObject(&slotRawBlock(&frame->method)->code), slotRawObject(&slotRawBlock(&frame->method)->code)->classptr);
2127 postfl("class: '%s'\n", slotRawSymbol(&slotRawObject(&slotRawBlock(&frame->method)->code)->classptr->name)->name);
2128 failed = true;
2131 if (frame->caller.utag != tagHFrame && frame->caller.utag != tagNil) {
2132 postfl("Frame %p caller tag wrong %p\n", frame, frame->caller.utag);
2133 failed = true;
2135 if (frame->context.utag != tagHFrame && frame->context.utag != tagNil) {
2136 postfl("Frame %p context tag wrong %p\n", frame, frame->context.utag);
2137 failed = true;
2139 if (frame->homeContext.utag != tagHFrame && frame->homeContext.utag != tagNil) {
2140 postfl("Frame %p homeContext tag wrong %p\n", frame, frame->homeContext.utag);
2141 failed = true;
2144 if (!IsPtr(&frame->ip)) {
2145 postfl("Frame %p ip tag wrong %p\n", frame, GetTag(&frame->ip));
2146 failed = true;
2148 return failed;
2151 void DumpFrame(PyrFrame *frame)
2153 char str[256];
2154 int i, numargs;
2155 PyrMethod *meth;
2156 PyrMethodRaw *methraw;
2158 if (FrameSanity(frame, "DumpFrame")) {
2159 post("FRAME CORRUPTED\n");
2160 return;
2162 slotOneWord(&frame->method, str);
2163 //slotString(&frame->method, str);
2165 meth = slotRawMethod(&frame->method);
2166 methraw = METHRAW(meth);
2167 if (methraw->numtemps) {
2168 post("\t%s %p\n", str, frame);
2169 numargs = methraw->numargs + methraw->varargs;
2170 for (i=0; i<methraw->numtemps; ++i) {
2171 slotOneWord(frame->vars + i, str);
2172 //slotString(frame->vars + i, str);
2173 if (i < numargs) {
2174 post("\t\targ %s = %s\n", slotRawSymbolArray(&meth->argNames)->symbols[i]->name, str);
2175 } else {
2176 post("\t\tvar %s = %s\n", slotRawSymbolArray(&meth->varNames)->symbols[i - numargs]->name, str);
2179 } else {
2180 post("\t%s (no arguments or variables)\n", str);
2184 void dumpByteCodes(PyrBlock *theBlock);
2186 void DumpDetailedFrame(PyrFrame *frame);
2187 void DumpDetailedFrame(PyrFrame *frame)
2189 char mstr[256];
2190 char str[256];
2191 int i, numargs;
2192 PyrMethod *meth;
2193 PyrMethodRaw *methraw;
2195 if (FrameSanity(frame, "DumpDetailedFrame")) {
2196 post("FRAME CORRUPTED\n");
2197 return;
2199 slotOneWord(&frame->method, mstr);
2200 //slotString(&frame->method, str);
2202 meth = slotRawMethod(&frame->method);
2203 methraw = METHRAW(meth);
2205 if (methraw->numtemps) {
2206 post("\t%s\n", mstr);
2207 numargs = methraw->numargs + methraw->varargs;
2208 for (i=0; i<methraw->numtemps; ++i) {
2209 slotOneWord(frame->vars + i, str);
2210 //slotString(frame->vars + i, str);
2211 if (i < numargs) {
2212 post("\t\targ %s = %s\n", slotRawSymbolArray(&meth->argNames)->symbols[i]->name, str);
2213 } else {
2214 post("\t\tvar %s = %s\n", slotRawSymbolArray(&meth->varNames)->symbols[i - numargs]->name, str);
2217 } else {
2218 post("\t%s (no arguments or variables)\n", mstr);
2221 post("\t....%s details:\n", mstr);
2222 post("\t\tneedsHeapContext = %d\n", methraw->needsHeapContext);
2223 post("\t\tnumtemps = %d\n", methraw->numtemps);
2224 post("\t\tpopSize = %d\n", methraw->popSize);
2226 slotString(&frame->method, str); post("\t\tmethod = %s\n", str);
2227 slotString(&frame->caller, str); post("\t\tcaller = %s\n", str);
2228 slotString(&frame->context, str); post("\t\tcontext = %s\n", str);
2229 slotString(&frame->homeContext, str); post("\t\thomeCtx = %s\n", str);
2230 slotString(&frame->ip, str); post("\t\tip = %s\n", str);
2232 if (IsPtr(&frame->ip)) {
2233 post("ipoffset = %d\n", (char*)slotRawPtr(&frame->ip) - (char*)slotRawInt8Array(&meth->code)->b);
2234 dumpByteCodes(meth);
2240 bool respondsTo(PyrSlot *slot, PyrSymbol *selector)
2242 PyrClass *classobj;
2243 PyrMethod *meth;
2244 int index;
2246 classobj = classOfSlot(slot);
2248 index = slotRawInt(&classobj->classIndex) + selector->u.index;
2249 meth = gRowTable[index];
2250 return slotRawSymbol(&meth->name) == selector;
2253 PyrMethod* methodLookup(PyrSlot *slot, PyrSymbol *selector);
2254 PyrMethod* methodLookup(PyrSlot *slot, PyrSymbol *selector)
2256 PyrClass *classobj;
2257 PyrMethod *meth;
2258 int index;
2260 classobj = classOfSlot(slot);
2262 index = slotRawInt(&classobj->classIndex) + selector->u.index;
2263 meth = gRowTable[index];
2264 return meth;
2268 bool isSubclassOf(PyrClass *classobj, PyrClass *testclass)
2270 while (classobj) {
2271 if (classobj == testclass) {
2272 return true;
2274 classobj = slotRawSymbol(&classobj->superclass)->u.classobj;
2276 return false;
2279 /*bool isKindOf(PyrObjectHdr *obj, PyrClass *testclass)
2281 int objClassIndex = slotRawInt(&obj->classptr->classIndex);
2282 return objClassIndex >= slotRawInt(&testclass->classIndex) && objClassIndex <= slotRawInt(&testclass->maxSubclassIndex);
2285 bool objAddIndexedSlot(PyrObject *obj, PyrSlot *slot)
2287 if (obj->size < ARRAYMAXINDEXSIZE(obj)) {
2288 slotCopy(&obj->slots[obj->size++], slot);
2289 return true;
2290 } else {
2291 return false;
2295 bool objAddIndexedSymbol(PyrSymbolArray *obj, PyrSymbol *symbol)
2297 if (obj->size < MAXINDEXSIZE((PyrObject*)obj)) {
2298 obj->symbols[obj->size++] = symbol;
2299 return true;
2300 } else {
2301 return false;
2305 bool objAddIndexedObject(PyrObject *obj, PyrObject *obj2)
2307 if (obj->size < ARRAYMAXINDEXSIZE(obj)) {
2308 SetObject(obj->slots + obj->size, obj2);
2309 obj->size++;
2310 return true;
2311 } else {
2312 return false;
2316 void fillSlots(PyrSlot* slot, int size, PyrSlot* fillslot)
2318 for (int i = 0; i != size; ++i)
2319 slotCopy(&slot[i], fillslot);
2322 void nilSlots(PyrSlot* slot, int size)
2324 fillSlots(slot, size, &o_nil);
2327 void zeroSlots(PyrSlot* slot, int size)
2329 PyrSlot zero;
2330 SetTagRaw(&zero, 0);
2331 SetRaw(&zero, 0.0);
2332 fillSlots(slot, size, &zero);
2335 PyrObject* newPyrObject(class PyrGC *gc, size_t inNumBytes, int inFlags, int inFormat, bool inCollect)
2337 return gc->New(inNumBytes, inFlags, inFormat, inCollect);
2340 PyrObject* newPyrArray(class PyrGC *gc, int size, int flags, bool collect)
2342 PyrObject* array;
2344 int numbytes = size * sizeof(PyrSlot);
2345 if (!gc)
2346 array = PyrGC::NewPermanent(numbytes, flags, obj_slot);
2347 else
2348 array = gc->New(numbytes, flags, obj_slot, collect);
2349 array->classptr = class_array;
2350 return array;
2353 PyrSymbolArray* newPyrSymbolArray(class PyrGC *gc, int size, int flags, bool collect)
2355 PyrSymbolArray* array;
2357 int numbytes = size * sizeof(PyrSymbol*);
2358 if (!gc) array = (PyrSymbolArray*)PyrGC::NewPermanent(numbytes, flags, obj_symbol);
2359 else array = (PyrSymbolArray*)gc->New(numbytes, flags, obj_symbol, collect);
2360 array->classptr = class_symbolarray;
2361 return array;
2364 PyrInt8Array* newPyrInt8Array(class PyrGC *gc, int size, int flags, bool collect)
2366 PyrInt8Array* array;
2368 if (!gc) array = (PyrInt8Array*)PyrGC::NewPermanent(size, flags, obj_int8);
2369 else array = (PyrInt8Array*)gc->New(size, flags, obj_int8, collect);
2370 array->classptr = class_int8array;
2371 return array;
2374 PyrInt32Array* newPyrInt32Array(class PyrGC *gc, int size, int flags, bool collect)
2376 PyrInt32Array* array;
2377 int numbytes = size * sizeof(int32);
2378 if (!gc) array = (PyrInt32Array*)PyrGC::NewPermanent(numbytes, flags, obj_int32);
2379 else array = (PyrInt32Array*)gc->New(numbytes, flags, obj_int32, collect);
2380 array->classptr = class_int32array;
2381 return array;
2384 PyrDoubleArray* newPyrDoubleArray(class PyrGC *gc, int size, int flags, bool collect)
2386 PyrDoubleArray* array;
2388 int numbytes = size * sizeof(double);
2389 if (!gc) array = (PyrDoubleArray*)PyrGC::NewPermanent(numbytes, flags, obj_double);
2390 else array = (PyrDoubleArray*)gc->New(size, flags, obj_double, collect);
2391 array->classptr = class_doublearray;
2392 return array;
2395 PyrString* newPyrString(class PyrGC *gc, const char *s, int flags, bool collect)
2397 PyrString* string;
2398 int length = strlen(s);
2400 if (!gc) string = (PyrString*)PyrGC::NewPermanent(length, flags, obj_char);
2401 else string = (PyrString*)gc->New(length, flags, obj_char, collect);
2402 string->classptr = class_string;
2403 string->size = length;
2404 memcpy(string->s, s, length);
2405 return string;
2408 PyrString* newPyrStringN(class PyrGC *gc, int length, int flags, bool collect)
2410 PyrString* string;
2412 if (!gc) string = (PyrString*)PyrGC::NewPermanent(length, flags, obj_char);
2413 else string = (PyrString*)gc->New(length, flags, obj_char, collect);
2414 string->classptr = class_string;
2415 string->size = length; // filled with garbage!
2416 return string;
2419 PyrBlock* newPyrBlock(int flags)
2421 PyrBlock* block;
2422 PyrMethodRaw *methraw;
2425 int32 numbytes = sizeof(PyrBlock) - sizeof(PyrObjectHdr);
2426 int32 numSlots = numbytes / sizeof(PyrSlot);
2428 if (!compilingCmdLine) block = (PyrBlock*)PyrGC::NewPermanent(numbytes, flags, obj_notindexed);
2429 else block = (PyrBlock*)gMainVMGlobals->gc->New(numbytes, flags, obj_notindexed, false);
2430 block->classptr = class_fundef;
2431 block->size = numSlots;
2433 // clear out raw area
2434 methraw = METHRAW(block);
2435 methraw->specialIndex = 0;
2436 methraw->methType = methBlock;
2437 methraw->needsHeapContext = 0;
2438 methraw->frameSize = 0;
2439 methraw->varargs = 0;
2440 methraw->numargs = 0;
2441 methraw->numvars = 0;
2442 methraw->numtemps = 0;
2443 methraw->popSize = 0;
2445 nilSlots(&block->rawData1, numSlots);
2446 return block;
2449 SC_DLLEXPORT_C struct VMGlobals* scGlobals()
2451 return gMainVMGlobals;
2454 PyrMethod* initPyrMethod(PyrMethod* method)
2457 int32 numbytes = sizeof(PyrMethod) - sizeof(PyrObjectHdr);
2458 int32 numSlots = numbytes / sizeof(PyrSlot);
2460 method->classptr = class_method;
2461 method->size = 0;
2462 method->size = numSlots;
2463 SetFloat(&method->rawData1, 0.0);
2464 SetFloat(&method->rawData2, 0.0);
2465 nilSlots(&method->code, numSlots-2);
2466 //slotCopy(&method->byteMeter, &o_zero);
2467 //slotCopy(&method->callMeter, &o_zero);
2468 //post("<- newPyrMethod %p %p\n", method, methraw);
2469 return method;
2472 PyrMethod* newPyrMethod()
2474 int32 numbytes = sizeof(PyrMethod) - sizeof(PyrObjectHdr);
2475 PyrMethod* method = (PyrMethod*)PyrGC::NewPermanent(numbytes, obj_permanent | obj_immutable, obj_notindexed);
2476 return initPyrMethod(method);
2479 void freePyrSlot(PyrSlot *slot)
2481 if (NotNil(slot)) {
2482 PyrObject *obj;
2483 if (IsSym(slot))
2484 obj = (PyrObject*)slotRawSymbol(slot); // i don't want to know, what this means
2485 else if (IsObj(slot))
2486 obj = slotRawObject(slot);
2487 else
2488 assert(false);
2490 if (obj && obj->IsPermanent()) {
2491 // don't deallocate these
2492 if (obj != slotRawObject(&o_emptyarray) && obj != slotRawObject(&o_onenilarray) && obj != slotRawObject(&o_argnamethis)) {
2493 pyr_pool_runtime->Free((void*)obj);
2495 SetNil(slot);
2500 void freePyrObject(PyrObject *obj)
2502 if (obj->IsPermanent()) {
2503 pyr_pool_runtime->Free((void*)obj);
2507 int getIndexedInt(PyrObject *obj, int index, int *value)
2509 PyrSlot *slot;
2510 int err = errNone;
2511 if (index < 0 || index >= obj->size) return errIndexOutOfRange;
2512 switch (obj->obj_format) {
2513 case obj_slot :
2514 slot = obj->slots + index;
2515 if (IsFloat(slot)) {
2516 *value = (int)slotRawFloat(slot);
2517 } else if (IsInt(slot)) {
2518 *value = slotRawInt(slot);
2519 } else {
2520 err = errWrongType;
2522 break;
2523 case obj_double :
2524 *value = (int)((double*)(obj->slots))[index];
2525 break;
2526 case obj_float :
2527 *value = (int)((float*)(obj->slots))[index];
2528 break;
2529 case obj_int32 :
2530 *value = ((int32*)(obj->slots))[index];
2531 break;
2532 case obj_int16 :
2533 *value = ((int16*)(obj->slots))[index];
2534 break;
2535 case obj_int8 :
2536 *value = ((int8*)(obj->slots))[index];
2537 break;
2538 default :
2539 err = errWrongType;
2541 return err;
2544 int getIndexedFloat(PyrObject *obj, int index, float *value)
2546 PyrSlot *slot;
2547 int err = errNone;
2548 if (index < 0 || index >= obj->size) return errIndexOutOfRange;
2549 switch (obj->obj_format) {
2550 case obj_slot :
2551 slot = obj->slots + index;
2552 if (IsFloat(slot)) {
2553 *value = slotRawFloat(slot);
2554 } else if (IsInt(slot)) {
2555 *value = slotRawInt(slot);
2556 } else {
2557 err = errWrongType;
2559 break;
2560 case obj_double :
2561 *value = ((double*)(obj->slots))[index];
2562 break;
2563 case obj_float :
2564 *value = ((float*)(obj->slots))[index];
2565 break;
2566 case obj_int32 :
2567 *value = ((int32*)(obj->slots))[index];
2568 break;
2569 case obj_int16 :
2570 *value = ((int16*)(obj->slots))[index];
2571 break;
2572 case obj_int8 :
2573 *value = ((int8*)(obj->slots))[index];
2574 break;
2575 default :
2576 err = errWrongType;
2578 return err;
2581 int getIndexedDouble(PyrObject *obj, int index, double *value)
2583 PyrSlot *slot;
2584 int err = errNone;
2585 if (index < 0 || index >= obj->size) return errIndexOutOfRange;
2586 switch (obj->obj_format) {
2587 case obj_slot :
2588 slot = obj->slots + index;
2589 if (IsFloat(slot)) {
2590 *value = slotRawFloat(slot);
2591 } else if (IsInt(slot)) {
2592 *value = slotRawInt(slot);
2593 } else {
2594 err = errWrongType;
2596 break;
2597 case obj_double :
2598 *value = ((double*)(obj->slots))[index];
2599 break;
2600 case obj_float :
2601 *value = ((float*)(obj->slots))[index];
2602 break;
2603 case obj_int32 :
2604 *value = ((int32*)(obj->slots))[index];
2605 break;
2606 case obj_int16 :
2607 *value = ((int16*)(obj->slots))[index];
2608 break;
2609 case obj_int8 :
2610 *value = ((int8*)(obj->slots))[index];
2611 break;
2612 default :
2613 err = errWrongType;
2615 return err;
2619 void getIndexedSlot(PyrObject *obj, PyrSlot *a, int index)
2621 // postfl("getIndexedSlot %s %X %d\n", slotRawSymbol(&obj->classptr->name)->name,
2622 // obj, index);
2623 switch (obj->obj_format) {
2624 case obj_slot :
2625 slotCopy(a, &obj->slots[index]);
2626 break;
2627 case obj_double :
2628 SetFloat(a, ((double*)(obj->slots))[index]);
2629 break;
2630 case obj_float :
2631 SetFloat(a, ((float*)(obj->slots))[index]);
2632 break;
2633 case obj_int32 :
2634 SetInt(a, ((int32*)(obj->slots))[index]);
2635 break;
2636 case obj_int16 :
2637 SetInt(a, ((int16*)(obj->slots))[index]);
2638 break;
2639 case obj_int8 :
2640 SetInt(a, ((int8*)(obj->slots))[index]);
2641 break;
2642 case obj_symbol :
2643 SetSymbol(a, (PyrSymbol*)((int**)(obj->slots))[index]);
2644 break;
2645 case obj_char :
2646 SetChar(a, ((unsigned char*)(obj->slots))[index]);
2647 break;
2651 int putIndexedSlot(VMGlobals *g, PyrObject *obj, PyrSlot *c, int index)
2653 PyrSlot *slot;
2654 switch (obj->obj_format) {
2655 case obj_slot :
2656 if (obj->obj_flags & obj_immutable) return errImmutableObject;
2657 slot = obj->slots + index;
2658 slotCopy(slot, c);
2659 g->gc->GCWrite(obj, slot);
2660 break;
2661 case obj_double :
2662 if (NotFloat(c)) {
2663 if (NotInt(c)) return errWrongType;
2664 else {
2665 ((double*)(obj->slots))[index] = slotRawInt(c);
2667 } else
2668 ((double*)(obj->slots))[index] = slotRawFloat(c);
2669 break;
2670 case obj_float :
2671 if (NotFloat(c)) {
2672 if (NotInt(c)) return errWrongType;
2673 else {
2674 ((float*)(obj->slots))[index] = slotRawInt(c);
2676 } else
2677 ((float*)(obj->slots))[index] = slotRawFloat(c);
2678 break;
2679 case obj_int32 :
2680 if (NotInt(c)) return errWrongType;
2681 ((int32*)(obj->slots))[index] = slotRawInt(c);
2682 break;
2683 case obj_int16 :
2684 if (NotInt(c)) return errWrongType;
2685 ((int16*)(obj->slots))[index] = slotRawInt(c);
2686 break;
2687 case obj_int8 :
2688 if (NotInt(c)) return errWrongType;
2689 ((int8*)(obj->slots))[index] = slotRawInt(c);
2690 break;
2691 case obj_symbol :
2692 if (NotSym(c)) return errWrongType;
2693 ((PyrSymbol**)(obj->slots))[index] = slotRawSymbol(c);
2694 break;
2695 case obj_char :
2696 if (NotChar(c)) return errWrongType;
2697 ((unsigned char*)(obj->slots))[index] = slotRawChar(c);
2698 break;
2700 return errNone;
2703 int putIndexedFloat(PyrObject *obj, double val, int index)
2705 PyrSlot *slot;
2706 switch (obj->obj_format) {
2707 case obj_slot :
2708 if (obj->obj_flags & obj_immutable) return errImmutableObject;
2709 slot = obj->slots + index;
2710 SetFloat(slot, val);
2711 break;
2712 case obj_double :
2713 ((double*)(obj->slots))[index] = val;
2714 break;
2715 case obj_float :
2716 ((float*)(obj->slots))[index] = (float)val;
2717 break;
2718 case obj_int32 :
2719 ((int32*)(obj->slots))[index] = (int32)val;
2720 break;
2721 case obj_int16 :
2722 ((int16*)(obj->slots))[index] = (int16)val;
2723 break;
2724 case obj_int8 :
2725 ((int8*)(obj->slots))[index] = (int8)val;
2726 break;
2728 return errNone;
2731 static int hashPtr(void* ptr)
2733 int32 hashed_part = int32((long)ptr&0xffffffff);
2734 return Hash(hashed_part);
2737 int calcHash(PyrSlot *a);
2738 int calcHash(PyrSlot *a)
2740 int hash;
2741 switch (GetTag(a)) {
2742 case tagObj : hash = hashPtr(slotRawObject(a)); break;
2743 case tagInt : hash = Hash(slotRawInt(a)); break;
2744 case tagChar : hash = Hash(slotRawChar(a) & 255); break;
2745 case tagSym : hash = slotRawSymbol(a)->hash; break;
2746 case tagNil : hash = 0xA5A5A5A5; break;
2747 case tagFalse : hash = 0x55AA55AA; break;
2748 case tagTrue : hash = 0x69696969; break;
2749 case tagPtr : hash = hashPtr(slotRawPtr(a)); break;
2750 default :
2751 // hash for a double
2752 union {
2753 int32 i[2];
2754 double d;
2755 } u;
2756 u.d = slotRawFloat(a);
2757 hash = Hash(u.i[0] + Hash(u.i[1]));
2759 return hash;
2762 void InstallFinalizer(VMGlobals* g, PyrObject *inObj, int slotIndex, ObjFuncPtr inFunc)
2764 PyrObject *finalizer = g->gc->NewFinalizer(inFunc, inObj, false);
2765 SetObject(inObj->slots + slotIndex, finalizer);
2766 g->gc->GCWrite(inObj, finalizer);