4142bc6bc1
In simplified numbering, we make sanity checks based on types (e.g., NumberSubtract should take numbers as inputs), but this can be violated if optimization passes make types less precise. In this CL, we fix load elimination to make sure that types are smaller in the store -> load elimination by taking an intersection of the load's type with the store value's type and inserting a guard with that type. Note that the load type comes from type feedback, so it can be disjoint from the stored value type (in that case, this must be dead code because the map chack for the load should prevent us from using the stored value). BUG=chromium:599412 LOG=n Review URL: https://codereview.chromium.org/1857133003 Cr-Commit-Position: refs/heads/master@{#35259}
78 lines
2.8 KiB
C++
78 lines
2.8 KiB
C++
// Copyright 2014 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.
|
|
|
|
#include "src/compiler/access-builder.h"
|
|
#include "src/compiler/load-elimination.h"
|
|
#include "src/compiler/simplified-operator.h"
|
|
#include "test/unittests/compiler/graph-unittest.h"
|
|
#include "test/unittests/compiler/node-test-utils.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace compiler {
|
|
|
|
class LoadEliminationTest : public TypedGraphTest {
|
|
public:
|
|
LoadEliminationTest()
|
|
: TypedGraphTest(3), common_(zone()), simplified_(zone()) {}
|
|
~LoadEliminationTest() override {}
|
|
|
|
protected:
|
|
Reduction Reduce(Node* node) {
|
|
// TODO(titzer): mock the GraphReducer here for better unit testing.
|
|
GraphReducer graph_reducer(zone(), graph());
|
|
LoadElimination reducer(&graph_reducer, graph(), common());
|
|
return reducer.Reduce(node);
|
|
}
|
|
|
|
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
|
|
CommonOperatorBuilder* common() { return &common_; }
|
|
|
|
private:
|
|
CommonOperatorBuilder common_;
|
|
SimplifiedOperatorBuilder simplified_;
|
|
};
|
|
|
|
|
|
TEST_F(LoadEliminationTest, LoadFieldWithStoreField) {
|
|
Node* object1 = Parameter(Type::Any(), 0);
|
|
Node* object2 = Parameter(Type::Any(), 1);
|
|
Node* value = Parameter(Type::Any(), 2);
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
|
|
FieldAccess access1 = AccessBuilder::ForContextSlot(42);
|
|
Node* store1 = graph()->NewNode(simplified()->StoreField(access1), object1,
|
|
value, effect, control);
|
|
Reduction r1 = Reduce(graph()->NewNode(simplified()->LoadField(access1),
|
|
object1, store1, control));
|
|
ASSERT_TRUE(r1.Changed());
|
|
EXPECT_EQ(value, r1.replacement());
|
|
|
|
FieldAccess access2 = AccessBuilder::ForMap();
|
|
Node* store2 = graph()->NewNode(simplified()->StoreField(access2), object1,
|
|
object2, store1, control);
|
|
Reduction r2 = Reduce(graph()->NewNode(simplified()->LoadField(access2),
|
|
object1, store2, control));
|
|
ASSERT_TRUE(r2.Changed());
|
|
EXPECT_EQ(object2, r2.replacement());
|
|
|
|
Node* store3 = graph()->NewNode(
|
|
simplified()->StoreBuffer(BufferAccess(kExternalInt8Array)), object2,
|
|
value, Int32Constant(10), object1, store2, control);
|
|
|
|
Reduction r3 = Reduce(graph()->NewNode(simplified()->LoadField(access1),
|
|
object2, store3, control));
|
|
ASSERT_FALSE(r3.Changed());
|
|
|
|
Reduction r4 = Reduce(graph()->NewNode(simplified()->LoadField(access1),
|
|
object1, store3, control));
|
|
ASSERT_TRUE(r4.Changed());
|
|
EXPECT_EQ(value, r4.replacement());
|
|
}
|
|
|
|
} // namespace compiler
|
|
} // namespace internal
|
|
} // namespace v8
|