[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