VM Maker: VMMaker.oscog-eem.547.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: VMMaker.oscog-eem.547.mcz

commits-2
 
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!