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();