[Vm-dev] VM Maker: VMMaker.oscog-eem.3023.mcz

commits at source.squeak.org commits at source.squeak.org
Wed Aug 4 01:45:37 UTC 2021

Eliot Miranda uploaded a new version of VMMaker to project VM Maker:

==================== Summary ====================

Name: VMMaker.oscog-eem.3023
Author: eem
Time: 3 August 2021, 6:45:07.99875 pm
UUID: 61eede2e-898d-4e76-bfda-c8977f0add59
Ancestors: VMMaker.oscog-eem.3022

Add a separate trace flag to turn on logging of FastCPrimitiveCall primitives.

=============== Diff against VMMaker.oscog-eem.3022 ===============

Item was added:
+ ----- Method: CoInterpreter>>recordFastCCallPrimTraceForMethod: (in category 'compiled methods') -----
+ recordFastCCallPrimTraceForMethod: aMethodObj
+ 	"This is a little elaborate.  The primTraceLog is only useful if it is not full of noise.
+ 	 To reduce noise when debugging a specific plugin we allow a plugin name to be
+ 	 specified and will only generate the primTraceLog code for primitives in that plugin."
+ 	<api>
+ 	<inline: true>
+ 	^cogit recordFastCCallPrimTrace
+ 	  and: [primTracePluginName
+ 				ifNil: [true]
+ 				ifNotNil: [self methodHasPrimitiveInPrimTracePlugin: aMethodObj]]!

Item was added:
+ ----- Method: Cogit>>recordFastCCallPrimTrace (in category 'debugging') -----
+ recordFastCCallPrimTrace
+ 	<api>
+ 	<cmacro: '() (traceFlags & 512)'>
+ 	^(traceFlags bitAnd: 512) ~= 0!

Item was changed:
  ----- Method: Cogit>>sendTrace: (in category 'debugging') -----
  sendTrace: aBooleanOrInteger
  	"traceFlags is a set of flags.
  	 1 => print trace (if something below is selected)
  	 2 => trace sends
  	 4 => trace block activations
+ 	 8 => trace interpreter primitives (on by default; see Cogit class>>#declareCVarsIn:)
- 	 8 => trace interpreter primitives
  	 16 => trace events (context switches, GCs, etc)
  	 32 => trace stack overflow
  	 64 => send breakpoint on implicit receiver (Newspeak VM only)
  	128 => check stack depth on send (simulation only)
+ 	256 => trace linked sends
+ 	512 => trace fast C call interpreter primitives (off by default)"
- 	256 => trace linked sends "
  	traceFlags := aBooleanOrInteger isInteger
+ 						ifTrue: [aBooleanOrInteger]
+ 						ifFalse: [aBooleanOrInteger ifTrue: [traceFlags bitOr: 6] ifFalse: [traceFlags bitClear: 6]]!
- 							ifTrue: [aBooleanOrInteger]
- 							ifFalse: [aBooleanOrInteger ifTrue: [6] ifFalse: [0]]!

Item was changed:
  ----- Method: InterpreterPlugin>>doesNotUnderstand: (in category 'simulation support') -----
  doesNotUnderstand: aMessage
+ 	"Override doesNotUnderstand: to intercept sends of translated primitive selectors.
- 	"Override doesNotUnderstand: to iuntercept sends of translated primitive selectors.
  	 The translated primitives are primitives derived from the primitive methods themselves
+ 	 translating their failure code/method body into Slang code.  There used to be several
+ 	 translated primitives in the MiscPrimitivePlugin, but these have been replaced.  As of
+ 	 mid 2021 only ADPCMCodec[Plugin] class and AbstractSound/SoundGenerationPlugin class
+ 	 define translatedPrimitives."
- 	 translating their failure code/method body into Slang code."
  	(self methodAndTypesOrNilForTranslatedPrimitiveSelector: aMessage selector)
  		ifNil: [^super doesNotUnderstand: aMessage]
  			[:tuple| | method |
  			 "First check the cache for validity; if the last element of the tuple is the actual method
  			 then the cache is up-to-date.  if it is not, the method has changed and should be regenerated."
  			 method := tuple last.
  			 method == (method methodClass >> method selector) ifFalse:
  				[translatedMethodCache removeKey: aMessage selector.
  				 ^self doesNotUnderstand: aMessage].
  			 method := tuple first.
  			 tuple second
  				ifNil: [interpreterProxy primitiveFail]
  					 self tryToRunTranslatedPrimitive: method types: types subsidiaries: tuple third].
+ 			 interpreterProxy transcript print: method; cr.
+ 			 interpreterProxy coInterpreter printExternalHeadFrame.
- 			(#(	compare:with:collated:
- 				findFirstInString:inSet:startingAt:
- 				findSubstring:in:startingAt:matchTable:
- 				hashBytes:startingWith:
- 				indexOfAscii:inString:startingAt:
- 				translate:from:to:table:
- 				compress:toByteArray:
- 				decompress:fromByteArray:at:)
- 					includes: method selector) ifFalse:
- 				[interpreterProxy transcript print: method; cr.
- 				 interpreterProxy coInterpreter printExternalHeadFrame].
  			 interpreterProxy failed ifTrue:
  				[interpreterProxy transcript
  					nextPutAll: 'WARNING!! Failing translated primitive ';
  					nextPutAll: aMessage selector;
  					nextPutAll: ' implemented by ';
  					nextPutAll: method methodClass name;
  					nextPutAll: '>>';
  					nextPutAll: method selector;

Item was changed:
  ----- Method: SimpleStackBasedCogit>>compileOnStackExternalPrimitive:flags: (in category 'primitive generators') -----
  compileOnStackExternalPrimitive: primitiveRoutine flags: flags
  	"Compile a fast call of a C primitive using the current stack page, avoiding the stack switch except on failure.
  	 This convention still uses stackPointer and argumentCount to access operands.  Push all operands to the stack,
  	 assign stackPointer, argumentCount, and zero primFailCode.  Make the call (saving a LinkReg if required).
  	 Test for failure and return.  On failure on Spur, if there is an accessor depth, assign framePointer and newMethod,
  	 do the stack switch, call checkForAndFollowForwardedPrimitiveState, and loop back if forwarders are found.
  	 Fall through to frame build."
  	<var: #primitiveRoutine declareC: 'void (*primitiveRoutine)(void)'>
  	| calleeSavedRegisterMask linkRegSaveRegister spRegSaveRegister jmp retry |
  	self assert: (objectRepresentation hasSpurMemoryManagerAPI and: [flags anyMask: PrimCallOnSmalltalkStack]).
  	self deny: (backEnd hasVarBaseRegister
  				and: [self register: VarBaseReg isInMask: ABICallerSavedRegisterMask]).
+ 	(coInterpreter recordFastCCallPrimTraceForMethod: methodObj) ifTrue:
+ 		[self genFastPrimTraceUsing: ClassReg and: SendNumArgsReg].
  	"Clear the primFailCode and set argumentCount"
  	self MoveCq: 0 R: TempReg.
  	self MoveR: TempReg Aw: coInterpreter primFailCodeAddress.
  	methodOrBlockNumArgs ~= 0 ifTrue:
  		[self AddCq: methodOrBlockNumArgs R: TempReg]. "As small or smaller than move on most archs"
  	self MoveR: TempReg Aw: coInterpreter argumentCountAddress.
  	self genExternalizeStackPointerForFastPrimitiveCall.
  	"We may need to save LinkReg and/or SPReg, and given the stack machinations
  	  it is much easier to save them in callee saved registers than on the stack itself."
  	calleeSavedRegisterMask := ABICalleeSavedRegisterMask bitClear: (self registerMaskFor: ClassReg).
  	backEnd hasLinkRegister ifTrue:
  		[linkRegSaveRegister := self availableRegisterOrNoneIn: calleeSavedRegisterMask.
  		 self deny: linkRegSaveRegister = NoReg.
  		 self MoveR: LinkReg R: linkRegSaveRegister.
  		 calleeSavedRegisterMask := calleeSavedRegisterMask bitClear: (self registerMaskFor: linkRegSaveRegister)].
  	spRegSaveRegister := NoReg.
  	(SPReg ~= NativeSPReg
  	 and: [(self isCalleeSavedReg: SPReg) not]) ifTrue:
  		[spRegSaveRegister := self availableRegisterOrNoneIn: calleeSavedRegisterMask.
  		 self deny: spRegSaveRegister = NoReg.
  		 self MoveR: SPReg R: spRegSaveRegister].
  	retry := self Label.
  	(flags anyMask: PrimCallOnSmalltalkStackAlign2x)
  		ifTrue: [self AndCq: (objectMemory wordSize * 2 - 1) bitInvert R: SPReg R: NativeSPReg]
  			[SPReg ~= NativeSPReg ifTrue:
  				[backEnd genLoadNativeSPRegWithAlignedSPReg]].
  	self CallFullRT: primitiveRoutine.
  	self MoveAw: coInterpreter primFailCodeAddress R: TempReg.
  	spRegSaveRegister ~= NoReg ifTrue:
  		[self MoveR: spRegSaveRegister R: SPReg].
  	self CmpCq: 0 R: TempReg.
  	jmp := self JumpNonZero: 0.
  	"At this point the primitive has cut back stackPointer to point to the result."
  	self MoveAw: coInterpreter stackPointerAddress R: TempReg.
  	"get result and restore retpc"
  	backEnd hasLinkRegister
  			[self MoveMw: 0 r: TempReg R: ReceiverResultReg;
  				AddCq: objectMemory wordSize R: TempReg R: SPReg;
  				MoveR: linkRegSaveRegister R: LinkReg]
  			[| retpcOffset |
  			"The original retpc is (argumentCount + 1) words below stackPointer."
  			 retpcOffset := (methodOrBlockNumArgs + 1 * objectMemory wordSize) negated.
  			 self MoveMw: retpcOffset r: TempReg R: ClassReg; "get retpc"
  				MoveR: TempReg R: SPReg;
  			 	MoveMw: 0 r: TempReg R: ReceiverResultReg;
  				MoveR: ClassReg Mw: 0 r: TempReg "put it back on stack for the return..."].
  	self RetN: 0.
  	jmp jmpTarget: self Label.
  	(coInterpreter accessorDepthForExternalPrimitiveMethod: methodObj) >= 0
  			[| skip |
  			 "Given that following primitive state to the accessor depth is recursive, we're asking for
  			  trouble if we run the fixup on the Smalltalk stack page.  Run it on the full C stack instead.
  			 This won't be a performance issue since primitive failure should be very rare."
  			self MoveR: FPReg Aw: coInterpreter framePointerAddress.
  			self MoveCw: primitiveRoutine asInteger R: TempReg.
  			self MoveR: TempReg Aw: coInterpreter primitiveFunctionPointerAddress.
  			methodLabel addDependent:
  				(self annotateAbsolutePCRef:
  					(self MoveCw: methodLabel asInteger R: ClassReg)).
  			self MoveMw: (self offset: CogMethod of: #methodObject) r: ClassReg R: TempReg.
  			self MoveR: TempReg Aw: coInterpreter newMethodAddress.
  			self genLoadCStackPointersForPrimCall.
  			self CallFullRT: (self cCode: [#checkForAndFollowForwardedPrimitiveState asUnsignedIntegerPtr]
  								   inSmalltalk: [self simulatedTrampolineFor: #checkForAndFollowForwardedPrimitiveState]).
  			backEnd genLoadStackPointersForFastPrimCall: ClassReg.
  			self CmpCq: 0 R: ABIResultReg.
  			skip := self JumpZero: 0.
  			self MoveCq: 0 R: TempReg.
  			self MoveR: TempReg Aw: coInterpreter primFailCodeAddress.
  			self Jump: retry.
  			skip jmpTarget: self Label]
  		ifFalse: "must reload SPReg to undo any alignment change,"
  			[(flags anyMask: PrimCallOnSmalltalkStackAlign2x) ifTrue:
  				[backEnd genLoadStackPointersForFastPrimCall: ClassReg]].
  	"The LinkRegister now contains the return address either of the primitive call or of checkForAndFollowForwardedPrimitiveState.
  	 It must be restored to the return address of the send invoking this primtiive method."
  	backEnd hasLinkRegister ifTrue:
  		[self MoveR: linkRegSaveRegister R: LinkReg].
  	"Finally remember to reload ReceiverResultReg if required.  Even if
  	 arguments have been pushed, the prolog sequence assumes it is live."
  	(self register: ReceiverResultReg isInMask: ABICallerSavedRegisterMask) ifTrue:
  		[self MoveMw: (methodOrBlockNumArgs + (backEnd hasLinkRegister ifTrue: [0] ifFalse: [1])) * objectMemory wordSize
  			r: SPReg
  			R: ReceiverResultReg].
  	"continue to frame build..."

More information about the Vm-dev mailing list