Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1276.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.1276 Author: eem Time: 1 May 2015, 4:36:58.846 pm UUID: 2e88ef12-ccb1-40db-84b8-71122c8ed738 Ancestors: VMMaker.oscog-eem.1275
Rescue open PICs in the SimpleStackBasedCogit on ARM. Refactor genSmalltalkToCStackSwitch to move the LinkReg push there-in.
Make SpurMemoryManager>>lookupAddress: more robust.
=============== Diff against VMMaker.oscog-eem.1275 ===============
Item was changed: ----- Method: Cogit>>compileTrampolineFor:numArgs:arg:arg:arg:arg:saveRegs:pushLinkReg:resultReg: (in category 'initialization') ----- compileTrampolineFor: aRoutine numArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3 saveRegs: saveRegs pushLinkReg: pushLinkReg resultReg: resultRegOrNil "Generate a trampoline with up to four arguments. Generate either a call or a jump to aRoutine as requested by callJumpBar. If generating a call and resultRegOrNil is non-zero pass the C result back in resultRegOrNil. Hack: a negative value indicates an abstract register, a non-negative value indicates a constant." <var: #aRoutine type: #'void *'> <inline: false> + self genSmalltalkToCStackSwitch: pushLinkReg. - "If on an ARM-like RISC processor, the return address needs to be pushed to the - stack so that the interpreter sees the same stack layout as on CISC." - (pushLinkReg and: [backEnd hasLinkRegister]) ifTrue: - [self PushR: LinkReg]. - self genSmalltalkToCStackSwitch. self compileCallFor: aRoutine numArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3 resultReg: resultRegOrNil saveRegs: saveRegs. backEnd genLoadStackPointers. (pushLinkReg and: [backEnd hasLinkRegister]) ifTrue: [self PopR: PCReg] "since we know there is no SP messing to do, might as well pop the stacked return address straight into PC" ifFalse:[ self RetN: 0]!
Item was removed: - ----- Method: Cogit>>genSmalltalkToCStackSwitch (in category 'trampoline support') ----- - genSmalltalkToCStackSwitch - backEnd genSaveStackPointers. - cFramePointerInUse - ifTrue: [backEnd genLoadCStackPointers] - ifFalse: [backEnd genLoadCStackPointer]. - ^0!
Item was added: + ----- Method: Cogit>>genSmalltalkToCStackSwitch: (in category 'trampoline support') ----- + genSmalltalkToCStackSwitch: pushLinkReg + "If the client requires, then on an ARM-like RISC processor, the return address needs to + be pushed to the stack so that the interpreter sees the same stack layout as on CISC." + (backEnd hasLinkRegister and: [pushLinkReg]) ifTrue: + [self PushR: LinkReg]. + backEnd genSaveStackPointers. + cFramePointerInUse + ifTrue: [backEnd genLoadCStackPointers] + ifFalse: [backEnd genLoadCStackPointer]. + ^0!
Item was changed: ----- Method: SimpleStackBasedCogit>>compileOpenPIC:numArgs: (in category 'in-line cacheing') ----- compileOpenPIC: selector numArgs: numArgs "Compile the code for an open PIC. Perform a probe of the first-level method lookup cache followed by a call of ceSendFromInLineCacheMiss: if the probe fails." | jumpSelectorMiss jumpClassMiss itsAHit jumpBCMethod | <var: #jumpSelectorMiss type: #'AbstractInstruction *'> <var: #jumpClassMiss type: #'AbstractInstruction *'> <var: #itsAHit type: #'AbstractInstruction *'> <var: #jumpBCMethod type: #'AbstractInstruction *'> self compilePICAbort: numArgs. entry := objectRepresentation genGetClassTagOf: ReceiverResultReg into: ClassReg scratchReg: TempReg.
"Do first of three probes. See CoInterpreter>>lookupInMethodCacheSel:classTag:" self flag: #lookupInMethodCacheSel:classTag:. "so this method shows up as a sender of lookupInMethodCacheSel:class:" self MoveR: ClassReg R: SendNumArgsReg. self annotate: (self XorCw: selector R: ClassReg) objRef: selector. self LogicalShiftLeftCq: objectMemory shiftForWord R: ClassReg. self AndCq: MethodCacheMask << objectMemory shiftForWord R: ClassReg. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheSelector << objectMemory shiftForWord) r: ClassReg R: TempReg. self annotate: (self CmpCw: selector R: TempReg) objRef: selector. jumpSelectorMiss := self JumpNonZero: 0. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheClass << objectMemory shiftForWord) r: ClassReg R: TempReg. self CmpR: SendNumArgsReg R: TempReg. jumpClassMiss := self JumpNonZero: 0.
itsAHit := self Label. "Fetch the method. The interpret trampoline requires the bytecoded method in SendNumArgsReg" self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheMethod << objectMemory shiftForWord) r: ClassReg R: SendNumArgsReg. "If the method is compiled jump to its unchecked entry-point, otherwise interpret it." objectRepresentation genLoadSlot: HeaderIndex sourceReg: SendNumArgsReg destReg: TempReg. self MoveR: TempReg R: ClassReg. jumpBCMethod := objectRepresentation genJumpSmallIntegerInScratchReg: TempReg. jumpBCMethod jmpTarget: picInterpretAbort. self AddCq: cmNoCheckEntryOffset R: ClassReg. self JumpR: ClassReg.
"First probe missed. Do second of three probes. Shift hash right one and retry." jumpSelectorMiss jmpTarget: (jumpClassMiss jmpTarget: self Label). self MoveR: SendNumArgsReg R: ClassReg. self annotate: (self XorCw: selector R: ClassReg) objRef: selector. self LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: ClassReg. self AndCq: MethodCacheMask << objectMemory shiftForWord R: ClassReg. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheSelector << objectMemory shiftForWord) r: ClassReg R: TempReg. self annotate: (self CmpCw: selector R: TempReg) objRef: selector. jumpSelectorMiss := self JumpNonZero: 0. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheClass << objectMemory shiftForWord) r: ClassReg R: TempReg. self CmpR: SendNumArgsReg R: TempReg. self JumpZero: itsAHit.
"Second probe missed. Do last probe. Shift hash right two and retry." jumpSelectorMiss jmpTarget: self Label. self MoveR: SendNumArgsReg R: ClassReg. self annotate: (self XorCw: selector R: ClassReg) objRef: selector. objectMemory shiftForWord > 2 ifTrue: [self LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: ClassReg]. self AndCq: MethodCacheMask << objectMemory shiftForWord R: ClassReg. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheSelector << objectMemory shiftForWord) r: ClassReg R: TempReg. self annotate: (self CmpCw: selector R: TempReg) objRef: selector. jumpSelectorMiss := self JumpNonZero: 0. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheClass << objectMemory shiftForWord) r: ClassReg R: TempReg. self CmpR: SendNumArgsReg R: TempReg. self JumpZero: itsAHit.
"Last probe missed. Call ceSendFromInLineCacheMiss: to do the full lookup." jumpSelectorMiss jmpTarget: self Label. + self genSmalltalkToCStackSwitch: true. - backEnd genSaveStackPointers. - backEnd genLoadCStackPointers. methodLabel addDependent: (self annotateAbsolutePCRef: (self MoveCw: methodLabel asInteger R: SendNumArgsReg)). self compileCallFor: #ceSendFromInLineCacheMiss: numArgs: 1 arg: SendNumArgsReg arg: nil arg: nil arg: nil resultReg: nil saveRegs: false "Note that this call does not return."!
Item was changed: ----- Method: SistaStackToRegisterMappingCogit>>genMustBeBooleanTrampolineFor:called: (in category 'initialization') ----- genMustBeBooleanTrampolineFor: boolean called: trampolineName "This can be entered in one of two states, depending on SendNumArgsReg. See e.g. genJumpIf:to:. If SendNumArgsReg is non-zero then this has been entered via the initial test of the counter in the jump executed count (i.e. the counter has tripped). In this case TempReg contains the boolean to be tested and should not be offset, and ceCounterTripped should be invoked with the unoffset TempReg. If SendNumArgsReg is zero then this has been entered for must-be-boolean processing. TempReg has been offset by boolean and must be corrected and ceSendMustBeBoolean: invoked with the corrected value." <var: #trampolineName type: #'char *'> | jumpMBB | <var: #jumpMBB type: #'AbstractInstruction *'> <inline: false> opcodeIndex := 0. self CmpCq: 0 R: SendNumArgsReg. jumpMBB := self JumpZero: 0. "Open-code self compileTrampolineFor: #ceCounterTripped: numArgs: 1 arg: TempReg ... so we can restore ResultReceiverReg." + self genSmalltalkToCStackSwitch: true. - backEnd hasLinkRegister ifTrue: - [self PushR: LinkReg]. - self genSmalltalkToCStackSwitch. self compileCallFor: #ceCounterTripped: numArgs: 1 arg: TempReg arg: nil arg: nil arg: nil resultReg: TempReg "(*)" saveRegs: false. "(*) For the case where the ceCounterTripped: call returns (e.g. because there's no callback selector installed), the call to the ceSendMustBeBooleanAddTrue/FalseTrampoline is followed by a jump back to the start of the counter/condition test sequence. For this case copy the C result to TempReg (the register that is tested), to reload it with the boolean to be tested." backEnd genLoadStackPointers. backEnd hasLinkRegister ifTrue: [self PopR: LinkReg]. "To keep ResultReceiverReg live if optStatus thiught it was, simply reload it from the frame pointer. This avoids having to reload it in the common case (counter does not trip) if it was live." self MoveMw: FoxMFReceiver r: FPReg R: ReceiverResultReg. self RetN: 0. "If the objectRepresentation does want true & false to be mobile then we need to record these addresses." self assert: (objectRepresentation shouldAnnotateObjectReference: boolean) not. jumpMBB jmpTarget: (self AddCq: boolean R: TempReg). ^self genTrampolineFor: #ceSendMustBeBoolean: called: trampolineName numArgs: 1 arg: TempReg arg: nil arg: nil arg: nil saveRegs: false pushLinkReg: true resultReg: nil appendOpcodes: true!
Item was changed: ----- Method: SpurMemoryManager>>lookupAddress: (in category 'simulation only') ----- lookupAddress: address "If address appears to be that of a Symbol or a few well-known objects (such as classes) answer it, otherwise answer nil. For code disassembly" <doNotGenerate> | fmt size string class classSize maybeThisClass classNameIndex thisClassIndex | ((self addressCouldBeObj: address) + and: [(thisClassIndex := self classIndexOf: address) > 0]) ifFalse: - and: [(self classIndexOf: address) > 0]) ifFalse: [^address = scavengeThreshold ifTrue: ['scavengeThreshold']]. address - self baseHeaderSize = hiddenRootsObj ifTrue: [^'(hiddenRootsObj+baseHeaderSize)']. fmt := self formatOf: address. size := self lengthOf: address baseHeader: (self baseHeader: address) format: fmt. size = 0 ifTrue: [^address caseOf: { [nilObj] -> ['nil']. [trueObj] -> ['true']. [falseObj] -> ['false'] } otherwise: []]. ((fmt between: self firstByteFormat and: self firstCompiledMethodFormat - 1) "indexable byte fields" and: [(size between: 1 and: 64) and: [Scanner isLiteralSymbol: (string := (0 to: size - 1) collect: [:i| Character value: (self fetchByte: i ofObject: address)])]]) ifTrue: [^'#', (ByteString withAll: string)]. + class := self noCheckClassAtIndex: thisClassIndex. - class := self fetchClassOfNonImm: address. (class isNil or: [class = nilObj]) ifTrue: [^nil]. "address is either a class or a metaclass, or an instance of a class or invalid. determine which." classNameIndex := coInterpreter classNameIndex. thisClassIndex := coInterpreter thisClassIndex. ((classSize := self numSlotsOf: class) <= (classNameIndex max: thisClassIndex) or: [classSize > 255]) ifTrue: [^nil]. "Address could be a class or a metaclass" (fmt = 1 and: [size > classNameIndex]) ifTrue: ["Is address a class? If so class's thisClass is address." (self lookupAddress: (self fetchPointer: classNameIndex ofObject: address)) ifNotNil: [:maybeClassName| (self fetchPointer: thisClassIndex ofObject: class) = address ifTrue: [^maybeClassName allButFirst]]. "Is address a Metaclass? If so class's name is Metaclass and address's thisClass holds the class name" ((self isBytes: (self fetchPointer: classNameIndex ofObject: class)) and: [(self lookupAddress: (self fetchPointer: classNameIndex ofObject: class)) = '#Metaclass' and: [size >= thisClassIndex]]) ifTrue: [maybeThisClass := self fetchPointer: thisClassIndex ofObject: address. (self lookupAddress: (self fetchPointer: classNameIndex ofObject: maybeThisClass)) ifNotNil: [:maybeThisClassName| ^maybeThisClassName allButFirst, ' class']]]. ^(self lookupAddress: (self fetchPointer: classNameIndex ofObject: class)) ifNotNil: [:maybeClassName| 'a(n) ', maybeClassName allButFirst]!
Item was changed: ----- Method: StackToRegisterMappingCogit>>compileOpenPIC:numArgs: (in category 'in-line cacheing') ----- compileOpenPIC: selector numArgs: numArgs "Compile the code for an open PIC. Perform a probe of the first-level method lookup cache followed by a call of ceSendFromInLineCacheMiss: if the probe fails. Override to push the register args when calling ceSendFromInLineCacheMiss:" | jumpSelectorMiss jumpClassMiss itsAHit jumpBCMethod | <var: #jumpSelectorMiss type: #'AbstractInstruction *'> <var: #jumpClassMiss type: #'AbstractInstruction *'> <var: #itsAHit type: #'AbstractInstruction *'> <var: #jumpBCMethod type: #'AbstractInstruction *'> self compilePICAbort: numArgs. entry := objectRepresentation genGetClassTagOf: ReceiverResultReg into: ClassReg scratchReg: TempReg.
"Do first of three probes. See CoInterpreter>>lookupInMethodCacheSel:classTag:" self flag: #lookupInMethodCacheSel:classTag:. "so this method shows up as a sender of lookupInMethodCacheSel:class:" self MoveR: ClassReg R: SendNumArgsReg. self annotate: (self XorCw: selector R: ClassReg) objRef: selector. self LogicalShiftLeftCq: objectMemory shiftForWord R: ClassReg. self AndCq: MethodCacheMask << objectMemory shiftForWord R: ClassReg. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheSelector << objectMemory shiftForWord) r: ClassReg R: TempReg. self annotate: (self CmpCw: selector R: TempReg) objRef: selector. jumpSelectorMiss := self JumpNonZero: 0. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheClass << objectMemory shiftForWord) r: ClassReg R: TempReg. self CmpR: SendNumArgsReg R: TempReg. jumpClassMiss := self JumpNonZero: 0.
itsAHit := self Label. "Fetch the method. The interpret trampoline requires the bytecoded method in SendNumArgsReg" self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheMethod << objectMemory shiftForWord) r: ClassReg R: SendNumArgsReg. "If the method is compiled jump to its unchecked entry-point, otherwise interpret it." objectRepresentation genLoadSlot: HeaderIndex sourceReg: SendNumArgsReg destReg: TempReg. self MoveR: TempReg R: ClassReg. jumpBCMethod := objectRepresentation genJumpSmallIntegerInScratchReg: TempReg. jumpBCMethod jmpTarget: picInterpretAbort. self AddCq: cmNoCheckEntryOffset R: ClassReg. self JumpR: ClassReg.
"First probe missed. Do second of three probes. Shift hash right one and retry." jumpSelectorMiss jmpTarget: (jumpClassMiss jmpTarget: self Label). self MoveR: SendNumArgsReg R: ClassReg. self annotate: (self XorCw: selector R: ClassReg) objRef: selector. self LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: ClassReg. self AndCq: MethodCacheMask << objectMemory shiftForWord R: ClassReg. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheSelector << objectMemory shiftForWord) r: ClassReg R: TempReg. self annotate: (self CmpCw: selector R: TempReg) objRef: selector. jumpSelectorMiss := self JumpNonZero: 0. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheClass << objectMemory shiftForWord) r: ClassReg R: TempReg. self CmpR: SendNumArgsReg R: TempReg. self JumpZero: itsAHit.
"Second probe missed. Do last probe. Shift hash right two and retry." jumpSelectorMiss jmpTarget: self Label. self MoveR: SendNumArgsReg R: ClassReg. self annotate: (self XorCw: selector R: ClassReg) objRef: selector. objectMemory shiftForWord > 2 ifTrue: [self LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: ClassReg]. self AndCq: MethodCacheMask << objectMemory shiftForWord R: ClassReg. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheSelector << objectMemory shiftForWord) r: ClassReg R: TempReg. self annotate: (self CmpCw: selector R: TempReg) objRef: selector. jumpSelectorMiss := self JumpNonZero: 0. self MoveMw: coInterpreter methodCacheAddress asUnsignedInteger + (MethodCacheClass << objectMemory shiftForWord) r: ClassReg R: TempReg. self CmpR: SendNumArgsReg R: TempReg. self JumpZero: itsAHit.
"Last probe missed. Call ceSendFromInLineCacheMiss: to do the full lookup." jumpSelectorMiss jmpTarget: self Label. backEnd genPushRegisterArgsForNumArgs: numArgs. + self genSmalltalkToCStackSwitch: true. - "because genPushRegisterArgsForNumArgs: doesn't push LinkReg on ARM..." - backEnd hasLinkRegister ifTrue: - [self PushR: LinkReg]. - self genSmalltalkToCStackSwitch. methodLabel addDependent: (self annotateAbsolutePCRef: (self MoveCw: methodLabel asInteger R: SendNumArgsReg)). self compileCallFor: #ceSendFromInLineCacheMiss: numArgs: 1 arg: SendNumArgsReg arg: nil arg: nil arg: nil resultReg: nil saveRegs: false "Note that this call does not return."!
vm-dev@lists.squeakfoundation.org