sclang: array primitives - respect mutability when changing object.
[supercollider.git] / lang / LangSource / PyrObject.cpp
blob5abd074fa571825ca1e63874e2980d4864090d66
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;
78 PyrClass *class_server_shm_interface;
80 PyrSymbol *s_none;
81 PyrSymbol *s_object;
82 PyrSymbol *s_bag;
83 PyrSymbol *s_set;
84 PyrSymbol *s_identityset;
85 PyrSymbol *s_dictionary;
86 PyrSymbol *s_identitydictionary;
87 PyrSymbol *s_linkedlist;
88 PyrSymbol *s_sortedlist;
89 PyrSymbol *s_array;
90 PyrSymbol *s_list, *s_method, *s_fundef, *s_frame, *s_class;
91 PyrSymbol *s_symbol, *s_nil;
92 PyrSymbol *s_boolean, *s_true, *s_false;
93 PyrSymbol *s_int, *s_char, *s_color, *s_float, *s_complex;
94 PyrSymbol *s_rawptr, *s_objptr;
95 PyrSymbol *s_string;
96 PyrSymbol *s_magnitude, *s_number, *s_collection, *s_ordered_collection;
97 PyrSymbol *s_arrayed_collection;
98 PyrSymbol *s_sequenceable_collection;
99 PyrSymbol *s_simple_number;
100 PyrSymbol *s_signal;
101 PyrSymbol *s_wavetable;
103 PyrSymbol *s_rawarray;
104 PyrSymbol *s_int8array;
105 PyrSymbol *s_int16array;
106 PyrSymbol *s_int32array;
107 PyrSymbol *s_symbolarray;
108 PyrSymbol *s_doublearray;
109 PyrSymbol *s_floatarray;
110 PyrSymbol *s_point;
111 PyrSymbol *s_rect;
112 PyrSymbol *s_func, *s_absfunc;
113 PyrSymbol *s_stream;
114 PyrSymbol *s_process;
115 PyrSymbol *s_main;
116 PyrSymbol *s_thread;
117 PyrSymbol *s_routine;
118 PyrSymbol *s_task;
119 PyrSymbol *s_prstart;
120 PyrSymbol *s_interpreter;
121 PyrSymbol *s_finalizer;
122 PyrSymbol *s_awake;
123 PyrSymbol *s_appclock;
124 PyrSymbol *s_systemclock;
125 PyrSymbol *s_server_shm_interface;
127 PyrSymbol *s_nocomprendo;
128 PyrSymbol *s_curProcess, *s_curMethod, *s_curBlock, *s_curClosure, *s_curThread;
129 //PyrSymbol *s_sampleRate;
130 //PyrSymbol *s_audioClock, *s_logicalClock;
131 PyrSymbol *s_run;
132 PyrSymbol *s_startup;
133 PyrSymbol *s_docmdline;
134 PyrSymbol *s_audio;
135 PyrSymbol *s_control;
136 PyrSymbol *s_scalar;
137 PyrSymbol *s_next;
138 PyrSymbol *s_env;
139 PyrSymbol *s_ugen, *s_outputproxy;
140 PyrSymbol *s_new, *s_ref, *s_value, *s_at, *s_put;
141 PyrSymbol *s_performList, *s_superPerformList;
142 PyrSymbol *s_series, *s_copyseries, *s_putseries;
143 PyrSymbol *s_envirGet, *s_envirPut;
144 PyrSymbol *s_synth, *s_spawn, *s_environment, *s_event;
145 PyrSymbol *s_hardwaresetup, *s_shutdown;
146 PyrSymbol *s_linear, *s_exponential, *s_gate;
147 PyrSymbol *s_super, *s_this;
148 PyrSlot o_nil, o_true, o_false, o_end;
149 PyrSlot o_pi, o_twopi;
150 PyrSlot o_fhalf, o_fnegone, o_fzero, o_fone, o_ftwo, o_inf;
151 PyrSlot o_negtwo, o_negone, o_zero, o_one, o_two;
152 PyrSlot o_nullframe, o_none;
153 PyrSlot o_emptyarray, o_onenilarray, o_argnamethis;
156 void initSymbols()
158 s_new = getsym("new");
159 s_ref = getsym("Ref");
160 s_none = getsym("none");
161 s_object = getsym("Object");
162 s_this = getsym("this");
163 s_super = getsym("super");
165 s_dictionary = getsym("Dictionary");
166 s_bag = getsym("Bag");
167 s_set = getsym("Set");
168 s_identityset = getsym("IdentitySet");
169 s_identitydictionary = getsym("IdentityDictionary");
170 s_linkedlist = getsym("LinkedList");
171 s_sortedlist = getsym("SortedList");
172 s_array = getsym("Array");
173 s_list = getsym("List");
174 s_method = getsym("Method");
175 s_fundef = getsym("FunctionDef");
176 s_frame = getsym("Frame");
177 s_class = getsym("Class");
178 s_symbol = getsym("Symbol");
179 s_nil = getsym("Nil");
180 s_true = getsym("True");
181 s_false = getsym("False");
182 s_int = getsym("Integer");
183 s_float = getsym("Float");
184 s_char = getsym("Char");
185 s_color = getsym("Color");
186 s_rawptr = getsym("RawPointer");
187 s_objptr = getsym("ObjectPointer");
188 s_string = getsym("String");
189 s_magnitude = getsym("Magnitude");
190 s_number = getsym("Number");
191 s_simple_number = getsym("SimpleNumber");
192 s_collection = getsym("Collection");
193 //s_ordered_collection = getsym("OrderedCollection");
194 s_arrayed_collection = getsym("ArrayedCollection");
195 s_sequenceable_collection = getsym("SequenceableCollection");
196 s_boolean = getsym("Boolean");
197 s_signal = getsym("Signal");
198 s_wavetable = getsym("Wavetable");
199 //s_signalnode = getsym("SignalNode");
200 s_rawarray = getsym("RawArray");
201 s_int8array = getsym("Int8Array");
202 s_int16array = getsym("Int16Array");
203 s_int32array = getsym("Int32Array");
204 s_symbolarray = getsym("SymbolArray");
205 s_floatarray = getsym("FloatArray");
206 s_doublearray = getsym("DoubleArray");
207 s_complex = getsym("Complex");
208 s_point = getsym("Point");
209 s_rect = getsym("Rect");
210 s_absfunc = getsym("AbstractFunction");
211 s_func = getsym("Function");
212 s_stream = getsym("Stream");
213 s_process = getsym("Process");
214 s_main = getsym("Main");
215 s_thread = getsym("Thread");
216 s_routine = getsym("Routine");
217 s_task = getsym("Task");
218 s_prstart = getsym("prStart");
219 s_interpreter = getsym("Interpreter");
220 s_finalizer = getsym("Finalizer");
221 s_awake = getsym("awake");
222 s_appclock = getsym("AppClock");
223 s_systemclock = getsym("SystemClock");
224 s_server_shm_interface = getsym("ServerShmInterface");
226 s_linear = getsym("linear");
227 s_exponential = getsym("exponential");
228 s_gate = getsym("gate");
230 //s_dsp = getsym("DSP");
231 //s_dspsettings = getsym("DSPSettings");
232 s_synth = getsym("Synth");
233 s_spawn = getsym("BasicSpawn");
234 s_environment = getsym("Environment");
235 s_event = getsym("Event");
236 s_hardwaresetup = getsym("hardwareSetup");
237 s_shutdown = getsym("shutdown");
239 s_nocomprendo = getsym("doesNotUnderstand");
241 s_curProcess = getsym("thisProcess");
242 s_curThread = getsym("thisThread");
243 s_curMethod = getsym("thisMethod");
244 s_curBlock = getsym("thisFunctionDef");
245 s_curClosure = getsym("thisFunction");
246 //s_sampleRate = getsym("gSR");
247 //s_logicalClock = getsym("gTime");
248 //s_audioClock = getsym("gAudioTime");
249 s_audio = getsym("audio");
250 s_control = getsym("control");
251 s_scalar = getsym("scalar");
252 s_run = getsym("run");
253 s_startup = getsym("startup");
254 s_docmdline = getsym("doCmdLine");
255 s_next = getsym("next");
256 s_value = getsym("value");
257 s_performList = getsym("performList");
258 s_superPerformList = getsym("superPerformList");
259 s_at = getsym("at");
260 s_put = getsym("put");
262 s_series = getsym("prSimpleNumberSeries");
263 s_copyseries = getsym("copySeries");
264 s_putseries = getsym("putSeries");
266 s_ugen = getsym("UGen");
267 s_outputproxy = getsym("OutputProxy");
268 s_env = getsym("Env");
270 s_envirGet = getsym("envirGet");
271 s_envirPut = getsym("envirPut");
273 SetNil(&o_nil);
274 SetFalse(&o_false);
275 SetTrue(&o_true);
277 SetFloat(&o_pi, pi);
278 SetFloat(&o_twopi, twopi);
279 SetFloat(&o_fhalf, .5);
280 SetFloat(&o_fnegone, -1.);
281 SetFloat(&o_fzero, 0.);
282 SetFloat(&o_fone, 1.);
283 SetFloat(&o_ftwo, 2.);
284 SetInt(&o_negtwo, -2);
285 SetInt(&o_negone, -1);
286 SetInt(&o_zero, 0);
287 SetInt(&o_one, 1);
288 SetInt(&o_two, 2);
289 SetSymbol(&o_none, s_none);
290 #ifdef SC_WIN32
292 double a = 0.0;
293 double b = 1.0/a;
294 SetFloat(&o_inf, b);
296 #else
297 SetFloat(&o_inf, INFINITY);
298 #endif
300 slotCopy(&gSpecialValues[svNil], &o_nil);
301 slotCopy(&gSpecialValues[svFalse], &o_false);
302 slotCopy(&gSpecialValues[svTrue], &o_true);
303 slotCopy(&gSpecialValues[svNegOne], &o_negone);
304 slotCopy(&gSpecialValues[svZero], &o_zero);
305 slotCopy(&gSpecialValues[svOne], &o_one);
306 slotCopy(&gSpecialValues[svTwo], &o_two);
307 slotCopy(&gSpecialValues[svFHalf], &o_fhalf);
308 slotCopy(&gSpecialValues[svFNegOne], &o_fnegone);
309 slotCopy(&gSpecialValues[svFZero], &o_fzero);
310 slotCopy(&gSpecialValues[svFOne], &o_fone);
311 slotCopy(&gSpecialValues[svFTwo], &o_ftwo);
312 slotCopy(&gSpecialValues[svInf], &o_inf);
314 gFormatElemSize[obj_notindexed] = sizeof(PyrSlot);
315 gFormatElemSize[obj_slot ] = sizeof(PyrSlot);
316 gFormatElemSize[obj_double] = sizeof(double);
317 gFormatElemSize[obj_float ] = sizeof(float);
318 gFormatElemSize[obj_int32 ] = sizeof(int32);
319 gFormatElemSize[obj_int16 ] = sizeof(int16);
320 gFormatElemSize[obj_int8 ] = sizeof(int8);
321 gFormatElemSize[obj_char ] = sizeof(char);
322 gFormatElemSize[obj_symbol ] = sizeof(PyrSymbol*);
324 gFormatElemCapc[obj_notindexed] = sizeof(PyrSlot) / sizeof(PyrSlot);
325 gFormatElemCapc[obj_slot ] = sizeof(PyrSlot) / sizeof(PyrSlot);
326 gFormatElemCapc[obj_double] = sizeof(PyrSlot) / sizeof(double);
327 gFormatElemCapc[obj_float ] = sizeof(PyrSlot) / sizeof(float);
328 gFormatElemCapc[obj_int32 ] = sizeof(PyrSlot) / sizeof(int32);
329 gFormatElemCapc[obj_int16 ] = sizeof(PyrSlot) / sizeof(int16);
330 gFormatElemCapc[obj_int8 ] = sizeof(PyrSlot) / sizeof(int8);
331 gFormatElemCapc[obj_char ] = sizeof(PyrSlot) / sizeof(char);
332 gFormatElemCapc[obj_symbol] = sizeof(PyrSlot) / sizeof(PyrSymbol*);
334 gFormatElemTag[obj_notindexed] = -1;
335 gFormatElemTag[obj_slot ] = -1;
336 gFormatElemTag[obj_double] = 0;
337 gFormatElemTag[obj_float ] = 0;
338 gFormatElemTag[obj_int32 ] = tagInt;
339 gFormatElemTag[obj_int16 ] = tagInt;
340 gFormatElemTag[obj_int8 ] = tagInt;
341 gFormatElemTag[obj_char ] = tagChar;
342 gFormatElemTag[obj_symbol] = tagSym;
345 const char *slotSymString(PyrSlot* slot)
347 switch (GetTag(slot)) {
348 case tagObj : return slotRawSymbol(&slotRawObject(slot)->classptr->name)->name;
349 case tagInt : return "Integer";
350 case tagChar : return "Char";
351 case tagSym : return slotRawSymbol(slot)->name;
352 case tagNil : return "Nil";
353 case tagFalse : return "False";
354 case tagTrue : return "True";
355 default : return "<float>";
359 PyrClass* newClassObj(PyrClass *classObjSuperClass,
360 PyrSymbol* className, PyrSymbol* superClassName,
361 int numInstVars, int numClassVars, int numConsts, int numInstMethods,
362 int instFormat, int instFlags)
364 PyrClass* classobj, *superclassobj;
365 PyrObject* array;
366 PyrSymbolArray *symarray;
367 int classFlags;
370 int c;
371 c = className->name[0];
372 if (!(c >= 'A' && c <= 'Z')) Debugger();
374 // pyrmalloc:
375 // lifetime: kill upon recompiling library
376 classobj = (PyrClass*)pyr_pool_runtime->Alloc(sizeof(PyrClass));
377 MEMFAIL(classobj);
378 classobj->size = (sizeof(PyrClass) - sizeof(PyrObjectHdr))/sizeof(PyrSlot);
379 classobj->prev = classobj->next = NULL;
380 classobj->obj_flags = obj_immutable ;
381 classobj->obj_format = obj_notindexed ;
382 classobj->gc_color = obj_permanent ;
383 classobj->obj_sizeclass = LOG2CEIL(classobj->size);
384 classobj->classptr = classObjSuperClass;
387 // append to the list of classes
388 if (gClassList) SetObject(&classobj->nextclass, gClassList);
389 else SetNil(&classobj->nextclass);
391 gClassList = classobj;
393 className->u.classobj = classobj;
394 //postfl("> '%s' %d %d\n", className->name, className, classobj);
396 SetSymbol(&classobj->name, className);
397 if (superClassName) {
398 SetSymbol(&classobj->superclass, superClassName);
399 superclassobj = superClassName->u.classobj;
400 } else {
401 SetSymbol(&classobj->superclass, s_none);
402 superclassobj = NULL;
405 SetInt(&classobj->subclasses, 0); // to be filled with subclasses later
406 // in the meantime it is used as a tally of subclasses so that its allocation
407 // size can be known
409 if (numInstMethods) {
410 array = newPyrArray(NULL, numInstMethods, obj_permanent | obj_immutable, false);
411 SetObject(&classobj->methods, array);
412 } else {
413 SetNil(&classobj->methods);
416 if (numInstVars) {
417 symarray = newPyrSymbolArray(NULL, numInstVars, obj_permanent | obj_immutable, false);
418 SetObject(&classobj->instVarNames, symarray);
420 array = newPyrArray(NULL, numInstVars, obj_permanent | obj_immutable, false);
421 SetObject(&classobj->iprototype, array);
422 nilSlots(array->slots, numInstVars);
423 } else {
424 SetNil(&classobj->instVarNames);
425 SetNil(&classobj->iprototype);
428 if (numClassVars) {
429 symarray = newPyrSymbolArray(NULL, numClassVars, obj_permanent | obj_immutable, false);
430 SetObject(&classobj->classVarNames, symarray);
432 array = newPyrArray(NULL, numClassVars, obj_permanent | obj_immutable, false);
433 SetObject(&classobj->cprototype, array);
434 nilSlots(array->slots, numClassVars);
435 } else {
436 SetNil(&classobj->classVarNames);
437 SetNil(&classobj->cprototype);
440 if (numConsts) {
441 symarray = newPyrSymbolArray(NULL, numConsts, obj_permanent | obj_immutable, false);
442 SetObject(&classobj->constNames, symarray);
444 array = newPyrArray(NULL, numConsts, obj_permanent | obj_immutable, false);
445 SetObject(&classobj->constValues, array);
446 nilSlots(array->slots, numConsts);
447 } else {
448 SetNil(&classobj->constNames);
449 SetNil(&classobj->constValues);
452 classFlags = 0;
453 if (instFormat != obj_notindexed) {
454 classFlags |= classHasIndexableInstances;
457 SetInt(&classobj->instanceFormat, instFormat);
458 SetInt(&classobj->instanceFlags, instFlags);
459 SetInt(&classobj->classIndex, -1);
460 SetInt(&classobj->classFlags, classFlags);
461 SetInt(&classobj->maxSubclassIndex, 0);
462 SetNil(&classobj->filenameSym);
463 SetInt(&classobj->charPos, 0);
464 SetInt(&classobj->classVarIndex, gNumClassVars);
465 //if (numClassVars) post("%16s %4d %4d\n", className->name, gNumClassVars, numClassVars);
466 gNumClassVars += numClassVars;
467 return classobj;
470 void reallocClassObj(PyrClass* classobj,
471 int numInstVars, int numClassVars, int numConsts, int numMethods,
472 int instFormat, int instFlags)
474 PyrObject* array;
475 PyrSymbolArray *symarray;
476 PyrClass *superclassobj;
478 freePyrSlot(&classobj->methods);
479 freePyrSlot(&classobj->instVarNames);
480 freePyrSlot(&classobj->classVarNames);
481 freePyrSlot(&classobj->iprototype);
482 freePyrSlot(&classobj->cprototype);
484 freePyrSlot(&classobj->constNames);
485 freePyrSlot(&classobj->constValues);
487 if (numMethods) {
488 array = newPyrArray(NULL, numMethods, obj_permanent | obj_immutable, false);
489 SetObject(&classobj->methods, array);
490 } else {
491 SetNil(&classobj->methods);
494 if (numInstVars) {
495 //post("reallocClassObj %s numInstVars %d\n", slotRawSymbol(&classobj->name)->name, numInstVars);
496 symarray = newPyrSymbolArray(NULL, numInstVars, obj_permanent | obj_immutable, false);
497 SetObject(&classobj->instVarNames, symarray);
499 array = newPyrArray(NULL, numInstVars, obj_permanent | obj_immutable, false);
500 SetObject(&classobj->iprototype, array);
501 nilSlots(array->slots, numInstVars);
502 } else {
503 SetNil(&classobj->instVarNames);
504 SetNil(&classobj->iprototype);
507 if (numClassVars) {
508 //post("reallocClassObj %s numClassVars %d\n", slotRawSymbol(&classobj->name)->name, numClassVars);
509 symarray = newPyrSymbolArray(NULL, numClassVars, obj_permanent | obj_immutable, false);
510 SetObject(&classobj->classVarNames, symarray);
511 nilSlots(array->slots, numClassVars);
513 array = newPyrArray(NULL, numClassVars, obj_permanent | obj_immutable, false);
514 SetObject(&classobj->cprototype, array);
515 nilSlots(array->slots, numClassVars);
516 } else {
517 SetNil(&classobj->classVarNames);
518 SetNil(&classobj->cprototype);
521 if (numConsts) {
522 //post("reallocClassObj %s numConsts %d\n", slotRawSymbol(&classobj->name)->name, numConsts);
523 symarray = newPyrSymbolArray(NULL, numConsts, obj_permanent | obj_immutable, false);
524 SetObject(&classobj->constNames, symarray);
526 array = newPyrArray(NULL, numConsts, obj_permanent | obj_immutable, false);
527 SetObject(&classobj->constValues, array);
528 nilSlots(array->slots, numConsts);
529 } else {
530 SetNil(&classobj->constNames);
531 SetNil(&classobj->constValues);
534 superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
536 SetInt(&classobj->instanceFormat, instFormat);
537 SetInt(&classobj->instanceFlags, instFlags);
538 SetInt(&classobj->classIndex, -1);
541 void fixClassArrays(PyrClass *classobj);
542 void fixClassArrays(PyrClass *classobj)
544 if (IsObj(&classobj->methods)) slotRawObject(&classobj->methods)->classptr = class_array;
545 if (IsObj(&classobj->instVarNames)) slotRawObject(&classobj->instVarNames)->classptr = class_symbolarray;
546 if (IsObj(&classobj->classVarNames)) slotRawObject(&classobj->classVarNames)->classptr = class_symbolarray;
547 if (IsObj(&classobj->iprototype)) slotRawObject(&classobj->iprototype)->classptr = class_array;
548 if (IsObj(&classobj->cprototype)) slotRawObject(&classobj->cprototype)->classptr = class_array;
551 int numInstVars(PyrClass* classobj)
553 int res;
554 if (IsNil(&classobj->instVarNames))
555 res = 0;
556 else
557 res = slotRawObject(&classobj->instVarNames)->size;
558 return res;
561 int numClassVars(PyrClass* classobj)
563 int res;
564 if (IsNil(&classobj->classVarNames)) res = 0;
565 else res = slotRawObject(&classobj->classVarNames)->size;
566 return res;
570 void objAddIndexedSlotGrow(PyrSlot *arraySlot, PyrSlot *addSlot);
571 void objAddIndexedSlotGrow(PyrSlot *arraySlot, PyrSlot *addSlot)
573 PyrObject *obj;
574 if (IsNil(arraySlot)) {
575 PyrObject *newobj = (PyrObject*)newPyrArray(NULL, 1, obj_permanent | obj_immutable, false);
576 SetObject(arraySlot, newobj);
577 obj = newobj;
578 } else {
579 obj = slotRawObject(arraySlot);
580 if (obj->size >= ARRAYMAXINDEXSIZE(obj)) {
581 //post("objAddIndexedSlotGrow\n");
582 PyrObject *newobj = (PyrObject*)newPyrArray(NULL, obj->size * 2, obj_permanent | obj_immutable, false);
583 memcpy(newobj->slots, obj->slots, obj->size * sizeof(PyrSlot));
584 newobj->size = obj->size;
585 SetObject(arraySlot, newobj);
586 pyr_pool_runtime->Free((void*)obj);
587 obj = newobj;
590 slotCopy(&obj->slots[obj->size++], addSlot);
593 void addMethod(PyrClass *classobj, PyrMethod *method)
595 PyrSlot slot;
596 SetObject(&slot, method);
597 objAddIndexedSlotGrow(&classobj->methods, &slot);
602 PyrMethod* classFindDirectMethod(PyrClass* classobj, PyrSymbol *name)
604 PyrMethod *method;
605 PyrSlot *methods;
606 int i, numMethods;
607 if (IsNil(&classobj->methods)) return NULL;
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) break;
614 if (i>=numMethods) method = NULL;
615 return method;
618 int numSuperInstVars(PyrClass *superclassobj)
620 int superinstvars = 0;
621 if (superclassobj) {
622 if (IsObj(&superclassobj->iprototype)) {
623 superinstvars = slotRawObject(&superclassobj->iprototype)->size;
626 return superinstvars;
629 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;
648 return false;
651 int instVarOffset(const char *classname, const char *instvarname)
653 PyrSymbol *instvarsymbol, *classsymbol;
654 PyrClass* classobj;
655 int index;
656 char c;
658 classsymbol = getsym(classname);
659 instvarsymbol = getsym(instvarname);
661 c = classname[0];
662 if (!(c >= 'A' && c <= 'Z')) return -1;
664 classobj = classsymbol->u.classobj;
665 if (!classobj) return -1;
666 if (!classFindInstVar(classobj, instvarsymbol, &index)) return -1;
667 return index;
670 int classVarOffset(const char *classname, const char *classvarname, PyrClass** classobj)
672 PyrSymbol *classvarsymbol, *classsymbol;
673 int index;
674 char c;
676 classsymbol = getsym(classname);
677 classvarsymbol = getsym(classvarname);
679 c = classname[0];
680 if (!(c >= 'A' && c <= 'Z')) return -1;
682 *classobj = classsymbol->u.classobj;
683 if (!*classobj) return -1;
684 if (!classFindClassVar(classobj, classvarsymbol, &index)) return -1;
685 return index;
688 bool classFindClassVar(PyrClass** classobj, PyrSymbol *name, int *index)
690 PyrSymbolArray *cvnames;
691 PyrSymbol *cvname;
692 int i, j;
693 char *classname;
694 PyrClass* localclassobj = *classobj;
695 // if this is a Metaclass then we need to search its normal Class for
696 // the class vars
697 classname = slotRawSymbol(&localclassobj->name)->name;
698 if (strncmp(classname, "Meta_", 5) == 0) {
699 localclassobj = getsym(classname+5)->u.classobj;
701 for (j=0; localclassobj; ++j) {
702 if (NotNil(&localclassobj->classVarNames)) {
703 cvnames = slotRawSymbolArray(&localclassobj->classVarNames);
704 if (cvnames) {
705 for (i=0; i<cvnames->size; ++i) {
706 cvname = cvnames->symbols[i];
707 if (cvname == name) {
708 *classobj = localclassobj;
709 *index = i;
710 return true;
715 if (IsSym(&localclassobj->superclass)) {
716 localclassobj = slotRawSymbol(&localclassobj->superclass)->u.classobj;
717 } else {
718 localclassobj = NULL;
721 return false;
724 bool classFindConst(PyrClass** classobj, PyrSymbol *name, int *index)
726 PyrSymbolArray *knames;
727 PyrSymbol *kname;
728 int i, j;
729 char *classname;
730 PyrClass* localclassobj = *classobj;
731 // if this is a Metaclass then we need to search its normal Class for
732 // the class vars
733 classname = slotRawSymbol(&localclassobj->name)->name;
734 if (strncmp(classname, "Meta_", 5) == 0) {
735 localclassobj = getsym(classname+5)->u.classobj;
737 for (j=0; localclassobj; ++j) {
738 if (NotNil(&localclassobj->constNames)) {
739 knames = slotRawSymbolArray(&localclassobj->constNames);
740 if (knames) {
741 for (i=0; i<knames->size; ++i) {
742 kname = knames->symbols[i];
743 if (kname == name) {
744 *classobj = localclassobj;
745 *index = i;
746 return true;
751 if (IsSym(&localclassobj->superclass)) {
752 localclassobj = slotRawSymbol(&localclassobj->superclass)->u.classobj;
753 } else {
754 localclassobj = NULL;
757 return false;
760 struct compareByName
762 bool operator()(PyrClass * lhs, PyrClass * rhs) const
764 return strcmp(slotRawSymbol(&lhs->name)->name, slotRawSymbol(&rhs->name)->name) < 0;
769 template <class T>
770 class pyr_pool_compile_allocator
772 public:
773 typedef std::size_t size_type;
774 typedef std::ptrdiff_t difference_type;
775 typedef T* pointer;
776 typedef const T* const_pointer;
777 typedef T& reference;
778 typedef const T& const_reference;
779 typedef T value_type;
781 template <class U> struct rebind
783 typedef pyr_pool_compile_allocator<U> other;
786 pyr_pool_compile_allocator(void)
789 template <class U>
790 pyr_pool_compile_allocator(pyr_pool_compile_allocator<U> const &)
793 pointer address(reference x) const
795 return &x;
798 const_pointer address(const_reference x) const
800 return &x;
803 pointer allocate(size_type n, const void* hint = 0)
805 return (pointer)pyr_pool_compile->Alloc(n*sizeof(T));
808 void deallocate(pointer p, size_type n)
810 pyr_pool_compile->Free(p);
813 void construct(pointer p, const T& val)
815 ::new(p) T(val);
818 void destroy(pointer p)
820 p->~T();
825 /* sort list of classes:
826 * we fill a binary search tree
829 static PyrClass * sortClasses(PyrClass * aClassList)
831 typedef std::set<PyrClass*, compareByName, pyr_pool_compile_allocator<PyrClass*> > classSetType;
832 classSetType classSet;
834 PyrClass * insertHead = aClassList;
835 do {
836 assert(classSet.find(insertHead) == classSet.end());
837 classSet.insert(insertHead);
838 insertHead = slotRawClass(&insertHead->nextclass);
839 } while (insertHead);
841 classSetType::iterator it = classSet.begin();
842 PyrClass * sortedClasses = *it;
843 ++it;
845 PyrClass * lastClass = sortedClasses;
846 for (; it != classSet.end(); ++it) {
847 PyrClass * current = *it;
848 SetObject(&lastClass->nextclass, (PyrObject*)current);
849 lastClass = current;
851 SetNil(&lastClass->nextclass);
852 return sortedClasses;
855 #include <boost/threadpool.hpp>
857 static int cpuCount = boost::thread::hardware_concurrency();
858 static int helperThreadCount = cpuCount - 1;
859 static boost::threadpool::fifo_pool compileThreadPool;
861 void buildClassTree()
863 // the first time we use the pool
864 compileThreadPool.size_controller().resize(helperThreadCount);
866 // after all classes are compiled this function builds the tree and
867 // indexes the classes
869 // count subclasses
870 //postfl("count subclasses\n");
871 PyrClass *classobj = gClassList;
872 while (classobj) {
873 PyrClass * superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
874 if (superclassobj) {
875 //postfl(" superclassobj %s\n", slotRawSymbol(&superclassobj->name)->name);
876 SetRaw(&superclassobj->subclasses, slotRawInt(&superclassobj->subclasses) + 1);
878 classobj = slotRawClass(&classobj->nextclass);
880 // allocate subclass arrays
881 //postfl("allocate subclass arrays\n");
882 classobj = gClassList;
883 while (classobj) {
884 int numSubclasses;
885 numSubclasses = slotRawInt(&classobj->subclasses);
886 //postfl(" %s %d\n", slotRawSymbol(&classobj->name)->name, numSubclasses);
887 if (numSubclasses) {
888 SetObject(&classobj->subclasses, (PyrObject*)newPyrArray(NULL, numSubclasses, obj_permanent | obj_immutable, false));
889 slotRawObject(&classobj->subclasses)->size = 0;
890 } else {
891 SetNil(&classobj->subclasses);
893 classobj = slotRawClass(&classobj->nextclass);
895 // fill in subclass arrays
896 //postfl("fill in subclass arrays\n");
897 classobj = gClassList;
898 while (classobj) {
899 //postfl(" %s\n", slotRawSymbol(&classobj->name)->name);
900 PyrClass *superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
901 if (superclassobj) {
902 objAddIndexedObject(slotRawObject(&superclassobj->subclasses), (PyrObject*)classobj);
903 //postfl(" superclassobj %s %d\n", slotRawSymbol(&superclassobj->name)->name,
904 // slotRawObject(&superclassobj->subclasses)->size);
906 classobj = slotRawClass(&classobj->nextclass);
909 // alpha sort the classes via insertion sort
910 gClassList = sortClasses(gClassList);
913 void indexClassTree(PyrClass *classobj, int numSuperMethods)
915 int i, numMethods;
917 if (!classobj) return;
919 SetInt(&classobj->classIndex, gNumClasses);
920 gNumClasses ++;
922 if (IsObj(&classobj->methods)) {
923 PyrObject * methods = slotRawObject(&classobj->methods);
924 numMethods = methods->size;
926 else
927 numMethods = 0;
929 numMethods = numSuperMethods + numMethods;
930 if (IsObj(&classobj->subclasses)) {
931 PyrObject * subclasses = slotRawObject(&classobj->subclasses);
932 for (i=0; i<subclasses->size; ++i)
933 indexClassTree(slotRawClass(&subclasses->slots[i]), numMethods);
935 SetInt(&classobj->maxSubclassIndex, gNumClasses - 1);
938 void findDiscrepancy();
939 void findDiscrepancy()
941 PyrClass *classobjA, *classobjB;
943 classobjA = gClassList;
944 while (classobjA) {
945 classobjB = slotRawClass(&classobjA->nextclass);;
946 while (classobjB) {
947 if (slotRawSymbol(&classobjA->name) == slotRawSymbol(&classobjB->name)) {
948 post("duplicate %s\n", slotRawSymbol(&classobjA->name)->name);
950 classobjB = slotRawClass(&classobjB->nextclass);
952 classobjA = slotRawClass(&classobjA->nextclass);
957 static void indent(int n)
959 for (int i=0; i<n; ++i) {
960 post(" ");
964 void postClassTree(PyrClass *classobj, int level)
966 PyrObject *subclasses;
967 int i;
969 //post("%4d ", slotRawInt(&classobj->classIndex));
970 indent(level);
971 post("%s\n", slotRawSymbol(&classobj->name)->name);
973 if (classobj == class_class) {
974 indent(level+1);
975 post(" [.. all metaclasses ..]\n");
976 } else {
977 if (IsNil(&classobj->subclasses))
978 return; // FIXME: can we initialize subclasses with a NULL pointer?
979 subclasses = slotRawObject(&classobj->subclasses);
980 if (subclasses) {
981 // determine if can put on one line
982 bool oneline = subclasses->size <= 5;
983 for (i=0; oneline && i<subclasses->size; ++i) {
984 PyrClass *subclassobj = slotRawClass(&subclasses->slots[i]);
985 if (IsObj(&subclassobj->subclasses))
986 // FIXME: shall we do a null-pointer check?
987 oneline = false;
989 if (oneline) {
990 indent(level+1);
991 post("[");
992 for (i=0; i<subclasses->size; ++i) {
993 PyrClass *subclassobj = slotRawClass(&subclasses->slots[i]);
994 post(" %s", slotRawSymbol(&subclassobj->name)->name);
996 post(" ]\n");
997 } else {
998 indent(level);
999 post("[\n");
1000 for (i=0; i<subclasses->size; ++i) {
1001 postClassTree(slotRawClass(&subclasses->slots[i]), level+1);
1003 indent(level);
1004 post("]\n");
1011 void setSelectorFlags()
1013 int i;
1015 PyrClass * classobj = gClassList;
1016 while (classobj) {
1017 if (IsObj(&classobj->methods)) {
1018 PyrObject *methods = slotRawObject(&classobj->methods);
1019 for (i=0; i<methods->size; ++i) {
1020 PyrMethod * method = slotRawMethod(&methods->slots[i]);
1021 slotRawSymbol(&method->name)->flags |= sym_Selector;
1022 //if (method->methType == methRedirect) {
1023 // post("rd: %3d %s:%s\n", k++, slotRawSymbol(&classobj->name)->name,
1024 // slotRawSymbol(&method->name)->name);
1028 classobj = slotRawClass(&classobj->nextclass);
1030 // count selectors
1031 gNumSelectors = 0;
1032 SymbolTable* symbolTable = gMainVMGlobals->symbolTable;
1033 for (int i=0; i<symbolTable->TableSize(); ++i) {
1034 PyrSymbol *sym = symbolTable->Get(i);
1035 if (sym && (sym->flags & sym_Selector)) {
1036 sym->u.index = gNumSelectors++;
1039 //post("gNumSelectors %d\n", gNumSelectors);
1042 // the chunky stuff can be commented back in for implementing a better
1043 // compression scheme. The Q&D method works fine for my small class tree for now.
1045 typedef struct {
1046 PyrSymbol *selector;
1047 int minClassIndex;
1048 int maxClassIndex;
1049 int rowWidth;
1050 //int largestChunk;
1051 //int chunkOffset;
1052 int selectorIndex;
1053 int population;
1054 int rowOffset;
1055 } ColumnDescriptor;
1057 int compareColDescs(const void *va, const void *vb);
1058 int compareColDescs(const void *va, const void *vb)
1060 ColumnDescriptor *a = (ColumnDescriptor*)va;
1061 ColumnDescriptor *b = (ColumnDescriptor*)vb;
1062 int diff;
1063 //diff = b->largestChunk - a->largestChunk;
1064 //if (diff != 0) return diff;
1065 diff = b->rowWidth - a->rowWidth;
1066 if (diff != 0) return diff;
1067 //diff = b->chunkOffset - a->chunkOffset;
1068 diff = b->minClassIndex - a->minClassIndex;
1069 return diff;
1072 #define CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME 0
1073 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1074 double elapsedTime();
1075 #endif
1077 static size_t fillClassRow(PyrClass *classobj, PyrMethod** bigTable);
1080 static void updateSelectorRowWidth(ColumnDescriptor* sels, size_t begin, size_t end)
1082 for (int i=begin; i<end; ++i) {
1083 //if (chunkSize > sels[i].largestChunk) {
1084 // sels[i].largestChunk = chunkSize;
1085 // sels[i].chunkOffset = chunkOffset;
1087 sels[i].rowWidth = sels[i].maxClassIndex - sels[i].minClassIndex + 1;
1091 static void binsortClassRows(PyrMethod ** bigTable, const ColumnDescriptor* sels, size_t numSelectors, size_t begin, size_t end)
1093 // bin sort the class rows to the new ordering
1094 //post("reorder rows\n");
1095 const int allocaThreshold = 4096;
1097 PyrMethod** temprow = (numSelectors < allocaThreshold) ? (PyrMethod**)alloca(numSelectors * sizeof(PyrMethod*))
1098 : (PyrMethod**)malloc(numSelectors * sizeof(PyrMethod*));
1100 for (int j=begin; j<end; ++j) {
1101 PyrMethod** row = bigTable + j * numSelectors;
1102 memcpy(temprow, row, numSelectors * sizeof(PyrMethod*));
1103 for (int i=0; i<numSelectors; ++i)
1104 row[i] = temprow[sels[i].selectorIndex];
1107 if (numSelectors >= allocaThreshold)
1108 free(temprow);
1111 static void prepareColumnTable(ColumnDescriptor * sels, int numSelectors)
1113 // fill selector table
1114 //post("fill selector table\n");
1115 SymbolTable* symbolTable = gMainVMGlobals->symbolTable;
1116 for (int i=0, j=0; i<symbolTable->TableSize(); ++i) {
1117 PyrSymbol *sym = symbolTable->Get(i);
1118 if (sym && (sym->flags & sym_Selector))
1119 sels[j++].selector = sym;
1122 for (int i=0; i<numSelectors; ++i) {
1123 //postfl("%3d %s\n", i, sels[i].selector->name);
1124 sels[i].minClassIndex = INT_MAX;
1125 sels[i].maxClassIndex = 0;
1126 //sels[i].largestChunk = 0;
1127 //sels[i].chunkOffset = 0;
1128 sels[i].selectorIndex = i;
1129 sels[i].population = 0;
1133 static void calcRowStats(PyrMethod** bigTable, ColumnDescriptor * sels, int numClasses, int numSelectors, int begin, int end)
1135 //chunkSize = 0;
1136 //chunkOffset = 0;
1137 for (int j=0; j<numClasses; ++j) {
1138 for (int i=begin; i<end; ++i) {
1139 PyrMethod* method = bigTable[j * numSelectors + i];
1140 if (method) {
1141 //classobj = method->ownerclass.uoc;
1142 if (j > sels[i].maxClassIndex) {
1143 sels[i].maxClassIndex = j;
1145 if (j < sels[i].minClassIndex) {
1146 sels[i].minClassIndex = j;
1148 sels[i].population ++;
1149 //if (chunkSize == 0) chunkOffset = j;
1150 //chunkSize++;
1151 //postfl(" %8s %3d %3d %3d %3d\n", slotRawSymbol(&classobj->name)->name, i, j,
1152 // chunkSize, slotRawInt(&classobj->classIndex));
1153 //} else {
1154 //if (chunkSize > sels[i].largestChunk) {
1155 // sels[i].largestChunk = chunkSize;
1156 // sels[i].chunkOffset = chunkOffset;
1158 //chunkSize = 0;
1165 void buildBigMethodMatrix()
1167 PyrMethod **bigTable, **row;
1168 PyrClass *classobj, **classes;
1169 int i, j, k;
1170 int popSum, widthSum;
1171 int rowOffset, freeIndex;
1172 int rowTableSize;
1173 int bigTableSize;
1174 const int numSelectors = gNumSelectors;
1175 const int numClasses = gNumClasses;
1176 //post("allocate arrays\n");
1178 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1179 double t0 = elapsedTime();
1180 #endif
1182 // pyrmalloc:
1183 // lifetime: kill after compile
1184 bigTableSize = numSelectors * numClasses;
1185 //post("bigTableSize %d %d %d\n", bigTableSize, numSelectors, numClasses);
1186 ColumnDescriptor *sels = (ColumnDescriptor*)pyr_pool_compile->Alloc(numSelectors * sizeof(ColumnDescriptor));
1187 MEMFAIL(sels);
1188 if (helperThreadCount)
1189 compileThreadPool.schedule(boost::bind(&prepareColumnTable, sels, numSelectors));
1190 else
1191 prepareColumnTable(sels, numSelectors);
1193 bigTable = (PyrMethod**)pyr_pool_compile->Alloc(bigTableSize * sizeof(PyrMethod*));
1194 MEMFAIL(bigTable);
1195 classes = (PyrClass**)pyr_pool_compile->Alloc(numClasses * sizeof(PyrClass*));
1196 MEMFAIL(classes);
1198 classobj = gClassList;
1199 while (classobj) {
1200 classes[slotRawInt(&classobj->classIndex)] = classobj;
1201 classobj = slotRawClass(&classobj->nextclass);
1204 size_t numentries = fillClassRow(class_object, bigTable);
1205 post("\tnumentries = %lu / %d = %.2g\n", numentries, bigTableSize, (double)numentries/(double)bigTableSize);
1207 // no need to wait for the theadpool, because it is done in fillClassRow
1209 // calc row stats
1210 //post("calc row stats\n");
1211 const int classesPerThread = numClasses/cpuCount;
1212 const int selectorsPerThread = numSelectors/cpuCount;
1213 for (i = 0; i != helperThreadCount; ++i)
1214 compileThreadPool.schedule(boost::bind(&calcRowStats, bigTable, sels, numClasses, numSelectors,
1215 selectorsPerThread * i, selectorsPerThread * (i+1)));
1217 calcRowStats(bigTable, sels, numClasses, numSelectors, helperThreadCount*selectorsPerThread, numSelectors);
1218 if (helperThreadCount) compileThreadPool.wait();
1220 for (i = 0; i != helperThreadCount; ++i)
1221 compileThreadPool.schedule(boost::bind(&updateSelectorRowWidth, sels,
1222 selectorsPerThread * i, selectorsPerThread * (i+1)));
1224 updateSelectorRowWidth(sels, helperThreadCount*selectorsPerThread, numSelectors);
1225 if (helperThreadCount) compileThreadPool.wait();
1227 //post("qsort\n");
1228 // sort rows by largest chunk, then by width, then by chunk offset
1229 //qsort(sels, numSelectors, sizeof(ColumnDescriptor), (std::_compare_function)compareColDescs);
1230 qsort(sels, numSelectors, sizeof(ColumnDescriptor), compareColDescs);
1232 // bin sort the class rows to the new ordering
1233 //post("reorder rows\n");
1234 for (i = 0; i != helperThreadCount; ++i)
1235 compileThreadPool.schedule(boost::bind(&binsortClassRows, bigTable, sels, numSelectors,
1236 classesPerThread * i, classesPerThread * (i+1)));
1238 binsortClassRows(bigTable, sels, numSelectors, helperThreadCount*classesPerThread, numClasses);
1239 if (helperThreadCount) compileThreadPool.wait();
1241 //post("calc row offsets %d\n", numSelectors);
1242 widthSum = 0;
1243 popSum = 0;
1244 freeIndex = 0;
1245 rowOffset = -1;
1246 for (i=0; i<numSelectors; ++i) {
1247 widthSum += sels[i].rowWidth;
1248 popSum += sels[i].population;
1249 rowOffset = sc_max(rowOffset+1, freeIndex - sels[i].minClassIndex);
1250 freeIndex = rowOffset + sels[i].maxClassIndex + 1;
1251 sels[i].rowOffset = rowOffset;
1252 sels[i].selector->u.index = rowOffset;
1253 //post("%3d %24s %3d %5d %5d\n", i, sels[i].selector->name,
1254 // sels[i].rowWidth, rowOffset, freeIndex);
1256 //post("alloc row table %d\n", freeIndex);
1257 rowTableSize = (freeIndex + numClasses) * sizeof(PyrMethod*);
1258 gRowTable = (PyrMethod**)pyr_pool_runtime->Alloc(rowTableSize);
1259 MEMFAIL(gRowTable);
1261 // having the method ptr always be valid saves a branch in SendMessage()
1262 for (i=0; i<freeIndex + numClasses; ++i)
1263 gRowTable[i] = gNullMethod;
1265 //post("fill compressed table\n");
1266 //{ FILE* fp;
1267 // newPyrMethod
1268 //fp = fopen("meth table", "w");
1269 for (i=0; i<numSelectors; ++i) {
1270 int offset, maxwidth;
1271 offset = sels[i].rowOffset + sels[i].minClassIndex;
1272 maxwidth = offset + sels[i].rowWidth;
1273 row = bigTable + sels[i].minClassIndex * numSelectors + i;
1274 PyrMethod ** table = gRowTable;
1275 for (j=offset,k=0; j<maxwidth; ++j, k+=numSelectors) {
1276 if (row[k])
1277 table[j] = row[k];
1280 //fclose(fp);
1283 for (i=0; i<freeIndex + numClasses; ++i)
1284 assert(gRowTable[i]);
1287 //post("freeIndex %d\n", freeIndex);
1288 //post("widthSum %d\n", widthSum);
1289 //post("popSum %d\n", popSum);
1291 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1292 post("building table took %.3g seconds\n", elapsedTime() - t0);
1294 int numFilled = 0;
1295 for (i=0; i<rowTableSize/sizeof(PyrMethod*); ++i) {
1296 if (gRowTable[i] != gNullMethod) numFilled++;
1298 post("Filled %d of %d = %f percent\n", numFilled, rowTableSize/sizeof(PyrMethod*),
1299 100. * (double)numFilled/(rowTableSize/sizeof(PyrMethod*)));
1301 #endif
1302 post("\t%d method selectors, %d classes\n", numSelectors, numClasses);
1303 post("\tmethod table size %d bytes, ", rowTableSize);
1304 post("big table size %d\n", numSelectors * numClasses * sizeof(PyrMethod*));
1305 //postfl("%p %p %p\n", classes, bigTable, sels);
1307 // not necessary since the entire pool will be freed..
1308 pyr_pool_compile->Free(classes);
1309 pyr_pool_compile->Free(bigTable);
1310 pyr_pool_compile->Free(sels);
1312 compileThreadPool.size_controller().resize(0); // terminate threads
1315 #include <boost/atomic.hpp>
1317 static void fillClassRowSubClasses(PyrObject * subclasses, int begin, int end, PyrMethod** bigTable, boost::atomic<size_t> * rCount);
1319 static void fillClassRow(PyrClass *classobj, PyrMethod** bigTable, boost::atomic<size_t> * rCount)
1321 size_t count = 0;
1323 PyrMethod ** myrow = bigTable + slotRawInt(&classobj->classIndex) * gNumSelectors;
1324 PyrClass* superclassobj = slotRawSymbol(&classobj->superclass)->u.classobj;
1325 if (superclassobj) {
1326 PyrMethod ** superrow = bigTable + slotRawInt(&superclassobj->classIndex) * gNumSelectors;
1328 for (int i = 0; i != gNumSelectors; ++i) {
1329 myrow[i] = superrow[i];
1330 if (superrow[i])
1331 ++count;
1333 } else {
1334 memset(myrow, 0, gNumSelectors * sizeof(PyrMethod*));
1337 if (IsObj(&classobj->methods)) {
1338 PyrObject * methods = slotRawObject(&classobj->methods);
1339 //postfl(" %d\n", methods->size);
1340 for (int i=0; i<methods->size; ++i) {
1341 PyrMethod* method = slotRawMethod(&methods->slots[i]);
1342 int selectorIndex = slotRawSymbol(&method->name)->u.index;
1344 if (myrow[selectorIndex] == 0)
1345 ++count;
1347 myrow[selectorIndex] = method;
1351 *rCount += count;
1353 if (IsObj(&classobj->subclasses)) {
1354 PyrObject * subclasses = slotRawObject(&classobj->subclasses);
1355 size_t numSubclasses = subclasses->size;
1357 if (numSubclasses > 4*cpuCount) {
1358 int subclassesPerThread = numSubclasses / cpuCount;
1359 for (int i = 0; i != helperThreadCount; ++i)
1360 compileThreadPool.schedule(boost::bind(&fillClassRowSubClasses, subclasses,
1361 subclassesPerThread * i, subclassesPerThread * (i+1),
1362 bigTable, rCount));
1363 fillClassRowSubClasses(subclasses, subclassesPerThread * helperThreadCount, numSubclasses, bigTable, rCount);
1365 else
1366 fillClassRowSubClasses(subclasses, 0, numSubclasses, bigTable, rCount);
1370 static void fillClassRowSubClasses(PyrObject * subclasses, int begin, int end, PyrMethod** bigTable, boost::atomic<size_t> * rCount)
1372 for (int i = begin; i != end; ++i)
1373 fillClassRow(slotRawClass(&subclasses->slots[i]), bigTable, rCount);
1377 static size_t fillClassRow(PyrClass *classobj, PyrMethod** bigTable)
1379 boost::atomic<size_t> ret (0);
1381 fillClassRow(classobj, bigTable, &ret);
1382 if (helperThreadCount) compileThreadPool.wait();
1383 return ret.load(boost::memory_order_acquire);
1387 bool funcFindArg(PyrBlock* func, PyrSymbol *name, int *index)
1389 int i;
1390 for (i=0; i<slotRawSymbolArray(&func->argNames)->size; ++i) {
1391 if (slotRawSymbolArray(&func->argNames)->symbols[i] == name) {
1392 *index = i;
1393 return true;
1396 return false;
1399 bool funcFindVar(PyrBlock* func, PyrSymbol *name, int *index)
1401 int i;
1402 for (i=0; i<slotRawSymbolArray(&func->varNames)->size; ++i) {
1403 if (slotRawSymbolArray(&func->varNames)->symbols[i] == name) {
1404 *index = i;
1405 return true;
1408 return false;
1411 PyrClass* makeIntrinsicClass(PyrSymbol *className, PyrSymbol *superClassName,
1412 int numInstVars, int numClassVars)
1414 PyrClass *superClass = NULL;
1415 PyrClass *metaSuperClass = NULL;
1416 PyrSymbol *metaClassName = NULL;
1417 PyrSymbol *metaSuperClassName = NULL;
1418 PyrClass *classobj = NULL;
1419 PyrClass *metaclassobj = NULL;
1420 int superInstVars;
1422 //postfl("makeIntrinsicClass '%s'\n", className->name);
1423 if (superClassName) {
1424 superClass = superClassName->u.classobj;
1425 if (!superClass) {
1426 error("Can't find superclass '%s' of '%s'\n", superClassName->name,
1427 className->name);
1428 return NULL;
1430 metaSuperClassName = getmetasym(superClassName->name);
1431 metaSuperClass = metaSuperClassName->u.classobj;
1432 superInstVars = numSuperInstVars(superClass);
1433 } else {
1434 // else it must be Object and so has no superclass
1435 metaSuperClassName = NULL;
1436 superInstVars = 0;
1439 metaClassName = getmetasym(className->name);
1440 metaClassName->flags |= sym_MetaClass;
1441 metaclassobj = newClassObj( class_class,
1442 metaClassName, metaSuperClassName,
1443 classClassNumInstVars, 0, 0, 0, obj_notindexed, 0);
1444 SetInt(&metaclassobj->classFlags, slotRawInt(&metaclassobj->classFlags) | classIsIntrinsic);
1446 if (metaSuperClassName && classClassNumInstVars) {
1447 memcpy(slotRawObject(&metaclassobj->iprototype)->slots, slotRawObject(&metaSuperClass->iprototype)->slots,
1448 sizeof(PyrSlot) * classClassNumInstVars);
1449 memcpy(slotRawSymbolArray(&metaclassobj->instVarNames)->symbols,
1450 slotRawSymbolArray(&metaSuperClass->instVarNames)->symbols,
1451 sizeof(PyrSymbol*) * classClassNumInstVars);
1452 slotRawObject(&metaclassobj->iprototype)->size = classClassNumInstVars;
1453 slotRawObject(&metaclassobj->instVarNames)->size = classClassNumInstVars;
1454 //dumpObject((PyrObject*)metaclassobj);
1457 classobj = newClassObj(metaclassobj,
1458 className, superClassName,
1459 numInstVars + superInstVars, numClassVars, 0, 0, obj_notindexed, 0);
1460 SetInt(&classobj->classFlags, slotRawInt(&classobj->classFlags) | classIsIntrinsic);
1462 //postfl("%s:%s : %d\n", className->name, superClassName->name, superInstVars);
1463 if (superClass && superInstVars) {
1464 memcpy(slotRawObject(&classobj->iprototype)->slots, slotRawObject(&superClass->iprototype)->slots,
1465 sizeof(PyrSlot) * superInstVars);
1466 memcpy(slotRawSymbolArray(&classobj->instVarNames)->symbols,
1467 slotRawSymbolArray(&superClass->instVarNames)->symbols,
1468 sizeof(PyrSymbol*) * superInstVars);
1469 slotRawObject(&classobj->iprototype)->size = superInstVars;
1470 slotRawObject(&classobj->instVarNames)->size = superInstVars;
1473 return classobj;
1476 void addIntrinsicVar(PyrClass *classobj, const char *varName, PyrSlot *slot)
1478 //postfl("%s %s %d\n", slotRawSymbol(&classobj->name)->name, varName,
1479 // slotRawObject(&classobj->instVarNames)->size);
1480 objAddIndexedSymbol(slotRawSymbolArray(&classobj->instVarNames), getsym(varName));
1481 objAddIndexedSlot(slotRawObject(&classobj->iprototype), slot);
1484 void addIntrinsicClassVar(PyrClass *classobj, const char *varName, PyrSlot *slot);
1485 void addIntrinsicClassVar(PyrClass *classobj, const char *varName, PyrSlot *slot)
1487 //postfl("%s %s %d\n", slotRawSymbol(&classobj->name)->name, varName,
1488 // slotRawObject(&classobj->instVarNames)->size);
1489 objAddIndexedSymbol(slotRawSymbolArray(&classobj->classVarNames), getsym(varName));
1490 objAddIndexedSlot(slotRawObject(&classobj->cprototype), slot);
1493 void initClasses()
1495 PyrClass *class_object_meta;
1496 PyrMethodRaw *methraw;
1498 // BOOTSTRAP THE OBJECT HIERARCHY
1500 gNumClassVars = 0;
1501 gClassList = NULL;
1502 gNullMethod = newPyrMethod();
1503 SetSymbol(&gNullMethod->name, (PyrSymbol*)NULL);
1504 methraw = METHRAW(gNullMethod);
1505 methraw->methType = methNormal;
1507 // build intrinsic classes
1508 class_class = NULL;
1509 class_object = makeIntrinsicClass(s_object, 0, 0, 4);
1510 class_class = makeIntrinsicClass(s_class, s_object, classClassNumInstVars, 1);
1512 // now fix class_class ptrs that were just previously installed erroneously
1513 class_object->classptr->classptr = class_class;
1514 class_class->classptr->classptr = class_class;
1515 class_object_meta = class_object->classptr;
1516 class_object_meta->superclass = class_class->name;
1518 addIntrinsicClassVar(class_object, "dependantsDictionary", &o_nil);
1519 addIntrinsicClassVar(class_object, "currentEnvironment", &o_nil);
1520 addIntrinsicClassVar(class_object, "topEnvironment", &o_nil);
1521 addIntrinsicClassVar(class_object, "uniqueMethods", &o_nil);
1523 // declare varNames for Class
1525 addIntrinsicVar(class_class, "name", &o_nil);
1526 addIntrinsicVar(class_class, "nextclass", &o_nil);
1527 addIntrinsicVar(class_class, "superclass", &o_nil);
1528 addIntrinsicVar(class_class, "subclasses", &o_nil);
1529 addIntrinsicVar(class_class, "methods", &o_nil);
1531 addIntrinsicVar(class_class, "instVarNames", &o_nil);
1532 addIntrinsicVar(class_class, "classVarNames", &o_nil);
1533 addIntrinsicVar(class_class, "iprototype", &o_nil);
1534 addIntrinsicVar(class_class, "cprototype", &o_nil);
1536 addIntrinsicVar(class_class, "constNames", &o_nil);
1537 addIntrinsicVar(class_class, "constValues", &o_nil);
1539 addIntrinsicVar(class_class, "instanceFormat", &o_nil);
1540 addIntrinsicVar(class_class, "instanceFlags", &o_zero);
1541 addIntrinsicVar(class_class, "classIndex", &o_zero);
1542 addIntrinsicVar(class_class, "classFlags", &o_zero);
1543 addIntrinsicVar(class_class, "maxSubclassIndex", &o_zero);
1544 addIntrinsicVar(class_class, "filenameSymbol", &o_nil);
1545 addIntrinsicVar(class_class, "charPos", &o_zero);
1546 addIntrinsicVar(class_class, "classVarIndex", &o_zero);
1548 addIntrinsicClassVar(class_class, "classesInited", &o_nil);
1550 // class_object_meta's inst var names need to be copied from class_class
1551 // because class_class didn't exist when it was created
1552 memcpy(slotRawObject(&class_object_meta->iprototype)->slots, slotRawObject(&class_class->iprototype)->slots,
1553 sizeof(PyrSlot) * classClassNumInstVars);
1554 memcpy(slotRawSymbolArray(&class_object_meta->instVarNames)->symbols,
1555 slotRawSymbolArray(&class_class->instVarNames)->symbols,
1556 sizeof(PyrSymbol*) * classClassNumInstVars);
1558 memcpy(slotRawObject(&class_class->classptr->iprototype)->slots, slotRawObject(&class_class->iprototype)->slots,
1559 sizeof(PyrSlot) * classClassNumInstVars);
1560 memcpy(slotRawSymbolArray(&class_class->classptr->instVarNames)->symbols,
1561 slotRawSymbolArray(&class_class->instVarNames)->symbols,
1562 sizeof(PyrSymbol*) * classClassNumInstVars);
1565 // OK the next thing I need is arrays..
1566 class_collection = makeIntrinsicClass(s_collection, s_object, 0, 0);
1567 class_sequenceable_collection = makeIntrinsicClass(s_sequenceable_collection, s_collection, 0, 0);
1569 class_arrayed_collection = makeIntrinsicClass(s_arrayed_collection, s_sequenceable_collection, 0, 0);
1570 class_array = makeIntrinsicClass(s_array, s_arrayed_collection, 0, 0);
1571 SetInt(&class_array->instanceFormat, obj_slot);
1572 SetInt(&class_array->classFlags, slotRawInt(&class_array->classFlags) | classHasIndexableInstances);
1574 // now fix array classptrs in already created classes
1575 fixClassArrays(class_class);
1576 fixClassArrays(class_class->classptr);
1577 fixClassArrays(class_object_meta);
1578 fixClassArrays(class_collection);
1579 fixClassArrays(class_sequenceable_collection);
1580 fixClassArrays(class_arrayed_collection);
1581 fixClassArrays(class_array);
1583 class_fundef = makeIntrinsicClass(s_fundef, s_object, 10, 0);
1584 // declare varNames for Block
1586 addIntrinsicVar(class_fundef, "raw1", &o_nil);
1587 addIntrinsicVar(class_fundef, "raw2", &o_nil);
1588 addIntrinsicVar(class_fundef, "code", &o_nil);
1589 addIntrinsicVar(class_fundef, "selectors", &o_nil);
1590 addIntrinsicVar(class_fundef, "constants", &o_nil);
1592 addIntrinsicVar(class_fundef, "prototypeFrame", &o_nil);
1593 addIntrinsicVar(class_fundef, "context", &o_nil);
1594 addIntrinsicVar(class_fundef, "argNames", &o_nil);
1595 addIntrinsicVar(class_fundef, "varNames", &o_nil);
1596 addIntrinsicVar(class_fundef, "sourceCode", &o_nil);
1598 class_method = makeIntrinsicClass(s_method, s_fundef, 5, 0);
1599 addIntrinsicVar(class_method, "ownerClass", &o_nil);
1600 addIntrinsicVar(class_method, "name", &o_nil);
1601 addIntrinsicVar(class_method, "primitiveName", &o_nil);
1602 addIntrinsicVar(class_method, "filenameSymbol", &o_nil);
1603 addIntrinsicVar(class_method, "charPos", &o_zero);
1604 //addIntrinsicVar(class_method, "byteMeter", &o_zero);
1605 //addIntrinsicVar(class_method, "callMeter", &o_zero);
1607 class_frame = makeIntrinsicClass(s_frame, s_object, 0, 0);
1608 SetInt(&class_frame->classFlags, slotRawInt(&class_frame->classFlags) | classHasIndexableInstances);
1609 //addIntrinsicVar(class_frame, "method", &o_nil);
1610 //addIntrinsicVar(class_frame, "caller", &o_nil);
1611 //addIntrinsicVar(class_frame, "context", &o_nil);
1612 //addIntrinsicVar(class_frame, "homeContext", &o_nil);
1613 //addIntrinsicVar(class_frame, "ip", &o_nil);
1615 class_process = makeIntrinsicClass(s_process, s_object, 6, 0);
1616 addIntrinsicVar(class_process, "classVars", &o_nil);
1617 addIntrinsicVar(class_process, "interpreter", &o_nil);
1618 addIntrinsicVar(class_process, "curThread", &o_nil);
1619 addIntrinsicVar(class_process, "mainThread", &o_nil);
1620 addIntrinsicVar(class_process, "schedulerQueue", &o_nil);
1621 addIntrinsicVar(class_process, "nowExecutingPath", &o_nil);
1623 class_interpreter = makeIntrinsicClass(s_interpreter, s_object, 29, 0);
1624 addIntrinsicVar(class_interpreter, "cmdLine", &o_nil);
1625 addIntrinsicVar(class_interpreter, "context", &o_nil);
1626 for (int i=0; i<26; ++i) {
1627 char name[2];
1628 name[0] = 'a' + i;
1629 name[1] = 0;
1630 addIntrinsicVar(class_interpreter, name, &o_nil);
1632 addIntrinsicVar(class_interpreter, "codeDump", &o_nil);
1633 addIntrinsicVar(class_interpreter, "preProcessor", &o_nil);
1635 class_absfunc = makeIntrinsicClass(s_absfunc, s_object, 0, 0);
1636 class_stream = makeIntrinsicClass(s_stream, s_absfunc, 0, 0);
1638 class_thread = makeIntrinsicClass(s_thread, s_stream, 27, 0);
1639 addIntrinsicVar(class_thread, "state", &o_nil);
1640 addIntrinsicVar(class_thread, "func", &o_nil);
1641 addIntrinsicVar(class_thread, "stack", &o_nil);
1642 addIntrinsicVar(class_thread, "method", &o_nil);
1643 addIntrinsicVar(class_thread, "block", &o_nil);
1644 addIntrinsicVar(class_thread, "frame", &o_nil);
1645 addIntrinsicVar(class_thread, "ip", &o_zero);
1646 addIntrinsicVar(class_thread, "sp", &o_zero);
1647 addIntrinsicVar(class_thread, "numpop", &o_zero);
1648 addIntrinsicVar(class_thread, "receiver", &o_nil);
1649 addIntrinsicVar(class_thread, "numArgsPushed", &o_zero);
1650 addIntrinsicVar(class_thread, "parent", &o_nil);
1651 addIntrinsicVar(class_thread, "terminalValue", &o_nil);
1653 addIntrinsicVar(class_thread, "primitiveError", &o_zero);
1654 addIntrinsicVar(class_thread, "primitiveIndex", &o_zero);
1655 addIntrinsicVar(class_thread, "randData", &o_zero);
1656 addIntrinsicVar(class_thread, "beats", &o_fzero);
1657 addIntrinsicVar(class_thread, "seconds", &o_fzero);
1658 addIntrinsicVar(class_thread, "clock", &o_nil);
1659 addIntrinsicVar(class_thread, "nextBeat", &o_nil);
1660 addIntrinsicVar(class_thread, "endBeat", &o_nil);
1661 addIntrinsicVar(class_thread, "endValue", &o_nil);
1663 addIntrinsicVar(class_thread, "environment", &o_nil);
1664 addIntrinsicVar(class_thread, "exceptionHandler", &o_nil);
1665 addIntrinsicVar(class_thread, "threadPlayer", &o_nil);
1667 addIntrinsicVar(class_thread, "executingPath", &o_nil);
1668 addIntrinsicVar(class_thread, "oldExecutingPath", &o_nil);
1670 class_finalizer = makeIntrinsicClass(s_finalizer, s_object, 2, 0);
1671 addIntrinsicVar(class_finalizer, "cFunction", &o_nil);
1672 addIntrinsicVar(class_finalizer, "object", &o_nil);
1674 class_routine = makeIntrinsicClass(s_routine, s_thread, 0, 0);
1676 class_symbol = makeIntrinsicClass(s_symbol, s_object, 0, 0);
1677 class_nil = makeIntrinsicClass(s_nil, s_object, 0, 0);
1679 class_boolean = makeIntrinsicClass(s_boolean, s_object, 0, 0);
1680 class_true = makeIntrinsicClass(s_true, s_boolean, 0, 0);
1681 class_false = makeIntrinsicClass(s_false, s_boolean, 0, 0);
1683 class_magnitude = makeIntrinsicClass(s_magnitude, s_object, 0, 0);
1684 class_char = makeIntrinsicClass(s_char, s_magnitude, 0, 0);
1685 class_number = makeIntrinsicClass(s_number, s_magnitude, 0, 0);
1686 class_simple_number = makeIntrinsicClass(s_simple_number, s_number, 0, 0);
1687 class_int = makeIntrinsicClass(s_int, s_simple_number, 0, 0);
1688 class_float = makeIntrinsicClass(s_float, s_simple_number, 0, 0);
1690 class_rawptr = makeIntrinsicClass(s_rawptr, s_object, 0, 0);
1693 class_complex = makeIntrinsicClass(s_complex, s_number, 2, 0);
1694 addIntrinsicVar(class_complex, "real", &o_nil);
1695 addIntrinsicVar(class_complex, "imag", &o_nil);
1698 class_rawarray = makeIntrinsicClass(s_rawarray, s_arrayed_collection, 0, 0);
1699 //SetInt(&class_rawarray->instanceFormat, obj_int8);
1700 //slotRawInt(&class_rawarray->classFlags) |= classHasIndexableInstances;
1701 class_int8array = makeIntrinsicClass(s_int8array, s_rawarray, 0, 0);
1702 SetInt(&class_int8array->instanceFormat, obj_int8);
1703 SetInt(&class_int8array->classFlags, slotRawInt(&class_int8array->classFlags) | classHasIndexableInstances);
1704 class_int16array = makeIntrinsicClass(s_int16array, s_rawarray, 0, 0);
1705 SetInt(&class_int16array->instanceFormat, obj_int16);
1706 SetInt(&class_int16array->classFlags, slotRawInt(&class_int16array->classFlags) | classHasIndexableInstances);
1707 class_int32array = makeIntrinsicClass(s_int32array, s_rawarray, 0, 0);
1708 SetInt(&class_int32array->instanceFormat, obj_int32);
1709 SetInt(&class_int32array->classFlags, slotRawInt(&class_int32array->classFlags) | classHasIndexableInstances);
1710 class_symbolarray = makeIntrinsicClass(s_symbolarray, s_rawarray, 0, 0);
1711 SetInt(&class_symbolarray->instanceFormat, obj_symbol);
1712 SetInt(&class_symbolarray->classFlags, slotRawInt(&class_symbolarray->classFlags) | classHasIndexableInstances);
1713 class_string = makeIntrinsicClass(s_string, s_rawarray, 0, 1);
1714 addIntrinsicClassVar(class_string, "unixCmdActions", &o_nil);
1715 SetInt(&class_string->instanceFormat, obj_char);
1716 SetInt(&class_string->classFlags, slotRawInt(&class_string->classFlags) | classHasIndexableInstances);
1717 class_floatarray = makeIntrinsicClass(s_floatarray, s_rawarray, 0, 0);
1718 SetInt(&class_floatarray->instanceFormat, obj_float);
1719 SetInt(&class_floatarray->classFlags, slotRawInt(&class_floatarray->classFlags) | classHasIndexableInstances);
1720 class_signal = makeIntrinsicClass(s_signal, s_floatarray, 0, 0);
1721 SetInt(&class_signal->instanceFormat, obj_float);
1722 SetInt(&class_signal->classFlags, slotRawInt(&class_signal->classFlags) | classHasIndexableInstances);
1723 class_wavetable = makeIntrinsicClass(s_wavetable, s_floatarray, 0, 0);
1724 SetInt(&class_wavetable->instanceFormat, obj_float);
1725 SetInt(&class_wavetable->classFlags, slotRawInt(&class_wavetable->classFlags) | classHasIndexableInstances);
1727 //addIntrinsicVar(class_signal, "rate", &o_nil);
1728 class_doublearray = makeIntrinsicClass(s_doublearray, s_rawarray, 0, 0);
1729 SetInt(&class_doublearray->instanceFormat, obj_double);
1730 SetInt(&class_doublearray->classFlags, slotRawInt(&class_doublearray->classFlags) | classHasIndexableInstances);
1732 class_list = makeIntrinsicClass(s_list, s_sequenceable_collection, 1, 0);
1733 addIntrinsicVar(class_list, "array", &o_nil);
1734 //addIntrinsicVar(class_list, "size", &o_zero);
1736 class_func = makeIntrinsicClass(s_func, s_absfunc, 2, 0);
1737 addIntrinsicVar(class_func, "def", &o_nil);
1738 addIntrinsicVar(class_func, "context", &o_nil);
1740 class_server_shm_interface = makeIntrinsicClass(s_server_shm_interface, s_object, 2, 0);
1741 addIntrinsicVar(class_server_shm_interface, "ptr", &o_nil);
1742 addIntrinsicVar(class_server_shm_interface, "finalizer", &o_nil);
1744 gTagClassTable[ 0] = NULL;
1745 gTagClassTable[ 1] = NULL;
1746 gTagClassTable[ 2] = class_int;
1747 gTagClassTable[ 3] = class_symbol;
1748 gTagClassTable[ 4] = class_char;
1749 gTagClassTable[ 5] = class_nil;
1750 gTagClassTable[ 6] = class_false;
1751 gTagClassTable[ 7] = class_true;
1752 gTagClassTable[ 8] = class_rawptr;
1753 gTagClassTable[ 9] = class_float;
1754 gTagClassTable[10] = class_float;
1755 gTagClassTable[11] = class_float;
1756 gTagClassTable[12] = class_float;
1758 SetObject(&o_emptyarray, newPyrArray(NULL, 0, obj_permanent | obj_immutable, false));
1760 SetObject(&o_onenilarray, newPyrArray(NULL, 1, obj_permanent | obj_immutable, false));
1761 slotRawObject(&o_onenilarray)->size = 1;
1762 SetNil(slotRawObject(&o_onenilarray)->slots);
1764 SetObject(&o_argnamethis, newPyrSymbolArray(NULL, 1, obj_permanent | obj_immutable, false));
1765 slotRawSymbolArray(&o_argnamethis)->size = 1;
1766 slotRawSymbolArray(&o_argnamethis)->symbols[0] = s_this;
1769 post("array %p '%s'\n", class_array, class_array->name.us->name);
1770 post("o_emptyarray %p '%s'\n", slotRawObject(&o_emptyarray)->classptr, slotRawObject(&o_emptyarray)->classptr->name.us->name);
1771 post("o_argnamethis %p '%s'\n", slotRawObject(&o_argnamethis)->classptr, slotRawObject(&o_argnamethis)->classptr->name.us->name);
1772 post("o_onenilarray %p '%s'\n", slotRawObject(&o_onenilarray)->classptr, slotRawObject(&o_onenilarray)->classptr->name.us->name);
1773 dumpObjectSlot(&o_emptyarray);
1774 dumpObjectSlot(&o_argnamethis);
1775 dumpObjectSlot(&o_onenilarray);
1779 PyrObject* instantiateObject(class PyrGC *gc, PyrClass* classobj, int size,
1780 bool fill, bool collect)
1782 PyrObject *newobj, *proto;
1783 int numbytes, format, flags;
1785 format = slotRawInt(&classobj->instanceFormat);
1786 flags = slotRawInt(&classobj->instanceFlags);
1788 if (slotRawInt(&classobj->classFlags) & classHasIndexableInstances) {
1789 // create an indexable object
1790 numbytes = size * gFormatElemSize[format];
1791 newobj = gc->New(numbytes, flags, format, collect);
1792 if (fill) {
1793 newobj->size = size;
1794 if (format == obj_slot) {
1795 nilSlots(newobj->slots, size);
1796 } else {
1797 memset(newobj->slots, format == obj_char ? ' ' : 0, size * gFormatElemSize[format]);
1799 } else {
1800 newobj->size = 0;
1802 } else {
1803 if (IsObj(&classobj->iprototype)) {
1804 proto = slotRawObject(&classobj->iprototype);
1805 size = proto->size;
1806 numbytes = size * sizeof(PyrSlot);
1807 newobj = gc->New(numbytes, flags, format, collect);
1808 newobj->size = size;
1809 if (size) {
1810 memcpy(newobj->slots, proto->slots, numbytes);
1812 } else {
1813 numbytes = 0;
1814 newobj = gc->New(numbytes, flags, format, collect);
1815 newobj->size = 0;
1818 newobj->classptr = classobj;
1819 return newobj;
1822 PyrObject* instantiateObjectLight(class PyrGC *gc, PyrClass* classobj, int size, bool collect);
1823 PyrObject* instantiateObjectLight(class PyrGC *gc, PyrClass* classobj, int size, bool collect)
1825 PyrObject *newobj, *proto;
1826 int numbytes, format, flags;
1828 format = slotRawInt(&classobj->instanceFormat);
1829 flags = slotRawInt(&classobj->instanceFlags);
1831 if (slotRawInt(&classobj->classFlags) & classHasIndexableInstances) {
1832 numbytes = size * gFormatElemSize[format];
1833 } else {
1834 if (IsObj(&classobj->iprototype)) {
1835 proto = slotRawObject(&classobj->iprototype);
1836 size = proto->size;
1837 numbytes = size * sizeof(PyrSlot);
1838 } else {
1839 size = 0;
1840 numbytes = 0;
1843 newobj = gc->New(numbytes, flags, format, collect);
1844 newobj->size = size;
1845 newobj->classptr = classobj;
1847 return newobj;
1850 PyrObject* copyObject(class PyrGC *gc, PyrObject *inobj, bool collect)
1852 PyrObject *newobj;
1854 int flags = ~(obj_immutable) & inobj->obj_flags;
1856 int elemsize = gFormatElemSize[inobj->obj_format];
1857 int numbytes = inobj->size * elemsize;
1859 newobj = gc->New(numbytes, flags, inobj->obj_format, collect);
1861 newobj->size = inobj->size;
1862 newobj->classptr = inobj->classptr;
1864 memcpy(newobj->slots, inobj->slots, inobj->size * elemsize);
1865 return newobj;
1868 PyrObject* copyObjectRange(class PyrGC *gc, PyrObject *inobj, int start, int end, bool collect)
1870 PyrObject *newobj;
1872 if (start < 0) start = 0;
1873 if (end >= inobj->size) end = inobj->size - 1;
1874 int length = end - start + 1;
1875 if (length < 0) length = 0;
1877 int elemsize = gFormatElemSize[inobj->obj_format];
1878 int numbytes = length * elemsize;
1880 int flags = ~(obj_immutable) & inobj->obj_flags;
1882 newobj = gc->New(numbytes, flags, inobj->obj_format, collect);
1883 newobj->size = length;
1884 newobj->classptr = inobj->classptr;
1886 if (length > 0) {
1887 memcpy(newobj->slots, (char*)(inobj->slots) + start * elemsize, length * elemsize);
1889 return newobj;
1892 void dumpObject(PyrObject *obj)
1894 char str[256];
1895 PyrClass *classobj;
1896 int i;
1898 if (obj == NULL) {
1899 postfl("NULL object pointer\n");
1900 return;
1902 classobj = obj->classptr;
1903 if (isKindOf(obj, class_class)) {
1904 post("class %s (%p) {\n", slotRawSymbol(&((PyrClass*)obj)->name)->name, obj);
1905 } else {
1906 //post("Instance of %s (%p) {\n", slotRawSymbol(&classobj->name)->name, obj);
1907 post("Instance of %s { (%p, gc=%02X, fmt=%02X, flg=%02X, set=%02X)\n",
1908 slotRawSymbol(&classobj->name)->name, obj, obj->gc_color, obj->obj_format, obj->obj_flags,
1909 obj->obj_sizeclass);
1911 //flushPostBuf();
1913 if (obj->obj_format == obj_notindexed) {
1914 post(" instance variables [%d]\n", obj->size);
1915 for (i=0; i<obj->size; ++i) {
1916 slotString(obj->slots + i, str);
1917 post(" %s : %s\n", slotRawSymbolArray(&classobj->instVarNames)->symbols[i]->name, str);
1919 } else {
1920 int maxsize;
1921 post(" indexed slots [%d]\n", obj->size);
1922 maxsize = sc_min(32, obj->size);
1923 switch (obj->obj_format) {
1924 case obj_slot :
1925 for (i=0; i<maxsize; ++i) {
1926 slotString(obj->slots + i, str);
1927 post(" %3d : %s\n", i, str);
1929 break;
1930 case obj_double :
1931 for (i=0; i<maxsize; ++i) {
1932 post(" %3d : %f\n", i, slotRawFloat(&obj->slots[i]));
1934 break;
1935 case obj_float :
1936 for (i=0; i<maxsize; ++i) {
1937 float val;
1938 val = ((float*)(obj->slots))[i];
1939 post(" %3d : %g\n", i, val);
1941 break;
1942 case obj_int32 :
1943 for (i=0; i<maxsize; ++i) {
1944 int32 val;
1945 val = ((int32*)(obj->slots))[i];
1946 post(" %3d : %d\n", i, val);
1948 break;
1949 case obj_int16 :
1950 for (i=0; i<maxsize; ++i) {
1951 int16 val;
1952 val = ((int16*)(obj->slots))[i];
1953 post(" %3d : %d\n", i, val);
1955 break;
1956 case obj_int8 :
1957 for (i=0; i<maxsize; ++i) {
1958 int8 val;
1959 val = ((int8*)(obj->slots))[i];
1960 post(" %3d : %4d %4u 0x%02X\n", i, val, val&255, val&255);
1962 break;
1963 case obj_char :
1964 for (i=0; i<maxsize; ++i) {
1965 char val;
1966 val = ((char*)(obj->slots))[i];
1967 post(" %3d : %c\n", i, val);
1969 break;
1970 case obj_symbol :
1971 for (i=0; i<maxsize; ++i) {
1972 PyrSymbol* sym;
1973 sym = ((PyrSymbol**)(obj->slots))[i];
1974 post(" %3d : '%s'\n", i, sym->name);
1976 break;
1977 default :
1978 post("unknown obj_format %X\n", obj->obj_format);
1980 if (obj->size > maxsize) {
1981 post(" ...\n");
1984 post("}\n");
1987 void dumpBadObject(PyrObject *obj)
1989 char str[128];
1990 PyrClass *classobj;
1991 int i;
1993 if (obj == NULL) {
1994 postfl("NULL object pointer\n");
1995 return;
1997 classobj = obj->classptr;
1998 if (isKindOf(obj, class_class)) {
1999 postfl("class %s (%p) {\n", slotRawSymbol(&((PyrClass*)obj)->name)->name, obj);
2000 } else {
2001 //postfl("Instance of %s (%p) {\n", slotRawSymbol(&classobj->name)->name, obj);
2002 postfl("Instance of %s { (%p, gc=%02X, fmt=%02X, flg=%02X, set=%02X)\n",
2003 slotRawSymbol(&classobj->name)->name, obj, obj->gc_color, obj->obj_format, obj->obj_flags,
2004 obj->obj_sizeclass);
2006 if (obj->obj_format == obj_notindexed) {
2007 postfl(" instance variables [%d]\n", obj->size);
2008 for (i=0; i<obj->size; ++i) {
2009 slotString(obj->slots + i, str);
2010 postfl(" %s : %s\n", slotRawSymbolArray(&classobj->instVarNames)->symbols[i]->name, str);
2012 } else {
2013 int maxsize;
2014 postfl(" indexed slots [%d]\n", obj->size);
2015 maxsize = obj->size;
2016 maxsize = sc_min(32, maxsize);
2017 switch (obj->obj_format) {
2018 case obj_slot :
2019 for (i=0; i<maxsize; ++i) {
2020 slotString(obj->slots + i, str);
2021 postfl(" %3d : %s\n", i, str);
2023 break;
2024 case obj_double :
2025 for (i=0; i<maxsize; ++i) {
2026 postfl(" %3d : %f\n", i, slotRawFloat(&obj->slots[i]));
2028 break;
2029 case obj_float :
2030 for (i=0; i<maxsize; ++i) {
2031 float val;
2032 val = ((float*)(obj->slots))[i];
2033 postfl(" %3d : %g\n", i, val);
2035 break;
2036 case obj_int32 :
2037 for (i=0; i<maxsize; ++i) {
2038 int32 val;
2039 val = ((int32*)(obj->slots))[i];
2040 postfl(" %3d : %d\n", i, val);
2042 break;
2043 case obj_int16 :
2044 for (i=0; i<maxsize; ++i) {
2045 int16 val;
2046 val = ((int16*)(obj->slots))[i];
2047 postfl(" %3d : %d\n", i, val);
2049 break;
2050 case obj_int8 :
2051 for (i=0; i<maxsize; ++i) {
2052 int8 val;
2053 val = ((int8*)(obj->slots))[i];
2054 postfl(" %3d : %4d %4u 0x%02X\n", i, val, val&255, val&255);
2056 break;
2057 case obj_char :
2058 for (i=0; i<maxsize; ++i) {
2059 char val;
2060 val = ((char*)(obj->slots))[i];
2061 postfl(" %3d : %c\n", i, val);
2063 break;
2064 case obj_symbol :
2065 for (i=0; i<maxsize; ++i) {
2066 PyrSymbol* sym;
2067 sym = ((PyrSymbol**)(obj->slots))[i];
2068 post(" %3d : '%s'\n", i, sym->name);
2070 break;
2071 default :
2072 postfl("unknown obj_format %X\n", obj->obj_format);
2074 if (obj->size > maxsize) {
2075 postfl(" ...\n");
2078 postfl("}\n");
2081 void dumpObjectSlot(PyrSlot *slot)
2083 if (IsObj(slot)) {
2084 dumpObject(slotRawObject(slot));
2085 } else {
2086 dumpPyrSlot(slot);
2090 void dumpSlotOneWord(const char *tagstr, PyrSlot *slot)
2092 char str[256];
2093 slotOneWord(slot, str);
2094 post("%s %s\n", tagstr, str);
2097 void CallStackSanity(VMGlobals *g, const char *tagstr);
2098 void CallStackSanity(VMGlobals *g, const char *tagstr)
2100 PyrFrame *frame;
2101 frame = g->frame;
2102 while (frame) {
2103 if (FrameSanity(frame, tagstr)) {
2104 DumpBackTrace(g);
2105 //Debugger();
2106 break;
2108 frame = slotRawFrame(&frame->caller);
2112 bool FrameSanity(PyrFrame *frame, const char *tagstr);
2113 bool FrameSanity(PyrFrame *frame, const char *tagstr)
2115 bool failed = false;
2116 if (frame==NULL) return false;
2117 if (NotObj(&frame->method)) {
2118 postfl("Frame %p method tag wrong %p\n", frame, GetTag(&frame->method));
2119 failed = true;
2120 //} else if (!isKindOf((PyrObject*)slotRawObject(&frame->method)->classptr, class_fundef)) {
2121 } else if (slotRawObject(&frame->method)->classptr != class_method && slotRawObject(&frame->method)->classptr != class_fundef) {
2122 postfl("Frame %p method class wrong %p\n", frame, slotRawObject(&frame->method)->classptr);
2123 failed = true;
2124 //if (slotRawObject(&frame->method)->classptr->classptr == class_class) {
2125 postfl("class: '%s'\n", slotRawSymbol(&slotRawObject(&frame->method)->classptr->name)->name);
2126 ///} else {
2127 // postfl("not even a class\n");
2129 } else if (NotObj(&slotRawBlock(&frame->method)->code)) {
2130 postfl("Method %p code tag wrong %p\n", slotRawBlock(&frame->method), GetTag(&slotRawBlock(&frame->method)->code));
2131 failed = true;
2132 } else if (slotRawObject(&slotRawBlock(&frame->method)->code)->classptr != class_int8array) {
2133 postfl("Code %p class wrong %p\n", slotRawObject(&slotRawBlock(&frame->method)->code), slotRawObject(&slotRawBlock(&frame->method)->code)->classptr);
2134 postfl("class: '%s'\n", slotRawSymbol(&slotRawObject(&slotRawBlock(&frame->method)->code)->classptr->name)->name);
2135 failed = true;
2138 if (frame->caller.utag != tagHFrame && frame->caller.utag != tagNil) {
2139 postfl("Frame %p caller tag wrong %p\n", frame, frame->caller.utag);
2140 failed = true;
2142 if (frame->context.utag != tagHFrame && frame->context.utag != tagNil) {
2143 postfl("Frame %p context tag wrong %p\n", frame, frame->context.utag);
2144 failed = true;
2146 if (frame->homeContext.utag != tagHFrame && frame->homeContext.utag != tagNil) {
2147 postfl("Frame %p homeContext tag wrong %p\n", frame, frame->homeContext.utag);
2148 failed = true;
2151 if (!IsPtr(&frame->ip)) {
2152 postfl("Frame %p ip tag wrong %p\n", frame, GetTag(&frame->ip));
2153 failed = true;
2155 return failed;
2158 void DumpFrame(PyrFrame *frame)
2160 char str[256];
2161 int i, numargs;
2162 PyrMethod *meth;
2163 PyrMethodRaw *methraw;
2165 if (FrameSanity(frame, "DumpFrame")) {
2166 post("FRAME CORRUPTED\n");
2167 return;
2169 slotOneWord(&frame->method, str);
2170 //slotString(&frame->method, str);
2172 meth = slotRawMethod(&frame->method);
2173 methraw = METHRAW(meth);
2174 if (methraw->numtemps) {
2175 post("\t%s %p\n", str, frame);
2176 numargs = methraw->numargs + methraw->varargs;
2177 for (i=0; i<methraw->numtemps; ++i) {
2178 slotOneWord(frame->vars + i, str);
2179 //slotString(frame->vars + i, str);
2180 if (i < numargs) {
2181 post("\t\targ %s = %s\n", slotRawSymbolArray(&meth->argNames)->symbols[i]->name, str);
2182 } else {
2183 post("\t\tvar %s = %s\n", slotRawSymbolArray(&meth->varNames)->symbols[i - numargs]->name, str);
2186 } else {
2187 post("\t%s (no arguments or variables)\n", str);
2191 void dumpByteCodes(PyrBlock *theBlock);
2193 void DumpDetailedFrame(PyrFrame *frame);
2194 void DumpDetailedFrame(PyrFrame *frame)
2196 char mstr[256];
2197 char str[256];
2198 int i, numargs;
2199 PyrMethod *meth;
2200 PyrMethodRaw *methraw;
2202 if (FrameSanity(frame, "DumpDetailedFrame")) {
2203 post("FRAME CORRUPTED\n");
2204 return;
2206 slotOneWord(&frame->method, mstr);
2207 //slotString(&frame->method, str);
2209 meth = slotRawMethod(&frame->method);
2210 methraw = METHRAW(meth);
2212 if (methraw->numtemps) {
2213 post("\t%s\n", mstr);
2214 numargs = methraw->numargs + methraw->varargs;
2215 for (i=0; i<methraw->numtemps; ++i) {
2216 slotOneWord(frame->vars + i, str);
2217 //slotString(frame->vars + i, str);
2218 if (i < numargs) {
2219 post("\t\targ %s = %s\n", slotRawSymbolArray(&meth->argNames)->symbols[i]->name, str);
2220 } else {
2221 post("\t\tvar %s = %s\n", slotRawSymbolArray(&meth->varNames)->symbols[i - numargs]->name, str);
2224 } else {
2225 post("\t%s (no arguments or variables)\n", mstr);
2228 post("\t....%s details:\n", mstr);
2229 post("\t\tneedsHeapContext = %d\n", methraw->needsHeapContext);
2230 post("\t\tnumtemps = %d\n", methraw->numtemps);
2231 post("\t\tpopSize = %d\n", methraw->popSize);
2233 slotString(&frame->method, str); post("\t\tmethod = %s\n", str);
2234 slotString(&frame->caller, str); post("\t\tcaller = %s\n", str);
2235 slotString(&frame->context, str); post("\t\tcontext = %s\n", str);
2236 slotString(&frame->homeContext, str); post("\t\thomeCtx = %s\n", str);
2237 slotString(&frame->ip, str); post("\t\tip = %s\n", str);
2239 if (IsPtr(&frame->ip)) {
2240 post("ipoffset = %d\n", (char*)slotRawPtr(&frame->ip) - (char*)slotRawInt8Array(&meth->code)->b);
2241 dumpByteCodes(meth);
2247 bool respondsTo(PyrSlot *slot, PyrSymbol *selector)
2249 PyrClass *classobj;
2250 PyrMethod *meth;
2251 int index;
2253 classobj = classOfSlot(slot);
2255 index = slotRawInt(&classobj->classIndex) + selector->u.index;
2256 meth = gRowTable[index];
2257 return slotRawSymbol(&meth->name) == selector;
2260 PyrMethod* methodLookup(PyrSlot *slot, PyrSymbol *selector);
2261 PyrMethod* methodLookup(PyrSlot *slot, PyrSymbol *selector)
2263 PyrClass *classobj;
2264 PyrMethod *meth;
2265 int index;
2267 classobj = classOfSlot(slot);
2269 index = slotRawInt(&classobj->classIndex) + selector->u.index;
2270 meth = gRowTable[index];
2271 return meth;
2275 bool isSubclassOf(PyrClass *classobj, PyrClass *testclass)
2277 while (classobj) {
2278 if (classobj == testclass) {
2279 return true;
2281 classobj = slotRawSymbol(&classobj->superclass)->u.classobj;
2283 return false;
2286 /*bool isKindOf(PyrObjectHdr *obj, PyrClass *testclass)
2288 int objClassIndex = slotRawInt(&obj->classptr->classIndex);
2289 return objClassIndex >= slotRawInt(&testclass->classIndex) && objClassIndex <= slotRawInt(&testclass->maxSubclassIndex);
2292 bool objAddIndexedSlot(PyrObject *obj, PyrSlot *slot)
2294 if (obj->size < ARRAYMAXINDEXSIZE(obj)) {
2295 slotCopy(&obj->slots[obj->size++], slot);
2296 return true;
2297 } else {
2298 return false;
2302 bool objAddIndexedSymbol(PyrSymbolArray *obj, PyrSymbol *symbol)
2304 if (obj->size < MAXINDEXSIZE((PyrObject*)obj)) {
2305 obj->symbols[obj->size++] = symbol;
2306 return true;
2307 } else {
2308 return false;
2312 bool objAddIndexedObject(PyrObject *obj, PyrObject *obj2)
2314 if (obj->size < ARRAYMAXINDEXSIZE(obj)) {
2315 SetObject(obj->slots + obj->size, obj2);
2316 obj->size++;
2317 return true;
2318 } else {
2319 return false;
2323 void fillSlots(PyrSlot* slot, int size, PyrSlot* fillslot)
2325 for (int i = 0; i != size; ++i)
2326 slotCopy(&slot[i], fillslot);
2329 void nilSlots(PyrSlot* slot, int size)
2331 fillSlots(slot, size, &o_nil);
2334 void zeroSlots(PyrSlot* slot, int size)
2336 PyrSlot zero;
2337 SetTagRaw(&zero, 0);
2338 SetRaw(&zero, 0.0);
2339 fillSlots(slot, size, &zero);
2342 PyrObject* newPyrObject(class PyrGC *gc, size_t inNumBytes, int inFlags, int inFormat, bool inCollect)
2344 return gc->New(inNumBytes, inFlags, inFormat, inCollect);
2347 PyrObject* newPyrArray(class PyrGC *gc, int size, int flags, bool collect)
2349 PyrObject* array;
2351 int numbytes = size * sizeof(PyrSlot);
2352 if (!gc)
2353 array = PyrGC::NewPermanent(numbytes, flags, obj_slot);
2354 else
2355 array = gc->New(numbytes, flags, obj_slot, collect);
2356 array->classptr = class_array;
2357 return array;
2360 PyrSymbolArray* newPyrSymbolArray(class PyrGC *gc, int size, int flags, bool collect)
2362 PyrSymbolArray* array;
2364 int numbytes = size * sizeof(PyrSymbol*);
2365 if (!gc) array = (PyrSymbolArray*)PyrGC::NewPermanent(numbytes, flags, obj_symbol);
2366 else array = (PyrSymbolArray*)gc->New(numbytes, flags, obj_symbol, collect);
2367 array->classptr = class_symbolarray;
2368 return array;
2371 PyrInt8Array* newPyrInt8Array(class PyrGC *gc, int size, int flags, bool collect)
2373 PyrInt8Array* array;
2375 if (!gc) array = (PyrInt8Array*)PyrGC::NewPermanent(size, flags, obj_int8);
2376 else array = (PyrInt8Array*)gc->New(size, flags, obj_int8, collect);
2377 array->classptr = class_int8array;
2378 return array;
2381 PyrInt32Array* newPyrInt32Array(class PyrGC *gc, int size, int flags, bool collect)
2383 PyrInt32Array* array;
2384 int numbytes = size * sizeof(int32);
2385 if (!gc) array = (PyrInt32Array*)PyrGC::NewPermanent(numbytes, flags, obj_int32);
2386 else array = (PyrInt32Array*)gc->New(numbytes, flags, obj_int32, collect);
2387 array->classptr = class_int32array;
2388 return array;
2391 PyrDoubleArray* newPyrDoubleArray(class PyrGC *gc, int size, int flags, bool collect)
2393 PyrDoubleArray* array;
2395 int numbytes = size * sizeof(double);
2396 if (!gc) array = (PyrDoubleArray*)PyrGC::NewPermanent(numbytes, flags, obj_double);
2397 else array = (PyrDoubleArray*)gc->New(size, flags, obj_double, collect);
2398 array->classptr = class_doublearray;
2399 return array;
2402 PyrString* newPyrString(class PyrGC *gc, const char *s, int flags, bool collect)
2404 PyrString* string;
2405 int length = strlen(s);
2407 if (!gc) string = (PyrString*)PyrGC::NewPermanent(length, flags, obj_char);
2408 else string = (PyrString*)gc->New(length, flags, obj_char, collect);
2409 string->classptr = class_string;
2410 string->size = length;
2411 memcpy(string->s, s, length);
2412 return string;
2415 PyrString* newPyrStringN(class PyrGC *gc, int length, int flags, bool collect)
2417 PyrString* string;
2419 if (!gc) string = (PyrString*)PyrGC::NewPermanent(length, flags, obj_char);
2420 else string = (PyrString*)gc->New(length, flags, obj_char, collect);
2421 string->classptr = class_string;
2422 string->size = length; // filled with garbage!
2423 return string;
2426 PyrBlock* newPyrBlock(int flags)
2428 PyrBlock* block;
2429 PyrMethodRaw *methraw;
2432 int32 numbytes = sizeof(PyrBlock) - sizeof(PyrObjectHdr);
2433 int32 numSlots = numbytes / sizeof(PyrSlot);
2435 if (!compilingCmdLine) block = (PyrBlock*)PyrGC::NewPermanent(numbytes, flags, obj_notindexed);
2436 else block = (PyrBlock*)gMainVMGlobals->gc->New(numbytes, flags, obj_notindexed, false);
2437 block->classptr = class_fundef;
2438 block->size = numSlots;
2440 // clear out raw area
2441 methraw = METHRAW(block);
2442 methraw->specialIndex = 0;
2443 methraw->methType = methBlock;
2444 methraw->needsHeapContext = 0;
2445 methraw->frameSize = 0;
2446 methraw->varargs = 0;
2447 methraw->numargs = 0;
2448 methraw->numvars = 0;
2449 methraw->numtemps = 0;
2450 methraw->popSize = 0;
2452 nilSlots(&block->rawData1, numSlots);
2453 return block;
2456 SC_DLLEXPORT_C struct VMGlobals* scGlobals()
2458 return gMainVMGlobals;
2461 PyrMethod* initPyrMethod(PyrMethod* method)
2464 int32 numbytes = sizeof(PyrMethod) - sizeof(PyrObjectHdr);
2465 int32 numSlots = numbytes / sizeof(PyrSlot);
2467 method->classptr = class_method;
2468 method->size = 0;
2469 method->size = numSlots;
2470 SetFloat(&method->rawData1, 0.0);
2471 SetFloat(&method->rawData2, 0.0);
2472 nilSlots(&method->code, numSlots-2);
2473 //slotCopy(&method->byteMeter, &o_zero);
2474 //slotCopy(&method->callMeter, &o_zero);
2475 //post("<- newPyrMethod %p %p\n", method, methraw);
2476 return method;
2479 PyrMethod* newPyrMethod()
2481 int32 numbytes = sizeof(PyrMethod) - sizeof(PyrObjectHdr);
2482 PyrMethod* method = (PyrMethod*)PyrGC::NewPermanent(numbytes, obj_permanent | obj_immutable, obj_notindexed);
2483 return initPyrMethod(method);
2486 void freePyrSlot(PyrSlot *slot)
2488 if (IsObj(slot)) {
2489 PyrObject *obj = slotRawObject(slot);
2491 if (obj && obj->IsPermanent()) {
2492 // don't deallocate these
2493 if (obj != slotRawObject(&o_emptyarray) && obj != slotRawObject(&o_onenilarray) && obj != slotRawObject(&o_argnamethis))
2494 pyr_pool_runtime->Free((void*)obj);
2496 SetNil(slot);
2501 void freePyrObject(PyrObject *obj)
2503 if (obj->IsPermanent()) {
2504 pyr_pool_runtime->Free((void*)obj);
2508 int getIndexedInt(PyrObject *obj, int index, int *value)
2510 PyrSlot *slot;
2511 int err = errNone;
2512 if (index < 0 || index >= obj->size) return errIndexOutOfRange;
2513 switch (obj->obj_format) {
2514 case obj_slot :
2515 slot = obj->slots + index;
2516 if (IsFloat(slot)) {
2517 *value = (int)slotRawFloat(slot);
2518 } else if (IsInt(slot)) {
2519 *value = slotRawInt(slot);
2520 } else {
2521 err = errWrongType;
2523 break;
2524 case obj_double :
2525 *value = (int)((double*)(obj->slots))[index];
2526 break;
2527 case obj_float :
2528 *value = (int)((float*)(obj->slots))[index];
2529 break;
2530 case obj_int32 :
2531 *value = ((int32*)(obj->slots))[index];
2532 break;
2533 case obj_int16 :
2534 *value = ((int16*)(obj->slots))[index];
2535 break;
2536 case obj_int8 :
2537 *value = ((int8*)(obj->slots))[index];
2538 break;
2539 default :
2540 err = errWrongType;
2542 return err;
2545 int getIndexedFloat(PyrObject *obj, int index, float *value)
2547 PyrSlot *slot;
2548 int err = errNone;
2549 if (index < 0 || index >= obj->size) return errIndexOutOfRange;
2550 switch (obj->obj_format) {
2551 case obj_slot :
2552 slot = obj->slots + index;
2553 if (IsFloat(slot)) {
2554 *value = slotRawFloat(slot);
2555 } else if (IsInt(slot)) {
2556 *value = slotRawInt(slot);
2557 } else {
2558 err = errWrongType;
2560 break;
2561 case obj_double :
2562 *value = ((double*)(obj->slots))[index];
2563 break;
2564 case obj_float :
2565 *value = ((float*)(obj->slots))[index];
2566 break;
2567 case obj_int32 :
2568 *value = ((int32*)(obj->slots))[index];
2569 break;
2570 case obj_int16 :
2571 *value = ((int16*)(obj->slots))[index];
2572 break;
2573 case obj_int8 :
2574 *value = ((int8*)(obj->slots))[index];
2575 break;
2576 default :
2577 err = errWrongType;
2579 return err;
2582 int getIndexedDouble(PyrObject *obj, int index, double *value)
2584 PyrSlot *slot;
2585 int err = errNone;
2586 if (index < 0 || index >= obj->size) return errIndexOutOfRange;
2587 switch (obj->obj_format) {
2588 case obj_slot :
2589 slot = obj->slots + index;
2590 if (IsFloat(slot)) {
2591 *value = slotRawFloat(slot);
2592 } else if (IsInt(slot)) {
2593 *value = slotRawInt(slot);
2594 } else {
2595 err = errWrongType;
2597 break;
2598 case obj_double :
2599 *value = ((double*)(obj->slots))[index];
2600 break;
2601 case obj_float :
2602 *value = ((float*)(obj->slots))[index];
2603 break;
2604 case obj_int32 :
2605 *value = ((int32*)(obj->slots))[index];
2606 break;
2607 case obj_int16 :
2608 *value = ((int16*)(obj->slots))[index];
2609 break;
2610 case obj_int8 :
2611 *value = ((int8*)(obj->slots))[index];
2612 break;
2613 default :
2614 err = errWrongType;
2616 return err;
2620 void getIndexedSlot(PyrObject *obj, PyrSlot *a, int index)
2622 // postfl("getIndexedSlot %s %X %d\n", slotRawSymbol(&obj->classptr->name)->name,
2623 // obj, index);
2624 switch (obj->obj_format) {
2625 case obj_slot :
2626 slotCopy(a, &obj->slots[index]);
2627 break;
2628 case obj_double :
2629 SetFloat(a, ((double*)(obj->slots))[index]);
2630 break;
2631 case obj_float :
2632 SetFloat(a, ((float*)(obj->slots))[index]);
2633 break;
2634 case obj_int32 :
2635 SetInt(a, ((int32*)(obj->slots))[index]);
2636 break;
2637 case obj_int16 :
2638 SetInt(a, ((int16*)(obj->slots))[index]);
2639 break;
2640 case obj_int8 :
2641 SetInt(a, ((int8*)(obj->slots))[index]);
2642 break;
2643 case obj_symbol :
2644 SetSymbol(a, (PyrSymbol*)((int**)(obj->slots))[index]);
2645 break;
2646 case obj_char :
2647 SetChar(a, ((unsigned char*)(obj->slots))[index]);
2648 break;
2652 int putIndexedSlot(VMGlobals *g, PyrObject *obj, PyrSlot *c, int index)
2654 PyrSlot *slot;
2655 switch (obj->obj_format) {
2656 case obj_slot :
2657 if (obj->IsImmutable()) return errImmutableObject;
2658 slot = obj->slots + index;
2659 slotCopy(slot, c);
2660 g->gc->GCWrite(obj, slot);
2661 break;
2662 case obj_double :
2663 if (NotFloat(c)) {
2664 if (NotInt(c)) return errWrongType;
2665 else {
2666 ((double*)(obj->slots))[index] = slotRawInt(c);
2668 } else
2669 ((double*)(obj->slots))[index] = slotRawFloat(c);
2670 break;
2671 case obj_float :
2672 if (NotFloat(c)) {
2673 if (NotInt(c)) return errWrongType;
2674 else {
2675 ((float*)(obj->slots))[index] = slotRawInt(c);
2677 } else
2678 ((float*)(obj->slots))[index] = slotRawFloat(c);
2679 break;
2680 case obj_int32 :
2681 if (NotInt(c)) return errWrongType;
2682 ((int32*)(obj->slots))[index] = slotRawInt(c);
2683 break;
2684 case obj_int16 :
2685 if (NotInt(c)) return errWrongType;
2686 ((int16*)(obj->slots))[index] = slotRawInt(c);
2687 break;
2688 case obj_int8 :
2689 if (NotInt(c)) return errWrongType;
2690 ((int8*)(obj->slots))[index] = slotRawInt(c);
2691 break;
2692 case obj_symbol :
2693 if (NotSym(c)) return errWrongType;
2694 ((PyrSymbol**)(obj->slots))[index] = slotRawSymbol(c);
2695 break;
2696 case obj_char :
2697 if (NotChar(c)) return errWrongType;
2698 ((unsigned char*)(obj->slots))[index] = slotRawChar(c);
2699 break;
2701 return errNone;
2704 int putIndexedFloat(PyrObject *obj, double val, int index)
2706 PyrSlot *slot;
2707 switch (obj->obj_format) {
2708 case obj_slot :
2709 if (obj->IsImmutable()) return errImmutableObject;
2710 slot = obj->slots + index;
2711 SetFloat(slot, val);
2712 break;
2713 case obj_double :
2714 ((double*)(obj->slots))[index] = val;
2715 break;
2716 case obj_float :
2717 ((float*)(obj->slots))[index] = (float)val;
2718 break;
2719 case obj_int32 :
2720 ((int32*)(obj->slots))[index] = (int32)val;
2721 break;
2722 case obj_int16 :
2723 ((int16*)(obj->slots))[index] = (int16)val;
2724 break;
2725 case obj_int8 :
2726 ((int8*)(obj->slots))[index] = (int8)val;
2727 break;
2729 return errNone;
2732 static int hashPtr(void* ptr)
2734 int32 hashed_part = int32((size_t)ptr&0xffffffff);
2735 return Hash(hashed_part);
2738 int calcHash(PyrSlot *a);
2739 int calcHash(PyrSlot *a)
2741 int hash;
2742 switch (GetTag(a)) {
2743 case tagObj : hash = hashPtr(slotRawObject(a)); break;
2744 case tagInt : hash = Hash(slotRawInt(a)); break;
2745 case tagChar : hash = Hash(slotRawChar(a) & 255); break;
2746 case tagSym : hash = slotRawSymbol(a)->hash; break;
2747 case tagNil : hash = 0xA5A5A5A5; break;
2748 case tagFalse : hash = 0x55AA55AA; break;
2749 case tagTrue : hash = 0x69696969; break;
2750 case tagPtr : hash = hashPtr(slotRawPtr(a)); break;
2751 default :
2752 // hash for a double
2753 union {
2754 int32 i[2];
2755 double d;
2756 } u;
2757 u.d = slotRawFloat(a);
2758 hash = Hash(u.i[0] + Hash(u.i[1]));
2760 return hash;
2763 void InstallFinalizer(VMGlobals* g, PyrObject *inObj, int slotIndex, ObjFuncPtr inFunc)
2765 PyrObject *finalizer = g->gc->NewFinalizer(inFunc, inObj, false);
2766 SetObject(inObj->slots + slotIndex, finalizer);
2767 g->gc->GCWrite(inObj, finalizer);