Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.3194.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.3194 Author: eem Time: 20 June 2022, 5:37:47.097263 pm UUID: b977319b-9026-4c13-afff-8f5515732e4f Ancestors: VMMaker.oscog-eem.3193
Add the upscaleDisplayIfHighDPI flag to the VM. This is true by default. It is controlled by bit 8 of the Persistent image header flags, accessed via vmParameterAt: 48 [put:...].
When this flag is true (i.e. when the image header flag bit is unset) then VMs are expected to upscale the display on high DPI displays as they have in the past. When this flag is false (i.e. when the image header flag bit is set) the VM is expected not to upscale, leaving it to the image to do so.
This flag is present to enable new VMs to allow the image to do its own scaling while keeping on scaling older images unaware of the option.
=============== Diff against VMMaker.oscog-eem.3193 ===============
Item was changed: ----- Method: CoInterpreter>>getImageHeaderFlags (in category 'image save/restore') ----- getImageHeaderFlags "Answer the flags that are contained in the 7th long of the image header." ^fullScreenFlag "0 or 1" + (VMBIGENDIAN ifTrue: [0] ifFalse: [2]) "this is the imageFloatsLittleEndian flag" + (flagInterpretedMethods ifTrue: [8] ifFalse: [0]) + (preemptionYields ifTrue: [0] ifFalse: [16r10]) + (newFinalization ifTrue: [16r40] ifFalse: [0]) + (sendWheelEvents ifTrue: [16r80] ifFalse: [0]) + (primitiveDoMixedArithmetic ifTrue: [0] ifFalse: [16r100]) + "N.B. flag mask 16r200 is fileTimesInUTC, responded to by the FIlePlugin & FileAttributesPlugin" + + (upscaleDisplayIfHighDPI ifTrue: [0] ifFalse: [16r400]) + + (imageHeaderFlags bitClear: 1+2+8+16r10+16r40+16r80+16r100+16r200+16r400) "these are any flags we do not recognize"! - + (imageHeaderFlags bitClear: 1+2+8+16r10+16r40+16r80+16r100) "these are any flags we do not recognize"!
Item was changed: ----- Method: CoInterpreter>>setImageHeaderFlags: (in category 'internal interpreter access') ----- setImageHeaderFlags: flags "Set an array of flags indicating various properties of the saved image, responded to on image load. These are the same as the image header flags shifted right two bits, omitting the fullScreenFlag and float byte order flag. Bit 0: if set, implies the image's Process class has threadId as its 3rd inst var (zero relative) (meaningful to the MT VM only) Bit 1: if set, methods that are interpreted will have the flag bit set in their header Bit 2: if set, implies preempting a process does not put it to the back of its run queue Bit 3: if set, implies a threaded VM will not disown the VM if owned by the GUI thread (meaningful to the MT VM only) Bit 4: if set, implies the new finalization scheme where WeakArrays are queued Bit 5: if set, implies wheel events will be delivered as such and not mapped to arrow key events Bit 6: if set, implies arithmetic primitives will fail if given arguments of different types (float vs int) + Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times + Bit 8: if set, implies the VM will not upscale the display on high DPI monitors; older VMs did this by default. + Bit 8: if set, implies the VM will not upscale the display on high DPI devices" + flags asUnsignedInteger > 511 ifTrue: - Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times" - flags asUnsignedInteger > 255 ifTrue: [^self primitiveFailFor: PrimErrUnsupported]. "processHasThreadId := flags anyMask: 1. specific to CoInterpreterMT" imageHeaderFlags := (flags anyMask: 1) ifTrue: [imageHeaderFlags bitOr: 4] ifFalse: [imageHeaderFlags bitClear: 4]. flagInterpretedMethods := flags anyMask: 2. preemptionYields := flags noMask: 4. "noThreadingOfGUIThread := flags anyMask: 8.. specific to CoInterpreterMT" imageHeaderFlags := (flags anyMask: 8) ifTrue: [imageHeaderFlags bitOr: 32] ifFalse: [imageHeaderFlags bitClear: 32]. newFinalization := flags anyMask: 16. sendWheelEvents := flags anyMask: 32. primitiveDoMixedArithmetic := flags noMask: 64. imageHeaderFlags := (flags anyMask: 128) ifTrue: [imageHeaderFlags bitOr: 512] + ifFalse: [imageHeaderFlags bitClear: 512]. + upscaleDisplayIfHighDPI := flags noMask: 256! - ifFalse: [imageHeaderFlags bitClear: 512]!
Item was changed: ----- Method: CoInterpreter>>setImageHeaderFlagsFrom: (in category 'image save/restore') ----- setImageHeaderFlagsFrom: headerFlags "Set the flags that are contained in the 7th long of the image header." imageHeaderFlags := headerFlags. "so as to preserve unrecognised flags." fullScreenFlag := headerFlags bitAnd: 1. imageFloatsBigEndian := (headerFlags noMask: 2) ifTrue: [1] ifFalse: [0]. "processHasThreadId := headerFlags anyMask: 4. specific to CoInterpreterMT" flagInterpretedMethods := headerFlags anyMask: 8. preemptionYields := headerFlags noMask: 16. "noThreadingOfGUIThread := headerFlags anyMask: 32. specific to CoInterpreterMT" newFinalization := headerFlags anyMask: 64. sendWheelEvents := headerFlags anyMask: 128. + primitiveDoMixedArithmetic := headerFlags noMask: 256. + "N.B. flag mask 512 is responded to by the FIlePlugin & FileAttributesPlugin" + upscaleDisplayIfHighDPI := headerFlags noMask: 1024! - primitiveDoMixedArithmetic := headerFlags noMask: 256!
Item was changed: ----- Method: CoInterpreterMT>>getImageHeaderFlags (in category 'image save/restore') ----- getImageHeaderFlags "Answer the flags that are contained in the 7th long of the image header." ^fullScreenFlag "0 or 1" + (VMBIGENDIAN ifTrue: [0] ifFalse: [2]) "this is the imageFloatsLittleEndian flag" + (processHasThreadId ifTrue: [4] ifFalse: [0]) + (flagInterpretedMethods ifTrue: [8] ifFalse: [0]) + (preemptionYields ifTrue: [0] ifFalse: [16r10]) "was: noThreadingOfGUIThread ifTrue: [16r20] ifFalse: [0]); a broken idea" + (newFinalization ifTrue: [16r40] ifFalse: [0]) + (sendWheelEvents ifTrue: [16r80] ifFalse: [0]) + (primitiveDoMixedArithmetic ifTrue: [0] ifFalse: [16r100]) + "N.B. flag mask 16r200 is fileTimesInUTC, responded to by the FIlePlugin & FileAttributesPlugin" + + (upscaleDisplayIfHighDPI ifTrue: [0] ifFalse: [16r400]) + + (imageHeaderFlags bitClear: 16r7FF) "these are any flags we do not recognize"! - + (imageHeaderFlags bitClear: 16r1FF) "these are any flags we do not recognize"!
Item was changed: ----- Method: CoInterpreterMT>>setImageHeaderFlags: (in category 'internal interpreter access') ----- setImageHeaderFlags: flags "Set an array of flags indicating various properties of the saved image, responded to on image load. These are the same as the image header flags shifted right two bits, omitting the fullScreenFlag and float byte order flag. Bit 0: if set, implies the image's Process class has threadId as its 3rd inst var (zero relative) Bit 1: if set, methods that are interpreted will have the flag bit set in their header Bit 2: if set, implies preempting a process does not put it to the back of its run queue Bit 3: unassigned; used to mean if set, implies a threaded VM will not disown the VM if owned by the GUI thread; a broken idea Bit 4: if set, implies the new finalization scheme where WeakArrays are queued Bit 5: if set, implies wheel events will be delivered as such and not mapped to arrow key events Bit 6: if set, implies arithmetic primitives will fail if given arguments of different types (float vs int) + Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times + Bit 8: if set, implies the VM will not upscale the display on high DPI devices" + flags asUnsignedInteger > 511 ifTrue: - Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times" - flags asUnsignedInteger > 255 ifTrue: [^self primitiveFailFor: PrimErrUnsupported]. (flags anyMask: 8) ifTrue: [^self primitiveFailFor: PrimErrInappropriate]. processHasThreadId := flags anyMask: 1. flagInterpretedMethods := flags anyMask: 2. preemptionYields := flags noMask: 4. "was: noThreadingOfGUIThread := flags anyMask: 8. a broken idea" newFinalization := flags anyMask: 16. sendWheelEvents := flags anyMask: 32. primitiveDoMixedArithmetic := flags noMask: 64. imageHeaderFlags := (flags anyMask: 128) ifTrue: [imageHeaderFlags bitOr: 512] + ifFalse: [imageHeaderFlags bitClear: 512]. + upscaleDisplayIfHighDPI := flags noMask: 256! - ifFalse: [imageHeaderFlags bitClear: 512]!
Item was changed: ----- Method: CoInterpreterMT>>setImageHeaderFlagsFrom: (in category 'image save/restore') ----- setImageHeaderFlagsFrom: headerFlags "Set the flags that are contained in the 7th long of the image header." imageHeaderFlags := headerFlags. "so as to preserve unrecognised flags." fullScreenFlag := headerFlags bitAnd: 1. imageFloatsBigEndian := (headerFlags noMask: 2) ifTrue: [1] ifFalse: [0]. processHasThreadId := headerFlags anyMask: 4. flagInterpretedMethods := headerFlags anyMask: 8. preemptionYields := headerFlags noMask: 16. "was: noThreadingOfGUIThread := headerFlags anyMask: 32. a broken idea" newFinalization := headerFlags anyMask: 64. sendWheelEvents := headerFlags anyMask: 128. primitiveDoMixedArithmetic := headerFlags noMask: 256. + "N.B. flag mask 512 is responded to by the FIlePlugin & FileAttributesPlugin" + upscaleDisplayIfHighDPI := headerFlags noMask: 1024.
processHasThreadId ifFalse: [self print: 'warning, processHasThreadId flag is unset; cannot function as a threaded VM if so.'; cr]!
Item was changed: InterpreterPrimitives subclass: #StackInterpreter (excessive size, no diff calculated)
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: '<stdio.h> /* for printf */'; addHeaderFile: '<stdlib.h> /* for e.g. alloca */'; addHeaderFile: '<setjmp.h>'; addHeaderFile: '<wchar.h> /* for wint_t */'; addHeaderFile: '"vmCallback.h"'; addHeaderFile: '"sqMemoryFence.h"'; addHeaderFile: '"sqImageFileAccess.h"'; addHeaderFile: '"sqSetjmpShim.h"'; addHeaderFile: '"dispdbg.h"'. LowcodeVM ifTrue: [aCCodeGenerator addHeaderFile: '"sqLowcodeFFI.h"'].
vmClass declareInterpreterVersionIn: aCCodeGenerator defaultName: 'Stack'. + #('primitiveDoMixedArithmetic' 'upscaleDisplayIfHighDPI' ) do: + [:var| + aCCodeGenerator + var: var + declareC: 'sqInt ', var, ' = true']. aCCodeGenerator var: #interpreterProxy type: #'struct VirtualMachine*'. aCCodeGenerator declareVar: #sendTrace type: 'volatile int'; declareVar: #byteCount type: #usqLong. "see dispdbg.h" "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 var: #transcript type: #'FILE *'. 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 primitiveAccessorDepthTableUsing: aCCodeGenerator). aCCodeGenerator removeConstant: #PrimNumberInstVarAt; removeConstant: #PrimNumberPerform; removeConstant: # PrimNumberPerformWithArgs; removeConstant: #PrimNumberShallowCopy; removeConstant: #PrimNumberSlotAt; removeConstant: #PrimNumberFlushExternalPrimitives; removeConstant: #PrimNumberUnloadModule] ifFalse: [aCCodeGenerator removeVariable: #primitiveAccessorDepthTable; removeConstant: #PrimNumberVMParameter].
aCCodeGenerator var: #displayBits type: #'void *'; var: #primitiveCalloutPointer declareC: 'void *primitiveCalloutPointer = (void *)-1'. self declareC: #(displayWidth displayHeight displayDepth) as: #int in: aCCodeGenerator. aCCodeGenerator var: #primitiveFunctionPointer declareC: 'void (*primitiveFunctionPointer)()'; var: 'pcPreviousToFunction' declareC: 'sqInt (* const pcPreviousToFunction)(sqInt,sqInt) = ', (aCCodeGenerator cFunctionNameFor: PCPreviousToFunction); 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)'.
self declareCAsUSqLong: #(nextPollUsecs nextWakeupUsecs "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 type: 'jmp_buf'. 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]]. (self instVarNames select: [:ivn| ivn beginsWith: 'longRunningPrimitive']) do: [:lrpmVar| aCCodeGenerator var: lrpmVar declareC: '#if LRPCheck', ((lrpmVar endsWith: 'Usecs') ifTrue: [#usqLong] ifFalse: [#sqInt]), ' ', lrpmVar, '#endif']!
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)."
^(super mustBeGlobal: var) or: [(self objectMemoryClass mustBeGlobal: var) or: [(#('interpreterProxy' 'interpreterVersion' 'inIOProcessEvents' 'sendWheelEvents' 'deferDisplayUpdates' 'cannotDeferDisplayUpdates' 'eventTraceMask' 'extraVMMemory' 'showSurfaceFn' 'displayBits' 'displayWidth' 'displayHeight' 'displayDepth' 'desiredNumStackPages' 'desiredEdenBytes' + 'primitiveDoMixedArithmetic' 'upscaleDisplayIfHighDPI' - '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>>getImageHeaderFlags (in category 'image save/restore') ----- getImageHeaderFlags "Answer the flags that are contained in the 7th long of the image header." ^fullScreenFlag "0 or 1" + (VMBIGENDIAN ifTrue: [0] ifFalse: [2]) "this is the imageFloatsLittleEndian flag" + (preemptionYields ifTrue: [0] ifFalse: [16r10]) + (newFinalization ifTrue: [16r40] ifFalse: [0]) + (sendWheelEvents ifTrue: [16r80] ifFalse: [0]) + (primitiveDoMixedArithmetic ifTrue: [0] ifFalse: [16r100]) + "N.B. flag mask 16r200 is fileTimesInUTC, responded to by the FIlePlugin & FileAttributesPlugin" + + (upscaleDisplayIfHighDPI ifTrue: [0] ifFalse: [16r400]) + + (imageHeaderFlags bitClear: 1+2+16r10+16r40+16r80+16r100+16r200+16r400) "these are any flags we do not recognize"! - + (imageHeaderFlags bitClear: 1+2+16r10+16r40+16r80+16r100) "these are any flags we do not recognize"!
Item was changed: ----- Method: StackInterpreter>>initialize (in category 'initialization') ----- initialize "Here we can initialize the variables C initializes to zero. #initialize methods do /not/ get translated." super initialize. - primitiveDoMixedArithmetic := true. "whether we authorize primitives to perform mixed arithmetic or not". newFinalization := false. stackLimit := 0. "This is also the initialization flag for the stack system." stackPage := overflowedPage := nil. extraFramesToMoveOnOverflow := 0. bytecodeSetSelector := 0. highestRunnableProcessPriority := 0. nextPollUsecs := 0. nextWakeupUsecs := 0. tempOop := tempOop2 := theUnknownShort := 0. interruptPending := false. inIOProcessEvents := 0. fullScreenFlag := 0. sendWheelEvents := deferDisplayUpdates := cannotDeferDisplayUpdates := false. displayBits := displayWidth := displayHeight := displayDepth := 0. pendingFinalizationSignals := statPendingFinalizationSignals := 0. globalSessionID := 0. longRunningPrimitiveStartUsecs := longRunningPrimitiveStopUsecs := 0. maxExtSemTabSizeSet := false. debugCallbackInvokes := debugCallbackPath := debugCallbackReturns := 0. primitiveCalloutPointer := -1. "initialized in declaration in declareCVarsIn:" transcript := Transcript. "initialized to stdout in readImageFromFile:HeapSize:StartingAt:" pcPreviousToFunction := PCPreviousToFunction. "initialized via StackInterpreter class>>declareCVarsIn:" statForceInterruptCheck := statStackOverflow := statCheckForEvents := statProcessSwitch := statIOProcessEvents := statStackPageDivorce := statIdleUsecs := 0!
Item was changed: ----- Method: StackInterpreter>>initializeInterpreter: (in category 'initialization') ----- initializeInterpreter: bytesToShift + "Initialize Interpreter state before starting execution of a new image. + N.B. do *NOT* initialize variables that can be initialized via command line + arguments since command line arguments are proicessed before the image + is loaded and this initialization takes place after the image is loaded. + Anything that us not initialized to either 0 or false (the C default value) + should be initialized in StackInterpeeter class>>declareCVarsIn:" - "Initialize Interpreter state before starting execution of a new image." interpreterProxy := self sqGetInterpreterProxy. self dummyReferToProxy. objectMemory initializeObjectMemory: bytesToShift. self checkAssumedCompactClasses. self initializeExtraClassInstVarIndices. method := newMethod := objectMemory nilObject. self cCode: '' inSmalltalk: [breakSelectorLength ifNil: [breakSelectorLength := objectMemory minSmallInteger]. breakLookupClassTag ifNil: [breakLookupClassTag := -1]. reenterInterpreter := ReenterInterpreter new]. methodDictLinearSearchLimit := 8. self initialCleanup. - primitiveDoMixedArithmetic := true. LowcodeVM ifTrue: [ self setupNativeStack ]. profileSemaphore := profileProcess := profileMethod := objectMemory nilObject. self cCode: '' inSmalltalk: [InitializationOptions at: #profiling ifPresent: [:profiling| "hack turn on profiling, for testing in the simulator." profiling ifTrue: [profileSemaphore := objectMemory cloneObject: (objectMemory splObj: TheInterruptSemaphore). objectMemory storePointerUnchecked: FirstLinkIndex ofObject: profileSemaphore withValue: objectMemory nilObject; storePointerUnchecked: NextLinkIndex ofObject: profileSemaphore withValue: objectMemory nilObject; storePointerUnchecked: ExcessSignalsIndex ofObject: profileSemaphore withValue: (objectMemory integerObjectOf: 0)]]]. interruptKeycode := 2094. "cmd-. as used for Mac but no other OS" [globalSessionID = 0] whileTrue: [globalSessionID := self cCode: [((self time: #NULL) + self ioMSecs) bitAnd: 16r7FFFFFFF] inSmalltalk: [(Random new next * (SmallInteger maxVal min: 16r7FFFFFFF)) asInteger]]. metaAccessorDepth := -2. super initializeInterpreter: bytesToShift!
Item was changed: ----- Method: StackInterpreter>>setImageHeaderFlags: (in category 'internal interpreter access') ----- setImageHeaderFlags: flags "Set an array of flags indicating various properties of the saved image, responded to on image load. These are the same as the image header flags shifted right two bits, omitting the fullScreenFlag and float byte order flag. Bit 0: if set, implies the image's Process class has threadId as its 3rd inst var (zero relative) (meaningful to the MT VM only) Bit 1: if set, methods that are interpreted will have the flag bit set in their header (meaningful to the Cog VM only) Bit 2: if set, implies preempting a process does not put it to the back of its run queue Bit 3: if set, implies a threaded VM will not disown the VM if owned by the GUI thread (meaningful to the MT VM only) Bit 4: if set, implies the new finalization scheme where WeakArrays are queued Bit 5: if set, implies wheel events will be delivered as such and not mapped to arrow key events Bit 6: if set, implies arithmetic primitives will fail if given arguments of different types (float vs int) + Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times + Bit 8: if set, implies the VM will not upscale the display on high DPI devices" + flags asUnsignedInteger > 511 ifTrue: - Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times" - flags asUnsignedInteger > 255 ifTrue: [^self primitiveFailFor: PrimErrUnsupported]. "processHasThreadId := flags anyMask: 1. specific to CoInterpreterMT" imageHeaderFlags := (flags anyMask: 1) ifTrue: [imageHeaderFlags bitOr: 4] ifFalse: [imageHeaderFlags bitClear: 4]. "flagInterpretedMethods := flags anyMask: 2. specific to CoInterpreter" imageHeaderFlags := (flags anyMask: 2) ifTrue: [imageHeaderFlags bitOr: 8] ifFalse: [imageHeaderFlags bitClear: 8]. preemptionYields := flags noMask: 4. "noThreadingOfGUIThread := flags anyMask: 8.. specific to CoInterpreterMT" imageHeaderFlags := (flags anyMask: 8) ifTrue: [imageHeaderFlags bitOr: 32] ifFalse: [imageHeaderFlags bitClear: 32]. newFinalization := flags anyMask: 16. sendWheelEvents := flags anyMask: 32. primitiveDoMixedArithmetic := flags noMask: 64. imageHeaderFlags := (flags anyMask: 128) ifTrue: [imageHeaderFlags bitOr: 512] + ifFalse: [imageHeaderFlags bitClear: 512]. + upscaleDisplayIfHighDPI := flags noMask: 256! - ifFalse: [imageHeaderFlags bitClear: 512]!
Item was changed: ----- Method: StackInterpreter>>setImageHeaderFlagsFrom: (in category 'image save/restore') ----- setImageHeaderFlagsFrom: headerFlags "Set the flags that are contained in the 7th long of the image header." imageHeaderFlags := headerFlags. "so as to preserve unrecognised flags." fullScreenFlag := headerFlags bitAnd: 1. imageFloatsBigEndian := (headerFlags noMask: 2) ifTrue: [1] ifFalse: [0]. "processHasThreadId := headerFlags anyMask: 4. specific to CoInterpreterMT" "flagInterpretedMethods := headerFlags anyMask: 8. specific to CoInterpreter" preemptionYields := headerFlags noMask: 16. "noThreadingOfGUIThread := headerFlags anyMask: 32. specific to CoInterpreterMT" newFinalization := headerFlags anyMask: 64. sendWheelEvents := headerFlags anyMask: 128. + primitiveDoMixedArithmetic := headerFlags noMask: 256. + "N.B. flag mask 512 is responded to by the FIlePlugin & FileAttributesPlugin" + upscaleDisplayIfHighDPI := headerFlags noMask: 1024! - primitiveDoMixedArithmetic := headerFlags noMask: 256!
Hi Eliot --
This means that we would have to change the Squeak 6.0 image again for the next VM release? Okay ... we should make sure that #primitiveScreenScaleFactor MUST ALWAYS answer 1.0 when upscaleDisplayIfHighDPI is true...
[...] then VMs are expected to upscale the display on high DPI displays as they have in the past.
Still not correct. Only (!) the --metal backend on macOS did that in the past. All other cases and platforms relied on the platform to do the scaling. The VM had nothing to do with it. Potato potato... =D
Best, Marcel Am 21.06.2022 02:38:37 schrieb commits@source.squeak.org commits@source.squeak.org:
Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.3194.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.3194 Author: eem Time: 20 June 2022, 5:37:47.097263 pm UUID: b977319b-9026-4c13-afff-8f5515732e4f Ancestors: VMMaker.oscog-eem.3193
Add the upscaleDisplayIfHighDPI flag to the VM. This is true by default. It is controlled by bit 8 of the Persistent image header flags, accessed via vmParameterAt: 48 [put:...].
When this flag is true (i.e. when the image header flag bit is unset) then VMs are expected to upscale the display on high DPI displays as they have in the past. When this flag is false (i.e. when the image header flag bit is set) the VM is expected not to upscale, leaving it to the image to do so.
This flag is present to enable new VMs to allow the image to do its own scaling while keeping on scaling older images unaware of the option.
=============== Diff against VMMaker.oscog-eem.3193 ===============
Item was changed: ----- Method: CoInterpreter>>getImageHeaderFlags (in category 'image save/restore') ----- getImageHeaderFlags "Answer the flags that are contained in the 7th long of the image header." ^fullScreenFlag "0 or 1" + (VMBIGENDIAN ifTrue: [0] ifFalse: [2]) "this is the imageFloatsLittleEndian flag" + (flagInterpretedMethods ifTrue: [8] ifFalse: [0]) + (preemptionYields ifTrue: [0] ifFalse: [16r10]) + (newFinalization ifTrue: [16r40] ifFalse: [0]) + (sendWheelEvents ifTrue: [16r80] ifFalse: [0]) + (primitiveDoMixedArithmetic ifTrue: [0] ifFalse: [16r100]) + "N.B. flag mask 16r200 is fileTimesInUTC, responded to by the FIlePlugin & FileAttributesPlugin" + + (upscaleDisplayIfHighDPI ifTrue: [0] ifFalse: [16r400]) + + (imageHeaderFlags bitClear: 1+2+8+16r10+16r40+16r80+16r100+16r200+16r400) "these are any flags we do not recognize"! - + (imageHeaderFlags bitClear: 1+2+8+16r10+16r40+16r80+16r100) "these are any flags we do not recognize"!
Item was changed: ----- Method: CoInterpreter>>setImageHeaderFlags: (in category 'internal interpreter access') ----- setImageHeaderFlags: flags "Set an array of flags indicating various properties of the saved image, responded to on image load. These are the same as the image header flags shifted right two bits, omitting the fullScreenFlag and float byte order flag. Bit 0: if set, implies the image's Process class has threadId as its 3rd inst var (zero relative) (meaningful to the MT VM only) Bit 1: if set, methods that are interpreted will have the flag bit set in their header Bit 2: if set, implies preempting a process does not put it to the back of its run queue Bit 3: if set, implies a threaded VM will not disown the VM if owned by the GUI thread (meaningful to the MT VM only) Bit 4: if set, implies the new finalization scheme where WeakArrays are queued Bit 5: if set, implies wheel events will be delivered as such and not mapped to arrow key events Bit 6: if set, implies arithmetic primitives will fail if given arguments of different types (float vs int) + Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times + Bit 8: if set, implies the VM will not upscale the display on high DPI monitors; older VMs did this by default. + Bit 8: if set, implies the VM will not upscale the display on high DPI devices" + flags asUnsignedInteger > 511 ifTrue: - Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times" - flags asUnsignedInteger > 255 ifTrue: [^self primitiveFailFor: PrimErrUnsupported]. "processHasThreadId := flags anyMask: 1. specific to CoInterpreterMT" imageHeaderFlags := (flags anyMask: 1) ifTrue: [imageHeaderFlags bitOr: 4] ifFalse: [imageHeaderFlags bitClear: 4]. flagInterpretedMethods := flags anyMask: 2. preemptionYields := flags noMask: 4. "noThreadingOfGUIThread := flags anyMask: 8.. specific to CoInterpreterMT" imageHeaderFlags := (flags anyMask: 8) ifTrue: [imageHeaderFlags bitOr: 32] ifFalse: [imageHeaderFlags bitClear: 32]. newFinalization := flags anyMask: 16. sendWheelEvents := flags anyMask: 32. primitiveDoMixedArithmetic := flags noMask: 64. imageHeaderFlags := (flags anyMask: 128) ifTrue: [imageHeaderFlags bitOr: 512] + ifFalse: [imageHeaderFlags bitClear: 512]. + upscaleDisplayIfHighDPI := flags noMask: 256! - ifFalse: [imageHeaderFlags bitClear: 512]!
Item was changed: ----- Method: CoInterpreter>>setImageHeaderFlagsFrom: (in category 'image save/restore') ----- setImageHeaderFlagsFrom: headerFlags "Set the flags that are contained in the 7th long of the image header." imageHeaderFlags := headerFlags. "so as to preserve unrecognised flags." fullScreenFlag := headerFlags bitAnd: 1. imageFloatsBigEndian := (headerFlags noMask: 2) ifTrue: [1] ifFalse: [0]. "processHasThreadId := headerFlags anyMask: 4. specific to CoInterpreterMT" flagInterpretedMethods := headerFlags anyMask: 8. preemptionYields := headerFlags noMask: 16. "noThreadingOfGUIThread := headerFlags anyMask: 32. specific to CoInterpreterMT" newFinalization := headerFlags anyMask: 64. sendWheelEvents := headerFlags anyMask: 128. + primitiveDoMixedArithmetic := headerFlags noMask: 256. + "N.B. flag mask 512 is responded to by the FIlePlugin & FileAttributesPlugin" + upscaleDisplayIfHighDPI := headerFlags noMask: 1024! - primitiveDoMixedArithmetic := headerFlags noMask: 256!
Item was changed: ----- Method: CoInterpreterMT>>getImageHeaderFlags (in category 'image save/restore') ----- getImageHeaderFlags "Answer the flags that are contained in the 7th long of the image header." ^fullScreenFlag "0 or 1" + (VMBIGENDIAN ifTrue: [0] ifFalse: [2]) "this is the imageFloatsLittleEndian flag" + (processHasThreadId ifTrue: [4] ifFalse: [0]) + (flagInterpretedMethods ifTrue: [8] ifFalse: [0]) + (preemptionYields ifTrue: [0] ifFalse: [16r10]) "was: noThreadingOfGUIThread ifTrue: [16r20] ifFalse: [0]); a broken idea" + (newFinalization ifTrue: [16r40] ifFalse: [0]) + (sendWheelEvents ifTrue: [16r80] ifFalse: [0]) + (primitiveDoMixedArithmetic ifTrue: [0] ifFalse: [16r100]) + "N.B. flag mask 16r200 is fileTimesInUTC, responded to by the FIlePlugin & FileAttributesPlugin" + + (upscaleDisplayIfHighDPI ifTrue: [0] ifFalse: [16r400]) + + (imageHeaderFlags bitClear: 16r7FF) "these are any flags we do not recognize"! - + (imageHeaderFlags bitClear: 16r1FF) "these are any flags we do not recognize"!
Item was changed: ----- Method: CoInterpreterMT>>setImageHeaderFlags: (in category 'internal interpreter access') ----- setImageHeaderFlags: flags "Set an array of flags indicating various properties of the saved image, responded to on image load. These are the same as the image header flags shifted right two bits, omitting the fullScreenFlag and float byte order flag. Bit 0: if set, implies the image's Process class has threadId as its 3rd inst var (zero relative) Bit 1: if set, methods that are interpreted will have the flag bit set in their header Bit 2: if set, implies preempting a process does not put it to the back of its run queue Bit 3: unassigned; used to mean if set, implies a threaded VM will not disown the VM if owned by the GUI thread; a broken idea Bit 4: if set, implies the new finalization scheme where WeakArrays are queued Bit 5: if set, implies wheel events will be delivered as such and not mapped to arrow key events Bit 6: if set, implies arithmetic primitives will fail if given arguments of different types (float vs int) + Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times + Bit 8: if set, implies the VM will not upscale the display on high DPI devices" + flags asUnsignedInteger > 511 ifTrue: - Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times" - flags asUnsignedInteger > 255 ifTrue: [^self primitiveFailFor: PrimErrUnsupported]. (flags anyMask: 8) ifTrue: [^self primitiveFailFor: PrimErrInappropriate]. processHasThreadId := flags anyMask: 1. flagInterpretedMethods := flags anyMask: 2. preemptionYields := flags noMask: 4. "was: noThreadingOfGUIThread := flags anyMask: 8. a broken idea" newFinalization := flags anyMask: 16. sendWheelEvents := flags anyMask: 32. primitiveDoMixedArithmetic := flags noMask: 64. imageHeaderFlags := (flags anyMask: 128) ifTrue: [imageHeaderFlags bitOr: 512] + ifFalse: [imageHeaderFlags bitClear: 512]. + upscaleDisplayIfHighDPI := flags noMask: 256! - ifFalse: [imageHeaderFlags bitClear: 512]!
Item was changed: ----- Method: CoInterpreterMT>>setImageHeaderFlagsFrom: (in category 'image save/restore') ----- setImageHeaderFlagsFrom: headerFlags "Set the flags that are contained in the 7th long of the image header." imageHeaderFlags := headerFlags. "so as to preserve unrecognised flags." fullScreenFlag := headerFlags bitAnd: 1. imageFloatsBigEndian := (headerFlags noMask: 2) ifTrue: [1] ifFalse: [0]. processHasThreadId := headerFlags anyMask: 4. flagInterpretedMethods := headerFlags anyMask: 8. preemptionYields := headerFlags noMask: 16. "was: noThreadingOfGUIThread := headerFlags anyMask: 32. a broken idea" newFinalization := headerFlags anyMask: 64. sendWheelEvents := headerFlags anyMask: 128. primitiveDoMixedArithmetic := headerFlags noMask: 256. + "N.B. flag mask 512 is responded to by the FIlePlugin & FileAttributesPlugin" + upscaleDisplayIfHighDPI := headerFlags noMask: 1024.
processHasThreadId ifFalse: [self print: 'warning, processHasThreadId flag is unset; cannot function as a threaded VM if so.'; cr]!
Item was changed: InterpreterPrimitives subclass: #StackInterpreter (excessive size, no diff calculated)
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: ' /* for printf */'; addHeaderFile: ' /* for e.g. alloca */'; addHeaderFile: ''; addHeaderFile: ' /* for wint_t */'; addHeaderFile: '"vmCallback.h"'; addHeaderFile: '"sqMemoryFence.h"'; addHeaderFile: '"sqImageFileAccess.h"'; addHeaderFile: '"sqSetjmpShim.h"'; addHeaderFile: '"dispdbg.h"'. LowcodeVM ifTrue: [aCCodeGenerator addHeaderFile: '"sqLowcodeFFI.h"'].
vmClass declareInterpreterVersionIn: aCCodeGenerator defaultName: 'Stack'. + #('primitiveDoMixedArithmetic' 'upscaleDisplayIfHighDPI' ) do: + [:var| + aCCodeGenerator + var: var + declareC: 'sqInt ', var, ' = true']. aCCodeGenerator var: #interpreterProxy type: #'struct VirtualMachine*'. aCCodeGenerator declareVar: #sendTrace type: 'volatile int'; declareVar: #byteCount type: #usqLong. "see dispdbg.h" "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 var: #transcript type: #'FILE *'. 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 primitiveAccessorDepthTableUsing: aCCodeGenerator). aCCodeGenerator removeConstant: #PrimNumberInstVarAt; removeConstant: #PrimNumberPerform; removeConstant: # PrimNumberPerformWithArgs; removeConstant: #PrimNumberShallowCopy; removeConstant: #PrimNumberSlotAt; removeConstant: #PrimNumberFlushExternalPrimitives; removeConstant: #PrimNumberUnloadModule] ifFalse: [aCCodeGenerator removeVariable: #primitiveAccessorDepthTable; removeConstant: #PrimNumberVMParameter].
aCCodeGenerator var: #displayBits type: #'void *'; var: #primitiveCalloutPointer declareC: 'void *primitiveCalloutPointer = (void *)-1'. self declareC: #(displayWidth displayHeight displayDepth) as: #int in: aCCodeGenerator. aCCodeGenerator var: #primitiveFunctionPointer declareC: 'void (*primitiveFunctionPointer)()'; var: 'pcPreviousToFunction' declareC: 'sqInt (* const pcPreviousToFunction)(sqInt,sqInt) = ', (aCCodeGenerator cFunctionNameFor: PCPreviousToFunction); 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)'.
self declareCAsUSqLong: #(nextPollUsecs nextWakeupUsecs "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 type: 'jmp_buf'. 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]]. (self instVarNames select: [:ivn| ivn beginsWith: 'longRunningPrimitive']) do: [:lrpmVar| aCCodeGenerator var: lrpmVar declareC: '#if LRPCheck', ((lrpmVar endsWith: 'Usecs') ifTrue: [#usqLong] ifFalse: [#sqInt]), ' ', lrpmVar, '#endif']!
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)."
^(super mustBeGlobal: var) or: [(self objectMemoryClass mustBeGlobal: var) or: [(#('interpreterProxy' 'interpreterVersion' 'inIOProcessEvents' 'sendWheelEvents' 'deferDisplayUpdates' 'cannotDeferDisplayUpdates' 'eventTraceMask' 'extraVMMemory' 'showSurfaceFn' 'displayBits' 'displayWidth' 'displayHeight' 'displayDepth' 'desiredNumStackPages' 'desiredEdenBytes' + 'primitiveDoMixedArithmetic' 'upscaleDisplayIfHighDPI' - '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>>getImageHeaderFlags (in category 'image save/restore') ----- getImageHeaderFlags "Answer the flags that are contained in the 7th long of the image header." ^fullScreenFlag "0 or 1" + (VMBIGENDIAN ifTrue: [0] ifFalse: [2]) "this is the imageFloatsLittleEndian flag" + (preemptionYields ifTrue: [0] ifFalse: [16r10]) + (newFinalization ifTrue: [16r40] ifFalse: [0]) + (sendWheelEvents ifTrue: [16r80] ifFalse: [0]) + (primitiveDoMixedArithmetic ifTrue: [0] ifFalse: [16r100]) + "N.B. flag mask 16r200 is fileTimesInUTC, responded to by the FIlePlugin & FileAttributesPlugin" + + (upscaleDisplayIfHighDPI ifTrue: [0] ifFalse: [16r400]) + + (imageHeaderFlags bitClear: 1+2+16r10+16r40+16r80+16r100+16r200+16r400) "these are any flags we do not recognize"! - + (imageHeaderFlags bitClear: 1+2+16r10+16r40+16r80+16r100) "these are any flags we do not recognize"!
Item was changed: ----- Method: StackInterpreter>>initialize (in category 'initialization') ----- initialize "Here we can initialize the variables C initializes to zero. #initialize methods do /not/ get translated." super initialize. - primitiveDoMixedArithmetic := true. "whether we authorize primitives to perform mixed arithmetic or not". newFinalization := false. stackLimit := 0. "This is also the initialization flag for the stack system." stackPage := overflowedPage := nil. extraFramesToMoveOnOverflow := 0. bytecodeSetSelector := 0. highestRunnableProcessPriority := 0. nextPollUsecs := 0. nextWakeupUsecs := 0. tempOop := tempOop2 := theUnknownShort := 0. interruptPending := false. inIOProcessEvents := 0. fullScreenFlag := 0. sendWheelEvents := deferDisplayUpdates := cannotDeferDisplayUpdates := false. displayBits := displayWidth := displayHeight := displayDepth := 0. pendingFinalizationSignals := statPendingFinalizationSignals := 0. globalSessionID := 0. longRunningPrimitiveStartUsecs := longRunningPrimitiveStopUsecs := 0. maxExtSemTabSizeSet := false. debugCallbackInvokes := debugCallbackPath := debugCallbackReturns := 0. primitiveCalloutPointer := -1. "initialized in declaration in declareCVarsIn:" transcript := Transcript. "initialized to stdout in readImageFromFile:HeapSize:StartingAt:" pcPreviousToFunction := PCPreviousToFunction. "initialized via StackInterpreter class>>declareCVarsIn:" statForceInterruptCheck := statStackOverflow := statCheckForEvents := statProcessSwitch := statIOProcessEvents := statStackPageDivorce := statIdleUsecs := 0!
Item was changed: ----- Method: StackInterpreter>>initializeInterpreter: (in category 'initialization') ----- initializeInterpreter: bytesToShift + "Initialize Interpreter state before starting execution of a new image. + N.B. do *NOT* initialize variables that can be initialized via command line + arguments since command line arguments are proicessed before the image + is loaded and this initialization takes place after the image is loaded. + Anything that us not initialized to either 0 or false (the C default value) + should be initialized in StackInterpeeter class>>declareCVarsIn:" - "Initialize Interpreter state before starting execution of a new image." interpreterProxy := self sqGetInterpreterProxy. self dummyReferToProxy. objectMemory initializeObjectMemory: bytesToShift. self checkAssumedCompactClasses. self initializeExtraClassInstVarIndices. method := newMethod := objectMemory nilObject. self cCode: '' inSmalltalk: [breakSelectorLength ifNil: [breakSelectorLength := objectMemory minSmallInteger]. breakLookupClassTag ifNil: [breakLookupClassTag := -1]. reenterInterpreter := ReenterInterpreter new]. methodDictLinearSearchLimit := 8. self initialCleanup. - primitiveDoMixedArithmetic := true. LowcodeVM ifTrue: [ self setupNativeStack ]. profileSemaphore := profileProcess := profileMethod := objectMemory nilObject. self cCode: '' inSmalltalk: [InitializationOptions at: #profiling ifPresent: [:profiling| "hack turn on profiling, for testing in the simulator." profiling ifTrue: [profileSemaphore := objectMemory cloneObject: (objectMemory splObj: TheInterruptSemaphore). objectMemory storePointerUnchecked: FirstLinkIndex ofObject: profileSemaphore withValue: objectMemory nilObject; storePointerUnchecked: NextLinkIndex ofObject: profileSemaphore withValue: objectMemory nilObject; storePointerUnchecked: ExcessSignalsIndex ofObject: profileSemaphore withValue: (objectMemory integerObjectOf: 0)]]]. interruptKeycode := 2094. "cmd-. as used for Mac but no other OS" [globalSessionID = 0] whileTrue: [globalSessionID := self cCode: [((self time: #NULL) + self ioMSecs) bitAnd: 16r7FFFFFFF] inSmalltalk: [(Random new next * (SmallInteger maxVal min: 16r7FFFFFFF)) asInteger]]. metaAccessorDepth := -2. super initializeInterpreter: bytesToShift!
Item was changed: ----- Method: StackInterpreter>>setImageHeaderFlags: (in category 'internal interpreter access') ----- setImageHeaderFlags: flags "Set an array of flags indicating various properties of the saved image, responded to on image load. These are the same as the image header flags shifted right two bits, omitting the fullScreenFlag and float byte order flag. Bit 0: if set, implies the image's Process class has threadId as its 3rd inst var (zero relative) (meaningful to the MT VM only) Bit 1: if set, methods that are interpreted will have the flag bit set in their header (meaningful to the Cog VM only) Bit 2: if set, implies preempting a process does not put it to the back of its run queue Bit 3: if set, implies a threaded VM will not disown the VM if owned by the GUI thread (meaningful to the MT VM only) Bit 4: if set, implies the new finalization scheme where WeakArrays are queued Bit 5: if set, implies wheel events will be delivered as such and not mapped to arrow key events Bit 6: if set, implies arithmetic primitives will fail if given arguments of different types (float vs int) + Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times + Bit 8: if set, implies the VM will not upscale the display on high DPI devices" + flags asUnsignedInteger > 511 ifTrue: - Bit 7: if set, implies file primitives (FilePlugin, FileAttributesPlugin) will answer file times in UTC not local times" - flags asUnsignedInteger > 255 ifTrue: [^self primitiveFailFor: PrimErrUnsupported]. "processHasThreadId := flags anyMask: 1. specific to CoInterpreterMT" imageHeaderFlags := (flags anyMask: 1) ifTrue: [imageHeaderFlags bitOr: 4] ifFalse: [imageHeaderFlags bitClear: 4]. "flagInterpretedMethods := flags anyMask: 2. specific to CoInterpreter" imageHeaderFlags := (flags anyMask: 2) ifTrue: [imageHeaderFlags bitOr: 8] ifFalse: [imageHeaderFlags bitClear: 8]. preemptionYields := flags noMask: 4. "noThreadingOfGUIThread := flags anyMask: 8.. specific to CoInterpreterMT" imageHeaderFlags := (flags anyMask: 8) ifTrue: [imageHeaderFlags bitOr: 32] ifFalse: [imageHeaderFlags bitClear: 32]. newFinalization := flags anyMask: 16. sendWheelEvents := flags anyMask: 32. primitiveDoMixedArithmetic := flags noMask: 64. imageHeaderFlags := (flags anyMask: 128) ifTrue: [imageHeaderFlags bitOr: 512] + ifFalse: [imageHeaderFlags bitClear: 512]. + upscaleDisplayIfHighDPI := flags noMask: 256! - ifFalse: [imageHeaderFlags bitClear: 512]!
Item was changed: ----- Method: StackInterpreter>>setImageHeaderFlagsFrom: (in category 'image save/restore') ----- setImageHeaderFlagsFrom: headerFlags "Set the flags that are contained in the 7th long of the image header." imageHeaderFlags := headerFlags. "so as to preserve unrecognised flags." fullScreenFlag := headerFlags bitAnd: 1. imageFloatsBigEndian := (headerFlags noMask: 2) ifTrue: [1] ifFalse: [0]. "processHasThreadId := headerFlags anyMask: 4. specific to CoInterpreterMT" "flagInterpretedMethods := headerFlags anyMask: 8. specific to CoInterpreter" preemptionYields := headerFlags noMask: 16. "noThreadingOfGUIThread := headerFlags anyMask: 32. specific to CoInterpreterMT" newFinalization := headerFlags anyMask: 64. sendWheelEvents := headerFlags anyMask: 128. + primitiveDoMixedArithmetic := headerFlags noMask: 256. + "N.B. flag mask 512 is responded to by the FIlePlugin & FileAttributesPlugin" + upscaleDisplayIfHighDPI := headerFlags noMask: 1024! - primitiveDoMixedArithmetic := headerFlags noMask: 256!
Add the upscaleDisplayIfHighDPI flag to the VM. This is true by default. It is controlled by bit 8 of the Persistent image header flags, accessed via vmParameterAt: 48 [put:...].
When this flag is true (i.e. when the image header flag bit is unset) then VMs are expected to upscale the display on high DPI displays as they have in the past. When this flag is false (i.e. when the image header flag bit is set) the VM is expected not to upscale, leaving it to the image to do so.
This flag is present to enable new VMs to allow the image to do its own scaling while keeping on scaling older images unaware of the option.
I'm not really happy with that.
Whether an OS can handle scaling is nothing that should end up in the image format.
just my 2ct. -t
Hi Tobias --
Whether an OS can handle scaling is nothing that should end up in the image format.
It's not about the OS capabilities. Instead, we assume that the OS cannot handle scaling and offer scaling through the VM. For the OS, that VM/app would always look like it is able to be high-DPI compatible. It is just about a contract between VM and image.
(Yet, opt-out would be nice since Windows can still offer scaling itself and might be faster with it...)
Best, Marcel Am 21.06.2022 12:56:40 schrieb Tobias Pape das.linux@gmx.de:
Add the upscaleDisplayIfHighDPI flag to the VM. This is true by default. It is controlled by bit 8 of the Persistent image header flags, accessed via vmParameterAt: 48 [put:...].
When this flag is true (i.e. when the image header flag bit is unset) then VMs are expected to upscale the display on high DPI displays as they have in the past. When this flag is false (i.e. when the image header flag bit is set) the VM is expected not to upscale, leaving it to the image to do so.
This flag is present to enable new VMs to allow the image to do its own scaling while keeping on scaling older images unaware of the option.
I'm not really happy with that.
Whether an OS can handle scaling is nothing that should end up in the image format.
just my 2ct. -t
vm-dev@lists.squeakfoundation.org