diff --git a/include/v8config.h b/include/v8config.h index a8b54c18d8..24b0e5ff3e 100644 --- a/include/v8config.h +++ b/include/v8config.h @@ -183,6 +183,7 @@ // V8_HAS_BUILTIN_POPCOUNT - __builtin_popcount() supported // V8_HAS_BUILTIN_SADD_OVERFLOW - __builtin_sadd_overflow() supported // V8_HAS_BUILTIN_SSUB_OVERFLOW - __builtin_ssub_overflow() supported +// V8_HAS_BUILTIN_UADD_OVERFLOW - __builtin_uadd_overflow() supported // V8_HAS_DECLSPEC_ALIGN - __declspec(align(n)) supported // V8_HAS_DECLSPEC_DEPRECATED - __declspec(deprecated) supported // V8_HAS_DECLSPEC_NOINLINE - __declspec(noinline) supported @@ -221,6 +222,7 @@ # define V8_HAS_BUILTIN_POPCOUNT (__has_builtin(__builtin_popcount)) # define V8_HAS_BUILTIN_SADD_OVERFLOW (__has_builtin(__builtin_sadd_overflow)) # define V8_HAS_BUILTIN_SSUB_OVERFLOW (__has_builtin(__builtin_ssub_overflow)) +# define V8_HAS_BUILTIN_UADD_OVERFLOW (__has_builtin(__builtin_uadd_overflow)) # define V8_HAS_CXX11_ALIGNAS (__has_feature(cxx_alignas)) # define V8_HAS_CXX11_STATIC_ASSERT (__has_feature(cxx_static_assert)) diff --git a/src/base/bits.h b/src/base/bits.h index b237d62bcb..abcfd9a9ed 100644 --- a/src/base/bits.h +++ b/src/base/bits.h @@ -236,6 +236,19 @@ int32_t SignedDiv32(int32_t lhs, int32_t rhs); int32_t SignedMod32(int32_t lhs, int32_t rhs); +// UnsignedAddOverflow32(lhs,rhs,val) performs an unsigned summation of |lhs| +// and |rhs| and stores the result into the variable pointed to by |val| and +// returns true if the unsigned summation resulted in an overflow. +inline bool UnsignedAddOverflow32(uint32_t lhs, uint32_t rhs, uint32_t* val) { +#if V8_HAS_BUILTIN_SADD_OVERFLOW + return __builtin_uadd_overflow(lhs, rhs, val); +#else + *val = lhs + rhs; + return *val < (lhs | rhs); +#endif +} + + // UnsignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient // truncated to uint32. If |rhs| is zero, then zero is returned. inline uint32_t UnsignedDiv32(uint32_t lhs, uint32_t rhs) { diff --git a/src/compiler/graph-reducer.cc b/src/compiler/graph-reducer.cc index 2164d1e7c5..5435fb072c 100644 --- a/src/compiler/graph-reducer.cc +++ b/src/compiler/graph-reducer.cc @@ -140,7 +140,7 @@ void GraphReducer::ReduceTop() { } // Remember the max node id before reduction. - NodeId const max_id = graph()->NodeCount() - 1; + NodeId const max_id = static_cast(graph()->NodeCount() - 1); // All inputs should be visited or on stack. Apply reductions to node. Reduction reduction = Reduce(node); diff --git a/src/compiler/graph-reducer.h b/src/compiler/graph-reducer.h index 21e0a84b99..a8a907fa12 100644 --- a/src/compiler/graph-reducer.h +++ b/src/compiler/graph-reducer.h @@ -19,7 +19,7 @@ class Node; // NodeIds are identifying numbers for nodes that can be used to index auxiliary // out-of-line data associated with each node. -typedef int32_t NodeId; +typedef uint32_t NodeId; // Represents the result of trying to reduce a node in the graph. diff --git a/src/compiler/graph.cc b/src/compiler/graph.cc index 193861187b..07bf2ba44e 100644 --- a/src/compiler/graph.cc +++ b/src/compiler/graph.cc @@ -53,7 +53,7 @@ Node* Graph::NewNode(const Operator* op, int input_count, Node** inputs, NodeId Graph::NextNodeId() { NodeId const id = next_node_id_; - CHECK(!base::bits::SignedAddOverflow32(id, 1, &next_node_id_)); + CHECK(!base::bits::UnsignedAddOverflow32(id, 1, &next_node_id_)); return id; } diff --git a/src/compiler/graph.h b/src/compiler/graph.h index 0b1277ca1d..50da168493 100644 --- a/src/compiler/graph.h +++ b/src/compiler/graph.h @@ -26,7 +26,7 @@ typedef uint32_t Mark; // NodeIds are identifying numbers for nodes that can be used to index auxiliary // out-of-line data associated with each node. -typedef int32_t NodeId; +typedef uint32_t NodeId; class Graph : public ZoneObject { @@ -90,7 +90,7 @@ class Graph : public ZoneObject { void SetStart(Node* start) { start_ = start; } void SetEnd(Node* end) { end_ = end; } - int NodeCount() const { return next_node_id_; } + size_t NodeCount() const { return next_node_id_; } void Decorate(Node* node, bool incomplete); void AddDecorator(GraphDecorator* decorator); diff --git a/src/compiler/loop-analysis.h b/src/compiler/loop-analysis.h index 77c2a95928..1a06b666dd 100644 --- a/src/compiler/loop-analysis.h +++ b/src/compiler/loop-analysis.h @@ -63,8 +63,7 @@ class LoopTree : public ZoneObject { // Return the innermost nested loop, if any, that contains {node}. Loop* ContainingLoop(Node* node) { - if (node->id() >= static_cast(node_to_loop_num_.size())) - return nullptr; + if (node->id() >= node_to_loop_num_.size()) return nullptr; int num = node_to_loop_num_[node->id()]; return num > 0 ? &all_loops_[num - 1] : nullptr; } diff --git a/src/compiler/node.h b/src/compiler/node.h index 16b2aeeb1c..08b775c1ff 100644 --- a/src/compiler/node.h +++ b/src/compiler/node.h @@ -27,7 +27,7 @@ typedef uint32_t Mark; // NodeIds are identifying numbers for nodes that can be used to index auxiliary // out-of-line data associated with each node. -typedef int32_t NodeId; +typedef uint32_t NodeId; // A Node is the basic primitive of graphs. Nodes are chained together by diff --git a/src/compiler/osr.cc b/src/compiler/osr.cc index 81b97bb629..4d8583bdc1 100644 --- a/src/compiler/osr.cc +++ b/src/compiler/osr.cc @@ -44,7 +44,7 @@ static void PeelOuterLoopsForOsr(Graph* graph, CommonOperatorBuilder* common, Zone* tmp_zone, Node* dead, LoopTree* loop_tree, LoopTree::Loop* osr_loop, Node* osr_normal_entry, Node* osr_loop_entry) { - const int original_count = graph->NodeCount(); + const size_t original_count = graph->NodeCount(); AllNodes all(tmp_zone, graph); NodeVector tmp_inputs(tmp_zone); Node* sentinel = graph->NewNode(dead->op()); diff --git a/src/compiler/schedule.cc b/src/compiler/schedule.cc index adb80a7b08..69ece96d4e 100644 --- a/src/compiler/schedule.cc +++ b/src/compiler/schedule.cc @@ -145,8 +145,7 @@ BasicBlock* Schedule::block(Node* node) const { bool Schedule::IsScheduled(Node* node) { - int length = static_cast(nodeid_to_block_.size()); - if (node->id() >= length) return false; + if (node->id() >= nodeid_to_block_.size()) return false; return nodeid_to_block_[node->id()] != NULL; } @@ -324,8 +323,7 @@ void Schedule::SetControlInput(BasicBlock* block, Node* node) { void Schedule::SetBlockForNode(BasicBlock* block, Node* node) { - int length = static_cast(nodeid_to_block_.size()); - if (node->id() >= length) { + if (node->id() >= nodeid_to_block_.size()) { nodeid_to_block_.resize(node->id() + 1); } nodeid_to_block_[node->id()] = block; diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index 482a283e85..825de35aa5 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -1085,7 +1085,7 @@ class RepresentationSelector { private: JSGraph* jsgraph_; - int count_; // number of nodes in the graph + size_t const count_; // number of nodes in the graph NodeInfo* info_; // node id -> usage information NodeVector nodes_; // collected nodes NodeVector replacements_; // replacements to be done after lowering diff --git a/test/cctest/compiler/test-js-constant-cache.cc b/test/cctest/compiler/test-js-constant-cache.cc index fa2614cd14..175047f170 100644 --- a/test/cctest/compiler/test-js-constant-cache.cc +++ b/test/cctest/compiler/test-js-constant-cache.cc @@ -335,7 +335,7 @@ TEST(JSGraph_GetCachedNodes_int32) { 25, 15, 30, 31, 45, 46, 47, 48}; for (size_t i = 0; i < arraysize(constants); i++) { - int count_before = T.graph()->NodeCount(); + size_t count_before = T.graph()->NodeCount(); NodeVector nodes_before(T.main_zone()); T.GetCachedNodes(&nodes_before); Node* n = T.Int32Constant(constants[i]); @@ -357,7 +357,7 @@ TEST(JSGraph_GetCachedNodes_float64) { 11, 11, -33.3, -33.3, -22, -11}; for (size_t i = 0; i < arraysize(constants); i++) { - int count_before = T.graph()->NodeCount(); + size_t count_before = T.graph()->NodeCount(); NodeVector nodes_before(T.main_zone()); T.GetCachedNodes(&nodes_before); Node* n = T.Float64Constant(constants[i]); @@ -379,7 +379,7 @@ TEST(JSGraph_GetCachedNodes_int64) { 19, 20, 20, 21, 21, 22, 23, 24, 25}; for (size_t i = 0; i < arraysize(constants); i++) { - int count_before = T.graph()->NodeCount(); + size_t count_before = T.graph()->NodeCount(); NodeVector nodes_before(T.main_zone()); T.GetCachedNodes(&nodes_before); Node* n = T.Int64Constant(constants[i]); @@ -401,7 +401,7 @@ TEST(JSGraph_GetCachedNodes_number) { 11, 11, -33.3, -33.3, -22, -11}; for (size_t i = 0; i < arraysize(constants); i++) { - int count_before = T.graph()->NodeCount(); + size_t count_before = T.graph()->NodeCount(); NodeVector nodes_before(T.main_zone()); T.GetCachedNodes(&nodes_before); Node* n = T.Constant(constants[i]); @@ -428,7 +428,7 @@ TEST(JSGraph_GetCachedNodes_external) { ExternalReference::address_of_one_half()}; for (size_t i = 0; i < arraysize(constants); i++) { - int count_before = T.graph()->NodeCount(); + size_t count_before = T.graph()->NodeCount(); NodeVector nodes_before(T.main_zone()); T.GetCachedNodes(&nodes_before); Node* n = T.ExternalConstant(constants[i]); diff --git a/test/unittests/base/bits-unittest.cc b/test/unittests/base/bits-unittest.cc index 9caba8484e..3d17a050db 100644 --- a/test/unittests/base/bits-unittest.cc +++ b/test/unittests/base/bits-unittest.cc @@ -255,6 +255,25 @@ TEST(Bits, SignedMod32) { } +TEST(Bits, UnsignedAddOverflow32) { + uint32_t val = 0; + EXPECT_FALSE(UnsignedAddOverflow32(0, 0, &val)); + EXPECT_EQ(0u, val); + EXPECT_TRUE( + UnsignedAddOverflow32(std::numeric_limits::max(), 1u, &val)); + EXPECT_EQ(std::numeric_limits::min(), val); + EXPECT_TRUE(UnsignedAddOverflow32(std::numeric_limits::max(), + std::numeric_limits::max(), + &val)); + TRACED_FORRANGE(uint32_t, i, 1, 50) { + TRACED_FORRANGE(uint32_t, j, 1, i) { + EXPECT_FALSE(UnsignedAddOverflow32(i, j, &val)); + EXPECT_EQ(i + j, val); + } + } +} + + TEST(Bits, UnsignedDiv32) { TRACED_FORRANGE(uint32_t, i, 0, 50) { EXPECT_EQ(0u, UnsignedDiv32(i, 0)); diff --git a/test/unittests/compiler/control-equivalence-unittest.cc b/test/unittests/compiler/control-equivalence-unittest.cc index f420883c27..47be5407f7 100644 --- a/test/unittests/compiler/control-equivalence-unittest.cc +++ b/test/unittests/compiler/control-equivalence-unittest.cc @@ -41,7 +41,7 @@ class ControlEquivalenceTest : public GraphTest { } bool IsEquivalenceClass(size_t length, Node** nodes) { - BitVector in_class(graph()->NodeCount(), zone()); + BitVector in_class(static_cast(graph()->NodeCount()), zone()); size_t expected_class = classes_[nodes[0]->id()]; for (size_t i = 0; i < length; ++i) { in_class.Add(nodes[i]->id()); diff --git a/test/unittests/compiler/graph-reducer-unittest.cc b/test/unittests/compiler/graph-reducer-unittest.cc index 06befae59e..8b95872a7b 100644 --- a/test/unittests/compiler/graph-reducer-unittest.cc +++ b/test/unittests/compiler/graph-reducer-unittest.cc @@ -524,7 +524,7 @@ TEST_F(GraphReducerTest, ReduceInPlace1) { // Tests A* => B* with in-place updates. InPlaceABReducer r; for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpB0, n1->op()); @@ -544,7 +544,7 @@ TEST_F(GraphReducerTest, ReduceInPlace2) { // Tests A* => B* with in-place updates. InPlaceABReducer r; for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpB0, n1->op()); @@ -569,7 +569,7 @@ TEST_F(GraphReducerTest, ReduceNew1) { NewABReducer r(graph()); // Tests A* => B* while creating new nodes. for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); if (i == 0) { EXPECT_NE(before, graph()->NodeCount()); @@ -643,7 +643,7 @@ TEST_F(GraphReducerTest, Forwarding1) { // Tests A1(x) => x for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpA0, n1->op()); @@ -663,7 +663,7 @@ TEST_F(GraphReducerTest, Forwarding2) { // Tests reducing A2(A1(x), A1(y)) => A2(x, y). for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpA0, n1->op()); @@ -688,8 +688,8 @@ TEST_F(GraphReducerTest, Forwarding3) { A1Forwarder r; - for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + for (size_t i = 0; i < 3; i++) { + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpA0, n1->op()); @@ -710,8 +710,8 @@ TEST_F(GraphReducerTest, ReduceForward1) { B1Forwarder f; // Tests first reducing A => B, then B1(x) => x. - for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + for (size_t i = 0; i < 3; i++) { + size_t before = graph()->NodeCount(); ReduceGraph(&r, &f); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpB0, n1->op()); @@ -743,7 +743,7 @@ TEST_F(GraphReducerTest, Sorter1) { graph()->SetEnd(end); - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpA0, n1->op()); @@ -838,8 +838,8 @@ TEST_F(GraphReducerTest, Order) { InPlaceBCReducer bcr; // Tests A* => C* with in-place updates. - for (int j = 0; j < 3; j++) { - int before = graph()->NodeCount(); + for (size_t j = 0; j < 3; j++) { + size_t before = graph()->NodeCount(); if (i == 0) { ReduceGraph(&abr, &bcr); } else { diff --git a/test/unittests/compiler/graph-unittest.cc b/test/unittests/compiler/graph-unittest.cc index d2ab3c3a26..c7c79b44f4 100644 --- a/test/unittests/compiler/graph-unittest.cc +++ b/test/unittests/compiler/graph-unittest.cc @@ -136,8 +136,8 @@ TEST_F(GraphTest, NewNode) { Node* n0 = graph()->NewNode(&kDummyOperator); Node* n1 = graph()->NewNode(&kDummyOperator); EXPECT_NE(n0, n1); - EXPECT_LT(0, n0->id()); - EXPECT_LT(0, n1->id()); + EXPECT_LT(0u, n0->id()); + EXPECT_LT(0u, n1->id()); EXPECT_NE(n0->id(), n1->id()); EXPECT_EQ(&kDummyOperator, n0->op()); EXPECT_EQ(&kDummyOperator, n1->op());