V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
frame-states.cc
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 #include "src/compiler/frame-states.h"
6 
7 #include "src/base/functional.h"
8 #include "src/callable.h"
9 #include "src/compiler/graph.h"
10 #include "src/compiler/js-graph.h"
11 #include "src/compiler/node.h"
12 #include "src/handles-inl.h"
13 #include "src/objects-inl.h"
14 
15 namespace v8 {
16 namespace internal {
17 namespace compiler {
18 
19 size_t hash_value(OutputFrameStateCombine const& sc) {
20  return base::hash_value(sc.parameter_);
21 }
22 
23 
24 std::ostream& operator<<(std::ostream& os, OutputFrameStateCombine const& sc) {
25  if (sc.parameter_ == OutputFrameStateCombine::kInvalidIndex)
26  return os << "Ignore";
27  return os << "PokeAt(" << sc.parameter_ << ")";
28 }
29 
30 
31 bool operator==(FrameStateInfo const& lhs, FrameStateInfo const& rhs) {
32  return lhs.type() == rhs.type() && lhs.bailout_id() == rhs.bailout_id() &&
33  lhs.state_combine() == rhs.state_combine() &&
34  lhs.function_info() == rhs.function_info();
35 }
36 
37 
38 bool operator!=(FrameStateInfo const& lhs, FrameStateInfo const& rhs) {
39  return !(lhs == rhs);
40 }
41 
42 
43 size_t hash_value(FrameStateInfo const& info) {
44  return base::hash_combine(static_cast<int>(info.type()), info.bailout_id(),
45  info.state_combine());
46 }
47 
48 
49 std::ostream& operator<<(std::ostream& os, FrameStateType type) {
50  switch (type) {
51  case FrameStateType::kInterpretedFunction:
52  os << "INTERPRETED_FRAME";
53  break;
54  case FrameStateType::kArgumentsAdaptor:
55  os << "ARGUMENTS_ADAPTOR";
56  break;
57  case FrameStateType::kConstructStub:
58  os << "CONSTRUCT_STUB";
59  break;
60  case FrameStateType::kBuiltinContinuation:
61  os << "BUILTIN_CONTINUATION_FRAME";
62  break;
63  case FrameStateType::kJavaScriptBuiltinContinuation:
64  os << "JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME";
65  break;
66  case FrameStateType::kJavaScriptBuiltinContinuationWithCatch:
67  os << "JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME";
68  break;
69  }
70  return os;
71 }
72 
73 
74 std::ostream& operator<<(std::ostream& os, FrameStateInfo const& info) {
75  os << info.type() << ", " << info.bailout_id() << ", "
76  << info.state_combine();
77  Handle<SharedFunctionInfo> shared_info;
78  if (info.shared_info().ToHandle(&shared_info)) {
79  os << ", " << Brief(*shared_info);
80  }
81  return os;
82 }
83 
84 namespace {
85 
86 // Lazy deopt points where the frame state is assocated with a call get an
87 // additional parameter for the return result from the call. The return result
88 // is added by the deoptimizer and not explicitly specified in the frame state.
89 // Lazy deopt points which can catch exceptions further get an additional
90 // parameter, namely the exception thrown. The exception is also added by the
91 // deoptimizer.
92 uint8_t DeoptimizerParameterCountFor(ContinuationFrameStateMode mode) {
93  switch (mode) {
94  case ContinuationFrameStateMode::EAGER:
95  return 0;
96  case ContinuationFrameStateMode::LAZY:
97  return 1;
98  case ContinuationFrameStateMode::LAZY_WITH_CATCH:
99  return 2;
100  }
101  UNREACHABLE();
102 }
103 
104 Node* CreateBuiltinContinuationFrameStateCommon(
105  JSGraph* jsgraph, FrameStateType frame_type, Builtins::Name name,
106  Node* closure, Node* context, Node** parameters, int parameter_count,
107  Node* outer_frame_state,
108  Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>()) {
109  Isolate* const isolate = jsgraph->isolate();
110  Graph* const graph = jsgraph->graph();
111  CommonOperatorBuilder* const common = jsgraph->common();
112 
113  BailoutId bailout_id = Builtins::GetContinuationBailoutId(name);
114  Callable callable = Builtins::CallableFor(isolate, name);
115 
116  const Operator* op_param =
117  common->StateValues(parameter_count, SparseInputMask::Dense());
118  Node* params_node = graph->NewNode(op_param, parameter_count, parameters);
119 
120  const FrameStateFunctionInfo* state_info =
121  common->CreateFrameStateFunctionInfo(frame_type, parameter_count, 0,
122  shared);
123  const Operator* op = common->FrameState(
124  bailout_id, OutputFrameStateCombine::Ignore(), state_info);
125 
126  Node* frame_state = graph->NewNode(
127  op, params_node, jsgraph->EmptyStateValues(), jsgraph->EmptyStateValues(),
128  context, closure, outer_frame_state);
129 
130  return frame_state;
131 }
132 
133 } // namespace
134 
135 Node* CreateStubBuiltinContinuationFrameState(
136  JSGraph* jsgraph, Builtins::Name name, Node* context,
137  Node* const* parameters, int parameter_count, Node* outer_frame_state,
138  ContinuationFrameStateMode mode) {
139  Isolate* isolate = jsgraph->isolate();
140  Callable callable = Builtins::CallableFor(isolate, name);
141  CallInterfaceDescriptor descriptor = callable.descriptor();
142 
143  std::vector<Node*> actual_parameters;
144  // Stack parameters first. Depending on {mode}, final parameters are added
145  // by the deoptimizer and aren't explicitly passed in the frame state.
146  int stack_parameter_count =
147  descriptor.GetParameterCount() - DeoptimizerParameterCountFor(mode);
148  // Reserving space in the vector, except for the case where
149  // stack_parameter_count is -1.
150  actual_parameters.reserve(stack_parameter_count >= 0
151  ? stack_parameter_count +
152  descriptor.GetRegisterParameterCount()
153  : 0);
154  for (int i = 0; i < stack_parameter_count; ++i) {
155  actual_parameters.push_back(
156  parameters[descriptor.GetRegisterParameterCount() + i]);
157  }
158  // Register parameters follow, context will be added by instruction selector
159  // during FrameState translation.
160  for (int i = 0; i < descriptor.GetRegisterParameterCount(); ++i) {
161  actual_parameters.push_back(parameters[i]);
162  }
163 
164  return CreateBuiltinContinuationFrameStateCommon(
165  jsgraph, FrameStateType::kBuiltinContinuation, name,
166  jsgraph->UndefinedConstant(), context, actual_parameters.data(),
167  static_cast<int>(actual_parameters.size()), outer_frame_state);
168 }
169 
170 Node* CreateJavaScriptBuiltinContinuationFrameState(
171  JSGraph* jsgraph, const SharedFunctionInfoRef& shared, Builtins::Name name,
172  Node* target, Node* context, Node* const* stack_parameters,
173  int stack_parameter_count, Node* outer_frame_state,
174  ContinuationFrameStateMode mode) {
175  Isolate* const isolate = jsgraph->isolate();
176  Callable const callable = Builtins::CallableFor(isolate, name);
177 
178  // Depending on {mode}, final parameters are added by the deoptimizer
179  // and aren't explicitly passed in the frame state.
180  DCHECK_EQ(Builtins::GetStackParameterCount(name) + 1, // add receiver
181  stack_parameter_count + DeoptimizerParameterCountFor(mode));
182 
183  Node* argc = jsgraph->Constant(Builtins::GetStackParameterCount(name));
184 
185  // Stack parameters first. They must be first because the receiver is expected
186  // to be the second value in the translation when creating stack crawls
187  // (e.g. Error.stack) of optimized JavaScript frames.
188  std::vector<Node*> actual_parameters;
189  for (int i = 0; i < stack_parameter_count; ++i) {
190  actual_parameters.push_back(stack_parameters[i]);
191  }
192 
193  // Register parameters follow stack paraemters. The context will be added by
194  // instruction selector during FrameState translation.
195  actual_parameters.push_back(target);
196  actual_parameters.push_back(jsgraph->UndefinedConstant());
197  actual_parameters.push_back(argc);
198 
199  return CreateBuiltinContinuationFrameStateCommon(
200  jsgraph,
201  mode == ContinuationFrameStateMode::LAZY_WITH_CATCH
202  ? FrameStateType::kJavaScriptBuiltinContinuationWithCatch
203  : FrameStateType::kJavaScriptBuiltinContinuation,
204  name, target, context, &actual_parameters[0],
205  static_cast<int>(actual_parameters.size()), outer_frame_state,
206  shared.object());
207 }
208 
209 } // namespace compiler
210 } // namespace internal
211 } // namespace v8
Definition: libplatform.h:13