[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