Each shape represents a specific set of attributes (instance variables and other properties) and their values. In our implementation, all objects have a shape. The shapes are nodes in a tree data structure. Every edge in the tree represents an attribute transition.
More specifically, setting an instance variable on an instance of an object creates an outgoing edge from the instance’s current shape. This is a transition from one shape to another. The edge represents the instance variable that is set. (View Highlight)
There is one global shape tree and objects which undergo the same shape transitions in the same order will end up with the same final shape (View Highlight)
In the diagram below, purple represents shared transitions, blue represents transitions for only foo, and red represents transitions for only bar.
(View Highlight)
Note: class Foo
def initialize
Currently this instance is the root shape (ID 0)
@a = 1 # Transitions to a new shape via edge @a (ID 1)
@b = 2 # Transitions to a new shape via edge @b (ID 2)
end
end
class Bar
def initialize
Currently this instance is the root shape (ID 0)
@a = 1 # Transitions to shape defined earlier via edge @a (ID 1)
@c = 1 # Transitions to a new shape via edge @c (ID 3)
@b = 1 # Transitions to a new shape via edge @b (ID 4)
end
end
foo = Foo.new # blue in the diagram
bar = Bar.new # red in the diagram
For instance variable writers, the current shape ID, the shape ID that ivar write would transition to and instance variable index are all stored in the inline cache. The shape ID is the key to the cache.
For instance variable readers, the shape ID and instance variable index are stored in the inline cache. Again, the shape ID is the cache key. (View Highlight)
When Foo is intialized, its shape is the root shape with ID 0. The root shape represents an empty object with no instance variables. Each time an instance variable is set on foo, the shape of the instance changes. It first transitions with @a to a shape with ID 1, and then transitions with @b to a shape with ID 2. If @a is then set to a different value, its shape will remain the shape with ID 2, since this shape already includes the instance variable @a.
(View Highlight)
Note: class Foo
def initialize
Currently this instance is the root shape (ID 0)
@a = 1 # Transitions to a new shape via edge @a (ID 1)
@b = 2 # Transitions to a new shape via edge @b (ID 2)
end
end
foo = Foo.new