completefrontend
Open lab My progress
THE JAVASCRIPT FIELD GUIDE

Inline caches

Learn how JavaScript engines cache property lookups at each call site, move from monomorphic to megamorphic, and feed JIT optimizers.

By the end, you can
  • 01
    Explain the fast way to read a propertyDescribe how one place in your code remembers an object's shape and the slot of a property, so the next matching object needs one check and one read.
  • 02
    Name the cache statesTell apart a cache that has seen no shapes, one shape (monomorphic), a few (polymorphic), and too many (megamorphic). Know that the cut-off number is the engine's choice, not a language rule.
  • 03
    Use this in real codeRecognize caches for square-bracket reads, writes, calls, global names, and prototypes. Then write objects with steady shapes, and measure before you optimize.

Remember where a property is

When you write obj.x, the JavaScript engine has to find x. The engine is the program inside the browser or Node.js that runs your code. By the rules of the language, finding x is a search:

  • First the engine looks at the object's own properties.
  • If x is not there, it looks at the object's prototype. A prototype is another object that this object borrows properties from.
  • It keeps going up this line of prototypes, called the prototype chain, until it finds x or runs out of objects.

This search is why obj.x works even when x lives on a prototype. But a search takes time, and a busy program may read the same property millions of times.

Definition

An inline cache is a small memory attached to one place in your code that reads or writes a property. It remembers where the property was found last time. For example: "for objects with this layout, x is in slot 0." When the next object has the same layout, the engine checks the layout once and reads slot 0. It skips the search.

The word "inline" comes from history. Early engines wrote a tiny shortcut right inside the code, next to the property read. Modern engines keep this memory in other places, but the idea is the same: each place in your code learns from the objects it sees.

The slow way: search the object, then its prototypesPop out in the code editor (opens in a new tab)JavaScript
const record = { user: { name: "Ada" } };const proto = { role: "author" };Object.setPrototypeOf(record.user, proto); function naiveLookup(object, name) {  let current = object;  while (current) {    if (Object.prototype.hasOwnProperty.call(current, name)) {      return current[name];    }    current = Object.getPrototypeOf(current);  }  return undefined;} console.log(naiveLookup(record.user, "name"));console.log(naiveLookup(record.user, "role"));

This function copies the language's search rule into plain JavaScript:

  • Line 6 starts at the object itself.
  • Line 7 keeps going while there is an object to look at.
  • Line 8 asks: does this object have the property as its own property?
  • Line 9 returns the value when it does.
  • Line 11 moves one step up, to the prototype.

So naiveLookup(record.user, "name") finds "Ada" on the object itself and prints Ada. The "role" search finds nothing on the object, moves to the prototype, and prints author. Doing this full search on every busy read would be too slow. So after the first search, the engine remembers where the property was.

Real-life analogyA mail carrier learns the mailboxes

A mail carrier visits a new building. The first time, she reads the map to find the mailbox for flat 4. Next time she sees the same kind of building, she knows the box is the third one. She only checks that the building looks the same. If her route has too many different buildings, she stops memorizing and asks the main desk instead.

In real life: On a new street, the carrier reads the street map
In JavaScript: The first object at a place in your code needs the slow search
In real life: Next time, the carrier only checks the building type
In JavaScript: The cache checks the object's layout
In real life: In this building type, flat 4's box is always the third one
In JavaScript: The engine reads the remembered slot directly
In real life: With too many building types, the carrier asks the main desk
In JavaScript: With too many layouts, the engine uses a shared table

This lesson builds on type feedback. It helps to know object basics, the prototype chain, classes, and property descriptors. The next section explains layouts in just enough detail for this lesson. The later Hidden classes & object shapes lesson goes deeper.

Shapes: a layout shared by similar objects

Engines keep a hidden record for each object layout. The record lists the property names in order and says where each value is kept. Each place is a numbered slot. The slot number is also called the offset.

Different engines give this record different names:

  • V8 (Chrome and Node.js) calls it a map.
  • SpiderMonkey (Firefox) calls it a shape.
  • Other texts call it a hidden class.

This lesson says shape. Objects with the same property names, added in the same order, share one shape. If the shape says x is in slot 0, the engine can check the shape and then read slot 0. No search is needed.

Same names in the same order give the same layoutPop out in the code editor (opens in a new tab)JavaScript
function makeUser(name) {  return { name, score: 0, active: true };} const ada = makeUser("Ada");const lin = makeUser("Lin");const reordered = { score: 0, name: "Grace", active: true }; console.log(Object.keys(ada).join(","));console.log(Object.keys(lin).join(","));console.log(Object.keys(reordered).join(","));

Line 2 always adds name, then score, then active. So ada and lin have the same layout. Line 7 writes the same three names in a different order: score first. Object.keys lists an object's property names in order, so the last line prints score,name,active. That different order is a clue that reordered has a different shape.

Two carts, ada and lin. The ada cart holds the values Ada, 0 and true. The lin cart holds Lin, 0 and true. Both point to one shared shape that says slot 0 is name, slot 1 is score, and slot 2 is active.makeUser("Ada")Ada0trueadaone shape0: name1: score2: activemakeUser("Lin")Lin0truelin
ada and lin were made the same way, so they share one shape. Each object keeps only its values. The shape says which slot holds which name.

Normal JavaScript can't see shapes. The code above only prints the order of the names. To see real shapes, the next example uses Node.js 22, which runs V8 version 12.4. It turns on a test-only feature with the flag --allow-natives-syntax. That flag adds helpers that start with %, such as %HaveSameMap(a, b). It answers: do a and b have the same map? This code can't run in the browser editor, so its Run button is turned off.

Ask V8 directly with %HaveSameMap (Node.js only)JavaScript
function Point(x) {  this.x = x;} const a = { x: 1, y: 2 };const b = { x: 3, y: 4 };const c = { y: 2, x: 1 };const p = new Point(1);const q = new Point(2); console.log(`Node ${process.versions.node} (V8 ${process.versions.v8.split(".").slice(0, 2).join(".")})`);console.log("same property order", %HaveSameMap(a, b));console.log("different property order", %HaveSameMap(a, c));console.log("constructor start", %HaveSameMap(p, q));p.y = 2;console.log("after one transition", %HaveSameMap(p, q));q.y = 3;console.log("after both transition", %HaveSameMap(p, q));
What this code really printed

The lesson's tests run this code in Node.js 22 with V8 12.4. Here is what it printed:

  • Same property order: true. The two objects share one map.
  • Different order: false.
  • Two new Point objects: true.
  • After adding y to p only: false. Adding a property moves p to a new map.
  • After adding y to q as well: true. Both took the same step, so they match again.

Want to read more? The V8 team explains how it stores properties in Fast properties in V8. The V8 maps docs show that the map is the first thing stored in every object. Mathias Bynens and Benedikt Meurer's Shapes and Inline Caches article gives a friendly overview.

One shape: one check and one read

An inline cache belongs to one place in your code, not to a property name. If your program has two different obj.x reads, each one has its own cache. Engines call such a place a site.

At a site, the first object finds the cache empty. That is a miss. The engine does the slow search, then saves a small, ready-made shortcut for that shape and slot. Engines call this shortcut a stub. A later object that matches the saved shape is a hit.

Step through: one shape, then one check and one read
Step 0 of 7Ready
Your turn: follow the blue line

Watch one place in code learn a shape on the first call, then use one check and one read on the second call.

Running in
  1. script
Next: line 13
function createGetXSite() {  let cachedShape = null;  let cachedOffset = "x";  return function getX(record) {    if (record.shape === cachedShape) {      return record.slots[cachedOffset];    }    cachedShape = record.shape;    return record.slots.x;  };} const a = { shape: "x,y", slots: { x: 1, y: 10 } };const b = { shape: "x,y", slots: { x: 2, y: 20 } };console.log(getX(a));console.log(getX(b));
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

The replay is a simple model written in JavaScript. Each object carries a shape string, so you can watch the check happen. Step through it:

  • The first getX(a) call is a miss. It saves the shape x,y and returns 1.
  • The second call, getX(b), gets a different object with the same shape. The check on line 5 passes.
  • Line 6 reads the value straight away and returns 2.
Top row: getX(a) does a slow search, remembers that shape x,y keeps x in slot 0, and gives 1. Bottom row: getX(b) asks the question same shape? The answer is yes, so it reads slot 0 and gives 2.getX(a)slow searchmiss: nothing saved yetremembersshape x,yx: slot 01getX(b)sameshape?yesread slot 0hit: one check, one read2
The first call finds nothing saved, so it searches and then remembers where x is. The second object has the same shape, so one check and one read are enough.

A cache that has seen only one shape is called monomorphic ("mono" means one, "morph" means form). This is the best case. The engine needs only two steps: check the shape, then read the slot.

What does the cache save?

The cache does not save the value 1. It saves a safe instruction: "if the object has this shape, read this slot." The value in the slot can change, and the instruction still works. If the shape check fails, the site misses and learns again.

A few shapes, then too many

Real programs often send two or three different layouts through one helper function. Then the site has a short list of saved shapes, and it checks them one by one. A site like this is polymorphic ("poly" means many).

Each site keeps only a few shapes. When too many different shapes arrive, the site stops saving them. It is now megamorphic ("mega" means huge). From then on it asks a slower table shared by the whole engine. Engines call that table the stub cache.

This lesson's model lets a site keep 4 shapes, and the 5th shape makes it megamorphic. Real engines choose their own number. It can change between engines, kinds of cache, and versions. No number is part of the JavaScript language.

One getX cache in the lesson's model. After 1 shape it is monomorphic: one quick check. With 2 to 4 shapes it is polymorphic: a few checks. At the 5th shape it becomes megamorphic and uses a shared table.1 shapemonomorphicone quick check2 to 4 shapespolymorphica few checks5th shapemegamorphicshared table
The same cache as more shapes arrive. The lesson's model keeps up to 4 shapes; the 5th sends it to a shared table. Real engines pick their own number.
Step through: from one shape to too many
Step 0 of 7Ready
Your turn: follow the blue line

Step through one site as it goes from one shape, to a few, to too many, and then uses a shared table.

Running in
  1. script
Next: line 1
const site = { state: "uninitialized", entries: [], stubCache: new Map() }; function readX(record) {  const key = record.shape + ":x";  if (site.state === "megamorphic" && site.stubCache.has(key)) {    return site.stubCache.get(key)(record);  }  if (site.entries.includes(record.shape)) {    return record.slots.x;  }  if (site.entries.length === limit) {    site.state = "megamorphic";    site.stubCache.set(key, (object) => object.slots.x);    return record.slots.x;  }  site.entries.push(record.shape);  site.state = site.entries.length === 1 ? "monomorphic" : "polymorphic";  return record.slots.x;} const records = [  { shape: "S1", slots: { x: 1 } },  { shape: "S2", slots: { x: 2 } },  { shape: "S3", slots: { x: 3 } },  { shape: "S4", slots: { x: 4 } },  { shape: "S5", slots: { x: 5 } },]; for (const record of records) console.log(readX(record));console.log(readX(records[4]));
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Playground: send objects through one getX site
The model's getX siteJavaScript
const site = createInlineCacheSite("getX");const objects = [  makeObject([["x", 1], ["a", 10]], "x-a"),  makeObject([["a", 20], ["x", 2]], "a-x"),  makeObject([["x", 3], ["b", 30]], "x-b"),  makeObject([["b", 40], ["x", 4]], "b-x"),  makeObject([["c", 50], ["x", 5]], "c-x"),]; for (const object of objects) {  console.log(site.read(object, "x"));}
Cache stateuninitialized
0 hits (shape matched)0 misses (slow search)0 properties searched0 found in shared table
x-aS2

x → a

a-xS4

a → x

x-bS5

x → b

b-xS7

b → x

c-xS9

c → x

No reads yet. Start with the first button, then try sending objects yourself.

Step 0 of 6uninitialized

Send an object through getX(obj). Objects with the same layout are quick hits. Many different layouts make the site megamorphic.

This is a small model that runs in your browser. It does not look inside your browser's engine. It acts out the cache states from this lesson. Each object's name shows its property order: x-a means x first, then a.

The table below lists the four states a site can be in. Read each row as: the site is in this state, it has seen this, and a read costs this much.

The four states of an inline cache and what a read costs in each
StateWhat the site has seenWhat a read costs
UninitializedNothing yet. The code has not run.The first read does the full slow search, then saves a shortcut if it can.
Monomorphic (one shape)One shape for this property.One shape check and one slot read. This is the fastest case.
Polymorphic (a few shapes)A few shapes. How many it keeps depends on the engine.A short list of shape checks. Still fast, but slower than one check.
Megamorphic (too many shapes)Too many different shapes at the same place.The site stops saving shortcuts and looks in a slower table shared by the whole engine.

In V8, a megamorphic property read looks in the shared stub cache. It finds the entry using the object's map and the property name. This stops one busy site from saving more and more shortcuts forever. But it is slower than one quick shape check.

How many shapes does this site see?
  • getX reads objects from one constructor that always sets x, then y.
  • getX gets rows shaped {x, name} and chart points shaped {label, x}.
  • A busy formatter reads .x from dozens of unrelated JSON objects.
  • A drawing function sees four steady object shapes and no others.
  • A loop reads items[i] from full arrays that one helper always builds.
  • A plugin hook calls a different function, with a different object shape, for every installed plugin.
Try it yourself
0 of 6 correct

Each card describes one busy place in code. Put it in the state that place most likely reaches.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Caches for keys, writes, calls, and global names

Reading obj.x is the easiest case to picture. But engines keep caches for many other operations too.

A keyed cache handles reads with square brackets, like obj[key]. The key can be a property name or an array index, so the cache has to tell them apart. Arrays add more cases:

  • A packed array has a value at every index.
  • A holey array has gaps, called holes, where no value was ever set.
  • An array can hold only small whole numbers, only decimal numbers, or any values. The engine tracks which kind it is.
One keyed read sees names, array items, and holesPop out in the code editor (opens in a new tab)JavaScript
function readKey(target, key) {  return target[key];} const user = { name: "Ada" };const packed = ["zero", "one", "two"];const holey = [];holey[2] = "two"; console.log(readKey(user, "name"));console.log(readKey(packed, 1));console.log(0 in holey);console.log(readKey(holey, 2));

Line 1 reads with target[key]. Line 10 passes it a property name, and line 11 passes an index into a packed array. Line 8 sets only index 2 of holey, so indexes 0 and 1 are holes. The in operator asks whether a property exists, so line 12 prints false.

A store cache handles writes, like obj.x = value. It learns one of two things:

  • The write changes a slot that already exists.
  • The write adds a new property, so the object moves to a new shape. Engines call this move a transition.
A write either changes a slot or adds onePop out in the code editor (opens in a new tab)JavaScript
function writeX(object, value) {  object.x = value;  return object.x;} const a = { x: 0, y: 0 };const b = { x: 1, y: 1 };const c = { y: 0 }; console.log(writeX(a, 7));console.log(writeX(b, 8));console.log(Object.keys(c).join(","));console.log(writeX(c, 9));console.log(Object.keys(c).join(","));

Line 2 is the write. For a and b, x already exists, so the write only changes a slot. Line 12 shows that c has only y. Line 13 adds x to c, which is a transition. Line 14 then prints y,x.

A call cache remembers which function a call ran. If one call site always runs the same function, a faster compiler can later copy that function's body right into the caller. This is called inlining.

A call cache remembers which function ranPop out in the code editor (opens in a new tab)JavaScript
function render(formatter, value) {  return formatter(value);} function money(amount) {  return "$" + amount.toFixed(2);} function label(value) {  return "item:" + value;} console.log(render(money, 3));console.log(render(money, 4));console.log(render(label, "A"));

Line 2 calls whatever function arrives as formatter. Lines 13 and 14 send money twice. Line 15 sends a different function, label. Now the call cache on line 2 has seen two functions.

Global caches do the same job for global names such as Math or document. Reads that go through a prototype need one more thing. The cache must remember the object's shape and check that the prototypes have not changed since. V8 keeps a small flag for this, called a validity cell. The later hidden classes and prototypes inside the engine lessons go deeper.

Changing a prototype changes what child.x givesPop out in the code editor (opens in a new tab)JavaScript
const proto = { x: 1 };const child = Object.create(proto); console.log(child.x);proto.x = 2;console.log(child.x);child.x = 3;console.log(child.x);console.log(proto.x);

Line 2 makes child with proto as its prototype. Line 4 prints 1, found on the prototype. Line 5 changes the prototype, so the same child.x on line 6 now prints 2. Line 7 gives child its own x, so line 8 prints 3. A saved shortcut must notice each change. That is why the engine checks before it trusts the cache.

The table below sums up the kinds of cache. Read each row as: this kind of cache, for code like this, remembers this.

Kinds of inline cache and what each one remembers
Kind of cacheCode it is used forWhat it remembers
Named read cacheobj.xThe object's shape and the slot where x is kept.
Keyed read cacheobj[key] or array[index]Whether the key is a name or an index. For arrays: full or with holes, and what kind of values they hold.
Write (store) cacheobj.x = valueWhether the write changes an existing slot or adds a property, which moves the object to a new shape.
Call cachefn(arg) or obj.method()Which function ran. If it is always the same one, a faster compiler can copy it into the caller.
Global name cachedocument or MathWhere a global name was found, with a check that it has not changed since.

How Firefox writes a cache: CacheIR

Firefox's engine, SpiderMonkey, writes each cache shortcut as a short list of simple steps. This list format is called CacheIR ("IR" means a simple in-between language that the engine turns into machine code). The list has two kinds of steps:

  • Guards check that something is still true. If a check fails, the shortcut is skipped.
  • One final result step produces the value.

The official docs show a simple obj.x read. It checks that the input is an object, checks its shape, and then reads a fixed slot.

The CacheIR steps for obj.x, simplifiedText
GetProp "x"  GuardToObject input  GuardShape shape=S1  LoadFixedSlotResult slot=0

In plain words, line by line:

  1. Line 1 names the operation: read the property "x".
  2. Line 2 is a guard: the input must be an object.
  3. Line 3 is a guard: the object must have shape S1.
  4. Line 4 is the result: read slot 0 of the object.

Jan de Mooij's CacheIR post explains why Firefox moved to this format. The SpiderMonkey docs say two of Firefox's compilers, Baseline and Warp, both build their code from these steps. Safari's engine, JavaScriptCore, uses inline caches too. WebKit's Speculation in JavaScriptCore explains how it guesses from what the code did so far, and checks each guess.

Different names, same job

Each engine uses its own words:

  • V8 (Chrome, Node.js): maps, feedback vectors, and stubs.
  • SpiderMonkey (Firefox): shapes, CacheIR, and the Baseline and Warp compilers.
  • JavaScriptCore (Safari): structures, inline caches, and speculation.

The job is the same in all three. Make a fast path from what the code did before, and put a check in front of it.

How faster compilers use what the cache learned

Engines run code in stages, called tiers. Early tiers start quickly and fill the caches as the code runs. When a function runs many times, an optimizing compiler turns it into fast machine code. It reads what the caches learned to decide what to build.

For a monomorphic read, the machine code can do just this:

  1. Check that the object has shape S.
  2. If not, leave the fast code and go back to the slower code. Engines call this deoptimizing.
  3. If yes, read the value at slot k in memory.

That is how one property read can become one shape check and one memory read.

A polymorphic site can still get fast code, with a short list of checks. A megamorphic site is harder. It says "this read sees many different shapes," so the compiler has less to plan around. It often keeps a call to the slower shared lookup. Call caches work the same way. One known function can be inlined. Many different functions make inlining less worth it.

Measure the real code first

You rarely need to track cache states by hand. Start with measuring performance. If a profile shows one property read is slow and very busy, then check whether its objects have mixed shapes.

Write objects with steady shapes

The advice for real code is simple:

  • Create every property you expect, right away.
  • Create them in the same order each time.
  • Avoid delete on objects that busy code uses again and again.
  • Don't send many unrelated kinds of objects through one small, busy helper.

Don't twist clear code out of shape just to please the cache.

Create every property up front, in the same orderPop out in the code editor (opens in a new tab)JavaScript
function User(name, admin = false) {  this.name = name;  this.admin = admin;  this.score = 0;} const ada = new User("Ada");const lin = new User("Lin", true);lin.score = 10; console.log(Object.keys(ada).join(","));console.log(Object.keys(lin).join(","));delete ada.admin;console.log(Object.keys(ada).join(","));

Lines 2 to 4 create the same three properties, in the same order, for every User. So ada and lin share one layout. Line 13 shows the habit to avoid in busy code: delete removes a property, which changes the layout. V8 may even switch the object to a slower way of storing properties. Sometimes delete is still the clearest choice. Just don't expect it to be free inside a busy loop.

  • Build objects with the same properties in the same order.
  • To clear a property on a busy object, set it to null or undefined instead of using delete.
  • If one busy helper gets many unrelated kinds of objects, and a profile says it matters, split it into smaller helpers.
  • Keep the code easy to read first. Measure before and after any change.

Common misconceptions

  • "The cache saves values." It saves where to find the value, behind a shape check. The value can change.
  • "A polymorphic site is always bad." A few steady shapes are normal, and engines often handle them well.
  • "Megamorphic means broken." It means the engine switched to a slower shared lookup for a site with many shapes. It only matters if a profile shows that site is busy and slow.
  • "Shapes are part of JavaScript." They are a trick inside engines. The language only says a property is found on the object or its prototypes.
  • "Engine tricks should decide how I write all my code." Clear data, tests, and real measurements matter more than rumors about speed.

Some of these words sound alike. The table below sets them side by side. Read each row as: this idea means this, and it is easy to mix up with that.

Ideas from this lesson that are easy to mix up
IdeaWhat it meansDon't mix it up with
ShapeThe engine's hidden record of an object's layout: the names, in order, and the slot for each.The values inside the object. Two objects can share a shape and hold different values.
Inline cacheA small memory at one place in your code that says which slot to read for a shape.A saved value. The cache saves where to find the value, not the value.
PolymorphicOne place in code has seen a few shapes. It checks a short list.Megamorphic, where there are too many shapes and the site uses a slower shared table.
Shapes and cachesTricks inside the engine that make property reads fast.The JavaScript language. The language only says: look on the object, then on its prototypes.

Practice exercises

Exercise 1 · Warm-upPredict what getX prints

Read the code. Type the two values it prints.

Starter codePop out in the code editor (opens in a new tab)JavaScript
function getX(object) {
  return object.x;
}
const a = { x: 1, y: 10 };
const b = { x: 2, y: 20 };
console.log(getX(a));
console.log(getX(b));

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · Warm-upHow many shapes does the model keep?

    How many shapes can one site keep in this lesson's model?

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeFind the hole in an array

      What does the hole check print?

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const holey = [];
      holey[2] = "two";
      console.log(0 in holey);

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeName the CacheIR shape check

        Which CacheIR step checks the object's shape in the lesson's example?

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengePick a habit for steady shapes

          Name one habit that helps a busy site keep seeing the same shape.

          Answer, then press Check. Spacing and letter case don’t matter.

            Check your understanding

            Inline caches quiz · 7 questionsScore: first tries count
            1. Question 1 of 7What does an inline cache remember for a normal obj.x read?

              Choose an answer to see the explanation.

            2. Question 2 of 7What does this code about property order print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const a = { x: 1, y: 2 };
              const b = { y: 2, x: 1 };
              console.log(Object.keys(a).join("|"));
              console.log(Object.keys(b).join("|"));

              Choose an answer to see the explanation.

            3. Question 3 of 7In this lesson's model, what happens when one place in code sees more than four shapes?

              Choose an answer to see the explanation.

            4. Question 4 of 7What does this code about an array hole print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const holey = [];
              holey[2] = "two";
              console.log(0 in holey);

              Choose an answer to see the explanation.

            5. Question 5 of 7A call always runs the same function. Why does that help a faster compiler?

              Choose an answer to see the explanation.

            6. Question 6 of 7Which CacheIR steps match a simple read of a property from a fixed slot?

              Choose an answer to see the explanation.

            7. Question 7 of 7Which habit best keeps object shapes steady?

              Choose an answer to see the explanation.

            Key takeaways

            • An inline cache belongs to one place in your code. One obj.x can be monomorphic while another is megamorphic.
            • A shape lists property names and their slots. So a cached read becomes one shape check and one slot read.
            • This lesson's model keeps 4 shapes per site. More than that sends the site to a slower shared table.
            • Engines also cache keyed reads, writes, calls, global names, and reads through prototypes. Faster compilers use what they learn.
            • Give similar objects the same properties in the same order, avoid delete in busy code, and measure before you optimize.

            In one line: the engine remembers where a property was, and checks the shape before it trusts that memory.

            Next in this module, Baseline compilers shows simple compilers that start fast and skip some interpreter work, before the strongest optimizing compilers take over.

            CompleteFrontend Clear concepts. Working examples.