Added #Symbols slot to #globals during bootstrap to avoid a #forwardTo: before the...
[cslatevm.git] / src / mobius / bootstrap.slate
blobc66a32c3e7848cbf561fa0472c93b3d81f68288d
1 "fixme: this is overwritten everytime you make a new generator"
2 define: #BytesPerWord -> 4.
3 "The size of a word in bytes on the target platform."
4 "TODO: Make this an attribute of an accessible target description."
6 define: #Chunk &slots: {#oop}.
8 _@(Chunk traits) wordSize [overrideThis].
10 define: #SlotEntry &slots: {#name. #offset}.
12 se@(SlotEntry traits) newNamed: name offset: offset
13 [se clone `>> [name := name. offset := offset. ]].
15 define: #RoleEntry &slots:
16   {#name. #rolePositions -> 0. #methodDefinition}.
18 re@(RoleEntry traits) newNamed: name rolePositions: positions methodDefinition: method
19 [re clone `>>
20    [name := name. rolePositions := positions. methodDefinition := method. ]].
22 define: #MethodDefinition &slots:
23   {#dispatchPositions -> 0. #method. #slotAccessor}.
25 md@(MethodDefinition traits) newDispatchPositions: positions method: method
26 [md clone `>> [dispatchPositions := positions. method := method. ]].
28 define: #Map &slots:
29   {#flags -> 0. #representative -> Nil.
30    #delegates -> {}.
31    #slotCount -> 0.
32    #slotTable -> {}.
33    #roleTable -> {}}.
35 map@(Map traits) addSlotNamed: name at: offset
37   map slotTable infect: #clone `er.
38   map slotTable := map slotTable copyWith:
39     (map surroundings SlotEntry newNamed: name offset: offset).
42 map@(Map traits) addRoleNamed: name at: position dispatching: def
44   map roleTable
45     doWithIndex:
46       [| :role :index |
47        role methodDefinition == def
48          ifTrue:
49            [(map roleTable := map roleTable copy) at: index :=
50               (map surroundings RoleEntry
51                  newNamed: name
52                  rolePositions: (role rolePositions bitOr: (1 bitShift: position))
53                  methodDefinition: def).
54             ^ False]].
55   map roleTable :=
56     map roleTable copyWith:
57       (map surroundings RoleEntry
58          newNamed: name
59          rolePositions: (1 bitShift: position)
60          methodDefinition: def).
61   True
64 define: #Object &parents: {Chunk} &slots:
65   {#idHash. #bmap -> Map. #slotValues -> {}}.
67 _@(Object traits) headerWords
68 [4].
70 obj@(Object traits) wordSizeSansPayload
71 [obj headerWords + obj slotValues size].
73 obj@(Object traits) wordSize
74 [obj wordSizeSansPayload].
76 obj@(Object traits) makeSlotNamed: name valued: value
77 [| index |
78   index := obj bmap slotCount.
79   obj bmap := obj bmap clone `>>
80     [slotCount := index + 1.
81      addSlotNamed: name at: obj headerWords + index * obj surroundings BytesPerWord. ].
82   obj slotValues := obj slotValues copyWith: value.
83   obj
86 obj@(Object traits) setSlot: name to: val
88   obj bmap slotTable
89     do: [| :slot | slot name = name ifTrue:
90       [^ (obj slotValues at: slot offset / obj surroundings BytesPerWord - obj headerWords put: val)]].
91   error: 'Slot missing: ' ; name
94 obj@(Object traits) setSlots: namesAndValues
96   namesAndValues do: [| :assoc | obj setSlot: assoc key to: assoc value]
99 obj@(Object traits) getSlot: name
101   obj bmap slotTable
102     do: [| :slot | slot name = name ifTrue:
103       [^ (obj slotValues at: slot offset / obj surroundings BytesPerWord - obj headerWords)]].
104   error: 'Slot missing: ' ; name
107 obj@(Object traits) addDelegateValued: value
109   obj bmap := obj bmap clone `>>
110     [delegates := obj bmap delegates copyWith: value. ].
111   obj
114 obj@(Object traits) addRoleNamed: name at: position dispatching: def
116   obj bmap addRoleNamed: name at: position dispatching: def
119 method@(Object traits) addMethodNamed: name on: roles
120 [| def |
121   def := method surroundings MethodDefinition newDispatchPositions: 0 method: method.
122   roles doWithIndex:
123     [| :role :index |
124       role ifNotNil:
125         [def dispatchPositions := def dispatchPositions bitOr: (1 bitShift: index).
126          role addRoleNamed: name at: index dispatching: def]].
127   "inform: 'Adding method %r roles: %r pos: %r', name, roles, def dispatchPositions."
128   def
131 define: #Array &parents: {Object}.
133 define: #OopArray &parents: {Array}
134   &slots: {#elements -> {}}.
136 arr@(OopArray traits) wordSize
137 [arr wordSizeSansPayload + arr elements size].
139 define: #ByteArray &parents: {Array}
140   &slots: {#elements -> imports ByteArray new}.
142 arr@(ByteArray traits) byteSize
144   arr wordSizeSansPayload * arr surroundings BytesPerWord + arr elements size
147 arr@(ByteArray traits) wordSize
149   arr wordSizeSansPayload + (arr elements size + arr surroundings BytesPerWord - 1 // arr surroundings BytesPerWord)
152 define: #CompiledMethod &parents: {Object}.
154 define: #Generator &slots: {
155   #translations -> IdentityDictionary new.
156   #chunks -> ExtensibleArray new.
157   #characters -> ({} newSizeOf: imports ASCIIString Character CharacterSet).
158   #symbols -> Dictionary new.
159   #littleEndian -> True.
160   #bytesPerWord -> BytesPerWord.
161   #nextHash -> 0.
162   #imageSize -> 0.
163   #objects -> Dictionary new.
166 gen@(Generator traits) new &littleEndian: littleEndian &wordSize: wordSize
168   littleEndian `defaultsTo: gen littleEndian.
169   wordSize `defaultsTo: Platform Current bytesPerWord * 8.
170   define: #BytesPerWord -> (wordSize // 8).
171   gen clone `setting:
172     #{#objects. #translations. #chunks. #characters. #symbols. #bytesPerWord. #littleEndian}
173     to: {gen objects new.
174          gen translations new.
175          gen chunks new.
176          gen characters copy.
177          gen symbols new.
178          wordSize // 8.
179          littleEndian}
182 gen@(Generator traits) generateImageBooting: method withPrims: prims
183 "Generates the primary image objects such that the supplied CompiledMethod
184 will be interpreted immediately upon loading the image."
186   inform: 'Generating kernel'.
187   gen generateKernel.
188   inform: 'Generating utilities'.
189   gen generateUtilities.
190   inform: 'Generating kernel accessors'.
191   gen generateKernelAccessors.
192   inform: 'Generating interpreter'.
193   gen generateInterpreterBooting: method.
194   inform: 'Generating lobby'.
195   gen generateLobby.
196   inform: 'Generating prims'.
197   prims do: [| :assoc | gen generatePrimitive: assoc value at: assoc key].
198   inform: 'Generating maps'.
199   gen generateMaps.
200   inform: 'Generating linkage'.
201   gen generateLinkage
204 gen@(Generator traits) objectNamed: name
205 [gen objects at: name].
207 gen@(Generator traits) bytesAt: i in: arr put: val numBytes: bytes
209   0 below: bytes do:
210     [| :index |
211      arr elements at: i + index put:
212        (val byteShift: (gen littleEndian ifTrue: [0 - index]
213                                          ifFalse: [0 - bytes + index])) intoByte]
216 gen@(Generator traits) shortAt: i in: arr put: val
218   gen bytesAt: i in: arr put: val numBytes: gen bytesPerWord // 2
221 gen@(Generator traits) longAt: i in: arr put: val
223   gen bytesAt: i in: arr put: val numBytes: gen bytesPerWord
226 gen@(Generator traits) capacityForTable: table
228   (table size * 5 // 4) leastGreaterPowerOfTwo
231 gen@(Generator traits) generateSlotTableFor: map
232 [| obj capacity selector hash |
233   capacity := gen capacityForTable: map slotTable.
234   obj := gen cloneOf: (gen objectNamed: #ArrayProto) sized: 2 * capacity.
235   map slotTable do:
236     [| :se |
237      selector := gen generateLiteral: se name.
238      hash := (selector idHash bitAnd: capacity - 1) * 2.
239      [(obj elements at: hash) isNil]
240        whileFalse:
241          [hash := (hash + 2) \\ (capacity * 2)].
242      obj elements at: hash put: selector.
243      obj elements at: hash + 1 put: se offset].
244   obj
247 gen@(Generator traits) generateRoleTableFor: map
248 [| obj capacity selector hash insert |
249   capacity := gen capacityForTable: map roleTable.
250   obj := gen cloneOf: (gen objectNamed: #ArrayProto) sized: 4 * capacity.
251   map roleTable do:
252     [| :re |
253      selector := gen generateLiteral: re name.
254      hash := (selector idHash bitAnd: capacity - 1) * 4.
255      [(obj elements at: hash) isNil
256         \/ [(obj elements at: hash) == selector]]
257        whileFalse:
258          [hash := (hash + 4) \\ (capacity * 4)].
259      insert := hash.
260      [(obj elements at: insert) isNil]
261        whileFalse:
262          [insert := (insert + 4) \\ (capacity * 4)].
263      obj elements at: insert put: selector.
264      obj elements at: insert + 1 put: re rolePositions.
265      obj elements at: insert + 2 put: (gen generateMethodDef: re methodDefinition).
266      insert == hash
267        ifFalse:
268          [[(obj elements at: hash + 3) isNil]
269             whileFalse: [hash := (obj elements at: hash + 3) * 4].
270           obj elements at: hash + 3 put: insert // 4]].
271   obj
274 gen@(Generator traits) generateMethodDef: def
276   gen translations at: def
277     ifAbsentPut:
278       [| obj sym |
279        (sym := def method getSlot: #selector)
280          setSlot: #cacheMask to: ((sym getSlot: #cacheMask) bitOr: def dispatchPositions).
281        (obj := gen cloneOf: (gen objectNamed: #MethodDefinitionProto)) setSlots: {
282          #method -> def method.
283          #slotAccessor -> (gen generateLiteral: def slotAccessor)
284        }.
285        gen longAt: 1 * gen bytesPerWord in: obj put: def dispatchPositions.
286        obj]
289 gen@(Generator traits) generateMap: map
291   gen translations at: map
292     ifAbsentPut:
293       [(gen cloneOf: (gen objectNamed: #MapProto)) `>>
294          [setSlots: {#flags -> map flags.
295                      #representative -> (map representative ifNil: [gen objectNamed: #NilObject]).
296                      #delegates -> (gen cloneOf: (gen objectNamed: #ArrayProto) elements: map delegates).
297                      #slotCount -> map slotCount.
298                      #slotTable -> (gen generateSlotTableFor: map).
299                      #roleTable -> (gen generateRoleTableFor: map)}. ]]
302 gen@(Generator traits) generateMaps
304   gen objects keysAndValuesDo:
305     [| :name :obj |
306      inform: ' Adding map for %s', name.
307      gen generateMap: obj bmap]
310 obj@(Object traits) nextOop
311 "Answer the pointer to just beyond this object."
312 [obj oop + (obj wordSize * obj surroundings BytesPerWord)].
314 gen@(Generator traits) assignOops
315 "Assign oops to all of the chunks, accumulating the final oop which is used
316 to set the image size."
318   gen imageSize := gen chunks inject: 0 into:
319     [| :oop :chunk | chunk oop := oop. chunk nextOop]
322 gen@(Generator traits) emitInteger: val on: stream byteSize: byteSize
323 "Takes an integer and outputs the binary data value in the correct byte-order
324 onto the stream."
326   stream next: byteSize putInteger: val &littleEndian: gen littleEndian
329 gen@(Generator traits) emitLong: val on: stream
330 "Takes an integer and outputs the binary data value in the correct byte-order
331 onto the stream."
333   gen emitInteger: val on: stream byteSize: gen bytesPerWord
336 gen@(Generator traits) emitOopOf: chunk on: stream
337 [gen emitLong: chunk oop on: stream].
339 gen@(Generator traits) emitOopOf: _@Nil on: stream
340 [gen emitOopOf: (gen objectNamed: #NilObject) on: stream].
342 gen@(Generator traits) emitOopOf: i@(imports SmallInteger traits) on: stream
343 [gen emitLong: (i << 1 bitOr: 1) on: stream].
345 gen@(Generator traits) emitObjectHashed: hash sized: size payload: payload format: format on: stream
347   "fix: check big endian"
348   "header"
349   gen littleEndian ifFalse:
350     [gen emitInteger: 0 on: stream byteSize: gen bytesPerWord - 4].
351   stream nextPutAll:
352     ((gen littleEndian
353       ifTrue:
354         [{2r1 bitOr: (hash bitAnd: 16r7F) << 1.
355           (hash >> 7) intoByte.
356           (hash >> 15) intoByte.
357           format << 6}]
358       ifFalse:
359         [{2r10000000 bitOr: (hash >> 16 bitAnd: 16r7F).
360           (hash >> 8) intoByte.
361           hash intoByte.
362           format}]) as: ByteArray).
363   gen littleEndian ifTrue:
364     [gen emitInteger: 0 on: stream byteSize: gen bytesPerWord - 4].
366   "size in words of slot data"
367   gen emitLong: size on: stream.
368   "size in bytes of payload (oop array or byte array)"
369   gen emitLong: payload on: stream.  
371   stream
374 gen@(Generator traits) emit: obj@(Object traits) on: stream
376   gen emitObjectHashed: obj idHash sized: obj wordSize payload: 0 format: 2r00 on: stream.
377   gen emitLong: (gen translations at: obj bmap) oop on: stream.
378   obj slotValues
379     do: [| :slotVal | gen emitOopOf: slotVal on: stream].
380   obj
383 gen@(Generator traits) emit: obj@(OopArray traits) on: stream
385   gen emitObjectHashed: obj idHash
386     sized: obj wordSizeSansPayload
387     payload: obj elements size * gen bytesPerWord
388     format: 2r01
389     on: stream.
390   gen emitLong: (gen translations at: obj bmap) oop on: stream.
391   (obj slotValues ;; obj elements)
392     do: [| :slotVal | gen emitOopOf: slotVal on: stream].
393   obj
396 gen@(Generator traits) emit: obj@(ByteArray traits) on: stream
398   gen emitObjectHashed: obj idHash
399     sized: obj wordSizeSansPayload
400     payload: obj elements size
401     format: 2r10
402     on: stream.
403   gen emitLong: (gen translations at: obj bmap) oop on: stream.
404   obj slotValues do: [| :slotVal | gen emitOopOf: slotVal on: stream].
405   stream nextPutAll: obj elements.
406   stream next: (gen bytesPerWord - obj elements size) \\ gen bytesPerWord put: 0.
407   obj
410 gen@(Generator traits) emitHeaderOn: stream
412   gen emitLong: 16rABCDEF43 on: stream.
413   gen emitLong: gen imageSize on: stream.
414   gen emitLong: gen nextHash on: stream.
415   gen emitLong: ((gen objectNamed: #GlobalsObject) getSlot: #specialOops) oop on: stream.
416 "i shortened dispatch id to one word"
417   gen emitLong: 0 on: stream.
420 gen@(Generator traits) emitOn: stream
421 "Emits a bootstrap image on the stream after it has been generated."
423   inform: 'Assigning oops'.
424   gen assignOops.
425   inform: 'Emitting image: %s', stream resource locator.
426   gen emitHeaderOn: stream.
427   gen chunks do: [| :chunk | gen emit: chunk on: stream]
430 gen@(Generator traits) addObjectNamed: name valued: obj
432   inform: ' Adding object %s', name.
433   gen objects at: name put: obj.
434   obj
437 gen@(Generator traits) newIdentityHash
438 [| hash |
439   hash := gen nextHash.
440   gen nextHash += 1.
441   hash
444 gen@(Generator traits) new: layout fromMap: map
445 [| obj |
446   obj := layout clone `>> [idHash := gen newIdentityHash. bmap := map. ].
447   obj slotValues := obj slotValues newSize: map slotCount.
448   map representative := obj.
449   gen chunks addLast: obj.
450   obj
453 gen@(Generator traits) newMap
455   gen surroundings Map clone
458 gen@(Generator traits) newObject
460   gen new: gen surroundings Object
463 gen@(Generator traits) new: layout
465   gen new: layout fromMap: gen newMap
468 gen@(Generator traits) cloneOf: proto@(Object traits)
470   gen chunks addLast: proto clone `>>
471     [idHash := gen newIdentityHash. slotValues := proto slotValues copy. ]
474 gen@(Generator traits) cloneOf: arr@(Array traits)
475 [resend `>> [elements := arr elements copy. ]].
477 gen@(Generator traits) cloneOf: proto sized: size
478 [(gen cloneOf: proto) `>> [elements := proto elements newSize: size. ]].
480 gen@(Generator traits) cloneOf: proto elements: elements
481 [(gen cloneOf: proto) `>> [elements := elements as: proto elements. ]].
483 gen@(Generator traits) addAccessorFor: slotName on: obj
484 [| accessor selector |
485   selector := obj accessorNameFor: slotName.
486   accessor := gen cloneOf: (gen objectNamed: #CompiledMethodProto).
487   accessor setSlots: {
488     #method -> accessor.
489     #selector -> (gen generateLiteral: selector).
490     #inputVariables -> 1.
491     #localVariables -> 1.
492     #registerCount -> 3.
493     #literals -> (gen cloneOf: (gen objectNamed: #ArrayProto) elements: {gen generateLiteral: slotName}).
494     #selectors -> (gen cloneOf: (gen objectNamed: #ArrayProto) elements: {gen generateLiteral: #atSlotNamed:}).
495     #code ->
496     (gen cloneOf: (gen objectNamed: #ArrayProto)
497       elements: {
498         VM SSACode loadVariable. 0.
499         VM SSACode loadLiteral. 1. gen generateLiteral: slotName.
500         VM SSACode directSendMessage. 0. gen generateLiteral: #atSlotNamed:. 2. 0. 1.
501         VM SSACode returnRegister. 0
502       })
503   }.
504   (accessor addMethodNamed: selector on: {obj}) slotAccessor: slotName.
505   accessor
508 gen@(Generator traits) addMutatorFor: slotName on: obj
509 [| mutator selector |
510   mutator := gen cloneOf: (gen objectNamed: #CompiledMethodProto).
511   selector := obj mutatorNameFor: slotName.
512   mutator setSlots: {
513     #method -> mutator.
514     #selector -> (gen generateLiteral: selector).
515     #inputVariables -> 2.
516     #localVariables -> 1.
517     #registerCount -> 4.
518     #literals -> (gen cloneOf: (gen objectNamed: #ArrayProto) elements: {gen generateLiteral: slotName}).
519     #selectors -> (gen cloneOf: (gen objectNamed: #ArrayProto) elements: {gen generateLiteral: #atSlotNamed:put:}).
520     #code ->
521     (gen cloneOf: (gen objectNamed: #ArrayProto)
522       elements:
523         {
524           VM SSACode loadVariable. 0.
525           VM SSACode loadVariable. 1.
526           VM SSACode loadLiteral. 2. gen generateLiteral: slotName.
527           VM SSACode directSendMessage. 0. gen generateLiteral: #atSlotNamed:put:. 3. 0. 2. 1.
528           VM SSACode returnRegister. 0
529         })
530   }.
531   (mutator addMethodNamed: selector on: {obj. Nil}) slotAccessor: slotName.
532   mutator
535 gen@(Generator traits) addAccessorsFor: slotName on: obj
537   gen addAccessorFor: slotName on: obj.
538   gen addMutatorFor: slotName on: obj
541 gen@(Generator traits) generateKernelAccessors
543   gen objects do:
544     [| :obj |
545      obj bmap slotTable do: [| :slot | gen addAccessorsFor: slot name on: obj]]
548 gen@(Generator traits) generatePrototype: name &suffix: suffix &layout: layout &parents: parents &slots: slotSpecs &elements: elements
549 [| traits window result |
550   suffix `defaultsTo: 'Proto'.
551   traits := (gen addObjectNamed: (name ; 'Traits') intern valued: gen newObject)
552     `>> [addDelegateValued: Nil. ].
553   window := (gen addObjectNamed: (name ; 'Window') intern valued: gen newObject)
554     `>> [bmap flags := 1. addDelegateValued: Nil. ].
555   parents
556     ifNotNil:
557       [parents reverseDoWithIndex:
558         [| :parent :index |
559           window addDelegateValued: parent]].
560   window addDelegateValued: traits.
561   result := (gen addObjectNamed: (name ; suffix) intern
562                valued: (layout ifNil: [gen newObject] ifNotNil: [gen new: layout]))
563     `>> [addDelegateValued: window. ].
564   elements ifNotNil:
565     [(result hasSlotNamed: #elements) ifTrue: [result elements := elements]].
566   (slotSpecs `defaultsTo: {}) do:
567     [| :spec | result makeSlotNamed: spec key valued: spec value].
568   result
571 gen@(Generator traits) generateInstance: name of: window
572 [(gen addObjectNamed: name valued: gen newObject) `>>
573   [addDelegateValued: window.]
576 gen@(Generator traits) generateKernel
578   gen generatePrototype: 'Root'.
579   gen generatePrototype: 'Oddball' &parents: {gen objectNamed: #RootTraits}.
580   gen generatePrototype: 'Derivable' &parents: {gen objectNamed: #RootTraits}.
581   gen generatePrototype: 'Cloneable' &parents: {gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}.
583   gen generateInstance: #NilObject of: (gen objectNamed: #OddballWindow).
584   gen generateInstance: #NoRoleObject of: (gen objectNamed: #OddballWindow).
586   gen generatePrototype: 'Boolean' &parents: {gen objectNamed: #OddballTraits. gen objectNamed: #RootTraits}.
587   gen generateInstance: #TrueObject of: (gen objectNamed: #BooleanWindow).
588   gen generateInstance: #FalseObject of: (gen objectNamed: #BooleanWindow).
590   gen generatePrototype: 'Array' &layout: gen surroundings OopArray
591     &parents: {gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}
592     &elements: Array new.
593   gen generatePrototype: 'ByteArray' &layout: gen surroundings ByteArray
594     &parents: {gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}
595     &elements: ByteArray new.
597   gen generatePrototype: 'SmallInteger' &parents: {gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #OddballTraits. gen objectNamed: #RootTraits}.
598   (gen generatePrototype: 'Float' &layout: gen surroundings ByteArray
599     &parents: {gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #ByteArrayTraits. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}) `>>
600     [elements: (ByteArray newSize: gen bytesPerWord)].
602   gen generatePrototype: 'ASCIIString' &layout: gen surroundings ByteArray
603     &parents: {gen objectNamed: #NilObject. gen objectNamed: #ByteArrayTraits. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}.
605   gen generatePrototype: 'Symbol' &layout: gen surroundings ByteArray
606     &parents: {gen objectNamed: #ASCIIStringTraits. gen objectNamed: #NilObject. gen objectNamed: #ByteArrayTraits. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}
607     &slots: {#cacheMask -> 0}.
609   gen symbols at: #'' put: (gen objectNamed: #SymbolProto).
611   gen generatePrototype: 'ASCIICharacter'
612     &parents: {gen objectNamed: #NilObject. gen objectNamed: #OddballTraits. gen objectNamed: #RootTraits} &slots: {#code -> 0}.
613   gen characters at: 0 put: (gen objectNamed: #ASCIICharacterProto).
614   1 below: gen characters size
615     do: [| :index c |
616       c: (gen cloneOf: (gen objectNamed: #ASCIICharacterProto)).
617       c setSlot: #code to: index.
618       gen characters at: index put: c].
619   (gen objectNamed: #ASCIIStringTraits) makeSlotNamed: #Character valued: (gen objectNamed: #ASCIICharacterProto).
621   gen generatePrototype: 'Namespace'
622     &parents: {gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}.
623   gen generateInstance: #BootstrapObject of: (gen objectNamed: #NamespaceWindow).
625   gen generatePrototype: 'Method' &parents: {gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}.
627   gen generatePrototype: 'PrimitiveMethod'
628     &parents: {gen objectNamed: #MethodTraits. gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}
629     &slots: {#index -> 0. #selector -> (gen objectNamed: #NilObject). #inputVariables -> 0}.
631   gen generatePrototype: 'CompiledMethod'
632     &parents: {gen objectNamed: #MethodTraits. gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}
633     &slots: {#method -> (gen objectNamed: #NilObject). #selector -> (gen objectNamed: #NilObject).
634         #inputVariables -> 0. #localVariables -> 0.
635         #restVariable -> (gen objectNamed: #FalseObject).
636         #optionalKeywords -> (gen objectNamed: #ArrayProto).
637         #heapAllocate -> (gen objectNamed: #FalseObject).
638         #environment -> (gen objectNamed: #BootstrapObject).
639         #literals -> (gen objectNamed: #ArrayProto).
640         #selectors -> (gen objectNamed: #ArrayProto).
641         #code -> (gen objectNamed: #ArrayProto).
642         #sourceTree -> (gen objectNamed: #NilObject).
643         #debugMap -> (gen objectNamed: #ArrayProto).
644         #isInlined -> (gen objectNamed: #FalseObject).
645         #oldCode -> (gen objectNamed: #NilObject).
646         #callCount -> 0.
647         #calleeCount -> (gen objectNamed: #NilObject).
648         #registerCount -> 0.
649         #cachedInCallers -> (gen objectNamed: #NilObject).
650         #cachedInCallersCount -> 0.
651         #nextInlineAtCallCount -> (gen objectNamed: #NilObject).
652         #reserved5 -> (gen objectNamed: #NilObject).
653         #reserved6 -> 0}.
655   gen generatePrototype: 'Closure' &layout: gen surroundings OopArray
656     &parents: {gen objectNamed: #MethodTraits. gen objectNamed: #ArrayTraits. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}
657     &slots: {#method -> (gen objectNamed: #NilObject)}.
659   gen generatePrototype: 'MethodDefinition' &layout: gen surroundings ByteArray
660     &parents: {gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}
661     &slots: {#method -> (gen objectNamed: #CompiledMethodProto). #slotAccessor -> (gen objectNamed: #NilObject)}
662     &elements: (ByteArray newSize: 4 * gen bytesPerWord).
664   gen generatePrototype: 'Map' &layout: gen surroundings ByteArray
665     &parents: {gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}
666     &slots: {#flags -> 0. #representative -> (gen objectNamed: #NilObject).
667      #delegates -> (gen objectNamed: #ArrayProto). #slotCount -> 0.
668      #slotTable -> (gen objectNamed: #ArrayProto). #roleTable -> (gen objectNamed: #ArrayProto)}
669     &elements: (ByteArray newSize: 3 * gen bytesPerWord).
671   gen generatePrototype: 'LexicalContext' &layout: gen surroundings OopArray
672     &parents: {gen objectNamed: #ArrayTraits. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #NilObject. gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}
673     &slots: {#framePointer -> 0}.
675   gen generatePrototype: 'Interpreter' &layout: gen surroundings ByteArray
676     &parents: {gen objectNamed: #CloneableTraits. gen objectNamed: #DerivableTraits. gen objectNamed: #RootTraits}
677     &slots: {#stack -> (gen objectNamed: #ArrayProto).
678      #method -> (gen objectNamed: #NilObject).
679      #closure -> (gen objectNamed: #NilObject).
680      #lexicalContext -> (gen objectNamed: #NilObject).
681      #ensureHandlers -> 0}
682     &elements: (ByteArray newSize: 5 * gen bytesPerWord).
684   (gen addObjectNamed: #EnsureMarkerObject valued: (gen cloneOf: (gen objectNamed: #CompiledMethodProto))) `>>
685     [| :marker |
686       setSlot: #method to: marker.
687       setSlot: #code to:
688         (gen cloneOf: (gen objectNamed: #ArrayProto)
689           elements: {VM SSACode resume})].
692 gen@(Generator traits) generateInterpreterBooting: method
693 [| compiler stackObj stackSize methodObj codeSize |
694   compiler := VM SSACompiler new.
695   _@compiler branchTableHash: key
696   [| literal |
697     literal := gen generateLiteral: key.
698     (literal isSameAs: SmallInteger)
699       ifTrue: [literal]
700       ifFalse: [literal idHash]
701   ].
702   inform: 'Compiling the syntax tree of bootstrap code and libraries into SSA code.'.
703   
704   method := (compiler generate: method result: Nil &topLevel: True) `>> [heapAllocate := False. ].
706   "compiler decompile: method code."
708   methodObj := gen generateLiteral: method.
710   stackSize := 16. "if you change this, change vm.c which has it hard-coded in the beginning of interpret()"
712   stackObj := (gen cloneOf: (gen objectNamed: #ArrayProto) sized: stackSize) `>>
713     [elements at: 0 put: 0. "-6: prev sp"
714      elements at: 1 put: -1. "-5: resultStackPointer"
715      elements at: 2 put: 0. "-4: code pointer"
716      elements at: 3 put: methodObj. "-3: closure"
717      elements at: 4 put: 0. "-2: lexical context"
718      elements at: 5 put: 0. "-1: prev fp"
719      elements at: 6 put: 0. ].
721   codeSize := method code size.
723   gen addObjectNamed: #InterpreterObject valued: (gen cloneOf: (gen objectNamed: #InterpreterProto)).
724   (gen objectNamed: #InterpreterObject) setSlots: {
725     #stack -> stackObj.
726     #method -> methodObj.
727     #closure -> methodObj
728   }.
729   gen longAt: 0 * gen bytesPerWord in: (gen objectNamed: #InterpreterObject) put: 6. " frame pointer (framesize=6)"
730   "long at 1 is code pointer -- I guess this gets filled later or is zero"
731   gen longAt: 2 * gen bytesPerWord in: (gen objectNamed: #InterpreterObject) put: codeSize.
732   gen longAt: 3 * gen bytesPerWord in: (gen objectNamed: #InterpreterObject) put: 6. "stack pointer (framesize=6)"
733   gen longAt: 4 * gen bytesPerWord in: (gen objectNamed: #InterpreterObject) put: stackSize
736 gen@(Generator traits) generateUtilities
738   gen generateInstance: #ConsoleObject of: (gen objectNamed: #OddballWindow).
740   gen generatePrototype: 'File' &parents: {
741     gen objectNamed: #NilObject.
742     gen objectNamed: #CloneableTraits.
743     gen objectNamed: #DerivableTraits.
744     gen objectNamed: #RootTraits
745   }.
746   gen generatePrototype: 'Directory' &parents: {
747     gen objectNamed: #NilObject.
748     gen objectNamed: #CloneableTraits.
749     gen objectNamed: #DerivableTraits.
750     gen objectNamed: #RootTraits
751   }.
752   gen generatePrototype: 'ExternalLibrary' &parents: {
753     gen objectNamed: #NilObject.
754     gen objectNamed: #CloneableTraits.
755     gen objectNamed: #DerivableTraits.
756     gen objectNamed: #RootTraits
757   }.
760 gen@(Generator traits) generateLobby
762   gen addObjectNamed: #PrototypesObject valued: (gen cloneOf: (gen objectNamed: #NamespaceProto)).
763   (gen objectNamed: #BootstrapObject) addDelegateValued: (gen objectNamed: #PrototypesObject).
764   "timmy: no named delegate slots but name needed for accessor"
765   (gen objectNamed: #BootstrapObject) makeSlotNamed: #prototypes valued: (gen objectNamed: #PrototypesObject).
766   gen addAccessorFor: #prototypes on: (gen objectNamed: #BootstrapObject).
767   "Install slots/accessors in the 'prototypes' namespace,
768    set up traits traits, and set up printName. Make sure all bootstrapped protos
769    are listed here, otherwise these important steps are left out for them."
770   [| :slotName :objectName obj printNameLiteral window traits |
771     obj := gen objectNamed: objectName.
772     (gen objectNamed: #PrototypesObject) makeSlotNamed: slotName valued: obj.
773     gen addAccessorFor: slotName on: (gen objectNamed: #PrototypesObject).
774     window := obj bmap delegates first.
775     window bmap delegates at: 0 put: (gen objectNamed: #CloneableWindow).
776     traits := window bmap delegates last"(window getSlot: #traits)".
777     traits bmap delegates at: 0 put: (gen objectNamed: #CloneableWindow).
778     printNameLiteral := gen generateLiteral: slotName name.
779     traits makeSlotNamed: #printNameTraits valued: printNameLiteral.
780     gen addAccessorFor: #printNameTraits on: traits.
781     window makeSlotNamed: #printNameWindow valued: printNameLiteral.
782     gen addAccessorFor: #printNameWindow on: window
783   ] applier for: #{
784     {#Root.             #RootProto}.
785     {#Oddball.          #OddballProto}.
786     {#Cloneable.        #CloneableProto}.
787     {#Derivable.        #DerivableProto}.
788     {#Namespace.        #NamespaceProto}.
789     {#Boolean.          #BooleanProto}.
790     {#Array.            #ArrayProto}.
791     {#ByteArray.        #ByteArrayProto}.
792     {#ASCIIString.      #ASCIIStringProto}.
793     {#ASCIICharacter.   #ASCIICharacterProto}.
794     {#Symbol.           #SymbolProto}.
795     {#SmallInteger.     #SmallIntegerProto}.
796     {#SingleFloat.      #FloatProto}.
797     {#Map.              #MapProto}.
798     {#LexicalContext.   #LexicalContextProto}.
799     {#MethodDefinition. #MethodDefinitionProto}.
800     {#Method.           #MethodProto}.
801     {#PrimitiveMethod.  #PrimitiveMethodProto}.
802     {#CompiledMethod.   #CompiledMethodProto}.
803     {#Closure.          #ClosureProto}.
804     {#Interpreter.      #InterpreterProto}.
805     {#File.             #FileProto}.
806     {#Directory.        #DirectoryProto}.
807     {#ExternalLibrary.  #ExternalLibraryProto}
808   }.
810   gen addObjectNamed: #GlobalsObject valued: (gen cloneOf: (gen objectNamed: #NamespaceProto)).
811   (gen objectNamed: #BootstrapObject) addDelegateValued: (gen objectNamed: #GlobalsObject).
812   (gen objectNamed: #BootstrapObject) makeSlotNamed: #globals valued: (gen objectNamed: #GlobalsObject).
813   gen addAccessorFor: #globals on: (gen objectNamed: #BootstrapObject).
814   [| :key :value |
815    (gen objectNamed: #GlobalsObject) makeSlotNamed: key valued: value.
816    gen addAccessorFor: key on: (gen objectNamed: #GlobalsObject)] applier for: {
817      #Console.              gen objectNamed: #ConsoleObject.
818      #NoRole.               gen objectNamed: #NoRoleObject.
819      #Nil.                  gen objectNamed: #NilObject.
820      #True.                 gen objectNamed: #TrueObject.
821      #False.                gen objectNamed: #FalseObject.
822      #lobby.                gen objectNamed: #BootstrapObject.
823      #bootstrapCharacters.  gen cloneOf: (gen objectNamed: #ArrayProto) elements: gen characters.
824      #bootstrapSymbols.     gen objectNamed: #ArrayProto.
825      #Symbols.              gen objectNamed: #NilObject.
826      #bootstrapInterpreter. gen objectNamed: #InterpreterObject.
827      #ensureMarker.         gen objectNamed: #EnsureMarkerObject.
828      #specialOops.          gen objectNamed: #ArrayProto.
829      #features.             gen objectNamed: #ArrayProto.
830   }.
831   gen addMutatorFor: #bootstrapSymbols on: (gen objectNamed: #GlobalsObject).
832   gen addMutatorFor: #features on: (gen objectNamed: #GlobalsObject)
835 gen@(Generator traits) generateLinkage
836 "TODO: The order in this method must be the same as in memory.slate, enforce it"
838   (gen objectNamed: #GlobalsObject) setSlot: #specialOops to:
839     (gen cloneOf: (gen objectNamed: #ArrayProto) elements:
840        (#{#BootstrapObject.
841           #NoRoleObject.
842           #NilObject.
843           #TrueObject.
844           #FalseObject.
845           #ArrayProto.
846           #ByteArrayProto.
847           #ASCIIStringProto.
848           #MapProto.
849           #MethodDefinitionProto.
850           #SmallIntegerProto.
851           #FloatProto.
852           #ClosureWindow.
853           #CompiledMethodWindow.
854           #PrimitiveMethodWindow.
855           #ClosureProto.
856           #LexicalContextProto.
857           #InterpreterObject.
858           #EnsureMarkerObject.
859       } collect: #(gen objectNamed: _) `er)
860        ; ({#notFoundOn:.
861            #notFoundOn:after:.
862            #wrongInputsTo:.
863            #mayNotReturnTo:.
864            #slotNotFoundNamed:.
865            #keyNotFoundOn:.
866            #immutable.
867            #bitShiftOverflow:.
868            #addOverflow:.
869            #subtractOverflow:.
870            #multiplyOverflow:.
871            #divideByZero.
872            #notABoolean.
873            #applyTo:.
874            #&optionals:.
875            #badTypeError} collect: #(gen generateLiteral: _) `er)).
876   (gen objectNamed: #GlobalsObject) setSlot: #bootstrapSymbols to:
877     (gen cloneOf: (gen objectNamed: #ArrayProto) elements: gen symbols valueSet).
880 gen@(Generator traits) generatePrimitive: prim at: index
881 "Given a MethodDefinition representing a Pidgin primitive definition,
882 this defines a PrimitiveMethod stub that will invoke the given primitive
883 index. Must be called after generateImageBooting:."
885   (gen cloneOf: (gen objectNamed: #PrimitiveMethodProto)) `>>
886    [setSlots: {
887       #selector -> (gen generateLiteral: prim selector).
888       #inputVariables -> prim roles size.
889       #index -> index
890     }.
891     addMethodNamed: prim selector on:
892       (prim roles collect:
893          [| :role |
894           (role isSameAs: nodes UnaryMessage)
895             ifTrue:
896               [inform: ' Adding primitive %s to %s', index, role selector.
897                gen objectNamed: role selector]]) ]
900 gen@(Generator traits) generateLiteral: literal
902   literal == NoRole
903     ifTrue: [gen objectNamed: #NoRoleObject]
904     ifFalse: [error: 'Unsupported literal.']
907 gen@(Generator traits) generateLiteral: i@(imports SmallInteger traits)
908 [i].
910 gen@(Generator traits) generateLiteral: _@(imports BigInteger traits)
912   error: 'The bootstrap generator does not support big integers.'
915 gen@(Generator traits) generateLiteral: _@True
916 [gen objectNamed: #TrueObject].
918 gen@(Generator traits) generateLiteral: _@False
919 [gen objectNamed: #FalseObject].
921 gen@(Generator traits) generateLiteral: _@Nil
922 [gen objectNamed: #NilObject].
924 gen@(Generator traits) generateLiteral: _@lobby
925 [gen objectNamed: #BootstrapObject].
927 gen@(Generator traits) generateLiteral: s@(imports ASCIIString traits)
929   s isEmpty
930     ifTrue: [gen objectNamed: #ASCIIStringProto]
931     ifFalse: [gen cloneOf: (gen objectNamed: #ASCIIStringProto) elements:
932                 (s collect: #code`er into: (ByteArray newSizeOf: s))]
935 gen@(Generator traits) generateLiteral: s@(imports Symbol traits)
937   gen symbols
938     at: s
939     ifAbsentPut:
940       [gen cloneOf: (gen objectNamed: #SymbolProto) elements:
941          (s name collect: #code`er into: (ByteArray newSizeOf: s name))]
944 gen@(Generator traits) generateLiteral: f@(imports SingleFloat traits)
945 [| obj |
946   obj := gen cloneOf: (gen objectNamed: #FloatProto) elements: (ByteArray newWithAll: f).
947   gen littleEndian = -1.0 isLittleEndian
948     ifFalse: [obj elements := obj elements reversed].
949   obj
952 gen@(Generator traits) generateLiteral: a@(imports ByteArray traits)
954   a isEmpty
955     ifTrue: [gen objectNamed: #ByteArrayProto]
956     ifFalse: [gen cloneOf: (gen objectNamed: #ByteArrayProto) elements: a]
959 gen@(Generator traits) generateLiteral: a@(imports Array traits)
961   a isEmpty
962     ifTrue: [gen objectNamed: #ArrayProto]
963     ifFalse: [gen cloneOf: (gen objectNamed: #ArrayProto) elements:
964                 (a collect: #(gen generateLiteral: _) `er)]
967 gen@(Generator traits) generateLiteral: c@(imports ASCIIString Character traits)
969   gen characters at: c code
972 gen@(Generator traits) generateLiteral: block@(imports CompiledMethod traits)
973 [| obj |
974   obj := (gen cloneOf: (gen objectNamed: #CompiledMethodProto)) `>>
975    [setSlots: {
976       #inputVariables -> block inputVariables.
977       #localVariables -> block localVariables.
978       #restVariable -> (gen generateLiteral: block restVariable).
979       #heapAllocate -> (gen generateLiteral: block heapAllocate).
980       #literals -> (gen generateLiteral: block literals).
981       #registerCount -> (gen generateLiteral: block registerCount).
982       #selectors -> (gen generateLiteral: block selectors).
983       #code -> (gen generateLiteral: block code)}. ].
984   obj setSlot: #method to: obj.
985   block optionalKeywords isEmpty ifFalse:
986     [obj setSlot: #optionalKeywords to: (gen generateLiteral: block optionalKeywords)].
987   obj