Commit 50a80c93 authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

[turbofan] Make hints equality cheaper using hashing

Put the nesting limit of the serializer back to 25.

Bug: chromium:1034768
Change-Id: I7ea827d27241ea930bae40142069bab1962e4133
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1981156
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65630}
parent 7fcef442
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_COMPILER_FUNCTIONAL_LIST_H_ #define V8_COMPILER_FUNCTIONAL_LIST_H_
#include <iterator> #include <iterator>
#include "src/base/functional.h"
#include "src/zone/zone.h" #include "src/zone/zone.h"
namespace v8 { namespace v8 {
...@@ -17,7 +18,7 @@ namespace compiler { ...@@ -17,7 +18,7 @@ namespace compiler {
// in ML-like languages, with the only difference that it also caches the length // in ML-like languages, with the only difference that it also caches the length
// of the list in each node. // of the list in each node.
// TODO(tebbi): Use this implementation also for RedundancyElimination. // TODO(tebbi): Use this implementation also for RedundancyElimination.
template <class A> template <typename A>
class FunctionalList { class FunctionalList {
private: private:
struct Cons : ZoneObject { struct Cons : ZoneObject {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "src/compiler/serializer-for-background-compilation.h" #include "src/compiler/serializer-for-background-compilation.h"
#include <functional>
#include <sstream> #include <sstream>
#include "src/base/optional.h" #include "src/base/optional.h"
...@@ -298,6 +299,34 @@ class VirtualClosure { ...@@ -298,6 +299,34 @@ class VirtualClosure {
Hints const context_hints_; Hints const context_hints_;
}; };
struct HintsHash {
size_t operator()(Hints const& hints) const {
return base::hash_combine(hints.constants().Hash(), hints.maps().Hash(),
hints.virtual_closures().Hash(),
hints.virtual_contexts().Hash(),
hints.virtual_bound_functions().Hash());
}
};
size_t hash_value(Hints const& hints) { return HintsHash()(hints); }
struct VirtualBoundFunctionHash {
size_t operator()(VirtualBoundFunction const& vbf) const {
return base::hash_combine(HintsHash()(vbf.bound_target),
base::hash_range(vbf.bound_arguments.begin(),
vbf.bound_arguments.end()));
}
};
struct VirtualClosureHash {
size_t operator()(VirtualClosure const& c) const {
return base::hash_combine(
Handle<SharedFunctionInfo>::hash()(c.shared()),
Handle<FeedbackVector>::hash()(c.feedback_vector()),
HintsHash()(c.context_hints()));
}
};
// A CompilationSubject is a VirtualClosure, optionally with a matching // A CompilationSubject is a VirtualClosure, optionally with a matching
// concrete closure. // concrete closure.
class CompilationSubject { class CompilationSubject {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#ifndef V8_COMPILER_SERIALIZER_HINTS_H_ #ifndef V8_COMPILER_SERIALIZER_HINTS_H_
#define V8_COMPILER_SERIALIZER_HINTS_H_ #define V8_COMPILER_SERIALIZER_HINTS_H_
#include "src/base/functional.h"
#include "src/compiler/functional-list.h" #include "src/compiler/functional-list.h"
#include "src/handles/handles.h" #include "src/handles/handles.h"
#include "src/zone/zone-containers.h" #include "src/zone/zone-containers.h"
...@@ -23,7 +24,7 @@ class Map; ...@@ -23,7 +24,7 @@ class Map;
namespace compiler { namespace compiler {
template <typename T, typename EqualTo> template <typename T, typename EqualTo, typename Hasher>
class FunctionalSet { class FunctionalSet {
public: public:
void Add(T const& elem, Zone* zone) { void Add(T const& elem, Zone* zone) {
...@@ -31,9 +32,12 @@ class FunctionalSet { ...@@ -31,9 +32,12 @@ class FunctionalSet {
if (equal_to(l, elem)) return; if (equal_to(l, elem)) return;
} }
data_.PushFront(elem, zone); data_.PushFront(elem, zone);
// We rely on commutative property of the computed hash, otherwise
// we would use base::hash_combine here.
hash_ = hash_ ^ hasher(elem);
} }
void Union(FunctionalSet<T, EqualTo> other, Zone* zone) { void Union(FunctionalSet<T, EqualTo, Hasher> other, Zone* zone) {
if (!data_.TriviallyEquals(other.data_)) { if (!data_.TriviallyEquals(other.data_)) {
// Choose the larger side as tail. // Choose the larger side as tail.
if (data_.Size() < other.data_.Size()) std::swap(data_, other.data_); if (data_.Size() < other.data_.Size()) std::swap(data_, other.data_);
...@@ -44,23 +48,25 @@ class FunctionalSet { ...@@ -44,23 +48,25 @@ class FunctionalSet {
bool IsEmpty() const { return data_.begin() == data_.end(); } bool IsEmpty() const { return data_.begin() == data_.end(); }
// Warning: quadratic time complexity. // Warning: quadratic time complexity.
bool Includes(FunctionalSet<T, EqualTo> const& other) const { bool Includes(FunctionalSet<T, EqualTo, Hasher> const& other) const {
return std::all_of(other.begin(), other.end(), [&](T const& other_elem) { return std::all_of(other.begin(), other.end(), [&](T const& other_elem) {
return std::any_of(this->begin(), this->end(), [&](T const& this_elem) { return std::any_of(this->begin(), this->end(), [&](T const& this_elem) {
return equal_to(this_elem, other_elem); return equal_to(this_elem, other_elem);
}); });
}); });
} }
bool operator==(const FunctionalSet<T, EqualTo>& other) const { bool operator==(const FunctionalSet<T, EqualTo, Hasher>& other) const {
return this->data_.TriviallyEquals(other.data_) || return this->data_.TriviallyEquals(other.data_) ||
(this->data_.Size() == other.data_.Size() && this->Includes(other) && (this->data_.Size() == other.data_.Size() &&
this->Hash() == other.Hash() && this->Includes(other) &&
other.Includes(*this)); other.Includes(*this));
} }
bool operator!=(const FunctionalSet<T, EqualTo>& other) const { bool operator!=(const FunctionalSet<T, EqualTo, Hasher>& other) const {
return !(*this == other); return !(*this == other);
} }
size_t Size() const { return data_.Size(); } size_t Size() const { return data_.Size(); }
size_t Hash() const { return hash_; }
using iterator = typename FunctionalList<T>::iterator; using iterator = typename FunctionalList<T>::iterator;
...@@ -69,11 +75,16 @@ class FunctionalSet { ...@@ -69,11 +75,16 @@ class FunctionalSet {
private: private:
static EqualTo equal_to; static EqualTo equal_to;
static Hasher hasher;
FunctionalList<T> data_; FunctionalList<T> data_;
size_t hash_ = 0;
}; };
template <typename T, typename EqualTo> template <typename T, typename EqualTo, typename Hasher>
EqualTo FunctionalSet<T, EqualTo>::equal_to; EqualTo FunctionalSet<T, EqualTo, Hasher>::equal_to;
template <typename T, typename EqualTo, typename Hasher>
Hasher FunctionalSet<T, EqualTo, Hasher>::hasher;
struct VirtualContext { struct VirtualContext {
unsigned int distance; unsigned int distance;
...@@ -86,19 +97,32 @@ struct VirtualContext { ...@@ -86,19 +97,32 @@ struct VirtualContext {
bool operator==(const VirtualContext& other) const { bool operator==(const VirtualContext& other) const {
return context.equals(other.context) && distance == other.distance; return context.equals(other.context) && distance == other.distance;
} }
struct Hash {
size_t operator()(VirtualContext const& c) const {
return base::hash_combine(static_cast<size_t>(c.distance),
Handle<Context>::hash()(c.context));
}
};
}; };
class VirtualClosure; class VirtualClosure;
struct VirtualClosureHash;
struct VirtualBoundFunction; struct VirtualBoundFunction;
struct VirtualBoundFunctionHash;
using ConstantsSet = FunctionalSet<Handle<Object>, Handle<Object>::equal_to>; using ConstantsSet = FunctionalSet<Handle<Object>, Handle<Object>::equal_to,
Handle<Object>::hash>;
using VirtualContextsSet = using VirtualContextsSet =
FunctionalSet<VirtualContext, std::equal_to<VirtualContext>>; FunctionalSet<VirtualContext, std::equal_to<VirtualContext>,
using MapsSet = FunctionalSet<Handle<Map>, Handle<Map>::equal_to>; VirtualContext::Hash>;
using MapsSet =
FunctionalSet<Handle<Map>, Handle<Map>::equal_to, Handle<Map>::hash>;
using VirtualClosuresSet = using VirtualClosuresSet =
FunctionalSet<VirtualClosure, std::equal_to<VirtualClosure>>; FunctionalSet<VirtualClosure, std::equal_to<VirtualClosure>,
VirtualClosureHash>;
using VirtualBoundFunctionsSet = using VirtualBoundFunctionsSet =
FunctionalSet<VirtualBoundFunction, std::equal_to<VirtualBoundFunction>>; FunctionalSet<VirtualBoundFunction, std::equal_to<VirtualBoundFunction>,
VirtualBoundFunctionHash>;
struct HintsImpl; struct HintsImpl;
class JSHeapBroker; class JSHeapBroker;
......
...@@ -501,7 +501,7 @@ DEFINE_BOOL(block_concurrent_recompilation, false, ...@@ -501,7 +501,7 @@ DEFINE_BOOL(block_concurrent_recompilation, false,
"block queued jobs until released") "block queued jobs until released")
DEFINE_BOOL(concurrent_inlining, false, DEFINE_BOOL(concurrent_inlining, false,
"run optimizing compiler's inlining phase on a separate thread") "run optimizing compiler's inlining phase on a separate thread")
DEFINE_INT(max_serializer_nesting, 15, DEFINE_INT(max_serializer_nesting, 25,
"maximum levels for nesting child serializers") "maximum levels for nesting child serializers")
DEFINE_IMPLICATION(future, concurrent_inlining) DEFINE_IMPLICATION(future, concurrent_inlining)
DEFINE_BOOL(trace_heap_broker_verbose, false, DEFINE_BOOL(trace_heap_broker_verbose, false,
......
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