Commit 318e5230 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[turbofan] Handle LoadField with type mismatch in LoadElimination.

This allows to replace redundant LoadField's whose type doesn't match
the type of the replacement, by just turning those LoadField's into
TypeGuard's.

Bug: v8:8070
Change-Id: Ia329bb536f8829be27e070e90e9eaae0618dac7a
Reviewed-on: https://chromium-review.googlesource.com/1188131Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55407}
parent a839bd42
...@@ -912,8 +912,9 @@ Reduction LoadElimination::ReduceTransitionAndStoreElement(Node* node) { ...@@ -912,8 +912,9 @@ Reduction LoadElimination::ReduceTransitionAndStoreElement(Node* node) {
Reduction LoadElimination::ReduceLoadField(Node* node) { Reduction LoadElimination::ReduceLoadField(Node* node) {
FieldAccess const& access = FieldAccessOf(node->op()); FieldAccess const& access = FieldAccessOf(node->op());
Node* const object = NodeProperties::GetValueInput(node, 0); Node* object = NodeProperties::GetValueInput(node, 0);
Node* const effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
AbstractState const* state = node_states_.Get(effect); AbstractState const* state = node_states_.Get(effect);
if (state == nullptr) return NoChange(); if (state == nullptr) return NoChange();
if (access.offset == HeapObject::kMapOffset && if (access.offset == HeapObject::kMapOffset &&
...@@ -931,12 +932,19 @@ Reduction LoadElimination::ReduceLoadField(Node* node) { ...@@ -931,12 +932,19 @@ Reduction LoadElimination::ReduceLoadField(Node* node) {
if (field_index >= 0) { if (field_index >= 0) {
if (Node* replacement = state->LookupField(object, field_index)) { if (Node* replacement = state->LookupField(object, field_index)) {
// Make sure we don't resurrect dead {replacement} nodes. // Make sure we don't resurrect dead {replacement} nodes.
// Skip lowering if the type of the {replacement} node is not a subtype if (!replacement->IsDead()) {
// of the original {node}'s type. // Introduce a TypeGuard if the type of the {replacement} node is not
// TODO(tebbi): We should insert a {TypeGuard} for the intersection of // a subtype of the original {node}'s type.
// these two types here once we properly handle {Type::None} everywhere. if (!NodeProperties::GetType(replacement)
if (!replacement->IsDead() && NodeProperties::GetType(replacement) .Is(NodeProperties::GetType(node))) {
.Is(NodeProperties::GetType(node))) { Type replacement_type = Type::Intersect(
NodeProperties::GetType(node),
NodeProperties::GetType(replacement), graph()->zone());
replacement = effect =
graph()->NewNode(common()->TypeGuard(replacement_type),
replacement, effect, control);
NodeProperties::SetType(replacement, replacement_type);
}
ReplaceWithValue(node, replacement, effect); ReplaceWithValue(node, replacement, effect);
return Replace(replacement); return Replace(replacement);
} }
......
...@@ -410,9 +410,10 @@ TEST_F(LoadEliminationTest, LoadFieldWithTypeMismatch) { ...@@ -410,9 +410,10 @@ TEST_F(LoadEliminationTest, LoadFieldWithTypeMismatch) {
Node* load = graph()->NewNode(simplified()->LoadField(access), object, effect, Node* load = graph()->NewNode(simplified()->LoadField(access), object, effect,
control); control);
EXPECT_CALL(editor, ReplaceWithValue(load, IsTypeGuard(value, _), _, _));
Reduction r = load_elimination.Reduce(load); Reduction r = load_elimination.Reduce(load);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_EQ(load, r.replacement()); EXPECT_THAT(r.replacement(), IsTypeGuard(value, _));
} }
TEST_F(LoadEliminationTest, LoadElementWithTypeMismatch) { TEST_F(LoadEliminationTest, LoadElementWithTypeMismatch) {
......
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