Extracting parts of the formatting method into configuration and an options helper...
[cslatevm.git] / src / mobius / bootstrap.slate
blobbd75e4bac8fd7aa388f6c3eac8b2835298e839d4
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: {
7   #oop
8 }.
10 _@(Chunk traits) wordSize [overrideThis].
12 define: #SlotEntry &slots: {#name. #offset}.
14 se@(SlotEntry traits) newNamed: name offset: offset
15 [se clone `>> [name := name. offset := offset. ]].
17 define: #RoleEntry &slots: {
18   #name.
19   #rolePositions -> 0.
20   #methodDefinition
23 re@(RoleEntry traits) newNamed: name rolePositions: positions methodDefinition: method
24 [re clone `>>
25    [name := name. rolePositions := positions. methodDefinition := method. ]].
27 define: #MethodDefinition &slots: {
28   #dispatchPositions -> 0.
29   #method.
30   #slotAccessor
33 define: #Map &slots: {
34   #flags -> 0.
35   #representative -> Nil.
36   #delegates -> {}.
37   #slotCount -> 0.
38   #slotTable -> {}.
39   #roleTable -> {}
42 map@(Map traits) addSlotNamed: name at: offset
44   map slotTable :=
45     (map slotTable collect: #clone `er)
46     ; {map surroundings SlotEntry newNamed: name offset: offset}.
49 map@(Map traits) addRoleNamed: name at: position dispatching: def
51   map roleTable doWithIndex:
52     [| :role :index |
53      role methodDefinition == def
54        ifTrue:
55          [(map roleTable := map roleTable copy) at: index :=
56             (map surroundings RoleEntry
57                newNamed: name
58                rolePositions: (role rolePositions bitOr: (1 bitShift: position))
59                methodDefinition: def).
60           ^ False]].
61   map roleTable :=
62     map roleTable copyWith:
63       (map surroundings RoleEntry
64          newNamed: name
65          rolePositions: (1 bitShift: position)
66          methodDefinition: def).
67   True
70 define: #Object &parents: {Chunk} &slots: {
71   #idHash.
72   #bmap -> Map.
73   #slotValues -> {}
76 _@(Object traits) headerWords
77 [4].
79 obj@(Object traits) wordSizeSansPayload
80 [obj headerWords + obj slotValues size].
82 obj@(Object traits) wordSize
83 [obj wordSizeSansPayload].
85 obj@(Object traits) makeSlotNamed: name valued: value
86 [| index |
87   index := obj bmap slotCount.
88   obj bmap := obj bmap clone `>>
89     [slotCount := index + 1.
90      addSlotNamed: name at: obj headerWords + index * obj surroundings BytesPerWord. ].
91   obj slotValues := obj slotValues copyWith: value.
92   obj
95 obj@(Object traits) slotNamed: name
97   obj bmap slotTable
98     detect: [| :slot | slot name = name]
99     ifNone: [obj error: 'Slot missing: ' ; name]
102 obj@(Object traits) setSlot: name to: val
104   (obj slotNamed: name) ifNotNilDo:
105     [| :slot | obj slotValues at: slot offset / obj surroundings BytesPerWord - obj headerWords put: val]
108 obj@(Object traits) getSlot: name
110   (obj slotNamed: name) ifNotNilDo:
111     [| :slot | obj slotValues at: slot offset / obj surroundings BytesPerWord - obj headerWords]
114 obj@(Object traits) addDelegateValued: value
116   obj bmap := obj bmap clone `>>
117     [delegates := obj bmap delegates copyWith: value. ].
118   obj
121 obj@(Object traits) addRoleNamed: name at: position dispatching: def
123   obj bmap addRoleNamed: name at: position dispatching: def
126 method@(Object traits) addMethodNamed: name on: roles
127 [| def |
128   def := method surroundings MethodDefinition new
129    `>> [dispatchPositions := 0. method := method. ].
130   roles doWithIndex:
131     [| :role :index |
132      role ifNotNil:
133        [def dispatchPositions := def dispatchPositions bitOr: (1 bitShift: index).
134         role addRoleNamed: name at: index dispatching: def]].
135   "inform: 'Adding method %r roles: %r pos: %r', name, roles, def dispatchPositions."
136   def
139 define: #Array &parents: {Object}.
141 define: #OopArray &parents: {Array} &slots: {
142   #elements -> {}
145 arr@(OopArray traits) wordSize
146 [arr wordSizeSansPayload + arr elements size].
148 define: #ByteArray &parents: {Array} &slots: {
149   #elements -> imports ByteArray new
152 arr@(ByteArray traits) byteSize
154   arr wordSizeSansPayload * arr surroundings BytesPerWord + arr elements size
157 arr@(ByteArray traits) wordSize
159   arr wordSizeSansPayload + (arr elements size + arr surroundings BytesPerWord - 1 // arr surroundings BytesPerWord)
162 define: #CompiledMethod &parents: {Object}.
164 define: #Generator &slots: {
165   #translations -> IdentityDictionary new.
166   #chunks -> ExtensibleArray new.
167   #characters -> ({} newSizeOf: imports ASCIIString Character CharacterSet).
168   #symbols -> Dictionary new.
169   #littleEndian -> True.
170   #bytesPerWord -> BytesPerWord.
171   #nextHash -> 0.
172   #imageSize -> 0.
173   #objects -> Dictionary new.
176 gen@(Generator traits) new &littleEndian: littleEndian &wordSize: wordSize
178   littleEndian `defaultsTo: gen littleEndian.
179   wordSize `defaultsTo: Platform Current bytesPerWord * 8.
180   define: #BytesPerWord -> (wordSize // 8).
181   gen clone `>>
182     [objects := gen objects new.
183      translations := gen translations new.
184      chunks := gen chunks new.
185      characters := gen characters copy.
186      symbols := gen symbols new.
187      bytesPerWord := wordSize // 8.
188      littleEndian := littleEndian. ]
191 gen@(Generator traits) generateImageBooting: method withPrims: prims
192 "Generates the primary image objects such that the supplied CompiledMethod
193 will be interpreted immediately upon loading the image."
195   inform: 'Generating kernel'.
196   gen generateKernel.
197   inform: 'Generating utilities'.
198   gen generateUtilities.
199   inform: 'Generating kernel accessors'.
200   gen generateKernelAccessors.
201   inform: 'Generating interpreter'.
202   gen generateInterpreterBooting: method.
203   inform: 'Generating bootstrap namespace'.
204   gen generateBootstrapNamespace.
205   inform: 'Generating prims'.
206   prims do: [| :assoc | gen generatePrimitive: assoc value at: assoc key].
207   inform: 'Generating maps'.
208   gen generateMaps.
209   inform: 'Generating linkage'.
210   gen generateLinkage
213 gen@(Generator traits) objectsAt: name
214 [gen objects at: name].
216 gen@(Generator traits) objectsAt: name put: obj
218   inform: ' Adding object %s', name.
219   gen objects at: name put: obj
222 gen@(Generator traits) bytesAt: i in: arr put: val numBytes: bytes
224   0 below: bytes do:
225     [| :index |
226      arr elements at: i + index put:
227        (val byteShift: (gen littleEndian ifTrue: [0 - index]
228                                          ifFalse: [0 - bytes + index])) intoByte]
231 gen@(Generator traits) shortAt: i in: arr put: val
233   gen bytesAt: i in: arr put: val numBytes: 2
236 gen@(Generator traits) wordAt: i in: arr put: val
238   gen bytesAt: i in: arr put: val numBytes: gen bytesPerWord
241 gen@(Generator traits) capacityForTable: table
243   (table size * 5 // 4) leastGreaterPowerOfTwo
246 gen@(Generator traits) generateSlotTableFor: map
247 [| obj capacity selector hash |
248   capacity := gen capacityForTable: map slotTable.
249   obj := gen cloneOf: (gen objectsAt: #ArrayProto) sized: 2 * capacity.
250   map slotTable do:
251     [| :se |
252      selector := gen generateLiteral: se name.
253      hash := (selector idHash bitAnd: capacity - 1) * 2.
254      [(obj elements at: hash) isNil]
255        whileFalse:
256          [hash := (hash + 2) \\ (capacity * 2)].
257      obj elements at: hash put: selector.
258      obj elements at: hash + 1 put: se offset].
259   obj
262 gen@(Generator traits) generateRoleTableFor: map
263 [| obj capacity selector hash insert |
264   capacity := gen capacityForTable: map roleTable.
265   obj := gen cloneOf: (gen objectsAt: #ArrayProto) sized: 4 * capacity.
266   map roleTable do:
267     [| :re |
268      selector := gen generateLiteral: re name.
269      hash := (selector idHash bitAnd: capacity - 1) * 4.
270      [(obj elements at: hash) isNil
271         \/ [(obj elements at: hash) == selector]]
272        whileFalse:
273          [hash := (hash + 4) \\ (capacity * 4)].
274      insert := hash.
275      [(obj elements at: insert) isNil]
276        whileFalse:
277          [insert := (insert + 4) \\ (capacity * 4)].
278      obj elements at: insert put: selector.
279      obj elements at: insert + 1 put: re rolePositions.
280      obj elements at: insert + 2 put: (gen generateMethodDef: re methodDefinition).
281      insert == hash
282        ifFalse:
283          [[(obj elements at: hash + 3) isNil]
284             whileFalse: [hash := (obj elements at: hash + 3) * 4].
285           obj elements at: hash + 3 put: insert // 4]].
286   obj
289 gen@(Generator traits) generateMethodDef: def
291   gen translations at: def ifAbsentPut:
292     [| obj sym |
293      (sym := def method getSlot: #selector)
294        setSlot: #cacheMask to: ((sym getSlot: #cacheMask) bitOr: def dispatchPositions).
295      (obj := gen cloneOf: (gen objectsAt: #MethodDefinitionProto)) `>>
296        [setSlot: #method to: def method.
297         setSlot: #slotAccessor to: (gen generateLiteral: def slotAccessor). ].
298      gen wordAt: 1 * gen bytesPerWord in: obj put: def dispatchPositions.
299      obj]
302 gen@(Generator traits) generateMap: map
304   gen translations at: map ifAbsentPut:
305     [(gen cloneOf: (gen objectsAt: #MapProto)) `>>
306        [setSlot: #flags to: map flags.
307         setSlot: #representative to: (map representative ifNil: [gen objectsAt: #NilObject]).
308         setSlot: #delegates to: (gen cloneOf: (gen objectsAt: #ArrayProto) elements: map delegates).
309         setSlot: #slotCount to: map slotCount.
310         setSlot: #slotTable to: (gen generateSlotTableFor: map).
311         setSlot: #roleTable to: (gen generateRoleTableFor: map). ]]
314 gen@(Generator traits) generateMaps
316   gen objects keysAndValuesDo:
317     [| :name :obj |
318      inform: ' Adding map for %s', name.
319      gen generateMap: obj bmap]
322 obj@(Object traits) nextOop
323 "Answer the pointer to just beyond this object."
324 [obj oop + (obj wordSize * obj surroundings BytesPerWord)].
326 gen@(Generator traits) assignOops
327 "Assign oops to all of the chunks, accumulating the final oop which is used
328 to set the image size."
330   gen imageSize := gen chunks inject: 0 into:
331     [| :oop :chunk | chunk oop := oop. chunk nextOop]
334 gen@(Generator traits) emitInteger: val on: stream byteSize: byteSize
335 "Takes an integer and outputs the binary data value in the correct byte-order
336 onto the stream."
338   stream next: byteSize putInteger: val &littleEndian: gen littleEndian
341 gen@(Generator traits) emitWord: val on: stream
342 "Takes an integer and outputs the binary data value in the correct byte-order
343 onto the stream."
345   gen emitInteger: val on: stream byteSize: gen bytesPerWord
348 gen@(Generator traits) emitOopOf: chunk on: stream
349 [gen emitWord: chunk oop on: stream].
351 gen@(Generator traits) emitOopOf: _@Nil on: stream
352 [gen emitOopOf: (gen objectsAt: #NilObject) on: stream].
354 gen@(Generator traits) emitOopOf: i@(imports SmallInteger traits) on: stream
355 [gen emitWord: (i << 1 bitOr: 1) on: stream].
357 gen@(Generator traits) emitHeaderOf: obj sized: size payload: payload format: format on: stream
359   hash ::= obj idHash.
360   "header"
361   gen littleEndian
362     ifTrue:
363       [stream nextPut: (2r00000001 bitOr: (hash bitAnd: 16r7F) << 1).
364        stream nextPut: (hash >> 7) intoByte.
365        stream nextPut: (hash >> 15) intoByte.
366        stream nextPut: format << 6.
367        gen emitInteger: 0 on: stream byteSize: gen bytesPerWord - 4]
368     ifFalse:
369       [gen emitInteger: 0 on: stream byteSize: gen bytesPerWord - 4.
370        stream nextPut: (2r10000000 bitOr: (hash >> 16 bitAnd: 16r7F)).
371        stream nextPut: (hash >> 8) intoByte.
372        stream nextPut: hash intoByte.
373        stream nextPut: format].
375   "size in words of slot data"
376   gen emitWord: size on: stream.
377   "size in bytes of payload (oop array or byte array)"
378   gen emitWord: payload on: stream.
381 gen@(Generator traits) emit: obj@(Object traits) on: stream
383   gen emitHeaderOf: obj
384     sized: obj wordSize
385     payload: 0
386     format: 2r00
387     on: stream.
388   gen emitWord: (gen translations at: obj bmap) oop on: stream.
389   obj slotValues do:
390     [| :slotVal | gen emitOopOf: slotVal on: stream].
391   obj
394 gen@(Generator traits) emit: obj@(OopArray traits) on: stream
396   gen emitHeaderOf: obj
397     sized: obj wordSizeSansPayload
398     payload: obj elements size * gen bytesPerWord
399     format: 2r01
400     on: stream.
401   gen emitWord: (gen translations at: obj bmap) oop on: stream.
402   obj slotValues ;; obj elements do:
403     [| :slotVal | gen emitOopOf: slotVal on: stream].
404   obj
407 gen@(Generator traits) emit: obj@(ByteArray traits) on: stream
409   gen emitHeaderOf: obj
410     sized: obj wordSizeSansPayload
411     payload: obj elements size
412     format: 2r10
413     on: stream.
414   gen emitWord: (gen translations at: obj bmap) oop on: stream.
415   obj slotValues do:
416     [| :slotVal | gen emitOopOf: slotVal on: stream].
417   stream nextPutAll: obj elements.
418   stream next: (gen bytesPerWord - obj elements size) \\ gen bytesPerWord put: 0.
419   obj
422 gen@(Generator traits) emitHeaderOn: stream
424   gen emitWord: 16rABCDEF43 on: stream.
425   gen emitWord: gen imageSize on: stream.
426   gen emitWord: gen nextHash on: stream.
427   gen emitWord: ((gen objectsAt: #GlobalsObject) getSlot: #specialOops) oop on: stream.
428 "i shortened dispatch id to one word"
429   gen emitWord: 0 on: stream.
432 gen@(Generator traits) emitOn: stream
433 "Emits a bootstrap image on the stream after it has been generated."
435   inform: 'Assigning oops'.
436   gen assignOops.
437   inform: 'Emitting image: %s', stream resource locator.
438   gen emitHeaderOn: stream.
439   gen chunks do: [| :chunk | gen emit: chunk on: stream]
442 gen@(Generator traits) newIdentityHash
443 [| hash |
444   hash := gen nextHash.
445   gen nextHash += 1.
446   hash
449 gen@(Generator traits) newMap
451   gen surroundings Map clone
454 gen@(Generator traits) newObject &layout: layout &map: map
455 [| obj |
456   layout `defaultsTo: gen surroundings Object.
457   map `defaultsTo: gen newMap.
458   obj := layout clone `>> [idHash := gen newIdentityHash. bmap := map. ].
459   obj slotValues := obj slotValues newSize: map slotCount.
460   map representative := obj.
461   gen chunks addLast: obj.
462   obj
465 gen@(Generator traits) cloneOf: proto@(Object traits)
467   gen chunks addLast: proto clone `>>
468     [idHash := gen newIdentityHash. slotValues := proto slotValues copy. ]
471 gen@(Generator traits) cloneOf: arr@(Array traits)
472 [resend `>> [elements := arr elements copy. ]].
474 gen@(Generator traits) cloneOf: proto sized: size
475 [(gen cloneOf: proto) `>> [elements := proto elements newSize: size. ]].
477 gen@(Generator traits) cloneOf: proto elements: elements
478 [(gen cloneOf: proto) `>> [elements := elements as: proto elements. ]].
480 gen@(Generator traits) addAccessorFor: slotName on: obj
481 [| accessor selector |
482   selector := obj accessorNameFor: slotName.
483   (accessor := gen cloneOf: (gen objectsAt: #CompiledMethodProto)) `>>
484     [setSlot: #method to: accessor.
485      setSlot: #selector to: (gen generateLiteral: selector).
486      setSlot: #inputVariables to: 1.
487      setSlot: #localVariables to: 1.
488      setSlot: #registerCount to: 3.
489      setSlot: #literals to: (gen cloneOf: (gen objectsAt: #ArrayProto) elements: {gen generateLiteral: slotName}).
490      setSlot: #selectors to: (gen cloneOf: (gen objectsAt: #ArrayProto) elements: {gen generateLiteral: #atSlotNamed:}).
491      setSlot: #code to:
492        (gen cloneOf: (gen objectsAt: #ArrayProto) elements: {
493          VM SSACode loadVariable. 0.
494          VM SSACode loadLiteral. 1. gen generateLiteral: slotName.
495          VM SSACode directSendMessage. 0. gen generateLiteral: #atSlotNamed:. 2. 0. 1.
496          VM SSACode returnRegister. 0
497      }). ].
498   (accessor addMethodNamed: selector on: {obj}) slotAccessor: slotName.
499   accessor
502 gen@(Generator traits) addMutatorFor: slotName on: obj
503 [| mutator selector |
504   selector := obj mutatorNameFor: slotName.
505   (mutator := gen cloneOf: (gen objectsAt: #CompiledMethodProto)) `>>
506     [setSlot: #method to: mutator.
507      setSlot: #selector to: (gen generateLiteral: selector).
508      setSlot: #inputVariables to: 2.
509      setSlot: #localVariables to: 1.
510      setSlot: #registerCount to: 4.
511      setSlot: #literals to: (gen cloneOf: (gen objectsAt: #ArrayProto) elements: {gen generateLiteral: slotName}).
512      setSlot: #selectors to: (gen cloneOf: (gen objectsAt: #ArrayProto) elements: {gen generateLiteral: #atSlotNamed:put:}).
513      setSlot: #code to:
514        (gen cloneOf: (gen objectsAt: #ArrayProto) elements: {
515          VM SSACode loadVariable. 0.
516          VM SSACode loadVariable. 1.
517          VM SSACode loadLiteral. 2. gen generateLiteral: slotName.
518          VM SSACode directSendMessage. 0. gen generateLiteral: #atSlotNamed:put:. 3. 0. 2. 1.
519          VM SSACode returnRegister. 0
520      }). ].
521   (mutator addMethodNamed: selector on: {obj. Nil}) slotAccessor: slotName.
522   mutator
525 gen@(Generator traits) addAccessorsFor: slotName on: obj
527   gen addAccessorFor: slotName on: obj.
528   gen addMutatorFor: slotName on: obj
531 gen@(Generator traits) generateKernelAccessors
533   gen objects do:
534     [| :obj |
535      obj bmap slotTable do: [| :slot | gen addAccessorsFor: slot name on: obj]]
538 gen@(Generator traits) generatePrototype: name &suffix: suffix &layout: layout &parents: parents &slots: slotSpecs &elements: elements
539 [| traits window result |
540   suffix `defaultsTo: 'Proto'.
541   traits := (gen objectsAt: (name ; 'Traits') intern := gen newObject)
542     `>> [addDelegateValued: Nil. ].
543   window := (gen objectsAt: (name ; 'Window') intern := gen newObject)
544     `>> [bmap flags := 1. addDelegateValued: Nil. ].
545   parents
546     ifNotNil:
547       [parents reverseDoWithIndex:
548         [| :parent :index |
549           window addDelegateValued: parent]].
550   window addDelegateValued: traits.
551   result := (gen objectsAt: (name ; suffix) intern := gen newObject &layout: layout)
552     `>> [addDelegateValued: window. ].
553   elements ifNotNil:
554     [(result hasSlotNamed: #elements) ifTrue: [result elements := elements]].
555   (slotSpecs `defaultsTo: {}) do:
556     [| :spec | result makeSlotNamed: spec key valued: spec value].
557   result
560 gen@(Generator traits) generateInstance: name of: window
561 [(gen objectsAt: name := gen newObject) `>>
562   [addDelegateValued: window.]
565 gen@(Generator traits) generateKernel
567   gen generatePrototype: 'Root'.
568   gen generatePrototype: 'Oddball' &parents: {gen objectsAt: #RootTraits}.
569   gen generatePrototype: 'Derivable' &parents: {gen objectsAt: #RootTraits}.
570   gen generatePrototype: 'Cloneable' &parents: {gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}.
572   gen generateInstance: #NilObject of: (gen objectsAt: #OddballWindow).
573   gen generateInstance: #NoRoleObject of: (gen objectsAt: #OddballWindow).
575   gen generatePrototype: 'Boolean' &parents: {gen objectsAt: #OddballTraits. gen objectsAt: #RootTraits}.
576   gen generateInstance: #TrueObject of: (gen objectsAt: #BooleanWindow).
577   gen generateInstance: #FalseObject of: (gen objectsAt: #BooleanWindow).
579   gen generatePrototype: 'Array' &layout: gen surroundings OopArray
580     &parents: {gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}
581     &elements: Array new.
582   gen generatePrototype: 'ByteArray' &layout: gen surroundings ByteArray
583     &parents: {gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}
584     &elements: ByteArray new.
586   gen generatePrototype: 'SmallInteger' &parents: {gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #OddballTraits. gen objectsAt: #RootTraits}.
587   (gen generatePrototype: 'Float' &layout: gen surroundings ByteArray
588     &parents: {gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #ByteArrayTraits. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits})
589     `>> [elements := ByteArray newSize: gen bytesPerWord].
591   gen generatePrototype: 'ASCIIString' &layout: gen surroundings ByteArray
592     &parents: {gen objectsAt: #NilObject. gen objectsAt: #ByteArrayTraits. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}.
594   gen generatePrototype: 'Symbol' &layout: gen surroundings ByteArray
595     &parents: {gen objectsAt: #ASCIIStringTraits. gen objectsAt: #NilObject. gen objectsAt: #ByteArrayTraits. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}
596     &slots: {#cacheMask -> 0}.
598   gen symbols at: #'' put: (gen objectsAt: #SymbolProto).
600   gen generatePrototype: 'ASCIICharacter'
601     &parents: {gen objectsAt: #NilObject. gen objectsAt: #OddballTraits. gen objectsAt: #RootTraits} &slots: {#code -> 0}.
602   gen characters at: 0 put: (gen objectsAt: #ASCIICharacterProto).
603   1 below: gen characters size do:
604     [| :index c |
605      c := gen cloneOf: (gen objectsAt: #ASCIICharacterProto).
606      c setSlot: #code to: index.
607      gen characters at: index put: c].
608   (gen objectsAt: #ASCIIStringTraits) makeSlotNamed: #Character valued: (gen objectsAt: #ASCIICharacterProto).
610   gen generatePrototype: 'Namespace'
611     &parents: {gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}.
612   gen generateInstance: #BootstrapObject of: (gen objectsAt: #NamespaceWindow).
614   gen generatePrototype: 'Method' &parents: {gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}.
616   gen generatePrototype: 'PrimitiveMethod'
617     &parents: {gen objectsAt: #MethodTraits. gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}
618     &slots: {#index -> 0. #selector -> (gen objectsAt: #NilObject). #inputVariables -> 0}.
620   gen generatePrototype: 'CompiledMethod'
621     &parents: {gen objectsAt: #MethodTraits. gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}
622     &slots: {
623       #method -> (gen objectsAt: #NilObject).
624       #selector -> (gen objectsAt: #NilObject).
625       #inputVariables -> 0. #localVariables -> 0.
626       #restVariable -> (gen objectsAt: #FalseObject).
627       #optionalKeywords -> (gen objectsAt: #ArrayProto).
628       #heapAllocate -> (gen objectsAt: #FalseObject).
629       #environment -> (gen objectsAt: #BootstrapObject).
630       #literals -> (gen objectsAt: #ArrayProto).
631       #selectors -> (gen objectsAt: #ArrayProto).
632       #code -> (gen objectsAt: #ArrayProto).
633       #sourceTree -> (gen objectsAt: #NilObject).
634       #debugMap -> (gen objectsAt: #ArrayProto).
635       #isInlined -> (gen objectsAt: #FalseObject).
636       #oldCode -> (gen objectsAt: #NilObject).
637       #callCount -> 0.
638       #calleeCount -> (gen objectsAt: #NilObject).
639       #registerCount -> 0.
640       #cachedInCallers -> (gen objectsAt: #NilObject).
641       #cachedInCallersCount -> 0.
642       #nextInlineAtCallCount -> (gen objectsAt: #NilObject).
643       #reserved5 -> (gen objectsAt: #NilObject).
644       #reserved6 -> 0}.
646   gen generatePrototype: 'Closure' &layout: gen surroundings OopArray
647     &parents: {gen objectsAt: #MethodTraits. gen objectsAt: #ArrayTraits. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}
648     &slots: {#method -> (gen objectsAt: #NilObject)}.
650   gen generatePrototype: 'MethodDefinition' &layout: gen surroundings ByteArray
651     &parents: {gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}
652     &slots: {
653       #method -> (gen objectsAt: #CompiledMethodProto).
654       #slotAccessor -> (gen objectsAt: #NilObject)}
655     &elements: (ByteArray newSize: 4 * gen bytesPerWord).
657   gen generatePrototype: 'Map' &layout: gen surroundings ByteArray
658     &parents: {gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}
659     &slots: {
660       #flags -> 0.
661       #representative -> (gen objectsAt: #NilObject).
662       #delegates -> (gen objectsAt: #ArrayProto).
663       #slotCount -> 0.
664       #slotTable -> (gen objectsAt: #ArrayProto).
665       #roleTable -> (gen objectsAt: #ArrayProto)}
666     &elements: (ByteArray newSize: 3 * gen bytesPerWord).
668   gen generatePrototype: 'LexicalContext' &layout: gen surroundings OopArray
669     &parents: {gen objectsAt: #ArrayTraits. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #NilObject. gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}
670     &slots: {#framePointer -> 0}.
672   gen generatePrototype: 'Interpreter' &layout: gen surroundings ByteArray
673     &parents: {gen objectsAt: #CloneableTraits. gen objectsAt: #DerivableTraits. gen objectsAt: #RootTraits}
674     &slots: {
675       #stack -> (gen objectsAt: #ArrayProto).
676       #method -> (gen objectsAt: #NilObject).
677       #closure -> (gen objectsAt: #NilObject).
678       #lexicalContext -> (gen objectsAt: #NilObject).
679       #ensureHandlers -> 0}
680     &elements: (ByteArray newSize: 5 * gen bytesPerWord).
682   (gen objectsAt: #EnsureMarkerObject := gen cloneOf: (gen objectsAt: #CompiledMethodProto)) `>>
683     [| :marker |
684      setSlot: #method to: marker.
685      setSlot: #code to:
686        (gen cloneOf: (gen objectsAt: #ArrayProto)
687           elements: {VM SSACode resume})].
690 Generator traits define: #Compiler &parents: {VM SSACompiler} &slots: {
691   #generator.
694 c@(Generator Compiler traits) newFor: gen
696   result ::= c new.
697   result generator := gen.
698   result
701 c@(Generator Compiler traits) branchTableHash: key
703   ((literal ::= c generator generateLiteral: key) isSameAs: SmallInteger)
704     ifTrue: [literal]
705     ifFalse: [literal idHash]
708 gen@(Generator traits) generateInterpreterBooting: method
709 [| stackSize |
710   compiler ::= gen Compiler newFor: gen.
711   inform: 'Compiling bootstrap source into VM instructions.'.
713   methodCompiled ::= (compiler generate: method result: Nil &topLevel: True)
714     `>> [heapAllocate := False. ].
716   "compiler decompile: method code."
718   methodLiteral ::= gen generateLiteral: methodCompiled.
720   stackSize := 16. "if you change this, change vm.c which has it hard-coded in the beginning of interpret()"
722   stackObj ::= (gen cloneOf: (gen objectsAt: #ArrayProto) sized: stackSize) `>>
723     [elements at: 0 put: 0. "-6: prev sp"
724      elements at: 1 put: -1. "-5: resultStackPointer"
725      elements at: 2 put: 0. "-4: code pointer"
726      elements at: 3 put: methodLiteral. "-3: closure"
727      elements at: 4 put: 0. "-2: lexical context"
728      elements at: 5 put: 0. "-1: prev fp"
729      elements at: 6 put: 0. ].
731   codeSize ::= methodCompiled code size.
733   (interpreter ::= gen objectsAt: #InterpreterObject := gen cloneOf: (gen objectsAt: #InterpreterProto)) `>>
734     [setSlot: #stack to: stackObj.
735      setSlot: #method to: methodLiteral.
736      setSlot: #closure to: methodLiteral. ].
737   gen wordAt: 0 * gen bytesPerWord in: interpreter put: 6. " frame pointer (framesize=6)"
738   "long at 1 is code pointer -- I guess this gets filled later or is zero"
739   gen wordAt: 2 * gen bytesPerWord in: interpreter put: codeSize.
740   gen wordAt: 3 * gen bytesPerWord in: interpreter put: 6. "stack pointer (framesize=6)"
741   gen wordAt: 4 * gen bytesPerWord in: interpreter put: stackSize
744 gen@(Generator traits) generateUtilities
746   gen generateInstance: #ConsoleObject of: (gen objectsAt: #OddballWindow).
748   gen generatePrototype: 'File' &parents: {
749     gen objectsAt: #NilObject.
750     gen objectsAt: #CloneableTraits.
751     gen objectsAt: #DerivableTraits.
752     gen objectsAt: #RootTraits
753   }.
754   gen generatePrototype: 'Directory' &parents: {
755     gen objectsAt: #NilObject.
756     gen objectsAt: #CloneableTraits.
757     gen objectsAt: #DerivableTraits.
758     gen objectsAt: #RootTraits
759   }.
760   gen generatePrototype: 'ExternalLibrary' &parents: {
761     gen objectsAt: #NilObject.
762     gen objectsAt: #CloneableTraits.
763     gen objectsAt: #DerivableTraits.
764     gen objectsAt: #RootTraits
765   }.
768 gen@(Generator traits) generateBootstrapNamespace
770   gen objectsAt: #PrototypesObject := gen cloneOf: (gen objectsAt: #NamespaceProto).
771   (gen objectsAt: #BootstrapObject) addDelegateValued: (gen objectsAt: #PrototypesObject).
772   "timmy: no named delegate slots but name needed for accessor"
773   (gen objectsAt: #BootstrapObject) makeSlotNamed: #prototypes valued: (gen objectsAt: #PrototypesObject).
774   gen addAccessorFor: #prototypes on: (gen objectsAt: #BootstrapObject).
775   "Install slots/accessors in the 'prototypes' namespace,
776    set up traits traits, and set up printName. Make sure all bootstrapped protos
777    are listed here, otherwise these important steps are left out for them."
778   [| :slotName :objectName obj printNameLiteral window traits |
779     obj := gen objectsAt: objectName.
780     (gen objectsAt: #PrototypesObject) makeSlotNamed: slotName valued: obj.
781     gen addAccessorFor: slotName on: (gen objectsAt: #PrototypesObject).
782     window := obj bmap delegates first.
783     window bmap delegates at: 0 put: (gen objectsAt: #CloneableWindow).
784     traits := window bmap delegates last"(window getSlot: #traits)".
785     traits bmap delegates at: 0 put: (gen objectsAt: #CloneableWindow).
786     printNameLiteral := gen generateLiteral: slotName name.
787     traits makeSlotNamed: #printNameTraits valued: printNameLiteral.
788     gen addAccessorFor: #printNameTraits on: traits.
789     window makeSlotNamed: #printNameWindow valued: printNameLiteral.
790     gen addAccessorFor: #printNameWindow on: window
791   ] applier for: #{
792     {#Root.             #RootProto}.
793     {#Oddball.          #OddballProto}.
794     {#Cloneable.        #CloneableProto}.
795     {#Derivable.        #DerivableProto}.
796     {#Namespace.        #NamespaceProto}.
797     {#Boolean.          #BooleanProto}.
798     {#Array.            #ArrayProto}.
799     {#ByteArray.        #ByteArrayProto}.
800     {#ASCIIString.      #ASCIIStringProto}.
801     {#ASCIICharacter.   #ASCIICharacterProto}.
802     {#Symbol.           #SymbolProto}.
803     {#SmallInteger.     #SmallIntegerProto}.
804     {#SingleFloat.      #FloatProto}.
805     {#Map.              #MapProto}.
806     {#LexicalContext.   #LexicalContextProto}.
807     {#MethodDefinition. #MethodDefinitionProto}.
808     {#Method.           #MethodProto}.
809     {#PrimitiveMethod.  #PrimitiveMethodProto}.
810     {#CompiledMethod.   #CompiledMethodProto}.
811     {#Closure.          #ClosureProto}.
812     {#Interpreter.      #InterpreterProto}.
813     {#File.             #FileProto}.
814     {#Directory.        #DirectoryProto}.
815     {#ExternalLibrary.  #ExternalLibraryProto}
816   }.
818   gen objectsAt: #GlobalsObject := gen cloneOf: (gen objectsAt: #NamespaceProto).
819   (gen objectsAt: #BootstrapObject) addDelegateValued: (gen objectsAt: #GlobalsObject).
820   (gen objectsAt: #BootstrapObject) makeSlotNamed: #globals valued: (gen objectsAt: #GlobalsObject).
821   gen addAccessorFor: #globals on: (gen objectsAt: #BootstrapObject).
822   [| :key :value |
823    (gen objectsAt: #GlobalsObject) makeSlotNamed: key valued: value.
824    gen addAccessorFor: key on: (gen objectsAt: #GlobalsObject)] applier for: {
825      {#Console.              gen objectsAt: #ConsoleObject}.
826      {#NoRole.               gen objectsAt: #NoRoleObject}.
827      {#Nil.                  gen objectsAt: #NilObject}.
828      {#True.                 gen objectsAt: #TrueObject}.
829      {#False.                gen objectsAt: #FalseObject}.
830      {#lobby.                gen objectsAt: #BootstrapObject}.
831      {#bootstrapCharacters.  gen cloneOf: (gen objectsAt: #ArrayProto) elements: gen characters}.
832      {#Symbols.              gen objectsAt: #ArrayProto}.
833      {#bootstrapInterpreter. gen objectsAt: #InterpreterObject}.
834      {#ensureMarker.         gen objectsAt: #EnsureMarkerObject}.
835      {#specialOops.          gen objectsAt: #ArrayProto}.
836      {#features.             gen objectsAt: #ArrayProto}.
837   }.
838   gen addMutatorFor: #features on: (gen objectsAt: #GlobalsObject)
841 gen@(Generator traits) generateLinkage
842 "TODO: The order in this method must be the same as in memory.slate, enforce it"
844   (gen objectsAt: #GlobalsObject) setSlot: #specialOops to:
845     (gen cloneOf: (gen objectsAt: #ArrayProto) elements:
846        (#{#BootstrapObject.
847           #NoRoleObject.
848           #NilObject.
849           #TrueObject.
850           #FalseObject.
851           #ArrayProto.
852           #ByteArrayProto.
853           #ASCIIStringProto.
854           #MapProto.
855           #MethodDefinitionProto.
856           #SmallIntegerProto.
857           #FloatProto.
858           #ClosureWindow.
859           #CompiledMethodWindow.
860           #PrimitiveMethodWindow.
861           #ClosureProto.
862           #LexicalContextProto.
863           #InterpreterObject.
864           #EnsureMarkerObject.
865       } collect: #(gen objectsAt: _) `er)
866        ; ({#notFoundOn:.
867            #notFoundOn:after:.
868            #wrongInputsTo:.
869            #mayNotReturnTo:.
870            #slotNotFoundNamed:.
871            #keyNotFoundOn:.
872            #immutable.
873            #bitShiftOverflow:.
874            #addOverflow:.
875            #subtractOverflow:.
876            #multiplyOverflow:.
877            #divideByZero.
878            #notABoolean.
879            #applyTo:.
880            #&optionals:.
881            #badTypeError} collect: #(gen generateLiteral: _) `er)).
882   (gen objectsAt: #GlobalsObject) setSlot: #Symbols to:
883     (gen cloneOf: (gen objectsAt: #ArrayProto) elements: gen symbols valueSet).
886 gen@(Generator traits) generatePrimitive: prim at: index
887 "Given a MethodDefinition representing a Pidgin primitive definition,
888 this defines a PrimitiveMethod stub that will invoke the given primitive
889 index. Must be called after generateImageBooting:."
891   (gen cloneOf: (gen objectsAt: #PrimitiveMethodProto)) `>>
892     [setSlot: #selector to: (gen generateLiteral: prim selector).
893      setSlot: #inputVariables to: prim roles size.
894      setSlot: #index to: index.
895      addMethodNamed: prim selector on:
896        (prim roles collect:
897           [| :role |
898            (role isSameAs: nodes UnaryMessage) ifTrue:
899              [inform: ' Adding primitive %s to %s', index, role selector.
900               gen objectsAt: role selector]]) ]
903 gen@(Generator traits) generateLiteral: literal
905   literal == NoRole
906     ifTrue: [gen objectsAt: #NoRoleObject]
907     ifFalse: [error: 'Unsupported literal.']
910 gen@(Generator traits) generateLiteral: i@(imports SmallInteger traits)
911 [i].
913 gen@(Generator traits) generateLiteral: _@(imports BigInteger traits)
915   error: 'The bootstrap generator does not support big integers.'
918 gen@(Generator traits) generateLiteral: _@True
919 [gen objectsAt: #TrueObject].
921 gen@(Generator traits) generateLiteral: _@False
922 [gen objectsAt: #FalseObject].
924 gen@(Generator traits) generateLiteral: _@Nil
925 [gen objectsAt: #NilObject].
927 gen@(Generator traits) generateLiteral: _@lobby
928 [gen objectsAt: #BootstrapObject].
930 gen@(Generator traits) generateLiteral: s@(imports ASCIIString traits)
932   s isEmpty
933     ifTrue: [gen objectsAt: #ASCIIStringProto]
934     ifFalse: [gen cloneOf: (gen objectsAt: #ASCIIStringProto) elements:
935                 (s collect: #code`er into: (ByteArray newSizeOf: s))]
938 gen@(Generator traits) generateLiteral: s@(imports Symbol traits)
940   gen symbols at: s ifAbsentPut:
941     [gen cloneOf: (gen objectsAt: #SymbolProto) elements:
942        (s name collect: #code`er into: (ByteArray newSizeOf: s name))]
945 gen@(Generator traits) generateLiteral: f@(imports SingleFloat traits)
946 [| obj |
947   obj := gen cloneOf: (gen objectsAt: #FloatProto) elements: (ByteArray newWithAll: f).
948   gen littleEndian = -1.0 isLittleEndian
949     ifFalse: [obj elements := obj elements reversed].
950   obj
953 gen@(Generator traits) generateLiteral: a@(imports ByteArray traits)
955   a isEmpty
956     ifTrue: [gen objectsAt: #ByteArrayProto]
957     ifFalse: [gen cloneOf: (gen objectsAt: #ByteArrayProto) elements: a]
960 gen@(Generator traits) generateLiteral: a@(imports Array traits)
962   a isEmpty
963     ifTrue: [gen objectsAt: #ArrayProto]
964     ifFalse: [gen cloneOf: (gen objectsAt: #ArrayProto) elements:
965                 (a collect: #(gen generateLiteral: _) `er)]
968 gen@(Generator traits) generateLiteral: c@(imports ASCIIString Character traits)
970   gen characters at: c code
973 gen@(Generator traits) generateLiteral: block@(imports CompiledMethod traits)
974 [| obj |
975   obj := (gen cloneOf: (gen objectsAt: #CompiledMethodProto)) `>>
976    [| :obj |
977     setSlot: #inputVariables to: block inputVariables.
978     setSlot: #localVariables to: block localVariables.
979     setSlot: #restVariable to: (gen generateLiteral: block restVariable).
980     setSlot: #heapAllocate to: (gen generateLiteral: block heapAllocate).
981     setSlot: #literals to: (gen generateLiteral: block literals).
982     setSlot: #registerCount to: (gen generateLiteral: block registerCount).
983     setSlot: #selectors to: (gen generateLiteral: block selectors).
984     setSlot: #code to: (gen generateLiteral: block code).
985     setSlot: #method to: obj. ].
986   block optionalKeywords isEmpty ifFalse:
987     [obj setSlot: #optionalKeywords to: (gen generateLiteral: block optionalKeywords)].
988   obj