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

commits at source.squeak.org commits at source.squeak.org
Tue Jan 24 22:11:42 UTC 2017


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

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

Name: VMMaker.oscog-eem.2109
Author: eem
Time: 24 January 2017, 2:10:33.410134 pm
UUID: 75381cf8-f227-4599-ab5b-9787ef9bd6a5
Ancestors: VMMaker.oscog-eem.2108

SistaCogit:
Fix conditional branches following inline primitive comparisons given the branch following logic.  The unconditional branch following can only be elided if jumping to the bytecode following the conditional branch, which mnay no longer be the case with branch following.  To this end refactor nextDescriptorAndExtensionsInto: into nextDescriptorExtensionsAndNextPCInto:.

SistaCogit Simulation:
Fix stack depth calculations for trap bytecodes and non-local returns in full blocks.

Fix frame pointer checking in handleCallOrJumpSimulationTrap: for primitiveSlotAtPut sent to a Context.

Neaten [detailed]symbolicMethod: eliding the VMProxy noise.

Fix Character printing in shortPrint: to add the $ in front of the character, not just the code.

Make debugBytecodePCs and debugOpcodeIndices specific to breakMethod if it is set.

Send Label to the right dude in noneImmediateBranchIf:notInstanceOfBehaviors:target:.

Can now simulate Clément's Scorch image enough to see the UI (FFI calls are not simulated so no getenv: hence no sources.  And a createDirectory: causes a primitive failed which shows up in the debugger in the simulation.)

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

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>noneImmediateBranchIf:notInstanceOfBehaviors:target: (in category 'sista support') -----
  noneImmediateBranchIf: reg notInstanceOfBehaviors: arrayObj target: targetFixUp
  	"All classes in arrayObj are not immediate"
  	| label numJumps jumps classObj |
- 	<var: #targetFixUp type: #'AbstractInstruction *'>
  	<var: #label type: #'AbstractInstruction *'>
  	<var: #jumps type: #'AbstractInstruction **'>
+ 	<var: #targetFixUp type: #'AbstractInstruction *'>
  	jumps := self alloca: (objectMemory numSlotsOf: arrayObj) type: (self cCode: [#'AbstractInstruction *'] inSmalltalk: [cogit backEnd class]).
  	(self genJumpImmediate: reg) jmpTarget: targetFixUp.
  	self genGetClassIndexOfNonImm: reg into: TempReg.
  	0 to: (numJumps := objectMemory numSlotsOf: arrayObj) - 1 do:
  		[:i|
  		 classObj := objectMemory fetchPointer: i ofObject: arrayObj.
  		 self genCmpClassIndex: (objectMemory classTagForClass: classObj) R: TempReg.
  		jumps at: i put: (cogit JumpZero: 0) ].
  	cogit Jump: targetFixUp.
+ 	label := cogit Label.
- 	label := self Label.
  	0 to: numJumps - 1 do: [:i |
  		(jumps at: i) jmpTarget: label ].
  	^0!

Item was changed:
  ----- Method: CogVMSimulator>>maybeCheckStackDepth:sp:pc: (in category 'debug support') -----
  maybeCheckStackDepth: delta sp: sp pc: mcpc
  	| asp bcpc startbcpc cogHomeMethod cogBlockMethod csp debugStackPointers |
  	debugStackDepthDictionary ifNil: [^self].
  	(self isMachineCodeFrame: framePointer) ifFalse: [^self].
  	cogBlockMethod := self mframeCogMethod: framePointer.
  	cogHomeMethod := self asCogHomeMethod: cogBlockMethod.
  	debugStackPointers := debugStackDepthDictionary
  								at: cogHomeMethod methodObject
  								ifAbsentPut: [self debugStackPointersFor: cogHomeMethod methodObject].
  	startbcpc := cogHomeMethod = cogBlockMethod
  					ifTrue: [self startPCOfMethod: cogHomeMethod methodObject]
  					ifFalse: [self startPCOfClosure: (self pushedReceiverOrClosureOfFrame: framePointer)].
  	bcpc := cogit bytecodePCFor: mcpc startBcpc: startbcpc in: cogBlockMethod.
  	self assert: bcpc ~= 0.
+ 	((cogBlockMethod ~= cogHomeMethod or: [cogBlockMethod cmIsFullBlock])
- 	(cogBlockMethod ~= cogHomeMethod
  	 and: [cogit isNonLocalReturnPC: mcpc]) ifTrue:
  		[| lastbcpc |
  		 "Method returns within a block (within an unwind-protect) must check the stack depth at the
  		  return, not the bytecode following, but the pc mapping maps to the bytecode following the
  		  return. lastBytecodePCForBlockAt:in: catches method returns at the end of a block, modifying
  		  the bcpc to that of the return.  isNonLocalReturnPC: catches method returns not at the end.
  		  Assumes method return bytecodes are 1 bytecode long;a  dodgy assumption, but good enough."
+ 		 lastbcpc := cogBlockMethod cmIsFullBlock
+ 						ifTrue: [cogit endPCOf: cogHomeMethod methodObject]
+ 						ifFalse: [cogit lastBytecodePCForBlockAt: startbcpc in: cogHomeMethod methodObject].
- 		 lastbcpc := cogit lastBytecodePCForBlockAt: startbcpc in: cogHomeMethod methodObject.
  		 bcpc := bcpc > lastbcpc ifTrue: [lastbcpc] ifFalse: [bcpc - 1]].
  	asp := self stackPointerIndexForFrame: framePointer WithSP: sp + objectMemory wordSize.
  	csp := debugStackPointers at: bcpc ifAbsent: [-1].
+ 	"Compensate for some edge cases"
+ 	asp - delta = csp ifTrue:
+ 		["Compensate for the implicit context receiver push in a trap bytecode with the absence of a contnuation.
+ 		  Assumes trap bytecodes are 1 byte bytecodes."
+ 		 (SistaVM
+ 		  and: [cogit isTrapAt: mcpc]) ifTrue:
+ 			[csp := csp + 1].
+ 		"Compensate lazily for absent receiver sends (cuz mapping is slow, even though incrememting csp is a dodgy idea)."
+ 		(NewspeakVM
+ 		 and: [cogit isAbsentReceiverSendAt: mcpc in: cogHomeMethod]) ifTrue:
+ 			[csp := debugStackPointers at: bcpc put: csp + 1]].
- 	"Compensate lazily for absent receiver sends."
- 	(NewspeakVM
- 	 and: [asp - delta = csp
- 	 and: [cogit isAbsentReceiverSendAt: mcpc in: cogHomeMethod]]) ifTrue:
- 		[csp := debugStackPointers at: bcpc put: csp + 1].
  	self assert: asp - delta + 1 = csp!

Item was changed:
  ----- Method: Cogit>>abstractInstructionAt: (in category 'compile abstract instructions') -----
  abstractInstructionAt: index
  	<cmacro: '(index) (&abstractOpcodes[index])'>
+ 	((debugOpcodeIndices includes: index)
+ 	 and: [breakMethod isNil or: [methodObj = breakMethod]]) ifTrue:
+ 		[self halt].
- 	(debugOpcodeIndices includes: index) ifTrue: [self halt].
  	^abstractOpcodes at: index!

Item was changed:
  ----- Method: Cogit>>handleCallOrJumpSimulationTrap: (in category 'simulation only') -----
  handleCallOrJumpSimulationTrap: aProcessorSimulationTrap
  	<doNotGenerate>
  	| evaluable function result savedFramePointer savedStackPointer savedArgumentCount rpc |
  	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: coInterpreter memory.
  			self recordInstruction: {'(simulated call of '. aProcessorSimulationTrap address. '/'. function. ')'}]
  		ifFalse:
  			[processor
  				simulateJumpCallOf: aProcessorSimulationTrap address
  				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: coInterpreter 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]]]
- 						[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: coInterpreter memory. ')'}.
  		 rpc := processor retpcIn: coInterpreter memory.
  		 self assert: (rpc >= codeBase and: [rpc < methodZone freeStart]).
  		 processor
  			smashCallerSavedRegistersWithValuesFrom: 16r80000000 by: objectMemory wordSize;
  			simulateReturnIn: coInterpreter 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>>isNonLocalReturnPC: (in category 'jit - api') -----
  isNonLocalReturnPC: retpc
  	<doNotGenerate>
  	"Answer if the instruction preceding retpc is a call instruction."
+ 	^(backEnd isCallPrecedingReturnPC: retpc)
+ 	 and: [(backEnd callTargetFromReturnAddress: retpc) = ceNonLocalReturnTrampoline]!
- 	(backEnd isCallPrecedingReturnPC: retpc) ifFalse:
- 		[^false].
- 	^(backEnd callTargetFromReturnAddress: retpc) = ceNonLocalReturnTrampoline!

Item was changed:
  ----- Method: Cogit>>maybeHaltIfDebugPC (in category 'compile abstract instructions') -----
  maybeHaltIfDebugPC 
  	<cmacro: '() 0'> "Simulation only; void in C"
+ 	((debugBytecodePointers includes: bytecodePC)
+ 	 and: [breakMethod isNil or: [methodObj = breakMethod]]) ifTrue:
- 	(debugBytecodePointers includes: bytecodePC) ifTrue:
  		[self halt]!

Item was removed:
- ----- Method: Cogit>>nextDescriptorAndExtensionsInto: (in category 'bytecode generator support') -----
- nextDescriptorAndExtensionsInto: aTrinaryBlock
- 	"Peek ahead and deliver the next descriptor plus extension bytes."
- 	<inline: true>
- 	| savedB0 savedB1 savedB2 savedB3 savedEA savedEB savedNEB descriptor bcpc |
- 	<var: #descriptor type: #'BytecodeDescriptor *'>
- 	descriptor := self generatorAt: byte0.
- 	savedB0 := byte0. savedB1 := byte1. savedB2 := byte2. savedB3 := byte3.
- 	savedEA := extA. savedEB := extB. savedNEB := numExtB.
- 	bcpc := bytecodePC + descriptor numBytes.
- 	[bcpc > endPC ifTrue:
- 		[^aTrinaryBlock value: nil value: 0 value: 0].
- 	 byte0 := (objectMemory fetchByte: bcpc ofObject: methodObj)  + bytecodeSetOffset.
- 	 descriptor := self generatorAt: byte0.
- 	 self loadSubsequentBytesForDescriptor: descriptor at: bcpc.
- 	 descriptor isExtension ifFalse:
- 		[| eA eB |
- 		 eA := extA. eB := extB.
- 		 extA := savedEA. extB := savedEB. numExtB := savedNEB.
- 		 byte0 := savedB0. byte1 := savedB1. byte2 := savedB2. byte3 := savedB3.
- 	 	 ^aTrinaryBlock value: descriptor value: eA value: eB].
- 	 self perform: descriptor generator.
- 	 bcpc := bcpc + descriptor numBytes.
- 	 true] whileTrue!

Item was added:
+ ----- Method: Cogit>>nextDescriptorExtensionsAndNextPCInto: (in category 'bytecode generator support') -----
+ nextDescriptorExtensionsAndNextPCInto: aQuaternaryBlock
+ 	"Peek ahead and deliver the next descriptor, extension bytes and next pc."
+ 	<inline: true>
+ 	| savedB0 savedB1 savedB2 savedB3 savedEA savedEB savedNEB descriptor bcpc |
+ 	<var: #descriptor type: #'BytecodeDescriptor *'>
+ 	descriptor := self generatorAt: byte0.
+ 	savedB0 := byte0. savedB1 := byte1. savedB2 := byte2. savedB3 := byte3.
+ 	savedEA := extA. savedEB := extB. savedNEB := numExtB.
+ 	bcpc := bytecodePC + descriptor numBytes.
+ 	[bcpc > endPC ifTrue:
+ 		[^aQuaternaryBlock value: nil value: 0 value: 0 value: 0].
+ 	 byte0 := (objectMemory fetchByte: bcpc ofObject: methodObj)  + bytecodeSetOffset.
+ 	 descriptor := self generatorAt: byte0.
+ 	 self loadSubsequentBytesForDescriptor: descriptor at: bcpc.
+ 	 descriptor isExtension ifFalse:
+ 		[| eA eB |
+ 		 eA := extA. eB := extB.
+ 		 extA := savedEA. extB := savedEB. numExtB := savedNEB.
+ 		 byte0 := savedB0. byte1 := savedB1. byte2 := savedB2. byte3 := savedB3.
+ 	 	 ^aQuaternaryBlock value: descriptor value: eA value: eB value: bcpc].
+ 	 self perform: descriptor generator.
+ 	 bcpc := bcpc + descriptor numBytes.
+ 	 true] whileTrue!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genPushLiteralVariableGivenDirectedSuper: (in category 'bytecode generator support') -----
  genPushLiteralVariableGivenDirectedSuper: literalIndex
  	"This is a version of genPushLiteralVariable: that looks ahead for a directed super send bytecode
  	 and does not generate any code for the dereference yet if followed by a directed super send."
  	<inline: false>
+ 	self nextDescriptorExtensionsAndNextPCInto:
+ 		[:descriptor :exta :extb :followingPC|
- 	self nextDescriptorAndExtensionsInto:
- 		[:descriptor :exta :extb|
  		(self isDirectedSuper: descriptor extA: exta extB: extb) ifTrue:
  			[tempOop := self getLiteral: literalIndex.
  			 ^0]].
  	^self genPushLiteralVariable: literalIndex!

Item was changed:
  ----- Method: SistaCogit>>genBinaryInlineComparison:opFalse:destReg: (in category 'inline primitive generators') -----
  genBinaryInlineComparison: opTrue opFalse: opFalse destReg: destReg
  	"Inlined comparison. opTrue = jump for true and opFalse = jump for false"
  	<var: #branchDescriptor type: #'BytecodeDescriptor *'>
  	| nextPC branchDescriptor targetBytecodePC postBranchPC |	
  		
  	self extractMaybeBranchDescriptorInto: [ :descr :next :postBranch :target | 
  		branchDescriptor := descr. nextPC := next. postBranchPC := postBranch. targetBytecodePC := target ].
+ 
- 	
  	(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse])
  		ifTrue: "This is the path where the inlined comparison is followed immediately by a branch"
  			[ (self fixupAt: nextPC - initialPC) notAFixup
  				ifTrue: "The next instruction is dead.  we can skip it."
  					[deadCode := true.
  				 	 self ensureFixupAt: targetBytecodePC - initialPC.
  					 self ensureFixupAt: postBranchPC - initialPC ]
  				ifFalse:
  					[self ssPushConstant: objectMemory trueObject]. "dummy value"
  			self genConditionalBranch: (branchDescriptor isBranchTrue ifTrue: [opTrue] ifFalse: [opFalse])
+ 				operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+ 			"We can only elide the jump if the pc after nextPC is the same as postBranchPC.
+ 			 Branch following means it may not be."
+ 			self nextDescriptorExtensionsAndNextPCInto:
+ 				[:iguana1 :iguana2 :iguana3 :followingPC| nextPC := followingPC].
+ 			(deadCode and: [nextPC = postBranchPC]) ifFalse:
+ 				[ self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC) ] ]
- 				operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger. 
- 			deadCode ifFalse: [ self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC) ] ]
  		ifFalse: "This is the path where the inlined comparison is *not* followed immediately by a branch"
  			[| condJump jump |
  			condJump := self genConditionalBranch: opTrue operand: 0.
  			self genMoveFalseR: destReg.
  	 		jump := self Jump: 0.
  			condJump jmpTarget: (self genMoveTrueR: destReg).
  			jump jmpTarget: self Label].
  	^ 0!

Item was added:
+ ----- Method: SistaCogit>>isTrapAt: (in category 'simulation only') -----
+ isTrapAt: retpc
+ 	"For stack depth checking."
+ 	<doNotGenerate>
+ 	^(backEnd isCallPrecedingReturnPC: retpc)
+ 	 and: [(backEnd callTargetFromReturnAddress: retpc) = ceTrapTrampoline]!

Item was changed:
  ----- Method: StackInterpreter>>detailedSymbolicMethod: (in category 'debug support') -----
  detailedSymbolicMethod: aMethod
  	<doNotGenerate>
+ 	 self transcript
+ 		ensureCr;
+ 		nextPutAll:
+ 			((String streamContents:
+ 				[:ts| | prim proxy |
+ 				(prim := self primitiveIndexOf: aMethod) > 0 ifTrue:
+ 					[ts nextPutAll: '<primitive: '; print: prim; nextPut: $>.
+ 					(self isQuickPrimitiveIndex: prim) ifTrue:
+ 						[ts nextPutAll: ' quick method'; cr; flush.
+ 						 ^self].
+ 					ts cr].
+ 				proxy := VMCompiledMethodProxy new
+ 								for: aMethod
+ 								coInterpreter: self
+ 								objectMemory: objectMemory.
+ 				(DetailedInstructionPrinter on: proxy)
+ 					stackHeightComputer: (StackDepthFinder on: proxy);
+ 					indent: 0;
+ 					printInstructionsOn: ts]) copyReplaceAll: 'a VMObjectProxy for ' with: '');
+ 		flush!
- 	| ts prim proxy |
- 	(ts := self transcript) ensureCr.
- 	(prim := self primitiveIndexOf: aMethod) > 0 ifTrue:
- 		[ts nextPutAll: '<primitive: '; print: prim; nextPut: $>.
- 		(self isQuickPrimitiveIndex: prim) ifTrue:
- 			[ts nextPutAll: ' quick method'; cr; flush.
- 			 ^self].
- 		ts cr].
- 	proxy := VMCompiledMethodProxy new
- 					for: aMethod
- 					coInterpreter: self
- 					objectMemory: objectMemory.
- 	(DetailedInstructionPrinter on: proxy)
- 		stackHeightComputer: (StackDepthFinder on: proxy);
- 		indent: 0;
- 		printInstructionsOn: ts.
- 	ts flush!

Item was changed:
  ----- Method: StackInterpreter>>shortPrint: (in category 'simulation') -----
  shortPrint: oop
  	<doNotGenerate>
  	| name classOop |
  	(objectMemory isImmediate: oop) ifTrue:
  		[(objectMemory isImmediateCharacter: oop) ifTrue:
  			[^(objectMemory characterValueOf: oop) < 256
  				ifTrue:
  					['=$', (objectMemory characterValueOf: oop) printString,
+ 					' ($', (String with: (Character value: (objectMemory characterValueOf: oop))), ')']
- 					' (', (String with: (Character value: (objectMemory characterValueOf: oop))), ')']
  				ifFalse:
+ 					['=$', (objectMemory characterValueOf: oop) printString, '($???)']].
- 					['=$', (objectMemory characterValueOf: oop) printString, '(???)']].
  		(objectMemory isIntegerObject: oop) ifTrue:
  			[^'=', (objectMemory integerValueOf: oop) printString,
  			' (', (objectMemory integerValueOf: oop) hex, ')'].
  		(objectMemory isImmediateFloat: oop) ifTrue:
  			[^ '=', (objectMemory floatValueOf: oop) printString, ' (', oop hex, ')'].
  		^'= UNKNOWN IMMEDIATE', ' (', (objectMemory integerValueOf: oop) hex, ')'].
  	(objectMemory addressCouldBeObj: oop) ifFalse:
  		[^(oop bitAnd: objectMemory allocationUnit - 1) ~= 0
  			ifTrue: [' is misaligned']
  			ifFalse: [self whereIs: oop]].
  	(objectMemory isFreeObject: oop) ifTrue:
  		[^' is a free chunk of size ', (objectMemory sizeOfFree: oop) printString,
  			(objectMemory hasSpurMemoryManagerAPI
  				ifTrue: [' 0th: ', (objectMemory fetchPointer: 0 ofFreeChunk: oop) hex]
  				ifFalse: [''])].
  	(objectMemory isForwarded: oop) ifTrue:
  		[^' is a forwarded object to ', (objectMemory followForwarded: oop) hex,
  			' of slot size ', (objectMemory numSlotsOfAny: oop) printString].
  	(objectMemory isFloatInstance: oop) ifTrue:
  		[^'=', (objectMemory dbgFloatValueOf: oop) printString].
  	oop = objectMemory nilObject ifTrue:
  		[^'nil'].
  	oop = objectMemory falseObject ifTrue:
  		[^'false'].
  	oop = objectMemory trueObject ifTrue:
  		[^'true'].
  
  	classOop := objectMemory fetchClassOfNonImm: oop.
  	((self objCouldBeClassObj: oop)
  	 and: [(objectMemory numSlotsOf: classOop) = metaclassNumSlots]) ifTrue:
  		[^'class ', (self nameOfClass: oop)].
  	name := self nameOfClass: classOop.
  	name size = 0 ifTrue: [name := '??'].
  	(#('String'  'ByteString') includes: name) ifTrue:
  		[^(self stringOf: oop) printString].
  	(#('Symbol'  'ByteSymbol') includes: name) ifTrue:
  		[^'#', (self stringOf: oop)].
  	name = 'Character' ifTrue: "SpurMemoryManager has immediate Characters (see above); ObjectMemory does not"
  		[^'=', (Character value: (objectMemory integerValueOf: 
  				(objectMemory fetchPointer: 0 ofObject: oop))) printString].
  
  	"Try to spot association-like things; they're all subclasses of LookupKey"
  	((objectMemory isPointersNonImm: oop)
  	 and: [classOop ~= objectMemory nilObject
  	 and: [((objectMemory instanceSizeOf: classOop) between: ValueIndex + 1 and: ValueIndex + 2)
  	 and: [(objectMemory addressCouldBeObj: (objectMemory fetchPointer: KeyIndex ofObject: oop))]
  	 and: [(objectMemory isBytesNonImm: (objectMemory fetchPointer: KeyIndex ofObject: oop))]]]) ifTrue:
  		[| classLookupKey |
  		 classLookupKey := objectMemory fetchClassOfNonImm: (objectMemory splObj: SchedulerAssociation).
  		 [classLookupKey = objectMemory nilObject ifTrue:
  			[^(('AEIOU' includes: name first) ifTrue: ['an '] ifFalse: ['a ']), name].
  		  (objectMemory instanceSizeOf: classLookupKey) = (KeyIndex + 1)] whileFalse:
  			[classLookupKey := self superclassOf: classLookupKey].
  		 (self includesBehavior: classOop ThatOf: classLookupKey) ifTrue:
  			[^(('AEIOU' includes: name first) ifTrue: ['an '] ifFalse: ['a ']), name,
  				' ', (self shortPrint: (objectMemory fetchPointer: KeyIndex ofObject: oop)),
  				' -> ',
  				(objectMemory fetchPointer: ValueIndex ofObject: oop) hex8]].
  
  	^(('AEIOU' includes: name first) ifTrue: ['an '] ifFalse: ['a ']), name!

Item was changed:
  ----- Method: StackInterpreter>>symbolicMethod: (in category 'debug support') -----
  symbolicMethod: aMethod
  	<doNotGenerate>
+ 	 self transcript
+ 		ensureCr;
+ 		nextPutAll:
+ 			((String streamContents:
+ 				[:ts| | prim |
+ 				(prim := self primitiveIndexOf: aMethod) > 0 ifTrue:
+ 					[ts nextPutAll: '<primitive: '; print: prim; nextPut: $>.
+ 					(self isQuickPrimitiveIndex: prim) ifTrue:
+ 						[ts nextPutAll: ' quick method'; cr; flush.
+ 						 ^self].
+ 					ts cr].
+ 				(InstructionPrinter
+ 						on: (VMCompiledMethodProxy new
+ 								for: aMethod
+ 								coInterpreter: self
+ 								objectMemory: objectMemory))
+ 					indent: 0;
+ 					printInstructionsOn: ts]) copyReplaceAll: 'a VMObjectProxy for ' with: '');
+ 		flush!
- 	| ts prim |
- 	(ts := self transcript) ensureCr.
- 	(prim := self primitiveIndexOf: aMethod) > 0 ifTrue:
- 		[ts nextPutAll: '<primitive: '; print: prim; nextPut: $>.
- 		(self isQuickPrimitiveIndex: prim) ifTrue:
- 			[ts nextPutAll: ' quick method'; cr; flush.
- 			 ^self].
- 		ts cr].
- 	(InstructionPrinter
- 			on: (VMCompiledMethodProxy new
- 					for: aMethod
- 					coInterpreter: self
- 					objectMemory: objectMemory))
- 		indent: 0;
- 		printInstructionsOn: ts.
- 	ts flush!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>fixupAt: (in category 'compile abstract instructions') -----
  fixupAt: index
  	<cmacro: '(index) (&fixups[index])'>
  	<returnTypeC: #'BytecodeFixup *'>
+ 	((debugFixupBreaks includes: index)
+ 	 and: [breakMethod isNil or: [methodObj = breakMethod]]) ifTrue:
- 	(debugFixupBreaks includes: index) ifTrue:
  		[self halt].
  	^self addressOf: (fixups at: index)!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genPushLiteralVariableGivenDirectedSuper: (in category 'bytecode generator support') -----
  genPushLiteralVariableGivenDirectedSuper: literalIndex
  	"This is a version of genPushLiteralVariable: that looks ahead for a directed super send bytecode
  	 and does not generate any code for the dereference yet if followed by a directed super send."
  	<inline: false>
+ 	self nextDescriptorExtensionsAndNextPCInto:
+ 		[:descriptor :exta :extb :followingPC|
- 	self nextDescriptorAndExtensionsInto:
- 		[:descriptor :exta :extb|
  		(self isDirectedSuper: descriptor extA: exta extB: extb) ifTrue:
  			[self ssPushConstant: (self getLiteral: literalIndex).
  			 ^0]].
  	^self genPushLiteralVariable: literalIndex!



More information about the Vm-dev mailing list