最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Can anyone explain V8 bytecode LdaTheHole? - Stack Overflow

programmeradmin2浏览0评论

I know the V8 bytecode "LdaUndefined" load the constant "undefined" into the accumulator register.
Then what does "LdaTheHole" load into the accumulator?
Maybe "TheHole"?
What is the meaning of the "TheHole"?
Thank you.

I know the V8 bytecode "LdaUndefined" load the constant "undefined" into the accumulator register.
Then what does "LdaTheHole" load into the accumulator?
Maybe "TheHole"?
What is the meaning of the "TheHole"?
Thank you.

Share Improve this question edited Feb 4, 2022 at 12:25 ZhefengJin asked Apr 25, 2020 at 3:23 ZhefengJinZhefengJin 1,0929 silver badges19 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 18

(V8 developer here.)

what does "LdaTheHole" load into the accumulator? Maybe "TheHole"?

Yes.

What is the meaning of the "TheHole"?

As Mark's answer correctly guesses, it's an internal sentinel that means "no value here". The reason it's needed is not performance (or allocations), though; it's needed to get the correct behavior in a few situations.

For an array-based example, consider this code:

var a = [1, 2, 3];           // (1)
a.__proto__ = [11, 22, 33];  // (2)
delete a[1];                 // (3)
console.log(a[1]);           // (4)

This will print 22, because a will conceptually have a "hole" at index [1], and you can "see its prototype through that hole", so to speak. (You could create the same situation if you replaced lines (1) and (3) with var a = [1, , 3].) If a had the default prototype, then instead of delete a[1] you could write a[1] = undefined, or that's what delete could do under the hood, and the result would be the same. But with a custom prototype, there is a difference: if you wrote a[1] = undefined instead of line (3), then line (4) would print undefined. We need the "hole" sentinel to distinguish whether element [1] is undefined or not present at all.

There are a few other cases where distinguishing between "no value" and "defined to be 'undefined'" is useful or necessary, for example for the "temporal dead-zone" of block-scoped variables. Old-style var-variables implicitly get their declarations hoisted, whereas accessing new-style let-variables before their definition is an error. The correct behavior is:

var a = 1; print(a);  // 1
let b = 1; print(b);  // 1
print(c); var c = 1;  // undefined
print(d); let d = 1;  // ReferenceError: Cannot access 'd' before initialization
print(e);             // ReferenceError: e is not defined

So the print statement (which is just an example; the same holds for many other operations) must do three different things depending on the surrounding code. V8 accomplishes this by internally transforming the lines to:

let c = undefined; print(c); c = 1;
let d = <TheHole>; print(d); d = 1;

That way, when a variable that's being accessed has the "hole" as its value, the system knows that something's wrong, so in this case rather than loading the variable's value and passing it to the print function, it knows that this must be a block-scoped variable being accessed before its definition, so it produces an appropriate error message.

If you get tempted to play with this stuff, be aware that "the hole" is purely an internal sentinel. It can never "leak" out to JavaScript. There is no way to check from your code that a variable or property currently has this value. It's a hidden implementation detail -- engines could do things differently; it just so happens that having an internal "hole" sentinel is a reasonably elegant and efficient way to solve a bunch of problems, so V8 chooses to do it that way.

I did a Google search through the v8/Chromium code, and it appears TheHole is a sentinel value for unassigned values. In many situations in JavaScript, an unassigned value is treated as if it was undefined (for example, when accessing an array element that hasn't been assigned, or a var which has been declared, but never assigned).

But occasionally, the interpreter needs to make a distinction between when there is no value, and when something is set to undefined. This is the difference between:

var a = [1,2];
console.log(a[2]);

and

var a = [1,2,3];
delete a[2];
console.log(a[2]);

In both cases, accessing a[2] will return "undefined", but in the second case, there's a "hole" at the end of the backing store (raw memory) for the array, which means if you later assigned a value to a[2] again, you wouldn't need to copy the values to a larger array first. So, TheHole is the value used for "nothing there". You can't use undefined for that, because you can explicitly set the value of an array element to undefined.

Where this really matters is for operations like Array.splice, or for anything that searches an array. If you extensively modify the contents of an array in-line, you don't want every operation to require memory allocation and freeing, because those operations are slow.

So, LdaTheHole is used to initialize a variable before you search an array, or to "clear out" deleted array values.

发布评论

评论列表(0)

  1. 暂无评论