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

commits at source.squeak.org commits at source.squeak.org
Thu Jun 11 19:51:57 UTC 2015


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

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

Name: VMMaker.oscog-eem.1347
Author: eem
Time: 11 June 2015, 12:49:55.335 pm
UUID: 2a1037d4-068d-465f-871f-673a04dd7e0f
Ancestors: VMMaker.oscog-eem.1346

Fix the blunder with shared out-of-line literals;
the out-of-line literal for an in-line send cache
must be unique.

Fix genQuickReturnConst for out-of-line literals.

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

Item was changed:
  ----- Method: CogInLineLiteralsARMCompiler>>rewriteInlineCacheAt:tag:target: (in category 'inline cacheing') -----
  rewriteInlineCacheAt: callSiteReturnAddress tag: cacheTag target: callTargetAddress
  	"Rewrite an inline cache to call a different target for a new tag.  This variant is used
  	 to link unlinked sends in ceSend:to:numArgs: et al.  Answer the extent of the code
  	 change which is used to compute the range of the icache to flush."
- 	
- 	"chacheTag contains an oop to the selector which need be loaded before jumping"
  	<var: #callSiteReturnAddress type: #usqInt>
  	<var: #callTargetAddress type: #usqInt>
  	| call callDistance |
  	false
  		ifTrue: [self assert: callTargetAddress >= cogit minCallAddress]
  		ifFalse: [callTargetAddress >= cogit minCallAddress ifFalse:
  					[self error: 'linking callsite to invalid address']].
  	callDistance := (callTargetAddress - (callSiteReturnAddress + 8 "pc offset"- 4 "return offset")) signedIntToLong.
  	self assert: (self isInImmediateJumpRange: callDistance). "we don't support long call updates here"
  	call := self bl: callDistance.
  	objectMemory longAt: callSiteReturnAddress - 4 put: call.
  	self insert32BitOperand: cacheTag into4InstructionsPreceeding: callSiteReturnAddress - 4.
  	self assert: (self callTargetFromReturnAddress: callSiteReturnAddress) signedIntToLong = callTargetAddress.
  	self assert: (self extract32BitOperandFrom4InstructionsPreceeding: callSiteReturnAddress - 4) = cacheTag.
  	"self cCode: ''
  		inSmalltalk: [cogit disassembleFrom: callSiteReturnAddress - 20 to: callSiteReturnAddress - 1]."
  	^20!

Item was changed:
  ----- Method: CogOutOfLineLiteralsARMCompiler>>inlineCacheTagAt: (in category 'inline cacheing') -----
+ inlineCacheTagAt: address
- inlineCacheTagAt: address 
  	^objectMemory longAt: (self pcRelativeAddressAt: address - 8)!

Item was added:
+ ----- Method: CogOutOfLineLiteralsARMCompiler>>isSharable (in category 'generate machine code') -----
+ isSharable
+ 	"Hack:  To know if a literal should be unique (not shared) mark the second operand."
+ 	<inline: true>
+ 	self assert: opcode = Literal.
+ 	^(operands at: 1) isNil!

Item was added:
+ ----- Method: CogOutOfLineLiteralsARMCompiler>>isUnique (in category 'generate machine code') -----
+ isUnique
+ 	"Hack:  To know if a literal should be unique (not shared) mark the second operand."
+ 	<inline: true>
+ 	self assert: opcode = Literal.
+ 	^(operands at: 1) notNil!

Item was changed:
  ----- Method: CogOutOfLineLiteralsARMCompiler>>literalOpcodeIndex (in category 'generate machine code') -----
  literalOpcodeIndex
  	"Hack:  To know how far away a literal is from its referencing instruction we store
  	 its opcodeIndex, or -1, if as yet unassigned, in the second operand of the literal."
  	<inline: true>
+ 	self assert: opcode = Literal.
  	^operands at: 2!

Item was added:
+ ----- Method: CogOutOfLineLiteralsARMCompiler>>rewriteInlineCacheAt:tag:target: (in category 'inline cacheing') -----
+ rewriteInlineCacheAt: callSiteReturnAddress tag: cacheTag target: callTargetAddress
+ 	"Rewrite an inline cache to call a different target for a new tag.  This variant is used
+ 	 to link unlinked sends in ceSend:to:numArgs: et al.  Answer the extent of the code
+ 	 change which is used to compute the range of the icache to flush."
+ 	<var: #callSiteReturnAddress type: #usqInt>
+ 	<var: #callTargetAddress type: #usqInt>
+ 	| call callDistance |
+ 	callTargetAddress >= cogit minCallAddress ifFalse:
+ 		[self error: 'linking callsite to invalid address'].
+ 	callDistance := (callTargetAddress - (callSiteReturnAddress + 8 "pc offset"- 4 "return offset")) signedIntToLong.
+ 	self assert: (self isInImmediateJumpRange: callDistance). "we don't support long call updates here"
+ 	call := self bl: callDistance.
+ 	objectMemory
+ 		longAt: callSiteReturnAddress - 4 put: call;
+ 		longAt: (self pcRelativeAddressAt: callSiteReturnAddress - 8) put: cacheTag.
+ 	self assert: (self inlineCacheTagAt: callSiteReturnAddress) = cacheTag.
+ 	"self cCode: ''
+ 		inSmalltalk: [cogit disassembleFrom: callSiteReturnAddress - 20 to: callSiteReturnAddress - 1]."
+ 	^4!

Item was added:
+ ----- Method: CogOutOfLineLiteralsARMCompiler>>setIsUnique (in category 'generate machine code') -----
+ setIsUnique
+ 	"Hack:  To know if a literal should be unique (not shared) mark the second operand."
+ 	<inline: true>
+ 	self assert: opcode = Literal.
+ 	^operands at: 1 put: true!

Item was changed:
  ----- Method: CogOutOfLineLiteralsARMCompiler>>setLiteralOpcodeIndex: (in category 'generate machine code') -----
  setLiteralOpcodeIndex: index
  	"Hack:  To know how far away a literal is from its referencing instruction we store
  	 its opcodeIndex, or -1, if as yet unassigned, in the second operand of the literal."
  	<inline: true>
+ 	self assert: opcode = Literal.
  	^operands at: 2 put: index!

Item was added:
+ ----- Method: Cogit>>MoveUniqueCw:R: (in category 'abstract instructions') -----
+ MoveUniqueCw: wordConstant R: reg
+ 	"If the backEnd is using out-of-line literals then those for inline caches cannot be shared, and
+ 	 this method ensures the instruction has its own unique label.  If the backEnd is using
+ 	 in-line literals then the literal is unique anyway and this is equivalent to MoveCw:R:"
+ 	<inline: true>
+ 	<returnTypeC: #'AbstractInstruction *'>
+ 	^self gen: MoveCwR uniqueLiteral: wordConstant operand: reg!

Item was changed:
  ----- Method: Cogit>>cogExtendPIC:CaseNMethod:tag:isMNUCase: (in category 'in-line cacheing') -----
  cogExtendPIC: cPIC CaseNMethod: caseNMethod tag: caseNTag isMNUCase: isMNUCase
  	"Extend the cPIC with the supplied case.  If caseNMethod is cogged dispatch direct to
  	 its unchecked entry-point.  If caseNMethod is not cogged, jump to the fast interpreter
  	 dispatch, and if isMNUCase then dispatch to fast MNU invocation and mark the cPIC as
  	 having the MNU case for cache flushing."
   	<var: #cPIC type: #'CogMethod *'>
  	| operand target address size end |
  	"stack allocate the various collections so that they
  	 are effectively garbage collected on return."
  	coInterpreter
  		compilationBreak: cPIC selector
  		point: (objectMemory numBytesOf: cPIC selector)
  		isMNUCase: isMNUCase.
+ 	self allocateOpcodes: 8 bytecodes: 0.
- 	self allocateOpcodes: 5 bytecodes: 0.
  	literalsManager resetLiterals: 5.
  	methodLabel address: cPIC asUnsignedInteger; dependent: nil. "for pc-relative MoveCw: cPIC R: ClassReg"
  	self assert: (objectRepresentation inlineCacheTagIsYoung: caseNTag) not.
  	"Caller patches to open pic if caseNMethod is young."
  	self assert: (caseNMethod notNil and: [(objectMemory isYoung: caseNMethod) not]).
  	(isMNUCase not
  	 and: [coInterpreter methodHasCogMethod: caseNMethod])
  		ifTrue:
  			[operand := 0.
  			 target := (coInterpreter cogMethodOf: caseNMethod) asInteger + cmNoCheckEntryOffset]
  		ifFalse:
  			[operand := caseNMethod.
  			 isMNUCase
  				ifTrue:
  					[cPIC cpicHasMNUCase: true.
  					 target := cPIC asInteger + (self sizeof: CogMethod)]
  				ifFalse:
  					[target := cPIC asInteger + self picInterpretAbortOffset]].
  	self CmpCw: caseNTag R: TempReg.
+ 	self MoveUniqueCw: operand R: SendNumArgsReg.
- 	self MoveCw: operand R: SendNumArgsReg.
  	self DumpJumpLongZero: target.
  	self MoveCw: cPIC asUnsignedInteger R: ClassReg.
  	self JumpLong: (self cPICMissTrampolineFor: cPIC cmNumArgs).
  	self computeMaximumSizes.
  	address := self addressOfEndOfCase: cPIC cPICNumCases - 1 inCPIC: cPIC.
  	size := self generateInstructionsAt: address.
  	end := self outputInstructionsAt: address.
  	processor flushICacheFrom: cPIC asUnsignedInteger to: cPIC asUnsignedInteger + closedPICSize.
  	cPIC cPICNumCases: cPIC cPICNumCases + 1.
  	^0!

Item was changed:
  ----- Method: Cogit>>compileCPIC:Case0:Case1Method:tag:isMNUCase:numArgs: (in category 'in-line cacheing') -----
  compileCPIC: cPIC Case0: case0CogMethod Case1Method: case1Method tag: case1Tag isMNUCase: isMNUCase numArgs: numArgs
  	"Compile the code for a two-case PIC for case0CogMethod and  case1Method,case1Tag.
  	 The tag for case0CogMethod is at the send site and so doesn't need to be generated.
  	 case1Method may be any of
  		- a Cog method; jump to its unchecked entry-point
  		- a CompiledMethod; jump to the ceInterpretFromPIC trampoline
  		- nil; call ceMNUFromPIC"
  	<var: #cPIC type: #'CogMethod *'>
  	| operand targetEntry jumpNext |
  	<var: #case0CogMethod type: #'CogMethod *'>
  	<var: #targetEntry type: #'void *'>
  	<var: #jumpNext type: #'AbstractInstruction *'>
  	self assert: case1Method notNil.
  	self compilePICAbort: numArgs.
  	self assert: (objectRepresentation inlineCacheTagIsYoung: case1Tag) not.
  	(isMNUCase not
  	 and: [coInterpreter methodHasCogMethod: case1Method])
  		ifTrue:
  			[operand := 0.
  			 targetEntry := ((coInterpreter cogMethodOf: case1Method) asInteger + cmNoCheckEntryOffset) asVoidPointer]
  		ifFalse: "We do not scavenge PICs, hence we cannot cache the MNU method if it is in new space."
  			[operand := (case1Method isNil or: [objectMemory isYoungObject: case1Method])
  							ifTrue: [0]
  							ifFalse: [case1Method].
  			 targetEntry := case1Method isNil ifTrue: [picMNUAbort] ifFalse: [picInterpretAbort]].
  
  	jumpNext := self compileCPICEntry.
+ 	self MoveUniqueCw: 0 R: SendNumArgsReg.
- 	self MoveCw: 0 R: SendNumArgsReg.
  	self DumpJumpLong: case0CogMethod asInteger + cmNoCheckEntryOffset.
  	endCPICCase0 := self CmpCw: case1Tag R: TempReg.
  	jumpNext jmpTarget: endCPICCase0.
+ 	self MoveUniqueCw: operand R: SendNumArgsReg.
- 	self MoveCw: operand R: SendNumArgsReg.
  	self DumpJumpLongZero: (isMNUCase ifTrue: [picMNUAbort] ifFalse: [targetEntry]) asInteger.
  	endCPICCase1 := self MoveCw: cPIC asUnsignedInteger R: ClassReg.
  	self JumpLong: (self cPICMissTrampolineFor: numArgs).
  	^0
  !

Item was changed:
  ----- Method: Cogit>>compileClosedPICPrototype (in category 'in-line cacheing') -----
  compileClosedPICPrototype
  	"Compile the abstract instructions for a full closed PIC used to initialize closedPICSize.
  	 The loads into SendNumArgsReg are those for optional method objects which may be
  	 used in MNU cases."
  	<inline: true>
  	| numArgs jumpNext |
  	<var: #jumpNext type: #'AbstractInstruction *'>
  	numArgs := 0.
  	self compilePICAbort: numArgs.
  	jumpNext := self compileCPICEntry.
+ 	self MoveUniqueCw: 16r5EAF00D R: SendNumArgsReg.
- 	self MoveCw: 16r5EAF00D R: SendNumArgsReg.
  	self DumpJumpLong: methodZoneBase + 16rCA5E10.
  	jumpNext jmpTarget: (endCPICCase0 := self Label).
  	1 to: numPICCases - 1 do:
  		[:h|
  		self CmpCw: 16rBABE1F15+h R: TempReg.
+ 		self MoveUniqueCw: 16rBADA550 + h R: SendNumArgsReg.
- 		self MoveCw: 16rBADA550 + h R: SendNumArgsReg.
  		self DumpJumpLongZero: 16rCA5E10 + (h * 16).
  		h = 1 ifTrue:
  			[endCPICCase1 := self Label]].
  	self MoveCw: methodLabel address R: ClassReg.
  	self JumpLong: (self cPICMissTrampolineFor: numArgs).
  	^0!

Item was changed:
  ----- Method: Cogit>>compileMNUCPIC:methodOperand:numArgs: (in category 'in-line cacheing') -----
  compileMNUCPIC: cPIC methodOperand: methodOperand numArgs: numArgs
  	"Compile the code for a one-case MNU PIC that calls ceMNUFromPIC for case0Tag
  	 The tag for case0 is at the send site and so doesn't need to be generated."
  	<var: #cPIC type: #'CogMethod *'>
  	| jumpNext operand |
  	<var: #jumpNext type: #'AbstractInstruction *'>
  	self compilePICAbort: numArgs.
  	jumpNext := self compileCPICEntry.
  	"We do not scavenge PICs, hence we cannot cache the MNU method if it is in new space."
  	operand := (methodOperand isNil or: [objectMemory isYoungObject: methodOperand])
  					ifTrue: [0]
  					ifFalse: [methodOperand].
+ 	self MoveUniqueCw: operand R: SendNumArgsReg.
- 	self MoveCw: operand R: SendNumArgsReg.
  	self DumpJumpLong: picMNUAbort asInteger.
  	jumpNext jmpTarget: (self MoveCw: cPIC asUnsignedInteger R: ClassReg).
  	self JumpLong: (self cPICMissTrampolineFor: numArgs).
  	^0
  !

Item was added:
+ ----- Method: Cogit>>gen:uniqueLiteral:operand: (in category 'compile abstract instructions') -----
+ gen: opcode "<Integer>" uniqueLiteral: operandOne "<Integer>" operand: operandTwo "<Integer|CogAbstractInstruction>"
+ 	"Literals are constants that either represent objects on the heap that may get updated by
+ 	 the garbage collector, or pc-relative spans that may get changed by code compaction, and
+ 	 must hence always be encoded in a form that allows updating to refer to a different value."
+ 	<inline: true>
+ 	<returnTypeC: #'AbstractInstruction *'>
+ 	<var: #abstractInstruction type: #'AbstractInstruction *'>
+ 	^literalsManager
+ 		uniqueLiteral: operandOne
+ 		forInstruction: (self gen: opcode operand: operandOne operand: operandTwo)!

Item was added:
+ ----- Method: InLineLiteralsManager>>uniqueLiteral:forInstruction: (in category 'compile abstract instructions') -----
+ uniqueLiteral: literal forInstruction: anInstruction
+ 	<var: #anInstruction type: #'AbstractInstruction *'>
+ 	<returnTypeC: #'AbstractInstruction *'>
+ 	<inline: true>
+ 	^anInstruction!

Item was added:
+ ----- Method: OutOfLineLiteralsManager>>allocateLiteral: (in category 'compile abstract instructions') -----
+ allocateLiteral: aLiteral
+ 	"Allocate a n unsharable Literal instruction for the literal and answer it."
+ 	<returnTypeC: #'AbstractInstruction *'>
+ 	<inline: true>
+ 	| litInst |
+ 	<var: 'litInst' type: #'AbstractInstruction *'>
+ 	nextLiteralIndex >= literalsSize ifTrue:
+ 		[self allocateLiterals: literalsSize + 8].
+ 	litInst := self literalInstructionAt: nextLiteralIndex.
+ 	litInst
+ 		opcode: Literal;
+ 		operand0: aLiteral;
+ 		setIsUnique;
+ 		setLiteralOpcodeIndex: -1. "means as-yet-unassigned; see literalInstructionInRange:"
+ 	nextLiteralIndex := nextLiteralIndex + 1.
+ 	"Record the opcodeIndex of the first dependent instructuon (the first instruction that references an out-of-line literal)"
+ 	firstOpcodeIndex > cogit getOpcodeIndex ifTrue:
+ 		[firstOpcodeIndex := cogit getOpcodeIndex - 1].
+ 	^litInst!

Item was changed:
  ----- Method: OutOfLineLiteralsManager>>locateLiteral: (in category 'compile abstract instructions') -----
  locateLiteral: aLiteral
  	"Search for a Literal instruction that is in-range and answer it.  Otherwise
  	 allocate a new Literal instruction for the literal and answer it."
  	<returnTypeC: #'AbstractInstruction *'>
  	<inline: false>
  	| litInst |
  	<var: 'litInst' type: #'AbstractInstruction *'>
  	0 to: nextLiteralIndex - 1 do:
  		[:i|
  		litInst := self literalInstructionAt: i.
  		((litInst operands at: 0) = aLiteral
+ 		 and: [litInst isSharable
+ 		 and: [self literalInstructionInRange: litInst]]) ifTrue:
- 		 and: [self literalInstructionInRange: litInst]) ifTrue:
  			[^litInst]].
  	nextLiteralIndex >= literalsSize ifTrue:
  		[self allocateLiterals: literalsSize + 8].
  	litInst := self literalInstructionAt: nextLiteralIndex.
  	litInst
  		opcode: Literal;
  		operand0: aLiteral;
  		setLiteralOpcodeIndex: -1. "means as-yet-unassigned; see literalInstructionInRange:"
  	nextLiteralIndex := nextLiteralIndex + 1.
  	"Record the opcodeIndex of the first dependent instructuon (the first instruction that references an out-of-line literal)"
  	firstOpcodeIndex > cogit getOpcodeIndex ifTrue:
  		[firstOpcodeIndex := cogit getOpcodeIndex - 1].
  	^litInst!

Item was added:
+ ----- Method: OutOfLineLiteralsManager>>uniqueLiteral:forInstruction: (in category 'compile abstract instructions') -----
+ uniqueLiteral: literal forInstruction: anInstruction
+ 	<var: #anInstruction type: #'AbstractInstruction *'>
+ 	<returnTypeC: #'AbstractInstruction *'>
+ 	<inline: true>
+ 	self assert: anInstruction usesOutOfLineLiteral.
+ 	anInstruction dependent: (self allocateLiteral: literal).
+ 	^anInstruction!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genQuickReturnConst (in category 'primitive generators') -----
  genQuickReturnConst
  	<api> "because selected by CoInterpreter>>quickPrimitiveGeneratorFor:"
  	| constant |
  	constant := coInterpreter quickPrimitiveConstantFor: primitiveIndex.
  	self annotate:
+ 			((objectRepresentation isImmediate: constant)
+ 				ifTrue: [self MoveCq: constant R: ReceiverResultReg]
+ 				ifFalse: [self MoveCw: constant R: ReceiverResultReg])
- 			(self gen: ((objectRepresentation isImmediate: constant)
- 						ifTrue: [MoveCqR]
- 						ifFalse: [MoveCwR])
- 				operand: constant
- 				operand: ReceiverResultReg)
  		objRef: constant.
  	^self genUpArrowReturn!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genSend:numArgs:sendTable: (in category 'bytecode generator support') -----
  genSend: selector numArgs: numArgs sendTable: sendTable
  	<inline: false>
  	<var: #sendTable type: #'sqInt *'>
  	| annotation |
  	(objectMemory isYoung: selector) ifTrue:
  		[hasYoungReferent := true].
  	self assert: needsFrame.
  	annotation := self annotationForSendTable: sendTable.
  	self assert: (numArgs between: 0 and: 255). "say"
  	self assert: (objectMemory addressCouldBeOop: selector).
  	self MoveMw: numArgs * objectMemory wordSize r: SPReg R: ReceiverResultReg.
  	"Deal with stale super sends; see SpurMemoryManager's class comment."
  	(self annotationIsForUncheckedEntryPoint: annotation) ifTrue:
  		[objectRepresentation genEnsureOopInRegNotForwarded: ReceiverResultReg scratchReg: TempReg].
  	"0 through (NumSendTrampolines - 2) numArgs sends have the arg count implciti in the trampoline.
  	 The last send trampoline (NumSendTrampolines - 1) passes numArgs in SendNumArgsReg."
  	numArgs >= (NumSendTrampolines - 1) ifTrue:
  		[self MoveCq: numArgs R: SendNumArgsReg].
  	(BytecodeSetHasDirectedSuperSend
  	 and: [annotation = IsDirectedSuperSend]) ifTrue:
  		[self genMoveConstant: tempOop R: TempReg].
+ 	self MoveUniqueCw: selector R: ClassReg.
- 	self MoveCw: selector R: ClassReg.
  	(self Call: (sendTable at: (numArgs min: NumSendTrampolines - 1))) annotation: annotation.
  	self PushR: ReceiverResultReg.
  	^0!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genSendAbsentImplicitOrOuter:numArgs:depth:sendTable: (in category 'bytecode generators') -----
  genSendAbsentImplicitOrOuter: selector numArgs: numArgs depth: depth sendTable: sendTable
  	<var: #sendTable type: #'sqInt *'>
  	| nsSendCache |
  	(objectMemory isYoung: selector) ifTrue:
  		[hasYoungReferent := true].
  
  	nsSendCache := theIRCs + (NumOopsPerNSC * objectMemory bytesPerOop * indexOfIRC).
  	indexOfIRC := indexOfIRC + 1.
  	self assert: (objectMemory isInOldSpace: nsSendCache).
  	self initializeNSSendCache: nsSendCache selector: selector numArgs: numArgs depth: depth.
  
  	"This leaves the method receiver on the stack, which might not be the implicit receiver.
  	 But the lookup trampoline will establish the on-stack receiver once it locates it."
  	self marshallAbsentReceiverSendArguments: numArgs.
  
  	"Load the cache last so it is a fixed distance from the call."
+ 	self MoveUniqueCw: nsSendCache R: SendNumArgsReg.
- 	self MoveCw: nsSendCache R: SendNumArgsReg.
  	self CallNewspeakSend: (sendTable at: (numArgs min: NumSendTrampolines - 1)).
  
  	self PushR: ReceiverResultReg.
  	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genMarshalledSend:numArgs:sendTable: (in category 'bytecode generator support') -----
  genMarshalledSend: selector numArgs: numArgs sendTable: sendTable
  	<inline: false>
  	<var: #sendTable type: #'sqInt *'>
  	| annotation |
  	(objectMemory isYoung: selector) ifTrue:
  		[hasYoungReferent := true].
  	self assert: needsFrame.
  	annotation := self annotationForSendTable: sendTable.
  	"Deal with stale super sends; see SpurMemoryManager's class comment."
  	(self annotationIsForUncheckedEntryPoint: annotation) ifTrue:
  		[objectRepresentation genEnsureOopInRegNotForwarded: ReceiverResultReg scratchReg: TempReg].
  	"0 through (NumSendTrampolines - 2) numArgs sends have the arg count implciti in the trampoline.
  	 The last send trampoline (NumSendTrampolines - 1) passes numArgs in SendNumArgsReg."
  	numArgs >= (NumSendTrampolines - 1) ifTrue:
  		[self MoveCq: numArgs R: SendNumArgsReg].
  	(BytecodeSetHasDirectedSuperSend
  	 and: [annotation = IsDirectedSuperSend]) ifTrue:
  		[self genMoveConstant: tempOop R: TempReg].
+ 	self MoveUniqueCw: selector R: ClassReg.
- 	self MoveCw: selector R: ClassReg.
  	(self Call: (sendTable at: (numArgs min: NumSendTrampolines - 1))) annotation: annotation.
  	optStatus isReceiverResultRegLive: false.
  	^self ssPushRegister: ReceiverResultReg!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genSendAbsentImplicitOrOuter:numArgs:depth:sendTable: (in category 'bytecode generators') -----
  genSendAbsentImplicitOrOuter: selector numArgs: numArgs depth: depth sendTable: sendTable
  	<var: #sendTable type: #'sqInt *'>
  	| nsSendCache |
  	(objectMemory isYoung: selector) ifTrue:
  		[hasYoungReferent := true].
  
  	nsSendCache := theIRCs + (NumOopsPerNSC * objectMemory bytesPerOop * indexOfIRC).
  	indexOfIRC := indexOfIRC + 1.
  	self assert: (objectMemory isInOldSpace: nsSendCache).
  	self initializeNSSendCache: nsSendCache selector: selector numArgs: numArgs depth: depth.
  
  	self ssAllocateCallReg: SendNumArgsReg.
  
  	"This may leave the method receiver on the stack, which might not be the implicit receiver.
  	 But the lookup trampoline will establish an on-stack receiver once it locates it."
  	self marshallAbsentReceiverSendArguments: numArgs.
  
  	"Load the cache last so it is a fixed distance from the call."
+ 	self MoveUniqueCw: nsSendCache R: SendNumArgsReg.
- 	self MoveCw: nsSendCache R: SendNumArgsReg.
  	self CallNewspeakSend: (sendTable at: (numArgs min: NumSendTrampolines - 1)).
  
  	optStatus isReceiverResultRegLive: false.
  	self ssPushRegister: ReceiverResultReg.
  	^0!



More information about the Vm-dev mailing list