[Vm-dev] VM Maker: VMMaker.oscog-eem.2989.mcz
commits at source.squeak.org
commits at source.squeak.org
Wed Jul 21 01:01:33 UTC 2021
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2989.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.2989
Author: eem
Time: 20 July 2021, 6:01:24.90512 pm
UUID: 57c50442-278b-4065-8cc8-02c2bbc45570
Ancestors: VMMaker.oscog-eem.2988
Avoid toggling code zone executability on scavenge.
Fiddle with associated assertions.
=============== Diff against VMMaker.oscog-eem.2988 ===============
Item was changed:
----- Method: CogMethodZone>>ensureInYoungReferrers: (in category 'young referers') -----
ensureInYoungReferrers: cogMethod
<var: #cogMethod type: #'CogMethod *'>
cogit assertValidDualZoneReadAddress: cogMethod.
cogMethod cmRefersToYoung ifFalse:
[| writableMethod |
self assert: (self occurrencesInYoungReferrers: cogMethod) = 0.
+ cogit ensureWritableCodeZone.
- self ensureWritableCodeZone.
(writableMethod := cogit writableMethodFor: cogMethod) cmRefersToYoung: true.
self addToYoungReferrers: writableMethod]!
Item was changed:
----- Method: Cogit>>debugAPISelector (in category 'debugging') -----
debugAPISelector
+ "Answer the selector the CoInterpreter or machine code called in on. Simulation only.
- "Answer the selector theCoInterpereter called in on. Simulation only.
Used to help the codeZoneIsExecutableNotWritable assert work."
<doNotGenerate>
+ ^(thisContext findContextSuchThat:
+ [:ctxt|
+ ((ctxt selector beginsWith: 'ce') and: [ctxt selector third isUppercase])
+ or: [ctxt sender notNil and: [ctxt sender receiver == coInterpreter]]]) ifNotNil: [:ctxt| ctxt selector]!
- ^(thisContext findContextSuchThat: [:ctxt| ctxt sender notNil and: [ctxt sender receiver == coInterpreter]]) ifNotNil: [:ctxt| ctxt selector]!
Item was changed:
----- Method: Cogit>>ensureExecutableCodeZone (in category 'memory access') -----
ensureExecutableCodeZone
"On some platforms run-time calls may be required to enable execution and disable
write-protect of the code zone. This is sequenced by ensuring that the code zone is
executable most of the time. Note that any code space modification requires an
icache flush (on processors with such an icache). Hence the least invasive time to
ensure code is executable is post icache flush. Making sure code is writable can be
done either before any bulk edit (e.g. code zone reclamation) or as part of any fine-
grained code modification (e.g. setting an anonymous method's selector)."
<inline: #always>
self cppIf: #DUAL_MAPPED_CODE_ZONE
ifFalse:
[backEnd needsCodeZoneExecuteWriteSwitch ifTrue:
+ [self cCode: nil inSmalltalk: [| currentAPISelector |
+ "What's all this crap? We're trying to catch cases where ensureExecutableCodeZone
+ is called without first calling ensureWritableCodeZone, and vice verse. But there are
+ lots of exceptions where code is not modified but executability is turned on unnecessarily.
+ The list of exceptions follows."
+ currentAPISelector := self debugAPISelector.
+ self assert: (codeZoneIsExecutableNotWritable not
+ or: [currentAPISelector == #mapObjectReferencesInMachineCode:
+ or: [currentAPISelector == #cogitPostGCAction:
+ or: [currentAPISelector == #ceSICMiss:
+ or: [currentAPISelector == #ceCPICMiss:receiver:
+ or: [currentAPISelector == #unlinkSendsOf:isMNUSelector:
+ or: [currentAPISelector == #unlinkSendsTo:andFreeIf:
+ or: [currentAPISelector == #followMovableLiteralsAndUpdateYoungReferrers]]]]]]])].
- [self cCode: nil inSmalltalk: [self assert: (codeZoneIsExecutableNotWritable not
- "this happens when the CoInterpreter sends
- mapObjectReferencesInMachineCode: followed by cogitPostGCAction:"
- or: [debugAPISelector == self debugAPISelector
- or: [debugAPISelector == #mapObjectReferencesInMachineCode:]])].
backEnd makeCodeZoneExecutable.
self cCode: nil inSmalltalk: [codeZoneIsExecutableNotWritable := true. debugAPISelector := self debugAPISelector]]]!
Item was changed:
----- Method: Cogit>>mapObjectReferencesInMachineCode: (in category 'jit - api') -----
mapObjectReferencesInMachineCode: gcMode
<api>
"Update all references to objects in machine code."
- self ensureWritableCodeZone.
gcMode caseOf: {
+ [GCModeNewSpace] -> ["N.B. do *not* ensureWritableCodeZone for every scavenge."
+ self mapObjectReferencesInMachineCodeForYoungGC].
+ [GCModeFull] -> [self ensureWritableCodeZone.
+ self mapObjectReferencesInMachineCodeForFullGC].
+ [GCModeBecome] -> [self ensureWritableCodeZone.
+ self mapObjectReferencesInMachineCodeForBecome] }.
- [GCModeNewSpace] -> [self mapObjectReferencesInMachineCodeForYoungGC].
- [GCModeFull] -> [self mapObjectReferencesInMachineCodeForFullGC].
- [GCModeBecome] -> [self mapObjectReferencesInMachineCodeForBecome] }.
(self asserta: methodZone freeStart <= methodZone youngReferrers) ifFalse:
[self error: 'youngReferrers list overflowed']!
Item was changed:
----- Method: Cogit>>mapObjectReferencesInMachineCodeForYoungGC (in category 'garbage collection') -----
mapObjectReferencesInMachineCodeForYoungGC
"Update all references to objects in machine code for either a Spur scavenging gc
or a Squeak V3 incremental GC. Avoid scanning all code by using the youngReferrers
list. In a young gc a method referring to young may no longer refer to young, but a
method not referring to young cannot and will not refer to young afterwards."
+ | pointer cogMethod hasYoungObj hasYoungObjPtr zoneIsWritable |
+ codeModified := zoneIsWritable := hasYoungObj := false.
- | pointer cogMethod hasYoungObj hasYoungObjPtr |
- hasYoungObj := false.
hasYoungObjPtr := (self addressOf: hasYoungObj put: [:val| hasYoungObj := val]) asInteger.
- codeModified := false.
pointer := methodZone youngReferrers.
[pointer < methodZone zoneEnd] whileTrue:
[self assert: hasYoungObj not.
cogMethod := coInterpreter cCoerceSimple: (objectMemory longAt: pointer) to: #'CogMethod *'.
cogMethod cmType = CMFree
ifTrue: [self assert: cogMethod cmRefersToYoung not]
ifFalse:
[self assert: (self cogMethodDoesntLookKosher: cogMethod) = 0.
cogMethod cmRefersToYoung ifTrue:
[| writableCogMethod |
self assert: (cogMethod cmType = CMMethod
or: [cogMethod cmType = CMOpenPIC]).
+ zoneIsWritable ifFalse:
+ [self ensureWritableCodeZone.
+ zoneIsWritable := true].
writableCogMethod := self writableMethodFor: cogMethod.
writableCogMethod selector: (objectRepresentation remapOop: cogMethod selector).
(objectMemory isYoung: cogMethod selector) ifTrue:
[hasYoungObj := true].
cogMethod cmType = CMMethod ifTrue:
[self assert: cogMethod objectHeader = objectMemory nullHeaderForMachineCodeMethod.
writableCogMethod methodObject: (objectRepresentation remapOop: cogMethod methodObject).
(objectMemory isYoung: cogMethod methodObject) ifTrue:
[hasYoungObj := true]].
self mapFor: cogMethod
performUntil: #remapIfObjectRef:pc:hasYoung:
arg: hasYoungObjPtr.
hasYoungObj
ifTrue: [hasYoungObj := false]
ifFalse: [writableCogMethod cmRefersToYoung: false]]].
pointer := pointer + objectMemory wordSize].
methodZone pruneYoungReferrers.
codeModified ifTrue: "After updating oops in inline caches we need to flush the icache."
[backEnd flushICacheFrom: methodZoneBase asUnsignedInteger to: methodZone freeStart]!
Item was changed:
----- Method: Cogit>>setCodeModified (in category 'memory access') -----
setCodeModified
"Three cases to avoid reading codeModified unless absolutely necessary. On some platforms run-time calls
may be required to enable execution and disable write-protect of the code zone. See the comment in ensureExecutableCodeZone."
<inline: #always>
self cppIf: #DUAL_MAPPED_CODE_ZONE
ifTrue: [codeModified := true]
ifFalse:
[backEnd needsCodeZoneExecuteWriteSwitch
ifTrue:
[codeModified ifFalse:
[codeModified := true.
+ backEnd makeCodeZoneWritable.
+ self cCode: nil inSmalltalk: [codeZoneIsExecutableNotWritable := false]]]
- backEnd makeCodeZoneWritable]]
ifFalse: [codeModified := true]]!
More information about the Vm-dev
mailing list