ClementBera uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-cb.1263.mcz
==================== Summary ====================
Name: VMMaker.oscog-cb.1263 Author: cb Time: 27 April 2015, 3:26:40.541 pm UUID: a1bd713c-e904-4df8-8db6-540c64c90ab8 Ancestors: VMMaker.oscog-cb.1262
added inlining of 4 Args block with value: value: value: value: in slang
Add and remove a few types to make gcc and CCodeGenerator happy.
=============== Diff against VMMaker.oscog-cb.1262 ===============
Item was changed: ----- Method: CCodeGenerator>>initializeCTranslationDictionary (in category 'C translation support') ----- initializeCTranslationDictionary "Initialize the dictionary mapping message names to actions for C code generation."
| pairs | translationDict := Dictionary new: 200. pairs := #( #& #generateAnd:on:indent: #| #generateOr:on:indent: #and: #generateSequentialAnd:on:indent: #or: #generateSequentialOr:on:indent: #not #generateNot:on:indent:
#+ #generatePlus:on:indent: #- #generateMinus:on:indent: #negated #generateNegated:on:indent: #* #generateTimes:on:indent: #/ #generateDivide:on:indent: #// #generateDivide:on:indent: #\ #generateModulo:on:indent: #<< #generateShiftLeft:on:indent: #>> #generateShiftRight:on:indent: #>>> #generateSignedShiftRight:on:indent: #min: #generateMin:on:indent: #max: #generateMax:on:indent: #between:and: #generateBetweenAnd:on:indent:
#bitAnd: #generateBitAnd:on:indent: #bitOr: #generateBitOr:on:indent: #bitXor: #generateBitXor:on:indent: #bitShift: #generateBitShift:on:indent: #signedBitShift: #generateSignedBitShift:on:indent: #bitInvert32 #generateBitInvert:on:indent: #bitInvert64 #generateBitInvert:on:indent: #bitClear: #generateBitClear:on:indent: #truncateTo: #generateTruncateTo:on:indent: #rounded #generateRounded:on:indent:
#< #generateLessThan:on:indent: #<= #generateLessThanOrEqual:on:indent: #= #generateEqual:on:indent: #> #generateGreaterThan:on:indent: #>= #generateGreaterThanOrEqual:on:indent: #~= #generateNotEqual:on:indent: #== #generateEqual:on:indent: #~~ #generateNotEqual:on:indent: #isNil #generateIsNil:on:indent: #notNil #generateNotNil:on:indent:
#whileTrue: #generateWhileTrue:on:indent: #whileFalse: #generateWhileFalse:on:indent: #whileTrue #generateDoWhileTrue:on:indent: #whileFalse #generateDoWhileFalse:on:indent: #to:do: #generateToDo:on:indent: #to:by:do: #generateToByDo:on:indent: #repeat #generateRepeat:on:indent: #timesRepeat: #generateTimesRepeat:on:indent:
#ifTrue: #generateIfTrue:on:indent: #ifFalse: #generateIfFalse:on:indent: #ifTrue:ifFalse: #generateIfTrueIfFalse:on:indent: #ifFalse:ifTrue: #generateIfFalseIfTrue:on:indent:
#ifNotNil: #generateIfNotNil:on:indent: #ifNil: #generateIfNil:on:indent: #ifNotNil:ifNil: #generateIfNotNilIfNil:on:indent: #ifNil:ifNotNil: #generateIfNilIfNotNil:on:indent:
#at: #generateAt:on:indent: #at:put: #generateAtPut:on:indent: #basicAt: #generateAt:on:indent: #basicAt:put: #generateAtPut:on:indent:
#integerValueOf: #generateIntegerValueOf:on:indent: #integerObjectOf: #generateIntegerObjectOf:on:indent: #isIntegerObject: #generateIsIntegerObject:on:indent: #cCode: #generateInlineCCode:on:indent: #cCode:inSmalltalk: #generateInlineCCode:on:indent: #cPreprocessorDirective: #generateInlineCPreprocessorDirective:on:indent: #cppIf:ifTrue:ifFalse: #generateInlineCppIfElse:on:indent: #cppIf:ifTrue: #generateInlineCppIfElse:on:indent: #cCoerce:to: #generateCCoercion:on:indent: #cCoerceSimple:to: #generateCCoercion:on:indent: #addressOf: #generateAddressOf:on:indent: #addressOf:put: #generateAddressOf:on:indent: #asAddress:put: #generateAsAddress:on:indent: #signedIntFromLong #generateSignedIntFromLong:on:indent: #signedIntToLong #generateSignedIntToLong:on:indent: #signedIntFromShort #generateSignedIntFromShort:on:indent: #signedIntToShort #generateSignedIntToShort:on:indent: #preIncrement #generatePreIncrement:on:indent: #preDecrement #generatePreDecrement:on:indent: #inline: #generateInlineDirective:on:indent: #asFloat #generateAsFloat:on:indent: #asInteger #generateAsInteger:on:indent: #asUnsignedInteger #generateAsUnsignedInteger:on:indent: #asLong #generateAsLong:on:indent: #asUnsignedLong #generateAsUnsignedLong:on:indent: #asVoidPointer #generateAsVoidPointer:on:indent: #asSymbol #generateAsSymbol:on:indent: #flag: #generateFlag:on:indent: #anyMask: #generateBitAnd:on:indent: #noMask: #generateNoMask:on:indent: #raisedTo: #generateRaisedTo:on:indent: #touch: #generateTouch:on:indent:
#bytesPerOop #generateBytesPerOop:on:indent: #bytesPerWord #generateBytesPerWord:on:indent: #wordSize #generateBytesPerWord:on:indent: #baseHeaderSize #generateBaseHeaderSize:on:indent: #minSmallInteger #generateSmallIntegerConstant:on:indent: #maxSmallInteger #generateSmallIntegerConstant:on:indent: #sharedCodeNamed:inCase: #generateSharedCodeDirective:on:indent:
#perform: #generatePerform:on:indent: #perform:with: #generatePerform:on:indent: #perform:with:with: #generatePerform:on:indent: #perform:with:with:with: #generatePerform:on:indent: #perform:with:with:with:with: #generatePerform:on:indent: #perform:with:with:with:with:with: #generatePerform:on:indent:
#value #generateValue:on:indent: #value: #generateValue:on:indent: #value:value: #generateValue:on:indent: #value:value:value: #generateValue:on:indent: + #value:value:value:value: #generateValue:on:indent:
#deny: #generateDeny:on:indent:
#shouldNotImplement #generateSmalltalkMetaError:on:indent: #shouldBeImplemented #generateSmalltalkMetaError:on:indent: #subclassResponsibility #generateSmalltalkMetaError:on:indent: ).
1 to: pairs size by: 2 do: [:i | translationDict at: (pairs at: i) put: (pairs at: i + 1)].
pairs := #( #ifTrue: #generateIfTrueAsArgument:on:indent: #ifFalse: #generateIfFalseAsArgument:on:indent: #ifTrue:ifFalse: #generateIfTrueIfFalseAsArgument:on:indent: #ifFalse:ifTrue: #generateIfFalseIfTrueAsArgument:on:indent: #ifNotNil: #generateIfNotNilAsArgument:on:indent: #ifNil: #generateIfNilAsArgument:on:indent: #ifNotNil:ifNil: #generateIfNotNilIfNilAsArgument:on:indent: #ifNil:ifNotNil: #generateIfNilIfNotNilAsArgument:on:indent: #cCode: #generateInlineCCodeAsArgument:on:indent: #cCode:inSmalltalk: #generateInlineCCodeAsArgument:on:indent: #cppIf:ifTrue:ifFalse: #generateInlineCppIfElseAsArgument:on:indent: #cppIf:ifTrue: #generateInlineCppIfElseAsArgument:on:indent:
#value #generateValueAsArgument:on:indent: #value: #generateValueAsArgument:on:indent: #value:value: #generateValueAsArgument:on:indent: ).
asArgumentTranslationDict := Dictionary new: 8. 1 to: pairs size by: 2 do: [:i | asArgumentTranslationDict at: (pairs at: i) put: (pairs at: i + 1)]. !
Item was changed: ----- Method: CogObjectRepresentationForSpur>>genEnsureOopInRegNotForwarded:scratchReg:jumpBackTo: (in category 'compile abstract instructions') ----- genEnsureOopInRegNotForwarded: reg scratchReg: scratch jumpBackTo: instruction + <inline: true> ^ self genEnsureOopInRegNotForwarded: reg scratchReg: scratch ifForwarder: instruction ifNotForwarder: 0!
Item was changed: ----- Method: StackToRegisterMappingCogit>>extractMaybeBranchDescriptorInto: (in category 'bytecode generator support') ----- extractMaybeBranchDescriptorInto: fourArgBlock "Looks one instruction ahead of the current bytecodePC and answers its bytecode descriptor and its pc. If the instruction found is a branch, also answers the pc after the branch and the pc targetted by the branch" | primDescriptor nextPC nExts branchDescriptor targetBytecodePC postBranchPC | <inline: true> <var: #primDescriptor type: #'BytecodeDescriptor *'> <var: #branchDescriptor type: #'BytecodeDescriptor *'> primDescriptor := self generatorAt: byte0.
nextPC := bytecodePC + primDescriptor numBytes. nExts := 0. [branchDescriptor := self generatorAt: (objectMemory fetchByte: nextPC ofObject: methodObj) + bytecodeSetOffset. branchDescriptor isExtension] whileTrue: [nExts := nExts + 1. nextPC := nextPC + branchDescriptor numBytes].
+ targetBytecodePC := postBranchPC := 0. + + (branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifTrue: + [ targetBytecodePC := nextPC - (branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse: - [ ^ fourArgBlock value: branchDescriptor value: nextPC value: 0 value: 0 ]. - - targetBytecodePC := nextPC + branchDescriptor numBytes + (self spanFor: branchDescriptor at: nextPC exts: nExts in: methodObj). + postBranchPC := nextPC + branchDescriptor numBytes ]. - postBranchPC := nextPC + branchDescriptor numBytes. fourArgBlock value: branchDescriptor value: nextPC value: postBranchPC value: targetBytecodePC!
Item was changed: ----- Method: StackToRegisterMappingCogit>>genSpecialSelectorEqualsEqualsWithForwarders (in category 'bytecode generators') ----- genSpecialSelectorEqualsEqualsWithForwarders | nextPC branchDescriptor unforwardRcvr argReg targetBytecodePC unforwardArg rcvrReg postBranchPC label fixup | <var: #fixup type: #'BytecodeFixup *'> - <var: #primDescriptor type: #'BytecodeDescriptor *'> <var: #branchDescriptor type: #'BytecodeDescriptor *'> + <var: #label type: #'AbstractInstruction *'> self extractMaybeBranchDescriptorInto: [ :descr :next :postBranch :target | branchDescriptor := descr. nextPC := next. postBranchPC := postBranch. targetBytecodePC := target ].
"If an operand is an annotable constant, it may be forwarded, so we need to store it into a register so the forwarder check can jump back to the comparison after unforwarding the constant. However, if one of the operand is an unnanotable constant, does not allocate a register for it (machine code will use operations on constants) and does not generate forwarder checks." unforwardRcvr := (objectRepresentation isUnannotatableConstant: (self ssValue: 1)) not. unforwardArg := (objectRepresentation isUnannotatableConstant: self ssTop) not.
self allocateEqualsEqualsRegistersArgNeedsReg: unforwardArg rcvrNeedsReg: unforwardRcvr into: [ :rcvr :arg | rcvrReg:= rcvr. argReg := arg ].
"If not followed by a branch, resolve to true or false." (branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse: [^ self genEqualsEqualsNoBranchArgIsConstant: unforwardArg not rcvrIsConstant: unforwardRcvr not argReg: argReg rcvrReg: rcvrReg]. "If branching the stack must be flushed for the merge" self ssFlushTo: simStackPtr - 2. label := self Label. self genEqualsEqualsComparisonArgIsConstant: unforwardArg not rcvrIsConstant: unforwardRcvr not argReg: argReg rcvrReg: rcvrReg. self ssPop: 2.
"Further since there is a following conditional jump bytecode, define non-merge fixups and leave the cond bytecode to set the mergeness." (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 assert: (unforwardArg or: [ unforwardRcvr ]). branchDescriptor isBranchTrue ifTrue: [ fixup := self ensureNonMergeFixupAt: postBranchPC - initialPC. self JumpZero: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger ] ifFalse: "branchDescriptor is branchFalse" [ fixup := self ensureNonMergeFixupAt: targetBytecodePC - initialPC. self JumpZero: (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger ]. "The forwarders checks need to jump back to the comparison (label) if a forwarder is found, else jump forward either to the next forwarder check or to the postBranch or branch target (fixup)." unforwardArg ifTrue: [ unforwardRcvr ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg jumpBackTo: label ] ifFalse: [ objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg ifForwarder: label ifNotForwarder: fixup ] ]. unforwardRcvr ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: rcvrReg scratchReg: TempReg ifForwarder: label ifNotForwarder: fixup ]. "Not reached, execution flow have jumped to fixup" ^0!
Item was changed: ----- Method: StackToRegisterMappingCogit>>genVanillaSpecialSelectorEqualsEquals (in category 'bytecode generators') ----- genVanillaSpecialSelectorEqualsEquals | nextPC postBranchPC targetBytecodePC branchDescriptor rcvrReg argReg argIsConstant rcvrIsConstant | - <var: #primDescriptor type: #'BytecodeDescriptor *'> <var: #branchDescriptor type: #'BytecodeDescriptor *'> self extractMaybeBranchDescriptorInto: [ :descr :next :postBranch :target | branchDescriptor := descr. nextPC := next. postBranchPC := postBranch. targetBytecodePC := target ]. argIsConstant := self ssTop type = SSConstant. "they can't be both constants because we do not have instructions manipulating two constants, if this is the case, which can happen due to annotable constants that can be moved in memory with become and therefore can't resolve #== at compilation time, still write the rcvr into a register as if it was not a constant. It's uncommon anyway." rcvrIsConstant := argIsConstant not and: [(self ssValue: 1) type = SSConstant]. self allocateEqualsEqualsRegistersArgNeedsReg: argIsConstant not rcvrNeedsReg: rcvrIsConstant not into: [ :rcvr :arg | rcvrReg:= rcvr. argReg := arg ]. "If not followed by a branch, resolve to true or false." (branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse: [ ^ self genEqualsEqualsNoBranchArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrReg]. "If branching the stack must be flushed for the merge" self ssFlushTo: simStackPtr - 2. self genEqualsEqualsComparisonArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrReg. self ssPop: 2.
"Further since there is a following conditional jump bytecode, define non-merge fixups and leave the cond bytecode to set the mergeness." (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.
"If the branch is dead, then we can just fall through postBranchPC (only a nop in-between), else we need to jump over the code of the branch" deadCode ifFalse: [self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC)]. ^0!
vm-dev@lists.squeakfoundation.org