OLD | NEW |
(Empty) | |
| 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 "src/compiler/access-builder.h" |
| 8 #include "src/compiler/js-graph.h" |
| 9 #include "src/compiler/node-properties-inl.h" |
| 10 |
| 11 namespace v8 { |
| 12 namespace internal { |
| 13 namespace compiler { |
| 14 |
| 15 JSIntrinsicLowering::JSIntrinsicLowering(JSGraph* jsgraph) |
| 16 : jsgraph_(jsgraph), simplified_(jsgraph->zone()) {} |
| 17 |
| 18 |
| 19 Reduction JSIntrinsicLowering::Reduce(Node* node) { |
| 20 if (node->opcode() != IrOpcode::kJSCallRuntime) return NoChange(); |
| 21 const Runtime::Function* const f = |
| 22 Runtime::FunctionForId(CallRuntimeParametersOf(node->op()).id()); |
| 23 if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) return NoChange(); |
| 24 switch (f->function_id) { |
| 25 case Runtime::kInlineIsSmi: |
| 26 return ReduceInlineIsSmi(node); |
| 27 case Runtime::kInlineIsNonNegativeSmi: |
| 28 return ReduceInlineIsNonNegativeSmi(node); |
| 29 case Runtime::kInlineIsArray: |
| 30 return ReduceInlineIsInstanceType(node, JS_ARRAY_TYPE); |
| 31 case Runtime::kInlineIsFunction: |
| 32 return ReduceInlineIsInstanceType(node, JS_FUNCTION_TYPE); |
| 33 case Runtime::kInlineIsRegExp: |
| 34 return ReduceInlineIsInstanceType(node, JS_REGEXP_TYPE); |
| 35 case Runtime::kInlineValueOf: |
| 36 return ReduceInlineValueOf(node); |
| 37 default: |
| 38 break; |
| 39 } |
| 40 return NoChange(); |
| 41 } |
| 42 |
| 43 |
| 44 Reduction JSIntrinsicLowering::ReduceInlineIsSmi(Node* node) { |
| 45 return Change(node, simplified()->ObjectIsSmi()); |
| 46 } |
| 47 |
| 48 |
| 49 Reduction JSIntrinsicLowering::ReduceInlineIsNonNegativeSmi(Node* node) { |
| 50 return Change(node, simplified()->ObjectIsNonNegativeSmi()); |
| 51 } |
| 52 |
| 53 |
| 54 Reduction JSIntrinsicLowering::ReduceInlineIsInstanceType( |
| 55 Node* node, InstanceType instance_type) { |
| 56 // if (%_IsSmi(value)) { |
| 57 // return false; |
| 58 // } else { |
| 59 // return %_GetInstanceType(%_GetMap(value)) == instance_type; |
| 60 // } |
| 61 MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged); |
| 62 |
| 63 Node* value = NodeProperties::GetValueInput(node, 0); |
| 64 Node* effect = NodeProperties::GetEffectInput(node); |
| 65 Node* control = NodeProperties::GetControlInput(node); |
| 66 |
| 67 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value); |
| 68 Node* branch = graph()->NewNode(common()->Branch(), check, control); |
| 69 |
| 70 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| 71 Node* etrue = effect; |
| 72 Node* vtrue = jsgraph()->FalseConstant(); |
| 73 |
| 74 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| 75 Node* efalse = graph()->NewNode( |
| 76 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), |
| 77 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), value, |
| 78 effect, if_false), |
| 79 effect, if_false); |
| 80 Node* vfalse = graph()->NewNode(machine()->Word32Equal(), efalse, |
| 81 jsgraph()->Int32Constant(instance_type)); |
| 82 |
| 83 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
| 84 |
| 85 // Replace all effect uses of {node} with the {ephi}. |
| 86 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); |
| 87 NodeProperties::ReplaceWithValue(node, node, ephi); |
| 88 |
| 89 // Turn the {node} into a Phi. |
| 90 return Change(node, common()->Phi(type, 2), vtrue, vfalse, merge); |
| 91 } |
| 92 |
| 93 |
| 94 Reduction JSIntrinsicLowering::ReduceInlineValueOf(Node* node) { |
| 95 // if (%_IsSmi(value)) { |
| 96 // return value; |
| 97 // } else if (%_GetInstanceType(%_GetMap(value)) == JS_VALUE_TYPE) { |
| 98 // return %_GetValue(value); |
| 99 // } else { |
| 100 // return value; |
| 101 // } |
| 102 const Operator* const merge_op = common()->Merge(2); |
| 103 const Operator* const ephi_op = common()->EffectPhi(2); |
| 104 const Operator* const phi_op = common()->Phi(kMachAnyTagged, 2); |
| 105 |
| 106 Node* value = NodeProperties::GetValueInput(node, 0); |
| 107 Node* effect = NodeProperties::GetEffectInput(node); |
| 108 Node* control = NodeProperties::GetControlInput(node); |
| 109 |
| 110 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value); |
| 111 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); |
| 112 |
| 113 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 114 Node* etrue0 = effect; |
| 115 Node* vtrue0 = value; |
| 116 |
| 117 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 118 Node* efalse0; |
| 119 Node* vfalse0; |
| 120 { |
| 121 Node* check1 = graph()->NewNode( |
| 122 machine()->Word32Equal(), |
| 123 graph()->NewNode( |
| 124 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), |
| 125 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
| 126 value, effect, if_false0), |
| 127 effect, if_false0), |
| 128 jsgraph()->Int32Constant(JS_VALUE_TYPE)); |
| 129 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); |
| 130 |
| 131 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 132 Node* etrue1 = |
| 133 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForValue()), |
| 134 value, effect, if_true1); |
| 135 Node* vtrue1 = etrue1; |
| 136 |
| 137 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 138 Node* efalse1 = effect; |
| 139 Node* vfalse1 = value; |
| 140 |
| 141 Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1); |
| 142 efalse0 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1); |
| 143 vfalse0 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1); |
| 144 } |
| 145 |
| 146 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); |
| 147 |
| 148 |
| 149 // Replace all effect uses of {node} with the {ephi0}. |
| 150 Node* ephi0 = graph()->NewNode(ephi_op, etrue0, efalse0, merge0); |
| 151 NodeProperties::ReplaceWithValue(node, node, ephi0); |
| 152 |
| 153 // Turn the {node} into a Phi. |
| 154 return Change(node, phi_op, vtrue0, vfalse0, merge0); |
| 155 } |
| 156 |
| 157 |
| 158 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op) { |
| 159 // Remove the effects from the node and update its effect usages. |
| 160 NodeProperties::ReplaceWithValue(node, node); |
| 161 // Remove the inputs corresponding to context, effect and control. |
| 162 NodeProperties::RemoveNonValueInputs(node); |
| 163 // Finally update the operator to the new one. |
| 164 node->set_op(op); |
| 165 return Changed(node); |
| 166 } |
| 167 |
| 168 |
| 169 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a, |
| 170 Node* b, Node* c) { |
| 171 node->set_op(op); |
| 172 node->ReplaceInput(0, a); |
| 173 node->ReplaceInput(1, b); |
| 174 node->ReplaceInput(2, c); |
| 175 node->TrimInputCount(3); |
| 176 return Changed(node); |
| 177 } |
| 178 |
| 179 |
| 180 Graph* JSIntrinsicLowering::graph() const { return jsgraph()->graph(); } |
| 181 |
| 182 |
| 183 CommonOperatorBuilder* JSIntrinsicLowering::common() const { |
| 184 return jsgraph()->common(); |
| 185 } |
| 186 |
| 187 |
| 188 MachineOperatorBuilder* JSIntrinsicLowering::machine() const { |
| 189 return jsgraph()->machine(); |
| 190 } |
| 191 |
| 192 } // namespace compiler |
| 193 } // namespace internal |
| 194 } // namespace v8 |
OLD | NEW |