From 4f9193e047d50b1ffbca95e8185576af82c722b3 Mon Sep 17 00:00:00 2001 From: bmeurer Date: Tue, 23 Dec 2014 06:12:04 -0800 Subject: [PATCH] [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} --- BUILD.gn | 1 + src/compiler/common-node-cache.cc | 29 +++++++++++++++++++++ src/compiler/common-node-cache.h | 42 +++++++++++++++++------------- src/compiler/js-graph.cc | 7 +++-- src/compiler/node-cache.cc | 19 +++++++++++--- src/compiler/node-cache.h | 30 +++++++++++++++++----- test/cctest/compiler/test-node-cache.cc | 45 --------------------------------- tools/gyp/v8.gyp | 1 + 8 files changed, 98 insertions(+), 76 deletions(-) create mode 100644 src/compiler/common-node-cache.cc diff --git a/BUILD.gn b/BUILD.gn index 28695dd..262e09e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -489,6 +489,7 @@ source_set("v8_base") { "src/compiler/code-generator-impl.h", "src/compiler/code-generator.cc", "src/compiler/code-generator.h", + "src/compiler/common-node-cache.cc", "src/compiler/common-node-cache.h", "src/compiler/common-operator-reducer.cc", "src/compiler/common-operator-reducer.h", diff --git a/src/compiler/common-node-cache.cc b/src/compiler/common-node-cache.cc new file mode 100644 index 0000000..ee1fa0f --- /dev/null +++ b/src/compiler/common-node-cache.cc @@ -0,0 +1,29 @@ +// 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(value.address())); +} + + +void CommonNodeCache::GetCachedNodes(ZoneVector* 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 diff --git a/src/compiler/common-node-cache.h b/src/compiler/common-node-cache.h index 5479574..7ec70ae 100644 --- a/src/compiler/common-node-cache.h +++ b/src/compiler/common-node-cache.h @@ -5,57 +5,63 @@ #ifndef V8_COMPILER_COMMON_NODE_CACHE_H_ #define V8_COMPILER_COMMON_NODE_CACHE_H_ -#include "src/assembler.h" #include "src/compiler/node-cache.h" namespace v8 { namespace internal { + +// Forward declarations. +class ExternalReference; + + namespace compiler { // Bundles various caches for common nodes. -class CommonNodeCache FINAL : public ZoneObject { +class CommonNodeCache FINAL { public: explicit CommonNodeCache(Zone* zone) : zone_(zone) {} + ~CommonNodeCache() {} Node** FindInt32Constant(int32_t value) { - return int32_constants_.Find(zone_, value); + return int32_constants_.Find(zone(), 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(value)); } Node** FindFloat64Constant(double value) { // We canonicalize double constants at the bit representation level. - return float64_constants_.Find(zone_, bit_cast(value)); + return float64_constants_.Find(zone(), bit_cast(value)); } - Node** FindExternalConstant(ExternalReference reference) { - return external_constants_.Find(zone_, reference.address()); - } + Node** FindExternalConstant(ExternalReference value); Node** FindNumberConstant(double value) { // We canonicalize double constants at the bit representation level. - return number_constants_.Find(zone_, bit_cast(value)); + return number_constants_.Find(zone(), bit_cast(value)); } - Zone* zone() const { return zone_; } + // Return all nodes from the cache. + void GetCachedNodes(ZoneVector* nodes); - void GetCachedNodes(NodeVector* nodes) { - int32_constants_.GetCachedNodes(nodes); - int64_constants_.GetCachedNodes(nodes); - float64_constants_.GetCachedNodes(nodes); - external_constants_.GetCachedNodes(nodes); - number_constants_.GetCachedNodes(nodes); - } + Zone* zone() const { return zone_; } private: Int32NodeCache int32_constants_; Int64NodeCache int64_constants_; + Int32NodeCache float32_constants_; Int64NodeCache float64_constants_; - PtrNodeCache external_constants_; + IntPtrNodeCache external_constants_; Int64NodeCache number_constants_; Zone* zone_; + + DISALLOW_COPY_AND_ASSIGN(CommonNodeCache); }; } // namespace compiler diff --git a/src/compiler/js-graph.cc b/src/compiler/js-graph.cc index b8a7f97..7759ba1 100644 --- a/src/compiler/js-graph.cc +++ b/src/compiler/js-graph.cc @@ -174,8 +174,11 @@ Node* JSGraph::NumberConstant(double value) { Node* JSGraph::Float32Constant(float value) { - // TODO(turbofan): cache float32 constants. - return graph()->NewNode(common()->Float32Constant(value)); + Node** loc = cache_.FindFloat32Constant(value); + if (*loc == NULL) { + *loc = graph()->NewNode(common()->Float32Constant(value)); + } + return *loc; } diff --git a/src/compiler/node-cache.cc b/src/compiler/node-cache.cc index 35d03ce..92a3fa0 100644 --- a/src/compiler/node-cache.cc +++ b/src/compiler/node-cache.cc @@ -13,6 +13,13 @@ namespace v8 { namespace internal { namespace compiler { +namespace { + +enum { kInitialSize = 16u, kLinearProbe = 5u }; + +} // namespace + + template struct NodeCache::Entry { Key key_; @@ -92,17 +99,21 @@ Node** NodeCache::Find(Zone* zone, Key key) { template -void NodeCache::GetCachedNodes(NodeVector* nodes) { +void NodeCache::GetCachedNodes(ZoneVector* nodes) { if (entries_) { 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; + +// ----------------------------------------------------------------------------- +// Instantiations + + template class NodeCache; -template class NodeCache; +template class NodeCache; } // namespace compiler } // namespace internal diff --git a/src/compiler/node-cache.h b/src/compiler/node-cache.h index 2622e4d..b123922 100644 --- a/src/compiler/node-cache.h +++ b/src/compiler/node-cache.h @@ -7,20 +7,31 @@ #include "src/base/functional.h" #include "src/base/macros.h" -#include "src/compiler/node.h" namespace v8 { namespace internal { + +// Forward declarations. +class Zone; +template +class ZoneVector; + + 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 Pred = std::equal_to > class NodeCache FINAL { public: - explicit NodeCache(size_t max = 256) + explicit NodeCache(unsigned max = 256) : entries_(nullptr), size_(0), max_(max) {} + ~NodeCache() {} // 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 @@ -31,11 +42,10 @@ class NodeCache FINAL { // too full or encounters too many hash collisions. Node** Find(Zone* zone, Key key); - void GetCachedNodes(NodeVector* nodes); + // Appends all nodes from this cache to {nodes}. + void GetCachedNodes(ZoneVector* nodes); private: - enum { kInitialSize = 16u, kLinearProbe = 5u }; - struct Entry; Entry* entries_; // lazily-allocated hash entries. @@ -45,12 +55,18 @@ class NodeCache FINAL { Pred pred_; bool Resize(Zone* zone); + + DISALLOW_COPY_AND_ASSIGN(NodeCache); }; // Various default cache types. -typedef NodeCache Int64NodeCache; typedef NodeCache Int32NodeCache; -typedef NodeCache PtrNodeCache; +typedef NodeCache Int64NodeCache; +#if V8_HOST_ARCH_32_BIT +typedef Int32NodeCache IntPtrNodeCache; +#else +typedef Int64NodeCache IntPtrNodeCache; +#endif } // namespace compiler } // namespace internal diff --git a/test/cctest/compiler/test-node-cache.cc b/test/cctest/compiler/test-node-cache.cc index 57bf7fa..a48adb9 100644 --- a/test/cctest/compiler/test-node-cache.cc +++ b/test/cctest/compiler/test-node-cache.cc @@ -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(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(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) { for (size_t i = 0; i < nodes->size(); i++) { if (nodes->at(i) == n) return true; diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index 8901681..16fa114 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -416,6 +416,7 @@ '../../src/compiler/code-generator-impl.h', '../../src/compiler/code-generator.cc', '../../src/compiler/code-generator.h', + '../../src/compiler/common-node-cache.cc', '../../src/compiler/common-node-cache.h', '../../src/compiler/common-operator-reducer.cc', '../../src/compiler/common-operator-reducer.h', -- 2.7.4