Hi,
Both mehtods are implemented as primitives but it's not clear to me how a Collection (for instance) tells the VM that it's an indexable class. I'm a bit lost with these indexed variables thing... Any pointer would be appreciated. Thanks |
Fernando,
> Both mehtods are implemented as primitives but it's not clear to me > how a Collection (for instance) tells the VM that it's an indexable > class. Have a look at the class definitions. For example ... Collection is an "Object subclass". You can't create usable instances of Collection (for indexing anyway) so it just a "normal" class with no indexed instance variables. Array is an "ArrayedCollection variableSubclass". This tells the compiler/vm that it has indexed instance variables after it's named instance variables. ByteArray is an "ArrayedCollection variableByteSubclass". This indicates that it is only allowed to have byte values in it's indexed instance variables (and no named instance variables are allowed in subclasses). > I'm a bit lost with these indexed variables thing... Any pointer would > be appreciated. A "normal" class stores it's instance variables in slots associated with each instance and can only have "named" variables. For example Point has two named instance variables #x and #y which can be accessed normally .... (100 @ 200) x ==> 100 or via the instVar's position (100 @ 200) instVarAt: 1 ==> 100 A "variableSubclass" has (optionally) named instance variables followed by indexed instance variables. Create a subclass of Array named ArrayX, give it one named instVar called #fred and provide an accessor. ax := ArrayX new: 5. ax fred: 123. ax at: 1 put: 'Hello'. ax instVarAt: 1 => 123 ax instVarAt: 2 ==> 'Hello' A "variableByteSubclass" is the same but no named instVars are allowed so (a at: 1) == (a instVarAt: 1) ==> true One final point. named instance variables are added from the superclass(es) down. Add an subclass of ArrayX called ArrayY and give it an instVar and accessor named #bert. ay := ArrayY new: 5. ay fred: 22. ay bert: 33. ay at: 1 put: 44. ay instVarAt: 1.==> 22 ay instVarAt: 2.==> 33 ay instVarAt: 3.==> 44 -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
In reply to this post by Fernando Rodríguez
Fernando wrote:
> Hi, > > Both mehtods are implemented as primitives but it's not clear to me > how a Collection (for instance) tells the VM that it's an indexable > class. I don't know about Dolphin but in VW it is part of the class definition template. For example: Smalltalk.Core defineClass: #OrderedCollection superclass: #{Core.SequenceableCollection} indexedType: #objects private: false instanceVariableNames: 'firstIndex lastIndex ' classInstanceVariableNames: '' imports: '' category: 'Collections-Sequenceable' the indexType: determines the type of storage, normal objects have type #none, ByteArrays have type #bytes and Arrays have type #objects. This is how the VM is informed about indexability. In VW the class Object implements #at: and #basicAt: (both identically) as well as #size and #basicSize (identically). The idea is that methods starting with 'basic' are never overridden. So in the case of OrderedCollection above #basicSize will return the amount of storage available (also known as the collection's capacity) but #size will return a different value calculated from the instance variables firstIndex and lastIndex. IOW #size has been overridden in OrderedCollection to make use of these variables. Enjoy! Reinout ------- |
In reply to this post by Fernando Rodríguez
Mark van Gulik (ghoul) wrote:
> The first two replies described instance variables, but that wasn't > quite the question. The poster wanted to know how the VM knows about > it. The answer is that the class's "format" instance variable encodes > the number of named instance variables, as well as flags that indicate > whether there can be numbered pointer instance variables, numbered byte > instance variables, weak slots (VW), and ephemeral slots (VW). The > VM's instance creation machinery uses this information to determine how > many bytes to allocate, how to initialize those bytes, etc. The > garbage collector uses this information to distinguish inter-object > pointers from raw bytes. ...and flag bits in every object header are used to indicate what kind of object each is, along with a (potentially indirect) reference to its class for looking up messages, finding the class's "format" inst var. The GC only needs inspect the flag bits to do its stuff (e.g. it can ignore the contents of a byte object when doing a scan-mark). The basicAt: & size primitive may have to go to the class to find the number of fixed fields if a given implementation has no room for that info in the object header. -- _______________,,,^..^,,,____________________________ Eliot Miranda Smalltalk - Scene not herd |
In reply to this post by Fernando Rodríguez
Mark van Gulik (ghoul) wrote:
> The first two replies described instance variables, but that wasn't > quite the question. The poster wanted to know how the VM knows about > it. The answer is that the class's "format" instance variable encodes > the number of named instance variables, as well as flags that indicate > whether there can be numbered pointer instance variables, numbered byte > instance variables, weak slots (VW), and ephemeral slots (VW). The > VM's instance creation machinery uses this information to determine how > many bytes to allocate, how to initialize those bytes, etc. The > garbage collector uses this information to distinguish inter-object > pointers from raw bytes. To be still more precise, the format stores the number of *fixed fields* of an object. Named instance variables is a concept introduced at the image level, and only by ClassDescription rather than base Behavior. VM is oblivious to names. In the default image, fixed fields and named variables are the same, but it is theoretically possible to have subclasses of Behavior for which it wouldn't be so. Anyway, that still doesn't explain how indexed variables work--for example, where the result of #basicSize comes from and how #basicAt: ensures the index is within bounds. The missing bit of information so far was that not everything is determined by the class. In case of classes with indexed variables, the class only contains a flag that says its instances *can* have additional fields. The actual number of those fields is specified at the instance creation time (the argument passed with the #new: message) and is stored in that particular object's header, after adding the number of fixed fields required by the class format. The header is a block of information visible to the VM and is not (at least not in a portable between dialects way) accessible from the image. You can think of the information passed to #new: as "magically remembered". As an example, if you have a class A with two instance variables, plus one inherited from the superclass, the class format has 3 as the fixed slot count. If the class is declared as variableSubclass, the format also has the indexed flag set. All together, the format says that any instance of that class will have at least 3 fields--but possibly more. "A new: 4" creates an instance with 7 fields total, and remembers 7 as the instance size in its object header. The primitive for #basicSize will fetch that 7 from the header, subtract the fixed field count as declared by the class, and answer 4. "basicAt: 1" will add the 3 from the class format, ensure that the result is not greater than 7, and fetch the 4th field of the instance. -- Vassili Bykov VisualWorks Engineering, Tools Technical Lead v b y k o v A T c i n c o m D O T c o m http://www.cincomsmalltalk.com/userblogs/vbykov |
Free forum by Nabble | Edit this page |