Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1147.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.1147 Author: eem Time: 1 April 2015, 2:52:03.518 pm UUID: 0fd3920d-c904-484f-b436-e6563dce31c2 Ancestors: VMMaker.oscog-eem.1146
Spur: Make sure that all stacked values are followed in CoInterpreter>>makeBaseFrameFor:
Newspeak: Unstub ceSelfSend:to:numArgs:. Nuke the obsolete NewspeakV3PlusClosures bytecode table initializers.
Eliminate some compiler warnings.
=============== Diff against VMMaker.oscog-eem.1146 ===============
Item was changed: ----- Method: CoInterpreter>>ceSelfSend:to:numArgs: (in category 'trampolines') ----- ceSelfSend: selector to: rcvr numArgs: numArgs "Entry-point for an unlinked self send in a CogMethod. Smalltalk stack looks like receiver args head sp -> sender return pc If an MNU then defer to handleMNUInMachineCodeTo:... which will dispatch the MNU and may choose to allocate a closed PIC with a fast MNU dispatch for this send. Otherwise attempt to link the send site as efficiently as possible. All link attempts may fail; e.g. because we're out of code memory.
Continue execution via either executeMethod or interpretMethodFromMachineCode: depending on whether the target method is cogged or not." <api> <option: #NewspeakVM> | classTag errSelIdx cogMethod | <inline: false> <var: #cogMethod type: #'CogMethod *'> <var: #newCogMethod type: #'CogMethod *'> - true ifTrue: [^self ceSend: selector super: 0 to: rcvr numArgs: numArgs]. "self printExternalHeadFrame" "self printStringOf: selector" cogit assertCStackWellAligned. self assert: (objectMemory addressCouldBeOop: rcvr). self sendBreakpoint: selector receiver: rcvr. classTag := objectMemory fetchClassTagOf: rcvr. argumentCount := numArgs. (self lookupInMethodCacheSel: selector classTag: classTag) ifTrue:"check for coggability because method is in the cache" [self ifAppropriateCompileToNativeCode: newMethod selector: selector] ifFalse: [(objectMemory isOopForwarded: selector) ifTrue: [^self ceSelfSend: (self handleForwardedSelectorFaultFor: selector) to: rcvr numArgs: numArgs]. (objectMemory isForwardedClassTag: classTag) ifTrue: [^self ceSelfSend: selector to: (self handleForwardedSendFaultForReceiver: rcvr stackDelta: 1 "skip return pc") numArgs: numArgs]. messageSelector := selector. (errSelIdx := self lookupMethodNoMNUEtcInClass: (objectMemory classForClassTag: classTag)) ~= 0 ifTrue: [self handleMNU: errSelIdx InMachineCodeTo: rcvr classForMessage: (objectMemory classForClassTag: classTag). self assert: false "NOTREACHED"]]. "Method found and has a cog method. Attempt to link to it." (self maybeMethodHasCogMethod: newMethod) ifTrue: [cogMethod := self cogMethodOf: newMethod. cogMethod selector = objectMemory nilObject ifTrue: [cogit setSelectorOf: cogMethod to: selector] ifFalse: ["Deal with anonymous accessors, e.g. in Newspeak. The cogMethod may not have the correct selector. If not, try and compile a new method with the correct selector." cogMethod selector ~= selector ifTrue: [(cogit cog: newMethod selector: selector) ifNotNil: [:newCogMethod| cogMethod := newCogMethod]]]. cogMethod selector = selector ifTrue: [cogit linkSendAt: (stackPages longAt: stackPointer) in: (self mframeHomeMethod: framePointer) to: cogMethod offset: cogit selfSendEntryOffset receiver: rcvr]. instructionPointer := self popStack. self executeNewMethod. self assert: false "NOTREACHED"]. instructionPointer := self popStack. ^self interpretMethodFromMachineCode "NOTREACHED"!
Item was changed: ----- Method: CoInterpreter>>followForwardingPointersInStackZone: (in category 'object memory support') ----- followForwardingPointersInStackZone: theBecomeEffectsFlags "Spur's become: is lazy, turning the becommed object into a forwarding object to the other. The read-barrier is minimised by arranging that forwarding pointers will fail a method cache probe, since notionally objects' internals are accessed only via sending messages to them, the exception is primitives that access the internals of the non-receiver argument(s). To avoid a read barrier on inst var fetch we scan the receivers in the stack zone and follow any forwarded ones. This is way cheaper than scanning all of memory as in the old become.
Override to handle machine code frames, and to handle the lack of an explicit read barrier on super sends. With most super send implementations (not Newspeak's absent super bytecodes) self, the receiver of the super send, is pushed before any arguments. So if self is becommed during argument marshalling, e.g. super doSomethingWith: (self become: self somethingElse) then a stale forwarded reference to self could be left on the stack. In the StackInterpreter we deal with this with an explicit read barrier on supersend. In the CoInterpreter we deal with it by following all non-argument stack contents." | theIPPtr | <inline: false> <var: #thePage type: #'StackPage *'> <var: #theSP type: #'char *'> <var: #theFP type: #'char *'> + <var: #offset type: #'char *'> <var: #callerFP type: #'char *'> <var: #theIPPtr type: #usqInt>
self externalWriteBackHeadFramePointers.
(theBecomeEffectsFlags anyMask: BecameCompiledMethodFlag) ifTrue: [(objectMemory isForwarded: method) ifTrue: [theIPPtr := instructionPointer - method. method := objectMemory followForwarded: method. instructionPointer := method + theIPPtr]. (objectMemory isOopForwarded: newMethod) ifTrue: [newMethod := objectMemory followForwarded: newMethod]].
self assert: stackPage ~= 0. 0 to: numStackPages - 1 do: [:i| | thePage theSP theFP callerFP oop offset | thePage := stackPages stackPageAt: i. thePage isFree ifFalse: [theSP := thePage headSP. theFP := thePage headFP. "Skip the instruction pointer on top of stack of inactive pages." thePage = stackPage ifTrue: [theIPPtr := 0] ifFalse: [theIPPtr := theSP asUnsignedInteger. theSP := theSP + objectMemory wordSize]. [self assert: (thePage addressIsInPage: theFP). self assert: (theIPPtr = 0 or: [thePage addressIsInPage: theIPPtr asVoidPointer]). offset := self frameStackedReceiverOffset: theFP. [theSP <= offset] whileTrue: [oop := stackPages longAt: theSP. (objectMemory isOopForwarded: oop) ifTrue: [stackPages longAt: theSP put: (objectMemory followForwarded: oop)]. theSP := theSP + objectMemory wordSize]. ((self frameHasContext: theFP) and: [(objectMemory isForwarded: (self frameContext: theFP))]) ifTrue: [stackPages longAt: theFP + FoxThisContext put: (objectMemory followForwarded: (self frameContext: theFP))]. (self isMachineCodeFrame: theFP) ifTrue: [oop := stackPages longAt: theFP + FoxMFReceiver. (objectMemory isOopForwarded: oop) ifTrue: [stackPages longAt: theFP + FoxMFReceiver put: (objectMemory followForwarded: oop)]. oop := (self mframeHomeMethod: theFP) methodObject. self assert: (objectMemory isForwarded: oop) not] ifFalse: [oop := stackPages longAt: theFP + FoxIFReceiver. (objectMemory isOopForwarded: oop) ifTrue: [stackPages longAt: theFP + FoxIFReceiver put: (objectMemory followForwarded: oop)]. oop := self iframeMethod: theFP. (objectMemory isForwarded: oop) ifTrue: [| newOop delta | newOop := objectMemory followForwarded: oop. delta := newOop - oop. (theIPPtr ~= 0 and: [(stackPages longAt: theIPPtr) > oop]) ifTrue: [stackPages longAt: theIPPtr put: (stackPages longAt: theIPPtr) + delta]. stackPages longAt: theFP + FoxIFSavedIP put: (stackPages longAt: theFP + FoxIFSavedIP) + delta. stackPages longAt: theFP + FoxMethod put: (oop := newOop)]]. (callerFP := self frameCallerFP: theFP) ~= 0] whileTrue: [theIPPtr := (theFP + FoxCallerSavedIP) asUnsignedInteger. theSP := theIPPtr + objectMemory wordSize. theFP := callerFP]. "And finally follow the saved context and the caller context." theSP := thePage baseAddress - objectMemory wordSize. [theSP <= thePage baseAddress] whileTrue: [oop := stackPages longAt: theSP. (objectMemory isForwarded: oop) ifTrue: [stackPages longAt: theSP put: (objectMemory followForwarded: oop)]. theSP := theSP + objectMemory wordSize]]]!
Item was changed: ----- Method: CoInterpreter>>makeBaseFrameFor: (in category 'frame access') ----- makeBaseFrameFor: aContext "<Integer>" "Marry aContext with the base frame of a new stack page. Build the base frame to reflect the context's state. Answer the new page. Override to hold the caller context in a different place, In the StackInterpreter we use the caller saved ip, but in the Cog VM caller saved ip is the ceBaseReturn: trampoline. Simply hold the caller context in the first word of the stack." <returnTypeC: #'StackPage *'> | page pointer theMethod theIP numArgs stackPtrIndex maybeClosure rcvr | <inline: false> <var: #page type: #'StackPage *'> <var: #pointer type: #'char *'> <var: #cogMethod type: #'CogMethod *'> "theIP must be typed as signed because it is assigned ceCannotResumePC and so maybe implicitly typed as unsigned." <var: #theIP type: #sqInt> self assert: (objectMemory isContext: aContext). self assert: (self isSingleContext: aContext). self assert: (objectMemory goodContextSize: aContext). theIP := objectMemory fetchPointer: InstructionPointerIndex ofObject: aContext. self assert: HasBeenReturnedFromMCPC signedIntFromLong < 0. theIP := (objectMemory isIntegerObject: theIP) ifTrue: [objectMemory integerValueOf: theIP] ifFalse: [HasBeenReturnedFromMCPC]. theMethod := objectMemory followObjField: MethodIndex ofObject: aContext. page := self newStackPage. "first word on stack is caller context of base frame" stackPages longAt: (pointer := page baseAddress) + put: (objectMemory followObjField: SenderIndex ofObject: aContext). - put: (objectMemory fetchPointer: SenderIndex ofObject: aContext). "second word is the context itself; needed for cannotReturn processing; see ceBaseReturn:." stackPages longAt: (pointer := pointer - objectMemory wordSize) put: aContext. rcvr := objectMemory followField: ReceiverIndex ofObject: aContext. "If the frame is a closure activation then the closure should be on the stack in the pushed receiver position (closures receiver the value[:value:] messages). Otherwise it should be the receiver proper." maybeClosure := objectMemory fetchPointer: ClosureIndex ofObject: aContext. maybeClosure ~= objectMemory nilObject ifTrue: [numArgs := self argumentCountOfClosure: maybeClosure. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: maybeClosure] ifFalse: [| header | header := objectMemory methodHeaderOf: theMethod. numArgs := self argumentCountOfMethodHeader: header. "If this is a synthetic context its IP could be pointing at the CallPrimitive opcode. If so, skip it." (theIP signedIntFromLong > 0 and: [(self methodHeaderHasPrimitive: header) and: [theIP = (1 + (objectMemory lastPointerOfMethodHeader: header))]]) ifTrue: [theIP := theIP + (self sizeOfCallPrimitiveBytecode: header)]. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: rcvr]. "Put the arguments on the stack" 1 to: numArgs do: [:i| stackPages longAt: (pointer := pointer - objectMemory wordSize) put: (objectMemory fetchPointer: ReceiverIndex + i ofObject: aContext)]. "saved caller ip is base return trampoline" stackPages longAt: (pointer := pointer - objectMemory wordSize) put: cogit ceBaseFrameReturnPC. "base frame's saved fp is null" stackPages longAt: (pointer := pointer - objectMemory wordSize) put: 0. "N.B. Don't set the baseFP, which marks the page as in use, until after ensureMethodIsCogged: and/or instructionPointer:forContext:frame:. These can cause a compiled code compaction which, if marked as in use, will examine this partially initialized page and crash." page headFP: pointer. "Create either a machine code frame or an interpreter frame based on the pc. If the pc is -ve it is a machine code pc and so we produce a machine code frame. If +ve an interpreter frame. N.B. Do *not* change this to try and map from a bytecode pc to a machine code frame under any circumstances. See ensureContextIsExecutionSafeAfterAssignToStackPointer:" theIP signedIntFromLong < 0 ifTrue: [| cogMethod | "Since we would have to generate a machine-code method to be able to map the native pc anyway we should create a native method and native frame." cogMethod := self ensureMethodIsCogged: theMethod. theMethod := cogMethod asInteger. maybeClosure ~= objectMemory nilObject ifTrue: ["If the pc is the special HasBeenReturnedFromMCPC pc set the pc appropriately so that the frame stays in the cannotReturn: state." theIP = HasBeenReturnedFromMCPC signedIntFromLong ifTrue: [theMethod := (cogit findMethodForStartBcpc: (self startPCOfClosure: maybeClosure) inHomeMethod: (self cCoerceSimple: theMethod to: #'CogMethod *')) asInteger. theMethod = 0 ifTrue: [self error: 'cannot find machine code block matching closure''s startpc']. theIP := cogit ceCannotResumePC] ifFalse: [self assert: (theIP signedBitShift: -16) < -1. "See contextInstructionPointer:frame:" theMethod := theMethod - ((theIP signedBitShift: -16) * cogit blockAlignment). theIP := theMethod - theIP signedIntFromShort]. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: theMethod + MFMethodFlagHasContextFlag + MFMethodFlagIsBlockFlag] ifFalse: [self assert: (theIP signedBitShift: -16) >= -1. "If the pc is the special HasBeenReturnedFromMCPC pc set the pc appropriately so that the frame stays in the cannotReturn: state." theIP := theIP = HasBeenReturnedFromMCPC signedIntFromLong ifTrue: [cogit ceCannotResumePC] ifFalse: [theMethod asInteger - theIP]. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: theMethod + MFMethodFlagHasContextFlag]. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: aContext] ifFalse: [stackPages longAt: (pointer := pointer - objectMemory wordSize) put: theMethod. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: aContext. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: (self encodeFrameFieldHasContext: true isBlock: maybeClosure ~= objectMemory nilObject numArgs: numArgs). stackPages longAt: (pointer := pointer - objectMemory wordSize) put: 0. "FoxIFSavedIP" theIP := self iframeInstructionPointerForIndex: theIP method: theMethod]. page baseFP: page headFP. self assert: (self frameHasContext: page baseFP). self assert: (self frameNumArgs: page baseFP) == numArgs. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: rcvr. stackPtrIndex := self quickFetchInteger: StackPointerIndex ofObject: aContext. self assert: ReceiverIndex + stackPtrIndex < (objectMemory lengthOf: aContext). + "Copy the non-argument temps and stack contents to the stack. + Follow these to avoid any stale self references from super sends." numArgs + 1 to: stackPtrIndex do: [:i| stackPages longAt: (pointer := pointer - objectMemory wordSize) + put: (objectMemory followField: ReceiverIndex + i ofObject: aContext)]. - put: (objectMemory fetchPointer: ReceiverIndex + i ofObject: aContext)]. "top of stack is the instruction pointer" stackPages longAt: (pointer := pointer - objectMemory wordSize) put: theIP. page headSP: pointer. self assert: (self context: aContext hasValidInversePCMappingOf: theIP in: page baseFP).
"Mark context as married by setting its sender to the frame pointer plus SmallInteger tags and the InstructionPointer to the saved fp (which ensures correct alignment w.r.t. the frame when we check for validity) plus SmallInteger tags." objectMemory storePointerUnchecked: SenderIndex ofObject: aContext withValue: (self withSmallIntegerTags: page baseFP). objectMemory storePointerUnchecked: InstructionPointerIndex ofObject: aContext withValue: (self withSmallIntegerTags: 0). self assert: (objectMemory isIntegerObject: (objectMemory fetchPointer: SenderIndex ofObject: aContext)). self assert: (self frameOfMarriedContext: aContext) = page baseFP. self assert: (self validStackPageBaseFrame: page). ^page!
Item was changed: ----- Method: Cogit class>>initializeBytecodeTable (in category 'class initialization') ----- initializeBytecodeTable "SimpleStackBasedCogit initializeBytecodeTableWith: Dictionary new" "StackToRegisterMappingCogit initializeBytecodeTableWith: Dictionary new"
| initializer | initializer := initializationOptions at: #bytecodeTableInitializer ifAbsent: [NewspeakVM ifTrue: + [MULTIPLEBYTECODESETS + ifTrue: [#initializeBytecodeTableForSqueakV3PlusClosuresNewspeakV4Hybrid] + ifFalse: [#initializeBytecodeTableForNewspeakV4]] - [(initializationOptions at: #SpurObjectMemory ifAbsent: false) - ifTrue: - [MULTIPLEBYTECODESETS - ifTrue: [#initializeBytecodeTableForSqueakV3PlusClosuresNewspeakV4Hybrid] - ifFalse: [#initializeBytecodeTableForNewspeakV4]] - ifFalse: - [MULTIPLEBYTECODESETS - ifTrue: [#initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid] - ifFalse: [#initializeBytecodeTableForNewspeakV3PlusClosures]]] ifFalse: [#initializeBytecodeTableForSqueakV3PlusClosures]]. "Now make sure all classes in the hierarchy have initialized to the same bytecode table." (self withAllSuperclasses copyUpTo: Cogit) reverseDo: "i.e. exclude Cogit" [:cogitClass| cogitClass perform: initializer]!
Item was removed: - ----- Method: Cogit class>>initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid (in category 'class initialization') ----- - initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid - "SimpleStackBasedCogit initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid" - "StackToRegisterMappingCogit initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid" - - | v3Table v4Table | - "N.B. Must do it backwards to evaluate AltBlockCreationBytecodeSize & BlockCreationBytecodeSize et al correctly." - self initializeBytecodeTableForNewspeakV4. - v4Table := generatorTable. - AltBlockCreationBytecodeSize := BlockCreationBytecodeSize. - AltNSSendIsPCAnnotated := NSSendIsPCAnnotated. - AltFirstSpecialSelector := FirstSpecialSelector. - self initializeBytecodeTableForNewspeakV3PlusClosures. - v3Table := generatorTable. - generatorTable := CArrayAccessor on: v3Table object, v4Table object!
Item was changed: ----- Method: Cogit>>genEnilopmartFor:and:and:forCall:called: (in category 'initialization') ----- genEnilopmartFor: regArg1 and: regArg2 and: regArg3 forCall: forCall called: trampolineName "An enilopmart (the reverse of a trampoline) is a piece of code that makes the system-call-like transition from the C runtime into generated machine code. The desired arguments and entry-point are pushed on a stackPage's stack. The enilopmart pops off the values to be loaded into registers and then executes a return instruction to pop off the entry-point and jump to it.
BEFORE AFTER (stacks grow down) whatever stackPointer -> whatever target address => reg1 = reg1val, etc reg1val pc = target address reg2val stackPointer -> reg3val" + + <var: #trampolineName type: #'char *'> <returnTypeC: #'void (*genEnilopmartForandandforCallcalled(sqInt regArg1, sqInt regArg2, sqInt regArg3, sqInt forCall, sqInt trampolineName))(void)'> + | size endAddress enilopmart | opcodeIndex := 0. backEnd maybeEstablishVarBase. "Must happen first; value may be used in genLoadStackPointers" backEnd genLoadStackPointers. regArg3 ifNotNil: [self PopR: regArg3]. regArg2 ifNotNil: [self PopR: regArg2]. self PopR: regArg1. self genEnilopmartReturn: forCall. self computeMaximumSizes. size := self generateInstructionsAt: methodZoneBase. endAddress := self outputInstructionsAt: methodZoneBase. self assert: methodZoneBase + size = endAddress. enilopmart := methodZoneBase. methodZoneBase := self alignUptoRoutineBoundary: endAddress. backEnd nopsFrom: endAddress to: methodZoneBase - 1. self recordGeneratedRunTime: trampolineName address: enilopmart. ^self cCoerceSimple: enilopmart to: #'void (*)(void)'!
Item was changed: ----- Method: StackInterpreter class>>initializeBytecodeTable (in category 'initialization') ----- initializeBytecodeTable "StackInterpreter initializeBytecodeTable"
(initializationOptions at: #bytecodeTableInitializer ifAbsent: nil) ifNotNil: [:initalizer| ^self perform: initalizer].
NewspeakVM ifTrue: + [^MULTIPLEBYTECODESETS + ifTrue: [self initializeBytecodeTableForSqueakV3PlusClosuresNewspeakV4Hybrid] + ifFalse: [self initializeBytecodeTableForNewspeakV4]]. - [^(initializationOptions at: #SpurObjectMemory ifAbsent: false) - ifTrue: - [MULTIPLEBYTECODESETS - ifTrue: [self initializeBytecodeTableForSqueakV3PlusClosuresNewspeakV4Hybrid] - ifFalse: [self initializeBytecodeTableForNewspeakV4]] - ifFalse: - [MULTIPLEBYTECODESETS - ifTrue: [self initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid] - ifFalse: [self initializeBytecodeTableForNewspeakV3PlusClosures]]].
^self initializeBytecodeTableForSqueakV3PlusClosures!
Item was removed: - ----- Method: StackInterpreter class>>initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid (in category 'initialization') ----- - initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid - "StackInterpreter initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid" - - | v3Table v4Table | - self initializeBytecodeTableForNewspeakV4. - v4Table := BytecodeTable. - AltBytecodeEncoderClassName := BytecodeEncoderClassName. - AltLongStoreBytecode := LongStoreBytecode. - self initializeBytecodeTableForNewspeakV3PlusClosures. - v3Table := BytecodeTable. - BytecodeTable := v3Table, v4Table!
Item was changed: ----- Method: StackInterpreter>>makeBaseFrameFor: (in category 'frame access') ----- makeBaseFrameFor: aContext "<Integer>" "Marry aContext with the base frame of a new stack page. Build the base frame to reflect the context's state. Answer the new page." <returnTypeC: #'StackPage *'> | page pointer theMethod theIP numArgs stackPtrIndex maybeClosure rcvr | <inline: false> <var: #page type: #'StackPage *'> <var: #pointer type: #'char *'> self assert: (objectMemory isContext: aContext). self assert: (self isSingleContext: aContext). self assert: (objectMemory goodContextSize: aContext). page := self newStackPage. pointer := page baseAddress. theIP := objectMemory fetchPointer: InstructionPointerIndex ofObject: aContext. theMethod := objectMemory followObjField: MethodIndex ofObject: aContext. (objectMemory isIntegerObject: theIP) ifFalse: [self error: 'context is not resumable']. theIP := objectMemory integerValueOf: theIP. rcvr := objectMemory followField: ReceiverIndex ofObject: aContext. "If the frame is a closure activation then the closure should be on the stack in the pushed receiver position (closures receiver the value[:value:] messages). Otherwise it should be the receiver proper." maybeClosure := objectMemory followField: ClosureIndex ofObject: aContext. maybeClosure ~= objectMemory nilObject ifTrue: [numArgs := self argumentCountOfClosure: maybeClosure. stackPages longAt: pointer put: maybeClosure] ifFalse: [| header | header := objectMemory methodHeaderOf: theMethod. numArgs := self argumentCountOfMethodHeader: header. "If this is a synthetic context its IP could be pointing at the CallPrimitive opcode. If so, skip it." (theIP signedIntFromLong > 0 and: [(self methodHeaderHasPrimitive: header) and: [theIP = (1 + (objectMemory lastPointerOfMethodHeader: header))]]) ifTrue: [theIP := theIP + (self sizeOfCallPrimitiveBytecode: header)]. stackPages longAt: pointer put: rcvr]. "Put the arguments on the stack" 1 to: numArgs do: [:i| stackPages longAt: (pointer := pointer - objectMemory wordSize) put: (objectMemory fetchPointer: ReceiverIndex + i ofObject: aContext)]. "saved caller ip is sender context in base frame" stackPages longAt: (pointer := pointer - objectMemory wordSize) + put: (objectMemory followObjField: SenderIndex ofObject: aContext). - put: (objectMemory fetchPointer: SenderIndex ofObject: aContext). "base frame's saved fp is null" stackPages longAt: (pointer := pointer - objectMemory wordSize) put: 0. page baseFP: pointer; headFP: pointer. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: theMethod. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: (self encodeFrameFieldHasContext: true isBlock: maybeClosure ~= objectMemory nilObject numArgs: numArgs). self assert: (self frameHasContext: page baseFP). self assert: (self frameNumArgs: page baseFP) == numArgs. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: aContext. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: rcvr. stackPtrIndex := self quickFetchInteger: StackPointerIndex ofObject: aContext. self assert: ReceiverIndex + stackPtrIndex < (objectMemory lengthOf: aContext). numArgs + 1 to: stackPtrIndex do: [:i| stackPages longAt: (pointer := pointer - objectMemory wordSize) put: (objectMemory fetchPointer: ReceiverIndex + i ofObject: aContext)]. "top of stack is the instruction pointer" theIP := self iframeInstructionPointerForIndex: theIP method: theMethod. stackPages longAt: (pointer := pointer - objectMemory wordSize) put: theIP. page headSP: pointer. self assert: (self context: aContext hasValidInversePCMappingOf: theIP in: page baseFP).
"Mark context as married by setting its sender to the frame pointer plus SmallInteger tags and the InstructionPointer to the saved fp (which ensures correct alignment w.r.t. the frame when we check for validity) plus SmallInteger tags." objectMemory storePointerUnchecked: SenderIndex ofObject: aContext withValue: (self withSmallIntegerTags: page baseFP). objectMemory storePointerUnchecked: InstructionPointerIndex ofObject: aContext withValue: (self withSmallIntegerTags: 0). self assert: (objectMemory isIntegerObject: (objectMemory fetchPointer: SenderIndex ofObject: aContext)). self assert: (self frameOfMarriedContext: aContext) = page baseFP. self assert: (self validStackPageBaseFrame: page). ^page!
Item was removed: - ----- Method: StackToRegisterMappingCogit class>>initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid (in category 'class initialization') ----- - initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid - "StackToRegisterMappingCogit initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid" - - super initializeBytecodeTableForNewspeakV3PlusClosuresNewspeakV4Hybrid. - numPushNilsFunction := #v3or4:Num:Push:Nils:. - pushNilSizeFunction := #v3or4PushNilSize:!
vm-dev@lists.squeakfoundation.org