[squeak-dev] The Inbox: Environments-ul.43.mcz

Frank Shearar frank.shearar at gmail.com
Mon Dec 30 09:58:00 UTC 2013


On 29 December 2013 23:33, Levente Uzonyi <leves at elte.hu> wrote:
> On Sun, 29 Dec 2013, Frank Shearar wrote:
>
>> "Radical" would be the #becomeForwards: calls?
>
>
> No. Radical in the sense that those three methods are not just forwarders
> anymore. A bug in any of them can have bad consequences.

Right.

>> If I read it right, this commit "just" updates the various caches
>> (references, exports), and updates undeclared, when something's added
>> to the Environment. It then also ensures that _removed_ bindings are
>> removed from the various caches. Should #removeKey:ifAbsent: possibly
>> update undeclared? Couldn't you still have CompiledMethods floating
>> around holding references to a class you just deleted from the
>> Environment?
>
>
> No, code which uses #removeKey:ifAbsent: also updates Undeclared.

Er, of course, because had I been thinking properly, I'd have realised
that the receiver is an Environment, not an IdentityDictionary.

>> Lastly, the postscript runs over all globals, finds those globals with
>> more than one binding, and forcibly unifies them all (through
>> #becomeForward:) to point to whatever Smalltalk globals points to.
>
>
> The postscript also fixes the exports and cleans the imports.
>
>
>>
>> I'd be interested in seeing tests exercising these changes directly,
>> but I realise that partly they will be, by virtue of making the
>> current test suite work.
>
>
> We definitely need more tests for Environments.
>
>
> Levente
>
>
>>
>> frank
>>
>> On 29 December 2013 21:28, Levente Uzonyi <leves at elte.hu> wrote:
>>>
>>> I've uploaded this version to the Inbox to let you review it before I
>>> push
>>> it to the Trunk. It fixes the most urgent issues of Environments, but it
>>> also includes some "radical" changes, and a "high impact" postscript.
>>>
>>>
>>> Levente
>>>
>>>
>>> On Sun, 29 Dec 2013, commits at source.squeak.org wrote:
>>>
>>>> A new version of Environments was added to project The Inbox:
>>>> http://source.squeak.org/inbox/Environments-ul.43.mcz
>>>>
>>>> ==================== Summary ====================
>>>>
>>>> Name: Environments-ul.43
>>>> Author: ul
>>>> Time: 29 December 2013, 10:04:32.454 pm
>>>> UUID: a91a7c62-f608-48aa-b296-2d541c0083f5
>>>> Ancestors: Environments-ul.42
>>>>
>>>> Fixed a typo in the postscript.
>>>>
>>>> =============== Diff against Environments-ul.40 ===============
>>>>
>>>> Item was changed:
>>>>  ----- Method: Environment>>at:ifAbsentPut: (in category 'emulating')
>>>> -----
>>>>  at: aSymbol ifAbsentPut: aBlock
>>>> +
>>>> +       ^declarations
>>>> -       ^ declarations
>>>>                 at: aSymbol
>>>> +               ifAbsent: [ self at: aSymbol put: aBlock value ]!
>>>> -               ifAbsentPut: aBlock!
>>>>
>>>> Item was changed:
>>>>  ----- Method: Environment>>at:put: (in category 'emulating') -----
>>>>  at: aSymbol put: anObject
>>>> +
>>>> +       | binding newBinding |
>>>> +       newBinding := aSymbol => anObject.
>>>> +       binding := declarations associationAt: aSymbol ifAbsent: [ nil
>>>> ].
>>>> +       binding ifNotNil: [
>>>> +               binding class == newBinding class
>>>> +                       ifTrue: [ binding value: anObject ]
>>>> +                       ifFalse: [ binding becomeForward: newBinding ].
>>>> +               ^anObject ].
>>>> +       binding := undeclared associationAt: aSymbol ifAbsent: [ nil ].
>>>> +       binding
>>>> +               ifNil: [ binding := newBinding ]
>>>> +               ifNotNil: [
>>>> +                       undeclared removeKey: aSymbol.
>>>> +                       binding class == newBinding class
>>>> +                               ifTrue: [ binding value: anObject ]
>>>> +                               ifFalse: [ binding becomeForward:
>>>> newBinding ] ].
>>>> +       declarations add: binding.
>>>> +       references add: binding.
>>>> +       exports bind: binding. "Do we really want this?"
>>>> +       ^anObject
>>>> -       | binding |
>>>> -       (declarations includesKey: aSymbol)
>>>> -               ifTrue: [declarations at: aSymbol put: anObject]
>>>> -               ifFalse:
>>>> -                       [(undeclared includesKey: aSymbol)
>>>> -                               ifTrue:
>>>> -                                       [declarations declare: aSymbol
>>>> from: undeclared.
>>>> -                                       declarations at: aSymbol put:
>>>> anObject]
>>>> -                               ifFalse:
>>>> -                                       [binding := aSymbol => anObject.
>>>> -                                       declarations add: binding.
>>>> -                                       exports bind: binding]].
>>>> -       ^ anObject
>>>>  !
>>>>
>>>> Item was changed:
>>>>  ----- Method: Environment>>removeKey:ifAbsent: (in category
>>>> 'emulating')
>>>> -----
>>>>  removeKey: key ifAbsent: aBlock
>>>> +
>>>> +       (declarations includesKey: key) ifFalse: [ ^aBlock value ].
>>>> +       references removeKey: key ifAbsent: [].
>>>> +       public removeKey: key ifAbsent: [].
>>>> +       ^declarations removeKey: key!
>>>> -       self flag: #review.
>>>> -       ^ declarations removeKey: key ifAbsent: aBlock!
>>>>
>>>> Item was changed:
>>>> + (PackageInfo named: 'Environments') postscript: '|
>>>> globalsWithMultipleBindings |
>>>> + "Fix exports."
>>>> + Smalltalk globals exports instVarNamed: #namespace put: Smalltalk
>>>> globals public.
>>>> + "Fix imports."
>>>> + (Smalltalk globals instVarNamed: #imports) instVarNamed: #next put:
>>>> nil.
>>>> + "Unify globals."
>>>> + globalsWithMultipleBindings := Dictionary new.
>>>> + Binding allSubInstances do: [ :binding |
>>>> +       (globalsWithMultipleBindings at: binding key ifAbsentPut: [
>>>> IdentitySet new ]) add: binding ].
>>>> + globalsWithMultipleBindings := globalsWithMultipleBindings select: [
>>>> :each | each size > 1 ].
>>>> + globalsWithMultipleBindings keysAndValuesDo: [ :name :set |
>>>> +       | realBinding |
>>>> +       realBinding := Smalltalk associationAt: name ifAbsent: [ nil ].
>>>> +       realBinding ifNotNil: [
>>>> +               set do: [ :each |
>>>> +                       each == realBinding ifFalse: [ each
>>>> becomeForward:
>>>> realBinding ] ] ] ]'!
>>>> - (PackageInfo named: 'Environments') postscript: '"below, add code to
>>>> be
>>>> run after the loading of this package"
>>>> -
>>>> - | allAliases toBeRecompiled undesirableAliases |
>>>> -
>>>> - "Collect the CompiledMethods pointing to an Alias"
>>>> - allAliases := Alias allInstances.
>>>> - toBeRecompiled := CompiledMethod allInstances select: [:c | c
>>>> isInstalled and: [allAliases anySatisfy: [:a | c pointsTo: a]]].
>>>> -
>>>> - "Collect the Aliases pointing to some class binding in the same
>>>> Environment with same name"
>>>> - undesirableAliases := (Smalltalk globals instVarNamed: ''references'')
>>>> associations select: [:e |
>>>> -       e class = Alias and: [e key = e source key
>>>> -               and: [(Smalltalk globals instVarNamed: ''declarations'')
>>>> associations includes: e source]]].
>>>> -
>>>> - "Replace the undesirable Aliases with their source binding"
>>>> - undesirableAliases do: [:a | a becomeForward: a source].
>>>> -
>>>> - "Rehash the references because they pointed to those Aliases - hope
>>>> there''s nothing else to rehash"
>>>> - (Smalltalk globals instVarNamed: ''references'') rehash.
>>>> -
>>>> - "Recompile the CompiledMethod that used to point to an Alias, because
>>>> the bytecodes do change"
>>>> - Symbol rehash.
>>>> - toBeRecompiled do: [:c | c methodClass recompile: c selector].
>>>> -
>>>> - allAliases := toBeRecompiled := undesirableAliases := nil.
>>>> - Smalltalk garbageCollect.
>>>> - Alias allInstances size.
>>>> - '!


More information about the Squeak-dev mailing list