[squeak-dev] Re: autopsy of a nasty environment bug

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Tue Oct 25 13:11:28 UTC 2016


Some lessons from this snippet:
- if several undeclared share the same binding, then we should rebind all
at once, not just some
- the undeclared shall better point weakly to the bindings, letting them
being garbaged collected if possible
- what do we expect when we have two unrelated bindings #Foo->nil in envA
undeclared and envB undeclared, then import envA into envB (envB import:
envA)?
  I would expect (envB undeclared associationAt: #Foo) becomeForward: (envA
undeclared associationAt: #Foo)...
- moving a binding from undeclared to some classPool/sharedPool
(PoolDictionary) is completely ignoring the variable scope by now, which
may lead to erroneous re-binding.

I don't see obvious solution for the last point (testing that all
references to the binding are reachable by the defining class scope thru
methodDictionary and subclasses methodDictionary?).
For PoolDictionary, it's even more tough (going thru all classes sharing
this poolDictionary).

I didn't see any attempt at handling the case when both environment A & B
declare a variable Foo, and environment C imports both A and B...
This is another problem but may lead to other requirements on undeclared
handling.

2016-10-25 10:30 GMT+02:00 Nicolas Cellier <
nicolas.cellier.aka.nice at gmail.com>:

>
>     "Create a foreign environment importing all from Smalltalk globals"
>     foreign := Environment withName: #Foreign.
>     foreign exportSelf.
>     foreign import: Smalltalk globals.
>
>     "Bind a new global"
>     fooKey := #ClassVarScopeFoo.
>     fooValue := Smalltalk globals at: fooKey put: Object basicNew.
>     fooBinding := Smalltalk globals bindingOf: fooKey.
>     self assert: (foreign bindingOf: fooKey) == fooBinding.
>
>     "Unbind the global: it is moved to, and shared by both undeclared"
>     Smalltalk globals removeKey: fooKey.
>     self assert: (Smalltalk globals undeclared associationAt: fooKey) ==
> fooBinding.
>     self assert: (foreign undeclared associationAt: fooKey) == fooBinding.
>
>     "Create a class var: the undeclared binding is moved to classPool.
>     This is questionable, it was a global with potentially
> larger/different scope."
>     parent := Object
>         subclass: #ClassVarScopeParent
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'Dummy-Tests-Class'.
>     child := parent
>         subclass: #ClassVarScopeChild
>         instanceVariableNames: ''
>         classVariableNames: 'ClassVarScopeFoo'
>         poolDictionaries: ''
>         category: 'Dummy-Tests-Class'.
>     self assert: (child classPool associationAt: fooKey) == fooBinding.
>
>     "The global is no more in Smalltalk globals undeclared"
>     self assert: (Smalltalk globals undeclared includesKey: fooKey) not.
>     "But it is still in foreign undeclared"
>     self assert: (foreign undeclared associationAt: fooKey) == fooBinding.
>
>     "Rebind a new global"
>     fooValue := Smalltalk globals at: fooKey put: Object basicNew.
>     globalFooBinding := Smalltalk globals bindingOf: fooKey.
>
>     "The binding has been removed from foreign undeclared"
>     self assert: (foreign undeclared includesKey: fooKey) not.
>     self assert: (foreign bindingOf: fooKey) == globalFooBinding.
>
>     "But because #showBinding: did use a becomeForward: the class pool and
> global bindings are now surprisingly fused.
>     That explains that a foreign environment importing Smalltalk globals
> is enough to make ClassVarScopeTest fail"
>     self assert: globalFooBinding == fooBinding.
>     self assert: (child classPool associationAt: fooKey) ==
> globalFooBinding.
>
>     "save our souls"
>     classes := { child. parent }.
>     child := parent := nil.
>     classes do: [ :each |
>         each
>             removeFromChanges;
>             removeFromSystemUnlogged ].
>     classes := nil.
>     Smalltalk globals removeKey: fooKey.
>     foreign destroy.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20161025/b9639c47/attachment.htm


More information about the Squeak-dev mailing list