Skip to content

Instantly share code, notes, and snippets.

@naugtur
Forked from justjavac/GetOptimizationStatus.md
Created August 9, 2019 21:08
Show Gist options
  • Save naugtur/4b03a9f9f72346a9f79d7969728a849f to your computer and use it in GitHub Desktop.
Save naugtur/4b03a9f9f72346a9f79d7969728a849f to your computer and use it in GitHub Desktop.
V8 %GetOptimizationStatus

%GetOptimizationStatus return a set of bitwise flags instead of a single value, to access the value, you need to take the binary representation of the returned value. Now, for example, if 65 is returned, the binary representation is the following:

(65).toString(2).padStart(12, '0');
// 000001000001

Each binary digit acts as a boolean with the following meaning:

0 0 0 0 0 1 0 0 0 0 0 1
┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ │ │ │ │ │ │ └─╸ is function
│ │ │ │ │ │ │ │ │ │ └───╸ is never optimized
│ │ │ │ │ │ │ │ │ └─────╸ is always optimized
│ │ │ │ │ │ │ │ └───────╸ is maybe deoptimized
│ │ │ │ │ │ │ └─────────╸ is optimized
│ │ │ │ │ │ └───────────╸ is optimized by TurboFan
│ │ │ │ │ └─────────────╸ is interpreted
│ │ │ │ └───────────────╸ is marked for optimization
│ │ │ └─────────────────╸ is marked for concurrent optimization
│ │ └───────────────────╸ is optimizing concurrently
│ └─────────────────────╸ is executing
└───────────────────────╸ topmost frame is turbo fanned

test.js:

// Function that contains the pattern to be inspected (using an `with` statement)
function fn() {
    with ({ i: 0, v: 0 }) {
        return v;
    }
}

function printStatus(fn) {
    const status = %GetOptimizationStatus(fn);
    console.log(status.toString(2).padStart(12, '0'));

    if (status & (1 << 0)) {
        console.log("is function");
    }

    if (status & (1 << 1)) {
        console.log("is never optimized");
    }
    
    if (status & (1 << 2)) {
        console.log("is always optimized");
    }
    
    if (status & (1 << 3)) {
        console.log("is maybe deoptimized");
    }
    
    if (status & (1 << 4)) {
        console.log("is optimized");
    }
    
    if (status & (1 << 5)) {
        console.log("is optimized by TurboFan");
    }
    
    if (status & (1 << 6)) {
        console.log("is interpreted");
    }
    
    if (status & (1 << 7)) {
        console.log("is marked for optimization");
    }
    
    if (status & (1 << 8)) {
        console.log("is marked for concurrent optimization");
    }
    
    if (status & (1 << 9)) {
        console.log("is optimizing concurrently");
    }
    
    if (status & (1 << 10)) {
        console.log("is executing");
    }
    
    if (status & (1 << 11)) {
        console.log("topmost frame is turbo fanned");
    }
}

console.log('0. prepare function for optimization');
printStatus(fn);

console.log("1. fill type-info");
fn();

console.log('2. calls function to go from uninitialized -> pre-monomorphic -> monomorphic')
fn();
printStatus(fn);

%OptimizeFunctionOnNextCall(fn);

console.log('3. optimize function on next call')
printStatus(fn);

console.log('4. next call')
fn();

console.log('5. get optimization status')
printStatus(fn);

Run it:

node --allow-natives-syntax test.js

or with details:

node --trace_opt --trace_deopt --allow-natives-syntax test.js
@hinell
Copy link

hinell commented Sep 30, 2020

Any idea what are intrinsics used for?

Exact decoding of the OptimizationStatus enum can be found at the runtime.h#L822.
The full list of instrinsics can be found at runtime.h.

enum class OptimizationStatus {
  kIsFunction = 1 << 0,
  kNeverOptimize = 1 << 1,
  kAlwaysOptimize = 1 << 2,
  kMaybeDeopted = 1 << 3,
  kOptimized = 1 << 4,
  kTurboFanned = 1 << 5,
  kInterpreted = 1 << 6,
  kMarkedForOptimization = 1 << 7,
  kMarkedForConcurrentOptimization = 1 << 8,
  kOptimizingConcurrently = 1 << 9,
  kIsExecuting = 1 << 10,
  kTopmostFrameIsTurboFanned = 1 << 11,
  kLiteMode = 1 << 12,
  kMarkedForDeoptimization = 1 << 13,
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment