The Trunk: Compiler-eem.397.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Compiler-eem.397.mcz

commits-2
Eliot Miranda uploaded a new version of Compiler to project The Trunk:
http://source.squeak.org/trunk/Compiler-eem.397.mcz

==================== Summary ====================

Name: Compiler-eem.397
Author: eem
Time: 3 January 2019, 3:15:09.938414 pm
UUID: 0561e11a-8d91-4ed1-b806-535264b98ef8
Ancestors: Compiler-eem.396

Fix the recorded pcs for inlined blocks.  The old code assumed one-byte branches and so generated off-by-one pcs for all multiple byte branches.  In addition the code for case guards was simply wrong, always off-by-one.
The fix is to use emncoder nextPC in teh right place, not encoder pc after branch/send generation when a multibyte send will compute the wrong pc.  Tests exist in Tests-eem.405 and later.  Play via debugging e.g.:

5
        caseOf: {
        [4] -> [#nope].
        [3] -> [#nope].
        [2] -> [#nope].
        [1] -> [#nope].
        [0] -> [#nope] }
        otherwise: [#dope]

=============== Diff against Compiler-eem.396 ===============

Item was changed:
  ----- Method: MessageNode>>emitCodeForCase:encoder:value: (in category 'code generation') -----
  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.
+ keyNode pc: encoder nextPC.
- keyNode pc: encoder pc.
  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: MessageNode>>emitCodeForIf:encoder:value: (in category 'code generation') -----
  emitCodeForIf: stack encoder: encoder value: forValue
  | thenExpr thenSize elseExpr elseSize |
  thenSize := sizes at: 1.
  elseSize := sizes at: 2.
  thenExpr := arguments at: 1.
  elseExpr := arguments at: 2.
  receiver emitCodeForValue: stack encoder: encoder.
+ pc := encoder nextPC.
  elseSize * thenSize > 0
  ifTrue:  "Code for two-armed"
  [self emitCodeForBranchOn: false dist: thenSize pop: stack encoder: encoder.
- pc := encoder pc.
  thenExpr emitCodeForEvaluatedValue: stack encoder: encoder.
  stack pop: 1.  "then and else alternate; they don't accumulate"
+ thenExpr returns ifFalse: "Elide jump over else after a return"
- thenExpr returns ifFalse:
- "Elide jump over else after a return"
  [self emitCodeForJump: elseSize encoder: encoder].
  elseExpr emitCodeForEvaluatedValue: stack encoder: encoder.
+ forValue ifFalse: "Two-armed IFs forEffect share a single pop - except if both return"
+ [(arguments allSatisfy: #returns) ifFalse: [encoder genPop].
+ stack pop: 1]]
- forValue
- ifFalse:
- ["Two-armed IFs forEffect share a single pop - except if both return"
- (arguments allSatisfy: #returns) ifFalse: [encoder genPop].
- stack pop: 1]]
  ifFalse:  "One arm is empty here (this can only ever be for effect)"
  [thenSize > 0
  ifTrue:
  [self emitCodeForBranchOn: false dist: thenSize pop: stack encoder: encoder.
- pc := encoder pc.
  thenExpr emitCodeForEvaluatedEffect: stack encoder: encoder]
  ifFalse:
  [self emitCodeForBranchOn: true dist: elseSize pop: stack encoder: encoder.
- pc := encoder pc.
  elseExpr emitCodeForEvaluatedEffect: stack encoder: encoder]]!

Item was changed:
  ----- Method: MessageNode>>emitCodeForIfNil:encoder:value: (in category 'code generation') -----
  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.
+ pc := encoder nextPC.
- pc := encoder pc.
  self
  emitCodeForBranchOn: (selector key == ifNotNilSelector)
  dist: theSize
  pop: stack
  encoder: encoder.
  forValue
  ifTrue:
  [encoder genPop. stack pop: 1.
  theNode emitCodeForEvaluatedValue: stack encoder: encoder]
  ifFalse: [theNode emitCodeForEvaluatedEffect: stack encoder: encoder]!

Item was changed:
  ----- Method: MessageNode>>emitCodeForToDo:encoder:value: (in category 'code generation') -----
  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.
 
  "This will return the receiver of to:do: which is the initial value of the loop"
  forValue
  ifTrue: [initStmt emitCodeForValue: stack encoder: encoder]
  ifFalse: [initStmt emitCodeForEffect: stack encoder: encoder].
  limitInit ifNotNil:
  [limitInit emitCodeForEffect: stack encoder: encoder].
  test emitCodeForValue: stack encoder: encoder.
+ pc := encoder nextPC.
  self emitCodeForBranchOn: false dist: blockSize pop: stack encoder: encoder.
- pc := encoder pc.
  block emitCodeForEvaluatedEffect: stack encoder: encoder.
  incStmt emitCodeForEffect: stack encoder: encoder.
  self emitCodeForJump: 0 - loopSize encoder: encoder!

Item was changed:
  ----- Method: MessageNode>>emitCodeForWhile:encoder:value: (in category 'code generation') -----
  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.
+ pc := encoder nextPC.
  self emitCodeForBranchOn: (selector key == #whileFalse:)  "Bfp for whileTrue"
  dist: stmtSize pop: stack encoder: encoder.   "Btp for whileFalse"
- pc := encoder pc.
  stmt emitCodeForEvaluatedEffect: stack encoder: encoder.
  self emitCodeForJump: 0 - loopSize encoder: encoder.
  forValue ifTrue: [encoder genPushSpecialLiteral: nil. stack push: 1]!