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

commits at source.squeak.org commits at source.squeak.org
Fri Dec 20 23:31:48 UTC 2013


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

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

Name: VMMaker.oscog-eem.566
Author: eem
Time: 20 December 2013, 3:28:56.681 pm
UUID: d9776d75-8481-4378-92ff-c099be4b4e97
Ancestors: VMMaker.oscog-eem.565

Check-in experiment with different entry code based on method's
methodClass.  Idea is to eliminate extra jump if methodClass infers
method can't have immediate instances.  Experiment looks like it
doesn't make enough difference to justify the complexity but the
code is worth recordingeven if it'll be discarded later.

Changes are:

refactor entryCode into CogObjectRepresentation>>
entryCodeForMethodClass:sendMissCall:

Add AlignmentNopsTo opcode to allow filling with nops up to the
no-check entry-point.

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

Item was added:
+ ----- Method: CoInterpreter>>methodClassOf: (in category 'message sending') -----
+ methodClassOf: methodPointer
+ 	<inline: true>
+ 	<option: #SpurObjectMemory>
+ 	<api>
+ 	^super methodClassOf: methodPointer!

Item was added:
+ ----- Method: CoInterpreter>>superclassOf: (in category 'message sending') -----
+ superclassOf: classPointer
+ 	<inline: true>
+ 	<option: #SpurObjectMemory>
+ 	<api>
+ 	^super superclassOf: classPointer!

Item was changed:
  ----- Method: CogIA32Compiler>>computeMaximumSize (in category 'generate machine code') -----
  computeMaximumSize
  	"Compute the maximum size for each opcode.  This allows jump offsets to
  	 be determined, provided that all backward branches are long branches."
  	"N.B.  The ^maxSize := N forms are to get around the compiler's long branch
  	 limits which are exceeded when each case jumps around the otherwise."
  	opcode caseOf: {
  		"Noops & Pseudo Ops"
  		[Label]					-> [^maxSize := 0].
  		[AlignmentNops]		-> [^maxSize := (operands at: 0) - 1].
+ 		[AlignmentNopsTo]		-> ["this is a hack but we get away with it because there are no forward branches over the entry code."
+ 									^maxSize := (operands at: 0) - address].
  		[Fill16]					-> [^maxSize := 2].
  		[Fill32]					-> [^maxSize := 4].
  		[FillFromWord]			-> [^maxSize := 4].
  		[Nop]					-> [^maxSize := 1].
  		"Specific Control/Data Movement"
  		[CDQ]					-> [^maxSize := 1].
  		[IDIVR]					-> [^maxSize := 2].
  		[IMULRR]				-> [^maxSize := 3].
  		[CPUID]					-> [^maxSize := 2].
  		[CMPXCHGAwR]			-> [^maxSize := 7].
  		[CMPXCHGMwrR]		-> [^maxSize := 8].
  		[LFENCE]				-> [^maxSize := 3].
  		[MFENCE]				-> [^maxSize := 3].
  		[SFENCE]				-> [^maxSize := 3].
  		[LOCK]					-> [^maxSize := 1].
  		[XCHGAwR]				-> [^maxSize := 6].
  		[XCHGMwrR]			-> [^maxSize := 7].
  		[XCHGRR]				-> [^maxSize := 2].
  		"Control"
  		[Call]					-> [^maxSize := 5].
  		[JumpR]					-> [^maxSize := 2].
  		[Jump]					-> [self resolveJumpTarget. ^maxSize := 5].
  		[JumpLong]				-> [self resolveJumpTarget. ^maxSize := 5].
  		[JumpZero]				-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpNonZero]			-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpNegative]			-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpNonNegative]		-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpOverflow]			-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpNoOverflow]		-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpCarry]				-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpNoCarry]			-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpLess]				-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpGreaterOrEqual]	-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpGreater]			-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpLessOrEqual]		-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpBelow]				-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpAboveOrEqual]		-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpAbove]			-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpBelowOrEqual]		-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpLongZero]			-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpLongNonZero]		-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpFPEqual]			-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpFPNotEqual]		-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpFPLess]			-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpFPGreaterOrEqual]	-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpFPGreater]			-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpFPLessOrEqual]	-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpFPOrdered]		-> [self resolveJumpTarget. ^maxSize := 6].
  		[JumpFPUnordered]		-> [self resolveJumpTarget. ^maxSize := 6].
  		[RetN]					-> [^maxSize := (operands at: 0) = 0
  													ifTrue: [1]
  													ifFalse: [3]].
  		"Arithmetic"
  		[AddCqR]		-> [^maxSize := (self isQuick: (operands at: 0))
  											ifTrue: [3]
  											ifFalse: [(self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]]].
  		[AndCqR]		-> [^maxSize := (self isQuick: (operands at: 0))
  											ifTrue: [3]
  											ifFalse: [(self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]]].
  		[CmpCqR]		-> [^maxSize := (self isQuick: (operands at: 0))
  											ifTrue: [3]
  											ifFalse: [(self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]]].
  		[OrCqR]			-> [^maxSize := (self isQuick: (operands at: 0))
  											ifTrue: [3]
  											ifFalse: [(self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]]].
  		[SubCqR]		-> [^maxSize := (self isQuick: (operands at: 0))
  											ifTrue: [3]
  											ifFalse: [(self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]]].
  		[AddCwR]		-> [^maxSize := (self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]].
  		[AndCwR]		-> [^maxSize := (self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]].
  		[CmpCwR]		-> [^maxSize := (self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]].
  		[OrCwR]		-> [^maxSize := (self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]].
  		[SubCwR]		-> [^maxSize := (self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]].
  		[XorCwR]		-> [^maxSize := (self concreteRegister: (operands at: 1)) = EAX
  														ifTrue: [5]
  														ifFalse: [6]].
  		[AddRR]			-> [^maxSize := 2].
  		[AndRR]			-> [^maxSize := 2].
  		[CmpRR]		-> [^maxSize := 2].
  		[OrRR]			-> [^maxSize := 2].
  		[XorRR]			-> [^maxSize := 2].
  		[SubRR]			-> [^maxSize := 2].
  		[NegateR]		-> [^maxSize := 2].
  		[LoadEffectiveAddressMwrR]
  						-> [^maxSize := ((self isQuick: (operands at: 0))
  											ifTrue: [3]
  											ifFalse: [6])
  										+ ((self concreteRegister: (operands at: 1)) = ESP
  											ifTrue: [1]
  											ifFalse: [0])].
  		[LogicalShiftLeftCqR]		-> [^maxSize := (operands at: 0) = 1
  														ifTrue: [2]
  														ifFalse: [3]].
  		[LogicalShiftRightCqR]	-> [^maxSize := (operands at: 0) = 1
  														ifTrue: [2]
  														ifFalse: [3]].
  		[ArithmeticShiftRightCqR]	-> [^maxSize := (operands at: 0) = 1
  														ifTrue: [2]
  														ifFalse: [3]].
  		[LogicalShiftLeftRR]		-> [self computeShiftRRSize].
  		[LogicalShiftRightRR]		-> [self computeShiftRRSize].
  		[ArithmeticShiftRightRR]	-> [self computeShiftRRSize].
  		[AddRdRd]				-> [^maxSize := 4].
  		[CmpRdRd]				-> [^maxSize := 4].
  		[SubRdRd]				-> [^maxSize := 4].
  		[MulRdRd]				-> [^maxSize := 4].
  		[DivRdRd]				-> [^maxSize := 4].
  		[SqrtRd]					-> [^maxSize := 4].
  		"Data Movement"
  		[MoveCqR]		-> [^maxSize := (operands at: 0) = 0 ifTrue: [2] ifFalse: [5]].
  		[MoveCwR]		-> [^maxSize := 5].
  		[MoveRR]		-> [^maxSize := 2].
  		[MoveRdRd]		-> [^maxSize := 4].
  		[MoveAwR]		-> [^maxSize := (self concreteRegister: (operands at: 1)) = EAX
  											ifTrue: [5]
  											ifFalse: [6]].
  		[MoveRAw]		-> [^maxSize := (self concreteRegister: (operands at: 0)) = EAX
  											ifTrue: [5]
  											ifFalse: [6]].
  		[MoveRMwr]		-> [^maxSize := ((self isQuick: (operands at: 1))
  											ifTrue: [3]
  											ifFalse: [6])
  										+ ((self concreteRegister: (operands at: 2)) = ESP
  											ifTrue: [1]
  											ifFalse: [0])].
  		[MoveRdM64r]	-> [^maxSize := ((self isQuick: (operands at: 1))
  											ifTrue: [5]
  											ifFalse: [8])
  										+ ((self concreteRegister: (operands at: 2)) = ESP
  											ifTrue: [1]
  											ifFalse: [0])].
  		[MoveMbrR]		-> [^maxSize := ((self isQuick: (operands at: 0))
  											ifTrue: [3]
  											ifFalse: [6])
  										+ ((self concreteRegister: (operands at: 1)) = ESP
  											ifTrue: [1]
  											ifFalse: [0])].
  		[MoveRMbr]		-> [^maxSize := ((self isQuick: (operands at: 1))
  											ifTrue: [3]
  											ifFalse: [6])
  										+ ((self concreteRegister: (operands at: 2)) = ESP
  											ifTrue: [1]
  											ifFalse: [0])].
  		[MoveM16rR]	-> [^maxSize := ((self isQuick: (operands at: 0))
  											ifTrue: [4]
  											ifFalse: [7])
  										+ ((self concreteRegister: (operands at: 1)) = ESP
  											ifTrue: [1]
  											ifFalse: [0])].
  		[MoveM64rRd]	-> [^maxSize := ((self isQuick: (operands at: 0))
  											ifTrue: [5]
  											ifFalse: [8])
  										+ ((self concreteRegister: (operands at: 1)) = ESP
  											ifTrue: [1]
  											ifFalse: [0])].
  		[MoveMwrR]		-> [^maxSize := ((self isQuick: (operands at: 0))
  											ifTrue: [3]
  											ifFalse: [6])
  										+ ((self concreteRegister: (operands at: 1)) = ESP
  											ifTrue: [1]
  											ifFalse: [0])].
  		[MoveXbrRR]	-> [self assert: (self concreteRegister: (operands at: 0)) ~= ESP.
  							^maxSize := (self concreteRegister: (operands at: 1)) = EBP
  											ifTrue: [5]
  											ifFalse: [4]].
  		[MoveRXbrR]	->	[self assert: (self concreteRegister: (operands at: 1)) ~= ESP.
  							^maxSize := (self concreteRegister: (operands at: 2)) = EBP
  											ifTrue: [4]
  											ifFalse: [3]].
  		[MoveXwrRR]	-> [self assert: (self concreteRegister: (operands at: 0)) ~= ESP.
  							^maxSize := (self concreteRegister: (operands at: 1)) = EBP
  											ifTrue: [4]
  											ifFalse: [3]].
  		[MoveRXwrR]	-> [self assert: (self concreteRegister: (operands at: 1)) ~= ESP.
  							^maxSize := (self concreteRegister: (operands at: 2)) = EBP
  											ifTrue: [4]
  											ifFalse: [3]].
  		[PopR]			-> [^maxSize := 1].
  		[PushR]			-> [^maxSize := 1].
  		[PushCw]		-> [^maxSize := 5].
  		[PrefetchAw]	-> [^maxSize := self hasSSEInstructions ifTrue: [7] ifFalse: [0]].
  		"Conversion"
  		[ConvertRRd]	-> [^maxSize := 4] }.
  	^0 "to keep C compiler quiet"!

Item was added:
+ ----- Method: CogIA32Compiler>>concretizeAlignmentNopsTo (in category 'generate machine code') -----
+ concretizeAlignmentNopsTo
+ 	<inline: true>
+ 	| targetAddress label |
+ 	<var: 'label'  type: #'AbstractInstruction *'>
+ 	label := self cCoerceSimple: (operands at: 1) to: #'AbstractInstruction *'.
+ 	targetAddress := label address + (operands at: 0).
+ 	self assert: targetAddress >= address.
+ 	machineCodeSize := targetAddress - address.
+ 	^self concretizeAlignmentNops!

Item was changed:
  ----- Method: CogIA32Compiler>>dispatchConcretize (in category 'generate machine code') -----
  dispatchConcretize
  	"Attempt to generate concrete machine code for the instruction at address.
  	 This is the inner dispatch of concretizeAt: actualAddress which exists only
  	 to get around the branch size limits in the SqueakV3 (blue book derived)
  	 bytecode set."
  	<returnTypeC: #void>
  	opcode caseOf: {
  		"Noops & Pseudo Ops"
  		[Label]				-> [^self concretizeLabel].
  		[AlignmentNops]	-> [^self concretizeAlignmentNops].
+ 		[AlignmentNopsTo]	-> [^self concretizeAlignmentNopsTo].
  		[Fill16]				-> [^self concretizeFill16].
  		[Fill32]				-> [^self concretizeFill32].
  		[FillFromWord]		-> [^self concretizeFillFromWord].
  		[Nop]				-> [^self concretizeNop].
  		"Specific Control/Data Movement"
  		[CDQ]					-> [^self concretizeCDQ].
  		[IDIVR]					-> [^self concretizeIDIVR].
  		[IMULRR]				-> [^self concretizeMulRR].
  		[CPUID]					-> [^self concretizeCPUID].
  		[CMPXCHGAwR]			-> [^self concretizeCMPXCHGAwR].
  		[CMPXCHGMwrR]		-> [^self concretizeCMPXCHGMwrR].
  		[LFENCE]				-> [^self concretizeFENCE: 5].
  		[MFENCE]				-> [^self concretizeFENCE: 6].
  		[SFENCE]				-> [^self concretizeFENCE: 7].
  		[LOCK]					-> [^self concretizeLOCK].
  		[XCHGAwR]				-> [^self concretizeXCHGAwR].
  		[XCHGMwrR]			-> [^self concretizeXCHGMwrR].
  		[XCHGRR]				-> [^self concretizeXCHGRR].
  		"Control"
  		[Call]					-> [^self concretizeCall].
  		[JumpR]					-> [^self concretizeJumpR].
  		[JumpLong]				-> [^self concretizeJumpLong].
  		[JumpLongZero]		-> [^self concretizeConditionalJumpLong: 16r4].
  		[JumpLongNonZero]	-> [^self concretizeConditionalJumpLong: 16r5].
  		[Jump]					-> [^self concretizeJump].
  		"Table B-1 Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 1: Basic Architecture"
  		[JumpZero]				-> [^self concretizeConditionalJump: 16r4].
  		[JumpNonZero]			-> [^self concretizeConditionalJump: 16r5].
  		[JumpNegative]			-> [^self concretizeConditionalJump: 16r8].
  		[JumpNonNegative]		-> [^self concretizeConditionalJump: 16r9].
  		[JumpOverflow]			-> [^self concretizeConditionalJump: 16r0].
  		[JumpNoOverflow]		-> [^self concretizeConditionalJump: 16r1].
  		[JumpCarry]			-> [^self concretizeConditionalJump: 16r2].
  		[JumpNoCarry]			-> [^self concretizeConditionalJump: 16r3].
  		[JumpLess]				-> [^self concretizeConditionalJump: 16rC].
  		[JumpGreaterOrEqual]	-> [^self concretizeConditionalJump: 16rD].
  		[JumpGreater]			-> [^self concretizeConditionalJump: 16rF].
  		[JumpLessOrEqual]		-> [^self concretizeConditionalJump: 16rE].
  		[JumpBelow]			-> [^self concretizeConditionalJump: 16r2].
  		[JumpAboveOrEqual]	-> [^self concretizeConditionalJump: 16r3].
  		[JumpAbove]			-> [^self concretizeConditionalJump: 16r7].
  		[JumpBelowOrEqual]	-> [^self concretizeConditionalJump: 16r6].
  		[JumpFPEqual]				-> [^self concretizeConditionalJump: 16r4].
  		[JumpFPNotEqual]			-> [^self concretizeConditionalJump: 16r5].
  		[JumpFPLess]				-> [^self concretizeConditionalJump: 16r2].
  		[JumpFPGreaterOrEqual]	-> [^self concretizeConditionalJump: 16r3].
  		[JumpFPGreater]			-> [^self concretizeConditionalJump: 16r7].
  		[JumpFPLessOrEqual]		-> [^self concretizeConditionalJump: 16r6].
  		[JumpFPOrdered]			-> [^self concretizeConditionalJump: 16rB].
  		[JumpFPUnordered]			-> [^self concretizeConditionalJump: 16rA].
  		[RetN]						-> [^self concretizeRetN].
  		"Arithmetic"
  		[AddCqR]					-> [^self concretizeAddCqR].
  		[AddCwR]					-> [^self concretizeAddCwR].
  		[AddRR]						-> [^self concretizeAddRR].
  		[AddRdRd]					-> [^self concretizeSEE2OpRdRd: 16r58].
  		[AndCqR]					-> [^self concretizeAndCqR].
  		[AndCwR]					-> [^self concretizeAndCwR].
  		[AndRR]						-> [^self concretizeAndRR].
  		[CmpCqR]					-> [^self concretizeCmpCqR].
  		[CmpCwR]					-> [^self concretizeCmpCwR].
  		[CmpRR]					-> [^self concretizeCmpRR].
  		[CmpRdRd]					-> [^self concretizeCmpRdRd].
  		[DivRdRd]					-> [^self concretizeSEE2OpRdRd: 16r5E].
  		[MulRdRd]					-> [^self concretizeSEE2OpRdRd: 16r59].
  		[OrCqR]						-> [^self concretizeOrCqR].
  		[OrCwR]					-> [^self concretizeOrCwR].
  		[OrRR]						-> [^self concretizeOrRR].
  		[SubCqR]					-> [^self concretizeSubCqR].
  		[SubCwR]					-> [^self concretizeSubCwR].
  		[SubRR]						-> [^self concretizeSubRR].
  		[SubRdRd]					-> [^self concretizeSEE2OpRdRd: 16r5C].
  		[SqrtRd]						-> [^self concretizeSqrtRd].
  		[XorCwR]						-> [^self concretizeXorCwR].
  		[XorRR]							-> [^self concretizeXorRR].
  		[NegateR]						-> [^self concretizeNegateR].
  		[LoadEffectiveAddressMwrR]	-> [^self concretizeLoadEffectiveAddressMwrR].
  		[ArithmeticShiftRightCqR]		-> [^self concretizeArithmeticShiftRightCqR].
  		[LogicalShiftRightCqR]			-> [^self concretizeLogicalShiftRightCqR].
  		[LogicalShiftLeftCqR]			-> [^self concretizeLogicalShiftLeftCqR].
  		[ArithmeticShiftRightRR]			-> [^self concretizeArithmeticShiftRightRR].
  		[LogicalShiftLeftRR]				-> [^self concretizeLogicalShiftLeftRR].
  		"Data Movement"
  		[MoveCqR]			-> [^self concretizeMoveCqR].
  		[MoveCwR]			-> [^self concretizeMoveCwR].
  		[MoveRR]			-> [^self concretizeMoveRR].
  		[MoveAwR]			-> [^self concretizeMoveAwR].
  		[MoveRAw]			-> [^self concretizeMoveRAw].
  		[MoveMbrR]			-> [^self concretizeMoveMbrR].
  		[MoveRMbr]			-> [^self concretizeMoveRMbr].
  		[MoveM16rR]		-> [^self concretizeMoveM16rR].
  		[MoveM64rRd]		-> [^self concretizeMoveM64rRd].
  		[MoveMwrR]		-> [^self concretizeMoveMwrR].
  		[MoveXbrRR]		-> [^self concretizeMoveXbrRR].
  		[MoveRXbrR]		-> [^self concretizeMoveRXbrR].
  		[MoveXwrRR]		-> [^self concretizeMoveXwrRR].
  		[MoveRXwrR]		-> [^self concretizeMoveRXwrR].
  		[MoveRMwr]		-> [^self concretizeMoveRMwr].
  		[MoveRdM64r]		-> [^self concretizeMoveRdM64r].
  		[PopR]				-> [^self concretizePopR].
  		[PushR]				-> [^self concretizePushR].
  		[PushCw]			-> [^self concretizePushCw].
  		[PrefetchAw]		-> [^self concretizePrefetchAw].
  		"Conversion"
  		[ConvertRRd]		-> [^self concretizeConvertRRd] }!

Item was changed:
  ----- Method: CogIA32Compiler>>machineCodeBytes (in category 'generate machine code') -----
  machineCodeBytes
  	"Answer the maximum number of bytes of machine code generated for any abstract instruction.
+ 	 e.g. lock movsd  0x400(%esp),%xmm4 => f0 f2 0f 10 a4 24 00 04 00 00
+ 	 But with the new entry code, AlignmentNopsTo may generate 13 bytes of nops."
+ 	^14 "10"!
- 	 e.g. lock movsd  0x400(%esp),%xmm4 => f0 f2 0f 10 a4 24 00 04 00 00"
- 	^10!

Item was added:
+ ----- Method: CogObjectRepresentation>>entryCodeForMethodClass:sendMissCall: (in category 'in-line cacheing') -----
+ entryCodeForMethodClass: methodClassOrNil sendMissCall: theSendMissCall
+ 	"Generate the method-entry code.  Extract the inline cache tag for the object
+ 	 in ReceiverResultReg into TempReg and compare it against ClassReg. The inline
+ 	 cache tag for a given object is the value loaded in inline caches to distinguish
+ 	 objects of different classes."
+ 	<var: #sendMissCall type: #'AbstractInstruction *'>
+ 	| entryLabel |
+ 	<var: #entryLabel type: #'AbstractInstruction *'>
+ 	entryLabel := self getInlineCacheClassTagFrom: ReceiverResultReg into: TempReg.
+ 	cogit CmpR: ClassReg R: TempReg.
+ 	cogit JumpNonZero: theSendMissCall.
+ 	^entryLabel!

Item was added:
+ ----- Method: CogObjectRepresentationFor32BitSpur>>entryCodeForMethodClass:sendMissCall: (in category 'in-line cacheing') -----
+ entryCodeForMethodClass: methodClassOrNil sendMissCall: theSendMissCall
+ 	"Generate the method-entry code.  Extract the inline cache tag for the object
+ 	 in ReceiverResultReg into TempReg and compare it against ClassReg. The inline
+ 	 cache tag for a given object is the value loaded in inline caches to distinguish
+ 	 objects of different classes.  In Spur this is either the tags for immediates, (with
+ 	 1 & 3 collapsed to 1 for SmallIntegers, and 2 collapsed to 0 for Characters), or
+ 	 the receiver's classIndex.  Try and special-case sends to immediates and sends
+ 	 to non-immediates."
+ 	<var: #sendMissCall type: #'AbstractInstruction *'>
+ 	| entryLabel characterClass smallIntegerClass |
+ 	<var: #entryLabel type: #'AbstractInstruction *'>
+ 	"special cases"
+ 	methodClassOrNil ~= objectMemory nilObject ifTrue:
+ 		[characterClass := objectMemory classCharacter.
+ 		 smallIntegerClass := objectMemory classSmallInteger.
+ 
+ 		 (methodClassOrNil = characterClass
+ 		  or: [methodClassOrNil = smallIntegerClass]) ifTrue:
+ 			["methodClass is an immediate class.  immediate classes can't
+ 			  have subclasses so test for the immediate tag directly."
+ 			 cogit AlignmentNops: (BytesPerWord max: self entryAlignment).
+ 			 entryLabel := cogit Label.
+ 			 cogit MoveR: ReceiverResultReg R: TempReg.
+ 			 cogit AndCq: objectMemory tagMask R: TempReg.
+ 			 cogit CmpCq: (methodClassOrNil = characterClass
+ 								ifTrue: [objectMemory characterTag]
+ 								ifFalse: [objectMemory smallIntegerTag])
+ 					R: TempReg.
+ 			 cogit JumpNonZero: theSendMissCall.
+ 			 cogit AlignmentNopsTo: cogit noCheckEntryOffset from: cogit methodLabel.
+ 			 ^entryLabel].
+ 
+ 		 (self methodClass: methodClassOrNil isSuperclassOf: characterClass or: smallIntegerClass) ifFalse:
+ 			["methodClass can't have immediate general instances, so fail on immediate."
+ 			 cogit AlignmentNops: (BytesPerWord max: self entryAlignment).
+ 			 entryLabel := cogit Label.
+ 			 cogit MoveR: ReceiverResultReg R: TempReg.
+ 			 cogit AndCq: objectMemory tagMask R: TempReg.
+ 			 cogit JumpNonZero: theSendMissCall.
+ 			 self flag: #endianness.
+ 			 "Get least significant half of header word in destReg"
+ 			 cogit MoveMw: 0 r: ReceiverResultReg R: TempReg.
+ 			 cogit AndCq: objectMemory classIndexMask R: TempReg.
+ 			 cogit CmpR: ClassReg R: TempReg.
+ 			 cogit JumpNonZero: theSendMissCall.
+ 			 cogit AlignmentNopsTo: cogit noCheckEntryOffset from: cogit methodLabel.
+ 			 ^entryLabel]].
+ 
+ 	"generic case, could be either immediate or non-immediate."
+ 	entryLabel := self getInlineCacheClassTagFrom: ReceiverResultReg into: TempReg.
+ 	cogit CmpR: ClassReg R: TempReg.
+ 	cogit JumpNonZero: theSendMissCall.
+ 	^entryLabel!

Item was changed:
  ----- Method: CogObjectRepresentationFor32BitSpur>>getInlineCacheClassTagFrom:into: (in category 'compile abstract instructions') -----
  getInlineCacheClassTagFrom: sourceReg into: destReg
  	"Extract the inline cache tag for the object in sourceReg into destReg. The inline
  	 cache tag for a given object is the value loaded in inline caches to distinguish
  	 objects of different classes.  In Spur this is either the tags for immediates, (with
  	 1 & 3 collapsed to 1 for SmallIntegers, and 2 collapsed to 0 for Characters), or
  	 the receiver's classIndex.  Generate something like this:
  		Lentry:
  			movl rSource, rDest
  			andl $0x3, rDest
  			jz LnotImm
  			andl $1, rDest
  			j Lcmp
  		LnotImm:
  			movl 0(%edx), rDest
  			andl $0x3fffff, rDest
  		Lcmp:
  	 At least on a 2.2GHz Intel Core i7 it is slightly faster,
  	 136m sends/sec vs 130m sends/sec for nfib in tinyBenchmarks, than
  		Limm:
  			andl $0x1, rDest
  			j Lcmp
  		Lentry:
  			movl rSource, rDest
  			andl $0x3, rDest
  			jnz Limm
  			movl 0(%edx), rDest
  			andl $0x3fffff, rDest
  		Lcmp:
  	"
  	| immLabel jumpNotImm entryLabel jumpCompare |
  	<var: #immLabel type: #'AbstractInstruction *'>
  	<var: #jumpNotImm type: #'AbstractInstruction *'>
  	<var: #entryLabel type: #'AbstractInstruction *'>
  	<var: #jumpCompare type: #'AbstractInstruction *'>
  	true
  		ifTrue:
+ 			[cogit AlignmentNops: (BytesPerWord max: self entryAlignment).
- 			[cogit AlignmentNops: (BytesPerWord max: 8).
  			 entryLabel := cogit Label.
  			 cogit MoveR: sourceReg R: destReg.
  			 cogit AndCq: objectMemory tagMask R: destReg.
  			 jumpNotImm := cogit JumpZero: 0.
  			 cogit AndCq: 1 R: destReg.
  			 jumpCompare := cogit Jump: 0.
  			 "Get least significant half of header word in destReg"
  			 self flag: #endianness.
  			 jumpNotImm jmpTarget:
  				(cogit MoveMw: 0 r: sourceReg R: destReg).
  			 jumpCompare jmpTarget:
  				(cogit AndCq: objectMemory classIndexMask R: destReg)]
  		ifFalse:
  			[cogit AlignmentNops: BytesPerWord.
  			 immLabel := cogit Label.
  			 cogit AndCq: 1 R: destReg.
  			 jumpCompare := cogit Jump: 0.
  			 cogit AlignmentNops: BytesPerWord.
  			 entryLabel := cogit Label.
  			 cogit MoveR: sourceReg R: destReg.
  			 cogit AndCq: objectMemory tagMask R: destReg.
  			 cogit JumpNonZero: immLabel.
  			 self flag: #endianness.
  			 "Get least significant half of header word in destReg"
  			 cogit MoveMw: 0 r: sourceReg R: destReg.
  			 cogit AndCq: objectMemory classIndexMask R: destReg.
  			 jumpCompare jmpTarget: cogit Label].
  	^entryLabel!

Item was added:
+ ----- Method: CogObjectRepresentationForSpur>>entryAlignment (in category 'in-line cacheing') -----
+ entryAlignment
+ 	"At least on Core i7, 8 is no better than 4, and 4 gives more compact code."
+ 	^4 "8"!

Item was added:
+ ----- Method: CogObjectRepresentationForSpur>>methodClass:isSuperclassOf:or: (in category 'in-line cacheing') -----
+ methodClass: methodClass isSuperclassOf: firstImmediateClass or: secondImmediateClass
+ 	| classAOrNil classBOrNil nilObj |
+ 	classAOrNil := firstImmediateClass.
+ 	classBOrNil := secondImmediateClass.
+ 	nilObj := objectMemory nilObject.
+ 	[classAOrNil = nilObj
+ 		ifTrue:
+ 			[classBOrNil = nilObj ifTrue:
+ 				[^false]]
+ 		ifFalse:
+ 			[(classAOrNil := objectMemory superclassOf: classAOrNil) = methodClass ifTrue:
+ 				[^true]].
+ 	 classBOrNil = nilObj
+ 		ifTrue:
+ 			[classAOrNil = nilObj ifTrue:
+ 				[^false]]
+ 		ifFalse:
+ 			[(classBOrNil := objectMemory superclassOf: classBOrNil) = methodClass ifTrue:
+ 				[^true]]] repeat!

Item was changed:
  SharedPool subclass: #CogRTLOpcodes
  	instanceVariableNames: ''
+ 	classVariableNames: 'AddCqR AddCwR AddRR AddRdRd AlignmentNops AlignmentNopsTo AndCqR AndCwR AndRR Arg0Reg Arg1Reg ArithmeticShiftRightCqR ArithmeticShiftRightRR Call ClassReg CmpCqR CmpCwR CmpRR CmpRdRd ConvertRRd DPFPReg0 DPFPReg1 DPFPReg2 DPFPReg3 DPFPReg4 DPFPReg5 DPFPReg6 DPFPReg7 DivRdRd FPReg Fill16 Fill32 Fill8 FillBytesFrom FillFromWord FirstJump FirstShortJump GPRegMax GPRegMin Jump JumpAbove JumpAboveOrEqual JumpBelow JumpBelowOrEqual JumpCarry JumpFPEqual JumpFPGreater JumpFPGreaterOrEqual JumpFPLess JumpFPLessOrEqual JumpFPNotEqual JumpFPOrdered JumpFPUnordered JumpGreater JumpGreaterOrEqual JumpLess JumpLessOrEqual JumpLong JumpLongNonZero JumpLongZero JumpNegative JumpNoCarry JumpNoOverflow JumpNonNegative JumpNonZero JumpOverflow JumpR JumpZero Label LastJump LastRTLCode LinkReg LoadEffectiveAddressMwrR LoadEffectiveAddressXowrR LogicalShiftLeftCqR LogicalShiftLeftRR LogicalShiftRightCqR LogicalShiftRightRR MoveAbR MoveAwR MoveC32R MoveC64R MoveCqR MoveCwR MoveM16rR MoveM32rR MoveM64rRd MoveMbrR MoveMwrR MoveRAw MoveRM16r MoveRM32r MoveRMbr MoveRMwr MoveRR MoveRX16rR MoveRX32rR MoveRXbrR MoveRXowr MoveRXwrR MoveRdM64r MoveRdRd MoveX16rRR MoveX32rRR MoveXbrRR MoveXowrR MoveXwrRR MulCqR MulCwR MulRR MulRdRd NegateR Nop OrCqR OrCwR OrRR PopR PrefetchAw PushCw PushR ReceiverResultReg RetN SPReg SendNumArgsReg SqrtRd SubCqR SubCwR SubRR SubRdRd TempReg XorCqR XorCwR XorRR'
- 	classVariableNames: 'AddCqR AddCwR AddRR AddRdRd AlignmentNops AndCqR AndCwR AndRR Arg0Reg Arg1Reg ArithmeticShiftRightCqR ArithmeticShiftRightRR Call ClassReg CmpCqR CmpCwR CmpRR CmpRdRd ConvertRRd DPFPReg0 DPFPReg1 DPFPReg2 DPFPReg3 DPFPReg4 DPFPReg5 DPFPReg6 DPFPReg7 DivRdRd FPReg Fill16 Fill32 Fill8 FillBytesFrom FillFromWord FirstJump FirstShortJump GPRegMax GPRegMin Jump JumpAbove JumpAboveOrEqual JumpBelow JumpBelowOrEqual JumpCarry JumpFPEqual JumpFPGreater JumpFPGreaterOrEqual JumpFPLess JumpFPLessOrEqual JumpFPNotEqual JumpFPOrdered JumpFPUnordered JumpGreater JumpGreaterOrEqual JumpLess JumpLessOrEqual JumpLong JumpLongNonZero JumpLongZero JumpNegative JumpNoCarry JumpNoOverflow JumpNonNegative JumpNonZero JumpOverflow JumpR JumpZero Label LastJump LastRTLCode LinkReg LoadEffectiveAddressMwrR LogicalShiftLeftCqR LogicalShiftLeftRR LogicalShiftRightCqR LogicalShiftRightRR MoveAbR MoveAwR MoveC32R MoveC64R MoveCqR MoveCwR MoveM16rR MoveM64rRd MoveMbrR MoveMwrR MoveRAw MoveRM16r MoveRMbr MoveRMwr MoveRR MoveRX16rR MoveRXbrR MoveRXowr MoveRXwrR MoveRdM64r MoveRdRd MoveX16rRR MoveXbrRR MoveXowrR MoveXwrRR MulCqR MulCwR MulRR MulRdRd NegateR Nop OrCqR OrCwR OrRR PopR PrefetchAw PushCw PushR ReceiverResultReg RetN SPReg SendNumArgsReg SqrtRd SubCqR SubCwR SubRR SubRdRd TempReg XorCqR XorCwR XorRR'
  	poolDictionaries: ''
  	category: 'VMMaker-JIT'!
  
  !CogRTLOpcodes commentStamp: '<historical>' prior: 0!
  I am a pool for the Register-Transfer-Language to which Cog compiles.  I define unique integer values for all RTL opcodes and abstract registers.  See CogAbstractInstruction for instances of instructions with the opcodes that I define.!

Item was changed:
  ----- Method: CogRTLOpcodes class>>initialize (in category 'class initialization') -----
  initialize
  	"Abstract opcodes are a compound of a one word operation specifier and zero or more operand type specifiers.
  	 e.g. MoveRR is the Move opcode with two register operand specifiers and defines a move register to
  	 register instruction from operand 0 to operand 1.  The word and register size is assumed to be either 32-bits on
  	 a 32-bit architecture or 64-bits on a 64-bit architecture.  
  	The operand specifiers are
  		R		- general purpose register
  		Rd		- double-precision floating-point register
  		Cq		- a quick constant that can be encoded in the minimum space possible.
  		Cw		- a constant with word size where word is the default operand size for the Smalltalk VM, 32-bits
  				  for a 32-bit VM, 64-bits for a 64-bit VM.  The generated constant must occupy the default number
  				  of bits.  This allows e.g. a garbage collector to update the value without invalidating the code.
  		C32	- a constant with 32 bit size.  The generated constant must occupy 32 bits.
  		C64	- a constant with 64 bit size.  The generated constant must occupy 64 bits.
+ 		Aw		- memory word at an absolute address
+ 		Ab		- memory byte at an absolute address
- 		Aw		- memory word with an absolute address
- 		Ab		- memory byte with an absolute address
  		Mwr	- memory word whose address is at a constant offset from an address in a register
  		Mbr		- memory byte whose address is at a constant offset from an address in a register
  		M16r	- memory 16-bit halfword whose address is at a constant offset from an address in a register
  		M32r	- memory 32-bit halfword whose address is at a constant offset from an address in a register
  		M64r	- memory 64-bit doubleword whose address is at a constant offset from an address in a register
  		XbrR	- memory word whose address is r * byte size away from an address in a register
  		X16rR	- memory word whose address is r * (2 bytes size) away from an address in a register
  		XwrR	- memory word whose address is r * word size away from an address in a register
  		XowrR	- memory word whose address is (r * word size) + o away from an address in a register (scaled indexed)
  
  	An alternative would be to decouple opcodes from operands, e.g.
  		Move := 1. Add := 2. Sub := 3...
  		RegisterOperand := 1. ConstantQuickOperand := 2. ConstantWordOperand := 3...
  	But not all combinations make sense and even fewer are used so we stick with the simple compound approach.
  
  	The assumption is that comparison and arithmetic instructions set condition codes and that move instructions
  	leave the condition codes unaffected.  In particular LoadEffectiveAddressMwrR does not set condition codes
  	although it can be used to do arithmetic.
  
  	Not all of the definitions in opcodeDefinitions below are implemented.  In particular we do not implement the
  	 XowrR scaled index addressing mode since it requires 4 operands.
  
  	Note that there are no generic division instructions defined, but a processor may define some."
  
  	"CogRTLOpcodes initialize.
  	 CogAbstractInstruction allSubclasses do: [:sc| sc initialize]"
  
  	| opcodeNames refs |
  	FPReg := -1.
  	SPReg := -2.
  	ReceiverResultReg := GPRegMax := -3.
  	TempReg := -4.
  	ClassReg := -5.
  	SendNumArgsReg := -6.
  	Arg0Reg := -7.
  	Arg1Reg := GPRegMin := -8.
  
  	DPFPReg0 := -9.
  	DPFPReg1 := -10.
  	DPFPReg2 := -11.
  	DPFPReg3 := -12.
  	DPFPReg4 := -13.
  	DPFPReg5 := -14.
  	DPFPReg6 := -15.
  	DPFPReg7 := -16.
  	
  	LinkReg := -17.
  
+ 	opcodeNames := #("No ops & Pseudo Ops"
- 	opcodeNames := #("Noops & Pseudo Ops"
  						Label
+ 						AlignmentNops		"output nops until a byte aligned on an operand 0 boundary"
+ 						AlignmentNopsTo	"output nops until just before the address in operand 0 + operand 1"
+ 						FillBytesFrom		"output operand 0's worth of bytes from the address in operand 1"
+ 						Fill8					"output a byte's worth of bytes with operand 0"
+ 						Fill16				"output two byte's worth of bytes with operand 0"
+ 						Fill32				"output four byte's worth of bytes with operand 0"
+ 						FillFromWord		"output BytesPerWord's worth of bytes with operand 0 + operand 1"
- 						AlignmentNops
- 						FillBytesFrom	"output operand 0's worth of bytes from the address in operand 1"
- 						Fill8				"output a byte's worth of bytes with operand 0"
- 						Fill16			"output two byte's worth of bytes with operand 0"
- 						Fill32			"output four byte's worth of bytes with operand 0"
- 						FillFromWord	"output BytesPerWord's worth of bytes with operand 0 + operand 1"
  						Nop
  
  						"Control"
  						Call
  						RetN
  						JumpR				"Not a regular jump, i.e. not pc dependent."
  
  						"N.B.  Jumps are contiguous.  Long jumps are contigiuous within them.  See FirstJump et al below"
  						JumpLong
  						JumpLongZero		"a.k.a. JumpLongEqual"
  						JumpLongNonZero	"a.k.a. JumpLongNotEqual"
  						Jump
  						JumpZero			"a.k.a. JumpEqual"
  						JumpNonZero		"a.k.a. JumpNotEqual"
  						JumpNegative
  						JumpNonNegative
  						JumpOverflow
  						JumpNoOverflow
  						JumpCarry
  						JumpNoCarry
  						JumpLess			"signed"
  						JumpGreaterOrEqual
  						JumpGreater
  						JumpLessOrEqual
  						JumpBelow			"unsigned"
  						JumpAboveOrEqual
  						JumpAbove
  						JumpBelowOrEqual
  
  						JumpFPEqual
  						JumpFPNotEqual
  						JumpFPLess
  						JumpFPLessOrEqual
  						JumpFPGreater
  						JumpFPGreaterOrEqual
  						JumpFPOrdered
  						JumpFPUnordered
  
  						"Data Movement; destination is always last operand"
  						MoveRR
  						MoveAwR
  						MoveRAw
  						MoveAbR
  						MoveMwrR MoveRMwr MoveXwrRR MoveRXwrR MoveXowrR MoveRXowr
  						MoveM16rR MoveRM16r MoveX16rRR MoveRX16rR
  						MoveM32rR MoveRM32r MoveX32rRR MoveRX32rR
  						MoveMbrR MoveRMbr MoveXbrRR MoveRXbrR
  						MoveCqR MoveCwR MoveC32R MoveC64R
  						MoveRdRd MoveM64rRd MoveRdM64r
  						PopR PushR PushCw
  						PrefetchAw
  
  						"Arithmetic; destination is always last operand except Cmp; CmpXR is SubRX with no update of result"
  						LoadEffectiveAddressMwrR LoadEffectiveAddressXowrR "Variants of add/multiply"
  						NegateR "2's complement negation"
  						ArithmeticShiftRightCqR ArithmeticShiftRightRR
  						LogicalShiftRightCqR LogicalShiftRightRR
  						LogicalShiftLeftCqR LogicalShiftLeftRR
  
  						CmpRR AddRR SubRR AndRR OrRR XorRR MulRR
  						CmpCqR AddCqR SubCqR AndCqR OrCqR XorCqR MulCqR
  						CmpCwR AddCwR SubCwR AndCwR OrCwR XorCwR MulCwR
  
  						CmpRdRd AddRdRd SubRdRd MulRdRd DivRdRd SqrtRd
  
  						"Conversion"
  						ConvertRRd
  
  						LastRTLCode).
  
  	"Magic auto declaration. Add to the classPool any new variables and nuke any obsolete ones, and assign values"
  	"Find the variables directly referenced by this method"
  	refs := (thisContext method literals select: [:l| l isVariableBinding and: [classPool includesKey: l key]]) collect:
  				[:ea| ea key].
  	"Move to Undeclared any opcodes in classPool not in opcodes or this method."
  	(classPool keys reject: [:k| (opcodeNames includes: k) or: [refs includes: k]]) do:
  		[:k|
  		Undeclared declare: k from: classPool].
  	"Declare as class variables and number elements of opcodeArray above"
  	opcodeNames withIndexDo:
  		[:classVarName :value|
  		self classPool
  			declare: classVarName from: Undeclared;
  			at: classVarName put: value].
  
  	"For CogAbstractInstruction>>isJump etc..."
  	FirstJump := JumpLong.
  	LastJump := JumpFPUnordered.
  	FirstShortJump := Jump!

Item was added:
+ ----- Method: Cogit>>AlignmentNopsTo:from: (in category 'abstract instructions') -----
+ AlignmentNopsTo: offset from: label
+ 	<inline: true>
+ 	<returnTypeC: #'AbstractInstruction *'>
+ 	^self gen: AlignmentNopsTo operand: offset operand: label!

Item was changed:
  ----- Method: Cogit>>compileEntry (in category 'compile abstract instructions') -----
  compileEntry
  	"The entry code to a method checks that the class of the current receiver matches
  	 that in the inline cache.  Other non-obvious elements are that its alignment must be
  	 different from the alignment of the noCheckEntry so that the method map machinery
  	 can distinguish normal and super sends (super sends bind to the noCheckEntry).
  	 In Newspeak we also need to distinguish dynSuperSends from normal and super
+ 	 sends (which is done by their alignment) and so bind the preceeding nop (on x86
+ 	 there happens to be one anyway)."
- 	 and so bind a the preceeding nop (on x86 there happens to be one anyway)."
  
  	self cppIf: NewspeakVM ifTrue:
  		[self Nop. "1st nop differentiates dynSuperEntry from no-check entry if using nextMethod"
  		 dynSuperEntry := self Nop].
+ 	entry := objectRepresentation
+ 				entryCodeForMethodClass: (methodObj
+ 												ifNil: [objectMemory nilObject]
+ 												ifNotNil: [coInterpreter methodClassOf: methodObj])
+ 				sendMissCall: sendMissCall.
- 	entry := objectRepresentation getInlineCacheClassTagFrom: ReceiverResultReg into: TempReg.
- 	self CmpR: ClassReg R: TempReg.
- 	self JumpNonZero: sendMissCall.
  	noCheckEntry := self Label.
  	self recordSendTrace ifTrue:
  		[self CallRT: ceTraceLinkedSendTrampoline]!

Item was added:
+ ----- Method: Cogit>>methodLabel (in category 'accessing') -----
+ methodLabel
+ 	<cmacro: '() methodLabel'>
+ 	^methodLabel!

Item was added:
+ ----- Method: Spur32BitCoMemoryManager>>smallIntegerTag (in category 'object access') -----
+ smallIntegerTag
+ 	<api>
+ 	^1!

Item was added:
+ ----- Method: Spur32BitCoMemoryManager>>superclassOf: (in category 'cogit support') -----
+ superclassOf: classPointer
+ 	<doNotGenerate>
+ 	^coInterpreter superclassOf: classPointer!

Item was changed:
  ----- Method: SpurMemoryManager>>classCharacter (in category 'plugin support') -----
  classCharacter
+ 	<api>
  	^self splObj: ClassCharacter!



More information about the Vm-dev mailing list