Changeset 157539 in webkit


Ignore:
Timestamp:
Oct 16, 2013, 4:47:45 PM (11 years ago)
Author:
mhahnenberg@apple.com
Message:

llint_slow_path_put_by_id can deadlock on a ConcurrentJITLock
https://bugs.webkit.org/show_bug.cgi?id=122667

Reviewed by Geoffrey Garen.

The issue this patch is attempting to fix is that there are places in our codebase
where we acquire the ConcurrentJITLock for a particular CodeBlock, then we do some
operations that can initiate a garbage collection. Garbage collection then calls
some methods of CodeBlock that also take the ConcurrentJITLock (because they don't
always necessarily run during garbage collection). This causes a deadlock.

To fix this issue, this patch adds a new RAII-style object (DisallowGC) that stores
into a thread-local field that indicates that it is unsafe to perform any operation
that could trigger garbage collection on the current thread. In debug builds,
ConcurrentJITLocker contains one of these DisallowGC objects so that we can eagerly
detect deadlocks.

This patch also adds a new type of ConcurrentJITLocker, GCSafeConcurrentJITLocker,
which uses the DeferGC mechanism to prevent collections from occurring while the
lock is held.

(JSC::DisallowGC::DisallowGC):
(JSC::DisallowGC::~DisallowGC):
(JSC::DisallowGC::isGCDisallowedOnCurrentThread):
(JSC::DisallowGC::initialize):

  • jit/Repatch.cpp:

(JSC::repatchPutByID):
(JSC::buildPutByIdList):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • runtime/ConcurrentJITLock.h:

(JSC::ConcurrentJITLockerBase::ConcurrentJITLockerBase):
(JSC::ConcurrentJITLockerBase::~ConcurrentJITLockerBase):
(JSC::ConcurrentJITLockerBase::unlockEarly):
(JSC::GCSafeConcurrentJITLocker::GCSafeConcurrentJITLocker):
(JSC::GCSafeConcurrentJITLocker::~GCSafeConcurrentJITLocker):
(JSC::GCSafeConcurrentJITLocker::NoDefer::NoDefer):
(JSC::ConcurrentJITLocker::ConcurrentJITLocker):

  • runtime/InitializeThreading.cpp:

(JSC::initializeThreadingOnce):

  • runtime/JSCellInlines.h:

(JSC::allocateCell):

  • runtime/JSSymbolTableObject.h:

(JSC::symbolTablePut):

  • runtime/Structure.cpp: materializePropertyMapIfNecessary* now has a problem in that it

can start a garbage collection when the GCSafeConcurrentJITLocker goes out of scope, but
before the caller has a chance to use the newly created PropertyTable. The garbage collection
clears the PropertyTable, and then the caller uses it assuming it's valid. To avoid this,
we must DeferGC until the caller is done getting the newly materialized PropertyTable from
the Structure.
(JSC::Structure::materializePropertyMap):
(JSC::Structure::despecifyDictionaryFunction):
(JSC::Structure::changePrototypeTransition):
(JSC::Structure::despecifyFunctionTransition):
(JSC::Structure::attributeChangeTransition):
(JSC::Structure::toDictionaryTransition):
(JSC::Structure::preventExtensionsTransition):
(JSC::Structure::takePropertyTableOrCloneIfPinned):
(JSC::Structure::isSealed):
(JSC::Structure::isFrozen):
(JSC::Structure::addPropertyWithoutTransition):
(JSC::Structure::removePropertyWithoutTransition):
(JSC::Structure::get):
(JSC::Structure::despecifyFunction):
(JSC::Structure::despecifyAllFunctions):
(JSC::Structure::putSpecificValue):
(JSC::Structure::createPropertyMap):
(JSC::Structure::getPropertyNamesFromStructure):

  • runtime/Structure.h:

(JSC::Structure::materializePropertyMapIfNecessary):
(JSC::Structure::materializePropertyMapIfNecessaryForPinning):

  • runtime/StructureInlines.h:

(JSC::Structure::get):

  • runtime/SymbolTable.h:

(JSC::SymbolTable::find):
(JSC::SymbolTable::end):

Location:
trunk/Source/JavaScriptCore
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r157424 r157539  
    182182    heap/CopiedSpace.cpp
    183183    heap/CopyVisitor.cpp
     184    heap/DeferGC.cpp
    184185    heap/GCThread.cpp
    185186    heap/GCThreadSharedData.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r157537 r157539  
     12013-10-16  Mark Hahnenberg  <mhahnenberg@apple.com>
     2
     3        llint_slow_path_put_by_id can deadlock on a ConcurrentJITLock
     4        https://bugs.webkit.org/show_bug.cgi?id=122667
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        The issue this patch is attempting to fix is that there are places in our codebase
     9        where we acquire the ConcurrentJITLock for a particular CodeBlock, then we do some
     10        operations that can initiate a garbage collection. Garbage collection then calls
     11        some methods of CodeBlock that also take the ConcurrentJITLock (because they don't
     12        always necessarily run during garbage collection). This causes a deadlock.
     13 
     14        To fix this issue, this patch adds a new RAII-style object (DisallowGC) that stores
     15        into a thread-local field that indicates that it is unsafe to perform any operation
     16        that could trigger garbage collection on the current thread. In debug builds,
     17        ConcurrentJITLocker contains one of these DisallowGC objects so that we can eagerly
     18        detect deadlocks.
     19 
     20        This patch also adds a new type of ConcurrentJITLocker, GCSafeConcurrentJITLocker,
     21        which uses the DeferGC mechanism to prevent collections from occurring while the
     22        lock is held.
     23
     24        * CMakeLists.txt:
     25        * GNUmakefile.list.am:
     26        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     27        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     28        * JavaScriptCore.xcodeproj/project.pbxproj:
     29        * heap/DeferGC.h:
     30        (JSC::DisallowGC::DisallowGC):
     31        (JSC::DisallowGC::~DisallowGC):
     32        (JSC::DisallowGC::isGCDisallowedOnCurrentThread):
     33        (JSC::DisallowGC::initialize):
     34        * jit/Repatch.cpp:
     35        (JSC::repatchPutByID):
     36        (JSC::buildPutByIdList):
     37        * llint/LLIntSlowPaths.cpp:
     38        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     39        * runtime/ConcurrentJITLock.h:
     40        (JSC::ConcurrentJITLockerBase::ConcurrentJITLockerBase):
     41        (JSC::ConcurrentJITLockerBase::~ConcurrentJITLockerBase):
     42        (JSC::ConcurrentJITLockerBase::unlockEarly):
     43        (JSC::GCSafeConcurrentJITLocker::GCSafeConcurrentJITLocker):
     44        (JSC::GCSafeConcurrentJITLocker::~GCSafeConcurrentJITLocker):
     45        (JSC::GCSafeConcurrentJITLocker::NoDefer::NoDefer):
     46        (JSC::ConcurrentJITLocker::ConcurrentJITLocker):
     47        * runtime/InitializeThreading.cpp:
     48        (JSC::initializeThreadingOnce):
     49        * runtime/JSCellInlines.h:
     50        (JSC::allocateCell):
     51        * runtime/JSSymbolTableObject.h:
     52        (JSC::symbolTablePut):
     53        * runtime/Structure.cpp: materializePropertyMapIfNecessary* now has a problem in that it
     54        can start a garbage collection when the GCSafeConcurrentJITLocker goes out of scope, but
     55        before the caller has a chance to use the newly created PropertyTable. The garbage collection
     56        clears the PropertyTable, and then the caller uses it assuming it's valid. To avoid this,
     57        we must DeferGC until the caller is done getting the newly materialized PropertyTable from
     58        the Structure.
     59        (JSC::Structure::materializePropertyMap):
     60        (JSC::Structure::despecifyDictionaryFunction):
     61        (JSC::Structure::changePrototypeTransition):
     62        (JSC::Structure::despecifyFunctionTransition):
     63        (JSC::Structure::attributeChangeTransition):
     64        (JSC::Structure::toDictionaryTransition):
     65        (JSC::Structure::preventExtensionsTransition):
     66        (JSC::Structure::takePropertyTableOrCloneIfPinned):
     67        (JSC::Structure::isSealed):
     68        (JSC::Structure::isFrozen):
     69        (JSC::Structure::addPropertyWithoutTransition):
     70        (JSC::Structure::removePropertyWithoutTransition):
     71        (JSC::Structure::get):
     72        (JSC::Structure::despecifyFunction):
     73        (JSC::Structure::despecifyAllFunctions):
     74        (JSC::Structure::putSpecificValue):
     75        (JSC::Structure::createPropertyMap):
     76        (JSC::Structure::getPropertyNamesFromStructure):
     77        * runtime/Structure.h:
     78        (JSC::Structure::materializePropertyMapIfNecessary):
     79        (JSC::Structure::materializePropertyMapIfNecessaryForPinning):
     80        * runtime/StructureInlines.h:
     81        (JSC::Structure::get):
     82        * runtime/SymbolTable.h:
     83        (JSC::SymbolTable::find):
     84        (JSC::SymbolTable::end):
     85
    1862013-10-16  Daniel Bates  <dabates@apple.com>
    287
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r157424 r157539  
    468468        Source/JavaScriptCore/heap/ConservativeRoots.cpp \
    469469        Source/JavaScriptCore/heap/ConservativeRoots.h \
     470   Source/JavaScriptCore/heap/DeferGC.cpp \
    470471        Source/JavaScriptCore/heap/DeferGC.h \
    471472        Source/JavaScriptCore/heap/GCAssertions.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r157424 r157539  
    337337    <ClCompile Include="..\heap\CopiedSpace.cpp" />
    338338    <ClCompile Include="..\heap\CopyVisitor.cpp" />
     339    <ClCompile Include="..\heap\DeferGC.cpp" />
    339340    <ClCompile Include="..\heap\GCThread.cpp" />
    340341    <ClCompile Include="..\heap\GCThreadSharedData.cpp" />
     
    705706    <ClInclude Include="..\heap\CopyVisitorInlines.h" />
    706707    <ClInclude Include="..\heap\CopyWorkList.h" />
     708    <ClInclude Include="..\heap\DeferGC.h" />
    707709    <ClInclude Include="..\heap\GCAssertions.h" />
    708710    <ClInclude Include="..\heap\GCThread.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r157424 r157539  
    874874      <Filter>heap</Filter>
    875875    </ClCompile>
     876    <ClCompile Include="..\heap\DeferGC.cpp">
     877      <Filter>heap</Filter>
     878    </ClCompile>
    876879    <ClCompile Include="..\bytecode\DeferredCompilationCallback.cpp">
    877880      <Filter>bytecode</Filter>
     
    12221225    </ClInclude>
    12231226    <ClInclude Include="..\heap\CopyWorkList.h">
     1227      <Filter>heap</Filter>
     1228    </ClInclude>
     1229    <ClInclude Include="..\heap\DeferGC.h">
    12241230      <Filter>heap</Filter>
    12251231    </ClInclude>
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r157474 r157539  
    374374                0FC815151405119B00CFA603 /* VTableSpectrum.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC815141405118D00CFA603 /* VTableSpectrum.h */; settings = {ATTRIBUTES = (Private, ); }; };
    375375                0FC81516140511B500CFA603 /* VTableSpectrum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC815121405118600CFA603 /* VTableSpectrum.cpp */; };
     376       0FCEFAAB1804C13E00472CE4 /* FTLSaveRestore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */; };
     377       0FCEFAAC1804C13E00472CE4 /* FTLSaveRestore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */; settings = {ATTRIBUTES = (Private, ); }; };
    376378                0FCCAE4516D0CF7400D0C65B /* ParserError.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCCAE4316D0CF6E00D0C65B /* ParserError.h */; settings = {ATTRIBUTES = (Private, ); }; };
    377379                0FCEFAB01805CA6D00472CE4 /* InitializeLLVM.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAAE1805CA6D00472CE4 /* InitializeLLVM.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    685687                1ACF7377171CA6FB00C9BB1E /* Weak.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACF7376171CA6FB00C9BB1E /* Weak.cpp */; };
    686688                2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */; };
     689       2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */; };
    687690                2600B5A7152BAAA70091EE5F /* JSStringJoiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */; };
    688691                2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = C211B574176A224D000E2A23 /* APICallbackFunction.h */; };
     
    16281631                0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JITToDFGDeferredCompilationCallback.h; sourceTree = "<group>"; };
    16291632                0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierSupport.cpp; sourceTree = "<group>"; };
     1633       0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLSaveRestore.cpp; path = ftl/FTLSaveRestore.cpp; sourceTree = "<group>"; };
     1634       0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSaveRestore.h; path = ftl/FTLSaveRestore.h; sourceTree = "<group>"; };
    16301635                0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierSupport.h; sourceTree = "<group>"; };
    16311636                0FC815121405118600CFA603 /* VTableSpectrum.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VTableSpectrum.cpp; sourceTree = "<group>"; };
     
    18921897                1C9051440BA9E8A70081E9D0 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; };
    18931898                1C9051450BA9E8A70081E9D0 /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
     1899       2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeferGC.cpp; sourceTree = "<group>"; };
    18941900                1CAA8B4A0D32C39A0041BCFF /* JavaScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScript.h; sourceTree = "<group>"; };
    18951901                1CAA8B4B0D32C39A0041BCFF /* JavaScriptCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptCore.h; sourceTree = "<group>"; };
     
    29172923                        isa = PBXGroup;
    29182924                        children = (
     2925               2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */,
    29192926                                14816E19154CC56C00B8054C /* BlockAllocator.cpp */,
    29202927                                14816E1A154CC56C00B8054C /* BlockAllocator.h */,
     
    54815488                                0FD8A32B17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp in Sources */,
    54825489                                14280842107EC0930013E7B2 /* RegExpConstructor.cpp in Sources */,
     5490               2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */,
    54835491                                8642C512151C083D0046D4EF /* RegExpMatchesArray.cpp in Sources */,
    54845492                                14280843107EC0930013E7B2 /* RegExpObject.cpp in Sources */,
  • trunk/Source/JavaScriptCore/heap/DeferGC.h

    r157424 r157539  
    2929#include "Heap.h"
    3030#include <wtf/Noncopyable.h>
     31#include <wtf/ThreadSpecific.h>
    3132
    3233namespace JSC {
     
    6869};
    6970
     71#ifndef NDEBUG
     72class DisallowGC {
     73    WTF_MAKE_NONCOPYABLE(DisallowGC);
     74public:
     75    DisallowGC()
     76    {
     77        WTF::threadSpecificSet(s_isGCDisallowedOnCurrentThread, reinterpret_cast<void*>(true));
     78    }
     79
     80    ~DisallowGC()
     81    {
     82        WTF::threadSpecificSet(s_isGCDisallowedOnCurrentThread, reinterpret_cast<void*>(false));
     83    }
     84
     85    static bool isGCDisallowedOnCurrentThread()
     86    {
     87        return !!WTF::threadSpecificGet(s_isGCDisallowedOnCurrentThread);
     88    }
     89    static void initialize()
     90    {
     91        WTF::threadSpecificKeyCreate(&s_isGCDisallowedOnCurrentThread, 0);
     92    }
     93
     94private:
     95    JS_EXPORT_PRIVATE static WTF::ThreadSpecificKey s_isGCDisallowedOnCurrentThread;
     96};
     97#endif // NDEBUG
     98
    7099} // namespace JSC
    71100
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r157489 r157539  
    361361void repatchGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
    362362{
    363     ConcurrentJITLocker locker(exec->codeBlock()->m_lock);
     363    GCSafeConcurrentJITLocker locker(exec->codeBlock()->m_lock, exec->vm().heap);
    364364   
    365365    bool cached = tryCacheGetByID(exec, baseValue, propertyName, slot, stubInfo);
     
    602602void buildGetByIDList(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
    603603{
    604     ConcurrentJITLocker locker(exec->codeBlock()->m_lock);
     604    GCSafeConcurrentJITLocker locker(exec->codeBlock()->m_lock, exec->vm().heap);
    605605   
    606606    bool dontChangeCall = tryBuildGetByIDList(exec, baseValue, propertyName, slot, stubInfo);
     
    10071007void repatchPutByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
    10081008{
    1009     ConcurrentJITLocker locker(exec->codeBlock()->m_lock);
     1009    GCSafeConcurrentJITLocker locker(exec->codeBlock()->m_lock, exec->vm().heap);
    10101010   
    10111011    bool cached = tryCachePutByID(exec, baseValue, propertyName, slot, stubInfo, putKind);
     
    11021102void buildPutByIdList(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
    11031103{
    1104     ConcurrentJITLocker locker(exec->codeBlock()->m_lock);
     1104    GCSafeConcurrentJITLocker locker(exec->codeBlock()->m_lock, exec->vm().heap);
    11051105   
    11061106    bool cached = tryBuildPutByIdList(exec, baseValue, propertyName, slot, stubInfo, putKind);
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r157474 r157539  
    597597           
    598598            if (slot.type() == PutPropertySlot::NewProperty) {
    599                 ConcurrentJITLocker locker(codeBlock->m_lock);
     599                GCSafeConcurrentJITLocker locker(codeBlock->m_lock, vm.heap);
    600600           
    601601                if (!structure->isDictionary() && structure->previousID()->outOfLineCapacity() == structure->outOfLineCapacity()) {
  • trunk/Source/JavaScriptCore/runtime/ConcurrentJITLock.h

    r157424 r157539  
    2727#define ConcurrentJITLock_h
    2828
     29#include "DeferGC.h"
    2930#include <wtf/ByteSpinLock.h>
    3031#include <wtf/NoLock.h>
     
    3435#if ENABLE(CONCURRENT_JIT)
    3536typedef ByteSpinLock ConcurrentJITLock;
    36 typedef ByteSpinLocker ConcurrentJITLocker;
     37typedef ByteSpinLocker ConcurrentJITLockerImpl;
    3738#else
    3839typedef NoLock ConcurrentJITLock;
    39 typedef NoLockLocker ConcurrentJITLocker;
     40typedef NoLockLocker ConcurrentJITLockerImpl;
    4041#endif
     42
     43class ConcurrentJITLockerBase {
     44    WTF_MAKE_NONCOPYABLE(ConcurrentJITLockerBase);
     45public:
     46    explicit ConcurrentJITLockerBase(ConcurrentJITLock& lockable)
     47        : m_locker(&lockable)
     48    {
     49    }
     50    explicit ConcurrentJITLockerBase(ConcurrentJITLock* lockable)
     51        : m_locker(lockable)
     52    {
     53    }
     54
     55    ~ConcurrentJITLockerBase()
     56    {
     57    }
     58   
     59    void unlockEarly()
     60    {
     61        m_locker.unlockEarly();
     62    }
     63
     64private:
     65    ConcurrentJITLockerImpl m_locker;
     66};
     67
     68class GCSafeConcurrentJITLocker : public ConcurrentJITLockerBase {
     69public:
     70    GCSafeConcurrentJITLocker(ConcurrentJITLock& lockable, Heap& heap)
     71        : ConcurrentJITLockerBase(lockable)
     72        , m_deferGC(heap)
     73    {
     74    }
     75
     76    GCSafeConcurrentJITLocker(ConcurrentJITLock* lockable, Heap& heap)
     77        : ConcurrentJITLockerBase(lockable)
     78        , m_deferGC(heap)
     79    {
     80    }
     81
     82    ~GCSafeConcurrentJITLocker()
     83    {
     84        // We have to unlock early due to the destruction order of base
     85        // vs. derived classes. If we didn't, then we would destroy the
     86        // DeferGC object before unlocking the lock which could cause a GC
     87        // and resulting deadlock.
     88        unlockEarly();
     89    }
     90
     91private:
     92#if ENABLE(CONCURRENT_JIT)
     93    DeferGC m_deferGC;
     94#else
     95    struct NoDefer {
     96        NoDefer(Heap& heap) : m_heap(heap) { }
     97        Heap& m_heap;
     98    };
     99    NoDefer m_deferGC;
     100#endif
     101};
     102
     103class ConcurrentJITLocker : public ConcurrentJITLockerBase {
     104public:
     105    ConcurrentJITLocker(ConcurrentJITLock& lockable)
     106        : ConcurrentJITLockerBase(lockable)
     107    {
     108    }
     109
     110    ConcurrentJITLocker(ConcurrentJITLock* lockable)
     111        : ConcurrentJITLockerBase(lockable)
     112    {
     113    }
     114
     115#if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG)
     116private:
     117    DisallowGC m_disallowGC;
     118#endif
     119};
    41120
    42121} // namespace JSC
    43122
    44123#endif // ConcurrentJITLock_h
    45 
  • trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp

    r157424 r157539  
    7070    LLInt::initialize();
    7171#endif
     72#ifndef NDEBUG
     73    DisallowGC::initialize();
     74#endif
    7275}
    7376
  • trunk/Source/JavaScriptCore/runtime/JSCellInlines.h

    r157424 r157539  
    2828
    2929#include "CallFrame.h"
     30#include "DeferGC.h"
    3031#include "Handle.h"
    3132#include "JSCell.h"
     
    8687void* allocateCell(Heap& heap, size_t size)
    8788{
     89    ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread());
    8890    ASSERT(size >= sizeof(T));
    8991#if ENABLE(GC_VALIDATION)
  • trunk/Source/JavaScriptCore/runtime/JSSymbolTableObject.h

    r154459 r157539  
    126126    {
    127127        SymbolTable& symbolTable = *object->symbolTable();
    128         ConcurrentJITLocker locker(symbolTable.m_lock);
     128        GCSafeConcurrentJITLocker locker(symbolTable.m_lock, exec->vm().heap);
    129129        SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
    130130        if (iter == symbolTable.end(locker))
  • trunk/Source/JavaScriptCore/runtime/Structure.cpp

    r157424 r157539  
    281281    // property map. We don't want getConcurrently() to see the property map in a half-baked
    282282    // state.
    283     ConcurrentJITLocker locker(m_lock);
     283    GCSafeConcurrentJITLocker locker(m_lock, vm.heap);
    284284    if (!table)
    285285        createPropertyMap(locker, vm, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
     
    314314    StringImpl* rep = propertyName.uid();
    315315
    316     materializePropertyMapIfNecessary(vm);
     316    DeferGC deferGC(vm.heap);
     317    materializePropertyMapIfNecessary(vm, deferGC);
    317318
    318319    ASSERT(isDictionary());
     
    452453    transition->m_prototype.set(vm, transition, prototype);
    453454
    454     structure->materializePropertyMapIfNecessary(vm);
     455    DeferGC deferGC(vm.heap);
     456    structure->materializePropertyMapIfNecessary(vm, deferGC);
    455457    transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition));
    456458    transition->m_offset = structure->m_offset;
     
    468470    ++transition->m_specificFunctionThrashCount;
    469471
    470     structure->materializePropertyMapIfNecessary(vm);
     472    DeferGC deferGC(vm.heap);
     473    structure->materializePropertyMapIfNecessary(vm, deferGC);
    471474    transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition));
    472475    transition->m_offset = structure->m_offset;
     
    486489Structure* Structure::attributeChangeTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes)
    487490{
     491    DeferGC deferGC(vm.heap);
    488492    if (!structure->isUncacheableDictionary()) {
    489493        Structure* transition = create(vm, structure);
    490494
    491         structure->materializePropertyMapIfNecessary(vm);
     495        structure->materializePropertyMapIfNecessary(vm, deferGC);
    492496        transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition));
    493497        transition->m_offset = structure->m_offset;
     
    512516    Structure* transition = create(vm, structure);
    513517
    514     structure->materializePropertyMapIfNecessary(vm);
     518    DeferGC deferGC(vm.heap);
     519    structure->materializePropertyMapIfNecessary(vm, deferGC);
    515520    transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition));
    516521    transition->m_offset = structure->m_offset;
     
    572577    // Don't set m_offset, as one can not transition to this.
    573578
    574     structure->materializePropertyMapIfNecessary(vm);
     579    DeferGC deferGC(vm.heap);
     580    structure->materializePropertyMapIfNecessary(vm, deferGC);
    575581    transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition));
    576582    transition->m_offset = structure->m_offset;
     
    584590PropertyTable* Structure::takePropertyTableOrCloneIfPinned(VM& vm, Structure* owner)
    585591{
    586     materializePropertyMapIfNecessaryForPinning(vm);
     592    DeferGC deferGC(vm.heap);
     593    materializePropertyMapIfNecessaryForPinning(vm, deferGC);
    587594   
    588595    if (m_isPinnedPropertyTable)
     
    641648        return false;
    642649
    643     materializePropertyMapIfNecessary(vm);
     650    DeferGC deferGC(vm.heap);
     651    materializePropertyMapIfNecessary(vm, deferGC);
    644652    if (!propertyTable())
    645653        return true;
     
    659667        return false;
    660668
    661     materializePropertyMapIfNecessary(vm);
     669    DeferGC deferGC(vm.heap);
     670    materializePropertyMapIfNecessary(vm, deferGC);
    662671    if (!propertyTable())
    663672        return true;
     
    719728        specificValue = 0;
    720729
    721     materializePropertyMapIfNecessaryForPinning(vm);
     730    DeferGC deferGC(vm.heap);
     731    materializePropertyMapIfNecessaryForPinning(vm, deferGC);
    722732   
    723733    pin();
     
    731741    ASSERT(!enumerationCache());
    732742
    733     materializePropertyMapIfNecessaryForPinning(vm);
     743    DeferGC deferGC(vm.heap);
     744    materializePropertyMapIfNecessaryForPinning(vm, deferGC);
    734745
    735746    pin();
     
    841852    ASSERT(structure()->classInfo() == info());
    842853
    843     materializePropertyMapIfNecessary(vm);
     854    DeferGC deferGC(vm.heap);
     855    materializePropertyMapIfNecessary(vm, deferGC);
    844856    if (!propertyTable())
    845857        return invalidOffset;
     
    856868bool Structure::despecifyFunction(VM& vm, PropertyName propertyName)
    857869{
    858     materializePropertyMapIfNecessary(vm);
     870    DeferGC deferGC(vm.heap);
     871    materializePropertyMapIfNecessary(vm, deferGC);
    859872    if (!propertyTable())
    860873        return false;
     
    871884void Structure::despecifyAllFunctions(VM& vm)
    872885{
    873     materializePropertyMapIfNecessary(vm);
     886    DeferGC deferGC(vm.heap);
     887    materializePropertyMapIfNecessary(vm, deferGC);
    874888    if (!propertyTable())
    875889        return;
     
    882896PropertyOffset Structure::putSpecificValue(VM& vm, PropertyName propertyName, unsigned attributes, JSCell* specificValue)
    883897{
    884     ConcurrentJITLocker locker(m_lock);
     898    GCSafeConcurrentJITLocker locker(m_lock, vm.heap);
    885899   
    886900    ASSERT(!JSC::isValidOffset(get(vm, propertyName)));
     
    927941}
    928942
    929 void Structure::createPropertyMap(const ConcurrentJITLocker&, VM& vm, unsigned capacity)
     943void Structure::createPropertyMap(const GCSafeConcurrentJITLocker&, VM& vm, unsigned capacity)
    930944{
    931945    ASSERT(!propertyTable());
     
    937951void Structure::getPropertyNamesFromStructure(VM& vm, PropertyNameArray& propertyNames, EnumerationMode mode)
    938952{
    939     materializePropertyMapIfNecessary(vm);
     953    DeferGC deferGC(vm.heap);
     954    materializePropertyMapIfNecessary(vm, deferGC);
    940955    if (!propertyTable())
    941956        return;
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r157424 r157539  
    5252namespace JSC {
    5353
     54class DeferGC;
    5455class LLIntOffsetsExtractor;
    5556class PropertyNameArray;
     
    394395    PropertyOffset remove(PropertyName);
    395396
    396     void createPropertyMap(const ConcurrentJITLocker&, VM&, unsigned keyCount = 0);
     397    void createPropertyMap(const GCSafeConcurrentJITLocker&, VM&, unsigned keyCount = 0);
    397398    void checkConsistency();
    398399
     
    405406    PropertyTable* copyPropertyTableForPinning(VM&, Structure* owner);
    406407    JS_EXPORT_PRIVATE void materializePropertyMap(VM&);
    407     void materializePropertyMapIfNecessary(VM& vm)
     408    void materializePropertyMapIfNecessary(VM& vm, DeferGC&)
    408409    {
    409410        ASSERT(!isCompilationThread());
     
    413414            materializePropertyMap(vm);
    414415    }
    415     void materializePropertyMapIfNecessaryForPinning(VM& vm)
     416    void materializePropertyMapIfNecessaryForPinning(VM& vm, DeferGC&)
    416417    {
    417418        ASSERT(structure()->classInfo() == info());
  • trunk/Source/JavaScriptCore/runtime/StructureInlines.h

    r154127 r157539  
    7878    ASSERT(!isCompilationThread());
    7979    ASSERT(structure()->classInfo() == info());
    80     materializePropertyMapIfNecessary(vm);
     80    DeferGC deferGC(vm.heap);
     81    materializePropertyMapIfNecessary(vm, deferGC);
    8182    if (!propertyTable())
    8283        return invalidOffset;
     
    9091    ASSERT(!isCompilationThread());
    9192    ASSERT(structure()->classInfo() == info());
    92     materializePropertyMapIfNecessary(vm);
     93    DeferGC deferGC(vm.heap);
     94    materializePropertyMapIfNecessary(vm, deferGC);
    9395    if (!propertyTable())
    9496        return invalidOffset;
  • trunk/Source/JavaScriptCore/runtime/SymbolTable.h

    r156079 r157539  
    355355    }
    356356   
     357    Map::iterator find(const GCSafeConcurrentJITLocker&, StringImpl* key)
     358    {
     359        return m_map.find(key);
     360    }
     361   
    357362    SymbolTableEntry get(const ConcurrentJITLocker&, StringImpl* key)
    358363    {
     
    383388   
    384389    Map::iterator end(const ConcurrentJITLocker&)
     390    {
     391        return m_map.end();
     392    }
     393   
     394    Map::iterator end(const GCSafeConcurrentJITLocker&)
    385395    {
    386396        return m_map.end();
Note: See TracChangeset for help on using the changeset viewer.