Title: [204670] trunk
Revision
204670
Author
[email protected]
Date
2016-08-19 19:00:44 -0700 (Fri, 19 Aug 2016)

Log Message

[JSC] ArithSqrt should work with any argument type
https://bugs.webkit.org/show_bug.cgi?id=160954

Patch by Benjamin Poulain <[email protected]> on 2016-08-19
Reviewed by Saam Barati.

JSTests:

* stress/arith-sqrt-on-various-types.js: Added.
(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueAllTypesSqrt):
(testAllTypesCall):
(testSingleTypeCall):
(opaqueSqrtForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueSqrtForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(testException.opaqueSqrtWithException):
(testException):

Source/_javascript_Core:

Previsouly, ArithSqrt would always OSR Exit if the argument
is not typed Integer, Double, or Boolean.
Since we can't recover by generalizing to those, we continuously
OSR Exit and recompile the same code over and over again.

This patch introduces a fallback to handle the remaining types.

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

* dfg/DFGMayExit.cpp:
This is somewhat unrelated. While discussing the design of this
with Filip, we decided not to use ToNumber+ArithSqrt despite
the guarantee that ToNumber does not OSR Exit.
Since it does not OSR Exit, we should say so in mayExitImpl().

* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileArithSqrt):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileArithSqrt):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (204669 => 204670)


--- trunk/JSTests/ChangeLog	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/JSTests/ChangeLog	2016-08-20 02:00:44 UTC (rev 204670)
@@ -1,3 +1,25 @@
+2016-08-19  Benjamin Poulain  <[email protected]>
+
+        [JSC] ArithSqrt should work with any argument type
+        https://bugs.webkit.org/show_bug.cgi?id=160954
+
+        Reviewed by Saam Barati.
+
+        * stress/arith-sqrt-on-various-types.js: Added.
+        (let.validInputTypedTestCases.validInputTestCases.map):
+        (isIdentical):
+        (opaqueAllTypesSqrt):
+        (testAllTypesCall):
+        (testSingleTypeCall):
+        (opaqueSqrtForSideEffects):
+        (testSideEffect.let.testObject.valueOf):
+        (testSideEffect):
+        (opaqueSqrtForCSE):
+        (testCSE.let.testObject.valueOf):
+        (testCSE):
+        (testException.opaqueSqrtWithException):
+        (testException):
+
 2016-08-19  Joseph Pecoraro  <[email protected]>
 
         Make custom Error properties (line, column, sourceURL) configurable and writable

Added: trunk/JSTests/stress/arith-sqrt-on-various-types.js (0 => 204670)


--- trunk/JSTests/stress/arith-sqrt-on-various-types.js	                        (rev 0)
+++ trunk/JSTests/stress/arith-sqrt-on-various-types.js	2016-08-20 02:00:44 UTC (rev 204670)
@@ -0,0 +1,162 @@
+"use strict";
+
+let validInputTestCases = [
+    // input as string, expected result as string.
+    ["undefined", "NaN"],
+    ["null", "0"],
+    ["0", "0"],
+    ["-0.", "-0."],
+    ["4", "2"],
+    ["42.5", "6.519202405202649"],
+    ["Infinity", "Infinity"],
+    ["-Infinity", "NaN"],
+    ["NaN", "NaN"],
+    ["\"WebKit\"", "NaN"],
+    ["\"4\"", "2"],
+    ["{ valueOf: () => { return 4; } }", "2"],
+];
+
+let validInputTypedTestCases = validInputTestCases.map((element) => { return [eval("(" + element[0] + ")"), eval(element[1])] });
+
+function isIdentical(result, expected)
+{
+    if (expected === expected) {
+        if (result !== expected)
+            return false;
+        if (!expected && 1 / expected === -Infinity && 1 / result !== -Infinity)
+            return false;
+
+        return true;
+    }
+    return result !== result;
+}
+
+
+// Test Math.sqrt() with a very polymorphic input. All test cases are seen at each iteration.
+function opaqueAllTypesSqrt(argument) {
+    return Math.sqrt(argument);
+}
+noInline(opaqueAllTypesSqrt);
+noOSRExitFuzzing(opaqueAllTypesSqrt);
+
+function testAllTypesCall() {
+    for (let i = 0; i < 1e3; ++i) {
+        for (let testCaseInput of validInputTypedTestCases) {
+            let output = opaqueAllTypesSqrt(testCaseInput[0]);
+            if (!isIdentical(output, testCaseInput[1]))
+                throw "Failed testAllTypesCall for input " + testCaseInput[0] + " expected " + testCaseInput[1] + " got " + output;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueAllTypesSqrt) > 2)
+        throw "We should have detected sqrt() was polymorphic and generated a generic version.";
+}
+testAllTypesCall();
+
+
+// Test Math.sqrt() on a completely typed input. Every call see only one type.
+function testSingleTypeCall() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueSqrt(argument) {
+                return Math.sqrt(argument);
+            }
+            noInline(opaqueSqrt);
+            noOSRExitFuzzing(opaqueSqrt);
+
+            for (let i = 0; i < 1e4; ++i) {
+                if (!isIdentical(opaqueSqrt(${testCaseInput[0]}), ${testCaseInput[1]})) {
+                    throw "Failed testSingleTypeCall()";
+                }
+            }
+            if (numberOfDFGCompiles(opaqueSqrt) > 1)
+                throw "We should have compiled a single sqrt for the expected type.";
+        `);
+    }
+}
+testSingleTypeCall();
+
+
+// Verify we call valueOf() exactly once per call.
+function opaqueSqrtForSideEffects(argument) {
+    return Math.sqrt(argument);
+}
+noInline(opaqueSqrtForSideEffects);
+noOSRExitFuzzing(opaqueSqrtForSideEffects);
+
+function testSideEffect() {
+    let testObject = {
+        counter: 0,
+        valueOf: function() { ++this.counter; return 16; }
+    };
+    for (let i = 0; i < 1e4; ++i) {
+        if (opaqueSqrtForSideEffects(testObject) !== 4)
+            throw "Incorrect result in testSideEffect()";
+    }
+    if (testObject.counter !== 1e4)
+        throw "Failed testSideEffect()";
+    if (numberOfDFGCompiles(opaqueSqrtForSideEffects) > 1)
+        throw "opaqueSqrtForSideEffects() is predictable, it should only be compiled once.";
+}
+testSideEffect();
+
+
+// Verify SQRT is not subject to CSE if the argument has side effects.
+function opaqueSqrtForCSE(argument) {
+    return Math.sqrt(argument) + Math.sqrt(argument) + Math.sqrt(argument);
+}
+noInline(opaqueSqrtForCSE);
+noOSRExitFuzzing(opaqueSqrtForCSE);
+
+function testCSE() {
+    let testObject = {
+        counter: 0,
+        valueOf: function() { ++this.counter; return 16; }
+    };
+    for (let i = 0; i < 1e4; ++i) {
+        if (opaqueSqrtForCSE(testObject) !== 12)
+            throw "Incorrect result in testCSE()";
+    }
+    if (testObject.counter !== 3e4)
+        throw "Failed testCSE()";
+    if (numberOfDFGCompiles(opaqueSqrtForCSE) > 1)
+        throw "opaqueSqrtForCSE() is predictable, it should only be compiled once.";
+}
+testCSE();
+
+
+// Test exceptions in the argument.
+function testException() {
+    let counter = 0;
+    function opaqueSqrtWithException(argument) {
+        let result = Math.sqrt(argument);
+        ++counter;
+        return result;
+    }
+    noInline(opaqueSqrtWithException);
+
+    let testObject = { valueOf: () => {  return 64; } };
+
+    // Warm up without exception.
+    for (let i = 0; i < 1e3; ++i) {
+        if (opaqueSqrtWithException(testObject) !== 8)
+            throw "Incorrect result in opaqueSqrtWithException()";
+    }
+
+    let testThrowObject = { valueOf: () => { throw testObject; return 64; } };
+
+    for (let i = 0; i < 1e2; ++i) {
+        try {
+            if (opaqueSqrtWithException(testThrowObject) !== 8)
+                throw "This code should not be reached!!";
+        } catch (e) {
+            if (e !== testObject) {
+                throw "Wrong object thrown from opaqueSqrtWithException."
+            }
+        }
+    }
+
+    if (counter !== 1e3) {
+        throw "Invalid count in testException()";
+    }
+}
+testException();

Modified: trunk/Source/_javascript_Core/ChangeLog (204669 => 204670)


--- trunk/Source/_javascript_Core/ChangeLog	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-08-20 02:00:44 UTC (rev 204670)
@@ -1,3 +1,40 @@
+2016-08-19  Benjamin Poulain  <[email protected]>
+
+        [JSC] ArithSqrt should work with any argument type
+        https://bugs.webkit.org/show_bug.cgi?id=160954
+
+        Reviewed by Saam Barati.
+
+        Previsouly, ArithSqrt would always OSR Exit if the argument
+        is not typed Integer, Double, or Boolean.
+        Since we can't recover by generalizing to those, we continuously
+        OSR Exit and recompile the same code over and over again.
+
+        This patch introduces a fallback to handle the remaining types.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+
+        * dfg/DFGMayExit.cpp:
+        This is somewhat unrelated. While discussing the design of this
+        with Filip, we decided not to use ToNumber+ArithSqrt despite
+        the guarantee that ToNumber does not OSR Exit.
+        Since it does not OSR Exit, we should say so in mayExitImpl().
+
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileArithSqrt):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileArithSqrt):
+
 2016-08-19  Joseph Pecoraro  <[email protected]>
 
         Make custom Error properties (line, column, sourceURL) configurable and writable

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-08-20 02:00:44 UTC (rev 204670)
@@ -961,7 +961,10 @@
             setConstant(node, jsDoubleNumber(sqrt(child.asNumber())));
             break;
         }
-        forNode(node).setType(typeOfDoubleUnaryOp(forNode(node->child1()).m_type));
+        SpeculatedType sqrtType = SpecFullNumber;
+        if (node->child1().useKind() == DoubleRepUse)
+            sqrtType = typeOfDoubleUnaryOp(forNode(node->child1()).m_type);
+        forNode(node).setType(sqrtType);
         break;
     }
         

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-08-20 02:00:44 UTC (rev 204670)
@@ -91,6 +91,10 @@
     return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount()
         && isSupportedForInlining(codeBlock);
 }
+bool canUseOSRExitFuzzing(CodeBlock* codeBlock)
+{
+    return codeBlock->ownerScriptExecutable()->canUseOSRExitFuzzing();
+}
 
 inline void debugFail(CodeBlock* codeBlock, OpcodeID opcodeID, CapabilityLevel result)
 {

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.h (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.h	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.h	2016-08-20 02:00:44 UTC (rev 204670)
@@ -47,6 +47,7 @@
 bool mightInlineFunctionForCall(CodeBlock*);
 bool mightInlineFunctionForClosureCall(CodeBlock*);
 bool mightInlineFunctionForConstruct(CodeBlock*);
+bool canUseOSRExitFuzzing(CodeBlock*);
 
 inline CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc);
 
@@ -59,6 +60,7 @@
 inline bool mightInlineFunctionForCall(CodeBlock*) { return false; }
 inline bool mightInlineFunctionForClosureCall(CodeBlock*) { return false; }
 inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
+inline bool canUseOSRExitFuzzing(CodeBlock*) { return false; }
 
 inline CapabilityLevel capabilityLevel(OpcodeID, CodeBlock*, Instruction*) { return CannotCompile; }
 inline CapabilityLevel capabilityLevel(CodeBlock*) { return CannotCompile; }

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-08-20 02:00:44 UTC (rev 204670)
@@ -154,7 +154,6 @@
     case ArithMin:
     case ArithMax:
     case ArithPow:
-    case ArithSqrt:
     case ArithFRound:
     case ArithSin:
     case ArithCos:
@@ -190,6 +189,15 @@
         def(PureValue(node));
         return;
 
+    case ArithSqrt:
+        if (node->child1().useKind() == DoubleRepUse)
+            def(PureValue(node));
+        else {
+            read(World);
+            write(Heap);
+        }
+        return;
+
     case BitAnd:
     case BitOr:
     case BitXor:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-08-20 02:00:44 UTC (rev 204670)
@@ -386,7 +386,14 @@
             break;
         }
             
-        case ArithSqrt:
+        case ArithSqrt: {
+            Edge& child1 = node->child1();
+            if (child1->shouldSpeculateNumberOrBoolean())
+                fixDoubleOrBooleanEdge(child1);
+            else
+                fixEdge<UntypedUse>(child1);
+            break;
+        }
         case ArithFRound:
         case ArithSin:
         case ArithCos:

Modified: trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp	2016-08-20 02:00:44 UTC (rev 204670)
@@ -100,12 +100,13 @@
     case ConstructVarargs:
     case CallForwardVarargs:
     case ConstructForwardVarargs:
+    case CreateActivation:
     case MaterializeCreateActivation:
     case MaterializeNewObject:
     case NewFunction:
     case NewGeneratorFunction:
     case NewStringObject:
-    case CreateActivation:
+    case ToNumber:
         result = ExitsForExceptions;
         break;
 

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-08-20 02:00:44 UTC (rev 204670)
@@ -159,7 +159,7 @@
     macro(ArithFloor, NodeResultNumber) \
     macro(ArithCeil, NodeResultNumber) \
     macro(ArithTrunc, NodeResultNumber) \
-    macro(ArithSqrt, NodeResultNumber) \
+    macro(ArithSqrt, NodeResultDouble) \
     macro(ArithSin, NodeResultNumber) \
     macro(ArithCos, NodeResultNumber) \
     macro(ArithLog, NodeResultNumber) \

Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExitFuzz.h (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGOSRExitFuzz.h	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExitFuzz.h	2016-08-20 02:00:44 UTC (rev 204670)
@@ -34,9 +34,8 @@
 
 inline bool doOSRExitFuzzing()
 {
-    if (!Options::useOSRExitFuzz())
-        return false;
-    
+    ASSERT(Options::useOSRExitFuzz());
+
     g_numberOfStaticOSRExitFuzzChecks++;
     if (unsigned atStatic = Options::fireOSRExitFuzzAtStatic())
         return atStatic == g_numberOfStaticOSRExitFuzzChecks;

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-08-20 02:00:44 UTC (rev 204670)
@@ -322,6 +322,18 @@
     return JSValue::encode(jsNumber(a / b));
 }
 
+double JIT_OPERATION operationArithSqrt(ExecState* exec, EncodedJSValue encodedOp1)
+{
+    VM* vm = &exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    JSValue op1 = JSValue::decode(encodedOp1);
+    double a = op1.toNumber(exec);
+    if (UNLIKELY(vm->exception()))
+        return JSValue::encode(JSValue());
+    return sqrt(a);
+}
+
 static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
 {
     VM& vm = exec->vm();

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2016-08-20 02:00:44 UTC (rev 204670)
@@ -53,6 +53,7 @@
 EncodedJSValue JIT_OPERATION operationValueBitURShift(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;
+double JIT_OPERATION operationArithSqrt(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByValArrayInt(ExecState*, JSArray*, int32_t) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-08-20 02:00:44 UTC (rev 204670)
@@ -33,6 +33,7 @@
 #include "DFGArrayifySlowPathGenerator.h"
 #include "DFGCallArrayAllocatorSlowPathGenerator.h"
 #include "DFGCallCreateDirectArgumentsSlowPathGenerator.h"
+#include "DFGCapabilities.h"
 #include "DFGMayExit.h"
 #include "DFGOSRExitFuzz.h"
 #include "DFGSaneStringGetByValSlowPathGenerator.h"
@@ -193,7 +194,9 @@
 
 MacroAssembler::Jump SpeculativeJIT::emitOSRExitFuzzCheck()
 {
-    if (!doOSRExitFuzzing())
+    if (!Options::useOSRExitFuzz()
+        || !canUseOSRExitFuzzing(m_jit.graph().baselineCodeBlockFor(m_origin.semantic))
+        || !doOSRExitFuzzing())
         return MacroAssembler::Jump();
     
     MacroAssembler::Jump result;
@@ -4887,19 +4890,30 @@
 
 void SpeculativeJIT::compileArithSqrt(Node* node)
 {
-    SpeculateDoubleOperand op1(this, node->child1());
-    FPRReg op1FPR = op1.fpr();
+    if (node->child1().useKind() == DoubleRepUse) {
+        SpeculateDoubleOperand op1(this, node->child1());
+        FPRReg op1FPR = op1.fpr();
 
-    if (!MacroAssembler::supportsFloatingPointSqrt() || !Options::useArchitectureSpecificOptimizations()) {
-        flushRegisters();
-        FPRResult result(this);
-        callOperation(sqrt, result.fpr(), op1FPR);
-        doubleResult(result.fpr(), node);
-    } else {
-        FPRTemporary result(this, op1);
-        m_jit.sqrtDouble(op1.fpr(), result.fpr());
-        doubleResult(result.fpr(), node);
+        if (!MacroAssembler::supportsFloatingPointSqrt() || !Options::useArchitectureSpecificOptimizations()) {
+            flushRegisters();
+            FPRResult result(this);
+            callOperation(sqrt, result.fpr(), op1FPR);
+            doubleResult(result.fpr(), node);
+        } else {
+            FPRTemporary result(this, op1);
+            m_jit.sqrtDouble(op1.fpr(), result.fpr());
+            doubleResult(result.fpr(), node);
+        }
+        return;
     }
+
+    JSValueOperand op1(this, node->child1());
+    JSValueRegs op1Regs = op1.jsValueRegs();
+    flushRegisters();
+    FPRResult result(this);
+    callOperation(operationArithSqrt, result.fpr(), op1Regs);
+    m_jit.exceptionCheck();
+    doubleResult(result.fpr(), node);
 }
 
 // For small positive integers , it is worth doing a tiny inline loop to exponentiate the base.

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (204669 => 204670)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2016-08-20 02:00:44 UTC (rev 204670)
@@ -1712,6 +1712,11 @@
         m_jit.setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), TrustedImm32(op3), regOp4, regOp5);
         return appendCall(operation);
     }
+    JITCompiler::Call callOperation(D_JITOperation_EJ operation, FPRReg result, JSValueRegs arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1.gpr());
+        return appendCallSetResult(operation, result);
+    }
 #else // USE(JSVALUE32_64)
 
     JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC)
@@ -2138,6 +2143,11 @@
         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identOp2), TrustedImm32(op3), arg4, arg5);
         return appendCall(operation);
     }
+    JITCompiler::Call callOperation(D_JITOperation_EJ operation, FPRReg result, JSValueRegs arg1)
+    {
+        m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR());
+        return appendCallSetResult(operation, result);
+    }
 #endif // USE(JSVALUE32_64)
     
 #if !defined(NDEBUG) && !CPU(ARM) && !CPU(MIPS) && !CPU(SH4)

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (204669 => 204670)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-08-20 02:00:44 UTC (rev 204670)
@@ -38,6 +38,7 @@
 #include "CallFrameShuffler.h"
 #include "CodeBlockWithJITType.h"
 #include "DFGAbstractInterpreterInlines.h"
+#include "DFGCapabilities.h"
 #include "DFGDominators.h"
 #include "DFGInPlaceAbstractState.h"
 #include "DFGOSRAvailabilityAnalysisPhase.h"
@@ -2272,7 +2273,16 @@
             setDouble(result);
     }
 
-    void compileArithSqrt() { setDouble(m_out.doubleSqrt(lowDouble(m_node->child1()))); }
+    void compileArithSqrt()
+    {
+        if (m_node->child1().useKind() == DoubleRepUse) {
+            setDouble(m_out.doubleSqrt(lowDouble(m_node->child1())));
+            return;
+        }
+        LValue argument = lowJSValue(m_node->child1());
+        LValue result = vmCall(Double, m_out.operation(operationArithSqrt), m_callFrame, argument);
+        setDouble(result);
+    }
 
     void compileArithLog() { setDouble(m_out.doubleLog(lowDouble(m_node->child1()))); }
     
@@ -11058,8 +11068,11 @@
         }
 
         DFG_ASSERT(m_graph, m_node, origin.exitOK);
-        
-        if (doOSRExitFuzzing() && !isExceptionHandler) {
+
+        if (!isExceptionHandler
+            && Options::useOSRExitFuzz()
+            && canUseOSRExitFuzzing(m_graph.baselineCodeBlockFor(m_node->origin.semantic))
+            && doOSRExitFuzzing()) {
             LValue numberOfFuzzChecks = m_out.add(
                 m_out.load32(m_out.absolute(&g_numberOfOSRExitFuzzChecks)),
                 m_out.int32One);

Modified: trunk/Source/_javascript_Core/jsc.cpp (204669 => 204670)


--- trunk/Source/_javascript_Core/jsc.cpp	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/jsc.cpp	2016-08-20 02:00:44 UTC (rev 204670)
@@ -598,6 +598,7 @@
 static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
@@ -795,6 +796,7 @@
         addFunction(vm, "noInline", functionNeverInlineFunction, 1);
         addFunction(vm, "noDFG", functionNoDFG, 1);
         addFunction(vm, "noFTL", functionNoFTL, 1);
+        addFunction(vm, "noOSRExitFuzzing", functionNoOSRExitFuzzing, 1);
         addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
         addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
         addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
@@ -1580,6 +1582,11 @@
     return JSValue::encode(jsUndefined());
 }
 
+EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState* exec)
+{
+    return JSValue::encode(setCannotUseOSRExitFuzzing(exec));
+}
+
 EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
 {
     return JSValue::encode(optimizeNextInvocation(exec));

Modified: trunk/Source/_javascript_Core/runtime/Executable.cpp (204669 => 204670)


--- trunk/Source/_javascript_Core/runtime/Executable.cpp	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/runtime/Executable.cpp	2016-08-20 02:00:44 UTC (rev 204670)
@@ -146,6 +146,7 @@
     , m_neverOptimize(false)
     , m_neverFTLOptimize(false)
     , m_isArrowFunctionContext(isInArrowFunctionContext)
+    , m_canUseOSRExitFuzzing(true)
     , m_derivedContextType(static_cast<unsigned>(derivedContextType))
     , m_evalContextType(static_cast<unsigned>(evalContextType))
     , m_overrideLineNumber(-1)

Modified: trunk/Source/_javascript_Core/runtime/Executable.h (204669 => 204670)


--- trunk/Source/_javascript_Core/runtime/Executable.h	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/runtime/Executable.h	2016-08-20 02:00:44 UTC (rev 204670)
@@ -337,6 +337,7 @@
     void setNeverOptimize(bool value) { m_neverOptimize = value; }
     void setNeverFTLOptimize(bool value) { m_neverFTLOptimize = value; }
     void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; }
+    void setCanUseOSRExitFuzzing(bool value) { m_canUseOSRExitFuzzing = value; }
     bool neverInline() const { return m_neverInline; }
     bool neverOptimize() const { return m_neverOptimize; }
     bool neverFTLOptimize() const { return m_neverFTLOptimize; }
@@ -343,6 +344,7 @@
     bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; }
     bool isInliningCandidate() const { return !neverInline(); }
     bool isOkToOptimize() const { return !neverOptimize(); }
+    bool canUseOSRExitFuzzing() const { return m_canUseOSRExitFuzzing; }
     
     bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; }
 
@@ -403,6 +405,7 @@
     bool m_neverOptimize : 1;
     bool m_neverFTLOptimize : 1;
     bool m_isArrowFunctionContext : 1;
+    bool m_canUseOSRExitFuzzing : 1;
     unsigned m_derivedContextType : 2; // DerivedContextType
     unsigned m_evalContextType : 2; // EvalContextType
 

Modified: trunk/Source/_javascript_Core/runtime/TestRunnerUtils.cpp (204669 => 204670)


--- trunk/Source/_javascript_Core/runtime/TestRunnerUtils.cpp	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/runtime/TestRunnerUtils.cpp	2016-08-20 02:00:44 UTC (rev 204670)
@@ -131,6 +131,18 @@
     return setNeverOptimize(exec->uncheckedArgument(0));
 }
 
+JSValue setCannotUseOSRExitFuzzing(ExecState* exec)
+{
+    if (exec->argumentCount() < 1)
+        return jsUndefined();
+
+    JSValue theFunctionValue = exec->uncheckedArgument(0);
+    if (FunctionExecutable* executable = getExecutableForFunction(theFunctionValue))
+        executable->setCanUseOSRExitFuzzing(false);
+
+    return jsUndefined();
+}
+
 JSValue optimizeNextInvocation(ExecState* exec)
 {
     if (exec->argumentCount() < 1)

Modified: trunk/Source/_javascript_Core/runtime/TestRunnerUtils.h (204669 => 204670)


--- trunk/Source/_javascript_Core/runtime/TestRunnerUtils.h	2016-08-20 00:45:30 UTC (rev 204669)
+++ trunk/Source/_javascript_Core/runtime/TestRunnerUtils.h	2016-08-20 02:00:44 UTC (rev 204670)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -45,6 +45,7 @@
 JS_EXPORT_PRIVATE JSValue numberOfDFGCompiles(ExecState*);
 JS_EXPORT_PRIVATE JSValue setNeverInline(ExecState*);
 JS_EXPORT_PRIVATE JSValue setNeverOptimize(ExecState*);
+JS_EXPORT_PRIVATE JSValue setCannotUseOSRExitFuzzing(ExecState*);
 JS_EXPORT_PRIVATE JSValue optimizeNextInvocation(ExecState*);
 
 JS_EXPORT_PRIVATE unsigned numberOfExceptionFuzzChecks();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to