From 3df428bb927679eb4bde0247f05d4b52848ee92f Mon Sep 17 00:00:00 2001 From: "pan.deng" Date: Mon, 16 Jan 2017 19:12:08 -0800 Subject: [PATCH] [turbofan] A bug fix of loadElimination. KillFields of an object should remove its cache from all the fields. Currently, the cache in the front field is kept which is not expected. This patch fixes it. Review-Url: https://codereview.chromium.org/2618273002 Cr-Commit-Position: refs/heads/master@{#42388} --- src/compiler/load-elimination.cc | 2 +- .../compiler/load-elimination-unittest.cc | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/compiler/load-elimination.cc b/src/compiler/load-elimination.cc index f55ce2a2bd..6c2935f7ca 100644 --- a/src/compiler/load-elimination.cc +++ b/src/compiler/load-elimination.cc @@ -535,7 +535,7 @@ LoadElimination::AbstractState::KillFields(Node* object, Zone* zone) const { AbstractField const* that_field = this_field->Kill(object, zone); if (that_field != this_field) { AbstractState* that = new (zone) AbstractState(*this); - that->fields_[i] = this_field; + that->fields_[i] = that_field; while (++i < arraysize(fields_)) { if (this->fields_[i] != nullptr) { that->fields_[i] = this->fields_[i]->Kill(object, zone); diff --git a/test/unittests/compiler/load-elimination-unittest.cc b/test/unittests/compiler/load-elimination-unittest.cc index 22e843aa36..8d34fb9699 100644 --- a/test/unittests/compiler/load-elimination-unittest.cc +++ b/test/unittests/compiler/load-elimination-unittest.cc @@ -174,6 +174,46 @@ TEST_F(LoadEliminationTest, StoreFieldAndLoadField) { EXPECT_EQ(value, r.replacement()); } +TEST_F(LoadEliminationTest, StoreFieldAndKillFields) { + Node* object = Parameter(Type::Any(), 0); + Node* value = Parameter(Type::Any(), 1); + Node* effect = graph()->start(); + Node* control = graph()->start(); + + FieldAccess access1 = {kTaggedBase, kPointerSize, + MaybeHandle(), MaybeHandle(), + Type::Any(), MachineType::AnyTagged(), + kNoWriteBarrier}; + + // Offset that out of field cache size. + FieldAccess access2 = {kTaggedBase, 2048 * kPointerSize, + MaybeHandle(), MaybeHandle(), + Type::Any(), MachineType::AnyTagged(), + kNoWriteBarrier}; + + StrictMock editor; + LoadElimination load_elimination(&editor, jsgraph(), zone()); + + load_elimination.Reduce(graph()->start()); + + Node* store1 = effect = graph()->NewNode(simplified()->StoreField(access1), + object, value, effect, control); + load_elimination.Reduce(store1); + + // Invalidate caches of object. + Node* store2 = effect = graph()->NewNode(simplified()->StoreField(access2), + object, value, effect, control); + load_elimination.Reduce(store2); + + Node* store3 = graph()->NewNode(simplified()->StoreField(access1), + object, value, effect, control); + + Reduction r = load_elimination.Reduce(store3); + + // store3 shall not be replaced, since caches were invalidated. + EXPECT_EQ(store3, r.replacement()); +} + TEST_F(LoadEliminationTest, StoreFieldAndStoreElementAndLoadField) { Node* object = Parameter(Type::Any(), 0); Node* value = Parameter(Type::Any(), 1);