Title: [161732] branches/jsCStack/Source/_javascript_Core
Revision
161732
Author
[email protected]
Date
2014-01-10 21:06:10 -0800 (Fri, 10 Jan 2014)

Log Message

FTL should enough things to compile inlined closure calls (like CheckExecutable and GetScope)
https://bugs.webkit.org/show_bug.cgi?id=126799

Reviewed by Oliver Hunt.
        
Added FTL support for CheckExecutable and GetScope because I wanted to compile
closure calls. But then I realized that closure call inlining was broken because
the baseline JIT would link the closure stubs to the slow path, thereby causing
the DFG's profiling to think that all closure calls are actually virtual calls.
        
Also fixed some hash() computing stuff to make debugging easier.

* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileCheckExecutable):
(JSC::FTL::LowerDFGToLLVM::compileGetScope):
* jit/Repatch.cpp:
(JSC::linkClosureCall):
* runtime/Options.cpp:
(JSC::recomputeDependentOptions):
(JSC::Options::initialize):
(JSC::Options::setOption):
* tests/stress/inline-closure-call.js: Added.
(bar):

Modified Paths

Added Paths

Diff

Modified: branches/jsCStack/Source/_javascript_Core/ChangeLog (161731 => 161732)


--- branches/jsCStack/Source/_javascript_Core/ChangeLog	2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/_javascript_Core/ChangeLog	2014-01-11 05:06:10 UTC (rev 161732)
@@ -1,5 +1,35 @@
 2014-01-10  Filip Pizlo  <[email protected]>
 
+        FTL should enough things to compile inlined closure calls (like CheckExecutable and GetScope)
+        https://bugs.webkit.org/show_bug.cgi?id=126799
+
+        Reviewed by Oliver Hunt.
+        
+        Added FTL support for CheckExecutable and GetScope because I wanted to compile
+        closure calls. But then I realized that closure call inlining was broken because
+        the baseline JIT would link the closure stubs to the slow path, thereby causing
+        the DFG's profiling to think that all closure calls are actually virtual calls.
+        
+        Also fixed some hash() computing stuff to make debugging easier.
+
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileCheckExecutable):
+        (JSC::FTL::LowerDFGToLLVM::compileGetScope):
+        * jit/Repatch.cpp:
+        (JSC::linkClosureCall):
+        * runtime/Options.cpp:
+        (JSC::recomputeDependentOptions):
+        (JSC::Options::initialize):
+        (JSC::Options::setOption):
+        * tests/stress/inline-closure-call.js: Added.
+        (bar):
+
+2014-01-10  Filip Pizlo  <[email protected]>
+
         It should be easier to diagnose FTL performance issues due to register preservation thunks
         https://bugs.webkit.org/show_bug.cgi?id=126798
 

Modified: branches/jsCStack/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (161731 => 161732)


--- branches/jsCStack/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2014-01-11 05:06:10 UTC (rev 161732)
@@ -47,6 +47,8 @@
     macro(JSArrayBufferView_mode, JSArrayBufferView::offsetOfMode()) \
     macro(JSArrayBufferView_vector, JSArrayBufferView::offsetOfVector()) \
     macro(JSCell_structure, JSCell::structureOffset()) \
+    macro(JSFunction_executable, JSFunction::offsetOfExecutable()) \
+    macro(JSFunction_scope, JSFunction::offsetOfScopeChain()) \
     macro(JSObject_butterfly, JSObject::butterflyOffset()) \
     macro(JSScope_next, JSScope::offsetOfNext()) \
     macro(JSString_length, JSString::offsetOfLength()) \

Modified: branches/jsCStack/Source/_javascript_Core/ftl/FTLCapabilities.cpp (161731 => 161732)


--- branches/jsCStack/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2014-01-11 05:06:10 UTC (rev 161732)
@@ -116,6 +116,8 @@
     case CheckInBounds:
     case ConstantStoragePointer:
     case Check:
+    case CheckExecutable:
+    case GetScope:
         // These are OK.
         break;
     case GetById:

Modified: branches/jsCStack/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (161731 => 161732)


--- branches/jsCStack/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2014-01-11 05:06:10 UTC (rev 161732)
@@ -353,6 +353,9 @@
         case CheckFunction:
             compileCheckFunction();
             break;
+        case CheckExecutable:
+            compileCheckExecutable();
+            break;
         case ArrayifyToStructure:
             compileArrayifyToStructure();
             break;
@@ -427,6 +430,9 @@
         case NotifyWrite:
             compileNotifyWrite();
             break;
+        case GetScope:
+            compileGetScope();
+            break;
         case GetMyScope:
             compileGetMyScope();
             break;
@@ -1333,6 +1339,17 @@
             m_out.notEqual(cell, weakPointer(m_node->function())));
     }
     
+    void compileCheckExecutable()
+    {
+        LValue cell = lowCell(m_node->child1());
+        
+        speculate(
+            BadExecutable, jsValueValue(cell), m_node->child1().node(),
+            m_out.notEqual(
+                m_out.loadPtr(cell, m_heaps.JSFunction_executable),
+                weakPointer(m_node->function())));
+    }
+    
     void compileArrayifyToStructure()
     {
         LValue cell = lowCell(m_node->child1());
@@ -2403,6 +2420,11 @@
         m_out.appendTo(continuation, lastNext);
     }
     
+    void compileGetScope()
+    {
+        setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSFunction_scope));
+    }
+    
     void compileGetMyScope()
     {
         setJSValue(m_out.loadPtr(addressFor(

Modified: branches/jsCStack/Source/_javascript_Core/jit/Repatch.cpp (161731 => 161732)


--- branches/jsCStack/Source/_javascript_Core/jit/Repatch.cpp	2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/_javascript_Core/jit/Repatch.cpp	2014-01-11 05:06:10 UTC (rev 161732)
@@ -1406,7 +1406,10 @@
     LinkBuffer patchBuffer(*vm, &stubJit, callerCodeBlock);
     
     patchBuffer.link(call, FunctionPtr(codePtr.executableAddress()));
-    patchBuffer.link(done, callLinkInfo.callReturnLocation.labelAtOffset(0));
+    if (JITCode::isOptimizingJIT(callerCodeBlock->jitType()))
+        patchBuffer.link(done, callLinkInfo.callReturnLocation.labelAtOffset(0));
+    else
+        patchBuffer.link(done, callLinkInfo.hotPathOther.labelAtOffset(0));
     patchBuffer.link(slow, CodeLocationLabel(vm->getCTIStub(virtualThunkGeneratorFor(CodeForCall, registers)).code()));
     
     RefPtr<ClosureCallStubRoutine> stubRoutine = adoptRef(new ClosureCallStubRoutine(

Modified: branches/jsCStack/Source/_javascript_Core/runtime/Options.cpp (161731 => 161732)


--- branches/jsCStack/Source/_javascript_Core/runtime/Options.cpp	2014-01-11 05:02:01 UTC (rev 161731)
+++ branches/jsCStack/Source/_javascript_Core/runtime/Options.cpp	2014-01-11 05:06:10 UTC (rev 161732)
@@ -31,6 +31,7 @@
 #include <limits>
 #include <stdlib.h>
 #include <string.h>
+#include <wtf/DataLog.h>
 #include <wtf/NumberOfCores.h>
 #include <wtf/PageBlock.h>
 #include <wtf/StdLibExtras.h>
@@ -175,6 +176,49 @@
 #undef FOR_EACH_OPTION
 };
 
+static void recomputeDependentOptions()
+{
+#if !ENABLE(JIT)
+    Options::useJIT() = false;
+    Options::useDFGJIT() = false;
+#endif
+#if !ENABLE(YARR_JIT)
+    Options::useRegExpJIT() = false;
+#endif
+    
+    if (Options::showDisassembly()
+        || Options::showDFGDisassembly()
+        || Options::dumpBytecodeAtDFGTime()
+        || Options::dumpGraphAtEachPhase()
+        || Options::verboseCompilation()
+        || Options::logCompilationChanges()
+        || Options::validateGraph()
+        || Options::validateGraphAtEachPhase()
+        || Options::verboseOSR()
+        || Options::verboseCompilationQueue()
+        || Options::reportCompileTimes()
+        || Options::verboseCFA()
+        || Options::verboseFTLFailure())
+        Options::alwaysComputeHash() = true;
+    
+    // Do range checks where needed and make corrections to the options:
+    ASSERT(Options::thresholdForOptimizeAfterLongWarmUp() >= Options::thresholdForOptimizeAfterWarmUp());
+    ASSERT(Options::thresholdForOptimizeAfterWarmUp() >= Options::thresholdForOptimizeSoon());
+    ASSERT(Options::thresholdForOptimizeAfterWarmUp() >= 0);
+
+    // Compute the maximum value of the reoptimization retry counter. This is simply
+    // the largest value at which we don't overflow the execute counter, when using it
+    // to left-shift the execution counter by this amount. Currently the value ends
+    // up being 18, so this loop is not so terrible; it probably takes up ~100 cycles
+    // total on a 32-bit processor.
+    Options::reoptimizationRetryCounterMax() = 0;
+    while ((static_cast<int64_t>(Options::thresholdForOptimizeAfterLongWarmUp()) << (Options::reoptimizationRetryCounterMax() + 1)) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max()))
+        Options::reoptimizationRetryCounterMax()++;
+
+    ASSERT((static_cast<int64_t>(Options::thresholdForOptimizeAfterLongWarmUp()) << Options::reoptimizationRetryCounterMax()) > 0);
+    ASSERT((static_cast<int64_t>(Options::thresholdForOptimizeAfterLongWarmUp()) << Options::reoptimizationRetryCounterMax()) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max()));
+}
+
 void Options::initialize()
 {
     // Initialize each of the options with their default values:
@@ -204,45 +248,7 @@
     ; // Deconfuse editors that do auto indentation
 #endif
     
-#if !ENABLE(JIT)
-    useJIT() = false;
-    useDFGJIT() = false;
-#endif
-#if !ENABLE(YARR_JIT)
-    useRegExpJIT() = false;
-#endif
-    
-    if (showDisassembly()
-        || showDFGDisassembly()
-        || dumpBytecodeAtDFGTime()
-        || dumpGraphAtEachPhase()
-        || verboseCompilation()
-        || logCompilationChanges()
-        || validateGraph()
-        || validateGraphAtEachPhase()
-        || verboseOSR()
-        || verboseCompilationQueue()
-        || reportCompileTimes()
-        || verboseCFA()
-        || verboseFTLFailure())
-        alwaysComputeHash() = true;
-    
-    // Do range checks where needed and make corrections to the options:
-    ASSERT(thresholdForOptimizeAfterLongWarmUp() >= thresholdForOptimizeAfterWarmUp());
-    ASSERT(thresholdForOptimizeAfterWarmUp() >= thresholdForOptimizeSoon());
-    ASSERT(thresholdForOptimizeAfterWarmUp() >= 0);
-
-    // Compute the maximum value of the reoptimization retry counter. This is simply
-    // the largest value at which we don't overflow the execute counter, when using it
-    // to left-shift the execution counter by this amount. Currently the value ends
-    // up being 18, so this loop is not so terrible; it probably takes up ~100 cycles
-    // total on a 32-bit processor.
-    reoptimizationRetryCounterMax() = 0;
-    while ((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp()) << (reoptimizationRetryCounterMax() + 1)) <= static_cast<int64_t>(std::numeric_limits<int32>::max()))
-        reoptimizationRetryCounterMax()++;
-
-    ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp()) << reoptimizationRetryCounterMax()) > 0);
-    ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp()) << reoptimizationRetryCounterMax()) <= static_cast<int64_t>(std::numeric_limits<int32>::max()));
+    recomputeDependentOptions();
 }
 
 // Parses a single command line option in the format "<optionName>=<value>"
@@ -266,6 +272,7 @@
         bool success = parse(valueStr, value);          \
         if (success) {                                  \
             name_() = value;                            \
+            recomputeDependentOptions();                \
             return true;                                \
         }                                               \
         return false;                                   \
@@ -274,7 +281,7 @@
     JSC_OPTIONS(FOR_EACH_OPTION)
 #undef FOR_EACH_OPTION
 
-        return false; // No option matched.
+    return false; // No option matched.
 }
 
 void Options::dumpAllOptions(FILE* stream)

Added: branches/jsCStack/Source/_javascript_Core/tests/stress/inline-closure-call.js (0 => 161732)


--- branches/jsCStack/Source/_javascript_Core/tests/stress/inline-closure-call.js	                        (rev 0)
+++ branches/jsCStack/Source/_javascript_Core/tests/stress/inline-closure-call.js	2014-01-11 05:06:10 UTC (rev 161732)
@@ -0,0 +1,16 @@
+function foo(x) {
+    return function(y) { return x + y; }
+}
+
+function bar(a, b) {
+    return foo(a)(b);
+}
+
+noInline(foo);
+noInline(bar);
+
+for (var i = 0; i < 100000; ++i) {
+    var result = bar(i, i + 1);
+    if (result != i * 2 + 1)
+        throw "Error: bad result for " + i + ": " + result;
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to