[Vm-dev] VM Maker: VMMaker.oscog-eem.2555.mcz

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Fri Sep 6 20:05:35 UTC 2019


Superb :) I'm very happy to not even have tried to do it

Le ven. 6 sept. 2019 à 21:56, <commits at source.squeak.org> a écrit :

>
> Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
> http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2555.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-eem.2555
> Author: eem
> Time: 6 September 2019, 12:55:40.085336 pm
> UUID: 4c3d555e-9970-4e10-9620-8011a7a63e4b
> Ancestors: VMMaker.oscog-nice.2554
>
> Implement discarding methods with machine code primitives on toggling
> primitiveDoMixedArithmetic.
>
> Next up, adding primitiveDoMixedArithmetic as a flag saved in the image
> header.
>
> =============== Diff against VMMaker.oscog-nice.2554 ===============
>
> Item was added:
> + ----- Method:
> CoInterpreter>>divorceAMachineCodeFrameWithMachineCodePrimitiveMethodIn:
> (in category 'frame access') -----
> + divorceAMachineCodeFrameWithMachineCodePrimitiveMethodIn: aStackPage
> +       "Divorce at most one frame in the current page (since the divorce
> may cause the page to be split)
> +        and answer whether a frame was divorced."
> +       <var: #aStackPage type: #'StackPage *'>
> +       | theFP calleeFP theSP theContext |
> +       <var: #aStackPage type: #'StackPage *'>
> +       <var: #theFP type: #'char *'>
> +       <var: #calleeFP type: #'char *'>
> +       <var: #theSP type: #'char *'>
> +
> +       theFP := aStackPage headFP.
> +       theSP := aStackPage headSP.
> +       theSP := theSP + objectMemory wordSize. "theSP points at hottest
> item on frame's stack"
> +
> +       [((self isMachineCodeFrame: theFP)
> +         and: [cogit cogMethodHasMachineCodePrim: (self mframeHomeMethod:
> theFP)]) ifTrue:
> +               [theContext := self ensureFrameIsMarried: theFP SP: theSP.
> +                self externalDivorceFrame: theFP andContext: theContext.
> +                ^true].
> +        calleeFP := theFP.
> +        theFP := self frameCallerFP: theFP.
> +        theFP ~= 0] whileTrue:
> +               ["theSP points at stacked hottest item on frame's stack"
> +                theSP := self frameCallerSP: calleeFP].
> +
> +       ^false!
>
> Item was added:
> + ----- Method:
> CoInterpreter>>divorceMachineCodeFramesWithMachineCodePrimitiveMethod (in
> category 'frame access') -----
> + divorceMachineCodeFramesWithMachineCodePrimitiveMethod
> +       | divorcedSome |
> +       [stackPage ~= 0 ifTrue: "This is needed for the assert in
> externalDivorceFrame:andContext:"
> +               [stackPages markStackPageMostRecentlyUsed: stackPage].
> +        "Slang can't currently cope with the lack of the variable here.
> +         Something to do with the preceding statement.  Take it out
> +         and the code is good.  leave it in and we get do { ... }
> while(l1:)"
> +        divorcedSome := self
> divorceSomeFramesWithMachineCodePrimitiveMethod.
> +        divorcedSome] whileTrue!
>
> Item was added:
> + ----- Method:
> CoInterpreter>>divorceSomeFramesWithMachineCodePrimitiveMethod (in category
> 'frame access') -----
> + divorceSomeFramesWithMachineCodePrimitiveMethod
> +       "Divorce at most one frame (since the divorce may cause the
> containing
> +        page to be split) and answer whether a frame was divorced."
> +       <var: #cogMethod type: #'CogMethod *'>
> +       | divorcedSome |
> +       <var: #aPage type: #'StackPage *'>
> +       divorcedSome := false.
> +       0 to: numStackPages - 1 do:
> +               [:i| | aPage |
> +               aPage := stackPages stackPageAt: i.
> +               (stackPages isFree: aPage) ifFalse:
> +                       ["this to avoid assert in
> externalDivorceFrame:andContext:"
> +                        stackPages markStackPageMostRecentlyUsed:
> stackPage.
> +                        (self
> divorceAMachineCodeFrameWithMachineCodePrimitiveMethodIn: aPage) ifTrue:
> +                               [divorcedSome := true]]].
> +       ^divorcedSome!
>
> Item was added:
> + ----- Method:
> CoInterpreter>>ensureAllContextsWithMethodMachineCodePrimitiveMethodHaveBytecodePCs
> (in category 'frame access') -----
> + ensureAllContextsWithMethodMachineCodePrimitiveMethodHaveBytecodePCs
> +       "Map all native pcs to bytecoded pcs in all contexts that have a
> method with a cog method with a machine code primitive.
> +        Used to implement
> flushMethodsWithMachineCodePrimitivesAndContinueAnswering:/vmParameterAt:
> 75 put: aBool."
> +       <inline: true>
> +       objectMemory allObjectsDo:
> +               [:oop| | methodHeader |
> +                (objectMemory isContextNonImm: oop) ifTrue:
> +                       [methodHeader := self rawHeaderOf: (objectMemory
> fetchPointer: MethodIndex ofObject: oop).
> +                        ((self isCogMethodReference: methodHeader)
> +                         and: [cogit cogMethodHasMachineCodePrim: (self
> cCoerceSimple: methodHeader to: #'CogMethod *')]) ifTrue:
> +                               [self widowOrForceToBytecodePC: oop]]]!
>
> Item was added:
> + ----- Method:
> CoInterpreter>>flushMethodsWithMachineCodePrimitivesAndContinueAnswering:
> (in category 'primitive support') -----
> + flushMethodsWithMachineCodePrimitivesAndContinueAnswering: result
> +       "Arrange that any and all cog methods with machine code primitives
> can be and are discarded.
> +        Hence scan contexts and map their PCs to bytecode PCs if
> required, and scan frames, divorcing
> +        the frames of activationsif required.  The continue execution
> answering result.  THIS MUST BE
> +        INVOKED IN THE CONTEXT OF A PRIMITIVE.  It exists to support
> vmParameterAt:put:."
> +       | activeContext theFrame thePage |
> +       <var: #theFrame type: #'char *'>
> +       <var: #thePage type: #'StackPage *'>
> +       activeContext := self ensureFrameIsMarried: framePointer SP:
> stackPointer.
> +       self ensurePushedInstructionPointer.
> +       self externalWriteBackHeadFramePointers.
> +       self divorceMachineCodeFramesWithMachineCodePrimitiveMethod.
> +       self
> ensureAllContextsWithMethodMachineCodePrimitiveMethodHaveBytecodePCs.
> +       cogit unlinkSendsToMachineCodePrimitiveMethodsAndFreeIf: true.
> +
> +       "If flushing led to divorce continue in the interpreter."
> +       (self isStillMarriedContext: activeContext) ifFalse:
> +               [self zeroStackPage. "to avoid assert in
> marryContextInNewStackPageAndInitializeInterpreterRegisters:"
> +                self
> marryContextInNewStackPageAndInitializeInterpreterRegisters: activeContext.
> +               "pop bogus machine-code instructionPointer, arguments and
> receiver"
> +                self pop: argumentCount + 2 thenPush: result.
> +                self siglong: reenterInterpreter jmp: ReturnToInterpreter.
> +                "NOTREACHED"].
> +       "If not, work out where we are and continue"
> +       theFrame := self frameOfMarriedContext: activeContext.
> +       thePage := stackPages stackPageFor: theFrame.
> +       self assert: thePage headFP = theFrame.
> +       self setStackPageAndLimit: thePage.
> +       self setStackPointersFromPage: thePage.
> +       instructionPointer := self popStack.
> +        self pop: argumentCount + 1 thenPush: result!
>
> Item was changed:
>   ----- Method: Cogit>>setHasYoungReferent: (in category 'accessing') -----
>   setHasYoungReferent: boolean
>         "Written this way to allow reak-pointing in the simulator."
>         <cmacro: '(b) (hasYoungReferent = (b))'>
> +       "boolean ifTrue:
> +               [self halt]."
> -       boolean ifTrue:
> -               [self halt].
>         "(hasYoungReferent == false and: [boolean == true]) ifTrue:
>                 [self halt]."
>         hasYoungReferent := boolean!
>
> Item was added:
> + ----- Method: Cogit>>unlinkIfLinkedSend:pc:toMachineCodePrim: (in
> category 'in-line cacheing') -----
> + unlinkIfLinkedSend: annotation pc: mcpc toMachineCodePrim: ignored
> +       <var: #mcpc type: #'char *'>
> +       <var: #nsSendCache type: #'NSSendCache *'>
> +       | entryPoint |
> +
> +       NewspeakVM ifTrue:
> +               [| nsSendCache |
> +                annotation = IsNSSendCall ifTrue:
> +                       [nsSendCache := self nsSendCacheFromReturnAddress:
> mcpc asInteger.
> +                       (entryPoint := nsSendCache target) ~= 0 ifTrue:
> +                               [ | targetMethod |
> +                               targetMethod := entryPoint -
> cmNoCheckEntryOffset.
> +                               (self cogMethodHasMachineCodePrim:
> targetMethod) ifTrue:
> +                                       [self voidNSSendCache:
> nsSendCache]].
> +                       ^0 "keep scanning"]].
> +
> +       (self isPureSendAnnotation: annotation) ifTrue:
> +               [entryPoint := backEnd callTargetFromReturnAddress: mcpc
> asInteger.
> +                entryPoint > methodZoneBase ifTrue: "It's a linked send."
> +                       [self targetMethodAndSendTableFor: entryPoint
> annotation: annotation into:
> +                               [:targetMethod :sendTable|
> +                                (self cogMethodHasMachineCodePrim:
> targetMethod) ifTrue:
> +                                       [self unlinkSendAt: mcpc
> targetMethod: targetMethod sendTable: sendTable]]]].
> +
> +       ^0 "keep scanning"!
>
> Item was added:
> + ----- Method: Cogit>>unlinkSendsToMachineCodePrimitiveMethodsAndFreeIf:
> (in category 'jit - api') -----
> + unlinkSendsToMachineCodePrimitiveMethodsAndFreeIf: freeIfTrue
> +       <api>
> +       "Unlink all sends in cog methods to methods with a machine code
> +        primitive, and free machine code primitive methods if freeIfTrue.
> +        To avoid having to scan PICs, free any and all PICs"
> +       | cogMethod freedSomething |
> +       <var: #cogMethod type: #'CogMethod *'>
> +       methodZoneBase ifNil: [^self].
> +       codeModified := freedSomething := false.
> +       cogMethod := self cCoerceSimple: methodZoneBase to: #'CogMethod *'.
> +       [cogMethod < methodZone limitZony] whileTrue:
> +               [cogMethod cmType = CMMethod
> +                       ifTrue:
> +                               [(freeIfTrue
> +                                 and: [self cogMethodHasMachineCodePrim:
> cogMethod])
> +                                       ifTrue:
> +                                               [methodZone freeMethod:
> cogMethod.
> +                                                freedSomething := true]
> +                                       ifFalse:
> +                                               [self mapFor: cogMethod
> +                                                        performUntil:
> #unlinkIfLinkedSend:pc:toMachineCodePrim:
> +                                                        arg: 0]]
> +                       ifFalse:
> +                               [cogMethod cmType = CMClosedPIC ifTrue:
> +                                       [methodZone freeMethod: cogMethod.
> +                                        freedSomething := true]].
> +               cogMethod := methodZone methodAfter: cogMethod].
> +       freedSomething
> +               ifTrue: [self unlinkSendsToFree]
> +               ifFalse:
> +                       [codeModified ifTrue: "After possibly updating
> inline caches we need to flush the icache."
> +                               [processor flushICacheFrom: methodZoneBase
> asUnsignedInteger to: methodZone limitZony asUnsignedInteger]]!
>
> Item was added:
> + ----- Method: SimpleStackBasedCogit>>cogMethodHasMachineCodePrim: (in
> category 'in-line cacheing') -----
> + cogMethodHasMachineCodePrim: aCogMethod
> +       <api>
> +       <var: 'aCogMethod' type: #'CogMethod *'>
> +       <inline: true>
> +       | primIndex |
> +       primIndex := coInterpreter primitiveIndexOfMethod: aCogMethod
> methodObject header: aCogMethod objectHeader.
> +       ^(primIndex between: 1 and: MaxCompiledPrimitiveIndex)
> +         and: [(primitiveGeneratorTable at: primIndex) primitiveGenerator
> notNil]!
>
> Item was changed:
>   ----- Method: StackInterpreter class>>declareCVarsIn: (in category
> 'translation') -----
>   declareCVarsIn: aCCodeGenerator
>         | vmClass |
>         self class == thisContext methodClass ifFalse: [^self]. "Don't
> duplicate decls in subclasses"
>         vmClass := aCCodeGenerator vmClass. "Generate primitiveTable etc
> based on vmClass, not just StackInterpreter"
>         aCCodeGenerator
>                 addHeaderFile:'<stddef.h> /* for e.g. alloca */';
>                 addHeaderFile:'<setjmp.h>';
>                 addHeaderFile:'<wchar.h> /* for wint_t */';
>                 addHeaderFile:'"vmCallback.h"';
>                 addHeaderFile:'"sqMemoryFence.h"';
>                 addHeaderFile:'"dispdbg.h"'.
>         LowcodeVM ifTrue: [ aCCodeGenerator
> addHeaderFile:'"sqLowcodeFFI.h"'].
>
>         vmClass declareInterpreterVersionIn: aCCodeGenerator defaultName:
> 'Stack'.
>         aCCodeGenerator
>                 var: #interpreterProxy  type: #'struct VirtualMachine*'.
>         aCCodeGenerator
>                 declareVar: #sendTrace type: 'volatile int';
>                 declareVar: #byteCount type: #usqInt.
>         "These need to be pointers or unsigned."
>         self declareC: #(instructionPointer method newMethod)
>                 as: #usqInt
>                 in: aCCodeGenerator.
>         "These are all pointers; char * because Slang has no support for C
> pointer arithmetic."
>         self declareC: #(localIP localSP localFP stackPointer framePointer
> stackLimit breakSelector)
>                 as: #'char *'
>                 in: aCCodeGenerator.
>         aCCodeGenerator
>                 var: #breakSelectorLength
>                 declareC: 'sqInt breakSelectorLength = MinSmallInteger'.
>         self declareC: #(stackPage overflowedPage)
>                 as: #'StackPage *'
>                 in: aCCodeGenerator.
>         aCCodeGenerator removeVariable: 'stackPages'.  "this is an
> implicit receiver in the translated code."
>         "This defines bytecodeSetSelector as 0 if MULTIPLEBYTECODESETS
>          is not defined, for the benefit of the interpreter on slow
> machines."
>         aCCodeGenerator addConstantForBinding: (self bindingOf:
> #MULTIPLEBYTECODESETS).
>         MULTIPLEBYTECODESETS == false ifTrue:
>                 [aCCodeGenerator
>                         removeVariable: 'bytecodeSetSelector'].
>         BytecodeSetHasExtensions == false ifTrue:
>                 [aCCodeGenerator
>                         removeVariable: 'extA';
>                         removeVariable: 'extB'].
>         aCCodeGenerator
>                 var: #methodCache
>                 declareC: 'sqIntptr_t methodCache[MethodCacheSize + 1 /*
> ', (MethodCacheSize + 1) printString, ' */]'.
>         NewspeakVM
>                 ifTrue:
>                         [aCCodeGenerator
>                                 var: #nsMethodCache
>                                 declareC: 'sqIntptr_t
> nsMethodCache[NSMethodCacheSize + 1 /* ', (NSMethodCacheSize + 1)
> printString, ' */]']
>                 ifFalse:
>                         [aCCodeGenerator
>                                 removeVariable: #nsMethodCache;
>                                 removeVariable: 'localAbsentReceiver';
>                                 removeVariable:
> 'localAbsentReceiverOrZero'].
>         AtCacheTotalSize isInteger ifTrue:
>                 [aCCodeGenerator
>                         var: #atCache
>                         declareC: 'sqInt atCache[AtCacheTotalSize + 1 /*
> ', (AtCacheTotalSize + 1) printString, ' */]'].
>         aCCodeGenerator
>                 var: #primitiveTable
>                 declareC: 'void (*primitiveTable[MaxPrimitiveIndex + 2 /*
> ', (MaxPrimitiveIndex + 2) printString, ' */])(void) = ', vmClass
> primitiveTableString.
>         vmClass primitiveTable do:
>                 [:symbolOrNot|
>                 (symbolOrNot isSymbol
>                  and: [symbolOrNot ~~ #primitiveFail]) ifTrue:
>                         [(aCCodeGenerator methodNamed: symbolOrNot)
> ifNotNil:
>                                 [:tMethod| tMethod returnType: #void]]].
>         vmClass objectMemoryClass hasSpurMemoryManagerAPI
>                 ifTrue:
>                         [aCCodeGenerator
>                                 var: #primitiveAccessorDepthTable
>                                 type: 'signed char'
>                                 sizeString: 'MaxPrimitiveIndex + 2 /* ',
> (MaxPrimitiveIndex + 2) printString, ' */'
>                                 array: vmClass primitiveAccessorDepthTable]
>                 ifFalse:
>                         [aCCodeGenerator removeVariable:
> #primitiveAccessorDepthTable].
>         aCCodeGenerator
>                 var: #displayBits type: #'void *'.
>         self declareC: #(displayWidth displayHeight displayDepth) as: #int
> in: aCCodeGenerator.
>         aCCodeGenerator
>                 var: #primitiveFunctionPointer
>                         declareC: 'void (*primitiveFunctionPointer)()';
>                 var: #externalPrimitiveTable
>                         declareC: 'void
> (*externalPrimitiveTable[MaxExternalPrimitiveTableSize + 1 /* ',
> (MaxExternalPrimitiveTableSize + 1) printString, ' */])(void)';
>                 var: #interruptCheckChain
>                         declareC: 'void (*interruptCheckChain)(void) = 0';
>                 var: #showSurfaceFn
>                         declareC: 'int (*showSurfaceFn)(sqIntptr_t, int,
> int, int, int)';
>                 var: #jmpBuf
>                         declareC: 'jmp_buf jmpBuf[MaxJumpBuf + 1 /* ',
> (MaxJumpBuf + 1) printString, ' */]';
>                 var: #suspendedCallbacks
>                         declareC: 'usqInt suspendedCallbacks[MaxJumpBuf +
> 1 /* ', (MaxJumpBuf + 1) printString, ' */]';
>                 var: #suspendedMethods
>                         declareC: 'usqInt suspendedMethods[MaxJumpBuf + 1
> /* ', (MaxJumpBuf + 1) printString, ' */]'.
>
>         self declareCAsUSqLong: #(nextPollUsecs nextWakeupUsecs
> longRunningPrimitiveGCUsecs
>
> longRunningPrimitiveStartUsecs longRunningPrimitiveStopUsecs
>                                                                 "these are
> high-frequency enough that they're overflowing quite quickly on modern
> hardware"
>
> statProcessSwitch statIOProcessEvents statForceInterruptCheck
>
> statCheckForEvents statStackOverflow statStackPageDivorce
>
> statIdleUsecs)
>                 in: aCCodeGenerator.
>         aCCodeGenerator var: #nextProfileTick type: #sqLong.
>         aCCodeGenerator
>                 var: #reenterInterpreter
>                 declareC: 'jmp_buf reenterInterpreter; /* private export
> */'.
>         LowcodeVM
>                 ifTrue:
>                         [aCCodeGenerator
>                                 var: #lowcodeCalloutState type:
> #'sqLowcodeCalloutState*'.
>                          self declareC: #(nativeSP nativeStackPointer
> shadowCallStackPointer)
>                                 as: #'char *'
>                                 in: aCCodeGenerator]
>                 ifFalse:
>                         [#(lowcodeCalloutState nativeSP nativeStackPointer
> shadowCallStackPointer) do:
>                                 [:var| aCCodeGenerator removeVariable:
> var]].
>
>         aCCodeGenerator
>                 var: #primitiveDoMixedArithmetic
> +               declareC: 'char primitiveDoMixedArithmetic = 1'.!
> -               declareC: 'sqInt primitiveDoMixedArithmetic = 1'.!
>
> Item was changed:
>   ----- Method: StackInterpreter class>>mustBeGlobal: (in category
> 'translation') -----
>   mustBeGlobal: var
> +       "Answer if a variable must be global and exported.  Used for inst
> vars that are accessed from VM support code,
> +        and for variables that are initialized to some value (e.g.
> primitiveDoMixedArithmetic)."
> -       "Answer if a variable must be global and exported.  Used for inst
> vars that are accessed from VM support code."
>
>         ^(super mustBeGlobal: var)
>            or: [(self objectMemoryClass mustBeGlobal: var)
>            or: [(#('interpreterProxy' 'interpreterVersion'
> 'inIOProcessEvents' 'sendWheelEvents'
>                         'deferDisplayUpdates' 'extraVMMemory'
>                         'showSurfaceFn' 'displayBits' 'displayWidth'
> 'displayHeight' 'displayDepth'
>                         'desiredNumStackPages' 'desiredEdenBytes'
> +                       'primitiveDoMixedArithmetic'
>                         'breakLookupClassTag' 'breakSelector'
> 'breakSelectorLength' 'sendTrace' 'checkAllocFiller' 'checkedPluginName'
>                         'reenterInterpreter' 'suppressHeartbeatFlag'
> 'ffiExceptionResponse'
>                         'debugCallbackInvokes' 'debugCallbackPath'
> 'debugCallbackReturns') includes: var)
>            or: [ "This allows slow machines to define bytecodeSetSelector
> as 0
>                         to avoid the interpretation overhead."
>                         MULTIPLEBYTECODESETS not and: [var =
> 'bytecodeSetSelector']]]]!
>
> Item was changed:
>   ----- Method: StackInterpreter>>canContextSwitchIfActivating:header: (in
> category 'message sending') -----
>   canContextSwitchIfActivating: theMethod header: methodHeader
>         "Context switch should not be allowed on every method activation.
> In particular
>          the implementation of ensure: and ifCurtailed: depends on there
> being no
>          suspension point on failing primitive 198
> (primitiveMarkUnwindMethod).
>          slowPrimitiveResponse states
>                 ``N.B.  This means there is no suspension point on
> primitive failure
>                     which methods such as ensure: and ifCurtailed: rely
> on.''
>          Rather than prevent context switch on all primitives but the ones
> we really need
>          to be suspension points (primitiveSignal et al) we choose to
> allow context switch
>          for all but primitiveMarkUnwindMethod."
>         | primitiveIndex |
>         <api>
>         <inline: true>
>         primitiveIndex := self primitiveIndexOfMethod: theMethod header:
> methodHeader.
>         ^self cppIf: true
>                 ifTrue:
>                         [primitiveIndex ~= 198] "primitiveMarkUnwindMethod"
>                 ifFalse:
>                         [primitiveIndex = 0
>                           or: [(primitiveIndex between: 85 and: 88)
> "primitiveSignal primitiveWait primitiveResume primitiveSuspend"
> +                         or: [primitiveIndex = 167 "primitiveYield"
> +                         or: [primitiveIndex between: 185 and: 186
> "primitiveExitCriticalSection primitiveEnterCriticalSection"]]]]!
> -                         or: [primitiveIndex = 167]]] "primitiveYield"!
>
> Item was added:
> + ----- Method:
> StackInterpreter>>flushMethodsWithMachineCodePrimitivesAndContinueAnswering:
> (in category 'primitive support') -----
> + flushMethodsWithMachineCodePrimitivesAndContinueAnswering: result
> +       "In the StackInterpreter this is simply a no op"!
>
> Item was changed:
>   ----- Method: StackInterpreter>>primitiveDoMixedArithmetic (in category
> 'primitive support') -----
>   primitiveDoMixedArithmetic
>         "If primitiveDoMixedArithmetic is true, then primitive can handle
> the conversions:
>         SmallInteger arithmeticOp: Float (Small or Boxed)
>         SmallInteger compareOp: Float (Small or Boxed)
> +       Else, the primitive fail in case of mixed arithmetic, and
> conversion should be performed in the image."
> -       Else, the primitive fail in case of mixed arithmetic, and
> conversion should be performed at image side"
>         <api>
> +       <cmacro: '() primitiveDoMixedArithmetic'>
> -       <cmacro: '() GIV(primitiveDoMixedArithmetic)'>
>         ^primitiveDoMixedArithmetic!
>
> Item was removed:
> - ----- Method: StackInterpreter>>setPrimitiveDoMixedArithmetic: (in
> category 'primitive support') -----
> - setPrimitiveDoMixedArithmetic: aBool
> -       "See #primitiveDoMixedArithmetic method"
> -       primitiveDoMixedArithmetic = aBool ifFalse: [self
> flushMethodCache].
> -       primitiveDoMixedArithmetic := aBool!
>
> Item was changed:
>   ----- Method: StackInterpreterPrimitives>>primitiveSetVMParameter:arg:
> (in category 'system control primitives') -----
>   primitiveSetVMParameter: index arg: argOop
>         "See primitiveVMParameter method comment"
>         | arg result |
>
>         "argOop read & checks; in most cases this is an integer
> parameter.  In some it is either an integer or a Float"
>         index = 75
>                 ifTrue:
>                         [ arg := objectMemory booleanValueOf: argOop.
>                         self failed ifTrue: [^self primitiveFailFor:
> PrimErrBadArgument]]
>                 ifFalse: [(index = 17 or: [index = 55 or: [index = 68]])
>                         ifTrue:
>                                 [((objectMemory isFloatInstance: argOop)
>                                  or: [objectMemory isIntegerObject:
> argOop]) ifFalse:
>                                         [^self primitiveFailFor:
> PrimErrBadArgument]]
>                         ifFalse: [(objectMemory isIntegerObject: argOop)
> ifFalse:
>                                         [^self primitiveFailFor:
> PrimErrBadArgument].
>                                  arg := objectMemory integerValueOf:
> argOop]].
>
>         "assume failure, then set success for handled indices"
>         self primitiveFailFor: PrimErrBadArgument.
>         index caseOf: {
>                 [5] ->  [objectMemory hasSpurMemoryManagerAPI ifFalse:
>                                         ["Was:
>                                                         result :=
> allocationsBetweenGCs.
>
> allocationsBetweenGCs := arg."
>                                                 "Ignore for now, because
> old images won't start up otherwise.
>                                                  See 45 for eden size
> setting."
>                                          result := objectMemory nilObject.
>                                          self initPrimCall]].
>                 [6] ->  [result := objectMemory integerObjectOf:
> objectMemory tenuringThreshold.
>                                  primFailCode := objectMemory
> tenuringThreshold: arg].
>                 [11] -> [arg >= 0 ifTrue:
>                                         [result := objectMemory
> integerObjectOf: objectMemory statTenures.
>                                          objectMemory statTenures: arg.
>                                          self initPrimCall]].
>                 [17] -> [(SistaVM and: [self isCog]) ifTrue:
>                                         [result := objectMemory
> floatObjectOf: self getCogCodeZoneThreshold.
>                                          primFailCode := self
> setCogCodeZoneThreshold: (self noInlineLoadFloatOrIntFrom: argOop)]].
>                 [23] -> [result := objectMemory integerObjectOf:
> extraVMMemory.
>                                  extraVMMemory := arg.
>                                  self initPrimCall].
>                 [24] -> [arg > 0 ifTrue:
>                                         [result := objectMemory
> integerObjectOf: objectMemory shrinkThreshold.
>                                          objectMemory shrinkThreshold: arg.
>                                          self initPrimCall]].
>                 [25] -> [arg > 0 ifTrue:
>                                         [result := objectMemory
> integerObjectOf: objectMemory growHeadroom.
>                                          objectMemory growHeadroom: arg.
>                                          self initPrimCall]].
>                 [26] -> [arg >= 0 ifTrue: "0 turns off the heartbeat"
>                                         [result := objectMemory
> integerObjectOf: self ioHeartbeatMilliseconds.
>                                          self ioSetHeartbeatMilliseconds:
> arg.
>                                          self initPrimCall]].
>                 [34] -> [(objectMemory hasSpurMemoryManagerAPI "was
> statAllocationCount; now statAllocatedBytes"
>                                   and: [arg >= 0]) ifTrue:
>                                         [result := objectMemory
> positive64BitIntegerFor: objectMemory currentAllocatedBytes.
>                                          objectMemory
> setCurrentAllocatedBytesTo: arg.
>                                          self initPrimCall]].
>                 [43] -> [(arg between: 0 and: 65535) ifTrue:
>                                         [result := objectMemory
> integerObjectOf: desiredNumStackPages.
>                                          desiredNumStackPages := arg.
>                                          self initPrimCall]].
>                 [45] -> [arg >= 0 ifTrue:
>                                         [result := objectMemory
> integerObjectOf: desiredEdenBytes.
>                                          desiredEdenBytes := arg.
>                                          self initPrimCall]].
>                 [47] -> [(self isCog
>                                   and: [arg between: 0 and: self
> maxCogCodeSize]) ifTrue:
>                                         [result := objectMemory
> integerObjectOf: self getDesiredCogCodeSize.
>                                          self setDesiredCogCodeSize: arg.
>                                          self initPrimCall]].
>                 [48] -> [arg >= 0 ifTrue:
>                                         [result := objectMemory
> integerObjectOf: self getCogVMFlags.
>                                          self initPrimCall. "i.e.
> setCogVMFlags: can fail"
>                                          self setCogVMFlags: arg]].
>                 [49] -> [(arg between: 0 and: 65535) ifTrue:
>                                         [result := objectMemory
> integerObjectOf: self ioGetMaxExtSemTableSize.
>                                          self initPrimCall. "i.e.
> ioSetMaxExtSemTableSize: is allowed to fail"
>                                          self setMaxExtSemSizeTo: arg]].
>                 [55] -> [objectMemory hasSpurMemoryManagerAPI ifTrue:
>                                         [result := objectMemory
> floatObjectOf: objectMemory getHeapGrowthToSizeGCRatio.
>                                          primFailCode := objectMemory
> setHeapGrowthToSizeGCRatio: (self noInlineLoadFloatOrIntFrom: argOop)]].
>                 [67] -> [(arg >= 0
>                                   and: [objectMemory
> hasSpurMemoryManagerAPI]) ifTrue:
>                                         [result := objectMemory
> integerObjectOf: objectMemory maxOldSpaceSize.
>                                          primFailCode := objectMemory
> setMaxOldSpaceSize: arg]].
>                 [68] -> [result := objectMemory floatObjectOf: stackPages
> statAverageLivePagesWhenMapping.
>                                  self initPrimCall. "i.e.
> statAverageLivePagesWhenMapping: is allowed to fail"
>                                  stackPages
> statAverageLivePagesWhenMapping: (self noInlineLoadFloatOrIntFrom: argOop)].
>                 [69] -> [arg >= 0 ifTrue:
>                                         [result := objectMemory
> integerObjectOf: stackPages statMaxPageCountWhenMapping.
>                                          stackPages
> statMaxPageCountWhenMapping: arg.
>                                          self initPrimCall]].
>                 [74] -> [(arg >= 0
>                                   and: [objectMemory
> hasSpurMemoryManagerAPI]) ifTrue:
>                                         [result := objectMemory
> integerObjectOf: objectMemory statMaxAllocSegmentTime + 500 // 1000.
>                                          stackPages
> statMaxAllocSegmentTime: arg. "usually 0"
>                                          self initPrimCall]].
> +               [75] -> [| mustFlush |
> +                                result := objectMemory booleanObjectOf:
> self primitiveDoMixedArithmetic.
> +                                self initPrimCall.
> +                                mustFlush := primitiveDoMixedArithmetic
> ~= arg.
> +                                primitiveDoMixedArithmetic := arg.
> +                                mustFlush ifTrue:
> +                                       [self flushMethodCache.
> +                                        self
> flushMethodsWithMachineCodePrimitivesAndContinueAnswering: result
> +                                        "NOT REACHED (in
> CoInterpreter)"]] }
> -               [75] -> [result := objectMemory booleanObjectOf: self
> primitiveDoMixedArithmetic.
> -                               self setPrimitiveDoMixedArithmetic: arg.
> -                               self initPrimCall] }
>                 otherwise: [].
>
>         self successful
>                 ifTrue: [self methodReturnValue: result]  "return old
> value"
>                 ifFalse: [self primitiveFailFor: PrimErrInappropriate]
> "attempting to write a read-only or non-existent parameter"!
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20190906/ceaae09a/attachment-0001.html>


More information about the Vm-dev mailing list