[Pkg] The Trunk: Compiler-eem.164.mcz
commits at source.squeak.org
commits at source.squeak.org
Tue Aug 17 21:40:46 UTC 2010
Eliot Miranda uploaded a new version of Compiler to project The Trunk:
http://source.squeak.org/trunk/Compiler-eem.164.mcz
==================== Summary ====================
Name: Compiler-eem.164
Author: eem
Time: 17 August 2010, 2:00:44.208 pm
UUID: ea2d2d68-7509-45b6-a835-b038702661b5
Ancestors: Compiler-eem.163
Stage one cleanup of the old parse node sizers & emitters
=============== Diff against Compiler-eem.163 ===============
Item was changed:
+ ----- Method: BytecodeAgnosticMethodNode>>generateWithTempNames (in category 'code generation') -----
- ----- Method: BytecodeAgnosticMethodNode>>generateWithTempNames (in category 'code generation (new scheme)') -----
generateWithTempNames
"Answer a CompiledMethod with temps names encoded in trailer"
^ self generate: (CompiledMethodTrailer new tempNames: self schematicTempNamesString).
!
Item was added:
+ ----- Method: MethodNode>>noteBlockEntry: (in category 'code generation (closures)') -----
+ noteBlockEntry: aBlock
+ "Evaluate aBlock with the numbering for the block entry."
+ locationCounter isNil ifTrue:
+ [locationCounter := -1].
+ aBlock value: locationCounter + 1.
+ locationCounter := locationCounter + 2!
Item was changed:
+ ----- Method: FieldNode>>emitCodeForEffect:encoder: (in category 'code generation') -----
- ----- Method: FieldNode>>emitCodeForEffect:encoder: (in category 'code generation (new scheme)') -----
emitCodeForEffect: stack encoder: encoder!
Item was changed:
+ ----- Method: TempVariableNode>>sizeCodeForLoad: (in category 'code generation') -----
- ----- Method: TempVariableNode>>sizeCodeForLoad: (in category 'code generation (new scheme)') -----
sizeCodeForLoad: encoder
^remoteNode isNil
ifTrue: [0]
ifFalse: [remoteNode sizeCodeForLoadFor: self encoder: encoder]!
Item was changed:
+ ----- Method: TempVariableNode>>sizeCodeForStore: (in category 'code generation') -----
- ----- Method: TempVariableNode>>sizeCodeForStore: (in category 'code generation (new scheme)') -----
sizeCodeForStore: encoder
remoteNode ~~ nil ifTrue:
[^remoteNode sizeCodeForStoreInto: self encoder: encoder].
self reserve: encoder.
^encoder sizeStoreTemp: index!
Item was changed:
+ ----- Method: MessageNode>>emitCodeForWhile:encoder:value: (in category 'code generation') -----
- ----- Method: MessageNode>>emitCodeForWhile:encoder:value: (in category 'code generation (new scheme)') -----
emitCodeForWhile: stack encoder: encoder value: forValue
"L1: ... Bfp(L2)|Btp(L2) ... Jmp(L1) L2: "
| cond stmt stmtSize loopSize |
cond := receiver.
stmt := arguments at: 1.
stmtSize := sizes at: 1.
loopSize := sizes at: 2.
cond emitCodeForEvaluatedValue: stack encoder: encoder.
self emitCodeForBranchOn: (selector key == #whileFalse:) "Bfp for whileTrue"
dist: stmtSize pop: stack encoder: encoder. "Btp for whileFalse"
pc := encoder methodStreamPosition.
stmt emitCodeForEvaluatedEffect: stack encoder: encoder.
self emitCodeForJump: 0 - loopSize encoder: encoder.
forValue ifTrue: [encoder genPushSpecialLiteral: nil. stack push: 1]!
Item was changed:
+ ----- Method: VariableNode>>sizeCodeForReturn: (in category 'code generation') -----
- ----- Method: VariableNode>>sizeCodeForReturn: (in category 'code generation (new scheme)') -----
sizeCodeForReturn: encoder
encoder
if: code
isSpecialLiteralForPush:
[:specialLiteral|
^encoder sizeReturnSpecialLiteral: specialLiteral].
(self code = LdSelf or: [self code = LdSuper]) ifTrue:
[^encoder sizeReturnReceiver].
^super sizeCodeForReturn: encoder!
Item was changed:
+ ----- Method: AssignmentNode>>emitCodeForEffect:encoder: (in category 'code generation') -----
- ----- Method: AssignmentNode>>emitCodeForEffect:encoder: (in category 'code generation (new scheme)') -----
emitCodeForEffect: stack encoder: encoder
variable emitCodeForLoad: stack encoder: encoder.
value emitCodeForValue: stack encoder: encoder.
pc := encoder methodStreamPosition + 1. "debug pc is first byte of the store, i.e. the next byte".
variable emitCodeForStorePop: stack encoder: encoder!
Item was changed:
+ ----- Method: MessageNode>>emitCodeForToDo:encoder:value: (in category 'code generation') -----
- ----- Method: MessageNode>>emitCodeForToDo:encoder:value: (in category 'code generation (new scheme)') -----
emitCodeForToDo: stack encoder: encoder value: forValue
" var := rcvr. L1: [var <= arg1] Bfp(L2) [block body. var := var + inc] Jmp(L1) L2: "
| loopSize initStmt limitInit test block incStmt blockSize |
initStmt := arguments at: 4.
limitInit := arguments at: 7.
test := arguments at: 5.
block := arguments at: 3.
incStmt := arguments at: 6.
blockSize := sizes at: 1.
loopSize := sizes at: 2.
limitInit == nil
ifFalse: [limitInit emitCodeForEffect: stack encoder: encoder].
initStmt emitCodeForEffect: stack encoder: encoder.
test emitCodeForValue: stack encoder: encoder.
self emitCodeForBranchOn: false dist: blockSize pop: stack encoder: encoder.
pc := encoder methodStreamPosition.
block emitCodeForEvaluatedEffect: stack encoder: encoder.
incStmt emitCodeForEffect: stack encoder: encoder.
self emitCodeForJump: 0 - loopSize encoder: encoder.
forValue ifTrue: [encoder genPushSpecialLiteral: nil. stack push: 1]!
Item was changed:
+ ----- Method: CascadeNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: CascadeNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
receiver emitCodeForValue: stack encoder: encoder.
1 to: messages size - 1 do:
[:i |
encoder genDup.
stack push: 1.
(messages at: i) emitCodeForValue: stack encoder: encoder.
encoder genPop.
stack pop: 1].
messages last emitCodeForValue: stack encoder: encoder!
Item was changed:
+ ----- Method: FutureNode>>emitCodeForBlockValue:encoder: (in category 'code generation') -----
- ----- Method: FutureNode>>emitCodeForBlockValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForBlockValue: stack encoder: encoder
"Generate code for evaluating the last statement in a block."
^effectNode emitCodeForValue: stack encoder: encoder!
Item was changed:
+ ----- Method: LeafNode>>sizeCodeForLoad: (in category 'code generation') -----
- ----- Method: LeafNode>>sizeCodeForLoad: (in category 'code generation (new scheme)') -----
sizeCodeForLoad: encoder
"Default is to do nothing.
Subclasses may need to override."
^0!
Item was changed:
+ ----- Method: BlockNode>>sizeCodeExceptLast: (in category 'code generation') -----
- ----- Method: BlockNode>>sizeCodeExceptLast: (in category 'code generation (new scheme)') -----
sizeCodeExceptLast: encoder
| codeSize |
codeSize := 0.
1 to: statements size - 1 do:
[:i | | statement |
statement := statements at: i.
codeSize := codeSize + (statement sizeCodeForEffect: encoder)].
^codeSize!
Item was changed:
+ ----- Method: MaybeContextInstanceVariableNode>>sizeCodeForStorePop: (in category 'code generation') -----
- ----- Method: MaybeContextInstanceVariableNode>>sizeCodeForStorePop: (in category 'code generation (new scheme)') -----
sizeCodeForStorePop: encoder
^encoder sizeStorePopInstVarLong: index!
Item was changed:
+ ----- Method: FieldNode>>emitCodeForLoad:encoder: (in category 'code generation') -----
- ----- Method: FieldNode>>emitCodeForLoad:encoder: (in category 'code generation (new scheme)') -----
emitCodeForLoad: stack encoder: encoder
rcvrNode emitCodeForValue: stack encoder: encoder.
fieldDef accessKey ifNotNil:[
super emitCodeForValue: stack encoder: encoder.
].!
Item was changed:
+ ----- Method: ParseNode>>sizeCodeForReturn: (in category 'code generation') -----
- ----- Method: ParseNode>>sizeCodeForReturn: (in category 'code generation (new scheme)') -----
sizeCodeForReturn: encoder
^(self sizeCodeForValue: encoder) + encoder sizeReturnTop!
Item was changed:
+ ----- Method: VariableNode>>emitCodeForStorePop:encoder: (in category 'code generation') -----
- ----- Method: VariableNode>>emitCodeForStorePop:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStorePop: stack encoder: encoder
self type ~= 1 ifTrue:
[self halt].
encoder genStorePopInstVar: index.
stack pop: 1!
Item was changed:
+ ----- Method: MaybeContextInstanceVariableNode>>emitCodeForStorePop:encoder: (in category 'code generation') -----
- ----- Method: MaybeContextInstanceVariableNode>>emitCodeForStorePop:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStorePop: stack encoder: encoder
encoder genStorePopInstVarLong: index.
stack pop: 1!
Item was changed:
+ ----- Method: TempVariableNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: TempVariableNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
remoteNode ~~ nil ifTrue:
[^remoteNode emitCodeForValueOf: self stack: stack encoder: encoder].
encoder genPushTemp: index.
stack push: 1!
Item was changed:
+ ----- Method: BlockNode>>sizeCodeForEvaluatedValue: (in category 'code generation') -----
- ----- Method: BlockNode>>sizeCodeForEvaluatedValue: (in category 'code generation (new scheme)') -----
sizeCodeForEvaluatedValue: encoder
^(self sizeCodeExceptLast: encoder)
+ (statements last sizeCodeForBlockValue: encoder)!
Item was changed:
+ ----- Method: ReturnNode>>sizeCodeForReturn: (in category 'code generation') -----
- ----- Method: ReturnNode>>sizeCodeForReturn: (in category 'code generation (new scheme)') -----
sizeCodeForReturn: encoder
^expr sizeCodeForReturn: encoder!
Item was added:
+ ----- Method: MethodNode>>schematicTempNamesString (in category 'debugger support') -----
+ schematicTempNamesString
+ "Answer the temp names for the current method node in a form that captures
+ temp structure. The temps at each method and block scope level occur
+ space-separated, with any indirect temps enclosed in parentheses. Each block
+ level is enclosed in square brackets. e.g.
+ 'method level temps (indirect temp)[block args and temps (indirect)]'
+ This representation can be reconstituted into a blockExtentsToTempsMap
+ by a CompiledMethod that has been copied with the schematicTempNamesString."
+ encoder hasGeneratedMethod ifFalse:
+ ["create the encoder's blockExtentsToLoals map, except if the method is quick
+ in which case it has no temps."
+ (self generate) isQuick ifTrue:
+ [^'']].
+ ^encoder schematicTempNamesString!
Item was changed:
+ ----- Method: MessageAsTempNode>>sizeCodeForStorePop: (in category 'code generation') -----
- ----- Method: MessageAsTempNode>>sizeCodeForStorePop: (in category 'code generation (new scheme)') -----
sizeCodeForStorePop: encoder
"This node has the form {expr storeAt: offset inTempFrame: homeContext},
where the expr, the block argument, is already on the stack."
^self sizeCodeForEffect: encoder!
Item was changed:
+ ----- Method: FutureNode>>sizeCodeForEffect: (in category 'code generation') -----
- ----- Method: FutureNode>>sizeCodeForEffect: (in category 'code generation (new scheme)') -----
sizeCodeForEffect: encoder
receiver == NodeSuper ifTrue: [^self error: 'Futures cannot send to future'].
(futureArgs isNil or: [futureSelector isNil]) ifTrue:
[^self error: 'Futures must be sent messages'].
encoder sharableLitIndex: originalSelector. "to find its senders"
futureDelta ifNil:[futureDelta := encoder encodeLiteral: 0].
effectNode := MessageNode new
receiver: receiver
selector: #futureDo:at:args:
arguments: (Array
with: (encoder encodeLiteral: futureSelector)
with: futureDelta
with: (BraceNode new elements: futureArgs))
precedence: 3
from: encoder.
^effectNode sizeCodeForEffect: encoder!
Item was changed:
+ ----- Method: MessageAsTempNode>>emitCodeForStorePop:encoder: (in category 'code generation') -----
- ----- Method: MessageAsTempNode>>emitCodeForStorePop:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStorePop: stack encoder: encoder
"This node has the form {expr storeAt: offset inTempFrame: homeContext},
where the expr, the block argument, is already on the stack."
^self emitCodeForEffect: stack encoder: encoder!
Item was changed:
+ ----- Method: LeafNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: LeafNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
self subclassResponsibility!
Item was changed:
+ ----- Method: MaybeContextInstanceVariableNode>>sizeCodeForStore: (in category 'code generation') -----
- ----- Method: MaybeContextInstanceVariableNode>>sizeCodeForStore: (in category 'code generation (new scheme)') -----
sizeCodeForStore: encoder
^encoder sizeStoreInstVarLong: index!
Item was changed:
+ ----- Method: InstanceVariableNode>>sizeCodeForStorePop: (in category 'code generation') -----
- ----- Method: InstanceVariableNode>>sizeCodeForStorePop: (in category 'code generation (new scheme)') -----
sizeCodeForStorePop: encoder
^encoder sizeStorePopInstVar: index!
Item was changed:
+ ----- Method: InstanceVariableNode>>emitCodeForStorePop:encoder: (in category 'code generation') -----
- ----- Method: InstanceVariableNode>>emitCodeForStorePop:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStorePop: stack encoder: encoder
encoder genStorePopInstVar: index.
stack pop: 1!
Item was changed:
+ ----- Method: ParseNode>>sizeCode:forBranchOn:dist: (in category 'code generation') -----
- ----- Method: ParseNode>>sizeCode:forBranchOn:dist: (in category 'code generation (new scheme)') -----
sizeCode: encoder forBranchOn: condition dist: dist
dist = 0 ifTrue: [^encoder sizePop].
^condition
ifTrue: [encoder sizeBranchPopTrue: dist]
ifFalse: [encoder sizeBranchPopFalse: dist]!
Item was changed:
+ ----- Method: MessageNode>>emitCodeForIfNil:encoder:value: (in category 'code generation') -----
- ----- Method: MessageNode>>emitCodeForIfNil:encoder:value: (in category 'code generation (new scheme)') -----
emitCodeForIfNil: stack encoder: encoder value: forValue
| theNode theSize ifNotNilSelector |
theNode := arguments first.
theSize := sizes at: 1.
ifNotNilSelector := #ifNotNil:.
receiver emitCodeForValue: stack encoder: encoder.
forValue ifTrue: [encoder genDup. stack push: 1].
encoder genPushSpecialLiteral: nil. stack push: 1.
equalNode emitCode: stack args: 1 encoder: encoder.
self
emitCodeForBranchOn: (selector key == ifNotNilSelector)
dist: theSize
pop: stack
encoder: encoder.
pc := encoder methodStreamPosition.
forValue
ifTrue:
[encoder genPop. stack pop: 1.
theNode emitCodeForEvaluatedValue: stack encoder: encoder]
ifFalse: [theNode emitCodeForEvaluatedEffect: stack encoder: encoder]!
Item was changed:
+ ----- Method: MessageNode>>sizeCodeForWhile:value: (in category 'code generation') -----
- ----- Method: MessageNode>>sizeCodeForWhile:value: (in category 'code generation (new scheme)') -----
sizeCodeForWhile: encoder value: forValue
"L1: ... Bfp(L2) ... Jmp(L1) L2: nil (nil for value only);
justStmt, wholeLoop, justJump."
| cond stmt stmtSize loopSize branchSize |
cond := receiver.
stmt := arguments at: 1.
stmtSize := (stmt sizeCodeForEvaluatedEffect: encoder) + (encoder sizeJumpLong: 1).
branchSize := self
sizeCode: encoder
forBranchOn: selector key == #whileFalse: "Btp for whileFalse"
dist: stmtSize.
loopSize := (cond sizeCodeForEvaluatedValue: encoder) + branchSize + stmtSize.
sizes := Array with: stmtSize with: loopSize.
^loopSize + (forValue ifTrue: [encoder sizePushSpecialLiteral: nil] ifFalse: [0])!
Item was changed:
+ ----- Method: AssignmentNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: AssignmentNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
variable emitCodeForLoad: stack encoder: encoder.
value emitCodeForValue: stack encoder: encoder.
pc := encoder methodStreamPosition + 1. "debug pc is first byte of the store, i.e. the next byte".
variable emitCodeForStore: stack encoder: encoder!
Item was changed:
+ ----- Method: FieldNode>>emitCodeForStore:encoder: (in category 'code generation') -----
- ----- Method: FieldNode>>emitCodeForStore:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStore: stack encoder: encoder
fieldDef accessKey ifNil:[
writeNode emitCode: stack args: 1 encoder: encoder super: false.
] ifNotNil:[
writeNode emitCode: stack args: 2 encoder: encoder super: false.
].!
Item was changed:
+ ----- Method: ParseNode>>sizeCodeForBlockValue: (in category 'code generation') -----
- ----- Method: ParseNode>>sizeCodeForBlockValue: (in category 'code generation (new scheme)') -----
sizeCodeForBlockValue: encoder
"Answer the size for evaluating the last statement in a block"
^self sizeCodeForValue: encoder!
Item was changed:
+ ----- Method: SelectorNode>>emitCode:args:encoder: (in category 'code generation') -----
- ----- Method: SelectorNode>>emitCode:args:encoder: (in category 'code generation (new scheme)') -----
emitCode: stack args: nArgs encoder: encoder
self emitCode: stack
args: nArgs
encoder: encoder
super: false!
Item was changed:
+ ----- Method: VariableNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: VariableNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
self reserve: encoder.
encoder
if: code
isSpecialLiteralForPush:
[:specialLiteral| "i.e. the pseudo-variables nil true & false"
^encoder sizePushSpecialLiteral: specialLiteral].
(code = LdSelf or: [code = LdSuper]) ifTrue:
[^encoder sizePushReceiver].
code = LdThisContext ifTrue:
[^encoder sizePushThisContext].
self flag: 'probably superfluous'.
self halt.
^encoder sizePushInstVar: index!
Item was changed:
+ ----- Method: BlockNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: BlockNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
self generateAsClosure ifTrue:
[^self sizeCodeForClosureValue: encoder].
nArgsNode := encoder encodeLiteral: arguments size.
remoteCopyNode := encoder encodeSelector: #blockCopy:.
size := self sizeCodeForEvaluatedValue: encoder.
self returns ifFalse:
[size := size + encoder sizeReturnTopToCaller]. "endBlock"
arguments := arguments collect: "Chance to prepare debugger remote temps"
[:arg | arg asStorableNode: encoder].
arguments do: [:arg | size := size + (arg sizeCodeForStorePop: encoder)].
^encoder sizePushThisContext
+ (nArgsNode sizeCodeForValue: encoder)
+ (remoteCopyNode sizeCode: encoder args: 1 super: false)
+ (encoder sizeJumpLong: size)
+ size!
Item was changed:
+ ----- Method: VariableNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: VariableNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
stack push: 1.
encoder
if: code
isSpecialLiteralForPush:
[:specialLiteral|
^encoder genPushSpecialLiteral: specialLiteral].
(code = LdSelf or: [code = LdSuper]) ifTrue:
[^encoder genPushReceiver].
code = LdThisContext ifTrue:
[^encoder genPushThisContext].
self flag: 'probably superfluous'.
self halt.
^encoder genPushInstVar: index!
Item was changed:
+ ----- Method: MessageNode>>sizeCodeForIfNil:value: (in category 'code generation') -----
- ----- Method: MessageNode>>sizeCodeForIfNil:value: (in category 'code generation (new scheme)') -----
sizeCodeForIfNil: encoder value: forValue
| theNode theSize theSelector |
equalNode := encoder encodeSelector: #==.
sizes := Array new: 1.
theNode := arguments first.
theSelector := #ifNotNil:.
forValue
ifTrue:
[sizes at: 1 put: (theSize := (encoder sizePop + (theNode sizeCodeForEvaluatedValue: encoder))).
^(receiver sizeCodeForValue: encoder)
+ encoder sizeDup
+ (encoder sizePushSpecialLiteral: nil)
+ (equalNode sizeCode: encoder args: 1 super: false)
+ (self
sizeCode: encoder forBranchOn: selector key == theSelector
dist: theSize)
+ theSize]
ifFalse:
[sizes at: 1 put: (theSize := (theNode sizeCodeForEvaluatedEffect: encoder)).
^(receiver sizeCodeForValue: encoder)
+ (encoder sizePushSpecialLiteral: nil)
+ (equalNode sizeCode: encoder args: 1 super: false)
+ (self
sizeCode: encoder
forBranchOn: selector key == theSelector
dist: theSize)
+ theSize]!
Item was changed:
+ ----- Method: BlockNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: BlockNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
self generateAsClosure ifTrue:
[^self emitCodeForClosureValue: stack encoder: encoder].
encoder genPushThisContext.
stack push: 1.
nArgsNode emitCodeForValue: stack encoder: encoder.
remoteCopyNode
emitCode: stack
args: 1
encoder: encoder.
"Force a two byte jump."
encoder genJumpLong: size.
stack push: arguments size.
arguments reverseDo: [:arg | arg emitCodeForStorePop: stack encoder: encoder].
self emitCodeForEvaluatedValue: stack encoder: encoder.
self returns ifFalse:
[encoder genReturnTopToCaller.
pc := encoder methodStreamPosition].
stack pop: 1!
Item was changed:
+ ----- Method: MaybeContextInstanceVariableNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: MaybeContextInstanceVariableNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
stack push: 1.
^encoder genPushInstVarLong: index!
Item was changed:
+ ----- Method: NewArrayNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: NewArrayNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
encoder genPushNewArray: numElements.
stack push: 1!
Item was added:
+ ----- Method: MethodNode>>referencedValuesWithinBlockExtent: (in category 'code generation (closures)') -----
+ referencedValuesWithinBlockExtent: anInterval
+ ^(localsPool select:
+ [:temp|
+ temp isReferencedWithinBlockExtent: anInterval]) collect:
+ [:temp|
+ temp isRemote ifTrue: [temp remoteNode] ifFalse: [temp]]!
Item was changed:
+ ----- Method: BraceNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: BraceNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
(encoder supportsClosureOpcodes
"Hack; we have no way of knowing how much stack space is available"
and: [elements size <= self maxElementsForConsArray]) ifTrue:
[^(elements inject: 0 into: [:sum :node| sum + (node sizeCodeForValue: encoder)])
+ (encoder sizePushConsArray: elements size)].
emitNode := elements size <= 4
ifTrue: ["Short form: Array braceWith: a with: b ... "
MessageNode new
receiver: (encoder encodeVariable: #Array)
selector: (self selectorForShortForm: elements size)
arguments: elements precedence: 3 from: encoder]
ifFalse: ["Long form: (Array braceStream: N) nextPut: a; nextPut: b; ...; braceArray"
CascadeNode new
receiver: (MessageNode new
receiver: (encoder encodeVariable: #Array)
selector: #braceStream:
arguments: (Array with: (encoder encodeLiteral: elements size))
precedence: 3 from: encoder)
messages: ((elements collect: [:elt | MessageNode new receiver: nil
selector: #nextPut:
arguments: (Array with: elt)
precedence: 3 from: encoder])
copyWith: (MessageNode new receiver: nil
selector: #braceArray
arguments: (Array new)
precedence: 1 from: encoder))].
^emitNode sizeCodeForValue: encoder!
Item was changed:
+ ----- Method: MessageNode>>emitCodeForCase:encoder:value: (in category 'code generation') -----
- ----- Method: MessageNode>>emitCodeForCase:encoder:value: (in category 'code generation (new scheme)') -----
emitCodeForCase: stack encoder: encoder value: forValue
| braceNode sizeStream allReturn |
forValue ifFalse:
[^super emitCodeForEffect: stack encoder: encoder].
braceNode := arguments first.
sizeStream := ReadStream on: sizes.
receiver emitCodeForValue: stack encoder: encoder.
"There must be at least one branch around the otherwise/caseError
so the decompiler can identify the end of the otherwise/caseError."
allReturn := true. "assume every case ends with a return"
braceNode casesForwardDo:
[:keyNode :valueNode :last | | thenSize elseSize |
thenSize := sizeStream next.
elseSize := sizeStream next.
last ifFalse: [encoder genDup. stack push: 1].
keyNode emitCodeForEvaluatedValue: stack encoder: encoder.
equalNode emitCode: stack args: 1 encoder: encoder.
self emitCodeForBranchOn: false dist: thenSize pop: stack encoder: encoder.
last ifFalse: [encoder genPop. stack pop: 1].
valueNode emitCodeForEvaluatedValue: stack encoder: encoder.
last ifTrue: [stack pop: 1].
valueNode returns ifFalse:
[self emitCodeForJump: elseSize encoder: encoder.
allReturn := false].
(last and: [allReturn]) ifTrue:
[self emitCodeForJump: elseSize encoder: encoder]].
arguments size = 2
ifTrue:
[arguments last emitCodeForEvaluatedValue: stack encoder: encoder] "otherwise: [...]"
ifFalse:
[NodeSelf emitCodeForValue: stack encoder: encoder.
caseErrorNode emitCode: stack args: 0 encoder: encoder]!
Item was changed:
+ ----- Method: BraceNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: BraceNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
(encoder supportsClosureOpcodes
"Hack; we have no way of knowing how much stack space is available"
and: [elements size <= self maxElementsForConsArray]) ifTrue:
[elements do: [:node| node emitCodeForValue: stack encoder: encoder].
encoder genPushConsArray: elements size.
stack
pop: elements size;
push: 1.
^self].
^emitNode emitCodeForValue: stack encoder: encoder!
Item was changed:
+ ----- Method: SelectorNode>>emitCode:args:encoder:super: (in category 'code generation') -----
- ----- Method: SelectorNode>>emitCode:args:encoder:super: (in category 'code generation (new scheme)') -----
emitCode: stack args: nArgs encoder: encoder super: supered
stack pop: nArgs.
^supered
ifTrue:
[encoder genSendSuper: index numArgs: nArgs]
ifFalse:
[encoder
genSend: (code < Send ifTrue: [code negated] ifFalse: [index])
numArgs: nArgs]!
Item was changed:
+ ----- Method: LiteralVariableNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: LiteralVariableNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
self reserve: encoder.
(key isVariableBinding and: [key isSpecialReadBinding])
ifFalse:
[^encoder sizePushLiteralVar: index].
readNode := MessageNode new
receiver: (encoder encodeLiteral: key)
selector: (encoder encodeSelector: #value)
arguments: #()
precedence: #value precedence.
^readNode sizeCodeForValue: encoder!
Item was changed:
+ ----- Method: InstanceVariableNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: InstanceVariableNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
^encoder sizePushInstVar: index!
Item was added:
+ ----- Method: MethodNode>>ensureClosureAnalysisDone (in category 'code generation (closures)') -----
+ ensureClosureAnalysisDone
+ block blockExtent ifNil:
+ [temporaries := block analyseArguments: arguments temporaries: temporaries rootNode: self]!
Item was changed:
+ ----- Method: FutureNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: FutureNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
receiver == NodeSuper ifTrue: [^self error: 'Futures cannot send to future'].
(futureArgs isNil or: [futureSelector isNil]) ifTrue:
[^self error: 'Futures must be sent messages'].
encoder sharableLitIndex: originalSelector. "to find its senders"
futureDelta ifNil:[futureDelta := encoder encodeLiteral: 0].
valueNode := MessageNode new
receiver: receiver
selector: #futureSend:at:args:
arguments: (Array
with: (encoder encodeLiteral: futureSelector)
with: futureDelta
with: (BraceNode new elements: futureArgs))
precedence: 3
from: encoder.
^valueNode sizeCodeForValue: encoder!
Item was changed:
+ ----- Method: InstanceVariableNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: InstanceVariableNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
stack push: 1.
^encoder genPushInstVar: index!
Item was changed:
+ ----- Method: ReturnNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: ReturnNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
expr emitCodeForReturn: stack encoder: encoder.
pc := encoder methodStreamPosition!
Item was changed:
ParseNode subclass: #MethodNode
+ instanceVariableNames: 'selectorOrFalse precedence arguments block primitive encoder temporaries properties sourceText locationCounter localsPool'
- instanceVariableNames: 'selectorOrFalse precedence arguments block primitive encoder temporaries properties sourceText'
classVariableNames: ''
poolDictionaries: ''
category: 'Compiler-ParseNodes'!
!MethodNode commentStamp: '<historical>' prior: 0!
I am the root of the parse tree.!
Item was changed:
+ ----- Method: ParseNode>>emitCodeForJump:encoder: (in category 'code generation') -----
- ----- Method: ParseNode>>emitCodeForJump:encoder: (in category 'code generation (new scheme)') -----
emitCodeForJump: dist encoder: encoder
dist = 0 ifFalse: [encoder genJump: dist]!
Item was changed:
+ ----- Method: BlockNode>>emitCodeForEvaluatedEffect:encoder: (in category 'code generation') -----
- ----- Method: BlockNode>>emitCodeForEvaluatedEffect:encoder: (in category 'code generation (new scheme)') -----
emitCodeForEvaluatedEffect: stack encoder: encoder
| position |
position := stack position.
self returns
ifTrue:
[self emitCodeForEvaluatedValue: stack encoder: encoder.
stack pop: 1]
ifFalse:
[self emitCodeExceptLast: stack encoder: encoder.
statements last emitCodeForEffect: stack encoder: encoder].
self assert: stack position = position!
Item was added:
+ ----- Method: MethodNode>>hasGeneratedMethod (in category 'debugger support') -----
+ hasGeneratedMethod
+ ^encoder hasGeneratedMethod!
Item was changed:
+ ----- Method: MessageNode>>emitCodeForEffect:encoder: (in category 'code generation') -----
- ----- Method: MessageNode>>emitCodeForEffect:encoder: (in category 'code generation (new scheme)') -----
emitCodeForEffect: stack encoder: encoder
"For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly."
special > 0
ifTrue:
[pc := 0.
self perform: (NewStyleMacroEmitters at: special) with: stack with: encoder with: false]
ifFalse:
[super emitCodeForEffect: stack encoder: encoder]!
Item was added:
+ ----- Method: MethodNode>>blockExtentsToTempsMap (in category 'debugger support') -----
+ blockExtentsToTempsMap
+ "Answer a Dictionary of blockExtent to temp locations for the current method.
+ This is used by the debugger to locate temp vars in contexts. A temp map
+ entry is a pair of the temp's name and its index, where an index is either an
+ integer for a normal temp or a pair of the index of the indirect temp vector
+ containing the temp and the index of the temp in its indirect temp vector."
+
+ ^encoder blockExtentsToTempsMap ifNil:
+ [| methNode |
+ methNode := encoder classEncoding parserClass new
+ encoderClass: encoder class;
+ parse: (sourceText ifNil: [self decompileString])
+ class: self methodClass.
+ "As a side effect generate: creates data needed for the map."
+ methNode generate.
+ methNode encoder blockExtentsToTempsMap]!
Item was changed:
+ ----- Method: FieldNode>>sizeCodeForStorePop: (in category 'code generation') -----
- ----- Method: FieldNode>>sizeCodeForStorePop: (in category 'code generation (new scheme)') -----
sizeCodeForStorePop: encoder
^(self sizeCodeForStore: encoder) + encoder sizePop!
Item was changed:
+ ----- Method: AssignmentNode>>sizeCodeForEffect: (in category 'code generation') -----
- ----- Method: AssignmentNode>>sizeCodeForEffect: (in category 'code generation (new scheme)') -----
sizeCodeForEffect: encoder
^(variable sizeCodeForLoad: encoder)
+ (value sizeCodeForValue: encoder)
+ (variable sizeCodeForStorePop: encoder)!
Item was changed:
+ ----- Method: LiteralVariableNode>>emitCodeForLoad:encoder: (in category 'code generation') -----
- ----- Method: LiteralVariableNode>>emitCodeForLoad:encoder: (in category 'code generation (new scheme)') -----
emitCodeForLoad: stack encoder: encoder
writeNode ifNotNil:
[encoder genPushLiteral: index.
stack push: 1]!
Item was changed:
+ ----- Method: FieldNode>>emitCodeForStorePop:encoder: (in category 'code generation') -----
- ----- Method: FieldNode>>emitCodeForStorePop:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStorePop: stack encoder: encoder
self emitCodeForStore: stack encoder: encoder.
encoder genPop.
stack pop: 1.!
Item was changed:
+ ----- Method: ParseNode>>sizeCode:forJump: (in category 'code generation') -----
- ----- Method: ParseNode>>sizeCode:forJump: (in category 'code generation (new scheme)') -----
sizeCode: encoder forJump: dist
^dist = 0 ifTrue: [0] ifFalse: [encoder sizeJump: dist]!
Item was changed:
+ ----- Method: ParseNode>>emitCodeForBlockValue:encoder: (in category 'code generation') -----
- ----- Method: ParseNode>>emitCodeForBlockValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForBlockValue: stack encoder: encoder
"Generate code for evaluating the last statement in a block"
^self emitCodeForValue: stack encoder: encoder!
Item was changed:
+ ----- Method: SelectorNode>>emitCodeForEffect:encoder: (in category 'code generation') -----
- ----- Method: SelectorNode>>emitCodeForEffect:encoder: (in category 'code generation (new scheme)') -----
emitCodeForEffect: stack encoder: encoder
self shouldNotImplement!
Item was changed:
+ ----- Method: MessageNode>>sizeCodeForCase:value: (in category 'code generation') -----
- ----- Method: MessageNode>>sizeCodeForCase:value: (in category 'code generation (new scheme)') -----
sizeCodeForCase: encoder value: forValue
| braceNode sizeIndex elseSize allReturn |
forValue not ifTrue:
[^super sizeCodeForEffect: encoder].
equalNode := encoder encodeSelector: #=.
braceNode := arguments first.
sizes := Array new: 2 * braceNode numElements.
sizeIndex := sizes size.
elseSize := arguments size = 2
ifTrue:
[arguments last sizeCodeForEvaluatedValue: encoder] "otherwise: [...]"
ifFalse:
[caseErrorNode := encoder encodeSelector: #caseError.
(NodeSelf sizeCodeForValue: encoder)
+ (caseErrorNode sizeCode: encoder args: 0 super: false)]. "self caseError"
"There must be at least one branch around the otherwise/caseError
so the decompiler can identify the end of the otherwise/caseError."
allReturn := true. "assume every case ends with a return"
braceNode casesForwardDo:
[:keyNode :valueNode :last |
valueNode returns ifFalse: [allReturn := false]].
braceNode casesReverseDo:
[:keyNode :valueNode :last | | thenSize |
sizes at: sizeIndex put: elseSize.
thenSize := valueNode sizeCodeForEvaluatedValue: encoder.
last ifFalse: [thenSize := thenSize + encoder sizePop].
valueNode returns ifFalse: [thenSize := thenSize + (self sizeCode: encoder forJump: elseSize)].
(last and: [allReturn]) ifTrue: [thenSize := thenSize + (self sizeCode: encoder forJump: elseSize)].
sizes at: sizeIndex-1 put: thenSize.
last ifFalse: [elseSize := elseSize + encoder sizeDup].
elseSize := elseSize
+ (keyNode sizeCodeForEvaluatedValue: encoder)
+ (equalNode sizeCode: encoder args: 1 super: false)
+ (self sizeCode: encoder forBranchOn: false dist: thenSize)
+ thenSize.
sizeIndex := sizeIndex - 2].
^(receiver sizeCodeForValue: encoder) + elseSize!
Item was added:
+ ----- Method: MethodNode>>noteBlockExit: (in category 'code generation (closures)') -----
+ noteBlockExit: aBlock
+ "Evaluate aBlock with the numbering for the block exit."
+ aBlock value: locationCounter + 1.
+ locationCounter := locationCounter + 2!
Item was changed:
+ ----- Method: VariableNode>>emitCodeForReturn:encoder: (in category 'code generation') -----
- ----- Method: VariableNode>>emitCodeForReturn:encoder: (in category 'code generation (new scheme)') -----
emitCodeForReturn: stack encoder: encoder
encoder
if: code
isSpecialLiteralForReturn:
[:specialLiteral|
"short returns"
encoder genReturnSpecialLiteral: specialLiteral.
stack push: 1 "doesnt seem right".
^self].
(self code = LdSelf or: [self code = LdSuper]) ifTrue:
["short returns"
encoder genReturnReceiver.
stack push: 1 "doesnt seem right".
^self].
super emitCodeForReturn: stack encoder: encoder!
Item was changed:
+ ----- Method: CascadeNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: CascadeNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
| size |
size := (receiver sizeCodeForValue: encoder)
+ (messages size - 1 * (encoder sizeDup + encoder sizePop)).
messages do: [:aMessage | size := size + (aMessage sizeCodeForValue: encoder)].
^size!
Item was changed:
+ ----- Method: FieldNode>>sizeCodeForStore: (in category 'code generation') -----
- ----- Method: FieldNode>>sizeCodeForStore: (in category 'code generation (new scheme)') -----
sizeCodeForStore: encoder
rcvrNode ifNil:[self encodeReceiverOn: encoder].
fieldDef accessKey ifNil:[
writeNode ifNil:[writeNode := encoder encodeSelector: fieldDef toSet].
^(rcvrNode sizeCodeForValue: encoder) +
(writeNode sizeCode: encoder args: 1 super: false)
].
writeNode ifNil:[writeNode := encoder encodeSelector: #set:to:].
^(rcvrNode sizeCodeForValue: encoder) +
(super sizeCodeForValue: encoder) +
(writeNode sizeCode: encoder args: 2 super: false)!
Item was changed:
+ ----- Method: BlockNode>>sizeCodeForEvaluatedEffect: (in category 'code generation') -----
- ----- Method: BlockNode>>sizeCodeForEvaluatedEffect: (in category 'code generation (new scheme)') -----
sizeCodeForEvaluatedEffect: encoder
^self returns
ifTrue: [self sizeCodeForEvaluatedValue: encoder]
ifFalse: [(self sizeCodeExceptLast: encoder)
+ (statements last sizeCodeForEffect: encoder)]!
Item was changed:
+ ----- Method: TempVariableNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: TempVariableNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
remoteNode ~~ nil ifTrue:
[^remoteNode sizeCodeForValueOf: self encoder: encoder].
self reserve: encoder.
^encoder sizePushTemp: index!
Item was changed:
+ ----- Method: ParseNode>>emitCodeForReturn:encoder: (in category 'code generation') -----
- ----- Method: ParseNode>>emitCodeForReturn:encoder: (in category 'code generation (new scheme)') -----
emitCodeForReturn: stack encoder: encoder
self emitCodeForValue: stack encoder: encoder.
encoder genReturnTop!
Item was changed:
+ ----- Method: ParseNode>>sizeCodeForEffect: (in category 'code generation') -----
- ----- Method: ParseNode>>sizeCodeForEffect: (in category 'code generation (new scheme)') -----
sizeCodeForEffect: encoder
^(self sizeCodeForValue: encoder) + encoder sizePop!
Item was changed:
+ ----- Method: MessageNode>>sizeCodeForToDo:value: (in category 'code generation') -----
- ----- Method: MessageNode>>sizeCodeForToDo:value: (in category 'code generation (new scheme)') -----
sizeCodeForToDo: encoder value: forValue
" var := rcvr. L1: [var <= arg1] Bfp(L2) [block body. var := var + inc] Jmp(L1) L2: "
| loopSize initStmt test block incStmt blockSize initSize limitInit |
block := arguments at: 3.
initStmt := arguments at: 4.
test := arguments at: 5.
incStmt := arguments at: 6.
limitInit := arguments at: 7.
initSize := initStmt sizeCodeForEffect: encoder.
limitInit == nil ifFalse:
[initSize := initSize + (limitInit sizeCodeForEffect: encoder)].
blockSize := (block sizeCodeForEvaluatedEffect: encoder)
+ (incStmt sizeCodeForEffect: encoder)
+ (encoder sizeJumpLong: -1).
loopSize := (test sizeCodeForValue: encoder)
+ (self sizeCode: encoder forBranchOn: false dist: blockSize)
+ blockSize.
sizes := Array with: blockSize with: loopSize.
^initSize
+ loopSize
+ (forValue ifTrue: [encoder sizePushSpecialLiteral: nil] ifFalse: [0])!
Item was changed:
+ ----- Method: LiteralVariableNode>>emitCodeForStore:encoder: (in category 'code generation') -----
- ----- Method: LiteralVariableNode>>emitCodeForStore:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStore: stack encoder: encoder
writeNode ifNil: [^encoder genStoreLiteralVar: index].
"THIS IS WRONG!!!! THE VALUE IS LOST FROM THE STACK!!!!
The various value: methods on Association ReadOnlyVariableBinding
etc _do not_ return the value assigned; they return the receiver."
"Should generate something more like
push expr
push lit
push temp (index of expr)
send value:
pop
or use e.g. valueForStore:"
self flag: #bogus.
writeNode
emitCode: stack
args: 1
encoder: encoder
super: false!
Item was changed:
+ ----- Method: ReturnNode>>emitCodeForReturn:encoder: (in category 'code generation') -----
- ----- Method: ReturnNode>>emitCodeForReturn:encoder: (in category 'code generation (new scheme)') -----
emitCodeForReturn: stack encoder: encoder
expr emitCodeForReturn: stack encoder: encoder.
pc := encoder methodStreamPosition!
Item was changed:
+ ----- Method: MessageNode>>sizeCodeForIf:value: (in category 'code generation') -----
- ----- Method: MessageNode>>sizeCodeForIf:value: (in category 'code generation (new scheme)') -----
sizeCodeForIf: encoder value: forValue
| thenExpr elseExpr branchSize thenSize elseSize |
thenExpr := arguments at: 1.
elseExpr := arguments at: 2.
(forValue
or: [(thenExpr isJust: NodeNil)
or: [elseExpr isJust: NodeNil]]) not
"(...not ifTrue: avoids using ifFalse: alone during this compile)"
ifTrue: "Two-armed IFs forEffect share a single pop"
[^super sizeCodeForEffect: encoder].
forValue
ifTrue: "Code all forValue as two-armed"
[elseSize := elseExpr sizeCodeForEvaluatedValue: encoder.
thenSize := (thenExpr sizeCodeForEvaluatedValue: encoder)
+ (thenExpr returns
ifTrue: [0] "Elide jump over else after a return"
ifFalse: [self sizeCode: encoder forJump: elseSize]).
branchSize := self sizeCode: encoder forBranchOn: false dist: thenSize]
ifFalse: "One arm is empty here (two-arms code forValue)"
[(elseExpr isJust: NodeNil)
ifTrue:
[elseSize := 0.
thenSize := thenExpr sizeCodeForEvaluatedEffect: encoder.
branchSize := self sizeCode: encoder forBranchOn: false dist: thenSize]
ifFalse:
[thenSize := 0.
elseSize := elseExpr sizeCodeForEvaluatedEffect: encoder.
branchSize := self sizeCode: encoder forBranchOn: true dist: elseSize]].
sizes := Array with: thenSize with: elseSize.
^(receiver sizeCodeForValue: encoder)
+ branchSize + thenSize + elseSize!
Item was changed:
+ ----- Method: FieldNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: FieldNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
fieldDef accessKey ifNil:[
rcvrNode emitCodeForValue: stack encoder: encoder.
readNode emitCode: stack args: 0 encoder: encoder super: false.
] ifNotNil:[
rcvrNode emitCodeForValue: stack encoder: encoder.
super emitCodeForValue: stack encoder: encoder.
readNode emitCode: stack args: 1 encoder: encoder super: false.
].!
Item was changed:
+ ----- Method: SelectorNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: SelectorNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
self shouldNotImplement!
Item was changed:
+ ----- Method: AssignmentNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: AssignmentNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
^(variable sizeCodeForLoad: encoder)
+ (value sizeCodeForValue: encoder)
+ (variable sizeCodeForStore: encoder)!
Item was changed:
+ ----- Method: LeafNode>>emitCodeForEffect:encoder: (in category 'code generation') -----
- ----- Method: LeafNode>>emitCodeForEffect:encoder: (in category 'code generation (new scheme)') -----
emitCodeForEffect: stack encoder: encoder
^self!
Item was changed:
+ ----- Method: SelectorNode>>sizeCode:args:super: (in category 'code generation') -----
- ----- Method: SelectorNode>>sizeCode:args:super: (in category 'code generation (new scheme)') -----
sizeCode: encoder args: nArgs super: supered
self reserve: encoder.
^supered
ifTrue:
[code < Send "i.e. its a special selector" ifTrue:
[code := self code: (index := encoder sharableLitIndex: key) type: 5].
encoder sizeSendSuper: index numArgs: nArgs]
ifFalse:
[self flag: #yuck. "special selector sends cause this problem"
encoder
sizeSend: (code < Send ifTrue: [code negated] ifFalse: [index])
numArgs: nArgs]!
Item was changed:
+ ----- Method: TempVariableNode>>emitCodeForLoad:encoder: (in category 'code generation') -----
- ----- Method: TempVariableNode>>emitCodeForLoad:encoder: (in category 'code generation (new scheme)') -----
emitCodeForLoad: stack encoder: encoder
remoteNode ~~ nil ifTrue:
[remoteNode emitCodeForLoadFor: self stack: stack encoder: encoder]!
Item was changed:
+ ----- Method: MaybeContextInstanceVariableNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: MaybeContextInstanceVariableNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
^encoder sizePushInstVarLong: index!
Item was changed:
+ ----- Method: NewArrayNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: NewArrayNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
^encoder sizePushNewArray: numElements!
Item was changed:
+ ----- Method: VariableNode>>sizeCodeForStorePop: (in category 'code generation') -----
- ----- Method: VariableNode>>sizeCodeForStorePop: (in category 'code generation (new scheme)') -----
sizeCodeForStorePop: encoder
self shouldNotImplement!
Item was added:
+ ----- Method: MethodNode>>locationCounter (in category 'code generation (closures)') -----
+ locationCounter
+ ^locationCounter!
Item was changed:
+ ----- Method: LiteralNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: LiteralNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
self reserve: encoder.
(encoder
if: code
isSpecialLiteralForPush:
[:specialLiteral|
^encoder sizePushSpecialLiteral: specialLiteral])
ifFalse:
[^encoder sizePushLiteral: index]!
Item was changed:
+ ----- Method: LeafNode>>emitCodeForLoad:encoder: (in category 'code generation') -----
- ----- Method: LeafNode>>emitCodeForLoad:encoder: (in category 'code generation (new scheme)') -----
emitCodeForLoad: stack encoder: encoder
"Default is to do nothing.
Subclasses may need to override."!
Item was changed:
+ ----- Method: LiteralNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: LiteralNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
stack push: 1.
(encoder
if: code
isSpecialLiteralForPush:
[:specialLiteral|
encoder genPushSpecialLiteral: specialLiteral])
ifFalse:
[encoder genPushLiteral: index]!
Item was changed:
+ ----- Method: MessageNode>>emitCodeForIf:encoder:value: (in category 'code generation') -----
- ----- Method: MessageNode>>emitCodeForIf:encoder:value: (in category 'code generation (new scheme)') -----
emitCodeForIf: stack encoder: encoder value: forValue
| thenExpr thenSize elseExpr elseSize |
thenSize := sizes at: 1.
elseSize := sizes at: 2.
(forValue not and: [elseSize * thenSize > 0]) ifTrue:
"Two-armed IFs forEffect share a single pop"
[^super emitCodeForEffect: stack encoder: encoder].
thenExpr := arguments at: 1.
elseExpr := arguments at: 2.
receiver emitCodeForValue: stack encoder: encoder.
forValue
ifTrue: "Code all forValue as two-armed"
[self emitCodeForBranchOn: false dist: thenSize pop: stack encoder: encoder.
pc := encoder methodStreamPosition.
thenExpr emitCodeForEvaluatedValue: stack encoder: encoder.
stack pop: 1. "then and else alternate; they don't accumulate"
thenExpr returns not ifTrue:
"...not ifTrue: avoids using ifFalse: alone during this compile)"
"Elide jump over else after a return"
[self emitCodeForJump: elseSize encoder: encoder].
elseExpr emitCodeForEvaluatedValue: stack encoder: encoder]
ifFalse: "One arm is empty here (two-arms code forValue)"
[thenSize > 0
ifTrue:
[self emitCodeForBranchOn: false dist: thenSize pop: stack encoder: encoder.
pc := encoder methodStreamPosition.
thenExpr emitCodeForEvaluatedEffect: stack encoder: encoder]
ifFalse:
[self emitCodeForBranchOn: true dist: elseSize pop: stack encoder: encoder.
pc := encoder methodStreamPosition.
elseExpr emitCodeForEvaluatedEffect: stack encoder: encoder]]!
Item was changed:
+ ----- Method: ReturnNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: ReturnNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
^expr sizeCodeForReturn: encoder!
Item was changed:
+ ----- Method: BlockNode>>emitCodeExceptLast:encoder: (in category 'code generation') -----
- ----- Method: BlockNode>>emitCodeExceptLast:encoder: (in category 'code generation (new scheme)') -----
emitCodeExceptLast: stack encoder: encoder
| position nextToLast |
position := stack position.
nextToLast := statements size - 1.
1 to: nextToLast do:
[:i | | statement |
statement := statements at: i.
statement emitCodeForEffect: stack encoder: encoder.
self assert: stack position = position].!
Item was changed:
+ ----- Method: TempVariableNode>>emitCodeForStore:encoder: (in category 'code generation') -----
- ----- Method: TempVariableNode>>emitCodeForStore:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStore: stack encoder: encoder
remoteNode ~~ nil ifTrue:
[^remoteNode emitCodeForStoreInto: self stack: stack encoder: encoder].
encoder genStoreTemp: index!
Item was changed:
+ ----- Method: ParseNode>>emitCodeForEffect:encoder: (in category 'code generation') -----
- ----- Method: ParseNode>>emitCodeForEffect:encoder: (in category 'code generation (new scheme)') -----
emitCodeForEffect: stack encoder: encoder
self emitCodeForValue: stack encoder: encoder.
encoder genPop.
stack pop: 1!
Item was changed:
+ ----- Method: MessageNode>>sizeCodeForEffect: (in category 'code generation') -----
- ----- Method: MessageNode>>sizeCodeForEffect: (in category 'code generation (new scheme)') -----
sizeCodeForEffect: encoder
special > 0
ifTrue: [^self perform: (NewStyleMacroSizers at: special) with: encoder with: false].
^super sizeCodeForEffect: encoder!
Item was changed:
+ ----- Method: VariableNode>>sizeCodeForStore: (in category 'code generation') -----
- ----- Method: VariableNode>>sizeCodeForStore: (in category 'code generation (new scheme)') -----
sizeCodeForStore: encoder
self shouldNotImplement!
Item was changed:
+ ----- Method: VariableNode>>emitCodeForLoad:encoder: (in category 'code generation') -----
- ----- Method: VariableNode>>emitCodeForLoad:encoder: (in category 'code generation (new scheme)') -----
emitCodeForLoad: stack encoder: encoder
"Do nothing"!
Item was changed:
+ ----- Method: LiteralVariableNode>>sizeCodeForStorePop: (in category 'code generation') -----
- ----- Method: LiteralVariableNode>>sizeCodeForStorePop: (in category 'code generation (new scheme)') -----
sizeCodeForStorePop: encoder
self reserve: encoder.
^(key isVariableBinding and: [key isSpecialWriteBinding])
ifTrue: [(self sizeCodeForStore: encoder) + encoder sizePop]
ifFalse: [encoder sizeStorePopLiteralVar: index]!
Item was changed:
+ ----- Method: BytecodeAgnosticMethodNode>>generate: (in category 'code generation') -----
- ----- Method: BytecodeAgnosticMethodNode>>generate: (in category 'code generation (new scheme)') -----
generate: trailer
"The receiver is the root of a parse tree. Answer a CompiledMethod.
The argument, trailer, is arbitrary but is typically either the reference
to the source code that is stored with every CompiledMethod, or an
encoding of the method's temporary names."
| primErrNode blkSize nLits literals stack method |
self generate: trailer ifQuick:
[:m |
m literalAt: 2 put: encoder associationForClass;
properties: properties.
^m].
primErrNode := self primitiveErrorVariableName ifNotNil:
[encoder fixTemp: self primitiveErrorVariableName].
encoder supportsClosureOpcodes ifTrue:
[self ensureClosureAnalysisDone.
encoder rootNode: self. "this is for BlockNode>>sizeCodeForClosureValue:"].
blkSize := (block sizeCodeForEvaluatedValue: encoder)
+ (primErrNode
ifNil: [0]
ifNotNil: [primErrNode sizeCodeForStore: encoder "The VM relies on storeIntoTemp: (129)"]).
method := CompiledMethod
newBytes: blkSize
trailerBytes: trailer
nArgs: arguments size
nTemps: (encoder supportsClosureOpcodes
ifTrue: [| locals |
locals := arguments,
temporaries,
(primErrNode
ifNil: [#()]
ifNotNil: [{primErrNode}]).
encoder
noteBlockExtent: block blockExtent
hasLocals: locals.
locals size]
ifFalse: [encoder maxTemp])
nStack: 0
nLits: (nLits := (literals := encoder allLiterals) size)
primitive: primitive.
nLits > 255 ifTrue:
[^self error: 'Too many literals referenced'].
1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)].
encoder streamToMethod: method.
stack := ParseStack new init.
primErrNode ifNotNil: [primErrNode emitCodeForStore: stack encoder: encoder].
stack position: method numTemps.
block emitCodeForEvaluatedValue: stack encoder: encoder.
stack position ~= (method numTemps + 1) ifTrue:
[^self error: 'Compiler stack discrepancy'].
encoder methodStreamPosition ~= (method size - trailer size) ifTrue:
[^self error: 'Compiler code size discrepancy'].
method needsFrameSize: stack size - method numTemps.
method properties: properties.
^method!
Item was changed:
+ ----- Method: FutureNode>>emitCodeForEffect:encoder: (in category 'code generation') -----
- ----- Method: FutureNode>>emitCodeForEffect:encoder: (in category 'code generation (new scheme)') -----
emitCodeForEffect: stack encoder: encoder
^effectNode emitCodeForEffect: stack encoder: encoder!
Item was changed:
+ ----- Method: LiteralVariableNode>>emitCodeForStorePop:encoder: (in category 'code generation') -----
- ----- Method: LiteralVariableNode>>emitCodeForStorePop:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStorePop: stack encoder: encoder
writeNode ifNil:
[stack pop: 1.
^encoder genStorePopLiteralVar: index].
self emitCodeForStore: stack encoder: encoder.
encoder genPop.
stack pop: 1.!
Item was changed:
----- Method: MessageNode class>>initialize (in category 'class initialization') -----
initialize "MessageNode initialize"
MacroSelectors :=
#( ifTrue: ifFalse: ifTrue:ifFalse: ifFalse:ifTrue:
and: or:
whileFalse: whileTrue: whileFalse whileTrue
to:do: to:by:do:
caseOf: caseOf:otherwise:
ifNil: ifNotNil: ifNil:ifNotNil: ifNotNil:ifNil:).
MacroTransformers :=
#( transformIfTrue: transformIfFalse: transformIfTrueIfFalse: transformIfFalseIfTrue:
transformAnd: transformOr:
transformWhile: transformWhile: transformWhile: transformWhile:
transformToDo: transformToDo:
transformCase: transformCase:
transformIfNil: transformIfNil: transformIfNilIfNotNil: transformIfNotNilIfNil:).
+ MacroEmitters := NewStyleMacroEmitters :=
- MacroEmitters :=
- #( emitIf:on:value: emitIf:on:value: emitIf:on:value: emitIf:on:value:
- emitIf:on:value: emitIf:on:value:
- emitWhile:on:value: emitWhile:on:value: emitWhile:on:value: emitWhile:on:value:
- emitToDo:on:value: emitToDo:on:value:
- emitCase:on:value: emitCase:on:value:
- emitIfNil:on:value: emitIfNil:on:value: emitIf:on:value: emitIf:on:value:).
- NewStyleMacroEmitters :=
#( emitCodeForIf:encoder:value: emitCodeForIf:encoder:value:
emitCodeForIf:encoder:value: emitCodeForIf:encoder:value:
emitCodeForIf:encoder:value: emitCodeForIf:encoder:value:
emitCodeForWhile:encoder:value: emitCodeForWhile:encoder:value:
emitCodeForWhile:encoder:value: emitCodeForWhile:encoder:value:
emitCodeForToDo:encoder:value: emitCodeForToDo:encoder:value:
emitCodeForCase:encoder:value: emitCodeForCase:encoder:value:
emitCodeForIfNil:encoder:value: emitCodeForIfNil:encoder:value:
emitCodeForIf:encoder:value: emitCodeForIf:encoder:value:).
+ MacroSizers := NewStyleMacroSizers :=
- MacroSizers :=
- #( sizeIf:value: sizeIf:value: sizeIf:value: sizeIf:value:
- sizeIf:value: sizeIf:value:
- sizeWhile:value: sizeWhile:value: sizeWhile:value: sizeWhile:value:
- sizeToDo:value: sizeToDo:value:
- sizeCase:value: sizeCase:value:
- sizeIfNil:value: sizeIfNil:value: sizeIf:value: sizeIf:value:).
- NewStyleMacroSizers :=
#( sizeCodeForIf:value: sizeCodeForIf:value: sizeCodeForIf:value: sizeCodeForIf:value:
sizeCodeForIf:value: sizeCodeForIf:value:
sizeCodeForWhile:value: sizeCodeForWhile:value: sizeCodeForWhile:value: sizeCodeForWhile:value:
sizeCodeForToDo:value: sizeCodeForToDo:value:
sizeCodeForCase:value: sizeCodeForCase:value:
sizeCodeForIfNil:value: sizeCodeForIfNil:value: sizeCodeForIf:value: sizeCodeForIf:value:).
MacroPrinters :=
#( printIfOn:indent: printIfOn:indent: printIfOn:indent: printIfOn:indent:
printIfOn:indent: printIfOn:indent:
printWhileOn:indent: printWhileOn:indent: printWhileOn:indent: printWhileOn:indent:
printToDoOn:indent: printToDoOn:indent:
printCaseOn:indent: printCaseOn:indent:
printIfNil:indent: printIfNil:indent: printIfNilNotNil:indent: printIfNilNotNil:indent:)!
Item was changed:
+ ----- Method: FieldNode>>sizeCodeForEffect: (in category 'code generation') -----
- ----- Method: FieldNode>>sizeCodeForEffect: (in category 'code generation (new scheme)') -----
sizeCodeForEffect: encoder
^0!
Item was changed:
+ ----- Method: BlockNode>>emitCodeForEvaluatedValue:encoder: (in category 'code generation') -----
- ----- Method: BlockNode>>emitCodeForEvaluatedValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForEvaluatedValue: stack encoder: encoder
| position |
position := stack position.
self emitCodeExceptLast: stack encoder: encoder.
statements last emitCodeForBlockValue: stack encoder: encoder.
self assert: stack position - 1 = position!
Item was changed:
+ ----- Method: SelectorNode>>sizeCodeForEffect: (in category 'code generation') -----
- ----- Method: SelectorNode>>sizeCodeForEffect: (in category 'code generation (new scheme)') -----
sizeCodeForEffect: encoder
self shouldNotImplement!
Item was changed:
+ ----- Method: FutureNode>>sizeCodeForBlockValue: (in category 'code generation') -----
- ----- Method: FutureNode>>sizeCodeForBlockValue: (in category 'code generation (new scheme)') -----
sizeCodeForBlockValue: encoder
receiver == NodeSuper ifTrue: [^self error: 'Futures cannot send to future'].
(futureArgs isNil or: [futureSelector isNil]) ifTrue:
[^self error: 'Futures must be sent messages'].
encoder sharableLitIndex: originalSelector. "to find its senders"
futureDelta ifNil:[futureDelta := encoder encodeLiteral: 0].
effectNode := MessageNode new
receiver: receiver
selector: #futureDo:at:args:
arguments: (Array
with: (encoder encodeLiteral: futureSelector)
with: futureDelta
with: (BraceNode new elements: futureArgs))
precedence: 3
from: encoder.
^effectNode sizeCodeForValue: encoder!
Item was changed:
+ ----- Method: LiteralVariableNode>>sizeCodeForLoad: (in category 'code generation') -----
- ----- Method: LiteralVariableNode>>sizeCodeForLoad: (in category 'code generation (new scheme)') -----
sizeCodeForLoad: encoder
^writeNode ifNil: [0] ifNotNil: [encoder sizePushLiteral: index]!
Item was changed:
+ ----- Method: LiteralVariableNode>>sizeCodeForStore: (in category 'code generation') -----
- ----- Method: LiteralVariableNode>>sizeCodeForStore: (in category 'code generation (new scheme)') -----
sizeCodeForStore: encoder
self reserve: encoder.
(key isVariableBinding and: [key isSpecialWriteBinding]) ifFalse:
[^encoder sizeStoreLiteralVar: index].
code < 0 ifTrue:
[self flag: #dubious.
self code: (self code: self index type: LdLitType)].
"THIS IS WRONG!!!! THE VALUE IS LOST FROM THE STACK!!!!
The various value: methods on Association ReadOnlyVariableBinding
etc _do not_ return the value assigned; they return the receiver."
"Should generate something more like
push expr
push lit
push temp (index of expr)
send value:
pop"
self flag: #bogus.
writeNode := encoder encodeSelector: #value:.
^(encoder sizePushLiteralVar: index)
+ (writeNode sizeCode: encoder args: 1 super: false)!
Item was changed:
+ ----- Method: InstanceVariableNode>>sizeCodeForStore: (in category 'code generation') -----
- ----- Method: InstanceVariableNode>>sizeCodeForStore: (in category 'code generation (new scheme)') -----
sizeCodeForStore: encoder
^encoder sizeStoreInstVar: index!
Item was changed:
+ ----- Method: ParseNode>>emitCodeForBranchOn:dist:pop:encoder: (in category 'code generation') -----
- ----- Method: ParseNode>>emitCodeForBranchOn:dist:pop:encoder: (in category 'code generation (new scheme)') -----
emitCodeForBranchOn: condition dist: dist pop: stack encoder: encoder
stack pop: 1.
dist = 0 ifTrue: [^encoder genPop].
condition
ifTrue: [encoder genBranchPopTrue: dist]
ifFalse: [encoder genBranchPopFalse: dist]!
Item was added:
+ ----- Method: MethodNode>>addLocalsToPool: (in category 'code generation (closures)') -----
+ addLocalsToPool: locals "<Set of: TempVariableNode>"
+ localsPool isNil ifTrue:
+ [localsPool := IdentitySet new].
+ localsPool addAll: locals!
Item was changed:
+ ----- Method: VariableNode>>emitCodeForStore:encoder: (in category 'code generation') -----
- ----- Method: VariableNode>>emitCodeForStore:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStore: stack encoder: encoder
self shouldNotImplement!
Item was changed:
+ ----- Method: MaybeContextInstanceVariableNode>>emitCodeForStore:encoder: (in category 'code generation') -----
- ----- Method: MaybeContextInstanceVariableNode>>emitCodeForStore:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStore: stack encoder: encoder
encoder genStoreInstVarLong: index!
Item was added:
+ ----- Method: MethodNode>>generateWithTempNames (in category 'code generation') -----
+ generateWithTempNames
+ "Answer a CompiledMethod with temps names encoded in trailer"
+ ^ self generate: (CompiledMethodTrailer new tempNames: self schematicTempNamesString).
+ !
Item was changed:
+ ----- Method: LiteralVariableNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: LiteralVariableNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
^readNode
ifNil: [stack push: 1.
encoder genPushLiteralVar: index]
ifNotNil: [readNode emitCodeForValue: stack encoder: encoder]!
Item was changed:
+ ----- Method: MessageNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: MessageNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
| total |
special > 0
ifTrue: [^self perform: (NewStyleMacroSizers at: special) with: encoder with: true].
receiver == NodeSuper
ifTrue: [selector := selector copy "only necess for splOops"].
total := selector sizeCode: encoder args: arguments size super: receiver == NodeSuper.
receiver == nil
ifFalse: [total := total + (receiver sizeCodeForValue: encoder)].
sizes := arguments collect:
[:arg | | argSize |
argSize := arg sizeCodeForValue: encoder.
total := total + argSize.
argSize].
^total!
Item was changed:
+ ----- Method: FutureNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: FutureNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
^valueNode emitCodeForValue: stack encoder: encoder!
Item was changed:
+ ----- Method: MessageNode>>emitCodeForValue:encoder: (in category 'code generation') -----
- ----- Method: MessageNode>>emitCodeForValue:encoder: (in category 'code generation (new scheme)') -----
emitCodeForValue: stack encoder: encoder
"For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly."
special > 0
ifTrue:
[pc := 0.
self perform: (NewStyleMacroEmitters at: special) with: stack with: encoder with: true]
ifFalse:
[receiver ~~ nil ifTrue: [receiver emitCodeForValue: stack encoder: encoder].
arguments do: [:argument | argument emitCodeForValue: stack encoder: encoder].
pc := encoder methodStreamPosition + 1. "debug pc is first byte of the send, i.e. the next byte".
selector
emitCode: stack
args: arguments size
encoder: encoder
super: receiver == NodeSuper]!
Item was changed:
+ ----- Method: InstanceVariableNode>>emitCodeForStore:encoder: (in category 'code generation') -----
- ----- Method: InstanceVariableNode>>emitCodeForStore:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStore: stack encoder: encoder
encoder genStoreInstVar: index!
Item was changed:
+ ----- Method: TempVariableNode>>sizeCodeForStorePop: (in category 'code generation') -----
- ----- Method: TempVariableNode>>sizeCodeForStorePop: (in category 'code generation (new scheme)') -----
sizeCodeForStorePop: encoder
remoteNode ~~ nil ifTrue:
[^remoteNode sizeCodeForStorePopInto: self encoder: encoder].
self reserve: encoder.
^encoder sizeStorePopTemp: index!
Item was changed:
+ ----- Method: FieldNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: FieldNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
rcvrNode ifNil:[self encodeReceiverOn: encoder].
fieldDef accessKey ifNil:[
readNode ifNil:[readNode := encoder encodeSelector: fieldDef toGet].
^(rcvrNode sizeCodeForValue: encoder) +
(readNode sizeCode: encoder args: 0 super: false)
].
readNode ifNil:[readNode := encoder encodeSelector: #get:].
^(rcvrNode sizeCodeForValue: encoder) +
(super sizeCodeForValue: encoder) +
(readNode sizeCode: encoder args: 1 super: false)!
Item was changed:
+ ----- Method: TempVariableNode>>emitCodeForStorePop:encoder: (in category 'code generation') -----
- ----- Method: TempVariableNode>>emitCodeForStorePop:encoder: (in category 'code generation (new scheme)') -----
emitCodeForStorePop: stack encoder: encoder
remoteNode ~~ nil ifTrue:
[^remoteNode emitCodeForStorePopInto: self stack: stack encoder: encoder].
encoder genStorePopTemp: index.
stack pop: 1!
Item was changed:
+ ----- Method: SelectorNode>>sizeCodeForValue: (in category 'code generation') -----
- ----- Method: SelectorNode>>sizeCodeForValue: (in category 'code generation (new scheme)') -----
sizeCodeForValue: encoder
self shouldNotImplement!
Item was changed:
+ ----- Method: LeafNode>>sizeCodeForEffect: (in category 'code generation') -----
- ----- Method: LeafNode>>sizeCodeForEffect: (in category 'code generation (new scheme)') -----
sizeCodeForEffect: encoder
^0!
Item was removed:
- ----- Method: ParseNode>>emitJump:on: (in category 'code generation') -----
- emitJump: dist on: strm
-
- dist = 0 ifFalse: [self emitShortOrLong: dist code: Jmp on: strm]!
Item was removed:
- ----- Method: FieldNode>>sizeForEffect: (in category 'code generation') -----
- sizeForEffect: encoder
- ^0!
Item was removed:
- ----- Method: FieldNode>>emitStorePop:on: (in category 'code generation') -----
- emitStorePop: stack on: strm
- self emitStore: stack on: strm.
- strm nextPut: Pop.
- stack pop: 1.!
Item was removed:
- ----- Method: MessageNode>>sizeCase:value: (in category 'code generation') -----
- sizeCase: encoder value: forValue
-
- | braceNode sizeIndex elseSize |
- forValue not
- ifTrue: [^super sizeForEffect: encoder].
- equalNode := encoder encodeSelector: #=.
- braceNode := arguments first.
- sizes := Array new: 2 * braceNode numElements.
- sizeIndex := sizes size.
- elseSize := arguments size = 2
- ifTrue:
- [arguments last sizeForEvaluatedValue: encoder] "otherwise: [...]"
- ifFalse:
- [caseErrorNode := encoder encodeSelector: #caseError.
- 1 + (caseErrorNode size: encoder args: 0 super: false)]. "self caseError"
- braceNode casesReverseDo:
- [:keyNode :valueNode :last | | thenSize |
- sizes at: sizeIndex put: elseSize.
- thenSize := valueNode sizeForEvaluatedValue: encoder.
- last ifFalse: [thenSize := thenSize + 1]. "Pop"
- valueNode returns ifFalse: [thenSize := thenSize + (self sizeJump: elseSize)].
- sizes at: sizeIndex-1 put: thenSize.
- last ifFalse: [elseSize := elseSize + 1]. "Dup"
- elseSize := elseSize + (keyNode sizeForEvaluatedValue: encoder) +
- (equalNode size: encoder args: 1 super: false) +
- (self sizeBranchOn: false dist: thenSize) + thenSize.
- sizeIndex := sizeIndex - 2].
- ^(receiver sizeForValue: encoder) + elseSize
- !
Item was removed:
- ----- Method: MessageNode>>sizeIfNil:value: (in category 'code generation') -----
- sizeIfNil: encoder value: forValue
-
- | theNode theSize theSelector |
- equalNode := encoder encodeSelector: #==.
- sizes := Array new: 1.
- theNode := arguments first.
- theSelector := #ifNotNil:.
- forValue
- ifTrue:
- [sizes at: 1 put: (theSize := (1 "pop" + (theNode sizeForEvaluatedValue: encoder))).
- ^(receiver sizeForValue: encoder) +
- 2 "Dup. LdNil" +
- (equalNode size: encoder args: 1 super: false) +
- (self
- sizeBranchOn: (selector key == theSelector)
- dist: theSize) +
- theSize]
- ifFalse:
- [sizes at: 1 put: (theSize := (theNode sizeForEvaluatedEffect: encoder)).
- ^(receiver sizeForValue: encoder) +
- 1 "LdNil" +
- (equalNode size: encoder args: 1 super: false) +
- (self
- sizeBranchOn: (selector key == theSelector)
- dist: theSize) +
- theSize]
-
- !
Item was removed:
- ----- Method: FieldNode>>sizeForValue: (in category 'code generation') -----
- sizeForValue: encoder
- rcvrNode ifNil:[self encodeReceiverOn: encoder].
- fieldDef accessKey ifNil:[
- readNode ifNil:[readNode := encoder encodeSelector: fieldDef toGet].
- ^(rcvrNode sizeForValue: encoder) +
- (readNode size: encoder args: 0 super: false)
- ].
- readNode ifNil:[readNode := encoder encodeSelector: #get:].
- ^(rcvrNode sizeForValue: encoder) +
- (super sizeForValue: encoder) +
- (readNode size: encoder args: 1 super: false)!
Item was removed:
- ----- Method: AssignmentNode>>sizeForValue: (in category 'code generation') -----
- sizeForValue: encoder
-
- ^(value sizeForValue: encoder)
- + (variable sizeForStore: encoder)!
Item was removed:
- ----- Method: VariableNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: strm
-
- code < 256
- ifTrue:
- [strm nextPut: (code = LdSuper ifTrue: [LdSelf] ifFalse: [code]).
- stack push: 1]
- ifFalse:
- [self emitLong: LoadLong on: strm.
- stack push: 1]!
Item was removed:
- ----- Method: BlockNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: aStream
-
- aStream nextPut: LdThisContext.
- stack push: 1.
- nArgsNode emitForValue: stack on: aStream.
- remoteCopyNode
- emit: stack
- args: 1
- on: aStream.
- "Force a two byte jump."
- self emitLong: size code: JmpLong on: aStream.
- stack push: arguments size.
- arguments reverseDo: [:arg | arg emitStorePop: stack on: aStream].
- self emitForEvaluatedValue: stack on: aStream.
- self returns ifFalse: [
- aStream nextPut: EndRemote.
- pc := aStream position.
- ].
- stack pop: 1!
Item was removed:
- ----- Method: BlockNode>>emitExceptLast:on: (in category 'code generation') -----
- emitExceptLast: stack on: aStream
- | nextToLast |
- nextToLast := statements size - 1.
- nextToLast < 1 ifTrue: [^ self]. "Only one statement"
- 1 to: nextToLast do:
- [:i | (statements at: i) emitForEffect: stack on: aStream].
- !
Item was removed:
- ----- Method: BlockNode>>sizeExceptLast: (in category 'code generation') -----
- sizeExceptLast: encoder
- | codeSize nextToLast |
- nextToLast := statements size - 1.
- nextToLast < 1 ifTrue: [^ 0]. "Only one statement"
- codeSize := 0.
- 1 to: nextToLast do:
- [:i | codeSize := codeSize + ((statements at: i) sizeForEffect: encoder)].
- ^ codeSize!
Item was removed:
- ----- Method: VariableNode>>emitLoad:on: (in category 'code generation') -----
- emitLoad: stack on: strm
- "Do nothing"!
Item was removed:
- ----- Method: FieldNode>>emitForEffect:on: (in category 'code generation') -----
- emitForEffect: stack on: strm
- !
Item was removed:
- ----- Method: MessageNode>>sizeToDo:value: (in category 'code generation') -----
- sizeToDo: encoder value: forValue
- " var := rcvr. L1: [var <= arg1] Bfp(L2) [block body. var := var + inc] Jmp(L1) L2: "
- | loopSize initStmt test block incStmt blockSize blockVar initSize limitInit |
- block := arguments at: 3.
- blockVar := block firstArgument.
- initStmt := arguments at: 4.
- test := arguments at: 5.
- incStmt := arguments at: 6.
- limitInit := arguments at: 7.
- initSize := initStmt sizeForEffect: encoder.
- limitInit == nil
- ifFalse: [initSize := initSize + (limitInit sizeForEffect: encoder)].
- blockSize := (block sizeForEvaluatedEffect: encoder)
- + (incStmt sizeForEffect: encoder) + 2. "+2 for Jmp backward"
- loopSize := (test sizeForValue: encoder)
- + (self sizeBranchOn: false dist: blockSize)
- + blockSize.
- sizes := Array with: blockSize with: loopSize.
- ^ initSize + loopSize
- + (forValue ifTrue: [1] ifFalse: [0]) " +1 for value (push nil) "!
Item was removed:
- ----- Method: BraceNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: aStream
-
- ^ emitNode emitForValue: stack on: aStream!
Item was removed:
- ----- Method: ReturnNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: strm
-
- expr emitForReturn: stack on: strm.
- pc := strm position!
Item was removed:
- ----- Method: FutureNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: strm
- ^valueNode emitForValue: stack on: strm!
Item was removed:
- ----- Method: ParseNode>>emitShortOrLong:code:on: (in category 'code generation') -----
- emitShortOrLong: dist code: shortCode on: strm
- (1 <= dist and: [dist <= JmpLimit])
- ifTrue: [strm nextPut: shortCode + dist - 1]
- ifFalse: [self emitLong: dist code: shortCode + (JmpLong-Jmp) on: strm]!
Item was removed:
- ----- Method: ParseNode>>sizeForBlockValue: (in category 'code generation') -----
- sizeForBlockValue: encoder
- "Answer the size for evaluating the last statement in a block"
- ^self sizeForValue: encoder!
Item was removed:
- ----- Method: LiteralVariableNode>>emitStore:on: (in category 'code generation') -----
- emitStore: stack on: strm
- writeNode ifNil:[^super emitStore: stack on: strm].
- writeNode
- emit: stack
- args: 1
- on: strm
- super: false.!
Item was removed:
- ----- Method: ReturnNode>>sizeForValue: (in category 'code generation') -----
- sizeForValue: encoder
-
- ^expr sizeForReturn: encoder!
Item was removed:
- ----- Method: BlockNode>>emitForEvaluatedValue:on: (in category 'code generation') -----
- emitForEvaluatedValue: stack on: aStream
- self emitExceptLast: stack on: aStream.
- statements last emitForBlockValue: stack on: aStream.
- !
Item was removed:
- ----- Method: FutureNode>>sizeForBlockValue: (in category 'code generation') -----
- sizeForBlockValue: encoder
- receiver == NodeSuper ifTrue: [^self error: 'Futures cannot send to future'].
- encoder sharableLitIndex: originalSelector. "to find its senders"
- futureDelta ifNil:[futureDelta := encoder encodeLiteral: 0].
- effectNode := MessageNode new
- receiver: receiver
- selector: #futureDo:at:args:
- arguments: (Array
- with: (encoder encodeLiteral: futureSelector)
- with: futureDelta
- with: (BraceNode new elements: futureArgs))
- precedence: 3
- from: encoder.
- ^effectNode sizeForValue: encoder!
Item was removed:
- ----- Method: LeafNode>>sizeForEffect: (in category 'code generation') -----
- sizeForEffect: encoder
-
- ^0!
Item was removed:
- ----- Method: VariableNode>>sizeForStore: (in category 'code generation') -----
- sizeForStore: encoder
- self reserve: encoder.
- code < 256 ifTrue: [^ 2].
- (code \\ 256) <= 63 ifTrue: [^ 2].
- ^ 3!
Item was removed:
- ----- Method: SelectorNode>>size:args:super: (in category 'code generation') -----
- size: encoder args: nArgs super: supered
- | index |
- self reserve: encoder.
- (supered not and: [code - Send < SendLimit and: [nArgs < 3]])
- ifTrue: [^1]. "short send"
- (supered and: [code < Send]) ifTrue:
- ["super special:"
- code := self code: (encoder sharableLitIndex: key) type: 5].
- index := code < 256 ifTrue: [code - Send] ifFalse: [code \\ 256].
- (index <= 31 and: [nArgs <= 7])
- ifTrue: [^ 2]. "medium send"
- (supered not and: [index <= 63 and: [nArgs <= 3]])
- ifTrue: [^ 2]. "new medium send"
- ^ 3 "long send"!
Item was removed:
- ----- Method: VariableNode>>sizeForReturn: (in category 'code generation') -----
- sizeForReturn: encoder
-
- (code >= LdSelf and: [code <= LdNil])
- ifTrue: ["short returns" ^1].
- ^super sizeForReturn: encoder!
Item was removed:
- ----- Method: MessageNode>>emitWhile:on:value: (in category 'code generation') -----
- emitWhile: stack on: strm value: forValue
- " L1: ... Bfp(L2)|Btp(L2) ... Jmp(L1) L2: "
- | cond stmt stmtSize loopSize |
- cond := receiver.
- stmt := arguments at: 1.
- stmtSize := sizes at: 1.
- loopSize := sizes at: 2.
- cond emitForEvaluatedValue: stack on: strm.
- self emitBranchOn: (selector key == #whileFalse:) "Bfp for whileTrue"
- dist: stmtSize pop: stack on: strm. "Btp for whileFalse"
- pc := strm position.
- stmt emitForEvaluatedEffect: stack on: strm.
- self emitJump: 0 - loopSize on: strm.
- forValue ifTrue: [strm nextPut: LdNil. stack push: 1]!
Item was removed:
- ----- Method: VariableNode>>sizeForStorePop: (in category 'code generation') -----
- sizeForStorePop: encoder
- self reserve: encoder.
- (code < 24 and: [code noMask: 8]) ifTrue: [^ 1].
- code < 256 ifTrue: [^ 2].
- code \\ 256 <= 63 ifTrue: [^ 2]. "extended StorePop"
- code // 256 = 1 ifTrue: [^ 3]. "dbl extended StorePopInst"
- code // 256 = 4 ifTrue: [^ 4]. "dbl extended StoreLitVar , Pop"
- self halt. "Shouldn't get here"!
Item was removed:
- ----- Method: CascadeNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: aStream
-
- receiver emitForValue: stack on: aStream.
- 1 to: messages size - 1 do:
- [:i |
- aStream nextPut: Dup.
- stack push: 1.
- (messages at: i) emitForValue: stack on: aStream.
- aStream nextPut: Pop.
- stack pop: 1].
- messages last emitForValue: stack on: aStream!
Item was removed:
- ----- Method: ParseNode>>sizeForReturn: (in category 'code generation') -----
- sizeForReturn: encoder
-
- ^(self sizeForValue: encoder) + 1!
Item was removed:
- ----- Method: ParseNode>>sizeForEffect: (in category 'code generation') -----
- sizeForEffect: encoder
-
- ^(self sizeForValue: encoder) + 1!
Item was removed:
- ----- Method: MessageNode>>sizeIf:value: (in category 'code generation') -----
- sizeIf: encoder value: forValue
- | thenExpr elseExpr branchSize thenSize elseSize |
- thenExpr := arguments at: 1.
- elseExpr := arguments at: 2.
- (forValue
- or: [(thenExpr isJust: NodeNil)
- or: [elseExpr isJust: NodeNil]]) not
- "(...not ifTrue: avoids using ifFalse: alone during this compile)"
- ifTrue: "Two-armed IFs forEffect share a single pop"
- [^ super sizeForEffect: encoder].
- forValue
- ifTrue: "Code all forValue as two-armed"
- [elseSize := elseExpr sizeForEvaluatedValue: encoder.
- thenSize := (thenExpr sizeForEvaluatedValue: encoder)
- + (thenExpr returns
- ifTrue: [0] "Elide jump over else after a return"
- ifFalse: [self sizeJump: elseSize]).
- branchSize := self sizeBranchOn: false dist: thenSize]
- ifFalse: "One arm is empty here (two-arms code forValue)"
- [(elseExpr isJust: NodeNil)
- ifTrue:
- [elseSize := 0.
- thenSize := thenExpr sizeForEvaluatedEffect: encoder.
- branchSize := self sizeBranchOn: false dist: thenSize]
- ifFalse:
- [thenSize := 0.
- elseSize := elseExpr sizeForEvaluatedEffect: encoder.
- branchSize := self sizeBranchOn: true dist: elseSize]].
- sizes := Array with: thenSize with: elseSize.
- ^ (receiver sizeForValue: encoder) + branchSize
- + thenSize + elseSize!
Item was removed:
- ----- Method: ReturnNode>>sizeForReturn: (in category 'code generation') -----
- sizeForReturn: encoder
-
- ^expr sizeForReturn: encoder!
Item was removed:
- ----- Method: LiteralVariableNode>>emitStorePop:on: (in category 'code generation') -----
- emitStorePop: stack on: strm
- writeNode ifNil:[^super emitStorePop: stack on: strm].
- self emitStore: stack on: strm.
- strm nextPut: Pop.
- stack pop: 1.!
Item was removed:
- ----- Method: FutureNode>>sizeForEffect: (in category 'code generation') -----
- sizeForEffect: encoder
- receiver == NodeSuper ifTrue: [^self error: 'Futures cannot send to future'].
- encoder sharableLitIndex: originalSelector. "to find its senders"
- futureDelta ifNil:[futureDelta := encoder encodeLiteral: 0].
- effectNode := MessageNode new
- receiver: receiver
- selector: #futureDo:at:args:
- arguments: (Array
- with: (encoder encodeLiteral: futureSelector)
- with: futureDelta
- with: (BraceNode new elements: futureArgs))
- precedence: 3
- from: encoder.
- ^effectNode sizeForEffect: encoder!
Item was removed:
- ----- Method: LiteralVariableNode>>sizeForValue: (in category 'code generation') -----
- sizeForValue: encoder
- | index |
- (key isVariableBinding and:[key isSpecialReadBinding])
- ifFalse:[^super sizeForValue: encoder].
- code < 0 ifTrue:[
- index := self index.
- code := self code: index type: LdLitType].
- readNode := encoder encodeSelector: #value.
- ^(readNode size: encoder args: 0 super: false) + (super sizeForValue: encoder)!
Item was removed:
- ----- Method: MessageNode>>sizeForValue: (in category 'code generation') -----
- sizeForValue: encoder
- | total |
- special > 0
- ifTrue: [^self perform: (MacroSizers at: special) with: encoder with: true].
- receiver == NodeSuper
- ifTrue: [selector := selector copy "only necess for splOops"].
- total := selector size: encoder args: arguments size super: receiver == NodeSuper.
- receiver == nil
- ifFalse: [total := total + (receiver sizeForValue: encoder)].
- sizes := arguments collect:
- [:arg | | argSize |
- argSize := arg sizeForValue: encoder.
- total := total + argSize.
- argSize].
- ^total!
Item was removed:
- ----- Method: FieldNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: aStream
- fieldDef accessKey ifNil:[
- rcvrNode emitForValue: stack on: aStream.
- readNode emit: stack args: 0 on: aStream super: false.
- ] ifNotNil:[
- rcvrNode emitForValue: stack on: aStream.
- super emitForValue: stack on: aStream.
- readNode emit: stack args: 1 on: aStream super: false.
- ].
- !
Item was removed:
- ----- Method: AssignmentNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: aStream
-
- variable emitLoad: stack on: aStream.
- value emitForValue: stack on: aStream.
- pc := aStream position + 1. "debug pc is first byte of the store"
- variable emitStore: stack on: aStream!
Item was removed:
- ----- Method: FieldNode>>emitLoad:on: (in category 'code generation') -----
- emitLoad: stack on: strm
- rcvrNode emitForValue: stack on: strm.
- fieldDef accessKey ifNotNil:[
- super emitForValue: stack on: strm.
- ].!
Item was removed:
- ----- Method: FutureNode>>emitForEffect:on: (in category 'code generation') -----
- emitForEffect: stack on: strm
- ^effectNode emitForEffect: stack on: strm!
Item was removed:
- ----- Method: MessageNode>>emitForEffect:on: (in category 'code generation') -----
- emitForEffect: stack on: strm
- "For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly."
- special > 0
- ifTrue:
- [pc := 0.
- self perform: (MacroEmitters at: special) with: stack with: strm with: false]
- ifFalse:
- [super emitForEffect: stack on: strm]!
Item was removed:
- ----- Method: BlockNode>>emitForEvaluatedEffect:on: (in category 'code generation') -----
- emitForEvaluatedEffect: stack on: aStream
-
- self returns
- ifTrue:
- [self emitForEvaluatedValue: stack on: aStream.
- stack pop: 1]
- ifFalse:
- [self emitExceptLast: stack on: aStream.
- statements last emitForEffect: stack on: aStream]!
Item was removed:
- ----- Method: ParseNode>>emitBranchOn:dist:pop:on: (in category 'code generation') -----
- emitBranchOn:
- condition dist: dist pop: stack on: strm
- stack pop: 1.
- dist = 0 ifTrue: [^ strm nextPut: Pop].
- condition
- ifTrue: [self emitLong: dist code: BtpLong on: strm]
- ifFalse: [self emitShortOrLong: dist code: Bfp on: strm]!
Item was removed:
- ----- Method: VariableNode>>emitStore:on: (in category 'code generation') -----
- emitStore: stack on: strm
-
- self emitLong: Store on: strm!
Item was removed:
- ----- Method: SelectorNode>>emit:args:on:super: (in category 'code generation') -----
- emit: stack args: nArgs on: aStream super: supered
- | index |
- stack pop: nArgs.
- (supered not and: [code - Send < SendLimit and: [nArgs < 3]]) ifTrue:
- ["short send"
- code < Send
- ifTrue: [^ aStream nextPut: code "special"]
- ifFalse: [^ aStream nextPut: nArgs * 16 + code]].
- index := code < 256 ifTrue: [code - Send] ifFalse: [code \\ 256].
- (index <= 31 and: [nArgs <= 7]) ifTrue:
- ["extended (2-byte) send [131 and 133]"
- aStream nextPut: SendLong + (supered ifTrue: [2] ifFalse: [0]).
- ^ aStream nextPut: nArgs * 32 + index].
- (supered not and: [index <= 63 and: [nArgs <= 3]]) ifTrue:
- ["new extended (2-byte) send [134]"
- aStream nextPut: SendLong2.
- ^ aStream nextPut: nArgs * 64 + index].
- "long (3-byte) send"
- aStream nextPut: DblExtDoAll.
- aStream nextPut: nArgs + (supered ifTrue: [32] ifFalse: [0]).
- aStream nextPut: index!
Item was removed:
- ----- Method: LiteralNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: strm
-
- code < 256
- ifTrue: [strm nextPut: code]
- ifFalse: [self emitLong: LoadLong on: strm].
- stack push: 1!
Item was removed:
- ----- Method: BlockNode>>sizeForEvaluatedValue: (in category 'code generation') -----
- sizeForEvaluatedValue: encoder
-
- ^(self sizeExceptLast: encoder)
- + (statements last sizeForBlockValue: encoder)!
Item was removed:
- ----- Method: LeafNode>>emitLong:on: (in category 'code generation') -----
- emitLong: mode on: aStream
- "Emit extended variable access."
- | type index |
- code < 256
- ifTrue:
- [code < 16
- ifTrue: [type := 0.
- index := code]
- ifFalse: [code < 32
- ifTrue: [type := 1.
- index := code - 16]
- ifFalse: [code < 96
- ifTrue: [type := code // 32 + 1.
- index := code \\ 32]
- ifFalse: [self error:
- 'Sends should be handled in SelectorNode']]]]
- ifFalse:
- [index := code \\ 256.
- type := code // 256 - 1].
- index <= 63 ifTrue:
- [aStream nextPut: mode.
- ^ aStream nextPut: type * 64 + index].
- "Compile for Double-exetended Do-anything instruction..."
- mode = LoadLong ifTrue:
- [aStream nextPut: DblExtDoAll.
- aStream nextPut: (#(64 0 96 128) at: type+1). "Cant be temp (type=1)"
- ^ aStream nextPut: index].
- mode = Store ifTrue:
- [aStream nextPut: DblExtDoAll.
- aStream nextPut: (#(160 0 0 224) at: type+1). "Cant be temp or const (type=1 or 2)"
- ^ aStream nextPut: index].
- mode = StorePop ifTrue:
- [aStream nextPut: DblExtDoAll.
- aStream nextPut: (#(192 0 0 0) at: type+1). "Can only be inst"
- ^ aStream nextPut: index].
- !
Item was removed:
- ----- Method: BlockNode>>sizeForEvaluatedEffect: (in category 'code generation') -----
- sizeForEvaluatedEffect: encoder
-
- self returns ifTrue: [^self sizeForEvaluatedValue: encoder].
- ^(self sizeExceptLast: encoder)
- + (statements last sizeForEffect: encoder)!
Item was removed:
- ----- Method: FieldNode>>sizeForStorePop: (in category 'code generation') -----
- sizeForStorePop: encoder
- ^(self sizeForStore: encoder) + 1!
Item was removed:
- ----- Method: ParseNode>>sizeBranchOn:dist: (in category 'code generation') -----
- sizeBranchOn: condition dist: dist
- dist = 0 ifTrue: [^1].
- ^ condition
- ifTrue: [2] "Branch on true is always 2 bytes"
- ifFalse: [self sizeShortOrLong: dist]!
Item was removed:
- ----- Method: LeafNode>>sizeForValue: (in category 'code generation') -----
- sizeForValue: encoder
- self reserve: encoder.
- code < 256 ifTrue: [^ 1].
- (code \\ 256) <= 63 ifTrue: [^ 2].
- ^ 3!
Item was removed:
- ----- Method: AssignmentNode>>sizeForEffect: (in category 'code generation') -----
- sizeForEffect: encoder
-
- ^(value sizeForValue: encoder)
- + (variable sizeForStorePop: encoder)!
Item was removed:
- ----- Method: VariableNode>>emitForReturn:on: (in category 'code generation') -----
- emitForReturn: stack on: strm
-
- (code >= LdSelf and: [code <= LdNil])
- ifTrue:
- ["short returns"
- strm nextPut: EndMethod - 4 + (code - LdSelf).
- stack push: 1 "doesnt seem right"]
- ifFalse:
- [super emitForReturn: stack on: strm]!
Item was removed:
- ----- Method: VariableNode>>emitStorePop:on: (in category 'code generation') -----
- emitStorePop: stack on: strm
- (code between: 0 and: 7)
- ifTrue:
- [strm nextPut: ShortStoP + code "short stopop inst"]
- ifFalse:
- [(code between: 16 and: 23)
- ifTrue: [strm nextPut: ShortStoP + 8 + code - 16 "short stopop temp"]
- ifFalse: [(code >= 256 and: [code \\ 256 > 63 and: [code // 256 = 4]])
- ifTrue: [self emitLong: Store on: strm. strm nextPut: Pop]
- ifFalse: [self emitLong: StorePop on: strm]]].
- stack pop: 1!
Item was removed:
- ----- Method: LeafNode>>emitForEffect:on: (in category 'code generation') -----
- emitForEffect: stack on: strm
-
- ^self!
Item was removed:
- ----- Method: BlockNode>>sizeForValue: (in category 'code generation') -----
- sizeForValue: encoder
- nArgsNode := encoder encodeLiteral: arguments size.
- remoteCopyNode := encoder encodeSelector: #blockCopy:.
- size := (self sizeForEvaluatedValue: encoder)
- + (self returns ifTrue: [0] ifFalse: [1]). "endBlock"
- arguments := arguments collect: "Chance to prepare debugger remote temps"
- [:arg | arg asStorableNode: encoder].
- arguments do: [:arg | size := size + (arg sizeForStorePop: encoder)].
- ^1 + (nArgsNode sizeForValue: encoder)
- + (remoteCopyNode size: encoder args: 1 super: false) + 2 + size!
Item was removed:
- ----- Method: SelectorNode>>emit:args:on: (in category 'code generation') -----
- emit: stack args: nArgs on: strm
-
- self emit: stack
- args: nArgs
- on: strm
- super: false!
Item was removed:
- ----- Method: ParseNode>>emitForBlockValue:on: (in category 'code generation') -----
- emitForBlockValue: stack on: aStream
- "Generate code for evaluating the last statement in a block"
- ^self emitForValue: stack on: aStream!
Item was removed:
- ----- Method: ParseNode>>emitForReturn:on: (in category 'code generation') -----
- emitForReturn: stack on: strm
-
- self emitForValue: stack on: strm.
- strm nextPut: EndMethod!
Item was removed:
- ----- Method: AssignmentNode>>emitForEffect:on: (in category 'code generation') -----
- emitForEffect: stack on: aStream
-
- variable emitLoad: stack on: aStream.
- value emitForValue: stack on: aStream.
- pc := aStream position + 1. "debug pc is first byte of the store".
- variable emitStorePop: stack on: aStream!
Item was removed:
- ----- Method: ParseNode>>emitLong:code:on: (in category 'code generation') -----
- emitLong: dist code: longCode on: aStream
- "Force a two-byte jump."
- | code distance |
- code := longCode.
- distance := dist.
- distance < 0
- ifTrue:
- [distance := distance + 1024.
- code := code - 4]
- ifFalse:
- [distance > 1023 ifTrue: [distance := -1]].
- distance < 0
- ifTrue:
- [self error: 'A block compiles more than 1K bytes of code']
- ifFalse:
- [aStream nextPut: distance // 256 + code.
- aStream nextPut: distance \\ 256]!
Item was removed:
- ----- Method: MessageNode>>emitIf:on:value: (in category 'code generation') -----
- emitIf: stack on: strm value: forValue
- | thenExpr thenSize elseExpr elseSize |
- thenSize := sizes at: 1.
- elseSize := sizes at: 2.
- (forValue not and: [(elseSize*thenSize) > 0])
- ifTrue: "Two-armed IFs forEffect share a single pop"
- [^ super emitForEffect: stack on: strm].
- thenExpr := arguments at: 1.
- elseExpr := arguments at: 2.
- receiver emitForValue: stack on: strm.
- forValue
- ifTrue: "Code all forValue as two-armed"
- [self emitBranchOn: false dist: thenSize pop: stack on: strm.
- pc := strm position.
- thenExpr emitForEvaluatedValue: stack on: strm.
- stack pop: 1. "then and else alternate; they don't accumulate"
- thenExpr returns not
- ifTrue: "Elide jump over else after a return"
- [self emitJump: elseSize on: strm].
- elseExpr emitForEvaluatedValue: stack on: strm]
- ifFalse: "One arm is empty here (two-arms code forValue)"
- [thenSize > 0
- ifTrue:
- [self emitBranchOn: false dist: thenSize pop: stack on: strm.
- pc := strm position.
- thenExpr emitForEvaluatedEffect: stack on: strm]
- ifFalse:
- [self emitBranchOn: true dist: elseSize pop: stack on: strm.
- pc := strm position.
- elseExpr emitForEvaluatedEffect: stack on: strm]]!
Item was removed:
- ----- Method: LiteralVariableNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: strm
- super emitForValue: stack on: strm.
- readNode ifNotNil:[readNode emit: stack args: 0 on: strm super: false].!
Item was removed:
- ----- Method: ReturnNode>>emitForReturn:on: (in category 'code generation') -----
- emitForReturn: stack on: strm
-
- expr emitForReturn: stack on: strm.
- pc := strm position!
Item was removed:
- ----- Method: FutureNode>>emitForBlockValue:on: (in category 'code generation') -----
- emitForBlockValue: stack on: strm
- "Generate code for evaluating the last statement in a block."
- ^effectNode emitForValue: stack on: strm!
Item was removed:
- ----- Method: MessageNode>>emitIfNil:on:value: (in category 'code generation') -----
- emitIfNil: stack on: strm value: forValue
-
- | theNode theSize |
- theNode := arguments first.
- theSize := sizes at: 1.
- receiver emitForValue: stack on: strm.
- forValue ifTrue: [strm nextPut: Dup. stack push: 1].
- strm nextPut: LdNil. stack push: 1.
- equalNode emit: stack args: 1 on: strm.
- self
- emitBranchOn: selector key == #ifNotNil:
- dist: theSize
- pop: stack
- on: strm.
- pc := strm position.
- forValue
- ifTrue:
- [strm nextPut: Pop.
- stack pop: 1.
- theNode emitForEvaluatedValue: stack on: strm]
- ifFalse:
- [theNode emitForEvaluatedEffect: stack on: strm].!
Item was removed:
- ----- Method: ParseNode>>sizeShortOrLong: (in category 'code generation') -----
- sizeShortOrLong: dist
-
- (1 <= dist and: [dist <= JmpLimit])
- ifTrue: [^1].
- ^2!
Item was removed:
- ----- Method: BraceNode>>sizeForValue: (in category 'code generation') -----
- sizeForValue: encoder
-
- emitNode := elements size <= 4
- ifTrue: ["Short form: Array braceWith: a with: b ... "
- MessageNode new
- receiver: (encoder encodeVariable: #Array)
- selector: (self selectorForShortForm: elements size)
- arguments: elements precedence: 3 from: encoder]
- ifFalse: ["Long form: (Array braceStream: N) nextPut: a; nextPut: b; ...; braceArray"
- CascadeNode new
- receiver: (MessageNode new
- receiver: (encoder encodeVariable: #Array)
- selector: #braceStream:
- arguments: (Array with: (encoder encodeLiteral: elements size))
- precedence: 3 from: encoder)
- messages: ((elements collect: [:elt | MessageNode new receiver: nil
- selector: #nextPut:
- arguments: (Array with: elt)
- precedence: 3 from: encoder])
- copyWith: (MessageNode new receiver: nil
- selector: #braceArray
- arguments: (Array new)
- precedence: 1 from: encoder))].
- ^ emitNode sizeForValue: encoder!
Item was removed:
- ----- Method: MessageNode>>emitForValue:on: (in category 'code generation') -----
- emitForValue: stack on: strm
- "For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly."
- special > 0
- ifTrue:
- [pc := 0.
- self perform: (MacroEmitters at: special) with: stack with: strm with: true]
- ifFalse:
- [receiver ~~ nil ifTrue: [receiver emitForValue: stack on: strm].
- arguments do: [:argument | argument emitForValue: stack on: strm].
- pc := strm position + 1. "debug pc is first byte of the send, i.e. the next byte".
- selector
- emit: stack
- args: arguments size
- on: strm
- super: receiver == NodeSuper]!
Item was removed:
- ----- Method: LiteralVariableNode>>emitLoad:on: (in category 'code generation') -----
- emitLoad: stack on: strm
- writeNode ifNil:[^super emitLoad: stack on: strm].
- code < 256
- ifTrue: [strm nextPut: code]
- ifFalse: [self emitLong: LoadLong on: strm].
- stack push: 1.!
Item was removed:
- ----- Method: FutureNode>>sizeForValue: (in category 'code generation') -----
- sizeForValue: encoder
- receiver == NodeSuper ifTrue: [^self error: 'Futures cannot send to future'].
- encoder sharableLitIndex: originalSelector. "to find its senders"
- futureDelta ifNil:[futureDelta := encoder encodeLiteral: 0].
- valueNode := MessageNode new
- receiver: receiver
- selector: #futureSend:at:args:
- arguments: (Array
- with: (encoder encodeLiteral: futureSelector)
- with: futureDelta
- with: (BraceNode new elements: futureArgs))
- precedence: 3
- from: encoder.
- ^valueNode sizeForValue: encoder!
Item was removed:
- ----- Method: MessageNode>>emitCase:on:value: (in category 'code generation') -----
- emitCase: stack on: strm value: forValue
-
- | braceNode sizeStream |
- forValue not
- ifTrue: [^super emitForEffect: stack on: strm].
- braceNode := arguments first.
- sizeStream := ReadStream on: sizes.
- receiver emitForValue: stack on: strm.
- braceNode casesForwardDo:
- [:keyNode :valueNode :last | | thenSize elseSize |
- thenSize := sizeStream next.
- elseSize := sizeStream next.
- last ifFalse: [strm nextPut: Dup. stack push: 1].
- keyNode emitForEvaluatedValue: stack on: strm.
- equalNode emit: stack args: 1 on: strm.
- self emitBranchOn: false dist: thenSize pop: stack on: strm.
- last ifFalse: [strm nextPut: Pop. stack pop: 1].
- valueNode emitForEvaluatedValue: stack on: strm.
- last ifTrue: [stack pop: 1].
- valueNode returns ifFalse: [self emitJump: elseSize on: strm]].
- arguments size = 2
- ifTrue:
- [arguments last emitForEvaluatedValue: stack on: strm] "otherwise: [...]"
- ifFalse:
- [NodeSelf emitForValue: stack on: strm.
- caseErrorNode emit: stack args: 0 on: strm]!
Item was removed:
- ----- Method: ParseNode>>emitForEffect:on: (in category 'code generation') -----
- emitForEffect: stack on: strm
-
- self emitForValue: stack on: strm.
- strm nextPut: Pop.
- stack pop: 1!
Item was removed:
- ----- Method: FieldNode>>emitStore:on: (in category 'code generation') -----
- emitStore: stack on: strm
- fieldDef accessKey ifNil:[
- writeNode emit: stack args: 1 on: strm super: false.
- ] ifNotNil:[
- writeNode emit: stack args: 2 on: strm super: false.
- ].!
Item was removed:
- ----- Method: LiteralVariableNode>>sizeForStore: (in category 'code generation') -----
- sizeForStore: encoder
- | index |
- (key isVariableBinding and:[key isSpecialWriteBinding])
- ifFalse:[^super sizeForStore: encoder].
- code < 0 ifTrue:[
- index := self index.
- code := self code: index type: LdLitType].
- writeNode := encoder encodeSelector: #value:.
- ^(writeNode size: encoder args: 1 super: false) + (super sizeForValue: encoder)!
Item was removed:
- ----- Method: CascadeNode>>sizeForValue: (in category 'code generation') -----
- sizeForValue: encoder
-
- | size |
- size := (receiver sizeForValue: encoder) + (messages size - 1 * 2).
- messages do: [:aMessage | size := size + (aMessage sizeForValue: encoder)].
- ^size!
Item was removed:
- ----- Method: LiteralVariableNode>>sizeForStorePop: (in category 'code generation') -----
- sizeForStorePop: encoder
- | index |
- (key isVariableBinding and:[key isSpecialWriteBinding])
- ifFalse:[^super sizeForStorePop: encoder].
- code < 0 ifTrue:[
- index := self index.
- code := self code: index type: LdLitType].
- writeNode := encoder encodeSelector: #value:.
- ^(writeNode size: encoder args: 1 super: false) + (super sizeForValue: encoder) + 1!
Item was removed:
- ----- Method: ParseNode>>sizeJump: (in category 'code generation') -----
- sizeJump: dist
-
- dist = 0 ifTrue: [^0].
- ^self sizeShortOrLong: dist!
Item was removed:
- ----- Method: FieldNode>>sizeForStore: (in category 'code generation') -----
- sizeForStore: encoder
- rcvrNode ifNil:[self encodeReceiverOn: encoder].
- fieldDef accessKey ifNil:[
- writeNode ifNil:[writeNode := encoder encodeSelector: fieldDef toSet].
- ^(rcvrNode sizeForValue: encoder) +
- (writeNode size: encoder args: 1 super: false)
- ].
- writeNode ifNil:[writeNode := encoder encodeSelector: #set:to:].
- ^(rcvrNode sizeForValue: encoder) +
- (super sizeForValue: encoder) +
- (writeNode size: encoder args: 2 super: false)!
Item was removed:
- ----- Method: MessageNode>>sizeForEffect: (in category 'code generation') -----
- sizeForEffect: encoder
-
- special > 0
- ifTrue: [^self perform: (MacroSizers at: special) with: encoder with: false].
- ^super sizeForEffect: encoder!
Item was removed:
- ----- Method: MessageNode>>emitToDo:on:value: (in category 'code generation') -----
- emitToDo: stack on: strm value: forValue
- " var := rcvr. L1: [var <= arg1] Bfp(L2) [block body. var := var + inc] Jmp(L1) L2: "
- | loopSize initStmt limitInit test block incStmt blockSize |
- initStmt := arguments at: 4.
- limitInit := arguments at: 7.
- test := arguments at: 5.
- block := arguments at: 3.
- incStmt := arguments at: 6.
- blockSize := sizes at: 1.
- loopSize := sizes at: 2.
- limitInit == nil
- ifFalse: [limitInit emitForEffect: stack on: strm].
- initStmt emitForEffect: stack on: strm.
- test emitForValue: stack on: strm.
- self emitBranchOn: false dist: blockSize pop: stack on: strm.
- pc := strm position.
- block emitForEvaluatedEffect: stack on: strm.
- incStmt emitForEffect: stack on: strm.
- self emitJump: 0 - loopSize on: strm.
- forValue ifTrue: [strm nextPut: LdNil. stack push: 1]!
Item was removed:
- ----- Method: MessageNode>>sizeWhile:value: (in category 'code generation') -----
- sizeWhile: encoder value: forValue
- "L1: ... Bfp(L2) ... Jmp(L1) L2: nil (nil for value only);
- justStmt, wholeLoop, justJump."
- | cond stmt stmtSize loopSize branchSize |
- cond := receiver.
- stmt := arguments at: 1.
- stmtSize := (stmt sizeForEvaluatedEffect: encoder) + 2.
- branchSize := self sizeBranchOn: (selector key == #whileFalse:) "Btp for whileFalse"
- dist: stmtSize.
- loopSize := (cond sizeForEvaluatedValue: encoder)
- + branchSize + stmtSize.
- sizes := Array with: stmtSize with: loopSize.
- ^ loopSize " +1 for value (push nil) "
- + (forValue ifTrue: [1] ifFalse: [0])!
More information about the Packages
mailing list