Revision: 24632
Author:   [email protected]
Date:     Wed Oct 15 12:29:39 2014 UTC
Log: Add JSGraph::GetCachedNodes and NodeCache::GetCachedNodes. These routines are necessary in the dead code elimination phase to trim away uses from unreachable nodes.

[email protected]
BUG=

Review URL: https://codereview.chromium.org/656103002
https://code.google.com/p/v8/source/detail?r=24632

Modified:
 /branches/bleeding_edge/src/compiler/common-node-cache.h
 /branches/bleeding_edge/src/compiler/js-graph.cc
 /branches/bleeding_edge/src/compiler/js-graph.h
 /branches/bleeding_edge/src/compiler/node-cache.cc
 /branches/bleeding_edge/src/compiler/node-cache.h
 /branches/bleeding_edge/test/cctest/compiler/test-js-constant-cache.cc
 /branches/bleeding_edge/test/cctest/compiler/test-node-cache.cc

=======================================
--- /branches/bleeding_edge/src/compiler/common-node-cache.h Mon Oct 13 09:17:33 2014 UTC +++ /branches/bleeding_edge/src/compiler/common-node-cache.h Wed Oct 15 12:29:39 2014 UTC
@@ -40,6 +40,14 @@
   }

   Zone* zone() const { return zone_; }
+
+  void GetCachedNodes(NodeVector* nodes) {
+    int32_constants_.GetCachedNodes(nodes);
+    int64_constants_.GetCachedNodes(nodes);
+    float64_constants_.GetCachedNodes(nodes);
+    external_constants_.GetCachedNodes(nodes);
+    number_constants_.GetCachedNodes(nodes);
+  }

  private:
   Int32NodeCache int32_constants_;
=======================================
--- /branches/bleeding_edge/src/compiler/js-graph.cc Wed Oct 15 11:38:04 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-graph.cc Wed Oct 15 12:29:39 2014 UTC
@@ -190,6 +190,18 @@
   }
   return *loc;
 }
+
+
+void JSGraph::GetCachedNodes(NodeVector* nodes) {
+  cache_.GetCachedNodes(nodes);
+  SetOncePointer<Node>* ptrs[] = {
+      &c_entry_stub_constant_, &undefined_constant_, &the_hole_constant_,
+      &true_constant_,         &false_constant_,     &null_constant_,
+      &zero_constant_,         &one_constant_,       &nan_constant_};
+  for (size_t i = 0; i < arraysize(ptrs); i++) {
+    if (ptrs[i]->is_set()) nodes->push_back(ptrs[i]->get());
+  }
+}

 }  // namespace compiler
 }  // namespace internal
=======================================
--- /branches/bleeding_edge/src/compiler/js-graph.h Wed Oct 15 11:38:04 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-graph.h Wed Oct 15 12:29:39 2014 UTC
@@ -102,6 +102,8 @@
   Graph* graph() { return graph_; }
   Zone* zone() { return graph()->zone(); }
   Isolate* isolate() { return zone()->isolate(); }
+
+  void GetCachedNodes(NodeVector* nodes);

  private:
   Graph* graph_;
@@ -109,6 +111,7 @@
   JSOperatorBuilder* javascript_;
   MachineOperatorBuilder* machine_;

+  // TODO(titzer): make this into a simple array.
   SetOncePointer<Node> c_entry_stub_constant_;
   SetOncePointer<Node> undefined_constant_;
   SetOncePointer<Node> the_hole_constant_;
=======================================
--- /branches/bleeding_edge/src/compiler/node-cache.cc Mon Oct 6 12:27:24 2014 UTC +++ /branches/bleeding_edge/src/compiler/node-cache.cc Wed Oct 15 12:29:39 2014 UTC
@@ -7,6 +7,7 @@
 #include <cstring>

 #include "src/zone.h"
+#include "src/zone-containers.h"

 namespace v8 {
 namespace internal {
@@ -89,6 +90,15 @@
   return &entry->value_;
 }

+
+template <typename Key, typename Hash, typename Pred>
+void NodeCache<Key, Hash, Pred>::GetCachedNodes(NodeVector* nodes) {
+  if (entries_) {
+    for (size_t i = 0; i < size_; i++) {
+      if (entries_[i].value_ != NULL) nodes->push_back(entries_[i].value_);
+    }
+  }
+}

 template class NodeCache<int64_t>;
 template class NodeCache<int32_t>;
=======================================
--- /branches/bleeding_edge/src/compiler/node-cache.h Mon Oct 6 12:27:24 2014 UTC +++ /branches/bleeding_edge/src/compiler/node-cache.h Wed Oct 15 12:29:39 2014 UTC
@@ -7,20 +7,12 @@

 #include "src/base/functional.h"
 #include "src/base/macros.h"
+#include "src/compiler/node.h"

 namespace v8 {
 namespace internal {
-
-// Forward declarations.
-class Zone;
-
-
 namespace compiler {

-// Forward declarations.
-class Node;
-
-
// A cache for nodes based on a key. Useful for implementing canonicalization of
 // nodes such as constants, parameters, etc.
 template <typename Key, typename Hash = base::hash<Key>,
@@ -39,6 +31,8 @@
   // too full or encounters too many hash collisions.
   Node** Find(Zone* zone, Key key);

+  void GetCachedNodes(NodeVector* nodes);
+
  private:
   enum { kInitialSize = 16u, kLinearProbe = 5u };

=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-js-constant-cache.cc Wed Oct 15 11:38:04 2014 UTC +++ /branches/bleeding_edge/test/cctest/compiler/test-js-constant-cache.cc Wed Oct 15 12:29:39 2014 UTC
@@ -4,6 +4,7 @@

 #include "src/v8.h"

+#include "src/assembler.h"
 #include "src/compiler/js-graph.h"
 #include "src/compiler/node-properties-inl.h"
 #include "src/compiler/typer.h"
@@ -30,6 +31,7 @@
 };


+// TODO(dcarney): JSConstantCacheTester inherits from JSGraph???
 class JSConstantCacheTester : public HandleAndZoneScope,
                               public JSCacheTesterHelper,
                               public JSGraph {
@@ -293,3 +295,177 @@
 TEST(ExternalReferences) {
   // TODO(titzer): test canonicalization of external references.
 }
+
+
+static bool Contains(NodeVector* nodes, Node* n) {
+  for (size_t i = 0; i < nodes->size(); i++) {
+    if (nodes->at(i) == n) return true;
+  }
+  return false;
+}
+
+
+static void CheckGetCachedNodesContains(JSConstantCacheTester* T, Node* n) {
+  NodeVector nodes(T->main_zone());
+  T->GetCachedNodes(&nodes);
+  CHECK(Contains(&nodes, n));
+}
+
+
+TEST(JSGraph_GetCachedNodes1) {
+  JSConstantCacheTester T;
+  CheckGetCachedNodesContains(&T, T.TrueConstant());
+  CheckGetCachedNodesContains(&T, T.UndefinedConstant());
+  CheckGetCachedNodesContains(&T, T.TheHoleConstant());
+  CheckGetCachedNodesContains(&T, T.TrueConstant());
+  CheckGetCachedNodesContains(&T, T.FalseConstant());
+  CheckGetCachedNodesContains(&T, T.NullConstant());
+  CheckGetCachedNodesContains(&T, T.ZeroConstant());
+  CheckGetCachedNodesContains(&T, T.OneConstant());
+  CheckGetCachedNodesContains(&T, T.NaNConstant());
+}
+
+
+TEST(JSGraph_GetCachedNodes_int32) {
+  JSConstantCacheTester T;
+
+  int32_t constants[] = {0, 11, 12, 13, 14, 55, -55, -44, -33, -22, -11,
+                         0, 11, 11, 12, 12, 11, 11,  -33, -33, -22, -11};
+
+  for (size_t i = 0; i < arraysize(constants); i++) {
+    int count_before = T.graph()->NodeCount();
+    NodeVector nodes_before(T.main_zone());
+    T.GetCachedNodes(&nodes_before);
+    Node* n = T.Int32Constant(constants[i]);
+    if (n->id() < count_before) {
+      // An old ID indicates a cached node. It should have been in the set.
+      CHECK(Contains(&nodes_before, n));
+    }
+    // Old or new, it should be in the cached set afterwards.
+    CheckGetCachedNodesContains(&T, n);
+  }
+}
+
+
+TEST(JSGraph_GetCachedNodes_float64) {
+  JSConstantCacheTester T;
+
+  double constants[] = {0,   11.1, 12.2,  13,    14,   55.5, -55.5, -44.4,
+                        -33, -22,  -11,   0,     11.1, 11.1, 12.3,  12.3,
+                        11,  11,   -33.3, -33.3, -22,  -11};
+
+  for (size_t i = 0; i < arraysize(constants); i++) {
+    int count_before = T.graph()->NodeCount();
+    NodeVector nodes_before(T.main_zone());
+    T.GetCachedNodes(&nodes_before);
+    Node* n = T.Float64Constant(constants[i]);
+    if (n->id() < count_before) {
+      // An old ID indicates a cached node. It should have been in the set.
+      CHECK(Contains(&nodes_before, n));
+    }
+    // Old or new, it should be in the cached set afterwards.
+    CheckGetCachedNodesContains(&T, n);
+  }
+}
+
+
+TEST(JSGraph_GetCachedNodes_int64) {
+  JSConstantCacheTester T;
+
+  int32_t constants[] = {0, 11, 12, 13, 14, 55, -55, -44, -33, -22, -11,
+                         0, 11, 11, 12, 12, 11, 11,  -33, -33, -22, -11};
+
+  for (size_t i = 0; i < arraysize(constants); i++) {
+    int count_before = T.graph()->NodeCount();
+    NodeVector nodes_before(T.main_zone());
+    T.GetCachedNodes(&nodes_before);
+    Node* n = T.Int64Constant(constants[i]);
+    if (n->id() < count_before) {
+      // An old ID indicates a cached node. It should have been in the set.
+      CHECK(Contains(&nodes_before, n));
+    }
+    // Old or new, it should be in the cached set afterwards.
+    CheckGetCachedNodesContains(&T, n);
+  }
+}
+
+
+TEST(JSGraph_GetCachedNodes_number) {
+  JSConstantCacheTester T;
+
+  double constants[] = {0,   11.1, 12.2,  13,    14,   55.5, -55.5, -44.4,
+                        -33, -22,  -11,   0,     11.1, 11.1, 12.3,  12.3,
+                        11,  11,   -33.3, -33.3, -22,  -11};
+
+  for (size_t i = 0; i < arraysize(constants); i++) {
+    int count_before = T.graph()->NodeCount();
+    NodeVector nodes_before(T.main_zone());
+    T.GetCachedNodes(&nodes_before);
+    Node* n = T.Constant(constants[i]);
+    if (n->id() < count_before) {
+      // An old ID indicates a cached node. It should have been in the set.
+      CHECK(Contains(&nodes_before, n));
+    }
+    // Old or new, it should be in the cached set afterwards.
+    CheckGetCachedNodesContains(&T, n);
+  }
+}
+
+
+TEST(JSGraph_GetCachedNodes_external) {
+  JSConstantCacheTester T;
+
+  ExternalReference constants[] = {ExternalReference::address_of_min_int(),
+                                   ExternalReference::address_of_min_int(),
+                                   ExternalReference::address_of_min_int(),
+ ExternalReference::address_of_one_half(), + ExternalReference::address_of_one_half(),
+                                   ExternalReference::address_of_min_int(),
+ ExternalReference::address_of_the_hole_nan(), + ExternalReference::address_of_one_half()};
+
+  for (size_t i = 0; i < arraysize(constants); i++) {
+    int count_before = T.graph()->NodeCount();
+    NodeVector nodes_before(T.main_zone());
+    T.GetCachedNodes(&nodes_before);
+    Node* n = T.ExternalConstant(constants[i]);
+    if (n->id() < count_before) {
+      // An old ID indicates a cached node. It should have been in the set.
+      CHECK(Contains(&nodes_before, n));
+    }
+    // Old or new, it should be in the cached set afterwards.
+    CheckGetCachedNodesContains(&T, n);
+  }
+}
+
+
+TEST(JSGraph_GetCachedNodes_together) {
+  JSConstantCacheTester T;
+
+  Node* constants[] = {
+      T.TrueConstant(),
+      T.UndefinedConstant(),
+      T.TheHoleConstant(),
+      T.TrueConstant(),
+      T.FalseConstant(),
+      T.NullConstant(),
+      T.ZeroConstant(),
+      T.OneConstant(),
+      T.NaNConstant(),
+      T.Int32Constant(0),
+      T.Int32Constant(1),
+      T.Int64Constant(-2),
+      T.Int64Constant(-4),
+      T.Float64Constant(0.9),
+      T.Float64Constant(V8_INFINITY),
+      T.Constant(0.99),
+      T.Constant(1.11),
+      T.ExternalConstant(ExternalReference::address_of_one_half())};
+
+  NodeVector nodes(T.main_zone());
+  T.GetCachedNodes(&nodes);
+
+  for (size_t i = 0; i < arraysize(constants); i++) {
+    CHECK(Contains(&nodes, constants[i]));
+  }
+}
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-node-cache.cc Tue Aug 26 09:19:24 2014 UTC +++ /branches/bleeding_edge/test/cctest/compiler/test-node-cache.cc Wed Oct 15 12:29:39 2014 UTC
@@ -158,3 +158,63 @@
   }
   CHECK_LT(4, hits);
 }
+
+
+static bool Contains(NodeVector* nodes, Node* n) {
+  for (size_t i = 0; i < nodes->size(); i++) {
+    if (nodes->at(i) == n) return true;
+  }
+  return false;
+}
+
+
+TEST(NodeCache_GetCachedNodes_int32) {
+  GraphTester graph;
+  Int32NodeCache cache;
+  CommonOperatorBuilder common(graph.zone());
+
+ int32_t constants[] = {0, 311, 12, 13, 14, 555, -555, -44, -33, -22, -11, + 0, 311, 311, 412, 412, 11, 11, -33, -33, -22, -11};
+
+  for (size_t i = 0; i < arraysize(constants); i++) {
+    int32_t k = constants[i];
+    Node** pos = cache.Find(graph.zone(), k);
+    if (*pos != NULL) {
+      NodeVector nodes(graph.zone());
+      cache.GetCachedNodes(&nodes);
+      CHECK(Contains(&nodes, *pos));
+    } else {
+      NodeVector nodes(graph.zone());
+      Node* n = graph.NewNode(common.Int32Constant(k));
+      *pos = n;
+      cache.GetCachedNodes(&nodes);
+      CHECK(Contains(&nodes, n));
+    }
+  }
+}
+
+
+TEST(NodeCache_GetCachedNodes_int64) {
+  GraphTester graph;
+  Int64NodeCache cache;
+  CommonOperatorBuilder common(graph.zone());
+
+ int64_t constants[] = {0, 311, 12, 13, 14, 555, -555, -44, -33, -22, -11, + 0, 311, 311, 412, 412, 11, 11, -33, -33, -22, -11};
+
+  for (size_t i = 0; i < arraysize(constants); i++) {
+    int64_t k = constants[i];
+    Node** pos = cache.Find(graph.zone(), k);
+    if (*pos != NULL) {
+      NodeVector nodes(graph.zone());
+      cache.GetCachedNodes(&nodes);
+      CHECK(Contains(&nodes, *pos));
+    } else {
+      NodeVector nodes(graph.zone());
+      Node* n = graph.NewNode(common.Int64Constant(k));
+      *pos = n;
+      cache.GetCachedNodes(&nodes);
+      CHECK(Contains(&nodes, n));
+    }
+  }
+}

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to