Commit 4f9193e0 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Cache float32 constants on the JSGraph level.

Also slightly refactor the NodeCache and CommonNodeCache classes to
reduce inherent overhead of caching.

TEST=cctest

Review URL: https://codereview.chromium.org/822923002

Cr-Commit-Position: refs/heads/master@{#25937}
parent 9be7f79a
...@@ -489,6 +489,7 @@ source_set("v8_base") { ...@@ -489,6 +489,7 @@ source_set("v8_base") {
"src/compiler/code-generator-impl.h", "src/compiler/code-generator-impl.h",
"src/compiler/code-generator.cc", "src/compiler/code-generator.cc",
"src/compiler/code-generator.h", "src/compiler/code-generator.h",
"src/compiler/common-node-cache.cc",
"src/compiler/common-node-cache.h", "src/compiler/common-node-cache.h",
"src/compiler/common-operator-reducer.cc", "src/compiler/common-operator-reducer.cc",
"src/compiler/common-operator-reducer.h", "src/compiler/common-operator-reducer.h",
......
// 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/common-node-cache.h"
#include "src/assembler.h"
namespace v8 {
namespace internal {
namespace compiler {
Node** CommonNodeCache::FindExternalConstant(ExternalReference value) {
return external_constants_.Find(zone(), bit_cast<intptr_t>(value.address()));
}
void CommonNodeCache::GetCachedNodes(ZoneVector<Node*>* nodes) {
int32_constants_.GetCachedNodes(nodes);
int64_constants_.GetCachedNodes(nodes);
float32_constants_.GetCachedNodes(nodes);
float64_constants_.GetCachedNodes(nodes);
external_constants_.GetCachedNodes(nodes);
number_constants_.GetCachedNodes(nodes);
}
} // namespace compiler
} // namespace internal
} // namespace v8
...@@ -5,57 +5,63 @@ ...@@ -5,57 +5,63 @@
#ifndef V8_COMPILER_COMMON_NODE_CACHE_H_ #ifndef V8_COMPILER_COMMON_NODE_CACHE_H_
#define V8_COMPILER_COMMON_NODE_CACHE_H_ #define V8_COMPILER_COMMON_NODE_CACHE_H_
#include "src/assembler.h"
#include "src/compiler/node-cache.h" #include "src/compiler/node-cache.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
// Forward declarations.
class ExternalReference;
namespace compiler { namespace compiler {
// Bundles various caches for common nodes. // Bundles various caches for common nodes.
class CommonNodeCache FINAL : public ZoneObject { class CommonNodeCache FINAL {
public: public:
explicit CommonNodeCache(Zone* zone) : zone_(zone) {} explicit CommonNodeCache(Zone* zone) : zone_(zone) {}
~CommonNodeCache() {}
Node** FindInt32Constant(int32_t value) { Node** FindInt32Constant(int32_t value) {
return int32_constants_.Find(zone_, value); return int32_constants_.Find(zone(), value);
} }
Node** FindInt64Constant(int64_t value) { Node** FindInt64Constant(int64_t value) {
return int64_constants_.Find(zone_, value); return int64_constants_.Find(zone(), value);
}
Node** FindFloat32Constant(float value) {
// We canonicalize float constants at the bit representation level.
return float32_constants_.Find(zone(), bit_cast<int32_t>(value));
} }
Node** FindFloat64Constant(double value) { Node** FindFloat64Constant(double value) {
// We canonicalize double constants at the bit representation level. // We canonicalize double constants at the bit representation level.
return float64_constants_.Find(zone_, bit_cast<int64_t>(value)); return float64_constants_.Find(zone(), bit_cast<int64_t>(value));
} }
Node** FindExternalConstant(ExternalReference reference) { Node** FindExternalConstant(ExternalReference value);
return external_constants_.Find(zone_, reference.address());
}
Node** FindNumberConstant(double value) { Node** FindNumberConstant(double value) {
// We canonicalize double constants at the bit representation level. // We canonicalize double constants at the bit representation level.
return number_constants_.Find(zone_, bit_cast<int64_t>(value)); return number_constants_.Find(zone(), bit_cast<int64_t>(value));
} }
Zone* zone() const { return zone_; } // Return all nodes from the cache.
void GetCachedNodes(ZoneVector<Node*>* nodes);
void GetCachedNodes(NodeVector* nodes) { Zone* zone() const { return zone_; }
int32_constants_.GetCachedNodes(nodes);
int64_constants_.GetCachedNodes(nodes);
float64_constants_.GetCachedNodes(nodes);
external_constants_.GetCachedNodes(nodes);
number_constants_.GetCachedNodes(nodes);
}
private: private:
Int32NodeCache int32_constants_; Int32NodeCache int32_constants_;
Int64NodeCache int64_constants_; Int64NodeCache int64_constants_;
Int32NodeCache float32_constants_;
Int64NodeCache float64_constants_; Int64NodeCache float64_constants_;
PtrNodeCache external_constants_; IntPtrNodeCache external_constants_;
Int64NodeCache number_constants_; Int64NodeCache number_constants_;
Zone* zone_; Zone* zone_;
DISALLOW_COPY_AND_ASSIGN(CommonNodeCache);
}; };
} // namespace compiler } // namespace compiler
......
...@@ -174,8 +174,11 @@ Node* JSGraph::NumberConstant(double value) { ...@@ -174,8 +174,11 @@ Node* JSGraph::NumberConstant(double value) {
Node* JSGraph::Float32Constant(float value) { Node* JSGraph::Float32Constant(float value) {
// TODO(turbofan): cache float32 constants. Node** loc = cache_.FindFloat32Constant(value);
return graph()->NewNode(common()->Float32Constant(value)); if (*loc == NULL) {
*loc = graph()->NewNode(common()->Float32Constant(value));
}
return *loc;
} }
......
...@@ -13,6 +13,13 @@ namespace v8 { ...@@ -13,6 +13,13 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
namespace {
enum { kInitialSize = 16u, kLinearProbe = 5u };
} // namespace
template <typename Key, typename Hash, typename Pred> template <typename Key, typename Hash, typename Pred>
struct NodeCache<Key, Hash, Pred>::Entry { struct NodeCache<Key, Hash, Pred>::Entry {
Key key_; Key key_;
...@@ -92,17 +99,21 @@ Node** NodeCache<Key, Hash, Pred>::Find(Zone* zone, Key key) { ...@@ -92,17 +99,21 @@ Node** NodeCache<Key, Hash, Pred>::Find(Zone* zone, Key key) {
template <typename Key, typename Hash, typename Pred> template <typename Key, typename Hash, typename Pred>
void NodeCache<Key, Hash, Pred>::GetCachedNodes(NodeVector* nodes) { void NodeCache<Key, Hash, Pred>::GetCachedNodes(ZoneVector<Node*>* nodes) {
if (entries_) { if (entries_) {
for (size_t i = 0; i < size_ + kLinearProbe; i++) { for (size_t i = 0; i < size_ + kLinearProbe; i++) {
if (entries_[i].value_ != NULL) nodes->push_back(entries_[i].value_); if (entries_[i].value_) nodes->push_back(entries_[i].value_);
} }
} }
} }
template class NodeCache<int64_t>;
// -----------------------------------------------------------------------------
// Instantiations
template class NodeCache<int32_t>; template class NodeCache<int32_t>;
template class NodeCache<void*>; template class NodeCache<int64_t>;
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
......
...@@ -7,20 +7,31 @@ ...@@ -7,20 +7,31 @@
#include "src/base/functional.h" #include "src/base/functional.h"
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/compiler/node.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
// Forward declarations.
class Zone;
template <typename>
class ZoneVector;
namespace compiler { namespace compiler {
// Forward declarations.
class Node;
// A cache for nodes based on a key. Useful for implementing canonicalization of // A cache for nodes based on a key. Useful for implementing canonicalization of
// nodes such as constants, parameters, etc. // nodes such as constants, parameters, etc.
template <typename Key, typename Hash = base::hash<Key>, template <typename Key, typename Hash = base::hash<Key>,
typename Pred = std::equal_to<Key> > typename Pred = std::equal_to<Key> >
class NodeCache FINAL { class NodeCache FINAL {
public: public:
explicit NodeCache(size_t max = 256) explicit NodeCache(unsigned max = 256)
: entries_(nullptr), size_(0), max_(max) {} : entries_(nullptr), size_(0), max_(max) {}
~NodeCache() {}
// Search for node associated with {key} and return a pointer to a memory // Search for node associated with {key} and return a pointer to a memory
// location in this cache that stores an entry for the key. If the location // location in this cache that stores an entry for the key. If the location
...@@ -31,11 +42,10 @@ class NodeCache FINAL { ...@@ -31,11 +42,10 @@ class NodeCache FINAL {
// too full or encounters too many hash collisions. // too full or encounters too many hash collisions.
Node** Find(Zone* zone, Key key); Node** Find(Zone* zone, Key key);
void GetCachedNodes(NodeVector* nodes); // Appends all nodes from this cache to {nodes}.
void GetCachedNodes(ZoneVector<Node*>* nodes);
private: private:
enum { kInitialSize = 16u, kLinearProbe = 5u };
struct Entry; struct Entry;
Entry* entries_; // lazily-allocated hash entries. Entry* entries_; // lazily-allocated hash entries.
...@@ -45,12 +55,18 @@ class NodeCache FINAL { ...@@ -45,12 +55,18 @@ class NodeCache FINAL {
Pred pred_; Pred pred_;
bool Resize(Zone* zone); bool Resize(Zone* zone);
DISALLOW_COPY_AND_ASSIGN(NodeCache);
}; };
// Various default cache types. // Various default cache types.
typedef NodeCache<int64_t> Int64NodeCache;
typedef NodeCache<int32_t> Int32NodeCache; typedef NodeCache<int32_t> Int32NodeCache;
typedef NodeCache<void*> PtrNodeCache; typedef NodeCache<int64_t> Int64NodeCache;
#if V8_HOST_ARCH_32_BIT
typedef Int32NodeCache IntPtrNodeCache;
#else
typedef Int64NodeCache IntPtrNodeCache;
#endif
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
......
...@@ -115,51 +115,6 @@ TEST(Int64Constant_hits) { ...@@ -115,51 +115,6 @@ TEST(Int64Constant_hits) {
} }
TEST(PtrConstant_back_to_back) {
GraphTester graph;
PtrNodeCache cache;
int32_t buffer[50];
for (int32_t* p = buffer;
(p - buffer) < static_cast<ptrdiff_t>(arraysize(buffer)); p++) {
Node** pos = cache.Find(graph.zone(), p);
CHECK_NE(NULL, pos);
for (int j = 0; j < 3; j++) {
Node** npos = cache.Find(graph.zone(), p);
CHECK_EQ(pos, npos);
}
}
}
TEST(PtrConstant_hits) {
GraphTester graph;
PtrNodeCache cache;
const int32_t kSize = 50;
int32_t buffer[kSize];
Node* nodes[kSize];
CommonOperatorBuilder common(graph.zone());
for (size_t i = 0; i < arraysize(buffer); i++) {
int k = static_cast<int>(i);
int32_t* p = &buffer[i];
nodes[i] = graph.NewNode(common.Int32Constant(k));
*cache.Find(graph.zone(), p) = nodes[i];
}
int hits = 0;
for (size_t i = 0; i < arraysize(buffer); i++) {
int32_t* p = &buffer[i];
Node** pos = cache.Find(graph.zone(), p);
if (*pos != NULL) {
CHECK_EQ(nodes[i], *pos);
hits++;
}
}
CHECK_LT(4, hits);
}
static bool Contains(NodeVector* nodes, Node* n) { static bool Contains(NodeVector* nodes, Node* n) {
for (size_t i = 0; i < nodes->size(); i++) { for (size_t i = 0; i < nodes->size(); i++) {
if (nodes->at(i) == n) return true; if (nodes->at(i) == n) return true;
......
...@@ -416,6 +416,7 @@ ...@@ -416,6 +416,7 @@
'../../src/compiler/code-generator-impl.h', '../../src/compiler/code-generator-impl.h',
'../../src/compiler/code-generator.cc', '../../src/compiler/code-generator.cc',
'../../src/compiler/code-generator.h', '../../src/compiler/code-generator.h',
'../../src/compiler/common-node-cache.cc',
'../../src/compiler/common-node-cache.h', '../../src/compiler/common-node-cache.h',
'../../src/compiler/common-operator-reducer.cc', '../../src/compiler/common-operator-reducer.cc',
'../../src/compiler/common-operator-reducer.h', '../../src/compiler/common-operator-reducer.h',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment