How exactly does JavaScript perform memory allocation during evaluation process? - javascript

I know that JavaScript is a dynamic type language and executes programs divided by evaluation and execution processes. And JavaScript registers variables in the Lexical environment of the execution context during the evaluation process, and allocates the actual value while executing the allocation statement during the execution process.
Here I was wondering how JavaScript allocates memory for each variable during the evaluation process.
Because it's before JavaScript evaluate the type, is JavaScript allocating it to a certain byte size and keeping each of them away?
I could find many articles about JavaScript's memory management, but I couldn't figure out how the allocation occurred in the beginning.
Is there any way I can know this?

AFAIK it will use the stack for everything that has a known size and for the rest it uses the heap.
I found this article useful.
https://felixgerschau.com/javascript-memory-management/#the-memory-heap-and-stack

Related

About JavaScript compilation phase

As far as I know, JavaScript code goes through two phases: compilation phase and execution phase, when a JavaScript engine like V8 runs our code.
I wonder when the heap memory is actually allocated for a function.
More specifically, if I declare function and not call it in our code, does the JavaScript engine such as V8 still allocate memory for the function in the compilation phase?
Thank you
It's a bit more complicated than just two phases. Engines typically try to save memory when they can, but nothing is entirely free. It's safe to assume that a function that's never called consumes less memory than one that is called, but not zero.
In V8 in particular, (most) code is at first "pre-parsed". The preparser leaves behind some metadata about functions it has seen; mostly where in the source they start/end and some information about which variables from their outer context, if any, they'll need.
When program execution reaches a point where a function becomes available to JavaScript (as a variable), an actual object is created for it. This function object does not contain code or bytecode yet.
When a function is called, it is just-in-time compiled to bytecode. From this point on, memory is consumed for the bytecode.
If V8 notices that a lot of time is spent in the function, it may decide to generate optimized code for it. Optimized code is stored in addition to the bytecode, so the function's memory consumption grows again. Some functions never reach this point (e.g. when they're only called a few times).
Of course, when a function is executed, it can create other objects. (That's probably not what you're asking; just mentioning it for completeness.)

Does V8 crash if it cannot allocate memory? Does this crash the entire process?

This question is similar to one I recently asked about LLVM.
V8 allocates JavaScript objects on a manually-managed heap, memory for which is ultimately obtained from mmap/VirtualAlloc (on Linux/Windows). However, for its internal data structures, V8 uses C++ standard containers such as std::vector. If these containers need to allocate memory, but are unable to, they usually throw std::bad_alloc.
However, V8 is compiled with -fno-exceptions. If exceptions cannot be used, how does V8 handle the situation where the internal data structures are unable to allocate memory? Does it crash? If so, does this take down any process which embeds V8?
In general even if your code is compiled with -fno-exceptions (then new won't throw std::bad_alloc but it will return nullptr instead) the standard C++ library libstdc++ is compiled with exceptions then new will still throw std::bad_alloc when you're running out-of-memory.
That said, seriously, when you're running out-of-memory to crash as fast as possible is (more often than not) the best thing you can do. If you need some some sort of reliability it's much easier to have a monitor process that will restart your application.
What V8 does? Obviously they overloaded new operator and when allocation fails (malloc() still returns NULL, of course) they call a special function to handle low memory conditions. It dumps some debug information, report this error (you may have a custom error handler) and then (if error handler returns) call FATAL() to quit the application.
Browse source code at api.cc on GitHub. From code, simply:
When V8 cannot allocated memory FatalProcessOutOfMemory is called.
The default OOM error handler is called and execution is stopped.

Memory allocation using "new" in Javascript

I have few basic questions about dynamic object creation using Javascript.
I understand that browser takes care of allocating memory space for any 'new' keyword found in the JS. If my understanding is correct, then i have following queries one by one.
Query #1 : Please refer the comments given below for the two lines inside 'sample' function. That is my first query.
function sample() {
var a = 5; // is the memory allocated for variable 'a' in stack ?
var b = new obj1(); // The object instance created for 'obj1' gets allocated in heap?
}
var obj1 = function() {
this.strDate = "";
}
Query #2: Once the execution scope is out of function sample(), will the browser engine free the memory allocated for both the variables. I have read about GC's reference algorithm & mark and sweep algorithm
and recommendations to assign null to variables once not in use, yet could not get a clear cut idea on the standards to be followed as we would do in C++. If variable a is there in stack, then I need not worry
and if obj1 instance is no longer accessible or say unmarked or no further reference to it, will it also be cleared by GC ?.
Query #3: Do browsers differ in allocating and freeing memory for the instances created using 'new' operator. ( I had seen only about heap profilers in chrome and rather few more terms related to it, but I have also come across 'out of stack space' error. Does that mean all browsers would universally use both stack and heap ?
Please help me out here ;)
As a programmer, in JavaScript you do not have control over stack or heap allocation. You create objects or primitives that are located somewhere in the memory. Internally JS engines (such as V8 or Spidermonkey) perform all kinds of optimizations. Generally you can think of everything as if it's stored on heap.
To get started you need to know that GC frees the memory from the objects that are not referenced. While you hold a reference to an object somewhere in your code, it will not be destroyed.
Browsers (JS engines) do not leak memory allocation abstraction to you. The error you're referring to is probably call stack exceeded that happens when too many functions are called (mostly due to recursion).

What's the role of "Isolate" in V8? and how can it be possible to make "Isolate" isolately?

The explanations of "Isolate" what I found so far.
exp #1: http://izs.me/v8-docs/classv8_1_1Isolate.html
"Isolate represents an isolated instance of the V8 engine.
V8 isolates have completely separate states. Objects from one isolate must not be used in other isolates. When V8 is initialized a default isolate is implicitly created and entered. The embedder can create additional isolates and use them in parallel in multiple threads. An isolate can be entered by at most one thread at any given time. The Locker/Unlocker API can be used to synchronize."
exp #2: https://developers.google.com/v8/get_started
"An isolate is a VM instance with its own heap."
OK, I see. "Isolate" is an isolate thread that can operate seperately. Followings are my questions.
It looks like just thread for me, except that it has its own heap. is there any difference?
I think "Isolate" can be used for implementing concurrent GC. The definition above says that each "Isolate" cannot be used in other "Isolate". But concurrent GC should check(or mark) the main(or other) thread(or Isolate)'s live objects. How can it be possible?
How can it be possible to protect their own objects? "Isolate" is a thread not a process. So other thread can access that thread's object if it knows the address. How could protect it? And I cannot understand the meaning of own heap. Because it can be accessed by other thread if other thread knows the address. And normal thread can have their heap in memory space. Since address space of heap is not seperated exactly but if one thread malloc a memory, how could other thread use it unless others know the address? What's the difference each thread just malloc their own heap space and "Isolate" have its own heap space?
My questions can be easily summarized that what is the role of the "Isolate" and how can it be possible to have their own heap space and why does it have to have its own heap.
It will be very helpful if someone shares some good documentations of "Isolate".
Thanks for reading.
---- Make the question clear ----
The key point of my question is that
Q: What makes google to implement isolate in V8?
what's the benefit of isolate and what would be a good example of using isolate in V8? What are they(isolates) executing concurrently?
It looks like just thread for me, except that it has its own heap. is there any difference?
They are orthogonal, a thread can execute multiple isolates at a time while an isolate can only be executed by one thread at a time. And of course one isolate can be executed by different threads at different times but it's probably not common. An isolate is only an instance of a JavaScript VM and it only has its own JavaScript heap, the normal process heap is still shared in the process as normal.
I think "Isolate" can be used for implementing concurrent GC. The definition above says that each "Isolate" cannot be used in other "Isolate". But concurrent GC should check(or mark) the main(or other) thread(or Isolate)'s live objects. How can it be possible?
Noncompacting sweep operation in a Mark&Sweep GC can be performed concurrently from another thread. Other GC operations, like compacting sweep, scavenge, marking can only be performed while JS is not executing in an isolate.
How can it be possible to protect their own objects? "Isolate" is a thread not a process. So other thread can access that thread's object if it knows the address. How could protect it? And I cannot understand the meaning of own heap. Because it can be accessed by other thread if other thread knows the address. And normal thread can have their heap in memory space. Since address space of heap is not seperated exactly but if one thread malloc a memory, how could other thread use it unless others know the address? What's the difference each thread just malloc their own heap space and "Isolate" have its own heap space?
Well you don't know the address and it's not possible to get it sticking to V8 API. Even if you could get the address, the address is not safe to use because V8 moves stuff in its heap constantly. And malloc will not return addresses that point to some isolate's js heap because obviously that memory has been malloced by the isolate.
Isolate : We can run several JavaScript functions independently using a single instance of V8.

stack and heap in V8 ( JavaScript)

does V8 uses stack and heap like the JVM?
if so does it put primitives on the stack and objects on the heap?
In V8 null, undefined, true and false internally are heap allocated objects. If you are comming from Java you can say that true and false in V8 are more like Boolean.TRUE and Boolean.FALSE in Java.
There is an important difference between real local variables and variables that are captured by closures or shadowed by eval/with. Captures variables are stored in a special heap allocated structure called Context and are accessed indirectly. For more details about real vs. context allocates variables see my answer to a different question
V8 has two compilers: non-optimizing (aka full) and optimizing one:
Non-optimizing compiler can't store floating point numbers and integers beyond 31-bit (32-bit on x64) on the stack it always boxes them into HeapNumbers. It does not try to do register allocation and stores real local variables on the stack.
Optimizing compiler is much smarter. It does register allocation (linear scan) and can keep full 32-bit integers and floating point numbers on the stack and in the registers (including XMM registers).
Speaking of JVM: it can perform so called stack allocation and allocate a non-escaping object on the stack instead of the heap. A more generic optimization (scalar replacement) can sometimes completely eliminate allocation of non-escaping object and explode it into separate fields.
Yes, V8 uses a heap similar to JVM and most other languages. This, however, means that local variables (as a general rule) are put on the stack and objects in the heap. This may for instance not hold if a function closes over these values.
As in the JVM, primitives can only be stored on the stack if they are stored in a local variable.
As a user it is not something you would normally need to worry about.
In the most general terms, Yes V8 uses a heap and stack for functioning wherein general local variables are stored in the stack while the objects that need to be maintained are stored in the heap.

Categories