[Pkg] The Trunk: Compiler-eem.397.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Jan 3 23:15:11 UTC 2019


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]!



More information about the Packages mailing list