| Index: src/compiler/js-typed-lowering.cc
|
| diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
|
| index 320e699c43abb0d59e0d37d07abe54482c982df6..f221577104c1d84679249ee2c81019a8d74749dc 100644
|
| --- a/src/compiler/js-typed-lowering.cc
|
| +++ b/src/compiler/js-typed-lowering.cc
|
| @@ -3,6 +3,7 @@
|
| // found in the LICENSE file.
|
|
|
| #include "src/code-factory.h"
|
| +#include "src/compilation-dependencies.h"
|
| #include "src/compiler/access-builder.h"
|
| #include "src/compiler/js-graph.h"
|
| #include "src/compiler/js-typed-lowering.h"
|
| @@ -22,8 +23,13 @@ namespace compiler {
|
| // - relax effects from generic but not-side-effecting operations
|
|
|
|
|
| -JSTypedLowering::JSTypedLowering(Editor* editor, JSGraph* jsgraph, Zone* zone)
|
| - : AdvancedReducer(editor), jsgraph_(jsgraph) {
|
| +JSTypedLowering::JSTypedLowering(Editor* editor,
|
| + CompilationDependencies* dependencies,
|
| + Flags flags, JSGraph* jsgraph, Zone* zone)
|
| + : AdvancedReducer(editor),
|
| + dependencies_(dependencies),
|
| + flags_(flags),
|
| + jsgraph_(jsgraph) {
|
| for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
|
| double min = kMinInt / (1 << k);
|
| double max = kMaxInt / (1 << k);
|
| @@ -1059,6 +1065,117 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
|
| }
|
|
|
|
|
| +Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
|
| + DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
|
| +
|
| + // If deoptimization is disabled, we cannot optimize.
|
| + if (!(flags() & kDeoptimizationEnabled)) return NoChange();
|
| +
|
| + JSBinopReduction r(this, node);
|
| + Node* effect = r.effect();
|
| + Node* control = r.control();
|
| +
|
| + if (r.right_type()->IsConstant() &&
|
| + r.right_type()->AsConstant()->Value()->IsJSFunction()) {
|
| + Handle<JSFunction> function =
|
| + Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value());
|
| + Handle<SharedFunctionInfo> shared(function->shared(), isolate());
|
| + if (!function->map()->has_non_instance_prototype()) {
|
| + JSFunction::EnsureHasInitialMap(function);
|
| + DCHECK(function->has_initial_map());
|
| + Handle<Map> initial_map(function->initial_map(), isolate());
|
| + this->dependencies()->AssumeInitialMapCantChange(initial_map);
|
| + Node* prototype =
|
| + jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
|
| +
|
| + Node* if_is_smi = nullptr;
|
| + Node* e_is_smi = nullptr;
|
| + // If the left hand side is an object, no smi check is needed.
|
| + if (r.left_type()->Maybe(Type::TaggedSigned())) {
|
| + Node* is_smi = graph()->NewNode(simplified()->ObjectIsSmi(), r.left());
|
| + Node* branch_is_smi = graph()->NewNode(
|
| + common()->Branch(BranchHint::kFalse), is_smi, control);
|
| + if_is_smi = graph()->NewNode(common()->IfTrue(), branch_is_smi);
|
| + e_is_smi = effect;
|
| + control = graph()->NewNode(common()->IfFalse(), branch_is_smi);
|
| + }
|
| +
|
| + Node* object_map = effect =
|
| + graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
|
| + r.left(), effect, control);
|
| +
|
| + // Loop through the {object}s prototype chain looking for the {prototype}.
|
| + Node* loop = control =
|
| + graph()->NewNode(common()->Loop(2), control, control);
|
| +
|
| + Node* loop_effect = effect =
|
| + graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
|
| +
|
| + Node* loop_object_map = graph()->NewNode(common()->Phi(kMachAnyTagged, 2),
|
| + object_map, r.left(), loop);
|
| +
|
| +
|
| + Node* object_prototype = effect = graph()->NewNode(
|
| + simplified()->LoadField(AccessBuilder::ForMapPrototype()),
|
| + loop_object_map, loop_effect, control);
|
| +
|
| + // Check if object prototype is equal to function prototype.
|
| + Node* eq_proto =
|
| + graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
|
| + object_prototype, prototype);
|
| + Node* branch_eq_proto = graph()->NewNode(
|
| + common()->Branch(BranchHint::kFalse), eq_proto, control);
|
| + Node* if_eq_proto = graph()->NewNode(common()->IfTrue(), branch_eq_proto);
|
| + Node* e_eq_proto = effect;
|
| +
|
| + control = graph()->NewNode(common()->IfFalse(), branch_eq_proto);
|
| +
|
| + // If not, check if object prototype is the null prototype.
|
| + Node* null_proto =
|
| + graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
|
| + object_prototype, jsgraph()->NullConstant());
|
| + Node* branch_null_proto = graph()->NewNode(
|
| + common()->Branch(BranchHint::kFalse), null_proto, control);
|
| + Node* if_null_proto =
|
| + graph()->NewNode(common()->IfTrue(), branch_null_proto);
|
| + Node* e_null_proto = effect;
|
| +
|
| + control = graph()->NewNode(common()->IfFalse(), branch_null_proto);
|
| + Node* load_object_map = effect =
|
| + graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
|
| + object_prototype, effect, control);
|
| + // Close the loop.
|
| + loop_effect->ReplaceInput(1, effect);
|
| + loop_object_map->ReplaceInput(1, load_object_map);
|
| + loop->ReplaceInput(1, control);
|
| +
|
| + control =
|
| + graph()->NewNode(common()->Merge(2), if_eq_proto, if_null_proto);
|
| + effect = graph()->NewNode(common()->EffectPhi(2), e_eq_proto,
|
| + e_null_proto, control);
|
| +
|
| +
|
| + Node* result = graph()->NewNode(common()->Phi(kTypeBool, 2),
|
| + jsgraph()->TrueConstant(),
|
| + jsgraph()->FalseConstant(), control);
|
| +
|
| + if (if_is_smi != nullptr) {
|
| + DCHECK(e_is_smi != nullptr);
|
| + control = graph()->NewNode(common()->Merge(2), if_is_smi, control);
|
| + effect =
|
| + graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control);
|
| + result = graph()->NewNode(common()->Phi(kTypeBool, 2),
|
| + jsgraph()->FalseConstant(), result, control);
|
| + }
|
| + ReplaceWithValue(node, result, effect, control);
|
| + return Changed(result);
|
| + }
|
| + }
|
| +
|
| + return NoChange();
|
| +}
|
| +
|
| +
|
| Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
|
| DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
|
| ContextAccess const& access = ContextAccessOf(node->op());
|
| @@ -2028,6 +2145,8 @@ Reduction JSTypedLowering::Reduce(Node* node) {
|
| return ReduceJSLoadProperty(node);
|
| case IrOpcode::kJSStoreProperty:
|
| return ReduceJSStoreProperty(node);
|
| + case IrOpcode::kJSInstanceOf:
|
| + return ReduceJSInstanceOf(node);
|
| case IrOpcode::kJSLoadContext:
|
| return ReduceJSLoadContext(node);
|
| case IrOpcode::kJSStoreContext:
|
| @@ -2175,6 +2294,11 @@ MachineOperatorBuilder* JSTypedLowering::machine() const {
|
| return jsgraph()->machine();
|
| }
|
|
|
| +
|
| +CompilationDependencies* JSTypedLowering::dependencies() const {
|
| + return dependencies_;
|
| +}
|
| +
|
| } // namespace compiler
|
| } // namespace internal
|
| } // namespace v8
|
|
|