5 #include "src/compiler/js-intrinsic-lowering.h" 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" 24 JSIntrinsicLowering::JSIntrinsicLowering(Editor* editor, JSGraph* jsgraph)
25 : AdvancedReducer(editor), jsgraph_(jsgraph) {}
27 Reduction JSIntrinsicLowering::Reduce(Node* node) {
28 if (node->opcode() != IrOpcode::kJSCallRuntime)
return NoChange();
29 const Runtime::Function*
const f =
30 Runtime::FunctionForId(CallRuntimeParametersOf(node->op()).
id());
31 if (f->intrinsic_type != Runtime::IntrinsicType::INLINE)
return NoChange();
32 switch (f->function_id) {
33 case Runtime::kInlineCreateIterResultObject:
34 return ReduceCreateIterResultObject(node);
35 case Runtime::kInlineDeoptimizeNow:
36 return ReduceDeoptimizeNow(node);
37 case Runtime::kInlineGeneratorClose:
38 return ReduceGeneratorClose(node);
39 case Runtime::kInlineCreateJSGeneratorObject:
40 return ReduceCreateJSGeneratorObject(node);
41 case Runtime::kInlineAsyncFunctionAwaitCaught:
42 return ReduceAsyncFunctionAwaitCaught(node);
43 case Runtime::kInlineAsyncFunctionAwaitUncaught:
44 return ReduceAsyncFunctionAwaitUncaught(node);
45 case Runtime::kInlineAsyncFunctionEnter:
46 return ReduceAsyncFunctionEnter(node);
47 case Runtime::kInlineAsyncFunctionReject:
48 return ReduceAsyncFunctionReject(node);
49 case Runtime::kInlineAsyncFunctionResolve:
50 return ReduceAsyncFunctionResolve(node);
51 case Runtime::kInlineAsyncGeneratorAwaitCaught:
52 return ReduceAsyncGeneratorAwaitCaught(node);
53 case Runtime::kInlineAsyncGeneratorAwaitUncaught:
54 return ReduceAsyncGeneratorAwaitUncaught(node);
55 case Runtime::kInlineAsyncGeneratorReject:
56 return ReduceAsyncGeneratorReject(node);
57 case Runtime::kInlineAsyncGeneratorResolve:
58 return ReduceAsyncGeneratorResolve(node);
59 case Runtime::kInlineAsyncGeneratorYield:
60 return ReduceAsyncGeneratorYield(node);
61 case Runtime::kInlineGeneratorGetResumeMode:
62 return ReduceGeneratorGetResumeMode(node);
63 case Runtime::kInlineIsArray:
64 return ReduceIsInstanceType(node, JS_ARRAY_TYPE);
65 case Runtime::kInlineIsTypedArray:
66 return ReduceIsInstanceType(node, JS_TYPED_ARRAY_TYPE);
67 case Runtime::kInlineIsJSReceiver:
68 return ReduceIsJSReceiver(node);
69 case Runtime::kInlineIsSmi:
70 return ReduceIsSmi(node);
71 case Runtime::kInlineToLength:
72 return ReduceToLength(node);
73 case Runtime::kInlineToObject:
74 return ReduceToObject(node);
75 case Runtime::kInlineToString:
76 return ReduceToString(node);
77 case Runtime::kInlineCall:
78 return ReduceCall(node);
86 Reduction JSIntrinsicLowering::ReduceCreateIterResultObject(Node* node) {
87 Node*
const value = NodeProperties::GetValueInput(node, 0);
88 Node*
const done = NodeProperties::GetValueInput(node, 1);
89 Node*
const context = NodeProperties::GetContextInput(node);
90 Node*
const effect = NodeProperties::GetEffectInput(node);
91 return Change(node, javascript()->CreateIterResultObject(), value, done,
95 Reduction JSIntrinsicLowering::ReduceDeoptimizeNow(Node* node) {
96 Node*
const frame_state = NodeProperties::GetFrameStateInput(node);
97 Node*
const effect = NodeProperties::GetEffectInput(node);
98 Node*
const control = NodeProperties::GetControlInput(node);
101 Node* deoptimize = graph()->NewNode(
102 common()->Deoptimize(DeoptimizeKind::kEager,
103 DeoptimizeReason::kDeoptimizeNow, VectorSlotPair()),
104 frame_state, effect, control);
105 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
106 Revisit(graph()->end());
108 node->TrimInputCount(0);
109 NodeProperties::ChangeOp(node, common()->Dead());
110 return Changed(node);
113 Reduction JSIntrinsicLowering::ReduceCreateJSGeneratorObject(Node* node) {
114 Node*
const closure = NodeProperties::GetValueInput(node, 0);
115 Node*
const receiver = NodeProperties::GetValueInput(node, 1);
116 Node*
const context = NodeProperties::GetContextInput(node);
117 Node*
const effect = NodeProperties::GetEffectInput(node);
118 Node*
const control = NodeProperties::GetControlInput(node);
119 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 return Changed(create_generator);
126 Reduction JSIntrinsicLowering::ReduceGeneratorClose(Node* node) {
127 Node*
const generator = NodeProperties::GetValueInput(node, 0);
128 Node*
const effect = NodeProperties::GetEffectInput(node);
129 Node*
const control = NodeProperties::GetControlInput(node);
130 Node*
const closed = jsgraph()->Constant(JSGeneratorObject::kGeneratorClosed);
131 Node*
const undefined = jsgraph()->UndefinedConstant();
132 Operator
const*
const op = simplified()->StoreField(
133 AccessBuilder::ForJSGeneratorObjectContinuation());
135 ReplaceWithValue(node, undefined, node);
136 NodeProperties::RemoveType(node);
137 return Change(node, op, generator, closed, effect, control);
140 Reduction JSIntrinsicLowering::ReduceAsyncFunctionAwaitCaught(Node* node) {
143 Builtins::CallableFor(isolate(), Builtins::kAsyncFunctionAwaitCaught), 0);
146 Reduction JSIntrinsicLowering::ReduceAsyncFunctionAwaitUncaught(Node* node) {
149 Builtins::CallableFor(isolate(), Builtins::kAsyncFunctionAwaitUncaught),
153 Reduction JSIntrinsicLowering::ReduceAsyncFunctionEnter(Node* node) {
154 NodeProperties::ChangeOp(node, javascript()->AsyncFunctionEnter());
155 return Changed(node);
158 Reduction JSIntrinsicLowering::ReduceAsyncFunctionReject(Node* node) {
160 NodeProperties::ChangeOp(node, javascript()->AsyncFunctionReject());
161 return Changed(node);
164 Reduction JSIntrinsicLowering::ReduceAsyncFunctionResolve(Node* node) {
166 NodeProperties::ChangeOp(node, javascript()->AsyncFunctionResolve());
167 return Changed(node);
170 Reduction JSIntrinsicLowering::ReduceAsyncGeneratorAwaitCaught(Node* node) {
173 Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorAwaitCaught),
177 Reduction JSIntrinsicLowering::ReduceAsyncGeneratorAwaitUncaught(Node* node) {
180 Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorAwaitUncaught),
184 Reduction JSIntrinsicLowering::ReduceAsyncGeneratorReject(Node* node) {
186 node, Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorReject),
190 Reduction JSIntrinsicLowering::ReduceAsyncGeneratorResolve(Node* node) {
192 node, Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorResolve),
196 Reduction JSIntrinsicLowering::ReduceAsyncGeneratorYield(Node* node) {
198 node, Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorYield),
202 Reduction JSIntrinsicLowering::ReduceGeneratorGetResumeMode(Node* node) {
203 Node*
const generator = NodeProperties::GetValueInput(node, 0);
204 Node*
const effect = NodeProperties::GetEffectInput(node);
205 Node*
const control = NodeProperties::GetControlInput(node);
206 Operator
const*
const op =
207 simplified()->LoadField(AccessBuilder::ForJSGeneratorObjectResumeMode());
209 return Change(node, op, generator, effect, control);
212 Reduction JSIntrinsicLowering::ReduceIsInstanceType(
213 Node* node, InstanceType instance_type) {
219 Node* value = NodeProperties::GetValueInput(node, 0);
220 Node* effect = NodeProperties::GetEffectInput(node);
221 Node* control = NodeProperties::GetControlInput(node);
223 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
224 Node* branch = graph()->NewNode(common()->Branch(), check, control);
226 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
227 Node* etrue = effect;
228 Node* vtrue = jsgraph()->FalseConstant();
230 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
231 Node* efalse = effect;
233 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), value,
235 Node* map_instance_type = efalse = graph()->NewNode(
236 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), map, efalse,
239 graph()->NewNode(simplified()->NumberEqual(), map_instance_type,
240 jsgraph()->Constant(instance_type));
242 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
245 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
246 ReplaceWithValue(node, node, ephi, merge);
249 return Change(node, common()->Phi(MachineRepresentation::kTagged, 2), vtrue,
254 Reduction JSIntrinsicLowering::ReduceIsJSReceiver(Node* node) {
255 return Change(node, simplified()->ObjectIsReceiver());
259 Reduction JSIntrinsicLowering::ReduceIsSmi(Node* node) {
260 return Change(node, simplified()->ObjectIsSmi());
263 Reduction JSIntrinsicLowering::Change(Node* node,
const Operator* op) {
265 RelaxEffectsAndControls(node);
267 NodeProperties::RemoveNonValueInputs(node);
269 NodeProperties::ChangeOp(node, op);
270 return Changed(node);
274 Reduction JSIntrinsicLowering::ReduceToLength(Node* node) {
275 NodeProperties::ChangeOp(node, javascript()->ToLength());
276 return Changed(node);
280 Reduction JSIntrinsicLowering::ReduceToObject(Node* node) {
281 NodeProperties::ChangeOp(node, javascript()->ToObject());
282 return Changed(node);
286 Reduction JSIntrinsicLowering::ReduceToString(Node* node) {
288 HeapObjectMatcher m(NodeProperties::GetValueInput(node, 0));
289 if (m.HasValue() && m.Value()->IsString()) {
290 ReplaceWithValue(node, m.node());
291 return Replace(m.node());
293 NodeProperties::ChangeOp(node, javascript()->ToString());
294 return Changed(node);
298 Reduction JSIntrinsicLowering::ReduceCall(Node* node) {
299 size_t const arity = CallRuntimeParametersOf(node->op()).arity();
300 NodeProperties::ChangeOp(node, javascript()->Call(arity));
301 return Changed(node);
304 Reduction JSIntrinsicLowering::Change(Node* node,
const Operator* op, Node* a,
307 node->ReplaceInput(0, a);
308 node->ReplaceInput(1, b);
309 node->TrimInputCount(2);
310 NodeProperties::ChangeOp(node, op);
311 return Changed(node);
315 Reduction JSIntrinsicLowering::Change(Node* node,
const Operator* op, Node* a,
318 node->ReplaceInput(0, a);
319 node->ReplaceInput(1, b);
320 node->ReplaceInput(2, c);
321 node->TrimInputCount(3);
322 NodeProperties::ChangeOp(node, op);
323 return Changed(node);
327 Reduction JSIntrinsicLowering::Change(Node* node,
const Operator* op, Node* a,
328 Node* b, Node* c, Node* d) {
330 node->ReplaceInput(0, a);
331 node->ReplaceInput(1, b);
332 node->ReplaceInput(2, c);
333 node->ReplaceInput(3, d);
334 node->TrimInputCount(4);
335 NodeProperties::ChangeOp(node, op);
336 return Changed(node);
340 Reduction JSIntrinsicLowering::Change(Node* node, Callable
const& callable,
341 int stack_parameter_count) {
342 auto call_descriptor = Linkage::GetStubCallDescriptor(
343 graph()->zone(), callable.descriptor(), stack_parameter_count,
344 CallDescriptor::kNeedsFrameState, node->op()->properties());
345 node->InsertInput(graph()->zone(), 0,
346 jsgraph()->HeapConstant(callable.code()));
347 NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
348 return Changed(node);
352 Graph* JSIntrinsicLowering::graph()
const {
return jsgraph()->graph(); }
355 Isolate* JSIntrinsicLowering::isolate()
const {
return jsgraph()->isolate(); }
358 CommonOperatorBuilder* JSIntrinsicLowering::common()
const {
359 return jsgraph()->common();
362 JSOperatorBuilder* JSIntrinsicLowering::javascript()
const {
363 return jsgraph_->javascript();
366 SimplifiedOperatorBuilder* JSIntrinsicLowering::simplified()
const {
367 return jsgraph()->simplified();