Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the <primitive: xyz> statement do in a method declaration?

Here's the asciiValue method of the Character class:

asciiValue
   <primitive: 171>
   ^ self primitiveFailed

asciiValue is sent to a character object, for example $A, and returns its ascii code. Can someone explain how does the asciiValue method work? where does that <primitive: 171> comes from and what its purpose?

like image 371
Zoltan King Avatar asked Jul 06 '20 22:07

Zoltan King


1 Answers

The reason why this is a primitive rather than a regular Smalltalk method is that Characters in Pharo are immediate objects.

When seen in memory, objects are data structures with a header and some additional fields, one for each of the instance variables. Those slots contain pointers to the objects currently bound to the ivars.

In the case of SmallIntegers, however, this structure was traditionally simplified in that an object having an ivar that is a SmallInteger does not point to the small integer object, it has the SmallInteger. This is why SmallIntegers are called immediate objects: you don't point to them, you have them.

Of course, to implement immediate values you need a way to distinguish them in memory. SmallIntegers are integers but in memory pointers are integers too. The trick to establish the distinction is to observe that all objects are allocated in addresses that are multiple of 4 (32 bits) or 8 (64 bits). This means that pointers always have their two lower bits equal to 0. Thus, you can use these spare bits to tag immediate objects and store the immediate value in the remaining higher bits.

In the case of Pharo and other dialects, Characters whose code point fits within a byte, can be easily tagged so they become immediate. This is why Characters (and SmallIntegers) have no ivars: they are the value they represent, plus some tag for the Virtual Machine to tell the difference.

In consequence, the Smalltalk image has no way to access the numeric value of an ASCII Character, and needs to ask the VM to read it instead. This is why Pharo needs a primitive to answer the #asciiValue message.

For more information on primitives in Smalltalk take a look at Smalltalk: How primitives are implemented?.

like image 119
Leandro Caniglia Avatar answered Jan 03 '23 18:01

Leandro Caniglia