Actual V8 implementation of JS execution stack

392 views Asked by At

I am just curious. How exactly are JavaScript engines internally implementing the EMCAScript execution stack instructions.

If you look at the code below, ECMAScript will expect us to create a Global execution context with an Environmental Record that will contain the fun1, res and c variables. When fun1 is invoked, we will then create a new function execution context which will have an Environmental Record that will contain the a and b variables and associated values.

In this blog post from the V8 team Blazingly fast parsing, part 2: lazy parsing, it is clear that internally they are using the memory stack to control function invocations unless variables are affected by closure.

I am curious if the res and c variables in the code below will be placed on the stack as well? Will environmental records for the global and function execution context actually be created for a simple code like the one in the example.

Any answers will be appreciated, fully understanding that the answer in this case ultimately does not matter as far as use of JS is concerned.

let fun1 = function(a){
let b = 2;
return a+b;
}
let res = fun1(4);
let c = ”done";

1

There are 1 answers

0
jmrk On

(V8 developer here.)

How exactly

The exact details are complicated. Read the source if you really care about those.

are JavaScript engines internally implementing

The answer is going to be different for every engine. It is also going to change over time. Even if you zoom in on one version of one engine, the answer is likely "it depends".

I am curious if the res and c variables in the code below will be placed on the stack as well?

Global variables are properties on the global object. The values of these variables may or may not briefly be stored on the stack before being stored as global object properties.

Will environmental records for the global and function execution context actually be created for a simple code like the one in the example.

Yes -- one way or another. Having a global object and storing properties on it is one way of having an "environmental record" for the global context.

This abstraction is a key insight. Don't expect a class EnvironmentalRecord or something like that. It's an abstract concept, describing the notion that the engine must have some way to store variables for a function. That could be a slot in a stack frame, or a "context" object, or (in an optimizing compiler) some "live range" of some register, or any number of other internal implementation choices. It's also worth noting that there's a distinction between scope resolution at compile time, and actual value storage at run time: for the former, the engine might have to keep more metadata, and use a different internal implementation, than for the latter.