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"',
];