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/js-intrinsic-lowering.h"
6 :
7 : #include <stack>
8 :
9 : #include "src/code-factory.h"
10 : #include "src/compiler/access-builder.h"
11 : #include "src/compiler/js-graph.h"
12 : #include "src/compiler/linkage.h"
13 : #include "src/compiler/node-matchers.h"
14 : #include "src/compiler/node-properties.h"
15 : #include "src/compiler/operator-properties.h"
16 : #include "src/counters.h"
17 : #include "src/objects-inl.h"
18 : #include "src/objects/js-generator.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 : namespace compiler {
23 :
24 464118 : JSIntrinsicLowering::JSIntrinsicLowering(Editor* editor, JSGraph* jsgraph)
25 464118 : : AdvancedReducer(editor), jsgraph_(jsgraph) {}
26 :
27 33794140 : Reduction JSIntrinsicLowering::Reduce(Node* node) {
28 33794140 : if (node->opcode() != IrOpcode::kJSCallRuntime) return NoChange();
29 : const Runtime::Function* const f =
30 383188 : Runtime::FunctionForId(CallRuntimeParametersOf(node->op()).id());
31 383189 : if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) return NoChange();
32 19830 : switch (f->function_id) {
33 : case Runtime::kInlineCreateIterResultObject:
34 1349 : return ReduceCreateIterResultObject(node);
35 : case Runtime::kInlineDeoptimizeNow:
36 3881 : return ReduceDeoptimizeNow(node);
37 : case Runtime::kInlineGeneratorClose:
38 182 : return ReduceGeneratorClose(node);
39 : case Runtime::kInlineCreateJSGeneratorObject:
40 1290 : return ReduceCreateJSGeneratorObject(node);
41 : case Runtime::kInlineAsyncFunctionAwaitCaught:
42 205 : return ReduceAsyncFunctionAwaitCaught(node);
43 : case Runtime::kInlineAsyncFunctionAwaitUncaught:
44 2569 : return ReduceAsyncFunctionAwaitUncaught(node);
45 : case Runtime::kInlineAsyncFunctionEnter:
46 1255 : return ReduceAsyncFunctionEnter(node);
47 : case Runtime::kInlineAsyncFunctionReject:
48 1210 : return ReduceAsyncFunctionReject(node);
49 : case Runtime::kInlineAsyncFunctionResolve:
50 1118 : return ReduceAsyncFunctionResolve(node);
51 : case Runtime::kInlineAsyncGeneratorAwaitCaught:
52 5 : return ReduceAsyncGeneratorAwaitCaught(node);
53 : case Runtime::kInlineAsyncGeneratorAwaitUncaught:
54 214 : return ReduceAsyncGeneratorAwaitUncaught(node);
55 : case Runtime::kInlineAsyncGeneratorReject:
56 182 : return ReduceAsyncGeneratorReject(node);
57 : case Runtime::kInlineAsyncGeneratorResolve:
58 182 : return ReduceAsyncGeneratorResolve(node);
59 : case Runtime::kInlineAsyncGeneratorYield:
60 62 : return ReduceAsyncGeneratorYield(node);
61 : case Runtime::kInlineGeneratorGetResumeMode:
62 5868 : return ReduceGeneratorGetResumeMode(node);
63 : case Runtime::kInlineIsArray:
64 26 : return ReduceIsInstanceType(node, JS_ARRAY_TYPE);
65 : case Runtime::kInlineIsTypedArray:
66 1 : return ReduceIsInstanceType(node, JS_TYPED_ARRAY_TYPE);
67 : case Runtime::kInlineIsJSReceiver:
68 26 : return ReduceIsJSReceiver(node);
69 : case Runtime::kInlineIsSmi:
70 30 : return ReduceIsSmi(node);
71 : case Runtime::kInlineToLength:
72 36 : return ReduceToLength(node);
73 : case Runtime::kInlineToObject:
74 0 : return ReduceToObject(node);
75 : case Runtime::kInlineToString:
76 13 : return ReduceToString(node);
77 : case Runtime::kInlineCall:
78 40 : return ReduceCall(node);
79 : default:
80 : break;
81 : }
82 : return NoChange();
83 : }
84 :
85 :
86 1349 : Reduction JSIntrinsicLowering::ReduceCreateIterResultObject(Node* node) {
87 1349 : Node* const value = NodeProperties::GetValueInput(node, 0);
88 1349 : Node* const done = NodeProperties::GetValueInput(node, 1);
89 1349 : Node* const context = NodeProperties::GetContextInput(node);
90 1349 : Node* const effect = NodeProperties::GetEffectInput(node);
91 : return Change(node, javascript()->CreateIterResultObject(), value, done,
92 1349 : context, effect);
93 : }
94 :
95 3881 : Reduction JSIntrinsicLowering::ReduceDeoptimizeNow(Node* node) {
96 3881 : Node* const frame_state = NodeProperties::GetFrameStateInput(node);
97 3881 : Node* const effect = NodeProperties::GetEffectInput(node);
98 3881 : Node* const control = NodeProperties::GetControlInput(node);
99 :
100 : // TODO(bmeurer): Move MergeControlToEnd() to the AdvancedReducer.
101 7762 : Node* deoptimize = graph()->NewNode(
102 : common()->Deoptimize(DeoptimizeKind::kEager,
103 : DeoptimizeReason::kDeoptimizeNow, VectorSlotPair()),
104 : frame_state, effect, control);
105 3881 : NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
106 : Revisit(graph()->end());
107 :
108 3881 : node->TrimInputCount(0);
109 3881 : NodeProperties::ChangeOp(node, common()->Dead());
110 3881 : return Changed(node);
111 : }
112 :
113 1290 : Reduction JSIntrinsicLowering::ReduceCreateJSGeneratorObject(Node* node) {
114 1290 : Node* const closure = NodeProperties::GetValueInput(node, 0);
115 1290 : Node* const receiver = NodeProperties::GetValueInput(node, 1);
116 1290 : Node* const context = NodeProperties::GetContextInput(node);
117 1290 : Node* const effect = NodeProperties::GetEffectInput(node);
118 1290 : Node* const control = NodeProperties::GetControlInput(node);
119 1290 : Operator const* const op = javascript()->CreateGeneratorObject();
120 : Node* create_generator =
121 : graph()->NewNode(op, closure, receiver, context, effect, control);
122 : ReplaceWithValue(node, create_generator, create_generator);
123 1290 : return Changed(create_generator);
124 : }
125 :
126 182 : Reduction JSIntrinsicLowering::ReduceGeneratorClose(Node* node) {
127 182 : Node* const generator = NodeProperties::GetValueInput(node, 0);
128 182 : Node* const effect = NodeProperties::GetEffectInput(node);
129 182 : Node* const control = NodeProperties::GetControlInput(node);
130 182 : Node* const closed = jsgraph()->Constant(JSGeneratorObject::kGeneratorClosed);
131 182 : Node* const undefined = jsgraph()->UndefinedConstant();
132 : Operator const* const op = simplified()->StoreField(
133 182 : AccessBuilder::ForJSGeneratorObjectContinuation());
134 :
135 : ReplaceWithValue(node, undefined, node);
136 : NodeProperties::RemoveType(node);
137 182 : return Change(node, op, generator, closed, effect, control);
138 : }
139 :
140 205 : Reduction JSIntrinsicLowering::ReduceAsyncFunctionAwaitCaught(Node* node) {
141 : return Change(
142 : node,
143 410 : Builtins::CallableFor(isolate(), Builtins::kAsyncFunctionAwaitCaught), 0);
144 : }
145 :
146 2569 : Reduction JSIntrinsicLowering::ReduceAsyncFunctionAwaitUncaught(Node* node) {
147 : return Change(
148 : node,
149 5138 : Builtins::CallableFor(isolate(), Builtins::kAsyncFunctionAwaitUncaught),
150 5138 : 0);
151 : }
152 :
153 1255 : Reduction JSIntrinsicLowering::ReduceAsyncFunctionEnter(Node* node) {
154 1255 : NodeProperties::ChangeOp(node, javascript()->AsyncFunctionEnter());
155 1255 : return Changed(node);
156 : }
157 :
158 1210 : Reduction JSIntrinsicLowering::ReduceAsyncFunctionReject(Node* node) {
159 : RelaxControls(node);
160 1210 : NodeProperties::ChangeOp(node, javascript()->AsyncFunctionReject());
161 1210 : return Changed(node);
162 : }
163 :
164 1118 : Reduction JSIntrinsicLowering::ReduceAsyncFunctionResolve(Node* node) {
165 : RelaxControls(node);
166 1118 : NodeProperties::ChangeOp(node, javascript()->AsyncFunctionResolve());
167 1118 : return Changed(node);
168 : }
169 :
170 5 : Reduction JSIntrinsicLowering::ReduceAsyncGeneratorAwaitCaught(Node* node) {
171 : return Change(
172 : node,
173 10 : Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorAwaitCaught),
174 10 : 0);
175 : }
176 :
177 214 : Reduction JSIntrinsicLowering::ReduceAsyncGeneratorAwaitUncaught(Node* node) {
178 : return Change(
179 : node,
180 428 : Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorAwaitUncaught),
181 428 : 0);
182 : }
183 :
184 182 : Reduction JSIntrinsicLowering::ReduceAsyncGeneratorReject(Node* node) {
185 : return Change(
186 364 : node, Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorReject),
187 364 : 0);
188 : }
189 :
190 182 : Reduction JSIntrinsicLowering::ReduceAsyncGeneratorResolve(Node* node) {
191 : return Change(
192 364 : node, Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorResolve),
193 364 : 0);
194 : }
195 :
196 62 : Reduction JSIntrinsicLowering::ReduceAsyncGeneratorYield(Node* node) {
197 : return Change(
198 124 : node, Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorYield),
199 124 : 0);
200 : }
201 :
202 5868 : Reduction JSIntrinsicLowering::ReduceGeneratorGetResumeMode(Node* node) {
203 5868 : Node* const generator = NodeProperties::GetValueInput(node, 0);
204 5868 : Node* const effect = NodeProperties::GetEffectInput(node);
205 5868 : Node* const control = NodeProperties::GetControlInput(node);
206 : Operator const* const op =
207 5868 : simplified()->LoadField(AccessBuilder::ForJSGeneratorObjectResumeMode());
208 :
209 5868 : return Change(node, op, generator, effect, control);
210 : }
211 :
212 27 : Reduction JSIntrinsicLowering::ReduceIsInstanceType(
213 : Node* node, InstanceType instance_type) {
214 : // if (%_IsSmi(value)) {
215 : // return false;
216 : // } else {
217 : // return %_GetInstanceType(%_GetMap(value)) == instance_type;
218 : // }
219 27 : Node* value = NodeProperties::GetValueInput(node, 0);
220 27 : Node* effect = NodeProperties::GetEffectInput(node);
221 27 : Node* control = NodeProperties::GetControlInput(node);
222 :
223 27 : Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
224 27 : Node* branch = graph()->NewNode(common()->Branch(), check, control);
225 :
226 27 : Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
227 : Node* etrue = effect;
228 27 : Node* vtrue = jsgraph()->FalseConstant();
229 :
230 27 : Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
231 : Node* efalse = effect;
232 : Node* map = efalse =
233 54 : graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), value,
234 : efalse, if_false);
235 27 : Node* map_instance_type = efalse = graph()->NewNode(
236 54 : simplified()->LoadField(AccessBuilder::ForMapInstanceType()), map, efalse,
237 : if_false);
238 : Node* vfalse =
239 27 : graph()->NewNode(simplified()->NumberEqual(), map_instance_type,
240 : jsgraph()->Constant(instance_type));
241 :
242 27 : Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
243 :
244 : // Replace all effect uses of {node} with the {ephi}.
245 27 : Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
246 : ReplaceWithValue(node, node, ephi, merge);
247 :
248 : // Turn the {node} into a Phi.
249 : return Change(node, common()->Phi(MachineRepresentation::kTagged, 2), vtrue,
250 27 : vfalse, merge);
251 : }
252 :
253 :
254 26 : Reduction JSIntrinsicLowering::ReduceIsJSReceiver(Node* node) {
255 26 : return Change(node, simplified()->ObjectIsReceiver());
256 : }
257 :
258 :
259 30 : Reduction JSIntrinsicLowering::ReduceIsSmi(Node* node) {
260 30 : return Change(node, simplified()->ObjectIsSmi());
261 : }
262 :
263 56 : Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op) {
264 : // Replace all effect uses of {node} with the effect dependency.
265 : RelaxEffectsAndControls(node);
266 : // Remove the inputs corresponding to context, effect and control.
267 56 : NodeProperties::RemoveNonValueInputs(node);
268 : // Finally update the operator to the new one.
269 56 : NodeProperties::ChangeOp(node, op);
270 56 : return Changed(node);
271 : }
272 :
273 :
274 36 : Reduction JSIntrinsicLowering::ReduceToLength(Node* node) {
275 36 : NodeProperties::ChangeOp(node, javascript()->ToLength());
276 36 : return Changed(node);
277 : }
278 :
279 :
280 0 : Reduction JSIntrinsicLowering::ReduceToObject(Node* node) {
281 0 : NodeProperties::ChangeOp(node, javascript()->ToObject());
282 0 : return Changed(node);
283 : }
284 :
285 :
286 13 : Reduction JSIntrinsicLowering::ReduceToString(Node* node) {
287 : // ToString is unnecessary if the input is a string.
288 13 : HeapObjectMatcher m(NodeProperties::GetValueInput(node, 0));
289 18 : if (m.HasValue() && m.Value()->IsString()) {
290 : ReplaceWithValue(node, m.node());
291 : return Replace(m.node());
292 : }
293 12 : NodeProperties::ChangeOp(node, javascript()->ToString());
294 : return Changed(node);
295 : }
296 :
297 :
298 40 : Reduction JSIntrinsicLowering::ReduceCall(Node* node) {
299 40 : size_t const arity = CallRuntimeParametersOf(node->op()).arity();
300 80 : NodeProperties::ChangeOp(node, javascript()->Call(arity));
301 40 : return Changed(node);
302 : }
303 :
304 0 : Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a,
305 : Node* b) {
306 : RelaxControls(node);
307 0 : node->ReplaceInput(0, a);
308 0 : node->ReplaceInput(1, b);
309 0 : node->TrimInputCount(2);
310 0 : NodeProperties::ChangeOp(node, op);
311 0 : return Changed(node);
312 : }
313 :
314 :
315 5895 : Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a,
316 : Node* b, Node* c) {
317 : RelaxControls(node);
318 5895 : node->ReplaceInput(0, a);
319 5895 : node->ReplaceInput(1, b);
320 5895 : node->ReplaceInput(2, c);
321 5895 : node->TrimInputCount(3);
322 5895 : NodeProperties::ChangeOp(node, op);
323 5895 : return Changed(node);
324 : }
325 :
326 :
327 1531 : Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a,
328 : Node* b, Node* c, Node* d) {
329 : RelaxControls(node);
330 1531 : node->ReplaceInput(0, a);
331 1531 : node->ReplaceInput(1, b);
332 1531 : node->ReplaceInput(2, c);
333 1531 : node->ReplaceInput(3, d);
334 1531 : node->TrimInputCount(4);
335 1531 : NodeProperties::ChangeOp(node, op);
336 1531 : return Changed(node);
337 : }
338 :
339 :
340 3419 : Reduction JSIntrinsicLowering::Change(Node* node, Callable const& callable,
341 : int stack_parameter_count) {
342 3419 : auto call_descriptor = Linkage::GetStubCallDescriptor(
343 3419 : graph()->zone(), callable.descriptor(), stack_parameter_count,
344 3419 : CallDescriptor::kNeedsFrameState, node->op()->properties());
345 6838 : node->InsertInput(graph()->zone(), 0,
346 3419 : jsgraph()->HeapConstant(callable.code()));
347 3419 : NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
348 3419 : return Changed(node);
349 : }
350 :
351 :
352 0 : Graph* JSIntrinsicLowering::graph() const { return jsgraph()->graph(); }
353 :
354 :
355 0 : Isolate* JSIntrinsicLowering::isolate() const { return jsgraph()->isolate(); }
356 :
357 :
358 0 : CommonOperatorBuilder* JSIntrinsicLowering::common() const {
359 0 : return jsgraph()->common();
360 : }
361 :
362 0 : JSOperatorBuilder* JSIntrinsicLowering::javascript() const {
363 6310 : return jsgraph_->javascript();
364 : }
365 :
366 0 : SimplifiedOperatorBuilder* JSIntrinsicLowering::simplified() const {
367 0 : return jsgraph()->simplified();
368 : }
369 :
370 : } // namespace compiler
371 : } // namespace internal
372 121996 : } // namespace v8
|