Add JSGraph::GetCachedNodes and NodeCache::GetCachedNodes. These routines are necessary in the dead code elimination phase to trim away uses from unreachable nodes.
R=bmeurer@chromium.org BUG= Review URL: https://codereview.chromium.org/656103002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24632 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
23868b419c
commit
754abff699
@ -41,6 +41,14 @@ class CommonNodeCache FINAL : public ZoneObject {
|
||||
|
||||
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_;
|
||||
Int64NodeCache int64_constants_;
|
||||
|
@ -191,6 +191,18 @@ Node* JSGraph::ExternalConstant(ExternalReference reference) {
|
||||
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
|
||||
} // namespace v8
|
||||
|
@ -103,12 +103,15 @@ class JSGraph : public ZoneObject {
|
||||
Zone* zone() { return graph()->zone(); }
|
||||
Isolate* isolate() { return zone()->isolate(); }
|
||||
|
||||
void GetCachedNodes(NodeVector* nodes);
|
||||
|
||||
private:
|
||||
Graph* graph_;
|
||||
CommonOperatorBuilder* common_;
|
||||
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_;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include "src/zone.h"
|
||||
#include "src/zone-containers.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -90,6 +91,15 @@ Node** NodeCache<Key, Hash, Pred>::Find(Zone* zone, Key key) {
|
||||
}
|
||||
|
||||
|
||||
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>;
|
||||
template class NodeCache<void*>;
|
||||
|
@ -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 @@ class NodeCache FINAL {
|
||||
// too full or encounters too many hash collisions.
|
||||
Node** Find(Zone* zone, Key key);
|
||||
|
||||
void GetCachedNodes(NodeVector* nodes);
|
||||
|
||||
private:
|
||||
enum { kInitialSize = 16u, kLinearProbe = 5u };
|
||||
|
||||
|
@ -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 @@ class JSCacheTesterHelper {
|
||||
};
|
||||
|
||||
|
||||
// TODO(dcarney): JSConstantCacheTester inherits from JSGraph???
|
||||
class JSConstantCacheTester : public HandleAndZoneScope,
|
||||
public JSCacheTesterHelper,
|
||||
public JSGraph {
|
||||
@ -293,3 +295,177 @@ TEST(OddballTypes) {
|
||||
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]));
|
||||
}
|
||||
}
|
||||
|
@ -158,3 +158,63 @@ TEST(PtrConstant_hits) {
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user