Title: [193781] trunk
Revision
193781
Author
mark....@apple.com
Date
2015-12-08 13:44:12 -0800 (Tue, 08 Dec 2015)

Log Message

Polymorphic operand types for DFG and FTL div.
https://bugs.webkit.org/show_bug.cgi?id=151747

Reviewed by Geoffrey Garen.

Source/_javascript_Core:

Perf on benchmarks is neutral.  The new JSRegress ftl-object-div test shows
a speed up not from the div operator itself, but from the fact that the
polymorphic operand types support now allow the test function to run without OSR
exiting, thereby realizing the DFG and FTL's speed up on other work that the test
function does.

This patch has passed the layout tests on x86_64 with a debug build.
It passed the JSC tests with x86 and x86_64 debug builds.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileArithDiv):

* ftl/FTLCompileBinaryOp.cpp:
(JSC::FTL::generateBinaryArithOpFastPath):
(JSC::FTL::generateBinaryOpFastPath):

* ftl/FTLInlineCacheDescriptor.h:
* ftl/FTLInlineCacheDescriptorInlines.h:
(JSC::FTL::ArithDivDescriptor::ArithDivDescriptor):
(JSC::FTL::ArithDivDescriptor::icSize):

* ftl/FTLInlineCacheSize.cpp:
(JSC::FTL::sizeOfArithDiv):
* ftl/FTLInlineCacheSize.h:

* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::lower):
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithMul):
- Fixed a cut-paste bug where the op_mul IC was using the op_sub IC size.
  This bug is benign because the op_sub IC size turns out to be larger
  than op_mul needs.
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithDiv):

* jit/JITArithmetic.cpp:
(JSC::JIT::emit_op_div):
- Fixed a bug where the scratchFPR was not allocated for the 64bit port.
  This bug is benign because the scratchFPR is only needed if we are
  using scratchGPR register (used for branchConvertDoubleToInt32()) is
  >= X86Registers::r8.  Since we're always using regT2 for the scratchT2,
  the scratchFPR is never needed.   However, we should fix this anyway to
  be correct.

* tests/stress/op_div.js:
- Fixed some test values.

LayoutTests:

* js/regress/ftl-object-div-expected.txt: Added.
* js/regress/ftl-object-div.html: Added.
* js/regress/script-tests/ftl-object-div.js: Added.
(o1.valueOf):
(foo):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (193780 => 193781)


--- trunk/LayoutTests/ChangeLog	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/LayoutTests/ChangeLog	2015-12-08 21:44:12 UTC (rev 193781)
@@ -1,3 +1,16 @@
+2015-12-08  Mark Lam  <mark....@apple.com>
+
+        Polymorphic operand types for DFG and FTL div.
+        https://bugs.webkit.org/show_bug.cgi?id=151747
+
+        Reviewed by Geoffrey Garen.
+
+        * js/regress/ftl-object-div-expected.txt: Added.
+        * js/regress/ftl-object-div.html: Added.
+        * js/regress/script-tests/ftl-object-div.js: Added.
+        (o1.valueOf):
+        (foo):
+
 2015-12-08  Zalan Bujtas  <za...@apple.com>
 
         Do not insert positioned renderers to multiple gPositionedDescendantsMap.

Added: trunk/LayoutTests/js/regress/ftl-object-div-expected.txt (0 => 193781)


--- trunk/LayoutTests/js/regress/ftl-object-div-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-object-div-expected.txt	2015-12-08 21:44:12 UTC (rev 193781)
@@ -0,0 +1,10 @@
+JSRegress/ftl-object-div
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/ftl-object-div.html (0 => 193781)


--- trunk/LayoutTests/js/regress/ftl-object-div.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-object-div.html	2015-12-08 21:44:12 UTC (rev 193781)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/script-tests/ftl-object-div.js (0 => 193781)


--- trunk/LayoutTests/js/regress/script-tests/ftl-object-div.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/ftl-object-div.js	2015-12-08 21:44:12 UTC (rev 193781)
@@ -0,0 +1,43 @@
+//@ runFTLNoCJIT
+var o1 = {
+    i: 0,
+    valueOf: function() { return this.i; }
+};
+
+result = 0;
+function foo(a, b) {
+    var result = 0;
+    for (var j = 0; j < 10; j++) {
+        var temp;
+        if (a > b)
+            temp = a / b;
+        else
+            temp = b / 1;
+        temp = temp | 0;
+        result += temp;
+    }
+    for (var i = 0; i < 1000; i++)
+        result += i;
+    return result;
+}
+noInline(foo);
+
+var iterations;
+var expectedResult;
+if (this.window) {
+    // The layout test doesn't like too many iterations and may time out.
+    iterations = 10000;
+    expectedResult = 5045480390;
+} else {
+    iterations = 100000;
+    expectedResult = 54950300390;
+}
+
+
+for (var i = 0; i <= iterations; i++) {
+    o1.i = i + 2;
+    result += foo(o1, 10);
+}
+
+if (result != expectedResult)
+    throw "Bad result: " + result;

Modified: trunk/Source/_javascript_Core/ChangeLog (193780 => 193781)


--- trunk/Source/_javascript_Core/ChangeLog	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-12-08 21:44:12 UTC (rev 193781)
@@ -1,3 +1,66 @@
+2015-12-08  Mark Lam  <mark....@apple.com>
+
+        Polymorphic operand types for DFG and FTL div.
+        https://bugs.webkit.org/show_bug.cgi?id=151747
+
+        Reviewed by Geoffrey Garen.
+
+        Perf on benchmarks is neutral.  The new JSRegress ftl-object-div test shows
+        a speed up not from the div operator itself, but from the fact that the
+        polymorphic operand types support now allow the test function to run without OSR
+        exiting, thereby realizing the DFG and FTL's speed up on other work that the test
+        function does.
+
+        This patch has passed the layout tests on x86_64 with a debug build.
+        It passed the JSC tests with x86 and x86_64 debug builds.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileArithDiv):
+
+        * ftl/FTLCompileBinaryOp.cpp:
+        (JSC::FTL::generateBinaryArithOpFastPath):
+        (JSC::FTL::generateBinaryOpFastPath):
+
+        * ftl/FTLInlineCacheDescriptor.h:
+        * ftl/FTLInlineCacheDescriptorInlines.h:
+        (JSC::FTL::ArithDivDescriptor::ArithDivDescriptor):
+        (JSC::FTL::ArithDivDescriptor::icSize):
+
+        * ftl/FTLInlineCacheSize.cpp:
+        (JSC::FTL::sizeOfArithDiv):
+        * ftl/FTLInlineCacheSize.h:
+
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::lower):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithMul):
+        - Fixed a cut-paste bug where the op_mul IC was using the op_sub IC size.
+          This bug is benign because the op_sub IC size turns out to be larger
+          than op_mul needs.
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithDiv):
+
+        * jit/JITArithmetic.cpp:
+        (JSC::JIT::emit_op_div):
+        - Fixed a bug where the scratchFPR was not allocated for the 64bit port.
+          This bug is benign because the scratchFPR is only needed if we are
+          using scratchGPR register (used for branchConvertDoubleToInt32()) is
+          >= X86Registers::r8.  Since we're always using regT2 for the scratchT2,
+          the scratchFPR is never needed.   However, we should fix this anyway to
+          be correct.
+
+        * tests/stress/op_div.js:
+        - Fixed some test values.
+
 2015-12-05 Aleksandr Skachkov   <gskach...@gmail.com>
 
         [ES6] "super" and "this" should be lexically bound inside an arrow function and should live in a JSLexicalEnvironment

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (193780 => 193781)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2015-12-08 21:44:12 UTC (rev 193781)
@@ -673,6 +673,10 @@
                 typeOfDoubleQuotient(
                     forNode(node->child1()).m_type, forNode(node->child2()).m_type));
             break;
+        case UntypedUse:
+            clobberWorld(node->origin.semantic, clobberLimit);
+            forNode(node).setType(m_graph, SpecBytecodeNumber);
+            break;
         default:
             RELEASE_ASSERT_NOT_REACHED();
             break;

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (193780 => 193781)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2015-12-08 21:44:12 UTC (rev 193781)
@@ -247,15 +247,15 @@
 
     case ArithAdd:
     case ArithNegate:
-    case ArithDiv:
     case ArithMod:
     case DoubleAsInt32:
     case UInt32ToNumber:
         def(PureValue(node, node->arithMode()));
         return;
 
+    case ArithDiv:
+    case ArithMul:
     case ArithSub:
-    case ArithMul:
         switch (node->binaryUseKind()) {
         case Int32Use:
         case Int52RepUse:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (193780 => 193781)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2015-12-08 21:44:12 UTC (rev 193781)
@@ -265,11 +265,21 @@
 
         case ArithDiv:
         case ArithMod: {
-            if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
+            Edge& leftChild = node->child1();
+            Edge& rightChild = node->child2();
+            if (op == ArithDiv
+                && (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())
+                    || m_graph.hasExitSite(node->origin.semantic, BadType))) {
+                fixEdge<UntypedUse>(leftChild);
+                fixEdge<UntypedUse>(rightChild);
+                node->setResult(NodeResultJS);
+                break;
+            }
+            if (Node::shouldSpeculateInt32OrBooleanForArithmetic(leftChild.node(), rightChild.node())
                 && node->canSpeculateInt32(FixupPass)) {
                 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) {
-                    fixIntOrBooleanEdge(node->child1());
-                    fixIntOrBooleanEdge(node->child2());
+                    fixIntOrBooleanEdge(leftChild);
+                    fixIntOrBooleanEdge(rightChild);
                     if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
                         node->setArithMode(Arith::Unchecked);
                     else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
@@ -280,8 +290,8 @@
                 }
                 
                 // This will cause conversion nodes to be inserted later.
-                fixDoubleOrBooleanEdge(node->child1());
-                fixDoubleOrBooleanEdge(node->child2());
+                fixDoubleOrBooleanEdge(leftChild);
+                fixDoubleOrBooleanEdge(rightChild);
                 
                 // We don't need to do ref'ing on the children because we're stealing them from
                 // the original division.
@@ -297,8 +307,8 @@
                     node->setArithMode(Arith::CheckOverflowAndNegativeZero);
                 break;
             }
-            fixDoubleOrBooleanEdge(node->child1());
-            fixDoubleOrBooleanEdge(node->child2());
+            fixDoubleOrBooleanEdge(leftChild);
+            fixDoubleOrBooleanEdge(rightChild);
             node->setResult(NodeResultDouble);
             break;
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (193780 => 193781)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2015-12-08 21:44:12 UTC (rev 193781)
@@ -200,6 +200,19 @@
     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
 }
 
+EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    VM* vm = &exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
+
+    double a = op1.toNumber(exec);
+    double b = op2.toNumber(exec);
+    return JSValue::encode(jsNumber(a / b));
+}
+
 EncodedJSValue JIT_OPERATION operationValueMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
     VM* vm = &exec->vm();

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (193780 => 193781)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2015-12-08 21:44:12 UTC (rev 193781)
@@ -45,6 +45,7 @@
 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueDiv(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationValueMul(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationValueSub(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (193780 => 193781)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2015-12-08 21:44:12 UTC (rev 193781)
@@ -354,11 +354,15 @@
             SpeculatedType right = node->child2()->prediction();
             
             if (left && right) {
-                if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
-                    && node->canSpeculateInt32(m_pass))
-                    changed |= mergePrediction(SpecInt32);
-                else
-                    changed |= mergePrediction(SpecBytecodeDouble);
+                if (isFullNumberOrBooleanSpeculationExpectingDefined(left)
+                    && isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
+                    if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
+                        && node->canSpeculateInt32(m_pass))
+                        changed |= mergePrediction(SpecInt32);
+                    else
+                        changed |= mergePrediction(SpecBytecodeDouble);
+                } else
+                    changed |= mergePrediction(SpecInt32 | SpecBytecodeDouble);
             }
             break;
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (193780 => 193781)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2015-12-08 21:44:12 UTC (rev 193781)
@@ -39,6 +39,7 @@
 #include "DFGSlowPathGenerator.h"
 #include "DirectArguments.h"
 #include "JITAddGenerator.h"
+#include "JITDivGenerator.h"
 #include "JITMulGenerator.h"
 #include "JITSubGenerator.h"
 #include "JSArrowFunction.h"
@@ -3686,7 +3687,117 @@
         doubleResult(result.fpr(), node);
         break;
     }
-        
+
+    case UntypedUse: {
+        Edge& leftChild = node->child1();
+        Edge& rightChild = node->child2();
+
+        if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
+            JSValueOperand left(this, leftChild);
+            JSValueOperand right(this, rightChild);
+            JSValueRegs leftRegs = left.jsValueRegs();
+            JSValueRegs rightRegs = right.jsValueRegs();
+#if USE(JSVALUE64)
+            GPRTemporary result(this);
+            JSValueRegs resultRegs = JSValueRegs(result.gpr());
+#else
+            GPRTemporary resultTag(this);
+            GPRTemporary resultPayload(this);
+            JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
+#endif
+            flushRegisters();
+            callOperation(operationValueDiv, resultRegs, leftRegs, rightRegs);
+            m_jit.exceptionCheck();
+
+            jsValueResult(resultRegs, node);
+            return;
+        }
+
+        Optional<JSValueOperand> left;
+        Optional<JSValueOperand> right;
+
+        JSValueRegs leftRegs;
+        JSValueRegs rightRegs;
+
+        FPRTemporary leftNumber(this);
+        FPRTemporary rightNumber(this);
+        FPRReg leftFPR = leftNumber.fpr();
+        FPRReg rightFPR = rightNumber.fpr();
+        FPRTemporary fprScratch(this);
+        FPRReg scratchFPR = fprScratch.fpr();
+
+#if USE(JSVALUE64)
+        GPRTemporary result(this);
+        JSValueRegs resultRegs = JSValueRegs(result.gpr());
+        GPRTemporary scratch(this);
+        GPRReg scratchGPR = scratch.gpr();
+#else
+        GPRTemporary resultTag(this);
+        GPRTemporary resultPayload(this);
+        JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
+        GPRReg scratchGPR = resultTag.gpr();
+#endif
+
+        SnippetOperand leftOperand(m_state.forNode(leftChild).resultType());
+        SnippetOperand rightOperand(m_state.forNode(rightChild).resultType());
+
+        if (leftChild->isInt32Constant())
+            leftOperand.setConstInt32(leftChild->asInt32());
+#if USE(JSVALUE64)
+        else if (leftChild->isDoubleConstant())
+            leftOperand.setConstDouble(leftChild->asNumber());
+#endif
+
+        if (leftOperand.isConst()) {
+            // The snippet generator only supports 1 argument as a constant.
+            // Ignore the rightChild's const-ness.
+        } else if (rightChild->isInt32Constant())
+            rightOperand.setConstInt32(rightChild->asInt32());
+#if USE(JSVALUE64)
+        else if (rightChild->isDoubleConstant())
+            rightOperand.setConstDouble(rightChild->asNumber());
+#endif
+
+        RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
+
+        if (!leftOperand.isConst()) {
+            left = JSValueOperand(this, leftChild);
+            leftRegs = left->jsValueRegs();
+        }
+        if (!rightOperand.isConst()) {
+            right = JSValueOperand(this, rightChild);
+            rightRegs = right->jsValueRegs();
+        }
+
+        JITDivGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
+            leftFPR, rightFPR, scratchGPR, scratchFPR);
+        gen.generateFastPath(m_jit);
+
+        ASSERT(gen.didEmitFastPath());
+        gen.endJumpList().append(m_jit.jump());
+
+        gen.slowPathJumpList().link(&m_jit);
+        silentSpillAllRegisters(resultRegs);
+
+        if (leftOperand.isConst()) {
+            leftRegs = resultRegs;
+            m_jit.moveValue(leftChild->asJSValue(), leftRegs);
+        }
+        if (rightOperand.isConst()) {
+            rightRegs = resultRegs;
+            m_jit.moveValue(rightChild->asJSValue(), rightRegs);
+        }
+
+        callOperation(operationValueDiv, resultRegs, leftRegs, rightRegs);
+
+        silentFillAllRegisters(resultRegs);
+        m_jit.exceptionCheck();
+
+        gen.endJumpList().link(&m_jit);
+        jsValueResult(resultRegs, node);
+        return;
+    }
+
     default:
         RELEASE_ASSERT_NOT_REACHED();
         break;

Modified: trunk/Source/_javascript_Core/ftl/FTLCompileBinaryOp.cpp (193780 => 193781)


--- trunk/Source/_javascript_Core/ftl/FTLCompileBinaryOp.cpp	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/ftl/FTLCompileBinaryOp.cpp	2015-12-08 21:44:12 UTC (rev 193781)
@@ -32,6 +32,7 @@
 #include "FTLInlineCacheDescriptor.h"
 #include "GPRInfo.h"
 #include "JITAddGenerator.h"
+#include "JITDivGenerator.h"
 #include "JITMulGenerator.h"
 #include "JITSubGenerator.h"
 #include "ScratchRegisterAllocator.h"
@@ -153,7 +154,12 @@
     GPRReg m_savedTagTypeNumberRegister { InvalidGPRReg };
 };
 
-template<typename BinaryArithOpGenerator>
+enum ScratchFPRUsage {
+    DontNeedScratchFPR,
+    NeedScratchFPR
+};
+
+template<typename BinaryArithOpGenerator, ScratchFPRUsage scratchFPRUsage = DontNeedScratchFPR>
 void generateBinaryArithOpFastPath(BinaryOpDescriptor& ic, CCallHelpers& jit,
     GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
     CCallHelpers::Jump& done, CCallHelpers::Jump& slowPathStart)
@@ -166,6 +172,8 @@
     FPRReg leftFPR = allocator.allocateScratchFPR();
     FPRReg rightFPR = allocator.allocateScratchFPR();
     FPRReg scratchFPR = InvalidFPRReg;
+    if (scratchFPRUsage == NeedScratchFPR)
+        scratchFPR = allocator.allocateScratchFPR();
 
     BinaryArithOpGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result),
         JSValueRegs(left), JSValueRegs(right), leftFPR, rightFPR, scratchGPR, scratchFPR);
@@ -195,6 +203,9 @@
     CCallHelpers::Jump& done, CCallHelpers::Jump& slowPathStart)
 {
     switch (ic.nodeType()) {
+    case ArithDiv:
+        generateBinaryArithOpFastPath<JITDivGenerator, NeedScratchFPR>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
+        break;
     case ArithMul:
         generateBinaryArithOpFastPath<JITMulGenerator>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
         break;

Modified: trunk/Source/_javascript_Core/ftl/FTLInlineCacheDescriptor.h (193780 => 193781)


--- trunk/Source/_javascript_Core/ftl/FTLInlineCacheDescriptor.h	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/ftl/FTLInlineCacheDescriptor.h	2015-12-08 21:44:12 UTC (rev 193781)
@@ -165,6 +165,12 @@
     SnippetOperand m_rightOperand;
 };
 
+class ArithDivDescriptor : public BinaryOpDescriptor {
+public:
+    ArithDivDescriptor(unsigned stackmapID, CodeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand);
+    static size_t icSize();
+};
+
 class ArithMulDescriptor : public BinaryOpDescriptor {
 public:
     ArithMulDescriptor(unsigned stackmapID, CodeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand);

Modified: trunk/Source/_javascript_Core/ftl/FTLInlineCacheDescriptorInlines.h (193780 => 193781)


--- trunk/Source/_javascript_Core/ftl/FTLInlineCacheDescriptorInlines.h	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/ftl/FTLInlineCacheDescriptorInlines.h	2015-12-08 21:44:12 UTC (rev 193781)
@@ -35,6 +35,18 @@
 
 namespace JSC { namespace FTL {
 
+ArithDivDescriptor::ArithDivDescriptor(unsigned stackmapID, CodeOrigin codeOrigin,
+    const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
+    : BinaryOpDescriptor(DFG::ArithDiv, stackmapID, codeOrigin, icSize(),
+        "ArithDiv", "ArithDiv IC fast path", DFG::operationValueDiv, leftOperand, rightOperand)
+{
+}
+
+size_t ArithDivDescriptor::icSize()
+{
+    return sizeOfArithDiv();
+}
+
 ArithMulDescriptor::ArithMulDescriptor(unsigned stackmapID, CodeOrigin codeOrigin,
     const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
     : BinaryOpDescriptor(DFG::ArithMul, stackmapID, codeOrigin, icSize(),

Modified: trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.cpp (193780 => 193781)


--- trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.cpp	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.cpp	2015-12-08 21:44:12 UTC (rev 193781)
@@ -128,6 +128,23 @@
 #endif
 }
 
+size_t sizeOfArithDiv()
+{
+#if CPU(ARM64)
+#ifdef NDEBUG
+    return 180; // ARM64 release.
+#else
+    return 276; // ARM64 debug.
+#endif
+#else // CPU(X86_64)
+#ifdef NDEBUG
+    return 199; // X86_64 release.
+#else
+    return 286; // X86_64 debug.
+#endif
+#endif
+}
+
 size_t sizeOfArithMul()
 {
 #if CPU(ARM64)

Modified: trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.h (193780 => 193781)


--- trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.h	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.h	2015-12-08 21:44:12 UTC (rev 193781)
@@ -46,6 +46,7 @@
 size_t sizeOfConstructVarargs();
 size_t sizeOfConstructForwardVarargs();
 size_t sizeOfIn();
+size_t sizeOfArithDiv();
 size_t sizeOfArithMul();
 size_t sizeOfArithSub();
 size_t sizeOfValueAdd();

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (193780 => 193781)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2015-12-08 21:44:12 UTC (rev 193781)
@@ -240,6 +240,7 @@
                             maxNumberOfCatchSpills = std::max(maxNumberOfCatchSpills, m_graph.localsLiveInBytecode(opCatchOrigin).bitCount());
                         break;
                     }
+                    case ArithDiv:
                     case ArithMul:
                     case ArithSub:
                     case GetById:
@@ -1861,7 +1862,7 @@
             // Arguments: id, bytes, target, numArgs, args...
             StackmapArgumentList arguments;
             arguments.append(m_out.constInt64(stackmapID));
-            arguments.append(m_out.constInt32(ArithSubDescriptor::icSize()));
+            arguments.append(m_out.constInt32(ArithMulDescriptor::icSize()));
             arguments.append(constNull(m_out.ref8));
             arguments.append(m_out.constInt32(2));
             arguments.append(left);
@@ -1943,7 +1944,72 @@
                 lowDouble(m_node->child1()), lowDouble(m_node->child2())));
             break;
         }
-            
+
+        case UntypedUse: {
+            Edge& leftChild = m_node->child1();
+            Edge& rightChild = m_node->child2();
+
+            if (!(provenType(leftChild) & SpecFullNumber) || !(provenType(rightChild) & SpecFullNumber)) {
+                setJSValue(vmCall(m_out.int64, m_out.operation(operationValueDiv), m_callFrame,
+                    lowJSValue(leftChild), lowJSValue(rightChild)));
+                return;
+            }
+
+            unsigned stackmapID = m_stackmapIDs++;
+
+            if (Options::verboseCompilation())
+                dataLog("    Emitting ArithDiv patchpoint with stackmap #", stackmapID, "\n");
+
+#if FTL_USES_B3
+            CRASH();
+#else
+            LValue left = lowJSValue(leftChild);
+            LValue right = lowJSValue(rightChild);
+
+            SnippetOperand leftOperand(abstractValue(leftChild).resultType());
+            SnippetOperand rightOperand(abstractValue(rightChild).resultType());
+
+            if (leftChild->isInt32Constant())
+                leftOperand.setConstInt32(leftChild->asInt32());
+#if USE(JSVALUE64)
+            else if (leftChild->isDoubleConstant())
+                leftOperand.setConstDouble(leftChild->asNumber());
+#endif
+
+            if (leftOperand.isConst()) {
+                // The snippet generator only supports 1 argument as a constant.
+                // Ignore the rightChild's const-ness.
+            } else if (rightChild->isInt32Constant())
+                rightOperand.setConstInt32(rightChild->asInt32());
+#if USE(JSVALUE64)
+            else if (rightChild->isDoubleConstant())
+                rightOperand.setConstDouble(rightChild->asNumber());
+#endif
+
+            RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
+
+            // Arguments: id, bytes, target, numArgs, args...
+            StackmapArgumentList arguments;
+            arguments.append(m_out.constInt64(stackmapID));
+            arguments.append(m_out.constInt32(ArithDivDescriptor::icSize()));
+            arguments.append(constNull(m_out.ref8));
+            arguments.append(m_out.constInt32(2));
+            arguments.append(left);
+            arguments.append(right);
+
+            appendOSRExitArgumentsForPatchpointIfWillCatchException(arguments,
+                ExceptionType::BinaryOpGenerator, 3); // left, right, and result show up in the stackmap locations.
+
+            LValue call = m_out.call(m_out.int64, m_out.patchpointInt64Intrinsic(), arguments);
+            setInstructionCallingConvention(call, LLVMAnyRegCallConv);
+
+            m_ftlState.binaryOps.append(ArithDivDescriptor(stackmapID, m_node->origin.semantic, leftOperand, rightOperand));
+
+            setJSValue(call);
+#endif // FTL_USES_B3
+            break;
+        }
+
         default:
             DFG_CRASH(m_graph, m_node, "Bad use kind");
             break;

Modified: trunk/Source/_javascript_Core/jit/JITArithmetic.cpp (193780 => 193781)


--- trunk/Source/_javascript_Core/jit/JITArithmetic.cpp	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/jit/JITArithmetic.cpp	2015-12-08 21:44:12 UTC (rev 193781)
@@ -799,14 +799,13 @@
     JSValueRegs rightRegs = JSValueRegs(regT1);
     JSValueRegs resultRegs = leftRegs;
     GPRReg scratchGPR = regT2;
-    FPRReg scratchFPR = InvalidFPRReg;
 #else
     JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
     JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
     JSValueRegs resultRegs = leftRegs;
     GPRReg scratchGPR = regT4;
-    FPRReg scratchFPR = fpRegT2;
 #endif
+    FPRReg scratchFPR = fpRegT2;
 
     uint32_t* profilingCounter = &m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter;
 

Modified: trunk/Source/_javascript_Core/tests/stress/op_div.js (193780 => 193781)


--- trunk/Source/_javascript_Core/tests/stress/op_div.js	2015-12-08 21:41:04 UTC (rev 193780)
+++ trunk/Source/_javascript_Core/tests/stress/op_div.js	2015-12-08 21:44:12 UTC (rev 193781)
@@ -43,8 +43,8 @@
     '-0x7fff',
     '0x10000',
     '-0x10000',
-    '0x7ffffff',
-    '-0x7ffffff',
+    '0x7fffffff',
+    '-0x7fffffff',
     '0x100000000',
     '-0x100000000',
 
@@ -59,8 +59,8 @@
     '"-0x7fff"',
     '"0x10000"',
     '"-0x10000"',
-    '"0x7ffffff"',
-    '"-0x7ffffff"',
+    '"0x7fffffff"',
+    '"-0x7fffffff"',
     '"0x100000000"',
     '"-0x100000000"',
 ];
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to