---
title: 'Maps (Hidden Classes) in V8'
description: 'How does V8 track and optimize the perceived structure of your objects?'
---
Let's show how V8 builds it's hidden classes. The principal data structures are:
- `Map`: the hidden class itself. It's the first pointer value in an object and therefore allows easy comparison to see if two objects have the same class.
- `DescriptorArray`: The full list of properties that this class has along with information about them. In some cases, the property value is even in this array.
- `TransitionArray`: An array of "edges" from this `Map` to sibling Maps. Each edge is a property name, and should be thought of as "if I were to add a property with this name to the current class, what class would I transition to?"
Because many `Map` objects only have one transition to another one (ie, they are "transitional" maps, only used on the way to something else), V8 doesn't always create a full-blown `TransitionArray` for it. Instead it'll just link directly to this "next" `Map`. The system has to do a bit of spelunking in the `DescriptorArray` of the `Map` being pointed to in order to figure out the name attached to the transition.
This is an extremely rich subject. It's also subject to change, though, if you understand the concepts in this article future change should be incrementally understandable.
## Why have hidden classes?
V8 could do without hidden classes, sure. It would treat each object as a bag of properties. However, a very useful principle would have been left laying around: the principal of intelligent design. V8 surmises that you'll only create so many **different** kinds of objects. And each kind of object will be used in what can eventually be seen to be stereotypical ways. I say "eventually be seen" because the JavaScript language is a scripting language, not a pre-compiled one. So V8 never knows what will come next. To make use of intelligent design (that is, the assumption that there is a mind behind the code coming in), V8 has to watch and wait, letting the sense of structure seep in. The hidden class mechanism is the principal means to do this. Of course, it presupposes a sophisticated listening mechanism, and these are the Inline Caches (ICs) about which much has been written.
So, if you are convinced this is good and necessary work, follow me!
## An example
```javascript
function Peak(name, height, extra) {
this.name = name;
this.height = height;
if (isNaN(extra)) {
this.experience = extra;
} else {
this.prominence = extra;
}
}
m1 = new Peak("Matterhorn", 4478, 1040);
m2 = new Peak("Wendelstein", 1838, "good");
```
With this code we've already got an interesting map tree from the root map (also known as the initial map) which is attached to the function `Peak`:
Each blue box is a map, starting with the initial map. This is the map of the object returned if somehow, we managed to run the function `Peak` without adding a single property. The follow-on maps are the ones that result by adding the properties given by the names on the edges between maps. Each map has a list of the properties associated with an object of that map. Furthermore, it describes the exact location of each property. Finally, from one of these maps, say, `Map3` which is the hidden class of the object you'll get if you passed a number for the `extra` argument in `Peak()`, you can follow a back link up all the way to the initial map.
Let's draw it again with this extra information. The annotation (i0), (i1), means in-object field location 0, 1, etc:
Now, if you spend time examining these maps before you've created at least 7 `Peak` objects, you'll encounter **slack tracking** which can be confusing. I have [another article](https://v8.dev/blog/slack-tracking) about that. Just create 7 more objects and it will be finished. At this point, your Peak objects will have exactly 3 in-object properties, with no possibility to add more directly in the object. Any additional properties will be offloaded to the object's property backing store. It's just an array of property values, whose index comes from the map (Well, technically, from the `DescriptorArray` attached to the map). Let's add a property to `m2` on a new line, and look again at the map tree:
```javascript
m2.cost = "one arm, one leg";
```
I snuck something in here. Notice that all of the properties are annotated with "const," which means that from V8's point of view, nobody ever changed them since the constructor, so they can be considered constants once they've been initialized. TurboFan (the optimizing compiler) loves this. Say `m2` is referenced as a constant global by a function. Then the lookup of `m2.cost` can be done at compile time, since the field is marked as constant. I'll return to this later in the article.
Notice that property "cost" is marked as `const p0`, which means it's a constant property stored at index zero in the **properties backing store** rather than in the object directly. This is because we have no more room in the object. This information is visible in `%DebugPrint(m2)`:
```
d8> %DebugPrint(m2);
DebugPrint: 0x2f9488e9: [JS_OBJECT_TYPE]
- map: 0x219473fd