The Trunk: MethodMassage-ct.75.mcz

[email protected] Fri, 12 Jun 2026 00:00:13 0000
Newsgroups gmane.comp.lang.smalltalk.squeak.general
Message-ID <[email protected]>
Christoph Thiede uploaded a new version of MethodMassage to project The Trunk:
http://source.squeak.org/trunk/MethodMassage-ct.75.mcz

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

Name: MethodMassage-ct.75
Author: ct
Time: 12 June 2026, 2:00:13.167523 am
UUID: 0febae50-8cda-4140-b711-655af5d211f2
Ancestors: MethodMassage-dtl.74

Uses new #isAssociation instead of #isVariableBinding to detect labels between instructions, and reuses #isLabel: to improve readability. The new selector is especially helpful here because MethodMassage indeed deals with literals and associations as domain objects. :-)

=============== Diff against MethodMassage-dtl.74 ===============

Item was changed:
  ----- Method: AssemblerMethod>>isLabel: (in category 'private') -----
  isLabel: aMessageOrLookupKey
+ 	^aMessageOrLookupKey isAssociation!
- 	^aMessageOrLookupKey isVariableBinding!

Item was changed:
  ----- Method: AssemblerMethod>>labels (in category 'accessing') -----
  labels
+ 	^instructions select: [:ea| ea isAssociation]!
- 	^instructions select: [:ea| ea isVariableBinding]!

Item was changed:
  ----- Method: AssemblerMethod>>reshapeUsing:oldVars: (in category 'utilities') -----
  reshapeUsing: instVarMap oldVars: originalInstVarNames
  	"Reindex inst var accesses according to the Dictionary instVarMap from old index to new.
  	 Indices are zero-relative"
  	"Scan instructions looking for inst var refs..."
  	instructions withIndexDo:
  		[:messageOrLabel :index|
+ 		 (self isLabel: messageOrLabel) ifFalse:
- 		 messageOrLabel isVariableBinding ifFalse:
  			[(#(popIntoReceiverVariable:
  				pushReceiverVariable:
  				storeIntoReceiverVariable:) identityIncludes: messageOrLabel selector) ifTrue:
  					[instVarMap
  						at: (messageOrLabel arguments at: 1)
  						ifPresent: [:newOffset| messageOrLabel arguments at: 1 put: newOffset]
  						ifAbsent:"A missing ref needs to be mapped to a global variable, e.g. in Undeclared. This is trivial for reads; tediously difficult for writes"
  							[| binding |
  							 selector ~~ #pushReceiverVariable: ifTrue:
  								[UndeclaredVariable name: selector].
  							 binding := self declareAndAddToLiterals: (originalInstVarNames at: messageOrLabel argument + 1) asSymbol.
  							 instructions at: index put: (Message selector: #pushLiteralVariable: argument: binding)]]]].
  	"scan any and all blocks also..."
  	literals do:
  		[:literalOrLabelOrAssemblerMethod|
  		literalOrLabelOrAssemblerMethod class == self class ifTrue:
  			[literalOrLabelOrAssemblerMethod
  				selector: selector; "for UndeclaredVariable name: selector above"
  				reshapeUsing: instVarMap oldVars: originalInstVarNames]].
  	"Don't forget quick field read methods... Update both primitive and the callPrimitive: instruction used to generate."
  	(self isReturnFieldPrimitiveIndex: primitive) ifTrue:
  		[self assert: (instructions first class == Message
  				and: [instructions first selector == #callPrimitive:
  				and: [instructions first arguments first = primitive]]).
  		 instVarMap
  			at: primitive - 264
  			ifPresent:
  				[:newIndex|
  				self assert: newIndex + 264 <= 519.
  				instructions first arguments at: 1 put: (primitive := newIndex + 264)]
  			ifAbsent:
  				[| binding |
  				 self assert: (primitive - 263 between: 1 and: originalInstVarNames size).
  				 binding := self declareAndAddToLiterals: (originalInstVarNames at: primitive - 263) asSymbol.
  				 instructions := {	Message selector: #pushLiteralVariable: argument: binding.
  									Message selector: #methodReturnTop}]]!

Item was changed:
  ----- Method: BytecodeAssembler>>isLabel: (in category 'testing') -----
  isLabel: aMessageOrLookupKey
+ 	^aMessageOrLookupKey isAssociation!
- 	^aMessageOrLookupKey isVariableBinding!

Item was changed:
  ----- Method: BytecodeAssemblerTests>>testAsAssemblerFor: (in category 'test support') -----
  testAsAssemblerFor: aMethod
  	"self new testAsAssemblerFor: self >> #testAsAssemblerFor:"
  	| assemblerMethod assembler reassembledMethod |
  	assemblerMethod := BytecodeDisassembler new disassemble: aMethod.
  	assembler := String streamContents: [:s| assemblerMethod printAsAssemblerOn: s].
  	self shouldnt: [reassembledMethod := Compiler evaluate: assembler]
  		raise: Error.
  	self assert: assemblerMethod compiledMethodClass equals: reassembledMethod compiledMethodClass.
  	self assert: assemblerMethod flag equals: reassembledMethod flag.
  	self assert: assemblerMethod frameSize equals: reassembledMethod frameSize.
  	self assert: assemblerMethod methodClass equals: reassembledMethod methodClass.
  	self assert: assemblerMethod numArgs equals: reassembledMethod numArgs.
  	self assert: assemblerMethod numTemps equals: reassembledMethod numTemps.
  	self assert: assemblerMethod primitive equals: reassembledMethod primitive.
  	self assert: assemblerMethod selector equals: reassembledMethod selector.
  	self assert: assemblerMethod signFlag equals: reassembledMethod signFlag.
  	1 to: reassembledMethod literals size - 1 "ignore methodClass literal" do:
  		[:i|
  		self assert: (assemblerMethod literals at: i)
  			equals: (reassembledMethod literals at: i)].
  	assemblerMethod instructions
  		ifNil: [self assert: reassembledMethod instructions isNil]
  		ifNotNil:
  			[:insts|
  			 self assert: insts size equals: reassembledMethod instructions size.
  			 "Nil the labels' values for analogousCodeTo: comparison below; the values
  			  are usefully the bytecode pcs of the labels, but this fails the comparisons."
+ 			 insts do: [:inst| (assemblerMethod isLabel: inst) ifTrue: [inst value: nil]].
- 			 insts do: [:inst| inst isVariableBinding ifTrue: [inst value: nil]].
  			 insts
  				with: reassembledMethod instructions
  				do: [:old :new|
+ 					(assemblerMethod isLabel: old)
- 					old isVariableBinding
  						ifTrue: [self assert: old key = new key]
  						ifFalse: [self assert: (old analogousCodeTo: new)]]].
  	self assert: aMethod equals: (BytecodeAssembler new assemble: reassembledMethod)!

Squeak-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]