Почему создается несколько мономорфных кэшей вместо одного полиморфного

#javascript #v8

#javascript #v8

Вопрос:

Я читаю эту статью о мономорфизме, и там есть следующий фрагмент кода:

 function ff(b, o) {
  if (b) {
    return o.x
  } else {
    return o.x
  }
}

ff(true, { x: 1 })
ff(false, { x: 2, y: 0 })
ff(true, { x: 1 })
ff(false, { x: 2, y: 0 })
  

Сколько встроенных кэшей доступа к свойствам находится в функции ff? В каком
состоянии они находятся?
Ответы: существует 2 кэша, оба мономорфны, потому что каждый видит только объекты одной формы.

Я думал, что будет один полиморфный, потому что ранее автор показывает:

 f({ x: 4, y: 1 }) // polymorphic, degree 2
f({ x: 5, z: 1 }) // polymorphic, degree 3
f({ x: 6, a: 1 }) // polymorphic, degree 4
f({ x: 7, b: 1 }) // megamorphic
  

Функции передаются объекты разной структуры, и они мутируют мономорфный кэш в полиморфный. Почему это отличается от рассматриваемого примера?

Комментарии:

1. Я бы сказал, что автор несколько сбит с толку, поскольку ff функция выполняет одно и то же независимо от первого аргумента, но, поскольку я не читал всю статью и знаю, что автор работает в Google и раньше был частью команды V8, он, вероятно, знает, что он делаетчто делать?

2. @adeneo, да, я предполагаю, что это так. Я просто хочу понять тему)

3. О, это просто пример, показывающий, что o.x поиск кэшируется с первого вызова функции и т. Д.

4.Верно, но у каждого o.x поиска есть свой собственный кэш.

5. Я немного удивлен, что компилятор V8 просто не оптимизировал бы это, чтобы функция всегда возвращалась o.x . Google мог бы многому научиться у Рослин.

Ответ №1:

Эти вещи «встроенного кэша» существуют при каждой отдельной ссылке на свойство в коде. Таким образом, в функции:

 function ff(b, o) {
  if (b) {
    return o.x   // IC here
  } else {
    return o.x   // IC here
  }
}
  

У каждого из этих двух return операторов есть свой собственный встроенный кэш. Из-за способа вызова функции в примере, первый return выполняется только с объектами первой формы, а второй — только с объектами второй формы. Таким образом, каждый кэш (после этих четырех вызовов ff() ) будет иметь только 1 форму.

После пятого вызова функции, подобной этой:

 ff(true, { x: 1, z: 10 });
  

этот первый IC видел бы две формы, поэтому его IC был бы полиморфным.

Ответ №2:

Доступ к каждому свойству o.x имеет свой собственный IC, даже если к одному и тому же свойству одного и того же объекта обращаются несколько раз.

Если вы запустите node --trace-ic someScript.js , вы сможете увидеть, к какому номеру строки принадлежат ICS.