Christoph Thiede uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-ct.1451.mcz
==================== Summary ====================
Name: Kernel-ct.1451
Author: ct
Time: 25 March 2022, 6:47:25.617514 pm
UUID: 94732d1b-58e4-9f4b-a1b3-c950af711c77
Ancestors: Kernel-nice.1447
Revises fallback code for primitive 188 (primitiveExecuteMethodArgsArray) in Object>>#withArgs:executeMethod: and eliminates any side-effects to the method dictionary. This also adds support for Objects as Methods (OaM) in this place. To achieve this, extract and reuse the simulation of method execution from Context>>#send:to:with:lookupIn:.
Thanks to Eliot for the idea! This is the next iteration of Kernel-ct.1449 (inbox). The second part of that version (arity checks in sim of primitivePerform[WithArgs]) still remains relevant, though.
=============== Diff against Kernel-nice.1447 ===============
Item was added:
+ ----- Method: Context>>executeMethod:forSelector:withArgs:receiver: (in category 'controlling') -----
+ executeMethod: meth forSelector: selector withArgs: arguments receiver: rcvr
+
+ | primIndex val ctxt |
+ (self objectClass: meth) isCompiledCodeClass ifFalse:
+ ["Object as Methods (OaM) protocol: 'The contract is that, when the VM encounters an ordinary object (rather than a compiled method) in the method dictionary during lookup, it sends it the special selector #run:with:in: providing the original selector, arguments, and receiver.'. DOI: 10.1145/2991041.2991062."
+ ^self send: #run:with:in:
+ to: meth
+ with: {selector. arguments. rcvr}].
+
+ meth numArgs = arguments size ifFalse:
+ [^ self error: ('Wrong number of arguments in simulated method {1}' translated format: {meth})].
+ (primIndex := meth primitive) > 0 ifTrue:
+ [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments.
+ (self isPrimFailToken: val) ifFalse:
+ [^val]].
+
+ ctxt := self activateMethod: meth withArgs: arguments receiver: rcvr.
+ (primIndex isInteger and: [primIndex > 0]) ifTrue:
+ [ctxt failPrimitiveWith: val].
+
+ ^ctxt!
Item was changed:
----- Method: Context>>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 |
- | meth primIndex val ctxt |
(meth := lookupClass lookupSelector: selector) ifNil:
[selector == #doesNotUnderstand: ifTrue:
[self error: 'Recursive message not understood!!' translated].
^self send: #doesNotUnderstand:
to: rcvr
with: {(Message selector: selector arguments: arguments) lookupClass: lookupClass}
lookupIn: lookupClass].
+ ^ self
+ executeMethod: meth
+ forSelector: selector
+ withArgs: arguments
+ receiver: rcvr!
- (self objectClass: meth) isCompiledCodeClass ifFalse:
- ["Object as Methods (OaM) protocol: 'The contract is that, when the VM encounters an ordinary object (rather than a compiled method) in the method dictionary during lookup, it sends it the special selector #run:with:in: providing the original selector, arguments, and receiver.'. DOI: 10.1145/2991041.2991062."
- ^self send: #run:with:in:
- to: meth
- with: {selector. arguments. rcvr}].
-
- meth numArgs = arguments size ifFalse:
- [^ self error: ('Wrong number of arguments in simulated message {1}' translated format: {selector})].
- (primIndex := meth primitive) > 0 ifTrue:
- [val := self doPrimitive: primIndex method: meth receiver: rcvr args: arguments.
- (self isPrimFailToken: val) ifFalse:
- [^val]].
-
- ctxt := self activateMethod: meth withArgs: arguments receiver: rcvr.
- (primIndex isInteger and: [primIndex > 0]) ifTrue:
- [ctxt failPrimitiveWith: val].
-
- ^ctxt!
Item was changed:
----- Method: Object>>withArgs:executeMethod: (in category 'message handling') -----
withArgs: argArray executeMethod: compiledMethod
"Execute compiledMethod against the receiver and args in argArray"
+ | context |
- | selector |
<primitive: 188>
+ context := thisContext
+ executeMethod: compiledMethod
+ forSelector: Symbol new
+ withArgs: argArray
+ receiver: self.
+ ^ context == thisContext
+ ifTrue: ["quick return" thisContext top]
+ ifFalse: [context jump]!
- selector := Symbol new.
- self class addSelectorSilently: selector withMethod: compiledMethod.
- ^ [self perform: selector withArguments: argArray]
- ensure: [self class basicRemoveSelector: selector]!
Christoph Thiede uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-ct.1450.mcz
==================== Summary ====================
Name: Kernel-ct.1450
Author: ct
Time: 25 March 2022, 12:03:45.256465 am
UUID: 484c3944-1ae9-fa4b-888c-bacd59152bc5
Ancestors: Kernel-nice.1447
Updates comment in TimedOut.
=============== Diff against Kernel-nice.1447 ===============
Item was changed:
Notification subclass: #TimedOut
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Kernel-Exceptions'!
+ !TimedOut commentStamp: 'ct 3/25/2022 00:01' prior: 0!
+ I am signalled by BlockClosure>>#valueWithin:onTimeout: if the receiving block takes too long to execute.
- !TimedOut commentStamp: 'brp 10/21/2004 17:47' prior: 0!
- I am signalled by #duration:timeoutDo: if the receiving block takes too long to execute.
- I am signalled by a watchdog process spawned by #duration:timeoutDo: and caught in the same method.
-
I am not intended to be used elsewhere.!
Christoph Thiede uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-ct.1356.mcz
==================== Summary ====================
Name: Kernel-ct.1356
Author: ct
Time: 28 October 2020, 9:05:21.976652 pm
UUID: 27e8ca85-1191-5b4b-aa8c-92b65e01af50
Ancestors: Kernel-eem.1354
Fixes and refactors ClassBuilder cleanupAndCheckClassHierarchy which was broken due to a missing #informUserDuring: implementation. Also adds progress bars during the operation.
=============== Diff against Kernel-eem.1354 ===============
Item was changed:
----- Method: ClassBuilder class>>checkClassHierarchyConsistency (in category 'cleanup obsolete classes') -----
checkClassHierarchyConsistency
"Check the consistency of the class hierarchy. The class hierarchy is consistent if the following
two logical equivalences hold for classes A and B:
- B is obsolete and 'B superclass' yields A <--> 'A obsoleteSubclasses' contains B
- B is not obsolete and 'B superclass' yields A <--> 'A subclasses' contains B"
+
+ Transcript cr; show: 'Start checking the class hierarchy...'.
+ Smalltalk garbageCollect.
+
+ Metaclass allInstances
+ do: [:meta |
+ meta allInstances do: [:each | self checkClassHierarchyConsistencyFor: each].
+ self checkClassHierarchyConsistencyFor: meta]
+ displayingProgress: 'Validating class hierarchy' translated.
+
+ Transcript show: 'OK'.!
- self informUserDuring:[:bar|
- self checkClassHierarchyConsistency: bar.
- ].!
Item was removed:
- ----- Method: ClassBuilder class>>checkClassHierarchyConsistency: (in category 'cleanup obsolete classes') -----
- checkClassHierarchyConsistency: informer
- "Check the consistency of the class hierarchy. The class hierarchy is consistent if the following
- two logical equivalences hold for classes A and B:
- - B is obsolete and 'B superclass' yields A <--> 'A obsoleteSubclasses' contains B
- - B is not obsolete and 'B superclass' yields A <--> 'A subclasses' contains B"
- | classes |
- Transcript cr; show: 'Start checking the class hierarchy...'.
- Smalltalk garbageCollect.
- classes := Metaclass allInstances.
- classes keysAndValuesDo: [:index :meta |
- informer value:'Validating class hierarchy ', (index * 100 // classes size) printString,'%'.
- meta allInstances do: [:each | self checkClassHierarchyConsistencyFor: each].
- self checkClassHierarchyConsistencyFor: meta.
- ].
- Transcript show: 'OK'.!
Item was changed:
----- Method: ClassBuilder class>>cleanupAndCheckClassHierarchy (in category 'cleanup obsolete classes') -----
cleanupAndCheckClassHierarchy
"Makes the class hierarchy consistent and removes obsolete classes from the SystemDictionary.
Afterwards it checks whether the hierarchy is really consistent."
+
+ Project uiManager informUser: 'Cleaning up class hierarchy...' translated during: [
+ Transcript cr; show: '*** Before cleaning up ***'.
+ self countReallyObsoleteClassesAndMetaclasses.
+ self cleanupClassHierarchy.
+ self checkClassHierarchyConsistency.
+ Transcript cr; cr; show: '*** After cleaning up ***'.
+ self countReallyObsoleteClassesAndMetaclasses].!
- self informUserDuring:[:bar|
- self cleanupAndCheckClassHierarchy: bar.
- ].
- !
Item was removed:
- ----- Method: ClassBuilder class>>cleanupAndCheckClassHierarchy: (in category 'cleanup obsolete classes') -----
- cleanupAndCheckClassHierarchy: informer
- "Makes the class hierarchy consistent and removes obsolete classes from the SystemDictionary.
- Afterwards it checks whether the hierarchy is really consistent."
-
- Transcript cr; show: '*** Before cleaning up ***'.
- self countReallyObsoleteClassesAndMetaclasses.
- self cleanupClassHierarchy: informer.
- self checkClassHierarchyConsistency: informer.
- Transcript cr; cr; show: '*** After cleaning up ***'.
- self countReallyObsoleteClassesAndMetaclasses.!
Item was changed:
----- Method: ClassBuilder class>>cleanupClassHierarchy (in category 'cleanup obsolete classes') -----
cleanupClassHierarchy
"Makes the class hierarchy consistent and removes obsolete classes from the SystemDictionary."
+
+ Transcript cr; show: 'Start fixing the class hierarchy and cleaning up...'.
+ Smalltalk garbageCollect.
+
+ Metaclass allInstances
+ do: [:meta |
+ "Check classes before metaclasses (because Metaclass>>isObsolete checks whether the related class is obsolete)"
+ meta allInstances do: [:each | self cleanupClassHierarchyFor: each].
+ self cleanupClassHierarchyFor: meta]
+ displayingProgress: 'Fixing class hierarchy' translated.
+
+ Transcript show: 'DONE'.!
- self informUserDuring:[:bar|
- self cleanupClassHierarchy: bar.
- ].!
Item was removed:
- ----- Method: ClassBuilder class>>cleanupClassHierarchy: (in category 'cleanup obsolete classes') -----
- cleanupClassHierarchy: informer
- "Makes the class hierarchy consistent and removes obsolete classes from the SystemDictionary."
- | classes |
- Transcript cr; show: 'Start fixing the class hierarchy and cleaning up...'.
- Smalltalk garbageCollect.
- classes := Metaclass allInstances.
- classes keysAndValuesDo: [:index :meta |
- informer value:'Fixing class hierarchy ', (index * 100 // classes size) printString,'%'.
- "Check classes before metaclasses (because Metaclass>>isObsolete
- checks whether the related class is obsolete)"
- meta allInstances do: [:each | self cleanupClassHierarchyFor: each].
- self cleanupClassHierarchyFor: meta.
- ].
- Transcript show: 'DONE'.!
Christoph Thiede uploaded a new version of Kernel to project The Treated Inbox:
http://source.squeak.org/treated/Kernel-ct.1409.mcz
==================== Summary ====================
Name: Kernel-ct.1409
Author: ct
Time: 22 August 2021, 6:18:06.141465 pm
UUID: 003f761f-f99d-c245-a431-dcf1cb8405ba
Ancestors: Kernel-eem.1408
Fixes a simulation bug when returning from a sender that is a bottom context.
Examples to reproduce:
- sender := thisContext swapSender: nil.
^1
- sender := thisContext swapSender: nil.
true ifTrue: [^ 1].
- [sender := thisContext swapSender: nil.
true ifTrue: [^ 1]] value.
Without this patch, #return:from: would return nil instead of activating #cannotReturn: so simulating instead of executing e.g. the first example would not open the expected "computation terminated" debugger. See http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-May/215762.html for more information.
Thanks to Jaromir (jar) for pointing to this bug!
=============== Diff against Kernel-eem.1408 ===============
Item was changed:
----- Method: Context>>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 |
aSender isDead ifTrue:
[^self send: #cannotReturn: to: self with: {value}].
newTop := aSender sender.
+ newTop ifNil:
+ [^self send: #cannotReturn: to: self with: {value}].
(self findNextUnwindContextUpTo: newTop) ifNotNil:
[:unwindProtectCtxt|
^self send: #aboutToReturn:through: to: self with: {value. unwindProtectCtxt}].
self releaseTo: newTop.
newTop ifNotNil: [newTop push: value].
^newTop!