Commit a758c197 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Properly rename receiver on CheckHeapObject.

We need to rename the receiver on CheckHeapObject, because we
don't canonicalize numbers in SignedSmall range, and thus we
the representation selection can hand out TaggedSigned values
for receiver uses, even though we checked for TaggedPointerness
first.

Note that this is rather hacky and just intended to fix the bug
ASAP. We need to think about how to deal with representations in
earlier compilation stages.

BUG=chromium:662410
R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/2485563002
Cr-Commit-Position: refs/heads/master@{#40792}
parent 3a445b21
...@@ -107,6 +107,19 @@ JSBuiltinReducer::JSBuiltinReducer(Editor* editor, JSGraph* jsgraph, ...@@ -107,6 +107,19 @@ JSBuiltinReducer::JSBuiltinReducer(Editor* editor, JSGraph* jsgraph,
namespace { namespace {
// TODO(turbofan): Shall we move this to the NodeProperties? Or some (untyped)
// alias analyzer?
bool IsSame(Node* a, Node* b) {
if (a == b) {
return true;
} else if (a->opcode() == IrOpcode::kCheckHeapObject) {
return IsSame(a->InputAt(0), b);
} else if (b->opcode() == IrOpcode::kCheckHeapObject) {
return IsSame(a, b->InputAt(0));
}
return false;
}
MaybeHandle<Map> GetMapWitness(Node* node) { MaybeHandle<Map> GetMapWitness(Node* node) {
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = NodeProperties::GetValueInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
...@@ -114,7 +127,7 @@ MaybeHandle<Map> GetMapWitness(Node* node) { ...@@ -114,7 +127,7 @@ MaybeHandle<Map> GetMapWitness(Node* node) {
// for the {receiver}, and if so use that map for the lowering below. // for the {receiver}, and if so use that map for the lowering below.
for (Node* dominator = effect;;) { for (Node* dominator = effect;;) {
if (dominator->opcode() == IrOpcode::kCheckMaps && if (dominator->opcode() == IrOpcode::kCheckMaps &&
dominator->InputAt(0) == receiver) { IsSame(dominator->InputAt(0), receiver)) {
if (dominator->op()->ValueInputCount() == 2) { if (dominator->op()->ValueInputCount() == 2) {
HeapObjectMatcher m(dominator->InputAt(1)); HeapObjectMatcher m(dominator->InputAt(1));
if (m.HasValue()) return Handle<Map>::cast(m.Value()); if (m.HasValue()) return Handle<Map>::cast(m.Value());
...@@ -331,7 +344,7 @@ bool HasInstanceTypeWitness(Node* receiver, Node* effect, ...@@ -331,7 +344,7 @@ bool HasInstanceTypeWitness(Node* receiver, Node* effect,
InstanceType instance_type) { InstanceType instance_type) {
for (Node* dominator = effect;;) { for (Node* dominator = effect;;) {
if (dominator->opcode() == IrOpcode::kCheckMaps && if (dominator->opcode() == IrOpcode::kCheckMaps &&
dominator->InputAt(0) == receiver) { IsSame(dominator->InputAt(0), receiver)) {
// Check if all maps have the given {instance_type}. // Check if all maps have the given {instance_type}.
for (int i = 1; i < dominator->op()->ValueInputCount(); ++i) { for (int i = 1; i < dominator->op()->ValueInputCount(); ++i) {
Node* const map = NodeProperties::GetValueInput(dominator, i); Node* const map = NodeProperties::GetValueInput(dominator, i);
...@@ -922,7 +935,7 @@ Node* GetStringWitness(Node* node) { ...@@ -922,7 +935,7 @@ Node* GetStringWitness(Node* node) {
// the lowering below. // the lowering below.
for (Node* dominator = effect;;) { for (Node* dominator = effect;;) {
if (dominator->opcode() == IrOpcode::kCheckString && if (dominator->opcode() == IrOpcode::kCheckString &&
dominator->InputAt(0) == receiver) { IsSame(dominator->InputAt(0), receiver)) {
return dominator; return dominator;
} }
if (dominator->op()->EffectInputCount() != 1) { if (dominator->op()->EffectInputCount() != 1) {
......
...@@ -191,6 +191,19 @@ Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) { ...@@ -191,6 +191,19 @@ Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
namespace { namespace {
// TODO(turbofan): Shall we move this to the NodeProperties? Or some (untyped)
// alias analyzer?
bool IsSame(Node* a, Node* b) {
if (a == b) {
return true;
} else if (a->opcode() == IrOpcode::kCheckHeapObject) {
return IsSame(a->InputAt(0), b);
} else if (b->opcode() == IrOpcode::kCheckHeapObject) {
return IsSame(a, b->InputAt(0));
}
return false;
}
// TODO(turbofan): Share with similar functionality in JSInliningHeuristic // TODO(turbofan): Share with similar functionality in JSInliningHeuristic
// and JSNativeContextSpecialization, i.e. move to NodeProperties helper?! // and JSNativeContextSpecialization, i.e. move to NodeProperties helper?!
MaybeHandle<Map> InferReceiverMap(Node* node) { MaybeHandle<Map> InferReceiverMap(Node* node) {
...@@ -200,7 +213,7 @@ MaybeHandle<Map> InferReceiverMap(Node* node) { ...@@ -200,7 +213,7 @@ MaybeHandle<Map> InferReceiverMap(Node* node) {
// for the {receiver}, and if so use that map for the lowering below. // for the {receiver}, and if so use that map for the lowering below.
for (Node* dominator = effect;;) { for (Node* dominator = effect;;) {
if (dominator->opcode() == IrOpcode::kCheckMaps && if (dominator->opcode() == IrOpcode::kCheckMaps &&
dominator->InputAt(0) == receiver) { IsSame(dominator->InputAt(0), receiver)) {
if (dominator->op()->ValueInputCount() == 2) { if (dominator->op()->ValueInputCount() == 2) {
HeapObjectMatcher m(dominator->InputAt(1)); HeapObjectMatcher m(dominator->InputAt(1));
if (m.HasValue()) return Handle<Map>::cast(m.Value()); if (m.HasValue()) return Handle<Map>::cast(m.Value());
......
...@@ -282,6 +282,19 @@ Node* JSInliner::CreateTailCallerFrameState(Node* node, Node* frame_state) { ...@@ -282,6 +282,19 @@ Node* JSInliner::CreateTailCallerFrameState(Node* node, Node* frame_state) {
namespace { namespace {
// TODO(turbofan): Shall we move this to the NodeProperties? Or some (untyped)
// alias analyzer?
bool IsSame(Node* a, Node* b) {
if (a == b) {
return true;
} else if (a->opcode() == IrOpcode::kCheckHeapObject) {
return IsSame(a->InputAt(0), b);
} else if (b->opcode() == IrOpcode::kCheckHeapObject) {
return IsSame(a, b->InputAt(0));
}
return false;
}
// TODO(bmeurer): Unify this with the witness helper functions in the // TODO(bmeurer): Unify this with the witness helper functions in the
// js-builtin-reducer.cc once we have a better understanding of the // js-builtin-reducer.cc once we have a better understanding of the
// map tracking we want to do, and eventually changed the CheckMaps // map tracking we want to do, and eventually changed the CheckMaps
...@@ -296,7 +309,7 @@ namespace { ...@@ -296,7 +309,7 @@ namespace {
bool NeedsConvertReceiver(Node* receiver, Node* effect) { bool NeedsConvertReceiver(Node* receiver, Node* effect) {
for (Node* dominator = effect;;) { for (Node* dominator = effect;;) {
if (dominator->opcode() == IrOpcode::kCheckMaps && if (dominator->opcode() == IrOpcode::kCheckMaps &&
dominator->InputAt(0) == receiver) { IsSame(dominator->InputAt(0), receiver)) {
// Check if all maps have the given {instance_type}. // Check if all maps have the given {instance_type}.
for (int i = 1; i < dominator->op()->ValueInputCount(); ++i) { for (int i = 1; i < dominator->op()->ValueInputCount(); ++i) {
HeapObjectMatcher m(NodeProperties::GetValueInput(dominator, i)); HeapObjectMatcher m(NodeProperties::GetValueInput(dominator, i));
......
...@@ -161,7 +161,8 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( ...@@ -161,7 +161,8 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
receiver, effect, control); receiver, effect, control);
} else { } else {
// Monomorphic property access. // Monomorphic property access.
effect = BuildCheckHeapObject(receiver, effect, control); receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(),
receiver, effect, control);
effect = BuildCheckMaps(receiver, effect, control, effect = BuildCheckMaps(receiver, effect, control,
access_info.receiver_maps()); access_info.receiver_maps());
} }
...@@ -199,7 +200,8 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( ...@@ -199,7 +200,8 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch); receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
receiverissmi_effect = effect; receiverissmi_effect = effect;
} else { } else {
effect = BuildCheckHeapObject(receiver, effect, control); receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(),
receiver, effect, control);
} }
// Load the {receiver} map. The resulting effect is the dominating effect // Load the {receiver} map. The resulting effect is the dominating effect
...@@ -507,7 +509,8 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( ...@@ -507,7 +509,8 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
} }
// Ensure that {receiver} is a heap object. // Ensure that {receiver} is a heap object.
effect = BuildCheckHeapObject(receiver, effect, control); receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(),
receiver, effect, control);
// Check for the monomorphic case. // Check for the monomorphic case.
if (access_infos.size() == 1) { if (access_infos.size() == 1) {
...@@ -1449,33 +1452,6 @@ Node* JSNativeContextSpecialization::BuildCheckMaps( ...@@ -1449,33 +1452,6 @@ Node* JSNativeContextSpecialization::BuildCheckMaps(
inputs); inputs);
} }
Node* JSNativeContextSpecialization::BuildCheckHeapObject(Node* receiver,
Node* effect,
Node* control) {
switch (receiver->opcode()) {
case IrOpcode::kHeapConstant:
case IrOpcode::kJSCreate:
case IrOpcode::kJSCreateArguments:
case IrOpcode::kJSCreateArray:
case IrOpcode::kJSCreateClosure:
case IrOpcode::kJSCreateIterResultObject:
case IrOpcode::kJSCreateLiteralArray:
case IrOpcode::kJSCreateLiteralObject:
case IrOpcode::kJSCreateLiteralRegExp:
case IrOpcode::kJSConvertReceiver:
case IrOpcode::kJSToName:
case IrOpcode::kJSToString:
case IrOpcode::kJSToObject:
case IrOpcode::kJSTypeOf: {
return effect;
}
default: {
return graph()->NewNode(simplified()->CheckHeapObject(), receiver, effect,
control);
}
}
}
void JSNativeContextSpecialization::AssumePrototypesStable( void JSNativeContextSpecialization::AssumePrototypesStable(
std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) { std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) {
// Determine actual holder and perform prototype chain checks. // Determine actual holder and perform prototype chain checks.
......
...@@ -118,9 +118,6 @@ class JSNativeContextSpecialization final : public AdvancedReducer { ...@@ -118,9 +118,6 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
Node* BuildCheckMaps(Node* receiver, Node* effect, Node* control, Node* BuildCheckMaps(Node* receiver, Node* effect, Node* control,
std::vector<Handle<Map>> const& maps); std::vector<Handle<Map>> const& maps);
// Construct an appropriate heap object check.
Node* BuildCheckHeapObject(Node* receiver, Node* effect, Node* control);
// Adds stability dependencies on all prototypes of every class in // Adds stability dependencies on all prototypes of every class in
// {receiver_type} up to (and including) the {holder}. // {receiver_type} up to (and including) the {holder}.
void AssumePrototypesStable(std::vector<Handle<Map>> const& receiver_maps, void AssumePrototypesStable(std::vector<Handle<Map>> const& receiver_maps,
......
// Copyright 2016 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.
// Flags: --allow-natives-syntax
function g(v) { return v.constructor; }
g({});
g({});
function f() {
var i = 0;
do {
i = i + 1;
g(i);
} while (i < 1);
}
%OptimizeFunctionOnNextCall(f);
f();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment