Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.3050.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.3050 Author: eem Time: 31 August 2021, 4:19:17.748712 pm UUID: 735b9bfc-cf40-4a45-b98e-7f9a2b979b5e Ancestors: VMMaker.oscog-mt.3049
Cogit: avoid using the Context store check for the Spur extended push/spop/store receiver var bytecodes by extending receiverTags with a bit for "maybe Context class". This is good for a 35% speedup in ReadStream>>#next et al, e.g.
| string stream | string := (SourceFiles at: 2) contentsOfEntireFile. string := string first: (string size roundDownTo: 10000). stream := ReadStream on: string. [[stream next isNil] whileFalse] timeToRun
=============== Diff against VMMaker.oscog-mt.3049 ===============
Item was added: + ----- Method: CogObjectRepresentationForSpur>>storeTrampolines (in category 'accessing') ----- + storeTrampolines + <doNotGenerate> + ^ceStoreTrampolines!
Item was changed: ----- Method: Cogit>>cog:selector: (in category 'jit - api') ----- cog: aMethodObj selector: aSelectorOop "Attempt to produce a machine code method for the bytecode method object aMethodObj. N.B. If there is no code memory available do *NOT* attempt to reclaim the method zone. Certain clients (e.g. ceSICMiss:) depend on the zone remaining constant across method generation." <api> <returnTypeC: #'CogMethod *'> | selector cogMethod | <var: #cogMethod type: #'CogMethod *'> (self exclude: aMethodObj selector: aSelectorOop) ifTrue: [^nil]. "In Newspeak we support anonymous accessors and hence tolerate the same method being cogged multiple times. But only if the method class association is nil." NewspeakVM ifTrue: [(coInterpreter methodHasCogMethod: aMethodObj) ifTrue: [cogMethod := coInterpreter cogMethodOf: aMethodObj. self deny: cogMethod selector = aSelectorOop. cogMethod selector = aSelectorOop ifTrue: [^cogMethod]. (coInterpreter methodClassAssociationOf: aMethodObj) ~= objectMemory nilObject ifTrue: [self cCode: 'extern void *firstIndexableField(sqInt)'. "Slang, au natural" self warnMultiple: cogMethod selectors: aSelectorOop. ^nil]]] ifFalse: [self deny: (coInterpreter methodHasCogMethod: aMethodObj)]. self deny: (objectMemory isOopCompiledMethod: (coInterpreter ultimateLiteralOf: aMethodObj)). selector := aSelectorOop = objectMemory nilObject ifTrue: [coInterpreter maybeSelectorOfMethod: aMethodObj] ifFalse: [aSelectorOop]. "coInterpreter stringOf: selector" selector ifNotNil: [coInterpreter compilationBreakpoint: selector isMNUCase: false]. aMethodObj = breakMethod ifTrue: [self halt: 'Compilation of breakMethod']. NewspeakVM ifTrue: [cogMethod := methodZone findPreviouslyCompiledVersionOf: aMethodObj with: aSelectorOop. cogMethod ifNotNil: [(coInterpreter methodHasCogMethod: aMethodObj) not ifTrue: [self assert: (coInterpreter rawHeaderOf: aMethodObj) = cogMethod methodHeader. cogMethod methodObject: aMethodObj. coInterpreter rawHeaderOf: aMethodObj put: cogMethod asInteger]. ^cogMethod]]. "If the generators for the alternate bytecode set are missing then interpret." (coInterpreter methodUsesAlternateBytecodeSet: aMethodObj) ifTrue: [(self numElementsIn: generatorTable) <= 256 ifTrue: [^nil]. bytecodeSetOffset := 256] ifFalse: [bytecodeSetOffset := 0]. objectRepresentation ensureNoForwardedLiteralsIn: aMethodObj. methodObj := aMethodObj. methodHeader := objectMemory methodHeaderOf: aMethodObj. + receiverTags := -1. "lazy initialization" - receiverTags := objectMemory receiverTagBitsForMethod: methodObj. cogMethod := self compileCogMethod: aSelectorOop. (cogMethod asInteger between: MaxNegativeErrorCode and: -1) ifTrue: [cogMethod asInteger = InsufficientCodeSpace ifTrue: [coInterpreter callForCogCompiledCodeCompaction]. self maybeFreeCounters. "Right now no errors should be reported, so nothing more to do." "self reportError: (self cCoerceSimple: cogMethod to: #sqInt)." ^nil]. "self cCode: '' inSmalltalk: [coInterpreter printCogMethod: cogMethod. ""coInterpreter symbolicMethod: aMethodObj."" self assertValidMethodMap: cogMethod." "self disassembleMethod: cogMethod." "printInstructions := clickConfirm := true""]." ^cogMethod!
Item was changed: ----- Method: Cogit>>cogFullBlockMethod:numCopied: (in category 'jit - api') ----- cogFullBlockMethod: aMethodObj numCopied: numCopied "Attempt to produce a machine code method for the bytecode method object aMethodObj. N.B. If there is no code memory available do *NOT* attempt to reclaim the method zone. Certain clients (e.g. ceSICMiss:) depend on the zone remaining constant across method generation." <api> <option: #SistaV1BytecodeSet> <returnTypeC: #'CogMethod *'> | cogMethod | <var: #cogMethod type: #'CogMethod *'> (self exclude: aMethodObj) ifTrue: [^nil]. self deny: (coInterpreter methodHasCogMethod: aMethodObj). self assert: (objectMemory isOopCompiledMethod: (coInterpreter ultimateLiteralOf: aMethodObj)). aMethodObj = breakMethod ifTrue: [self halt: 'Compilation of breakMethod']. "If the generators for the alternate bytecode set are missing then interpret." (coInterpreter methodUsesAlternateBytecodeSet: aMethodObj) ifTrue: [(self numElementsIn: generatorTable) <= 256 ifTrue: [^nil]. bytecodeSetOffset := 256] ifFalse: [bytecodeSetOffset := 0]. objectRepresentation ensureNoForwardedLiteralsIn: aMethodObj. methodObj := aMethodObj. methodHeader := objectMemory methodHeaderOf: aMethodObj. + receiverTags := -1. "lazy initialization" - receiverTags := objectMemory receiverTagBitsForMethod: methodObj. cogMethod := self compileCogFullBlockMethod: numCopied. (cogMethod asInteger between: MaxNegativeErrorCode and: -1) ifTrue: [cogMethod asInteger = InsufficientCodeSpace ifTrue: [coInterpreter callForCogCompiledCodeCompaction]. self maybeFreeCounters. "Right now no errors should be reported, so nothing more to do." "self reportError: (self cCoerceSimple: cogMethod to: #sqInt)." ^nil]. "self cCode: '' inSmalltalk: [coInterpreter printCogMethod: cogMethod. ""coInterpreter symbolicMethod: aMethodObj."" self assertValidMethodMap: cogMethod." "self disassembleMethod: cogMethod." "printInstructions := clickConfirm := true""]." ^cogMethod!
Item was added: + ----- Method: Cogit>>mclassCouldBeContext (in category 'initialization') ----- + mclassCouldBeContext + receiverTags < 0 ifTrue: + [receiverTags := objectMemory receiverTagBitsForMethod: methodObj]. + ^receiverTags anyMask: (1 bitShift: objectMemory numTagBits)!
Item was changed: ----- Method: Cogit>>mclassIsSmallInteger (in category 'initialization') ----- mclassIsSmallInteger + receiverTags < 0 ifTrue: + [receiverTags := objectMemory receiverTagBitsForMethod: methodObj]. ^objectMemory isIntegerObject: receiverTags!
Item was added: + ----- Method: CurrentImageCoInterpreterFacade>>ifTestProfilingAdvanceNextProfileTick (in category 'accessing') ----- + ifTestProfilingAdvanceNextProfileTick + ^self!
Item was changed: ----- Method: CurrentImageCoInterpreterFacadeForSpurObjectRepresentation>>receiverTagBitsForMethod: (in category 'accessing') ----- receiverTagBitsForMethod: methodOop + | mclass | + ^(mclass := (self objectForOop: methodOop) methodClass) - ^(self objectForOop: methodOop) methodClass caseOf: { + [SmallInteger] -> [objectMemory smallIntegerTag]. + [Character] -> [objectMemory characterTag]. + [SmallFloat64] -> [objectMemory smallFloatTag]. + [Context] -> [1 bitShift: objectMemory numTagBits] } + otherwise: + [(Context includesBehavior: mclass) + ifTrue: [1 bitShift: objectMemory numTagBits] + ifFalse: [0]]! - [SmallInteger] -> [objectMemory smallIntegerTag]. - [Character] -> [objectMemory characterTag]. - [SmallFloat64] -> [objectMemory smallFloatTag] } - otherwise: [0]!
Item was changed: ----- Method: CurrentImageCoInterpreterFacadeForSqueakV3ObjectRepresentation>>receiverTagBitsForMethod: (in category 'accessing') ----- receiverTagBitsForMethod: methodOop + ^(self objectForOop: methodOop) methodClass = SmallInteger - ^(self objectForOop: methodOop) methodClass =SmallInteger ifTrue: [1] ifFalse: [0]!
Item was changed: ----- Method: SimpleStackBasedCogit>>genExtPushReceiverVariableBytecode (in category 'bytecode generators') ----- genExtPushReceiverVariableBytecode "226 11100010 i i i i i i i i Push Receiver Variable #iiiiiiii (+ Extend A * 256)" | index | index := byte1 + (extA << 8). extA := 0. + ^(self mclassCouldBeContext + and: [coInterpreter isReadMediatedContextInstVarIndex: index]) - ^(coInterpreter isReadMediatedContextInstVarIndex: index) ifTrue: [self genPushMaybeContextReceiverVariable: index] ifFalse: [self genPushReceiverVariable: index]!
Item was changed: ----- Method: SimpleStackBasedCogit>>genExtStoreAndPopReceiverVariableBytecode (in category 'bytecode generators') ----- genExtStoreAndPopReceiverVariableBytecode "235 11101011 i i i i i i i i Pop and Store Receiver Variable #iiiiiii (+ Extend A * 256)" | index | index := byte1 + (extA << 8). extA := 0. + ^(self mclassCouldBeContext + and: [coInterpreter isWriteMediatedContextInstVarIndex: index]) - ^(coInterpreter isWriteMediatedContextInstVarIndex: index) ifTrue: [self genStorePop: true MaybeContextReceiverVariable: index] ifFalse: [self genStorePop: true ReceiverVariable: index]!
Item was changed: ----- Method: SimpleStackBasedCogit>>genExtStoreReceiverVariableBytecode (in category 'bytecode generators') ----- genExtStoreReceiverVariableBytecode "232 11101000 i i i i i i i i Store Receiver Variable #iiiiiii (+ Extend A * 256)" | index | index := byte1 + (extA << 8). extA := 0. + ^(self mclassCouldBeContext + and: [coInterpreter isWriteMediatedContextInstVarIndex: index]) - ^(coInterpreter isWriteMediatedContextInstVarIndex: index) ifTrue: [self genStorePop: false MaybeContextReceiverVariable: index] ifFalse: [self genStorePop: false ReceiverVariable: index]!
Item was changed: ----- Method: SimpleStackBasedCogit>>genSistaExtStoreAndPopReceiverVariableBytecodePopBoolean: (in category 'bytecode generators') ----- genSistaExtStoreAndPopReceiverVariableBytecodePopBoolean: boolean | index | extB := 0. "Simple cogit don't use the extra flags" numExtB := 0. index := byte1 + (extA << 8). extA := 0. + ^(self mclassCouldBeContext + and: [coInterpreter isWriteMediatedContextInstVarIndex: index]) - ^(coInterpreter isWriteMediatedContextInstVarIndex: index) ifTrue: [self genStorePop: boolean MaybeContextReceiverVariable: index ] ifFalse: [self genStorePop: boolean ReceiverVariable: index ]!
Item was added: + ----- Method: Spur32BitCoMemoryManager>>receiverTagBitsForImmediateMethodClass: (in category 'cog jit support') ----- + receiverTagBitsForImmediateMethodClass: methodClassOrNil + <inline: #always> + ^methodClassOrNil = (self fetchPointer: self smallIntegerTag ofObject: classTableFirstPage) + ifTrue: [self smallIntegerTag] + ifFalse: [self assert: methodClassOrNil = (self fetchPointer: self characterTag ofObject: classTableFirstPage). + self characterTag]!
Item was removed: - ----- Method: Spur32BitCoMemoryManager>>receiverTagBitsForMethod: (in category 'cog jit support') ----- - receiverTagBitsForMethod: aMethodObj - "Answer the tag bits for the receiver based on the method's methodClass, if any." - <api> - | methodClassOrNil | - methodClassOrNil := coInterpreter methodClassOf: aMethodObj. - NewspeakVM "Mixins don't necessarily have a format inst var; filter out non-integer format." - ifTrue: - [| instSpec | - (methodClassOrNil = nilObj - or: [(self isNonIntegerObject: (instSpec := self fetchPointer: InstanceSpecificationIndex ofObject: methodClassOrNil)) - or: [(self instSpecOfClassFormat: (self integerValueOf: instSpec)) ~= self forwardedFormat]]) ifTrue: - [^0]] - ifFalse: - [(methodClassOrNil = nilObj - or: [(self instSpecOfClass: methodClassOrNil) ~= self forwardedFormat]) ifTrue: - [^0]]. - ^methodClassOrNil = (self fetchPointer: self smallIntegerTag ofObject: classTableFirstPage) - ifTrue: [self smallIntegerTag] - ifFalse: [self assert: methodClassOrNil = (self fetchPointer: self characterTag ofObject: classTableFirstPage). - self characterTag]!
Item was added: + ----- Method: Spur64BitCoMemoryManager>>receiverTagBitsForImmediateMethodClass: (in category 'cog jit support') ----- + receiverTagBitsForImmediateMethodClass: methodClassOrNil + <inline: #always> + methodClassOrNil = (self fetchPointer: self smallIntegerTag ofObject: classTableFirstPage) ifTrue: + [^self smallIntegerTag]. + methodClassOrNil = (self fetchPointer: self characterTag ofObject: classTableFirstPage) ifTrue: + [^self characterTag]. + self assert: methodClassOrNil = (self fetchPointer: self smallFloatTag ofObject: classTableFirstPage). + ^self smallFloatTag!
Item was removed: - ----- Method: Spur64BitCoMemoryManager>>receiverTagBitsForMethod: (in category 'cog jit support') ----- - receiverTagBitsForMethod: aMethodObj - "Answer the tag bits for the receiver based on the method's methodClass, if any." - <api> - | methodClassOrNil | - methodClassOrNil := coInterpreter methodClassOf: aMethodObj. - NewspeakVM "Mixins don't necessarily have a format inst var; filter out non-integer format." - ifTrue: - [| instSpec | - (methodClassOrNil = nilObj - or: [(self isNonIntegerObject: (instSpec := self fetchPointer: InstanceSpecificationIndex ofObject: methodClassOrNil)) - or: [(self instSpecOfClassFormat: (self integerValueOf: instSpec)) ~= self forwardedFormat]]) ifTrue: - [^0]] - ifFalse: - [(methodClassOrNil = nilObj - or: [(self instSpecOfClass: methodClassOrNil) ~= self forwardedFormat]) ifTrue: - [^0]]. - methodClassOrNil = (self fetchPointer: self smallIntegerTag ofObject: classTableFirstPage) ifTrue: - [^self smallIntegerTag]. - methodClassOrNil = (self fetchPointer: self characterTag ofObject: classTableFirstPage) ifTrue: - [^self characterTag]. - self assert: methodClassOrNil = (self fetchPointer: self smallFloatTag ofObject: classTableFirstPage). - ^self smallFloatTag!
Item was added: + ----- Method: SpurMemoryManager>>maybeContextMClassTagBits (in category 'cog jit support') ----- + maybeContextMClassTagBits + <inline: #always> + ^1 bitShift: self numTagBits!
Item was added: + ----- Method: SpurMemoryManager>>receiverTagBitsForMethod: (in category 'cog jit support') ----- + receiverTagBitsForMethod: aMethodObj + "Answer the tag bits for the receiver based on the method's methodClass, if any. + These bits are extended with a bit that says that the method may have a Context receiver, i.e. + mclass is Context or its superclasses. The absence of this bit is used to avoid expensive store checks, etc." + <api> + | methodClassOrNil classContextOrSuperclass | + methodClassOrNil := coInterpreter methodClassOf: aMethodObj. + methodClassOrNil = nilObj ifTrue: "If we don't know the methodClass be pessimal" + [^self maybeContextMClassTagBits]. + NewspeakVM "Mixins don't necessarily have a format inst var; filter out non-integer format." + ifTrue: + [| instSpec | + ((self isIntegerObject: (instSpec := self fetchPointer: InstanceSpecificationIndex ofObject: methodClassOrNil)) + and: [(self instSpecOfClassFormat: (self integerValueOf: instSpec)) = self forwardedFormat]) ifTrue: + [^self receiverTagBitsForImmediateMethodClass: methodClassOrNil]] + ifFalse: + [(self instSpecOfClass: methodClassOrNil) = self forwardedFormat ifTrue: + [^self receiverTagBitsForImmediateMethodClass: methodClassOrNil]]. + "Now check if mclass is one of Context's superclasses..." + classContextOrSuperclass := self knownClassAtIndex: ClassMethodContextCompactIndex. + [classContextOrSuperclass = methodClassOrNil ifTrue: + [^self maybeContextMClassTagBits]. + classContextOrSuperclass := self fetchPointer: SuperclassIndex ofObject: classContextOrSuperclass. + classContextOrSuperclass ~= nilObj] + whileTrue. + ^0!
vm-dev@lists.squeakfoundation.org