2011-01-07 Geoffrey Garen <ggaren@apple.com>
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 9 Jan 2011 03:04:42 +0000 (03:04 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 9 Jan 2011 03:04:42 +0000 (03:04 +0000)
        Reviewed by Gavin Barraclough.

        Split machine stack marking functions into their own class (MachineStackMarker)
        https://bugs.webkit.org/show_bug.cgi?id=52088

        * API/APIShims.h:
        (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): Moved registerThread()
        call behind an #ifdef because we shouldn't be registering threads at all
        if we don't support usage on multiple threads.

        * Android.mk:
        * CMakeLists.txt:
        * GNUmakefile.am:
        * JavaScriptCore.gypi:
        * JavaScriptCore.pro:
        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
        * JavaScriptCore.xcodeproj/project.pbxproj: Updated projects.

        * runtime/Collector.cpp:
        (JSC::Heap::Heap):
        (JSC::Heap::destroy):
        (JSC::Heap::markRoots):
        * runtime/Collector.h:
        (JSC::Heap::machineStackMarker): Moved code to machineStackMarker.

        * runtime/JSGlobalData.h:
        (JSC::JSGlobalData::makeUsableFromMultipleThreads): Removed an unnecessary
        level of indirection, to make Heap less of a God class.

        * runtime/MachineStackMarker.h: Copied from Source/JavaScriptCore/runtime/Collector.h.
        * runtime/MachineStackMarker.cpp: Copied from Source/JavaScriptCore/runtime/Collector.cpp.
        (JSC::MachineStackMarker::MachineStackMarker):
        (JSC::MachineStackMarker::~MachineStackMarker):
        (JSC::MachineStackMarker::makeUsableFromMultipleThreads):
        (JSC::MachineStackMarker::registerThread):
        (JSC::MachineStackMarker::unregisterThread):
        (JSC::MachineStackMarker::markCurrentThreadConservativelyInternal):
        (JSC::MachineStackMarker::markCurrentThreadConservatively):
        (JSC::MachineStackMarker::markOtherThreadConservatively):
        (JSC::MachineStackMarker::markMachineStackConservatively): Moved code from Heap.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75342 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
Source/JavaScriptCore/API/APIShims.h
Source/JavaScriptCore/Android.mk
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/GNUmakefile.am
Source/JavaScriptCore/JavaScriptCore.gypi
Source/JavaScriptCore/JavaScriptCore.pro
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/runtime/Collector.cpp
Source/JavaScriptCore/runtime/Collector.h
Source/JavaScriptCore/runtime/JSGlobalData.h
Source/JavaScriptCore/runtime/MachineStackMarker.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/MachineStackMarker.h [new file with mode: 0644]

index 0b49d704bb098bc42029084126ed5ea1344258cd..26db2dc146f2f09fdcc7cd497db1a2376a9d5ddc 100644 (file)
@@ -39,8 +39,11 @@ protected:
         : m_globalData(globalData)
         , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable))
     {
+        UNUSED_PARAM(registerThread);
+#if ENABLE(JSC_MULTIPLE_THREADS)
         if (registerThread)
-            globalData->heap.registerThread();
+            globalData->heap.machineStackMarker().registerThread();
+#endif
         m_globalData->heap.activityCallback()->synchronize();
         m_globalData->timeoutChecker.start();
     }
index 9cb26d599a235d79290f7863e422b2ab48b4dc2d..490989a262679d857505092d131664f60ab17ce3 100644 (file)
@@ -125,6 +125,7 @@ LOCAL_SRC_FILES := \
        runtime/JSWrapperObject.cpp \
        runtime/LiteralParser.cpp \
        runtime/Lookup.cpp \
+       runtime/MachineStackMarker.cpp \
        runtime/MarkStack.cpp \
        runtime/MarkStackPosix.cpp \
        runtime/MathObject.cpp \
index f8b4d1e0aa7e2d2a11dfc828d1d9f0219ac36692..fd26d774d2f6d6c3394c82e574b931cde11168b4 100644 (file)
@@ -135,6 +135,7 @@ SET(JavaScriptCore_SOURCES
     runtime/JSZombie.cpp
     runtime/LiteralParser.cpp
     runtime/Lookup.cpp
+    runtime/MachineStackMarker.cpp
     runtime/MarkStack.cpp
     runtime/MathObject.cpp
     runtime/NativeErrorConstructor.cpp
index 54ac1e97f03c6fc5bb7100442aa47d85b5b2ea88..abb205c509188a344931ad431813007ed4746805 100644 (file)
@@ -1,3 +1,46 @@
+2011-01-07  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Gavin Barraclough.
+
+        Split machine stack marking functions into their own class (MachineStackMarker)
+        https://bugs.webkit.org/show_bug.cgi?id=52088
+
+        * API/APIShims.h:
+        (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): Moved registerThread()
+        call behind an #ifdef because we shouldn't be registering threads at all
+        if we don't support usage on multiple threads.
+
+        * Android.mk:
+        * CMakeLists.txt:
+        * GNUmakefile.am:
+        * JavaScriptCore.gypi:
+        * JavaScriptCore.pro:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj: Updated projects.
+
+        * runtime/Collector.cpp:
+        (JSC::Heap::Heap):
+        (JSC::Heap::destroy):
+        (JSC::Heap::markRoots):
+        * runtime/Collector.h:
+        (JSC::Heap::machineStackMarker): Moved code to machineStackMarker.
+
+        * runtime/JSGlobalData.h:
+        (JSC::JSGlobalData::makeUsableFromMultipleThreads): Removed an unnecessary
+        level of indirection, to make Heap less of a God class.
+
+        * runtime/MachineStackMarker.h: Copied from Source/JavaScriptCore/runtime/Collector.h.
+        * runtime/MachineStackMarker.cpp: Copied from Source/JavaScriptCore/runtime/Collector.cpp.
+        (JSC::MachineStackMarker::MachineStackMarker):
+        (JSC::MachineStackMarker::~MachineStackMarker):
+        (JSC::MachineStackMarker::makeUsableFromMultipleThreads):
+        (JSC::MachineStackMarker::registerThread):
+        (JSC::MachineStackMarker::unregisterThread):
+        (JSC::MachineStackMarker::markCurrentThreadConservativelyInternal):
+        (JSC::MachineStackMarker::markCurrentThreadConservatively):
+        (JSC::MachineStackMarker::markOtherThreadConservatively):
+        (JSC::MachineStackMarker::markMachineStackConservatively): Moved code from Heap.
+
 2011-01-07  Gavin Barraclough  <barraclough@apple.com>
 
         Reviewed by Geoff Garen.
index 93f10ee7051e94566f2608c8c4ff90386eb759dc..30e3f097cb24e887671e05ad5e2543f5fe32c567 100644 (file)
@@ -336,6 +336,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/LiteralParser.h \
        Source/JavaScriptCore/runtime/Lookup.cpp \
        Source/JavaScriptCore/runtime/Lookup.h \
+       Source/JavaScriptCore/runtime/MachineStackMarker.cpp \
+       Source/JavaScriptCore/runtime/MachineStackMarker.h \
        Source/JavaScriptCore/runtime/MarkStack.cpp \
        Source/JavaScriptCore/runtime/MarkStack.h \
        Source/JavaScriptCore/runtime/MathObject.cpp \
index e60969e876254e95d7b37874e4bdf7af2866b2d1..4f4da733ad38b3d753172238db83b9a6f564603e 100644 (file)
             'runtime/LiteralParser.h',
             'runtime/Lookup.cpp',
             'runtime/Lookup.h',
+            'runtime/MachineStackMarker.cpp',
+            'runtime/MachineStackMarker.h',
             'runtime/MarkStack.cpp',
             'runtime/MarkStack.h',
             'runtime/MarkStackWin.cpp',
index 86b1b9a6e2c49f1703a4a76df78f66c77cc70ba4..fa4ebfb07f6a399a2a14bd92d151533713d7e30d 100644 (file)
@@ -174,6 +174,7 @@ SOURCES += \
     runtime/JSWrapperObject.cpp \
     runtime/LiteralParser.cpp \
     runtime/Lookup.cpp \
+    runtime/MachineStackMarker.cpp \
     runtime/MarkStackPosix.cpp \
     runtime/MarkStackSymbian.cpp \
     runtime/MarkStackWin.cpp \
index 728436286a7b06bf546219a98d8af5ee544ab78a..328363e5d692b8aa0dd1dab5cacf17d017715666 100644 (file)
                                RelativePath="..\..\runtime\Lookup.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\runtime\MachineStackMarker.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\runtime\MachineStackMarker.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\runtime\MarkStack.cpp"
                                >
index 414f8b1e3d4a83a448dfb1156dcda106223d3f6f..e08d0b7ec0316d25ead77745716e2317b7e603f7 100644 (file)
                14ABDF600A437FEF00ECCA01 /* JSCallbackObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14ABDF5E0A437FEF00ECCA01 /* JSCallbackObject.cpp */; };
                14B3EF0512BC24DD00D29EFF /* PageBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 14B3EF0312BC24DD00D29EFF /* PageBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
                14B3EF0612BC24DD00D29EFF /* PageBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14B3EF0412BC24DD00D29EFF /* PageBlock.cpp */; };
+               14B723B212D7DA46003BD5ED /* MachineStackMarker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */; };
+               14B723B812D7DA6F003BD5ED /* MachineStackMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */; settings = {ATTRIBUTES = (Private, ); }; };
                14B8EC720A5652090062BE54 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */; };
                14BD59C50A3E8F9F00BAF59C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; };
                14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD5A290A3E91F600BAF59C /* JSContextRef.cpp */; };
                14ABDF5E0A437FEF00ECCA01 /* JSCallbackObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCallbackObject.cpp; sourceTree = "<group>"; };
                14B3EF0312BC24DD00D29EFF /* PageBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageBlock.h; sourceTree = "<group>"; };
                14B3EF0412BC24DD00D29EFF /* PageBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageBlock.cpp; sourceTree = "<group>"; };
+               14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MachineStackMarker.cpp; sourceTree = "<group>"; };
+               14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachineStackMarker.h; sourceTree = "<group>"; };
                14B8ECA60A5653980062BE54 /* JavaScriptCore.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = JavaScriptCore.exp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
                14BD59BF0A3E8F9000BAF59C /* testapi */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testapi; sourceTree = BUILT_PRODUCTS_DIR; };
                14BD5A290A3E91F600BAF59C /* JSContextRef.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSContextRef.cpp; sourceTree = "<group>"; };
                7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = {
                        isa = PBXGroup;
                        children = (
-                               DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */,
-                               DDF7ABD311F60ED200108E36 /* GCActivityCallbackCF.cpp */,
                                BCF605110E203EF800B9A64D /* ArgList.cpp */,
                                BCF605120E203EF800B9A64D /* ArgList.h */,
                                BC257DE50E1F51C50016B6C9 /* Arguments.cpp */,
                                BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */,
                                F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */,
                                F692A85D0255597D01FF60F7 /* FunctionPrototype.h */,
+                               DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */,
+                               DDF7ABD311F60ED200108E36 /* GCActivityCallbackCF.cpp */,
                                DDE82AD11209D955005C1756 /* GCHandle.cpp */,
                                DDE82AD21209D955005C1756 /* GCHandle.h */,
                                BC02E9B80E184545000F9297 /* GetterSetter.cpp */,
                                A7E2EA690FB460CF00601F06 /* LiteralParser.h */,
                                F692A8680255597D01FF60F7 /* Lookup.cpp */,
                                F692A8690255597D01FF60F7 /* Lookup.h */,
+                               14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */,
+                               14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */,
                                A74B3498102A5F8E0032AB98 /* MarkStack.cpp */,
                                A779558F101A74D500114E55 /* MarkStack.h */,
                                A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */,
                                7E2C6C980D31C6B6002D44E2 /* ScopeChainMark.h */,
                                93303FE80E6A72B500786E6A /* SmallStrings.cpp */,
                                93303FEA0E6A72C000786E6A /* SmallStrings.h */,
+                               A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */,
+                               A730B6101250068F009D25B1 /* StrictEvalActivation.h */,
                                BC18C3C00E16EE3300B34460 /* StringConstructor.cpp */,
                                BC18C3C10E16EE3300B34460 /* StringConstructor.h */,
                                BC18C3C20E16EE3300B34460 /* StringObject.cpp */,
                                14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
                                14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */,
                                1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
-                               A730B6101250068F009D25B1 /* StrictEvalActivation.h */,
-                               A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */,
                        );
                        path = runtime;
                        sourceTree = "<group>";
                                A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */,
                                BC18C4360E16F5CD00B34460 /* Locker.h in Headers */,
                                BC18C4370E16F5CD00B34460 /* Lookup.h in Headers */,
+                               14B723B812D7DA6F003BD5ED /* MachineStackMarker.h in Headers */,
                                86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */,
                                86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */,
                                86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */,
                                148F21B0107EC5410042EC2C /* Lexer.cpp in Sources */,
                                A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */,
                                14469DDE107EC7E700650446 /* Lookup.cpp in Sources */,
+                               14B723B212D7DA46003BD5ED /* MachineStackMarker.cpp in Sources */,
                                86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
                                06D358B30DAADAA4003B174E /* MainThread.cpp in Sources */,
                                06D358B40DAADAAA003B174E /* MainThreadMac.mm in Sources */,
                                14469DE1107EC7E700650446 /* NativeErrorPrototype.cpp in Sources */,
                                148F21B7107EC5470042EC2C /* Nodes.cpp in Sources */,
                                655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */,
+                               93854A9A12C93D3B00DAAF77 /* NullPtr.cpp in Sources */,
                                14469DE2107EC7E700650446 /* NumberConstructor.cpp in Sources */,
                                14469DE3107EC7E700650446 /* NumberObject.cpp in Sources */,
                                14469DE4107EC7E700650446 /* NumberPrototype.cpp in Sources */,
                                86EAC4970F93E8D1008EC948 /* RegexInterpreter.cpp in Sources */,
                                86EAC4990F93E8D1008EC948 /* RegexJIT.cpp in Sources */,
                                14280841107EC0930013E7B2 /* RegExp.cpp in Sources */,
+                               868D81A212C428CE0093DC84 /* RegexPattern.cpp in Sources */,
                                A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */,
                                14280842107EC0930013E7B2 /* RegExpConstructor.cpp in Sources */,
                                14280843107EC0930013E7B2 /* RegExpObject.cpp in Sources */,
-                               868D81A212C428CE0093DC84 /* RegexPattern.cpp in Sources */,
                                14280844107EC0930013E7B2 /* RegExpPrototype.cpp in Sources */,
                                1428083A107EC0750013E7B2 /* RegisterFile.cpp in Sources */,
                                86B99AB8117E391E00DF5A90 /* RopeImpl.cpp in Sources */,
                                14469DEA107EC7E700650446 /* ScopeChain.cpp in Sources */,
                                0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */,
                                9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */,
+                               86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */,
                                A730B6131250068F009D25B1 /* StrictEvalActivation.cpp in Sources */,
                                86438FC41265503E00E0DFCA /* StringBuilder.cpp in Sources */,
-                               86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */,
                                14469DEB107EC7E700650446 /* StringConstructor.cpp in Sources */,
                                868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */,
                                14469DEC107EC7E700650446 /* StringObject.cpp in Sources */,
                                E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */,
                                868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */,
                                86D08D5311793613006E5ED0 /* WTFThreadData.cpp in Sources */,
-                               93854A9A12C93D3B00DAAF77 /* NullPtr.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 38845cee45608bd3363a08c58cbbe757765b4ab4..e72938aa2ad307c6d90d48346a8ff4dcc829b119 100644 (file)
 #include <wtf/UnusedParam.h>
 #include <wtf/VMTags.h>
 
-#if OS(DARWIN)
-
-#include <mach/mach_init.h>
-#include <mach/mach_port.h>
-#include <mach/task.h>
-#include <mach/thread_act.h>
-#include <mach/vm_map.h>
-
-#elif OS(WINDOWS)
-
-#include <windows.h>
-#include <malloc.h>
-
-#elif OS(HAIKU)
-
-#include <OS.h>
-
-#elif OS(UNIX)
-
-#include <stdlib.h>
-#if !OS(HAIKU)
-#include <sys/mman.h>
-#endif
-#include <unistd.h>
-
-#if OS(SOLARIS)
-#include <thread.h>
-#else
-#include <pthread.h>
-#endif
-
-#if HAVE(PTHREAD_NP_H)
-#include <pthread_np.h>
-#endif
-
-#if OS(QNX)
-#include <fcntl.h>
-#include <sys/procfs.h>
-#include <stdio.h>
-#include <errno.h>
-#endif
-
-#endif
-
 #define COLLECT_ON_EVERY_ALLOCATION 0
 
 using std::max;
@@ -106,38 +62,10 @@ const size_t ALLOCATIONS_PER_COLLECTION = 3600;
 // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
 #define MIN_ARRAY_SIZE (static_cast<size_t>(14))
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-#if OS(DARWIN)
-typedef mach_port_t PlatformThread;
-#elif OS(WINDOWS)
-typedef HANDLE PlatformThread;
-#endif
-
-class Heap::Thread {
-public:
-    Thread(pthread_t pthread, const PlatformThread& platThread, void* base) 
-        : posixThread(pthread)
-        , platformThread(platThread)
-        , stackBase(base)
-    {
-    }
-
-    Thread* next;
-    pthread_t posixThread;
-    PlatformThread platformThread;
-    void* stackBase;
-};
-
-#endif
-
 Heap::Heap(JSGlobalData* globalData)
     : m_markListSet(0)
-#if ENABLE(JSC_MULTIPLE_THREADS)
-    , m_registeredThreads(0)
-    , m_currentThreadRegistrar(0)
-#endif
     , m_globalData(globalData)
+    , m_machineStackMarker(this)
 {
     ASSERT(globalData);
     memset(&m_heap, 0, sizeof(CollectorHeap));
@@ -171,19 +99,6 @@ void Heap::destroy()
 
     freeBlocks();
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-    if (m_currentThreadRegistrar) {
-        int error = pthread_key_delete(m_currentThreadRegistrar);
-        ASSERT_UNUSED(error, !error);
-    }
-
-    MutexLocker registeredThreadsLock(m_registeredThreadsMutex);
-    for (Heap::Thread* t = m_registeredThreads; t;) {
-        Heap::Thread* next = t->next;
-        delete t;
-        t = next;
-    }
-#endif
     m_globalData = 0;
 }
 
@@ -385,82 +300,6 @@ void Heap::shrinkBlocks(size_t neededBlocks)
         m_heap.collectorBlock(i)->marked.set(HeapConstants::cellsPerBlock - 1);
 }
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-static inline PlatformThread getCurrentPlatformThread()
-{
-#if OS(DARWIN)
-    return pthread_mach_thread_np(pthread_self());
-#elif OS(WINDOWS)
-    return pthread_getw32threadhandle_np(pthread_self());
-#endif
-}
-
-void Heap::makeUsableFromMultipleThreads()
-{
-    if (m_currentThreadRegistrar)
-        return;
-
-    int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread);
-    if (error)
-        CRASH();
-}
-
-void Heap::registerThread()
-{
-    ASSERT(!m_globalData->exclusiveThread || m_globalData->exclusiveThread == currentThread());
-
-    if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar))
-        return;
-
-    pthread_setspecific(m_currentThreadRegistrar, this);
-    Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), m_globalData->stack().origin());
-
-    MutexLocker lock(m_registeredThreadsMutex);
-
-    thread->next = m_registeredThreads;
-    m_registeredThreads = thread;
-}
-
-void Heap::unregisterThread(void* p)
-{
-    if (p)
-        static_cast<Heap*>(p)->unregisterThread();
-}
-
-void Heap::unregisterThread()
-{
-    pthread_t currentPosixThread = pthread_self();
-
-    MutexLocker lock(m_registeredThreadsMutex);
-
-    if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) {
-        Thread* t = m_registeredThreads;
-        m_registeredThreads = m_registeredThreads->next;
-        delete t;
-    } else {
-        Heap::Thread* last = m_registeredThreads;
-        Heap::Thread* t;
-        for (t = m_registeredThreads->next; t; t = t->next) {
-            if (pthread_equal(t->posixThread, currentPosixThread)) {
-                last->next = t->next;
-                break;
-            }
-            last = t;
-        }
-        ASSERT(t); // If t is NULL, we never found ourselves in the list.
-        delete t;
-    }
-}
-
-#else // ENABLE(JSC_MULTIPLE_THREADS)
-
-void Heap::registerThread()
-{
-}
-
-#endif
-
 inline bool isPointerAligned(void* p)
 {
     return (((intptr_t)(p) & (sizeof(char*) - 1)) == 0);
@@ -521,212 +360,6 @@ void Heap::markConservatively(MarkStack& markStack, void* start, void* end)
     }
 }
 
-void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(MarkStack& markStack)
-{
-    markConservatively(markStack, m_globalData->stack().current(), m_globalData->stack().origin());
-    markStack.drain();
-}
-
-#if COMPILER(GCC)
-#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
-#else
-#define REGISTER_BUFFER_ALIGNMENT
-#endif
-
-void Heap::markCurrentThreadConservatively(MarkStack& markStack)
-{
-    // setjmp forces volatile registers onto the stack
-    jmp_buf registers REGISTER_BUFFER_ALIGNMENT;
-#if COMPILER(MSVC)
-#pragma warning(push)
-#pragma warning(disable: 4611)
-#endif
-    setjmp(registers);
-#if COMPILER(MSVC)
-#pragma warning(pop)
-#endif
-
-    markCurrentThreadConservativelyInternal(markStack);
-}
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-static inline void suspendThread(const PlatformThread& platformThread)
-{
-#if OS(DARWIN)
-    thread_suspend(platformThread);
-#elif OS(WINDOWS)
-    SuspendThread(platformThread);
-#else
-#error Need a way to suspend threads on this platform
-#endif
-}
-
-static inline void resumeThread(const PlatformThread& platformThread)
-{
-#if OS(DARWIN)
-    thread_resume(platformThread);
-#elif OS(WINDOWS)
-    ResumeThread(platformThread);
-#else
-#error Need a way to resume threads on this platform
-#endif
-}
-
-typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
-
-#if OS(DARWIN)
-
-#if CPU(X86)
-typedef i386_thread_state_t PlatformThreadRegisters;
-#elif CPU(X86_64)
-typedef x86_thread_state64_t PlatformThreadRegisters;
-#elif CPU(PPC)
-typedef ppc_thread_state_t PlatformThreadRegisters;
-#elif CPU(PPC64)
-typedef ppc_thread_state64_t PlatformThreadRegisters;
-#elif CPU(ARM)
-typedef arm_thread_state_t PlatformThreadRegisters;
-#else
-#error Unknown Architecture
-#endif
-
-#elif OS(WINDOWS) && CPU(X86)
-typedef CONTEXT PlatformThreadRegisters;
-#else
-#error Need a thread register struct for this platform
-#endif
-
-static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
-{
-#if OS(DARWIN)
-
-#if CPU(X86)
-    unsigned user_count = sizeof(regs)/sizeof(int);
-    thread_state_flavor_t flavor = i386_THREAD_STATE;
-#elif CPU(X86_64)
-    unsigned user_count = x86_THREAD_STATE64_COUNT;
-    thread_state_flavor_t flavor = x86_THREAD_STATE64;
-#elif CPU(PPC) 
-    unsigned user_count = PPC_THREAD_STATE_COUNT;
-    thread_state_flavor_t flavor = PPC_THREAD_STATE;
-#elif CPU(PPC64)
-    unsigned user_count = PPC_THREAD_STATE64_COUNT;
-    thread_state_flavor_t flavor = PPC_THREAD_STATE64;
-#elif CPU(ARM)
-    unsigned user_count = ARM_THREAD_STATE_COUNT;
-    thread_state_flavor_t flavor = ARM_THREAD_STATE;
-#else
-#error Unknown Architecture
-#endif
-
-    kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
-    if (result != KERN_SUCCESS) {
-        WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 
-                            "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
-        CRASH();
-    }
-    return user_count * sizeof(usword_t);
-// end OS(DARWIN)
-
-#elif OS(WINDOWS) && CPU(X86)
-    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
-    GetThreadContext(platformThread, &regs);
-    return sizeof(CONTEXT);
-#else
-#error Need a way to get thread registers on this platform
-#endif
-}
-
-static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
-{
-#if OS(DARWIN)
-
-#if __DARWIN_UNIX03
-
-#if CPU(X86)
-    return reinterpret_cast<void*>(regs.__esp);
-#elif CPU(X86_64)
-    return reinterpret_cast<void*>(regs.__rsp);
-#elif CPU(PPC) || CPU(PPC64)
-    return reinterpret_cast<void*>(regs.__r1);
-#elif CPU(ARM)
-    return reinterpret_cast<void*>(regs.__sp);
-#else
-#error Unknown Architecture
-#endif
-
-#else // !__DARWIN_UNIX03
-
-#if CPU(X86)
-    return reinterpret_cast<void*>(regs.esp);
-#elif CPU(X86_64)
-    return reinterpret_cast<void*>(regs.rsp);
-#elif CPU(PPC) || CPU(PPC64)
-    return reinterpret_cast<void*>(regs.r1);
-#else
-#error Unknown Architecture
-#endif
-
-#endif // __DARWIN_UNIX03
-
-// end OS(DARWIN)
-#elif CPU(X86) && OS(WINDOWS)
-    return reinterpret_cast<void*>((uintptr_t) regs.Esp);
-#else
-#error Need a way to get the stack pointer for another thread on this platform
-#endif
-}
-
-void Heap::markOtherThreadConservatively(MarkStack& markStack, Thread* thread)
-{
-    suspendThread(thread->platformThread);
-
-    PlatformThreadRegisters regs;
-    size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
-
-    // mark the thread's registers
-    markConservatively(markStack, static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
-    markStack.drain();
-
-    void* stackPointer = otherThreadStackPointer(regs);
-    markConservatively(markStack, stackPointer, thread->stackBase);
-    markStack.drain();
-
-    resumeThread(thread->platformThread);
-}
-
-#endif
-
-void Heap::markStackObjectsConservatively(MarkStack& markStack)
-{
-    markCurrentThreadConservatively(markStack);
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-    if (m_currentThreadRegistrar) {
-
-        MutexLocker lock(m_registeredThreadsMutex);
-
-#ifndef NDEBUG
-        // Forbid malloc during the mark phase. Marking a thread suspends it, so 
-        // a malloc inside markChildren() would risk a deadlock with a thread that had been 
-        // suspended while holding the malloc lock.
-        fastMallocForbid();
-#endif
-        // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held,
-        // and since this is a shared heap, they are real locks.
-        for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
-            if (!pthread_equal(thread->posixThread, pthread_self()))
-                markOtherThreadConservatively(markStack, thread);
-        }
-#ifndef NDEBUG
-        fastMallocAllow();
-#endif
-    }
-#endif
-}
-
 void Heap::updateWeakGCHandles()
 {
     for (unsigned i = 0; i < m_weakGCHandlePools.size(); ++i)
@@ -897,7 +530,7 @@ void Heap::markRoots()
     clearMarkBits();
 
     // Mark stack roots.
-    markStackObjectsConservatively(markStack);
+    m_machineStackMarker.markMachineStackConservatively(markStack);
     m_globalData->interpreter->registerFile().markCallFrames(markStack, this);
 
     // Mark explicitly registered roots.
index a4e2fe1b6e1a12595271111f1713eba4c4c10fd9..349fc4c3a831a77c20a334b49fe5dd52b42a4b97 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "GCHandle.h"
 #include "JSValue.h"
+#include "MachineStackMarker.h"
 #include <stddef.h>
 #include <string.h>
 #include <wtf/Bitmap.h>
 #include <wtf/PageAllocationAligned.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/StdLibExtras.h>
-#include <wtf/Threading.h>
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#include <pthread.h>
-#endif
 
 #define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell)
 
@@ -87,8 +83,6 @@ namespace JSC {
 
     class Heap : public Noncopyable {
     public:
-        class Thread;
-
         void destroy();
 
         void* allocateNumber(size_t);
@@ -127,8 +121,6 @@ namespace JSC {
         HashCountedSet<const char*>* protectedObjectTypeCounts();
         HashCountedSet<const char*>* objectTypeCounts();
 
-        void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
-
         static bool isCellMarked(const JSCell*);
         static bool checkMarkCell(const JSCell*);
         static void markCell(JSCell*);
@@ -148,6 +140,8 @@ namespace JSC {
         LiveObjectIterator primaryHeapBegin();
         LiveObjectIterator primaryHeapEnd();
 
+        MachineStackMarker& machineStackMarker() { return m_machineStackMarker; }
+
     private:
         void reset();
         void sweep();
@@ -175,10 +169,6 @@ namespace JSC {
         void markRoots();
         void markProtectedObjects(MarkStack&);
         void markTempSortVectors(MarkStack&);
-        void markCurrentThreadConservatively(MarkStack&);
-        void markCurrentThreadConservativelyInternal(MarkStack&);
-        void markOtherThreadConservatively(MarkStack&, Thread*);
-        void markStackObjectsConservatively(MarkStack&);
 
         void updateWeakGCHandles();
         WeakGCHandlePool* weakGCHandlePool(size_t index);
@@ -195,18 +185,9 @@ namespace JSC {
 
         OwnPtr<GCActivityCallback> m_activityCallback;
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-        void makeUsableFromMultipleThreads();
-
-        static void unregisterThread(void*);
-        void unregisterThread();
-
-        Mutex m_registeredThreadsMutex;
-        Thread* m_registeredThreads;
-        pthread_key_t m_currentThreadRegistrar;
-#endif
-
         JSGlobalData* m_globalData;
+        
+        MachineStackMarker m_machineStackMarker;
     };
 
     // tunable parameters
index 699f97592f689a57a525215cfcf2a85169ec9118..b4a6440dbcf2adc53d3491fe61530bf99de30afe 100644 (file)
@@ -128,7 +128,7 @@ namespace JSC {
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
         // Will start tracking threads that use the heap, which is resource-heavy.
-        void makeUsableFromMultipleThreads() { heap.makeUsableFromMultipleThreads(); }
+        void makeUsableFromMultipleThreads() { heap.machineStackMarker().makeUsableFromMultipleThreads(); }
 #endif
 
         GlobalDataType globalDataType;
diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp
new file mode 100644 (file)
index 0000000..22c2a87
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "MachineStackMarker.h"
+
+#include "Collector.h"
+#include "JSArray.h"
+#include "JSGlobalData.h"
+#include <setjmp.h>
+#include <stdlib.h>
+
+#if OS(DARWIN)
+
+#include <mach/mach_init.h>
+#include <mach/mach_port.h>
+#include <mach/task.h>
+#include <mach/thread_act.h>
+#include <mach/vm_map.h>
+
+#elif OS(WINDOWS)
+
+#include <windows.h>
+#include <malloc.h>
+
+#elif OS(HAIKU)
+
+#include <OS.h>
+
+#elif OS(UNIX)
+
+#include <stdlib.h>
+#if !OS(HAIKU)
+#include <sys/mman.h>
+#endif
+#include <unistd.h>
+
+#if OS(SOLARIS)
+#include <thread.h>
+#else
+#include <pthread.h>
+#endif
+
+#if HAVE(PTHREAD_NP_H)
+#include <pthread_np.h>
+#endif
+
+#if OS(QNX)
+#include <fcntl.h>
+#include <sys/procfs.h>
+#include <stdio.h>
+#include <errno.h>
+#endif
+
+#endif
+
+namespace JSC {
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+#if OS(DARWIN)
+typedef mach_port_t PlatformThread;
+#elif OS(WINDOWS)
+typedef HANDLE PlatformThread;
+#endif
+
+class MachineStackMarker::Thread {
+public:
+    Thread(pthread_t pthread, const PlatformThread& platThread, void* base) 
+        : posixThread(pthread)
+        , platformThread(platThread)
+        , stackBase(base)
+    {
+    }
+
+    Thread* next;
+    pthread_t posixThread;
+    PlatformThread platformThread;
+    void* stackBase;
+};
+
+#endif
+
+MachineStackMarker::MachineStackMarker(Heap* heap)
+    : m_heap(heap)
+#if ENABLE(JSC_MULTIPLE_THREADS)
+    , m_registeredThreads(0)
+    , m_currentThreadRegistrar(0)
+#endif
+{
+}
+
+MachineStackMarker::~MachineStackMarker()
+{
+#if ENABLE(JSC_MULTIPLE_THREADS)
+    if (m_currentThreadRegistrar) {
+        int error = pthread_key_delete(m_currentThreadRegistrar);
+        ASSERT_UNUSED(error, !error);
+    }
+
+    MutexLocker registeredThreadsLock(m_registeredThreadsMutex);
+    for (Thread* t = m_registeredThreads; t;) {
+        Thread* next = t->next;
+        delete t;
+        t = next;
+    }
+#endif
+}
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+static inline PlatformThread getCurrentPlatformThread()
+{
+#if OS(DARWIN)
+    return pthread_mach_thread_np(pthread_self());
+#elif OS(WINDOWS)
+    return pthread_getw32threadhandle_np(pthread_self());
+#endif
+}
+
+void MachineStackMarker::makeUsableFromMultipleThreads()
+{
+    if (m_currentThreadRegistrar)
+        return;
+
+    int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread);
+    if (error)
+        CRASH();
+}
+
+void MachineStackMarker::registerThread()
+{
+    ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread());
+
+    if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar))
+        return;
+
+    pthread_setspecific(m_currentThreadRegistrar, this);
+    Thread* thread = new Thread(pthread_self(), getCurrentPlatformThread(), m_heap->globalData()->stack().origin());
+
+    MutexLocker lock(m_registeredThreadsMutex);
+
+    thread->next = m_registeredThreads;
+    m_registeredThreads = thread;
+}
+
+void MachineStackMarker::unregisterThread(void* p)
+{
+    if (p)
+        static_cast<MachineStackMarker*>(p)->unregisterThread();
+}
+
+void MachineStackMarker::unregisterThread()
+{
+    pthread_t currentPosixThread = pthread_self();
+
+    MutexLocker lock(m_registeredThreadsMutex);
+
+    if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) {
+        Thread* t = m_registeredThreads;
+        m_registeredThreads = m_registeredThreads->next;
+        delete t;
+    } else {
+        Thread* last = m_registeredThreads;
+        Thread* t;
+        for (t = m_registeredThreads->next; t; t = t->next) {
+            if (pthread_equal(t->posixThread, currentPosixThread)) {
+                last->next = t->next;
+                break;
+            }
+            last = t;
+        }
+        ASSERT(t); // If t is NULL, we never found ourselves in the list.
+        delete t;
+    }
+}
+
+#endif
+
+void NEVER_INLINE MachineStackMarker::markCurrentThreadConservativelyInternal(MarkStack& markStack)
+{
+    m_heap->markConservatively(markStack, m_heap->globalData()->stack().current(), m_heap->globalData()->stack().origin());
+    markStack.drain();
+}
+
+#if COMPILER(GCC)
+#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
+#else
+#define REGISTER_BUFFER_ALIGNMENT
+#endif
+
+void MachineStackMarker::markCurrentThreadConservatively(MarkStack& markStack)
+{
+    // setjmp forces volatile registers onto the stack
+    jmp_buf registers REGISTER_BUFFER_ALIGNMENT;
+#if COMPILER(MSVC)
+#pragma warning(push)
+#pragma warning(disable: 4611)
+#endif
+    setjmp(registers);
+#if COMPILER(MSVC)
+#pragma warning(pop)
+#endif
+
+    markCurrentThreadConservativelyInternal(markStack);
+}
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+static inline void suspendThread(const PlatformThread& platformThread)
+{
+#if OS(DARWIN)
+    thread_suspend(platformThread);
+#elif OS(WINDOWS)
+    SuspendThread(platformThread);
+#else
+#error Need a way to suspend threads on this platform
+#endif
+}
+
+static inline void resumeThread(const PlatformThread& platformThread)
+{
+#if OS(DARWIN)
+    thread_resume(platformThread);
+#elif OS(WINDOWS)
+    ResumeThread(platformThread);
+#else
+#error Need a way to resume threads on this platform
+#endif
+}
+
+typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
+
+#if OS(DARWIN)
+
+#if CPU(X86)
+typedef i386_thread_state_t PlatformThreadRegisters;
+#elif CPU(X86_64)
+typedef x86_thread_state64_t PlatformThreadRegisters;
+#elif CPU(PPC)
+typedef ppc_thread_state_t PlatformThreadRegisters;
+#elif CPU(PPC64)
+typedef ppc_thread_state64_t PlatformThreadRegisters;
+#elif CPU(ARM)
+typedef arm_thread_state_t PlatformThreadRegisters;
+#else
+#error Unknown Architecture
+#endif
+
+#elif OS(WINDOWS) && CPU(X86)
+typedef CONTEXT PlatformThreadRegisters;
+#else
+#error Need a thread register struct for this platform
+#endif
+
+static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
+{
+#if OS(DARWIN)
+
+#if CPU(X86)
+    unsigned user_count = sizeof(regs)/sizeof(int);
+    thread_state_flavor_t flavor = i386_THREAD_STATE;
+#elif CPU(X86_64)
+    unsigned user_count = x86_THREAD_STATE64_COUNT;
+    thread_state_flavor_t flavor = x86_THREAD_STATE64;
+#elif CPU(PPC) 
+    unsigned user_count = PPC_THREAD_STATE_COUNT;
+    thread_state_flavor_t flavor = PPC_THREAD_STATE;
+#elif CPU(PPC64)
+    unsigned user_count = PPC_THREAD_STATE64_COUNT;
+    thread_state_flavor_t flavor = PPC_THREAD_STATE64;
+#elif CPU(ARM)
+    unsigned user_count = ARM_THREAD_STATE_COUNT;
+    thread_state_flavor_t flavor = ARM_THREAD_STATE;
+#else
+#error Unknown Architecture
+#endif
+
+    kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
+    if (result != KERN_SUCCESS) {
+        WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 
+                            "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
+        CRASH();
+    }
+    return user_count * sizeof(usword_t);
+// end OS(DARWIN)
+
+#elif OS(WINDOWS) && CPU(X86)
+    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
+    GetThreadContext(platformThread, &regs);
+    return sizeof(CONTEXT);
+#else
+#error Need a way to get thread registers on this platform
+#endif
+}
+
+static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
+{
+#if OS(DARWIN)
+
+#if __DARWIN_UNIX03
+
+#if CPU(X86)
+    return reinterpret_cast<void*>(regs.__esp);
+#elif CPU(X86_64)
+    return reinterpret_cast<void*>(regs.__rsp);
+#elif CPU(PPC) || CPU(PPC64)
+    return reinterpret_cast<void*>(regs.__r1);
+#elif CPU(ARM)
+    return reinterpret_cast<void*>(regs.__sp);
+#else
+#error Unknown Architecture
+#endif
+
+#else // !__DARWIN_UNIX03
+
+#if CPU(X86)
+    return reinterpret_cast<void*>(regs.esp);
+#elif CPU(X86_64)
+    return reinterpret_cast<void*>(regs.rsp);
+#elif CPU(PPC) || CPU(PPC64)
+    return reinterpret_cast<void*>(regs.r1);
+#else
+#error Unknown Architecture
+#endif
+
+#endif // __DARWIN_UNIX03
+
+// end OS(DARWIN)
+#elif CPU(X86) && OS(WINDOWS)
+    return reinterpret_cast<void*>((uintptr_t) regs.Esp);
+#else
+#error Need a way to get the stack pointer for another thread on this platform
+#endif
+}
+
+void MachineStackMarker::markOtherThreadConservatively(MarkStack& markStack, Thread* thread)
+{
+    suspendThread(thread->platformThread);
+
+    PlatformThreadRegisters regs;
+    size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
+
+    // mark the thread's registers
+    m_heap->markConservatively(markStack, static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
+    markStack.drain();
+
+    void* stackPointer = otherThreadStackPointer(regs);
+    m_heap->markConservatively(markStack, stackPointer, thread->stackBase);
+    markStack.drain();
+
+    resumeThread(thread->platformThread);
+}
+
+#endif
+
+void MachineStackMarker::markMachineStackConservatively(MarkStack& markStack)
+{
+    markCurrentThreadConservatively(markStack);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+    if (m_currentThreadRegistrar) {
+
+        MutexLocker lock(m_registeredThreadsMutex);
+
+#ifndef NDEBUG
+        // Forbid malloc during the mark phase. Marking a thread suspends it, so 
+        // a malloc inside markChildren() would risk a deadlock with a thread that had been 
+        // suspended while holding the malloc lock.
+        fastMallocForbid();
+#endif
+        // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held,
+        // and since this is a shared heap, they are real locks.
+        for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
+            if (!pthread_equal(thread->posixThread, pthread_self()))
+                markOtherThreadConservatively(markStack, thread);
+        }
+#ifndef NDEBUG
+        fastMallocAllow();
+#endif
+    }
+#endif
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.h b/Source/JavaScriptCore/runtime/MachineStackMarker.h
new file mode 100644 (file)
index 0000000..e80fe05
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef MachineStackMarker_h
+#define MachineStackMarker_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/ThreadingPrimitives.h>
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#include <pthread.h>
+#endif
+
+namespace JSC {
+
+    class Heap;
+    class MarkStack;
+
+    class MachineStackMarker : public Noncopyable {
+    public:
+        MachineStackMarker(Heap*);
+        ~MachineStackMarker();
+
+        void markMachineStackConservatively(MarkStack&);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+        void makeUsableFromMultipleThreads();
+        void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
+#endif
+
+    private:
+        void markCurrentThreadConservatively(MarkStack&);
+        void markCurrentThreadConservativelyInternal(MarkStack&);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+        class Thread;
+
+        static void unregisterThread(void*);
+
+        void unregisterThread();
+        void markOtherThreadConservatively(MarkStack&, Thread*);
+#endif
+
+        Heap* m_heap;
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+        Mutex m_registeredThreadsMutex;
+        Thread* m_registeredThreads;
+        pthread_key_t m_currentThreadRegistrar;
+#endif
+    };
+
+} // namespace JSC
+
+#endif // MachineStackMarker_h