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

commits at source.squeak.org commits at source.squeak.org
Tue Jul 16 22:47:40 UTC 2013


Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.303.mcz

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

Name: VMMaker.oscog-eem.303
Author: eem
Time: 16 July 2013, 3:45:37.149 pm
UUID: 99b81fe2-3c89-43bb-8a2c-2541842da7e0
Ancestors: VMMaker.oscog-eem.302

Add assert:l: and asserta:l: which take line numbers.
Refactor assertValidExecutionPointe:r:s:imbar: to take a line number
and supply it to assert:l: et al, for more informative assert failures.

Use sqLowLevelMFence in deferStackLimitSmashAround:with: et al.

Refactor preambleCCode emission so that a comment indicating its
source is generated.

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

Item was changed:
  ----- Method: CCodeGenerator>>emitCHeaderOn: (in category 'C code generator') -----
  emitCHeaderOn: aStream
  	"Emit the initial part of a source file on aStream, comprising the version stamp,
  	 the global struct usage flags, the header files and preamble code."
  
  	| headerClass |
  	headerClass := [vmClass coreInterpreterClass]
  						on: MessageNotUnderstood
  						do: [:ex| vmClass].
  	aStream nextPutAll: (self fileHeaderVersionStampForSourceClass: headerClass); cr; cr.
  	self emitGlobalStructFlagOn: aStream.
  
  	self addHeaderFileFirst: '"sq.h"'.
  	vmClass isInterpreterClass ifTrue:
  		[self addHeaderFile: '"sqMemoryAccess.h"'].
  	"Additional header files; include C library ones first."
  	self emitHeaderFiles: (headerFiles select: [:hdr| hdr includes: $<]) on: aStream.
  	"Additional header files; include squeak VM ones last"
  	self emitHeaderFiles: (headerFiles reject: [:hdr| hdr includes: $<]) on: aStream.
  
  	vmClass isInterpreterClass ifTrue:
+ 		[self maybePutPreambleFor: vmClass on: aStream].
- 		[aStream cr; cr; nextPutAll: vmClass preambleCCode].
  
  	aStream cr!

Item was added:
+ ----- Method: CCodeGenerator>>maybePutPreambleFor:on: (in category 'C code generator') -----
+ maybePutPreambleFor: aClass on: aStream
+ 	aClass preambleCCode ifNotNil:
+ 		[:preamble| | actualClass |
+ 		 actualClass := aClass class whichClassIncludesSelector: #preambleCCode.
+ 		 aStream
+ 			ensureCr; cr;
+ 			nextPutAll: '/* '; print: actualClass; nextPutAll: '>>preambleCCode */'; cr;
+ 			nextPutAll: preamble; cr;
+ 			nextPutAll: '/* end '; print: actualClass; nextPutAll: '>>preambleCCode */'; cr]!

Item was removed:
- ----- Method: CoInterpreter>>assertValidExecutionPointe:r:s:imbar: (in category 'debug support') -----
- assertValidExecutionPointe: lip r: lifp s: lisp imbar: inInterpreter
- 	<var: #lip type: #usqInt>
- 	<var: #lifp type: #'char *'>
- 	<var: #lisp type: #'char *'>
- 	| methodField cogMethod |
- 	<var: #cogMethod type: #'CogMethod *'>
- 	self assert: stackPage = (stackPages stackPageFor: lifp).
- 	self assert: stackPage = stackPages mostRecentlyUsedPage.
- 	self deferStackLimitSmashAround: #assertValidStackLimits.
- 	self assert: lifp < stackPage baseAddress.
- 	self assert: lisp < lifp.
- 	self assert: lifp > lisp.
- 	self assert: lisp >= (stackPage realStackLimit - self stackLimitOffset).
- 	self assert:  (lifp - lisp) < LargeContextSize.
- 	methodField := self frameMethodField: lifp.
- 	inInterpreter
- 		ifTrue:
- 			[self assert: (self isMachineCodeFrame: lifp) not.
- 			 self assert: method = methodField.
- 			 self cppIf: MULTIPLEBYTECODESETS
- 				ifTrue: [self assert: (self methodUsesAlternateBytecodeSet: method) = (bytecodeSetSelector = 256)].
- 			 ((self asserta: methodField asUnsignedInteger > objectMemory startOfMemory)
- 			   and: [self asserta: methodField asUnsignedInteger < objectMemory freeStart]) ifTrue:
- 				[lip ~= cogit ceReturnToInterpreterPC ifTrue:
- 					[self assert: (lip >= (methodField + (objectMemory lastPointerOf: methodField) + BaseHeaderSize - 1)
- 								  and: [lip < (methodField + (objectMemory byteLengthOf: methodField) + BaseHeaderSize)])]].
- 			 self assert: ((self iframeIsBlockActivation: lifp)
- 					or: [(self pushedReceiverOrClosureOfFrame: lifp) = (self iframeReceiver: lifp)])]
- 		ifFalse:
- 			[self assert: (self isMachineCodeFrame: lifp).
- 			 ((self asserta: methodField asUnsignedInteger >= cogit minCogMethodAddress)
- 			  and: [self asserta: methodField asUnsignedInteger < cogit maxCogMethodAddress]) ifTrue:
- 				[cogMethod := self mframeHomeMethod: lifp.
- 				 self assert: (lip > (methodField + ((self mframeIsBlockActivation: lifp)
- 													ifTrue: [self sizeof: CogBlockMethod]
- 													ifFalse: [self sizeof: CogMethod]))
- 						and: [lip < (methodField + cogMethod blockSize)])].
- 			 self assert: ((self mframeIsBlockActivation: lifp)
- 					or: [(self pushedReceiverOrClosureOfFrame: lifp) = (self mframeReceiver: lifp)])].
- 	(self isBaseFrame: lifp) ifTrue:
- 		[self assert: (self frameHasContext: lifp).
- 		 self assert: (self frameContext: lifp) = (stackPages longAt: stackPage baseAddress - BytesPerWord)]!

Item was added:
+ ----- Method: CoInterpreter>>assertValidExecutionPointe:r:s:imbar:line: (in category 'debug support') -----
+ assertValidExecutionPointe: lip r: lifp s: lisp imbar: inInterpreter line: ln
+ 	<var: #lip type: #usqInt>
+ 	<var: #lifp type: #'char *'>
+ 	<var: #lisp type: #'char *'>
+ 	| methodField cogMethod |
+ 	<var: #cogMethod type: #'CogMethod *'>
+ 	self assert: stackPage = (stackPages stackPageFor: lifp) l: ln.
+ 	self assert: stackPage = stackPages mostRecentlyUsedPage l: ln.
+ 	self deferStackLimitSmashAround: #assertValidStackLimits: asSymbol with: ln.
+ 	self assert: lifp < stackPage baseAddress l: ln.
+ 	self assert: lisp < lifp l: ln.
+ 	self assert: lifp > lisp l: ln.
+ 	self assert: lisp >= (stackPage realStackLimit - self stackLimitOffset) l: ln.
+ 	self assert:  (lifp - lisp) < LargeContextSize l: ln.
+ 	methodField := self frameMethodField: lifp.
+ 	inInterpreter
+ 		ifTrue:
+ 			[self assert: (self isMachineCodeFrame: lifp) not l: ln.
+ 			 self assert: method = methodField l: ln.
+ 			 self cppIf: MULTIPLEBYTECODESETS
+ 				ifTrue: [self assert: (self methodUsesAlternateBytecodeSet: method) = (bytecodeSetSelector = 256) l: ln].
+ 			 ((self asserta: methodField asUnsignedInteger > objectMemory startOfMemory l: ln)
+ 			   and: [self asserta: methodField asUnsignedInteger < objectMemory freeStart l: ln]) ifTrue:
+ 				[lip ~= cogit ceReturnToInterpreterPC ifTrue:
+ 					[self assert: (lip >= (methodField + (objectMemory lastPointerOf: methodField) + BaseHeaderSize - 1)
+ 								  and: [lip < (methodField + (objectMemory byteLengthOf: methodField) + BaseHeaderSize)])
+ 						l: ln]].
+ 			 self assert: ((self iframeIsBlockActivation: lifp)
+ 					or: [(self pushedReceiverOrClosureOfFrame: lifp) = (self iframeReceiver: lifp)])
+ 				l: ln]
+ 		ifFalse:
+ 			[self assert: (self isMachineCodeFrame: lifp) l: ln.
+ 			 ((self asserta: methodField asUnsignedInteger >= cogit minCogMethodAddress l: ln)
+ 			  and: [self asserta: methodField asUnsignedInteger < cogit maxCogMethodAddress l: ln]) ifTrue:
+ 				[cogMethod := self mframeHomeMethod: lifp.
+ 				 self assert: (lip > (methodField + ((self mframeIsBlockActivation: lifp)
+ 													ifTrue: [self sizeof: CogBlockMethod]
+ 													ifFalse: [self sizeof: CogMethod]))
+ 						and: [lip < (methodField + cogMethod blockSize)])
+ 					l: ln].
+ 			 self assert: ((self mframeIsBlockActivation: lifp)
+ 					or: [(self pushedReceiverOrClosureOfFrame: lifp) = (self mframeReceiver: lifp)])
+ 				l: ln].
+ 	(self isBaseFrame: lifp) ifTrue:
+ 		[self assert: (self frameHasContext: lifp) l: ln.
+ 		 self assert: (self frameContext: lifp) = (stackPages longAt: stackPage baseAddress - BytesPerWord) l: ln]!

Item was changed:
  ----- Method: CoInterpreter>>ceReturnToInterpreter: (in category 'trampolines') -----
  ceReturnToInterpreter: anOop
  	"Perform a return from a machine code frame to an interpreted frame.
  	 The machine code has executed a return instruction when the return address
  	 is set to ceReturnToInterpreterPC.  Return the result and switch to the interpreter."
  	<api>
  	self assert: ((objectMemory isIntegerObject: anOop) or: [objectMemory addressCouldBeObj: anOop]).
  	self flag: 'are you really sure setStackPageAndLimit: is needed?'.
  	"I think you're only doing this for the markStackPageMostRecentlyUsed:
  	 and that's probably not needed either"
  	self setStackPageAndLimit: stackPage.
  	self assert: (self isMachineCodeFrame: framePointer) not.
  	self setMethod: (self iframeMethod: framePointer).
  	self assertValidExecutionPointe: (self iframeSavedIP: framePointer)
  		r: framePointer
  		s: stackPointer
+ 		imbar: true
+ 		line: #'__LINE__'.
- 		imbar: true.
  	instructionPointer := self iframeSavedIP: framePointer.
  	self push: anOop.
  	self siglong: reenterInterpreter jmp: ReturnToInterpreter.
  	"NOTREACHED"
  	^nil!

Item was changed:
  ----- Method: CoInterpreter>>ceStackOverflow: (in category 'trampolines') -----
  ceStackOverflow: contextSwitchIfNotNil
  	"If contextSwitchIfNotNil is nil we can't context switch.
  	 contextSwitchIfNotNil is set to nil by
  		- the special primitiveClosureValueNoContextSwitch entry-point in block dispatch
  		- the stack check in methods with primitive 198.
  	 In a normal method contextSwitchIfNotNil will be the method (see e.g.
  	 SimpleStackBasedCogit>>compileFrameBuild).  In a block it will be the
  	 closure (see e.g. SimpleStackBasedCogit>>compileMethodBody)."
  	<api>
  	| cogMethod switched cesoRetAddr |
  	<var: #cogMethod type: #'CogBlockMethod *'>
  	cesoRetAddr := self popStack. "discard the ceStackOverflow call return address."
  	cogMethod := self mframeCogMethod: framePointer.
  	self assert: cesoRetAddr - cogit abortOffset = (self asCogHomeMethod: cogMethod) asInteger.
  	instructionPointer := cogMethod asInteger + cogMethod stackCheckOffset.
+ 	self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: false line: #'__LINE__'.
- 	self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: false.
  	method := newMethod := messageSelector := lkupClass := objectMemory nilObject.
  	switched := self handleStackOverflowOrEventAllowContextSwitch: contextSwitchIfNotNil ~= 0.
  	self returnToExecutive: false postContextSwitch: switched.
  	self error: 'should not be reached'
  !

Item was added:
+ ----- Method: CoInterpreter>>deferStackLimitSmashAround:with: (in category 'process primitive support') -----
+ deferStackLimitSmashAround: functionSymbol with: arg
+ 	"Defer smashes of the stackLimit around the call of functionSymbol (for assert checks)"
+ 	<var: #functionSymbol declareC: 'void (*functionSymbol)(sqInt)'>
+ 	deferSmash := true.
+ 	self sqLowLevelMFence.
+ 	self perform: functionSymbol with: arg.
+ 	deferSmash := false.
+ 	self sqLowLevelMFence.
+ 	deferredSmash ifTrue:
+ 		[deferredSmash := false.
+ 		 self sqLowLevelMFence.
+ 		 self forceInterruptCheck]!

Item was changed:
  ----- Method: CoInterpreter>>enterSmalltalkExecutiveImplementation (in category 'initialization') -----
  enterSmalltalkExecutiveImplementation
  	"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
  		 "NOTREACHED"].
  	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 assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true.
  	self interpret.
  	^0!

Item was changed:
  ----- Method: CoInterpreter>>executeCogMethodFromLinkedSend:withReceiver: (in category 'enilopmarts') -----
  executeCogMethodFromLinkedSend: cogMethod withReceiver: rcvr
  	<api>
  	"Execute a CogMethod from a linked send.  The receiver,
  	 arguments and return address are on the Smalltalk stack.  First
  	 push the entry-point and finally the register argument(s).  Then write
  	 back the frame pointers and call the routine that will pop off the register
  	 argument(s) and jump to the entry by executing a return instruction.
  
  	 In the simple jit only the receiver gets passed in registers, so only the
  	 receiver gets pushed."
  	<var: #cogMethod type: #'CogMethod *'>
  	cogit assertCStackWellAligned.
  	self assert: (self isMachineCodeFrame: framePointer).
+ 	self assertValidExecutionPointe: self stackTop r: framePointer s: stackPointer imbar: false line: #'__LINE__'.
- 	self assertValidExecutionPointe: self stackTop r: framePointer s: stackPointer imbar: false.
  	self
  		cppIf: cogit numRegArgs > 0
  		ifTrue:
  			[cogMethod cmNumArgs <= cogit numRegArgs ifTrue:
  				[self enterRegisterArgCogMethod: cogMethod at: cogit entryOffset receiver: rcvr]].
  	self
  		push: cogMethod asInteger + cogit entryOffset;
  		push: rcvr.
  	cogit ceEnterCogCodePopReceiverReg
  	"NOTREACHED"!

Item was changed:
  ----- Method: CoInterpreter>>executeCogMethodFromLinkedSend:withReceiver:andCacheTag: (in category 'enilopmarts') -----
  executeCogMethodFromLinkedSend: cogMethod withReceiver: rcvr andCacheTag: cacheTag
  	<api>
  	"Execute a CogMethod from a linked send.  The receiver,
  	 arguments and return address are on the Smalltalk stack.  First
  	 push the entry-point and finally the register argument(s).  Then write
  	 back the frame pointers and call the routine that will pop off the register
  	 argument(s) and jump to the entry by executing a return instruction.
  
  	 In the simple jit only the receiver gets passed in registers, so only the
  	 receiver gets pushed."
  	<var: #cogMethod type: #'CogMethod *'>
  	cogit assertCStackWellAligned.
  	self assert: (self isMachineCodeFrame: framePointer).
+ 	self assertValidExecutionPointe: self stackTop r: framePointer s: stackPointer imbar: false line: #'__LINE__'.
- 	self assertValidExecutionPointe: self stackTop r: framePointer s: stackPointer imbar: false.
  	self push: cogMethod asInteger + cogit entryOffset.
  	self
  		cppIf: cogit numRegArgs > 0
  		ifTrue:
  			[cogMethod cmNumArgs <= cogit numRegArgs ifTrue:
  				[self assert: cogit numRegArgs <= 2.
  				 self push: cacheTag.
  				 cogMethod cmNumArgs = 0 ifTrue:
  					[cogit ceEnter0ArgsPIC].
  				 cogMethod cmNumArgs = 1 ifTrue:
  					[cogit ceEnter1ArgsPIC].
  				 cogMethod cmNumArgs = 2 ifTrue:
  					[cogit ceEnter2ArgsPIC].
  				 self error: 'not reached']].
  	self
  		push: rcvr;
  		push: cacheTag.
  	cogit ceEnterCogCodePopReceiverAndClassRegs
  	"NOTREACHED"!

Item was changed:
  ----- Method: CoInterpreter>>executeCogMethodFromUnlinkedSend:withReceiver: (in category 'enilopmarts') -----
  executeCogMethodFromUnlinkedSend: cogMethod withReceiver: rcvr
  	"Execute a CogMethod from an unlinked send.  The receiver,
  	 arguments and return address are on the Smalltalk stack.  First
  	 push the entry-point and finally the register argument(s).  Then write
  	 back the frame pointers and call the routine that will pop off the register
  	 argument(s) and jump to the entry by executing a return instruction.
  
  	 In the simple jit only the receiver gets passed in registers, so only the
  	 receiver gets pushed."
  	<var: #cogMethod type: #'CogMethod *'>
  	cogit assertCStackWellAligned.
  	self assert: (self isMachineCodeFrame: framePointer).
+ 	self assertValidExecutionPointe: self stackTop r: framePointer s: stackPointer imbar: false line: #'__LINE__'.
- 	self assertValidExecutionPointe: self stackTop r: framePointer s: stackPointer imbar: false.
  	self
  		cppIf: cogit numRegArgs > 0
  		ifTrue:
  			[cogMethod cmNumArgs <= cogit numRegArgs ifTrue:
  				[self enterRegisterArgCogMethod: cogMethod at: cogit noCheckEntryOffset receiver: rcvr]].
  	self
  		push: cogMethod asInteger + cogit noCheckEntryOffset;
  		push: rcvr.
  	cogit ceEnterCogCodePopReceiverReg
  	"NOTREACHED"!

Item was changed:
  ----- Method: CoInterpreter>>forceInterruptCheckFromHeartbeat (in category 'process primitive support') -----
  forceInterruptCheckFromHeartbeat
  	"Force an interrupt check ASAP. This version is the
  	 entry-point to forceInterruptCheck for the heartbeat
  	 timer to allow for repeatable debugging."
  	suppressHeartbeatFlag ifFalse:
  		[self checkForLongRunningPrimitive.
+ 		 self sqLowLevelMFence.
  		 deferSmash
+ 			ifTrue:
+ 				[deferredSmash := true.
+ 				 self sqLowLevelMFence]
+ 			ifFalse:
+ 				[self forceInterruptCheck]]!
- 			ifTrue: [deferredSmash := true]
- 			ifFalse: [self forceInterruptCheck]]!

Item was changed:
  ----- Method: CoInterpreter>>long:jmp: (in category 'cog jit support') -----
  long: aJumpBuf jmp: returnValue
  	"Hack simulation of setjmp/longjmp.
  	 Signal the exception that simulates a longjmp back to the interpreter." 
  	<doNotGenerate>
  	aJumpBuf == reenterInterpreter ifTrue:
+ 		[self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true line: nil].
- 		[self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true].
  	aJumpBuf returnValue: returnValue; signal!

Item was changed:
  ----- Method: CoInterpreter>>printFrame:WithSP: (in category 'debug printing') -----
  printFrame: theFP WithSP: theSP
+ 	<api>
  	| theMethod theMethodEnd numArgs numTemps rcvrAddress topThing |
  	<inline: false>
  	<var: #theFP type: #'char *'>
  	<var: #theSP type: #'char *'>
  	<var: #addr type: #'char *'>
  	<var: #rcvrAddress type: #'char *'>
  	<var: #cogMethod type: #'CogBlockMethod *'>
  	<var: #homeMethod type: #'CogMethod *'>
  	self cCode: '' inSmalltalk: [self transcript ensureCr].
  	(self isMachineCodeFrame: theFP)
  		ifTrue:
  			[| cogMethod homeMethod |
  			 cogMethod := self mframeCogMethod: theFP.
  			 homeMethod := self mframeHomeMethod: theFP.
  			 theMethod := homeMethod asInteger.
  			 theMethodEnd := homeMethod asInteger + homeMethod blockSize.
  			 numArgs := cogMethod cmNumArgs.
  			 numTemps := self temporaryCountOfMethodHeader: homeMethod methodHeader]
  		ifFalse:
  			[theMethod := self frameMethodObject: theFP.
  			 theMethodEnd := theMethod + (objectMemory sizeBitsOfSafe: theMethod).
  			 numArgs := self iframeNumArgs: theFP.
  			 numTemps := self tempCountOf: theMethod].
  	(self frameIsBlockActivation: theFP) ifTrue:
  		[| rcvrOrClosure |
  		 rcvrOrClosure := self pushedReceiverOrClosureOfFrame: theFP.
  		 ((objectMemory isNonIntegerObject: rcvrOrClosure)
  		 and: [(objectMemory addressCouldBeObj: rcvrOrClosure)
  		 and: [(objectMemory fetchClassOfNonInt: rcvrOrClosure) = (objectMemory splObj: ClassBlockClosure)]])
  			ifTrue: [numTemps := numArgs + (self stSizeOf: rcvrOrClosure)]
  			ifFalse: [numTemps := 0]].
  	self shortPrintFrame: theFP.
  	(self isBaseFrame: theFP) ifTrue:
  		[self printFrameOop: '(caller ctxt'
  			at: theFP + (self frameStackedReceiverOffset: theFP) + (2 * BytesPerWord).
  		 self printFrameOop: '(saved ctxt'
  			at: theFP + (self frameStackedReceiverOffset: theFP) + (1 * BytesPerWord)].
  	self printFrameOop: 'rcvr/clsr'
  		at: theFP + FoxCallerSavedIP + ((numArgs + 1) * BytesPerWord).
  	numArgs to: 1 by: -1 do:
  		[:i|
  		self printFrameOop: 'arg' index: numArgs - i at: theFP + FoxCallerSavedIP + (i * BytesPerWord)].
  	self printFrameThing: 'caller ip' at: theFP + FoxCallerSavedIP.
  	self printFrameThing: 'saved fp' at: theFP + FoxSavedFP.
  	self printFrameMethodFor: theFP.
  	(self isMachineCodeFrame: theFP) ifFalse:
  		[self printFrameFlagsForFP: theFP].
  	self printFrameOop: 'context' at: theFP + FoxThisContext.
  	(self isMachineCodeFrame: theFP) ifTrue:
  		[self printFrameFlagsForFP: theFP].
  	(self isMachineCodeFrame: theFP)
  		ifTrue: [rcvrAddress := theFP + FoxMFReceiver]
  		ifFalse:
  			[self printFrameThing: 'saved ip'
  				at: theFP + FoxIFSavedIP
  				extra: ((self iframeSavedIP: theFP) = 0
  							ifTrue: [0]
  							ifFalse: [(self iframeSavedIP: theFP) - theMethod + 2 - BaseHeaderSize]).
  			 rcvrAddress := theFP + FoxIFReceiver].
  	self printFrameOop: 'receiver' at: rcvrAddress.
  	topThing := stackPages longAt: theSP.
  	(topThing between: theMethod and: theMethodEnd)
  		ifTrue:
  			[rcvrAddress - BytesPerWord to: theSP + BytesPerWord by: BytesPerWord negated do:
  				[:addr| | index |
  				index := rcvrAddress - addr / BytesPerWord + numArgs.
  				index <= numTemps
  					ifTrue: [self printFrameOop: 'temp' index: index - 1 at: addr]
  					ifFalse: [self printFrameOop: 'stck' at: addr]].
  			self printFrameThing: 'frame ip'
  				at: theSP
  				extra: ((self isMachineCodeFrame: theFP)
  						ifTrue: [topThing - theMethod]
  						ifFalse: [topThing - theMethod + 2 - BaseHeaderSize])]
  		ifFalse:
  			[rcvrAddress - BytesPerWord to: theSP by: BytesPerWord negated do:
  				[:addr| | index |
  				index := rcvrAddress - addr / BytesPerWord + numArgs.
  				index <= numTemps
  					ifTrue: [self printFrameOop: 'temp' index: index - 1 at: addr]
  					ifFalse: [self printFrameOop: 'stck' at: addr]]]!

Item was changed:
  ----- Method: CoInterpreter>>return:toExecutive: (in category 'enilopmarts') -----
  return: returnValue toExecutive: inInterpreter
  	"We have made a context switch, either when interpreting or from machine code.
  	 Effectively return to the current frame, either by entering machine code, or
  	 longjmp-ing back to the interpreter or simply returning, depending on where we are."
  
  	cogit assertCStackWellAligned.
  	(self isMachineCodeFrame: framePointer) ifTrue:
+ 		[self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: false line: #'__LINE__'.
- 		[self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: false.
  		 self push: instructionPointer.
  		 self push: returnValue.
  		 cogit ceEnterCogCodePopReceiverReg
  		 "NOTREACHED"].
  	self push: returnValue.
  	self setMethod: (self iframeMethod: framePointer).
+ 	self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true line: #'__LINE__'.
- 	self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true.
  	instructionPointer = cogit ceReturnToInterpreterPC ifTrue:
  		[instructionPointer := self iframeSavedIP: framePointer].
  	inInterpreter ifTrue:
  		[^nil].
  	self siglong: reenterInterpreter jmp: ReturnToInterpreter.
  	"NOTREACHED"
  	^nil!

Item was changed:
  ----- Method: CoInterpreter>>returnToExecutive:postContextSwitch: (in category 'enilopmarts') -----
  returnToExecutive: inInterpreter postContextSwitch: switchedContext
  	"Return to the current frame, either by entering machine code, or longjmp-ing back to the
  	 interpreter or simply returning, depending on where we are. To know whether to return or
  	 enter machine code we have to know from whence we came.  We could have come from
  	 the interpreter, either directly or via a machine code primitive.  We could have come from
  	 machine code.  The instructionPointer tells us where from.  If it is above startOfMemory we're
  	 in the interpreter.  If it is below, then we are in machine-code unless it is ceReturnToInterpreterPC,
  	 in which case we're in a machine-code primitive called from the interpreter."
  	<inline: false>
  	| cogMethod retValue fullyInInterpreter |
  	<var: #cogMethod type: #'CogBlockMethod *'>
  
  	cogit assertCStackWellAligned.
  	(self isMachineCodeFrame: framePointer) ifTrue:
+ 		[self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: false line: #'__LINE__'.
- 		[self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: false.
  		 "If returning after a context switch then a result may have to be popped from the stack.
  		  If the process is suspended at a send then the result of the primitive in which the
  		  process was suspended is still on the stack and must be popped into ReceiverResultReg.
  		  If not, nothing should be popped and ReceiverResultReg gets the receiver."
  		 switchedContext
  			ifTrue:
  				[cogMethod := self mframeCogMethod: framePointer.
  				 (instructionPointer ~= (cogMethod asInteger + cogMethod stackCheckOffset)
  				  and: [cogit isSendReturnPC: instructionPointer])
  					ifTrue:
  						[self assert: ((objectMemory isIntegerObject: self stackTop) or: [objectMemory addressCouldBeObj: self stackTop]).
  						 retValue := self popStack]
  					ifFalse:
  						[retValue := self mframeReceiver: framePointer]]
  			ifFalse: [retValue := self mframeReceiver: framePointer].
  		 self push: instructionPointer.
  		 self push: retValue.
  		 cogit ceEnterCogCodePopReceiverReg
  		 "NOTREACHED"].
  	self setMethod: (self iframeMethod: framePointer).
  	fullyInInterpreter := inInterpreter.
  	instructionPointer = cogit ceReturnToInterpreterPC ifTrue:
  		[instructionPointer := (self iframeSavedIP: framePointer) asUnsignedInteger.
  		 fullyInInterpreter := false].
+ 	self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true line: #'__LINE__'.
- 	self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true.
  	fullyInInterpreter ifFalse:
  		[self siglong: reenterInterpreter jmp: ReturnToInterpreter.
  		 "NOTREACHED"].
  	^nil!

Item was changed:
  ----- Method: CoInterpreter>>returnToMachineCodeFrame (in category 'return bytecodes') -----
  returnToMachineCodeFrame
  	"Return to the previous context/frame after assigning localIP, localSP and localFP."
  	<inline: true>
  	cogit assertCStackWellAligned.
  	self assert: localIP asUnsignedInteger < objectMemory startOfMemory.
  	self assert: (self isMachineCodeFrame: localFP).
+ 	self assertValidExecutionPointe: localIP asUnsignedInteger r: localFP s: localSP imbar: false line: #'__LINE__'.
- 	self assertValidExecutionPointe: localIP asUnsignedInteger r: localFP s: localSP imbar: false.
  	self internalStackTopPut: localIP.
  	self internalPush: localReturnValue.
  	self externalizeFPandSP.
  	self cCode: '' inSmalltalk:
  		[self maybeCheckStackDepth: 1 sp: stackPointer pc: localIP].
  	cogit ceEnterCogCodePopReceiverReg
  	"NOTREACHED"!

Item was changed:
  ----- Method: CoInterpreter>>siglong:jmp: (in category 'cog jit support') -----
  siglong: aJumpBuf jmp: returnValue
  	"Hack simulation of sigsetjmp/siglongjmp.
  	 Signal the exception that simulates a longjmp back to the interpreter." 
  	<doNotGenerate>
  	(aJumpBuf == reenterInterpreter
  	 and: [returnValue ~= 2 "2 == returnToThreadSchedulingLoopVia:"]) ifTrue:
  		[self assert: (self isOnRumpCStack: cogit processor sp).
+ 		 self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true line: nil].
- 		 self assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true].
  	aJumpBuf returnValue: returnValue; signal!

Item was added:
+ ----- Method: CoInterpreterMT>>deferStackLimitSmashAround:with: (in category 'process primitive support') -----
+ deferStackLimitSmashAround: functionSymbol with: arg
+ 	"Defer smashes of the stackLimit around the call of functionSymbol (for assert checks).	
+ 
+ 	 N.B. SYNCHRONIZE WITH forceInterruptCheckFromHeartbeat"
+ 
+ 	<var: #functionSymbol declareC: 'void (*functionSymbol)(sqInt)'>
+ 	deferSmash := true.
+ 	self sqLowLevelMFence.
+ 	self perform: functionSymbol with: arg.
+ 	deferSmash := false.
+ 	self sqLowLevelMFence.
+ 	deferredSmash ifTrue:
+ 		[deferredSmash := false.
+ 		 self sqLowLevelMFence.
+ 		 self forceInterruptCheck.
+ 		 self checkVMOwnershipFromHeartbeat]!

Item was changed:
  ----- Method: CoInterpreterMT>>enterSmalltalkExecutiveImplementation (in category 'initialization') -----
  enterSmalltalkExecutiveImplementation
  	"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.
  
  	 Override to return if a longjmp to reenterInterpreter passes a parameter greater than 1.
  	 This causes a return to threadSchedulingLoop:startingVM: and is used to surrender
  	 control to another thread."
  	<inline: false>
  	self assertSaneThreadAndProcess.
  	cogit assertCStackWellAligned.
  	cogit ceCaptureCStackPointers.
  	"Setjmp for reentry into interpreter from elsewhere, e.g. machine-code trampolines."
  	(self sigset: reenterInterpreter jmp: 0) > 1 ifTrue:
  		[^0].
  	(self isMachineCodeFrame: framePointer) ifTrue:
  		[self returnToExecutive: false postContextSwitch: true
  		 "NOTREACHED"].
  	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 assertValidExecutionPointe: instructionPointer r: framePointer s: stackPointer imbar: true.
  	self interpret.
  	"NOTREACHED"
  	^0!

Item was changed:
  ----- Method: CoInterpreterMT>>forceInterruptCheckFromHeartbeat (in category 'process primitive support') -----
  forceInterruptCheckFromHeartbeat
  	"Force an interrupt check ASAP. This version is the
  	 entry-point to forceInterruptCheck for the heartbeat
  	 timer to allow for repeatable debugging.
  
  	 N.B. SYNCHRONIZE WITH deferStackLimitSmashAround:"
  	suppressHeartbeatFlag ifFalse:
  		[self checkForLongRunningPrimitive.
+ 		 self sqLowLevelMFence.
  		 deferSmash
+ 			ifTrue:
+ 				[deferredSmash := true.
+ 				self sqLowLevelMFence]
- 			ifTrue: [deferredSmash := true]
  			ifFalse:
  				[self forceInterruptCheck.
  				 self checkVMOwnershipFromHeartbeat]]!

Item was changed:
  ----- Method: CoInterpreterPrimitives>>pathTo:using:followWeak: (in category 'object access primitives') -----
  pathTo: goal using: stack followWeak: followWeak
  	"Trace objects and frames from the root, marking visited objects, pushing the current path on stack, until goal is found.
  	 If found, unmark, leaving path in stack, and answer 0.  Otherwise answer an error:
  		PrimErrBadArgument if stack is not an Array
  		PrimErrBadIndex if search overflows stack
  		PrimErrNotFound if goal cannot be found"
  	| current hdr index next stackSize stackp freeStartAtStart |
  	(objectMemory isArray: stack) ifFalse:
  		[^PrimErrBadArgument].
  	freeStartAtStart := objectMemory freeStart. "check no allocations during search"
  	objectMemory beRootIfOld: stack. "so no store checks are necessary on stack"
  	stackSize := objectMemory lengthOf: stack.
  	objectMemory mark: stack.
  	"no need. the current context is not reachable from the active process (suspendedContext is nil)"
  	"objectMemory mark: self activeProcess."
  	current := objectMemory specialObjectsOop.
  	objectMemory mark: current.
  	index := objectMemory lengthOf: current.
  	stackp := 0.
  	[[(index := index - 1) >= -1] whileTrue:
  		[next := (stackPages couldBeFramePointer: current)
  					ifTrue:
  						[index >= 0
+ 							ifTrue: [self field: index ofFrame: (self cCoerceSimple: current to: #'char *')]
- 							ifTrue: [self field: index ofFrame: current]
  							ifFalse: [objectMemory nilObject]]
  					ifFalse:
  						[index >= 0
  							ifTrue:
  								[hdr := objectMemory baseHeader: current.
  								 (objectMemory isContextHeader: hdr)
  									ifTrue: [self fieldOrSenderFP: index ofContext: current]
  									ifFalse: [objectMemory fetchPointer: index ofObject: current]]
  							ifFalse:
  								[objectMemory fetchClassOfNonInt: current]].
  		 (stackPages couldBeFramePointer: next)
+ 			ifTrue: [self assert: (self isFrame: (self cCoerceSimple: next to: #'char *')
+ 										onPage: (stackPages stackPageFor: (self cCoerceSimple: next to: #'char *')))]
- 			ifTrue: [self assert: (self isFrame: next onPage: (stackPages stackPageFor: next))]
  			ifFalse:
  				[next >= heapBase ifTrue:
  					[self assert: (self checkOkayOop: next)]].
  		 next = goal ifTrue:
  			[self assert: freeStartAtStart = objectMemory freeStart.
  			 self unmarkAfterPathTo.
  			 objectMemory storePointer: stackp ofObject: stack withValue: current.
  			 self pruneStack: stack stackp: stackp.
  			 ^0].
  		 ((objectMemory isNonIntegerObject: next)
  		  and: [(stackPages couldBeFramePointer: next)
  				ifTrue: [(self frameIsMarked: next) not]
  				ifFalse:
  					[next >= heapBase "exclude Cog methods"
  					  and: [(objectMemory isMarked: next) not
  					  and: [((objectMemory isPointers: next) or: [objectMemory isCompiledMethod: next])
  					  and: [followWeak or: [(objectMemory isWeakNonInt: next) not]]]]]])
  			ifTrue:
  				[stackp + 2 > stackSize ifTrue:
  					[self assert: freeStartAtStart = objectMemory freeStart.
  					 self unmarkAfterPathTo.
  					 objectMemory nilFieldsOf: stack.
  					 ^PrimErrBadIndex]. "PrimErrNoMemory ?"
  				 objectMemory
  					storePointerUnchecked: stackp ofObject: stack withValue: current;
  					storePointerUnchecked: stackp + 1 ofObject: stack withValue: (objectMemory integerObjectOf: index).
  				 stackp := stackp + 2.
  				 (stackPages couldBeFramePointer: (self cCoerceSimple: next to: #'char *'))
  					ifTrue:
  						[self markFrame: next.
  						index := self fieldsInFrame: (self cCoerceSimple: next to: #'char *')]
  					ifFalse:
  						[hdr := objectMemory baseHeader: next.
  						 objectMemory baseHeader: next put: (hdr bitOr: MarkBit).
  						 (objectMemory isCompiledMethodHeader: hdr)
  							ifTrue: [index := self literalCountOf: next]
  							ifFalse: [index := objectMemory lengthOf: next]].
  				 current := next]].
  		 current = objectMemory specialObjectsOop ifTrue:
  			[self assert: freeStartAtStart = objectMemory freeStart.
  			 self unmarkAfterPathTo.
  			 objectMemory nilFieldsOf: stack.
  			^PrimErrNotFound].
  		 index := objectMemory integerValueOf: (objectMemory fetchPointer: stackp - 1 ofObject: stack).
  		 current := objectMemory fetchPointer: stackp - 2 ofObject: stack.
  		 stackp := stackp - 2] repeat!

Item was removed:
- ----- Method: CogVMSimulator>>assertValidExecutionPointers (in category 'testing') -----
- assertValidExecutionPointers
- 	self assertValidExecutionPointe: localIP r: localFP s: localSP!

Item was changed:
  ----- Method: StackInterpreter class>>preambleCCode (in category 'translation') -----
  preambleCCode
  	^	
+ '/* Disable Intel compiler inlining of warning which is used for breakpoints */
- 'void printCallStack(void);
- 
- /* Disable Intel compiler inlining of warning which is used for breakpoints */
  #pragma auto_inline off
  void
  warning(char *s) { /* Print an error message but don''t exit. */
  	printf("\n%s\n", s);
  }
+ void
+ warningat(char *s, int l) { /* ditto with line number. */
+ 	printf("\n%s %d\n", s,l);
+ }
  #pragma auto_inline on
  
  void
  invalidCompactClassError(char *s) { /* Print a compact class index error message and exit. */
- 	static sqInt printingStack = true; /* not running at this point */
- 
  	printf("\nClass %s does not have the required compact class index\n", s);
  	exit(-1);
  }
  
  /*
   * Define sigsetjmp and siglongjmp to be the most minimal setjmp/longjmp available on the platform.
   */
  #if WIN32
  # define sigsetjmp(jb,ssmf) setjmp(jb)
  # define siglongjmp(jb,v) longjmp(jb,v)
  #else
  # define sigsetjmp(jb,ssmf) _setjmp(jb)
  # define siglongjmp(jb,v) _longjmp(jb,v)
  #endif
  '!

Item was changed:
  ----- Method: StackInterpreter>>assertValidExecutionPointe:r:s: (in category 'debug support') -----
  assertValidExecutionPointe: lip r: lifp s: lisp
+ 	<inline: true>
  	<var: #lip type: #'usqInt'>
  	<var: #lifp type: #'char *'>
  	<var: #lisp type: #'char *'>
+ 	self assertValidExecutionPointe: lip r: lifp s: lisp imbar: (self isMachineCodeFrame: lifp) not line: #'__LINE__'!
- 	self assertValidExecutionPointe: lip r: lifp s: lisp imbar: (self isMachineCodeFrame: lifp) not!

Item was removed:
- ----- Method: StackInterpreter>>assertValidExecutionPointe:r:s:imbar: (in category 'debug support') -----
- assertValidExecutionPointe: lip r: lfp s: lsp imbar: inInterpreter
- 	<var: #lip type: #usqInt>
- 	<var: #lfp type: #'char *'>
- 	<var: #lsp type: #'char *'>
- 	self assert: inInterpreter.
- 	self assert: stackPage = (stackPages stackPageFor: lfp).
- 	self assert: stackPage = stackPages mostRecentlyUsedPage.
- 	self assertValidStackLimits.
- 	self assert: lfp < stackPage baseAddress.
- 	self assert: lsp < lfp.
- 	self assert: lfp > lsp.
- 	self assert: lsp >= (stackPage realStackLimit - self stackLimitOffset).
- 	self assert:  (lfp - lsp) < LargeContextSize.
- 	self assert: (self validInstructionPointer: lip inFrame: lfp).
- 	self assert: ((self frameIsBlockActivation: lfp)
- 				or: [(self pushedReceiverOrClosureOfFrame: lfp) = (self frameReceiver: lfp)]).
- 	self assert: method = (self frameMethod: lfp).
- 	self cppIf: MULTIPLEBYTECODESETS
- 		ifTrue: [self assert: (self methodUsesAlternateBytecodeSet: method) = (bytecodeSetSelector = 256)].!

Item was added:
+ ----- Method: StackInterpreter>>assertValidExecutionPointe:r:s:imbar:line: (in category 'debug support') -----
+ assertValidExecutionPointe: lip r: lfp s: lsp imbar: inInterpreter line: ln
+ 	<var: #lip type: #usqInt>
+ 	<var: #lfp type: #'char *'>
+ 	<var: #lsp type: #'char *'>
+ 	self assert: inInterpreter l: ln.
+ 	self assert: stackPage = (stackPages stackPageFor: lfp) l: ln.
+ 	self assert: stackPage = stackPages mostRecentlyUsedPage l: ln.
+ 	self assertValidStackLimits: ln.
+ 	self assert: lfp < stackPage baseAddress l: ln.
+ 	self assert: lsp < lfp l: ln.
+ 	self assert: lfp > lsp l: ln.
+ 	self assert: lsp >= (stackPage realStackLimit - self stackLimitOffset) l: ln.
+ 	self assert:  (lfp - lsp) < LargeContextSize l: ln.
+ 	self assert: (self validInstructionPointer: lip inFrame: lfp) l: ln.
+ 	self assert: ((self frameIsBlockActivation: lfp)
+ 				or: [(self pushedReceiverOrClosureOfFrame: lfp) = (self frameReceiver: lfp)])
+ 		l: ln.
+ 	self assert: method = (self frameMethod: lfp) l: ln.
+ 	self cppIf: MULTIPLEBYTECODESETS
+ 		ifTrue: [self assert: (self methodUsesAlternateBytecodeSet: method) = (bytecodeSetSelector = 256)  l: ln].!

Item was added:
+ ----- Method: StackInterpreter>>assertValidExecutionPointers (in category 'debug support') -----
+ assertValidExecutionPointers
+ 	<doNotGenerate> "simulator only"
+ 	self assertValidExecutionPointe: localIP r: localFP s: localSP!

Item was removed:
- ----- Method: StackInterpreter>>assertValidStackLimits (in category 'process primitive support') -----
- assertValidStackLimits
- 	<returnTypeC: #void>
- 	"Order in the stackLimit checks is important because stackLimit is smashed by
- 	 interrupts. So always check for unsmashed value first to avoid race condition."
- 	self assert: (stackLimit = stackPage realStackLimit
- 				or: [stackLimit = (self cCoerceSimple: -1 signedIntToLong to: 'char *')]).
- 	self assert: (stackPage stackLimit = stackPage realStackLimit
- 				or: [stackPage stackLimit = (self cCoerceSimple: -1 signedIntToLong to: 'char *')])!

Item was added:
+ ----- Method: StackInterpreter>>assertValidStackLimits: (in category 'process primitive support') -----
+ assertValidStackLimits: ln
+ 	<returnTypeC: #void>
+ 	"Order in the stackLimit checks is important because stackLimit is smashed by
+ 	 interrupts. So always check for unsmashed value first to avoid race condition."
+ 	self assert: (stackLimit = stackPage realStackLimit
+ 				or: [stackLimit = (self cCoerceSimple: -1 signedIntToLong to: #'char *')])
+ 		l: ln.
+ 	self assert: (stackPage stackLimit = stackPage realStackLimit
+ 				or: [stackPage stackLimit = (self cCoerceSimple: -1 signedIntToLong to: #'char *')])
+ 		l: ln!

Item was changed:
  ----- Method: StackInterpreter>>instVar:ofContext:put: (in category 'frame access') -----
  instVar: index ofContext: aMarriedContext put: anOop
  	| theFP |
  	"Assign the field of a married context.  The important case to optimize is
  	 assigning the sender.  We could also consider optimizing assiging the IP but
  	 typically that is followed by an assignment to the stack pointer and we can't
  	 efficiently assign the stack pointer because it involves moving frames around."
  	<inline: true>
  	self assert: (self isMarriedOrWidowedContext: aMarriedContext).
  	self writeBackHeadFramePointers.
  	(self isStillMarriedContext: aMarriedContext) ifFalse:
  		[objectMemory storePointer: index ofObject: aMarriedContext withValue: anOop.
  		 index = StackPointerIndex ifTrue:
  			[self ensureContextIsExecutionSafeAfterAssignToStackPointer: aMarriedContext].
  		 ^nil].
  	theFP := self frameOfMarriedContext: aMarriedContext.
  	index == SenderIndex ifTrue:
  		[| thePage onCurrentPage |
  		 thePage := stackPages stackPageFor: theFP.
  		 self assert: stackPage = stackPages mostRecentlyUsedPage.
  		 onCurrentPage := thePage = stackPage.
  		 self storeSenderOfFrame: theFP withValue: anOop.
  		 onCurrentPage
  			ifTrue:
  				[localFP := stackPage headFP.
  				 localSP := stackPage headSP]
  			ifFalse:
  				[stackPages markStackPageMostRecentlyUsed: stackPage].
  		 ^nil].
  	self externalizeIPandSP.
  	self externalDivorceFrame: theFP andContext: aMarriedContext.
  	objectMemory storePointer: index ofObject: aMarriedContext withValue: anOop.
  	index = StackPointerIndex ifTrue:
  		[self ensureContextIsExecutionSafeAfterAssignToStackPointer: aMarriedContext].
  	self internalizeIPandSP.
  	"Assigning various fields can force a divorce which can change the stackPage."
  	stackPages markStackPageMostRecentlyUsed: stackPage.
+ 	self assertValidExecutionPointe: localIP asUnsignedInteger r: localFP s: localSP imbar: true line: #'__LINE__'!
- 	self assertValidExecutionPointe: localIP asUnsignedInteger r: localFP s: localSP imbar: true!

Item was changed:
  ----- Method: StackInterpreter>>printFrame:WithSP: (in category 'debug printing') -----
  printFrame: theFP WithSP: theSP
+ 	<api>
  	| theMethod numArgs topThing |
  	<inline: false>
  	<var: #theFP type: #'char *'>
  	<var: #theSP type: #'char *'>
  	<var: #addr type: #'char *'>
  	self cCode: '' inSmalltalk: [self transcript ensureCr].
  	theMethod := self frameMethod: theFP.
  	numArgs := self frameNumArgs: theFP.
  	self shortPrintFrame: theFP.
  	self printFrameOop: 'rcvr/clsr'
  		at: theFP + FoxCallerSavedIP + ((numArgs + 1) * BytesPerWord).
  	numArgs to: 1 by: -1 do:
  		[:i| self printFrameOop: 'arg' at: theFP + FoxCallerSavedIP + (i * BytesPerWord)].
  	self printFrameThing: 'cllr ip/ctxt' at: theFP + FoxCallerSavedIP.
  	self printFrameThing: 'saved fp' at: theFP + FoxSavedFP.
  	self printFrameOop: 'method' at: theFP + FoxMethod.
  	self printFrameFlagsForFP: theFP.
  	self printFrameThing: 'context' at: theFP + FoxThisContext.
  	self printFrameOop: 'receiver' at: theFP + FoxReceiver.
  	topThing := stackPages longAt: theSP.
  	(topThing >= theMethod
  	 and: [topThing <= (theMethod + (objectMemory sizeBitsOfSafe: theMethod))])
  		ifTrue:
  			[theFP + FoxReceiver - BytesPerWord to: theSP + BytesPerWord by: BytesPerWord negated do:
  				[:addr|
  				self printFrameOop: 'temp/stck' at: addr].
  			self printFrameThing: 'frame ip' at: theSP]
  		ifFalse:
  			[theFP + FoxReceiver - BytesPerWord to: theSP by: BytesPerWord negated do:
  				[:addr|
  				self printFrameOop: 'temp/stck' at: addr]]!

Item was changed:
  ----- Method: StackInterpreterPrimitives>>field:ofFrame: (in category 'object access primitives') -----
  field: index ofFrame: theFP
  	"Arrange to answer naked frame pointers for unmarried
  	 senders to avoid reifying contexts in the search."
  	<var: #theFP type: #'char *'>
  	<inline: false>
  	| callerFP |
  	<var: #callerFP type: #'char *'>
  	^index caseOf:
  		{[SenderIndex] ->	[callerFP := self frameCallerFP: theFP.
  							 callerFP = 0
  								ifTrue: [self frameCallerContext: theFP]
  								ifFalse: [(self frameHasContext: callerFP)
  											ifTrue: [self assert: (self checkIsStillMarriedContext: (self frameContext: callerFP) currentFP: nil).
  													self frameContext: callerFP]
+ 											ifFalse: [callerFP asInteger]]].
- 											ifFalse: [callerFP]]].
  		[StackPointerIndex]			->	[ConstZero].
  		[InstructionPointerIndex]	->	[ConstZero].
  		[MethodIndex]				->	[self frameMethodObject: theFP].
  		[ClosureIndex]				->	[(self frameIsBlockActivation: theFP)
  											ifTrue: [self frameStackedReceiver: theFP
  														numArgs: (self frameNumArgs: theFP)]
  											ifFalse: [objectMemory nilObject]].
  		[ReceiverIndex]				->	[self frameReceiver: theFP] }
  		otherwise:
  			[self assert: (index - CtxtTempFrameStart between: 0 and: (self stackPointerIndexForFrame: theFP)).
  			 self temporary: index - CtxtTempFrameStart in: theFP]!

Item was removed:
- ----- Method: StackInterpreterSimulator>>assertValidExecutionPointers (in category 'testing') -----
- assertValidExecutionPointers
- 	self assertValidExecutionPointe: localIP r: localFP s: localSP!

Item was added:
+ ----- Method: VMClass>>assert:l: (in category 'debug support') -----
+ assert: aBooleanExpression l: linenum
+ 	<doNotGenerate>
+ 	^self assert: aBooleanExpression!

Item was added:
+ ----- Method: VMClass>>asserta:l: (in category 'debug support') -----
+ asserta: aBooleanExpression l: linenum
+ 	<doNotGenerate>
+ 	^self asserta: aBooleanExpression!

Item was changed:
  ----- Method: VMPluginCodeGenerator>>emitCHeaderOn: (in category 'C code generator') -----
  emitCHeaderOn: aStream
  	"Write a C file header onto the given stream."
  
  	aStream nextPutAll: (self fileHeaderVersionStampForSourceClass: pluginClass).
  	aStream cr; cr.
  
  	#('<math.h>' '<stdio.h>' '<stdlib.h>' '<string.h>' '<time.h>') reverseDo:
  		[:hdr| self addHeaderFileFirst: hdr].
  
  	"Additional header files; include C library ones first."
  	self emitHeaderFiles: (headerFiles select: [:hdr| hdr includes: $<]) on: aStream.
  
  	aStream cr; nextPutAll:'/* Default EXPORT macro that does nothing (see comment in sq.h): */
  #define EXPORT(returnType) returnType
  
  /* Do not include the entire sq.h file but just those parts needed. */
  /*  The virtual machine proxy definition */
  #include "sqVirtualMachine.h"
  /* Configuration options */
  #include "sqConfig.h"
  /* Platform specific definitions */
  #include "sqPlatformSpecific.h"
  
  #define true 1
  #define false 0
  #define null 0  /* using ''null'' because nil is predefined in Think C */
  #ifdef SQUEAK_BUILTIN_PLUGIN
  #undef EXPORT
  // was #undef EXPORT(returnType) but screws NorCroft cc
  #define EXPORT(returnType) static returnType
  #endif'; cr; cr.
  	self addHeaderFile: '"sqMemoryAccess.h"'.
  	"Additional header files; include squeak VM ones last"
  	self emitHeaderFiles: (headerFiles reject: [:hdr| hdr includes: $<]) on: aStream.
+ 	self maybePutPreambleFor: pluginClass on: aStream.
- 	pluginClass preambleCCode ifNotNil:
- 		[:preamble|
- 		aStream cr; nextPutAll: preamble].
  	aStream cr.!



More information about the Vm-dev mailing list