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