Title: [219176] trunk/Source
Revision
219176
Author
utatane....@gmail.com
Date
2017-07-05 18:57:43 -0700 (Wed, 05 Jul 2017)

Log Message

WTF::Thread should have the threads stack bounds.
https://bugs.webkit.org/show_bug.cgi?id=173975

Reviewed by Keith Miller.

Source/_javascript_Core:

There is a site in JSC that try to walk another thread's stack.
Currently, stack bounds are stored in WTFThreadData which is located
in TLS. Thus, only the thread itself can access its own WTFThreadData.
We workaround this situation by holding StackBounds in MachineThread in JSC,
but StackBounds should be put in WTF::Thread instead.

This patch moves StackBounds from WTFThreadData to WTF::Thread. StackBounds
information is tightly coupled with Thread. Thus putting it in WTF::Thread
is natural choice.

* heap/MachineStackMarker.cpp:
(JSC::MachineThreads::MachineThread::MachineThread):
(JSC::MachineThreads::MachineThread::captureStack):
* heap/MachineStackMarker.h:
(JSC::MachineThreads::MachineThread::stackBase):
(JSC::MachineThreads::MachineThread::stackEnd):
* runtime/InitializeThreading.cpp:
(JSC::initializeThreading):
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::updateStackLimits):
(JSC::VM::committedStackByteCount):
* runtime/VM.h:
(JSC::VM::isSafeToRecurse):
* runtime/VMEntryScope.cpp:
(JSC::VMEntryScope::VMEntryScope):
* runtime/VMInlines.h:
(JSC::VM::ensureStackCapacityFor):
* runtime/VMTraps.cpp:
* yarr/YarrPattern.cpp:
(JSC::Yarr::YarrPatternConstructor::isSafeToRecurse):

Source/WebCore:

When creating WebThread, we first allocate WebCore::ThreadGlobalData in UI thread
and share it with WebThread.
The problem is that WebCore::ThreadGlobalData has CachedResourceRequestInitiators.
It allocates AtomicString, which requires WTFThreadData.

Before this patch, it was OK because WTFThreadData does not touch threading related
things except for ThreadSpecific<>. However, after this patch, it touches
WTF::Thread::current() which requires WTF::initializeThreading().

In this patch, we call WTF::initializeThreading() before allocating WebCore::ThreadGlobalData.
And we also call AtomicString::init() before calling WebCore::ThreadGlobalData since
WebCore::ThreadGlobalData allocates AtomicString.

This fixes crashes in the iOS web threading environment (UIWebView).

* platform/ios/wak/WebCoreThread.mm:
(StartWebThread):

Source/WTF:

We move StackBounds from WTFThreadData to WTF::Thread.
One important thing is that we should make valid StackBounds
visible to Thread::create() caller. When the caller get
WTF::Thread from Thread::create(), this WTF::Thread should
have a valid StackBounds. But StackBounds information can be
retrived only in the WTF::Thread's thread itself.

We also clean up WTF::initializeThreading. StringImpl::empty()
is now statically initialized by using constexpr constructor.
Thus we do not need to call StringImpl::empty() explicitly here.
And WTF::initializeThreading() does not have any main thread
affinity right now in all the platforms. So we fix the comment
in Threading.h. Then, now, WTF::initializeThreading() is called
in UI thread when using Web thread in iOS.

* wtf/StackBounds.h:
(WTF::StackBounds::emptyBounds):
(WTF::StackBounds::StackBounds):
* wtf/StackStats.cpp:
(WTF::StackStats::PerThreadStats::PerThreadStats):
* wtf/Threading.cpp:
(WTF::threadEntryPoint):
(WTF::Thread::create):
(WTF::Thread::currentMayBeNull):
(WTF::Thread::initialize):
(WTF::initializeThreading):
* wtf/Threading.h:
(WTF::Thread::stack):
* wtf/ThreadingPthreads.cpp:
(WTF::Thread::initializeCurrentThreadEvenIfNonWTFCreated):
(WTF::Thread::current):
(WTF::initializeCurrentThreadEvenIfNonWTFCreated): Deleted.
(WTF::Thread::currentMayBeNull): Deleted.
* wtf/ThreadingWin.cpp:
(WTF::Thread::initializeCurrentThreadEvenIfNonWTFCreated):
(WTF::Thread::initializeCurrentThreadInternal):
(WTF::Thread::current):
* wtf/WTFThreadData.cpp:
(WTF::WTFThreadData::WTFThreadData):
* wtf/WTFThreadData.h:
(WTF::WTFThreadData::stack): Deleted.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (219175 => 219176)


--- trunk/Source/_javascript_Core/ChangeLog	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-07-06 01:57:43 UTC (rev 219176)
@@ -1,3 +1,42 @@
+2017-07-05  Yusuke Suzuki  <utatane....@gmail.com>
+
+        WTF::Thread should have the threads stack bounds.
+        https://bugs.webkit.org/show_bug.cgi?id=173975
+
+        Reviewed by Keith Miller.
+
+        There is a site in JSC that try to walk another thread's stack.
+        Currently, stack bounds are stored in WTFThreadData which is located
+        in TLS. Thus, only the thread itself can access its own WTFThreadData.
+        We workaround this situation by holding StackBounds in MachineThread in JSC,
+        but StackBounds should be put in WTF::Thread instead.
+
+        This patch moves StackBounds from WTFThreadData to WTF::Thread. StackBounds
+        information is tightly coupled with Thread. Thus putting it in WTF::Thread
+        is natural choice.
+
+        * heap/MachineStackMarker.cpp:
+        (JSC::MachineThreads::MachineThread::MachineThread):
+        (JSC::MachineThreads::MachineThread::captureStack):
+        * heap/MachineStackMarker.h:
+        (JSC::MachineThreads::MachineThread::stackBase):
+        (JSC::MachineThreads::MachineThread::stackEnd):
+        * runtime/InitializeThreading.cpp:
+        (JSC::initializeThreading):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::VM::updateStackLimits):
+        (JSC::VM::committedStackByteCount):
+        * runtime/VM.h:
+        (JSC::VM::isSafeToRecurse):
+        * runtime/VMEntryScope.cpp:
+        (JSC::VMEntryScope::VMEntryScope):
+        * runtime/VMInlines.h:
+        (JSC::VM::ensureStackCapacityFor):
+        * runtime/VMTraps.cpp:
+        * yarr/YarrPattern.cpp:
+        (JSC::Yarr::YarrPatternConstructor::isSafeToRecurse):
+
 2017-07-05  Keith Miller  <keith_mil...@apple.com>
 
         Crashing with information should have an abort reason

Modified: trunk/Source/_javascript_Core/heap/MachineStackMarker.cpp (219175 => 219176)


--- trunk/Source/_javascript_Core/heap/MachineStackMarker.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/_javascript_Core/heap/MachineStackMarker.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -239,9 +239,6 @@
 MachineThreads::MachineThread::MachineThread()
     : m_thread(WTF::Thread::current())
 {
-    auto stackBounds = wtfThreadData().stack();
-    m_stackBase = stackBounds.origin();
-    m_stackEnd = stackBounds.end();
 }
 
 size_t MachineThreads::MachineThread::getRegisters(MachineThread::Registers& registers)
@@ -302,7 +299,7 @@
 
 std::pair<void*, size_t> MachineThreads::MachineThread::captureStack(void* stackTop)
 {
-    char* begin = reinterpret_cast_ptr<char*>(m_stackBase);
+    char* begin = reinterpret_cast_ptr<char*>(stackBase());
     char* end = bitwise_cast<char*>(WTF::roundUpToMultipleOf<sizeof(void*)>(reinterpret_cast<uintptr_t>(stackTop)));
     ASSERT(begin >= end);
 
@@ -309,8 +306,8 @@
     char* endWithRedZone = end + osRedZoneAdjustment();
     ASSERT(WTF::roundUpToMultipleOf<sizeof(void*)>(reinterpret_cast<uintptr_t>(endWithRedZone)) == reinterpret_cast<uintptr_t>(endWithRedZone));
 
-    if (endWithRedZone < m_stackEnd)
-        endWithRedZone = reinterpret_cast_ptr<char*>(m_stackEnd);
+    if (endWithRedZone < stackEnd())
+        endWithRedZone = reinterpret_cast_ptr<char*>(stackEnd());
 
     std::swap(begin, endWithRedZone);
     return std::make_pair(begin, endWithRedZone - begin);

Modified: trunk/Source/_javascript_Core/heap/MachineStackMarker.h (219175 => 219176)


--- trunk/Source/_javascript_Core/heap/MachineStackMarker.h	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/_javascript_Core/heap/MachineStackMarker.h	2017-07-06 01:57:43 UTC (rev 219176)
@@ -72,12 +72,10 @@
         std::pair<void*, size_t> captureStack(void* stackTop);
 
         WTF::ThreadIdentifier threadID() const { return m_thread->id(); }
-        void* stackBase() const { return m_stackBase; }
-        void* stackEnd() const { return m_stackEnd; }
+        void* stackBase() const { return m_thread->stack().origin(); }
+        void* stackEnd() const { return m_thread->stack().end(); }
 
         Ref<WTF::Thread> m_thread;
-        void* m_stackBase;
-        void* m_stackEnd;
         MachineThread* m_next { nullptr };
         MachineThread* m_prev { nullptr };
     };
@@ -104,7 +102,7 @@
 #define DECLARE_AND_COMPUTE_CURRENT_THREAD_STATE(stateName) \
     CurrentThreadState stateName; \
     stateName.stackTop = &stateName; \
-    stateName.stackOrigin = wtfThreadData().stack().origin(); \
+    stateName.stackOrigin = Thread::current().stack().origin(); \
     ALLOCATE_AND_GET_REGISTER_STATE(stateName ## _registerState); \
     stateName.registerState = &stateName ## _registerState
 

Modified: trunk/Source/_javascript_Core/runtime/InitializeThreading.cpp (219175 => 219176)


--- trunk/Source/_javascript_Core/runtime/InitializeThreading.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/_javascript_Core/runtime/InitializeThreading.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -75,8 +75,7 @@
         DisallowVMReentry::initialize();
 #endif
         initializeSuperSampler();
-        WTFThreadData& threadData = wtfThreadData();
-        threadData.setSavedLastStackTop(threadData.stack().origin());
+        wtfThreadData().setSavedLastStackTop(Thread::current().stack().origin());
 
 #if ENABLE(WEBASSEMBLY)
         Wasm::Thunks::initialize();

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (219175 => 219176)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -211,7 +211,7 @@
     , m_shadowChicken(std::make_unique<ShadowChicken>())
 {
     interpreter = new Interpreter(*this);
-    StackBounds stack = wtfThreadData().stack();
+    StackBounds stack = Thread::current().stack();
     updateSoftReservedZoneSize(Options::softReservedZoneSize());
     setLastStackTop(stack.origin());
 
@@ -671,7 +671,7 @@
     void* lastSoftStackLimit = m_softStackLimit;
 #endif
 
-    const StackBounds& stack = wtfThreadData().stack();
+    const StackBounds& stack = Thread::current().stack();
     size_t reservedZoneSize = Options::reservedZoneSize();
     // We should have already ensured that Options::reservedZoneSize() >= minimumReserveZoneSize at
     // options initialization time, and the option value should not have been changed thereafter.
@@ -885,9 +885,9 @@
 #if ENABLE(JIT)
     // When using the C stack, we don't know how many stack pages are actually
     // committed. So, we use the current stack usage as an estimate.
-    ASSERT(wtfThreadData().stack().isGrowingDownward());
+    ASSERT(Thread::current().stack().isGrowingDownward());
     int8_t* current = reinterpret_cast<int8_t*>(&current);
-    int8_t* high = reinterpret_cast<int8_t*>(wtfThreadData().stack().origin());
+    int8_t* high = reinterpret_cast<int8_t*>(Thread::current().stack().origin());
     return high - current;
 #else
     return CLoopStack::committedByteCount();

Modified: trunk/Source/_javascript_Core/runtime/VM.h (219175 => 219176)


--- trunk/Source/_javascript_Core/runtime/VM.h	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2017-07-06 01:57:43 UTC (rev 219176)
@@ -689,7 +689,7 @@
 
     bool isSafeToRecurse(void* stackLimit) const
     {
-        ASSERT(wtfThreadData().stack().isGrowingDownward());
+        ASSERT(Thread::current().stack().isGrowingDownward());
         void* curr = reinterpret_cast<void*>(&curr);
         return curr >= stackLimit;
     }

Modified: trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp (219175 => 219176)


--- trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -41,7 +41,7 @@
     , m_globalObject(globalObject)
 {
     ASSERT(!DisallowVMReentry::isInEffectOnCurrentThread());
-    ASSERT(wtfThreadData().stack().isGrowingDownward());
+    ASSERT(Thread::current().stack().isGrowingDownward());
     if (!vm.entryScope) {
         vm.entryScope = this;
 

Modified: trunk/Source/_javascript_Core/runtime/VMInlines.h (219175 => 219176)


--- trunk/Source/_javascript_Core/runtime/VMInlines.h	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/_javascript_Core/runtime/VMInlines.h	2017-07-06 01:57:43 UTC (rev 219176)
@@ -34,7 +34,7 @@
 bool VM::ensureStackCapacityFor(Register* newTopOfStack)
 {
 #if ENABLE(JIT)
-    ASSERT(wtfThreadData().stack().isGrowingDownward());
+    ASSERT(Thread::current().stack().isGrowingDownward());
     return newTopOfStack >= m_softStackLimit;
 #else
     return ensureStackCapacityForCLoop(newTopOfStack);

Modified: trunk/Source/_javascript_Core/runtime/VMTraps.cpp (219175 => 219176)


--- trunk/Source/_javascript_Core/runtime/VMTraps.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/_javascript_Core/runtime/VMTraps.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -267,25 +267,7 @@
                     return;
 
                 Thread& thread = *ownerThread->get();
-                StackBounds stackBounds = StackBounds::emptyBounds();
-                {
-                    // FIXME: We need to use the machine threads because it is the only non-TLS source
-                    // for the stack bounds of this thread. We should keep in on the WTF::Thread instead.
-                    // see: https://bugs.webkit.org/show_bug.cgi?id=173975
-                    MachineThreads& machineThreads = vm.heap.machineThreads();
-                    auto machineThreadsLock = tryHoldLock(machineThreads.getLock());
-                    if (!machineThreadsLock)
-                        return; // Try again later.
-
-                    auto& threadList = machineThreads.threadsListHead(machineThreadsLock);
-                    for (MachineThreads::MachineThread* machineThread = threadList.head(); machineThread; machineThread = machineThread->next()) {
-                        if (machineThread->m_thread.get() == thread)
-                            stackBounds = StackBounds(machineThread->stackBase(), machineThread->stackEnd());
-                    }
-                    RELEASE_ASSERT(!stackBounds.isEmpty());
-                }
-
-                vm.traps().tryInstallTrapBreakpoints(context, stackBounds);
+                vm.traps().tryInstallTrapBreakpoints(context, thread.stack());
             });
         }
 

Modified: trunk/Source/_javascript_Core/yarr/YarrPattern.cpp (219175 => 219176)


--- trunk/Source/_javascript_Core/yarr/YarrPattern.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/_javascript_Core/yarr/YarrPattern.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -880,7 +880,7 @@
     {
         if (!m_stackLimit)
             return true;
-        ASSERT(wtfThreadData().stack().isGrowingDownward());
+        ASSERT(Thread::current().stack().isGrowingDownward());
         int8_t* curr = reinterpret_cast<int8_t*>(&curr);
         int8_t* limit = reinterpret_cast<int8_t*>(m_stackLimit);
         return curr >= limit;

Modified: trunk/Source/WTF/ChangeLog (219175 => 219176)


--- trunk/Source/WTF/ChangeLog	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WTF/ChangeLog	2017-07-06 01:57:43 UTC (rev 219176)
@@ -1,3 +1,52 @@
+2017-07-05  Yusuke Suzuki  <utatane....@gmail.com>
+
+        WTF::Thread should have the threads stack bounds.
+        https://bugs.webkit.org/show_bug.cgi?id=173975
+
+        Reviewed by Keith Miller.
+
+        We move StackBounds from WTFThreadData to WTF::Thread.
+        One important thing is that we should make valid StackBounds
+        visible to Thread::create() caller. When the caller get
+        WTF::Thread from Thread::create(), this WTF::Thread should
+        have a valid StackBounds. But StackBounds information can be
+        retrived only in the WTF::Thread's thread itself.
+
+        We also clean up WTF::initializeThreading. StringImpl::empty()
+        is now statically initialized by using constexpr constructor.
+        Thus we do not need to call StringImpl::empty() explicitly here.
+        And WTF::initializeThreading() does not have any main thread
+        affinity right now in all the platforms. So we fix the comment
+        in Threading.h. Then, now, WTF::initializeThreading() is called
+        in UI thread when using Web thread in iOS.
+
+        * wtf/StackBounds.h:
+        (WTF::StackBounds::emptyBounds):
+        (WTF::StackBounds::StackBounds):
+        * wtf/StackStats.cpp:
+        (WTF::StackStats::PerThreadStats::PerThreadStats):
+        * wtf/Threading.cpp:
+        (WTF::threadEntryPoint):
+        (WTF::Thread::create):
+        (WTF::Thread::currentMayBeNull):
+        (WTF::Thread::initialize):
+        (WTF::initializeThreading):
+        * wtf/Threading.h:
+        (WTF::Thread::stack):
+        * wtf/ThreadingPthreads.cpp:
+        (WTF::Thread::initializeCurrentThreadEvenIfNonWTFCreated):
+        (WTF::Thread::current):
+        (WTF::initializeCurrentThreadEvenIfNonWTFCreated): Deleted.
+        (WTF::Thread::currentMayBeNull): Deleted.
+        * wtf/ThreadingWin.cpp:
+        (WTF::Thread::initializeCurrentThreadEvenIfNonWTFCreated):
+        (WTF::Thread::initializeCurrentThreadInternal):
+        (WTF::Thread::current):
+        * wtf/WTFThreadData.cpp:
+        (WTF::WTFThreadData::WTFThreadData):
+        * wtf/WTFThreadData.h:
+        (WTF::WTFThreadData::stack): Deleted.
+
 2017-07-05  Keith Miller  <keith_mil...@apple.com>
 
         Crashing with information should have an abort reason

Modified: trunk/Source/WTF/wtf/StackBounds.h (219175 => 219176)


--- trunk/Source/WTF/wtf/StackBounds.h	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WTF/wtf/StackBounds.h	2017-07-06 01:57:43 UTC (rev 219176)
@@ -40,7 +40,7 @@
     const static size_t s_defaultAvailabilityDelta = 64 * 1024;
 
 public:
-    static StackBounds emptyBounds() { return StackBounds(); }
+    static constexpr StackBounds emptyBounds() { return StackBounds(); }
 
     static StackBounds currentThreadStackBounds()
     {
@@ -127,9 +127,9 @@
     }
 
 private:
-    StackBounds()
-        : m_origin(0)
-        , m_bound(0)
+    constexpr StackBounds()
+        : m_origin(nullptr)
+        , m_bound(nullptr)
     {
     }
 

Modified: trunk/Source/WTF/wtf/StackStats.cpp (219175 => 219176)


--- trunk/Source/WTF/wtf/StackStats.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WTF/wtf/StackStats.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -59,7 +59,7 @@
 
 StackStats::PerThreadStats::PerThreadStats()
 {
-    const StackBounds& stack = wtfThreadData().stack();
+    const StackBounds& stack = Thread::current().stack();
     m_reentryDepth = 0;
     m_stackStart = (char*)stack.origin();
     m_currentCheckPoint = 0;

Modified: trunk/Source/WTF/wtf/Threading.cpp (219175 => 219176)


--- trunk/Source/WTF/wtf/Threading.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WTF/wtf/Threading.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -46,12 +46,16 @@
 
 namespace WTF {
 
+enum class Stage {
+    Start, Initialized
+};
+
 struct NewThreadContext {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
     const char* name;
     Function<void()> entryPoint;
-    Mutex creationMutex;
+    Stage stage;
+    Mutex mutex;
+    ThreadCondition condition;
 };
 
 const char* Thread::normalizeThreadName(const char* threadName)
@@ -84,33 +88,48 @@
 static void threadEntryPoint(void* contextData)
 {
     NewThreadContext* context = static_cast<NewThreadContext*>(contextData);
-
-    // Block until our creating thread has completed any extra setup work, including
-    // establishing ThreadIdentifier.
+    Function<void()> entryPoint;
     {
-        MutexLocker locker(context->creationMutex);
-    }
+        // Block until our creating thread has completed any extra setup work, including establishing ThreadIdentifier.
+        MutexLocker locker(context->mutex);
 
-    Thread::initializeCurrentThreadInternal(context->name);
+        Thread::initializeCurrentThreadInternal(context->name);
+        entryPoint = WTFMove(context->entryPoint);
 
-    auto entryPoint = WTFMove(context->entryPoint);
+        // Ack completion of initialization to the creating thread.
+        context->stage = Stage::Initialized;
+        context->condition.signal();
+    }
 
-    // Delete the context before starting the thread.
-    delete context;
-
     entryPoint();
 }
 
 RefPtr<Thread> Thread::create(const char* name, Function<void()>&& entryPoint)
 {
-    NewThreadContext* context = new NewThreadContext { name, WTFMove(entryPoint), { } };
+    NewThreadContext context { name, WTFMove(entryPoint), Stage::Start, { }, { } };
 
-    // Prevent the thread body from executing until we've established the thread identifier.
-    MutexLocker locker(context->creationMutex);
+    MutexLocker locker(context.mutex);
+    RefPtr<Thread> result = Thread::createInternal(threadEntryPoint, &context, name);
+    // After establishing Thread, release the mutex and wait for completion of initialization.
+    while (context.stage != Stage::Initialized)
+        context.condition.wait(context.mutex);
 
-    return Thread::createInternal(threadEntryPoint, context, name);
+    return result;
 }
 
+Thread* Thread::currentMayBeNull()
+{
+    ThreadHolder* data = ""
+    if (data)
+        return &data->thread();
+    return nullptr;
+}
+
+void Thread::initialize()
+{
+    m_stack = StackBounds::currentThreadStackBounds();
+}
+
 void Thread::didExit()
 {
     std::unique_lock<std::mutex> locker(m_mutex);
@@ -166,9 +185,6 @@
     static std::once_flag initializeKey;
     std::call_once(initializeKey, [] {
         ThreadHolder::initializeOnce();
-        // StringImpl::empty() does not construct its static string in a threadsafe fashion,
-        // so ensure it has been initialized from here.
-        StringImpl::empty();
         initializeRandomNumberGenerator();
         wtfThreadData();
         initializeDates();

Modified: trunk/Source/WTF/wtf/Threading.h (219175 => 219176)


--- trunk/Source/WTF/wtf/Threading.h	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WTF/wtf/Threading.h	2017-07-06 01:57:43 UTC (rev 219176)
@@ -38,6 +38,7 @@
 #include <wtf/Function.h>
 #include <wtf/PlatformRegisters.h>
 #include <wtf/RefPtr.h>
+#include <wtf/StackBounds.h>
 #include <wtf/ThreadSafeRefCounted.h>
 
 #if USE(PTHREADS) && !OS(DARWIN)
@@ -67,7 +68,7 @@
 
     // Returns Thread object.
     WTF_EXPORT_PRIVATE static Thread& current();
-    WTF_EXPORT_PRIVATE static Thread* currentMayBeNull();
+    static Thread* currentMayBeNull();
 
     // Returns ThreadIdentifier directly. It is useful if the user only cares about identity
     // of threads. At that time, users should know that holding this ThreadIdentifier does not ensure
@@ -108,6 +109,7 @@
     // Called in the thread during initialization.
     // Helpful for platforms where the thread name must be set from within the thread.
     static void initializeCurrentThreadInternal(const char* threadName);
+    static void initializeCurrentThreadEvenIfNonWTFCreated();
 
     WTF_EXPORT_PRIVATE void dump(PrintStream& out) const;
 
@@ -125,6 +127,11 @@
 
     static void initializePlatformThreading();
 
+    const StackBounds& stack() const
+    {
+        return m_stack;
+    }
+
 #if OS(DARWIN)
     mach_port_t machThread() { return m_platformThread; }
 #endif
@@ -140,6 +147,7 @@
 #else
     void establish(HANDLE, ThreadIdentifier);
 #endif
+    void initialize();
 
 #if USE(PTHREADS) && !OS(DARWIN)
     static void signalHandlerSuspendResume(int, siginfo_t*, void* ucontext);
@@ -171,6 +179,7 @@
     std::mutex m_mutex;
     ThreadIdentifier m_id { 0 };
     JoinableState m_joinableState { Joinable };
+    StackBounds m_stack { StackBounds::emptyBounds() };
     bool m_didExit { false };
 #if USE(PTHREADS)
     pthread_t m_handle;
@@ -190,9 +199,7 @@
 #endif
 };
 
-// This function must be called from the main thread. It is safe to call it repeatedly.
-// Darwin is an exception to this rule: it is OK to call it from any thread, the only
-// requirement is that the calls are not reentrant.
+// This function can be called from any threads.
 WTF_EXPORT_PRIVATE void initializeThreading();
 
 inline ThreadIdentifier currentThread()

Modified: trunk/Source/WTF/wtf/ThreadingPthreads.cpp (219175 => 219176)


--- trunk/Source/WTF/wtf/ThreadingPthreads.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WTF/wtf/ThreadingPthreads.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -188,8 +188,9 @@
 #endif
 }
 
-static void initializeCurrentThreadEvenIfNonWTFCreated()
+void Thread::initializeCurrentThreadEvenIfNonWTFCreated()
 {
+    Thread::current().initialize();
 #if !OS(DARWIN)
     sigset_t mask;
     sigemptyset(&mask);
@@ -299,14 +300,6 @@
         didBecomeDetached();
 }
 
-Thread* Thread::currentMayBeNull()
-{
-    ThreadHolder* data = ""
-    if (data)
-        return &data->thread();
-    return nullptr;
-}
-
 Thread& Thread::current()
 {
     if (Thread* current = currentMayBeNull())
@@ -313,11 +306,11 @@
         return *current;
 
     // Not a WTF-created thread, ThreadIdentifier is not established yet.
-    RefPtr<Thread> thread = adoptRef(new Thread());
+    Ref<Thread> thread = adoptRef(*new Thread());
     thread->establish(pthread_self());
-    ThreadHolder::initialize(*thread);
+    ThreadHolder::initialize(thread.get());
     initializeCurrentThreadEvenIfNonWTFCreated();
-    return *thread;
+    return thread.get();
 }
 
 ThreadIdentifier Thread::currentID()

Modified: trunk/Source/WTF/wtf/ThreadingWin.cpp (219175 => 219176)


--- trunk/Source/WTF/wtf/ThreadingWin.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WTF/wtf/ThreadingWin.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -116,6 +116,11 @@
         CloseHandle(m_handle);
 }
 
+void Thread::initializeCurrentThreadEvenIfNonWTFCreated()
+{
+    Thread::current().initialize();
+}
+
 // MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadNameInternal all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
 static const DWORD MS_VC_EXCEPTION = 0x406D1388;
 
@@ -145,6 +150,7 @@
     } __except (EXCEPTION_CONTINUE_EXECUTION) {
     }
 #endif
+    initializeCurrentThreadEvenIfNonWTFCreated();
 }
 
 void Thread::initializePlatformThreading()
@@ -261,9 +267,8 @@
 
 Thread& Thread::current()
 {
-    ThreadHolder* data = ""
-    if (data)
-        return data->thread();
+    if (Thread* current = currentMayBeNull())
+        return *current;
 
     // Not a WTF-created thread, ThreadIdentifier is not established yet.
     Ref<Thread> thread = adoptRef(*new Thread());
@@ -274,6 +279,7 @@
 
     thread->establish(handle, currentID());
     ThreadHolder::initialize(thread.get(), Thread::currentID());
+    initializeCurrentThreadEvenIfNonWTFCreated();
     return thread.get();
 }
 

Modified: trunk/Source/WTF/wtf/WTFThreadData.cpp (219175 => 219176)


--- trunk/Source/WTF/wtf/WTFThreadData.cpp	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WTF/wtf/WTFThreadData.cpp	2017-07-06 01:57:43 UTC (rev 219176)
@@ -44,12 +44,11 @@
     , m_currentAtomicStringTable(0)
     , m_defaultAtomicStringTable(0)
     , m_atomicStringTableDestructor(0)
-    , m_stackBounds(StackBounds::currentThreadStackBounds())
 #if ENABLE(STACK_STATS)
     , m_stackStats()
 #endif
     , m_savedStackPointerAtVMEntry(0)
-    , m_savedLastStackTop(stack().origin())
+    , m_savedLastStackTop(Thread::current().stack().origin())
 {
     AtomicStringTable::create(*this);
     m_currentAtomicStringTable = m_defaultAtomicStringTable;

Modified: trunk/Source/WTF/wtf/WTFThreadData.h (219175 => 219176)


--- trunk/Source/WTF/wtf/WTFThreadData.h	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WTF/wtf/WTFThreadData.h	2017-07-06 01:57:43 UTC (rev 219176)
@@ -29,7 +29,6 @@
 
 #include <wtf/FastTLS.h>
 #include <wtf/Noncopyable.h>
-#include <wtf/StackBounds.h>
 #include <wtf/StackStats.h>
 #include <wtf/ThreadSpecific.h>
 
@@ -57,16 +56,6 @@
         return oldAtomicStringTable;
     }
 
-    const StackBounds& stack()
-    {
-        // We need to always get a fresh StackBounds from the OS due to how fibers work.
-        // See https://bugs.webkit.org/show_bug.cgi?id=102411
-#if OS(WINDOWS)
-        m_stackBounds = StackBounds::currentThreadStackBounds();
-#endif
-        return m_stackBounds;
-    }
-
 #if ENABLE(STACK_STATS)
     StackStats::PerThreadStats& stackStats()
     {
@@ -101,7 +90,6 @@
     AtomicStringTable* m_defaultAtomicStringTable;
     AtomicStringTableDestructor m_atomicStringTableDestructor;
 
-    StackBounds m_stackBounds;
 #if ENABLE(STACK_STATS)
     StackStats::PerThreadStats m_stackStats;
 #endif

Modified: trunk/Source/WebCore/ChangeLog (219175 => 219176)


--- trunk/Source/WebCore/ChangeLog	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WebCore/ChangeLog	2017-07-06 01:57:43 UTC (rev 219176)
@@ -1,3 +1,28 @@
+2017-07-05  Yusuke Suzuki  <utatane....@gmail.com>
+
+        WTF::Thread should have the threads stack bounds.
+        https://bugs.webkit.org/show_bug.cgi?id=173975
+
+        Reviewed by Keith Miller.
+
+        When creating WebThread, we first allocate WebCore::ThreadGlobalData in UI thread
+        and share it with WebThread.
+        The problem is that WebCore::ThreadGlobalData has CachedResourceRequestInitiators.
+        It allocates AtomicString, which requires WTFThreadData.
+
+        Before this patch, it was OK because WTFThreadData does not touch threading related
+        things except for ThreadSpecific<>. However, after this patch, it touches
+        WTF::Thread::current() which requires WTF::initializeThreading().
+
+        In this patch, we call WTF::initializeThreading() before allocating WebCore::ThreadGlobalData.
+        And we also call AtomicString::init() before calling WebCore::ThreadGlobalData since
+        WebCore::ThreadGlobalData allocates AtomicString.
+
+        This fixes crashes in the iOS web threading environment (UIWebView).
+
+        * platform/ios/wak/WebCoreThread.mm:
+        (StartWebThread):
+
 2017-07-05  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         CSSFontStyleValue::isItalic seems a bit bogus.

Modified: trunk/Source/WebCore/platform/ios/wak/WebCoreThread.mm (219175 => 219176)


--- trunk/Source/WebCore/platform/ios/wak/WebCoreThread.mm	2017-07-06 01:55:11 UTC (rev 219175)
+++ trunk/Source/WebCore/platform/ios/wak/WebCoreThread.mm	2017-07-06 01:57:43 UTC (rev 219176)
@@ -704,14 +704,17 @@
 {
     webThreadStarted = TRUE;
 
+    // ThreadGlobalData touches AtomicString, which requires WTFThreadData and Threading initialization.
+    WTF::initializeThreading();
+
+    // Initialize AtomicString on the main thread.
+    WTF::AtomicString::init();
+
     // Initialize ThreadGlobalData on the main UI thread so that the WebCore thread
     // can later set it's thread-specific data to point to the same objects.
     WebCore::ThreadGlobalData& unused = WebCore::threadGlobalData();
     (void)unused;
 
-    // Initialize AtomicString on the main thread.
-    WTF::AtomicString::init();
-
     RunLoop::initializeMainRunLoop();
 
     // register class for WebThread deallocation
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to