Teach DFG::Worklist and its clients that it may be reused for different kinds of...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Aug 2013 23:45:26 +0000 (23:45 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Aug 2013 23:45:26 +0000 (23:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=120489

Reviewed by Geoffrey Garen.

If the baseline JIT hits an OSR entry trigger into the DFG and we already have a
DFG compilation but we've also started one or more FTL compilations, then we
shouldn't get confused. Previously we would have gotten confused because we would
see an in-process deferred compile (the FTL compile) and also an optimized
replacement (the DFG code).

If the baseline JIT hits an OSR entry trigger into the DFG and we previously
did two things in this order: triggered a tier-up compilation from the DFG into
the FTL, and then jettisoned the DFG code because it exited a bunch, then we
shouldn't be confused by the presence of an in-process deferred compile (the FTL
compile). Previously we would have waited for that compile to finish; but the more
sensible thing to do is to let it complete and then invalidate it, while at the
same time enqueueing a DFG compile to create a new, more valid, DFG code block.

If the DFG JIT hits a loop OSR entry trigger (into the FTL) and it has already
triggered an FTL compile for replacement, then it should fire off a second compile
instead of thinking that it can wait for that one to finish. Or vice-versa. We
need to allow for two FTL compiles to be enqueued at the same time (one for
replacement and one for OSR entry in a loop).

Then there's also the problem that DFG::compile() is almost certainly going to be
the hook for triggering both DFG compiles and the two kinds of FTL compiles, but
right now there is no way to tell it which one you want.

This fixes these problems and removes a bunch of potential confusion by making the
key for a compile in the DFG::Worklist be a CompilationMode (one of DFGMode,
FTLMode, or FTLForOSREntryMode). That mode is also passed to DFG::compile().

Awkwardly, this still leaves us in a no DFG->FTL tier-up situation - so
DFG::compile() is always passed DFGMode and then it might do an FTL compile if
possible. Fixing that is a bigger issue for a later changeset.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::checkIfOptimizationThresholdReached):
* dfg/DFGCompilationKey.cpp: Added.
(JSC::DFG::CompilationKey::dump):
* dfg/DFGCompilationKey.h: Added.
(JSC::DFG::CompilationKey::CompilationKey):
(JSC::DFG::CompilationKey::operator!):
(JSC::DFG::CompilationKey::isHashTableDeletedValue):
(JSC::DFG::CompilationKey::profiledBlock):
(JSC::DFG::CompilationKey::mode):
(JSC::DFG::CompilationKey::operator==):
(JSC::DFG::CompilationKey::hash):
(JSC::DFG::CompilationKeyHash::hash):
(JSC::DFG::CompilationKeyHash::equal):
* dfg/DFGCompilationMode.cpp: Added.
(WTF::printInternal):
* dfg/DFGCompilationMode.h: Added.
* dfg/DFGDriver.cpp:
(JSC::DFG::compileImpl):
(JSC::DFG::compile):
* dfg/DFGDriver.h:
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::Plan):
(JSC::DFG::Plan::key):
* dfg/DFGPlan.h:
* dfg/DFGWorklist.cpp:
(JSC::DFG::Worklist::enqueue):
(JSC::DFG::Worklist::compilationState):
(JSC::DFG::Worklist::completeAllReadyPlansForVM):
(JSC::DFG::Worklist::runThread):
* dfg/DFGWorklist.h:
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):

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

18 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/GNUmakefile.list.am
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Target.pri
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/dfg/DFGCompilationKey.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGCompilationKey.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGCompilationMode.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGCompilationMode.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGDriver.cpp
Source/JavaScriptCore/dfg/DFGDriver.h
Source/JavaScriptCore/dfg/DFGPlan.cpp
Source/JavaScriptCore/dfg/DFGPlan.h
Source/JavaScriptCore/dfg/DFGWorklist.cpp
Source/JavaScriptCore/dfg/DFGWorklist.h
Source/JavaScriptCore/jit/JITStubs.cpp

index c674a69..219d8fa 100644 (file)
@@ -96,6 +96,8 @@ set(JavaScriptCore_SOURCES
     dfg/DFGClobberize.cpp
     dfg/DFGCommon.cpp
     dfg/DFGCommonData.cpp
+    dfg/DFGCompilationKey.cpp
+    dfg/DFGCompilationMode.cpp
     dfg/DFGConstantFoldingPhase.cpp
     dfg/DFGCriticalEdgeBreakingPhase.cpp
     dfg/DFGDCEPhase.cpp
index 0d024b9..fdb9d8e 100644 (file)
@@ -1,3 +1,81 @@
+2013-08-29  Filip Pizlo  <fpizlo@apple.com>
+
+        Teach DFG::Worklist and its clients that it may be reused for different kinds of compilations
+        https://bugs.webkit.org/show_bug.cgi?id=120489
+
+        Reviewed by Geoffrey Garen.
+        
+        If the baseline JIT hits an OSR entry trigger into the DFG and we already have a
+        DFG compilation but we've also started one or more FTL compilations, then we
+        shouldn't get confused. Previously we would have gotten confused because we would
+        see an in-process deferred compile (the FTL compile) and also an optimized
+        replacement (the DFG code).
+        
+        If the baseline JIT hits an OSR entry trigger into the DFG and we previously
+        did two things in this order: triggered a tier-up compilation from the DFG into
+        the FTL, and then jettisoned the DFG code because it exited a bunch, then we
+        shouldn't be confused by the presence of an in-process deferred compile (the FTL
+        compile). Previously we would have waited for that compile to finish; but the more
+        sensible thing to do is to let it complete and then invalidate it, while at the
+        same time enqueueing a DFG compile to create a new, more valid, DFG code block.
+        
+        If the DFG JIT hits a loop OSR entry trigger (into the FTL) and it has already
+        triggered an FTL compile for replacement, then it should fire off a second compile
+        instead of thinking that it can wait for that one to finish. Or vice-versa. We
+        need to allow for two FTL compiles to be enqueued at the same time (one for
+        replacement and one for OSR entry in a loop).
+        
+        Then there's also the problem that DFG::compile() is almost certainly going to be
+        the hook for triggering both DFG compiles and the two kinds of FTL compiles, but
+        right now there is no way to tell it which one you want.
+        
+        This fixes these problems and removes a bunch of potential confusion by making the
+        key for a compile in the DFG::Worklist be a CompilationMode (one of DFGMode,
+        FTLMode, or FTLForOSREntryMode). That mode is also passed to DFG::compile().
+        
+        Awkwardly, this still leaves us in a no DFG->FTL tier-up situation - so
+        DFG::compile() is always passed DFGMode and then it might do an FTL compile if
+        possible. Fixing that is a bigger issue for a later changeset.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Target.pri:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::checkIfOptimizationThresholdReached):
+        * dfg/DFGCompilationKey.cpp: Added.
+        (JSC::DFG::CompilationKey::dump):
+        * dfg/DFGCompilationKey.h: Added.
+        (JSC::DFG::CompilationKey::CompilationKey):
+        (JSC::DFG::CompilationKey::operator!):
+        (JSC::DFG::CompilationKey::isHashTableDeletedValue):
+        (JSC::DFG::CompilationKey::profiledBlock):
+        (JSC::DFG::CompilationKey::mode):
+        (JSC::DFG::CompilationKey::operator==):
+        (JSC::DFG::CompilationKey::hash):
+        (JSC::DFG::CompilationKeyHash::hash):
+        (JSC::DFG::CompilationKeyHash::equal):
+        * dfg/DFGCompilationMode.cpp: Added.
+        (WTF::printInternal):
+        * dfg/DFGCompilationMode.h: Added.
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compileImpl):
+        (JSC::DFG::compile):
+        * dfg/DFGDriver.h:
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::Plan):
+        (JSC::DFG::Plan::key):
+        * dfg/DFGPlan.h:
+        * dfg/DFGWorklist.cpp:
+        (JSC::DFG::Worklist::enqueue):
+        (JSC::DFG::Worklist::compilationState):
+        (JSC::DFG::Worklist::completeAllReadyPlansForVM):
+        (JSC::DFG::Worklist::runThread):
+        * dfg/DFGWorklist.h:
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+
 2013-08-29  Brent Fulgham  <bfulgham@apple.com>
 
         [Windows] Unreviewed build fix after r154847.
index 6f84ec3..6b807c9 100644 (file)
@@ -226,6 +226,10 @@ javascriptcore_sources += \
        Source/JavaScriptCore/dfg/DFGCommon.h \
        Source/JavaScriptCore/dfg/DFGCommonData.cpp \
        Source/JavaScriptCore/dfg/DFGCommonData.h \
+       Source/JavaScriptCore/dfg/DFGCompilationKey.cpp \
+       Source/JavaScriptCore/dfg/DFGCompilationKey.h \
+       Source/JavaScriptCore/dfg/DFGCompilationMode.cpp \
+       Source/JavaScriptCore/dfg/DFGCompilationMode.h \
        Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp \
        Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.h \
        Source/JavaScriptCore/dfg/DFGCriticalEdgeBreakingPhase.cpp \
index 29590bb..1ab8c85 100644 (file)
     <ClCompile Include="..\debugger\Debugger.cpp" />\r
     <ClCompile Include="..\debugger\DebuggerActivation.cpp" />\r
     <ClCompile Include="..\debugger\DebuggerCallFrame.cpp" />\r
+    <ClCompile Include="..\dfg\DFGCompilationKey.cpp" />\r
+    <ClCompile Include="..\dfg\DFGCompilationMode.cpp" />\r
+    <ClCompile Include="..\dfg\DFGDriver.cpp" />\r
     <ClCompile Include="..\disassembler\Disassembler.cpp" />\r
     <ClCompile Include="..\heap\BlockAllocator.cpp" />\r
     <ClCompile Include="..\heap\ConservativeRoots.cpp" />\r
     <ClInclude Include="..\debugger\Debugger.h" />\r
     <ClInclude Include="..\debugger\DebuggerActivation.h" />\r
     <ClInclude Include="..\debugger\DebuggerCallFrame.h" />\r
+    <ClInclude Include="..\dfg\DFGCompilationKey.h" />\r
+    <ClInclude Include="..\dfg\DFGCompilationMode.h" />\r
     <ClInclude Include="..\dfg\DFGDriver.h" />\r
     <ClInclude Include="..\dfg\DFGOSREntry.h" />\r
     <ClInclude Include="..\disassembler\Disassembler.h" />\r
index 39d3b3c..1853724 100644 (file)
                0F34B14C16D43E0D001CDA5A /* PolymorphicAccessStructureList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14B16D43E0C001CDA5A /* PolymorphicAccessStructureList.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F38B01117CF078000B144D3 /* LLIntEntrypoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F38B00F17CF077F00B144D3 /* LLIntEntrypoint.cpp */; };
                0F38B01217CF078300B144D3 /* LLIntEntrypoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F38B01017CF077F00B144D3 /* LLIntEntrypoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F38B01717CFE75500B144D3 /* DFGCompilationKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F38B01317CFE75500B144D3 /* DFGCompilationKey.cpp */; };
+               0F38B01817CFE75500B144D3 /* DFGCompilationKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F38B01417CFE75500B144D3 /* DFGCompilationKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F38B01917CFE75500B144D3 /* DFGCompilationMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F38B01517CFE75500B144D3 /* DFGCompilationMode.cpp */; };
+               0F38B01A17CFE75500B144D3 /* DFGCompilationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F38B01617CFE75500B144D3 /* DFGCompilationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F3B3A1A153E68F2003ED0FF /* DFGConstantFoldingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B3A17153E68EF003ED0FF /* DFGConstantFoldingPhase.cpp */; };
                0F3B3A1B153E68F4003ED0FF /* DFGConstantFoldingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B3A18153E68EF003ED0FF /* DFGConstantFoldingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F3B3A271544C995003ED0FF /* DFGCFGSimplificationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B3A241544C991003ED0FF /* DFGCFGSimplificationPhase.cpp */; };
                0F34B14B16D43E0C001CDA5A /* PolymorphicAccessStructureList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccessStructureList.h; sourceTree = "<group>"; };
                0F38B00F17CF077F00B144D3 /* LLIntEntrypoint.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoint.cpp; path = llint/LLIntEntrypoint.cpp; sourceTree = "<group>"; };
                0F38B01017CF077F00B144D3 /* LLIntEntrypoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LLIntEntrypoint.h; path = llint/LLIntEntrypoint.h; sourceTree = "<group>"; };
+               0F38B01317CFE75500B144D3 /* DFGCompilationKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCompilationKey.cpp; path = dfg/DFGCompilationKey.cpp; sourceTree = "<group>"; };
+               0F38B01417CFE75500B144D3 /* DFGCompilationKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCompilationKey.h; path = dfg/DFGCompilationKey.h; sourceTree = "<group>"; };
+               0F38B01517CFE75500B144D3 /* DFGCompilationMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCompilationMode.cpp; path = dfg/DFGCompilationMode.cpp; sourceTree = "<group>"; };
+               0F38B01617CFE75500B144D3 /* DFGCompilationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCompilationMode.h; path = dfg/DFGCompilationMode.h; sourceTree = "<group>"; };
                0F3B3A17153E68EF003ED0FF /* DFGConstantFoldingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGConstantFoldingPhase.cpp; path = dfg/DFGConstantFoldingPhase.cpp; sourceTree = "<group>"; };
                0F3B3A18153E68EF003ED0FF /* DFGConstantFoldingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGConstantFoldingPhase.h; path = dfg/DFGConstantFoldingPhase.h; sourceTree = "<group>"; };
                0F3B3A241544C991003ED0FF /* DFGCFGSimplificationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCFGSimplificationPhase.cpp; path = dfg/DFGCFGSimplificationPhase.cpp; sourceTree = "<group>"; };
                86EC9DB31328DF44002B2AD7 /* dfg */ = {
                        isa = PBXGroup;
                        children = (
+                               0F38B01317CFE75500B144D3 /* DFGCompilationKey.cpp */,
+                               0F38B01417CFE75500B144D3 /* DFGCompilationKey.h */,
+                               0F38B01517CFE75500B144D3 /* DFGCompilationMode.cpp */,
+                               0F38B01617CFE75500B144D3 /* DFGCompilationMode.h */,
                                A77A423617A0BBFD00A8DB81 /* DFGAbstractHeap.cpp */,
                                A77A423717A0BBFD00A8DB81 /* DFGAbstractHeap.h */,
                                A704D8FE17A0BAA8006BA554 /* DFGAbstractInterpreter.h */,
                                978801411471AD920041B016 /* JSDateMath.h in Headers */,
                                C2A7F688160432D400F76B98 /* JSDestructibleObject.h in Headers */,
                                86E3C614167BABD7006D760A /* JSExport.h in Headers */,
+                               0F38B01A17CFE75500B144D3 /* DFGCompilationMode.h in Headers */,
                                A7B4ACAF1484C9CE00B38A36 /* JSExportMacros.h in Headers */,
                                0F2B66EF17B6B5AB00A7AE3F /* JSFloat32Array.h in Headers */,
                                0F2B66F017B6B5AB00A7AE3F /* JSFloat64Array.h in Headers */,
                                0FF729BF166AD360000F5BA3 /* ProfilerOrigin.h in Headers */,
                                0FF729C0166AD360000F5BA3 /* ProfilerOriginStack.h in Headers */,
                                0FB1058C1675483300F8AB6E /* ProfilerOSRExit.h in Headers */,
+                               0F38B01817CFE75500B144D3 /* DFGCompilationKey.h in Headers */,
                                0FB1058E1675483A00F8AB6E /* ProfilerOSRExitSite.h in Headers */,
                                0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */,
                                A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */,
                                A77F1821164088B200640A47 /* CodeCache.cpp in Sources */,
                                0F8F9446166764F100D61971 /* CodeOrigin.cpp in Sources */,
                                86B5826714D2796C00A9C306 /* CodeProfile.cpp in Sources */,
+                               0F38B01917CFE75500B144D3 /* DFGCompilationMode.cpp in Sources */,
                                86B5826914D2797000A9C306 /* CodeProfiling.cpp in Sources */,
                                0F8F943C1667631300D61971 /* CodeSpecializationKind.cpp in Sources */,
                                0F8F94421667633500D61971 /* CodeType.cpp in Sources */,
                                C2C0F7CD17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp in Sources */,
                                0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
                                C2981FD817BAEE4B00A3BC98 /* DFGDesiredWeakReferences.cpp in Sources */,
+                               0F38B01717CFE75500B144D3 /* DFGCompilationKey.cpp in Sources */,
                                C2981FDC17BAFF4400A3BC98 /* DFGDesiredWriteBarriers.cpp in Sources */,
                                0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */,
                                7C3BA29817C039560072DDC9 /* JSPromiseResolverPrototype.cpp in Sources */,
index 98390c4..130991a 100644 (file)
@@ -129,6 +129,8 @@ SOURCES += \
     dfg/DFGClobberSet.cpp \
     dfg/DFGCommon.cpp \
     dfg/DFGCommonData.cpp \
+    dfg/DFGCompilationKey.cpp \
+    dfg/DFGCompilationMode.cpp \
     dfg/DFGCFAPhase.cpp \
     dfg/DFGCFGSimplificationPhase.cpp \
     dfg/DFGCPSRethreadingPhase.cpp \
index 54b369c..f8685e5 100644 (file)
@@ -2973,10 +2973,12 @@ int32_t CodeBlock::adjustedCounterValue(int32_t desiredThreshold)
 bool CodeBlock::checkIfOptimizationThresholdReached()
 {
 #if ENABLE(DFG_JIT)
-    if (m_vm->worklist
-        && m_vm->worklist->compilationState(this) == DFG::Worklist::Compiled) {
-        optimizeNextInvocation();
-        return true;
+    if (DFG::Worklist* worklist = m_vm->worklist.get()) {
+        if (worklist->compilationState(DFG::CompilationKey(this, DFG::DFGMode))
+            == DFG::Worklist::Compiled) {
+            optimizeNextInvocation();
+            return true;
+        }
     }
 #endif
     
diff --git a/Source/JavaScriptCore/dfg/DFGCompilationKey.cpp b/Source/JavaScriptCore/dfg/DFGCompilationKey.cpp
new file mode 100644 (file)
index 0000000..dd78d83
--- /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. 
+ */
+
+#include "config.h"
+#include "DFGCompilationKey.h"
+
+#include "CodeBlock.h"
+
+namespace JSC { namespace DFG {
+
+void CompilationKey::dump(PrintStream& out) const
+{
+    if (!*this) {
+        out.print("<empty>");
+        return;
+    }
+    out.print("(Compile of ", *m_profiledBlock, " with ", m_mode, ")");
+}
+
+} } // namespace JSC::DFG
+
+
diff --git a/Source/JavaScriptCore/dfg/DFGCompilationKey.h b/Source/JavaScriptCore/dfg/DFGCompilationKey.h
new file mode 100644 (file)
index 0000000..a866acd
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * 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 DFGCompilationKey_h
+#define DFGCompilationKey_h
+
+#include "DFGCompilationMode.h"
+#include <wtf/HashMap.h>
+
+namespace JSC {
+
+class CodeBlock;
+
+namespace DFG {
+
+class CompilationKey {
+public:
+    CompilationKey()
+        : m_profiledBlock(0)
+        , m_mode(InvalidCompilationMode)
+    {
+    }
+    
+    CompilationKey(WTF::HashTableDeletedValueType)
+        : m_profiledBlock(0)
+        , m_mode(DFGMode)
+    {
+    }
+    
+    CompilationKey(CodeBlock* profiledBlock, CompilationMode mode)
+        : m_profiledBlock(profiledBlock)
+        , m_mode(mode)
+    {
+    }
+    
+    bool operator!() const
+    {
+        return !m_profiledBlock && m_mode == InvalidCompilationMode;
+    }
+    
+    bool isHashTableDeletedValue() const
+    {
+        return !m_profiledBlock && m_mode != InvalidCompilationMode;
+    }
+    
+    CodeBlock* profiledBlock() const { return m_profiledBlock; }
+    CompilationMode mode() const { return m_mode; }
+    
+    bool operator==(const CompilationKey& other) const
+    {
+        return m_profiledBlock == other.m_profiledBlock
+            && m_mode == other.m_mode;
+    }
+    
+    unsigned hash() const
+    {
+        return WTF::pairIntHash(WTF::PtrHash<CodeBlock*>::hash(m_profiledBlock), m_mode);
+    }
+    
+    void dump(PrintStream&) const;
+
+private:
+    CodeBlock* m_profiledBlock;
+    CompilationMode m_mode;
+};
+
+struct CompilationKeyHash {
+    static unsigned hash(const CompilationKey& key) { return key.hash(); }
+    static bool equal(const CompilationKey& a, const CompilationKey& b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::DFG::CompilationKey> {
+    typedef JSC::DFG::CompilationKeyHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::DFG::CompilationKey> : SimpleClassHashTraits<JSC::DFG::CompilationKey> { };
+
+} // namespace WTF
+
+#endif // DFGCompilationKey_h
+
diff --git a/Source/JavaScriptCore/dfg/DFGCompilationMode.cpp b/Source/JavaScriptCore/dfg/DFGCompilationMode.cpp
new file mode 100644 (file)
index 0000000..4a44457
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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 "DFGCompilationMode.h"
+
+namespace WTF {
+
+using namespace JSC::DFG;
+
+void printInternal(PrintStream& out, CompilationMode mode)
+{
+    switch (mode) {
+    case InvalidCompilationMode:
+        out.print("InvalidCompilationMode");
+        return;
+    case DFGMode:
+        out.print("DFGMode");
+        return;
+    case FTLMode:
+        out.print("FTLMode");
+        return;
+    case FTLForOSREntryMode:
+        out.print("FTLForOSREntryMode");
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
+
diff --git a/Source/JavaScriptCore/dfg/DFGCompilationMode.h b/Source/JavaScriptCore/dfg/DFGCompilationMode.h
new file mode 100644 (file)
index 0000000..1035f60
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 DFGCompilationMode_h
+#define DFGCompilationMode_h
+
+#include <wtf/PrintStream.h>
+
+namespace JSC { namespace DFG {
+
+enum CompilationMode {
+    InvalidCompilationMode,
+    DFGMode,
+    FTLMode,
+    FTLForOSREntryMode
+};
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+void printInternal(PrintStream&, JSC::DFG::CompilationMode);
+
+} // namespace WTF
+
+#endif // DFGCompilationMode_h
+
index 8065294..dc147ed 100644 (file)
@@ -54,7 +54,10 @@ unsigned getNumCompilations()
 }
 
 #if ENABLE(DFG_JIT)
-static CompilationResult compileImpl(ExecState* exec, CodeBlock* codeBlock, unsigned osrEntryBytecodeIndex, PassRefPtr<DeferredCompilationCallback> callback, Worklist* worklist)
+static CompilationResult compileImpl(
+    ExecState* exec, CodeBlock* codeBlock, CompilationMode mode,
+    unsigned osrEntryBytecodeIndex, PassRefPtr<DeferredCompilationCallback> callback,
+    Worklist* worklist)
 {
     SamplingRegion samplingRegion("DFG Compilation (Driver)");
     
@@ -98,7 +101,7 @@ static CompilationResult compileImpl(ExecState* exec, CodeBlock* codeBlock, unsi
     else
         numVarsWithValues = 0;
     RefPtr<Plan> plan = adoptRef(
-        new Plan(codeBlock, osrEntryBytecodeIndex, numVarsWithValues));
+        new Plan(codeBlock, mode, osrEntryBytecodeIndex, numVarsWithValues));
     for (size_t i = 0; i < plan->mustHandleValues.size(); ++i) {
         int operand = plan->mustHandleValues.operandForIndex(i);
         if (operandIsArgument(operand)
@@ -126,16 +129,22 @@ static CompilationResult compileImpl(ExecState* exec, CodeBlock* codeBlock, unsi
     return plan->finalizeWithoutNotifyingCallback();
 }
 #else // ENABLE(DFG_JIT)
-static CompilationResult compileImpl(ExecState*, CodeBlock*, unsigned, PassRefPtr<DeferredCompilationCallback>, Worklist*)
+static CompilationResult compileImpl(
+    ExecState*, CodeBlock*, CompilationMode, unsigned,
+    PassRefPtr<DeferredCompilationCallback>, Worklist*)
 {
     return CompilationFailed;
 }
 #endif // ENABLE(DFG_JIT)
 
-CompilationResult compile(ExecState* exec, CodeBlock* codeBlock, unsigned osrEntryBytecodeIndex, PassRefPtr<DeferredCompilationCallback> passedCallback, Worklist* worklist)
+CompilationResult compile(
+    ExecState* exec, CodeBlock* codeBlock, CompilationMode mode,
+    unsigned osrEntryBytecodeIndex, PassRefPtr<DeferredCompilationCallback> passedCallback,
+    Worklist* worklist)
 {
     RefPtr<DeferredCompilationCallback> callback = passedCallback;
-    CompilationResult result = compileImpl(exec, codeBlock, osrEntryBytecodeIndex, callback, worklist);
+    CompilationResult result = compileImpl(
+        exec, codeBlock, mode, osrEntryBytecodeIndex, callback, worklist);
     if (result != CompilationDeferred)
         callback->compilationDidComplete(codeBlock, result);
     return result;
index 4220e9d..03204c8 100644 (file)
@@ -27,6 +27,7 @@
 #define DFGDriver_h
 
 #include "CallFrame.h"
+#include "DFGCompilationMode.h"
 #include "DFGPlan.h"
 #include <wtf/Platform.h>
 
@@ -45,7 +46,7 @@ JS_EXPORT_PRIVATE unsigned getNumCompilations();
 
 // If the worklist is non-null, we do a concurrent compile. Otherwise we do a synchronous
 // compile. Even if we do a synchronous compile, we call the callback with the result.
-CompilationResult compile(ExecState*, CodeBlock*, unsigned osrEntryBytecodeIndex, PassRefPtr<DeferredCompilationCallback>, Worklist*);
+CompilationResult compile(ExecState*, CodeBlock*, CompilationMode, unsigned osrEntryBytecodeIndex, PassRefPtr<DeferredCompilationCallback>, Worklist*);
 
 } } // namespace JSC::DFG
 
index f5a7434..696dc0e 100644 (file)
@@ -80,10 +80,11 @@ static void dumpAndVerifyGraph(Graph& graph, const char* text)
 }
 
 Plan::Plan(
-    PassRefPtr<CodeBlock> passedCodeBlock, unsigned osrEntryBytecodeIndex,
-    unsigned numVarsWithValues)
+    PassRefPtr<CodeBlock> passedCodeBlock, CompilationMode mode,
+    unsigned osrEntryBytecodeIndex, unsigned numVarsWithValues)
     : vm(*passedCodeBlock->vm())
     , codeBlock(passedCodeBlock)
+    , mode(mode)
     , osrEntryBytecodeIndex(osrEntryBytecodeIndex)
     , numVarsWithValues(numVarsWithValues)
     , mustHandleValues(codeBlock->numParameters(), numVarsWithValues)
@@ -310,9 +311,9 @@ void Plan::finalizeAndNotifyCallback()
     callback->compilationDidComplete(codeBlock.get(), finalizeWithoutNotifyingCallback());
 }
 
-CodeBlock* Plan::key()
+CompilationKey Plan::key()
 {
-    return codeBlock->alternative();
+    return CompilationKey(codeBlock->alternative(), mode);
 }
 
 } } // namespace JSC::DFG
index 59868d0..01d7c3c 100644 (file)
@@ -29,6 +29,8 @@
 #include <wtf/Platform.h>
 
 #include "CompilationResult.h"
+#include "DFGCompilationKey.h"
+#include "DFGCompilationMode.h"
 #include "DFGDesiredIdentifiers.h"
 #include "DFGDesiredStructureChains.h"
 #include "DFGDesiredTransitions.h"
@@ -53,7 +55,8 @@ class LongLivedState;
 
 struct Plan : public ThreadSafeRefCounted<Plan> {
     Plan(
-        PassRefPtr<CodeBlock>, unsigned osrEntryBytecodeIndex, unsigned numVarsWithValues);
+        PassRefPtr<CodeBlock>, CompilationMode, unsigned osrEntryBytecodeIndex,
+        unsigned numVarsWithValues);
     ~Plan();
     
     void compileInThread(LongLivedState&);
@@ -63,10 +66,11 @@ struct Plan : public ThreadSafeRefCounted<Plan> {
     
     void notifyReady();
     
-    CodeBlock* key();
+    CompilationKey key();
     
     VM& vm;
     RefPtr<CodeBlock> codeBlock;
+    CompilationMode mode;
     const unsigned osrEntryBytecodeIndex;
     const unsigned numVarsWithValues;
     Operands<JSValue> mustHandleValues;
index 7f3d130..3f434be 100644 (file)
@@ -72,7 +72,7 @@ void Worklist::enqueue(PassRefPtr<Plan> passedPlan)
     MutexLocker locker(m_lock);
     if (Options::verboseCompilationQueue()) {
         dump(locker, WTF::dataFile());
-        dataLog(": Enqueueing plan to optimize ", *plan->key(), "\n");
+        dataLog(": Enqueueing plan to optimize ", plan->key(), "\n");
     }
     ASSERT(m_plans.find(plan->key()) == m_plans.end());
     m_plans.add(plan->key(), plan);
@@ -80,10 +80,10 @@ void Worklist::enqueue(PassRefPtr<Plan> passedPlan)
     m_planEnqueued.signal();
 }
 
-Worklist::State Worklist::compilationState(CodeBlock* profiledBlock)
+Worklist::State Worklist::compilationState(CompilationKey key)
 {
     MutexLocker locker(m_lock);
-    PlanMap::iterator iter = m_plans.find(profiledBlock);
+    PlanMap::iterator iter = m_plans.find(key);
     if (iter == m_plans.end())
         return NotKnown;
     return iter->value->isCompiled ? Compiled : Compiling;
@@ -147,7 +147,7 @@ void Worklist::removeAllReadyPlansForVM(VM& vm)
     removeAllReadyPlansForVM(vm, myReadyPlans);
 }
 
-Worklist::State Worklist::completeAllReadyPlansForVM(VM& vm, CodeBlock* requestedProfiledBlock)
+Worklist::State Worklist::completeAllReadyPlansForVM(VM& vm, CompilationKey requestedKey)
 {
     DeferGC deferGC(vm.heap);
     Vector<RefPtr<Plan>, 8> myReadyPlans;
@@ -158,22 +158,22 @@ Worklist::State Worklist::completeAllReadyPlansForVM(VM& vm, CodeBlock* requeste
 
     while (!myReadyPlans.isEmpty()) {
         RefPtr<Plan> plan = myReadyPlans.takeLast();
-        CodeBlock* profiledBlock = plan->key();
+        CompilationKey currentKey = plan->key();
         
         if (Options::verboseCompilationQueue())
-            dataLog(*this, ": Completing ", *profiledBlock, "\n");
+            dataLog(*this, ": Completing ", currentKey, "\n");
         
         RELEASE_ASSERT(plan->isCompiled);
         
         plan->finalizeAndNotifyCallback();
         
-        if (profiledBlock == requestedProfiledBlock)
+        if (currentKey == requestedKey)
             resultingState = Compiled;
     }
     
-    if (requestedProfiledBlock && resultingState == NotKnown) {
+    if (!!requestedKey && resultingState == NotKnown) {
         MutexLocker locker(m_lock);
-        if (m_plans.contains(requestedProfiledBlock))
+        if (m_plans.contains(requestedKey))
             resultingState = Compiling;
     }
     
@@ -234,7 +234,7 @@ void Worklist::runThread()
         }
         
         if (Options::verboseCompilationQueue())
-            dataLog(*this, ": Compiling ", *plan->key(), " asynchronously\n");
+            dataLog(*this, ": Compiling ", plan->key(), " asynchronously\n");
         
         plan->compileInThread(longLivedState);
         
@@ -244,7 +244,7 @@ void Worklist::runThread()
             
             if (Options::verboseCompilationQueue()) {
                 dump(locker, WTF::dataFile());
-                dataLog(": Compiled ", *plan->key(), " asynchronously\n");
+                dataLog(": Compiled ", plan->key(), " asynchronously\n");
             }
             
             m_readyPlans.append(plan);
index 70101a2..f8f586d 100644 (file)
@@ -55,10 +55,10 @@ public:
     void completeAllPlansForVM(VM&);
     
     void waitUntilAllPlansForVMAreReady(VM&);
-    State completeAllReadyPlansForVM(VM&, CodeBlock* profiledBlock = 0);
+    State completeAllReadyPlansForVM(VM&, CompilationKey = CompilationKey());
     void removeAllReadyPlansForVM(VM&);
     
-    State compilationState(CodeBlock* profiledBlock);
+    State compilationState(CompilationKey);
     
     size_t queueLength();
     void dump(PrintStream&) const;
@@ -81,7 +81,7 @@ private:
     // is particularly great for the cti_optimize OSR slow path, which wants
     // to know: did I get here because a better version of me just got
     // compiled?
-    typedef HashMap<RefPtr<CodeBlock>, RefPtr<Plan> > PlanMap;
+    typedef HashMap<CompilationKey, RefPtr<Plan> > PlanMap;
     PlanMap m_plans;
     
     // Used to quickly find which plans have been compiled and are ready to
index 98e0d0b..64c39b7 100644 (file)
@@ -40,6 +40,7 @@
 #include "CodeBlock.h"
 #include "CodeProfiling.h"
 #include "CommonSlowPaths.h"
+#include "DFGCompilationMode.h"
 #include "DFGDriver.h"
 #include "DFGOSREntry.h"
 #include "DFGWorklist.h"
@@ -948,7 +949,7 @@ DEFINE_STUB_FUNCTION(void, optimize)
     // replacement.
     ASSERT(
         !vm.worklist
-        || !(vm.worklist->compilationState(codeBlock) != DFG::Worklist::NotKnown
+        || !(vm.worklist->compilationState(DFG::CompilationKey(codeBlock, DFG::DFGMode)) != DFG::Worklist::NotKnown
              && codeBlock->hasOptimizedReplacement()));
     
     DFG::Worklist::State worklistState;
@@ -972,8 +973,8 @@ DEFINE_STUB_FUNCTION(void, optimize)
         // possible in order to minimize the chances of us executing baseline code after
         // optimized code is already available.
         
-        worklistState =
-            vm.worklist->completeAllReadyPlansForVM(vm, codeBlock);
+        worklistState = vm.worklist->completeAllReadyPlansForVM(
+            vm, DFG::CompilationKey(codeBlock, DFG::DFGMode));
     } else
         worklistState = DFG::Worklist::NotKnown;
     
@@ -1043,7 +1044,8 @@ DEFINE_STUB_FUNCTION(void, optimize)
             vm.worklist = DFG::globalWorklist();
         
         CompilationResult result = DFG::compile(
-            callFrame, newCodeBlock.get(), bytecodeIndex, callback, vm.worklist.get());
+            callFrame, newCodeBlock.get(), DFG::DFGMode, bytecodeIndex, callback,
+            vm.worklist.get());
         
         if (result != CompilationSuccessful)
             return;