1// Copyright 2014 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef V8_COMPILER_OSR_H_ 6#define V8_COMPILER_OSR_H_ 7 8#include "src/zone.h" 9 10// TurboFan structures OSR graphs in a way that separates almost all phases of 11// compilation from OSR implementation details. This is accomplished with 12// special control nodes that are added at graph building time. In particular, 13// the graph is built in such a way that typing still computes the best types 14// and optimizations and lowering work unchanged. All that remains is to 15// deconstruct the OSR artifacts before scheduling and code generation. 16 17// Graphs built for OSR from the AstGraphBuilder are structured as follows: 18// Start 19// +-------------------^^-----+ 20// | | 21// OsrNormalEntry OsrLoopEntry <-------------+ 22// | | | 23// control flow before loop | A OsrValue 24// | | | | 25// | +------------------------+ | +-------+ 26// | | +-------------+ | | +--------+ 27// | | | | | | | | 28// ( Loop )<-----------|------------------ ( phi ) | 29// | | | 30// loop body | backedge(s) | 31// | | | | 32// | +--------------+ B <-----+ 33// | 34// end 35 36// The control structure expresses the relationship that the loop has a separate 37// entrypoint which corresponds to entering the loop directly from the middle 38// of unoptimized code. 39// Similarly, the values that come in from unoptimized code are represented with 40// {OsrValue} nodes that merge into any phis associated with the OSR loop. 41// In the above diagram, nodes {A} and {B} represent values in the "normal" 42// graph that correspond to the values of those phis before the loop and on any 43// backedges, respectively. 44 45// To deconstruct OSR, we simply replace the uses of the {OsrNormalEntry} 46// control node with {Dead} and {OsrLoopEntry} with start and run the 47// {ControlReducer}. Control reduction propagates the dead control forward, 48// essentially "killing" all the code before the OSR loop. The entrypoint to the 49// loop corresponding to the "normal" entry path will also be removed, as well 50// as the inputs to the loop phis, resulting in the reduced graph: 51 52// Start 53// Dead |^-------------------------+ 54// | | | 55// | | | 56// | | | 57// disconnected, dead | A=dead OsrValue 58// | | 59// +------------------+ +------+ 60// | +-------------+ | +--------+ 61// | | | | | | 62// ( Loop )<-----------|------------------ ( phi ) | 63// | | | 64// loop body | backedge(s) | 65// | | | | 66// | +--------------+ B <-----+ 67// | 68// end 69 70// Other than the presences of the OsrValue nodes, this is a normal, schedulable 71// graph. OsrValue nodes are handled specially in the instruction selector to 72// simply load from the unoptimized frame. 73 74// For nested OSR loops, loop peeling must first be applied as many times as 75// necessary in order to bring the OSR loop up to the top level (i.e. to be 76// an outer loop). 77 78namespace v8 { 79namespace internal { 80 81class CompilationInfo; 82 83namespace compiler { 84 85class JSGraph; 86class CommonOperatorBuilder; 87class Frame; 88class Linkage; 89 90// Encapsulates logic relating to OSR compilations as well has handles some 91// details of the frame layout. 92class OsrHelper { 93 public: 94 explicit OsrHelper(CompilationInfo* info); 95 // Only for testing. 96 OsrHelper(size_t parameter_count, size_t stack_slot_count) 97 : parameter_count_(parameter_count), 98 stack_slot_count_(stack_slot_count) {} 99 100 // Deconstructs the artificial {OsrNormalEntry} and rewrites the graph so 101 // that only the path corresponding to {OsrLoopEntry} remains. 102 void Deconstruct(JSGraph* jsgraph, CommonOperatorBuilder* common, 103 Zone* tmp_zone); 104 105 // Prepares the frame w.r.t. OSR. 106 void SetupFrame(Frame* frame); 107 108 // Returns the number of unoptimized frame slots for this OSR. 109 size_t UnoptimizedFrameSlots() { return stack_slot_count_; } 110 111 // Returns the environment index of the first stack slot. 112 static int FirstStackSlotIndex(int parameter_count) { 113 // n.b. unlike Crankshaft, TurboFan environments do not contain the context. 114 return 1 + parameter_count; // receiver + params 115 } 116 117 private: 118 size_t parameter_count_; 119 size_t stack_slot_count_; 120}; 121 122} // namespace compiler 123} // namespace internal 124} // namespace v8 125 126#endif // V8_COMPILER_OSR_H_ 127