Commit c0c3b207 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[turbofan] use ZoneUnorderedMap for NodeCache

This fixes a non-determinism issue caused by the cache being full.
Depending on the non-deterministic value of the handles in HeapConstant
nodes, different cache entries would be overwritten in this case.

The old implementation of NodeCache had a fixed limit, overwriting
entries when the cache is full. This behavior didn't really make sense,
but the hand-written hash map implementation couldn't handle arbitrary
numbers of hash collisions, so removing the limit wasn't an option either.
Thus this CL just replaces the custom hash map with a normal
std::unordered_map, that is, a ZoneUnorderedMap.

Bug: chromium:1046815
Change-Id: I95269f2b1068eb9dfe3ee2ab5cca1cb460bc8fa3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2087405Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66592}
parent 500d73b9
......@@ -1909,7 +1909,6 @@ v8_compiler_sources = [
"src/compiler/memory-optimizer.cc",
"src/compiler/memory-optimizer.h",
"src/compiler/node-aux-data.h",
"src/compiler/node-cache.cc",
"src/compiler/node-cache.h",
"src/compiler/node-marker.cc",
"src/compiler/node-marker.h",
......
......@@ -12,21 +12,23 @@ namespace internal {
namespace compiler {
Node** CommonNodeCache::FindExternalConstant(ExternalReference value) {
return external_constants_.Find(zone(), bit_cast<intptr_t>(value.address()));
return external_constants_.Find(bit_cast<intptr_t>(value.address()));
}
Node** CommonNodeCache::FindHeapConstant(Handle<HeapObject> value) {
return heap_constants_.Find(zone(), bit_cast<intptr_t>(value.address()));
return heap_constants_.Find(bit_cast<intptr_t>(value.address()));
}
void CommonNodeCache::GetCachedNodes(ZoneVector<Node*>* nodes) {
int32_constants_.GetCachedNodes(nodes);
int64_constants_.GetCachedNodes(nodes);
tagged_index_constants_.GetCachedNodes(nodes);
float32_constants_.GetCachedNodes(nodes);
float64_constants_.GetCachedNodes(nodes);
external_constants_.GetCachedNodes(nodes);
pointer_constants_.GetCachedNodes(nodes);
number_constants_.GetCachedNodes(nodes);
heap_constants_.GetCachedNodes(nodes);
relocatable_int32_constants_.GetCachedNodes(nodes);
......
......@@ -22,59 +22,66 @@ namespace compiler {
// Bundles various caches for common nodes.
class CommonNodeCache final {
public:
explicit CommonNodeCache(Zone* zone) : zone_(zone) {}
explicit CommonNodeCache(Zone* zone)
: int32_constants_(zone),
int64_constants_(zone),
tagged_index_constants_(zone),
float32_constants_(zone),
float64_constants_(zone),
external_constants_(zone),
pointer_constants_(zone),
number_constants_(zone),
heap_constants_(zone),
relocatable_int32_constants_(zone),
relocatable_int64_constants_(zone) {}
~CommonNodeCache() = default;
Node** FindInt32Constant(int32_t value) {
return int32_constants_.Find(zone(), value);
return int32_constants_.Find(value);
}
Node** FindInt64Constant(int64_t value) {
return int64_constants_.Find(zone(), value);
return int64_constants_.Find(value);
}
Node** FindTaggedIndexConstant(int32_t value) {
return tagged_index_constants_.Find(zone(), value);
return tagged_index_constants_.Find(value);
}
Node** FindFloat32Constant(float value) {
// We canonicalize float constants at the bit representation level.
return float32_constants_.Find(zone(), bit_cast<int32_t>(value));
return float32_constants_.Find(bit_cast<int32_t>(value));
}
Node** FindFloat64Constant(double value) {
// We canonicalize double constants at the bit representation level.
return float64_constants_.Find(zone(), bit_cast<int64_t>(value));
return float64_constants_.Find(bit_cast<int64_t>(value));
}
Node** FindExternalConstant(ExternalReference value);
Node** FindPointerConstant(intptr_t value) {
return pointer_constants_.Find(zone(), value);
return pointer_constants_.Find(value);
}
Node** FindNumberConstant(double value) {
// We canonicalize double constants at the bit representation level.
return number_constants_.Find(zone(), bit_cast<int64_t>(value));
return number_constants_.Find(bit_cast<int64_t>(value));
}
Node** FindHeapConstant(Handle<HeapObject> value);
Node** FindRelocatableInt32Constant(int32_t value, RelocInfoMode rmode) {
return relocatable_int32_constants_.Find(zone(),
std::make_pair(value, rmode));
return relocatable_int32_constants_.Find(std::make_pair(value, rmode));
}
Node** FindRelocatableInt64Constant(int64_t value, RelocInfoMode rmode) {
return relocatable_int64_constants_.Find(zone(),
std::make_pair(value, rmode));
return relocatable_int64_constants_.Find(std::make_pair(value, rmode));
}
// Return all nodes from the cache.
void GetCachedNodes(ZoneVector<Node*>* nodes);
Zone* zone() const { return zone_; }
private:
Int32NodeCache int32_constants_;
Int64NodeCache int64_constants_;
......@@ -87,7 +94,6 @@ class CommonNodeCache final {
IntPtrNodeCache heap_constants_;
RelocInt32NodeCache relocatable_int32_constants_;
RelocInt64NodeCache relocatable_int64_constants_;
Zone* const zone_;
DISALLOW_COPY_AND_ASSIGN(CommonNodeCache);
};
......
// 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/node-cache.h"
#include <cstring>
#include "src/common/globals.h"
#include "src/zone/zone-containers.h"
#include "src/zone/zone.h"
namespace v8 {
namespace internal {
namespace compiler {
namespace {
enum { kInitialSize = 16u, kLinearProbe = 5u };
} // namespace
template <typename Key, typename Hash, typename Pred>
struct NodeCache<Key, Hash, Pred>::Entry {
Key key_;
Node* value_;
};
template <typename Key, typename Hash, typename Pred>
bool NodeCache<Key, Hash, Pred>::Resize(Zone* zone) {
if (size_ >= max_) return false; // Don't grow past the maximum size.
// Allocate a new block of entries 4x the size.
Entry* old_entries = entries_;
size_t old_size = size_ + kLinearProbe;
size_ *= 4;
size_t num_entries = size_ + kLinearProbe;
entries_ = zone->NewArray<Entry>(num_entries);
memset(static_cast<void*>(entries_), 0, sizeof(Entry) * num_entries);
// Insert the old entries into the new block.
for (size_t i = 0; i < old_size; ++i) {
Entry* old = &old_entries[i];
if (old->value_) {
size_t hash = hash_(old->key_);
size_t start = hash & (size_ - 1);
size_t end = start + kLinearProbe;
for (size_t j = start; j < end; ++j) {
Entry* entry = &entries_[j];
if (!entry->value_) {
entry->key_ = old->key_;
entry->value_ = old->value_;
break;
}
}
}
}
return true;
}
template <typename Key, typename Hash, typename Pred>
Node** NodeCache<Key, Hash, Pred>::Find(Zone* zone, Key key) {
size_t hash = hash_(key);
if (!entries_) {
// Allocate the initial entries and insert the first entry.
size_t num_entries = kInitialSize + kLinearProbe;
entries_ = zone->NewArray<Entry>(num_entries);
size_ = kInitialSize;
memset(static_cast<void*>(entries_), 0, sizeof(Entry) * num_entries);
Entry* entry = &entries_[hash & (kInitialSize - 1)];
entry->key_ = key;
return &entry->value_;
}
for (;;) {
// Search up to N entries after (linear probing).
size_t start = hash & (size_ - 1);
size_t end = start + kLinearProbe;
for (size_t i = start; i < end; i++) {
Entry* entry = &entries_[i];
if (pred_(entry->key_, key)) return &entry->value_;
if (!entry->value_) {
entry->key_ = key;
return &entry->value_;
}
}
if (!Resize(zone)) break; // Don't grow past the maximum size.
}
// If resized to maximum and still didn't find space, overwrite an entry.
Entry* entry = &entries_[hash & (size_ - 1)];
entry->key_ = key;
entry->value_ = nullptr;
return &entry->value_;
}
template <typename Key, typename Hash, typename Pred>
void NodeCache<Key, Hash, Pred>::GetCachedNodes(ZoneVector<Node*>* nodes) {
if (entries_) {
for (size_t i = 0; i < size_ + kLinearProbe; i++) {
if (entries_[i].value_) nodes->push_back(entries_[i].value_);
}
}
}
// -----------------------------------------------------------------------------
// Instantiations
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) NodeCache<int32_t>;
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) NodeCache<int64_t>;
template class EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) NodeCache<RelocInt32Key>;
template class EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) NodeCache<RelocInt64Key>;
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -8,6 +8,7 @@
#include "src/base/export-template.h"
#include "src/base/functional.h"
#include "src/base/macros.h"
#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
......@@ -30,33 +31,25 @@ template <typename Key, typename Hash = base::hash<Key>,
typename Pred = std::equal_to<Key> >
class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) NodeCache final {
public:
explicit NodeCache(unsigned max = 256)
: entries_(nullptr), size_(0), max_(max) {}
explicit NodeCache(Zone* zone) : map_(zone) {}
~NodeCache() = default;
// 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
// returned by this method contains a non-nullptr node, the caller can use
// that
// node. Otherwise it is the responsibility of the caller to fill the entry
// with a new node.
// Note that a previous cache entry may be overwritten if the cache becomes
// too full or encounters too many hash collisions.
Node** Find(Zone* zone, Key key);
// that node. Otherwise it is the responsibility of the caller to fill the
// entry with a new node.
Node** Find(Key key) { return &(map_[key]); }
// Appends all nodes from this cache to {nodes}.
void GetCachedNodes(ZoneVector<Node*>* nodes);
void GetCachedNodes(ZoneVector<Node*>* nodes) {
for (const auto& entry : map_) {
if (entry.second) nodes->push_back(entry.second);
}
}
private:
struct Entry;
Entry* entries_; // lazily-allocated hash entries.
size_t size_;
size_t max_;
Hash hash_;
Pred pred_;
bool Resize(Zone* zone);
ZoneUnorderedMap<Key, Node*, Hash, Pred> map_;
DISALLOW_COPY_AND_ASSIGN(NodeCache);
};
......@@ -78,17 +71,6 @@ using IntPtrNodeCache = Int32NodeCache;
using IntPtrNodeCache = Int64NodeCache;
#endif
// Explicit instantiation declarations.
extern template class EXPORT_TEMPLATE_DECLARE(
V8_EXPORT_PRIVATE) NodeCache<int32_t>;
extern template class EXPORT_TEMPLATE_DECLARE(
V8_EXPORT_PRIVATE) NodeCache<int64_t>;
extern template class EXPORT_TEMPLATE_DECLARE(
V8_EXPORT_PRIVATE) NodeCache<RelocInt32Key>;
extern template class EXPORT_TEMPLATE_DECLARE(
V8_EXPORT_PRIVATE) NodeCache<RelocInt64Key>;
} // namespace compiler
} // namespace internal
} // namespace v8
......
......@@ -6323,14 +6323,15 @@ std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob(
std::unique_ptr<Zone> zone =
std::make_unique<Zone>(wasm_engine->allocator(), ZONE_NAME);
Graph* graph = new (zone.get()) Graph(zone.get());
CommonOperatorBuilder common(zone.get());
MachineOperatorBuilder machine(
CommonOperatorBuilder* common =
new (zone.get()) CommonOperatorBuilder(zone.get());
MachineOperatorBuilder* machine = new (zone.get()) MachineOperatorBuilder(
zone.get(), MachineType::PointerRepresentation(),
InstructionSelector::SupportedMachineOperatorFlags(),
InstructionSelector::AlignmentRequirements());
MachineGraph mcgraph(graph, &common, &machine);
MachineGraph* mcgraph = new (zone.get()) MachineGraph(graph, common, machine);
WasmWrapperGraphBuilder builder(zone.get(), &mcgraph, sig, nullptr,
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr,
StubCallMode::kCallBuiltinPointer,
enabled_features);
builder.BuildJSToWasmWrapper(is_import);
......@@ -6587,18 +6588,18 @@ wasm::WasmCompilationResult CompileWasmImportCallWrapper(
// Create the Graph
//----------------------------------------------------------------------------
Zone zone(wasm_engine->allocator(), ZONE_NAME);
Graph graph(&zone);
CommonOperatorBuilder common(&zone);
MachineOperatorBuilder machine(
Graph* graph = new (&zone) Graph(&zone);
CommonOperatorBuilder* common = new (&zone) CommonOperatorBuilder(&zone);
MachineOperatorBuilder* machine = new (&zone) MachineOperatorBuilder(
&zone, MachineType::PointerRepresentation(),
InstructionSelector::SupportedMachineOperatorFlags(),
InstructionSelector::AlignmentRequirements());
MachineGraph mcgraph(&graph, &common, &machine);
MachineGraph* mcgraph = new (&zone) MachineGraph(graph, common, machine);
SourcePositionTable* source_position_table =
source_positions ? new (&zone) SourcePositionTable(&graph) : nullptr;
source_positions ? new (&zone) SourcePositionTable(graph) : nullptr;
WasmWrapperGraphBuilder builder(&zone, &mcgraph, sig, source_position_table,
WasmWrapperGraphBuilder builder(&zone, mcgraph, sig, source_position_table,
StubCallMode::kCallWasmRuntimeStub,
env->enabled_features);
builder.BuildWasmImportCallWrapper(kind);
......@@ -6609,11 +6610,11 @@ wasm::WasmCompilationResult CompileWasmImportCallWrapper(
CallDescriptor* incoming =
GetWasmCallDescriptor(&zone, sig, WasmGraphBuilder::kNoRetpoline,
WasmCallKind::kWasmImportWrapper);
if (machine.Is32()) {
if (machine->Is32()) {
incoming = GetI32WasmCallDescriptor(&zone, incoming);
}
wasm::WasmCompilationResult result = Pipeline::GenerateCodeForWasmNativeStub(
wasm_engine, incoming, &mcgraph, Code::WASM_TO_JS_FUNCTION,
wasm_engine, incoming, mcgraph, Code::WASM_TO_JS_FUNCTION,
wasm::WasmCode::kWasmToJsWrapper, func_name, WasmStubAssemblerOptions(),
source_position_table);
result.kind = wasm::WasmCompilationResult::kWasmToJsWrapper;
......@@ -6678,22 +6679,22 @@ wasm::WasmCompilationResult CompileWasmInterpreterEntry(
// Create the Graph
//----------------------------------------------------------------------------
Zone zone(wasm_engine->allocator(), ZONE_NAME);
Graph graph(&zone);
CommonOperatorBuilder common(&zone);
MachineOperatorBuilder machine(
Graph* graph = new (&zone) Graph(&zone);
CommonOperatorBuilder* common = new (&zone) CommonOperatorBuilder(&zone);
MachineOperatorBuilder* machine = new (&zone) MachineOperatorBuilder(
&zone, MachineType::PointerRepresentation(),
InstructionSelector::SupportedMachineOperatorFlags(),
InstructionSelector::AlignmentRequirements());
MachineGraph mcgraph(&graph, &common, &machine);
MachineGraph* mcgraph = new (&zone) MachineGraph(graph, common, machine);
WasmWrapperGraphBuilder builder(&zone, &mcgraph, sig, nullptr,
WasmWrapperGraphBuilder builder(&zone, mcgraph, sig, nullptr,
StubCallMode::kCallWasmRuntimeStub,
enabled_features);
builder.BuildWasmInterpreterEntry(func_index);
// Schedule and compile to machine code.
CallDescriptor* incoming = GetWasmCallDescriptor(&zone, sig);
if (machine.Is32()) {
if (machine->Is32()) {
incoming = GetI32WasmCallDescriptor(&zone, incoming);
}
......@@ -6702,7 +6703,7 @@ wasm::WasmCompilationResult CompileWasmInterpreterEntry(
SNPrintF(func_name, "wasm-interpreter-entry#%d", func_index));
wasm::WasmCompilationResult result = Pipeline::GenerateCodeForWasmNativeStub(
wasm_engine, incoming, &mcgraph, Code::WASM_INTERPRETER_ENTRY,
wasm_engine, incoming, mcgraph, Code::WASM_INTERPRETER_ENTRY,
wasm::WasmCode::kInterpreterEntry, func_name.begin(),
WasmStubAssemblerOptions());
result.result_tier = wasm::ExecutionTier::kInterpreter;
......@@ -6716,14 +6717,15 @@ MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate,
std::unique_ptr<Zone> zone =
std::make_unique<Zone>(isolate->allocator(), ZONE_NAME);
Graph* graph = new (zone.get()) Graph(zone.get());
CommonOperatorBuilder common(zone.get());
MachineOperatorBuilder machine(
CommonOperatorBuilder* common =
new (zone.get()) CommonOperatorBuilder(zone.get());
MachineOperatorBuilder* machine = new (zone.get()) MachineOperatorBuilder(
zone.get(), MachineType::PointerRepresentation(),
InstructionSelector::SupportedMachineOperatorFlags(),
InstructionSelector::AlignmentRequirements());
MachineGraph mcgraph(graph, &common, &machine);
MachineGraph* mcgraph = new (zone.get()) MachineGraph(graph, common, machine);
WasmWrapperGraphBuilder builder(zone.get(), &mcgraph, sig, nullptr,
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr,
StubCallMode::kCallBuiltinPointer,
wasm::WasmFeatures::FromIsolate(isolate));
builder.BuildJSToJSWrapper(isolate);
......@@ -6762,14 +6764,15 @@ MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate,
std::unique_ptr<Zone> zone =
std::make_unique<Zone>(isolate->allocator(), ZONE_NAME);
Graph* graph = new (zone.get()) Graph(zone.get());
CommonOperatorBuilder common(zone.get());
MachineOperatorBuilder machine(
CommonOperatorBuilder* common =
new (zone.get()) CommonOperatorBuilder(zone.get());
MachineOperatorBuilder* machine = new (zone.get()) MachineOperatorBuilder(
zone.get(), MachineType::PointerRepresentation(),
InstructionSelector::SupportedMachineOperatorFlags(),
InstructionSelector::AlignmentRequirements());
MachineGraph mcgraph(graph, &common, &machine);
MachineGraph* mcgraph = new (zone.get()) MachineGraph(graph, common, machine);
WasmWrapperGraphBuilder builder(zone.get(), &mcgraph, sig, nullptr,
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr,
StubCallMode::kCallBuiltinPointer,
wasm::WasmFeatures::FromIsolate(isolate));
builder.BuildCWasmEntry();
......
......@@ -17,13 +17,13 @@ namespace node_cache_unittest {
using NodeCacheTest = GraphTest;
TEST_F(NodeCacheTest, Int32Constant_back_to_back) {
Int32NodeCache cache;
Int32NodeCache cache(zone());
for (int i = -2000000000; i < 2000000000; i += 3315177) {
Node** pos = cache.Find(zone(), i);
Node** pos = cache.Find(i);
ASSERT_TRUE(pos != nullptr);
for (int j = 0; j < 3; j++) {
Node** npos = cache.Find(zone(), i);
Node** npos = cache.Find(i);
EXPECT_EQ(pos, npos);
}
}
......@@ -31,38 +31,38 @@ TEST_F(NodeCacheTest, Int32Constant_back_to_back) {
TEST_F(NodeCacheTest, Int32Constant_five) {
Int32NodeCache cache;
Int32NodeCache cache(zone());
int32_t constants[] = {static_cast<int32_t>(0x80000000), -77, 0, 1, -1};
Node* nodes[arraysize(constants)];
for (size_t i = 0; i < arraysize(constants); i++) {
int32_t k = constants[i];
Node* node = graph()->NewNode(common()->Int32Constant(k));
*cache.Find(zone(), k) = nodes[i] = node;
*cache.Find(k) = nodes[i] = node;
}
for (size_t i = 0; i < arraysize(constants); i++) {
int32_t k = constants[i];
EXPECT_EQ(nodes[i], *cache.Find(zone(), k));
EXPECT_EQ(nodes[i], *cache.Find(k));
}
}
TEST_F(NodeCacheTest, Int32Constant_hits) {
Int32NodeCache cache;
Int32NodeCache cache(zone());
const int32_t kSize = 1500;
Node** nodes = zone()->NewArray<Node*>(kSize);
for (int i = 0; i < kSize; i++) {
int32_t v = i * -55;
nodes[i] = graph()->NewNode(common()->Int32Constant(v));
*cache.Find(zone(), v) = nodes[i];
*cache.Find(v) = nodes[i];
}
int hits = 0;
for (int i = 0; i < kSize; i++) {
int32_t v = i * -55;
Node** pos = cache.Find(zone(), v);
Node** pos = cache.Find(v);
if (*pos != nullptr) {
EXPECT_EQ(nodes[i], *pos);
hits++;
......@@ -73,13 +73,13 @@ TEST_F(NodeCacheTest, Int32Constant_hits) {
TEST_F(NodeCacheTest, Int64Constant_back_to_back) {
Int64NodeCache cache;
Int64NodeCache cache(zone());
for (int64_t i = -2000000000; i < 2000000000; i += 3315177) {
Node** pos = cache.Find(zone(), i);
Node** pos = cache.Find(i);
ASSERT_TRUE(pos != nullptr);
for (int j = 0; j < 3; j++) {
Node** npos = cache.Find(zone(), i);
Node** npos = cache.Find(i);
EXPECT_EQ(pos, npos);
}
}
......@@ -87,20 +87,20 @@ TEST_F(NodeCacheTest, Int64Constant_back_to_back) {
TEST_F(NodeCacheTest, Int64Constant_hits) {
Int64NodeCache cache;
Int64NodeCache cache(zone());
const int32_t kSize = 1500;
Node** nodes = zone()->NewArray<Node*>(kSize);
for (int i = 0; i < kSize; i++) {
int64_t v = static_cast<int64_t>(i) * static_cast<int64_t>(5003001);
nodes[i] = graph()->NewNode(common()->Int32Constant(i));
*cache.Find(zone(), v) = nodes[i];
*cache.Find(v) = nodes[i];
}
int hits = 0;
for (int i = 0; i < kSize; i++) {
int64_t v = static_cast<int64_t>(i) * static_cast<int64_t>(5003001);
Node** pos = cache.Find(zone(), v);
Node** pos = cache.Find(v);
if (*pos != nullptr) {
EXPECT_EQ(nodes[i], *pos);
hits++;
......@@ -111,13 +111,13 @@ TEST_F(NodeCacheTest, Int64Constant_hits) {
TEST_F(NodeCacheTest, GetCachedNodes_int32) {
Int32NodeCache cache;
Int32NodeCache cache(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(zone(), k);
Node** pos = cache.Find(k);
if (*pos != nullptr) {
ZoneVector<Node*> nodes(zone());
cache.GetCachedNodes(&nodes);
......@@ -134,13 +134,13 @@ TEST_F(NodeCacheTest, GetCachedNodes_int32) {
TEST_F(NodeCacheTest, GetCachedNodes_int64) {
Int64NodeCache cache;
Int64NodeCache cache(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(zone(), k);
Node** pos = cache.Find(k);
if (*pos != nullptr) {
ZoneVector<Node*> nodes(zone());
cache.GetCachedNodes(&nodes);
......
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