Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1471.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.1471 Author: eem Time: 27 September 2015, 10:44:07.215 am UUID: 59ce1851-0880-4d7b-990f-a19c882dbeae Ancestors: VMMaker.oscog-eem.1470
Cogit: Refactor context creation generation code in Sour object representations for sharing between 32 and 64 bits. Implement some 64-bit obj rep generation support.
=============== Diff against VMMaker.oscog-eem.1470 ===============
Item was removed: - ----- Method: CogObjectRepresentationFor32BitSpur>>genCreateClosureAt:numArgs:numCopied:contextNumArgs:large:inBlock: (in category 'bytecode generator support') ----- - genCreateClosureAt: bcpc numArgs: numArgs numCopied: numCopied contextNumArgs: ctxtNumArgs large: isLargeCtxt inBlock: isInBlock - "Create a closure with the given startpc, numArgs and numCopied - within a context with ctxtNumArgs, large if isLargeCtxt that is in a - block if isInBlock. If numCopied > 0 pop those values off the stack." - self genNoPopCreateClosureAt: bcpc - numArgs: numArgs - numCopied: numCopied - contextNumArgs: ctxtNumArgs - large: isLargeCtxt - inBlock: isInBlock. - 1 to: numCopied do: - [:i| - cogit - PopR: TempReg; - MoveR: TempReg - Mw: numCopied - i + ClosureFirstCopiedValueIndex * objectMemory bytesPerOop + objectMemory baseHeaderSize - r: ReceiverResultReg]. - ^0!
Item was removed: - ----- Method: CogObjectRepresentationFor32BitSpur>>genGetActiveContextLarge:inBlock: (in category 'initialization') ----- - genGetActiveContextLarge: isLarge inBlock: isInBlock - "Create a trampoline to answer the active context that will - answer it if a frame is already married, and create it otherwise. - Assume numArgs is in SendNumArgsReg and ClassReg is free." - | header slotSize jumpSingle loopHead jumpNeedScavenge continuation exit | - <var: #jumpNeedScavenge type: #'AbstractInstruction *'> - <var: #continuation type: #'AbstractInstruction *'> - <var: #jumpSingle type: #'AbstractInstruction *'> - <var: #loopHead type: #'AbstractInstruction *'> - <var: #exit type: #'AbstractInstruction *'> - cogit "load the flag; stash it in both TempReg & ClassReg; do the compare (a prime candidated for use of AndCq:R:R:)" - MoveMw: FoxMethod r: FPReg R: ClassReg; - AndCq: MFMethodFlagHasContextFlag R: ClassReg R: TempReg. - jumpSingle := cogit JumpZero: 0. "jump if flag bit not set" - cogit "since the flag bit was set, get the context in the receiver reg and return" - MoveMw: FoxThisContext r: FPReg R: ReceiverResultReg; - RetN: 0. - jumpSingle jmpTarget: cogit Label. - - "OK, it doesn't exist; instantiate and initialize it" - "set the hasContext flag; See CoInterpreter class>>initializeFrameIndices" - cogit - OrCq: MFMethodFlagHasContextFlag R: ClassReg; - MoveR: ClassReg Mw: FoxMethod r: FPReg. - "now get the home CogMethod into ClassReg and save for post-instantiation." - isInBlock - ifTrue: - [cogit - SubCq: 3 R: ClassReg; "-3 is -(hasContext+isBlock) flags" - MoveM16: 0 r: ClassReg R: TempReg; - SubR: TempReg R: ClassReg] - ifFalse: - [cogit SubCq: 1 R: ClassReg]. "-1 is hasContext flag" - - "instantiate the context..." - slotSize := isLarge ifTrue: [LargeContextSlots] ifFalse: [SmallContextSlots]. - header := objectMemory - headerForSlots: slotSize - format: objectMemory indexablePointersFormat - classIndex: ClassMethodContextCompactIndex. - self flag: #endianness. - cogit - MoveAw: objectMemory freeStartAddress R: ReceiverResultReg; - MoveCq: (self low32BitsOf: header) R: TempReg; - MoveR: TempReg Mw: 0 r: ReceiverResultReg; - MoveCq: header >> 32 R: TempReg; - MoveR: TempReg Mw: 4 r: ReceiverResultReg; - MoveR: ReceiverResultReg R: TempReg; - AddCq: (objectMemory smallObjectBytesForSlots: slotSize) R: TempReg; - MoveR: TempReg Aw: objectMemory freeStartAddress; - CmpCq: objectMemory getScavengeThreshold R: TempReg. - jumpNeedScavenge := cogit JumpAboveOrEqual: 0. - - "Now initialize the fields of the context. See CoInterpreter>>marryFrame:SP:copyTemps:" - "sender gets frame pointer as a SmallInteger" - continuation := - cogit MoveR: FPReg R: TempReg. - self genSetSmallIntegerTagsIn: TempReg. - cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (SenderIndex * objectMemory bytesPerOop) r: ReceiverResultReg. - - "pc gets frame caller as a SmallInteger" - cogit MoveMw: FoxSavedFP r: FPReg R: TempReg. - self genSetSmallIntegerTagsIn: TempReg. - cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (InstructionPointerIndex * objectMemory bytesPerOop) r: ReceiverResultReg. - - "Set the method field, freeing up ClassReg again, and frame's context field," - cogit - MoveMw: (cogit offset: CogMethod of: #methodObject) r: ClassReg R: TempReg; - MoveR: TempReg Mw: objectMemory baseHeaderSize + (MethodIndex * objectMemory wordSize) r: ReceiverResultReg; - MoveR: ReceiverResultReg Mw: FoxThisContext r: FPReg. - - "Now compute stack pointer; this is stackPointer (- 1 for return pc if a CISC) - framePointer - 4 (1 each for saved pc, method, context, receiver) + 1 (1-relative) + numArgs" - "TPR note - the code here is actually doing - context stackPointer := ((((fp - sp) / 4) - [3|4]) + num args) asSmallInteger" - cogit - MoveR: FPReg R: TempReg; - SubR: SPReg R: TempReg; - LogicalShiftRightCq: self log2BytesPerWord R: TempReg; - SubCq: (cogit backEnd hasLinkRegister ifTrue: [3] ifFalse: [4]) R: TempReg; - AddR: SendNumArgsReg R: TempReg. - self genConvertIntegerToSmallIntegerInReg: TempReg. - cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (StackPointerIndex * objectMemory bytesPerOop) r: ReceiverResultReg. - - "Set closureOrNil to either the stacked receiver or nil" - isInBlock - ifTrue: - [cogit - MoveR: SendNumArgsReg R: TempReg; - AddCq: 2 R: TempReg; "+2 for saved fp and saved pc" - MoveXwr: TempReg R: FPReg R: TempReg] - ifFalse: - [cogit genMoveConstant: objectMemory nilObject R: TempReg]. - cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (ClosureIndex * objectMemory bytesPerOop) r: ReceiverResultReg. - - "Set the receiver" - cogit - MoveMw: FoxMFReceiver r: FPReg R: TempReg; - MoveR: TempReg Mw: objectMemory baseHeaderSize + (ReceiverIndex * objectMemory bytesPerOop) r: ReceiverResultReg. - - "Now copy the arguments. This is tricky because of the shortage of registers,. ClassReg ranges - from 1 to numArgs (SendNumArgsReg), and from ReceiverIndex + 1 to ReceiverIndex + numArgs. - 1 to: numArgs do: - [:i| - temp := longAt(FPReg + ((SendNumArgs - i + 2) * BytesPerWord)). +2 for saved pc and savedfp - longAtput(FPReg + FoxMFReceiver + (i * BytesPerWord), temp)]" - "TPR note: this is a prime candidate for passing off to the backend to do at least faintly optimal code" - cogit MoveCq: 1 R: ClassReg. - loopHead := cogit CmpR: SendNumArgsReg R: ClassReg. - exit := cogit JumpGreater: 0. - cogit - MoveR: SendNumArgsReg R: TempReg; - SubR: ClassReg R: TempReg; - AddCq: 2 R: TempReg; "+2 for saved fp and saved pc" - MoveXwr: TempReg R: FPReg R: TempReg; - AddCq: ReceiverIndex + (objectMemory baseHeaderSize / objectMemory wordSize) R: ClassReg; "Now convert ClassReg from frame index to context index" - MoveR: TempReg Xwr: ClassReg R: ReceiverResultReg; - SubCq: ReceiverIndex + (objectMemory baseHeaderSize / objectMemory wordSize) - 1 R: ClassReg; "convert back adding 1 ;-)" - Jump: loopHead. - exit jmpTarget: cogit Label. - - "Finally nil or copy the non-argument temps. - ClassReg := FPReg + FoxMFReceiver. - SendNumArgsReg := SendNumArgsReg+ReceiverIndex. - [ClassReg := ClassReg - 4. - backEnd hasLinkRegister - ifTrue: [ClassReg > SPReg] - ifFalse: [ClassReg >= SPReg]] whileTrue: - [receiver[SendNumArgsReg] := *ClassReg. - SendNumArgsReg := SendNumArgsReg + 1]]" - coInterpreter marryFrameCopiesTemps ifFalse: - [cogit MoveCq: objectMemory nilObject R: TempReg]. - cogit - MoveR: FPReg R: ClassReg; - AddCq: FoxMFReceiver R: ClassReg; - AddCq: ReceiverIndex + 1 + (objectMemory baseHeaderSize / objectMemory wordSize) R: SendNumArgsReg. - loopHead := - cogit SubCq: objectMemory wordSize R: ClassReg. - cogit CmpR: SPReg R: ClassReg. - "If on a CISC there's a retpc for the trampoline call on top of stack; if on a RISC there isn't." - exit := cogit backEnd hasLinkRegister - ifTrue: [cogit JumpBelow: 0] - ifFalse: [cogit JumpBelowOrEqual: 0]. - coInterpreter marryFrameCopiesTemps ifTrue: - [cogit MoveMw: 0 r: ClassReg R: TempReg]. - cogit - MoveR: TempReg Xwr: SendNumArgsReg R: ReceiverResultReg; - AddCq: 1 R: SendNumArgsReg; - Jump: loopHead. - exit jmpTarget: cogit Label. - - cogit RetN: 0. - - jumpNeedScavenge jmpTarget: cogit Label. - cogit backEnd saveAndRestoreLinkRegAround: - [cogit CallRT: ceScheduleScavengeTrampoline]. - cogit Jump: continuation. - ^0!
Item was added: + ----- Method: CogObjectRepresentationFor32BitSpur>>genLoadHeaderIntoNewInstance: (in category 'initialization') ----- + genLoadHeaderIntoNewInstance: header + "Generate the instructions to move the constant header into a new instance pointed to by ReceiverResultReg." + <inline: true> + self flag: #endianness. + cogit + MoveCq: (self low32BitsOf: header) R: TempReg; + MoveR: TempReg Mw: 0 r: ReceiverResultReg; + MoveCq: header >> 32 R: TempReg; + MoveR: TempReg Mw: 4 r: ReceiverResultReg!
Item was removed: - ----- Method: CogObjectRepresentationFor32BitSpur>>genSetSmallIntegerTagsIn: (in category 'compile abstract instructions') ----- - genSetSmallIntegerTagsIn: scratchReg - cogit OrCq: 1 R: scratchReg. - ^0!
Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>genConvertIntegerToSmallIntegerInReg: (in category 'compile abstract instructions') ----- + genConvertIntegerToSmallIntegerInReg: reg + cogit LogicalShiftLeftCq: self numTagBits R: reg. + cogit AddCq: 1 R: reg. + ^0!
Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>genConvertSmallIntegerToIntegerInReg: (in category 'compile abstract instructions') ----- + genConvertSmallIntegerToIntegerInReg: reg + cogit ArithmeticShiftRightCq: self numTagBits R: reg. + ^0!
Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>genLoadHeaderIntoNewInstance: (in category 'initialization') ----- + genLoadHeaderIntoNewInstance: header + "Generate the instructions to move the constant header into a new instance pointed to by ReceiverResultReg." + <inline: true> + self flag: #endianness. + cogit + MoveCq: header R: TempReg; + MoveR: TempReg Mw: 0 r: ReceiverResultReg!
Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>numCharacterBits (in category 'compile abstract instructions') ----- + numCharacterBits + ^61!
Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>numSmallIntegerBits (in category 'compile abstract instructions') ----- + numSmallIntegerBits + ^61!
Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>numTagBits (in category 'compile abstract instructions') ----- + numTagBits + <inline: true> + ^3!
Item was added: + ----- Method: CogObjectRepresentationForSpur>>genCreateClosureAt:numArgs:numCopied:contextNumArgs:large:inBlock: (in category 'bytecode generator support') ----- + genCreateClosureAt: bcpc numArgs: numArgs numCopied: numCopied contextNumArgs: ctxtNumArgs large: isLargeCtxt inBlock: isInBlock + "Create a closure with the given startpc, numArgs and numCopied + within a context with ctxtNumArgs, large if isLargeCtxt that is in a + block if isInBlock. If numCopied > 0 pop those values off the stack." + self genNoPopCreateClosureAt: bcpc + numArgs: numArgs + numCopied: numCopied + contextNumArgs: ctxtNumArgs + large: isLargeCtxt + inBlock: isInBlock. + 1 to: numCopied do: + [:i| + cogit + PopR: TempReg; + MoveR: TempReg + Mw: numCopied - i + ClosureFirstCopiedValueIndex * objectMemory bytesPerOop + objectMemory baseHeaderSize + r: ReceiverResultReg]. + ^0!
Item was added: + ----- Method: CogObjectRepresentationForSpur>>genGetActiveContextLarge:inBlock: (in category 'initialization') ----- + genGetActiveContextLarge: isLarge inBlock: isInBlock + "Create a trampoline to answer the active context that will + answer it if a frame is already married, and create it otherwise. + Assume numArgs is in SendNumArgsReg and ClassReg is free." + | header slotSize jumpSingle loopHead jumpNeedScavenge continuation exit | + <var: #jumpNeedScavenge type: #'AbstractInstruction *'> + <var: #continuation type: #'AbstractInstruction *'> + <var: #jumpSingle type: #'AbstractInstruction *'> + <var: #loopHead type: #'AbstractInstruction *'> + <var: #exit type: #'AbstractInstruction *'> + cogit "load the flag; stash it in both TempReg & ClassReg; do the compare (a prime candidated for use of AndCq:R:R:)" + MoveMw: FoxMethod r: FPReg R: ClassReg; + AndCq: MFMethodFlagHasContextFlag R: ClassReg R: TempReg. + jumpSingle := cogit JumpZero: 0. "jump if flag bit not set" + cogit "since the flag bit was set, get the context in the receiver reg and return" + MoveMw: FoxThisContext r: FPReg R: ReceiverResultReg; + RetN: 0. + jumpSingle jmpTarget: cogit Label. + + "OK, it doesn't exist; instantiate and initialize it" + "set the hasContext flag; See CoInterpreter class>>initializeFrameIndices" + cogit + OrCq: MFMethodFlagHasContextFlag R: ClassReg; + MoveR: ClassReg Mw: FoxMethod r: FPReg. + "now get the home CogMethod into ClassReg and save for post-instantiation." + isInBlock + ifTrue: + [cogit + SubCq: 3 R: ClassReg; "-3 is -(hasContext+isBlock) flags" + MoveM16: 0 r: ClassReg R: TempReg; + SubR: TempReg R: ClassReg] + ifFalse: + [cogit SubCq: 1 R: ClassReg]. "-1 is hasContext flag" + + "instantiate the context..." + slotSize := isLarge ifTrue: [LargeContextSlots] ifFalse: [SmallContextSlots]. + header := objectMemory + headerForSlots: slotSize + format: objectMemory indexablePointersFormat + classIndex: ClassMethodContextCompactIndex. + self flag: #endianness. + cogit MoveAw: objectMemory freeStartAddress R: ReceiverResultReg. + self genLoadHeaderIntoNewInstance: header. + cogit + MoveR: ReceiverResultReg R: TempReg; + AddCq: (objectMemory smallObjectBytesForSlots: slotSize) R: TempReg; + MoveR: TempReg Aw: objectMemory freeStartAddress; + CmpCq: objectMemory getScavengeThreshold R: TempReg. + jumpNeedScavenge := cogit JumpAboveOrEqual: 0. + + "Now initialize the fields of the context. See CoInterpreter>>marryFrame:SP:copyTemps:" + "sender gets frame pointer as a SmallInteger" + continuation := + cogit MoveR: FPReg R: TempReg. + self genSetSmallIntegerTagsIn: TempReg. + cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (SenderIndex * objectMemory bytesPerOop) r: ReceiverResultReg. + + "pc gets frame caller as a SmallInteger" + cogit MoveMw: FoxSavedFP r: FPReg R: TempReg. + self genSetSmallIntegerTagsIn: TempReg. + cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (InstructionPointerIndex * objectMemory bytesPerOop) r: ReceiverResultReg. + + "Set the method field, freeing up ClassReg again, and frame's context field," + cogit + MoveMw: (cogit offset: CogMethod of: #methodObject) r: ClassReg R: TempReg; + MoveR: TempReg Mw: objectMemory baseHeaderSize + (MethodIndex * objectMemory wordSize) r: ReceiverResultReg; + MoveR: ReceiverResultReg Mw: FoxThisContext r: FPReg. + + "Now compute stack pointer; this is stackPointer (- 1 for return pc if a CISC) - framePointer - wordSize (1 each for saved pc, method, context, receiver) + 1 (1-relative) + numArgs" + "TPR note - the code here is actually doing + context stackPointer := ((((fp - sp) / wordSize) - [3|4]) + num args) asSmallInteger" + cogit + MoveR: FPReg R: TempReg; + SubR: SPReg R: TempReg; + LogicalShiftRightCq: self log2BytesPerWord R: TempReg; + SubCq: (cogit backEnd hasLinkRegister ifTrue: [3] ifFalse: [4]) R: TempReg; + AddR: SendNumArgsReg R: TempReg. + self genConvertIntegerToSmallIntegerInReg: TempReg. + cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (StackPointerIndex * objectMemory bytesPerOop) r: ReceiverResultReg. + + "Set closureOrNil to either the stacked receiver or nil" + isInBlock + ifTrue: + [cogit + MoveR: SendNumArgsReg R: TempReg; + AddCq: 2 R: TempReg; "+2 for saved fp and saved pc" + MoveXwr: TempReg R: FPReg R: TempReg] + ifFalse: + [cogit genMoveConstant: objectMemory nilObject R: TempReg]. + cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (ClosureIndex * objectMemory bytesPerOop) r: ReceiverResultReg. + + "Set the receiver" + cogit + MoveMw: FoxMFReceiver r: FPReg R: TempReg; + MoveR: TempReg Mw: objectMemory baseHeaderSize + (ReceiverIndex * objectMemory bytesPerOop) r: ReceiverResultReg. + + "Now copy the arguments. This is tricky because of the shortage of registers,. ClassReg ranges + from 1 to numArgs (SendNumArgsReg), and from ReceiverIndex + 1 to ReceiverIndex + numArgs. + 1 to: numArgs do: + [:i| + temp := longAt(FPReg + ((SendNumArgs - i + 2) * wordSize)). +2 for saved pc and savedfp + longAtput(FPReg + FoxMFReceiver + (i * wordSize), temp)]" + "TPR note: this is a prime candidate for passing off to the backend to do at least faintly optimal code" + cogit MoveCq: 1 R: ClassReg. + loopHead := cogit CmpR: SendNumArgsReg R: ClassReg. + exit := cogit JumpGreater: 0. + cogit + MoveR: SendNumArgsReg R: TempReg; + SubR: ClassReg R: TempReg; + AddCq: 2 R: TempReg; "+2 for saved fp and saved pc" + MoveXwr: TempReg R: FPReg R: TempReg; + AddCq: ReceiverIndex + (objectMemory baseHeaderSize / objectMemory wordSize) R: ClassReg; "Now convert ClassReg from frame index to context index" + MoveR: TempReg Xwr: ClassReg R: ReceiverResultReg; + SubCq: ReceiverIndex + (objectMemory baseHeaderSize / objectMemory wordSize) - 1 R: ClassReg; "convert back adding 1 ;-)" + Jump: loopHead. + exit jmpTarget: cogit Label. + + "Finally nil or copy the non-argument temps. + ClassReg := FPReg + FoxMFReceiver. + SendNumArgsReg := SendNumArgsReg+ReceiverIndex. + [ClassReg := ClassReg - wordSize. + backEnd hasLinkRegister + ifTrue: [ClassReg > SPReg] + ifFalse: [ClassReg >= SPReg]] whileTrue: + [receiver[SendNumArgsReg] := *ClassReg. + SendNumArgsReg := SendNumArgsReg + 1]]" + coInterpreter marryFrameCopiesTemps ifFalse: + [cogit MoveCq: objectMemory nilObject R: TempReg]. + cogit + MoveR: FPReg R: ClassReg; + AddCq: FoxMFReceiver R: ClassReg; + AddCq: ReceiverIndex + 1 + (objectMemory baseHeaderSize / objectMemory wordSize) R: SendNumArgsReg. + loopHead := + cogit SubCq: objectMemory wordSize R: ClassReg. + cogit CmpR: SPReg R: ClassReg. + "If on a CISC there's a retpc for the trampoline call on top of stack; if on a RISC there isn't." + exit := cogit backEnd hasLinkRegister + ifTrue: [cogit JumpBelow: 0] + ifFalse: [cogit JumpBelowOrEqual: 0]. + coInterpreter marryFrameCopiesTemps ifTrue: + [cogit MoveMw: 0 r: ClassReg R: TempReg]. + cogit + MoveR: TempReg Xwr: SendNumArgsReg R: ReceiverResultReg; + AddCq: 1 R: SendNumArgsReg; + Jump: loopHead. + exit jmpTarget: cogit Label. + + cogit RetN: 0. + + jumpNeedScavenge jmpTarget: cogit Label. + cogit backEnd saveAndRestoreLinkRegAround: + [cogit CallRT: ceScheduleScavengeTrampoline]. + cogit Jump: continuation. + ^0!
Item was added: + ----- Method: CogObjectRepresentationForSpur>>genLoadHeaderIntoNewInstance: (in category 'initialization') ----- + genLoadHeaderIntoNewInstance: header + "Generate the instructions to move the constant header into a new instance pointed to by ReceiverResultReg." + ^self subclassResponsibility!
Item was changed: ----- Method: CogObjectRepresentationForSpur>>genSetSmallIntegerTagsIn: (in category 'compile abstract instructions') ----- genSetSmallIntegerTagsIn: scratchReg + cogit OrCq: 1 R: scratchReg. + ^0! - self subclassResponsibility!
Item was added: + ----- Method: CogX64Compiler>>hasThreeAddressArithmetic (in category 'testing') ----- + hasThreeAddressArithmetic + "Answer if the receiver supports three-address arithmetic instructions" + <inline: true> + ^false!
vm-dev@lists.squeakfoundation.org