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

commits at source.squeak.org commits at source.squeak.org
Sat Dec 7 21:42:10 UTC 2013


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

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

Name: VMMaker.oscog-eem.547
Author: eem
Time: 7 December 2013, 1:39:54.394 pm
UUID: 5a0db750-d6a5-4742-b20a-e35ecb43ab38
Ancestors: VMMaker.oscog-eem.546

Rename handleForwardedSendFaultFor: to handleForwardedSendFaultForTag:.
Add handleForwardedSelectorFaultFor:.  Implement forwarding
fault handling in ceSend:super:to:numArgs: et al and rewrite
the handling in ceSendFromInLineCacheMiss: to match.

Abstract out the method following in handleForwardedSelectorFaultFor:
and override in CoInterpreter to follow the cogMethod.
Follow forwarded methdos in the method cache post-become.

Rename genEnsureRegNotForwarded:scratchReg: to
genEnsureObjInRegRegNotForwarded:scratchReg: and use to
implement forwarder following in Cogit special selector #==
(and rewritten lit var access).   Comment forwarder following in
genGetClassObjectOf:into:scratchReg:instRegIsReceiver:

Fix Spur's couldBeObject: to filter-out 0 (for closed PICs).

Fix printOopShortInner: to print forwarders (for frame printing).

Print how much space is missing when the
scavenger eden limit - freeStart > coInterpreter interpreterAllocationReserveBytes
assert fails on scavenge.

Slang and clients:
Fix dead code elimination in if exprs when there expr is just a single
boolean-constant-returning send.

Refactor var:type:array: in terms of arrayInitializerCalled:for:type:.

Fix decls of memory, heapBase & labelCounter so they're not hacked
as static.  Make cePositive32BitIntegerTrampoline & eFlushICache
private.

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

Item was changed:
  ----- Method: CCodeGenerator>>emitCVariablesOn: (in category 'C code generator') -----
  emitCVariablesOn: aStream 
  	"Store the global variable declarations on the given stream."
  
  	aStream cr; nextPutAll: '/*** Variables ***/'; cr.
  	(self sortStrings: variables) do:
  		[:var | | varString decl |
  		varString := var asString.
  		decl := variableDeclarations at: varString ifAbsent: ['sqInt ' , varString].
  		decl first == $# "support cgen var: #bytecodeSetSelector declareC: '#define bytecodeSetSelector 0' hack"
  			ifTrue:
  				[aStream nextPutAll: decl; cr]
  			ifFalse:
  				[self isGeneratingPluginCode
  					ifTrue:
  						[varString = 'interpreterProxy'
  							ifTrue: "quite special..."
  								[self preDeclareInterpreterProxyOn: aStream]
  							ifFalse: [(decl beginsWith: 'static') ifFalse:
  										[aStream nextPutAll: 'static ']]]
  					ifFalse:
+ 						[(vmClass mustBeGlobal: varString)
+ 							ifTrue:
+ 								[(decl beginsWith: 'static ') ifTrue:
+ 									[decl := decl allButFirst: 7]]
+ 							ifFalse:
+ 								[(decl beginsWith: 'static') ifFalse:
+ 									[aStream nextPutAll: 'static ']]].
- 						[(vmClass mustBeGlobal: varString) ifFalse:
- 							[(decl beginsWith: 'static') ifFalse:
- 								[aStream nextPutAll: 'static ']]].
  				aStream
  					nextPutAll: decl;
  					nextPut: $;;
  					cr]].
  	aStream cr!

Item was changed:
  ----- Method: CCodeGenerator>>emitGlobalCVariablesOn: (in category 'C code generator') -----
  emitGlobalCVariablesOn: aStream
  	"Store the global variable declarations on the given stream."
  
  	aStream cr; nextPutAll: '/*** Global Variables ***/'; cr.
  	(self sortStrings: (variables select: [:v| vmClass mustBeGlobal: v])) do:
  		[:var | | varString decl |
  		varString := var asString.
  		decl := variableDeclarations at: varString ifAbsent: ['sqInt ' , varString].
  		decl first == $# "support cgen var: #bytecodeSetSelector declareC: '#define bytecodeSetSelector 0' hack"
  			ifTrue:
  				[aStream nextPutAll: decl; cr]
  			ifFalse:
  				[((decl includesSubString: ' private ')
+ 				  "or: [decl beginsWith: 'static']") ifFalse: "work-around hack to prevent localization of variables only referenced once."
- 				  or: [decl beginsWith: 'static']) ifFalse: "work-around hack to prevent localization of variables only referenced once."
  					[(decl includes: $=) ifTrue:
  						[decl := decl copyFrom: 1 to: (decl indexOf: $=) - 1].
  					aStream
  						nextPutAll: decl;
  						nextPut: $;;
  						cr]]].
  	aStream cr!

Item was changed:
  ----- Method: CCodeGenerator>>nilOrBooleanConstantReceiverOf: (in category 'utilities') -----
  nilOrBooleanConstantReceiverOf: aNode
  	"Answer nil or the boolean constant that is the receiver of the given message send.
  	 Used to suppress conditional code when the condition is a translation-time constant."
  
  	generateDeadCode ifTrue:[^nil].
  	(aNode isConstant
  	 and: [#(true false) includes: aNode value]) ifTrue:
  		[^aNode value].
  	aNode isSend ifTrue:
  		[((#(or: and:) includes: aNode selector)
  		 and: [aNode args last isStmtList
  		 and: [aNode args last statements size = 1]]) ifTrue:
  			[(self nilOrBooleanConstantReceiverOf: aNode receiver) ifNotNil:
  				[:rcvr|
  				(self nilOrBooleanConstantReceiverOf: aNode args last statements first) ifNotNil:
  					[:arg|
  					^rcvr perform: aNode selector with: [arg]]]].
  		 ((#(= ~= < > <= >=) includes: aNode selector)
  		  and: [(aNode receiver isConstant and: [aNode receiver value isInteger])
  		  and: [(aNode args first isConstant and: [aNode args first value isInteger])]]) ifTrue:
+ 			[^aNode receiver value perform: aNode selector with: aNode args first value].
+ 		(self methodNamed: aNode selector) ifNotNil:
+ 			[:m|
+ 			(m statements size = 1
+ 			 and: [m statements last isReturn]) ifTrue:
+ 				[^self nilOrBooleanConstantReceiverOf: m statements last expression]]].
- 			[^aNode receiver value perform: aNode selector with: aNode args first value]].
  	^nil
  !

Item was removed:
- ----- Method: CCodeGenerator>>printArray:on: (in category 'private') -----
- printArray: array on: aStream
- 	| first |
- 	first := true.
- 	1 to: array size do:
- 		[:i |
- 		first 
- 			ifTrue: [first := false]
- 			ifFalse: [aStream nextPutAll: ', '].
- 		i \\ 16 = 1 ifTrue: [aStream cr].
- 		self printInt: (array at: i) on: aStream]!

Item was removed:
- ----- Method: CCodeGenerator>>printInt:on: (in category 'private') -----
- printInt: int on: aStream
- 	aStream print: int.
- 	(int between: -2147483648 and: 2147483647)
- 		ifFalse: [(int between: 2147483648 and: 4294967295)
- 			ifTrue: [aStream nextPut: $U]
- 			ifFalse: [aStream nextPut: $L]]!

Item was changed:
  ----- Method: CCodeGenerator>>var:type:array: (in category 'public') -----
+ var: varName type: cType array: array
+ 	"Use this in preference to #var:declareC: when possible. This produces a C
+ 	 statment of the form
+ 		int * fooArray[]={1,2,3}
+ 	 See also #var:type: for simple var decls" 
- var: varName type: type array: array
- "use this in preference to #var:declareC: when possible. This produces a C statment of the form
- int * fooArray[]={1,2,3}
- See also #var:type: for simple var decls" 
  	self
  		var: varName
+ 		declareC: (self arrayInitializerCalled: varName for: array type: cType)!
- 		declareC: (String streamContents: [:s |
- 			s nextPutAll: type.
- 			s space.
- 			s nextPutAll: varName.
- 			s nextPutAll: '[] = {'.
- 			self printArray: array on: s.
- 			s nextPut: $}])!

Item was changed:
  ----- Method: CoInterpreter class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: aCCodeGenerator
  	"Override to avoid repeating StackInterpreter's declarations and add our own extensions"
  	| threaded |
  	self class == thisContext methodClass ifFalse: [^self]. "Don't duplicate decls in subclasses"
  	threaded := aCCodeGenerator vmClass isThreadedVM.
  	aCCodeGenerator
  		addHeaderFile:'"sqCogStackAlignment.h"';
  		addHeaderFile:'"cogmethod.h"';
  		addHeaderFile: (threaded ifTrue: ['"cointerpmt.h"'] ifFalse: ['"cointerp.h"']);
  		addHeaderFile:'"cogit.h"'.
  	self declareInterpreterVersionIn: aCCodeGenerator
  		defaultName: (threaded ifTrue: ['Cog MT'] ifFalse: ['Cog']).
  	aCCodeGenerator
+ 		var: #heapBase type: #usqInt;
+ 		var: #statCodeCompactionUsecs type: #usqLong;
- 		var: #heapBase
- 		declareC: 'static usqInt heapBase';
  		var: #maxLiteralCountForCompile
+ 			declareC: 'sqInt maxLiteralCountForCompile = MaxLiteralCountForCompile /* ', MaxLiteralCountForCompile printString, ' */';
- 		declareC: 'sqInt maxLiteralCountForCompile = MaxLiteralCountForCompile /* ', MaxLiteralCountForCompile printString, ' */';
  		var: #minBackwardJumpCountForCompile
+ 			declareC: 'sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* ', MinBackwardJumpCountForCompile printString, ' */'.
- 		declareC: 'sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* ', MinBackwardJumpCountForCompile printString, ' */'.
  	aCCodeGenerator
  		var: #reenterInterpreter
  		declareC: 'jmp_buf reenterInterpreter; /* private export */'.
  	aCCodeGenerator
- 		var: #statCodeCompactionUsecs
- 		type: #usqLong.
- 	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: #traceSources
- 		declareC: (aCCodeGenerator
- 					arrayInitializerCalled: 'traceSources'
- 					for: TraceSources
- 					type: 'char *')!

Item was changed:
  ----- Method: CoInterpreter>>ceDynamicSuperSend:to:numArgs: (in category 'trampolines') -----
  ceDynamicSuperSend: selector to: rcvr numArgs: numArgs
  	"Entry-point for an unlinked dynamic super send in a CogMethod.  Smalltalk stack looks like
  					receiver
  					args
  		head sp ->	sender return pc
  		
  	If an MNU then defer to handleMNUInMachineCodeTo:... which will dispatch the MNU and
  	may choose to allocate a closed PIC with a fast MNU dispatch for this send.  Otherwise
  	attempt to link the send site as efficiently as possible.  All link attempts may fail; e.g.
  	because we're out of code memory.
  
  	Continue execution via either executeMethod or interpretMethodFromMachineCode:
  	depending on whether the target method is cogged or not."
  	<api>
  	<option: #NewspeakVM>
  	| class classTag canLinkCacheTag errSelIdx cogMethod mClassMixin mixinApplication |
  	<inline: false>
  	<var: #cogMethod type: #'CogMethod *'>
  	<var: #newCogMethod type: #'CogMethod *'>
  	"self printExternalHeadFrame"
  	"self printStringOf: selector"
  	cogit assertCStackWellAligned.
  	self assert: (objectMemory addressCouldBeOop: rcvr).
  	self sendBreakpoint: selector receiver: rcvr.
  	mClassMixin := self mMethodClass.
  	mixinApplication := self 
  							findApplicationOfTargetMixin: mClassMixin
  							startingAtBehavior: (objectMemory fetchClassOf: rcvr).
  	self assert: (objectMemory lengthOf: mixinApplication) > (InstanceSpecificationIndex + 1).
  	classTag := self classTagForClass: (self superclassOf: mixinApplication).
  	class := objectMemory fetchClassOf: rcvr. "what about the read barrier??"
  	canLinkCacheTag := (objectMemory isYoungObject: class) not or: [cogit canLinkToYoungClasses].
  	argumentCount := numArgs.
  	(self lookupInMethodCacheSel: selector classTag: classTag)
  		ifTrue:"check for coggability because method is in the cache"
  			[self
  				ifAppropriateCompileToNativeCode: newMethod
  				selector: selector]
  		ifFalse:
+ 			[(objectMemory isOopForwarded: selector) ifTrue:
+ 				[^self
+ 					ceDynamicSuperSend: (self handleForwardedSelectorFaultFor: selector)
+ 					to: rcvr
+ 					numArgs: numArgs].
+ 			 (objectMemory isForwardedClassTag: classTag) ifTrue:
+ 				[^self
+ 					ceDynamicSuperSend: selector
+ 					to: (self handleForwardedSendFaultForReceiver: rcvr)
+ 					numArgs: numArgs].
+ 			 messageSelector := selector.
- 			[messageSelector := selector.
  			 (errSelIdx := self lookupMethodNoMNUEtcInClass: (objectMemory classForClassTag: classTag)) ~= 0 ifTrue:
  				[self handleMNU: errSelIdx InMachineCodeTo: rcvr classForMessage: (objectMemory classForClassTag: classTag).
  				self assert: false "NOTREACHED"]].
  	"Method found and has a cog method.  Attempt to link to it."
  	(self maybeMethodHasCogMethod: newMethod) ifTrue:
  		[cogMethod := self cogMethodOf: newMethod.
  		 cogMethod selector = objectMemory nilObject
  			ifTrue: [cogit setSelectorOf: cogMethod to: selector]
  			ifFalse:
  				["Deal with anonymous accessors, e.g. in Newspeak.  The cogMethod may not have the correct
  				  selector.  If not, try and compile a new method with the correct selector."
  				 cogMethod selector ~= selector ifTrue:
  					[(cogit cog: newMethod selector: selector) ifNotNil:
  						[:newCogMethod| cogMethod := newCogMethod]]].
  		 (cogMethod selector = selector
  		 and: [canLinkCacheTag]) ifTrue:
  			[cogit
  				linkSendAt: (stackPages longAt: stackPointer)
  				in: (self mframeHomeMethod: framePointer)
  				to: cogMethod
  				offset: cogit dynSuperEntryOffset
  				receiver: rcvr].
  		 instructionPointer := self popStack.
  		 self executeNewMethod.
  		 self assert: false "NOTREACHED"].
  	instructionPointer := self popStack.
  	^self interpretMethodFromMachineCode
  	"NOTREACHED"!

Item was changed:
  ----- Method: CoInterpreter>>ceInterpretMethodFromPIC:receiver: (in category 'trampolines') -----
  ceInterpretMethodFromPIC: aMethodObj receiver: rcvr
  	<api>
  	| pic primitiveIndex |
  	<var: #pic type: #'CogMethod *'>
  	self assert: (self methodHasCogMethod: aMethodObj) not.
  	"pop off inner return and locate open PIC"
  	pic := self cCoerceSimple: self popStack - cogit interpretOffset to: #'CogMethod *'.
  	self assert: (pic cmType = CMOpenPIC or: [pic cmType = CMClosedPIC]).
+ 	"If found from an open PIC then it must be an uncogged method and, since it's been found
- 	"If found from an open PIC then it must be an uncoged method and, since it's been found
  	 in the method cache, should be cogged if possible.  If found from a closed PIC it should
  	 be interpreted (since being reached by that route implies it is uncoggable)."
  	pic cmType = CMOpenPIC
  		ifTrue:
  			[(self methodShouldBeCogged: aMethodObj) ifTrue:
  				[cogit cog: aMethodObj selector: pic selector.
  				 (self methodHasCogMethod: aMethodObj) ifTrue:
  					[self executeCogMethodFromUnlinkedSend: (self cogMethodOf: aMethodObj)
  						withReceiver: rcvr]]]
  		ifFalse:
  			[self assert: (cogCompiledCodeCompactionCalledFor
  						or: [(cogit methodShouldBeCogged: aMethodObj) not])].
  	messageSelector := pic selector.
  	newMethod := aMethodObj.
  	primitiveIndex := self primitiveIndexOf: aMethodObj.
  	primitiveFunctionPointer := self functionPointerFor: primitiveIndex inClass: objectMemory nilObject.
  	argumentCount := pic cmNumArgs.
  	instructionPointer := self popStack.
  	^self interpretMethodFromMachineCode
  	"NOTREACHED"!

Item was changed:
  ----- Method: CoInterpreter>>ceSend:super:to:numArgs: (in category 'trampolines') -----
  ceSend: selector super: superNormalBar to: rcvr numArgs: numArgs
  	"Entry-point for an unlinked send in a CogMethod.  Smalltalk stack looks like
  					receiver
  					args
  		head sp ->	sender return pc
  		
  	If an MNU then defer to handleMNUInMachineCodeTo:... which will dispatch the MNU and
  	may choose to allocate a closed PIC with a fast MNU dispatch for this send.  Otherwise
  	attempt to link the send site as efficiently as possible.  All link attempts may fail; e.g.
  	because we're out of code memory.
  
  	Continue execution via either executeMethod or interpretMethodFromMachineCode:
  	depending on whether the target method is cogged or not."
  	<api>
  	| classTag canLinkCacheTag errSelIdx cogMethod |
  	<inline: false>
  	<var: #cogMethod type: #'CogMethod *'>
  	<var: #newCogMethod type: #'CogMethod *'>
  	"self printExternalHeadFrame"
  	"self printStringOf: selector"
  	cogit assertCStackWellAligned.
  	self assert: (objectMemory addressCouldBeOop: rcvr).
  	self sendBreakpoint: selector receiver: rcvr.
  	superNormalBar = 0
  		ifTrue: [classTag := objectMemory fetchClassTagOf: rcvr]
  		ifFalse: [classTag := objectMemory classTagForClass: (self superclassOf: (self methodClassOf: (self frameMethodObject: framePointer)))].
  	canLinkCacheTag := cogit canLinkToYoungClasses or: [(objectMemory isYoungObject: classTag) not].
  	argumentCount := numArgs.
  	(self lookupInMethodCacheSel: selector classTag: classTag)
  		ifTrue:"check for coggability because method is in the cache"
  			[self
  				ifAppropriateCompileToNativeCode: newMethod
  				selector: selector]
  		ifFalse:
+ 			[(objectMemory isOopForwarded: selector) ifTrue:
+ 				[^self
+ 					ceSend: (self handleForwardedSelectorFaultFor: selector)
+ 					super: superNormalBar
+ 					to: rcvr
+ 					numArgs: numArgs].
+ 			 (objectMemory isForwardedClassTag: classTag) ifTrue:
+ 				[self assert: superNormalBar = 0.
+ 				^self
+ 					ceSend: selector
+ 					super: superNormalBar
+ 					to: (self handleForwardedSendFaultForReceiver: rcvr)
+ 					numArgs: numArgs].
+ 			 messageSelector := selector.
- 			[messageSelector := selector.
  			 (errSelIdx := self lookupMethodNoMNUEtcInClass: (objectMemory classForClassTag: classTag)) ~= 0 ifTrue:
  				[(canLinkCacheTag
  				  and: [errSelIdx = SelectorDoesNotUnderstand
  				  and: [(cogMethod := cogit cogMNUPICSelector: messageSelector
  											methodOperand: (self mnuMethodOrNilFor: rcvr)
  											numArgs: argumentCount) asUnsignedInteger
  						> cogit minCogMethodAddress]]) ifTrue:
  						[cogit
  							linkSendAt: (stackPages longAt: stackPointer)
  							in: (self mframeHomeMethod: framePointer)
  							to: cogMethod
  							offset: (superNormalBar = 0
  									ifTrue: [cogit entryOffset]
  									ifFalse: [cogit noCheckEntryOffset])
  							receiver: rcvr].
  				self handleMNU: errSelIdx
  					InMachineCodeTo: rcvr
  					classForMessage: (objectMemory classForClassTag: classTag).
  				self assert: false "NOTREACHED"]].
  	"Method found and has a cog method.  Attempt to link to it.  The receiver's class may be young.
  	 If the Cogit can't store young classes in inline caches we can link to an open PIC instead."
  	(self maybeMethodHasCogMethod: newMethod) ifTrue:
  		[cogMethod := self cogMethodOf: newMethod.
  		 cogMethod selector = objectMemory nilObject
  			ifTrue: [cogit setSelectorOf: cogMethod to: selector]
  			ifFalse:
  				["Deal with anonymous accessors, e.g. in Newspeak.  The cogMethod may not have the
  				  correct selector.  If not, try and compile a new method with the correct selector."
  				 cogMethod selector ~= selector ifTrue:
  					[(cogit cog: newMethod selector: selector) ifNotNil:
  						[:newCogMethod| cogMethod := newCogMethod]]].
  		 (cogMethod selector = selector
  		  and: [canLinkCacheTag])
  			ifTrue:
  				[cogit
  					linkSendAt: (stackPages longAt: stackPointer)
  					in: (self mframeHomeMethod: framePointer)
  					to: cogMethod
  					offset: (superNormalBar = 0
  								ifTrue: [cogit entryOffset]
  								ifFalse: [cogit noCheckEntryOffset])
  					receiver: rcvr]
  			ifFalse: "If patchToOpenPICFor:.. returns we're out of code memory"
  				[cogit
  					patchToOpenPICFor: selector
  					numArgs: numArgs
  					receiver: rcvr].
  		 instructionPointer := self popStack.
  		 self executeNewMethod.
  		 self assert: false "NOTREACHED"].
  	instructionPointer := self popStack.
  	^self interpretMethodFromMachineCode
  	"NOTREACHED"!

Item was changed:
  ----- Method: CoInterpreter>>ceSendFromInLineCacheMiss: (in category 'trampolines') -----
  ceSendFromInLineCacheMiss: cogMethodOrPIC
  	"Send from an Open PIC when the first-level method lookup probe has failed,
  	 or to continue when PIC creation has failed (e.g. because we're out of code space),
  	 or when a send has failed due to a forwarded receiver."
  	<api>
  	<var: #cogMethodOrPIC type: #'CogMethod *'>
  	| numArgs rcvr classTag errSelIdx |
  	"self printFrame: stackPage headFP WithSP: stackPage headSP"
  	"self printStringOf: selector"
  	numArgs := cogMethodOrPIC cmNumArgs.
  	rcvr := self stackValue: numArgs + 1. "skip return pc"
  	self assert: (objectMemory addressCouldBeOop: rcvr).
  	classTag := objectMemory fetchClassTagOf: rcvr.
  	argumentCount := numArgs.
  	(self lookupInMethodCacheSel: cogMethodOrPIC selector classTag: classTag)
  		ifTrue:"check for coggability because method is in the cache"
  			[self
  				ifAppropriateCompileToNativeCode: newMethod
  				selector: cogMethodOrPIC selector]
  		ifFalse:
+ 			[(objectMemory isOopForwarded: cogMethodOrPIC selector) ifTrue:
+ 				[self handleForwardedSelectorFaultFor: cogMethodOrPIC selector.
+ 				 ^self ceSendFromInLineCacheMiss: cogMethodOrPIC].
+ 			 (objectMemory isForwardedClassTag: classTag) ifTrue:
+ 				[self handleForwardedSendFaultForReceiver: rcvr.
+ 				 ^self ceSendFromInLineCacheMiss: cogMethodOrPIC].
+ 			 messageSelector := cogMethodOrPIC selector.
- 			[messageSelector := cogMethodOrPIC selector.
- 			 ((objectMemory isOopForwarded: messageSelector)
- 			  or: [objectMemory isForwardedClassTag: classTag]) ifTrue:
- 				[(objectMemory isOopForwarded: messageSelector) ifTrue:
- 					[messageSelector := self handleForwardedSelectorFaultFor: messageSelector].
- 				 (objectMemory isForwardedClassTag: classTag) ifTrue:
- 					[classTag := self handleForwardedSendFaultFor: classTag]].
  			 (errSelIdx := self lookupMethodNoMNUEtcInClass: (objectMemory classForClassTag: classTag)) ~= 0 ifTrue:
  				[self handleMNU: errSelIdx InMachineCodeTo: rcvr classForMessage: (objectMemory classForClassTag: classTag).
  				"NOTREACHED"
  				self assert: false]].
  	instructionPointer := self popStack.
  	(self maybeMethodHasCogMethod: newMethod) ifTrue:
  		[self executeNewMethod.
  		 self assert: false
  		 "NOTREACHED"].
  	^self interpretMethodFromMachineCode
  	"NOTREACHED"!

Item was changed:
  ----- Method: CoInterpreter>>findNewMethodInClassTag: (in category 'message sending') -----
  findNewMethodInClassTag: classTagArg
  	"Find the compiled method to be run when the current messageSelector is
  	 sent to the given classTag, setting the values of newMethod and primitiveIndex."
  	| ok class classTag |
  	<inline: false>
  	ok := self lookupInMethodCacheSel: messageSelector classTag: classTagArg.
  	ok	ifTrue:
  			[self ifAppropriateCompileToNativeCode: newMethod selector: messageSelector]
  		ifFalse:
  			["entry was not found in the cache; perhaps soemthing was forwarded."
  			 classTag := classTagArg.
  			 ((objectMemory isOopForwarded: messageSelector)
  			  or: [objectMemory isForwardedClassTag: classTag]) ifTrue:
  				[(objectMemory isOopForwarded: messageSelector) ifTrue:
  					[messageSelector := self handleForwardedSelectorFaultFor: messageSelector].
  				 (objectMemory isForwardedClassTag: classTag) ifTrue:
+ 					[classTag := self handleForwardedSendFaultForTag: classTag].
- 					[classTag := self handleForwardedSendFaultFor: classTag].
  				ok := self lookupInMethodCacheSel: messageSelector classTag: classTag.
  				ok ifTrue:
  					[^self ifAppropriateCompileToNativeCode: newMethod selector: messageSelector]].
  			 "entry was not found in the cache; look it up the hard way "
  			 class := objectMemory classForClassTag: classTag.
  			 self lookupMethodInClass: class.
  			 self addNewMethodToCache: class]!

Item was added:
+ ----- Method: CoInterpreter>>followForwardedFieldsInCurrentMethod (in category 'message sending') -----
+ followForwardedFieldsInCurrentMethod
+ 	| cogMethod |
+ 	<var: #cogMethod type: #'CogMethod *'>
+ 	<inline: false>
+ 	(self isMachineCodeFrame: framePointer)
+ 		ifTrue:
+ 			[cogMethod := self mframeHomeMethod: framePointer.
+ 			 objectMemory
+ 				followForwardedObjectFields: cogMethod methodObject
+ 				toDepth: 0.
+ 			 cogit followForwardedLiteralsIn: cogMethod]
+ 		ifFalse:
+ 			[objectMemory
+ 				followForwardedObjectFields: method
+ 				toDepth: 0]!

Item was added:
+ ----- Method: CoInterpreter>>followForwardedMethods (in category 'object memory support') -----
+ followForwardedMethods
+ 	<doNotGenerate>
+ 	cogit followForwardedMethods!

Item was added:
+ ----- Method: CoInterpreter>>handleForwardedSendFaultForReceiver: (in category 'message sending') -----
+ handleForwardedSendFaultForReceiver: forwardedReceiver
+ 	"Handle a send fault that may be due to a send to a forwarded object.
+ 	 Unforward the receiver on the stack and answer it."
+ 	<option: #SpurObjectMemory>
+ 	| rcvr |
+ 	<inline: false>
+ 	"should *not* be a super send, so the receiver should be forwarded."
+ 	self assert: (objectMemory isOopForwarded: forwardedReceiver).
+ 
+ 	self assert: (self stackValue: argumentCount) = forwardedReceiver.
+ 	rcvr := objectMemory followForwarded: forwardedReceiver.
+ 	self stackValue: argumentCount put: rcvr.
+ 	self followForwardedFrameContents: framePointer
+ 		stackPointer: stackPointer + (argumentCount + 1 * BytesPerWord). "don't repeat effort"
+ 	(objectMemory isPointers: (self frameReceiver: framePointer)) ifTrue:
+ 		[objectMemory
+ 			followForwardedObjectFields: (self frameReceiver: framePointer)
+ 			toDepth: 0].
+ 	self followForwardedFieldsInCurrentMethod.
+ 	^rcvr!

Item was changed:
  ----- Method: CoInterpreter>>internalFindNewMethod (in category 'message sending') -----
  internalFindNewMethod
  	"Find the compiled method to be run when the current messageSelector is
  	 sent to the given class, setting the values of newMethod and primitiveIndex."
  	| ok |
  	<inline: true>
  	ok := self lookupInMethodCacheSel: messageSelector classTag: lkupClassTag.
  	ok	ifTrue:
  			[self ifAppropriateCompileToNativeCode: newMethod selector: messageSelector]
  		ifFalse:
  			[self externalizeIPandSP.
  			 ((objectMemory isOopForwarded: messageSelector)
  			  or: [objectMemory isForwardedClassTag: lkupClassTag]) ifTrue:
  				[(objectMemory isOopForwarded: messageSelector) ifTrue:
  					[messageSelector := self handleForwardedSelectorFaultFor: messageSelector].
  				 (objectMemory isForwardedClassTag: lkupClassTag) ifTrue:
+ 					[lkupClassTag := self handleForwardedSendFaultForTag: lkupClassTag].
- 					[lkupClassTag := self handleForwardedSendFaultFor: lkupClassTag].
  				ok := self lookupInMethodCacheSel: messageSelector classTag: lkupClassTag.
  				ok ifTrue:
  					[^self ifAppropriateCompileToNativeCode: newMethod selector: messageSelector]].
  			 lkupClass := objectMemory classForClassTag: lkupClassTag.
  			self lookupMethodInClass: lkupClass.
  			self internalizeIPandSP.
  			self addNewMethodToCache: lkupClass]!

Item was added:
+ ----- Method: CogObjectRepresentation>>genEnsureObjInRegRegNotForwarded:scratchReg: (in category 'compile abstract instructions') -----
+ genEnsureObjInRegRegNotForwarded: reg scratchReg: scratch
+ 	"Make sure that the object in reg is not forwarded.  By default there is
+ 	 nothing to do.  Subclasses for memory managers that forward will override."
+ 	^0!

Item was removed:
- ----- Method: CogObjectRepresentation>>genEnsureRegNotForwarded:scratchReg: (in category 'compile abstract instructions') -----
- genEnsureRegNotForwarded: reg scratchReg: scratch
- 	"Make sure that the obejct in reg is not forwarded.  By default there is
- 	 nothing to do.  Subclasses for memory managers that forward will override."
- 	^0!

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>couldBeObject: (in category 'garbage collection') -----
  couldBeObject: literal
+ 	^(objectMemory isNonImmediate: literal)
+ 	  and: [self oop: literal isGreaterThanOrEqualTo: objectMemory startOfMemory]!
- 	^objectMemory isNonImmediate: literal!

Item was added:
+ ----- Method: CogObjectRepresentationForSpur>>genEnsureObjInRegRegNotForwarded:scratchReg: (in category 'compile abstract instructions') -----
+ genEnsureObjInRegRegNotForwarded: reg scratchReg: scratch
+ 	"Make sure that the obejct in reg is not forwarded."
+ 	| loop ok |
+ 	<var: #ok type: #'AbstractInstruction *'>
+ 	<var: #loop type: #'AbstractInstruction *'>
+ 	self assert: reg ~= scratch.
+ 	loop := cogit Label.
+ 	self genGetClassIndexOfNonImm: reg into: scratch.
+ 	cogit CmpCq: objectMemory isForwardedObjectClassIndexPun
+ 		R: TempReg.
+ 	ok := cogit JumpNonZero:  0.
+ 	self genLoadSlot: 0 sourceReg: reg destReg: reg.
+ 	cogit Jump: loop.
+ 	ok jmpTarget: cogit Label.
+ 	^0!

Item was removed:
- ----- Method: CogObjectRepresentationForSpur>>genEnsureRegNotForwarded:scratchReg: (in category 'compile abstract instructions') -----
- genEnsureRegNotForwarded: reg scratchReg: scratch
- 	"Make sure that the obejct in reg is not forwarded."
- 	| loop ok |
- 	<var: #ok type: #'AbstractInstruction *'>
- 	<var: #loop type: #'AbstractInstruction *'>
- 	self assert: reg ~= scratch.
- 	loop := cogit Label.
- 	self genGetClassIndexOfNonImm: reg into: scratch.
- 	cogit CmpCq: objectMemory isForwardedObjectClassIndexPun
- 		R: TempReg.
- 	ok := cogit JumpNonZero:  0.
- 	self genLoadSlot: 0 sourceReg: reg destReg: reg.
- 	cogit Jump: loop.
- 	ok jmpTarget: cogit Label.
- 	^0!

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>genGetClassObjectOf:into:scratchReg:instRegIsReceiver: (in category 'compile abstract instructions') -----
  genGetClassObjectOf: instReg into: destReg scratchReg: scratchReg instRegIsReceiver: instRegIsReceiver
+ 	"Fetch the instance's class into destReg.  If the instance is forwarded, follow forwarding."
- 	"Fetch the instance's class into destReg."
  	| jumpIsImm jumpNotForwarded loop |
  	<var: #jumpIsImm type: #'AbstractInstruction *'>
  	<var: #jumpNotForwarded type: #'AbstractInstruction *'>
  	<var: #loop type: #'AbstractInstruction *'>
  	instReg = destReg ifTrue:
  		[^BadRegisterSet].
  	loop := cogit MoveR: instReg R: scratchReg.
  	cogit AndCq: objectMemory tagMask R: scratchReg.
  	jumpIsImm := cogit JumpNonZero: 0.
  	self flag: #endianness.
  	"Get least significant half of header word in destReg"
  	cogit MoveMw: 0 r: instReg R: scratchReg.
  	"mask off class index"
  	cogit AndCq: objectMemory classIndexMask R: scratchReg.
  	instRegIsReceiver ifFalse:
  		["if it is forwarded..."
  		cogit CmpCq: objectMemory isForwardedObjectClassIndexPun R: scratchReg.
  		jumpNotForwarded := cogit JumpNonZero: 0.
  		"...follow the forwarding pointer and loop to fetch its classIndex"
  		cogit MoveMw: objectMemory baseHeaderSize r: instReg R: instReg.
  		cogit Jump: loop.
  		jumpNotForwarded jmpTarget: cogit Label].
  	jumpIsImm jmpTarget:
  	(cogit MoveR: scratchReg R: destReg).
  	cogit PushR: instReg.
  	self genGetClassObjectOfClassIndex: destReg into: instReg scratchReg: TempReg.
  	cogit MoveR: instReg R: destReg.
  	cogit PopR: instReg.
  	^0!

Item was added:
+ ----- Method: CogObjectRepresentationForSqueakV3>>isOopForwarded: (in category 'garbage collection') -----
+ isOopForwarded: oop
+ 	"Compatibility wth SpurMemoryManager.  In ObjectMemory, no forwarding pointers
+ 	 are visible to the VM."
+ 	<inline: true>
+ 	^false!

Item was changed:
  ----- Method: Cogit class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: aCCodeGenerator
  	#(	'coInterpreter' 'objectMemory' 'methodZone' 'objectRepresentation'
  		'cogBlockMethodSurrogateClass' 'cogMethodSurrogateClass'
  		'threadManager' 'processor' 'lastNInstructions' 'simulatedAddresses'
  		'simulatedTrampolines' 'simulatedVariableGetters' 'simulatedVariableSetters'
  		'printRegisters' 'printInstructions' 'clickConfirm' 'singleStep') do:
  			[:simulationVariableNotNeededForRealVM|
  			aCCodeGenerator removeVariable: simulationVariableNotNeededForRealVM].
  	NewspeakVM ifFalse:
  		[#(	'dynSuperEntry' 'dynSuperEntryAlignment' 'dynamicSuperSendTrampolines'
  			'ceImplicitReceiverTrampoline' 'ceExplicitReceiverTrampoline' 'cmDynSuperEntryOffset') do:
  				[:variableNotNeededInNormalVM|
  				aCCodeGenerator removeVariable: variableNotNeededInNormalVM]].
  	aCCodeGenerator removeConstant: #COGMTVM. "this should be defined at compile time"
  	aCCodeGenerator
  		addHeaderFile:'<stddef.h>'; "for e.g. offsetof"
  		addHeaderFile:'"sqCogStackAlignment.h"';
  		addHeaderFile:'"cogmethod.h"';
  		addHeaderFile:'#if COGMTVM';
  		addHeaderFile:'"cointerpmt.h"';
  		addHeaderFile:'#else';
  		addHeaderFile:'"cointerp.h"';
  		addHeaderFile:'#endif';
  		addHeaderFile:'"cogit.h"';
  		addHeaderFile:'"dispdbg.h"'.
  	aCCodeGenerator
  		var: #ceGetSP
  			declareC: 'unsigned long (*ceGetSP)(void)';
  		var: #ceCaptureCStackPointers
  			declareC: 'void (*ceCaptureCStackPointers)(void)';
  		var: #ceEnterCogCodePopReceiverReg
  			declareC: 'void (*ceEnterCogCodePopReceiverReg)(void)';
  		var: #realCEEnterCogCodePopReceiverReg
  			declareC: 'void (*realCEEnterCogCodePopReceiverReg)(void)';
  		var: #ceEnterCogCodePopReceiverAndClassRegs
  			declareC: 'void (*ceEnterCogCodePopReceiverAndClassRegs)(void)';
  		var: #realCEEnterCogCodePopReceiverAndClassRegs
  			declareC: 'void (*realCEEnterCogCodePopReceiverAndClassRegs)(void)';
  		var: #ceFlushICache
  			declareC: 'static void (*ceFlushICache)(unsigned long from, unsigned long to)';
  		var: #ceCheckFeaturesFunction
  			declareC: 'static unsigned long (*ceCheckFeaturesFunction)(void)';
  		var: #ceTryLockVMOwner
  			declareC: 'unsigned long (*ceTryLockVMOwner)(void)';
  		var: #ceUnlockVMOwner
  			declareC: 'void (*ceUnlockVMOwner)(void)';
  		var: #postCompileHook
  			declareC: 'void (*postCompileHook)(CogMethod *, void *)';
  		var: #openPICList declareC: 'CogMethod *openPICList = 0';
  		var: #maxMethodBefore type: #'CogBlockMethod *'.
  	aCCodeGenerator
  		declareVar: 'aMethodLabel' type: #'AbstractInstruction'; "Has to come lexicographically before backEnd & methodLabel"
  		var: #backEnd declareC: 'AbstractInstruction * const backEnd = &aMethodLabel';
  		var: #methodLabel declareC: 'AbstractInstruction * const methodLabel = &aMethodLabel';
  		var: #primInvokeLabel type: #'AbstractInstruction *'.
  	self declareC: #(abstractOpcodes stackCheckLabel
  					blockEntryLabel blockEntryNoContextSwitch
  					stackOverflowCall sendMissCall entry noCheckEntry dynSuperEntry
  					mnuCall interpretCall endCPICCase0 endCPICCase1)
  			as: #'AbstractInstruction *'
  				in: aCCodeGenerator.
  	aCCodeGenerator
  		declareVar: #annotations type: #'InstructionAnnotation *';
  		declareVar: #blockStarts type: #'BlockStart *';
  		declareVar: #fixups type: #'BytecodeFixup *'.
  	aCCodeGenerator
  		var: #sendTrampolines
  			declareC: 'sqInt sendTrampolines[NumSendTrampolines]';
  		var: #superSendTrampolines
  			declareC: 'sqInt superSendTrampolines[NumSendTrampolines]';
  		var: #dynamicSuperSendTrampolines
  			declareC: 'sqInt dynamicSuperSendTrampolines[NumSendTrampolines]';
  		var: #trampolineAddresses
  			declareC: 'static char *trampolineAddresses[NumTrampolines*2]';
  		var: #objectReferencesInRuntime
  			declareC: 'static sqInt objectReferencesInRuntime[NumObjRefsInRuntime]';
  		var: #cePositive32BitIntegerTrampoline
  			declareC: 'static sqInt cePositive32BitIntegerTrampoline';
  		var: #labelCounter
+ 			type: #int;
- 			declareC: 'static int labelCounter';
  		var: #traceFlags
  			declareC: 'int traceFlags = 8 /* prim trace log on by default */';
  		var: #cStackAlignment
  			declareC: 'const int cStackAlignment = STACK_ALIGN_BYTES'.
  	aCCodeGenerator
  		declareVar: #CFramePointer type: #'void *';
  		declareVar: #CStackPointer type: #'void *';
  		declareVar: #minValidCallAddress type: #'unsigned long';
  		declareVar: #debugPrimCallStackOffset type: #'unsigned long'.
  	aCCodeGenerator
  		var: #generatorTable
  			declareC: 'BytecodeDescriptor generatorTable[', aCCodeGenerator vmClass generatorTable size, ']'
  						, (self tableInitializerFor: aCCodeGenerator vmClass generatorTable
  							in: aCCodeGenerator);
  		var: #primitiveGeneratorTable
  			declareC: 'PrimitiveDescriptor primitiveGeneratorTable[MaxCompiledPrimitiveIndex+1]'
  						, (self tableInitializerFor: aCCodeGenerator vmClass primitiveTable
  							in: aCCodeGenerator).
  	"In C the abstract opcode names clash with the Smalltak generator syntactic sugar.
  	 Most of the syntactic sugar is inlined, but alas some remains.  Rename the syntactic
  	 sugar to avoid the clash."
  	(self organization listAtCategoryNamed: #'abstract instructions') do:
  		[:s|
  		aCCodeGenerator addSelectorTranslation: s to: 'g', (aCCodeGenerator cFunctionNameFor: s)].
  	aCCodeGenerator addSelectorTranslation: #halt: to: 'haltmsg'!

Item was changed:
  ----- Method: Cogit class>>mustBeGlobal: (in category 'translation') -----
  mustBeGlobal: var
  	"Answer if a variable must be global and exported.  Used for inst vars that are accessed from VM
  	 support code.  include cePositive32BitIntegerTrampoline as a hack to prevent it being inlined (it is
+ 	 only used outside of Cogit by the object representation).  Include CFramePointer CStackPointer as
+ 	 a hack to get them declared at all."
- 	 only used outside of Cogit by the object representation).  Include labelCounter as a hack to stop it
- 	 being inlined into genLabel, and CFramePointer CStackPointer as a hack to get them declared at all."
  	^#('ceBaseFrameReturnTrampoline' 'ceCaptureCStackPointers' 'ceCheckForInterruptTrampoline'
  		'ceEnterCogCodePopReceiverReg' 'realCEEnterCogCodePopReceiverReg'
  		'ceEnterCogCodePopReceiverAndClassRegs' 'realCEEnterCogCodePopReceiverAndClassRegs'
  		'ceReturnToInterpreterTrampoline' 'ceCannotResumeTrampoline'
+ 		'ceTryLockVMOwner' 'ceUnlockVMOwner'
- 		'cePositive32BitIntegerTrampoline' 'ceFlushICache' 'ceTryLockVMOwner' 'ceUnlockVMOwner'
  		'cmEntryOffset' 'cmNoCheckEntryOffset' 'cmDynSuperEntryOffset'
  		'blockNoContextSwitchOffset' 'breakPC'
+ 		'CFramePointer' 'CStackPointer' 'cFramePointerInUse' 'ceGetSP'
- 		'labelCounter' 'CFramePointer' 'CStackPointer' 'cFramePointerInUse' 'ceGetSP'
  		'traceFlags' 'traceStores' 'debugPrimCallStackOffset')
  			includes: var!

Item was added:
+ ----- Method: Cogit>>followForwardedLiteralsIn: (in category 'garbage collection') -----
+ followForwardedLiteralsIn: cogMethod
+ 	<api>
+ 	<option: #SpurObjectMemory>
+ 	<var: #cogMethod type: #'CogMethod *'>
+ 	self assert: (objectMemory shouldRemapOop: cogMethod methodObject) not.
+ 	(objectMemory shouldRemapOop: cogMethod selector) ifTrue:
+ 		[cogMethod selector: (objectMemory remapObj: cogMethod selector)].
+ 	self mapFor: cogMethod
+ 		performUntil: (self cppIf: NewspeakVM
+ 							ifTrue: [#remapNSIfObjectRef:pc:hasYoung:]
+ 							ifFalse: [#remapIfObjectRef:pc:hasYoung:])
+ 		arg: 0!

Item was added:
+ ----- Method: Cogit>>followForwardedMethods (in category 'garbage collection') -----
+ followForwardedMethods
+ 	<api>
+ 	<option: #SpurObjectMemory>
+ 	<var: #cogMethod type: #'CogMethod *'>
+ 	| cogMethod freedPIC |
+ 	<var: #cogMethod type: #'CogMethod *'>
+ 	freedPIC := false.
+ 	cogMethod := self cCoerceSimple: methodZoneBase to: #'CogMethod *'.
+ 	[cogMethod < methodZone limitZony] whileTrue:
+ 		[cogMethod cmType = CMMethod ifTrue:
+ 			[(objectMemory shouldRemapOop: cogMethod methodObject) ifTrue:
+ 				[cogMethod methodObject: (objectMemory remapObj: cogMethod methodObject).
+ 				 (cogMethod cmRefersToYoung not
+ 				  and: [objectMemory isYoungObject: cogMethod methodObject]) ifTrue:
+ 					[methodZone addToYoungReferrers: cogMethod methodObject]]].
+ 		 cogMethod cmType = CMClosedPIC ifTrue:
+ 			[(self mapObjectReferencesInClosedPIC: cogMethod) ifTrue:
+ 				[freedPIC := true.
+ 				 methodZone freeMethod: cogMethod]].
+ 		 cogMethod := methodZone methodAfter: cogMethod].
+ 	freedPIC ifTrue:
+ 		[self unlinkSendsToFree.
+ 		 processor flushICacheFrom: codeBase to: methodZone limitZony asInteger]!

Item was changed:
  ----- Method: ObjectMemory class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: aCCodeGenerator
+ 	self declareCAsOop:
+ 			#(	memory endOfMemory memoryLimit
+ 				youngStart youngStartLocal freeBlock
+ 				compStart compEnd
+ 				fwdTableNext fwdTableLast
+ 				gcBiasToGrowThreshold )
+ 		in: aCCodeGenerator.
+ 	self declareCAsUSqLong:
+ 			#( gcStartUsecs statFullGCUsecs statIncrGCUsecs statIGCDeltaUsecs )
+ 		in: aCCodeGenerator.
  	aCCodeGenerator
- 		var: #memory
- 		declareC: 'static usqInt memory'.
- 	aCCodeGenerator
  		var: #remapBuffer
  		declareC: 'sqInt remapBuffer[RemapBufferSize + 1 /* ', (RemapBufferSize + 1) printString, ' */]'.
  	aCCodeGenerator
  		var: #rootTable
  		declareC: 'sqInt rootTable[RootTableSize + 1 /* ', (RootTableSize + 1) printString, ' */]'.
  	"Weak roots must be large enough for roots+remapBuffer+sizeof(allCallsOn: #markAndTrace:)"
  	aCCodeGenerator
  		var: #weakRoots
  		declareC: 'sqInt weakRoots[WeakRootTableSize + 1 /* ', (WeakRootTableSize + 1) printString, ' */]'.
  	aCCodeGenerator
  		var: #headerTypeBytes
  		declareC: 'sqInt headerTypeBytes[4]'.
  	aCCodeGenerator
  		var: #extraRoots
  		declareC: 'sqInt* extraRoots[ExtraRootSize + 1 /* ', (ExtraRootSize + 1) printString, ' */]'.
- 	self declareCAsOop: {
- 			#youngStart .
- 			#endOfMemory .
- 			#memoryLimit .
- 			#youngStartLocal .
- 			#freeBlock .
- 			#compStart .
- 			#compEnd .
- 			#fwdTableNext .
- 			#fwdTableLast .
- 			#gcBiasToGrowThreshold }
- 		in: aCCodeGenerator.
  	aCCodeGenerator
+ 		var: #headerTypeBytes type: 'const sqInt' array: HeaderTypeExtraBytes!
- 		var: #headerTypeBytes type: 'const sqInt' array: HeaderTypeExtraBytes.
- 	self declareCAsUSqLong: #(gcStartUsecs statFullGCUsecs statIncrGCUsecs statIGCDeltaUsecs)
- 		in: aCCodeGenerator!

Item was changed:
  ----- Method: ObjectMemory class>>mustBeGlobal: (in category 'translation') -----
  mustBeGlobal: var
  	"Answer if a variable must be global and exported.  Used for inst vars that are accessed from VM support code."
  
+ 	^false "used to be: ^'memory' = var"!
- 	^'memory' = var!

Item was changed:
  ----- Method: ObjectMemory>>isOopForwarded: (in category 'interpreter access') -----
  isOopForwarded: oop
  	"Compatibility wth SpurMemoryManager.  In ObjectMemory, no forwarding pointers
  	 are visible to the VM."
- 	<api>
- 	<cmacro: '(oop) false'>
  	<inline: true>
  	^false!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genPushLiteralVariable: (in category 'bytecode generators') -----
  genPushLiteralVariable: literalIndex
  	<inline: false>
  	| association |
  	association := self getLiteral: literalIndex.
  	"N.B. Do _not_ use ReceiverResultReg to avoid overwriting receiver in assignment in frameless methods."
  	self annotate: (self MoveCw: association R: ClassReg) objRef: association.
- 	objectRepresentation genEnsureRegNotForwarded: ClassReg scratchReg: TempReg.
  	objectRepresentation
+ 		genEnsureObjInRegRegNotForwarded: ClassReg
+ 		scratchReg: TempReg.
+ 	objectRepresentation
  		genLoadSlot: ValueIndex
  		sourceReg: ClassReg
  		destReg: TempReg.
  	self PushR: TempReg.
  	^0!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genSpecialSelectorEqualsEquals (in category 'bytecode generators') -----
  genSpecialSelectorEqualsEquals
  	| jumpNotEqual jumpPush |
  	<var: #jumpNotEqual type: #'AbstractInstruction *'>
  	<var: #jumpPush type: #'AbstractInstruction *'>
+ 	self PopR: Arg0Reg.
+ 	objectRepresentation
+ 		genEnsureObjInRegRegNotForwarded: Arg0Reg
+ 		scratchReg: TempReg.
- 	self PopR: TempReg.
  	self MoveMw: 0 r: SPReg R: ClassReg.
+ 	objectRepresentation
+ 		genEnsureObjInRegRegNotForwarded: ClassReg
+ 		scratchReg: TempReg.
+ 	self CmpR: Arg0Reg R: ClassReg.
- 	self CmpR: TempReg R: ClassReg.
  	jumpNotEqual := self JumpNonZero: 0.
+ 	self annotate: (self MoveCw: objectMemory trueObject R: Arg0Reg)
- 	self annotate: (self MoveCw: objectMemory trueObject R: TempReg)
  		objRef: objectMemory trueObject.
  	jumpPush := self Jump: 0.
+ 	jumpNotEqual jmpTarget: (self annotate: (self MoveCw: objectMemory falseObject R: Arg0Reg)
- 	jumpNotEqual jmpTarget: (self annotate: (self MoveCw: objectMemory falseObject R: TempReg)
  							objRef: objectMemory falseObject).
+ 	jumpPush jmpTarget: (self MoveR: Arg0Reg Mw: 0 r: SPReg).
- 	jumpPush jmpTarget: (self MoveR: TempReg Mw: 0 r: SPReg).
  	^0!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genStorePop:LiteralVariable: (in category 'bytecode generators') -----
  genStorePop: popBoolean LiteralVariable: litVarIndex
  	<inline: false>
  	| association |
  	self assert: needsFrame.
  	association := self getLiteral: litVarIndex.
  	self annotate: (self MoveCw: association R: ReceiverResultReg) objRef: association.
+ 	objectRepresentation
+ 		genEnsureObjInRegRegNotForwarded: ReceiverResultReg
+ 		scratchReg: TempReg.
- 	objectRepresentation genEnsureRegNotForwarded: ReceiverResultReg scratchReg: TempReg.
  	popBoolean
  		ifTrue: [self PopR: ClassReg]
  		ifFalse: [self MoveMw: 0 r: SPReg R: ClassReg].
  	traceStores > 0 ifTrue:
  		[self CallRT: ceTraceStoreTrampoline].
  	^objectRepresentation
  		genStoreSourceReg: ClassReg
  		slotIndex: ValueIndex
  		destReg: ReceiverResultReg
  		scratchReg: TempReg!

Item was changed:
  ----- Method: Spur32BitCoMemoryManager>>startOfMemory (in category 'accessing') -----
  startOfMemory
  	"Return the start of object memory.  This is immediately after the native code zone.
  	 N.B. the stack zone is alloca'ed. Use a macro so as not to punish the debug VM."
+ 	<api>
  	<cmacro: '() heapBase'>
  	<returnTypeC: #usqInt>
  	^coInterpreter heapBase!

Item was changed:
  ----- Method: SpurMemoryManager>>scavengingGCTenuringIf: (in category 'gc - scavenging') -----
  scavengingGCTenuringIf: tenuringCriterion
  	"Run the scavenger."
  
  	self assert: remapBufferCount = 0.
+ 	(self asserta: scavenger eden limit - freeStart > coInterpreter interpreterAllocationReserveBytes) ifFalse:
+ 		[coInterpreter tab;
+ 			printNum: scavenger eden limit - freeStart; space;
+ 			printNum: coInterpreter interpreterAllocationReserveBytes; space;
+ 			printNum: coInterpreter interpreterAllocationReserveBytes - (scavenger eden limit - freeStart); cr].
- 	self assert: scavenger eden limit - freeStart > coInterpreter interpreterAllocationReserveBytes.
  	self checkMemoryMap.
  	self checkFreeSpace.
  	"coInterpreter printCallStackFP: coInterpreter framePointer"
  
  	self runLeakCheckerForFullGC: false.
  	coInterpreter
  		preGCAction: GCModeScavenge;
  		"would prefer this to be in mapInterpreterOops, but
  		 compatibility with ObjectMemory dictates it goes here."
  		flushMethodCacheFrom: newSpaceStart to: newSpaceLimit.
  	needGCFlag := false.
  
  	gcStartUsecs := coInterpreter ioUTCMicrosecondsNow.
  
  	self doScavenge: tenuringCriterion.
  
  	statScavenges := statScavenges + 1.
  	statGCEndUsecs := coInterpreter ioUTCMicrosecondsNow.
  	statSGCDeltaUsecs := statGCEndUsecs - gcStartUsecs.
  	statScavengeGCUsecs := statScavengeGCUsecs + statSGCDeltaUsecs.
  	statRootTableCount := scavenger rememberedSetSize.
  
  	coInterpreter postGCAction: GCModeScavenge.
  	self runLeakCheckerForFullGC: false.
  
  	self checkFreeSpace!

Item was changed:
  ----- Method: StackInterpreter>>findNewMethodInClassTag: (in category 'message sending') -----
  findNewMethodInClassTag: classTagArg
  	"Find the compiled method to be run when the current 
  	messageSelector is sent to the given class, setting the values 
  	of 'newMethod' and 'primitiveIndex'."
  	| ok class classTag |
  	<inline: false>
  	ok := self lookupInMethodCacheSel: messageSelector classTag: classTagArg.
  	ok ifFalse: "entry was not found in the cache; look it up the hard way "
  		[classTag := classTagArg.
  		 ((objectMemory isOopForwarded: messageSelector)
  		  or: [objectMemory isForwardedClassTag: classTag]) ifTrue:
  			[(objectMemory isOopForwarded: messageSelector) ifTrue:
  				[messageSelector := self handleForwardedSelectorFaultFor: messageSelector].
  			 (objectMemory isForwardedClassTag: classTag) ifTrue:
+ 				[classTag := self handleForwardedSendFaultForTag: classTag].
- 				[classTag := self handleForwardedSendFaultFor: classTag].
  			ok := self lookupInMethodCacheSel: messageSelector classTag: classTag.
  			ok ifTrue:
  				[^nil]].
  		 class := objectMemory classForClassTag: classTag.
  		 self lookupMethodInClass: class.
  		 self addNewMethodToCache: class]!

Item was added:
+ ----- Method: StackInterpreter>>followForwardedFieldsInCurrentMethod (in category 'message sending') -----
+ followForwardedFieldsInCurrentMethod
+ 	objectMemory
+ 		followForwardedObjectFields: method
+ 		toDepth: 0!

Item was added:
+ ----- Method: StackInterpreter>>followForwardedMethods (in category 'object memory support') -----
+ followForwardedMethods
+ 	"This is just a stub for the CoInterpreter"!

Item was added:
+ ----- Method: StackInterpreter>>followForwardedMethodsInMethodCache (in category 'object memory support') -----
+ followForwardedMethodsInMethodCache
+ 	0 to: MethodCacheSize - 1 by: MethodCacheEntrySize do:
+ 		[:i | | c s m |
+ 		c := methodCache at: i + MethodCacheClass.
+ 		s := methodCache at: i + MethodCacheSelector.
+ 		m := methodCache at: i + MethodCacheMethod.
+ 		(c ~= 0 and: [s ~= 0 and: [m ~= 0
+ 		 and: [objectMemory isOopForwarded: m]]]) ifTrue:
+ 			[m := objectMemory followForwarded: m.
+ 			 methodCache at: i + MethodCacheMethod put: m]]!

Item was changed:
  ----- Method: StackInterpreter>>handleForwardedSelectorFaultFor: (in category 'message sending') -----
  handleForwardedSelectorFaultFor: selectorOop
  	"Handle a send fault that is due to a send using a forwarded selector.
  	 Unforward the selector and follow the current method and special
  	 selectors array to unforward the source of the forwarded selector."
+ 	<option: #SpurObjectMemory>
  	<inline: false>
  	self assert: (objectMemory isOopForwarded: selectorOop).
+ 	self followForwardedFieldsInCurrentMethod.
- 
  	objectMemory
- 		followForwardedObjectFields: method
- 			toDepth: 0;
  		followForwardedObjectFields: (objectMemory splObj: SpecialSelectors)
+ 		toDepth: 0.
- 			toDepth: 0.
  	^objectMemory followForwarded: selectorOop!

Item was removed:
- ----- Method: StackInterpreter>>handleForwardedSendFaultFor: (in category 'message sending') -----
- handleForwardedSendFaultFor: classTag
- 	"Handle a send fault that may be due to a send to a forwarded object.
- 	 Unforward the receiver on the stack and answer its actual class."
- 	| rcvr |
- 	<inline: false>
- 	self assert: (objectMemory isForwardedClassTag: classTag).
- 
- 	rcvr := self stackValue: argumentCount.
- 	"should *not* be a super send, so the receiver should be forwarded."
- 	self assert: (objectMemory isOopForwarded: rcvr).
- 	rcvr := objectMemory followForwarded: rcvr.
- 	self stackValue: argumentCount put: rcvr.
- 	self followForwardedFrameContents: framePointer
- 		stackPointer: stackPointer + (argumentCount + 1 * BytesPerWord). "don't repeat effort"
- 	(objectMemory isPointers: (self frameReceiver: framePointer)) ifTrue:
- 		[objectMemory
- 			followForwardedObjectFields: (self frameReceiver: framePointer)
- 			toDepth: 0].
- 	^objectMemory fetchClassTagOf: rcvr!

Item was added:
+ ----- Method: StackInterpreter>>handleForwardedSendFaultForTag: (in category 'message sending') -----
+ handleForwardedSendFaultForTag: classTag
+ 	"Handle a send fault that may be due to a send to a forwarded object.
+ 	 Unforward the receiver on the stack and answer its actual class."
+ 	<option: #SpurObjectMemory>
+ 	| rcvr |
+ 	<inline: false>
+ 	self assert: (objectMemory isForwardedClassTag: classTag).
+ 
+ 	rcvr := self stackValue: argumentCount.
+ 	"should *not* be a super send, so the receiver should be forwarded."
+ 	self assert: (objectMemory isOopForwarded: rcvr).
+ 	rcvr := objectMemory followForwarded: rcvr.
+ 	self stackValue: argumentCount put: rcvr.
+ 	self followForwardedFrameContents: framePointer
+ 		stackPointer: stackPointer + (argumentCount + 1 * BytesPerWord). "don't repeat effort"
+ 	(objectMemory isPointers: (self frameReceiver: framePointer)) ifTrue:
+ 		[objectMemory
+ 			followForwardedObjectFields: (self frameReceiver: framePointer)
+ 			toDepth: 0].
+ 	^objectMemory fetchClassTagOf: rcvr!

Item was changed:
  ----- Method: StackInterpreter>>internalFindNewMethod (in category 'message sending') -----
  internalFindNewMethod
  	"Find the compiled method to be run when the current messageSelector is sent to the class 'lkupClass', setting the values of 'newMethod' and 'primitiveIndex'."
  	| ok | 
  	<inline: true>
  	ok := self lookupInMethodCacheSel: messageSelector classTag: lkupClassTag.
  	ok ifFalse: "entry was not found in the cache; look it up the hard way"
  		[self externalizeIPandSP.
  		 ((objectMemory isOopForwarded: messageSelector)
  		  or: [objectMemory isForwardedClassTag: lkupClassTag]) ifTrue:
  			[(objectMemory isOopForwarded: messageSelector) ifTrue:
  				[messageSelector := self handleForwardedSelectorFaultFor: messageSelector].
  			 (objectMemory isForwardedClassTag: lkupClassTag) ifTrue:
+ 				[lkupClassTag := self handleForwardedSendFaultForTag: lkupClassTag].
- 				[lkupClassTag := self handleForwardedSendFaultFor: lkupClassTag].
  			ok := self lookupInMethodCacheSel: messageSelector classTag: lkupClassTag.
  			ok ifTrue:
  				[^nil]].
  		 lkupClass := objectMemory classForClassTag: lkupClassTag.
  		 self lookupMethodInClass: lkupClass.
  		 self internalizeIPandSP.
  		 self addNewMethodToCache: lkupClass]!

Item was changed:
  ----- Method: StackInterpreter>>postBecomeAction: (in category 'object memory support') -----
  postBecomeAction: theBecomeEffectsFlags
  	theBecomeEffectsFlags ~= 0 ifTrue:
  		[self followForwardingPointersInStackZone: theBecomeEffectsFlags.
+ 		 (theBecomeEffectsFlags anyMask: BecameCompiledMethodFlag) ifTrue:
+ 			[self followForwardedMethodsInMethodCache].
+ 		 self followForwardedMethods. "for CoInterpreter"
  		 self followForwardingPointersInScheduler]!

Item was changed:
  ----- Method: StackInterpreter>>printOopShortInner: (in category 'debug printing') -----
  printOopShortInner: oop
  	| classOop name nameLen |
  	<var: #name type: #'char *'>
  	<inline: true>
  	(objectMemory isImmediate: oop) ifTrue:
  		[(objectMemory isImmediateCharacter: oop) ifTrue:
  			[^self
  				printChar: $$;
  				printChar: (objectMemory characterValueOf: oop);
  				printChar: $(;
  				printHex: (objectMemory integerValueOf: oop);
  				printChar: $)].
  		^self
  			printNum: (objectMemory integerValueOf: oop);
  			printChar: $(;
  			printHex: (objectMemory integerValueOf: oop);
  			printChar: $)].
  	(objectMemory addressCouldBeObj: oop) ifFalse:
  		[^self print: ((oop bitAnd: objectMemory allocationUnit - 1) ~= 0
  						ifTrue: [' is misaligned']
  						ifFalse: [' is not on the heap'])].
+ 	(objectMemory isOopForwarded: oop) ifTrue:
+ 		[^self printHex: oop; print: ' is a forwarder to '; printHex: (objectMemory followForwarded: oop)].
  	(self isFloatObject: oop) ifTrue:
  		[^self printFloat: (self dbgFloatValueOf: oop)].
  	classOop := objectMemory fetchClassOfNonImm: oop.
  	(objectMemory addressCouldBeObj: classOop) ifFalse:
  		[^self print: 'a ??'].
  	(objectMemory numSlotsOf: classOop) = metaclassNumSlots ifTrue:
  		[^self printNameOfClass: oop count: 5].
  	oop = objectMemory nilObject ifTrue: [^self print: 'nil'].
  	oop = objectMemory trueObject ifTrue: [^self print: 'true'].
  	oop = objectMemory falseObject ifTrue: [^self print: 'false'].
  	nameLen := self lengthOfNameOfClass: classOop.
  	nameLen = 0 ifTrue: [^self print: 'a ??'].
  	name := self nameOfClass: classOop.
  	nameLen = 10 ifTrue:
  		[(self str: name n: 'ByteString' cmp: 10) not "strncmp is weird" ifTrue:
  			[^self printChar: $'; printStringOf: oop; printChar: $'].
  		 (self str: name n: 'ByteSymbol' cmp: 10) not "strncmp is weird" ifTrue:
  			[self printChar: $#; printStringOf: oop. ^self]].
  	(nameLen = 9 and: [(self str: name n: 'Character' cmp: 9) not]) ifTrue:
  		[^self printChar: $$; printChar: (objectMemory integerValueOf: (objectMemory fetchPointer: 0 ofObject: oop))].
  	self print: 'a(n) '.
  	self
  		cCode: [0 to: nameLen - 1 do: [:i| self printChar: (name at: i)]]
  		inSmalltalk:
  			[name isString
  				ifTrue: [self print: name]
  				ifFalse: [0 to: nameLen - 1 do: [:i| self printChar: (name at: i)]]].
  	"Try to spot association-like things; they're all subclasses of LookupKey"
  	((objectMemory instanceSizeOf: classOop) = (ValueIndex + 1)
  	 and: [(self superclassOf: classOop) = (self superclassOf: (objectMemory fetchClassOfNonImm: (objectMemory splObj: SchedulerAssociation)))
  	 and: [objectMemory isBytes: (objectMemory fetchPointer: KeyIndex ofObject: oop)]]) ifTrue:
  		[self space;
  			printOopShort: (objectMemory fetchPointer: KeyIndex ofObject: oop);
  			print: ' -> ';
  			printHex: (objectMemory fetchPointer: ValueIndex ofObject: oop)]!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genPushLiteralVariable: (in category 'bytecode generators') -----
  genPushLiteralVariable: literalIndex
  	<inline: false>
  	| association freeReg |
  	freeReg := self ssAllocatePreferredReg: ClassReg.
  	association := self getLiteral: literalIndex.
  	"N.B. Do _not_ use ReceiverResultReg to avoid overwriting receiver in assignment in frameless methods."
  	"So far descriptors are not rich enough to describe the entire dereference so generate the register
  	 load but don't push the result.  There is an order-of-evaluation issue if we defer the dereference."
  	self annotate: (self MoveCw: association R: TempReg) objRef: association.
- 	objectRepresentation genEnsureRegNotForwarded: TempReg scratchReg: freeReg.
  	objectRepresentation
+ 		genEnsureObjInRegRegNotForwarded: TempReg
+ 		scratchReg: freeReg.
+ 	objectRepresentation
  		genLoadSlot: ValueIndex
  		sourceReg: TempReg
  		destReg: freeReg.
  	self ssPushRegister: freeReg.
  	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genStorePop:LiteralVariable: (in category 'bytecode generators') -----
  genStorePop: popBoolean LiteralVariable: litVarIndex
  	<inline: false>
  	| topReg valueReg association constVal |
  	self flag: 'with better register allocation this wouldn''t need a frame.  e.g. use SendNumArgs instead of ReceiverResultReg'.
  	self assert: needsFrame.
  	optStatus isReceiverResultRegLive: false.
  	"N.B.  No need to check the stack for references because we generate code for
  	 literal variable loads that stores the result in a register, deferring only the register push."
  	association := self getLiteral: litVarIndex.
  	constVal := self ssTop maybeConstant.
  	"Avoid store check for immediate values"
  	(self ssTop type = SSConstant
  	 and: [(objectRepresentation shouldAnnotateObjectReference: constVal) not]) ifTrue:
  		[self ssAllocateRequiredReg: ReceiverResultReg.
  		 self annotate: (self MoveCw: association R: ReceiverResultReg) objRef: association.
+ 		 objectRepresentation
+ 			genEnsureObjInRegRegNotForwarded: ReceiverResultReg
+ 			scratchReg: TempReg.
- 		 objectRepresentation genEnsureRegNotForwarded: ReceiverResultReg scratchReg: TempReg.
  		 self ssStorePop: popBoolean toPreferredReg: TempReg.
  		 traceStores > 0 ifTrue:
  			[self CallRT: ceTraceStoreTrampoline].
  		 ^objectRepresentation
  			genStoreImmediateInSourceReg: TempReg
  			slotIndex: ValueIndex
  			destReg: ReceiverResultReg].
  	((topReg := self ssTop registerOrNil) isNil
  	 or: [topReg = ReceiverResultReg]) ifTrue:
  		[topReg := ClassReg].
  	self ssPop: 1.
  	self ssAllocateCallReg: topReg. "for the ceStoreCheck call in genStoreSourceReg:... below"
  	self ssPush: 1.
  	valueReg := self ssStorePop: popBoolean toPreferredReg: topReg.
  	valueReg = ReceiverResultReg ifTrue:
  		[self MoveR: valueReg R: topReg].
  	self ssAllocateCallReg: ReceiverResultReg.
  	self annotate: (self MoveCw: association R: ReceiverResultReg) objRef: association.
+ 	objectRepresentation genEnsureObjInRegRegNotForwarded: ReceiverResultReg scratchReg: TempReg.
- 	objectRepresentation genEnsureRegNotForwarded: ReceiverResultReg scratchReg: TempReg.
  	traceStores > 0 ifTrue:
  		[self MoveR: topReg R: TempReg.
  		 self CallRT: ceTraceStoreTrampoline].
  	^objectRepresentation
  		genStoreSourceReg: topReg
  		slotIndex: ValueIndex
  		destReg: ReceiverResultReg
  		scratchReg: TempReg!



More information about the Vm-dev mailing list