Line data Source code
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 24853692 : size_t hash_value(OutputFrameStateCombine const& sc) {
20 24853692 : return base::hash_value(sc.parameter_);
21 : }
22 :
23 :
24 0 : std::ostream& operator<<(std::ostream& os, OutputFrameStateCombine const& sc) {
25 0 : if (sc.parameter_ == OutputFrameStateCombine::kInvalidIndex)
26 0 : return os << "Ignore";
27 0 : return os << "PokeAt(" << sc.parameter_ << ")";
28 : }
29 :
30 :
31 14997892 : bool operator==(FrameStateInfo const& lhs, FrameStateInfo const& rhs) {
32 7422863 : return lhs.type() == rhs.type() && lhs.bailout_id() == rhs.bailout_id() &&
33 8042868 : lhs.state_combine() == rhs.state_combine() &&
34 7498946 : lhs.function_info() == rhs.function_info();
35 : }
36 :
37 :
38 0 : bool operator!=(FrameStateInfo const& lhs, FrameStateInfo const& rhs) {
39 0 : return !(lhs == rhs);
40 : }
41 :
42 :
43 49707624 : size_t hash_value(FrameStateInfo const& info) {
44 : return base::hash_combine(static_cast<int>(info.type()), info.bailout_id(),
45 49707298 : info.state_combine());
46 : }
47 :
48 :
49 0 : std::ostream& operator<<(std::ostream& os, FrameStateType type) {
50 0 : switch (type) {
51 : case FrameStateType::kInterpretedFunction:
52 0 : os << "INTERPRETED_FRAME";
53 0 : break;
54 : case FrameStateType::kArgumentsAdaptor:
55 0 : os << "ARGUMENTS_ADAPTOR";
56 0 : break;
57 : case FrameStateType::kConstructStub:
58 0 : os << "CONSTRUCT_STUB";
59 0 : break;
60 : case FrameStateType::kBuiltinContinuation:
61 0 : os << "BUILTIN_CONTINUATION_FRAME";
62 0 : break;
63 : case FrameStateType::kJavaScriptBuiltinContinuation:
64 0 : os << "JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME";
65 0 : break;
66 : case FrameStateType::kGetterStub:
67 0 : os << "GETTER_STUB";
68 0 : break;
69 : case FrameStateType::kSetterStub:
70 0 : os << "SETTER_STUB";
71 0 : break;
72 : }
73 0 : return os;
74 : }
75 :
76 :
77 0 : std::ostream& operator<<(std::ostream& os, FrameStateInfo const& info) {
78 0 : os << info.type() << ", " << info.bailout_id() << ", "
79 0 : << info.state_combine();
80 : Handle<SharedFunctionInfo> shared_info;
81 0 : if (info.shared_info().ToHandle(&shared_info)) {
82 0 : os << ", " << Brief(*shared_info);
83 : }
84 0 : return os;
85 : }
86 :
87 : namespace {
88 2935 : Node* CreateBuiltinContinuationFrameStateCommon(
89 2935 : JSGraph* js_graph, Builtins::Name name, Node* context, Node** parameters,
90 : int parameter_count, Node* outer_frame_state, Handle<JSFunction> function) {
91 : Isolate* isolate = js_graph->isolate();
92 : Graph* graph = js_graph->graph();
93 : CommonOperatorBuilder* common = js_graph->common();
94 :
95 2935 : BailoutId bailout_id = Builtins::GetContinuationBailoutId(name);
96 2935 : Callable callable = Builtins::CallableFor(isolate, name);
97 :
98 : const Operator* op_param =
99 2935 : common->StateValues(parameter_count, SparseInputMask::Dense());
100 2935 : Node* params_node = graph->NewNode(op_param, parameter_count, parameters);
101 :
102 : FrameStateType frame_type =
103 : function.is_null() ? FrameStateType::kBuiltinContinuation
104 2935 : : FrameStateType::kJavaScriptBuiltinContinuation;
105 : const FrameStateFunctionInfo* state_info =
106 : common->CreateFrameStateFunctionInfo(
107 : frame_type, parameter_count, 0,
108 : function.is_null() ? Handle<SharedFunctionInfo>()
109 4162 : : Handle<SharedFunctionInfo>(function->shared()));
110 : const Operator* op = common->FrameState(
111 2935 : bailout_id, OutputFrameStateCombine::Ignore(), state_info);
112 :
113 : Node* function_node = function.is_null() ? js_graph->UndefinedConstant()
114 4162 : : js_graph->HeapConstant(function);
115 :
116 : Node* frame_state = graph->NewNode(
117 : op, params_node, js_graph->EmptyStateValues(),
118 2935 : js_graph->EmptyStateValues(), context, function_node, outer_frame_state);
119 :
120 2935 : return frame_state;
121 : }
122 : } // namespace
123 :
124 1708 : Node* CreateStubBuiltinContinuationFrameState(JSGraph* js_graph,
125 : Builtins::Name name,
126 : Node* context, Node** parameters,
127 : int parameter_count,
128 : Node* outer_frame_state,
129 : ContinuationFrameStateMode mode) {
130 : Isolate* isolate = js_graph->isolate();
131 1708 : Callable callable = Builtins::CallableFor(isolate, name);
132 : CallInterfaceDescriptor descriptor = callable.descriptor();
133 :
134 : std::vector<Node*> actual_parameters;
135 : // Stack parameters first. If the deoptimization is LAZY, the final parameter
136 : // is added by the deoptimizer and isn't explicitly passed in the frame state.
137 : int stack_parameter_count =
138 1708 : descriptor.GetRegisterParameterCount() -
139 1708 : (mode == ContinuationFrameStateMode::LAZY ? 1 : 0);
140 1708 : for (int i = 0; i < stack_parameter_count; ++i) {
141 : actual_parameters.push_back(
142 0 : parameters[descriptor.GetRegisterParameterCount() + i]);
143 : }
144 : // Register parameters follow, context will be added by instruction selector
145 : // during FrameState translation.
146 1708 : for (int i = 0; i < descriptor.GetRegisterParameterCount(); ++i) {
147 0 : actual_parameters.push_back(parameters[i]);
148 : }
149 :
150 : return CreateBuiltinContinuationFrameStateCommon(
151 : js_graph, name, context, actual_parameters.data(),
152 1708 : static_cast<int>(actual_parameters.size()), outer_frame_state,
153 3416 : Handle<JSFunction>());
154 : }
155 :
156 1227 : Node* CreateJavaScriptBuiltinContinuationFrameState(
157 1227 : JSGraph* js_graph, Handle<JSFunction> function, Builtins::Name name,
158 : Node* target, Node* context, Node** stack_parameters,
159 : int stack_parameter_count, Node* outer_frame_state,
160 : ContinuationFrameStateMode mode) {
161 : Isolate* isolate = js_graph->isolate();
162 1227 : Callable callable = Builtins::CallableFor(isolate, name);
163 :
164 : // Lazy deopt points where the frame state is assocated with a call get an
165 : // additional parameter for the return result from the call that's added by
166 : // the deoptimizer and not explicitly specified in the frame state. Check that
167 : // there is not a mismatch between the number of frame state parameters and
168 : // the stack parameters required by the builtin taking this into account.
169 : DCHECK_EQ(Builtins::GetStackParameterCount(name) + 1, // add receiver
170 : stack_parameter_count +
171 : (mode == ContinuationFrameStateMode::EAGER ? 0 : 1));
172 :
173 : Node* argc =
174 : js_graph->Constant(stack_parameter_count -
175 1227 : (mode == ContinuationFrameStateMode::EAGER ? 1 : 0));
176 :
177 : // Stack parameters first. They must be first because the receiver is expected
178 : // to be the second value in the translation when creating stack crawls
179 : // (e.g. Error.stack) of optimized JavaScript frames.
180 : std::vector<Node*> actual_parameters;
181 7881 : for (int i = 0; i < stack_parameter_count; ++i) {
182 6654 : actual_parameters.push_back(stack_parameters[i]);
183 : }
184 :
185 : // Register parameters follow stack paraemters. The context will be added by
186 : // instruction selector during FrameState translation.
187 1227 : actual_parameters.push_back(target);
188 2454 : actual_parameters.push_back(js_graph->UndefinedConstant());
189 1227 : actual_parameters.push_back(argc);
190 :
191 : return CreateBuiltinContinuationFrameStateCommon(
192 : js_graph, name, context, &actual_parameters[0],
193 3681 : static_cast<int>(actual_parameters.size()), outer_frame_state, function);
194 : }
195 :
196 : } // namespace compiler
197 : } // namespace internal
198 : } // namespace v8
|