The Trunk: Kernel-eem.1074.mcz

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

The Trunk: Kernel-eem.1074.mcz

commits-2
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1074.mcz

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

Name: Kernel-eem.1074
Author: eem
Time: 29 March 2017, 2:29:14.46683 pm
UUID: d3593a9c-0922-461c-8ce6-bf562c397ef5
Ancestors: Kernel-ul.1073

Compile all methods inherited from ContextPart by MethodContext in MethodContext, prior to eliminating ContextPart.

Eliminate some obsolete methods:
        hideFromDebugger

Add a convenience for scanForInstructionSequence: to CompiledMethod.

Update the comments in howToModifyPrimitives, & Object>>instVarAt:[put:] to reflect reality.

=============== Diff against Kernel-ul.1073 ===============

Item was removed:
- ----- Method: BlockContext>>hideFromDebugger (in category 'private') -----
- hideFromDebugger
-
- ^home ~~ nil and: [home hideFromDebugger]!

Item was added:
+ ----- Method: CompiledMethod>>scanForInstructionSequence: (in category 'scanning') -----
+ scanForInstructionSequence: naryBlock
+ "naryBlock is a block taking one or more arguments.
+ Evaluate it for each sequence of instructions of length
+ n in the receiver until naryBlock evaluates to true.
+ Answer if naryBlock evaluated to true."
+ ^(InstructionStream on: self) scanForInstructionSequence: naryBlock
+ "
+ self systemNavigation browseAllSelect: [:m | m scanForInstructionSequence: [:msg| msg selector = #send:super:numArgs: and: [msg arguments second]]] localTo: thisContext class
+ "!

Item was removed:
- ----- Method: ContextPart>>cachesStack (in category 'private-debugger') -----
- cachesStack
-
- ^false!

Item was added:
+ ----- Method: MethodContext class>>basicNew: (in category 'instance creation') -----
+ basicNew: size
+ ^ (size = CompiledMethod smallFrameSize or: [ size = CompiledMethod fullFrameSize ])
+ ifTrue: [ super basicNew: size ]
+ ifFalse: [ self error: 'Contexts must be ' , CompiledMethod smallFrameSize , ' or ' , CompiledMethod fullFrameSize , ' bytes.' ]!

Item was added:
+ ----- Method: MethodContext class>>carefullyPrint:on: (in category 'private') -----
+ carefullyPrint: anObject on: aStream
+ aStream nextPutAll: ([anObject printString]
+ on: Error
+ do: ['unprintable ' , anObject class name])!

Item was added:
+ ----- Method: MethodContext class>>contextEnsure: (in category 'special context creation') -----
+ contextEnsure: block
+ "Create an #ensure: context that is ready to return from executing its receiver"
+
+ | ctxt chain |
+ ctxt := thisContext.
+ [chain := thisContext sender cut: ctxt. ctxt jump] ensure: block.
+ "jump above will resume here without unwinding chain"
+ ^ chain!

Item was added:
+ ----- Method: MethodContext class>>contextOn:do: (in category 'special context creation') -----
+ contextOn: exceptionClass do: block
+ "Create an #on:do: context that is ready to return from executing its receiver"
+
+ | ctxt chain |
+ ctxt := thisContext.
+ [chain := thisContext sender cut: ctxt. ctxt jump] on: exceptionClass do: block.
+ "jump above will resume here without unwinding chain"
+ ^ chain!

Item was added:
+ ----- Method: MethodContext class>>initialize (in category 'class initialization') -----
+ initialize
+ ValueIndex := 2.
+ self assert: (Association instVarNameForIndex:ValueIndex) = 'value'.
+ PrimitiveFailToken class ~~ Object ifTrue:
+ [PrimitiveFailToken := Object new]!

Item was added:
+ ----- Method: MethodContext class>>initializedInstance (in category 'instance creation') -----
+ initializedInstance
+ ^ nil!

Item was added:
+ ----- Method: MethodContext class>>isContextClass (in category 'private') -----
+ isContextClass
+ ^true!

Item was added:
+ ----- Method: MethodContext class>>maxLengthForASingleDebugLogReport (in category 'preferences') -----
+ maxLengthForASingleDebugLogReport
+ <preference: 'Max. Debug Report Length'
+ category: 'debug'
+ description: 'The description of an Exception stack will be truncated so as to not exceed this value'
+ type: #Number>
+ ^MaxLengthForASingleDebugLogReport ifNil: [40000]!

Item was added:
+ ----- Method: MethodContext class>>maxLengthForASingleDebugLogReport: (in category 'preferences') -----
+ maxLengthForASingleDebugLogReport: anInteger
+ MaxLengthForASingleDebugLogReport := anInteger!

Item was added:
+ ----- Method: MethodContext class>>maxStackDepthForASingleDebugLogReport (in category 'preferences') -----
+ maxStackDepthForASingleDebugLogReport
+ <preference: 'Max. Debug Report Stack Depth'
+ category: 'debug'
+ description: 'In an exception stack, any sender deeper than this value will not be logged.'
+ type: #Number>
+ ^MaxStackDepthForASingleDebugLogReport ifNil: [60]!

Item was added:
+ ----- Method: MethodContext class>>maxStackDepthForASingleDebugLogReport: (in category 'preferences') -----
+ maxStackDepthForASingleDebugLogReport: anInteger
+ MaxStackDepthForASingleDebugLogReport := anInteger!

Item was removed:
- ----- Method: MethodContext class>>myEnvFieldIndex (in category 'closure support') -----
- myEnvFieldIndex
-
- ^ self allInstVarNames indexOf: 'receiverMap'!

Item was added:
+ ----- Method: MethodContext class>>new (in category 'instance creation') -----
+ new
+
+ self error: 'Contexts must only be created with newForMethod:'!

Item was added:
+ ----- Method: MethodContext class>>new: (in category 'instance creation') -----
+ new: size
+
+ self error: 'Contexts must only be created with newForMethod:'!

Item was added:
+ ----- Method: MethodContext class>>newForMethod: (in category 'instance creation') -----
+ newForMethod: aMethod
+ "This is the only method for creating new contexts, other than primitive cloning.
+ Any other attempts, such as inherited methods like shallowCopy, should be
+ avoided or must at least be rewritten to determine the proper size from the
+ method being activated.  This is because asking a context its size (even basicSize!!)
+ will not return the real object size but only the number of fields currently
+ accessible, as determined by stackp."
+
+ ^ super basicNew: aMethod frameSize!

Item was added:
+ ----- Method: MethodContext class>>primitiveFailToken (in category 'simulation') -----
+ primitiveFailToken
+
+ ^ PrimitiveFailToken!

Item was added:
+ ----- Method: MethodContext class>>primitiveFailTokenFor: (in category 'simulation') -----
+ primitiveFailTokenFor: errorCode
+
+ ^{PrimitiveFailToken. errorCode}!

Item was added:
+ ----- Method: MethodContext class>>runSimulated: (in category 'simulation') -----
+ runSimulated: aBlock
+ "Simulate the execution of the argument, current. Answer the result it
+ returns."
+
+ ^ thisContext sender
+ runSimulated: aBlock
+ contextAtEachStep: [:ignored]
+
+ "Context runSimulated: [Pen new defaultNib: 5; go: 100]"!

Item was added:
+ ----- Method: MethodContext class>>tallyInstructions: (in category 'examples') -----
+ tallyInstructions: aBlock
+ "This method uses the simulator to count the number of occurrences of
+ each of the Smalltalk instructions executed during evaluation of aBlock.
+ Results appear in order of the byteCode set."
+ | tallies |
+ tallies := Bag new.
+ thisContext sender
+ runSimulated: aBlock
+ contextAtEachStep:
+ [:current | tallies add: current nextByte].
+ ^tallies sortedElements
+
+ "Context tallyInstructions: [3.14159 printString]"!

Item was added:
+ ----- Method: MethodContext class>>tallyMethods: (in category 'examples') -----
+ tallyMethods: aBlock
+ "This method uses the simulator to count the number of calls on each method
+ invoked in evaluating aBlock. Results are given in order of decreasing counts."
+ | prev tallies |
+ tallies := Bag new.
+ prev := aBlock.
+ thisContext sender
+ runSimulated: aBlock
+ contextAtEachStep:
+ [:current |
+ current == prev ifFalse: "call or return"
+ [prev sender == nil ifFalse: "call only"
+ [tallies add: current printString].
+ prev := current]].
+ ^tallies sortedCounts
+
+ "Context tallyMethods: [3.14159 printString]"!

Item was added:
+ ----- Method: MethodContext class>>theReturnMethod (in category 'special context creation') -----
+ theReturnMethod
+
+ | meth |
+ meth := self lookupSelector: #return:.
+ meth primitive = 0 ifFalse: [^ self error: 'expected #return: to not be a primitive'].
+ ^ meth!

Item was added:
+ ----- Method: MethodContext class>>trace: (in category 'examples') -----
+ trace: aBlock "Context trace: [3 factorial]"
+ "This method uses the simulator to print calls and returned values in the Transcript."
+
+ Transcript clear.
+ ^ self trace: aBlock on: Transcript!

Item was added:
+ ----- Method: MethodContext class>>trace:on: (in category 'examples') -----
+ trace: aBlock on: aStream "Context trace: [3 factorial]"
+ "This method uses the simulator to print calls to a file."
+ | prev |
+ prev := aBlock.
+ ^ thisContext sender
+ runSimulated: aBlock
+ contextAtEachStep:
+ [:current |
+ Sensor anyButtonPressed ifTrue: [^ nil].
+ current == prev
+ ifFalse:
+ [prev sender ifNil:
+ [aStream space; nextPut: $^.
+ self carefullyPrint: current top on: aStream].
+ aStream cr.
+ (current depthBelow: aBlock) timesRepeat: [aStream space].
+ self carefullyPrint: current receiver on: aStream.
+ aStream space; nextPutAll: current selector; flush.
+ prev := current]]!

Item was added:
+ ----- Method: MethodContext class>>trace:onFileNamed: (in category 'examples') -----
+ trace: aBlock onFileNamed: fileName
+ "Context trace: [3 factorial] onFileNamed: 'trace'"
+ "This method uses the simulator to print calls to a file."
+
+ ^FileStream fileNamed: fileName do: [ :file |
+ self trace: aBlock on: file ]!

Item was added:
+ ----- Method: MethodContext>>activateMethod:withArgs:receiver:class: (in category 'controlling') -----
+ activateMethod: newMethod withArgs: args receiver: rcvr class: class
+ "Answer a ContextPart initialized with the arguments."
+
+ ^MethodContext
+ sender: self
+ receiver: rcvr
+ method: newMethod
+ arguments: args!

Item was added:
+ ----- Method: MethodContext>>activateReturn:value: (in category 'private') -----
+ activateReturn: aContext value: value
+ "Activate 'aContext return: value' in place of self, so execution will return to aContext's sender"
+
+ ^MethodContext
+ sender: self
+ receiver: aContext
+ method: MethodContext theReturnMethod
+ arguments: {value}!

Item was added:
+ ----- Method: MethodContext>>arguments (in category 'accessing') -----
+ arguments
+
+ ^ Array new: self numArgs streamContents: [:args |
+   1 to: self numArgs do: [: i |
+ args nextPut: (self tempAt: i)]]!

Item was added:
+ ----- Method: MethodContext>>asMessage (in category 'converting') -----
+ asMessage
+ | selector args |
+ selector := sender method selector.
+ args := Array new: selector numArgs.
+ 1 to: selector numArgs do: [ :i | args at: i put: (sender tempAt: i)].
+ ^ Message selector: selector arguments: args.!

Item was added:
+ ----- Method: MethodContext>>at: (in category 'accessing') -----
+ at: index
+ "Primitive. Assumes receiver is indexable. Answer the value of an
+ indexable element in the receiver. Fail if the argument index is not an
+ Integer or is out of bounds. Essential. See Object documentation
+ whatIsAPrimitive.  Override the default primitive to give latitude to
+ the VM in context management."
+
+ <primitive: 210>
+ index isInteger ifTrue:
+ [self errorSubscriptBounds: index].
+ index isNumber
+ ifTrue: [^self at: index asInteger]
+ ifFalse: [self errorNonIntegerIndex]!

Item was added:
+ ----- Method: MethodContext>>at:put: (in category 'accessing') -----
+ at: index put: value
+ "Primitive. Assumes receiver is indexable. Answer the value of an
+ indexable element in the receiver. Fail if the argument index is not
+ an Integer or is out of bounds. Essential. See Object documentation
+ whatIsAPrimitive.  Override the default primitive to give latitude to
+ the VM in context management."
+
+ <primitive: 211>
+ index isInteger ifTrue:
+ [self errorSubscriptBounds: index].
+ index isNumber
+ ifTrue: [^self at: index asInteger put: value]
+ ifFalse: [self errorNonIntegerIndex]!

Item was added:
+ ----- Method: MethodContext>>basicAt: (in category 'accessing') -----
+ basicAt: index
+ "Primitive. Assumes receiver is indexable. Answer the value of an
+ indexable element in the receiver. Fail if the argument index is not an
+ Integer or is out of bounds. Essential. See Object documentation
+ whatIsAPrimitive.  Override the default primitive to give latitude to
+ the VM in context management."
+
+ <primitive: 210>
+ index isInteger ifTrue:
+ [self errorSubscriptBounds: index].
+ index isNumber
+ ifTrue: [^self at: index asInteger]
+ ifFalse: [self errorNonIntegerIndex]!

Item was added:
+ ----- Method: MethodContext>>basicAt:put: (in category 'accessing') -----
+ basicAt: index put: value
+ "Primitive. Assumes receiver is indexable. Answer the value of an
+ indexable element in the receiver. Fail if the argument index is not
+ an Integer or is out of bounds. Essential. See Object documentation
+ whatIsAPrimitive.  Override the default primitive to give latitude to
+ the VM in context management."
+
+ <primitive: 211>
+ index isInteger ifTrue:
+ [self errorSubscriptBounds: index].
+ index isNumber
+ ifTrue: [^self at: index asInteger put: value]
+ ifFalse: [self errorNonIntegerIndex]!

Item was added:
+ ----- Method: MethodContext>>basicSize (in category 'accessing') -----
+ basicSize
+ "Primitive. Answer the number of indexable variables in the receiver.
+ This value is the same as the largest legal subscript. Essential. Do not
+ override in any subclass. See Object documentation whatIsAPrimitive.  Override the default primitive to give latitude to
+ the VM in context management."
+
+ <primitive: 212>
+ "The number of indexable fields of fixed-length objects is 0"
+ ^self primitiveFailed!

Item was added:
+ ----- Method: MethodContext>>blockCopy: (in category 'controlling') -----
+ blockCopy: numArgs
+ "Primitive. Distinguish a block of code from its enclosing method by
+ creating a new BlockContext for that block. The compiler inserts into all
+ methods that contain blocks the bytecodes to send the message
+ blockCopy:. Do not use blockCopy: in code that you write!! Only the
+ compiler can decide to send the message blockCopy:. Fail if numArgs is
+ not a SmallInteger. Optional. No Lookup. See Object documentation
+ whatIsAPrimitive."
+
+ <primitive: 80>
+ ^ (BlockContext newForMethod: self method)
+ home: self home
+ startpc: pc + 2
+ nargs: numArgs!

Item was added:
+ ----- Method: MethodContext>>bottomContext (in category 'query') -----
+ bottomContext
+ "Return the last context (the first context invoked) in my sender chain"
+
+ ^ self findContextSuchThat: [:c | c sender isNil]!

Item was removed:
- ----- Method: MethodContext>>cachesStack (in category 'private-debugger') -----
- cachesStack
-
- ^ false
- "^self selector == #valueUninterruptably
- and: [self receiver class == BlockContext]"!

Item was added:
+ ----- Method: MethodContext>>canHandleSignal: (in category 'private-exceptions') -----
+ canHandleSignal: exception
+ "Sent to handler (on:do:) contexts only.  If my exception class (first arg) handles exception then return true, otherwise forward this message to the next handler context.  If none left, return false (see nil>>canHandleSignal:)"
+
+ ^ (((self tempAt: 1) handles: exception) and: [self tempAt: 3])
+ or: [self nextHandlerContext canHandleSignal: exception].
+ !

Item was added:
+ ----- Method: MethodContext>>cannotReturn:to: (in category 'private') -----
+ cannotReturn: result to: homeContext
+ "The receiver tried to return result to homeContext that no longer exists."
+
+ ^ BlockCannotReturn new
+ result: result;
+ deadHome: homeContext;
+ signal!

Item was added:
+ ----- Method: MethodContext>>client (in category 'accessing') -----
+ client
+ "Answer the client, that is, the object that sent the message that created this context."
+
+ ^sender receiver!

Item was added:
+ ----- Method: MethodContext>>closureCopy:copiedValues: (in category 'controlling') -----
+ closureCopy: numArgs copiedValues: anArray
+ "Distinguish a block of code from its enclosing method by
+ creating a BlockClosure for that block. The compiler inserts into all
+ methods that contain blocks the bytecodes to send the message
+ closureCopy:copiedValues:. Do not use closureCopy:copiedValues: in code that you write!! Only the
+ compiler can decide to send the message closureCopy:copiedValues:. Fail if numArgs is
+ not a SmallInteger. Optional. No Lookup. See Object documentation
+ whatIsAPrimitive."
+
+ <primitive: 200>
+ ^BlockClosure outerContext: self startpc: pc + 2 numArgs: numArgs copiedValues: anArray!

Item was added:
+ ----- Method: MethodContext>>completeCallee: (in category 'system simulation') -----
+ completeCallee: aContext
+ "Simulate the execution of bytecodes until a return to the receiver."
+ | ctxt current ctxt1 |
+ ctxt := aContext.
+ [ctxt == current or: [ctxt hasSender: self]]
+ whileTrue:
+ [current := ctxt.
+ ctxt1 := ctxt quickStep.
+ ctxt1 ifNil: [self halt].
+ ctxt := ctxt1].
+ ^self stepToSendOrReturn!

Item was changed:
  ----- Method: MethodContext>>contextForLocalVariables (in category 'accessing') -----
  contextForLocalVariables
  "Answer the context in which local variables (temporaries) are stored."
 
+ self subclassResponsibility!
- ^self!

Item was added:
+ ----- Method: MethodContext>>contextStack (in category 'debugger access') -----
+ contextStack
+ "Answer an Array of the contexts on the receiver's sender chain."
+
+ ^self stackOfSize: 100000!

Item was added:
+ ----- Method: MethodContext>>copyStack (in category 'query') -----
+ copyStack
+
+ ^ self copyTo: nil!

Item was added:
+ ----- Method: MethodContext>>copyTo: (in category 'query') -----
+ copyTo: aContext
+ "Copy self and my sender chain down to, but not including, aContext.  End of copied chain will have nil sender."
+
+ | copy |
+ self == aContext ifTrue: [ ^nil ].
+ copy := self copy.
+ sender ifNotNil: [ copy privSender: (sender copyTo: aContext) ].
+ ^copy!

Item was added:
+ ----- Method: MethodContext>>copyTo:bottomContextDo: (in category 'query') -----
+ copyTo: aContext bottomContextDo: aBlock
+ "Copy self and my sender chain down to, but not including, aContext.  End of copied chain will have nil sender. Evaluate aBlock with the copy of bottom context when it still points to the original sender."
+
+ | copy |
+ self == aContext ifTrue: [ ^nil ].
+ copy := self copy.
+ sender
+ ifNil: [ aBlock value: copy ]
+ ifNotNil: [
+ sender == aContext ifTrue: [ aBlock value: copy ].
+ copy privSender: (sender copyTo: aContext bottomContextDo: aBlock) ].
+ ^copy!

Item was added:
+ ----- Method: MethodContext>>cut: (in category 'private') -----
+ cut: aContext
+ "Cut aContext and its senders from my sender chain"
+
+ | ctxt callee |
+ ctxt := self.
+ [ctxt == aContext] whileFalse: [
+ callee := ctxt.
+ ctxt := ctxt sender.
+ ctxt ifNil: [aContext ifNotNil: [self error: 'aContext not a sender']].
+ ].
+ callee privSender: nil.
+ !

Item was added:
+ ----- Method: MethodContext>>depthBelow: (in category 'debugger access') -----
+ depthBelow: aContext
+ "Answer how many calls there are between this and aContext."
+
+ | this depth |
+ this := self.
+ depth := 0.
+ [this == aContext or: [this == nil]]
+ whileFalse:
+ [this := this sender.
+ depth := depth + 1].
+ ^depth!

Item was added:
+ ----- Method: MethodContext>>doDup (in category 'instruction decoding') -----
+ doDup
+ "Simulate the action of a 'duplicate top of stack' bytecode."
+
+ self push: self top!

Item was added:
+ ----- Method: MethodContext>>doPop (in category 'instruction decoding') -----
+ doPop
+ "Simulate the action of a 'remove top of stack' bytecode."
+
+ self pop!

Item was added:
+ ----- Method: MethodContext>>doPrimitive:method:receiver:args: (in category 'private') -----
+ doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments
+ "Simulate a primitive method whose index is primitiveIndex.  The simulated receiver and
+ arguments are given as arguments to this message. If successful, push result and return
+ resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes
+ execution needs to be intercepted and simulated to avoid execution running away."
+
+ | value |
+ "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents
+ the debugger from entering various run-away activities such as spawning a new
+ process, etc.  Injudicious use results in the debugger not being able to debug
+ interesting code, such as the debugger itself.  hence use primitive 19 with care :-)"
+ "SystemNavigation new browseAllSelect: [:m| m primitive = 19]"
+ primitiveIndex = 19 ifTrue:
+ [ToolSet
+ debugContext: self
+ label:'Code simulation error'
+ contents: nil].
+
+ ((primitiveIndex between: 201 and: 222)
+ and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue:
+ [((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]"
+  or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]"
+ [^receiver simulateValueWithArguments: arguments caller: self].
+ primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:"
+ [^receiver simulateValueWithArguments: arguments first caller: self]].
+
+ primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]"
+ [^self send: arguments first to: receiver with: arguments allButFirst super: false].
+ primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:"
+ [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)].
+ primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:"
+ [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)].
+
+ "Mutex>>primitiveEnterCriticalSection
+ Mutex>>primitiveTestAndSetOwnershipOfCriticalSection"
+ (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue:
+ [| effective |
+ effective := Processor activeProcess effectiveProcess.
+ "active == effective"
+ value := primitiveIndex = 186
+ ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective]
+ ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective].
+ ^(self isPrimFailToken: value)
+ ifTrue: [value]
+ ifFalse: [self push: value]].
+
+ primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:"
+ [((self objectClass: (arguments at: 1)) == Array
+  and: [(self objectClass: (arguments at: 2)) includesBehavior: CompiledMethod]) ifFalse:
+ [^ContextPart primitiveFailTokenFor: #'bad argument'].
+ (arguments at: 2) numArgs = (arguments at: 1) size ifFalse:
+ [^ContextPart primitiveFailTokenFor: #'bad number of arguments'].
+ (arguments at: 2) primitive > 0 ifTrue:
+ [(arguments at: 2) isQuick ifTrue:
+ [^self push: (receiver withArgs: (arguments at: 1) executeMethod: (arguments at: 2))].
+ ^self doPrimitive: (arguments at: 2) primitive method: (arguments at: 2) receiver: receiver args: (arguments at: 1)].
+ ^MethodContext
+ sender: self
+ receiver: receiver
+ method: (arguments at: 2)
+ arguments: (arguments at: 1)].
+
+ "Closure primitives"
+ (primitiveIndex = 200 and: [self == receiver]) ifTrue:
+ "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right"
+ [^self push: (BlockClosure
+ outerContext: receiver
+ startpc: pc + 2
+ numArgs: arguments first
+ copiedValues: arguments last)].
+
+ primitiveIndex = 118 ifTrue: "[receiver:]tryPrimitive:withArgs:; avoid recursing in the VM"
+ [(arguments size = 3
+  and: [(self objectClass: arguments second) == SmallInteger
+  and: [(self objectClass: arguments last) == Array]]) ifTrue:
+ [^self doPrimitive: arguments second method: meth receiver: arguments first args: arguments last].
+ (arguments size = 2
+ and: [(self objectClass: arguments first) == SmallInteger
+ and: [(self objectClass: arguments last) == Array]]) ifFalse:
+ [^ContextPart primitiveFailTokenFor: nil].
+ ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last].
+
+ value := primitiveIndex = 120 "FFI method"
+ ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments]
+ ifFalse:
+ [primitiveIndex = 117 "named primitives"
+ ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments]
+ ifFalse:
+ ["should use self receiver: receiver tryPrimitive: primitiveIndex withArgs: arguments but this is only in later VMs"
+ receiver tryPrimitive: primitiveIndex withArgs: arguments]].
+
+ ^(self isPrimFailToken: value)
+ ifTrue: [value]
+ ifFalse: [self push: value]!

Item was added:
+ ----- Method: MethodContext>>exceptionMessage (in category 'accessing') -----
+ exceptionMessage
+ ^ self selector caseOf: {
+ [#doesNotUnderstand:] -> [self tempAt: 1].
+ [#notYetImplemented] -> [self asMessage].
+ [#shouldBeImplemented] -> [self asMessage].
+ [#subclassResponsibility] -> [self asMessage]}
+ otherwise: [self error: 'This context is not the result of a message exception.'].!

Item was added:
+ ----- Method: MethodContext>>findContextSuchThat: (in category 'query') -----
+ findContextSuchThat: testBlock
+ "Search self and my sender chain for first one that satisfies testBlock.  Return nil if none satisfy"
+
+ | ctxt |
+ ctxt := self.
+ [ctxt isNil] whileFalse: [
+ (testBlock value: ctxt) ifTrue: [^ ctxt].
+ ctxt := ctxt sender.
+ ].
+ ^ nil!

Item was added:
+ ----- Method: MethodContext>>findNextHandlerContextStarting (in category 'private-exceptions') -----
+ findNextHandlerContextStarting
+ "Return the next handler marked context, returning nil if there is none.  Search starts with self and proceeds up to nil."
+
+ | ctx |
+ <primitive: 197>
+ ctx := self.
+ [ctx isHandlerContext ifTrue:[^ctx].
+ (ctx := ctx sender) == nil ] whileFalse.
+ ^nil!

Item was added:
+ ----- Method: MethodContext>>findNextUnwindContextUpTo: (in category 'private-exceptions') -----
+ findNextUnwindContextUpTo: aContext
+ "Return the next unwind marked above the receiver, returning nil if there is none.  Search proceeds up to but not including aContext."
+
+ | ctx |
+ <primitive: 195>
+ ctx := self.
+ [(ctx := ctx sender) == nil or: [ctx == aContext]] whileFalse:
+ [ ctx isUnwindContext ifTrue: [^ctx]].
+ ^nil!

Item was added:
+ ----- Method: MethodContext>>findSecondToOldestSimilarSender (in category 'query') -----
+ findSecondToOldestSimilarSender
+ "Search the stack for the second-to-oldest occurance of self's method.  Very useful for an infinite recursion.  Gets back to the second call so you can see one complete recursion cycle, and how it was called at the beginning."
+
+ | sec ctxt bot |
+ sec := self.
+ ctxt := self.
+ [ bot := ctxt findSimilarSender.
+ bot isNil
+ ] whileFalse: [
+ sec := ctxt.
+ ctxt := bot.
+ ].
+ ^ sec
+ !

Item was added:
+ ----- Method: MethodContext>>findSimilarSender (in category 'query') -----
+ findSimilarSender
+ "Return the closest sender with the same method, return nil if none found"
+
+ | meth |
+ meth := self method.
+ ^ self sender findContextSuchThat: [:c | c method == meth]!

Item was added:
+ ----- Method: MethodContext>>handleSignal: (in category 'private-exceptions') -----
+ handleSignal: exception
+ "Sent to handler (on:do:) contexts only.  If my exception class (first arg) handles exception
+ and the handler is active then execute my handle block (second arg), otherwise forward
+ this message to the next handler context.  If none left, execute exception's defaultAction
+ (see nil>>handleSignal:)."
+
+ | handlerActive val |
+ "If the context has been returned from the handlerActive temp var may not be accessible."
+ handlerActive := stackp >= 3 and: [(self tempAt: 3) == true].
+ (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse:
+ [^self nextHandlerContext handleSignal: exception].
+
+ exception privHandlerContext: self contextTag.
+ self tempAt: 3 put: false.  "disable self while executing handle block"
+ val := [(self tempAt: 2) cull: exception]
+ ensure: [self tempAt: 3 put: true].
+ self return: val  "return from self if not otherwise directed in handle block"
+ !

Item was added:
+ ----- Method: MethodContext>>hasContext: (in category 'query') -----
+ hasContext: aContext
+ "Answer whether aContext is me or one of my senders"
+
+ ^ (self findContextSuchThat: [:c | c == aContext]) notNil!

Item was added:
+ ----- Method: MethodContext>>hasSender: (in category 'controlling') -----
+ hasSender: context
+ "Answer whether the receiver is strictly above context on the stack."
+
+ | s |
+ self == context ifTrue: [^false].
+ s := sender.
+ [s == nil]
+ whileFalse:
+ [s == context ifTrue: [^true].
+ s := s sender].
+ ^false!

Item was removed:
- ----- Method: MethodContext>>hideFromDebugger (in category 'private-debugger') -----
- hideFromDebugger
-
- | sndr sndrHome |
- ^self cachesStack
- or: [(sndr := self sender) ~~ nil
- and: [(sndrHome := sndr home) ~~ nil
- and: [sndrHome cachesStack]]]!

Item was added:
+ ----- Method: MethodContext>>insertSender: (in category 'private') -----
+ insertSender: aContext
+ "Insert aContext and its sender chain between me and my sender.  Return new callee of my original sender."
+
+ | ctxt |
+ ctxt := aContext bottomContext.
+ ctxt privSender: self sender.
+ self privSender: aContext.
+ ^ ctxt!

Item was added:
+ ----- Method: MethodContext>>isBottomContext (in category 'query') -----
+ isBottomContext
+ "Answer if this is the last context (the first context invoked) in my sender chain"
+
+ ^sender isNil!

Item was added:
+ ----- Method: MethodContext>>isContext (in category 'query') -----
+ isContext
+ ^true!

Item was added:
+ ----- Method: MethodContext>>isDead (in category 'query') -----
+ isDead
+ "Has self finished"
+
+ ^ pc isNil!

Item was added:
+ ----- Method: MethodContext>>isPrimFailToken: (in category 'private') -----
+ isPrimFailToken: anObject
+ ^(self objectClass: anObject) == Array
+  and: [anObject size = 2
+  and: [anObject first == PrimitiveFailToken]]!

Item was added:
+ ----- Method: MethodContext>>jump (in category 'controlling') -----
+ jump
+ "Abandon thisContext and resume self instead (using the same current process).  You may want to save thisContext's sender before calling this so you can jump back to it.
+ Self MUST BE a top context (ie. a suspended context or a abandoned context that was jumped out of).  A top context already has its return value on its stack (see Interpreter>>primitiveSuspend and other suspending primitives).
+ thisContext's sender is converted to a top context (by pushing a nil return value on its stack) so it can be jump back to."
+
+ | top |
+ "Make abandoned context a top context (has return value (nil)) so it can be jumped back to"
+ thisContext sender push: nil.
+
+ "Pop self return value then return it to self (since we jump to self by returning to it)"
+ stackp = 0 ifTrue: [self stepToSendOrReturn].
+ stackp = 0 ifTrue: [self push: nil].  "must be quick return self/constant"
+ top := self pop.
+ thisContext privSender: self.
+ ^ top!

Item was added:
+ ----- Method: MethodContext>>jump: (in category 'instruction decoding') -----
+ jump: distance
+ "Simulate the action of a 'unconditional jump' bytecode whose offset is
+ the argument, distance."
+
+ pc := pc + distance!

Item was added:
+ ----- Method: MethodContext>>jump:if: (in category 'instruction decoding') -----
+ jump: distance if: condition
+ "Simulate the action of a 'conditional jump' bytecode whose offset is the
+ argument, distance, and whose condition is the argument, condition."
+
+ | bool |
+ bool := self pop.
+ (bool == true or: [bool == false]) ifFalse: [
+ ^self
+ send: #mustBeBooleanIn:
+ to: bool
+ with: {self}
+ super: false].
+ (bool eqv: condition) ifTrue: [self jump: distance]!

Item was added:
+ ----- Method: MethodContext>>longStack (in category 'debugger access') -----
+ longStack
+ "Answer a String showing the top 100 contexts on my sender chain."
+
+ ^ String streamContents:
+ [:strm |
+ (self stackOfSize: 100)
+ do: [:item | strm print: item; cr]]!

Item was added:
+ ----- Method: MethodContext>>methodClass (in category 'debugger access') -----
+ methodClass
+ "Answer the class in which the receiver's method was found."
+
+ ^self method methodClass ifNil: [self objectClass: self receiver].!

Item was added:
+ ----- Method: MethodContext>>methodNode (in category 'accessing') -----
+ methodNode
+ ^ self method methodNode.!

Item was added:
+ ----- Method: MethodContext>>methodNodeFormattedAndDecorated: (in category 'accessing') -----
+ methodNodeFormattedAndDecorated: decorate
+ "Answer a method node made from pretty-printed (and colorized, if decorate is true)
+ source text."
+
+ ^ self method methodNodeFormattedAndDecorated: decorate.!

Item was added:
+ ----- Method: MethodContext>>methodReturnConstant: (in category 'instruction decoding') -----
+ methodReturnConstant: value
+ "Simulate the action of a 'return constant' bytecode whose value is the
+ argument, value. This corresponds to a source expression like '^0'."
+
+ ^self return: value from: self methodReturnContext!

Item was added:
+ ----- Method: MethodContext>>methodReturnReceiver (in category 'instruction decoding') -----
+ methodReturnReceiver
+ "Simulate the action of a 'return receiver' bytecode. This corresponds to
+ the source expression '^self'."
+
+ ^self return: self receiver from: self methodReturnContext!

Item was added:
+ ----- Method: MethodContext>>methodReturnTop (in category 'instruction decoding') -----
+ methodReturnTop
+ "Simulate the action of a 'return top of stack' bytecode. This corresponds
+ to source expressions like '^something'."
+
+ ^self return: self pop from: self methodReturnContext!

Item was added:
+ ----- Method: MethodContext>>namedTempAt: (in category 'debugger access') -----
+ namedTempAt: index
+ "Answer the value of the temp at index in the receiver's sequence of tempNames."
+ ^self debuggerMap namedTempAt: index in: self!

Item was added:
+ ----- Method: MethodContext>>namedTempAt:put: (in category 'debugger access') -----
+ namedTempAt: index put: aValue
+ "Set the value of the temp at index in the receiver's sequence of tempNames.
+ (Note that if the value is a copied value it is also set out along the lexical chain,
+  but alas not in along the lexical chain.)."
+ ^self debuggerMap namedTempAt: index put: aValue in: self!

Item was added:
+ ----- Method: MethodContext>>nextHandlerContext (in category 'private-exceptions') -----
+ nextHandlerContext
+
+ ^ self sender findNextHandlerContextStarting!

Item was added:
+ ----- Method: MethodContext>>object:basicAt: (in category 'mirror primitives') -----
+ object: anObject basicAt: index
+ "Answer the value of an indexable element in the argument anObject without sending
+ it a message. Fail if the argument index is not an Integer or is out of bounds, or if
+ anObject is not indexable. This mimics the action of the VM when it indexes an object.
+ Used to simulate the execution machinery by, for example, the debugger.
+ Primitive.  See Object documentation whatIsAPrimitive."
+
+ <primitive: 60>
+ index isInteger ifTrue: [self errorSubscriptBounds: index].
+ index isNumber
+ ifTrue: [^self object: anObject basicAt: index asInteger]
+ ifFalse: [self errorNonIntegerIndex]!

Item was added:
+ ----- Method: MethodContext>>object:basicAt:put: (in category 'mirror primitives') -----
+ object: anObject basicAt: index put: value
+ "Store the last argument
+ value in the indexable element of the argument anObject indicated by index without sending
+ anObject a message. Fail if the argument index is not an Integer or is out of bounds, or if
+ anObject is not indexable, or if value is an inappropriate value for anObject's indexable slots.
+ This mimics the action of the VM when it indexes an object.
+ Used to simulate the execution machinery by, for example, the debugger.
+ Primitive.  See Object documentation whatIsAPrimitive."
+
+ <primitive: 61>
+ index isInteger
+ ifTrue: [(index >= 1 and: [index <= (self objectSize: anObject)])
+ ifTrue: [self errorImproperStore]
+ ifFalse: [self errorSubscriptBounds: index]].
+ index isNumber
+ ifTrue: [^self object: anObject basicAt: index asInteger put: value]
+ ifFalse: [self errorNonIntegerIndex]!

Item was added:
+ ----- Method: MethodContext>>object:eqeq: (in category 'mirror primitives') -----
+ object: anObject eqeq: anOtherObject
+ "Answer whether the first and second arguments are the same object (have the
+ same object pointer) without sending a message to the first argument.  This
+ mimics the action of the VM when it compares two object pointers.  Used to
+ simulate the execution machinery by, for example, the debugger.
+ Primitive.  See Object documentation whatIsAPrimitive."
+
+ <primitive: 110>
+ self primitiveFailed!

Item was added:
+ ----- Method: MethodContext>>object:instVarAt: (in category 'mirror primitives') -----
+ object: anObject instVarAt: anIndex
+ "Primitive. Answer a fixed variable in an object. The numbering of the
+ variables corresponds to the named instance variables. Fail if the index
+ is not an Integer or is not the index of a fixed variable. Essential for the
+ debugger. See  Object documentation whatIsAPrimitive."
+
+ <primitive: 73>
+ "Access beyond fixed variables."
+ ^self object: anObject basicAt: anIndex - (self objectClass: anObject) instSize!

Item was added:
+ ----- Method: MethodContext>>object:instVarAt:put: (in category 'mirror primitives') -----
+ object: anObject instVarAt: anIndex put: aValue
+ "Primitive. Store a value into a fixed variable in the argument anObject.
+ The numbering of the variables corresponds to the named instance
+ variables.  Fail if the index is not an Integer or is not the index of a
+ fixed variable.  Answer the value stored as the result. Using this
+ message violates the  principle that each object has sovereign control
+ over the storing of values into its instance variables. Essential for the
+ debugger. See Object documentation whatIsAPrimitive."
+
+ <primitive: 74>
+ "Access beyond fixed fields"
+ ^self object: anObject basicAt: anIndex - (self objectClass: anObject) instSize put: aValue!

Item was added:
+ ----- Method: MethodContext>>object:perform:withArguments:inClass: (in category 'mirror primitives') -----
+ object: anObject perform: selector withArguments: argArray inClass: lookupClass
+ "Send the selector, aSymbol, to anObject with arguments in argArray.
+ Fail if the number of arguments expected by the selector
+ does not match the size of argArray, or if lookupClass
+ cannot be found among the anObject's superclasses.
+ Primitive. Essential for the debugger."
+
+ <primitive: 100 error: error>
+ (selector isSymbol) ifFalse:
+ [^self error: 'selector argument must be a Symbol'].
+ (argArray isMemberOf: Array) ifFalse:
+ [^self error: 'argArray must be an Array'].
+ (selector numArgs = argArray size)
+ ifFalse: [^self error: 'incorrect number of arguments'].
+ ((self objectClass: anObject) == lookupClass
+ or: [(self objectClass: anObject) inheritsFrom: lookupClass]) ifFalse:
+ [^self error: 'lookupClass is not in anObject''s inheritance chain'].
+ self primitiveFailed!

Item was added:
+ ----- Method: MethodContext>>objectClass: (in category 'mirror primitives') -----
+ objectClass: anObject
+ "Answer the class of the argument anObject without sending it a message.
+ This mimics the action of the VM when it fetches an object's class.  Used to
+ simulate the execution machinery by, for example, the debugger.
+ Primitive.  See Object documentation whatIsAPrimitive."
+
+ <primitive: 111>
+ self primitiveFailed!

Item was added:
+ ----- Method: MethodContext>>objectSize: (in category 'mirror primitives') -----
+ objectSize: anObject
+ "Answer the number of indexable variables in the argument anObject without sending
+ it a message. This mimics the action of the VM when it fetches an object's variable size.
+ Used to simulate the execution machinery by, for example, the debugger.
+ Primitive.  See Object documentation whatIsAPrimitive."
+
+ <primitive: 62>
+ "The number of indexable fields of fixed-length objects is 0"
+ ^0!

Item was changed:
  ----- Method: MethodContext>>outerContext (in category 'accessing') -----
  outerContext
  "Answer the context within which the receiver is nested."
 
+ ^closureOrNil ifNotNil:
- ^closureOrNil == nil ifFalse:
  [closureOrNil outerContext]!

Item was added:
+ ----- Method: MethodContext>>pc (in category 'debugger access') -----
+ pc
+ "Answer the index of the next bytecode to be executed."
+
+ ^pc!

Item was added:
+ ----- Method: MethodContext>>pop (in category 'controlling') -----
+ pop
+ "Answer the top of the receiver's stack and remove the top of the stack."
+ | val |
+ val := self at: stackp.
+ self stackp: stackp - 1.
+ ^ val!

Item was added:
+ ----- Method: MethodContext>>popIntoLiteralVariable: (in category 'instruction decoding') -----
+ popIntoLiteralVariable: value
+ "Simulate the action of bytecode that removes the top of the stack and
+ stores it into a literal variable of my method."
+
+ self object: value instVarAt: ValueIndex put: self pop!

Item was added:
+ ----- Method: MethodContext>>popIntoReceiverVariable: (in category 'instruction decoding') -----
+ popIntoReceiverVariable: offset
+ "Simulate the action of bytecode that removes the top of the stack and
+ stores it into an instance variable of my receiver."
+
+ self object: self receiver instVarAt: offset + 1 put: self pop!

Item was added:
+ ----- Method: MethodContext>>popIntoRemoteTemp:inVectorAt: (in category 'instruction decoding') -----
+ popIntoRemoteTemp: remoteTempIndex inVectorAt: tempVectorIndex
+ "Simulate the action of bytecode that removes the top of the stack and  stores
+ it into an offset in one of my local variables being used as a remote temp vector."
+
+ self object: (self at: tempVectorIndex + 1) basicAt: remoteTempIndex + 1 put: self pop!

Item was added:
+ ----- Method: MethodContext>>popIntoTemporaryVariable: (in category 'instruction decoding') -----
+ popIntoTemporaryVariable: offset
+ "Simulate the action of bytecode that removes the top of the stack and
+ stores it into one of my temporary variables."
+
+ self at: offset + 1 put: self pop!

Item was added:
+ ----- Method: MethodContext>>print:on: (in category 'debugger access') -----
+ print: anObject on: aStream
+ "Safely print anObject in the face of direct ProtoObject subclasses."
+ | objClass title |
+ objClass := self objectClass: anObject.
+ (objClass canUnderstand: #printOn:) ifTrue:
+ [^anObject printOn: aStream].
+ title := objClass name.
+ aStream
+ nextPutAll: (title first isVowel ifTrue: ['an '] ifFalse: ['a ']);
+ nextPutAll: title!

Item was changed:
  ----- Method: MethodContext>>printOn: (in category 'printing') -----
  printOn: aStream
+ | class mclass selector |
+ method ifNil:
+ [^super printOn: aStream].
 
+ closureOrNil ifNotNil:
+ [aStream nextPutAll: '[] in '.
+ closureOrNil outerContext printOn: aStream].
+
+ class := self objectClass: self receiver.
+ mclass := method methodClass.
+ selector := method selector ifNil: [method defaultSelector].
+
+ aStream nextPutAll: class name.
+ mclass ~~ class ifTrue:
+ [aStream nextPut: $(; nextPutAll: mclass name; nextPut: $)].
+ aStream nextPutAll: '>>'; nextPutAll: selector.
+
+ (selector == #doesNotUnderstand:
+ and: [(self objectClass: (self tempAt: 1)) == Message]) ifTrue:
+ [aStream space.
+ (self tempAt: 1) selector printOn: aStream]!
- self outerContext
- ifNil: [super printOn: aStream]
- ifNotNil:
- [:outerContext|
- aStream nextPutAll: '[] in '.
- outerContext printOn: aStream]!

Item was added:
+ ----- Method: MethodContext>>privSender: (in category 'private') -----
+ privSender: aContext
+
+ sender := aContext!

Item was added:
+ ----- Method: MethodContext>>push: (in category 'controlling') -----
+ push: val
+ "Push val on the receiver's stack."
+
+ self stackp: stackp + 1.
+ self at: stackp put: val!

Item was added:
+ ----- Method: MethodContext>>push:fromIndexable: (in category 'private') -----
+ push: numObjects fromIndexable: anIndexableCollection
+ "Push the elements of anIndexableCollection onto the receiver's stack.
+ Do not call directly.  Called indirectly by {1. 2. 3} constructs."
+
+ 1 to: numObjects do:
+ [:i | self push: (anIndexableCollection at: i)]!

Item was added:
+ ----- Method: MethodContext>>pushActiveContext (in category 'instruction decoding') -----
+ pushActiveContext
+ "Simulate the action of bytecode that pushes the the active context on the
+ top of its own stack."
+
+ self push: self!

Item was added:
+ ----- Method: MethodContext>>pushClosureCopyNumCopiedValues:numArgs:blockSize: (in category 'instruction decoding') -----
+ pushClosureCopyNumCopiedValues: numCopied numArgs: numArgs blockSize: blockSize
+ "Simulate the action of a 'closure copy' bytecode whose result is the
+ new BlockClosure for the following code"
+ | copiedValues |
+ numCopied > 0
+ ifTrue:
+ [copiedValues := Array new: numCopied.
+ numCopied to: 1 by: -1 do:
+ [:i|
+ copiedValues at: i put: self pop]]
+ ifFalse:
+ [copiedValues := nil].
+ self push: (BlockClosure
+ outerContext: self
+ startpc: pc
+ numArgs: numArgs
+ copiedValues: copiedValues).
+ self jump: blockSize!

Item was added:
+ ----- Method: MethodContext>>pushConstant: (in category 'instruction decoding') -----
+ pushConstant: value
+ "Simulate the action of bytecode that pushes the constant, value, on the
+ top of the stack."
+
+ self push: value!

Item was added:
+ ----- Method: MethodContext>>pushLiteralVariable: (in category 'instruction decoding') -----
+ pushLiteralVariable: value
+ "Simulate the action of bytecode that pushes the contents of the literal
+ variable whose index is the argument, index, on the top of the stack."
+
+ self push: (self object: value instVarAt: ValueIndex)!

Item was added:
+ ----- Method: MethodContext>>pushNewArrayOfSize: (in category 'instruction decoding') -----
+ pushNewArrayOfSize: arraySize
+ self push: (Array new: arraySize)!

Item was added:
+ ----- Method: MethodContext>>pushReceiver (in category 'instruction decoding') -----
+ pushReceiver
+ "Simulate the action of bytecode that pushes the active context's receiver
+ on the top of the stack."
+
+ self push: self receiver!

Item was added:
+ ----- Method: MethodContext>>pushReceiverVariable: (in category 'instruction decoding') -----
+ pushReceiverVariable: offset
+ "Simulate the action of bytecode that pushes the contents of the receiver's
+ instance variable whose index is the argument, index, on the top of the
+ stack."
+
+ self push: (self object: self receiver instVarAt: offset + 1)!

Item was added:
+ ----- Method: MethodContext>>pushRemoteTemp:inVectorAt: (in category 'instruction decoding') -----
+ pushRemoteTemp: remoteTempIndex inVectorAt: tempVectorIndex
+ "Simulate the action of bytecode that pushes the value at remoteTempIndex
+ in one of my local variables being used as a remote temp vector."
+ self push: (self object: (self at: tempVectorIndex + 1) basicAt: remoteTempIndex + 1)!

Item was added:
+ ----- Method: MethodContext>>pushTemporaryVariable: (in category 'instruction decoding') -----
+ pushTemporaryVariable: offset
+ "Simulate the action of bytecode that pushes the contents of the
+ temporary variable whose index is the argument, index, on the top of
+ the stack."
+
+ self push: (self at: offset + 1)!

Item was added:
+ ----- Method: MethodContext>>quickSend:to:with:super: (in category 'controlling') -----
+ quickSend: selector to: rcvr with: arguments super: superFlag
+ "Send the given selector with arguments in an environment which closely resembles
+ the non-simulating environment, with an interjected unwind-protected block to catch
+ nonlocal returns.  Attention: don't get lost!!  This beautiful method is due to
+ Hans-Martin Mosner.  Eliot Miranda merely added the mirror primitive code."
+ | oldSender contextToReturnTo result lookupClass |
+ contextToReturnTo := self.
+ lookupClass := superFlag
+ ifTrue: [self method methodClassAssociation value superclass]
+ ifFalse: [self objectClass: rcvr].
+ [oldSender := thisContext sender swapSender: self.
+ result := self object: rcvr perform: selector withArguments: arguments inClass: lookupClass.
+ thisContext sender swapSender: oldSender] ifCurtailed:
+ [contextToReturnTo := thisContext sender receiver. "The block context returning nonlocally"
+ contextToReturnTo pc: contextToReturnTo previousPc. "skip to front of return bytecode causing this unwind"
+ contextToReturnTo willReturnTopFromMethod ifTrue:
+ "If it was a returnTop, push the value to be returned.
+ Otherwise the value is implicit in the bytecode"
+ [contextToReturnTo push: (thisContext sender tempAt: 1)].
+ thisContext swapSender: thisContext home sender. "Make this block return to the method's sender"
+ contextToReturnTo].
+ contextToReturnTo push: result.
+ ^contextToReturnTo!

Item was added:
+ ----- Method: MethodContext>>quickStep (in category 'system simulation') -----
+ quickStep
+ "If the next instruction is a send, just perform it.
+ Otherwise, do a normal step."
+
+ self willReallySend ifTrue: [QuickStep := self].
+ ^self step!

Item was added:
+ ----- Method: MethodContext>>readDataFrom:size: (in category 'objects from disk') -----
+ readDataFrom: aDataStream size: varsOnDisk
+ "Fill in the fields of self based on the contents of aDataStream.  Answer self.
+ Read in the instance-variables written by Object>>storeDataOn:.
+ NOTE: This method must send beginReference: before reading any objects from aDataStream that might reference it.
+ Allow aDataStream to have fewer inst vars.  See SmartRefStream.
+ Override to not store nil stack contents beyond stack pointer."
+ | cntInstVars cntIndexedVars |
+
+ cntInstVars := self class instSize.
+ cntIndexedVars := varsOnDisk - cntInstVars.
+ cntIndexedVars < 0 ifTrue:
+ [self error: 'Class has changed too much.  Define a convertxxx method'].
+
+ aDataStream beginReference: self.
+ 1 to: cntInstVars do:
+ [:i | self instVarAt: i put: aDataStream next].
+ 1 to: stackp do:
+ [:i | self basicAt: i put: aDataStream next].
+ stackp + 1 to: cntIndexedVars do:
+ [:i | aDataStream next ~~ nil ifTrue:
+ [self error: 'Reading a Context''s contents expects only nil beyond top of stack']].
+ "Total number read MUST be equal to varsOnDisk!!"
+ ^self "If we ever answer something other than self, fix calls
+ on (super readDataFrom: aDataStream size: anInteger)"!

Item was added:
+ ----- Method: MethodContext>>rearmHandlerDuring: (in category 'private-exceptions') -----
+ rearmHandlerDuring: aBlock
+ "Sent to handler (on:do:) contexts only. Makes me re-entrant for the duration of aBlock. Only works in a closure-enabled image"
+
+ ^ [self tempAt: 3 put: true. aBlock value]
+ ensure: [self tempAt: 3 put: false]!

Item was added:
+ ----- Method: MethodContext>>release (in category 'debugger access') -----
+ release
+ "Remove information from the receiver and all of the contexts on its
+ sender chain in order to break circularities."
+
+ self releaseTo: nil!

Item was added:
+ ----- Method: MethodContext>>releaseTo: (in category 'debugger access') -----
+ releaseTo: caller
+ "Remove information from the receiver and the contexts on its sender
+ chain up to caller in order to break circularities."
+
+ | c s |
+ c := self.
+ [c == nil or: [c == caller]]
+ whileFalse:
+ [s := c sender.
+ c singleRelease.
+ c := s]!

Item was added:
+ ----- Method: MethodContext>>restart (in category 'controlling') -----
+ restart
+ "Unwind thisContext to self and resume from beginning.  Execute unwind blocks when unwinding.  ASSUMES self is a sender of thisContext"
+
+ | ctxt unwindBlock |
+ self isDead ifTrue: [self cannotReturn: nil to: self].
+ self privRefresh.
+ ctxt := thisContext.
+ [ ctxt := ctxt findNextUnwindContextUpTo: self.
+ ctxt isNil
+ ] whileFalse: [
+ (ctxt tempAt: 2) ifNil:[
+ ctxt tempAt: 2 put: true.
+ unwindBlock := ctxt tempAt: 1.
+ thisContext terminateTo: ctxt.
+ unwindBlock value].
+ ].
+ thisContext terminateTo: self.
+ self jump.
+ !

Item was added:
+ ----- Method: MethodContext>>resume (in category 'controlling') -----
+ resume
+ "Roll back thisContext to self and resume.  Execute unwind blocks when rolling back.  ASSUMES self is a sender of thisContext"
+
+ self resume: nil!

Item was added:
+ ----- Method: MethodContext>>resume: (in category 'controlling') -----
+ resume: value
+ "Unwind thisContext to self and resume with value as result of last send.  Execute unwind blocks when unwinding.  ASSUMES self is a sender of thisContext"
+
+ | ctxt unwindBlock |
+ self isDead ifTrue: [self cannotReturn: value to: self].
+ ctxt := thisContext.
+ [ ctxt := ctxt findNextUnwindContextUpTo: self.
+ ctxt isNil
+ ] whileFalse: [
+ (ctxt tempAt: 2) ifNil:[
+ ctxt tempAt: 2 put: true.
+ unwindBlock := ctxt tempAt: 1.
+ thisContext terminateTo: ctxt.
+ unwindBlock value].
+ ].
+ thisContext terminateTo: self.
+ ^ value
+ !

Item was added:
+ ----- Method: MethodContext>>resume:through: (in category 'controlling') -----
+ resume: value through: firstUnwindCtxt
+ "Unwind thisContext to self and resume with value as result of last send.
+ Execute any unwind blocks while unwinding.
+ ASSUMES self is a sender of thisContext."
+
+ | ctxt unwindBlock |
+ self isDead ifTrue: [self cannotReturn: value to: self].
+ ctxt := firstUnwindCtxt.
+ [ctxt isNil] whileFalse:
+ [(ctxt tempAt: 2) ifNil:
+ [ctxt tempAt: 2 put: true.
+ unwindBlock := ctxt tempAt: 1.
+ thisContext terminateTo: ctxt.
+ unwindBlock value].
+ ctxt := ctxt findNextUnwindContextUpTo: self].
+ thisContext terminateTo: self.
+ ^value
+ !

Item was added:
+ ----- Method: MethodContext>>return (in category 'controlling') -----
+ return
+ "Unwind until my sender is on top"
+
+ self return: self receiver!

Item was added:
+ ----- Method: MethodContext>>return: (in category 'controlling') -----
+ return: value
+ "Unwind thisContext to self and return value to self's sender.  Execute any unwind blocks while unwinding.  ASSUMES self is a sender of thisContext"
+
+ sender ifNil: [self cannotReturn: value to: sender].
+ sender resume: value!

Item was added:
+ ----- Method: MethodContext>>return:from: (in category 'instruction decoding') -----
+ return: value from: aSender
+ "For simulation.  Roll back self to aSender and return value from it.  Execute any unwind blocks on the way.  ASSUMES aSender is a sender of self"
+
+ | newTop ctxt |
+ aSender isDead ifTrue: [
+ ^ self send: #cannotReturn: to: self with: {value} super: false].
+ newTop := aSender sender.
+ ctxt := self findNextUnwindContextUpTo: newTop.
+ ctxt ifNotNil: [
+ ^ self send: #aboutToReturn:through: to: self with: {value. ctxt} super: false].
+ self releaseTo: newTop.
+ newTop ifNotNil: [newTop push: value].
+ ^ newTop
+ !

Item was added:
+ ----- Method: MethodContext>>return:through: (in category 'controlling') -----
+ return: value through: firstUnwindContext
+ "Unwind thisContext to self and return value to self's sender.
+ Execute any unwind blocks while unwinding.
+ ASSUMES self is a sender of thisContext."
+
+ sender ifNil: [self cannotReturn: value to: sender].
+ sender resume: value through: firstUnwindContext!

Item was added:
+ ----- Method: MethodContext>>return:to: (in category 'controlling') -----
+ return: value to: sendr
+ "Simulate the return of value to sendr."
+
+ self releaseTo: sendr.
+ sendr ifNil: [^ nil].
+ ^ sendr push: value!

Item was added:
+ ----- Method: MethodContext>>runSimulated:contextAtEachStep: (in category 'system simulation') -----
+ runSimulated: aBlock contextAtEachStep: block2
+ "Simulate the execution of the argument, aBlock, until it ends. aBlock
+ MUST NOT contain an '^'. Evaluate block2 with the current context
+ prior to each instruction executed. Answer the simulated value of aBlock."
+ | current |
+ aBlock hasMethodReturn
+ ifTrue: [self error: 'simulation of blocks with ^ can run loose'].
+ current := aBlock asContext.
+ current pushArgs: Array new from: self.
+ [current == self]
+ whileFalse:
+ [block2 value: current.
+ current := current step].
+ ^self pop!

Item was added:
+ ----- Method: MethodContext>>runUntilErrorOrReturnFrom: (in category 'controlling') -----
+ runUntilErrorOrReturnFrom: aSender
+ "ASSUMES aSender is a sender of self.  Execute self's stack until aSender returns or an unhandled exception is raised.  Return a pair containing the new top context and a possibly nil exception.  The exception is not nil if it was raised before aSender returned and it was not handled.  The exception is returned rather than openning the debugger, giving the caller the choice of how to handle it."
+ "Self is run by jumping directly to it (the active process abandons thisContext and executes self).  However, before jumping to self we insert an ensure block under aSender that jumps back to thisContext when evaluated.  We also insert an exception handler under aSender that jumps back to thisContext when an unhandled exception is raised.  In either case, the inserted ensure and exception handler are removed once control jumps back to thisContext."
+
+ | error ctxt here topContext |
+ here := thisContext.
+
+ "Insert ensure and exception handler contexts under aSender"
+ error := nil.
+ ctxt := aSender insertSender: (ContextPart
+ contextOn: UnhandledError do: [:ex |
+ error ifNil: [
+ error := ex exception.
+ topContext := thisContext.
+ ex resumeUnchecked: here jump]
+ ifNotNil: [ex pass]
+ ]).
+ ctxt := ctxt insertSender: (ContextPart
+ contextEnsure: [error ifNil: [
+ topContext := thisContext.
+ here jump]
+ ]).
+ self jump.  "Control jumps to self"
+
+ "Control resumes here once above ensure block or exception handler is executed"
+ ^ error ifNil: [
+ "No error was raised, remove ensure context by stepping until popped"
+ [ctxt isDead] whileFalse: [topContext := topContext stepToCallee].
+ {topContext. nil}
+
+ ] ifNotNil: [
+ "Error was raised, remove inserted above contexts then return signaler context"
+ aSender terminateTo: ctxt sender.  "remove above ensure and handler contexts"
+ {topContext. error}
+ ].
+ !

Item was added:
+ ----- Method: MethodContext>>secondFromBottom (in category 'query') -----
+ secondFromBottom
+ "Return the second from bottom of my sender chain"
+
+ self sender ifNil: [^ nil].
+ ^ self findContextSuchThat: [:c | c sender sender isNil]!

Item was added:
+ ----- Method: MethodContext>>selector (in category 'debugger access') -----
+ selector
+ "Answer the selector of the method that created the receiver."
+
+ ^self method selector ifNil: [self method defaultSelector].!

Item was added:
+ ----- Method: MethodContext>>selectorCategory (in category 'accessing') -----
+ selectorCategory
+ "Answer the category to which this message belongs (relative to the receiver).
+ If no superclass categorises this message, use the default."
+ | rcvrClass organizers |
+ rcvrClass := self objectClass: self receiver.
+ organizers := rcvrClass withAllSuperclasses collect: [:ea | ea organization].
+ organizers addFirst: rcvrClass organization.
+ ^(organizers collect: [ :org | org categoryOfElement: self selector])
+ detect: [:ea | ea ~= ClassOrganizer default and: [ea ~= nil]]
+ ifNone: [ClassOrganizer default]!

Item was added:
+ ----- Method: MethodContext>>send:super:numArgs: (in category 'instruction decoding') -----
+ send: selector super: superFlag numArgs: numArgs
+ "Simulate the action of bytecodes that send a message with selector,
+ selector. The argument, superFlag, tells whether the receiver of the
+ message was specified with 'super' in the source method. The arguments
+ of the message are found in the top numArgs locations on the stack and
+ the receiver just below them."
+
+ | receiver arguments |
+ arguments := Array new: numArgs.
+ numArgs to: 1 by: -1 do: [ :i | arguments at: i put: self pop].
+ receiver := self pop.
+ QuickStep == self ifTrue:
+ [QuickStep := nil.
+ ^self quickSend: selector to: receiver with: arguments super: superFlag].
+ ^self send: selector to: receiver with: arguments super: superFlag!

Item was added:
+ ----- Method: MethodContext>>send:to:with:lookupIn: (in category 'controlling') -----
+ send: selector to: rcvr with: arguments lookupIn: lookupClass
+ "Simulate the action of sending a message with selector and arguments
+ to rcvr. The argument, lookupClass, is the class in which to lookup the
+ message.  This is the receiver's class for normal messages, but for super
+ messages it will be some specific class related to the source method."
+
+ | meth primIndex val ctxt |
+ (meth := lookupClass lookupSelector: selector) ifNil:
+ [^self send: #doesNotUnderstand:
+ to: rcvr
+ with: {Message selector: selector arguments: arguments}
+ lookupIn: lookupClass].
+ meth numArgs ~= arguments size ifTrue:
+ [^self error: 'Wrong number of arguments in simulated message ', selector printString].
+ (primIndex := meth primitive) > 0 ifTrue:
+ [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments.
+ (self isPrimFailToken: val) ifFalse:
+ [^val]].
+ (selector == #doesNotUnderstand: and: [lookupClass == ProtoObject]) ifTrue:
+ [^self error: 'Simulated message ', arguments first selector, ' not understood'].
+ ctxt := MethodContext sender: self receiver: rcvr method: meth arguments: arguments.
+ primIndex > 0 ifTrue:
+ [ctxt failPrimitiveWith: val].
+ ^ctxt!

Item was added:
+ ----- Method: MethodContext>>send:to:with:startClass: (in category 'controlling') -----
+ send: selector to: rcvr with: args startClass: startClassOrNil
+ "Simulate the action of sending a message with selector, selector, and
+ arguments, args, to receiver. The argument, startClassOrNil, tells whether
+ the selector should be looked up in startClassOrNil or the class of the receiver."
+
+ | class meth val ctxt |
+ class := startClassOrNil ifNil: [self objectClass: rcvr].
+ meth := class lookupSelector: selector.
+ meth == nil ifTrue:
+ [^self
+ send: #doesNotUnderstand:
+ to: rcvr
+ with: (Array with: (Message selector: selector arguments: args))
+ startClass: class].
+ (args isArray
+ and: [args size = meth numArgs]) ifFalse:
+ [^ContextPart primitiveFailTokenFor: nil].
+ val := self tryPrimitiveFor: meth receiver: rcvr args: args.
+ ((self objectClass: val) == Array
+ and: [val size = 2
+ and: [val first == PrimitiveFailToken]]) ifFalse:
+ [^val].
+ (selector == #doesNotUnderstand:
+ and: [class == ProtoObject]) ifTrue:
+ [^self error: 'Simulated message ' , (args at: 1) selector, ' not understood'].
+ ctxt := self activateMethod: meth withArgs: args receiver: rcvr class: class.
+ ((self objectClass: val) == Array
+ and: [val size = 2
+ and: [val first == PrimitiveFailToken
+ and: [val last notNil
+ and: [(ctxt method at: ctxt pc) = 129 "long store temp"]]]]) ifTrue:
+ [ctxt at: ctxt stackPtr put: val last].
+ ^ctxt!

Item was added:
+ ----- Method: MethodContext>>send:to:with:super: (in category 'controlling') -----
+ send: selector to: rcvr with: arguments super: superFlag
+ "Simulate the action of sending a message with selector arguments
+ to rcvr. The argument, superFlag, tells whether the receiver of the
+ message was specified with 'super' in the source method."
+
+ ^self send: selector
+ to: rcvr
+ with: arguments
+ lookupIn: (superFlag
+ ifTrue: [self method methodClassAssociation value superclass]
+ ifFalse: [self objectClass: rcvr])!

Item was added:
+ ----- Method: MethodContext>>sender (in category 'debugger access') -----
+ sender
+ "Answer the context that sent the message that created the receiver."
+
+ ^sender!

Item was added:
+ ----- Method: MethodContext>>shortStack (in category 'debugger access') -----
+ shortStack
+ "Answer a String showing the top ten contexts on my sender chain."
+
+ ^ String streamContents:
+ [:strm |
+ (self stackOfSize: 10)
+ do: [:item | strm print: item; cr]]!

Item was added:
+ ----- Method: MethodContext>>singleRelease (in category 'debugger access') -----
+ singleRelease
+ "Remove information from the receiver in order to break circularities."
+
+ stackp == nil ifFalse: [1 to: stackp do: [:i | self at: i put: nil]].
+ sender := nil.
+ pc := nil.
+ !

Item was added:
+ ----- Method: MethodContext>>size (in category 'accessing') -----
+ size
+ "Primitive. Answer the number of indexable variables in the receiver.
+ This value is the same as the largest legal subscript. Essential. See Object
+ documentation whatIsAPrimitive.  Override the default primitive to give latitude to
+ the VM in context management."
+
+ <primitive: 212>
+ "The number of indexable fields of fixed-length objects is 0"
+ ^self primitiveFailed!

Item was added:
+ ----- Method: MethodContext>>sourceCode (in category 'debugger access') -----
+ sourceCode
+ ^self method getSource.
+
+ "Note: The above is a bit safer than
+ ^ methodClass sourceCodeAt: selector
+ which may fail if the receiver's method has been changed in
+ the debugger (e.g., the method is no longer in the methodDict
+ and thus the above selector is something like #Doit:with:with:with:)
+ but the source code is still available."!

Item was added:
+ ----- Method: MethodContext>>stack (in category 'debugger access') -----
+ stack
+ "Answer an Array of the contexts on the receiver's sender chain."
+
+ ^self stackOfSize: 9999!

Item was added:
+ ----- Method: MethodContext>>stackOfSize: (in category 'debugger access') -----
+ stackOfSize: limit
+ "Answer an OrderedCollection of the top 'limit' contexts
+ on the receiver's sender chain."
+
+ | stack ctxt |
+ stack := OrderedCollection new.
+ stack addLast: (ctxt := self).
+ [(ctxt := ctxt sender) ~~ nil
+ and: [stack size < limit]] whileTrue:
+ [stack addLast: ctxt].
+ ^stack!

Item was added:
+ ----- Method: MethodContext>>stackPtr (in category 'private') -----
+ stackPtr  "For use only by the SystemTracer and the Debugger, Inspectors etc"
+ ^ stackp!

Item was added:
+ ----- Method: MethodContext>>stackp: (in category 'private') -----
+ stackp: newStackp
+ "Storing into the stack pointer is a potentially dangerous thing.
+ This primitive stores nil into any cells that become accessible as a result,
+ and it performs the entire operation atomically."
+ "Once this primitive is implemented, failure code should cause an error"
+
+ <primitive: 76>
+ self error: 'stackp store failure'.
+ "
+ stackp == nil ifTrue: [stackp := 0].
+ newStackp > stackp  'effectively checks that it is a number'
+ ifTrue: [oldStackp := stackp.
+ stackp := newStackp.
+ 'Nil any newly accessible cells'
+ oldStackp + 1 to: stackp do: [:i | self at: i put: nil]]
+ ifFalse: [stackp := newStackp]
+ "!

Item was added:
+ ----- Method: MethodContext>>step (in category 'system simulation') -----
+ step
+ "Simulate the execution of the receiver's next bytecode. Answer the
+ context that would be the active context after this bytecode."
+
+ ^self interpretNextInstructionFor: self!

Item was added:
+ ----- Method: MethodContext>>stepToCallee (in category 'system simulation') -----
+ stepToCallee
+ "Step to callee or sender"
+
+ | ctxt |
+ ctxt := self.
+ [(ctxt := ctxt step) == self] whileTrue.
+ ^ ctxt!

Item was added:
+ ----- Method: MethodContext>>stepToSendOrReturn (in category 'system simulation') -----
+ stepToSendOrReturn
+ "Simulate the execution of bytecodes until either sending a message or
+ returning a value to the receiver (that is, until switching contexts)."
+
+ | ctxt |
+ [self willReallySend or: [self willReturn or: [self willReallyStore]]] whileFalse:
+ [ctxt := self step.
+ ctxt == self ifFalse:
+ [self halt.
+ "Caused by mustBeBoolean handling"
+ ^ctxt]]!

Item was added:
+ ----- Method: MethodContext>>storeDataOn: (in category 'objects from disk') -----
+ storeDataOn: aDataStream
+ "Contexts are not always allowed go to out in DataStreams.  They must be included inside an ImageSegment,
+ or be being saved for a closure."
+ | cntInstVars cntIndexedVars |
+
+ (aDataStream insideASegment
+ or: [(Notification new tag: self; signal) == self]) ifFalse: "or perhaps ImageSegments were not used at all"
+ [self error: 'This Context was not included in the ImageSegment'].
+
+ cntInstVars := self class instSize.
+ cntIndexedVars := self method frameSize.
+ aDataStream
+ beginInstance: self class
+ size: cntInstVars + cntIndexedVars.
+ 1 to: cntInstVars do:
+ [:i | aDataStream nextPut: (self instVarAt: i)].
+ 1 to: stackp do:
+ [:i | aDataStream nextPut: (self basicAt: i)].
+ stackp + 1 to: cntIndexedVars do:
+ [:i | aDataStream nextPut: nil]!

Item was added:
+ ----- Method: MethodContext>>storeIntoLiteralVariable: (in category 'instruction decoding') -----
+ storeIntoLiteralVariable: value
+ "Simulate the action of bytecode that stores the top of the stack into a
+ literal variable of my method."
+
+ self object: value instVarAt: ValueIndex put: self top!

Item was added:
+ ----- Method: MethodContext>>storeIntoReceiverVariable: (in category 'instruction decoding') -----
+ storeIntoReceiverVariable: offset
+ "Simulate the action of bytecode that stores the top of the stack into an
+ instance variable of my receiver."
+
+ self object: self receiver instVarAt: offset + 1 put: self top!

Item was added:
+ ----- Method: MethodContext>>storeIntoRemoteTemp:inVectorAt: (in category 'instruction decoding') -----
+ storeIntoRemoteTemp: remoteTempIndex inVectorAt: tempVectorIndex
+ "Simulate the action of bytecode that stores the top of the stack at
+ an offset in one of my local variables being used as a remote temp vector."
+
+ self object: (self at: tempVectorIndex + 1) basicAt: remoteTempIndex + 1 put: self top!

Item was added:
+ ----- Method: MethodContext>>storeIntoTemporaryVariable: (in category 'instruction decoding') -----
+ storeIntoTemporaryVariable: offset
+ "Simulate the action of bytecode that stores the top of the stack into one
+ of my temporary variables."
+
+ self at: offset + 1 put: self top!

Item was added:
+ ----- Method: MethodContext>>swapSender: (in category 'debugger access') -----
+ swapSender: coroutine
+ "Replace the receiver's sender with coroutine and answer the receiver's
+ previous sender. For use in coroutining."
+
+ | oldSender |
+ oldSender := sender.
+ sender := coroutine.
+ ^oldSender!

Item was added:
+ ----- Method: MethodContext>>tempNames (in category 'debugger access') -----
+ tempNames
+ "Answer a SequenceableCollection of the names of the receiver's temporary
+ variables, which are strings."
+
+ ^ self debuggerMap tempNamesForContext: self!

Item was added:
+ ----- Method: MethodContext>>tempsAndValues (in category 'debugger access') -----
+ tempsAndValues
+ "Return a string of the temporary variables and their current values"
+ ^self debuggerMap tempsAndValuesForContext: self!

Item was added:
+ ----- Method: MethodContext>>tempsAndValuesLimitedTo:indent: (in category 'debugger access') -----
+ tempsAndValuesLimitedTo: sizeLimit indent: indent
+ "Return a string of the temporary variabls and their current values"
+
+ | aStream |
+ aStream := WriteStream on: (String new: 100).
+ self tempNames
+ doWithIndex: [:title :index |
+ indent timesRepeat: [aStream tab].
+ aStream nextPutAll: title; nextPut: $:; space; tab.
+ aStream nextPutAll:
+ ((self tempAt: index) printStringLimitedTo: (sizeLimit -3 -title size max: 1)).
+ aStream cr].
+ ^aStream contents!

Item was added:
+ ----- Method: MethodContext>>terminate (in category 'controlling') -----
+ terminate
+ "Make myself unresumable."
+
+ sender := nil.
+ pc := nil.
+ !

Item was added:
+ ----- Method: MethodContext>>terminateTo: (in category 'controlling') -----
+ terminateTo: previousContext
+ "Terminate all the Contexts between me and previousContext, if previousContext is on my Context stack. Make previousContext my sender."
+
+ | currentContext sendingContext |
+ <primitive: 196>
+ (self hasSender: previousContext) ifTrue: [
+ currentContext := sender.
+ [currentContext == previousContext] whileFalse: [
+ sendingContext := currentContext sender.
+ currentContext terminate.
+ currentContext := sendingContext]].
+ sender := previousContext!

Item was added:
+ ----- Method: MethodContext>>top (in category 'controlling') -----
+ top
+ "Answer the top of the receiver's stack."
+
+ ^self at: stackp!

Item was added:
+ ----- Method: MethodContext>>tryNamedPrimitiveIn:for:withArgs: (in category 'private') -----
+ tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments
+ "Invoke the named primitive for aCompiledMethod, answering its result, or,
+ if the primiitve fails, answering the error code."
+ <primitive: 218 error: ec>
+ ec ifNotNil:
+ ["If ec is an integer other than -1 there was a problem with primitive 218,
+  not with the external primitive itself.  -1 indicates a generic failure (where
+  ec should be nil) but ec = nil means primitive 218 is not implemented.  So
+  interpret -1 to mean the external primitive failed with a nil error code."
+ ec isInteger ifTrue:
+ [ec = -1
+ ifTrue: [ec := nil]
+ ifFalse: [self primitiveFailed]]].
+ ^self class primitiveFailTokenFor: ec!

Item was added:
+ ----- Method: MethodContext>>tryPrimitiveFor:receiver:args: (in category 'private') -----
+ tryPrimitiveFor: method receiver: receiver args: arguments
+ "If this method has a primitive index, then run the primitive and return its result.
+ Otherwise (and also if the primitive fails) return PrimitiveFailToken,
+ as an indication that the method should be activated and run as bytecodes."
+ | primIndex |
+ (primIndex := method primitive) = 0 ifTrue: [^{PrimitiveFailToken. nil}].
+ ^ self doPrimitive: primIndex method: method receiver: receiver args: arguments!

Item was added:
+ ----- Method: MethodContext>>unwindTo: (in category 'private-exceptions') -----
+ unwindTo: aContext
+
+ | ctx unwindBlock |
+ ctx := self.
+ [(ctx := ctx findNextUnwindContextUpTo: aContext) isNil] whileFalse: [
+ (ctx tempAt: 2) ifNil:[
+ ctx tempAt: 2 put: true.
+ unwindBlock := ctx tempAt: 1.
+ unwindBlock value]
+ ].
+ !

Item was changed:
  ----- Method: Object class>>howToModifyPrimitives (in category 'documentation') -----
  howToModifyPrimitives
  "You are allowed to write methods which specify primitives, but please use
  caution.  If you make a subclass of a class which contains a primitive method,
  the subclass inherits the primitive.  The message which is implemented
  primitively may be overridden in the subclass (E.g., see at:put: in String's
  subclass Symbol).  The primitive behavior can be invoked using super (see
  Symbol string:).
 
  A class which attempts to mimic the behavior of another class without being
  its subclass may or may not be able to use the primitives of the original class.  
  In general, if the instance variables read or written by a primitive have the
  same meanings and are in the same fields in both classes, the primitive will
  work.  
 
  For certain frequently used 'special selectors', the compiler emits a
+ send-special-selector bytecode instead of a send-message bytecode. Special
+ selectors were created because they offer two advantages.  First, code which
+ sends special selectors compiles into fewer bytes than normal. Second, for
+ some pairs of receiver classes and special selectors, the interpreter jumps
+ directly to a primitive routine without looking up the method in the class,
+ and the just-in-time (JIT) compiler (if in use) may emit code to directly execute
+ the primitive.  At least in the interpeeter this is much faster than a normal
+ message lookup. In both the interpreter and the JIT send-special-selector,
+ conditional branch pairs are short-circuited for the comparison selectors.
- send-special-selector bytecode instead of a send-message bytecode.  
- Special selectors were created because they offer two advantages.  Code
- which sends special selectors compiles into fewer bytes than normal.  For
- some pairs of receiver classes and special selectors, the interpreter jumps
- directly to a primitive routine without looking up the method in the class.  
- This is much faster than a normal message lookup.
 
  A selector which is a special selector solely in order to save space has a
  normal behavior.  Methods whose selectors are special in order to
  gain speed contain the comment, 'No Lookup'.  When the interpreter
  encounters a send-special-selector bytecode, it checks the class of the
  receiver and the selector.  If the class-selector pair is a no-lookup pair,
  then the interpreter swiftly jumps to the routine which implements the
  corresponding primitive.  (A special selector whose receiver is not of the
  right class to make a no-lookup pair, is looked up normally).  The pairs are
  listed below.  No-lookup methods contain a primitive number specification,
  <primitive: xx>, which is redundant.  Since the method is not normally looked
  up, deleting the primitive number specification cannot prevent this
  primitive from running.  If a no-lookup primitive fails, the method is looked
  up normally, and the expressions in it are executed.
 
  No Lookup pairs of (class, selector)
+
+ SmallInteger and Float with any of + - * /
+ SmallInteger with any of \\  bitOr: bitShift: bitAnd:  // @
+ SmallInteger and Float with any of =  ~=  >  <  >=  <=
+ Any class with == ~~ class
+ Point with either of x y (interpreter only)
+ BlockClosure with either of value value: (interpreter only)
-
- SmallInteger with any of + - * /  \\  bitOr: bitShift: bitAnd:  //
- SmallInteger with any of =  ~=  >  <  >=  <=
- Any class with ==
- Any class with @
- Point with either of x y
- ContextPart with blockCopy:
- BlockContext with either of value value:
  "
 
  self error: 'comment only'!

Item was changed:
  ----- Method: Object>>instVarAt: (in category 'system primitives') -----
  instVarAt: index
  "Primitive. Answer a fixed variable in an object. The numbering of the variables
  corresponds to the named instance variables, followed by the indexed instance
+ variables. Fail if the index is not an Integer or is not the index of a fixed or
+ indexed variable. Essential. See Object documentation whatIsAPrimitive."
- variables. Fail if the index is not an Integer or is not the index of a fixed variable.
- Essential. See Object documentation whatIsAPrimitive."
 
  <primitive: 173 error: ec>
  self primitiveFailed!

Item was changed:
  ----- Method: Object>>instVarAt:put: (in category 'system primitives') -----
  instVarAt: index put: anObject
  "Primitive. Store a value into a fixed variable in an object. The numbering of the
  variables corresponds to the named instance variables, followed by the indexed
  instance variables. Fail if the index is not an Integer or is not the index of a fixed
+ or indexed variable. Essential. See Object documentation whatIsAPrimitive."
- variable. Essential. See Object documentation whatIsAPrimitive."
 
  <primitive: 174 error: ec>
  self primitiveFailed!