1 // Copyright 2015 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_FRAME_STATES_H_
6 #define V8_COMPILER_FRAME_STATES_H_
7 
8 #include "src/builtins/builtins.h"
9 #include "src/compiler/node.h"
10 #include "src/handles/handles.h"
11 #include "src/objects/shared-function-info.h"
12 #include "src/utils/utils.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 namespace wasm {
18 class ValueType;
19 using FunctionSig = Signature<ValueType>;
20 }  // namespace wasm
21 
22 namespace compiler {
23 
24 class JSGraph;
25 class Node;
26 class SharedFunctionInfoRef;
27 
28 // Flag that describes how to combine the current environment with
29 // the output of a node to obtain a framestate for lazy bailout.
30 class OutputFrameStateCombine {
31  public:
32   static const size_t kInvalidIndex = SIZE_MAX;
33 
Ignore()34   static OutputFrameStateCombine Ignore() {
35     return OutputFrameStateCombine(kInvalidIndex);
36   }
PokeAt(size_t index)37   static OutputFrameStateCombine PokeAt(size_t index) {
38     return OutputFrameStateCombine(index);
39   }
40 
GetOffsetToPokeAt()41   size_t GetOffsetToPokeAt() const {
42     DCHECK_NE(parameter_, kInvalidIndex);
43     return parameter_;
44   }
45 
IsOutputIgnored()46   bool IsOutputIgnored() const { return parameter_ == kInvalidIndex; }
47 
ConsumedOutputCount()48   size_t ConsumedOutputCount() const { return IsOutputIgnored() ? 0 : 1; }
49 
50   bool operator==(OutputFrameStateCombine const& other) const {
51     return parameter_ == other.parameter_;
52   }
53   bool operator!=(OutputFrameStateCombine const& other) const {
54     return !(*this == other);
55   }
56 
57   friend size_t hash_value(OutputFrameStateCombine const&);
58   friend std::ostream& operator<<(std::ostream&,
59                                   OutputFrameStateCombine const&);
60 
61  private:
OutputFrameStateCombine(size_t parameter)62   explicit OutputFrameStateCombine(size_t parameter) : parameter_(parameter) {}
63 
64   size_t const parameter_;
65 };
66 
67 
68 // The type of stack frame that a FrameState node represents.
69 enum class FrameStateType {
70   kUnoptimizedFunction,            // Represents an UnoptimizedFrame.
71   kArgumentsAdaptor,               // Represents an ArgumentsAdaptorFrame.
72   kConstructStub,                  // Represents a ConstructStubFrame.
73   kBuiltinContinuation,            // Represents a continuation to a stub.
74 #if V8_ENABLE_WEBASSEMBLY          // ↓ WebAssembly only
75   kJSToWasmBuiltinContinuation,    // Represents a lazy deopt continuation for a
76                                    // JS to Wasm call.
77 #endif                             // ↑ WebAssembly only
78   kJavaScriptBuiltinContinuation,  // Represents a continuation to a JavaScipt
79                                    // builtin.
80   kJavaScriptBuiltinContinuationWithCatch  // Represents a continuation to a
81                                            // JavaScipt builtin with a catch
82                                            // handler.
83 };
84 
85 class FrameStateFunctionInfo {
86  public:
FrameStateFunctionInfo(FrameStateType type,int parameter_count,int local_count,Handle<SharedFunctionInfo> shared_info)87   FrameStateFunctionInfo(FrameStateType type, int parameter_count,
88                          int local_count,
89                          Handle<SharedFunctionInfo> shared_info)
90       : type_(type),
91         parameter_count_(parameter_count),
92         local_count_(local_count),
93         shared_info_(shared_info) {}
94 
local_count()95   int local_count() const { return local_count_; }
parameter_count()96   int parameter_count() const { return parameter_count_; }
shared_info()97   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
type()98   FrameStateType type() const { return type_; }
99 
IsJSFunctionType(FrameStateType type)100   static bool IsJSFunctionType(FrameStateType type) {
101     return type == FrameStateType::kUnoptimizedFunction ||
102            type == FrameStateType::kJavaScriptBuiltinContinuation ||
103            type == FrameStateType::kJavaScriptBuiltinContinuationWithCatch;
104   }
105 
106  private:
107   FrameStateType const type_;
108   int const parameter_count_;
109   int const local_count_;
110   Handle<SharedFunctionInfo> const shared_info_;
111 };
112 
113 #if V8_ENABLE_WEBASSEMBLY
114 class JSToWasmFrameStateFunctionInfo : public FrameStateFunctionInfo {
115  public:
JSToWasmFrameStateFunctionInfo(FrameStateType type,int parameter_count,int local_count,Handle<SharedFunctionInfo> shared_info,const wasm::FunctionSig * signature)116   JSToWasmFrameStateFunctionInfo(FrameStateType type, int parameter_count,
117                                  int local_count,
118                                  Handle<SharedFunctionInfo> shared_info,
119                                  const wasm::FunctionSig* signature)
120       : FrameStateFunctionInfo(type, parameter_count, local_count, shared_info),
121         signature_(signature) {
122     DCHECK_NOT_NULL(signature);
123   }
124 
signature()125   const wasm::FunctionSig* signature() const { return signature_; }
126 
127  private:
128   const wasm::FunctionSig* const signature_;
129 };
130 #endif  // V8_ENABLE_WEBASSEMBLY
131 
132 class FrameStateInfo final {
133  public:
FrameStateInfo(BytecodeOffset bailout_id,OutputFrameStateCombine state_combine,const FrameStateFunctionInfo * info)134   FrameStateInfo(BytecodeOffset bailout_id,
135                  OutputFrameStateCombine state_combine,
136                  const FrameStateFunctionInfo* info)
137       : bailout_id_(bailout_id),
138         frame_state_combine_(state_combine),
139         info_(info) {}
140 
type()141   FrameStateType type() const {
142     return info_ == nullptr ? FrameStateType::kUnoptimizedFunction
143                             : info_->type();
144   }
bailout_id()145   BytecodeOffset bailout_id() const { return bailout_id_; }
state_combine()146   OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
shared_info()147   MaybeHandle<SharedFunctionInfo> shared_info() const {
148     return info_ == nullptr ? MaybeHandle<SharedFunctionInfo>()
149                             : info_->shared_info();
150   }
parameter_count()151   int parameter_count() const {
152     return info_ == nullptr ? 0 : info_->parameter_count();
153   }
local_count()154   int local_count() const {
155     return info_ == nullptr ? 0 : info_->local_count();
156   }
function_info()157   const FrameStateFunctionInfo* function_info() const { return info_; }
158 
159  private:
160   BytecodeOffset const bailout_id_;
161   OutputFrameStateCombine const frame_state_combine_;
162   const FrameStateFunctionInfo* const info_;
163 };
164 
165 bool operator==(FrameStateInfo const&, FrameStateInfo const&);
166 bool operator!=(FrameStateInfo const&, FrameStateInfo const&);
167 
168 size_t hash_value(FrameStateInfo const&);
169 
170 std::ostream& operator<<(std::ostream&, FrameStateInfo const&);
171 
172 enum class ContinuationFrameStateMode { EAGER, LAZY, LAZY_WITH_CATCH };
173 
174 class FrameState;
175 
176 FrameState CreateStubBuiltinContinuationFrameState(
177     JSGraph* graph, Builtin name, Node* context, Node* const* parameters,
178     int parameter_count, Node* outer_frame_state,
179     ContinuationFrameStateMode mode,
180     const wasm::FunctionSig* signature = nullptr);
181 
182 #if V8_ENABLE_WEBASSEMBLY
183 FrameState CreateJSWasmCallBuiltinContinuationFrameState(
184     JSGraph* jsgraph, Node* context, Node* outer_frame_state,
185     const wasm::FunctionSig* signature);
186 #endif  // V8_ENABLE_WEBASSEMBLY
187 
188 FrameState CreateJavaScriptBuiltinContinuationFrameState(
189     JSGraph* graph, const SharedFunctionInfoRef& shared, Builtin name,
190     Node* target, Node* context, Node* const* stack_parameters,
191     int stack_parameter_count, Node* outer_frame_state,
192     ContinuationFrameStateMode mode);
193 
194 FrameState CreateGenericLazyDeoptContinuationFrameState(
195     JSGraph* graph, const SharedFunctionInfoRef& shared, Node* target,
196     Node* context, Node* receiver, Node* outer_frame_state);
197 
198 }  // namespace compiler
199 }  // namespace internal
200 }  // namespace v8
201 
202 #endif  // V8_COMPILER_FRAME_STATES_H_
203