Title: [203786] trunk/Source/_javascript_Core
Revision
203786
Author
sbar...@apple.com
Date
2016-07-27 12:56:28 -0700 (Wed, 27 Jul 2016)

Log Message

MathICs should be able to emit only a jump along the inline path when they don't have any type data
https://bugs.webkit.org/show_bug.cgi?id=160110

Reviewed by Mark Lam.

This patch allows for MathIC fast-path generation to be delayed.
We delay when we don't see any observed type information for
the lhs/rhs operand, which implies that the MathIC has never
executed. This is profitable for two main reasons:
1. If the math operation never executes, we emit much less code.
2. Once we get type information for the lhs/rhs, we can emit better code.

To implement this, we just emit a jump to the slow path call
that will repatch on first execution.

New data for add:
           |   JetStream  |  Unity 3D  |
     ------| -------------|--------------
      Old  |   148 bytes  |  143 bytes |
     ------| -------------|--------------
      New  |   116  bytes |  113 bytes |
     ------------------------------------

New data for mul:
           |   JetStream  |  Unity 3D  |
     ------| -------------|--------------
      Old  |   210 bytes  |  185 bytes |
     ------| -------------|--------------
      New  |   170  bytes |  137 bytes |
     ------------------------------------

* jit/JITAddGenerator.cpp:
(JSC::JITAddGenerator::generateInline):
* jit/JITAddGenerator.h:
(JSC::JITAddGenerator::isLeftOperandValidConstant):
(JSC::JITAddGenerator::isRightOperandValidConstant):
(JSC::JITAddGenerator::arithProfile):
* jit/JITMathIC.h:
(JSC::JITMathIC::generateInline):
(JSC::JITMathIC::generateOutOfLine):
(JSC::JITMathIC::finalizeInlineCode):
* jit/JITMathICInlineResult.h:
* jit/JITMulGenerator.cpp:
(JSC::JITMulGenerator::generateInline):
* jit/JITMulGenerator.h:
(JSC::JITMulGenerator::isLeftOperandValidConstant):
(JSC::JITMulGenerator::isRightOperandValidConstant):
(JSC::JITMulGenerator::arithProfile):
* jit/JITOperations.cpp:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (203785 => 203786)


--- trunk/Source/_javascript_Core/ChangeLog	2016-07-27 18:46:42 UTC (rev 203785)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-07-27 19:56:28 UTC (rev 203786)
@@ -1,3 +1,55 @@
+2016-07-27  Saam Barati  <sbar...@apple.com>
+
+        MathICs should be able to emit only a jump along the inline path when they don't have any type data
+        https://bugs.webkit.org/show_bug.cgi?id=160110
+
+        Reviewed by Mark Lam.
+
+        This patch allows for MathIC fast-path generation to be delayed.
+        We delay when we don't see any observed type information for
+        the lhs/rhs operand, which implies that the MathIC has never
+        executed. This is profitable for two main reasons:
+        1. If the math operation never executes, we emit much less code.
+        2. Once we get type information for the lhs/rhs, we can emit better code.
+
+        To implement this, we just emit a jump to the slow path call
+        that will repatch on first execution.
+
+        New data for add:
+                   |   JetStream  |  Unity 3D  |
+             ------| -------------|--------------
+              Old  |   148 bytes  |  143 bytes |
+             ------| -------------|--------------
+              New  |   116  bytes |  113 bytes |
+             ------------------------------------
+
+        New data for mul:
+                   |   JetStream  |  Unity 3D  |
+             ------| -------------|--------------
+              Old  |   210 bytes  |  185 bytes |
+             ------| -------------|--------------
+              New  |   170  bytes |  137 bytes |
+             ------------------------------------
+
+        * jit/JITAddGenerator.cpp:
+        (JSC::JITAddGenerator::generateInline):
+        * jit/JITAddGenerator.h:
+        (JSC::JITAddGenerator::isLeftOperandValidConstant):
+        (JSC::JITAddGenerator::isRightOperandValidConstant):
+        (JSC::JITAddGenerator::arithProfile):
+        * jit/JITMathIC.h:
+        (JSC::JITMathIC::generateInline):
+        (JSC::JITMathIC::generateOutOfLine):
+        (JSC::JITMathIC::finalizeInlineCode):
+        * jit/JITMathICInlineResult.h:
+        * jit/JITMulGenerator.cpp:
+        (JSC::JITMulGenerator::generateInline):
+        * jit/JITMulGenerator.h:
+        (JSC::JITMulGenerator::isLeftOperandValidConstant):
+        (JSC::JITMulGenerator::isRightOperandValidConstant):
+        (JSC::JITMulGenerator::arithProfile):
+        * jit/JITOperations.cpp:
+
 2016-07-26  Saam Barati  <sbar...@apple.com>
 
         rollout r203666

Modified: trunk/Source/_javascript_Core/jit/JITAddGenerator.cpp (203785 => 203786)


--- trunk/Source/_javascript_Core/jit/JITAddGenerator.cpp	2016-07-27 18:46:42 UTC (rev 203785)
+++ trunk/Source/_javascript_Core/jit/JITAddGenerator.cpp	2016-07-27 19:56:28 UTC (rev 203786)
@@ -42,12 +42,6 @@
     if (m_arithProfile) {
         lhs = m_arithProfile->lhsObservedType();
         rhs = m_arithProfile->rhsObservedType();
-        if (lhs.isEmpty() || rhs.isEmpty()) {
-            // FIXME: ICs should be able to repatch without emitting an inline path:
-            // https://bugs.webkit.org/show_bug.cgi?id=160110
-            lhs = ObservedType().withInt32();
-            rhs = ObservedType().withInt32();
-        }
     }
 
     if (lhs.isOnlyNonNumber() && rhs.isOnlyNonNumber())

Modified: trunk/Source/_javascript_Core/jit/JITAddGenerator.h (203785 => 203786)


--- trunk/Source/_javascript_Core/jit/JITAddGenerator.h	2016-07-27 18:46:42 UTC (rev 203785)
+++ trunk/Source/_javascript_Core/jit/JITAddGenerator.h	2016-07-27 19:56:28 UTC (rev 203786)
@@ -65,6 +65,7 @@
 
     bool isLeftOperandValidConstant() const { return m_leftOperand.isConstInt32(); }
     bool isRightOperandValidConstant() const { return m_rightOperand.isConstInt32(); }
+    ArithProfile* arithProfile() const { return m_arithProfile; }
 
 private:
     SnippetOperand m_leftOperand;

Modified: trunk/Source/_javascript_Core/jit/JITMathIC.h (203785 => 203786)


--- trunk/Source/_javascript_Core/jit/JITMathIC.h	2016-07-27 18:46:42 UTC (rev 203785)
+++ trunk/Source/_javascript_Core/jit/JITMathIC.h	2016-07-27 19:56:28 UTC (rev 203786)
@@ -27,6 +27,7 @@
 
 #if ENABLE(JIT)
 
+#include "ArithProfile.h"
 #include "CCallHelpers.h"
 #include "JITAddGenerator.h"
 #include "JITMathICInlineResult.h"
@@ -64,6 +65,24 @@
     {
         state.fastPathStart = jit.label();
         size_t startSize = jit.m_assembler.buffer().codeSize();
+
+        if (ArithProfile* arithProfile = m_generator.arithProfile()) {
+            if (arithProfile->lhsObservedType().isEmpty() || arithProfile->rhsObservedType().isEmpty()) {
+                // It looks like the MathIC has yet to execute. We don't want to emit code in this
+                // case for a couple reasons. First, the operation may never execute, so if we don't emit
+                // code, it's a win. Second, if the operation does execute, we can emit better code
+                // once we have an idea about the types of lhs and rhs.
+                state.slowPathJumps.append(jit.patchableJump());
+                state.shouldSlowPathRepatch = true;
+                state.fastPathEnd = jit.label();
+                ASSERT(!m_generateFastPathOnRepatch); // We should have gathered some observed type info for lhs and rhs before trying to regenerate again.
+                m_generateFastPathOnRepatch = true;
+                size_t inlineSize = jit.m_assembler.buffer().codeSize() - startSize;
+                ASSERT_UNUSED(inlineSize, static_cast<ptrdiff_t>(inlineSize) <= MacroAssembler::maxJumpReplacementSize());
+                return true;
+            }
+        }
+
         JITMathICInlineResult result = m_generator.generateInline(jit, state);
 
         switch (result) {
@@ -100,10 +119,64 @@
 
     void generateOutOfLine(VM& vm, CodeBlock* codeBlock, FunctionPtr callReplacement)
     {
+        auto linkJumpToOutOfLineSnippet = [&] () {
+            CCallHelpers jit(&vm, codeBlock);
+            auto jump = jit.jump();
+            // We don't need a nop sled here because nobody should be jumping into the middle of an IC.
+            bool needsBranchCompaction = false;
+            RELEASE_ASSERT(jit.m_assembler.buffer().codeSize() <= static_cast<size_t>(m_inlineSize));
+            LinkBuffer linkBuffer(jit, m_inlineStart.dataLocation(), jit.m_assembler.buffer().codeSize(), JITCompilationMustSucceed, needsBranchCompaction);
+            RELEASE_ASSERT(linkBuffer.isValid());
+            linkBuffer.link(jump, CodeLocationLabel(m_code.code()));
+            FINALIZE_CODE(linkBuffer, ("JITMathIC: linking constant jump to out of line stub"));
+        };
+
+        auto replaceCall = [&] () {
+            ftlThunkAwareRepatchCall(codeBlock, slowPathCallLocation(), callReplacement);
+        };
+
+        bool shouldEmitProfiling = !JITCode::isOptimizingJIT(codeBlock->jitType());
+
+        if (m_generateFastPathOnRepatch) {
+
+            CCallHelpers jit(&vm, codeBlock);
+            MathICGenerationState generationState;
+            bool generatedInline = generateInline(jit, generationState, shouldEmitProfiling);
+
+            // We no longer want to try to regenerate the fast path.
+            m_generateFastPathOnRepatch = false;
+
+            if (generatedInline) {
+                auto jumpToDone = jit.jump();
+
+                LinkBuffer linkBuffer(vm, jit, codeBlock, JITCompilationCanFail);
+                if (!linkBuffer.didFailToAllocate()) {
+                    linkBuffer.link(generationState.slowPathJumps, slowPathStartLocation());
+                    linkBuffer.link(jumpToDone, doneLocation());
+
+                    m_code = FINALIZE_CODE_FOR(
+                        codeBlock, linkBuffer, ("JITMathIC: generating out of line fast IC snippet"));
+
+                    if (!generationState.shouldSlowPathRepatch) {
+                        // We won't need to regenerate, so we can wire the slow path call
+                        // to a non repatching variant.
+                        replaceCall();
+                    }
+
+                    linkJumpToOutOfLineSnippet();
+
+                    return;
+                }
+            }
+            
+            // We weren't able to generate an out of line fast path.
+            // We just generate the snippet in its full generality.
+        }
+
         // We rewire to the alternate regardless of whether or not we can allocate the out of line path
         // because if we fail allocating the out of line path, we don't want to waste time trying to
         // allocate it in the future.
-        ftlThunkAwareRepatchCall(codeBlock, slowPathCallLocation(), callReplacement);
+        replaceCall();
 
         {
             CCallHelpers jit(&vm, codeBlock);
@@ -111,7 +184,6 @@
             MacroAssembler::JumpList endJumpList; 
             MacroAssembler::JumpList slowPathJumpList; 
 
-            bool shouldEmitProfiling = !JITCode::isOptimizingJIT(codeBlock->jitType());
             bool emittedFastPath = m_generator.generateFastPath(jit, endJumpList, slowPathJumpList, shouldEmitProfiling);
             if (!emittedFastPath)
                 return;
@@ -128,17 +200,7 @@
                 codeBlock, linkBuffer, ("JITMathIC: generating out of line IC snippet"));
         }
 
-        {
-            CCallHelpers jit(&vm, codeBlock);
-            auto jump = jit.jump();
-            // We don't need a nop sled here because nobody should be jumping into the middle of an IC.
-            bool needsBranchCompaction = false;
-            RELEASE_ASSERT(jit.m_assembler.buffer().codeSize() <= static_cast<size_t>(m_inlineSize));
-            LinkBuffer linkBuffer(jit, m_inlineStart.dataLocation(), jit.m_assembler.buffer().codeSize(), JITCompilationMustSucceed, needsBranchCompaction);
-            RELEASE_ASSERT(linkBuffer.isValid());
-            linkBuffer.link(jump, CodeLocationLabel(m_code.code()));
-            FINALIZE_CODE(linkBuffer, ("JITMathIC: linking constant jump to out of line stub"));
-        }
+        linkJumpToOutOfLineSnippet();
     }
 
     void finalizeInlineCode(const MathICGenerationState& state, LinkBuffer& linkBuffer)
@@ -172,6 +234,7 @@
     int32_t m_inlineSize;
     int32_t m_deltaFromStartToSlowPathCallLocation;
     int32_t m_deltaFromStartToSlowPathStart;
+    bool m_generateFastPathOnRepatch { false };
     GeneratorType m_generator;
 };
 

Modified: trunk/Source/_javascript_Core/jit/JITMulGenerator.cpp (203785 => 203786)


--- trunk/Source/_javascript_Core/jit/JITMulGenerator.cpp	2016-07-27 18:46:42 UTC (rev 203785)
+++ trunk/Source/_javascript_Core/jit/JITMulGenerator.cpp	2016-07-27 19:56:28 UTC (rev 203786)
@@ -42,12 +42,6 @@
     if (m_arithProfile) {
         lhs = m_arithProfile->lhsObservedType();
         rhs = m_arithProfile->rhsObservedType();
-        if (lhs.isEmpty() || rhs.isEmpty()) {
-            // FIXME: ICs should be able to repatch without emitting an inline path:
-            // https://bugs.webkit.org/show_bug.cgi?id=160110
-            lhs = ObservedType().withInt32();
-            rhs = ObservedType().withInt32();
-        }
     }
 
     if (lhs.isOnlyNonNumber() && rhs.isOnlyNonNumber())

Modified: trunk/Source/_javascript_Core/jit/JITMulGenerator.h (203785 => 203786)


--- trunk/Source/_javascript_Core/jit/JITMulGenerator.h	2016-07-27 18:46:42 UTC (rev 203785)
+++ trunk/Source/_javascript_Core/jit/JITMulGenerator.h	2016-07-27 19:56:28 UTC (rev 203786)
@@ -64,6 +64,8 @@
     bool isLeftOperandValidConstant() const { return m_leftOperand.isPositiveConstInt32(); }
     bool isRightOperandValidConstant() const { return m_rightOperand.isPositiveConstInt32(); }
 
+    ArithProfile* arithProfile() const { return m_arithProfile; }
+
 private:
     SnippetOperand m_leftOperand;
     SnippetOperand m_rightOperand;

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (203785 => 203786)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-07-27 18:46:42 UTC (rev 203785)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-07-27 19:56:28 UTC (rev 203786)
@@ -2319,7 +2319,12 @@
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
 
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
+
     auto nonOptimizeVariant = operationValueAddNoOptimize;
+    if (ArithProfile* arithProfile = addIC->m_generator.arithProfile())
+        arithProfile->observeLHSAndRHS(op1, op2);
     addIC->generateOutOfLine(*vm, exec->codeBlock(), nonOptimizeVariant);
 
 #if ENABLE(MATH_IC_STATS)
@@ -2326,8 +2331,6 @@
     exec->codeBlock()->dumpMathICStats();
 #endif
 
-    JSValue op1 = JSValue::decode(encodedOp1);
-    JSValue op2 = JSValue::decode(encodedOp2);
     return JSValue::encode(jsAdd(exec, op1, op2));
 }
 
@@ -2392,6 +2395,8 @@
     NativeCallFrameTracer tracer(vm, exec);
 
     auto nonOptimizeVariant = operationValueMulNoOptimize;
+    if (ArithProfile* arithProfile = mulIC->m_generator.arithProfile())
+        arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
     mulIC->generateOutOfLine(*vm, exec->codeBlock(), nonOptimizeVariant);
 
 #if ENABLE(MATH_IC_STATS)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to