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
;
83 PyrSymbol
*s_identityset
;
84 PyrSymbol
*s_dictionary
;
85 PyrSymbol
*s_identitydictionary
;
86 PyrSymbol
*s_linkedlist
;
87 PyrSymbol
*s_sortedlist
;
89 PyrSymbol
*s_list
, *s_method
, *s_fundef
, *s_frame
, *s_class
;
90 PyrSymbol
*s_symbol
, *s_nil
;
91 PyrSymbol
*s_boolean
, *s_true
, *s_false
;
92 PyrSymbol
*s_int
, *s_char
, *s_color
, *s_float
, *s_complex
;
93 PyrSymbol
*s_rawptr
, *s_objptr
;
95 PyrSymbol
*s_magnitude
, *s_number
, *s_collection
, *s_ordered_collection
;
96 PyrSymbol
*s_arrayed_collection
;
97 PyrSymbol
*s_sequenceable_collection
;
98 PyrSymbol
*s_simple_number
;
100 PyrSymbol
*s_wavetable
;
102 PyrSymbol
*s_rawarray
;
103 PyrSymbol
*s_int8array
;
104 PyrSymbol
*s_int16array
;
105 PyrSymbol
*s_int32array
;
106 PyrSymbol
*s_symbolarray
;
107 PyrSymbol
*s_doublearray
;
108 PyrSymbol
*s_floatarray
;
111 PyrSymbol
*s_func
, *s_absfunc
;
113 PyrSymbol
*s_process
;
116 PyrSymbol
*s_routine
;
118 PyrSymbol
*s_prstart
;
119 PyrSymbol
*s_interpreter
;
120 PyrSymbol
*s_finalizer
;
122 PyrSymbol
*s_appclock
;
123 PyrSymbol
*s_systemclock
;
125 PyrSymbol
*s_nocomprendo
;
126 PyrSymbol
*s_curProcess
, *s_curMethod
, *s_curBlock
, *s_curClosure
, *s_curThread
;
127 //PyrSymbol *s_sampleRate;
128 //PyrSymbol *s_audioClock, *s_logicalClock;
130 PyrSymbol
*s_startup
;
131 PyrSymbol
*s_docmdline
;
133 PyrSymbol
*s_control
;
137 PyrSymbol
*s_ugen
, *s_outputproxy
;
138 PyrSymbol
*s_new
, *s_ref
, *s_value
, *s_at
, *s_put
;
139 PyrSymbol
*s_performList
, *s_superPerformList
;
140 PyrSymbol
*s_series
, *s_copyseries
, *s_putseries
;
141 PyrSymbol
*s_envirGet
, *s_envirPut
;
142 PyrSymbol
*s_synth
, *s_spawn
, *s_environment
, *s_event
;
143 PyrSymbol
*s_hardwaresetup
, *s_shutdown
;
144 PyrSymbol
*s_linear
, *s_exponential
, *s_gate
;
145 PyrSymbol
*s_super
, *s_this
;
146 PyrSlot o_nil
, o_true
, o_false
, o_end
;
147 PyrSlot o_pi
, o_twopi
;
148 PyrSlot o_fhalf
, o_fnegone
, o_fzero
, o_fone
, o_ftwo
, o_inf
;
149 PyrSlot o_negtwo
, o_negone
, o_zero
, o_one
, o_two
;
150 PyrSlot o_nullframe
, o_none
;
151 PyrSlot o_emptyarray
, o_onenilarray
, o_argnamethis
;
156 s_new
= getsym("new");
157 s_ref
= getsym("Ref");
158 s_none
= getsym("none");
159 s_object
= getsym("Object");
160 s_this
= getsym("this");
161 s_super
= getsym("super");
163 s_dictionary
= getsym("Dictionary");
164 s_bag
= getsym("Bag");
165 s_set
= getsym("Set");
166 s_identityset
= getsym("IdentitySet");
167 s_identitydictionary
= getsym("IdentityDictionary");
168 s_linkedlist
= getsym("LinkedList");
169 s_sortedlist
= getsym("SortedList");
170 s_array
= getsym("Array");
171 s_list
= getsym("List");
172 s_method
= getsym("Method");
173 s_fundef
= getsym("FunctionDef");
174 s_frame
= getsym("Frame");
175 s_class
= getsym("Class");
176 s_symbol
= getsym("Symbol");
177 s_nil
= getsym("Nil");
178 s_true
= getsym("True");
179 s_false
= getsym("False");
180 s_int
= getsym("Integer");
181 s_float
= getsym("Float");
182 s_char
= getsym("Char");
183 s_color
= getsym("Color");
184 s_rawptr
= getsym("RawPointer");
185 s_objptr
= getsym("ObjectPointer");
186 s_string
= getsym("String");
187 s_magnitude
= getsym("Magnitude");
188 s_number
= getsym("Number");
189 s_simple_number
= getsym("SimpleNumber");
190 s_collection
= getsym("Collection");
191 //s_ordered_collection = getsym("OrderedCollection");
192 s_arrayed_collection
= getsym("ArrayedCollection");
193 s_sequenceable_collection
= getsym("SequenceableCollection");
194 s_boolean
= getsym("Boolean");
195 s_signal
= getsym("Signal");
196 s_wavetable
= getsym("Wavetable");
197 //s_signalnode = getsym("SignalNode");
198 s_rawarray
= getsym("RawArray");
199 s_int8array
= getsym("Int8Array");
200 s_int16array
= getsym("Int16Array");
201 s_int32array
= getsym("Int32Array");
202 s_symbolarray
= getsym("SymbolArray");
203 s_floatarray
= getsym("FloatArray");
204 s_doublearray
= getsym("DoubleArray");
205 s_complex
= getsym("Complex");
206 s_point
= getsym("Point");
207 s_rect
= getsym("Rect");
208 s_absfunc
= getsym("AbstractFunction");
209 s_func
= getsym("Function");
210 s_stream
= getsym("Stream");
211 s_process
= getsym("Process");
212 s_main
= getsym("Main");
213 s_thread
= getsym("Thread");
214 s_routine
= getsym("Routine");
215 s_task
= getsym("Task");
216 s_prstart
= getsym("prStart");
217 s_interpreter
= getsym("Interpreter");
218 s_finalizer
= getsym("Finalizer");
219 s_awake
= getsym("awake");
220 s_appclock
= getsym("AppClock");
221 s_systemclock
= getsym("SystemClock");
223 s_linear
= getsym("linear");
224 s_exponential
= getsym("exponential");
225 s_gate
= getsym("gate");
227 //s_dsp = getsym("DSP");
228 //s_dspsettings = getsym("DSPSettings");
229 s_synth
= getsym("Synth");
230 s_spawn
= getsym("BasicSpawn");
231 s_environment
= getsym("Environment");
232 s_event
= getsym("Event");
233 s_hardwaresetup
= getsym("hardwareSetup");
234 s_shutdown
= getsym("shutdown");
236 s_nocomprendo
= getsym("doesNotUnderstand");
238 s_curProcess
= getsym("thisProcess");
239 s_curThread
= getsym("thisThread");
240 s_curMethod
= getsym("thisMethod");
241 s_curBlock
= getsym("thisFunctionDef");
242 s_curClosure
= getsym("thisFunction");
243 //s_sampleRate = getsym("gSR");
244 //s_logicalClock = getsym("gTime");
245 //s_audioClock = getsym("gAudioTime");
246 s_audio
= getsym("audio");
247 s_control
= getsym("control");
248 s_scalar
= getsym("scalar");
249 s_run
= getsym("run");
250 s_startup
= getsym("startup");
251 s_docmdline
= getsym("doCmdLine");
252 s_next
= getsym("next");
253 s_value
= getsym("value");
254 s_performList
= getsym("performList");
255 s_superPerformList
= getsym("superPerformList");
257 s_put
= getsym("put");
259 s_series
= getsym("prSimpleNumberSeries");
260 s_copyseries
= getsym("copySeries");
261 s_putseries
= getsym("putSeries");
263 s_ugen
= getsym("UGen");
264 s_outputproxy
= getsym("OutputProxy");
265 s_env
= getsym("Env");
267 s_envirGet
= getsym("envirGet");
268 s_envirPut
= getsym("envirPut");
275 SetFloat(&o_twopi
, twopi
);
276 SetFloat(&o_fhalf
, .5);
277 SetFloat(&o_fnegone
, -1.);
278 SetFloat(&o_fzero
, 0.);
279 SetFloat(&o_fone
, 1.);
280 SetFloat(&o_ftwo
, 2.);
281 SetInt(&o_negtwo
, -2);
282 SetInt(&o_negone
, -1);
286 SetSymbol(&o_none
, s_none
);
294 SetFloat(&o_inf
, INFINITY
);
297 slotCopy(&gSpecialValues
[svNil
], &o_nil
);
298 slotCopy(&gSpecialValues
[svFalse
], &o_false
);
299 slotCopy(&gSpecialValues
[svTrue
], &o_true
);
300 slotCopy(&gSpecialValues
[svNegOne
], &o_negone
);
301 slotCopy(&gSpecialValues
[svZero
], &o_zero
);
302 slotCopy(&gSpecialValues
[svOne
], &o_one
);
303 slotCopy(&gSpecialValues
[svTwo
], &o_two
);
304 slotCopy(&gSpecialValues
[svFHalf
], &o_fhalf
);
305 slotCopy(&gSpecialValues
[svFNegOne
], &o_fnegone
);
306 slotCopy(&gSpecialValues
[svFZero
], &o_fzero
);
307 slotCopy(&gSpecialValues
[svFOne
], &o_fone
);
308 slotCopy(&gSpecialValues
[svFTwo
], &o_ftwo
);
309 slotCopy(&gSpecialValues
[svInf
], &o_inf
);
311 gFormatElemSize
[obj_notindexed
] = sizeof(PyrSlot
);
312 gFormatElemSize
[obj_slot
] = sizeof(PyrSlot
);
313 gFormatElemSize
[obj_double
] = sizeof(double);
314 gFormatElemSize
[obj_float
] = sizeof(float);
315 gFormatElemSize
[obj_int32
] = sizeof(int32
);
316 gFormatElemSize
[obj_int16
] = sizeof(int16
);
317 gFormatElemSize
[obj_int8
] = sizeof(int8
);
318 gFormatElemSize
[obj_char
] = sizeof(char);
319 gFormatElemSize
[obj_symbol
] = sizeof(PyrSymbol
*);
321 gFormatElemCapc
[obj_notindexed
] = sizeof(PyrSlot
) / sizeof(PyrSlot
);
322 gFormatElemCapc
[obj_slot
] = sizeof(PyrSlot
) / sizeof(PyrSlot
);
323 gFormatElemCapc
[obj_double
] = sizeof(PyrSlot
) / sizeof(double);
324 gFormatElemCapc
[obj_float
] = sizeof(PyrSlot
) / sizeof(float);
325 gFormatElemCapc
[obj_int32
] = sizeof(PyrSlot
) / sizeof(int32
);
326 gFormatElemCapc
[obj_int16
] = sizeof(PyrSlot
) / sizeof(int16
);
327 gFormatElemCapc
[obj_int8
] = sizeof(PyrSlot
) / sizeof(int8
);
328 gFormatElemCapc
[obj_char
] = sizeof(PyrSlot
) / sizeof(char);
329 gFormatElemCapc
[obj_symbol
] = sizeof(PyrSlot
) / sizeof(PyrSymbol
*);
331 gFormatElemTag
[obj_notindexed
] = -1;
332 gFormatElemTag
[obj_slot
] = -1;
333 gFormatElemTag
[obj_double
] = 0;
334 gFormatElemTag
[obj_float
] = 0;
335 gFormatElemTag
[obj_int32
] = tagInt
;
336 gFormatElemTag
[obj_int16
] = tagInt
;
337 gFormatElemTag
[obj_int8
] = tagInt
;
338 gFormatElemTag
[obj_char
] = tagChar
;
339 gFormatElemTag
[obj_symbol
] = tagSym
;
342 const char *slotSymString(PyrSlot
* slot
)
344 switch (GetTag(slot
)) {
345 case tagObj
: return slotRawSymbol(&slotRawObject(slot
)->classptr
->name
)->name
;
346 case tagInt
: return "Integer";
347 case tagChar
: return "Char";
348 case tagSym
: return slotRawSymbol(slot
)->name
;
349 case tagNil
: return "Nil";
350 case tagFalse
: return "False";
351 case tagTrue
: return "True";
352 default : return "<float>";
356 PyrClass
* newClassObj(PyrClass
*classObjSuperClass
,
357 PyrSymbol
* className
, PyrSymbol
* superClassName
,
358 int numInstVars
, int numClassVars
, int numConsts
, int numInstMethods
,
359 int instFormat
, int instFlags
)
361 PyrClass
* classobj
, *superclassobj
;
363 PyrSymbolArray
*symarray
;
368 c = className->name[0];
369 if (!(c >= 'A' && c <= 'Z')) Debugger();
372 // lifetime: kill upon recompiling library
373 classobj
= (PyrClass
*)pyr_pool_runtime
->Alloc(sizeof(PyrClass
));
375 classobj
->size
= (sizeof(PyrClass
) - sizeof(PyrObjectHdr
))/sizeof(PyrSlot
);
376 classobj
->prev
= classobj
->next
= NULL
;
377 classobj
->obj_flags
= obj_immutable
;
378 classobj
->obj_format
= obj_notindexed
;
379 classobj
->gc_color
= obj_permanent
;
380 classobj
->obj_sizeclass
= LOG2CEIL(classobj
->size
);
381 classobj
->classptr
= classObjSuperClass
;
384 // append to the list of classes
385 if (gClassList
) SetObject(&classobj
->nextclass
, gClassList
);
386 else SetNil(&classobj
->nextclass
);
388 gClassList
= classobj
;
390 className
->u
.classobj
= classobj
;
391 //postfl("> '%s' %d %d\n", className->name, className, classobj);
393 SetSymbol(&classobj
->name
, className
);
394 if (superClassName
) {
395 SetSymbol(&classobj
->superclass
, superClassName
);
396 superclassobj
= superClassName
->u
.classobj
;
398 SetSymbol(&classobj
->superclass
, s_none
);
399 superclassobj
= NULL
;
402 SetInt(&classobj
->subclasses
, 0); // to be filled with subclasses later
403 // in the meantime it is used as a tally of subclasses so that its allocation
406 if (numInstMethods
) {
407 array
= newPyrArray(NULL
, numInstMethods
, obj_permanent
| obj_immutable
, false);
408 SetObject(&classobj
->methods
, array
);
410 SetNil(&classobj
->methods
);
414 symarray
= newPyrSymbolArray(NULL
, numInstVars
, obj_permanent
| obj_immutable
, false);
415 SetObject(&classobj
->instVarNames
, symarray
);
417 array
= newPyrArray(NULL
, numInstVars
, obj_permanent
| obj_immutable
, false);
418 SetObject(&classobj
->iprototype
, array
);
419 nilSlots(array
->slots
, numInstVars
);
421 SetNil(&classobj
->instVarNames
);
422 SetNil(&classobj
->iprototype
);
426 symarray
= newPyrSymbolArray(NULL
, numClassVars
, obj_permanent
| obj_immutable
, false);
427 SetObject(&classobj
->classVarNames
, symarray
);
429 array
= newPyrArray(NULL
, numClassVars
, obj_permanent
| obj_immutable
, false);
430 SetObject(&classobj
->cprototype
, array
);
431 nilSlots(array
->slots
, numClassVars
);
433 SetNil(&classobj
->classVarNames
);
434 SetNil(&classobj
->cprototype
);
438 symarray
= newPyrSymbolArray(NULL
, numConsts
, obj_permanent
| obj_immutable
, false);
439 SetObject(&classobj
->constNames
, symarray
);
441 array
= newPyrArray(NULL
, numConsts
, obj_permanent
| obj_immutable
, false);
442 SetObject(&classobj
->constValues
, array
);
443 nilSlots(array
->slots
, numConsts
);
445 SetNil(&classobj
->constNames
);
446 SetNil(&classobj
->constValues
);
450 if (instFormat
!= obj_notindexed
) {
451 classFlags
|= classHasIndexableInstances
;
454 SetInt(&classobj
->instanceFormat
, instFormat
);
455 SetInt(&classobj
->instanceFlags
, instFlags
);
456 SetInt(&classobj
->classIndex
, -1);
457 SetInt(&classobj
->classFlags
, classFlags
);
458 SetInt(&classobj
->maxSubclassIndex
, 0);
459 SetNil(&classobj
->filenameSym
);
460 SetInt(&classobj
->charPos
, 0);
461 SetInt(&classobj
->classVarIndex
, gNumClassVars
);
462 //if (numClassVars) post("%16s %4d %4d\n", className->name, gNumClassVars, numClassVars);
463 gNumClassVars
+= numClassVars
;
467 void reallocClassObj(PyrClass
* classobj
,
468 int numInstVars
, int numClassVars
, int numConsts
, int numMethods
,
469 int instFormat
, int instFlags
)
472 PyrSymbolArray
*symarray
;
473 PyrClass
*superclassobj
;
475 freePyrSlot(&classobj
->methods
);
476 freePyrSlot(&classobj
->instVarNames
);
477 freePyrSlot(&classobj
->classVarNames
);
478 freePyrSlot(&classobj
->iprototype
);
479 freePyrSlot(&classobj
->cprototype
);
481 freePyrSlot(&classobj
->constNames
);
482 freePyrSlot(&classobj
->constValues
);
485 array
= newPyrArray(NULL
, numMethods
, obj_permanent
| obj_immutable
, false);
486 SetObject(&classobj
->methods
, array
);
488 SetNil(&classobj
->methods
);
492 //post("reallocClassObj %s numInstVars %d\n", slotRawSymbol(&classobj->name)->name, numInstVars);
493 symarray
= newPyrSymbolArray(NULL
, numInstVars
, obj_permanent
| obj_immutable
, false);
494 SetObject(&classobj
->instVarNames
, symarray
);
496 array
= newPyrArray(NULL
, numInstVars
, obj_permanent
| obj_immutable
, false);
497 SetObject(&classobj
->iprototype
, array
);
498 nilSlots(array
->slots
, numInstVars
);
500 SetNil(&classobj
->instVarNames
);
501 SetNil(&classobj
->iprototype
);
505 //post("reallocClassObj %s numClassVars %d\n", slotRawSymbol(&classobj->name)->name, numClassVars);
506 symarray
= newPyrSymbolArray(NULL
, numClassVars
, obj_permanent
| obj_immutable
, false);
507 SetObject(&classobj
->classVarNames
, symarray
);
508 nilSlots(array
->slots
, numClassVars
);
510 array
= newPyrArray(NULL
, numClassVars
, obj_permanent
| obj_immutable
, false);
511 SetObject(&classobj
->cprototype
, array
);
512 nilSlots(array
->slots
, numClassVars
);
514 SetNil(&classobj
->classVarNames
);
515 SetNil(&classobj
->cprototype
);
519 //post("reallocClassObj %s numConsts %d\n", slotRawSymbol(&classobj->name)->name, numConsts);
520 symarray
= newPyrSymbolArray(NULL
, numConsts
, obj_permanent
| obj_immutable
, false);
521 SetObject(&classobj
->constNames
, symarray
);
523 array
= newPyrArray(NULL
, numConsts
, obj_permanent
| obj_immutable
, false);
524 SetObject(&classobj
->constValues
, array
);
525 nilSlots(array
->slots
, numConsts
);
527 SetNil(&classobj
->constNames
);
528 SetNil(&classobj
->constValues
);
531 superclassobj
= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
533 SetInt(&classobj
->instanceFormat
, instFormat
);
534 SetInt(&classobj
->instanceFlags
, instFlags
);
535 SetInt(&classobj
->classIndex
, -1);
538 void fixClassArrays(PyrClass
*classobj
);
539 void fixClassArrays(PyrClass
*classobj
)
541 if (IsObj(&classobj
->methods
)) slotRawObject(&classobj
->methods
)->classptr
= class_array
;
542 if (IsObj(&classobj
->instVarNames
)) slotRawObject(&classobj
->instVarNames
)->classptr
= class_symbolarray
;
543 if (IsObj(&classobj
->classVarNames
)) slotRawObject(&classobj
->classVarNames
)->classptr
= class_symbolarray
;
544 if (IsObj(&classobj
->iprototype
)) slotRawObject(&classobj
->iprototype
)->classptr
= class_array
;
545 if (IsObj(&classobj
->cprototype
)) slotRawObject(&classobj
->cprototype
)->classptr
= class_array
;
548 int numInstVars(PyrClass
* classobj
)
551 if (IsNil(&classobj
->instVarNames
))
554 res
= slotRawObject(&classobj
->instVarNames
)->size
;
558 int numClassVars(PyrClass
* classobj
)
561 if (IsNil(&classobj
->classVarNames
)) res
= 0;
562 else res
= slotRawObject(&classobj
->classVarNames
)->size
;
567 void objAddIndexedSlotGrow(PyrSlot
*arraySlot
, PyrSlot
*addSlot
);
568 void objAddIndexedSlotGrow(PyrSlot
*arraySlot
, PyrSlot
*addSlot
)
571 if (IsNil(arraySlot
)) {
572 PyrObject
*newobj
= (PyrObject
*)newPyrArray(NULL
, 1, obj_permanent
| obj_immutable
, false);
573 SetObject(arraySlot
, newobj
);
576 obj
= slotRawObject(arraySlot
);
577 if (obj
->size
>= ARRAYMAXINDEXSIZE(obj
)) {
578 //post("objAddIndexedSlotGrow\n");
579 PyrObject
*newobj
= (PyrObject
*)newPyrArray(NULL
, obj
->size
* 2, obj_permanent
| obj_immutable
, false);
580 memcpy(newobj
->slots
, obj
->slots
, obj
->size
* sizeof(PyrSlot
));
581 newobj
->size
= obj
->size
;
582 SetObject(arraySlot
, newobj
);
583 pyr_pool_runtime
->Free((void*)obj
);
587 slotCopy(&obj
->slots
[obj
->size
++], addSlot
);
590 void addMethod(PyrClass
*classobj
, PyrMethod
*method
)
593 SetObject(&slot
, method
);
594 objAddIndexedSlotGrow(&classobj
->methods
, &slot
);
599 PyrMethod
* classFindDirectMethod(PyrClass
* classobj
, PyrSymbol
*name
)
604 if (IsNil(&classobj
->methods
)) return NULL
;
605 methods
= slotRawObject(&classobj
->methods
)->slots
;
606 numMethods
= slotRawObject(&classobj
->methods
)->size
;
607 for (i
=0; i
<numMethods
; ++i
) {
608 method
= slotRawMethod(&methods
[i
]);
609 if (slotRawSymbol(&method
->name
) == name
) break;
611 if (i
>=numMethods
) method
= NULL
;
615 int numSuperInstVars(PyrClass
*superclassobj
)
617 int superinstvars
= 0;
619 if (IsObj(&superclassobj
->iprototype
)) {
620 superinstvars
= slotRawObject(&superclassobj
->iprototype
)->size
;
623 return superinstvars
;
626 bool classFindInstVar(PyrClass
* classobj
, PyrSymbol
*name
, int *index
)
628 PyrSymbolArray
*ivnames
;
631 if (NotNil(&classobj
->instVarNames
)) {
632 ivnames
= slotRawSymbolArray(&classobj
->instVarNames
);
634 for (i
=0; i
<ivnames
->size
; ++i
) {
635 ivname
= ivnames
->symbols
[i
];
636 if (ivname
== name
) {
637 //numsupervars = numSuperInstVars(slotRawSymbol(&classobj->superclass)->u.classobj);
638 //*index = numsupervars + i;
648 int instVarOffset(const char *classname
, const char *instvarname
)
650 PyrSymbol
*instvarsymbol
, *classsymbol
;
655 classsymbol
= getsym(classname
);
656 instvarsymbol
= getsym(instvarname
);
659 if (!(c
>= 'A' && c
<= 'Z')) return -1;
661 classobj
= classsymbol
->u
.classobj
;
662 if (!classobj
) return -1;
663 if (!classFindInstVar(classobj
, instvarsymbol
, &index
)) return -1;
667 int classVarOffset(const char *classname
, const char *classvarname
, PyrClass
** classobj
)
669 PyrSymbol
*classvarsymbol
, *classsymbol
;
673 classsymbol
= getsym(classname
);
674 classvarsymbol
= getsym(classvarname
);
677 if (!(c
>= 'A' && c
<= 'Z')) return -1;
679 *classobj
= classsymbol
->u
.classobj
;
680 if (!*classobj
) return -1;
681 if (!classFindClassVar(classobj
, classvarsymbol
, &index
)) return -1;
685 bool classFindClassVar(PyrClass
** classobj
, PyrSymbol
*name
, int *index
)
687 PyrSymbolArray
*cvnames
;
691 PyrClass
* localclassobj
= *classobj
;
692 // if this is a Metaclass then we need to search its normal Class for
694 classname
= slotRawSymbol(&localclassobj
->name
)->name
;
695 if (strncmp(classname
, "Meta_", 5) == 0) {
696 localclassobj
= getsym(classname
+5)->u
.classobj
;
698 for (j
=0; localclassobj
; ++j
) {
699 if (NotNil(&localclassobj
->classVarNames
)) {
700 cvnames
= slotRawSymbolArray(&localclassobj
->classVarNames
);
702 for (i
=0; i
<cvnames
->size
; ++i
) {
703 cvname
= cvnames
->symbols
[i
];
704 if (cvname
== name
) {
705 *classobj
= localclassobj
;
712 if (IsSym(&localclassobj
->superclass
)) {
713 localclassobj
= slotRawSymbol(&localclassobj
->superclass
)->u
.classobj
;
715 localclassobj
= NULL
;
721 bool classFindConst(PyrClass
** classobj
, PyrSymbol
*name
, int *index
)
723 PyrSymbolArray
*knames
;
727 PyrClass
* localclassobj
= *classobj
;
728 // if this is a Metaclass then we need to search its normal Class for
730 classname
= slotRawSymbol(&localclassobj
->name
)->name
;
731 if (strncmp(classname
, "Meta_", 5) == 0) {
732 localclassobj
= getsym(classname
+5)->u
.classobj
;
734 for (j
=0; localclassobj
; ++j
) {
735 if (NotNil(&localclassobj
->constNames
)) {
736 knames
= slotRawSymbolArray(&localclassobj
->constNames
);
738 for (i
=0; i
<knames
->size
; ++i
) {
739 kname
= knames
->symbols
[i
];
741 *classobj
= localclassobj
;
748 if (IsSym(&localclassobj
->superclass
)) {
749 localclassobj
= slotRawSymbol(&localclassobj
->superclass
)->u
.classobj
;
751 localclassobj
= NULL
;
759 bool operator()(PyrClass
* lhs
, PyrClass
* rhs
) const
761 return strcmp(slotRawSymbol(&lhs
->name
)->name
, slotRawSymbol(&rhs
->name
)->name
) < 0;
767 class pyr_pool_compile_allocator
770 typedef std::size_t size_type
;
771 typedef std::ptrdiff_t difference_type
;
773 typedef const T
* const_pointer
;
774 typedef T
& reference
;
775 typedef const T
& const_reference
;
776 typedef T value_type
;
778 template <class U
> struct rebind
780 typedef pyr_pool_compile_allocator
<U
> other
;
783 pyr_pool_compile_allocator(void)
787 pyr_pool_compile_allocator(pyr_pool_compile_allocator
<U
> const &)
790 pointer
address(reference x
) const
795 const_pointer
address(const_reference x
) const
800 pointer
allocate(size_type n
, const void* hint
= 0)
802 return (pointer
)pyr_pool_compile
->Alloc(n
*sizeof(T
));
805 void deallocate(pointer p
, size_type n
)
807 pyr_pool_compile
->Free(p
);
810 void construct(pointer p
, const T
& val
)
815 void destroy(pointer p
)
822 /* sort list of classes:
823 * we fill a binary search tree
826 static PyrClass
* sortClasses(PyrClass
* aClassList
)
828 typedef std::set
<PyrClass
*, compareByName
, pyr_pool_compile_allocator
<PyrClass
*> > classSetType
;
829 classSetType classSet
;
831 PyrClass
* insertHead
= aClassList
;
833 assert(classSet
.find(insertHead
) == classSet
.end());
834 classSet
.insert(insertHead
);
835 insertHead
= slotRawClass(&insertHead
->nextclass
);
836 } while (insertHead
);
838 classSetType::iterator it
= classSet
.begin();
839 PyrClass
* sortedClasses
= *it
;
842 PyrClass
* lastClass
= sortedClasses
;
843 for (; it
!= classSet
.end(); ++it
) {
844 PyrClass
* current
= *it
;
845 SetObject(&lastClass
->nextclass
, (PyrObject
*)current
);
848 SetNil(&lastClass
->nextclass
);
849 return sortedClasses
;
852 #include <boost/threadpool.hpp>
854 static int cpuCount
= boost::thread::hardware_concurrency();
855 static int helperThreadCount
= cpuCount
- 1;
856 static boost::threadpool::fifo_pool compileThreadPool
;
858 void buildClassTree()
860 // the first time we use the pool
861 compileThreadPool
.size_controller().resize(helperThreadCount
);
863 // after all classes are compiled this function builds the tree and
864 // indexes the classes
867 //postfl("count subclasses\n");
868 PyrClass
*classobj
= gClassList
;
870 PyrClass
* superclassobj
= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
872 //postfl(" superclassobj %s\n", slotRawSymbol(&superclassobj->name)->name);
873 SetRaw(&superclassobj
->subclasses
, slotRawInt(&superclassobj
->subclasses
) + 1);
875 classobj
= slotRawClass(&classobj
->nextclass
);
877 // allocate subclass arrays
878 //postfl("allocate subclass arrays\n");
879 classobj
= gClassList
;
882 numSubclasses
= slotRawInt(&classobj
->subclasses
);
883 //postfl(" %s %d\n", slotRawSymbol(&classobj->name)->name, numSubclasses);
885 SetObject(&classobj
->subclasses
, (PyrObject
*)newPyrArray(NULL
, numSubclasses
, obj_permanent
| obj_immutable
, false));
886 slotRawObject(&classobj
->subclasses
)->size
= 0;
888 SetNil(&classobj
->subclasses
);
890 classobj
= slotRawClass(&classobj
->nextclass
);
892 // fill in subclass arrays
893 //postfl("fill in subclass arrays\n");
894 classobj
= gClassList
;
896 //postfl(" %s\n", slotRawSymbol(&classobj->name)->name);
897 PyrClass
*superclassobj
= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
899 objAddIndexedObject(slotRawObject(&superclassobj
->subclasses
), (PyrObject
*)classobj
);
900 //postfl(" superclassobj %s %d\n", slotRawSymbol(&superclassobj->name)->name,
901 // slotRawObject(&superclassobj->subclasses)->size);
903 classobj
= slotRawClass(&classobj
->nextclass
);
906 // alpha sort the classes via insertion sort
907 gClassList
= sortClasses(gClassList
);
910 void indexClassTree(PyrClass
*classobj
, int numSuperMethods
)
914 if (!classobj
) return;
916 SetInt(&classobj
->classIndex
, gNumClasses
);
919 if (IsObj(&classobj
->methods
)) {
920 PyrObject
* methods
= slotRawObject(&classobj
->methods
);
921 numMethods
= methods
->size
;
926 numMethods
= numSuperMethods
+ numMethods
;
927 if (IsObj(&classobj
->subclasses
)) {
928 PyrObject
* subclasses
= slotRawObject(&classobj
->subclasses
);
929 for (i
=0; i
<subclasses
->size
; ++i
)
930 indexClassTree(slotRawClass(&subclasses
->slots
[i
]), numMethods
);
932 SetInt(&classobj
->maxSubclassIndex
, gNumClasses
- 1);
935 void findDiscrepancy();
936 void findDiscrepancy()
938 PyrClass
*classobjA
, *classobjB
;
940 classobjA
= gClassList
;
942 classobjB
= slotRawClass(&classobjA
->nextclass
);;
944 if (slotRawSymbol(&classobjA
->name
) == slotRawSymbol(&classobjB
->name
)) {
945 post("duplicate %s\n", slotRawSymbol(&classobjA
->name
)->name
);
947 classobjB
= slotRawClass(&classobjB
->nextclass
);
949 classobjA
= slotRawClass(&classobjA
->nextclass
);
954 static void indent(int n
)
956 for (int i
=0; i
<n
; ++i
) {
961 void postClassTree(PyrClass
*classobj
, int level
)
963 PyrObject
*subclasses
;
966 //post("%4d ", slotRawInt(&classobj->classIndex));
968 post("%s\n", slotRawSymbol(&classobj
->name
)->name
);
970 if (classobj
== class_class
) {
972 post(" [.. all metaclasses ..]\n");
974 if (IsNil(&classobj
->subclasses
))
975 return; // FIXME: can we initialize subclasses with a NULL pointer?
976 subclasses
= slotRawObject(&classobj
->subclasses
);
978 // determine if can put on one line
979 bool oneline
= subclasses
->size
<= 5;
980 for (i
=0; oneline
&& i
<subclasses
->size
; ++i
) {
981 PyrClass
*subclassobj
= slotRawClass(&subclasses
->slots
[i
]);
982 if (IsObj(&subclassobj
->subclasses
))
983 // FIXME: shall we do a null-pointer check?
989 for (i
=0; i
<subclasses
->size
; ++i
) {
990 PyrClass
*subclassobj
= slotRawClass(&subclasses
->slots
[i
]);
991 post(" %s", slotRawSymbol(&subclassobj
->name
)->name
);
997 for (i
=0; i
<subclasses
->size
; ++i
) {
998 postClassTree(slotRawClass(&subclasses
->slots
[i
]), level
+1);
1008 void setSelectorFlags()
1012 PyrClass
* classobj
= gClassList
;
1014 if (IsObj(&classobj
->methods
)) {
1015 PyrObject
*methods
= slotRawObject(&classobj
->methods
);
1016 for (i
=0; i
<methods
->size
; ++i
) {
1017 PyrMethod
* method
= slotRawMethod(&methods
->slots
[i
]);
1018 slotRawSymbol(&method
->name
)->flags
|= sym_Selector
;
1019 //if (method->methType == methRedirect) {
1020 // post("rd: %3d %s:%s\n", k++, slotRawSymbol(&classobj->name)->name,
1021 // slotRawSymbol(&method->name)->name);
1025 classobj
= slotRawClass(&classobj
->nextclass
);
1029 SymbolTable
* symbolTable
= gMainVMGlobals
->symbolTable
;
1030 for (int i
=0; i
<symbolTable
->TableSize(); ++i
) {
1031 PyrSymbol
*sym
= symbolTable
->Get(i
);
1032 if (sym
&& (sym
->flags
& sym_Selector
)) {
1033 sym
->u
.index
= gNumSelectors
++;
1036 //post("gNumSelectors %d\n", gNumSelectors);
1039 // the chunky stuff can be commented back in for implementing a better
1040 // compression scheme. The Q&D method works fine for my small class tree for now.
1043 PyrSymbol
*selector
;
1054 int compareColDescs(const void *va
, const void *vb
);
1055 int compareColDescs(const void *va
, const void *vb
)
1057 ColumnDescriptor
*a
= (ColumnDescriptor
*)va
;
1058 ColumnDescriptor
*b
= (ColumnDescriptor
*)vb
;
1060 //diff = b->largestChunk - a->largestChunk;
1061 //if (diff != 0) return diff;
1062 diff
= b
->rowWidth
- a
->rowWidth
;
1063 if (diff
!= 0) return diff
;
1064 //diff = b->chunkOffset - a->chunkOffset;
1065 diff
= b
->minClassIndex
- a
->minClassIndex
;
1069 #define CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME 0
1070 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1071 double elapsedTime();
1074 static size_t fillClassRow(PyrClass
*classobj
, PyrMethod
** bigTable
);
1077 static void updateSelectorRowWidth(ColumnDescriptor
* sels
, size_t begin
, size_t end
)
1079 for (int i
=begin
; i
<end
; ++i
) {
1080 //if (chunkSize > sels[i].largestChunk) {
1081 // sels[i].largestChunk = chunkSize;
1082 // sels[i].chunkOffset = chunkOffset;
1084 sels
[i
].rowWidth
= sels
[i
].maxClassIndex
- sels
[i
].minClassIndex
+ 1;
1088 static void binsortClassRows(PyrMethod
** bigTable
, const ColumnDescriptor
* sels
, size_t numSelectors
, size_t begin
, size_t end
)
1090 // bin sort the class rows to the new ordering
1091 //post("reorder rows\n");
1092 const int allocaThreshold
= 4096;
1094 PyrMethod
** temprow
= (numSelectors
< allocaThreshold
) ? (PyrMethod
**)alloca(numSelectors
* sizeof(PyrMethod
*))
1095 : (PyrMethod
**)malloc(numSelectors
* sizeof(PyrMethod
*));
1097 for (int j
=begin
; j
<end
; ++j
) {
1098 PyrMethod
** row
= bigTable
+ j
* numSelectors
;
1099 memcpy(temprow
, row
, numSelectors
* sizeof(PyrMethod
*));
1100 for (int i
=0; i
<numSelectors
; ++i
)
1101 row
[i
] = temprow
[sels
[i
].selectorIndex
];
1104 if (numSelectors
>= allocaThreshold
)
1108 static void prepareColumnTable(ColumnDescriptor
* sels
, int numSelectors
)
1110 // fill selector table
1111 //post("fill selector table\n");
1112 SymbolTable
* symbolTable
= gMainVMGlobals
->symbolTable
;
1113 for (int i
=0, j
=0; i
<symbolTable
->TableSize(); ++i
) {
1114 PyrSymbol
*sym
= symbolTable
->Get(i
);
1115 if (sym
&& (sym
->flags
& sym_Selector
))
1116 sels
[j
++].selector
= sym
;
1119 for (int i
=0; i
<numSelectors
; ++i
) {
1120 //postfl("%3d %s\n", i, sels[i].selector->name);
1121 sels
[i
].minClassIndex
= INT_MAX
;
1122 sels
[i
].maxClassIndex
= 0;
1123 //sels[i].largestChunk = 0;
1124 //sels[i].chunkOffset = 0;
1125 sels
[i
].selectorIndex
= i
;
1126 sels
[i
].population
= 0;
1130 static void calcRowStats(PyrMethod
** bigTable
, ColumnDescriptor
* sels
, int numClasses
, int numSelectors
, int begin
, int end
)
1134 PyrMethod
** methodPtr
= bigTable
;
1135 for (int j
=0; j
<numClasses
; ++j
) {
1136 for (int i
=begin
; i
<end
; ++i
) {
1137 PyrMethod
* method
= bigTable
[j
* numSelectors
+ i
];
1139 //classobj = method->ownerclass.uoc;
1140 if (j
> sels
[i
].maxClassIndex
) {
1141 sels
[i
].maxClassIndex
= j
;
1143 if (j
< sels
[i
].minClassIndex
) {
1144 sels
[i
].minClassIndex
= j
;
1146 sels
[i
].population
++;
1147 //if (chunkSize == 0) chunkOffset = j;
1149 //postfl(" %8s %3d %3d %3d %3d\n", slotRawSymbol(&classobj->name)->name, i, j,
1150 // chunkSize, slotRawInt(&classobj->classIndex));
1152 //if (chunkSize > sels[i].largestChunk) {
1153 // sels[i].largestChunk = chunkSize;
1154 // sels[i].chunkOffset = chunkOffset;
1163 void buildBigMethodMatrix()
1165 PyrMethod
**bigTable
, **temprow
, **row
;
1166 PyrClass
*classobj
, **classes
;
1168 int popSum
, widthSum
;
1169 int rowOffset
, freeIndex
;
1172 const int numSelectors
= gNumSelectors
;
1173 const int numClasses
= gNumClasses
;
1174 //post("allocate arrays\n");
1176 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1177 double t0
= elapsedTime();
1181 // lifetime: kill after compile
1182 bigTableSize
= numSelectors
* numClasses
;
1183 //post("bigTableSize %d %d %d\n", bigTableSize, numSelectors, numClasses);
1184 ColumnDescriptor
*sels
= (ColumnDescriptor
*)pyr_pool_compile
->Alloc(numSelectors
* sizeof(ColumnDescriptor
));
1186 if (helperThreadCount
)
1187 compileThreadPool
.schedule(boost::bind(&prepareColumnTable
, sels
, numSelectors
));
1189 prepareColumnTable(sels
, numSelectors
);
1191 bigTable
= (PyrMethod
**)pyr_pool_compile
->Alloc(bigTableSize
* sizeof(PyrMethod
*));
1193 classes
= (PyrClass
**)pyr_pool_compile
->Alloc(numClasses
* sizeof(PyrClass
*));
1196 classobj
= gClassList
;
1198 classes
[slotRawInt(&classobj
->classIndex
)] = classobj
;
1199 classobj
= slotRawClass(&classobj
->nextclass
);
1202 size_t numentries
= fillClassRow(class_object
, bigTable
);
1203 post("\tnumentries = %lu / %d = %.2g\n", numentries
, bigTableSize
, (double)numentries
/(double)bigTableSize
);
1205 // no need to wait for the theadpool, because it is done in fillClassRow
1208 //post("calc row stats\n");
1209 const int classesPerThread
= numClasses
/cpuCount
;
1210 const int selectorsPerThread
= numSelectors
/cpuCount
;
1211 for (i
= 0; i
!= helperThreadCount
; ++i
)
1212 compileThreadPool
.schedule(boost::bind(&calcRowStats
, bigTable
, sels
, numClasses
, numSelectors
,
1213 selectorsPerThread
* i
, selectorsPerThread
* (i
+1)));
1215 calcRowStats(bigTable
, sels
, numClasses
, numSelectors
, helperThreadCount
*selectorsPerThread
, numSelectors
);
1216 if (helperThreadCount
) compileThreadPool
.wait();
1218 for (i
= 0; i
!= helperThreadCount
; ++i
)
1219 compileThreadPool
.schedule(boost::bind(&updateSelectorRowWidth
, sels
,
1220 selectorsPerThread
* i
, selectorsPerThread
* (i
+1)));
1222 updateSelectorRowWidth(sels
, helperThreadCount
*selectorsPerThread
, numSelectors
);
1223 if (helperThreadCount
) compileThreadPool
.wait();
1226 // sort rows by largest chunk, then by width, then by chunk offset
1227 //qsort(sels, numSelectors, sizeof(ColumnDescriptor), (std::_compare_function)compareColDescs);
1228 qsort(sels
, numSelectors
, sizeof(ColumnDescriptor
), compareColDescs
);
1230 // bin sort the class rows to the new ordering
1231 //post("reorder rows\n");
1232 for (i
= 0; i
!= helperThreadCount
; ++i
)
1233 compileThreadPool
.schedule(boost::bind(&binsortClassRows
, bigTable
, sels
, numSelectors
,
1234 classesPerThread
* i
, classesPerThread
* (i
+1)));
1236 binsortClassRows(bigTable
, sels
, numSelectors
, helperThreadCount
*classesPerThread
, numClasses
);
1237 if (helperThreadCount
) compileThreadPool
.wait();
1239 //post("calc row offsets %d\n", numSelectors);
1244 for (i
=0; i
<numSelectors
; ++i
) {
1245 widthSum
+= sels
[i
].rowWidth
;
1246 popSum
+= sels
[i
].population
;
1247 rowOffset
= sc_max(rowOffset
+1, freeIndex
- sels
[i
].minClassIndex
);
1248 freeIndex
= rowOffset
+ sels
[i
].maxClassIndex
+ 1;
1249 sels
[i
].rowOffset
= rowOffset
;
1250 sels
[i
].selector
->u
.index
= rowOffset
;
1251 //post("%3d %24s %3d %5d %5d\n", i, sels[i].selector->name,
1252 // sels[i].rowWidth, rowOffset, freeIndex);
1254 //post("alloc row table %d\n", freeIndex);
1255 rowTableSize
= (freeIndex
+ numClasses
) * sizeof(PyrMethod
*);
1256 gRowTable
= (PyrMethod
**)pyr_pool_runtime
->Alloc(rowTableSize
);
1259 // having the method ptr always be valid saves a branch in SendMessage()
1260 for (i
=0; i
<freeIndex
+ numClasses
; ++i
)
1261 gRowTable
[i
] = gNullMethod
;
1263 //post("fill compressed table\n");
1266 //fp = fopen("meth table", "w");
1267 for (i
=0; i
<numSelectors
; ++i
) {
1268 int offset
, maxwidth
;
1269 offset
= sels
[i
].rowOffset
+ sels
[i
].minClassIndex
;
1270 maxwidth
= offset
+ sels
[i
].rowWidth
;
1271 row
= bigTable
+ sels
[i
].minClassIndex
* numSelectors
+ i
;
1272 PyrMethod
** table
= gRowTable
;
1273 for (j
=offset
,k
=0; j
<maxwidth
; ++j
, k
+=numSelectors
) {
1281 for (i
=0; i
<freeIndex
+ numClasses
; ++i
)
1282 assert(gRowTable
[i
]);
1285 //post("freeIndex %d\n", freeIndex);
1286 //post("widthSum %d\n", widthSum);
1287 //post("popSum %d\n", popSum);
1289 #if CHECK_METHOD_LOOKUP_TABLE_BUILD_TIME
1290 post("building table took %.3g seconds\n", elapsedTime() - t0
);
1293 for (i
=0; i
<rowTableSize
/sizeof(PyrMethod
*); ++i
) {
1294 if (gRowTable
[i
] != gNullMethod
) numFilled
++;
1296 post("Filled %d of %d = %f percent\n", numFilled
, rowTableSize
/sizeof(PyrMethod
*),
1297 100. * (double)numFilled
/(rowTableSize
/sizeof(PyrMethod
*)));
1300 post("\t%d method selectors, %d classes\n", numSelectors
, numClasses
);
1301 post("\tmethod table size %d bytes, ", rowTableSize
);
1302 post("big table size %d\n", numSelectors
* numClasses
* sizeof(PyrMethod
*));
1303 //postfl("%p %p %p\n", classes, bigTable, sels);
1305 // not necessary since the entire pool will be freed..
1306 pyr_pool_compile->Free(classes);
1307 pyr_pool_compile->Free(bigTable);
1308 pyr_pool_compile->Free(sels);
1310 compileThreadPool
.size_controller().resize(0); // terminate threads
1313 #include <boost/atomic.hpp>
1315 static void fillClassRowSubClasses(PyrObject
* subclasses
, int begin
, int end
, PyrMethod
** bigTable
, boost::atomic
<size_t> * rCount
);
1317 static void fillClassRow(PyrClass
*classobj
, PyrMethod
** bigTable
, boost::atomic
<size_t> * rCount
)
1321 PyrMethod
** myrow
= bigTable
+ slotRawInt(&classobj
->classIndex
) * gNumSelectors
;
1322 PyrClass
* superclassobj
= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
1323 if (superclassobj
) {
1324 PyrMethod
** superrow
= bigTable
+ slotRawInt(&superclassobj
->classIndex
) * gNumSelectors
;
1326 for (int i
= 0; i
!= gNumSelectors
; ++i
) {
1327 myrow
[i
] = superrow
[i
];
1332 memset(myrow
, 0, gNumSelectors
* sizeof(PyrMethod
*));
1335 if (IsObj(&classobj
->methods
)) {
1336 PyrObject
* methods
= slotRawObject(&classobj
->methods
);
1337 //postfl(" %d\n", methods->size);
1338 for (int i
=0; i
<methods
->size
; ++i
) {
1339 PyrMethod
* method
= slotRawMethod(&methods
->slots
[i
]);
1340 int selectorIndex
= slotRawSymbol(&method
->name
)->u
.index
;
1342 if (myrow
[selectorIndex
] == 0)
1345 myrow
[selectorIndex
] = method
;
1351 if (IsObj(&classobj
->subclasses
)) {
1352 PyrObject
* subclasses
= slotRawObject(&classobj
->subclasses
);
1353 size_t numSubclasses
= subclasses
->size
;
1355 if (numSubclasses
> 4*cpuCount
) {
1356 int subclassesPerThread
= numSubclasses
/ cpuCount
;
1357 for (int i
= 0; i
!= helperThreadCount
; ++i
)
1358 compileThreadPool
.schedule(boost::bind(&fillClassRowSubClasses
, subclasses
,
1359 subclassesPerThread
* i
, subclassesPerThread
* (i
+1),
1361 fillClassRowSubClasses(subclasses
, subclassesPerThread
* helperThreadCount
, numSubclasses
, bigTable
, rCount
);
1364 fillClassRowSubClasses(subclasses
, 0, numSubclasses
, bigTable
, rCount
);
1368 static void fillClassRowSubClasses(PyrObject
* subclasses
, int begin
, int end
, PyrMethod
** bigTable
, boost::atomic
<size_t> * rCount
)
1370 for (int i
= begin
; i
!= end
; ++i
)
1371 fillClassRow(slotRawClass(&subclasses
->slots
[i
]), bigTable
, rCount
);
1375 static size_t fillClassRow(PyrClass
*classobj
, PyrMethod
** bigTable
)
1377 boost::atomic
<size_t> ret (0);
1379 fillClassRow(classobj
, bigTable
, &ret
);
1380 if (helperThreadCount
) compileThreadPool
.wait();
1381 return ret
.load(boost::memory_order_acquire
);
1385 bool funcFindArg(PyrBlock
* func
, PyrSymbol
*name
, int *index
)
1388 for (i
=0; i
<slotRawSymbolArray(&func
->argNames
)->size
; ++i
) {
1389 if (slotRawSymbolArray(&func
->argNames
)->symbols
[i
] == name
) {
1397 bool funcFindVar(PyrBlock
* func
, PyrSymbol
*name
, int *index
)
1400 for (i
=0; i
<slotRawSymbolArray(&func
->varNames
)->size
; ++i
) {
1401 if (slotRawSymbolArray(&func
->varNames
)->symbols
[i
] == name
) {
1409 PyrClass
* makeIntrinsicClass(PyrSymbol
*className
, PyrSymbol
*superClassName
,
1410 int numInstVars
, int numClassVars
)
1412 PyrClass
*superClass
= NULL
;
1413 PyrClass
*metaSuperClass
= NULL
;
1414 PyrSymbol
*metaClassName
= NULL
;
1415 PyrSymbol
*metaSuperClassName
= NULL
;
1416 PyrClass
*classobj
= NULL
;
1417 PyrClass
*metaclassobj
= NULL
;
1420 //postfl("makeIntrinsicClass '%s'\n", className->name);
1421 if (superClassName
) {
1422 superClass
= superClassName
->u
.classobj
;
1424 error("Can't find superclass '%s' of '%s'\n", superClassName
->name
,
1428 metaSuperClassName
= getmetasym(superClassName
->name
);
1429 metaSuperClass
= metaSuperClassName
->u
.classobj
;
1430 superInstVars
= numSuperInstVars(superClass
);
1432 // else it must be Object and so has no superclass
1433 metaSuperClassName
= NULL
;
1437 metaClassName
= getmetasym(className
->name
);
1438 metaClassName
->flags
|= sym_MetaClass
;
1439 metaclassobj
= newClassObj( class_class
,
1440 metaClassName
, metaSuperClassName
,
1441 classClassNumInstVars
, 0, 0, 0, obj_notindexed
, 0);
1442 SetInt(&metaclassobj
->classFlags
, slotRawInt(&metaclassobj
->classFlags
) | classIsIntrinsic
);
1444 if (metaSuperClassName
&& classClassNumInstVars
) {
1445 memcpy(slotRawObject(&metaclassobj
->iprototype
)->slots
, slotRawObject(&metaSuperClass
->iprototype
)->slots
,
1446 sizeof(PyrSlot
) * classClassNumInstVars
);
1447 memcpy(slotRawSymbolArray(&metaclassobj
->instVarNames
)->symbols
,
1448 slotRawSymbolArray(&metaSuperClass
->instVarNames
)->symbols
,
1449 sizeof(PyrSymbol
*) * classClassNumInstVars
);
1450 slotRawObject(&metaclassobj
->iprototype
)->size
= classClassNumInstVars
;
1451 slotRawObject(&metaclassobj
->instVarNames
)->size
= classClassNumInstVars
;
1452 //dumpObject((PyrObject*)metaclassobj);
1455 classobj
= newClassObj(metaclassobj
,
1456 className
, superClassName
,
1457 numInstVars
+ superInstVars
, numClassVars
, 0, 0, obj_notindexed
, 0);
1458 SetInt(&classobj
->classFlags
, slotRawInt(&classobj
->classFlags
) | classIsIntrinsic
);
1460 //postfl("%s:%s : %d\n", className->name, superClassName->name, superInstVars);
1461 if (superClass
&& superInstVars
) {
1462 memcpy(slotRawObject(&classobj
->iprototype
)->slots
, slotRawObject(&superClass
->iprototype
)->slots
,
1463 sizeof(PyrSlot
) * superInstVars
);
1464 memcpy(slotRawSymbolArray(&classobj
->instVarNames
)->symbols
,
1465 slotRawSymbolArray(&superClass
->instVarNames
)->symbols
,
1466 sizeof(PyrSymbol
*) * superInstVars
);
1467 slotRawObject(&classobj
->iprototype
)->size
= superInstVars
;
1468 slotRawObject(&classobj
->instVarNames
)->size
= superInstVars
;
1474 void addIntrinsicVar(PyrClass
*classobj
, const char *varName
, PyrSlot
*slot
)
1476 //postfl("%s %s %d\n", slotRawSymbol(&classobj->name)->name, varName,
1477 // slotRawObject(&classobj->instVarNames)->size);
1478 objAddIndexedSymbol(slotRawSymbolArray(&classobj
->instVarNames
), getsym(varName
));
1479 objAddIndexedSlot(slotRawObject(&classobj
->iprototype
), slot
);
1482 void addIntrinsicClassVar(PyrClass
*classobj
, const char *varName
, PyrSlot
*slot
);
1483 void addIntrinsicClassVar(PyrClass
*classobj
, const char *varName
, PyrSlot
*slot
)
1485 //postfl("%s %s %d\n", slotRawSymbol(&classobj->name)->name, varName,
1486 // slotRawObject(&classobj->instVarNames)->size);
1487 objAddIndexedSymbol(slotRawSymbolArray(&classobj
->classVarNames
), getsym(varName
));
1488 objAddIndexedSlot(slotRawObject(&classobj
->cprototype
), slot
);
1493 PyrClass
*class_object_meta
;
1494 PyrMethodRaw
*methraw
;
1496 // BOOTSTRAP THE OBJECT HIERARCHY
1500 gNullMethod
= newPyrMethod();
1501 SetSymbol(&gNullMethod
->name
, (PyrSymbol
*)NULL
);
1502 methraw
= METHRAW(gNullMethod
);
1503 methraw
->methType
= methNormal
;
1505 // build intrinsic classes
1507 class_object
= makeIntrinsicClass(s_object
, 0, 0, 4);
1508 class_class
= makeIntrinsicClass(s_class
, s_object
, classClassNumInstVars
, 1);
1510 // now fix class_class ptrs that were just previously installed erroneously
1511 class_object
->classptr
->classptr
= class_class
;
1512 class_class
->classptr
->classptr
= class_class
;
1513 class_object_meta
= class_object
->classptr
;
1514 class_object_meta
->superclass
= class_class
->name
;
1516 addIntrinsicClassVar(class_object
, "dependantsDictionary", &o_nil
);
1517 addIntrinsicClassVar(class_object
, "currentEnvironment", &o_nil
);
1518 addIntrinsicClassVar(class_object
, "topEnvironment", &o_nil
);
1519 addIntrinsicClassVar(class_object
, "uniqueMethods", &o_nil
);
1521 // declare varNames for Class
1523 addIntrinsicVar(class_class
, "name", &o_nil
);
1524 addIntrinsicVar(class_class
, "nextclass", &o_nil
);
1525 addIntrinsicVar(class_class
, "superclass", &o_nil
);
1526 addIntrinsicVar(class_class
, "subclasses", &o_nil
);
1527 addIntrinsicVar(class_class
, "methods", &o_nil
);
1529 addIntrinsicVar(class_class
, "instVarNames", &o_nil
);
1530 addIntrinsicVar(class_class
, "classVarNames", &o_nil
);
1531 addIntrinsicVar(class_class
, "iprototype", &o_nil
);
1532 addIntrinsicVar(class_class
, "cprototype", &o_nil
);
1534 addIntrinsicVar(class_class
, "constNames", &o_nil
);
1535 addIntrinsicVar(class_class
, "constValues", &o_nil
);
1537 addIntrinsicVar(class_class
, "instanceFormat", &o_nil
);
1538 addIntrinsicVar(class_class
, "instanceFlags", &o_zero
);
1539 addIntrinsicVar(class_class
, "classIndex", &o_zero
);
1540 addIntrinsicVar(class_class
, "classFlags", &o_zero
);
1541 addIntrinsicVar(class_class
, "maxSubclassIndex", &o_zero
);
1542 addIntrinsicVar(class_class
, "filenameSymbol", &o_nil
);
1543 addIntrinsicVar(class_class
, "charPos", &o_zero
);
1544 addIntrinsicVar(class_class
, "classVarIndex", &o_zero
);
1546 addIntrinsicClassVar(class_class
, "classesInited", &o_nil
);
1548 // class_object_meta's inst var names need to be copied from class_class
1549 // because class_class didn't exist when it was created
1550 memcpy(slotRawObject(&class_object_meta
->iprototype
)->slots
, slotRawObject(&class_class
->iprototype
)->slots
,
1551 sizeof(PyrSlot
) * classClassNumInstVars
);
1552 memcpy(slotRawSymbolArray(&class_object_meta
->instVarNames
)->symbols
,
1553 slotRawSymbolArray(&class_class
->instVarNames
)->symbols
,
1554 sizeof(PyrSymbol
*) * classClassNumInstVars
);
1556 memcpy(slotRawObject(&class_class
->classptr
->iprototype
)->slots
, slotRawObject(&class_class
->iprototype
)->slots
,
1557 sizeof(PyrSlot
) * classClassNumInstVars
);
1558 memcpy(slotRawSymbolArray(&class_class
->classptr
->instVarNames
)->symbols
,
1559 slotRawSymbolArray(&class_class
->instVarNames
)->symbols
,
1560 sizeof(PyrSymbol
*) * classClassNumInstVars
);
1563 // OK the next thing I need is arrays..
1564 class_collection
= makeIntrinsicClass(s_collection
, s_object
, 0, 0);
1565 class_sequenceable_collection
= makeIntrinsicClass(s_sequenceable_collection
, s_collection
, 0, 0);
1567 class_arrayed_collection
= makeIntrinsicClass(s_arrayed_collection
, s_sequenceable_collection
, 0, 0);
1568 class_array
= makeIntrinsicClass(s_array
, s_arrayed_collection
, 0, 0);
1569 SetInt(&class_array
->instanceFormat
, obj_slot
);
1570 SetInt(&class_array
->classFlags
, slotRawInt(&class_array
->classFlags
) | classHasIndexableInstances
);
1572 // now fix array classptrs in already created classes
1573 fixClassArrays(class_class
);
1574 fixClassArrays(class_class
->classptr
);
1575 fixClassArrays(class_object_meta
);
1576 fixClassArrays(class_collection
);
1577 fixClassArrays(class_sequenceable_collection
);
1578 fixClassArrays(class_arrayed_collection
);
1579 fixClassArrays(class_array
);
1581 class_fundef
= makeIntrinsicClass(s_fundef
, s_object
, 10, 0);
1582 // declare varNames for Block
1584 addIntrinsicVar(class_fundef
, "raw1", &o_nil
);
1585 addIntrinsicVar(class_fundef
, "raw2", &o_nil
);
1586 addIntrinsicVar(class_fundef
, "code", &o_nil
);
1587 addIntrinsicVar(class_fundef
, "selectors", &o_nil
);
1588 addIntrinsicVar(class_fundef
, "constants", &o_nil
);
1590 addIntrinsicVar(class_fundef
, "prototypeFrame", &o_nil
);
1591 addIntrinsicVar(class_fundef
, "context", &o_nil
);
1592 addIntrinsicVar(class_fundef
, "argNames", &o_nil
);
1593 addIntrinsicVar(class_fundef
, "varNames", &o_nil
);
1594 addIntrinsicVar(class_fundef
, "sourceCode", &o_nil
);
1596 class_method
= makeIntrinsicClass(s_method
, s_fundef
, 5, 0);
1597 addIntrinsicVar(class_method
, "ownerClass", &o_nil
);
1598 addIntrinsicVar(class_method
, "name", &o_nil
);
1599 addIntrinsicVar(class_method
, "primitiveName", &o_nil
);
1600 addIntrinsicVar(class_method
, "filenameSymbol", &o_nil
);
1601 addIntrinsicVar(class_method
, "charPos", &o_zero
);
1602 //addIntrinsicVar(class_method, "byteMeter", &o_zero);
1603 //addIntrinsicVar(class_method, "callMeter", &o_zero);
1605 class_frame
= makeIntrinsicClass(s_frame
, s_object
, 0, 0);
1606 SetInt(&class_frame
->classFlags
, slotRawInt(&class_frame
->classFlags
) | classHasIndexableInstances
);
1607 //addIntrinsicVar(class_frame, "method", &o_nil);
1608 //addIntrinsicVar(class_frame, "caller", &o_nil);
1609 //addIntrinsicVar(class_frame, "context", &o_nil);
1610 //addIntrinsicVar(class_frame, "homeContext", &o_nil);
1611 //addIntrinsicVar(class_frame, "ip", &o_nil);
1613 class_process
= makeIntrinsicClass(s_process
, s_object
, 6, 0);
1614 addIntrinsicVar(class_process
, "classVars", &o_nil
);
1615 addIntrinsicVar(class_process
, "interpreter", &o_nil
);
1616 addIntrinsicVar(class_process
, "curThread", &o_nil
);
1617 addIntrinsicVar(class_process
, "mainThread", &o_nil
);
1618 addIntrinsicVar(class_process
, "schedulerQueue", &o_nil
);
1619 addIntrinsicVar(class_process
, "nowExecutingPath", &o_nil
);
1621 class_interpreter
= makeIntrinsicClass(s_interpreter
, s_object
, 29, 0);
1622 addIntrinsicVar(class_interpreter
, "cmdLine", &o_nil
);
1623 addIntrinsicVar(class_interpreter
, "context", &o_nil
);
1624 for (int i
=0; i
<26; ++i
) {
1628 addIntrinsicVar(class_interpreter
, name
, &o_nil
);
1630 addIntrinsicVar(class_interpreter
, "codeDump", &o_nil
);
1631 addIntrinsicVar(class_interpreter
, "preProcessor", &o_nil
);
1633 class_absfunc
= makeIntrinsicClass(s_absfunc
, s_object
, 0, 0);
1634 class_stream
= makeIntrinsicClass(s_stream
, s_absfunc
, 0, 0);
1636 class_thread
= makeIntrinsicClass(s_thread
, s_stream
, 26, 0);
1637 addIntrinsicVar(class_thread
, "state", &o_nil
);
1638 addIntrinsicVar(class_thread
, "func", &o_nil
);
1639 addIntrinsicVar(class_thread
, "stack", &o_nil
);
1640 addIntrinsicVar(class_thread
, "method", &o_nil
);
1641 addIntrinsicVar(class_thread
, "block", &o_nil
);
1642 addIntrinsicVar(class_thread
, "frame", &o_nil
);
1643 addIntrinsicVar(class_thread
, "ip", &o_zero
);
1644 addIntrinsicVar(class_thread
, "sp", &o_zero
);
1645 addIntrinsicVar(class_thread
, "numpop", &o_zero
);
1646 addIntrinsicVar(class_thread
, "receiver", &o_nil
);
1647 addIntrinsicVar(class_thread
, "numArgsPushed", &o_zero
);
1648 addIntrinsicVar(class_thread
, "parent", &o_nil
);
1649 addIntrinsicVar(class_thread
, "terminalValue", &o_nil
);
1651 addIntrinsicVar(class_thread
, "primitiveError", &o_zero
);
1652 addIntrinsicVar(class_thread
, "primitiveIndex", &o_zero
);
1653 addIntrinsicVar(class_thread
, "randData", &o_zero
);
1654 addIntrinsicVar(class_thread
, "beats", &o_fzero
);
1655 addIntrinsicVar(class_thread
, "seconds", &o_fzero
);
1656 addIntrinsicVar(class_thread
, "clock", &o_nil
);
1657 addIntrinsicVar(class_thread
, "nextBeat", &o_nil
);
1658 addIntrinsicVar(class_thread
, "endBeat", &o_nil
);
1659 addIntrinsicVar(class_thread
, "endValue", &o_nil
);
1661 addIntrinsicVar(class_thread
, "environment", &o_nil
);
1662 addIntrinsicVar(class_thread
, "exceptionHandler", &o_nil
);
1664 addIntrinsicVar(class_thread
, "executingPath", &o_nil
);
1665 addIntrinsicVar(class_thread
, "oldExecutingPath", &o_nil
);
1667 class_finalizer
= makeIntrinsicClass(s_finalizer
, s_object
, 2, 0);
1668 addIntrinsicVar(class_finalizer
, "cFunction", &o_nil
);
1669 addIntrinsicVar(class_finalizer
, "object", &o_nil
);
1671 class_routine
= makeIntrinsicClass(s_routine
, s_thread
, 0, 0);
1673 class_symbol
= makeIntrinsicClass(s_symbol
, s_object
, 0, 0);
1674 class_nil
= makeIntrinsicClass(s_nil
, s_object
, 0, 0);
1676 class_boolean
= makeIntrinsicClass(s_boolean
, s_object
, 0, 0);
1677 class_true
= makeIntrinsicClass(s_true
, s_boolean
, 0, 0);
1678 class_false
= makeIntrinsicClass(s_false
, s_boolean
, 0, 0);
1680 class_magnitude
= makeIntrinsicClass(s_magnitude
, s_object
, 0, 0);
1681 class_char
= makeIntrinsicClass(s_char
, s_magnitude
, 0, 0);
1682 class_number
= makeIntrinsicClass(s_number
, s_magnitude
, 0, 0);
1683 class_simple_number
= makeIntrinsicClass(s_simple_number
, s_number
, 0, 0);
1684 class_int
= makeIntrinsicClass(s_int
, s_simple_number
, 0, 0);
1685 class_float
= makeIntrinsicClass(s_float
, s_simple_number
, 0, 0);
1687 class_rawptr
= makeIntrinsicClass(s_rawptr
, s_object
, 0, 0);
1690 class_complex = makeIntrinsicClass(s_complex, s_number, 2, 0);
1691 addIntrinsicVar(class_complex, "real", &o_nil);
1692 addIntrinsicVar(class_complex, "imag", &o_nil);
1695 class_rawarray
= makeIntrinsicClass(s_rawarray
, s_arrayed_collection
, 0, 0);
1696 //SetInt(&class_rawarray->instanceFormat, obj_int8);
1697 //slotRawInt(&class_rawarray->classFlags) |= classHasIndexableInstances;
1698 class_int8array
= makeIntrinsicClass(s_int8array
, s_rawarray
, 0, 0);
1699 SetInt(&class_int8array
->instanceFormat
, obj_int8
);
1700 SetInt(&class_int8array
->classFlags
, slotRawInt(&class_int8array
->classFlags
) | classHasIndexableInstances
);
1701 class_int16array
= makeIntrinsicClass(s_int16array
, s_rawarray
, 0, 0);
1702 SetInt(&class_int16array
->instanceFormat
, obj_int16
);
1703 SetInt(&class_int16array
->classFlags
, slotRawInt(&class_int16array
->classFlags
) | classHasIndexableInstances
);
1704 class_int32array
= makeIntrinsicClass(s_int32array
, s_rawarray
, 0, 0);
1705 SetInt(&class_int32array
->instanceFormat
, obj_int32
);
1706 SetInt(&class_int32array
->classFlags
, slotRawInt(&class_int32array
->classFlags
) | classHasIndexableInstances
);
1707 class_symbolarray
= makeIntrinsicClass(s_symbolarray
, s_rawarray
, 0, 0);
1708 SetInt(&class_symbolarray
->instanceFormat
, obj_symbol
);
1709 SetInt(&class_symbolarray
->classFlags
, slotRawInt(&class_symbolarray
->classFlags
) | classHasIndexableInstances
);
1710 class_string
= makeIntrinsicClass(s_string
, s_rawarray
, 0, 1);
1711 addIntrinsicClassVar(class_string
, "unixCmdActions", &o_nil
);
1712 SetInt(&class_string
->instanceFormat
, obj_char
);
1713 SetInt(&class_string
->classFlags
, slotRawInt(&class_string
->classFlags
) | classHasIndexableInstances
);
1714 class_floatarray
= makeIntrinsicClass(s_floatarray
, s_rawarray
, 0, 0);
1715 SetInt(&class_floatarray
->instanceFormat
, obj_float
);
1716 SetInt(&class_floatarray
->classFlags
, slotRawInt(&class_floatarray
->classFlags
) | classHasIndexableInstances
);
1717 class_signal
= makeIntrinsicClass(s_signal
, s_floatarray
, 0, 0);
1718 SetInt(&class_signal
->instanceFormat
, obj_float
);
1719 SetInt(&class_signal
->classFlags
, slotRawInt(&class_signal
->classFlags
) | classHasIndexableInstances
);
1720 class_wavetable
= makeIntrinsicClass(s_wavetable
, s_floatarray
, 0, 0);
1721 SetInt(&class_wavetable
->instanceFormat
, obj_float
);
1722 SetInt(&class_wavetable
->classFlags
, slotRawInt(&class_wavetable
->classFlags
) | classHasIndexableInstances
);
1724 //addIntrinsicVar(class_signal, "rate", &o_nil);
1725 class_doublearray
= makeIntrinsicClass(s_doublearray
, s_rawarray
, 0, 0);
1726 SetInt(&class_doublearray
->instanceFormat
, obj_double
);
1727 SetInt(&class_doublearray
->classFlags
, slotRawInt(&class_doublearray
->classFlags
) | classHasIndexableInstances
);
1729 class_list
= makeIntrinsicClass(s_list
, s_sequenceable_collection
, 1, 0);
1730 addIntrinsicVar(class_list
, "array", &o_nil
);
1731 //addIntrinsicVar(class_list, "size", &o_zero);
1733 class_func
= makeIntrinsicClass(s_func
, s_absfunc
, 2, 0);
1734 addIntrinsicVar(class_func
, "def", &o_nil
);
1735 addIntrinsicVar(class_func
, "context", &o_nil
);
1737 gTagClassTable
[ 0] = NULL
;
1738 gTagClassTable
[ 1] = NULL
;
1739 gTagClassTable
[ 2] = class_int
;
1740 gTagClassTable
[ 3] = class_symbol
;
1741 gTagClassTable
[ 4] = class_char
;
1742 gTagClassTable
[ 5] = class_nil
;
1743 gTagClassTable
[ 6] = class_false
;
1744 gTagClassTable
[ 7] = class_true
;
1745 gTagClassTable
[ 8] = class_rawptr
;
1746 gTagClassTable
[ 9] = class_float
;
1747 gTagClassTable
[10] = class_float
;
1748 gTagClassTable
[11] = class_float
;
1749 gTagClassTable
[12] = class_float
;
1751 SetObject(&o_emptyarray
, newPyrArray(NULL
, 0, obj_permanent
| obj_immutable
, false));
1753 SetObject(&o_onenilarray
, newPyrArray(NULL
, 1, obj_permanent
| obj_immutable
, false));
1754 slotRawObject(&o_onenilarray
)->size
= 1;
1755 SetNil(slotRawObject(&o_onenilarray
)->slots
);
1757 SetObject(&o_argnamethis
, newPyrSymbolArray(NULL
, 1, obj_permanent
| obj_immutable
, false));
1758 slotRawSymbolArray(&o_argnamethis
)->size
= 1;
1759 slotRawSymbolArray(&o_argnamethis
)->symbols
[0] = s_this
;
1762 post("array %p '%s'\n", class_array, class_array->name.us->name);
1763 post("o_emptyarray %p '%s'\n", slotRawObject(&o_emptyarray)->classptr, slotRawObject(&o_emptyarray)->classptr->name.us->name);
1764 post("o_argnamethis %p '%s'\n", slotRawObject(&o_argnamethis)->classptr, slotRawObject(&o_argnamethis)->classptr->name.us->name);
1765 post("o_onenilarray %p '%s'\n", slotRawObject(&o_onenilarray)->classptr, slotRawObject(&o_onenilarray)->classptr->name.us->name);
1766 dumpObjectSlot(&o_emptyarray);
1767 dumpObjectSlot(&o_argnamethis);
1768 dumpObjectSlot(&o_onenilarray);
1772 PyrObject
* instantiateObject(class PyrGC
*gc
, PyrClass
* classobj
, int size
,
1773 bool fill
, bool collect
)
1775 PyrObject
*newobj
, *proto
;
1776 int numbytes
, format
, flags
;
1778 format
= slotRawInt(&classobj
->instanceFormat
);
1779 flags
= slotRawInt(&classobj
->instanceFlags
);
1781 if (slotRawInt(&classobj
->classFlags
) & classHasIndexableInstances
) {
1782 // create an indexable object
1783 numbytes
= size
* gFormatElemSize
[format
];
1784 newobj
= gc
->New(numbytes
, flags
, format
, collect
);
1786 newobj
->size
= size
;
1787 if (format
== obj_slot
) {
1788 nilSlots(newobj
->slots
, size
);
1790 memset(newobj
->slots
, format
== obj_char
? ' ' : 0, size
* gFormatElemSize
[format
]);
1796 if (IsObj(&classobj
->iprototype
)) {
1797 proto
= slotRawObject(&classobj
->iprototype
);
1799 numbytes
= size
* sizeof(PyrSlot
);
1800 newobj
= gc
->New(numbytes
, flags
, format
, collect
);
1801 newobj
->size
= size
;
1803 memcpy(newobj
->slots
, proto
->slots
, numbytes
);
1807 newobj
= gc
->New(numbytes
, flags
, format
, collect
);
1811 newobj
->classptr
= classobj
;
1815 PyrObject
* instantiateObjectLight(class PyrGC
*gc
, PyrClass
* classobj
, int size
, bool collect
);
1816 PyrObject
* instantiateObjectLight(class PyrGC
*gc
, PyrClass
* classobj
, int size
, bool collect
)
1818 PyrObject
*newobj
, *proto
;
1819 int numbytes
, format
, flags
;
1821 format
= slotRawInt(&classobj
->instanceFormat
);
1822 flags
= slotRawInt(&classobj
->instanceFlags
);
1824 if (slotRawInt(&classobj
->classFlags
) & classHasIndexableInstances
) {
1825 numbytes
= size
* gFormatElemSize
[format
];
1827 if (IsObj(&classobj
->iprototype
)) {
1828 proto
= slotRawObject(&classobj
->iprototype
);
1830 numbytes
= size
* sizeof(PyrSlot
);
1836 newobj
= gc
->New(numbytes
, flags
, format
, collect
);
1837 newobj
->size
= size
;
1838 newobj
->classptr
= classobj
;
1843 PyrObject
* copyObject(class PyrGC
*gc
, PyrObject
*inobj
, bool collect
)
1847 int flags
= ~(obj_immutable
) & inobj
->obj_flags
;
1849 int elemsize
= gFormatElemSize
[inobj
->obj_format
];
1850 int numbytes
= inobj
->size
* elemsize
;
1852 newobj
= gc
->New(numbytes
, flags
, inobj
->obj_format
, collect
);
1854 newobj
->size
= inobj
->size
;
1855 newobj
->classptr
= inobj
->classptr
;
1857 memcpy(newobj
->slots
, inobj
->slots
, inobj
->size
* elemsize
);
1861 PyrObject
* copyObjectRange(class PyrGC
*gc
, PyrObject
*inobj
, int start
, int end
, bool collect
)
1865 if (start
< 0) start
= 0;
1866 if (end
>= inobj
->size
) end
= inobj
->size
- 1;
1867 int length
= end
- start
+ 1;
1868 if (length
< 0) length
= 0;
1870 int elemsize
= gFormatElemSize
[inobj
->obj_format
];
1871 int numbytes
= length
* elemsize
;
1873 int flags
= ~(obj_immutable
) & inobj
->obj_flags
;
1875 newobj
= gc
->New(numbytes
, flags
, inobj
->obj_format
, collect
);
1876 newobj
->size
= length
;
1877 newobj
->classptr
= inobj
->classptr
;
1880 memcpy(newobj
->slots
, (char*)(inobj
->slots
) + start
* elemsize
, length
* elemsize
);
1885 void dumpObject(PyrObject
*obj
)
1892 postfl("NULL object pointer\n");
1895 classobj
= obj
->classptr
;
1896 if (isKindOf(obj
, class_class
)) {
1897 post("class %s (%p) {\n", slotRawSymbol(&((PyrClass
*)obj
)->name
)->name
, obj
);
1899 //post("Instance of %s (%p) {\n", slotRawSymbol(&classobj->name)->name, obj);
1900 post("Instance of %s { (%p, gc=%02X, fmt=%02X, flg=%02X, set=%02X)\n",
1901 slotRawSymbol(&classobj
->name
)->name
, obj
, obj
->gc_color
, obj
->obj_format
, obj
->obj_flags
,
1902 obj
->obj_sizeclass
);
1906 if (obj
->obj_format
== obj_notindexed
) {
1907 post(" instance variables [%d]\n", obj
->size
);
1908 for (i
=0; i
<obj
->size
; ++i
) {
1909 slotString(obj
->slots
+ i
, str
);
1910 post(" %s : %s\n", slotRawSymbolArray(&classobj
->instVarNames
)->symbols
[i
]->name
, str
);
1914 post(" indexed slots [%d]\n", obj
->size
);
1915 maxsize
= sc_min(32, obj
->size
);
1916 switch (obj
->obj_format
) {
1918 for (i
=0; i
<maxsize
; ++i
) {
1919 slotString(obj
->slots
+ i
, str
);
1920 post(" %3d : %s\n", i
, str
);
1924 for (i
=0; i
<maxsize
; ++i
) {
1925 post(" %3d : %f\n", i
, slotRawFloat(&obj
->slots
[i
]));
1929 for (i
=0; i
<maxsize
; ++i
) {
1931 val
= ((float*)(obj
->slots
))[i
];
1932 post(" %3d : %g\n", i
, val
);
1936 for (i
=0; i
<maxsize
; ++i
) {
1938 val
= ((int32
*)(obj
->slots
))[i
];
1939 post(" %3d : %d\n", i
, val
);
1943 for (i
=0; i
<maxsize
; ++i
) {
1945 val
= ((int16
*)(obj
->slots
))[i
];
1946 post(" %3d : %d\n", i
, val
);
1950 for (i
=0; i
<maxsize
; ++i
) {
1952 val
= ((int8
*)(obj
->slots
))[i
];
1953 post(" %3d : %4d %4u 0x%02X\n", i
, val
, val
&255, val
&255);
1957 for (i
=0; i
<maxsize
; ++i
) {
1959 val
= ((char*)(obj
->slots
))[i
];
1960 post(" %3d : %c\n", i
, val
);
1964 for (i
=0; i
<maxsize
; ++i
) {
1966 sym
= ((PyrSymbol
**)(obj
->slots
))[i
];
1967 post(" %3d : '%s'\n", i
, sym
->name
);
1971 post("unknown obj_format %X\n", obj
->obj_format
);
1973 if (obj
->size
> maxsize
) {
1980 void dumpBadObject(PyrObject
*obj
)
1987 postfl("NULL object pointer\n");
1990 classobj
= obj
->classptr
;
1991 if (isKindOf(obj
, class_class
)) {
1992 postfl("class %s (%p) {\n", slotRawSymbol(&((PyrClass
*)obj
)->name
)->name
, obj
);
1994 //postfl("Instance of %s (%p) {\n", slotRawSymbol(&classobj->name)->name, obj);
1995 postfl("Instance of %s { (%p, gc=%02X, fmt=%02X, flg=%02X, set=%02X)\n",
1996 slotRawSymbol(&classobj
->name
)->name
, obj
, obj
->gc_color
, obj
->obj_format
, obj
->obj_flags
,
1997 obj
->obj_sizeclass
);
1999 if (obj
->obj_format
== obj_notindexed
) {
2000 postfl(" instance variables [%d]\n", obj
->size
);
2001 for (i
=0; i
<obj
->size
; ++i
) {
2002 slotString(obj
->slots
+ i
, str
);
2003 postfl(" %s : %s\n", slotRawSymbolArray(&classobj
->instVarNames
)->symbols
[i
]->name
, str
);
2007 postfl(" indexed slots [%d]\n", obj
->size
);
2008 maxsize
= obj
->size
;
2009 maxsize
= sc_min(32, maxsize
);
2010 switch (obj
->obj_format
) {
2012 for (i
=0; i
<maxsize
; ++i
) {
2013 slotString(obj
->slots
+ i
, str
);
2014 postfl(" %3d : %s\n", i
, str
);
2018 for (i
=0; i
<maxsize
; ++i
) {
2019 postfl(" %3d : %f\n", i
, slotRawFloat(&obj
->slots
[i
]));
2023 for (i
=0; i
<maxsize
; ++i
) {
2025 val
= ((float*)(obj
->slots
))[i
];
2026 postfl(" %3d : %g\n", i
, val
);
2030 for (i
=0; i
<maxsize
; ++i
) {
2032 val
= ((int32
*)(obj
->slots
))[i
];
2033 postfl(" %3d : %d\n", i
, val
);
2037 for (i
=0; i
<maxsize
; ++i
) {
2039 val
= ((int16
*)(obj
->slots
))[i
];
2040 postfl(" %3d : %d\n", i
, val
);
2044 for (i
=0; i
<maxsize
; ++i
) {
2046 val
= ((int8
*)(obj
->slots
))[i
];
2047 postfl(" %3d : %4d %4u 0x%02X\n", i
, val
, val
&255, val
&255);
2051 for (i
=0; i
<maxsize
; ++i
) {
2053 val
= ((char*)(obj
->slots
))[i
];
2054 postfl(" %3d : %c\n", i
, val
);
2058 for (i
=0; i
<maxsize
; ++i
) {
2060 sym
= ((PyrSymbol
**)(obj
->slots
))[i
];
2061 post(" %3d : '%s'\n", i
, sym
->name
);
2065 postfl("unknown obj_format %X\n", obj
->obj_format
);
2067 if (obj
->size
> maxsize
) {
2074 void dumpObjectSlot(PyrSlot
*slot
)
2077 dumpObject(slotRawObject(slot
));
2083 void dumpSlotOneWord(const char *tagstr
, PyrSlot
*slot
)
2086 slotOneWord(slot
, str
);
2087 post("%s %s\n", tagstr
, str
);
2090 void CallStackSanity(VMGlobals
*g
, const char *tagstr
);
2091 void CallStackSanity(VMGlobals
*g
, const char *tagstr
)
2096 if (FrameSanity(frame
, tagstr
)) {
2101 frame
= slotRawFrame(&frame
->caller
);
2105 bool FrameSanity(PyrFrame
*frame
, const char *tagstr
);
2106 bool FrameSanity(PyrFrame
*frame
, const char *tagstr
)
2108 bool failed
= false;
2109 if (frame
==NULL
) return false;
2110 if (NotObj(&frame
->method
)) {
2111 postfl("Frame %p method tag wrong %p\n", frame
, GetTag(&frame
->method
));
2113 //} else if (!isKindOf((PyrObject*)slotRawObject(&frame->method)->classptr, class_fundef)) {
2114 } else if (slotRawObject(&frame
->method
)->classptr
!= class_method
&& slotRawObject(&frame
->method
)->classptr
!= class_fundef
) {
2115 postfl("Frame %p method class wrong %p\n", frame
, slotRawObject(&frame
->method
)->classptr
);
2117 //if (slotRawObject(&frame->method)->classptr->classptr == class_class) {
2118 postfl("class: '%s'\n", slotRawSymbol(&slotRawObject(&frame
->method
)->classptr
->name
)->name
);
2120 // postfl("not even a class\n");
2122 } else if (NotObj(&slotRawBlock(&frame
->method
)->code
)) {
2123 postfl("Method %p code tag wrong %p\n", slotRawBlock(&frame
->method
), GetTag(&slotRawBlock(&frame
->method
)->code
));
2125 } else if (slotRawObject(&slotRawBlock(&frame
->method
)->code
)->classptr
!= class_int8array
) {
2126 postfl("Code %p class wrong %p\n", slotRawObject(&slotRawBlock(&frame
->method
)->code
), slotRawObject(&slotRawBlock(&frame
->method
)->code
)->classptr
);
2127 postfl("class: '%s'\n", slotRawSymbol(&slotRawObject(&slotRawBlock(&frame
->method
)->code
)->classptr
->name
)->name
);
2131 if (frame->caller.utag != tagHFrame && frame->caller.utag != tagNil) {
2132 postfl("Frame %p caller tag wrong %p\n", frame, frame->caller.utag);
2135 if (frame->context.utag != tagHFrame && frame->context.utag != tagNil) {
2136 postfl("Frame %p context tag wrong %p\n", frame, frame->context.utag);
2139 if (frame->homeContext.utag != tagHFrame && frame->homeContext.utag != tagNil) {
2140 postfl("Frame %p homeContext tag wrong %p\n", frame, frame->homeContext.utag);
2144 if (!IsPtr(&frame
->ip
)) {
2145 postfl("Frame %p ip tag wrong %p\n", frame
, GetTag(&frame
->ip
));
2151 void DumpFrame(PyrFrame
*frame
)
2156 PyrMethodRaw
*methraw
;
2158 if (FrameSanity(frame
, "DumpFrame")) {
2159 post("FRAME CORRUPTED\n");
2162 slotOneWord(&frame
->method
, str
);
2163 //slotString(&frame->method, str);
2165 meth
= slotRawMethod(&frame
->method
);
2166 methraw
= METHRAW(meth
);
2167 if (methraw
->numtemps
) {
2168 post("\t%s %p\n", str
, frame
);
2169 numargs
= methraw
->numargs
+ methraw
->varargs
;
2170 for (i
=0; i
<methraw
->numtemps
; ++i
) {
2171 slotOneWord(frame
->vars
+ i
, str
);
2172 //slotString(frame->vars + i, str);
2174 post("\t\targ %s = %s\n", slotRawSymbolArray(&meth
->argNames
)->symbols
[i
]->name
, str
);
2176 post("\t\tvar %s = %s\n", slotRawSymbolArray(&meth
->varNames
)->symbols
[i
- numargs
]->name
, str
);
2180 post("\t%s (no arguments or variables)\n", str
);
2184 void dumpByteCodes(PyrBlock
*theBlock
);
2186 void DumpDetailedFrame(PyrFrame
*frame
);
2187 void DumpDetailedFrame(PyrFrame
*frame
)
2193 PyrMethodRaw
*methraw
;
2195 if (FrameSanity(frame
, "DumpDetailedFrame")) {
2196 post("FRAME CORRUPTED\n");
2199 slotOneWord(&frame
->method
, mstr
);
2200 //slotString(&frame->method, str);
2202 meth
= slotRawMethod(&frame
->method
);
2203 methraw
= METHRAW(meth
);
2205 if (methraw
->numtemps
) {
2206 post("\t%s\n", mstr
);
2207 numargs
= methraw
->numargs
+ methraw
->varargs
;
2208 for (i
=0; i
<methraw
->numtemps
; ++i
) {
2209 slotOneWord(frame
->vars
+ i
, str
);
2210 //slotString(frame->vars + i, str);
2212 post("\t\targ %s = %s\n", slotRawSymbolArray(&meth
->argNames
)->symbols
[i
]->name
, str
);
2214 post("\t\tvar %s = %s\n", slotRawSymbolArray(&meth
->varNames
)->symbols
[i
- numargs
]->name
, str
);
2218 post("\t%s (no arguments or variables)\n", mstr
);
2221 post("\t....%s details:\n", mstr
);
2222 post("\t\tneedsHeapContext = %d\n", methraw
->needsHeapContext
);
2223 post("\t\tnumtemps = %d\n", methraw
->numtemps
);
2224 post("\t\tpopSize = %d\n", methraw
->popSize
);
2226 slotString(&frame
->method
, str
); post("\t\tmethod = %s\n", str
);
2227 slotString(&frame
->caller
, str
); post("\t\tcaller = %s\n", str
);
2228 slotString(&frame
->context
, str
); post("\t\tcontext = %s\n", str
);
2229 slotString(&frame
->homeContext
, str
); post("\t\thomeCtx = %s\n", str
);
2230 slotString(&frame
->ip
, str
); post("\t\tip = %s\n", str
);
2232 if (IsPtr(&frame
->ip
)) {
2233 post("ipoffset = %d\n", (char*)slotRawPtr(&frame
->ip
) - (char*)slotRawInt8Array(&meth
->code
)->b
);
2234 dumpByteCodes(meth
);
2240 bool respondsTo(PyrSlot
*slot
, PyrSymbol
*selector
)
2246 classobj
= classOfSlot(slot
);
2248 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
2249 meth
= gRowTable
[index
];
2250 return slotRawSymbol(&meth
->name
) == selector
;
2253 PyrMethod
* methodLookup(PyrSlot
*slot
, PyrSymbol
*selector
);
2254 PyrMethod
* methodLookup(PyrSlot
*slot
, PyrSymbol
*selector
)
2260 classobj
= classOfSlot(slot
);
2262 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
2263 meth
= gRowTable
[index
];
2268 bool isSubclassOf(PyrClass
*classobj
, PyrClass
*testclass
)
2271 if (classobj
== testclass
) {
2274 classobj
= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
2279 /*bool isKindOf(PyrObjectHdr *obj, PyrClass *testclass)
2281 int objClassIndex = slotRawInt(&obj->classptr->classIndex);
2282 return objClassIndex >= slotRawInt(&testclass->classIndex) && objClassIndex <= slotRawInt(&testclass->maxSubclassIndex);
2285 bool objAddIndexedSlot(PyrObject
*obj
, PyrSlot
*slot
)
2287 if (obj
->size
< ARRAYMAXINDEXSIZE(obj
)) {
2288 slotCopy(&obj
->slots
[obj
->size
++], slot
);
2295 bool objAddIndexedSymbol(PyrSymbolArray
*obj
, PyrSymbol
*symbol
)
2297 if (obj
->size
< MAXINDEXSIZE((PyrObject
*)obj
)) {
2298 obj
->symbols
[obj
->size
++] = symbol
;
2305 bool objAddIndexedObject(PyrObject
*obj
, PyrObject
*obj2
)
2307 if (obj
->size
< ARRAYMAXINDEXSIZE(obj
)) {
2308 SetObject(obj
->slots
+ obj
->size
, obj2
);
2316 void fillSlots(PyrSlot
* slot
, int size
, PyrSlot
* fillslot
)
2318 for (int i
= 0; i
!= size
; ++i
)
2319 slotCopy(&slot
[i
], fillslot
);
2322 void nilSlots(PyrSlot
* slot
, int size
)
2324 fillSlots(slot
, size
, &o_nil
);
2327 void zeroSlots(PyrSlot
* slot
, int size
)
2330 SetTagRaw(&zero
, 0);
2332 fillSlots(slot
, size
, &zero
);
2335 PyrObject
* newPyrObject(class PyrGC
*gc
, size_t inNumBytes
, int inFlags
, int inFormat
, bool inCollect
)
2337 return gc
->New(inNumBytes
, inFlags
, inFormat
, inCollect
);
2340 PyrObject
* newPyrArray(class PyrGC
*gc
, int size
, int flags
, bool collect
)
2344 int numbytes
= size
* sizeof(PyrSlot
);
2346 array
= PyrGC::NewPermanent(numbytes
, flags
, obj_slot
);
2348 array
= gc
->New(numbytes
, flags
, obj_slot
, collect
);
2349 array
->classptr
= class_array
;
2353 PyrSymbolArray
* newPyrSymbolArray(class PyrGC
*gc
, int size
, int flags
, bool collect
)
2355 PyrSymbolArray
* array
;
2357 int numbytes
= size
* sizeof(PyrSymbol
*);
2358 if (!gc
) array
= (PyrSymbolArray
*)PyrGC::NewPermanent(numbytes
, flags
, obj_symbol
);
2359 else array
= (PyrSymbolArray
*)gc
->New(numbytes
, flags
, obj_symbol
, collect
);
2360 array
->classptr
= class_symbolarray
;
2364 PyrInt8Array
* newPyrInt8Array(class PyrGC
*gc
, int size
, int flags
, bool collect
)
2366 PyrInt8Array
* array
;
2368 if (!gc
) array
= (PyrInt8Array
*)PyrGC::NewPermanent(size
, flags
, obj_int8
);
2369 else array
= (PyrInt8Array
*)gc
->New(size
, flags
, obj_int8
, collect
);
2370 array
->classptr
= class_int8array
;
2374 PyrInt32Array
* newPyrInt32Array(class PyrGC
*gc
, int size
, int flags
, bool collect
)
2376 PyrInt32Array
* array
;
2377 int numbytes
= size
* sizeof(int32
);
2378 if (!gc
) array
= (PyrInt32Array
*)PyrGC::NewPermanent(numbytes
, flags
, obj_int32
);
2379 else array
= (PyrInt32Array
*)gc
->New(numbytes
, flags
, obj_int32
, collect
);
2380 array
->classptr
= class_int32array
;
2384 PyrDoubleArray
* newPyrDoubleArray(class PyrGC
*gc
, int size
, int flags
, bool collect
)
2386 PyrDoubleArray
* array
;
2388 int numbytes
= size
* sizeof(double);
2389 if (!gc
) array
= (PyrDoubleArray
*)PyrGC::NewPermanent(numbytes
, flags
, obj_double
);
2390 else array
= (PyrDoubleArray
*)gc
->New(size
, flags
, obj_double
, collect
);
2391 array
->classptr
= class_doublearray
;
2395 PyrString
* newPyrString(class PyrGC
*gc
, const char *s
, int flags
, bool collect
)
2398 int length
= strlen(s
);
2400 if (!gc
) string
= (PyrString
*)PyrGC::NewPermanent(length
, flags
, obj_char
);
2401 else string
= (PyrString
*)gc
->New(length
, flags
, obj_char
, collect
);
2402 string
->classptr
= class_string
;
2403 string
->size
= length
;
2404 memcpy(string
->s
, s
, length
);
2408 PyrString
* newPyrStringN(class PyrGC
*gc
, int length
, int flags
, bool collect
)
2412 if (!gc
) string
= (PyrString
*)PyrGC::NewPermanent(length
, flags
, obj_char
);
2413 else string
= (PyrString
*)gc
->New(length
, flags
, obj_char
, collect
);
2414 string
->classptr
= class_string
;
2415 string
->size
= length
; // filled with garbage!
2419 PyrBlock
* newPyrBlock(int flags
)
2422 PyrMethodRaw
*methraw
;
2425 int32 numbytes
= sizeof(PyrBlock
) - sizeof(PyrObjectHdr
);
2426 int32 numSlots
= numbytes
/ sizeof(PyrSlot
);
2428 if (!compilingCmdLine
) block
= (PyrBlock
*)PyrGC::NewPermanent(numbytes
, flags
, obj_notindexed
);
2429 else block
= (PyrBlock
*)gMainVMGlobals
->gc
->New(numbytes
, flags
, obj_notindexed
, false);
2430 block
->classptr
= class_fundef
;
2431 block
->size
= numSlots
;
2433 // clear out raw area
2434 methraw
= METHRAW(block
);
2435 methraw
->specialIndex
= 0;
2436 methraw
->methType
= methBlock
;
2437 methraw
->needsHeapContext
= 0;
2438 methraw
->frameSize
= 0;
2439 methraw
->varargs
= 0;
2440 methraw
->numargs
= 0;
2441 methraw
->numvars
= 0;
2442 methraw
->numtemps
= 0;
2443 methraw
->popSize
= 0;
2445 nilSlots(&block
->rawData1
, numSlots
);
2449 SC_DLLEXPORT_C
struct VMGlobals
* scGlobals()
2451 return gMainVMGlobals
;
2454 PyrMethod
* initPyrMethod(PyrMethod
* method
)
2457 int32 numbytes
= sizeof(PyrMethod
) - sizeof(PyrObjectHdr
);
2458 int32 numSlots
= numbytes
/ sizeof(PyrSlot
);
2460 method
->classptr
= class_method
;
2462 method
->size
= numSlots
;
2463 SetFloat(&method
->rawData1
, 0.0);
2464 SetFloat(&method
->rawData2
, 0.0);
2465 nilSlots(&method
->code
, numSlots
-2);
2466 //slotCopy(&method->byteMeter, &o_zero);
2467 //slotCopy(&method->callMeter, &o_zero);
2468 //post("<- newPyrMethod %p %p\n", method, methraw);
2472 PyrMethod
* newPyrMethod()
2474 int32 numbytes
= sizeof(PyrMethod
) - sizeof(PyrObjectHdr
);
2475 PyrMethod
* method
= (PyrMethod
*)PyrGC::NewPermanent(numbytes
, obj_permanent
| obj_immutable
, obj_notindexed
);
2476 return initPyrMethod(method
);
2479 void freePyrSlot(PyrSlot
*slot
)
2484 obj
= (PyrObject
*)slotRawSymbol(slot
); // i don't want to know, what this means
2485 else if (IsObj(slot
))
2486 obj
= slotRawObject(slot
);
2490 if (obj
&& obj
->IsPermanent()) {
2491 // don't deallocate these
2492 if (obj
!= slotRawObject(&o_emptyarray
) && obj
!= slotRawObject(&o_onenilarray
) && obj
!= slotRawObject(&o_argnamethis
)) {
2493 pyr_pool_runtime
->Free((void*)obj
);
2500 void freePyrObject(PyrObject
*obj
)
2502 if (obj
->IsPermanent()) {
2503 pyr_pool_runtime
->Free((void*)obj
);
2507 int getIndexedInt(PyrObject
*obj
, int index
, int *value
)
2511 if (index
< 0 || index
>= obj
->size
) return errIndexOutOfRange
;
2512 switch (obj
->obj_format
) {
2514 slot
= obj
->slots
+ index
;
2515 if (IsFloat(slot
)) {
2516 *value
= (int)slotRawFloat(slot
);
2517 } else if (IsInt(slot
)) {
2518 *value
= slotRawInt(slot
);
2524 *value
= (int)((double*)(obj
->slots
))[index
];
2527 *value
= (int)((float*)(obj
->slots
))[index
];
2530 *value
= ((int32
*)(obj
->slots
))[index
];
2533 *value
= ((int16
*)(obj
->slots
))[index
];
2536 *value
= ((int8
*)(obj
->slots
))[index
];
2544 int getIndexedFloat(PyrObject
*obj
, int index
, float *value
)
2548 if (index
< 0 || index
>= obj
->size
) return errIndexOutOfRange
;
2549 switch (obj
->obj_format
) {
2551 slot
= obj
->slots
+ index
;
2552 if (IsFloat(slot
)) {
2553 *value
= slotRawFloat(slot
);
2554 } else if (IsInt(slot
)) {
2555 *value
= slotRawInt(slot
);
2561 *value
= ((double*)(obj
->slots
))[index
];
2564 *value
= ((float*)(obj
->slots
))[index
];
2567 *value
= ((int32
*)(obj
->slots
))[index
];
2570 *value
= ((int16
*)(obj
->slots
))[index
];
2573 *value
= ((int8
*)(obj
->slots
))[index
];
2581 int getIndexedDouble(PyrObject
*obj
, int index
, double *value
)
2585 if (index
< 0 || index
>= obj
->size
) return errIndexOutOfRange
;
2586 switch (obj
->obj_format
) {
2588 slot
= obj
->slots
+ index
;
2589 if (IsFloat(slot
)) {
2590 *value
= slotRawFloat(slot
);
2591 } else if (IsInt(slot
)) {
2592 *value
= slotRawInt(slot
);
2598 *value
= ((double*)(obj
->slots
))[index
];
2601 *value
= ((float*)(obj
->slots
))[index
];
2604 *value
= ((int32
*)(obj
->slots
))[index
];
2607 *value
= ((int16
*)(obj
->slots
))[index
];
2610 *value
= ((int8
*)(obj
->slots
))[index
];
2619 void getIndexedSlot(PyrObject
*obj
, PyrSlot
*a
, int index
)
2621 // postfl("getIndexedSlot %s %X %d\n", slotRawSymbol(&obj->classptr->name)->name,
2623 switch (obj
->obj_format
) {
2625 slotCopy(a
, &obj
->slots
[index
]);
2628 SetFloat(a
, ((double*)(obj
->slots
))[index
]);
2631 SetFloat(a
, ((float*)(obj
->slots
))[index
]);
2634 SetInt(a
, ((int32
*)(obj
->slots
))[index
]);
2637 SetInt(a
, ((int16
*)(obj
->slots
))[index
]);
2640 SetInt(a
, ((int8
*)(obj
->slots
))[index
]);
2643 SetSymbol(a
, (PyrSymbol
*)((int**)(obj
->slots
))[index
]);
2646 SetChar(a
, ((unsigned char*)(obj
->slots
))[index
]);
2651 int putIndexedSlot(VMGlobals
*g
, PyrObject
*obj
, PyrSlot
*c
, int index
)
2654 switch (obj
->obj_format
) {
2656 if (obj
->obj_flags
& obj_immutable
) return errImmutableObject
;
2657 slot
= obj
->slots
+ index
;
2659 g
->gc
->GCWrite(obj
, slot
);
2663 if (NotInt(c
)) return errWrongType
;
2665 ((double*)(obj
->slots
))[index
] = slotRawInt(c
);
2668 ((double*)(obj
->slots
))[index
] = slotRawFloat(c
);
2672 if (NotInt(c
)) return errWrongType
;
2674 ((float*)(obj
->slots
))[index
] = slotRawInt(c
);
2677 ((float*)(obj
->slots
))[index
] = slotRawFloat(c
);
2680 if (NotInt(c
)) return errWrongType
;
2681 ((int32
*)(obj
->slots
))[index
] = slotRawInt(c
);
2684 if (NotInt(c
)) return errWrongType
;
2685 ((int16
*)(obj
->slots
))[index
] = slotRawInt(c
);
2688 if (NotInt(c
)) return errWrongType
;
2689 ((int8
*)(obj
->slots
))[index
] = slotRawInt(c
);
2692 if (NotSym(c
)) return errWrongType
;
2693 ((PyrSymbol
**)(obj
->slots
))[index
] = slotRawSymbol(c
);
2696 if (NotChar(c
)) return errWrongType
;
2697 ((unsigned char*)(obj
->slots
))[index
] = slotRawChar(c
);
2703 int putIndexedFloat(PyrObject
*obj
, double val
, int index
)
2706 switch (obj
->obj_format
) {
2708 if (obj
->obj_flags
& obj_immutable
) return errImmutableObject
;
2709 slot
= obj
->slots
+ index
;
2710 SetFloat(slot
, val
);
2713 ((double*)(obj
->slots
))[index
] = val
;
2716 ((float*)(obj
->slots
))[index
] = (float)val
;
2719 ((int32
*)(obj
->slots
))[index
] = (int32
)val
;
2722 ((int16
*)(obj
->slots
))[index
] = (int16
)val
;
2725 ((int8
*)(obj
->slots
))[index
] = (int8
)val
;
2731 static int hashPtr(void* ptr
)
2733 int32 hashed_part
= int32((long)ptr
&0xffffffff);
2734 return Hash(hashed_part
);
2737 int calcHash(PyrSlot
*a
);
2738 int calcHash(PyrSlot
*a
)
2741 switch (GetTag(a
)) {
2742 case tagObj
: hash
= hashPtr(slotRawObject(a
)); break;
2743 case tagInt
: hash
= Hash(slotRawInt(a
)); break;
2744 case tagChar
: hash
= Hash(slotRawChar(a
) & 255); break;
2745 case tagSym
: hash
= slotRawSymbol(a
)->hash
; break;
2746 case tagNil
: hash
= 0xA5A5A5A5; break;
2747 case tagFalse
: hash
= 0x55AA55AA; break;
2748 case tagTrue
: hash
= 0x69696969; break;
2749 case tagPtr
: hash
= hashPtr(slotRawPtr(a
)); break;
2751 // hash for a double
2756 u
.d
= slotRawFloat(a
);
2757 hash
= Hash(u
.i
[0] + Hash(u
.i
[1]));
2762 void InstallFinalizer(VMGlobals
* g
, PyrObject
*inObj
, int slotIndex
, ObjFuncPtr inFunc
)
2764 PyrObject
*finalizer
= g
->gc
->NewFinalizer(inFunc
, inObj
, false);
2765 SetObject(inObj
->slots
+ slotIndex
, finalizer
);
2766 g
->gc
->GCWrite(inObj
, finalizer
);