Home | History | Annotate | Download | only in compiler
      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 
     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 
     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 
    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 
    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 
    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 
    158 Reduction JSIntrinsicLowering::ReduceDoubleHi(Node* node) {
    159   return Change(node, machine()->Float64ExtractHighWord32());
    160 }
    161 
    162 
    163 Reduction JSIntrinsicLowering::ReduceDoubleLo(Node* node) {
    164   return Change(node, machine()->Float64ExtractLowWord32());
    165 }
    166 
    167 
    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 
    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 
    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 
    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 
    318 Reduction JSIntrinsicLowering::ReduceIsSmi(Node* node) {
    319   return Change(node, simplified()->ObjectIsSmi());
    320 }
    321 
    322 
    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 
    332 Reduction JSIntrinsicLowering::ReduceMathClz32(Node* node) {
    333   return Change(node, machine()->Word32Clz());
    334 }
    335 
    336 
    337 Reduction JSIntrinsicLowering::ReduceMathFloor(Node* node) {
    338   if (!machine()->Float64RoundDown().IsSupported()) return NoChange();
    339   return Change(node, machine()->Float64RoundDown().op());
    340 }
    341 
    342 
    343 Reduction JSIntrinsicLowering::ReduceMathSqrt(Node* node) {
    344   return Change(node, machine()->Float64Sqrt());
    345 }
    346 
    347 
    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 
    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 
    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 
    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 
    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 
    472 Reduction JSIntrinsicLowering::ReduceRegExpConstructResult(Node* node) {
    473   // TODO(bmeurer): Introduce JSCreateRegExpResult?
    474   return Change(node, CodeFactory::RegExpConstructResult(isolate()), 0);
    475 }
    476 
    477 
    478 Reduction JSIntrinsicLowering::ReduceRegExpExec(Node* node) {
    479   return Change(node, CodeFactory::RegExpExec(isolate()), 4);
    480 }
    481 
    482 
    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 
    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 
    503 Reduction JSIntrinsicLowering::ReduceSubString(Node* node) {
    504   return Change(node, CodeFactory::SubString(isolate()), 3);
    505 }
    506 
    507 
    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 
    519 Reduction JSIntrinsicLowering::ReduceToName(Node* node) {
    520   NodeProperties::ChangeOp(node, javascript()->ToName());
    521   return Changed(node);
    522 }
    523 
    524 
    525 Reduction JSIntrinsicLowering::ReduceToNumber(Node* node) {
    526   NodeProperties::ChangeOp(node, javascript()->ToNumber());
    527   return Changed(node);
    528 }
    529 
    530 
    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 
    567 Reduction JSIntrinsicLowering::ReduceToObject(Node* node) {
    568   NodeProperties::ChangeOp(node, javascript()->ToObject());
    569   return Changed(node);
    570 }
    571 
    572 
    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 
    584 Reduction JSIntrinsicLowering::ReduceToString(Node* node) {
    585   NodeProperties::ChangeOp(node, javascript()->ToString());
    586   return Changed(node);
    587 }
    588 
    589 
    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 
    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 
    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 
    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 
    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 
    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 
    658 Reduction JSIntrinsicLowering::ChangeToUndefined(Node* node, Node* effect) {
    659   ReplaceWithValue(node, jsgraph()->UndefinedConstant(), effect);
    660   return Changed(node);
    661 }
    662 
    663 
    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 
    676 Graph* JSIntrinsicLowering::graph() const { return jsgraph()->graph(); }
    677 
    678 
    679 Isolate* JSIntrinsicLowering::isolate() const { return jsgraph()->isolate(); }
    680 
    681 
    682 CommonOperatorBuilder* JSIntrinsicLowering::common() const {
    683   return jsgraph()->common();
    684 }
    685 
    686 JSOperatorBuilder* JSIntrinsicLowering::javascript() const {
    687   return jsgraph_->javascript();
    688 }
    689 
    690 
    691 MachineOperatorBuilder* JSIntrinsicLowering::machine() const {
    692   return jsgraph()->machine();
    693 }
    694 
    695 
    696 SimplifiedOperatorBuilder* JSIntrinsicLowering::simplified() const {
    697   return jsgraph()->simplified();
    698 }
    699 
    700 }  // namespace compiler
    701 }  // namespace internal
    702 }  // namespace v8
    703