Commit feca33b4 authored by Jeremy Roman's avatar Jeremy Roman Committed by Commit Bot

WTF: Skip heap allocation for small objects in DEFINE_STATIC_LOCAL.

Many of these are only one or two pointers large anyway (e.g. AtomicString,
Vector), so using the heap doesn't save memory, and just adds a pointer
indirection to each access.

Change-Id: If63b228bd0b5f8040c7b13134f063c1e26322f85
Reviewed-on: https://chromium-review.googlesource.com/519846Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarYuta Kitamura <yutak@chromium.org>
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#476283}
parent 19fd249f
......@@ -27,6 +27,7 @@
#define WTF_StdLibExtras_h
#include <cstddef>
#include "base/memory/aligned_memory.h"
#include "base/numerics/safe_conversions.h"
#include "platform/wtf/Assertions.h"
#include "platform/wtf/CPU.h"
......@@ -38,6 +39,14 @@
#include "platform/wtf/Threading.h"
#endif
#define DEFINE_STATIC_LOCAL_IMPL(Type, Name, Arguments, allow_cross_thread) \
static WTF::StaticSingleton<Type> s_##Name( \
[&]() { return new WTF::StaticSingleton<Type>::WrapperType Arguments; }, \
[&](void* leaked_ptr) { \
new (leaked_ptr) WTF::StaticSingleton<Type>::WrapperType Arguments; \
}); \
Type& Name = s_##Name.Get(allow_cross_thread)
// Use |DEFINE_STATIC_LOCAL()| to declare and define a static local variable
// (|static T;|) so that it is leaked and its destructors are not called at
// exit. T may also be a Blink garbage collected object, in which case it is
......@@ -47,10 +56,8 @@
// A |DEFINE_STATIC_LOCAL()| static should only be used on the thread it was
// created on.
//
#define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \
static WTF::StaticSingleton<Type> s_##Name( \
new WTF::StaticSingleton<Type>::WrapperType Arguments); \
Type& Name = s_##Name.Get(false)
#define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \
DEFINE_STATIC_LOCAL_IMPL(Type, Name, Arguments, false)
// |DEFINE_THREAD_SAFE_STATIC_LOCAL()| is the cross-thread accessible variant
// of |DEFINE_STATIC_LOCAL()|; use it if the singleton can be accessed by
......@@ -58,9 +65,7 @@
//
// TODO: rename as DEFINE_CROSS_THREAD_STATIC_LOCAL() ?
#define DEFINE_THREAD_SAFE_STATIC_LOCAL(Type, Name, Arguments) \
static WTF::StaticSingleton<Type> s_##Name( \
new WTF::StaticSingleton<Type>::WrapperType Arguments); \
Type& Name = s_##Name.Get(true)
DEFINE_STATIC_LOCAL_IMPL(Type, Name, Arguments, true)
namespace blink {
template <typename T>
......@@ -108,22 +113,24 @@ class StaticSingleton final {
// LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy
// details.
explicit StaticSingleton(WrapperType* instance)
: instance_(LEAK_SANITIZER_REGISTER_STATIC_LOCAL(WrapperType, instance))
template <typename HeapNew, typename PlacementNew>
StaticSingleton(const HeapNew& heap_new, const PlacementNew& placement_new)
: instance_(heap_new, placement_new)
#if DCHECK_IS_ON()
,
safely_initialized_(WTF::IsBeforeThreadCreated()),
thread_(WTF::internal::CurrentThreadSyscall())
#endif
{
LEAK_SANITIZER_REGISTER_STATIC_LOCAL(WrapperType, instance_.Get());
}
Type& Get(bool allow_cross_thread_use) const {
Type& Get(bool allow_cross_thread_use) {
#if DCHECK_IS_ON()
DCHECK(IsNotRacy(allow_cross_thread_use));
#endif
ALLOW_UNUSED_LOCAL(allow_cross_thread_use);
return Wrapper<Type>::Unwrap(instance_);
return Wrapper<Type>::Unwrap(instance_.Get());
}
operator Type&() { return Get(); }
......@@ -139,8 +146,32 @@ class StaticSingleton final {
thread_ == WTF::internal::CurrentThreadSyscall();
}
#endif
template <typename T, bool is_small = sizeof(T) <= 32>
class InstanceStorage {
public:
template <typename HeapNew, typename PlacementNew>
InstanceStorage(const HeapNew& heap_new, const PlacementNew&)
: pointer_(heap_new()) {}
T* Get() { return pointer_; }
private:
T* pointer_;
};
template <typename T>
class InstanceStorage<T, true> {
public:
template <typename HeapNew, typename PlacementNew>
InstanceStorage(const HeapNew&, const PlacementNew& placement_new) {
placement_new(object_.void_data());
}
T* Get() { return object_.template data_as<T>(); }
private:
base::AlignedMemory<sizeof(T), ALIGNOF(T)> object_;
};
WrapperType* instance_;
InstanceStorage<WrapperType> instance_;
#if DCHECK_IS_ON()
bool safely_initialized_;
ThreadIdentifier thread_;
......
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