From d029d76120ea36eecd51b3df775a6249d234c1e7 Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Mon, 20 Oct 2014 06:25:41 +0000 Subject: [PATCH] [turbofan] Skip bounds checks for positive indices only. TEST=unittests,mjsunit/asm/int32array-constant-key R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/647773004 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24716 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler/simplified-operator-reducer.cc | 4 +- test/mjsunit/asm/int32array-constant-key.js | 32 +++++- .../simplified-operator-reducer-unittest.cc | 113 ++++++++++++++++----- 3 files changed, 121 insertions(+), 28 deletions(-) diff --git a/src/compiler/simplified-operator-reducer.cc b/src/compiler/simplified-operator-reducer.cc index 49b87b2..21a18ea 100644 --- a/src/compiler/simplified-operator-reducer.cc +++ b/src/compiler/simplified-operator-reducer.cc @@ -106,7 +106,7 @@ Reduction SimplifiedOperatorReducer::Reduce(Node* node) { NumericValueMatcher mlength(node->InputAt(2)); if (mkey.HasValue() && mlength.HasValue()) { // Skip the typed array bounds check if key and length are constant. - if (mkey.Value() < mlength.Value()) { + if (mkey.Value() >= 0 && mkey.Value() < mlength.Value()) { access.bounds_check = kNoBoundsCheck; node->set_op(simplified()->LoadElement(access)); return Changed(node); @@ -122,7 +122,7 @@ Reduction SimplifiedOperatorReducer::Reduce(Node* node) { NumericValueMatcher mlength(node->InputAt(2)); if (mkey.HasValue() && mlength.HasValue()) { // Skip the typed array bounds check if key and length are constant. - if (mkey.Value() < mlength.Value()) { + if (mkey.Value() >= 0 && mkey.Value() < mlength.Value()) { access.bounds_check = kNoBoundsCheck; node->set_op(simplified()->StoreElement(access)); return Changed(node); diff --git a/test/mjsunit/asm/int32array-constant-key.js b/test/mjsunit/asm/int32array-constant-key.js index b1fbd26..bb5b650 100644 --- a/test/mjsunit/asm/int32array-constant-key.js +++ b/test/mjsunit/asm/int32array-constant-key.js @@ -5,28 +5,58 @@ function Module(stdlib, foreign, heap) { "use asm"; var MEM32 = new stdlib.Int32Array(heap); + function loadm4194304() { + return MEM32[-4194304]; + } + function loadm0() { + return MEM32[-0]; + } function load0() { return MEM32[0]; } function load4() { return MEM32[4]; } + function storem4194304(v) { + MEM32[-4194304] = v; + } + function storem0(v) { + MEM32[-0] = v; + } function store0(v) { MEM32[0] = v; } function store4(v) { MEM32[4] = v; } - return { load0: load0, store0: store0, load4: load4, store4: store4 }; + return { loadm4194304: loadm4194304, storem4194304: storem4194304, + loadm0: loadm0, storem0: storem0, load0: load0, store0: store0, + load4: load4, store4: store4 }; } var m = Module(this, {}, new ArrayBuffer(4)); +assertEquals(undefined, m.loadm4194304()); +assertEquals(0, m.loadm0()); assertEquals(0, m.load0()); assertEquals(undefined, m.load4()); +m.storem4194304(123456789); +assertEquals(undefined, m.loadm4194304()); +assertEquals(0, m.loadm0()); +assertEquals(0, m.load0()); +assertEquals(undefined, m.load4()); +m.storem0(987654321); +assertEquals(undefined, m.loadm4194304()); +assertEquals(987654321, m.loadm0()); +assertEquals(987654321, m.load0()); +assertEquals(undefined, m.load4()); m.store0(0x12345678); +assertEquals(undefined, m.loadm4194304()); +assertEquals(0x12345678, m.loadm0()); assertEquals(0x12345678, m.load0()); assertEquals(undefined, m.load4()); m.store4(43); +assertEquals(undefined, m.loadm4194304()); +assertEquals(0x12345678, m.loadm0()); assertEquals(0x12345678, m.load0()); assertEquals(undefined, m.load4()); diff --git a/test/unittests/compiler/simplified-operator-reducer-unittest.cc b/test/unittests/compiler/simplified-operator-reducer-unittest.cc index 694bdd8..3d342e3 100644 --- a/test/unittests/compiler/simplified-operator-reducer-unittest.cc +++ b/test/unittests/compiler/simplified-operator-reducer-unittest.cc @@ -490,18 +490,46 @@ TEST_F(SimplifiedOperatorReducerTest, LoadElementWithConstantKeyAndLength) { Node* const base = Parameter(0); Node* const effect = graph()->start(); Node* const control = graph()->start(); - TRACED_FOREACH(double, key, kFloat64Values) { - TRACED_FOREACH(int32_t, length, kInt32Values) { - if (key < length) { - Reduction r = Reduce(graph()->NewNode( - simplified()->LoadElement(access), base, NumberConstant(key), - Int32Constant(length), effect, control)); - ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), - IsLoadElement(access_nocheck, base, IsNumberConstant(key), - IsInt32Constant(length), effect, control)); - } - } + { + Node* const key = NumberConstant(-42.0); + Node* const length = NumberConstant(100.0); + Reduction r = Reduce(graph()->NewNode(simplified()->LoadElement(access), + base, key, length, effect, control)); + ASSERT_FALSE(r.Changed()); + } + { + Node* const key = NumberConstant(-0.0); + Node* const length = NumberConstant(1.0); + Reduction r = Reduce(graph()->NewNode(simplified()->LoadElement(access), + base, key, length, effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsLoadElement(access_nocheck, base, key, + length, effect, control)); + } + { + Node* const key = Int32Constant(0); + Node* const length = Int32Constant(1); + Reduction r = Reduce(graph()->NewNode(simplified()->LoadElement(access), + base, key, length, effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsLoadElement(access_nocheck, base, key, + length, effect, control)); + } + { + Node* const key = NumberConstant(42.2); + Node* const length = Int32Constant(128); + Reduction r = Reduce(graph()->NewNode(simplified()->LoadElement(access), + base, key, length, effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsLoadElement(access_nocheck, base, key, + length, effect, control)); + } + { + Node* const key = NumberConstant(39.2); + Node* const length = NumberConstant(32.0); + Reduction r = Reduce(graph()->NewNode(simplified()->LoadElement(access), + base, key, length, effect, control)); + ASSERT_FALSE(r.Changed()); } } @@ -519,19 +547,54 @@ TEST_F(SimplifiedOperatorReducerTest, StoreElementWithConstantKeyAndLength) { Node* const value = Parameter(1); Node* const effect = graph()->start(); Node* const control = graph()->start(); - TRACED_FOREACH(int32_t, key, kInt32Values) { - TRACED_FOREACH(double, length, kFloat64Values) { - if (key < length) { - Reduction r = Reduce(graph()->NewNode( - simplified()->StoreElement(access), base, Int32Constant(key), - NumberConstant(length), value, effect, control)); - ASSERT_TRUE(r.Changed()); - EXPECT_THAT( - r.replacement(), - IsStoreElement(access_nocheck, base, IsInt32Constant(key), - IsNumberConstant(length), value, effect, control)); - } - } + { + Node* const key = NumberConstant(-72.1); + Node* const length = NumberConstant(0.0); + Reduction r = + Reduce(graph()->NewNode(simplified()->StoreElement(access), base, key, + length, value, effect, control)); + ASSERT_FALSE(r.Changed()); + } + { + Node* const key = NumberConstant(-0.0); + Node* const length = Int32Constant(999); + Reduction r = + Reduce(graph()->NewNode(simplified()->StoreElement(access), base, key, + length, value, effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), + IsStoreElement(access_nocheck, base, key, length, value, effect, + control)); + } + { + Node* const key = Int32Constant(0); + Node* const length = Int32Constant(1); + Reduction r = + Reduce(graph()->NewNode(simplified()->StoreElement(access), base, key, + length, value, effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), + IsStoreElement(access_nocheck, base, key, length, value, effect, + control)); + } + { + Node* const key = NumberConstant(42.2); + Node* const length = Int32Constant(128); + Reduction r = + Reduce(graph()->NewNode(simplified()->StoreElement(access), base, key, + length, value, effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), + IsStoreElement(access_nocheck, base, key, length, value, effect, + control)); + } + { + Node* const key = NumberConstant(39.2); + Node* const length = NumberConstant(32.0); + Reduction r = + Reduce(graph()->NewNode(simplified()->StoreElement(access), base, key, + length, value, effect, control)); + ASSERT_FALSE(r.Changed()); } } -- 2.7.4