| Index: src/compiler/js-intrinsic-lowering.cc
|
| diff --git a/src/compiler/js-intrinsic-lowering.cc b/src/compiler/js-intrinsic-lowering.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..99def3016f0bbd870ce7e859e8c5ddc2482b3a32
|
| --- /dev/null
|
| +++ b/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-inl.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
|
|
|