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

commits at source.squeak.org commits at source.squeak.org
Wed Apr 1 01:21:03 UTC 2020

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

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

Name: VMMaker.oscog-eem.2736
Author: eem
Time: 31 March 2020, 6:20:49.211408 pm
UUID: 1dd4c38f-c0b4-4edd-9165-f4a54a988fe7
Ancestors: VMMaker.oscog-eem.2735

Cog: fix genInvokeInterpretTrampoline; it must establish the var base.
Eliminate reenterInterpreter in the CoInterpreter (keeping it in the StackInterpreter; althoguh the success of the use in the CoInterpreter shows us that we should do the same, e.g. using assembler, in the StackInterpreter).

So now reentry into the interpreter from machine code does not use longjmp and we no longer use setjmp to establish the reentry-point.  We just use CFramePointer & CStackPointer.

Export the warning functions for Windows DLLs that want to use assertions.
Get rid of the preambleCCode implementation of invalidCompactClassError:

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

Item was changed:
  ----- Method: CoInterpreter class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: aCCodeGenerator
  	"Override to avoid repeating StackInterpreter's declarations and add our own extensions"
  	self class == thisContext methodClass ifFalse: [^self]. "Don't duplicate decls in subclasses"
  	NewspeakVM ifTrue:
  		[aCCodeGenerator addHeaderFile:'"nssendcache.h"'].
  		addHeaderFile: (aCCodeGenerator vmClass isThreadedVM 
  			ifTrue: ['"cointerpmt.h"'] 
  			ifFalse: ['"cointerp.h"']);
  	aCCodeGenerator vmClass
  		declareInterpreterVersionIn: aCCodeGenerator
  		defaultName: aCCodeGenerator interpreterVersion.
  		var: #heapBase type: #usqInt;
  		var: #statCodeCompactionUsecs type: #usqLong;
  		var: #maxLiteralCountForCompile
  			declareC: 'sqInt maxLiteralCountForCompile = MaxLiteralCountForCompile /* ', MaxLiteralCountForCompile printString, ' */';
  		var: #minBackwardJumpCountForCompile
  			declareC: 'sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* ', MinBackwardJumpCountForCompile printString, ' */'.
- 	aCCodeGenerator removeVariable: 'atCache'. "Way too much trouble than it's worth in the Cog VM"
+ 		removeVariable: 'atCache'; "Way too much trouble than it's worth in the Cog VM"
+ 		removeVariable: 'reenterInterpreter'. "We can use the JIT and CFrame/StrackPointer for a lighter-weight solution."
+ 	aCCodeGenerator
  		var: #primTraceLogIndex type: #'unsigned char';
  		var: #primTraceLog declareC: 'sqInt primTraceLog[256]';
  		var: #traceLog
  		declareC: 'sqInt traceLog[TraceBufferSize /* ', TraceBufferSize printString, ' */]';
  		var: #traceSources type: #'char *' array: TraceSources.
  		var: #CFramePointer type: #'volatile usqIntptr_t';
  		var: #CStackPointer type: #'volatile usqIntptr_t'!

Item was added:
+ ----- Method: CoInterpreter>>activateFailingPrimitiveMethod (in category 'primitive support') -----
+ activateFailingPrimitiveMethod
+ 	"Assuming the primFailCode (and any other relevant failure state) has been set,
+ 	 switch the VM to the interpreter if necessary (if in the CoInterpreter executing machine code),
+ 	 and activate the newMethod (which is expected to have a primitive)."
+ 	self assert: primFailCode ~= 0.
+ 	self assert: (objectMemory addressCouldBeObj: newMethod).
+ 	self assert: (objectMemory isCompiledMethod: newMethod).
+ 	self assert: (self primitiveIndexOf: newMethod) ~= 0.
+ 	self justActivateNewMethod: true. "Frame must be interpreted"
+ 	cogit ceInvokeInterpret.
+ 	^nil!

Item was changed:
  ----- Method: CoInterpreter>>callbackEnter: (in category 'callback support') -----
  callbackEnter: callbackID
  	"Re-enter the interpreter for executing a callback"
+ 	| currentCStackPointer currentCFramePointer wasInMachineCode calledFromMachineCode |
- 	| currentCStackPointer currentCFramePointer savedReenterInterpreter
- 	  wasInMachineCode calledFromMachineCode |
  	<export: true>
  	<var: #currentCStackPointer type: #usqIntptr_t>
  	<var: #currentCFramePointer type: #usqIntptr_t>
  	<var: #callbackID type: #'sqInt *'>
- 	<var: #savedReenterInterpreter type: #'jmp_buf'>
  	"For now, do not allow a callback unless we're in a primitiveResponse"
  	(self asserta: primitiveFunctionPointer ~= 0) ifFalse:
  	self assert: primFailCode = 0.
  	"Check if we've exceeded the callback depth"
  	(self asserta: jmpDepth < MaxJumpBuf) ifFalse:
  	jmpDepth := jmpDepth + 1.
  	wasInMachineCode := self isMachineCodeFrame: framePointer.
  	calledFromMachineCode := instructionPointer <= objectMemory startOfMemory.
  	"Suspend the currently active process"
  	suspendedCallbacks at: jmpDepth put: self activeProcess.
  	"We need to preserve newMethod explicitly since it is not activated yet
  	and therefore no context has been created for it. If the caller primitive
  	for any reason decides to fail we need to make sure we execute the correct
  	method and not the one 'last used' in the call back"
  	suspendedMethods at: jmpDepth put: newMethod.
  	self flag: 'need to debug this properly.  Conceptually it is the right thing to do but it crashes in practice'.
  			["Signal external semaphores since a signalSemaphoreWithIndex: request may
  			  have been issued immediately prior to this callback before the VM has any
  			  chance to do a signalExternalSemaphores in checkForEventsMayContextSwitch:"
  			 self signalExternalSemaphores.
  			 "If no process is awakened by signalExternalSemaphores then transfer
  			  to the highest priority runnable one."
  			 (suspendedCallbacks at: jmpDepth) = self activeProcess ifTrue:
  				[self transferTo: self wakeHighestPriority from: CSCallbackLeave]]
  			[self transferTo: self wakeHighestPriority from: CSCallbackLeave].
  	"Typically, invoking the callback means that some semaphore has been 
  	signaled to indicate the callback. Force an interrupt check as soon as possible."
  	self forceInterruptCheck.
+ 	"Save the previous CStackPointers..."
- 	"Save the previous CStackPointers and interpreter entry jmp_buf."
  	currentCStackPointer := CStackPointer.
  	currentCFramePointer := CFramePointer.
- 	self memcpy: savedReenterInterpreter asVoidPointer
- 		_: reenterInterpreter
- 		_: (self sizeof: #'jmp_buf').
  	cogit assertCStackWellAligned.
  	(self setjmp: (jmpBuf at: jmpDepth)) = 0 ifTrue: "Fill in callbackID"
  		[callbackID at: 0 put: jmpDepth.
  		 self enterSmalltalkExecutive.
  		 self assert: false "NOTREACHED"].
+ 	"Restore the previous CStackPointers..."
- 	"Restore the previous CStackPointers and interpreter entry jmp_buf."
  	self setCFramePointer: currentCFramePointer setCStackPointer: currentCStackPointer.
- 	self memcpy: reenterInterpreter
- 		_: (self cCoerceSimple: savedReenterInterpreter to: #'void *')
- 		_: (self sizeof: #'jmp_buf').
  	"Transfer back to the previous process so that caller can push result"
  	self putToSleep: self activeProcess yieldingIf: preemptionYields.
  	self transferTo: (suspendedCallbacks at: jmpDepth) from: CSCallbackLeave.
  	newMethod := suspendedMethods at: jmpDepth.	"see comment above"
  	argumentCount := self argumentCountOf: newMethod.
  	self assert: wasInMachineCode = (self isMachineCodeFrame: framePointer).
  			[instructionPointer asUnsignedInteger >= objectMemory startOfMemory ifTrue:
  				[self iframeSavedIP: framePointer put: instructionPointer.
  				 instructionPointer := cogit ceReturnToInterpreterPC]]
  			["Even if the context was flushed to the heap and rebuilt in transferTo:from:
  			  above it will remain an interpreted frame because the context's pc would
  			  remain a bytecode pc.  So the instructionPointer must also be a bytecode pc."
  			 self assert: (self isMachineCodeFrame: framePointer) not.
  			 self assert: instructionPointer > objectMemory startOfMemory].
  	self assert: primFailCode = 0.
  	jmpDepth := jmpDepth-1.

Item was changed:
  ----- Method: CoInterpreter>>enterSmalltalkExecutiveImplementation (in category 'initialization') -----
  	"Main entry-point into the interpreter at each execution level, where an execution
  	 level is either the start of execution or reentry for a callback.  Capture the C stack
  	 pointers so that calls from machine-code into the C run-time occur at this level.
  	 This is the actual implementation, separated from enterSmalltalkExecutive so the
  	 simulator can wrap it in an exception handler and hence simulate the setjmp/longjmp."
  	<inline: false>
  	cogit assertCStackWellAligned.
  	cogit ceCaptureCStackPointers.
- 	"Setjmp for reentry into interpreter from elsewhere, e.g. machine-code trampolines."
- 	self sigset: reenterInterpreter jmp: 0.
  	(self isMachineCodeFrame: framePointer) ifTrue:
  		[self returnToExecutive: false postContextSwitch: true
  	self setMethod: (self iframeMethod: framePointer).
  	instructionPointer = cogit ceReturnToInterpreterPC ifTrue:
  		[instructionPointer := self iframeSavedIP: framePointer].
  	self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true line: #'__LINE__'.
  	self interpret.

Item was changed:
  ----- Method: CoInterpreter>>invokeInterpreterFromMachineCode (in category 'trampolines') -----
  	"This is just a rename for a send of interpret, but provides
  	 a simulation hook; see the CogVMSimulator subclass."
  	<inline: #always>
+ 	cogit ceInvokeInterpret
- 	self interpret

Item was changed:
  ----- Method: CoInterpreter>>restoreCStackStateForCallbackContext: (in category 'callback support') -----
  restoreCStackStateForCallbackContext: vmCallbackContext
  	<var: #vmCallbackContext type: #'VMCallbackContext *'>
+ 	<inline: #always>
+ 	self setCFramePointer: vmCallbackContext savedCFramePointer setCStackPointer: vmCallbackContext savedCStackPointer!
- 	self setCFramePointer: vmCallbackContext savedCFramePointer setCStackPointer: vmCallbackContext savedCStackPointer.
- 	self memcpy: reenterInterpreter
- 		_: vmCallbackContext savedReenterInterpreter asVoidPointer
- 		_: (self sizeof: #'jmp_buf')!

Item was changed:
  ----- Method: CoInterpreter>>saveCStackStateForCallbackContext: (in category 'callback support') -----
  saveCStackStateForCallbackContext: vmCallbackContext
  	<var: #vmCallbackContext type: #'VMCallbackContext *'>
+ 	<inline: #always>
  		savedCStackPointer: CStackPointer asVoidPointer;
+ 		savedCFramePointer: CFramePointer asVoidPointer!
- 		savedCFramePointer: CFramePointer asVoidPointer.
- 	super saveCStackStateForCallbackContext: vmCallbackContext!

Item was removed:
- ----- Method: CogVMSimulator>>invalidCompactClassError: (in category 'interpreter shell') -----
- invalidCompactClassError: name
- 	self error: 'Class ', name, ' does not have the required compact class index'!

Item was changed:
  ----- Method: Cogit>>genInvokeInterpretTrampoline (in category 'initialization') -----
  	"Switch to the C stack (do *not* save the Smalltalk stack pointers;
  	 this is the caller's responsibility), and invoke interpret PDQ."
  	| startAddress |
  	<inline: false>
  	startAddress := methodZoneBase.
  	self zeroOpcodeIndex.
+ 	backEnd hasVarBaseRegister ifTrue:
+ 		[self MoveCq: self varBaseAddress R: VarBaseReg]. "Must happen first; value may be used in genLoadStackPointers"
  		ifTrue: [backEnd genLoadCStackPointers]
  		ifFalse: [backEnd genLoadCStackPointer].
+ 	self CallFullRT: #interpret registersToBeSavedMask: self emptyRegisterMask.
- 	self
- 		compileCallFor: #interpret
- 		numArgs: 0 arg: nil arg: nil arg: nil arg: nil
- 		resultReg: NoReg
- 		regsToSave: self emptyRegisterMask.
  	self outputInstructionsForGeneratedRuntimeAt: startAddress.
  	self recordGeneratedRunTime: 'ceInvokeInterpret' address: startAddress.

Item was removed:
- ----- Method: InterpreterSimulator>>invalidCompactClassError: (in category 'interpreter shell') -----
- invalidCompactClassError: name
- 	self error: 'Class ', name, ' does not have the required compact class index'!

Item was added:
+ ----- Method: ObjectMemory>>invalidCompactClassError: (in category 'initialization') -----
+ invalidCompactClassError: className
+ 	<inline: false>
+ 	self cCode:
+ 			['\nClass %s does not have the required compact class index\n' printf: className.
+ 			 self exit: -1]
+ 		inSmalltalk:
+ 			[self error: 'Class ', className, ' does not have the required compact class index']!

Item was added:
+ ----- Method: SpurMemoryManager>>invalidCompactClassError: (in category 'initialization') -----
+ invalidCompactClassError: className
+ 	<inline: false>
+ 	self cCode:
+ 			['\nClass %s does not have the required class index\n' printf: className.
+ 			 self exit: -1]
+ 		inSmalltalk:
+ 			[self error: 'Class ', className, ' does not have the required class index']!

Item was changed:
  ----- Method: StackInterpreter class>>preambleCCode (in category 'translation') -----
  '/* Disable Intel compiler inlining of warning which is used for breakpoints */
  #pragma auto_inline(off)
  sqInt warnpid, erroronwarn;
+ EXPORT(void)
- void
  warning(char *s) { /* Print an error message but don''t necessarily exit. */
  	if (erroronwarn) error(s);
  	if (warnpid)
  		printf("\n%s pid %ld\n", s, (long)warnpid);
  		printf("\n%s\n", s);
+ EXPORT(void)
- void
  warningat(char *s, int l) { /* ditto with line number. */
  	/* use alloca to call warning so one does not have to remember to set two breakpoints... */
  	char *sl = alloca(strlen(s) + 16);
  	sprintf(sl, "%s %d", s, l);
  #pragma auto_inline(on)
- void
- invalidCompactClassError(char *s) { /* Print a (compact) class index error message and exit. */
- #if SPURVM
- 	printf("\nClass %s does not have the required class index\n", s);
- #else
- 	printf("\nClass %s does not have the required compact class index\n", s);
- #endif
- 	exit(-1);
- }
   * Define sigsetjmp and siglongjmp to be the most minimal setjmp/longjmp available on the platform.
   * Note: on windows 64 via mingw-w64, the 2nd argument NULL to _setjmp prevents stack unwinding
+  * On windows 32 via MSVC _longjmpex prevents stack unwinding. Not supported on windows 64.
  #undef sigsetjmp
  #undef siglongjmp
  #if _MSC_VER
+ # if _WIN64
+ #	define sigsetjmp(jb,ssmf) _setjmp(jb)
+ #	define siglongjmp(jb,v) longjmp(jb,v)
+ # else
+ #	define sigsetjmp(jb,ssmf) _setjmp(jb)
+ #	define siglongjmp(jb,v) _longjmpex(jb,v)
+ # endif
- # define sigsetjmp(jb,ssmf) _setjmp(jb)
- # define siglongjmp(jb,v) longjmp(jb,v)
  #elif _WIN64 && __GNUC__
  # define sigsetjmp(jb,ssmf) _setjmp(jb,NULL)
  # define siglongjmp(jb,v) longjmp(jb,v)
  #elif _WIN32
  # define sigsetjmp(jb,ssmf) setjmp(jb)
  # define siglongjmp(jb,v) longjmp(jb,v)
  # define sigsetjmp(jb,ssmf) _setjmp(jb)
  # define siglongjmp(jb,v) _longjmp(jb,v)
  #define odd(v) ((int)(v)&1)
  #define even(v) (!!odd(v))

Item was removed:
- ----- Method: StackInterpreterSimulator>>invalidCompactClassError: (in category 'interpreter shell') -----
- invalidCompactClassError: name
- 	self error: 'Class ', name, ' does not have the required compact class index'!

More information about the Vm-dev mailing list