Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Unified Diff: src/compiler/js-typed-lowering.cc

Issue 2228783003: [turbofan] Fix typed lowering of JSConvertReceiver. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/js-operator.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/js-typed-lowering.cc
diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
index 01122bdfb4b9cfa6c9db34a63f1d12a8b07a7a02..878c32d1bed0c152dff592ff0578088b8715bcb9 100644
--- a/src/compiler/js-typed-lowering.cc
+++ b/src/compiler/js-typed-lowering.cc
@@ -386,7 +386,6 @@ JSTypedLowering::JSTypedLowering(Editor* editor,
}
}
-
Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
JSBinopReduction r(this, node);
NumberOperationHint hint;
@@ -742,7 +741,6 @@ Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
return NoChange();
}
-
Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
JSBinopReduction r(this, node);
if (r.left() == r.right()) {
@@ -805,7 +803,6 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
return NoChange();
}
-
Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
Node* const input = node->InputAt(0);
Type* const input_type = NodeProperties::GetType(input);
@@ -916,7 +913,6 @@ Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
return NoChange();
}
-
Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
// Try to reduce the input first.
Node* const input = node->InputAt(0);
@@ -935,7 +931,6 @@ Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
return NoChange();
}
-
Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
if (input->opcode() == IrOpcode::kJSToString) {
// Recursively try to reduce the input first.
@@ -963,7 +958,6 @@ Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
return NoChange();
}
-
Reduction JSTypedLowering::ReduceJSToString(Node* node) {
// Try to reduce the input first.
Node* const input = node->InputAt(0);
@@ -975,7 +969,6 @@ Reduction JSTypedLowering::ReduceJSToString(Node* node) {
return NoChange();
}
-
Reduction JSTypedLowering::ReduceJSToObject(Node* node) {
DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
Node* receiver = NodeProperties::GetValueInput(node, 0);
@@ -1053,7 +1046,6 @@ Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
return NoChange();
}
-
Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
Node* key = NodeProperties::GetValueInput(node, 1);
Node* base = NodeProperties::GetValueInput(node, 0);
@@ -1101,7 +1093,6 @@ Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
return NoChange();
}
-
Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
Node* key = NodeProperties::GetValueInput(node, 1);
Node* base = NodeProperties::GetValueInput(node, 0);
@@ -1179,7 +1170,6 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
return NoChange();
}
-
Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
Node* const context = NodeProperties::GetContextInput(node);
@@ -1282,7 +1272,6 @@ Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
Node* if_is_proxy = graph()->NewNode(common()->IfTrue(), branch_is_proxy);
Node* e_is_proxy = effect;
-
Node* runtime_has_in_proto_chain = control = graph()->NewNode(
common()->Merge(2), if_is_access_check_needed, if_is_proxy);
effect = graph()->NewNode(common()->EffectPhi(2), e_is_access_check_needed,
@@ -1353,7 +1342,6 @@ Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
return Changed(result);
}
-
Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
ContextAccess const& access = ContextAccessOf(node->op());
@@ -1374,7 +1362,6 @@ Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
return Changed(node);
}
-
Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
ContextAccess const& access = ContextAccessOf(node->op());
@@ -1395,7 +1382,6 @@ Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
return Changed(node);
}
-
Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode());
ConvertReceiverMode mode = ConvertReceiverModeOf(node->op());
@@ -1406,89 +1392,153 @@ Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
- if (!receiver_type->Is(Type::Receiver())) {
- if (receiver_type->Is(Type::NullOrUndefined()) ||
- mode == ConvertReceiverMode::kNullOrUndefined) {
- if (context_type->IsConstant()) {
- Handle<JSObject> global_proxy(
- Handle<Context>::cast(context_type->AsConstant()->Value())
- ->global_proxy(),
- isolate());
- receiver = jsgraph()->Constant(global_proxy);
- } else {
- Node* native_context = effect = graph()->NewNode(
- javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
- context, context, effect);
- receiver = effect = graph()->NewNode(
- javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
- native_context, native_context, effect);
- }
- } else if (!receiver_type->Maybe(Type::NullOrUndefined()) ||
- mode == ConvertReceiverMode::kNotNullOrUndefined) {
- receiver = effect =
- graph()->NewNode(javascript()->ToObject(), receiver, context,
- frame_state, effect, control);
+
+ // Check if {receiver} is known to be a receiver.
+ if (receiver_type->Is(Type::Receiver())) {
+ ReplaceWithValue(node, receiver, effect, control);
+ return Replace(receiver);
+ }
+
+ // If the {receiver} is known to be null or undefined, we can just replace it
+ // with the global proxy unconditionally.
+ if (receiver_type->Is(Type::NullOrUndefined()) ||
+ mode == ConvertReceiverMode::kNullOrUndefined) {
+ if (context_type->IsConstant()) {
+ Handle<JSObject> global_proxy(
+ Handle<Context>::cast(context_type->AsConstant()->Value())
+ ->global_proxy(),
+ isolate());
+ receiver = jsgraph()->Constant(global_proxy);
} else {
- // Check {receiver} for undefined.
- Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
- jsgraph()->UndefinedConstant());
- Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
- check0, control);
- Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
- Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
-
- // Check {receiver} for null.
- Node* check1 = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
- jsgraph()->NullConstant());
- Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
- check1, if_false0);
- Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
- Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
-
- // Convert {receiver} using ToObject.
- Node* if_convert = if_false1;
- Node* econvert = effect;
- Node* rconvert;
- {
- rconvert = econvert =
- graph()->NewNode(javascript()->ToObject(), receiver, context,
- frame_state, econvert, if_convert);
- }
+ Node* native_context = effect = graph()->NewNode(
+ javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+ context, context, effect);
+ receiver = effect = graph()->NewNode(
+ javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
+ native_context, native_context, effect);
+ }
+ ReplaceWithValue(node, receiver, effect, control);
+ return Replace(receiver);
+ }
- // Replace {receiver} with global proxy of {context}.
- Node* if_global =
- graph()->NewNode(common()->Merge(2), if_true0, if_true1);
- Node* eglobal = effect;
- Node* rglobal;
- {
- if (context_type->IsConstant()) {
- Handle<JSObject> global_proxy(
- Handle<Context>::cast(context_type->AsConstant()->Value())
- ->global_proxy(),
- isolate());
- rglobal = jsgraph()->Constant(global_proxy);
- } else {
- Node* native_context = eglobal = graph()->NewNode(
- javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
- context, context, eglobal);
- rglobal = eglobal = graph()->NewNode(
- javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
- native_context, native_context, eglobal);
- }
- }
+ // If {receiver} cannot be null or undefined we can skip a few checks.
+ if (!receiver_type->Maybe(Type::NullOrUndefined()) ||
+ mode == ConvertReceiverMode::kNotNullOrUndefined) {
+ Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
+ Node* branch =
+ graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* etrue = effect;
+ Node* rtrue = receiver;
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* efalse = effect;
+ Node* rfalse;
+ {
+ // Convert {receiver} using the ToObjectStub.
+ Callable callable = CodeFactory::ToObject(isolate());
+ CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
+ isolate(), graph()->zone(), callable.descriptor(), 0,
+ CallDescriptor::kNeedsFrameState, node->op()->properties());
+ rfalse = efalse = graph()->NewNode(
+ common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
+ receiver, context, frame_state, efalse);
+ }
+
+ control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+
+ // Morph the {node} into an appropriate Phi.
+ ReplaceWithValue(node, node, effect, control);
+ node->ReplaceInput(0, rtrue);
+ node->ReplaceInput(1, rfalse);
+ node->ReplaceInput(2, control);
+ node->TrimInputCount(3);
+ NodeProperties::ChangeOp(node,
+ common()->Phi(MachineRepresentation::kTagged, 2));
+ return Changed(node);
+ }
+
+ // Check if {receiver} is already a JSReceiver.
+ Node* check0 = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
+ Node* branch0 =
+ graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
+ Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+ Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+
+ // Check {receiver} for undefined.
+ Node* check1 = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
+ jsgraph()->UndefinedConstant());
+ Node* branch1 =
+ graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, if_false0);
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+
+ // Check {receiver} for null.
+ Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
+ jsgraph()->NullConstant());
+ Node* branch2 =
+ graph()->NewNode(common()->Branch(BranchHint::kFalse), check2, if_false1);
+ Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
+ Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
+
+ // We just use {receiver} directly.
+ Node* if_noop = if_true0;
+ Node* enoop = effect;
+ Node* rnoop = receiver;
+
+ // Convert {receiver} using ToObject.
+ Node* if_convert = if_false2;
+ Node* econvert = effect;
+ Node* rconvert;
+ {
+ // Convert {receiver} using the ToObjectStub.
+ Callable callable = CodeFactory::ToObject(isolate());
+ CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
+ isolate(), graph()->zone(), callable.descriptor(), 0,
+ CallDescriptor::kNeedsFrameState, node->op()->properties());
+ rconvert = econvert = graph()->NewNode(
+ common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
+ receiver, context, frame_state, econvert);
+ }
- control = graph()->NewNode(common()->Merge(2), if_convert, if_global);
- effect =
- graph()->NewNode(common()->EffectPhi(2), econvert, eglobal, control);
- receiver =
- graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
- rconvert, rglobal, control);
+ // Replace {receiver} with global proxy of {context}.
+ Node* if_global = graph()->NewNode(common()->Merge(2), if_true1, if_true2);
+ Node* eglobal = effect;
+ Node* rglobal;
+ {
+ if (context_type->IsConstant()) {
+ Handle<JSObject> global_proxy(
+ Handle<Context>::cast(context_type->AsConstant()->Value())
+ ->global_proxy(),
+ isolate());
+ rglobal = jsgraph()->Constant(global_proxy);
+ } else {
+ Node* native_context = eglobal = graph()->NewNode(
+ javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+ context, context, eglobal);
+ rglobal = eglobal = graph()->NewNode(
+ javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
+ native_context, native_context, eglobal);
}
}
- ReplaceWithValue(node, receiver, effect, control);
- return Changed(receiver);
-}
+ control =
+ graph()->NewNode(common()->Merge(3), if_noop, if_convert, if_global);
+ effect = graph()->NewNode(common()->EffectPhi(3), enoop, econvert, eglobal,
+ control);
+ // Morph the {node} into an appropriate Phi.
+ ReplaceWithValue(node, node, effect, control);
+ node->ReplaceInput(0, rnoop);
+ node->ReplaceInput(1, rconvert);
+ node->ReplaceInput(2, rglobal);
+ node->ReplaceInput(3, control);
+ node->TrimInputCount(4);
+ NodeProperties::ChangeOp(node,
+ common()->Phi(MachineRepresentation::kTagged, 3));
+ return Changed(node);
+}
Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) {
DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode());
« no previous file with comments | « src/compiler/js-operator.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698