Nicolas Cellier uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-nice.482.mcz ==================== Summary ==================== Name: Kernel-nice.482 Author: nice Time: 22 August 2010, 9:12:15.834 pm UUID: 0cda1747-d4ad-4e81-b7f9-a085602e5344 Ancestors: Kernel-nice.481 Fix WeakMessageSends Part 1. Thanks to Juan, see http://bugs.squeak.org/view.php?id=7352 I could nor resist and added my own simplifications There will be a second part for this fix. =============== Diff against Kernel-nice.481 =============== Item was added: + ----- Method: WeakMessageSend>>withEnsuredReceiverAndArgumentsDo:otherwise: (in category 'private') ----- + withEnsuredReceiverAndArgumentsDo: aBlock otherwise: altBlock + "Grab real references to receiver and arguments. If they still exist, evaluate aBlock." + + "Return if my receiver has gone away" + | r a | + r := self receiver. + r ifNil: [ ^altBlock value ]. + + + "Make sure that my arguments haven't gone away" + a := Array withAll: arguments. + a with: shouldBeNil do: [ :arg :flag | + arg ifNil: [ flag ifFalse: [ ^altBlock value ]] + ]. + + ^aBlock value: r value: a! Item was changed: ----- Method: WeakMessageSend>>valueWithArguments: (in category 'evaluating') ----- valueWithArguments: anArray + ^ self valueWithArguments: anArray otherwise: []! - self ensureReceiverAndArguments ifFalse: [ ^nil ]. - ^ self receiver - perform: selector - withArguments: (self collectArguments: anArray)! Item was added: + ----- Method: MessageSend>>valueOtherwise: (in category 'evaluating') ----- + valueOtherwise: aBlock + "Send the message and answer the return value" + + ^self value! Item was added: + ----- Method: WeakMessageSend>>withEnsuredReceiverDo:otherwise: (in category 'private') ----- + withEnsuredReceiverDo: aBlock otherwise: altBlock + "Grab a real reference to receive. If still there, evaluate aBlock. + Use altBlock if my receiver has gone away." + ^self receiver + ifNil: [ altBlock value ] + ifNotNil: [:r | aBlock value: r ]! Item was changed: ----- Method: WeakActionSequence>>valueWithArguments: (in category 'evaluating') ----- valueWithArguments: anArray - "Return the last result" + ^self inject: nil into: [ :previousAnswer :each | + each valueWithArguments: anArray otherwise: [ previousAnswer ]]! - | answer | - self do: - [:each | - each isValid ifTrue: [answer := each valueWithArguments: anArray]]. - ^answer! Item was added: + ----- Method: WeakMessageSend>>valueOtherwise: (in category 'evaluating') ----- + valueOtherwise: aBlock + ^ arguments + ifNil: [ + self withEnsuredReceiverDo: [ :r | r perform: selector ] otherwise: [ aBlock value ]] + ifNotNil: [ + self + withEnsuredReceiverAndArgumentsDo: [ :r :a | + r + perform: selector + withArguments: a ] + otherwise: [ aBlock value ]]! Item was added: + ----- Method: MessageSend>>isReceiverOrAnyArgumentGarbage (in category 'private') ----- + isReceiverOrAnyArgumentGarbage + ^false! Item was changed: ----- Method: WeakMessageSend>>asMinimalRepresentation (in category 'converting') ----- asMinimalRepresentation + ^self isReceiverOrAnyArgumentGarbage + ifTrue: [ nil ] + ifFalse: [ self ]! - self isReceiverOrAnyArgumentGarbage - ifTrue: [^nil] - ifFalse:[^self].! Item was added: + ----- Method: MessageSend>>valueWithArguments:otherwise: (in category 'evaluating') ----- + valueWithArguments: anArray otherwise: aBlock + + ^ self valueWithArguments: anArray! Item was changed: ----- Method: Object>>actionForEvent:ifAbsent: (in category 'events-accessing') ----- actionForEvent: anEventSelector ifAbsent: anExceptionBlock "Answer the action to be evaluated when <anEventSelector> has been triggered." | actions | actions := self actionMap at: anEventSelector asSymbol ifAbsent: [nil]. + ^actions ifNil: [anExceptionBlock value]! - actions ifNil: [^anExceptionBlock value]. - ^ actions asMinimalRepresentation! Item was changed: ----- Method: Object>>actionForEvent: (in category 'events-accessing') ----- actionForEvent: anEventSelector "Answer the action to be evaluated when <anEventSelector> has been triggered." + ^self actionMap - | actions | - actions := self actionMap at: anEventSelector asSymbol + ifAbsent: [nil]! - ifAbsent: [nil]. - actions ifNil: [^nil]. - ^ actions asMinimalRepresentation! Item was changed: ----- Method: WeakActionSequence>>asMinimalRepresentation (in category 'converting') ----- asMinimalRepresentation | valid | + valid := self reject: [:e | e isReceiverOrAnyArgumentGarbage ]. - valid := self select: [:e | e isValid ]. valid size = 0 + ifTrue: [ ^nil ]. - ifTrue: [^nil]. valid size = 1 + ifTrue: [ ^valid first ]. - ifTrue: [^valid first]. ^valid! Item was changed: ----- Method: Object>>setActionSequence:forEvent: (in category 'events-accessing') ----- setActionSequence: actionSequence forEvent: anEventSelector + | action | + "This is a good time to compact the action sequence of old, garbage collected stuff." + action := actionSequence asMinimalRepresentation. + action + ifNil: [ self removeActionsForEvent: anEventSelector] + ifNotNil: [ + self updateableActionMap + at: anEventSelector asSymbol + put: action]! - | action | - action := actionSequence asMinimalRepresentation. - action == nil - ifTrue: - [self removeActionsForEvent: anEventSelector] - ifFalse: - [self updateableActionMap - at: anEventSelector asSymbol - put: action]! Item was changed: ----- Method: WeakMessageSend>>value (in category 'evaluating') ----- value + ^self valueOtherwise: []! - ^ arguments isNil - ifTrue: [self ensureReceiver - ifTrue: [self receiver perform: selector] ifFalse: []] - ifFalse: [self ensureReceiverAndArguments - ifTrue: [self receiver - perform: selector - withArguments: (Array withAll: arguments)] ifFalse: []]! Item was added: + ----- Method: WeakMessageSend>>valueWithArguments:otherwise: (in category 'evaluating') ----- + valueWithArguments: anArray otherwise: aBlock + | argsToUse | + + "Safe to use, because they are built before ensureing receiver and args..." + argsToUse := self collectArguments: anArray. + ^ self + withEnsuredReceiverAndArgumentsDo: [ :r :a | + r + perform: selector + withArguments: argsToUse ] + otherwise: [ aBlock value ]! Item was changed: ----- Method: WeakActionSequence>>value (in category 'evaluating') ----- value + "Answer the result of evaluating the elements of the receiver. - "Answer the result of evaluating the elements of the receiver. Actually, return just the last result." + ^self inject: nil into: [ :previousAnswer :each | + each valueOtherwise: [ previousAnswer ]].! - | answer | - self do: - [:each | each isValid ifTrue: [answer := each value]]. - ^answer! |
Free forum by Nabble | Edit this page |