fourthTier: ASSERT that commonly used not-thread-safe methods in the runtime are...
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Jul 2013 03:59:09 +0000 (03:59 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Jul 2013 03:59:09 +0000 (03:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=115297

Source/JavaScriptCore:

Reviewed by Geoffrey Garen.

Put in assertions that we're not doing bad things in compilation threads. Also
factored compilation into compile+link so that even though we don't yet have
concurrent compilation, we can be explicit about which parts of DFG work are
meant to be concurrent, and which aren't.

Also fix a handful of bugs found by these assertions.

* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/ResolveGlobalStatus.cpp:
(JSC::computeForStructure):
* bytecode/Watchpoint.cpp:
(JSC::WatchpointSet::add):
(JSC::InlineWatchpointSet::inflateSlow):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::~JITCompiler):
(DFG):
(JSC::DFG::JITCompiler::compileBody):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compileFunction):
(JSC::DFG::JITCompiler::linkFunction):
* dfg/DFGJITCompiler.h:
(JITCompiler):
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* ftl/FTLCompile.h:
(FTL):
* ftl/FTLLink.cpp: Added.
(FTL):
(JSC::FTL::compileEntry):
(JSC::FTL::link):
* ftl/FTLLink.h: Added.
(FTL):
* ftl/FTLState.cpp:
(JSC::FTL::State::State):
* ftl/FTLState.h:
(FTL):
(State):
* runtime/Structure.cpp:
(JSC::Structure::get):
(JSC::Structure::prototypeChainMayInterceptStoreTo):
* runtime/Structure.h:
(JSC::Structure::materializePropertyMapIfNecessary):
* runtime/StructureInlines.h:
(JSC::Structure::get):

Source/WTF:

Reviewed by Geoffrey Garen.

Taught WTF the notion of compilation threads. This allows all parts of our stack
to assert that we're not being called from a JSC compilation thread. This is in
WTF because it will probably end up being used in StringImpl and WTFString.

* WTF.xcodeproj/project.pbxproj:
* wtf/CompilationThread.cpp: Added.
(WTF):
(WTF::initializeCompilationThreadsOnce):
(WTF::initializeCompilationThreads):
(WTF::isCompilationThread):
(WTF::exchangeIsCompilationThread):
* wtf/CompilationThread.h: Added.
(WTF):
(CompilationScope):
(WTF::CompilationScope::CompilationScope):
(WTF::CompilationScope::~CompilationScope):
(WTF::CompilationScope::leaveEarly):

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

20 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp
Source/JavaScriptCore/bytecode/Watchpoint.cpp
Source/JavaScriptCore/dfg/DFGDriver.cpp
Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
Source/JavaScriptCore/dfg/DFGJITCompiler.h
Source/JavaScriptCore/ftl/FTLCompile.cpp
Source/JavaScriptCore/ftl/FTLCompile.h
Source/JavaScriptCore/ftl/FTLLink.cpp [new file with mode: 0644]
Source/JavaScriptCore/ftl/FTLLink.h [new file with mode: 0644]
Source/JavaScriptCore/ftl/FTLState.cpp
Source/JavaScriptCore/ftl/FTLState.h
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/Structure.h
Source/JavaScriptCore/runtime/StructureInlines.h
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/CompilationThread.cpp [new file with mode: 0644]
Source/WTF/wtf/CompilationThread.h [new file with mode: 0644]

index b37aefb..ffc1411 100644 (file)
@@ -1,3 +1,62 @@
+2013-07-16  Oliver Hunt <oliver@apple.com>
+
+        Merge dfgFourthTier r149301
+
+    2013-04-28  Filip Pizlo  <fpizlo@apple.com>
+
+        fourthTier: ASSERT that commonly used not-thread-safe methods in the runtime are not being called during compilation
+        https://bugs.webkit.org/show_bug.cgi?id=115297
+
+        Reviewed by Geoffrey Garen.
+        
+        Put in assertions that we're not doing bad things in compilation threads. Also
+        factored compilation into compile+link so that even though we don't yet have
+        concurrent compilation, we can be explicit about which parts of DFG work are
+        meant to be concurrent, and which aren't.
+        
+        Also fix a handful of bugs found by these assertions.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/ResolveGlobalStatus.cpp:
+        (JSC::computeForStructure):
+        * bytecode/Watchpoint.cpp:
+        (JSC::WatchpointSet::add):
+        (JSC::InlineWatchpointSet::inflateSlow):
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compile):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::~JITCompiler):
+        (DFG):
+        (JSC::DFG::JITCompiler::compileBody):
+        (JSC::DFG::JITCompiler::compile):
+        (JSC::DFG::JITCompiler::link):
+        (JSC::DFG::JITCompiler::compileFunction):
+        (JSC::DFG::JITCompiler::linkFunction):
+        * dfg/DFGJITCompiler.h:
+        (JITCompiler):
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::compile):
+        * ftl/FTLCompile.h:
+        (FTL):
+        * ftl/FTLLink.cpp: Added.
+        (FTL):
+        (JSC::FTL::compileEntry):
+        (JSC::FTL::link):
+        * ftl/FTLLink.h: Added.
+        (FTL):
+        * ftl/FTLState.cpp:
+        (JSC::FTL::State::State):
+        * ftl/FTLState.h:
+        (FTL):
+        (State):
+        * runtime/Structure.cpp:
+        (JSC::Structure::get):
+        (JSC::Structure::prototypeChainMayInterceptStoreTo):
+        * runtime/Structure.h:
+        (JSC::Structure::materializePropertyMapIfNecessary):
+        * runtime/StructureInlines.h:
+        (JSC::Structure::get):
+
 2013-04-27  Filip Pizlo  <fpizlo@apple.com>
 
         FTL should support double variables
index d66fe5f..b5931fb 100644 (file)
                0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */; };
                0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F8364B7164B0C110053329A /* DFGBranchDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */; };
+               0F8F2B96172E04A3007DBDA5 /* FTLLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F2B94172E049E007DBDA5 /* FTLLink.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F8F943C1667631300D61971 /* CodeSpecializationKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F943A1667631100D61971 /* CodeSpecializationKind.cpp */; };
                0F8F94401667633000D61971 /* CodeBlockHash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F943D1667632D00D61971 /* CodeBlockHash.cpp */; };
                0F8F94411667633200D61971 /* CodeBlockHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F943E1667632D00D61971 /* CodeBlockHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = "<group>"; };
                0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBranchDirection.h; path = dfg/DFGBranchDirection.h; sourceTree = "<group>"; };
                0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariadicFunction.h; path = dfg/DFGVariadicFunction.h; sourceTree = "<group>"; };
+               0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FTLLink.cpp; path = ftl/FTLLink.cpp; sourceTree = "<group>"; };
+               0F8F2B94172E049E007DBDA5 /* FTLLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FTLLink.h; path = ftl/FTLLink.h; sourceTree = "<group>"; };
                0F8F943A1667631100D61971 /* CodeSpecializationKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeSpecializationKind.cpp; sourceTree = "<group>"; };
                0F8F943D1667632D00D61971 /* CodeBlockHash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlockHash.cpp; sourceTree = "<group>"; };
                0F8F943E1667632D00D61971 /* CodeBlockHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockHash.h; sourceTree = "<group>"; };
                                0FEA0A221709606900BB722C /* FTLIntrinsicRepository.h */,
                                0FEA0A02170513DB00BB722C /* FTLJITCode.cpp */,
                                0FEA0A03170513DB00BB722C /* FTLJITCode.h */,
+                               0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */,
+                               0F8F2B94172E049E007DBDA5 /* FTLLink.h */,
                                0FEA0A131706363600BB722C /* FTLLLVMHeaders.h */,
                                0FEA0A04170513DB00BB722C /* FTLLowerDFGToLLVM.cpp */,
                                0FEA0A05170513DB00BB722C /* FTLLowerDFGToLLVM.h */,
                                BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
                                BC18C4210E16F5CD00B34460 /* JSGlobalObject.h in Headers */,
                                BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */,
+                               0F8F2B96172E04A3007DBDA5 /* FTLLink.h in Headers */,
                                A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */,
                                BC18C4230E16F5CD00B34460 /* JSLock.h in Headers */,
                                C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */,
                                14469DE7107EC7E700650446 /* PropertyNameArray.cpp in Sources */,
                                14469DE8107EC7E700650446 /* PropertySlot.cpp in Sources */,
                                ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */,
+                               0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */,
                                1474C33C16AA2D9B0062F01D /* PrototypeMap.cpp in Sources */,
                                0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */,
                                0FF60AC316740F8800029779 /* ReduceWhitespace.cpp in Sources */,
index 7e16f73..d4b3ac5 100644 (file)
@@ -37,7 +37,7 @@ static ResolveGlobalStatus computeForStructure(CodeBlock* codeBlock, Structure*
 {
     unsigned attributesIgnored;
     JSCell* specificValue;
-    PropertyOffset offset = structure->get(*codeBlock->vm(), identifier, attributesIgnored, specificValue);
+    PropertyOffset offset = structure->getConcurrently(*codeBlock->vm(), identifier, attributesIgnored, specificValue);
     if (structure->isDictionary())
         specificValue = 0;
     if (!isValidOffset(offset))
index 2862cf8..be8270b 100644 (file)
@@ -27,6 +27,7 @@
 #include "Watchpoint.h"
 
 #include "LinkBuffer.h"
+#include <wtf/CompilationThread.h>
 #include <wtf/PassRefPtr.h>
 
 namespace JSC {
@@ -53,6 +54,7 @@ WatchpointSet::~WatchpointSet()
 
 void WatchpointSet::add(Watchpoint* watchpoint)
 {
+    ASSERT(!isCompilationThread());
     if (!watchpoint)
         return;
     m_set.push(watchpoint);
@@ -83,6 +85,7 @@ void InlineWatchpointSet::add(Watchpoint* watchpoint)
 WatchpointSet* InlineWatchpointSet::inflateSlow()
 {
     ASSERT(isThin());
+    ASSERT(!isCompilationThread());
     WatchpointSet* fat = adoptRef(new WatchpointSet(InitializedBlind)).leakRef();
     if (m_data & IsInvalidatedFlag)
         fat->m_isInvalidated = true;
index 27c39ef..6627624 100644 (file)
 #include "DFGVirtualRegisterAllocationPhase.h"
 #include "FTLCapabilities.h"
 #include "FTLCompile.h"
+#include "FTLLink.h"
 #include "FTLLowerDFGToLLVM.h"
 #include "FTLState.h"
 #include "Operations.h"
 #include "Options.h"
+#include <wtf/CompilationThread.h>
 
 namespace JSC { namespace DFG {
 
@@ -81,6 +83,7 @@ enum CompileMode { CompileFunction, CompileOther };
 static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck, unsigned osrEntryBytecodeIndex)
 {
     SamplingRegion samplingRegion("DFG Compilation (Driver)");
+    CompilationScope compilationScope;
     
     numCompilations++;
     
@@ -174,7 +177,9 @@ static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
         
         FTL::State state(dfg);
         FTL::lowerDFGToLLVM(state);
-        return FTL::compile(state, jitCode, *jitCodeWithArityCheck);
+        FTL::compile(state);
+        compilationScope.leaveEarly();
+        return FTL::link(state, jitCode, *jitCodeWithArityCheck);
     }
 #endif // ENABLE(FTL_JIT)
     
@@ -186,12 +191,18 @@ static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
     if (compileMode == CompileFunction) {
         ASSERT(jitCodeWithArityCheck);
         
-        result = dataFlowJIT.compileFunction(jitCode, *jitCodeWithArityCheck);
+        if (!dataFlowJIT.compileFunction())
+            return false;
+        compilationScope.leaveEarly();
+        result = dataFlowJIT.linkFunction(jitCode, *jitCodeWithArityCheck);
     } else {
         ASSERT(compileMode == CompileOther);
         ASSERT(!jitCodeWithArityCheck);
         
-        result = dataFlowJIT.compile(jitCode);
+        if (!dataFlowJIT.compile())
+            return false;
+        compilationScope.leaveEarly();
+        result = dataFlowJIT.link(jitCode);
     }
     
     return result;
index 6cc942b..7daaae1 100644 (file)
@@ -52,6 +52,10 @@ JITCompiler::JITCompiler(Graph& dfg)
         m_disassembler = adoptPtr(new Disassembler(dfg));
 }
 
+JITCompiler::~JITCompiler()
+{
+}
+
 void JITCompiler::linkOSRExits()
 {
     ASSERT(m_jitCode->osrExit.size() == m_exitCompilationInfo.size());
@@ -97,7 +101,7 @@ void JITCompiler::compileEntry()
     emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock);
 }
 
-void JITCompiler::compileBody(SpeculativeJIT& speculative)
+void JITCompiler::compileBody()
 {
     // We generate the speculative code path, followed by OSR exit code to return
     // to the old JIT code if speculations fail.
@@ -107,7 +111,7 @@ void JITCompiler::compileBody(SpeculativeJIT& speculative)
     breakpoint();
 #endif
     
-    bool compiledSpeculative = speculative.compile();
+    bool compiledSpeculative = m_speculative->compile();
     ASSERT_UNUSED(compiledSpeculative, compiledSpeculative);
 }
 
@@ -242,26 +246,31 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
     m_graph.m_watchpoints.reallyAdd();
 }
 
-bool JITCompiler::compile(RefPtr<JSC::JITCode>& entry)
+bool JITCompiler::compile()
 {
     SamplingRegion samplingRegion("DFG Backend");
 
     setStartOfCode();
     compileEntry();
-    SpeculativeJIT speculative(*this);
-    compileBody(speculative);
+    m_speculative = adoptPtr(new SpeculativeJIT(*this));
+    compileBody();
     setEndOfMainPath();
 
     // Generate slow path code.
-    speculative.runSlowPathGenerators();
+    m_speculative->runSlowPathGenerators();
     
     compileExceptionHandlers();
     linkOSRExits();
     
     // Create OSR entry trampolines if necessary.
-    speculative.createOSREntries();
+    m_speculative->createOSREntries();
     setEndOfCode();
 
+    return true;
+}
+
+bool JITCompiler::link(RefPtr<JSC::JITCode>& entry)
+{
     if (!m_graph.m_watchpoints.areStillValid())
         return false;
     
@@ -269,7 +278,7 @@ bool JITCompiler::compile(RefPtr<JSC::JITCode>& entry)
     if (linkBuffer.didFailToAllocate())
         return false;
     link(linkBuffer);
-    speculative.linkOSREntries(linkBuffer);
+    m_speculative->linkOSREntries(linkBuffer);
     
     m_jitCode->shrinkToFit();
     codeBlock()->shrinkToFit(CodeBlock::LateShrink);
@@ -284,7 +293,7 @@ bool JITCompiler::compile(RefPtr<JSC::JITCode>& entry)
     return true;
 }
 
-bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& entryWithArityCheck)
+bool JITCompiler::compileFunction()
 {
     SamplingRegion samplingRegion("DFG Backend");
     
@@ -305,8 +314,8 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
 
 
     // === Function body code generation ===
-    SpeculativeJIT speculative(*this);
-    compileBody(speculative);
+    m_speculative = adoptPtr(new SpeculativeJIT(*this));
+    compileBody();
     setEndOfMainPath();
 
     // === Function footer code generation ===
@@ -323,8 +332,8 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
 
     CallBeginToken token;
     beginCall(CodeOrigin(0), token);
-    Call callStackCheck = call();
-    notifyCall(callStackCheck, CodeOrigin(0), token);
+    m_callStackCheck = call();
+    notifyCall(m_callStackCheck, CodeOrigin(0), token);
     jump(fromStackCheck);
     
     // The fast entry point into a function does not check the correct number of arguments
@@ -332,7 +341,7 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
     // determine the correct number of arguments have been passed, or have already checked).
     // In cases where an arity check is necessary, we enter here.
     // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions).
-    Label arityCheck = label();
+    m_arityCheck = label();
     compileEntry();
 
     load32(AssemblyHelpers::payloadFor((VirtualRegister)JSStack::ArgumentCount), GPRInfo::regT1);
@@ -340,21 +349,26 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
     move(stackPointerRegister, GPRInfo::argumentGPR0);
     poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
     beginCall(CodeOrigin(0), token);
-    Call callArityCheck = call();
-    notifyCall(callArityCheck, CodeOrigin(0), token);
+    m_callArityCheck = call();
+    notifyCall(m_callArityCheck, CodeOrigin(0), token);
     move(GPRInfo::regT0, GPRInfo::callFrameRegister);
     jump(fromArityCheck);
     
     // Generate slow path code.
-    speculative.runSlowPathGenerators();
+    m_speculative->runSlowPathGenerators();
     
     compileExceptionHandlers();
     linkOSRExits();
     
     // Create OSR entry trampolines if necessary.
-    speculative.createOSREntries();
+    m_speculative->createOSREntries();
     setEndOfCode();
     
+    return true;
+}
+
+bool JITCompiler::linkFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& entryWithArityCheck)
+{
     if (!m_graph.m_watchpoints.areStillValid())
         return false;
 
@@ -363,21 +377,21 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
     if (linkBuffer.didFailToAllocate())
         return false;
     link(linkBuffer);
-    speculative.linkOSREntries(linkBuffer);
+    m_speculative->linkOSREntries(linkBuffer);
     
     m_jitCode->shrinkToFit();
     codeBlock()->shrinkToFit(CodeBlock::LateShrink);
     
     // FIXME: switch the stack check & arity check over to DFGOpertaion style calls, not JIT stubs.
-    linkBuffer.link(callStackCheck, cti_stack_check);
-    linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
+    linkBuffer.link(m_callStackCheck, cti_stack_check);
+    linkBuffer.link(m_callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
     
     if (shouldShowDisassembly())
         m_disassembler->dump(linkBuffer);
     if (m_graph.m_compilation)
         m_disassembler->reportToProfiler(m_graph.m_compilation.get(), linkBuffer);
 
-    entryWithArityCheck = linkBuffer.locationOf(arityCheck);
+    entryWithArityCheck = linkBuffer.locationOf(m_arityCheck);
     m_jitCode->initializeCodeRef(linkBuffer.finalizeCodeWithoutDisassembly());
     entry = m_jitCode;
     return true;
index 98956b3..42d6ad9 100644 (file)
@@ -245,9 +245,13 @@ struct PropertyAccessRecord {
 class JITCompiler : public CCallHelpers {
 public:
     JITCompiler(Graph& dfg);
+    ~JITCompiler();
     
-    bool compile(RefPtr<JSC::JITCode>& entry);
-    bool compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& entryWithArityCheck);
+    bool compile();
+    bool compileFunction();
+    
+    bool link(RefPtr<JSC::JITCode>& entry);
+    bool linkFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& entryWithArityCheck);
 
     // Accessors for properties.
     Graph& graph() { return m_graph; }
@@ -435,7 +439,7 @@ private:
     
     // Internal implementation to compile.
     void compileEntry();
-    void compileBody(SpeculativeJIT&);
+    void compileBody();
     void link(LinkBuffer&);
 
     void exitSpeculativeWithOSR(const OSRExit&, SpeculationRecovery*);
@@ -478,6 +482,11 @@ private:
     Vector<OSRExitCompilationInfo> m_exitCompilationInfo;
     Vector<Vector<Label> > m_exitSiteLabels;
     unsigned m_currentCodeOriginIndex;
+    
+    Call m_callStackCheck;
+    Call m_callArityCheck;
+    Label m_arityCheck;
+    OwnPtr<SpeculativeJIT> m_speculative;
 };
 
 } } // namespace JSC::DFG
index 7f33704..1c7aa3d 100644 (file)
@@ -31,7 +31,6 @@
 #include "CodeBlockWithJITType.h"
 #include "DFGCCallHelpers.h"
 #include "DFGCommon.h"
-#include "FTLJITCode.h"
 #include "FTLLLVMHeaders.h"
 #include "JITStubs.h"
 #include "LinkBuffer.h"
@@ -40,18 +39,8 @@ namespace JSC { namespace FTL {
 
 using namespace DFG;
 
-typedef EncodedJSValue (*GeneratedFunction)(ExecState*);
-
-static void compileEntry(CCallHelpers& jit)
-{
-    jit.preserveReturnAddressAfterCall(GPRInfo::regT2);
-    jit.emitPutToCallFrameHeader(GPRInfo::regT2, JSStack::ReturnPC);
-    jit.emitPutImmediateToCallFrameHeader(jit.codeBlock(), JSStack::CodeBlock);
-}
-
-bool compile(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
+void compile(State& state)
 {
-    LLVMExecutionEngineRef engine;
     char* error = 0;
     
     LLVMMCJITCompilerOptions options;
@@ -60,13 +49,13 @@ bool compile(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr&
     options.NoFramePointerElim = true;
     options.CodeModel = LLVMCodeModelSmall;
     
-    if (LLVMCreateMCJITCompilerForModule(&engine, state.module, &options, sizeof(options), &error)) {
+    if (LLVMCreateMCJITCompilerForModule(&state.engine, state.module, &options, sizeof(options), &error)) {
         dataLog("FATAL: Could not create LLVM execution engine: ", error, "\n");
         CRASH();
     }
     
     LLVMPassManagerRef pass = LLVMCreatePassManager();
-    LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
+    LLVMAddTargetData(LLVMGetExecutionEngineTargetData(state.engine), pass);
     LLVMAddConstantPropagationPass(pass);
     LLVMAddInstructionCombiningPass(pass);
     LLVMAddPromoteMemoryToRegisterPass(pass);
@@ -83,97 +72,8 @@ bool compile(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr&
     // https://bugs.webkit.org/show_bug.cgi?id=113619
     // FIXME: Need to add support for the case where JIT memory allocation failed.
     // https://bugs.webkit.org/show_bug.cgi?id=113620
-    GeneratedFunction function = reinterpret_cast<GeneratedFunction>(LLVMGetPointerToGlobal(engine, state.function));
+    state.generatedFunction = reinterpret_cast<GeneratedFunction>(LLVMGetPointerToGlobal(state.engine, state.function));
     LLVMDisposePassManager(pass);
-    
-    if (!state.graph.m_watchpoints.areStillValid()) {
-        LLVMDisposeExecutionEngine(engine);
-        return false;
-    }
-    
-    state.graph.m_watchpoints.reallyAdd();
-    
-    // Create the entrypoint.
-    // FIXME: This is a total kludge - LLVM should just use our calling convention.
-    // https://bugs.webkit.org/show_bug.cgi?id=113621
-    CCallHelpers jit(&state.graph.m_vm, state.graph.m_codeBlock);
-    
-    compileEntry(jit);
-    
-    // This part is only necessary for functions. We currently only compile functions.
-        
-    CCallHelpers::Label fromArityCheck = jit.label();
-        
-    // Plant a check that sufficient space is available in the JSStack.
-    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291
-    jit.addPtr(
-        CCallHelpers::TrustedImm32(state.graph.m_codeBlock->m_numCalleeRegisters * sizeof(Register)),
-        GPRInfo::callFrameRegister, GPRInfo::regT1);
-    CCallHelpers::Jump stackCheck = jit.branchPtr(
-        CCallHelpers::Below,
-        CCallHelpers::AbsoluteAddress(state.graph.m_vm.interpreter->stack().addressOfEnd()),
-        GPRInfo::regT1);
-    CCallHelpers::Label fromStackCheck = jit.label();
-        
-    jit.setupArgumentsExecState();
-    jit.move(CCallHelpers::TrustedImmPtr(reinterpret_cast<void*>(function)), GPRInfo::nonArgGPR0);
-    jit.call(GPRInfo::nonArgGPR0);
-    jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT1);
-    jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
-    jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
-    jit.ret();
-        
-    stackCheck.link(&jit);
-    jit.move(CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
-    jit.poke(
-        GPRInfo::callFrameRegister,
-        OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
-        
-    jit.store32(
-        CCallHelpers::TrustedImm32(0),
-        CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
-    CCallHelpers::Call callStackCheck = jit.call();
-    // FIXME: need to make this call register with exception handling somehow. This is
-    // part of a bigger problem: FTL should be able to handle exceptions.
-    // https://bugs.webkit.org/show_bug.cgi?id=113622
-    jit.jump(fromStackCheck);
-        
-    CCallHelpers::Label arityCheck = jit.label();
-    compileEntry(jit);
-    jit.load32(
-        CCallHelpers::payloadFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)),
-        GPRInfo::regT1);
-    jit.branch32(
-        CCallHelpers::AboveOrEqual, GPRInfo::regT1,
-        CCallHelpers::TrustedImm32(state.graph.m_codeBlock->numParameters()))
-        .linkTo(fromArityCheck, &jit);
-    jit.move(CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
-    jit.poke(
-        GPRInfo::callFrameRegister,
-        OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
-    jit.store32(
-        CCallHelpers::TrustedImm32(0),
-        CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
-    CCallHelpers::Call callArityCheck = jit.call();
-    // FIXME: need to make this call register with exception handling somehow. This is
-    // part of a bigger problem: FTL should be able to handle exceptions.
-    // https://bugs.webkit.org/show_bug.cgi?id=113622
-    jit.move(GPRInfo::regT0, GPRInfo::callFrameRegister);
-    jit.jump(fromArityCheck);
-        
-    LinkBuffer linkBuffer(state.graph.m_vm, &jit, state.graph.m_codeBlock, JITCompilationMustSucceed);
-    linkBuffer.link(callStackCheck, cti_stack_check);
-    linkBuffer.link(callArityCheck, state.graph.m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
-        
-    jitCodeWithArityCheck = linkBuffer.locationOf(arityCheck);
-    state.jitCode->initializeCode(
-        engine,
-        FINALIZE_DFG_CODE(
-            linkBuffer,
-            ("FTL entrypoint thunk for %s with LLVM generated code at %p", toCString(CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT)).data(), function)));
-    jitCode = state.jitCode;
-    
-    return true;
 }
 
 } } // namespace JSC::FTL
index 1215d52..c963643 100644 (file)
@@ -34,7 +34,7 @@
 
 namespace JSC { namespace FTL {
 
-bool compile(State&, RefPtr<JSC::JITCode>&, MacroAssemblerCodePtr& jitCodeWithArityCheck);
+void compile(State&);
 
 } } // namespace JSC::FTL
 
diff --git a/Source/JavaScriptCore/ftl/FTLLink.cpp b/Source/JavaScriptCore/ftl/FTLLink.cpp
new file mode 100644 (file)
index 0000000..a65ec00
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "FTLLink.h"
+
+#if ENABLE(FTL_JIT)
+
+#include "CodeBlockWithJITType.h"
+#include "DFGCCallHelpers.h"
+#include "DFGCommon.h"
+#include "FTLJITCode.h"
+#include "FTLLLVMHeaders.h"
+#include "JITStubs.h"
+#include "LinkBuffer.h"
+
+namespace JSC { namespace FTL {
+
+using namespace DFG;
+
+static void compileEntry(CCallHelpers& jit)
+{
+    jit.preserveReturnAddressAfterCall(GPRInfo::regT2);
+    jit.emitPutToCallFrameHeader(GPRInfo::regT2, JSStack::ReturnPC);
+    jit.emitPutImmediateToCallFrameHeader(jit.codeBlock(), JSStack::CodeBlock);
+}
+
+bool link(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
+{
+    if (!state.graph.m_watchpoints.areStillValid()) {
+        LLVMDisposeExecutionEngine(state.engine);
+        return false;
+    }
+    
+    state.graph.m_watchpoints.reallyAdd();
+    
+    // Create the entrypoint.
+    // FIXME: This is a total kludge - LLVM should just use our calling convention.
+    // https://bugs.webkit.org/show_bug.cgi?id=113621
+    CCallHelpers jit(&state.graph.m_vm, state.graph.m_codeBlock);
+    
+    compileEntry(jit);
+    
+    // This part is only necessary for functions. We currently only compile functions.
+        
+    CCallHelpers::Label fromArityCheck = jit.label();
+        
+    // Plant a check that sufficient space is available in the JSStack.
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291
+    jit.addPtr(
+        CCallHelpers::TrustedImm32(state.graph.m_codeBlock->m_numCalleeRegisters * sizeof(Register)),
+        GPRInfo::callFrameRegister, GPRInfo::regT1);
+    CCallHelpers::Jump stackCheck = jit.branchPtr(
+        CCallHelpers::Below,
+        CCallHelpers::AbsoluteAddress(state.graph.m_vm.interpreter->stack().addressOfEnd()),
+        GPRInfo::regT1);
+    CCallHelpers::Label fromStackCheck = jit.label();
+        
+    jit.setupArgumentsExecState();
+    jit.move(CCallHelpers::TrustedImmPtr(reinterpret_cast<void*>(state.generatedFunction)), GPRInfo::nonArgGPR0);
+    jit.call(GPRInfo::nonArgGPR0);
+    jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT1);
+    jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
+    jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
+    jit.ret();
+        
+    stackCheck.link(&jit);
+    jit.move(CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
+    jit.poke(
+        GPRInfo::callFrameRegister,
+        OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+        
+    jit.store32(
+        CCallHelpers::TrustedImm32(0),
+        CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
+    CCallHelpers::Call callStackCheck = jit.call();
+    // FIXME: need to make this call register with exception handling somehow. This is
+    // part of a bigger problem: FTL should be able to handle exceptions.
+    // https://bugs.webkit.org/show_bug.cgi?id=113622
+    jit.jump(fromStackCheck);
+        
+    CCallHelpers::Label arityCheck = jit.label();
+    compileEntry(jit);
+    jit.load32(
+        CCallHelpers::payloadFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)),
+        GPRInfo::regT1);
+    jit.branch32(
+        CCallHelpers::AboveOrEqual, GPRInfo::regT1,
+        CCallHelpers::TrustedImm32(state.graph.m_codeBlock->numParameters()))
+        .linkTo(fromArityCheck, &jit);
+    jit.move(CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
+    jit.poke(
+        GPRInfo::callFrameRegister,
+        OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+    jit.store32(
+        CCallHelpers::TrustedImm32(0),
+        CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
+    CCallHelpers::Call callArityCheck = jit.call();
+    // FIXME: need to make this call register with exception handling somehow. This is
+    // part of a bigger problem: FTL should be able to handle exceptions.
+    // https://bugs.webkit.org/show_bug.cgi?id=113622
+    jit.move(GPRInfo::regT0, GPRInfo::callFrameRegister);
+    jit.jump(fromArityCheck);
+        
+    LinkBuffer linkBuffer(state.graph.m_vm, &jit, state.graph.m_codeBlock, JITCompilationMustSucceed);
+    linkBuffer.link(callStackCheck, cti_stack_check);
+    linkBuffer.link(callArityCheck, state.graph.m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
+        
+    jitCodeWithArityCheck = linkBuffer.locationOf(arityCheck);
+    state.jitCode->initializeCode(
+        state.engine,
+        FINALIZE_DFG_CODE(
+            linkBuffer,
+            ("FTL entrypoint thunk for %s with LLVM generated code at %p", toCString(CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT)).data(), state.generatedFunction)));
+    jitCode = state.jitCode;
+    
+    return true;
+}
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT)
+
diff --git a/Source/JavaScriptCore/ftl/FTLLink.h b/Source/JavaScriptCore/ftl/FTLLink.h
new file mode 100644 (file)
index 0000000..7fcf134
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef FTLLink_h
+#define FTLLink_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(FTL_JIT)
+
+#include "FTLState.h"
+
+namespace JSC { namespace FTL {
+
+bool link(State&, RefPtr<JSC::JITCode>&, MacroAssemblerCodePtr& jitCodeWithArityCheck);
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT)
+
+#endif // FTLLink_h
+
index 46436e7..64d5f3e 100644 (file)
@@ -39,6 +39,8 @@ State::State(Graph& graph)
     , module(0)
     , function(0)
     , jitCode(adoptRef(new JITCode()))
+    , engine(0)
+    , generatedFunction(0)
 {
 }
 
index 8922d07..386912c 100644 (file)
@@ -38,6 +38,8 @@
 
 namespace JSC { namespace FTL {
 
+typedef EncodedJSValue (*GeneratedFunction)(ExecState*);
+
 class State {
     WTF_MAKE_NONCOPYABLE(State);
     
@@ -51,6 +53,8 @@ public:
     LValue function;
     RefPtr<JITCode> jitCode;
     Vector<OSRExitCompilationInfo> osrExit;
+    LLVMExecutionEngineRef engine;
+    GeneratedFunction generatedFunction;
     
     void dumpState(const char* when);
 };
index 1998eca..20e1e37 100644 (file)
@@ -810,6 +810,7 @@ PropertyOffset Structure::getConcurrently(VM&, PropertyName propertyName, unsign
 
 PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes, JSCell*& specificValue)
 {
+    ASSERT(!isCompilationThread());
     ASSERT(structure()->classInfo() == &s_info);
 
     materializePropertyMapIfNecessary(vm);
@@ -957,6 +958,10 @@ void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor)
 
 bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
 {
+    // Note, this method is called from two kinds of places: (1) assertions and (2)
+    // the compilation thread. As such, it does things somewhat carefully to ensure
+    // thread safety. Currently that only affects the way we do Structure::get().
+    
     unsigned i = propertyName.asIndex();
     if (i != PropertyName::NotAnIndex)
         return anyObjectInChainMayInterceptIndexedAccesses();
@@ -970,7 +975,7 @@ bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyN
         
         unsigned attributes;
         JSCell* specificValue;
-        PropertyOffset offset = current->get(vm, propertyName, attributes, specificValue);
+        PropertyOffset offset = current->getConcurrently(vm, propertyName, attributes, specificValue);
         if (!JSC::isValidOffset(offset))
             continue;
         
index 655c0bd..e8fb90d 100644 (file)
@@ -41,6 +41,7 @@
 #include "Watchpoint.h"
 #include "Weak.h"
 #include <wtf/ByteSpinLock.h>
+#include <wtf/CompilationThread.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/text/StringImpl.h>
@@ -395,6 +396,7 @@ private:
     JS_EXPORT_PRIVATE void materializePropertyMap(VM&);
     void materializePropertyMapIfNecessary(VM& vm)
     {
+        ASSERT(!isCompilationThread());
         ASSERT(structure()->classInfo() == &s_info);
         ASSERT(checkOffsetConsistency());
         if (!propertyTable() && previousID())
index 69064df..324620e 100644 (file)
@@ -58,6 +58,7 @@ inline Structure* Structure::create(VM& vm, const Structure* structure)
 
 inline PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
 {
+    ASSERT(!isCompilationThread());
     ASSERT(structure()->classInfo() == &s_info);
     materializePropertyMapIfNecessary(vm);
     if (!propertyTable())
@@ -69,6 +70,7 @@ inline PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
 
 inline PropertyOffset Structure::get(VM& vm, const WTF::String& name)
 {
+    ASSERT(!isCompilationThread());
     ASSERT(structure()->classInfo() == &s_info);
     materializePropertyMapIfNecessary(vm);
     if (!propertyTable())
index d48b8a0..339eb0c 100644 (file)
@@ -1,5 +1,34 @@
 2013-07-16  Oliver Hunt <oliver@apple.com>
 
+        Merge dfgFourthTier r149301
+
+    2013-04-28  Filip Pizlo  <fpizlo@apple.com>
+
+        fourthTier: ASSERT that commonly used not-thread-safe methods in the runtime are not being called during compilation
+        https://bugs.webkit.org/show_bug.cgi?id=115297
+
+        Reviewed by Geoffrey Garen.
+        
+        Taught WTF the notion of compilation threads. This allows all parts of our stack
+        to assert that we're not being called from a JSC compilation thread. This is in
+        WTF because it will probably end up being used in StringImpl and WTFString.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CompilationThread.cpp: Added.
+        (WTF):
+        (WTF::initializeCompilationThreadsOnce):
+        (WTF::initializeCompilationThreads):
+        (WTF::isCompilationThread):
+        (WTF::exchangeIsCompilationThread):
+        * wtf/CompilationThread.h: Added.
+        (WTF):
+        (CompilationScope):
+        (WTF::CompilationScope::CompilationScope):
+        (WTF::CompilationScope::~CompilationScope):
+        (WTF::CompilationScope::leaveEarly):
+
+2013-07-16  Oliver Hunt <oliver@apple.com>
+
         Merge dfgFourthTier r148836
 
     2013-04-21  Filip Pizlo  <fpizlo@apple.com>
index a45ae36..9c3f3de 100644 (file)
@@ -23,6 +23,8 @@
 /* Begin PBXBuildFile section */
                0F0D85B417234CC100338210 /* NoLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0D85B317234CB100338210 /* NoLock.h */; };
                0F87105A16643F190090B0AD /* RawPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F87105916643F190090B0AD /* RawPointer.h */; };
+               0F8F2B91172E00FC007DBDA5 /* CompilationThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F2B90172E00F0007DBDA5 /* CompilationThread.h */; };
+               0F8F2B92172E0103007DBDA5 /* CompilationThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */; };
                0F9D3360165DBA73005AD387 /* FilePrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D335B165DBA73005AD387 /* FilePrintStream.cpp */; };
                0F9D3361165DBA73005AD387 /* FilePrintStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D335C165DBA73005AD387 /* FilePrintStream.h */; };
                0F9D3362165DBA73005AD387 /* PrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D335D165DBA73005AD387 /* PrintStream.cpp */; };
 /* Begin PBXFileReference section */
                0F0D85B317234CB100338210 /* NoLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NoLock.h; sourceTree = "<group>"; };
                0F87105916643F190090B0AD /* RawPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RawPointer.h; sourceTree = "<group>"; };
+               0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CompilationThread.cpp; sourceTree = "<group>"; };
+               0F8F2B90172E00F0007DBDA5 /* CompilationThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompilationThread.h; sourceTree = "<group>"; };
                0F9D335B165DBA73005AD387 /* FilePrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FilePrintStream.cpp; sourceTree = "<group>"; };
                0F9D335C165DBA73005AD387 /* FilePrintStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilePrintStream.h; sourceTree = "<group>"; };
                0F9D335D165DBA73005AD387 /* PrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrintStream.cpp; sourceTree = "<group>"; };
                                A8A4726A151A825A004123FF /* CheckedArithmetic.h */,
                                A8A4726B151A825A004123FF /* CheckedBoolean.h */,
                                0FC4EDE51696149600F65041 /* CommaPrinter.h */,
+                               0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */,
+                               0F8F2B90172E00F0007DBDA5 /* CompilationThread.h */,
                                A8A47270151A825A004123FF /* Compiler.h */,
                                A8A47273151A825A004123FF /* CryptographicallyRandomNumber.cpp */,
                                A8A47274151A825A004123FF /* CryptographicallyRandomNumber.h */,
                                A8A473B2151A825B004123FF /* double.h in Headers */,
                                A8A473A7151A825B004123FF /* DoublyLinkedList.h in Headers */,
                                A8A473BB151A825B004123FF /* dtoa.h in Headers */,
+                               0F8F2B91172E00FC007DBDA5 /* CompilationThread.h in Headers */,
                                A8A473BD151A825B004123FF /* DynamicAnnotations.h in Headers */,
                                A8A473C0151A825B004123FF /* Encoder.h in Headers */,
                                44F66008171AFAE600E4AD19 /* EnumClass.h in Headers */,
                                A8A473A0151A825B004123FF /* DateMath.cpp in Sources */,
                                A8A473A2151A825B004123FF /* DecimalNumber.cpp in Sources */,
                                A8A473AE151A825B004123FF /* diy-fp.cc in Sources */,
+                               0F8F2B92172E0103007DBDA5 /* CompilationThread.cpp in Sources */,
                                A8A473B0151A825B004123FF /* double-conversion.cc in Sources */,
                                A8A473BA151A825B004123FF /* dtoa.cpp in Sources */,
                                A8A473BC151A825B004123FF /* DynamicAnnotations.cpp in Sources */,
diff --git a/Source/WTF/wtf/CompilationThread.cpp b/Source/WTF/wtf/CompilationThread.cpp
new file mode 100644 (file)
index 0000000..2317805
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CompilationThread.h"
+
+#include "StdLibExtras.h"
+#include "Threading.h"
+#include "ThreadSpecific.h"
+
+namespace WTF {
+
+static ThreadSpecific<bool>* s_isCompilationThread;
+static pthread_once_t initializeCompilationThreadsKeyOnce = PTHREAD_ONCE_INIT;
+
+static void initializeCompilationThreadsOnce()
+{
+    s_isCompilationThread = new ThreadSpecific<bool>();
+}
+
+static void initializeCompilationThreads()
+{
+    pthread_once(&initializeCompilationThreadsKeyOnce, initializeCompilationThreadsOnce);
+}
+
+bool isCompilationThread()
+{
+    if (!s_isCompilationThread)
+        return false;
+    if (!s_isCompilationThread->isSet())
+        return false;
+    return **s_isCompilationThread;
+}
+
+bool exchangeIsCompilationThread(bool newValue)
+{
+    initializeCompilationThreads();
+    bool oldValue = isCompilationThread();
+    **s_isCompilationThread = newValue;
+    return oldValue;
+}
+
+} // namespace WTF
+
diff --git a/Source/WTF/wtf/CompilationThread.h b/Source/WTF/wtf/CompilationThread.h
new file mode 100644 (file)
index 0000000..6e3fcdf
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CompilationThread_h
+#define CompilationThread_h
+
+namespace WTF {
+
+WTF_EXPORT_PRIVATE bool isCompilationThread();
+WTF_EXPORT_PRIVATE bool exchangeIsCompilationThread(bool newValue);
+
+class CompilationScope {
+public:
+    CompilationScope()
+        : m_oldValue(exchangeIsCompilationThread(true))
+    {
+    }
+    
+    ~CompilationScope()
+    {
+        exchangeIsCompilationThread(m_oldValue);
+    }
+    
+    void leaveEarly()
+    {
+        exchangeIsCompilationThread(m_oldValue);
+    }
+private:
+    bool m_oldValue;
+};
+
+} // namespace WTF
+
+using WTF::CompilationScope;
+using WTF::exchangeIsCompilationThread;
+using WTF::isCompilationThread;
+
+#endif // CompilationThread_h
+