Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1847.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.1847 Author: eem Time: 26 April 2016, 8:49:48.651885 am UUID: cc80350d-f8a9-47e6-960f-a0e31e20d725 Ancestors: VMMaker.oscog-cb.1846
primitiveVoidVMStateForMethod: ensureAllContextsWithMethodHaveBytecodePCs: should widow contexts, otherwise "separated" but not yet widowed contexts may persist..
Cogit: reorder annotation constants to simplify isPCMappedAnnotation:.
Simulation: fix receivers of integerObjectOf: in recent multiply prim changes.
=============== Diff against VMMaker.oscog-cb.1846 ===============
Item was changed: ----- Method: CoInterpreter>>ensureAllContextsWithMethodHaveBytecodePCs: (in category 'frame access') ----- ensureAllContextsWithMethodHaveBytecodePCs: methodObj "Map all native pcs to bytecoded pcs in all contexts on methodObj. Used to implement primitiveVoidVMStateForMethod." objectMemory allObjectsDo: [:oop| ((objectMemory isContextNonImm: oop) and: [(objectMemory fetchPointer: MethodIndex ofObject: oop) = methodObj]) ifTrue: [(self isMarriedOrWidowedContext: oop) ifTrue: + "Since any machine-code frame activations of the method have been divorced + there should only be interpreted activations of marriecd contexts." + [(self isWidowedContext: oop) ifFalse: + [self deny: (self isMachineCodeFrame: (self frameOfMarriedContext: oop))]] - [(self checkIsStillMarriedContext: oop currentFP: stackPage headFP) ifTrue: - [self assert: (self isMachineCodeFrame: (self frameOfMarriedContext: oop)) not]] ifFalse: [self ensureContextHasBytecodePC: oop]]]!
Item was changed: ----- Method: Cogit class>>initializeAnnotationConstants (in category 'class initialization') ----- initializeAnnotationConstants "These form the method map for a cog method. The map defines which addresses in a machine code method are ones with important functions, such as being a send site or being a reference to a heap object. Each annotated instruction has a byte in the map, and each byte in the map has two parts. In the least signficant bits are a distance in codeGranularity units from the start of the method or the previous map entry, except for the IsAnnotationExtension type. In the most signficant bits are the type of annotation at the point reached. A null byte ends the map. The first mapped location is a distance from the cmNoCheckEntryOffset.
The map occurs at the end of a method (*), in reverse, so that its start is found by adding the method's block size. If the distance between two mapped instructions will not fit in the displacement field then one or more displacement entries are placed in the map to bridge the gap. There is a * 32 displacement units type for spanning large gaps. The displacements are in codeGranularity units so that processors like e.g. ARM, with 4-byte instructions, do not have overly large maps. In [practice maps are very compact, but they should be as quick to navigate as possible, and hence be as compact as possible.
There is only one kind of call annotation that serves for all calls from machine code. There are several kinds of call, sends, super sends, calls of the generated run-time, and direct calls of primitive functions in the interpreter. These need different treatment at different times. For example, when the send cache is flushed or the method zone is shrunk some sends must be unlinked and some sends must be relocated. But to be able to parse bytecoded methods and match their pcs with corresponding machine code pcs the map needs to differentiate between sends and run-time calls.
Sends can be distinguished from run-time or direct primitive calls based on address; only sends have their target between methodZoneBase and methodZone freeStart. We used to distinguish normal sends from super sends based on alignment of entry-point, because normal sends link to the checked entry-point, whereas super sends link to the unchecked entry-point, and both entry points have different alignments. But now we use the IsAnnotationExtension to label sends other than normal sends. For these ``exotic'' sends there is both an IsAnnotationExtension annotation and an IsSendCall annotation.
While run-time calls can be distinguished from direct primitive calls on the basis of address there is no need to do so. They are merely calls to locations that don't move during method zone compaction.
Absolute PC references are used for method references and counter references. These are references from within a particular method to absolute pcs in that same method that must be relocated when the method moves." "self initializeAnnotationConstants"
AnnotationShift := 5. IsDisplacementX2N := 0. "N.B. A 0 byte ends the map" IsAnnotationExtension := 1. "Used to extend IsSendCall with different codes for exotic send types." IsObjectReference := 2. IsAbsPCReference := 3. + IsRelativeCall := 4. + HasBytecodePC := 5. - HasBytecodePC := 4. - IsRelativeCall := 5. IsNSSendCall := NewspeakVM ifTrue: [6]. IsSendCall := 7. "These are formed by combining IsSendCall and IsAnnotationExtension annotations." IsSuperSend := 8. IsDirectedSuperSend := 9. IsNSSelfSend := NewspeakVM ifTrue: [10]. IsNSDynamicSuperSend := NewspeakVM ifTrue: [11]. IsNSImplicitReceiverSend := NewspeakVM ifTrue: [12].
DisplacementMask := (1 << AnnotationShift) - 1. DisplacementX2N := IsDisplacementX2N << AnnotationShift. FirstAnnotation := IsObjectReference << AnnotationShift. MaxX2NDisplacement := DisplacementMask << AnnotationShift.
MapEnd := 0.
AnnotationConstantNames := #( IsDisplacementX2N IsAnnotationExtension IsObjectReference IsAbsPCReference HasBytecodePC IsRelativeCall IsNSSendCall IsSendCall IsSuperSend IsDirectedSuperSend IsNSSelfSend IsNSDynamicSuperSend IsNSImplicitReceiverSend). AnnotationsWithBytecodePCs := #(HasBytecodePC IsNSSendCall IsSendCall IsSuperSend IsDirectedSuperSend IsNSSelfSend IsNSDynamicSuperSend IsNSImplicitReceiverSend)!
Item was changed: ----- Method: Cogit>>isPCMappedAnnotation: (in category 'method map') ----- isPCMappedAnnotation: annotation + "See Cogit class>>initializeAnnotationConstants" <inline: true> + ^annotation >= HasBytecodePC! - ^annotation >= IsSendCall - or: [annotation = HasBytecodePC - or: [NewspeakVM and: [annotation = IsNSSendCall]]]!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveMultiply (in category 'arithmetic integer primitives') ----- primitiveMultiply | integerRcvr integerArg integerResult overflow | integerRcvr := self stackIntegerValue: 1. integerArg := self stackIntegerValue: 0. self successful ifTrue: [overflow := integerRcvr > 0 ifTrue: [integerArg > 0 ifTrue: [integerRcvr > (objectMemory maxSmallInteger / integerArg)] ifFalse: [integerArg < (objectMemory minSmallInteger / integerRcvr)]] ifFalse: [integerArg > 0 ifTrue: [integerRcvr < (objectMemory minSmallInteger / integerArg)] ifFalse: [(integerRcvr < 0) and: [integerArg < (objectMemory maxSmallInteger / integerRcvr)]]]. overflow ifTrue: [self primitiveFail] ifFalse: [integerResult := integerRcvr * integerArg. + self pop: 2 thenPush: (objectMemory integerObjectOf: integerResult)]]! - self pop: 2 thenPush: (self integerObjectOf: integerResult)]]!
Item was changed: ----- Method: StackInterpreter>>bytecodePrimMultiply (in category 'common selector sends') ----- bytecodePrimMultiply | rcvr arg result overflow oop | rcvr := self internalStackValue: 1. arg := self internalStackValue: 0. (objectMemory areIntegers: rcvr and: arg) ifTrue: [rcvr := objectMemory integerValueOf: rcvr. arg := objectMemory integerValueOf: arg. overflow := rcvr > 0 ifTrue: [arg > 0 ifTrue: [rcvr > (objectMemory maxSmallInteger / arg)] ifFalse: [arg < (objectMemory minSmallInteger / rcvr)]] ifFalse: [arg > 0 ifTrue: [rcvr < (objectMemory minSmallInteger / arg)] ifFalse: [(rcvr < 0) and: [arg < (objectMemory maxSmallInteger / rcvr)]]]. overflow ifFalse: [result := rcvr * arg. + oop := objectMemory integerObjectOf: result. - oop := self integerObjectOf: result. self internalPop: 2 thenPush: oop. ^self fetchNextBytecode "success"]] ifFalse: [self initPrimCall. self externalizeIPandSP. self primitiveFloatMultiply: rcvr byArg: arg. self internalizeIPandSP. self successful ifTrue: [^ self fetchNextBytecode "success"]].
messageSelector := self specialSelector: 8. argumentCount := 1. self normalSend!
vm-dev@lists.squeakfoundation.org