Немного удивлён, что никто не обратил внимания на фразу «На 64-битных платформах диапазон значений для SMI от -2³¹ до 2³¹-1». А для 32-битных как? А почему?
32-битные системы хранят указатели и SMI вот так (речь про v8)
64-битные вот так:
Т.е. в 32-битных системах мы теряем один бит на то, чтобы запомнить (протегировать) — указатель у нас или SMI, в SMI влазит только int31. В 64-битных системах метка (тег) переезжает в «свободные» 32-бита и мы можем хранить int32.
Кстати, с этим связан один неприятный момент. Когда в V8 решили включить Pointer Compression (сжатие указателей), то оказалось, что да, мы можем хранить два 32-битных указателя в одном 64-битном слове (там применяется достаточно сложный алгоритм), но вот снова положить два int31 — это приводит к деградации производительности (1% на Octane). А два int32 не помещаются, негде хранить тег.
Так как производительность важнее, а SMI у нас не так много в коде, то оставили как есть, всё равно выигрыш по памяти получился приличный, потребление практически вернулось к значениям для 32-битных систем.
UPD
В комментах @cevek подсказал, что всё же включили компрессию для SMI, и в браузере в SMI будет именно int31, а не int32 «как раньше».
С нодой интереснее, в ноде компрессия указателей изначально не была включена из-за проблем совместимости с нативными аддонами, потому мы продолжаем видеть в SMI int32. Есть такое обсуждение.
32-битные системы хранят указатели и SMI вот так (речь про v8)
|----- 32 bits -----|
Pointer: |_____address_____w1|
Smi: |___int31_value____0|
64-битные вот так:
|----- 32 bits -----|----- 32 bits -----|
Pointer: |________________address______________w1|
Smi: |____int32_value____|0000000000000000000|
Т.е. в 32-битных системах мы теряем один бит на то, чтобы запомнить (протегировать) — указатель у нас или SMI, в SMI влазит только int31. В 64-битных системах метка (тег) переезжает в «свободные» 32-бита и мы можем хранить int32.
Кстати, с этим связан один неприятный момент. Когда в V8 решили включить Pointer Compression (сжатие указателей), то оказалось, что да, мы можем хранить два 32-битных указателя в одном 64-битном слове (там применяется достаточно сложный алгоритм), но вот снова положить два int31 — это приводит к деградации производительности (1% на Octane). А два int32 не помещаются, негде хранить тег.
UPD
В комментах @cevek подсказал, что всё же включили компрессию для SMI, и в браузере в SMI будет именно int31, а не int32 «как раньше».
%DebugPrint(2147483647)
DebugPrint: 2147483647.0
0x5f700000339: [Map] in ReadOnlySpace
С нодой интереснее, в ноде компрессия указателей изначально не была включена из-за проблем совместимости с нативными аддонами, потому мы продолжаем видеть в SMI int32. Есть такое обсуждение.