[Vm-dev] VM Maker: VMMaker.oscog-eem.1755.mcz
Eliot Miranda
eliot.miranda at gmail.com
Thu Mar 31 21:29:55 UTC 2016
On Thu, Mar 31, 2016 at 2:27 PM, <commits at source.squeak.org> wrote:
>
> Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
> http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1755.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-eem.1755
> Author: eem
> Time: 1 January 1970, 2:26:33.237515 pm
>
^^Ouch^^ !! That's what one gets for living on the bleeding edge :-/
> UUID: adcfc67f-a856-48b8-aef2-71ff6275a903
> Ancestors: VMMaker.oscog-nice.1754
>
> Spur Cogit:
> Add a compile-time flag, CheckRememberedInTrampoline, that controls
> whether the remembered check is generated in-line or in the trampoline. If
> checked in the trampoline and on 64-bits use one memory access to get the
> header and share the access between the IMMUTABILITY check and the
> rememberedBit check. Factor out the rememberedBit check into its own
> method.
>
> The default leaves the code unchanged. I doubt that the option will
> improve anything significantly; measuring the generated code in the
> simulator the option saves only 0.6% of generated code. But it's so lovely
> being able to explore the question in a couple of hours instead of at least
> a day or two in C.
>
> Here's the data: CRIT=CheckRememberedInTrampoline; this methid is the last
> method generated in a listener image before it prompts the user:
> IMMTABILITY: 16r93F80 <-> 16r940E8: method: 16rC582F8 prim 117
> selector: 16r6D12C8 primRead:into:startingAt:count:
> IMMTABILICRIT: 16r93250 <-> 16r933B8: method: 16rC582F8 prim 117
> selector: 16r6D12C8 primRead:into:startingAt:count:
> VANILLA: 16r91C00 <-> 16r91D68: method: 16rC582F8 prim
> 117 selector: 16r6D12C8 primRead:into:startingAt:count:
> VANILLACRIT: 16r90D80 <-> 16r90EE8: method: 16rC582F8 prim 117
> selector: 16r6D12C8 primRead:into:startingAt:count:
> 16r93F80 - 16r93250 / 16r93250 * 100.0 0.5601422920704027
> 16r91C00 - 16r90D80 / 16r90D80 * 100.0 0.6256742179072277
>
> And interestingly IMMUTABILITY adds only 1.5% to the code bulk; writes are
> rare.
> 16r93F80 - 16r91C00 / 16r91C00 * 100.0 1.5222984562607205
> 16r93250 - 16r90D80 / 16r90D80 * 100.0 1.5884573894282634
>
> =============== Diff against VMMaker.oscog-nice.1754 ===============
>
> Item was added:
> + ----- Method: CogObjectRepresentation class>>initializeMiscConstants (in
> category 'initialization') -----
> + initializeMiscConstants
> + "Override to avoid inheriting (and hence repeating) VMClass
> class>>initializeMiscConstants.
> + Subclasses that have misc constants to initialize will override
> further."!
>
> Item was changed:
> CogObjectRepresentation subclass: #CogObjectRepresentationForSpur
> instanceVariableNames: 'ceScheduleScavengeTrampoline
> ceSmallActiveContextInMethodTrampoline
> ceSmallActiveContextInBlockTrampoline
> ceLargeActiveContextInMethodTrampoline
> ceLargeActiveContextInBlockTrampoline ceStoreCheckContextReceiverTrampoline
> ceStoreTrampolines'
> + classVariableNames: 'CheckRememberedInTrampoline
> NumStoreTrampolines'
> - classVariableNames: 'NumStoreTrampolines'
> poolDictionaries: 'VMBytecodeConstants VMSqueakClassIndices'
> category: 'VMMaker-JIT'!
>
> Item was added:
> + ----- Method: CogObjectRepresentationForSpur
> class>>initializeMiscConstants (in category 'initialization') -----
> + initializeMiscConstants
> + CheckRememberedInTrampoline := initializationOptions at:
> #CheckRememberedInTrampoline ifAbsent: [false]!
>
> Item was added:
> + ----- Method:
> CogObjectRepresentationForSpur>>genCheckRememberedBitOf:scratch: (in
> category 'compile abstract instructions') -----
> + genCheckRememberedBitOf: objReg scratch: scratchReg
> + "Check the remembered bit of the object in objReg; answer the jump
> taken if the bit is already set.
> + Only need to fetch the byte containing it, which reduces the size
> of the mask constant."
> + | rememberedBitByteOffset mask |
> + rememberedBitByteOffset := cogit backEnd isBigEndian
> +
> ifTrue: [objectMemory baseHeaderSize - 1 - (objectMemory
> rememberedBitShift // 8)]
> +
> ifFalse:[objectMemory rememberedBitShift // 8].
> + mask := 1 << (objectMemory rememberedBitShift \\ 8).
> + cogit MoveMb: rememberedBitByteOffset r: objReg R: scratchReg.
> + cogit TstCq: mask R: scratchReg.
> + ^cogit JumpNonZero: 0!
>
> Item was changed:
> ----- Method:
> CogObjectRepresentationForSpur>>genStoreCheckReceiverReg:valueReg:scratchReg:inFrame:
> (in category 'compile abstract instructions') -----
> genStoreCheckReceiverReg: destReg valueReg: valueReg scratchReg:
> scratchReg inFrame: inFrame
> "Generate the code for a store check of valueReg into destReg."
> + | jmpImmediate jmpDestYoung jmpSourceOld jmpAlreadyRemembered |
> - | jmpImmediate jmpDestYoung jmpSourceOld jmpAlreadyRemembered mask
> rememberedBitByteOffset |
> <var: #jmpImmediate type: #'AbstractInstruction *'>
> <var: #jmpDestYoung type: #'AbstractInstruction *'>
> <var: #jmpSourceOld type: #'AbstractInstruction *'>
> <var: #jmpAlreadyRemembered type: #'AbstractInstruction *'>
> "Is value stored an immediate? If so we're done"
> jmpImmediate := self genJumpImmediate: valueReg.
> "Get the old/new boundary in scratchReg"
> cogit MoveCw: objectMemory storeCheckBoundary R: scratchReg.
> "Is target young? If so we're done"
> cogit CmpR: scratchReg R: destReg. "N.B. FLAGS := destReg -
> scratchReg"
> jmpDestYoung := cogit JumpBelow: 0.
> "Is value stored old? If so we're done."
> cogit CmpR: scratchReg R: valueReg. "N.B. FLAGS := valueReg -
> scratchReg"
> jmpSourceOld := cogit JumpAboveOrEqual: 0.
> "value is young and target is old.
> + Need to remember this only if the remembered bit is not already
> set."
> + CheckRememberedInTrampoline ifFalse:
> + [jmpAlreadyRemembered := self genCheckRememberedBitOf:
> destReg scratch: scratchReg].
> - Need to remember this only if the remembered bit is not already
> set.
> - Test the remembered bit. Only need to fetch the byte containing
> it,
> - which reduces the size of the mask constant."
> - rememberedBitByteOffset := jmpSourceOld isBigEndian
> -
> ifTrue: [objectMemory baseHeaderSize - 1 - (objectMemory
> rememberedBitShift // 8)]
> -
> ifFalse:[objectMemory rememberedBitShift // 8].
> - mask := 1 << (objectMemory rememberedBitShift \\ 8).
> - cogit MoveMb: rememberedBitByteOffset r: destReg R: scratchReg.
> - cogit AndCq: mask R: scratchReg.
> - jmpAlreadyRemembered := cogit JumpNonZero: 0.
> "Remembered bit is not set. Call store check to insert dest into
> remembered table."
> self assert: destReg = ReceiverResultReg.
> cogit
> evaluateTrampolineCallBlock: [cogit CallRT:
> ceStoreCheckTrampoline]
> protectLinkRegIfNot: inFrame.
> jmpImmediate jmpTarget:
> (jmpDestYoung jmpTarget:
> (jmpSourceOld jmpTarget:
> + cogit Label)).
> + CheckRememberedInTrampoline ifFalse:
> + [jmpAlreadyRemembered jmpTarget: jmpSourceOld
> getJmpTarget].
> - (jmpAlreadyRemembered jmpTarget:
> - cogit Label))).
> ^0!
>
> Item was added:
> + ----- Method: CogObjectRepresentationForSpur>>genStoreCheckTrampoline
> (in category 'initialization') -----
> + genStoreCheckTrampoline
> + | jumpSC |
> + <var: #jumpSC type: #'AbstractInstruction *'>
> + <inline: true>
> + CheckRememberedInTrampoline ifTrue:
> + [cogit zeroOpcodeIndex.
> + jumpSC := self genCheckRememberedBitOf: ReceiverResultReg
> scratch: cogit backEnd cResultRegister.
> + self assert: jumpSC opcode = JumpNonZero.
> + jumpSC opcode: JumpZero.
> + cogit RetN: 0.
> + jumpSC jmpTarget: cogit Label].
> + ^cogit
> + genTrampolineFor: #remember:
> + called: 'ceStoreCheckTrampoline'
> + numArgs: 1
> + arg: ReceiverResultReg
> + arg: nil
> + arg: nil
> + arg: nil
> + regsToSave: (cogit callerSavedRegMask bitClear: (cogit
> registerMaskFor: ReceiverResultReg))
> + pushLinkReg: true
> + resultReg: cogit returnRegForStoreCheck
> + appendOpcodes: CheckRememberedInTrampoline!
>
> Item was changed:
> ----- Method:
> CogObjectRepresentationForSpur>>genStoreTrampolineCalled:instVarIndex: (in
> category 'initialization') -----
> genStoreTrampolineCalled: trampolineName instVarIndex: instVarIndex
> "Convention:
> - RcvrResultReg holds the object mutated.
> If immutability failure:
> - TempReg holds the instance variable index mutated
> if instVarIndex > numDedicatedStoreTrampoline
> - ClassReg holds the value to store
> Registers are not lived across this trampoline as the
> immutability failure may need new stack frames."
>
> + | jumpSC jumpRC |
> - | jumpSC |
> <option: #IMMUTABILITY>
> <var: #trampolineName type: #'char *'>
> <var: #jumpSC type: #'AbstractInstruction *'>
> + <var: #jumpRC type: #'AbstractInstruction *'>
> <inline: false>
> cogit zeroOpcodeIndex.
> "SendNumArgsReg is mutated but we don't care as register are not
> live across the trampoline.
> There is no reason why registers cannot be saved over the
> remember: call, but since the
> immutability check is a suspension point, registers cannot remain
> live."
> jumpSC := self genJumpMutable: ReceiverResultReg scratchReg:
> SendNumArgsReg.
> cogit
> compileTrampolineFor:
> #ceCannotAssignTo:withIndex:valueToAssign:
> numArgs: 3
> arg: ReceiverResultReg
> arg: (instVarIndex < (NumStoreTrampolines - 1)
> ifTrue: [cogit trampolineArgConstant:
> instVarIndex]
> ifFalse: [TempReg])
> arg: ClassReg
> arg: nil
> regsToSave: cogit emptyRegisterMask
> pushLinkReg: true
> resultReg: NoReg.
>
> "Store check"
> jumpSC jmpTarget: cogit Label.
> + "If on 64-bits and doing the remembered bit test here, we can
> combine the tests to fetch the header once."
> + CheckRememberedInTrampoline ifTrue:
> + [objectMemory wordSize = 8
> + ifTrue:
> + [cogit TstCq: 1 << objectMemory
> rememberedBitShift R: SendNumArgsReg.
> + jumpRC := cogit JumpZero: 0.
> + cogit RetN: 0]
> + ifFalse:
> + [jumpRC := self genCheckRememberedBitOf:
> ReceiverResultReg scratch: SendNumArgsReg.
> + self assert: jumpRC opcode = JumpNonZero.
> + jumpRC opcode: JumpZero.
> + cogit RetN: 0].
> + jumpRC jmpTarget: cogit Label].
> ^ cogit genTrampolineFor: #remember:
> called: trampolineName
> numArgs: 1
> arg: ReceiverResultReg
> arg: nil
> arg: nil
> arg: nil
> regsToSave: cogit emptyRegisterMask
> pushLinkReg: true
> resultReg: NoReg
> appendOpcodes: true!
>
> Item was changed:
> ----- Method:
> CogObjectRepresentationForSpur>>genStoreWithImmutabilityAndStoreCheckSourceReg:slotIndex:destReg:scratchReg:needRestoreRcvr:
> (in category 'compile abstract instructions') -----
> genStoreWithImmutabilityAndStoreCheckSourceReg: sourceReg slotIndex:
> index destReg: destReg scratchReg: scratchReg needRestoreRcvr:
> needRestoreRcvr
> "Store check code is duplicated to use a single trampoline"
> + | immutableJump jmpImmediate jmpDestYoung jmpSourceOld
> jmpAlreadyRemembered |
> - | immutableJump jmpImmediate jmpDestYoung jmpSourceOld
> rememberedBitByteOffset jmpAlreadyRemembered mask |
> <var: #immutableJump type: #'AbstractInstruction *'>
> <var: #jmpImmediate type: #'AbstractInstruction *'>
> <var: #jmpDestYoung type: #'AbstractInstruction *'>
> <var: #jmpSourceOld type: #'AbstractInstruction *'>
> <var: #jmpAlreadyRemembered type: #'AbstractInstruction *'>
>
> immutableJump := self genJumpImmutable: destReg scratchReg:
> scratchReg.
>
> cogit genTraceStores.
>
> "do the store"
> cogit MoveR: sourceReg
> Mw: index * objectMemory wordSize + objectMemory
> baseHeaderSize
> r: destReg.
>
> "store check"
> jmpImmediate := self genJumpImmediate: sourceReg.
> "Get the old/new boundary in scratchReg"
> cogit MoveCw: objectMemory storeCheckBoundary R: scratchReg.
> "Is target young? If so we're done"
> cogit CmpR: scratchReg R: destReg. "N.B. FLAGS := destReg -
> scratchReg"
> jmpDestYoung := cogit JumpBelow: 0.
> "Is value stored old? If so we're done."
> cogit CmpR: scratchReg R: sourceReg. "N.B. FLAGS := valueReg -
> scratchReg"
> jmpSourceOld := cogit JumpAboveOrEqual: 0.
> "value is young and target is old.
> + Need to remember this only if the remembered bit is not already
> set."
> + CheckRememberedInTrampoline ifFalse:
> + [jmpAlreadyRemembered := self genCheckRememberedBitOf:
> destReg scratch: scratchReg].
> - Need to remember this only if the remembered bit is not already
> set.
> - Test the remembered bit. Only need to fetch the byte containing
> it,
> - which reduces the size of the mask constant."
> - rememberedBitByteOffset := jmpSourceOld isBigEndian
> -
> ifTrue: [objectMemory baseHeaderSize - 1 - (objectMemory
> rememberedBitShift // 8)]
> -
> ifFalse:[objectMemory rememberedBitShift // 8].
> - mask := 1 << (objectMemory rememberedBitShift \\ 8).
> - cogit MoveMb: rememberedBitByteOffset r: destReg R: scratchReg.
> - cogit AndCq: mask R: scratchReg.
> - jmpAlreadyRemembered := cogit JumpNonZero: 0.
> "Set the inst var index for the benefit of the immutability check.
> The trampoline will
> repeat the check to choose between the immutbality violation and
> the store check."
> immutableJump jmpTarget: cogit Label.
> self genStoreTrampolineCall: index.
> needRestoreRcvr ifTrue: [ cogit putSelfInReceiverResultReg ].
>
> jmpImmediate jmpTarget:
> (jmpDestYoung jmpTarget:
> (jmpSourceOld jmpTarget:
> + cogit Label)).
> + CheckRememberedInTrampoline ifFalse:
> + [jmpAlreadyRemembered jmpTarget: jmpSourceOld
> getJmpTarget].
> - (jmpAlreadyRemembered jmpTarget:
> - cogit Label))).
> -
> ^ 0!
>
> Item was changed:
> ----- Method:
> CogObjectRepresentationForSpur>>generateObjectRepresentationTrampolines (in
> category 'initialization') -----
> generateObjectRepresentationTrampolines
> "Do the store check. Answer the argument for the benefit of the
> code generator;
> ReceiverResultReg may be caller-saved and hence smashed by this
> call. Answering
> it allows the code generator to reload ReceiverResultReg cheaply.
> In Spur the only thing we leave to the run-time is adding the
> receiver to the
> remembered set and setting its isRemembered bit."
> self
> cppIf: IMMUTABILITY
> ifTrue:
> [self cCode: [] inSmalltalk:
> [ceStoreTrampolines := CArrayAccessor on:
> (Array new: NumStoreTrampolines)].
> 0 to: NumStoreTrampolines - 1 do:
> [:instVarIndex |
> ceStoreTrampolines
> at: instVarIndex
> put: (self
>
> genStoreTrampolineCalled: (cogit
>
> trampolineName:
> 'ceStoreTrampoline'
>
> numArgs: instVarIndex
>
> limit: NumStoreTrampolines -
> 2)
> instVarIndex:
> instVarIndex)]].
> + ceStoreCheckTrampoline := self genStoreCheckTrampoline.
> - ceStoreCheckTrampoline := cogit
> -
> genTrampolineFor: #remember:
> -
> called: 'ceStoreCheckTrampoline'
> -
> arg: ReceiverResultReg
> -
> regsToSave: (cogit callerSavedRegMask bitClear: (cogit registerMaskFor:
> ReceiverResultReg))
> -
> result: cogit returnRegForStoreCheck.
> ceStoreCheckContextReceiverTrampoline := self
> genStoreCheckContextReceiverTrampoline.
> ceScheduleScavengeTrampoline := cogit
>
> genTrampolineFor: #ceScheduleScavenge
>
> called: 'ceScheduleScavengeTrampoline'
>
> regsToSave: cogit callerSavedRegMask.
> ceSmallActiveContextInMethodTrampoline := self
> genActiveContextTrampolineLarge: false inBlock: false called:
> 'ceSmallMethodContext'.
> ceSmallActiveContextInBlockTrampoline := self
> genActiveContextTrampolineLarge: false inBlock: true called:
> 'ceSmallBlockContext'.
> ceLargeActiveContextInMethodTrampoline := self
> genActiveContextTrampolineLarge: true inBlock: false called:
> 'ceLargeMethodContext'.
> ceLargeActiveContextInBlockTrampoline := self
> genActiveContextTrampolineLarge: true inBlock: true called:
> 'ceLargeBlockContext'!
>
> Item was changed:
> ----- Method: Cogit class>>initializeMiscConstants (in category 'class
> initialization') -----
> initializeMiscConstants
> super initializeMiscConstants.
> Debug := initializationOptions at: #Debug ifAbsent: [false].
> (initializationOptions includesKey: #EagerInstructionDecoration)
> ifTrue:
> [EagerInstructionDecoration :=
> initializationOptions at: #EagerInstructionDecoration]
> ifFalse:
> [EagerInstructionDecoration ifNil:
> [EagerInstructionDecoration := false]].
> "speeds up single stepping but could lose fidelity"
>
> ProcessorClass := (initializationOptions at: #ISA ifAbsentPut:
> [self objectMemoryClass defaultISA]) caseOf: {
> [#X64]
> -> [BochsX64Alien].
> [#IA32]
> -> [BochsIA32Alien].
> [#ARMv5]
> -> [GdbARMAlien].
> [#MIPSEL]
> -> [MIPSELSimulator] }.
> CogCompilerClass := self activeCompilerClass.
> (CogCompilerClass withAllSuperclasses copyUpTo:
> CogAbstractInstruction) reverseDo:
> [:compilerClass| compilerClass initialize;
> initializeAbstractRegisters].
> + self objectMemoryClass objectRepresentationClass
> initializeMiscConstants.
> "Our criterion for which methods to JIT is literal count. The
> default value is 60 literals or less."
> MaxLiteralCountForCompile := initializationOptions at:
> #MaxLiteralCountForCompile ifAbsent: [60].
> "we special-case 0, 1 & 2 argument sends, N is numArgs >= 3"
> NumSendTrampolines := 4.
> "Currently not even the ceImplicitReceiverTrampoline contains
> object references."
> NumObjRefsInRuntime := 0.
>
> NSCSelectorIndex := (NSSendCache instVarNames indexOf: #selector)
> - 1.
> NSCNumArgsIndex := (NSSendCache instVarNames indexOf: #numArgs) -
> 1.
> NSCClassTagIndex := (NSSendCache instVarNames indexOf: #classTag)
> - 1.
> NSCEnclosingObjectIndex := (NSSendCache instVarNames indexOf:
> #enclosingObject) - 1.
> NSCTargetIndex := (NSSendCache instVarNames indexOf: #target) - 1.
> NumOopsPerNSC := NSSendCache instVarNames size.
>
> "Max size to alloca when compiling.
> Mac OS X 10.6.8 segfaults approaching 8Mb.
> Linux 2.6.9 segfaults above 11Mb.
> WIndows XP segfaults approaching 2Mb."
> MaxStackAllocSize := 1024 * 1024 * 3 / 2 !
>
> Item was changed:
> ----- Method: VMBasicConstants class>>namesDefinedAtCompileTime (in
> category 'C translation') -----
> namesDefinedAtCompileTime
> "Answer the set of names for variables that should be defined at
> compile time.
> Some of these get default values during simulation, and hence get
> defaulted in
> the various initializeMiscConstants methods. But that they have
> values should
> /not/ cause the code generator to do dead code elimination based
> on their
> default values."
> ^#( VMBIGENDIAN
> IMMUTABILITY
> STACKVM COGVM COGMTVM SPURVM
> + PharoVM
> "Pharo vs Squeak"
> + EnforceAccessControl
> "Newspeak"
> + CheckRememberedInTrampoline) "IMMUTABILITY"!
> - "Pharo vs Squeak" PharoVM
> - "Newspeak" EnforceAccessControl)!
>
>
--
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20160331/1387571d/attachment-0001.htm
More information about the Vm-dev
mailing list