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
26 #include "PyrMessage.h"
27 #include "PyrInterpreter.h"
28 #include "PyrSymbolTable.h"
29 #include "PyrObjectProto.h"
30 #include "PyrKernelProto.h"
32 #include "InitAlloc.h"
34 #include "SC_Constants.h"
35 #include "SC_Alloca.h"
39 PyrClass
*gClassList
= NULL
;
40 int gNumSelectors
= 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
;
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
;
84 PyrSymbol
*s_identityset
;
85 PyrSymbol
*s_dictionary
;
86 PyrSymbol
*s_identitydictionary
;
87 PyrSymbol
*s_linkedlist
;
88 PyrSymbol
*s_sortedlist
;
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
;
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
;
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
;
112 PyrSymbol
*s_func
, *s_absfunc
;
114 PyrSymbol
*s_process
;
117 PyrSymbol
*s_routine
;
119 PyrSymbol
*s_prstart
;
120 PyrSymbol
*s_interpreter
;
121 PyrSymbol
*s_finalizer
;
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;
132 PyrSymbol
*s_startup
;
133 PyrSymbol
*s_docmdline
;
135 PyrSymbol
*s_control
;
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
;
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");
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");
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);
289 SetSymbol(&o_none
, s_none
);
297 SetFloat(&o_inf
, INFINITY
);
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
;
366 PyrSymbolArray
*symarray
;
371 c = className->name[0];
372 if (!(c >= 'A' && c <= 'Z')) Debugger();
375 // lifetime: kill upon recompiling library
376 classobj
= (PyrClass
*)pyr_pool_runtime
->Alloc(sizeof(PyrClass
));
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
;
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
409 if (numInstMethods
) {
410 array
= newPyrArray(NULL
, numInstMethods
, obj_permanent
| obj_immutable
, false);
411 SetObject(&classobj
->methods
, array
);
413 SetNil(&classobj
->methods
);
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
);
424 SetNil(&classobj
->instVarNames
);
425 SetNil(&classobj
->iprototype
);
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
);
436 SetNil(&classobj
->classVarNames
);
437 SetNil(&classobj
->cprototype
);
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
);
448 SetNil(&classobj
->constNames
);
449 SetNil(&classobj
->constValues
);
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
;
470 void reallocClassObj(PyrClass
* classobj
,
471 int numInstVars
, int numClassVars
, int numConsts
, int numMethods
,
472 int instFormat
, int instFlags
)
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
);
488 array
= newPyrArray(NULL
, numMethods
, obj_permanent
| obj_immutable
, false);
489 SetObject(&classobj
->methods
, array
);
491 SetNil(&classobj
->methods
);
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
);
503 SetNil(&classobj
->instVarNames
);
504 SetNil(&classobj
->iprototype
);
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
);
517 SetNil(&classobj
->classVarNames
);
518 SetNil(&classobj
->cprototype
);
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
);
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
)
554 if (IsNil(&classobj
->instVarNames
))
557 res
= slotRawObject(&classobj
->instVarNames
)->size
;
561 int numClassVars(PyrClass
* classobj
)
564 if (IsNil(&classobj
->classVarNames
)) res
= 0;
565 else res
= slotRawObject(&classobj
->classVarNames
)->size
;
570 void objAddIndexedSlotGrow(PyrSlot
*arraySlot
, PyrSlot
*addSlot
);
571 void objAddIndexedSlotGrow(PyrSlot
*arraySlot
, PyrSlot
*addSlot
)
574 if (IsNil(arraySlot
)) {
575 PyrObject
*newobj
= (PyrObject
*)newPyrArray(NULL
, 1, obj_permanent
| obj_immutable
, false);
576 SetObject(arraySlot
, newobj
);
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
);
590 slotCopy(&obj
->slots
[obj
->size
++], addSlot
);
593 void addMethod(PyrClass
*classobj
, PyrMethod
*method
)
596 SetObject(&slot
, method
);
597 objAddIndexedSlotGrow(&classobj
->methods
, &slot
);
602 PyrMethod
* classFindDirectMethod(PyrClass
* classobj
, PyrSymbol
*name
)
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
;
618 int numSuperInstVars(PyrClass
*superclassobj
)
620 int superinstvars
= 0;
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
;
634 if (NotNil(&classobj
->instVarNames
)) {
635 ivnames
= slotRawSymbolArray(&classobj
->instVarNames
);
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;
651 int instVarOffset(const char *classname
, const char *instvarname
)
653 PyrSymbol
*instvarsymbol
, *classsymbol
;
658 classsymbol
= getsym(classname
);
659 instvarsymbol
= getsym(instvarname
);
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;
670 int classVarOffset(const char *classname
, const char *classvarname
, PyrClass
** classobj
)
672 PyrSymbol
*classvarsymbol
, *classsymbol
;
676 classsymbol
= getsym(classname
);
677 classvarsymbol
= getsym(classvarname
);
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;
688 bool classFindClassVar(PyrClass
** classobj
, PyrSymbol
*name
, int *index
)
690 PyrSymbolArray
*cvnames
;
694 PyrClass
* localclassobj
= *classobj
;
695 // if this is a Metaclass then we need to search its normal Class for
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
);
705 for (i
=0; i
<cvnames
->size
; ++i
) {
706 cvname
= cvnames
->symbols
[i
];
707 if (cvname
== name
) {
708 *classobj
= localclassobj
;
715 if (IsSym(&localclassobj
->superclass
)) {
716 localclassobj
= slotRawSymbol(&localclassobj
->superclass
)->u
.classobj
;
718 localclassobj
= NULL
;
724 bool classFindConst(PyrClass
** classobj
, PyrSymbol
*name
, int *index
)
726 PyrSymbolArray
*knames
;
730 PyrClass
* localclassobj
= *classobj
;
731 // if this is a Metaclass then we need to search its normal Class for
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
);
741 for (i
=0; i
<knames
->size
; ++i
) {
742 kname
= knames
->symbols
[i
];
744 *classobj
= localclassobj
;
751 if (IsSym(&localclassobj
->superclass
)) {
752 localclassobj
= slotRawSymbol(&localclassobj
->superclass
)->u
.classobj
;
754 localclassobj
= NULL
;
762 bool operator()(PyrClass
* lhs
, PyrClass
* rhs
) const
764 return strcmp(slotRawSymbol(&lhs
->name
)->name
, slotRawSymbol(&rhs
->name
)->name
) < 0;
770 class pyr_pool_compile_allocator
773 typedef std::size_t size_type
;
774 typedef std::ptrdiff_t difference_type
;
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)
790 pyr_pool_compile_allocator(pyr_pool_compile_allocator
<U
> const &)
793 pointer
address(reference x
) const
798 const_pointer
address(const_reference x
) const
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
)
818 void destroy(pointer p
)
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
;
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
;
845 PyrClass
* lastClass
= sortedClasses
;
846 for (; it
!= classSet
.end(); ++it
) {
847 PyrClass
* current
= *it
;
848 SetObject(&lastClass
->nextclass
, (PyrObject
*)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
870 //postfl("count subclasses\n");
871 PyrClass
*classobj
= gClassList
;
873 PyrClass
* superclassobj
= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
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
;
885 numSubclasses
= slotRawInt(&classobj
->subclasses
);
886 //postfl(" %s %d\n", slotRawSymbol(&classobj->name)->name, numSubclasses);
888 SetObject(&classobj
->subclasses
, (PyrObject
*)newPyrArray(NULL
, numSubclasses
, obj_permanent
| obj_immutable
, false));
889 slotRawObject(&classobj
->subclasses
)->size
= 0;
891 SetNil(&classobj
->subclasses
);
893 classobj
= slotRawClass(&classobj
->nextclass
);
895 // fill in subclass arrays
896 //postfl("fill in subclass arrays\n");
897 classobj
= gClassList
;
899 //postfl(" %s\n", slotRawSymbol(&classobj->name)->name);
900 PyrClass
*superclassobj
= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
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
)
917 if (!classobj
) return;
919 SetInt(&classobj
->classIndex
, gNumClasses
);
922 if (IsObj(&classobj
->methods
)) {
923 PyrObject
* methods
= slotRawObject(&classobj
->methods
);
924 numMethods
= methods
->size
;
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
;
945 classobjB
= slotRawClass(&classobjA
->nextclass
);;
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
) {
964 void postClassTree(PyrClass
*classobj
, int level
)
966 PyrObject
*subclasses
;
969 //post("%4d ", slotRawInt(&classobj->classIndex));
971 post("%s\n", slotRawSymbol(&classobj
->name
)->name
);
973 if (classobj
== class_class
) {
975 post(" [.. all metaclasses ..]\n");
977 if (IsNil(&classobj
->subclasses
))
978 return; // FIXME: can we initialize subclasses with a NULL pointer?
979 subclasses
= slotRawObject(&classobj
->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?
992 for (i
=0; i
<subclasses
->size
; ++i
) {
993 PyrClass
*subclassobj
= slotRawClass(&subclasses
->slots
[i
]);
994 post(" %s", slotRawSymbol(&subclassobj
->name
)->name
);
1000 for (i
=0; i
<subclasses
->size
; ++i
) {
1001 postClassTree(slotRawClass(&subclasses
->slots
[i
]), level
+1);
1011 void setSelectorFlags()
1015 PyrClass
* classobj
= gClassList
;
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
);
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.
1046 PyrSymbol
*selector
;
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
;
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
;
1072 #define CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME 0
1073 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1074 double elapsedTime();
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
)
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
)
1137 for (int j
=0; j
<numClasses
; ++j
) {
1138 for (int i
=begin
; i
<end
; ++i
) {
1139 PyrMethod
* method
= bigTable
[j
* numSelectors
+ i
];
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;
1151 //postfl(" %8s %3d %3d %3d %3d\n", slotRawSymbol(&classobj->name)->name, i, j,
1152 // chunkSize, slotRawInt(&classobj->classIndex));
1154 //if (chunkSize > sels[i].largestChunk) {
1155 // sels[i].largestChunk = chunkSize;
1156 // sels[i].chunkOffset = chunkOffset;
1165 void buildBigMethodMatrix()
1167 PyrMethod
**bigTable
, **row
;
1168 PyrClass
*classobj
, **classes
;
1170 int popSum
, widthSum
;
1171 int rowOffset
, freeIndex
;
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();
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
));
1188 if (helperThreadCount
)
1189 compileThreadPool
.schedule(boost::bind(&prepareColumnTable
, sels
, numSelectors
));
1191 prepareColumnTable(sels
, numSelectors
);
1193 bigTable
= (PyrMethod
**)pyr_pool_compile
->Alloc(bigTableSize
* sizeof(PyrMethod
*));
1195 classes
= (PyrClass
**)pyr_pool_compile
->Alloc(numClasses
* sizeof(PyrClass
*));
1198 classobj
= gClassList
;
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
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();
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);
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
);
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");
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
) {
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
);
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
*)));
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
)
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
];
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)
1347 myrow
[selectorIndex
] = method
;
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),
1363 fillClassRowSubClasses(subclasses
, subclassesPerThread
* helperThreadCount
, numSubclasses
, bigTable
, rCount
);
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
)
1390 for (i
=0; i
<slotRawSymbolArray(&func
->argNames
)->size
; ++i
) {
1391 if (slotRawSymbolArray(&func
->argNames
)->symbols
[i
] == name
) {
1399 bool funcFindVar(PyrBlock
* func
, PyrSymbol
*name
, int *index
)
1402 for (i
=0; i
<slotRawSymbolArray(&func
->varNames
)->size
; ++i
) {
1403 if (slotRawSymbolArray(&func
->varNames
)->symbols
[i
] == name
) {
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
;
1422 //postfl("makeIntrinsicClass '%s'\n", className->name);
1423 if (superClassName
) {
1424 superClass
= superClassName
->u
.classobj
;
1426 error("Can't find superclass '%s' of '%s'\n", superClassName
->name
,
1430 metaSuperClassName
= getmetasym(superClassName
->name
);
1431 metaSuperClass
= metaSuperClassName
->u
.classobj
;
1432 superInstVars
= numSuperInstVars(superClass
);
1434 // else it must be Object and so has no superclass
1435 metaSuperClassName
= NULL
;
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
;
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
);
1495 PyrClass
*class_object_meta
;
1496 PyrMethodRaw
*methraw
;
1498 // BOOTSTRAP THE OBJECT HIERARCHY
1502 gNullMethod
= newPyrMethod();
1503 SetSymbol(&gNullMethod
->name
, (PyrSymbol
*)NULL
);
1504 methraw
= METHRAW(gNullMethod
);
1505 methraw
->methType
= methNormal
;
1507 // build intrinsic classes
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
) {
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
);
1793 newobj
->size
= size
;
1794 if (format
== obj_slot
) {
1795 nilSlots(newobj
->slots
, size
);
1797 memset(newobj
->slots
, format
== obj_char
? ' ' : 0, size
* gFormatElemSize
[format
]);
1803 if (IsObj(&classobj
->iprototype
)) {
1804 proto
= slotRawObject(&classobj
->iprototype
);
1806 numbytes
= size
* sizeof(PyrSlot
);
1807 newobj
= gc
->New(numbytes
, flags
, format
, collect
);
1808 newobj
->size
= size
;
1810 memcpy(newobj
->slots
, proto
->slots
, numbytes
);
1814 newobj
= gc
->New(numbytes
, flags
, format
, collect
);
1818 newobj
->classptr
= classobj
;
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
];
1834 if (IsObj(&classobj
->iprototype
)) {
1835 proto
= slotRawObject(&classobj
->iprototype
);
1837 numbytes
= size
* sizeof(PyrSlot
);
1843 newobj
= gc
->New(numbytes
, flags
, format
, collect
);
1844 newobj
->size
= size
;
1845 newobj
->classptr
= classobj
;
1850 PyrObject
* copyObject(class PyrGC
*gc
, PyrObject
*inobj
, bool collect
)
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
);
1868 PyrObject
* copyObjectRange(class PyrGC
*gc
, PyrObject
*inobj
, int start
, int end
, bool collect
)
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
;
1887 memcpy(newobj
->slots
, (char*)(inobj
->slots
) + start
* elemsize
, length
* elemsize
);
1892 void dumpObject(PyrObject
*obj
)
1899 postfl("NULL object pointer\n");
1902 classobj
= obj
->classptr
;
1903 if (isKindOf(obj
, class_class
)) {
1904 post("class %s (%p) {\n", slotRawSymbol(&((PyrClass
*)obj
)->name
)->name
, obj
);
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
);
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
);
1921 post(" indexed slots [%d]\n", obj
->size
);
1922 maxsize
= sc_min(32, obj
->size
);
1923 switch (obj
->obj_format
) {
1925 for (i
=0; i
<maxsize
; ++i
) {
1926 slotString(obj
->slots
+ i
, str
);
1927 post(" %3d : %s\n", i
, str
);
1931 for (i
=0; i
<maxsize
; ++i
) {
1932 post(" %3d : %f\n", i
, slotRawFloat(&obj
->slots
[i
]));
1936 for (i
=0; i
<maxsize
; ++i
) {
1938 val
= ((float*)(obj
->slots
))[i
];
1939 post(" %3d : %g\n", i
, val
);
1943 for (i
=0; i
<maxsize
; ++i
) {
1945 val
= ((int32
*)(obj
->slots
))[i
];
1946 post(" %3d : %d\n", i
, val
);
1950 for (i
=0; i
<maxsize
; ++i
) {
1952 val
= ((int16
*)(obj
->slots
))[i
];
1953 post(" %3d : %d\n", i
, val
);
1957 for (i
=0; i
<maxsize
; ++i
) {
1959 val
= ((int8
*)(obj
->slots
))[i
];
1960 post(" %3d : %4d %4u 0x%02X\n", i
, val
, val
&255, val
&255);
1964 for (i
=0; i
<maxsize
; ++i
) {
1966 val
= ((char*)(obj
->slots
))[i
];
1967 post(" %3d : %c\n", i
, val
);
1971 for (i
=0; i
<maxsize
; ++i
) {
1973 sym
= ((PyrSymbol
**)(obj
->slots
))[i
];
1974 post(" %3d : '%s'\n", i
, sym
->name
);
1978 post("unknown obj_format %X\n", obj
->obj_format
);
1980 if (obj
->size
> maxsize
) {
1987 void dumpBadObject(PyrObject
*obj
)
1994 postfl("NULL object pointer\n");
1997 classobj
= obj
->classptr
;
1998 if (isKindOf(obj
, class_class
)) {
1999 postfl("class %s (%p) {\n", slotRawSymbol(&((PyrClass
*)obj
)->name
)->name
, obj
);
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
);
2014 postfl(" indexed slots [%d]\n", obj
->size
);
2015 maxsize
= obj
->size
;
2016 maxsize
= sc_min(32, maxsize
);
2017 switch (obj
->obj_format
) {
2019 for (i
=0; i
<maxsize
; ++i
) {
2020 slotString(obj
->slots
+ i
, str
);
2021 postfl(" %3d : %s\n", i
, str
);
2025 for (i
=0; i
<maxsize
; ++i
) {
2026 postfl(" %3d : %f\n", i
, slotRawFloat(&obj
->slots
[i
]));
2030 for (i
=0; i
<maxsize
; ++i
) {
2032 val
= ((float*)(obj
->slots
))[i
];
2033 postfl(" %3d : %g\n", i
, val
);
2037 for (i
=0; i
<maxsize
; ++i
) {
2039 val
= ((int32
*)(obj
->slots
))[i
];
2040 postfl(" %3d : %d\n", i
, val
);
2044 for (i
=0; i
<maxsize
; ++i
) {
2046 val
= ((int16
*)(obj
->slots
))[i
];
2047 postfl(" %3d : %d\n", i
, val
);
2051 for (i
=0; i
<maxsize
; ++i
) {
2053 val
= ((int8
*)(obj
->slots
))[i
];
2054 postfl(" %3d : %4d %4u 0x%02X\n", i
, val
, val
&255, val
&255);
2058 for (i
=0; i
<maxsize
; ++i
) {
2060 val
= ((char*)(obj
->slots
))[i
];
2061 postfl(" %3d : %c\n", i
, val
);
2065 for (i
=0; i
<maxsize
; ++i
) {
2067 sym
= ((PyrSymbol
**)(obj
->slots
))[i
];
2068 post(" %3d : '%s'\n", i
, sym
->name
);
2072 postfl("unknown obj_format %X\n", obj
->obj_format
);
2074 if (obj
->size
> maxsize
) {
2081 void dumpObjectSlot(PyrSlot
*slot
)
2084 dumpObject(slotRawObject(slot
));
2090 void dumpSlotOneWord(const char *tagstr
, PyrSlot
*slot
)
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
)
2103 if (FrameSanity(frame
, tagstr
)) {
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
));
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
);
2124 //if (slotRawObject(&frame->method)->classptr->classptr == class_class) {
2125 postfl("class: '%s'\n", slotRawSymbol(&slotRawObject(&frame
->method
)->classptr
->name
)->name
);
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
));
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
);
2138 if (frame->caller.utag != tagHFrame && frame->caller.utag != tagNil) {
2139 postfl("Frame %p caller tag wrong %p\n", frame, frame->caller.utag);
2142 if (frame->context.utag != tagHFrame && frame->context.utag != tagNil) {
2143 postfl("Frame %p context tag wrong %p\n", frame, frame->context.utag);
2146 if (frame->homeContext.utag != tagHFrame && frame->homeContext.utag != tagNil) {
2147 postfl("Frame %p homeContext tag wrong %p\n", frame, frame->homeContext.utag);
2151 if (!IsPtr(&frame
->ip
)) {
2152 postfl("Frame %p ip tag wrong %p\n", frame
, GetTag(&frame
->ip
));
2158 void DumpFrame(PyrFrame
*frame
)
2163 PyrMethodRaw
*methraw
;
2165 if (FrameSanity(frame
, "DumpFrame")) {
2166 post("FRAME CORRUPTED\n");
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);
2181 post("\t\targ %s = %s\n", slotRawSymbolArray(&meth
->argNames
)->symbols
[i
]->name
, str
);
2183 post("\t\tvar %s = %s\n", slotRawSymbolArray(&meth
->varNames
)->symbols
[i
- numargs
]->name
, str
);
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
)
2200 PyrMethodRaw
*methraw
;
2202 if (FrameSanity(frame
, "DumpDetailedFrame")) {
2203 post("FRAME CORRUPTED\n");
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);
2219 post("\t\targ %s = %s\n", slotRawSymbolArray(&meth
->argNames
)->symbols
[i
]->name
, str
);
2221 post("\t\tvar %s = %s\n", slotRawSymbolArray(&meth
->varNames
)->symbols
[i
- numargs
]->name
, str
);
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
)
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
)
2267 classobj
= classOfSlot(slot
);
2269 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
2270 meth
= gRowTable
[index
];
2275 bool isSubclassOf(PyrClass
*classobj
, PyrClass
*testclass
)
2278 if (classobj
== testclass
) {
2281 classobj
= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
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
);
2302 bool objAddIndexedSymbol(PyrSymbolArray
*obj
, PyrSymbol
*symbol
)
2304 if (obj
->size
< MAXINDEXSIZE((PyrObject
*)obj
)) {
2305 obj
->symbols
[obj
->size
++] = symbol
;
2312 bool objAddIndexedObject(PyrObject
*obj
, PyrObject
*obj2
)
2314 if (obj
->size
< ARRAYMAXINDEXSIZE(obj
)) {
2315 SetObject(obj
->slots
+ obj
->size
, obj2
);
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
)
2337 SetTagRaw(&zero
, 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
)
2351 int numbytes
= size
* sizeof(PyrSlot
);
2353 array
= PyrGC::NewPermanent(numbytes
, flags
, obj_slot
);
2355 array
= gc
->New(numbytes
, flags
, obj_slot
, collect
);
2356 array
->classptr
= class_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
;
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
;
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
;
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
;
2402 PyrString
* newPyrString(class PyrGC
*gc
, const char *s
, int flags
, bool collect
)
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
);
2415 PyrString
* newPyrStringN(class PyrGC
*gc
, int length
, int flags
, bool collect
)
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!
2426 PyrBlock
* newPyrBlock(int flags
)
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
);
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
;
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);
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
)
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
);
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
)
2512 if (index
< 0 || index
>= obj
->size
) return errIndexOutOfRange
;
2513 switch (obj
->obj_format
) {
2515 slot
= obj
->slots
+ index
;
2516 if (IsFloat(slot
)) {
2517 *value
= (int)slotRawFloat(slot
);
2518 } else if (IsInt(slot
)) {
2519 *value
= slotRawInt(slot
);
2525 *value
= (int)((double*)(obj
->slots
))[index
];
2528 *value
= (int)((float*)(obj
->slots
))[index
];
2531 *value
= ((int32
*)(obj
->slots
))[index
];
2534 *value
= ((int16
*)(obj
->slots
))[index
];
2537 *value
= ((int8
*)(obj
->slots
))[index
];
2545 int getIndexedFloat(PyrObject
*obj
, int index
, float *value
)
2549 if (index
< 0 || index
>= obj
->size
) return errIndexOutOfRange
;
2550 switch (obj
->obj_format
) {
2552 slot
= obj
->slots
+ index
;
2553 if (IsFloat(slot
)) {
2554 *value
= slotRawFloat(slot
);
2555 } else if (IsInt(slot
)) {
2556 *value
= slotRawInt(slot
);
2562 *value
= ((double*)(obj
->slots
))[index
];
2565 *value
= ((float*)(obj
->slots
))[index
];
2568 *value
= ((int32
*)(obj
->slots
))[index
];
2571 *value
= ((int16
*)(obj
->slots
))[index
];
2574 *value
= ((int8
*)(obj
->slots
))[index
];
2582 int getIndexedDouble(PyrObject
*obj
, int index
, double *value
)
2586 if (index
< 0 || index
>= obj
->size
) return errIndexOutOfRange
;
2587 switch (obj
->obj_format
) {
2589 slot
= obj
->slots
+ index
;
2590 if (IsFloat(slot
)) {
2591 *value
= slotRawFloat(slot
);
2592 } else if (IsInt(slot
)) {
2593 *value
= slotRawInt(slot
);
2599 *value
= ((double*)(obj
->slots
))[index
];
2602 *value
= ((float*)(obj
->slots
))[index
];
2605 *value
= ((int32
*)(obj
->slots
))[index
];
2608 *value
= ((int16
*)(obj
->slots
))[index
];
2611 *value
= ((int8
*)(obj
->slots
))[index
];
2620 void getIndexedSlot(PyrObject
*obj
, PyrSlot
*a
, int index
)
2622 // postfl("getIndexedSlot %s %X %d\n", slotRawSymbol(&obj->classptr->name)->name,
2624 switch (obj
->obj_format
) {
2626 slotCopy(a
, &obj
->slots
[index
]);
2629 SetFloat(a
, ((double*)(obj
->slots
))[index
]);
2632 SetFloat(a
, ((float*)(obj
->slots
))[index
]);
2635 SetInt(a
, ((int32
*)(obj
->slots
))[index
]);
2638 SetInt(a
, ((int16
*)(obj
->slots
))[index
]);
2641 SetInt(a
, ((int8
*)(obj
->slots
))[index
]);
2644 SetSymbol(a
, (PyrSymbol
*)((int**)(obj
->slots
))[index
]);
2647 SetChar(a
, ((unsigned char*)(obj
->slots
))[index
]);
2652 int putIndexedSlot(VMGlobals
*g
, PyrObject
*obj
, PyrSlot
*c
, int index
)
2655 switch (obj
->obj_format
) {
2657 if (obj
->IsImmutable()) return errImmutableObject
;
2658 slot
= obj
->slots
+ index
;
2660 g
->gc
->GCWrite(obj
, slot
);
2664 if (NotInt(c
)) return errWrongType
;
2666 ((double*)(obj
->slots
))[index
] = slotRawInt(c
);
2669 ((double*)(obj
->slots
))[index
] = slotRawFloat(c
);
2673 if (NotInt(c
)) return errWrongType
;
2675 ((float*)(obj
->slots
))[index
] = slotRawInt(c
);
2678 ((float*)(obj
->slots
))[index
] = slotRawFloat(c
);
2681 if (NotInt(c
)) return errWrongType
;
2682 ((int32
*)(obj
->slots
))[index
] = slotRawInt(c
);
2685 if (NotInt(c
)) return errWrongType
;
2686 ((int16
*)(obj
->slots
))[index
] = slotRawInt(c
);
2689 if (NotInt(c
)) return errWrongType
;
2690 ((int8
*)(obj
->slots
))[index
] = slotRawInt(c
);
2693 if (NotSym(c
)) return errWrongType
;
2694 ((PyrSymbol
**)(obj
->slots
))[index
] = slotRawSymbol(c
);
2697 if (NotChar(c
)) return errWrongType
;
2698 ((unsigned char*)(obj
->slots
))[index
] = slotRawChar(c
);
2704 int putIndexedFloat(PyrObject
*obj
, double val
, int index
)
2707 switch (obj
->obj_format
) {
2709 if (obj
->IsImmutable()) return errImmutableObject
;
2710 slot
= obj
->slots
+ index
;
2711 SetFloat(slot
, val
);
2714 ((double*)(obj
->slots
))[index
] = val
;
2717 ((float*)(obj
->slots
))[index
] = (float)val
;
2720 ((int32
*)(obj
->slots
))[index
] = (int32
)val
;
2723 ((int16
*)(obj
->slots
))[index
] = (int16
)val
;
2726 ((int8
*)(obj
->slots
))[index
] = (int8
)val
;
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
)
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;
2752 // hash for a double
2757 u
.d
= slotRawFloat(a
);
2758 hash
= Hash(u
.i
[0] + Hash(u
.i
[1]));
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
);