[Vm-dev] VM Maker: VMMaker.oscog-cb.1207.mcz
commits at source.squeak.org
commits at source.squeak.org
Fri Apr 17 01:14:05 UTC 2015
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-cb.1207.mcz
==================== Summary ====================
Name: VMMaker.oscog-cb.1207
Author: cb
Time: 16 April 2015, 6:12:21.174 pm
UUID: 67297437-fcdb-41f7-a9cd-949fff51f29b
Ancestors: VMMaker.oscog-cb.1206
Fixed the dead code elimination so that now it eliminates an unconditionnal branch over a nop in case of inlined branches such as #== then branch or inlined comparison then branch.
Added a method for in-image compilation.
=============== Diff against VMMaker.oscog-cb.1206 ===============
Item was added:
+ ----- Method: CurrentImageCoInterpreterFacade>>marryFrameCopiesTemps (in category 'frame access') -----
+ marryFrameCopiesTemps
+ ^ false!
Item was changed:
----- Method: StackToRegisterMappingCogit>>compileAbstractInstructionsFrom:through: (in category 'compile abstract instructions') -----
compileAbstractInstructionsFrom: start through: end
"Loop over bytecodes, dispatching to the generator for each bytecode, handling fixups in due course."
| nextOpcodeIndex descriptor nExts fixup result |
<var: #descriptor type: #'BytecodeDescriptor *'>
<var: #fixup type: #'BytecodeFixup *'>
self traceSimStack.
bytecodePC := start.
nExts := 0.
descriptor := nil.
deadCode := false.
[self cCode: '' inSmalltalk:
[(debugBytecodePointers includes: bytecodePC) ifTrue: [self halt]].
fixup := self fixupAt: bytecodePC - initialPC.
fixup targetInstruction asUnsignedInteger > 0
ifTrue:
+ [fixup targetInstruction asUnsignedInteger >= 2 ifTrue:
+ [self merge: fixup afterContinuation: deadCode not].
+ deadCode := false]
- [deadCode := false.
- fixup targetInstruction asUnsignedInteger >= 2 ifTrue:
- [self merge: fixup
- afterContinuation: (descriptor notNil
- and: [descriptor isUnconditionalBranch
- or: [descriptor isReturn]]) not]]
ifFalse: "If there's no fixup following a return there's no jump to that code and it is dead."
[(descriptor notNil and: [descriptor isReturn]) ifTrue:
[deadCode := true]].
self cCode: '' inSmalltalk:
[deadCode ifFalse:
[self assert: simStackPtr + (needsFrame ifTrue: [0] ifFalse: [1])
= (self debugStackPointerFor: bytecodePC)]].
byte0 := (objectMemory fetchByte: bytecodePC ofObject: methodObj) + bytecodeSetOffset.
descriptor := self generatorAt: byte0.
self loadSubsequentBytesForDescriptor: descriptor at: bytecodePC.
nextOpcodeIndex := opcodeIndex.
result := deadCode
ifTrue: "insert nops for dead code that is mapped so that bc to mc mapping is not many to one"
[(descriptor isMapped
or: [inBlock and: [descriptor isMappedInBlock]]) ifTrue:
[self annotateBytecode: self Nop].
0]
ifFalse:
[self perform: descriptor generator].
descriptor isExtension ifFalse: "extended bytecodes must consume their extensions"
[self assert: (extA = 0 and: [extB = 0])].
self traceDescriptor: descriptor; traceSimStack.
(fixup targetInstruction asUnsignedInteger between: 1 and: 2) ifTrue:
["There is a fixup for this bytecode. It must point to the first generated
instruction for this bytecode. If there isn't one we need to add a label."
opcodeIndex = nextOpcodeIndex ifTrue:
[self Label].
fixup targetInstruction: (self abstractInstructionAt: nextOpcodeIndex)].
bytecodePC := self nextBytecodePCFor: descriptor at: bytecodePC exts: nExts in: methodObj.
result = 0 and: [bytecodePC <= end]] whileTrue:
[nExts := descriptor isExtension ifTrue: [nExts + 1] ifFalse: [0]].
self checkEnoughOpcodes.
^result!
Item was changed:
----- Method: StackToRegisterMappingCogit>>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"
| nextPC branchDescriptor nExts |
nextPC := bytecodePC + 3.
nExts := 0.
[branchDescriptor := self generatorAt: (objectMemory fetchByte: nextPC ofObject: methodObj) + (byte0 bitAnd: 256).
branchDescriptor isExtension] whileTrue:
[nExts := nExts + 1.
nextPC := nextPC + branchDescriptor numBytes].
(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse])
ifTrue: "This is the path where the inlined comparison is followed immediately by a branch"
[| targetBytecodePC postBranchPC |
targetBytecodePC := nextPC
+ branchDescriptor numBytes
+ (self spanFor: branchDescriptor at: nextPC exts: nExts in: methodObj).
postBranchPC := nextPC + branchDescriptor numBytes.
(self fixupAt: nextPC - initialPC) targetInstruction = 0
ifTrue: "The next instruction is dead. we can skip it."
[deadCode := true.
self ensureFixupAt: targetBytecodePC - initialPC.
+ self ensureFixupAt: postBranchPC - initialPC ]
- self ensureFixupAt: postBranchPC - initialPC]
ifFalse:
[self ssPushConstant: objectMemory trueObject]. "dummy value"
self gen: (branchDescriptor isBranchTrue ifTrue: [opTrue] ifFalse: [opFalse])
+ operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+ deadCode ifFalse: [ self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC) ] ]
- operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
- 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 gen: opTrue operand: 0.
self
annotate: (self MoveCw: objectMemory falseObject R: destReg)
objRef: objectMemory falseObject.
jump := self Jump: 0.
condJump jmpTarget: (self
annotate: (self MoveCw: objectMemory trueObject R: destReg)
objRef: objectMemory trueObject).
jump jmpTarget: self Label].
^ 0!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genSpecialSelectorEqualsEquals (in category 'bytecode generators') -----
genSpecialSelectorEqualsEquals
| nextPC postBranchPC targetBytecodePC primDescriptor branchDescriptor nExts
unforwardArg unforwardRcvr jumpEqual jumpNotEqual rcvrReg argReg result |
<var: #jumpEqual type: #'AbstractInstruction *'>
<var: #jumpNotEqual type: #'AbstractInstruction *'>
<var: #primDescriptor type: #'BytecodeDescriptor *'>
<var: #branchDescriptor type: #'BytecodeDescriptor *'>
primDescriptor := self generatorAt: byte0.
"forwarders have been followed in cog:selector:"
(self ssTop type = SSConstant
and: [(self ssValue: 1) type = SSConstant]) ifTrue:
[self assert: primDescriptor isMapped not.
result := self ssTop constant = (self ssValue: 1) constant
ifTrue: [objectMemory trueObject]
ifFalse: [objectMemory falseObject].
self ssPop: 2.
^self ssPushConstant: result].
nextPC := bytecodePC + primDescriptor numBytes.
nExts := 0.
[branchDescriptor := self generatorAt: (objectMemory fetchByte: nextPC ofObject: methodObj) + (byte0 bitAnd: 256).
branchDescriptor isExtension] whileTrue:
[nExts := nExts + 1.
nextPC := nextPC + branchDescriptor numBytes].
"If branching the stack must be flushed for the merge"
(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifTrue:
[self ssFlushTo: simStackPtr - 2].
unforwardRcvr := (self ssValue: 1) type ~= SSConstant
or: [objectRepresentation shouldAnnotateObjectReference: (self ssValue: 1) constant].
unforwardArg := self ssTop type ~= SSConstant
or: [objectRepresentation shouldAnnotateObjectReference: self ssTop constant].
"Don't use ReceiverResultReg for receiver to keep ReceiverResultReg live.
Optimize e.g. rcvr == nil, the common case for ifNil: et al."
needsFrame
ifTrue:
[unforwardArg ifTrue:
[self ssAllocateRequiredReg: (argReg := Arg0Reg) upThrough: simStackPtr - 1].
self ssAllocateRequiredReg: (rcvrReg := Arg1Reg) upThrough: simStackPtr - 2]
ifFalse:
[unforwardArg ifTrue:
[argReg := self ssAllocatePreferredReg: ClassReg].
rcvrReg := self ssAllocatePreferredReg: SendNumArgsReg].
unforwardArg
ifTrue:
[self ssTop popToReg: argReg.
objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg.
(self ssValue: 1) popToReg: rcvrReg.
unforwardRcvr ifTrue:
[objectRepresentation genEnsureOopInRegNotForwarded: rcvrReg scratchReg: TempReg].
self CmpR: argReg R: rcvrReg]
ifFalse:
[(self ssValue: 1) popToReg: rcvrReg.
unforwardRcvr ifTrue:
[objectRepresentation genEnsureOopInRegNotForwarded: rcvrReg scratchReg: TempReg].
self CmpCq: self ssTop constant R: rcvrReg].
self ssPop: 2.
"If not followed by a branch, resolve to true or false."
(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
[jumpNotEqual := self JumpNonZero: 0.
self annotate: (self MoveCw: objectMemory trueObject R: rcvrReg)
objRef: objectMemory trueObject.
jumpEqual := self Jump: 0.
jumpNotEqual jmpTarget: (self annotate: (self MoveCw: objectMemory falseObject R: rcvrReg)
objRef: objectMemory falseObject).
jumpEqual jmpTarget: self Label.
self ssPushRegister: rcvrReg.
^0].
"Further since there is a following conditional jump bytecode, define
non-merge fixups and leave the cond bytecode to set the mergeness."
targetBytecodePC := nextPC
+ branchDescriptor numBytes
+ (self spanFor: branchDescriptor at: nextPC exts: nExts in: methodObj).
postBranchPC := nextPC + branchDescriptor numBytes.
(self fixupAt: nextPC - initialPC) targetInstruction = 0
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 gen: (branchDescriptor isBranchTrue ifTrue: [JumpZero] ifFalse: [JumpNonZero])
operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+ deadCode ifFalse: [self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC)].
- self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC).
^0!
More information about the Vm-dev
mailing list