[Pharo4] First Class Global Variables
Hi, If we have meta-object describing (and thus having the power to change the semantics of) instance variables, we need the same for Globals. I think the easiest is to just re-use the object hat is already there: the âbindingâ, that is, the association from the dictionary where the global lives (e.g. the classPool for class vars, Smalltalk globals for true globals, and so on). SystemVersion bindingOf: âCurrent' The VM just cares that it is an assoiation (actually, it just care that there are two fields, but the rest of the image cares about value and keyâ¦) -> we can make a subclass of Association -> we can have the compiler forward code generation to the object that describes the global -> we can add a nice MOP API: #read and #write: (instead of #value and #value:) -> Programmers can subclass the GlobalVariable and change #read and #write like they want (or override the code gen methods) as in Slots. The only drawback is that you can not add an instance variables, I think, to check⦠maybe it even works? If not, there are ways around that e.g. using some fancy Slot that does not need an ivar but uses a weak dictionary in a class variable, for example). Thus: it would be fairly easy to have the class vars be as flexible as the slots⦠and then e.g. you will be able to put breakpoints and watchers on class vars. You could even define globals with special behaviour the same way as you do with Slots. Marcus
Sounds good. Could you read the paper guille sent to esug on the analysis use of sharedpools because having first class instance variables can really help us to make the system more explicit. Right now we have tons of different caches way to expression session reinitialization recreation on load (fuel and other). Stef On 3/7/14 17:51, Marcus Denker wrote:
Hi,
If we have meta-object describing (and thus having the power to change the semantics of) instance variables, we need the same for Globals.
I think the easiest is to just re-use the object hat is already there: the âbindingâ, that is, the association from the dictionary where the global lives (e.g. the classPool for class vars, Smalltalk globals for true globals, and so on).
SystemVersion bindingOf: âCurrent'
The VM just cares that it is an assoiation (actually, it just care that there are two fields, but the rest of the image cares about value and keyâ¦)
-> we can make a subclass of Association -> we can have the compiler forward code generation to the object that describes the global -> we can add a nice MOP API: #read and #write: (instead of #value and #value:) -> Programmers can subclass the GlobalVariable and change #read and #write like they want (or override the code gen methods) as in Slots.
The only drawback is that you can not add an instance variables, I think, to check⦠maybe it even works? If not, there are ways around that e.g. using some fancy Slot that does not need an ivar but uses a weak dictionary in a class variable, for example).
Thus: it would be fairly easy to have the class vars be as flexible as the slots⦠and then e.g. you will be able to put breakpoints and watchers on class vars. You could even define globals with special behaviour the same way as you do with Slots.
Marcus
Hi Classes are global variables too. How it related here? And what about environments to support some kind of namespaces? Do you have plan for this? Best regards Denis 2014-07-03 19:51 GMT+04:00 Marcus Denker <marcus.denker@inria.fr>:
Hi,
If we have meta-object describing (and thus having the power to change the semantics of) instance variables, we need the same for Globals.
I think the easiest is to just re-use the object hat is already there: the âbindingâ, that is, the association from the dictionary where the global lives (e.g. the classPool for class vars, Smalltalk globals for true globals, and so on).
SystemVersion bindingOf: âCurrent'
The VM just cares that it is an assoiation (actually, it just care that there are two fields, but the rest of the image cares about value and keyâ¦)
-> we can make a subclass of Association -> we can have the compiler forward code generation to the object that describes the global -> we can add a nice MOP API: #read and #write: (instead of #value and #value:) -> Programmers can subclass the GlobalVariable and change #read and #write like they want (or override the code gen methods) as in Slots.
The only drawback is that you can not add an instance variables, I think, to check⦠maybe it even works? If not, there are ways around that e.g. using some fancy Slot that does not need an ivar but uses a weak dictionary in a class variable, for example).
Thus: it would be fairly easy to have the class vars be as flexible as the slots⦠and then e.g. you will be able to put breakpoints and watchers on class vars. You could even define globals with special behaviour the same way as you do with Slots.
Marcus
On 04 Jul 2014, at 08:21, Denis Kudriashov <dionisiydk@gmail.com> wrote:
Hi
Classes are global variables too. How it related here?
Yes, they are defined by the âSmalltalk globalsâ dictionary. To read a Global the method has the binding (the association from that global dictionary) in itâs literal frame and uses the âpush/pop LiteralVaribleâ bytecode which pushes (or stores into) the value of the binding.
And what about environments to support some kind of namespaces? Do you have plan for this?
We need them but I need to first finish other things... Marcus
On 03 Jul 2014, at 17:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
If we have meta-object describing (and thus having the power to change the semantics of) instance variables, we need the same for Globals.
I think the easiest is to just re-use the object hat is already there: the âbindingâ, that is, the association from the dictionary where the global lives (e.g. the classPool for class vars, Smalltalk globals for true globals, and so on).
SystemVersion bindingOf: âCurrent'
The VM just cares that it is an assoiation (actually, it just care that there are two fields, but the rest of the image cares about value and keyâ¦)
-> we can make a subclass of Association -> we can have the compiler forward code generation to the object that describes the global -> we can add a nice MOP API: #read and #write: (instead of #value and #value:) -> Programmers can subclass the GlobalVariable and change #read and #write like they want (or override the code gen methods) as in Slots.
I have added a first GlobalVar hierarchy⦠it has already the code generation methods but Opal is not yet forwarding code generation (and the compiler does not yet compile bindings with the subclass). Marcus
I did not read the code in detail, but the behavior works beautifully now! Thanks! Doru On Fri, Jul 4, 2014 at 10:24 AM, Marcus Denker <marcus.denker@inria.fr> wrote:
On 03 Jul 2014, at 17:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
If we have meta-object describing (and thus having the power to change the semantics of) instance variables, we need the same for Globals.
I think the easiest is to just re-use the object hat is already there: the âbindingâ, that is, the association from the dictionary where the global lives (e.g. the classPool for class vars, Smalltalk globals for true globals, and so on).
SystemVersion bindingOf: âCurrent'
The VM just cares that it is an assoiation (actually, it just care that there are two fields, but the rest of the image cares about value and keyâ¦)
-> we can make a subclass of Association -> we can have the compiler forward code generation to the object that describes the global -> we can add a nice MOP API: #read and #write: (instead of #value and #value:) -> Programmers can subclass the GlobalVariable and change #read and #write like they want (or override the code gen methods) as in Slots.
I have added a first GlobalVar hierarchy⦠it has already the code generation methods but Opal is not yet forwarding code generation (and the compiler does not yet compile bindings with the subclass).
Marcus
-- www.tudorgirba.com "Every thing has its own flow"
On 04 Jul 2014, at 10:24, Marcus Denker <marcus.denker@inria.fr> wrote:
On 03 Jul 2014, at 17:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
If we have meta-object describing (and thus having the power to change the semantics of) instance variables, we need the same for Globals.
I think the easiest is to just re-use the object hat is already there: the âbindingâ, that is, the association from the dictionary where the global lives (e.g. the classPool for class vars, Smalltalk globals for true globals, and so on).
SystemVersion bindingOf: âCurrent'
The VM just cares that it is an assoiation (actually, it just care that there are two fields, but the rest of the image cares about value and keyâ¦)
-> we can make a subclass of Association -> we can have the compiler forward code generation to the object that describes the global -> we can add a nice MOP API: #read and #write: (instead of #value and #value:) -> Programmers can subclass the GlobalVariable and change #read and #write like they want (or override the code gen methods) as in Slots.
I have added a first GlobalVar hierarchy⦠it has already the code generation methods but Opal is not yet forwarding code generation (and the compiler does not yet compile bindings with the subclass).
update 40 095 contains changes to deeper integrate first class variables (Slots and first class Globals) int the system. 1) Both the binding in "Smalltalk globals" as well as all Class Variables are now instances of GlobalVariable. (I want to have both GlobalVariable and ClassVariable, but that is for later) e.g. Object binding class (SmalltalkImage classVariableNamed: 'ShutDownList') class all the Slots and Globals understand #definingClass -> returns the class defining the variable or "nil" for true globals #usingMethods -> all methods reading or writing the variable e.g. try (Point slotNamed: #x) usingMethods Next: -> Hook Opal to forward code generation for globals to the meta object -> use ClassVariable for class variables Marcus
I have added a first GlobalVar hierarchy⦠it has already the code generation methods but Opal is not yet forwarding code generation (and the compiler does not yet compile bindings with the subclass).
update 40 095 contains changes to deeper integrate first class variables (Slots and first class Globals) int the system.
1) Both the binding in "Smalltalk globals" as well as all Class Variables are now instances of GlobalVariable. (I want to have both GlobalVariable and ClassVariable, but that is for later)
e.g.
Object binding class (SmalltalkImage classVariableNamed: 'ShutDownList') class
all the Slots and Globals understand
#definingClass -> returns the class defining the variable or "nil" for true globals #usingMethods -> all methods reading or writing the variable
e.g. try (Point slotNamed: #x) usingMethods
Next:
-> Hook Opal to forward code generation for globals to the meta object Done (not yet integrated): https://pharo.fogbugz.com/f/cases/13584/Forward-code-generation-for-Globals-...
-> use ClassVariable for class variables Done (not yet integrated): https://pharo.fogbugz.com/f/cases/13586/Class-Variables-should-be-ClassVaria...
Marcus
On 18 Jul 2014, at 08:14, Marcus Denker <marcus.denker@inria.fr> wrote:
I have added a first GlobalVar hierarchy⦠it has already the code generation methods but Opal is not yet forwarding code generation (and the compiler does not yet compile bindings with the subclass).
update 40 095 contains changes to deeper integrate first class variables (Slots and first class Globals) int the system.
1) Both the binding in "Smalltalk globals" as well as all Class Variables are now instances of GlobalVariable. (I want to have both GlobalVariable and ClassVariable, but that is for later)
e.g.
Object binding class (SmalltalkImage classVariableNamed: 'ShutDownList') class
all the Slots and Globals understand
#definingClass -> returns the class defining the variable or "nil" for true globals #usingMethods -> all methods reading or writing the variable
e.g. try (Point slotNamed: #x) usingMethods
Next:
-> Hook Opal to forward code generation for globals to the meta object Done (not yet integrated): https://pharo.fogbugz.com/f/cases/13584/Forward-code-generation-for-Globals-...
-> use ClassVariable for class variables Done (not yet integrated): https://pharo.fogbugz.com/f/cases/13586/Class-Variables-should-be-ClassVaria...
This is now in Pharo4 update 097 Marcus
On 18 Jul 2014, at 09:47, Marcus Denker <marcus.denker@inria.fr> wrote:
On 18 Jul 2014, at 08:14, Marcus Denker <marcus.denker@inria.fr> wrote:
I have added a first GlobalVar hierarchy⦠it has already the code generation methods but Opal is not yet forwarding code generation (and the compiler does not yet compile bindings with the subclass).
update 40 095 contains changes to deeper integrate first class variables (Slots and first class Globals) int the system.
1) Both the binding in "Smalltalk globals" as well as all Class Variables are now instances of GlobalVariable. (I want to have both GlobalVariable and ClassVariable, but that is for later)
e.g.
Object binding class (SmalltalkImage classVariableNamed: 'ShutDownList') class
all the Slots and Globals understand
#definingClass -> returns the class defining the variable or "nil" for true globals #usingMethods -> all methods reading or writing the variable
in Pharo4 #102: -> CompiledMethod now has working #readsSlot:, #writesSlot: besides #accessesSlot: (for speed we could dispatch them to the Slot so slots could use faster ways than AST searching⦠but then, speed is fast after the AST is cached⦠#usingMethods already does that for IvarSlot to avoid creating the AST for all methods of a class, which indeed is slow the first time) e.g. (Point>>#setX:setY:) writesSlot: (Point slotNamed: #y) â> true Point methodsWritingSlot: (Point slotNamed: #x) â> {Point>>#bitShiftPoint:. Point>>#setX:setY:. Point>>#setR:degrees:} (Point slotNamed: #x) usingMethods size â> 60 (SmalltalkImage classVariableNamed: 'ShutDownList') usingMethods size â> 7 -> after having fun with #usingMethods on variables, I added #senders and #implementors to Symbol. So now one can use (e.g. nice for doing Demos): #+ senders size. #+ implementors inspect Marcus
Hello, One of the questions with having meta objects for variables (Slots and Globals) is: For what is is good? Here is one example⦠in early stage but working. Imagine you want to âhook intoâ instance variable access. It can be done with e.g. bytecode manipulation, or on the AST level. But that is far from nice. With the new first class variables, there is now a fun way to do it: MetaLinks. Make a class TT with an instance var âtâ and add an accessor. Now we can define a MetaLink: it describes a call to a meta object that we wan to do before, after or instead of what our variable normally does. (default is #before): | link | link := MetaLink new metaObject: Halt; selector: #now. This link says: âdo a Halt now before where I will get installedâ. To install the link, just get the Slot meta object and set it using #link: (TT slotNamed: #t) link: link. This sets the link by replacing the Slot with a LinkWrapper Slot, and then recompiles all using methods. Thus evaluating: TT new t will get you a #halt. Lots of things are not yet implemented (multiple links, uninstall, arguments,â¦) but it starts to show how simple one can do quite powerful things. Marcus
Man, this is exciting! A strong reason to already switch to Pharo 4 :) Doru On Mon, Jul 21, 2014 at 11:28 AM, Marcus Denker <marcus.denker@inria.fr> wrote:
Hello,
One of the questions with having meta objects for variables (Slots and Globals) is: For what is is good?
Here is one example⦠in early stage but working.
Imagine you want to âhook intoâ instance variable access. It can be done with e.g. bytecode manipulation, or on the AST level. But that is far from nice.
With the new first class variables, there is now a fun way to do it: MetaLinks.
Make a class TT with an instance var âtâ and add an accessor.
Now we can define a MetaLink: it describes a call to a meta object that we wan to do before, after or instead of what our variable normally does. (default is #before):
| link | link := MetaLink new metaObject: Halt; selector: #now.
This link says: âdo a Halt now before where I will get installedâ.
To install the link, just get the Slot meta object and set it using #link:
(TT slotNamed: #t) link: link.
This sets the link by replacing the Slot with a LinkWrapper Slot, and then recompiles all using methods.
Thus evaluating:
TT new t
will get you a #halt.
Lots of things are not yet implemented (multiple links, uninstall, arguments,â¦) but it starts to show how simple one can do quite powerful things.
Marcus
-- www.tudorgirba.com "Every thing has its own flow"
Super cool, and then we have to integrate with the metaLink based breakpoints (almost there), and we can start a party :D 2014-07-21 11:33 GMT+02:00 Tudor Girba <tudor@tudorgirba.com>:
Man, this is exciting!
A strong reason to already switch to Pharo 4 :)
Doru
On Mon, Jul 21, 2014 at 11:28 AM, Marcus Denker <marcus.denker@inria.fr> wrote:
Hello,
One of the questions with having meta objects for variables (Slots and Globals) is: For what is is good?
Here is one example⦠in early stage but working.
Imagine you want to âhook intoâ instance variable access. It can be done with e.g. bytecode manipulation, or on the AST level. But that is far from nice.
With the new first class variables, there is now a fun way to do it: MetaLinks.
Make a class TT with an instance var âtâ and add an accessor.
Now we can define a MetaLink: it describes a call to a meta object that we wan to do before, after or instead of what our variable normally does. (default is #before):
| link | link := MetaLink new metaObject: Halt; selector: #now.
This link says: âdo a Halt now before where I will get installedâ.
To install the link, just get the Slot meta object and set it using #link:
(TT slotNamed: #t) link: link.
This sets the link by replacing the Slot with a LinkWrapper Slot, and then recompiles all using methods.
Thus evaluating:
TT new t
will get you a #halt.
Lots of things are not yet implemented (multiple links, uninstall, arguments,â¦) but it starts to show how simple one can do quite powerful things.
Marcus
-- www.tudorgirba.com
"Every thing has its own flow"
I can just repeat myself. This is such a big impact and a huge step forward. Bravo! Sadly there is other work to do. Norbert Am 21.07.2014 um 11:28 schrieb Marcus Denker <marcus.denker@inria.fr>:
Hello,
One of the questions with having meta objects for variables (Slots and Globals) is: For what is is good?
Here is one example⦠in early stage but working.
Imagine you want to âhook intoâ instance variable access. It can be done with e.g. bytecode manipulation, or on the AST level. But that is far from nice.
With the new first class variables, there is now a fun way to do it: MetaLinks.
Make a class TT with an instance var âtâ and add an accessor.
Now we can define a MetaLink: it describes a call to a meta object that we wan to do before, after or instead of what our variable normally does. (default is #before):
| link | link := MetaLink new metaObject: Halt; selector: #now.
This link says: âdo a Halt now before where I will get installedâ.
To install the link, just get the Slot meta object and set it using #link:
(TT slotNamed: #t) link: link.
This sets the link by replacing the Slot with a LinkWrapper Slot, and then recompiles all using methods.
Thus evaluating:
TT new t
will get you a #halt.
Lots of things are not yet implemented (multiple links, uninstall, arguments,â¦) but it starts to show how simple one can do quite powerful things.
Marcus
On 21 Jul 2014, at 11:28, Marcus Denker <marcus.denker@inria.fr> wrote:
Hello,
One of the questions with having meta objects for variables (Slots and Globals) is: For what is is good?
Here is one example⦠in early stage but working.
Now working: MetaLinks on Class Variables. |link | link := MetaLink new metaObject: Halt; selector: #now. (TT classVariableNamed: #T) link: link. ⦠and any access of the class var will trigger a Halt. https://pharo.fogbugz.com/f/cases/13630/Links-on-Class-Variables next: Globals, this means Object binding link: link should trigger the link whenever the global Object is read anywhere⦠Marcus
On 21 Jul 2014, at 15:51, Marcus Denker <marcus.denker@inria.fr> wrote:
On 21 Jul 2014, at 11:28, Marcus Denker <marcus.denker@inria.fr> wrote:
Hello,
One of the questions with having meta objects for variables (Slots and Globals) is: For what is is good?
Here is one example⦠in early stage but working.
Now working: MetaLinks on Class Variables.
|link | link := MetaLink new metaObject: Halt; selector: #now.
(TT classVariableNamed: #T) link: link.
⦠and any access of the class var will trigger a Halt.
https://pharo.fogbugz.com/f/cases/13630/Links-on-Class-Variables
next: Globals, this means
Object binding link: link
should trigger the link whenever the global Object is read anywhereâ¦
This now crashes your image as expected⦠;-) https://pharo.fogbugz.com/f/cases/13632/MetaLinks-for-Globals Marcus
Hi Marcus, On Thu, Jul 3, 2014 at 8:51 AM, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
If we have meta-object describing (and thus having the power to change the semantics of) instance variables, we need the same for Globals.
I think the easiest is to just re-use the object hat is already there: the âbindingâ, that is, the association from the dictionary where the global lives (e.g. the classPool for class vars, Smalltalk globals for true globals, and so on).
SystemVersion bindingOf: âCurrent'
The VM just cares that it is an assoiation (actually, it just care that there are two fields, but the rest of the image cares about value and keyâ¦)
-> we can make a subclass of Association -> we can have the compiler forward code generation to the object that describes the global -> we can add a nice MOP API: #read and #write: (instead of #value and #value:) -> Programmers can subclass the GlobalVariable and change #read and #write like they want (or override the code gen methods) as in Slots.
One thing I think is worth-while is having the compiler inline read-only globals, especially classes. Most classes never change, and even if they do, become: means that references to them (including in machine code) get updated, so there's little downside. The only drawback is that you can not add an instance variables, I think,
to check⦠maybe it even works? If not, there are ways around that e.g. using some fancy Slot that does not need an ivar but uses a weak dictionary in a class variable, for example).
Since the VM doesn't look beyond the second field it doesn't care if you add inst vars. It only expects the value field to be the second inst var; it never asks for the size of the association or anything like that. Remember that both key and value are fixed inst vars. Thus: it would be fairly easy to have the class vars be as flexible as the
slots⦠and then e.g. you will be able to put breakpoints and watchers on class vars. You could even define globals with special behaviour the same way as you do with Slots.
Marcus
-- best, Eliot
participants (8)
-
Ben Coman -
Clara Allende -
Denis Kudriashov -
Eliot Miranda -
Marcus Denker -
Norbert Hartl -
stepharo -
Tudor Girba