Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1086.mcz
==================== Summary ====================
Name: Kernel-eem.1086
Author: eem
Time: 4 April 2017, 5:56:56.293644 pm
UUID: b7a5b8d8-6a97-4193-87b9-f1ca83a6f52d
Ancestors: Kernel-eem.1085
Improve Context's comment and move methods out of the effectively obsolete closure-specific instruction-decoding category.
=============== Diff against Kernel-eem.1085 ===============
Item was changed:
InstructionStream variableSubclass: #Context
instanceVariableNames: 'stackp method closureOrNil receiver'
classVariableNames: 'MaxLengthForASingleDebugLogReport MaxStackDepthForASingleDebugLogReport PrimitiveFailToken QuickStep ValueIndex'
poolDictionaries: ''
category: 'Kernel-Methods'!
+ !Context commentStamp: 'eem 4/4/2017 17:45' prior: 0!
+ My instances hold all the dynamic state associated with the execution of either a method activation resulting from a message send or a block activation resulting from a block evaluation. In addition to their inherited state, this includes the receiver (self), the closure for a BlockClosure activation (which is nil for a method activation), a CompiledMethod, and space in the variable part of the context for arguments, temporary variables, and intermediate results, and the stack pointer to the top of stack in this variable part.
+
+ Contexts are created automatically (at least conceptually (*)) whenever a message send activates a method, or a block evaluation activates a block. The current context can always be accessed via the thisContext pseudo-variable. For example, explore the following:
+ { thisContext. thisContext copy. thisContext method. thisContext pc. thisContext receiver. thisContext stackPtr. thisContext sender }.
+
+ Contexts refer to the context in which they were created via the sender inst var. An execution stack is made up of of a linked list of contexts, linked through their sender inst var. Returning involves returning back to the sender. When a context is returned from its sender and pc are nilled, and, if the context is still referred to, the virtual machine guarantees to preserve only the arguments after a return. A Smalltalk Process is simply a chain of contexts specific to that process. The debugger is essentially a Process inspector. Stepping in the debugger is done by sending messages to contexts to get them to execute their bytecodes. See methods in the instruction decoding protocol.
+
- !Context commentStamp: 'eem 3/30/2017 17:27' prior: 0!
- My instances hold all the dynamic state associated with the execution of either a method activation resulting from a message send or a block activation resulting from a block evaluation. In addition to their inherited state, this includes the receiver (self), the closure for a BlockClosure activation (which is nil for a method activation), a CompiledMethod, and space in the variable part of the context for arguments and temporary variables.
-
Contexts, though normal in their variable size, are actually only used in two sizes, small and large, which are determined by the temporary space required by the method being executed.
+ Contexts must only be created using the method newForMethod:. Note that it is impossible to determine the real object size of a Context except by asking for the frameSize of its method. Any fields above the stack pointer (stackp) are truly invisible -- even (and especially!!) to the garbage collector. Any store into stackp other than by the primitive method stackp: is potentially fatal.
+
+ (*) efficient virtual machines create contexts lazily on demand, avoiding the overhead of creating them on every message send and of copying receiver and arguments from sender context to caller context. This optimization is invisible to the Smalltalk system.!
- Contexts must only be created using the method newForMethod:. Note that it is impossible to determine the real object size of a Context except by asking for the frameSize of its method. Any fields above the stack pointer (stackp) are truly invisible -- even (and especially!!) to the garbage collector. Any store into stackp other than by the primitive method stackp: is potentially fatal.!
Item was changed:
+ ----- Method: Context>>blockReturnTop (in category 'instruction decoding') -----
- ----- Method: Context>>blockReturnTop (in category 'instruction decoding (closures)') -----
blockReturnTop
"Simulate the interpreter's action when a ReturnTopOfStackToCaller bytecode is
encountered in the receiver. This should only happen in a closure activation."
self assert: closureOrNil isClosure.
^self return: self pop from: self!
Item was changed:
+ ----- Method: Context>>pushConsArrayWithElements: (in category 'instruction decoding') -----
- ----- Method: Context>>pushConsArrayWithElements: (in category 'instruction decoding (closures)') -----
pushConsArrayWithElements: numElements
| array |
array := Array new: numElements.
numElements to: 1 by: -1 do:
[:i|
array at: i put: self pop].
self push: array!
Chris Muller uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-cmm.1333.mcz
==================== Summary ====================
Name: Morphic-cmm.1333
Author: cmm
Time: 4 April 2017, 3:52:04.9926 pm
UUID: 64767f0b-c6c4-4c32-97a9-d122c30222d5
Ancestors: Morphic-eem.1332
Fix the race condition introduced with Debugger>>'ErrorRecursion' which resulted in the Emergency Evaluator being opened too eagerly (and unable to be closed!) -- even when there was no recursion.
=============== Diff against Morphic-eem.1332 ===============
Item was changed:
----- Method: Debugger class>>morphicOpenContext:label:contents: (in category '*Morphic-opening') -----
+ morphicOpenContext: aContext label: aString contents: contentsStringOrNil
- morphicOpenContext: aContext label: aString contents: contentsStringOrNil
"Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger."
+ "Simulation guard"
+ <primitive: 19>
+ ErrorRecursionGuard critical:
+ [ ErrorRecursion not & Preferences logDebuggerStackToFile ifTrue:
+ [ Smalltalk
+ logSqueakError: aString
+ inContext: aContext ].
+ ErrorRecursion ifTrue:
+ [ ErrorRecursion := false.
+ self primitiveError: aString ].
+ ErrorRecursion := true.
+ self
+ informExistingDebugger: aContext
+ label: aString.
+ (Debugger morphicContext: aContext)
+ openNotifierContents: contentsStringOrNil
+ label: aString.
- <primitive: 19> "Simulation guard"
- ErrorRecursion not & Preferences logDebuggerStackToFile ifTrue:
- [Smalltalk logSqueakError: aString inContext: aContext].
- ErrorRecursion ifTrue:[
ErrorRecursion := false.
+ Processor activeProcess suspend ]!
- self primitiveError: aString].
- ErrorRecursion := true.
- self informExistingDebugger: aContext label: aString.
- (Debugger morphicContext: aContext)
- openNotifierContents: contentsStringOrNil
- label: aString.
- ErrorRecursion := false.
- Processor activeProcess suspend.!
Item was changed:
----- Method: Debugger class>>morphicOpenOn:context:label:contents:fullView: (in category '*Morphic-opening') -----
+ morphicOpenOn: process context: context label: title contents: contentsStringOrNil fullView: full
- morphicOpenOn: process context: context label: title contents: contentsStringOrNil fullView: full
"Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger."
+ ErrorRecursionGuard critical:
+ [ | errorWasInUIProcess debugger |
+ ErrorRecursion ifTrue:
+ [ "self assert: process == Project current uiProcess -- DOCUMENTATION ONLY"
+ ErrorRecursion := false.
+ ^ Project current handleFatalDrawingError: title ].
+ [ ErrorRecursion not & Preferences logDebuggerStackToFile ifTrue:
+ [ Smalltalk
+ logSqueakError: title
+ inContext: context ] ]
+ on: Error
+ do: [ : ex | ex return: nil ].
+ ErrorRecursion := true.
+ errorWasInUIProcess := Project current spawnNewProcessIfThisIsUI: process.
+ "Schedule debugging in deferred UI message because
-
- | errorWasInUIProcess debugger |
- ErrorRecursion ifTrue: [
- "self assert: process == Project current uiProcess -- DOCUMENTATION ONLY"
- ErrorRecursion := false.
- ^ Project current handleFatalDrawingError: title].
-
- [ErrorRecursion not & Preferences logDebuggerStackToFile
- ifTrue: [Smalltalk logSqueakError: title inContext: context]] on: Error do: [:ex | ex return: nil].
-
- ErrorRecursion := true.
-
- errorWasInUIProcess := Project current spawnNewProcessIfThisIsUI: process.
-
- "Schedule debugging in deferred UI message because
1) If process is the current UI process, it is already broken.
2) If process is some other process, it must not execute UI code"
+ Project current addDeferredUIMessage:
+ [ debugger := self new
+ process: process
+ controller: nil
+ context: context.
+ full
+ ifTrue: [ debugger openFullNoSuspendLabel: title ]
+ ifFalse:
+ [ debugger
+ openNotifierContents: contentsStringOrNil
+ label: title ].
+ debugger errorWasInUIProcess: errorWasInUIProcess.
+ "Try drawing the debugger tool at least once to avoid freeze."
+ Project current world displayWorldSafely.
+ ErrorRecursion := false ].
+ process suspend ]!
- Project current addDeferredUIMessage: [
- debugger := self new process: process controller: nil context: context.
- full
- ifTrue: [debugger openFullNoSuspendLabel: title]
- ifFalse: [debugger openNotifierContents: contentsStringOrNil label: title].
- debugger errorWasInUIProcess: errorWasInUIProcess.
-
- "Try drawing the debugger tool at least once to avoid freeze."
- Project current world displayWorldSafely.
-
- ErrorRecursion := false.
- ].
- process suspend.
- !
Chris Muller uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-cmm.755.mcz
==================== Summary ====================
Name: Tools-cmm.755
Author: cmm
Time: 4 April 2017, 3:49:36.354898 pm
UUID: d6acf9c9-c3e4-4076-b2a5-9757eefe0b0e
Ancestors: Tools-eem.754
Fix the race condition introduced with Debugger>>'ErrorRecursion' which resulted in the Emergency Evaluator being opened too eagerly (and unable to be closed!) -- even when there was no recursion.
=============== Diff against Tools-eem.754 ===============
Item was changed:
CodeHolder subclass: #Debugger
instanceVariableNames: 'interruptedProcess interruptedController contextStack contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject errorWasInUIProcess labelString message untilExpression'
+ classVariableNames: 'ContextStackKeystrokes ErrorRecursion ErrorRecursionGuard ErrorReportServer InterruptUIProcessIfBlockedOnErrorInBackgroundProcess WantsAnnotationPane'
- classVariableNames: 'ContextStackKeystrokes ErrorRecursion ErrorReportServer InterruptUIProcessIfBlockedOnErrorInBackgroundProcess WantsAnnotationPane'
poolDictionaries: ''
category: 'Tools-Debugger'!
!Debugger commentStamp: '<historical>' prior: 0!
I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context.
Special note on recursive errors:
Some errors affect Squeak's ability to present a debugger. This is normally an unrecoverable situation. However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger. Here is the chain of events in such a recovery.
* A recursive error is detected.
* The current project is queried for an isolationHead
* Changes in the isolationHead are revoked
* The parent project of isolated project is returned to
* The debugger is opened there and execution resumes.
If the user closes that debugger, execution continues in the outer project and layer. If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. !
Item was changed:
----- Method: Debugger class>>initialize (in category 'class initialization') -----
initialize
ErrorRecursion := false.
+ ErrorRecursionGuard := Mutex new.
ContextStackKeystrokes := Dictionary new
at: $e put: #send;
at: $t put: #doStep;
at: $T put: #stepIntoBlock;
at: $p put: #proceed;
at: $r put: #restart;
at: $f put: #fullStack;
at: $w put: #where;
yourself.
"Debugger initialize"!
Item was changed:
+ (PackageInfo named: 'Tools') postscript: 'Debugger initialize.'!
- (PackageInfo named: 'Tools') postscript: 'ProcessBrowser initialize.'!