Commit 14208380 authored by haraken@chromium.org's avatar haraken@chromium.org

Oilpan: Avoid looking up TLS in ThreadState::current()

This CL adds a fast, conservative way to determine if we are in the main thread.

1) In ThreadState::init(), take the underestimated size of the main thread.

2) When ThreadState::current() is called, check if the current stack address is within the underestimated size from the stack start of the main thread. If yes, we can immediately return the mainThreadState() without looking up TLS. Otherwise, we look up TLS.

TLS is very slow especially in Mac and Windows. This CL improves blink_perf.parser.querySelector-* (and other) benchmarks by 6% in Mac.

BUG=420515

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

git-svn-id: svn://svn.chromium.org/blink/trunk@183637 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 08eca2a4
......@@ -110,11 +110,37 @@ static void* getStackStart()
#endif
}
static size_t getUnderestimatedStackSize()
{
#if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD)
// We cannot get the stack size in these platforms because
// pthread_getattr_np() can fail for the main thread.
// This is OK because ThreadState::current() doesn't use the stack size
// in these platforms.
return 0;
#elif OS(MACOSX)
return pthread_get_stacksize_np(pthread_self());
#elif OS(WIN) && COMPILER(MSVC)
// On Windows stack limits for the current thread are available in
// the thread information block (TIB). Its fields can be accessed through
// FS segment register on x86 and GS segment register on x86_64.
#ifdef _WIN64
return __readgsqword(offsetof(NT_TIB64, StackBase)) - __readgsqword(offsetof(NT_TIB64, StackLimit));
#else
return __readfsdword(offsetof(NT_TIB, StackBase)) - __readfsdword(offsetof(NT_TIB, StackLimit));
#endif
#else
return 0;
#endif
}
// The maximum number of WrapperPersistentRegions to keep around in the
// m_pooledWrapperPersistentRegions pool.
static const size_t MaxPooledWrapperPersistentRegionCount = 2;
WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = 0;
uintptr_t ThreadState::s_mainThreadStackStart = 0;
uintptr_t ThreadState::s_mainThreadUnderestimatedStackSize = 0;
uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)];
SafePointBarrier* ThreadState::s_safePointBarrier = 0;
bool ThreadState::s_inGC = false;
......@@ -325,6 +351,11 @@ ThreadState::ThreadState()
ASSERT(!**s_threadSpecific);
**s_threadSpecific = this;
if (isMainThread()) {
s_mainThreadStackStart = reinterpret_cast<uintptr_t>(m_startOfStack) - sizeof(void*);
s_mainThreadUnderestimatedStackSize = getUnderestimatedStackSize() - sizeof(void*);
}
InitializeHeaps<NumberOfHeaps>::init(m_heaps, this);
m_weakCallbackStack = new CallbackStack();
......@@ -350,6 +381,8 @@ ThreadState::~ThreadState()
delete region;
}
**s_threadSpecific = 0;
s_mainThreadStackStart = 0;
s_mainThreadUnderestimatedStackSize = 0;
}
void ThreadState::init()
......
......@@ -375,7 +375,27 @@ public:
// can no longer use the garbage collected heap after this call.
static void detach();
static ThreadState* current() { return **s_threadSpecific; }
static ThreadState* current()
{
#if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD)
// TLS lookup is fast in these platforms.
return **s_threadSpecific;
#else
uintptr_t dummy;
uintptr_t addressDiff = s_mainThreadStackStart - reinterpret_cast<uintptr_t>(&dummy);
// This is a fast way to judge if we are in the main thread.
// If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from
// the stack start of the main thread, we judge that we are in
// the main thread.
if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) {
ASSERT(**s_threadSpecific == mainThreadState());
return mainThreadState();
}
// TLS lookup is slow.
return **s_threadSpecific;
#endif
}
static ThreadState* mainThreadState()
{
return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage);
......@@ -740,6 +760,8 @@ private:
void invokePreFinalizers(Visitor&);
static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific;
static uintptr_t s_mainThreadStackStart;
static uintptr_t s_mainThreadUnderestimatedStackSize;
static SafePointBarrier* s_safePointBarrier;
// This variable is flipped to true after all threads are stoped
......
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