[Vm-dev] VM Maker: VMMaker.oscog-eem.2621.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Dec 19 03:33:42 UTC 2019


Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2621.mcz

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

Name: VMMaker.oscog-eem.2621
Author: eem
Time: 18 December 2019, 7:33:27.184028 pm
UUID: 0ccf8a55-3118-4810-8098-c1ded0a6aad8
Ancestors: VMMaker.oscog-eem.2620

Simulation:
Provide context when fake addresses are not found in the mapping dictionaries but printRegisters and/or printInstructions is not in effect.

Improve generation breaqkpointing to break if the address is anywhere within the instruction, not just at the start of it.

=============== Diff against VMMaker.oscog-eem.2620 ===============

Item was added:
+ ----- Method: Cogit>>errorProcessingSimulationTrap:in: (in category 'simulation processor access') -----
+ errorProcessingSimulationTrap: aProcessorSimulationTrap in: aDictionary
+ 	printRegisters ifFalse:
+ 		[processor printRegistersOn: coInterpreter transcript].
+ 	printInstructions ifFalse:
+ 		[self disassembleFrom: processor pc to: processor pc].
+ 	^aDictionary errorKeyNotFound: aProcessorSimulationTrap address!

Item was changed:
  ----- Method: Cogit>>generateInstructionsAt: (in category 'generate machine code') -----
  generateInstructionsAt: eventualAbsoluteAddress
  	"Size pc-dependent instructions and assign eventual addresses to all instructions.
  	 Answer the size of the code.
  	 Compute forward branches based on virtual address (abstract code starts at 0),
  	 assuming that any branches branched over are long.
  	 Compute backward branches based on actual address.
  	 Reuse the fixups array to record the pc-dependent instructions that need to have
  	 their code generation postponed until after the others."
  	| absoluteAddress pcDependentIndex abstractInstruction fixup |
  	<var: #abstractInstruction type: #'AbstractInstruction *'>
  	<var: #fixup type: #'BytecodeFixup *'>
  	absoluteAddress := eventualAbsoluteAddress.
  	pcDependentIndex := 0.
  	0 to: opcodeIndex - 1 do:
  		[:i|
- 		self maybeBreakGeneratingAt: absoluteAddress.
  		abstractInstruction := self abstractInstructionAt: i.
+ 		self maybeBreakGeneratingFrom: absoluteAddress to: absoluteAddress + abstractInstruction maxSize - 1.
  		abstractInstruction isPCDependent
  			ifTrue:
  				[abstractInstruction sizePCDependentInstructionAt: absoluteAddress.
  				 fixup := self fixupAtIndex: pcDependentIndex.
  				 pcDependentIndex := pcDependentIndex + 1.
  				 fixup instructionIndex: i.
  				 absoluteAddress := absoluteAddress + abstractInstruction machineCodeSize]
  			ifFalse:
  				[absoluteAddress := abstractInstruction concretizeAt: absoluteAddress]].
  	0 to: pcDependentIndex - 1 do:
  		[:j|
  		fixup := self fixupAtIndex: j.
  		abstractInstruction := self abstractInstructionAt: fixup instructionIndex.
+ 		self maybeBreakGeneratingFrom: abstractInstruction address to: abstractInstruction address + abstractInstruction maxSize - 1.
- 		self maybeBreakGeneratingAt: abstractInstruction address.
  		abstractInstruction concretizeAt: abstractInstruction address].
  	^absoluteAddress - eventualAbsoluteAddress!

Item was changed:
  ----- Method: Cogit>>handleCallOrJumpSimulationTrap: (in category 'simulation only') -----
  handleCallOrJumpSimulationTrap: aProcessorSimulationTrap
  	<doNotGenerate>
  	| evaluable function memory result savedFramePointer savedStackPointer savedArgumentCount rpc |
+ 	evaluable := simulatedTrampolines
+ 					at: aProcessorSimulationTrap address
+ 					ifAbsent: [self errorProcessingSimulationTrap: aProcessorSimulationTrap
+ 								in: simulatedTrampolines].
- 	evaluable := simulatedTrampolines at: aProcessorSimulationTrap address.
  	function := evaluable isBlock
  					ifTrue: ['aBlock; probably some plugin primitive']
  					ifFalse:
  						[evaluable receiver == backEnd ifTrue:
  							[^self handleABICallOrJumpSimulationTrap: aProcessorSimulationTrap evaluable: evaluable].
  						 evaluable selector].
  	function ~~ #ceBaseFrameReturn: ifTrue:
  		[coInterpreter assertValidExternalStackPointers].
  	(function beginsWith: 'ceShort') ifTrue:
  		[^self perform: function with: aProcessorSimulationTrap].
  	aProcessorSimulationTrap type == #call
  		ifTrue:
  			[processor
  				simulateCallOf: aProcessorSimulationTrap address
  				nextpc: aProcessorSimulationTrap nextpc
  				memory: (memory := coInterpreter memory).
  			 self recordInstruction: {'(simulated call of '. aProcessorSimulationTrap address. '/'. function. ')'}]
  		ifFalse:
  			[processor
  				simulateJumpCallOf: aProcessorSimulationTrap address
  				memory: (memory := coInterpreter memory).
  			 self recordInstruction: {'(simulated jump to '. aProcessorSimulationTrap address. '/'. function. ')'}].
  	savedFramePointer := coInterpreter framePointer.
  	savedStackPointer := coInterpreter stackPointer.
  	savedArgumentCount := coInterpreter argumentCount.
  	result := ["self halt: evaluable selector."
  		   	   ((printRegisters or: [printInstructions]) and: [clickConfirm]) ifTrue:
  			 	[(self confirm: 'skip run-time call?') ifFalse:
  					[clickConfirm := false. self halt]].
  			   evaluable valueWithArguments: (processor
  												postCallArgumentsNumArgs: evaluable numArgs
  												in: memory)]
  				on: ReenterMachineCode
  				do: [:ex| ex return: ex returnValue].
  			
  	coInterpreter assertValidExternalStackPointers.
  	"Verify the stack layout assumption compileInterpreterPrimitive: makes, provided we've
  	 not called something that has built a frame, such as closure value or evaluate method, or
  	 switched frames, such as primitiveSignal, primitiveWait, primitiveResume, primitiveSuspend et al."
  	(function beginsWith: 'primitive') ifTrue:
  		[coInterpreter checkForLastObjectOverwrite.
  		 coInterpreter primFailCode = 0
  			ifTrue: [(#(	primitiveClosureValue primitiveClosureValueWithArgs primitiveClosureValueNoContextSwitch
  						primitiveFullClosureValue primitiveFullClosureValueWithArgs primitiveFullClosureValueNoContextSwitch
  						primitiveSignal primitiveWait primitiveResume primitiveSuspend primitiveYield
  						primitiveExecuteMethodArgsArray primitiveExecuteMethod
  						primitivePerform primitivePerformWithArgs primitivePerformInSuperclass
  						primitiveTerminateTo primitiveStoreStackp primitiveDoPrimitiveWithArgs)
  							includes: function) ifFalse:
  						["This is a rare case (e.g. in Scorch where a married context's sender is set to nil on trapTrpped and hence the stack layout is altered."
  						 (function == #primitiveSlotAtPut and: [objectMemory isContext: (coInterpreter frameReceiver: coInterpreter framePointer)]) ifFalse:
  							[self assert: savedFramePointer = coInterpreter framePointer.
  							 self assert: savedStackPointer + (savedArgumentCount * objectMemory wordSize)
  									= coInterpreter stackPointer]]]
  			ifFalse:
  				[self assert: savedFramePointer = coInterpreter framePointer.
  				 self assert: savedStackPointer = coInterpreter stackPointer]].
  	result ~~ #continueNoReturn ifTrue:
  		[self recordInstruction: {'(simulated return to '. processor retpcIn: memory. ')'}.
  		 rpc := processor retpcIn: memory.
  		 self assert: (rpc >= codeBase and: [rpc < methodZone freeStart]).
  		 processor
  			smashCallerSavedRegistersWithValuesFrom: 16r80000000 by: objectMemory wordSize in: memory;
  			simulateReturnIn: memory].
  	self assert: (result isInteger "an oop result"
  			or: [result == coInterpreter
  			or: [result == objectMemory
  			or: [#(nil continue continueNoReturn) includes: result]]]).
  	processor cResultRegister: (result
  							ifNil: [0]
  							ifNotNil: [result isInteger
  										ifTrue: [result]
  										ifFalse: [16rF00BA222]])
  
  	"coInterpreter cr.
  	 processor sp + 32 to: processor sp - 32 by: -4 do:
  		[:sp|
  		 sp = processor sp
  			ifTrue: [coInterpreter print: 'sp->'; tab]
  			ifFalse: [coInterpreter printHex: sp].
  		 coInterpreter tab; printHex: (coInterpreter longAt: sp); cr]"!

Item was changed:
  ----- Method: Cogit>>handleReadSimulationTrap: (in category 'simulation only') -----
  handleReadSimulationTrap: aProcessorSimulationTrap
  	<doNotGenerate>
  	| variableValue accessor |
+ 	variableValue := (simulatedVariableGetters
+ 						at: aProcessorSimulationTrap address
+ 						ifAbsent: [self errorProcessingSimulationTrap: aProcessorSimulationTrap
+ 									in: simulatedVariableGetters])
+ 							value asInteger.
- 	variableValue := (simulatedVariableGetters at: aProcessorSimulationTrap address) value asInteger.
  	accessor := aProcessorSimulationTrap registerAccessor.
  	processor
  		perform: accessor
  		with: variableValue signedIntToLong.
  	accessor ~~ #pc: ifTrue:
  		[processor pc: aProcessorSimulationTrap nextpc]!

Item was changed:
  ----- Method: Cogit>>handleWriteSimulationTrap: (in category 'simulation only') -----
  handleWriteSimulationTrap: aProcessorSimulationTrap 
  	<doNotGenerate>
  	| variableValue |
  	(self addressIsInCodeZone: aProcessorSimulationTrap address) ifTrue:
  		[self error: 'attempt to write to code space'].
  	variableValue := processor perform: aProcessorSimulationTrap registerAccessor.
+ 	(simulatedVariableSetters
+ 			at: aProcessorSimulationTrap address
+ 			ifAbsent: [self errorProcessingSimulationTrap: aProcessorSimulationTrap
+ 						in: simulatedVariableSetters])
+ 		value: variableValue.
- 	(simulatedVariableSetters at: aProcessorSimulationTrap address) value: variableValue.
  	processor pc: aProcessorSimulationTrap nextpc!

Item was removed:
- ----- Method: Cogit>>maybeBreakGeneratingAt: (in category 'simulation only') -----
- maybeBreakGeneratingAt: address
- 	"Variation on maybeBreakAt: that only works for integer breakPCs,
- 	 so we can have break blocks that stop at any pc, except when generating."
- 	<cmacro: '(address) 0'> "Simulation only; void in C"
- 	(breakPC = address
- 	 and: [breakBlock shouldStopIfAtPC: address]) ifTrue:
- 		[coInterpreter changed: #byteCountText.
- 		 self halt: 'machine code generation at ', address hex, ' in ', thisContext sender selector]!

Item was added:
+ ----- Method: Cogit>>maybeBreakGeneratingFrom:to: (in category 'simulation only') -----
+ maybeBreakGeneratingFrom: address to: end
+ 	"Variation on maybeBreakAt: that only works for integer breakPCs,
+ 	 so we can have break blocks that stop at any pc, except when generating."
+ 	<cmacro: '(address) 0'> "Simulation only; void in C"
+ 	(breakPC isInteger
+ 	 and: [(breakPC between: address and: end)
+ 	 and: [breakBlock shouldStopIfAtPC: address]]) ifTrue:
+ 		[coInterpreter changed: #byteCountText.
+ 		 self halt: 'machine code generation at ', address hex, ' in ', thisContext sender selector]!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>generateInstructionsAt: (in category 'generate machine code') -----
  generateInstructionsAt: eventualAbsoluteAddress
  	"Size pc-dependent instructions and assign eventual addresses to all instructions.
  	 Answer the size of the code.
  	 Compute forward branches based on virtual address (abstract code starts at 0),
  	 assuming that any branches branched over are long.
  	 Compute backward branches based on actual address.
  	 Reuse the fixups array to record the pc-dependent instructions that need to have
  	 their code generation postponed until after the others.
  
  	 Override to andd handling for null branches (branches to the immediately following
  	 instruction) occasioned by StackToRegisterMapping's following of jumps."
  	| absoluteAddress pcDependentIndex abstractInstruction fixup |
  	<var: #abstractInstruction type: #'AbstractInstruction *'>
  	<var: #fixup type: #'BytecodeFixup *'>
  	absoluteAddress := eventualAbsoluteAddress.
  	pcDependentIndex := 0.
  	0 to: opcodeIndex - 1 do:
  		[:i|
  		abstractInstruction := self abstractInstructionAt: i.
+ 		self maybeBreakGeneratingFrom: absoluteAddress to: absoluteAddress + abstractInstruction maxSize - 1.
- 		self maybeBreakGeneratingAt: absoluteAddress.
  		abstractInstruction isPCDependent
  			ifTrue:
  				[abstractInstruction sizePCDependentInstructionAt: absoluteAddress.
  				 (abstractInstruction isJump
  				  and: [(i + 1 < opcodeIndex
  				  		and: [abstractInstruction getJmpTarget == (self abstractInstructionAt: i + 1)])
  					or: [i + 2 < opcodeIndex
  						and: [abstractInstruction getJmpTarget == (self abstractInstructionAt: i + 2)
  						and: [(self abstractInstructionAt: i + 1) opcode = Nop]]]])
  					ifTrue:
  						[abstractInstruction
  							opcode: Nop;
  							concretizeAt: absoluteAddress]
  					ifFalse:
  						[fixup := self fixupAtIndex: pcDependentIndex.
  						 pcDependentIndex := pcDependentIndex + 1.
  						 fixup instructionIndex: i].
  				 absoluteAddress := absoluteAddress + abstractInstruction machineCodeSize]
  			ifFalse:
  				[absoluteAddress := abstractInstruction concretizeAt: absoluteAddress.
  				 self assert: abstractInstruction machineCodeSize = abstractInstruction maxSize]].
  	0 to: pcDependentIndex - 1 do:
  		[:j|
  		fixup := self fixupAtIndex: j.
  		abstractInstruction := self abstractInstructionAt: fixup instructionIndex.
+ 		self maybeBreakGeneratingFrom: abstractInstruction address to: abstractInstruction address + abstractInstruction maxSize - 1.
- 		self maybeBreakGeneratingAt: abstractInstruction address.
  		abstractInstruction concretizeAt: abstractInstruction address].
  	^absoluteAddress - eventualAbsoluteAddress!



More information about the Vm-dev mailing list