diff options
Diffstat (limited to 'deps/v8/src/compiler/js-intrinsic-lowering.cc')
-rw-r--r-- | deps/v8/src/compiler/js-intrinsic-lowering.cc | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/deps/v8/src/compiler/js-intrinsic-lowering.cc b/deps/v8/src/compiler/js-intrinsic-lowering.cc new file mode 100644 index 0000000000..a1e693585b --- /dev/null +++ b/deps/v8/src/compiler/js-intrinsic-lowering.cc @@ -0,0 +1,194 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/compiler/js-intrinsic-lowering.h" + +#include "src/compiler/access-builder.h" +#include "src/compiler/js-graph.h" +#include "src/compiler/node-properties.h" + +namespace v8 { +namespace internal { +namespace compiler { + +JSIntrinsicLowering::JSIntrinsicLowering(JSGraph* jsgraph) + : jsgraph_(jsgraph), simplified_(jsgraph->zone()) {} + + +Reduction JSIntrinsicLowering::Reduce(Node* node) { + if (node->opcode() != IrOpcode::kJSCallRuntime) return NoChange(); + const Runtime::Function* const f = + Runtime::FunctionForId(CallRuntimeParametersOf(node->op()).id()); + if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) return NoChange(); + switch (f->function_id) { + case Runtime::kInlineIsSmi: + return ReduceInlineIsSmi(node); + case Runtime::kInlineIsNonNegativeSmi: + return ReduceInlineIsNonNegativeSmi(node); + case Runtime::kInlineIsArray: + return ReduceInlineIsInstanceType(node, JS_ARRAY_TYPE); + case Runtime::kInlineIsFunction: + return ReduceInlineIsInstanceType(node, JS_FUNCTION_TYPE); + case Runtime::kInlineIsRegExp: + return ReduceInlineIsInstanceType(node, JS_REGEXP_TYPE); + case Runtime::kInlineValueOf: + return ReduceInlineValueOf(node); + default: + break; + } + return NoChange(); +} + + +Reduction JSIntrinsicLowering::ReduceInlineIsSmi(Node* node) { + return Change(node, simplified()->ObjectIsSmi()); +} + + +Reduction JSIntrinsicLowering::ReduceInlineIsNonNegativeSmi(Node* node) { + return Change(node, simplified()->ObjectIsNonNegativeSmi()); +} + + +Reduction JSIntrinsicLowering::ReduceInlineIsInstanceType( + Node* node, InstanceType instance_type) { + // if (%_IsSmi(value)) { + // return false; + // } else { + // return %_GetInstanceType(%_GetMap(value)) == instance_type; + // } + MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged); + + Node* value = NodeProperties::GetValueInput(node, 0); + Node* effect = NodeProperties::GetEffectInput(node); + Node* control = NodeProperties::GetControlInput(node); + + Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value); + Node* branch = graph()->NewNode(common()->Branch(), check, control); + + Node* if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* etrue = effect; + Node* vtrue = jsgraph()->FalseConstant(); + + Node* if_false = graph()->NewNode(common()->IfFalse(), branch); + Node* efalse = graph()->NewNode( + simplified()->LoadField(AccessBuilder::ForMapInstanceType()), + graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), value, + effect, if_false), + effect, if_false); + Node* vfalse = graph()->NewNode(machine()->Word32Equal(), efalse, + jsgraph()->Int32Constant(instance_type)); + + Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); + + // Replace all effect uses of {node} with the {ephi}. + Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); + NodeProperties::ReplaceWithValue(node, node, ephi); + + // Turn the {node} into a Phi. + return Change(node, common()->Phi(type, 2), vtrue, vfalse, merge); +} + + +Reduction JSIntrinsicLowering::ReduceInlineValueOf(Node* node) { + // if (%_IsSmi(value)) { + // return value; + // } else if (%_GetInstanceType(%_GetMap(value)) == JS_VALUE_TYPE) { + // return %_GetValue(value); + // } else { + // return value; + // } + const Operator* const merge_op = common()->Merge(2); + const Operator* const ephi_op = common()->EffectPhi(2); + const Operator* const phi_op = common()->Phi(kMachAnyTagged, 2); + + Node* value = NodeProperties::GetValueInput(node, 0); + Node* effect = NodeProperties::GetEffectInput(node); + Node* control = NodeProperties::GetControlInput(node); + + Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value); + Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); + + Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); + Node* etrue0 = effect; + Node* vtrue0 = value; + + Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); + Node* efalse0; + Node* vfalse0; + { + Node* check1 = graph()->NewNode( + machine()->Word32Equal(), + graph()->NewNode( + simplified()->LoadField(AccessBuilder::ForMapInstanceType()), + graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), + value, effect, if_false0), + effect, if_false0), + jsgraph()->Int32Constant(JS_VALUE_TYPE)); + Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); + + Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); + Node* etrue1 = + graph()->NewNode(simplified()->LoadField(AccessBuilder::ForValue()), + value, effect, if_true1); + Node* vtrue1 = etrue1; + + Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); + Node* efalse1 = effect; + Node* vfalse1 = value; + + Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1); + efalse0 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1); + vfalse0 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1); + } + + Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); + + + // Replace all effect uses of {node} with the {ephi0}. + Node* ephi0 = graph()->NewNode(ephi_op, etrue0, efalse0, merge0); + NodeProperties::ReplaceWithValue(node, node, ephi0); + + // Turn the {node} into a Phi. + return Change(node, phi_op, vtrue0, vfalse0, merge0); +} + + +Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op) { + // Remove the effects from the node and update its effect usages. + NodeProperties::ReplaceWithValue(node, node); + // Remove the inputs corresponding to context, effect and control. + NodeProperties::RemoveNonValueInputs(node); + // Finally update the operator to the new one. + node->set_op(op); + return Changed(node); +} + + +Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a, + Node* b, Node* c) { + node->set_op(op); + node->ReplaceInput(0, a); + node->ReplaceInput(1, b); + node->ReplaceInput(2, c); + node->TrimInputCount(3); + return Changed(node); +} + + +Graph* JSIntrinsicLowering::graph() const { return jsgraph()->graph(); } + + +CommonOperatorBuilder* JSIntrinsicLowering::common() const { + return jsgraph()->common(); +} + + +MachineOperatorBuilder* JSIntrinsicLowering::machine() const { + return jsgraph()->machine(); +} + +} // namespace compiler +} // namespace internal +} // namespace v8 |