Eliot Miranda uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-eem.757.mcz
==================== Summary ====================
Name: Tools-eem.757
Author: eem
Time: 13 April 2017, 2:02:11.819767 pm
UUID: 16ab4ff6-7a4c-49b7-aa90-025eb0164a8f
Ancestors: Tools-eem.756
Have the debugger look for both the old and the soon-to-appear new quickStep: methods when trying to inform an exsting debugger of an error.
=============== Diff against Tools-eem.756 ===============
Item was changed:
----- Method: Debugger class>>informExistingDebugger:label: (in category 'instance creation') -----
informExistingDebugger: aContext label: aString
"Walking the context chain, we try to find out if we're in a debugger stepping situation.
If we find the relevant contexts, we must rearrange them so they look just like they would
if the methods were executed outside of the debugger.
hmm 8/3/2001 13:05"
| ctx quickStepMethod oldSender baseContext |
ctx := thisContext.
+ quickStepMethod := Context
+ compiledMethodAt: #quickSend:to:with:lookupIn:
+ ifAbsent: [Context compiledMethodAt: #quickSend:to:with:super:].
+ [ctx sender == nil or: [ctx sender method == quickStepMethod]] whileFalse:
+ [ctx := ctx sender].
- quickStepMethod := Context compiledMethodAt: #quickSend:to:with:super:.
- [ctx sender == nil or: [ctx sender method == quickStepMethod]] whileFalse: [ctx := ctx sender].
ctx sender ifNil: [^self].
baseContext := ctx.
"baseContext is now the context created by the #quickSend... method."
oldSender := ctx := ctx sender home sender.
"oldSender is the context which originally sent the #quickSend... method"
+ [ctx == nil or: [(ctx objectClass: ctx receiver) includesBehavior: self]] whileFalse:
+ [ctx := ctx sender].
- [ctx == nil or: [(ctx objectClass: ctx receiver) includesBehavior: self]] whileFalse: [ctx := ctx sender].
ctx ifNil: [^self].
"ctx is the context of the Debugger method #doStep"
ctx receiver
labelString: aString;
externalInterrupt: false;
proceedValue: aContext receiver.
baseContext swapSender: baseContext sender sender sender. "remove intervening contexts"
thisContext swapSender: oldSender. "make myself return to debugger"
ErrorRecursion := false.
^aContext!
Eliot Miranda uploaded a new version of Compiler to project The Trunk:
http://source.squeak.org/trunk/Compiler-eem.351.mcz
==================== Summary ====================
Name: Compiler-eem.351
Author: eem
Time: 13 April 2017, 1:51:29.304066 pm
UUID: a6fc0090-227a-4e9c-b85d-a6c05c20707b
Ancestors: Compiler-eem.350
Add missing directedSuperSend: support.
=============== Diff against Compiler-eem.350 ===============
Item was added:
+ ----- Method: BlockLocalTempCounter>>directedSuperSend:numArgs: (in category 'instruction decoding') -----
+ directedSuperSend: selector numArgs: numArgs
+ "Send Message Above Specific Class With Selector, selector, bytecode.
+ Start the lookup above the class that is the value of the association on
+ top of stack. The arguments of the message are found in the top numArgs
+ stack locations beneath the association, and the receiver just below them."
+
+ stackPointer := stackPointer - (numArgs + 1)!
Item was added:
+ ----- Method: BytecodeEncoder>>sizeSendDirectedSuper:numArgs: (in category 'opcode sizing') -----
+ sizeSendDirectedSuper: selectorLiteralIndex numArgs: numArgs
+ ^self sizeOpcodeSelector: #genSendDirectedSuper:numArgs: withArguments: {selectorLiteralIndex. numArgs}!
Eliot Miranda uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-eem.756.mcz
==================== Summary ====================
Name: Tools-eem.756
Author: eem
Time: 11 April 2017, 12:06:44.157162 pm
UUID: e6634875-90c8-4ebf-9f07-5b3e1aadfc81
Ancestors: Tools-cmm.755
Make the debugger handle gracefully stepping through the termiation of a process.
=============== Diff against Tools-cmm.755 ===============
Item was changed:
----- Method: Debugger>>buildControlButtonsWith: (in category 'toolbuilder') -----
buildControlButtonsWith: builder
| panelSpec |
panelSpec := builder pluggablePanelSpec new.
panelSpec children: OrderedCollection new.
self customButtonSpecs do:[:spec|
| buttonSpec |
buttonSpec := builder pluggableActionButtonSpec new.
buttonSpec model: self.
buttonSpec label: spec first.
buttonSpec action: spec second.
spec second == #methodHierarchy ifTrue:[
buttonSpec color: #inheritanceButtonColor.
].
+ spec size > 2 ifTrue:
+ [buttonSpec help: spec third.
+ spec size > 3 ifTrue:
+ [buttonSpec enabled: spec fourth]].
- spec size > 2 ifTrue:[buttonSpec help: spec third].
panelSpec children add: buttonSpec.
].
panelSpec layout: #horizontal. "buttons"
^panelSpec!
Item was changed:
----- Method: Debugger>>customButtonSpecs (in category 'initialize') -----
customButtonSpecs
"Answer an array of elements of the form wording, selector, help-message, that characterize the custom button row of a debugger."
| list |
list := #(('Proceed' proceed 'close the debugger and proceed.')
('Restart' restart 'reset this context to its start.')
+ ('Into' send 'step Into message sends' interruptedProcessIsActive)
+ ('Over' doStep 'step Over message sends' interruptedProcessIsActive)
+ ('Through' stepIntoBlock 'step into a block' interruptedProcessIsActive)
- ('Into' send 'step Into message sends')
- ('Over' doStep 'step Over message sends')
- ('Through' stepIntoBlock 'step into a block')
('Full Stack' fullStack 'show full stack')
('Where' where 'select current pc range')
('Tally' tally 'time in milliseconds to execute')).
Preferences restartAlsoProceeds ifTrue:
[list := list collect: [:each |
each second == #restart
ifTrue: [each copy at: 3 put: 'proceed from the beginning of this context.'; yourself]
ifFalse: [each]]].
^ list!
Item was added:
+ ----- Method: Debugger>>interruptedProcessIsActive (in category 'user interface') -----
+ interruptedProcessIsActive
+ ^interruptedProcess isTerminated not!
Item was changed:
----- Method: Debugger>>resetContext:changeContents: (in category 'private') -----
resetContext: aContext changeContents: aBoolean
"Used when a new context becomes top-of-stack, for instance when the
method of the selected context is re-compiled, or the simulator steps or
returns to a new method. There is room for much optimization here, first
to save recomputing the whole stack list (and text), and secondly to avoid
recomposing all that text (by editing the paragraph instead of recreating it)."
| oldContext |
oldContext := self selectedContext.
+ self newStack: (aContext ifNil: [oldContext]) contextStack.
+ self changed: #contextStackList; changed: #interruptedProcessIsActive.
- self newStack: aContext contextStack.
- self changed: #contextStackList.
self contextStackIndex: 1 oldContextWas: oldContext.
aBoolean ifTrue: [self contentsChanged].
!
Eliot Miranda uploaded a new version of ST80 to project The Trunk:
http://source.squeak.org/trunk/ST80-eem.228.mcz
==================== Summary ====================
Name: ST80-eem.228
Author: eem
Time: 11 April 2017, 11:29:49.415405 am
UUID: 3a992a3d-dba9-48e6-8ab9-716c4735bf75
Ancestors: ST80-cmm.227
Fix a regression in ST80-cmm.227 which prevents a debugger opening while another is open. One should never suspend the active process within a critical: block; doing so prevents the critical: block from completing and hence releasing its lock. The fix is to pull the suspend out of the critical: block.
=============== Diff against ST80-cmm.227 ===============
Item was changed:
----- Method: Debugger class>>mvcOpenContext:label:contents: (in category '*ST80-opening') -----
mvcOpenContext: 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 mvcContext: aContext)
openNotifierContents: contentsStringOrNil
label: aString.
+ ErrorRecursion := false ].
+ Processor activeProcess suspend!
- ErrorRecursion := false.
- Processor activeProcess suspend ]!
Eliot Miranda uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-eem.1334.mcz
==================== Summary ====================
Name: Morphic-eem.1334
Author: eem
Time: 11 April 2017, 11:27:47.032574 am
UUID: cd47b9b1-d13f-4c90-8aab-d1fbabd162e0
Ancestors: Morphic-cmm.1333
Fix a regression in Morphic-cmm.1333 which prevents a debugger opening while another is open. One should never suspend the active process within a critical: block; doing so prevents the critical: block from completing and hence releasing its lock. The fix is to pull the suspend out of the critical: block.
=============== Diff against Morphic-cmm.1333 ===============
Item was changed:
----- Method: Debugger class>>morphicOpenContext:label:contents: (in category '*Morphic-opening') -----
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.
+ ErrorRecursion := false].
+ Processor activeProcess suspend !
- 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
"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
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 !
- ErrorRecursion := false ].
- process suspend ]!
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1092.mcz
==================== Summary ====================
Name: Kernel-eem.1092
Author: eem
Time: 10 April 2017, 11:52:56.611122 am
UUID: 49255d6b-cd3d-4604-b9ba-6ac025d951b3
Ancestors: Kernel-eem.1091
Add FullBlockClosure (blocks with independent bytecode methods; needed for Scorch/Sista). Give BlockClosure an informative comment.
=============== Diff against Kernel-eem.1091 ===============
Item was changed:
Object variableSubclass: #BlockClosure
instanceVariableNames: 'outerContext startpc numArgs'
classVariableNames: ''
poolDictionaries: ''
category: 'Kernel-Methods'!
+ !BlockClosure commentStamp: 'eem 4/10/2017 11:17' prior: 0!
+ Instances of BlockClosure represent blocks, a sequence of statements inside square brackets that can be evaluated at any time via one of the value messages (value, value:, value:value:, ... valueWithArguments:), which answer their last statement. Blocks therefore allow deferred evaluation and so are used to buikld control structures where a sequence of statements are evaluated or not depending on other values in the program.
+
+ Blocks can close over variables in their enclosing method or block. The method in which a block is nested is called its home method. Blocks can return from their home method via an up-arrow return, and returns to the sender of the message that created the home method, just like a return from the method itself. BlockClosures are fully first-class objects; they can outlive their enclosing method activation and be answered as results and/or assigned to variables.
+
+ BlockClosures are central to the implementation of control structures in Smalltalk. The arguments to the conditional message ifTrue:ifFalse: are zero-argument blocks, which the receiver is a boolean which responds by evaluating ether the first argument or the second. The bytecode compiler inlines blocks for certain selectors, compiling to conditional branch and branch bytecodes. This is done for efficiency. The full list of inlined messages can be found in MessageNode's MacroSelectors class variable (at time of writing ther=se are ifTrue:, ifFalse:, ifTrue:ifFalse:, ifFalse:ifTrue:, and:, or:, whileFalse:, whileTrue:, whileFalse, whileTrue, to:do:, to:by:do:, caseOf:, caseOf:otherwise:, ifNil:, ifNotNil:, ifNil:ifNotNil:, ifNotNil:ifNil: and repeat.
+
+ Examples (more can be found in BlockClosureTest's class comment):
+ [1@2] value
+
+ | counter |
+ counter := 0.
+ { counter. (1 to: 10) collect: [:n| counter := counter + 1. n + counter]. counter }
+
+ | fibonacciBlock |
+ fibonacciBlock := [:n|
+ n > 1 ifTrue: [(fibonacciBlock value: n - 1) + (fibonacciBlock value: n - 2)] ifFalse: [1]].
+ (1 to: 10) collect: fibonacciBlock
+
+ | randomNumbers |
+ randomNumbers := Random new next: 20.
+ { randomNumbers. randomNumbers sorted: [:a :b| a > b] }
+
+ Implementation:
+ BlockClosure implements blocks that are nested within an enclosing method or block context. Further, the bytecodes for the block are embedded within the home method. BlockClosure's subclass FullBlockClosure has an independent CompiledBlock as its method, and may or may not have an outerContext.
+
+ Instance Variables
+ numArgs: <Integer>
+ outerContext: <Context>
+ startpc: <Integer>
+
+ numArgs
+ - the number of arguments the block expects
+
+ outerContext
+ - the Context of the method or block activation in which the receiver is created
+
+ startpc
+ - the startpc of the block's bytecodes within the home method.!
- !BlockClosure commentStamp: '<historical>' prior: 0!
- I am a block closure for Eliot's closure implementation. Not to be confused with the old BlockClosure.!
Item was added:
+ BlockClosure variableSubclass: #FullBlockClosure
+ instanceVariableNames: 'receiver'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'Kernel-Methods'!
+
+ !FullBlockClosure commentStamp: 'eem 4/10/2017 11:18' prior: 0!
+ Instances of FullBlockClosure represent blocks, a sequence of statements inside square brackets that can be evaluated at any time via one of the value messages (value, value:, value:value:, ... valueWithArguments:), which answer their last statement. Blocks therefore allow deferred evaluation and so are used to buikld control structures where a sequence of statements are evaluated or not depending on other values in the program.
+
+ FullBlockClosure is a refinement of BlockClosure that allows the block to use its own method to hold its code instead of embedding that code within its home method.
+
+ Implementation:
+
+ A FullBlockClosure is a closure that can be independent of any outerContext if desired. It has its own method (currently reusing the startpc inst var) and its own receiver. outerContext can be either a Context or nil.
+
+ This closure design, implemented by Eliot Miranda and Clement Bera along with the sista work aims to simplify the block closure model while enhacing its capabilities. It allows lazy decompilation of closures and fast machine code dispatch in Cog's JIT, while allowing inlining of methods and blocks to be independent from their enclosing blocks.
+
+ At closure creation time, the bytecode specifies:
+ - the compiledBlock to execute when executing this block's code (in the literal frame)
+ - if the receiver is the current receiver or a receiver passed on stack before the copied values.
+ - if the closure needs an outerContext. outerContexts are used for non local returns and debugging. Blocks with non local returns have to set their outerContext. For other blocks (97% of blocks), it's a trade-off between performance and debuggability.
+
+ Instance Variables (inherited)
+ numArgs <SmallInteger>
+ outerContext: <Context|nil>
+ compiledBlock(startpc) <CompiledBlock>
+
+ Instance Variables
+ receiver: <Object>
+
+ numArgs
+ - the number of arguments the block expects. This is superfluous; the number of arguments can be obtained from the receiver's compiledBlock.
+
+ outerContext
+ - the Context of the method or block activation in which the receiver is created.
+
+ compiledBlock(startpc)
+ - reused to refer to the CompiledBlock that implements the receiver's code.
+
+ receiver
+ - the receiver of the message that created the block's home method activation.!
Item was added:
+ ----- Method: FullBlockClosure>>abstractBytecodeMessagesDo: (in category 'scanning') -----
+ abstractBytecodeMessagesDo: aBlock
+ ^ self compiledBlock abstractBytecodeMessagesDo: aBlock!
Item was added:
+ ----- Method: FullBlockClosure>>asContextWithSender: (in category 'private') -----
+ asContextWithSender: aContext
+ "Inner private support method for evaluation. Do not use unless you know what you're doing."
+
+ ^(Context newForMethod: self compiledBlock)
+ setSender: aContext
+ receiver: self receiver
+ method: self compiledBlock
+ closure: self
+ startpc: self startpc;
+ privRefresh!
Item was added:
+ ----- Method: FullBlockClosure>>compiledBlock (in category 'accessing') -----
+ compiledBlock
+ "To be able to inherit from BlockClosure"
+ ^ startpc!
Item was added:
+ ----- Method: FullBlockClosure>>compiledBlock: (in category 'accessing') -----
+ compiledBlock: aCompiledMethod
+ "To be able to inherit from BlockClosure"
+ startpc := aCompiledMethod!
Item was added:
+ ----- Method: FullBlockClosure>>endPC (in category 'accessing') -----
+ endPC
+ ^ self compiledBlock endPC!
Item was added:
+ ----- Method: FullBlockClosure>>hasMethodReturn (in category 'scanning') -----
+ hasMethodReturn
+ "Answer whether the receiver has a method-return ('^') in its code."
+ ^ self compiledBlock hasMethodReturn!
Item was added:
+ ----- Method: FullBlockClosure>>home (in category 'accessing') -----
+ home
+ ^ outerContext ifNotNil: [ outerContext home ]!
Item was added:
+ ----- Method: FullBlockClosure>>method (in category 'accessing') -----
+ method
+ ^ self compiledBlock!
Item was added:
+ ----- Method: FullBlockClosure>>numArgs: (in category 'accessing') -----
+ numArgs: n
+ numArgs := n!
Item was added:
+ ----- Method: FullBlockClosure>>numTemps (in category 'accessing') -----
+ numTemps
+ ^ self compiledBlock numTemps!
Item was added:
+ ----- Method: FullBlockClosure>>outerContext: (in category 'accessing') -----
+ outerContext: ctxt
+ outerContext := ctxt!
Item was added:
+ ----- Method: FullBlockClosure>>printOn: (in category 'private') -----
+ printOn: s
+ [ super printOn: s ] on: Error do: [ :ex | s << '!![' << ex messageText << ']!!' ]!
Item was added:
+ ----- Method: FullBlockClosure>>receiver (in category 'accessing') -----
+ receiver
+ ^ receiver!
Item was added:
+ ----- Method: FullBlockClosure>>receiver: (in category 'accessing') -----
+ receiver: anObject
+ receiver := anObject!
Item was added:
+ ----- Method: FullBlockClosure>>simulateValueWithArguments:caller: (in category 'simulation') -----
+ simulateValueWithArguments: anArray caller: aContext
+ "Simulate the valueWithArguments: primitive. Fail if anArray is not an array of the right arity."
+ | newContext |
+ newContext := (Context newForMethod: self compiledBlock)
+ setSender: aContext
+ receiver: receiver
+ method: self compiledBlock
+ closure: self
+ startpc: self compiledBlock initialPC.
+ ((newContext objectClass: anArray) ~~ Array
+ or: [numArgs ~= anArray size]) ifTrue:
+ [^Context primitiveFailTokenFor: nil].
+ newContext stackp: self compiledBlock numTemps.
+ 1 to: numArgs do:
+ [:i| newContext at: i put: (anArray at: i)].
+ 1 to: self basicSize do:
+ [:i| newContext at: i + numArgs put: (self at: i)].
+ ^newContext!
Item was added:
+ ----- Method: FullBlockClosure>>startpc (in category 'accessing') -----
+ startpc
+ ^ self compiledBlock initialPC!
Item was added:
+ ----- Method: FullBlockClosure>>value (in category 'evaluating') -----
+ value
+ "Activate the receiver, creating a closure activation (MethodContext)
+ whose closure is the receiver and whose caller is the sender of this
+ message. Supply the copied values to the activation as its copied
+ temps. Primitive. Essential."
+ <primitive: 207>
+ | newContext |
+ numArgs ~= 0 ifTrue:
+ [self numArgsError: 0].
+ false
+ ifTrue: "Old code to simulate the closure value primitive on VMs that lack it."
+ [newContext := self asContextWithSender: thisContext sender.
+ thisContext privSender: newContext]
+ ifFalse: [self primitiveFailed]!
Item was added:
+ ----- Method: FullBlockClosure>>value: (in category 'evaluating') -----
+ value: firstArg
+ "Activate the receiver, creating a closure activation (MethodContext)
+ whose closure is the receiver and whose caller is the sender of this
+ message. Supply the argument and copied values to the activation
+ as its argument and copied temps. Primitive. Essential."
+ <primitive: 207>
+ | newContext |
+ numArgs ~= 1 ifTrue:
+ [self numArgsError: 1].
+ false
+ ifTrue: "Old code to simulate the closure value primitive on VMs that lack it."
+ [newContext := self asContextWithSender: thisContext sender.
+ newContext at: 1 put: firstArg.
+ thisContext privSender: newContext]
+ ifFalse: [self primitiveFailed]!
Item was added:
+ ----- Method: FullBlockClosure>>value:value: (in category 'evaluating') -----
+ value: firstArg value: secondArg
+ "Activate the receiver, creating a closure activation (MethodContext)
+ whose closure is the receiver and whose caller is the sender of this
+ message. Supply the arguments and copied values to the activation
+ as its arguments and copied temps. Primitive. Essential."
+ <primitive: 207>
+ | newContext |
+ numArgs ~= 2 ifTrue:
+ [self numArgsError: 2].
+ false
+ ifTrue: "Old code to simulate the closure value primitive on VMs that lack it."
+ [newContext := self asContextWithSender: thisContext sender.
+ newContext at: 1 put: firstArg.
+ newContext at: 2 put: secondArg.
+ thisContext privSender: newContext]
+ ifFalse: [self primitiveFailed]!
Item was added:
+ ----- Method: FullBlockClosure>>value:value:value: (in category 'evaluating') -----
+ value: firstArg value: secondArg value: thirdArg
+ "Activate the receiver, creating a closure activation (MethodContext)
+ whose closure is the receiver and whose caller is the sender of this
+ message. Supply the arguments and copied values to the activation
+ as its arguments and copied temps. Primitive. Essential."
+ <primitive: 207>
+ | newContext |
+ numArgs ~= 3 ifTrue:
+ [self numArgsError: 3].
+ false
+ ifTrue: "Old code to simulate the closure value primitive on VMs that lack it."
+ [newContext := self asContextWithSender: thisContext sender.
+ newContext at: 1 put: firstArg.
+ newContext at: 2 put: secondArg.
+ newContext at: 3 put: thirdArg.
+ thisContext privSender: newContext]
+ ifFalse: [self primitiveFailed]!
Item was added:
+ ----- Method: FullBlockClosure>>value:value:value:value: (in category 'evaluating') -----
+ value: firstArg value: secondArg value: thirdArg value: fourthArg
+ "Activate the receiver, creating a closure activation (MethodContext)
+ whose closure is the receiver and whose caller is the sender of this
+ message. Supply the arguments and copied values to the activation
+ as its arguments and copied temps. Primitive. Essential."
+ <primitive: 207>
+ | newContext |
+ numArgs ~= 4 ifTrue:
+ [self numArgsError: 4].
+ false
+ ifTrue: "Old code to simulate the closure value primitive on VMs that lack it."
+ [newContext := self asContextWithSender: thisContext sender.
+ newContext at: 1 put: firstArg.
+ newContext at: 2 put: secondArg.
+ newContext at: 3 put: thirdArg.
+ newContext at: 4 put: fourthArg.
+ thisContext privSender: newContext]
+ ifFalse: [self primitiveFailed]!
Item was added:
+ ----- Method: FullBlockClosure>>valueNoContextSwitch (in category 'evaluating') -----
+ valueNoContextSwitch
+ "An exact copy of BlockClosure>>value except that this version will not preempt
+ the current process on block activation if a higher-priority process is runnable.
+ Primitive. Essential."
+ <primitive: 209>
+ numArgs ~= 0 ifTrue:
+ [self numArgsError: 0].
+ self primitiveFailed!
Item was added:
+ ----- Method: FullBlockClosure>>valueNoContextSwitch: (in category 'evaluating') -----
+ valueNoContextSwitch: anArg
+ "An exact copy of BlockClosure>>value: except that this version will not preempt
+ the current process on block activation if a higher-priority process is runnable.
+ Primitive. Essential."
+ <primitive: 209>
+ numArgs ~= 1 ifTrue:
+ [self numArgsError: 1].
+ self primitiveFailed!
Item was added:
+ ----- Method: FullBlockClosure>>valueWithArguments: (in category 'evaluating') -----
+ valueWithArguments: anArray
+ "Activate the receiver, creating a closure activation (MethodContext)
+ whose closure is the receiver and whose caller is the sender of this
+ message. Supply the arguments in an anArray and copied values to
+ the activation as its arguments and copied temps. Primitive. Essential."
+ <primitive: 208>
+ | newContext |
+ numArgs ~= anArray size ifTrue:
+ [self numArgsError: anArray size].
+ false
+ ifTrue: "Old code to simulate the closure value primitive on VMs that lack it."
+ [newContext := self asContextWithSender: thisContext sender.
+ 1 to: numArgs do:
+ [:i| newContext at: i put: (anArray at: i)].
+ thisContext privSender: newContext]
+ ifFalse: [self primitiveFailed]!