Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

192
Views
Does V8 monitor the execution of optimized machine code?

AFAIK, there are roughly two kinds of code objects in V8. One is javascript bytecode interpreted by Ignition, and the other is machine code which is compiled & optimized by Turbofan. According to the execution/frames.h, V8 constructs a different stackframe for each kind of code object. It means V8 should know the kind of the callee before it executes.

When unoptimized code(JS Bytecode) calls the optimized one, I guess that Ignition could handle the case properly to build a new stackframe for an optimized one. However, when the optimized code(machine code) calls the unoptimized one, I'm curious about how V8 determines whether callee is unoptimized or not. If the machine code is run directly on the processor, nothing can help V8 determine the kind of callee.

Also, in my understanding, V8 should detect whether some code dependency is compromised to mark or deoptimize the invalidated code objects. It also seems infeasible if V8 doesn't monitor the execution of machine code.

So my question is:

  1. Does V8 monitor the execution of (optimized) machine code? If so, how does it happen?

  2. If 1 is false, then how does V8 check the invalidation of code dependency or detect whether the callee is compiled or not?

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

(V8 developer here.)

V8 constructs a different stackframe for each kind of code object. It means V8 should know the kind of the callee before it executes.

Stack frames are set up by whoever needs them, so callers don't have to inspect callees. (They could, if they had to.)

If the machine code is run directly on the processor, nothing can help V8 determine the kind of callee.

V8 could emit machine code that checks the kind of callee. But to repeat myself: knowing the optimization status of a callee isn't necessary.

Does V8 monitor the execution of (optimized) machine code?

No, it doesn't.

how does V8 check the invalidation of code dependency

Dependencies are installed on something that can change (e.g. maps, protectors). When that change happens, registered code dependencies will be deoptimized (i.e. marked for "lazy deoptimization" when they have activations on the stack, or simply thrown away otherwise).

[how does V8] detect whether the callee is compiled or not?

It doesn't need to. When a function isn't compiled yet, its "code" will be a stub that triggers compilation.

about 4 years ago · Juan Pablo Isaza Report

0

To look at the concrete example you gave in the comments:

var b = false;

function change_o() {
  // as long as b is false, this won't be reassigned ...
  if (b) o = { y : 1, x : 0};
}

var o = { x : 1 };

function f() {
  change_o();
  // ... and thus o.x can be compiled down
  return o.x;
}

// f and change_o are compiled somewhen 
f(); f(); f(); // ...

// a precondition changes
b = true;

// during execution of change_o o is reassigned and changes its shape, accessing o.x will now need a different offset and thus f (which is currently on the stack) becomes invalid
f();

Thus at the moment the assignment o = happens, the runtime jumps into some deoptimization logic, which has to invalidate all the code based on the false assumption. Invalidating calls from non-compiled code to compiled code is easy, simply remove the reference to the compiled code from some kind of registry and nobobdy will call it anymore. Invalidating future calls from compiled functions to the invalidated compiled function is harder, though if the call uses some indirection, this indirection can be rewritten to redirect all future calls. This leaves two kind of invalidation problems:

  • the currently evaluated function needs to be invalidated (-> eager deoptimization), not that problematic either as it's the function that bailed out to the deoptimization routine
  • a function that called the evaluated function needs to be invalidated (-> lazy deoptimization), this is problematic, as they might be somewhere in the stack, and continuing execution would somewhen resume to them (e.g. f in the example above)

However in the later case, there is a way to find and replace those functions: Every time one function calls to another, it pushes the return address onto the stack (see e.g. x86 stack usage), and when the called function executes the ret instruction, it pops the address und jumps there. Thus by scanning the stack for return addresses residing inside invalidated functions, and replacing those by another address, when the inner function like change_o returns to f, it doesn't actually jump back to the compiled f code but into a handler, which can then make the necessary adjustments.

So V8 does not "monitor" the execution, it actively modifies it when necessary by rewriting the stack.

A detailed walkthrough can be found here.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!