How does Pharo store instance variables?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

How does Pharo store instance variables?

CodeDmitry
This post was updated on .
CONTENTS DELETED
The author has deleted this message.
Reply | Threaded
Open this post in threaded view
|

Re: How does Pharo store instance variables?

Nicolas Passerini
If you defined the variable as an instance variable in the class side, you can access it as

Greeter instVarNamed: 'greeting'
or
Greeter instVarAt: 1


But also you can define class variables from the instance side, which is slightly different (and I think most common, isn't it?)

Object subclass: #Greeter
instanceVariableNames: ''
classVariableNames: 'greeting'
package: 'Greetings'

if that is the case, there is in fact a dictionary which is accessed by doing 

Greeting classPool


On Mon, Oct 3, 2016 at 10:23 PM, CodeDmitry <[hidden email]> wrote:
I am trying to study Pharo's internals and I am now curious how it stores
class variables.

I notice that in order to have a class `Greeter` with a "static" variable
`greeting`, I need to make `greeting` an instance variable under "show show
the class side" and create a "Getter" and "Setter" for this "instance
variable".

First thing that confuses me is, why is this called an instance variable if
this particular "static" method is not bound to any particular instance? Is
it just because it is defined in an "instance" of a "ProtoClass"?

Second thing that confuses me is, where are these pairs of ("instance
variable name" => "instance variable value") stored? I know that I can call

Transcript show:
    ((Greeter class) instanceVariables at: 1).

which prints "greeting".

and

Transcript show:
  Greeter instanceVariables class.

which prints "Array"(curious, i expected a Dictionary mapping Strings to
Object).

Transcript show:
    ((Greeter class) instanceVariables at: 1) class.

prints "ByteSymbol".

Now I am confused, where are the actual values of the "static variables"
stored? I can find the names, but  can't understand where  the values are
hidden.

Can somebody help me understand  this?




--
View this message in context: http://forum.world.st/How-does-Pharo-store-instance-variables-tp4917924.html
Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.


Reply | Threaded
Open this post in threaded view
|

Re: How does Pharo store instance variables?

CodeDmitry
This post was updated on .
CONTENTS DELETED
The author has deleted this message.
Reply | Threaded
Open this post in threaded view
|

Re: How does Pharo store instance variables?

Martin McClure-2
In reply to this post by CodeDmitry
On 10/03/2016 01:23 PM, CodeDmitry wrote:

> I am trying to study Pharo's internals and I am now curious how it stores
> class variables.
>
> I notice that in order to have a class `Greeter` with a "static" variable
> `greeting`, I need to make `greeting` an instance variable under "show show
> the class side" and create a "Getter" and "Setter" for this "instance
> variable".
>
> First thing that confuses me is, why is this called an instance variable if
> this particular "static" method is not bound to any particular instance? Is
> it just because it is defined in an "instance" of a "ProtoClass"?
>
> Second thing that confuses me is, where are these pairs of ("instance
> variable name" => "instance variable value") stored? I know that I can call
>
> Transcript show:
>     ((Greeter class) instanceVariables at: 1).
>
> which prints "greeting".
>
> and
>
> Transcript show:
>   Greeter instanceVariables class.
>
> which prints "Array"(curious, i expected a Dictionary mapping Strings to
> Object).
>
> Transcript show:
>     ((Greeter class) instanceVariables at: 1) class.
>
> prints "ByteSymbol".
>
> Now I am confused, where are the actual values of the "static variables"
> stored? I can find the names, but  can't understand where  the values are
> hidden.
>
> Can somebody help me understand  this?

You've run into one of the core truths of Smalltalk. Both of the
following two statements are true:

1) Every object is an instance of some class.

2) Every class is an object.

---

So, every class must be the instance of some class.

What is the class of a class?

Every time you define a class, you are actually defining a pair of
classes -- the class, and another class to be the class of that class.
The latter is known as a "metaclass" and it is always an instance of
Metaclass. Each Metaclass has exactly one instance, which is a class.

The class defines "instance-side" behavior and variables, and the
metaclass defines "class-side" behavior and variables.

This lets the same rules apply for both normal classes and metaclasses.
For instance, every instance of a class contains a variable for each
variable defined in its class. So if you define a named instance
variable on a normal class, every instance of that class will contain
its own copy of that variable. If you define a named instance variable
in a metaclass, every instance of that metaclass will have its own copy
of that variable. But metaclasses only have one instance, the class, so
there's only one copy of that variable.

Until you subclass that class. The instance-side instance variables are
inherited, and so are the class-side instance variables. So you get a
new metaclass that's a subclass of the old metaclass, and a new class
that's a subclass of the class. This new subclass is distinct from its
superclass, so it gets its *own* copy of the class instance variable,
just like any other object.

This is one way in which class instance variables are different from
static variables. They're not really static at all, but they do have the
lifetime of the class, just like any instance variable has the lifetime
of the object it's in. And the usual rules of access to instance
variables apply, which is why you need getter/setter methods if you want
to access the variable from outside that class object.

I hope this helps you understand Smalltalk a bit better. There are also
class variables, which Nicolas mentioned, and which are quite different,
and which are closer to static variables.

Regards,

-Martin

Reply | Threaded
Open this post in threaded view
|

Re: How does Pharo store instance variables?

Ben Coman
In reply to this post by CodeDmitry
On Tue, Oct 4, 2016 at 4:23 AM, CodeDmitry <[hidden email]> wrote:
> I am trying to study Pharo's internals and I am now curious how it stores
> class variables.
>
> I notice that in order to have a class `Greeter` with a "static" variable
> `greeting`,


I guess you are referring to...
http://www.learncpp.com/cpp-tutorial/811-static-member-variables/

So its fair to analogize to a familiar concept, but you need to remember...

Rule 1: *Everything* is an object.

which includes class definitions, being instances of Metaclass. So try...
  Metaclass allInstances inspect.
then select one and compare its 'methodDict' and 'thisClass' ==> 'methodDict'
with what you see for that class in the System Browser.

Notice the ClassDescription superclass to Metaclass has an instance
variable 'instanceVariables'.
Now one thing that confused me for a moment just now is, if you try...
  Metaclass allInstances select: [ :mc | mc instanceVariables size > 0 ].
then look at that instance variable 'instanceVariables'
it is always nil due to the implementation in Pharo 5 of instance
variables as Slots.  In Pharo 4 you see actual names of instance
variables.   btw I'm curious now, does that ivar 'instanceVariables'
planned to be removed some time?

Now actually (IIUC) a C++ static member variable is most like a "Class
Variable" which is defined on the instance side of a class.  There are
three main variable types to consider when defining a class in Pharo:
Instance variables - scoped to instance methods, unique per instance
Class Variables - scoped to instance methods & class methods, common
to the class and all subclasses and all their instances
Class Instance Variables - scoped to class methods, unique per class
(i.e. instance of Metaclass)

To experience the finer points of these you might try the experiment I
describe here...
http://forum.world.st/Class-vars-and-inst-vars-of-a-class-tp4749910p4749914.html


> I need to make `greeting` an instance variable under "show
> the class side" and create a "Getter" and "Setter" for this "instance
> variable".
>
> First thing that confuses me is, why is this called an instance variable if
> this particular "static" method is not bound to any particular instance?


The method is bound to an instance of Metaclass, being the class
definition.  When you add methods or instance variables to the
class-side in the Browser, you are adding them to this instance.
There is one instance of Metaclass for each class in the system.


> Is
> it just because it is defined in an "instance" of a "ProtoClass"?

I don't understand this question.  Can you rephrase after doing the
experiment linked above?

>
> Second thing that confuses me is, where are these pairs of ("instance
> variable name" => "instance variable value") stored? I know that I can call
>
> Transcript show:
>     ((Greeter class) instanceVariables at: 1).
>
> which prints "greeting".
>
> and
>
> Transcript show:
>   Greeter instanceVariables class.
>
> which prints "Array"(curious, i expected a Dictionary mapping Strings to
> Object).


What you are seeing is a copy of the core representation. Try debugging into....
    (Greeter class instanceVariables at: 1)
paying particular attention to...
LayoutClassScope>>visibleSlots
LayoutClassScope>>do:


>
> Transcript show:
>     ((Greeter class) instanceVariables at: 1) class.
>
> prints "ByteSymbol".
>
> Now I am confused, where are the actual values of the "static variables"
> stored? I can find the names, but  can't understand where  the values are
> hidden.

You are looking at a copy of the core representation.

To work through a quick example... take the Morph class definition's
first two instanceVariables: 'bounds owner...'
and for each of their accessors #bounds and #owner
right-click and choose <Inspect Method>
then compare each [Bytecode] tab
with the first line showing "callPrimitive: 264" or "callPrimitive:
265" respectively.
These (and similar) primitives provide the *real* "compiled" access to
the instance variables.

So that demostration is the equivalent of asking "where are the values
in variables stored" for C++
and reviewing its generated assembler code - although our VM provides
a level of abstraction.  Hopefully the ease of digging from source
code down to its compiled bytecode demonstrates another aspect of the
power of the Pharo environment.


btw, you can see the list of VM primitives here...
https://github.com/pharo-project/pharo-vm/blob/36079d9be14542ea9e0d72e5ef57b596bd8aab52/mc/VMMaker.oscog.package/StackInterpreter.class/class/initializePrimitiveTable.st


cheers -ben

Reply | Threaded
Open this post in threaded view
|

Re: How does Pharo store instance variables?

Ben Coman
In reply to this post by CodeDmitry
On Tue, Oct 4, 2016 at 9:37 AM, CodeDmitry <[hidden email]> wrote:
> Oh! I see where I got confused now!
>
> "static" variables in Pharo outlive their Playground call!

More than that. They outlive closing the image. The paradigm*** shift
you need to make is that while the lifetime of "static" variables of a
C/C++ program ends when program execution ends, and even though you
stop and start execution of the VM, the execution of the "Image"
*never* ends, it is only suspended.

Try this experiment...

In the System Browser...
  Morph subclass: #MyMorph
    instanceVariableNames: ''
    classVariableNames: ''
    package: 'AnExperiment'

  MyMorph>>step
    self right > Display width ifTrue: [  self left: 0 ].
    self left: self left + 10.

  MyMorph>>stepTime
    ^100

In Playground...
  (m := MyMorph new) openInWorld.
  "After it has been running a while, Save & Quit the image**, then
restart it. Notice the movement of the morph continues from where it
left off."
  m delete. "...sometime later"

**Even copy the image and changes to another machine they start it up there.

*** and perhaps you might notice a change in your perception of "what
is possible" from exposure in your course to the "dead" language of
Smalltalk.  And further,  consider MyMorph is part of a control system
for a nuclear power plant or financial trading system operating 365x24
and you want to change MyMorph from moving right to moving left.
Consider how you would do that in C++ without stopping the system for
even a second, compared to doing that in Pharo.  Now Pharo may not be
production ready (i.e. $$$) to run a nuclear power plant, but the
concept of making such "live" changes to compiled code is now a
concept you can carry forward to other disciplines.

cheers -ben

>
> If I call
>
> Greeter greet.
> Greeter greeting: 'Hi!'.
> Greeter greet.
>
> Even if greet sets greeting to an initial value if it is nil, it will
> forever then stay 'Hi!' until I change it or reset it.
>
> So it is not unreasonable to get a response 'Hi! Hi!' in the playground even
> though 'Hi!' only gets set after greet is called, since the global state
> outlives the Transcript!

Reply | Threaded
Open this post in threaded view
|

Re: How does Pharo store instance variables?

SergeStinckwich
Hi guys,

I think such discussions should be done in pharo-users. These discussions will be very interesting to follow by users/beginners.

Pharo-dev is more about contributions/discussions aboit core development of Pharo.
Thank you

Envoyé de mon iPhone

> Le 4 oct. 2016 à 05:00, Ben Coman <[hidden email]> a écrit :
>
>> On Tue, Oct 4, 2016 at 9:37 AM, CodeDmitry <[hidden email]> wrote:
>> Oh! I see where I got confused now!
>>
>> "static" variables in Pharo outlive their Playground call!
>
> More than that. They outlive closing the image. The paradigm*** shift
> you need to make is that while the lifetime of "static" variables of a
> C/C++ program ends when program execution ends, and even though you
> stop and start execution of the VM, the execution of the "Image"
> *never* ends, it is only suspended.
>
> Try this experiment...
>
> In the System Browser...
>  Morph subclass: #MyMorph
>    instanceVariableNames: ''
>    classVariableNames: ''
>    package: 'AnExperiment'
>
>  MyMorph>>step
>    self right > Display width ifTrue: [  self left: 0 ].
>    self left: self left + 10.
>
>  MyMorph>>stepTime
>    ^100
>
> In Playground...
>  (m := MyMorph new) openInWorld.
>  "After it has been running a while, Save & Quit the image**, then
> restart it. Notice the movement of the morph continues from where it
> left off."
>  m delete. "...sometime later"
>
> **Even copy the image and changes to another machine they start it up there.
>
> *** and perhaps you might notice a change in your perception of "what
> is possible" from exposure in your course to the "dead" language of
> Smalltalk.  And further,  consider MyMorph is part of a control system
> for a nuclear power plant or financial trading system operating 365x24
> and you want to change MyMorph from moving right to moving left.
> Consider how you would do that in C++ without stopping the system for
> even a second, compared to doing that in Pharo.  Now Pharo may not be
> production ready (i.e. $$$) to run a nuclear power plant, but the
> concept of making such "live" changes to compiled code is now a
> concept you can carry forward to other disciplines.
>
> cheers -ben
>
>>
>> If I call
>>
>> Greeter greet.
>> Greeter greeting: 'Hi!'.
>> Greeter greet.
>>
>> Even if greet sets greeting to an initial value if it is nil, it will
>> forever then stay 'Hi!' until I change it or reset it.
>>
>> So it is not unreasonable to get a response 'Hi! Hi!' in the playground even
>> though 'Hi!' only gets set after greet is called, since the global state
>> outlives the Transcript!
>