Garbage collector forced deoptimization of this code because it contained a weak reference to a map (hidden class) that died during this GC cycle.
Garbage collector forced deoptimization of this code because it contained a weak reference to a map (hidden class) that died during this GC cycle.
This optimized code depended on a transition between maps (hidden classes) that was replaced by a new version.
This optimized code was generated in the assumption that certain prototype never changes hidden class. It was deoptimized because that prototype transitioned to a new hidden class.
This optimized code was generated in the assumption that certain object has no elements (indexed properties "0"
, "1"
, ...).
It was deoptimized because elements were added to that object.
This optimized code was generated in the assumption that certain global variable stays contant. It was deoptimized because value of that variable changed.
This optimized code was generated in the assumption that certain properties have specific type in all instances of the given hidden class. It was deoptimized because this assumption was violated.
This optimized code was generated in the assumption that initial map associated with the given constructor stays the same. This assumption was violated.
This optimized code embeds tenuring decisions that were invalidated by allocation site profiling.
This optimized code embeds elements transition decisions that were invalidated by allocation site profiling.
This instruction has side effects unknown to the compiler.
It can change hidden classes of objects, kind of array backing stores, etc.
Such instructions should be avoided inside hot loops because they inhibit optimizations.
An implementation detail of the On Stack Replacement mechanism
On Stack Replacement (OSR) is a process when an unoptimized code for a running function is replaced by an optimized code while the function is running (is on the stack). OSR is used to optimize functions with long running loops while these loops are still running.
In this case function is entered through a special block known as an OSR entry point instead of the normal entry (B0
). UnknownOSRValue
instructions evaluate to the values that were in the corresponding places in the environment (a set of local and parameter values) during execution of the unoptimized code - allowing optimized code to continue from the place where unoptimized code was.
Block containing these instructions is never executed if the function entered through normal entry.
OSR entry block inhibits LICM, so if OSR occured in one of the inner loops instead of the outermost one it might negatively impact code quality.
An implementation detail of the On Stack Replacement mechanism
On Stack Replacement (OSR) is a process when an unoptimized code for a running function is replaced by an optimized code while the function is running (is on the stack). OSR is used to optimize functions with long running loops while these loops are still running.
In this case function is entered through a special block known as an OSR entry point instead of the normal entry (B0
). UnknownOSRValue
instructions evaluate to the values that were in the corresponding places in the environment (a set of local and parameter values) during execution of the unoptimized code - allowing optimized code to continue from the place where unoptimized code was.
Block containing these instructions is never executed if the function entered through normal entry.
OSR entry block inhibits LICM, so if OSR occured in one of the inner loops instead of the outermost one it might negatively impact code quality.
Checks whether value's hidden class matches expected value and deoptimizes if this is not the case.
Deoptimization at CheckMaps
usually indicates that the code is polymorphic.
When executed this instruction always deoptimizes.
V8 generates them on control flow paths that were never executed before and thus contain no actionable type feedback that could be used to optimize the code.
For a function with a long running loop it is not uncommon to hit at OSR in the loop and then deoptimize on a Deoptimize
emitted after the loop
This is a pseudo instruction that follows every call.
Some assumptions V8's optimizing compiler makes are not explicitly checked in the optimized code itself. Instead they are guarded globally in the runtime system. When a change happens that violates an assumption all optimized code depending on this assumption has to be discarded.
If dependant code is currently active on the call stack it is marked for lazy deoptimization, i.e. deoptimization that will happen as soon as control returns into it. That's why lazy deoptimization always follows a call.
Reasons for invalidating currently running optimized code via lazy deoptimization code can be numerous:
This instruction converts value from one internal representation to another.
It will deoptimize if the value can't be converted
Conversion from a tagged representation to a 32-bit signed integer. Can be either truncating or exact (see if hydrogen counterpart is marked with truncating-int32
.
Deoptimizes when source is not representable in this format. Truncating conversions deoptimize when value is too big for an int32 type or not a number or undefined
. Exact conversions deoptimize if ToInt32(val) != val
Checks that value is a tagged smi (small integer): it is a tagged integer representation used by V8.
On 32bit platforms smi can contain 31-bit signed integers and on 64bit platforms they are wide enough for 32bit signed integers.
If numeric value does not fit into a smi it has to be boxed as a heap number.
This pane contains control flow graph of the method: vertices are blocks and edges are branches between them.
CFG block with label |
|
Control flow edge between blocks. Red color is used to mark loops' backedges. | |
Block that contains an unconditional deoptimization instruction. Such blocks always deoptimize when executed. Usually inserted when building IR for the parts of function that were never executed and thus have no type feedback to speculate upon. | |
Block that was marked as unreachable. No code will be generated from it. | |
Block that contains an instruction that has unknown arbitrary side-effects (marked with changes[*] ).
|
|
Fill color denotes hotness of the block: the more intense the hotter. If perf annotate profile is loaded the hotness is computed based on the number of ticks. Otherwise it is approximated from loop nesting - color is more intense inside nested loops.
|