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/type-cache.h"
19
20 namespace v8 {
21 namespace internal {
22 namespace compiler {
23
JSIntrinsicLowering(Editor * editor,JSGraph * jsgraph,DeoptimizationMode mode)24 JSIntrinsicLowering::JSIntrinsicLowering(Editor* editor, JSGraph* jsgraph,
25 DeoptimizationMode mode)
26 : AdvancedReducer(editor),
27 jsgraph_(jsgraph),
28 mode_(mode),
29 type_cache_(TypeCache::Get()) {}
30
31
Reduce(Node * node)32 Reduction JSIntrinsicLowering::Reduce(Node* node) {
33 if (node->opcode() != IrOpcode::kJSCallRuntime) return NoChange();
34 const Runtime::Function* const f =
35 Runtime::FunctionForId(CallRuntimeParametersOf(node->op()).id());
36 if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) return NoChange();
37 switch (f->function_id) {
38 case Runtime::kInlineConstructDouble:
39 return ReduceConstructDouble(node);
40 case Runtime::kInlineCreateIterResultObject:
41 return ReduceCreateIterResultObject(node);
42 case Runtime::kInlineDeoptimizeNow:
43 return ReduceDeoptimizeNow(node);
44 case Runtime::kInlineDoubleHi:
45 return ReduceDoubleHi(node);
46 case Runtime::kInlineDoubleLo:
47 return ReduceDoubleLo(node);
48 case Runtime::kInlineIncrementStatsCounter:
49 return ReduceIncrementStatsCounter(node);
50 case Runtime::kInlineIsArray:
51 return ReduceIsInstanceType(node, JS_ARRAY_TYPE);
52 case Runtime::kInlineIsDate:
53 return ReduceIsInstanceType(node, JS_DATE_TYPE);
54 case Runtime::kInlineIsTypedArray:
55 return ReduceIsInstanceType(node, JS_TYPED_ARRAY_TYPE);
56 case Runtime::kInlineIsFunction:
57 return ReduceIsFunction(node);
58 case Runtime::kInlineIsRegExp:
59 return ReduceIsInstanceType(node, JS_REGEXP_TYPE);
60 case Runtime::kInlineIsJSReceiver:
61 return ReduceIsJSReceiver(node);
62 case Runtime::kInlineIsSmi:
63 return ReduceIsSmi(node);
64 case Runtime::kInlineJSValueGetValue:
65 return ReduceJSValueGetValue(node);
66 case Runtime::kInlineMathClz32:
67 return ReduceMathClz32(node);
68 case Runtime::kInlineMathFloor:
69 return ReduceMathFloor(node);
70 case Runtime::kInlineMathSqrt:
71 return ReduceMathSqrt(node);
72 case Runtime::kInlineValueOf:
73 return ReduceValueOf(node);
74 case Runtime::kInlineIsMinusZero:
75 return ReduceIsMinusZero(node);
76 case Runtime::kInlineFixedArrayGet:
77 return ReduceFixedArrayGet(node);
78 case Runtime::kInlineFixedArraySet:
79 return ReduceFixedArraySet(node);
80 case Runtime::kInlineRegExpConstructResult:
81 return ReduceRegExpConstructResult(node);
82 case Runtime::kInlineRegExpExec:
83 return ReduceRegExpExec(node);
84 case Runtime::kInlineRegExpFlags:
85 return ReduceRegExpFlags(node);
86 case Runtime::kInlineRegExpSource:
87 return ReduceRegExpSource(node);
88 case Runtime::kInlineSubString:
89 return ReduceSubString(node);
90 case Runtime::kInlineToInteger:
91 return ReduceToInteger(node);
92 case Runtime::kInlineToLength:
93 return ReduceToLength(node);
94 case Runtime::kInlineToName:
95 return ReduceToName(node);
96 case Runtime::kInlineToNumber:
97 return ReduceToNumber(node);
98 case Runtime::kInlineToObject:
99 return ReduceToObject(node);
100 case Runtime::kInlineToPrimitive:
101 return ReduceToPrimitive(node);
102 case Runtime::kInlineToString:
103 return ReduceToString(node);
104 case Runtime::kInlineCall:
105 return ReduceCall(node);
106 case Runtime::kInlineTailCall:
107 return ReduceTailCall(node);
108 case Runtime::kInlineGetSuperConstructor:
109 return ReduceGetSuperConstructor(node);
110 default:
111 break;
112 }
113 return NoChange();
114 }
115
116
ReduceCreateIterResultObject(Node * node)117 Reduction JSIntrinsicLowering::ReduceCreateIterResultObject(Node* node) {
118 Node* const value = NodeProperties::GetValueInput(node, 0);
119 Node* const done = NodeProperties::GetValueInput(node, 1);
120 Node* const context = NodeProperties::GetContextInput(node);
121 Node* const effect = NodeProperties::GetEffectInput(node);
122 return Change(node, javascript()->CreateIterResultObject(), value, done,
123 context, effect);
124 }
125
126
ReduceConstructDouble(Node * node)127 Reduction JSIntrinsicLowering::ReduceConstructDouble(Node* node) {
128 Node* high = NodeProperties::GetValueInput(node, 0);
129 Node* low = NodeProperties::GetValueInput(node, 1);
130 Node* value =
131 graph()->NewNode(machine()->Float64InsertHighWord32(),
132 graph()->NewNode(machine()->Float64InsertLowWord32(),
133 jsgraph()->Constant(0), low),
134 high);
135 ReplaceWithValue(node, value);
136 return Replace(value);
137 }
138
139
ReduceDeoptimizeNow(Node * node)140 Reduction JSIntrinsicLowering::ReduceDeoptimizeNow(Node* node) {
141 if (mode() != kDeoptimizationEnabled) return NoChange();
142 Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
143 Node* const effect = NodeProperties::GetEffectInput(node);
144 Node* const control = NodeProperties::GetControlInput(node);
145
146 // TODO(bmeurer): Move MergeControlToEnd() to the AdvancedReducer.
147 Node* deoptimize =
148 graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
149 frame_state, effect, control);
150 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
151
152 node->TrimInputCount(0);
153 NodeProperties::ChangeOp(node, common()->Dead());
154 return Changed(node);
155 }
156
157
ReduceDoubleHi(Node * node)158 Reduction JSIntrinsicLowering::ReduceDoubleHi(Node* node) {
159 return Change(node, machine()->Float64ExtractHighWord32());
160 }
161
162
ReduceDoubleLo(Node * node)163 Reduction JSIntrinsicLowering::ReduceDoubleLo(Node* node) {
164 return Change(node, machine()->Float64ExtractLowWord32());
165 }
166
167
ReduceIncrementStatsCounter(Node * node)168 Reduction JSIntrinsicLowering::ReduceIncrementStatsCounter(Node* node) {
169 if (!FLAG_native_code_counters) return ChangeToUndefined(node);
170 HeapObjectMatcher m(NodeProperties::GetValueInput(node, 0));
171 if (!m.HasValue() || !m.Value()->IsString()) {
172 return ChangeToUndefined(node);
173 }
174 base::SmartArrayPointer<char> name =
175 Handle<String>::cast(m.Value())->ToCString();
176 StatsCounter counter(jsgraph()->isolate(), name.get());
177 if (!counter.Enabled()) return ChangeToUndefined(node);
178
179 Node* effect = NodeProperties::GetEffectInput(node);
180 Node* control = NodeProperties::GetControlInput(node);
181 FieldAccess access = AccessBuilder::ForStatsCounter();
182 Node* cnt = jsgraph()->ExternalConstant(ExternalReference(&counter));
183 Node* load =
184 graph()->NewNode(simplified()->LoadField(access), cnt, effect, control);
185 Node* inc =
186 graph()->NewNode(machine()->Int32Add(), load, jsgraph()->OneConstant());
187 Node* store = graph()->NewNode(simplified()->StoreField(access), cnt, inc,
188 load, control);
189 return ChangeToUndefined(node, store);
190 }
191
192
ReduceIsInstanceType(Node * node,InstanceType instance_type)193 Reduction JSIntrinsicLowering::ReduceIsInstanceType(
194 Node* node, InstanceType instance_type) {
195 // if (%_IsSmi(value)) {
196 // return false;
197 // } else {
198 // return %_GetInstanceType(%_GetMap(value)) == instance_type;
199 // }
200 Node* value = NodeProperties::GetValueInput(node, 0);
201 Node* effect = NodeProperties::GetEffectInput(node);
202 Node* control = NodeProperties::GetControlInput(node);
203
204 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
205 Node* branch = graph()->NewNode(common()->Branch(), check, control);
206
207 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
208 Node* etrue = effect;
209 Node* vtrue = jsgraph()->FalseConstant();
210
211 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
212 Node* efalse = graph()->NewNode(
213 simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
214 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), value,
215 effect, if_false),
216 effect, if_false);
217 Node* vfalse = graph()->NewNode(machine()->Word32Equal(), efalse,
218 jsgraph()->Int32Constant(instance_type));
219
220 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
221
222 // Replace all effect uses of {node} with the {ephi}.
223 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
224 ReplaceWithValue(node, node, ephi);
225
226 // Turn the {node} into a Phi.
227 return Change(node, common()->Phi(MachineRepresentation::kTagged, 2), vtrue,
228 vfalse, merge);
229 }
230
231
ReduceIsFunction(Node * node)232 Reduction JSIntrinsicLowering::ReduceIsFunction(Node* node) {
233 Node* value = NodeProperties::GetValueInput(node, 0);
234 Type* value_type = NodeProperties::GetType(value);
235 Node* effect = NodeProperties::GetEffectInput(node);
236 Node* control = NodeProperties::GetControlInput(node);
237 if (value_type->Is(Type::Function())) {
238 value = jsgraph()->TrueConstant();
239 } else {
240 // if (%_IsSmi(value)) {
241 // return false;
242 // } else {
243 // return FIRST_FUNCTION_TYPE <= %_GetInstanceType(%_GetMap(value))
244 // }
245 STATIC_ASSERT(LAST_TYPE == LAST_FUNCTION_TYPE);
246
247 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
248 Node* branch = graph()->NewNode(common()->Branch(), check, control);
249
250 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
251 Node* etrue = effect;
252 Node* vtrue = jsgraph()->FalseConstant();
253
254 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
255 Node* efalse = graph()->NewNode(
256 simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
257 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
258 value, effect, if_false),
259 effect, if_false);
260 Node* vfalse =
261 graph()->NewNode(machine()->Uint32LessThanOrEqual(),
262 jsgraph()->Int32Constant(FIRST_FUNCTION_TYPE), efalse);
263
264 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
265 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
266 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
267 vtrue, vfalse, control);
268 }
269 ReplaceWithValue(node, node, effect, control);
270 return Replace(value);
271 }
272
273
ReduceIsJSReceiver(Node * node)274 Reduction JSIntrinsicLowering::ReduceIsJSReceiver(Node* node) {
275 Node* value = NodeProperties::GetValueInput(node, 0);
276 Type* value_type = NodeProperties::GetType(value);
277 Node* effect = NodeProperties::GetEffectInput(node);
278 Node* control = NodeProperties::GetControlInput(node);
279 if (value_type->Is(Type::Receiver())) {
280 value = jsgraph()->TrueConstant();
281 } else if (!value_type->Maybe(Type::Receiver())) {
282 value = jsgraph()->FalseConstant();
283 } else {
284 // if (%_IsSmi(value)) {
285 // return false;
286 // } else {
287 // return FIRST_JS_RECEIVER_TYPE <= %_GetInstanceType(%_GetMap(value))
288 // }
289 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
290
291 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
292 Node* branch = graph()->NewNode(common()->Branch(), check, control);
293
294 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
295 Node* etrue = effect;
296 Node* vtrue = jsgraph()->FalseConstant();
297
298 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
299 Node* efalse = graph()->NewNode(
300 simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
301 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
302 value, effect, if_false),
303 effect, if_false);
304 Node* vfalse = graph()->NewNode(
305 machine()->Uint32LessThanOrEqual(),
306 jsgraph()->Int32Constant(FIRST_JS_RECEIVER_TYPE), efalse);
307
308 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
309 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
310 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
311 vtrue, vfalse, control);
312 }
313 ReplaceWithValue(node, node, effect, control);
314 return Replace(value);
315 }
316
317
ReduceIsSmi(Node * node)318 Reduction JSIntrinsicLowering::ReduceIsSmi(Node* node) {
319 return Change(node, simplified()->ObjectIsSmi());
320 }
321
322
ReduceJSValueGetValue(Node * node)323 Reduction JSIntrinsicLowering::ReduceJSValueGetValue(Node* node) {
324 Node* value = NodeProperties::GetValueInput(node, 0);
325 Node* effect = NodeProperties::GetEffectInput(node);
326 Node* control = NodeProperties::GetControlInput(node);
327 return Change(node, simplified()->LoadField(AccessBuilder::ForValue()), value,
328 effect, control);
329 }
330
331
ReduceMathClz32(Node * node)332 Reduction JSIntrinsicLowering::ReduceMathClz32(Node* node) {
333 return Change(node, machine()->Word32Clz());
334 }
335
336
ReduceMathFloor(Node * node)337 Reduction JSIntrinsicLowering::ReduceMathFloor(Node* node) {
338 if (!machine()->Float64RoundDown().IsSupported()) return NoChange();
339 return Change(node, machine()->Float64RoundDown().op());
340 }
341
342
ReduceMathSqrt(Node * node)343 Reduction JSIntrinsicLowering::ReduceMathSqrt(Node* node) {
344 return Change(node, machine()->Float64Sqrt());
345 }
346
347
ReduceValueOf(Node * node)348 Reduction JSIntrinsicLowering::ReduceValueOf(Node* node) {
349 // if (%_IsSmi(value)) {
350 // return value;
351 // } else if (%_GetInstanceType(%_GetMap(value)) == JS_VALUE_TYPE) {
352 // return %_GetValue(value);
353 // } else {
354 // return value;
355 // }
356 const Operator* const merge_op = common()->Merge(2);
357 const Operator* const ephi_op = common()->EffectPhi(2);
358 const Operator* const phi_op =
359 common()->Phi(MachineRepresentation::kTagged, 2);
360
361 Node* value = NodeProperties::GetValueInput(node, 0);
362 Node* effect = NodeProperties::GetEffectInput(node);
363 Node* control = NodeProperties::GetControlInput(node);
364
365 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
366 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control);
367
368 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
369 Node* etrue0 = effect;
370 Node* vtrue0 = value;
371
372 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
373 Node* efalse0;
374 Node* vfalse0;
375 {
376 Node* check1 = graph()->NewNode(
377 machine()->Word32Equal(),
378 graph()->NewNode(
379 simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
380 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
381 value, effect, if_false0),
382 effect, if_false0),
383 jsgraph()->Int32Constant(JS_VALUE_TYPE));
384 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
385
386 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
387 Node* etrue1 =
388 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForValue()),
389 value, effect, if_true1);
390 Node* vtrue1 = etrue1;
391
392 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
393 Node* efalse1 = effect;
394 Node* vfalse1 = value;
395
396 Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1);
397 efalse0 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1);
398 vfalse0 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1);
399 }
400
401 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
402
403 // Replace all effect uses of {node} with the {ephi0}.
404 Node* ephi0 = graph()->NewNode(ephi_op, etrue0, efalse0, merge0);
405 ReplaceWithValue(node, node, ephi0);
406
407 // Turn the {node} into a Phi.
408 return Change(node, phi_op, vtrue0, vfalse0, merge0);
409 }
410
411
Change(Node * node,const Operator * op)412 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op) {
413 // Replace all effect uses of {node} with the effect dependency.
414 RelaxEffectsAndControls(node);
415 // Remove the inputs corresponding to context, effect and control.
416 NodeProperties::RemoveNonValueInputs(node);
417 // Finally update the operator to the new one.
418 NodeProperties::ChangeOp(node, op);
419 return Changed(node);
420 }
421
422
ReduceIsMinusZero(Node * node)423 Reduction JSIntrinsicLowering::ReduceIsMinusZero(Node* node) {
424 Node* value = NodeProperties::GetValueInput(node, 0);
425 Node* effect = NodeProperties::GetEffectInput(node);
426
427 Node* double_lo =
428 graph()->NewNode(machine()->Float64ExtractLowWord32(), value);
429 Node* check1 = graph()->NewNode(machine()->Word32Equal(), double_lo,
430 jsgraph()->ZeroConstant());
431
432 Node* double_hi =
433 graph()->NewNode(machine()->Float64ExtractHighWord32(), value);
434 Node* check2 = graph()->NewNode(
435 machine()->Word32Equal(), double_hi,
436 jsgraph()->Int32Constant(static_cast<int32_t>(0x80000000)));
437
438 ReplaceWithValue(node, node, effect);
439
440 Node* and_result = graph()->NewNode(machine()->Word32And(), check1, check2);
441
442 return Change(node, machine()->Word32Equal(), and_result,
443 jsgraph()->Int32Constant(1));
444 }
445
446
ReduceFixedArrayGet(Node * node)447 Reduction JSIntrinsicLowering::ReduceFixedArrayGet(Node* node) {
448 Node* base = node->InputAt(0);
449 Node* index = node->InputAt(1);
450 Node* effect = NodeProperties::GetEffectInput(node);
451 Node* control = NodeProperties::GetControlInput(node);
452 return Change(
453 node, simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
454 base, index, effect, control);
455 }
456
457
ReduceFixedArraySet(Node * node)458 Reduction JSIntrinsicLowering::ReduceFixedArraySet(Node* node) {
459 Node* base = node->InputAt(0);
460 Node* index = node->InputAt(1);
461 Node* value = node->InputAt(2);
462 Node* effect = NodeProperties::GetEffectInput(node);
463 Node* control = NodeProperties::GetControlInput(node);
464 Node* store = (graph()->NewNode(
465 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement()), base,
466 index, value, effect, control));
467 ReplaceWithValue(node, value, store);
468 return Changed(store);
469 }
470
471
ReduceRegExpConstructResult(Node * node)472 Reduction JSIntrinsicLowering::ReduceRegExpConstructResult(Node* node) {
473 // TODO(bmeurer): Introduce JSCreateRegExpResult?
474 return Change(node, CodeFactory::RegExpConstructResult(isolate()), 0);
475 }
476
477
ReduceRegExpExec(Node * node)478 Reduction JSIntrinsicLowering::ReduceRegExpExec(Node* node) {
479 return Change(node, CodeFactory::RegExpExec(isolate()), 4);
480 }
481
482
ReduceRegExpFlags(Node * node)483 Reduction JSIntrinsicLowering::ReduceRegExpFlags(Node* node) {
484 Node* const receiver = NodeProperties::GetValueInput(node, 0);
485 Node* const effect = NodeProperties::GetEffectInput(node);
486 Node* const control = NodeProperties::GetControlInput(node);
487 Operator const* const op =
488 simplified()->LoadField(AccessBuilder::ForJSRegExpFlags());
489 return Change(node, op, receiver, effect, control);
490 }
491
492
ReduceRegExpSource(Node * node)493 Reduction JSIntrinsicLowering::ReduceRegExpSource(Node* node) {
494 Node* const receiver = NodeProperties::GetValueInput(node, 0);
495 Node* const effect = NodeProperties::GetEffectInput(node);
496 Node* const control = NodeProperties::GetControlInput(node);
497 Operator const* const op =
498 simplified()->LoadField(AccessBuilder::ForJSRegExpSource());
499 return Change(node, op, receiver, effect, control);
500 }
501
502
ReduceSubString(Node * node)503 Reduction JSIntrinsicLowering::ReduceSubString(Node* node) {
504 return Change(node, CodeFactory::SubString(isolate()), 3);
505 }
506
507
ReduceToInteger(Node * node)508 Reduction JSIntrinsicLowering::ReduceToInteger(Node* node) {
509 Node* value = NodeProperties::GetValueInput(node, 0);
510 Type* value_type = NodeProperties::GetType(value);
511 if (value_type->Is(type_cache().kIntegerOrMinusZero)) {
512 ReplaceWithValue(node, value);
513 return Replace(value);
514 }
515 return NoChange();
516 }
517
518
ReduceToName(Node * node)519 Reduction JSIntrinsicLowering::ReduceToName(Node* node) {
520 NodeProperties::ChangeOp(node, javascript()->ToName());
521 return Changed(node);
522 }
523
524
ReduceToNumber(Node * node)525 Reduction JSIntrinsicLowering::ReduceToNumber(Node* node) {
526 NodeProperties::ChangeOp(node, javascript()->ToNumber());
527 return Changed(node);
528 }
529
530
ReduceToLength(Node * node)531 Reduction JSIntrinsicLowering::ReduceToLength(Node* node) {
532 Node* value = NodeProperties::GetValueInput(node, 0);
533 Type* value_type = NodeProperties::GetType(value);
534 if (value_type->Is(type_cache().kIntegerOrMinusZero)) {
535 if (value_type->Max() <= 0.0) {
536 value = jsgraph()->ZeroConstant();
537 } else if (value_type->Min() >= kMaxSafeInteger) {
538 value = jsgraph()->Constant(kMaxSafeInteger);
539 } else {
540 if (value_type->Min() <= 0.0) {
541 value = graph()->NewNode(
542 common()->Select(MachineRepresentation::kTagged),
543 graph()->NewNode(simplified()->NumberLessThanOrEqual(), value,
544 jsgraph()->ZeroConstant()),
545 jsgraph()->ZeroConstant(), value);
546 value_type = Type::Range(0.0, value_type->Max(), graph()->zone());
547 NodeProperties::SetType(value, value_type);
548 }
549 if (value_type->Max() > kMaxSafeInteger) {
550 value = graph()->NewNode(
551 common()->Select(MachineRepresentation::kTagged),
552 graph()->NewNode(simplified()->NumberLessThanOrEqual(),
553 jsgraph()->Constant(kMaxSafeInteger), value),
554 jsgraph()->Constant(kMaxSafeInteger), value);
555 value_type =
556 Type::Range(value_type->Min(), kMaxSafeInteger, graph()->zone());
557 NodeProperties::SetType(value, value_type);
558 }
559 }
560 ReplaceWithValue(node, value);
561 return Replace(value);
562 }
563 return Change(node, CodeFactory::ToLength(isolate()), 0);
564 }
565
566
ReduceToObject(Node * node)567 Reduction JSIntrinsicLowering::ReduceToObject(Node* node) {
568 NodeProperties::ChangeOp(node, javascript()->ToObject());
569 return Changed(node);
570 }
571
572
ReduceToPrimitive(Node * node)573 Reduction JSIntrinsicLowering::ReduceToPrimitive(Node* node) {
574 Node* value = NodeProperties::GetValueInput(node, 0);
575 Type* value_type = NodeProperties::GetType(value);
576 if (value_type->Is(Type::Primitive())) {
577 ReplaceWithValue(node, value);
578 return Replace(value);
579 }
580 return NoChange();
581 }
582
583
ReduceToString(Node * node)584 Reduction JSIntrinsicLowering::ReduceToString(Node* node) {
585 NodeProperties::ChangeOp(node, javascript()->ToString());
586 return Changed(node);
587 }
588
589
ReduceCall(Node * node)590 Reduction JSIntrinsicLowering::ReduceCall(Node* node) {
591 size_t const arity = CallRuntimeParametersOf(node->op()).arity();
592 NodeProperties::ChangeOp(
593 node, javascript()->CallFunction(arity, STRICT, VectorSlotPair(),
594 ConvertReceiverMode::kAny,
595 TailCallMode::kDisallow));
596 return Changed(node);
597 }
598
599
ReduceTailCall(Node * node)600 Reduction JSIntrinsicLowering::ReduceTailCall(Node* node) {
601 size_t const arity = CallRuntimeParametersOf(node->op()).arity();
602 NodeProperties::ChangeOp(
603 node, javascript()->CallFunction(arity, STRICT, VectorSlotPair(),
604 ConvertReceiverMode::kAny,
605 TailCallMode::kAllow));
606 return Changed(node);
607 }
608
609
ReduceGetSuperConstructor(Node * node)610 Reduction JSIntrinsicLowering::ReduceGetSuperConstructor(Node* node) {
611 Node* active_function = NodeProperties::GetValueInput(node, 0);
612 Node* effect = NodeProperties::GetEffectInput(node);
613 Node* control = NodeProperties::GetControlInput(node);
614 Node* active_function_map = effect =
615 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
616 active_function, effect, control);
617 return Change(node, simplified()->LoadField(AccessBuilder::ForMapPrototype()),
618 active_function_map, effect, control);
619 }
620
621
Change(Node * node,const Operator * op,Node * a,Node * b)622 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a,
623 Node* b) {
624 RelaxControls(node);
625 node->ReplaceInput(0, a);
626 node->ReplaceInput(1, b);
627 node->TrimInputCount(2);
628 NodeProperties::ChangeOp(node, op);
629 return Changed(node);
630 }
631
632
Change(Node * node,const Operator * op,Node * a,Node * b,Node * c)633 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a,
634 Node* b, Node* c) {
635 RelaxControls(node);
636 node->ReplaceInput(0, a);
637 node->ReplaceInput(1, b);
638 node->ReplaceInput(2, c);
639 node->TrimInputCount(3);
640 NodeProperties::ChangeOp(node, op);
641 return Changed(node);
642 }
643
644
Change(Node * node,const Operator * op,Node * a,Node * b,Node * c,Node * d)645 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a,
646 Node* b, Node* c, Node* d) {
647 RelaxControls(node);
648 node->ReplaceInput(0, a);
649 node->ReplaceInput(1, b);
650 node->ReplaceInput(2, c);
651 node->ReplaceInput(3, d);
652 node->TrimInputCount(4);
653 NodeProperties::ChangeOp(node, op);
654 return Changed(node);
655 }
656
657
ChangeToUndefined(Node * node,Node * effect)658 Reduction JSIntrinsicLowering::ChangeToUndefined(Node* node, Node* effect) {
659 ReplaceWithValue(node, jsgraph()->UndefinedConstant(), effect);
660 return Changed(node);
661 }
662
663
Change(Node * node,Callable const & callable,int stack_parameter_count)664 Reduction JSIntrinsicLowering::Change(Node* node, Callable const& callable,
665 int stack_parameter_count) {
666 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
667 isolate(), graph()->zone(), callable.descriptor(), stack_parameter_count,
668 CallDescriptor::kNeedsFrameState, node->op()->properties());
669 node->InsertInput(graph()->zone(), 0,
670 jsgraph()->HeapConstant(callable.code()));
671 NodeProperties::ChangeOp(node, common()->Call(desc));
672 return Changed(node);
673 }
674
675
graph() const676 Graph* JSIntrinsicLowering::graph() const { return jsgraph()->graph(); }
677
678
isolate() const679 Isolate* JSIntrinsicLowering::isolate() const { return jsgraph()->isolate(); }
680
681
common() const682 CommonOperatorBuilder* JSIntrinsicLowering::common() const {
683 return jsgraph()->common();
684 }
685
javascript() const686 JSOperatorBuilder* JSIntrinsicLowering::javascript() const {
687 return jsgraph_->javascript();
688 }
689
690
machine() const691 MachineOperatorBuilder* JSIntrinsicLowering::machine() const {
692 return jsgraph()->machine();
693 }
694
695
simplified() const696 SimplifiedOperatorBuilder* JSIntrinsicLowering::simplified() const {
697 return jsgraph()->simplified();
698 }
699
700 } // namespace compiler
701 } // namespace internal
702 } // namespace v8
703