Diff
Modified: trunk/LayoutTests/ChangeLog (185238 => 185239)
--- trunk/LayoutTests/ChangeLog 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/LayoutTests/ChangeLog 2015-06-05 04:59:28 UTC (rev 185239)
@@ -1,3 +1,15 @@
+2015-06-03 Filip Pizlo <fpi...@apple.com>
+
+ Simplify unboxing of double JSValues known to be not NaN and not Int32
+ https://bugs.webkit.org/show_bug.cgi?id=145618
+
+ Reviewed by Geoffrey Garen.
+
+ * js/regress/double-real-use-expected.txt: Added.
+ * js/regress/double-real-use.html: Added.
+ * js/regress/script-tests/double-real-use.js: Added.
+ (foo):
+
2015-06-04 Joseph Pecoraro <pecor...@apple.com>
Web Inspector: Class constructor appearing as Object Tree property does not include parameters
Added: trunk/LayoutTests/js/regress/double-real-use-expected.txt (0 => 185239)
--- trunk/LayoutTests/js/regress/double-real-use-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/double-real-use-expected.txt 2015-06-05 04:59:28 UTC (rev 185239)
@@ -0,0 +1,10 @@
+JSRegress/double-real-use
+
+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/double-real-use.html (0 => 185239)
--- trunk/LayoutTests/js/regress/double-real-use.html (rev 0)
+++ trunk/LayoutTests/js/regress/double-real-use.html 2015-06-05 04:59:28 UTC (rev 185239)
@@ -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/double-real-use.js (0 => 185239)
--- trunk/LayoutTests/js/regress/script-tests/double-real-use.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/double-real-use.js 2015-06-05 04:59:28 UTC (rev 185239)
@@ -0,0 +1,16 @@
+function foo(a) {
+ var result = 0.0;
+ for (var i = 0; i < 1000; ++i) {
+ var o = a[i];
+ result += o.x + o.y;
+ }
+ return result;
+}
+
+noInline(foo);
+
+var array = [];
+for (var i = 0; i < 1000; ++i)
+ array.push({x:1.5, y:2.5});
+for (var i = 0; i < 10000; ++i)
+ foo(array);
Modified: trunk/Source/_javascript_Core/ChangeLog (185238 => 185239)
--- trunk/Source/_javascript_Core/ChangeLog 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-06-05 04:59:28 UTC (rev 185239)
@@ -1,3 +1,84 @@
+2015-06-03 Filip Pizlo <fpi...@apple.com>
+
+ Simplify unboxing of double JSValues known to be not NaN and not Int32
+ https://bugs.webkit.org/show_bug.cgi?id=145618
+
+ Reviewed by Geoffrey Garen.
+
+ In many cases we know that we most likely loaded a non-NaN double value from the heap.
+ Prior to this patch, we would do two branches before unboxing the double. This patch
+ reduces this to one branch in the common case. Before:
+
+ if (is int32)
+ unbox int32 and convert to double
+ else if (is number)
+ unbox double
+ else
+ exit
+
+ After:
+
+ tmp = unbox double
+ if (tmp == tmp)
+ done
+ else if (is int32)
+ unbox int32 and convert to double
+ else
+ exit
+
+ We only use the new style if we have profiling that tells us that we are unlikely to see
+ either Int32 or NaN - since we will now exit on NaN and int32 requires an extra branch.
+
+ This is a 8% speed-up on Octane/box2d. On one microbenchmark this is a 25% speed-up.
+
+ Rolling this back in after I made DFG::SpeculativeJIT call a new version of unboxDouble()
+ that doesn't assert that the JSValue is a double, since we are intentionally using it
+ before doing the "is a double" test. This wasn't a problem on 32-bit since unboxDouble()
+ does no such assertion on 32-bit.
+
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::observeUseKindOnNode):
+ (JSC::DFG::FixupPhase::fixEdgeRepresentation):
+ (JSC::DFG::FixupPhase::injectTypeConversionsForEdge):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::shouldSpeculateDouble):
+ (JSC::DFG::Node::shouldSpeculateDoubleReal):
+ (JSC::DFG::Node::shouldSpeculateNumber):
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::SafeToExecuteEdge::operator()):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileDoubleRep):
+ (JSC::DFG::SpeculativeJIT::speculateNumber):
+ (JSC::DFG::SpeculativeJIT::speculateRealNumber):
+ (JSC::DFG::SpeculativeJIT::speculateDoubleRepReal):
+ (JSC::DFG::SpeculativeJIT::speculate):
+ (JSC::DFG::SpeculativeJIT::speculateDoubleReal): Deleted.
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGUseKind.cpp:
+ (WTF::printInternal):
+ * dfg/DFGUseKind.h:
+ (JSC::DFG::typeFilterFor):
+ (JSC::DFG::isNumerical):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileDoubleRep):
+ (JSC::FTL::LowerDFGToLLVM::boxDouble):
+ (JSC::FTL::LowerDFGToLLVM::jsValueToStrictInt52):
+ (JSC::FTL::LowerDFGToLLVM::speculate):
+ (JSC::FTL::LowerDFGToLLVM::speculateNumber):
+ (JSC::FTL::LowerDFGToLLVM::speculateRealNumber):
+ (JSC::FTL::LowerDFGToLLVM::speculateDoubleRepReal):
+ (JSC::FTL::LowerDFGToLLVM::jsValueToDouble): Deleted.
+ (JSC::FTL::LowerDFGToLLVM::speculateDoubleReal): Deleted.
+ * jit/AssemblyHelpers.h:
+ (JSC::AssemblyHelpers::branchIfNotOther):
+ (JSC::AssemblyHelpers::branchIfInt32):
+ (JSC::AssemblyHelpers::branchIfNotInt32):
+ (JSC::AssemblyHelpers::branchIfNumber):
+
2015-06-04 Joseph Pecoraro <pecor...@apple.com>
Web Inspector: Class constructor appearing as Object Tree property does not include parameters
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (185238 => 185239)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-06-05 04:59:28 UTC (rev 185239)
@@ -378,6 +378,7 @@
case Int52RepUse:
case NumberUse:
+ case RealNumberUse:
break;
default:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (185238 => 185239)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-06-05 04:59:28 UTC (rev 185239)
@@ -1723,6 +1723,7 @@
m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
break;
case NumberUse:
+ case RealNumberUse:
case DoubleRepUse:
case DoubleRepRealUse:
if (variable->doubleFormatState() == UsingDoubleFormat)
@@ -2102,6 +2103,13 @@
edge.setUseKind(Int52RepUse);
break;
+ case RealNumberUse:
+ if (edge->hasDoubleResult())
+ edge.setUseKind(DoubleRepRealUse);
+ else if (edge->hasInt52Result())
+ edge.setUseKind(Int52RepUse);
+ break;
+
default:
break;
}
@@ -2128,9 +2136,13 @@
m_indexInBlock, SpecInt52AsDouble, DoubleRep, node->origin,
Edge(edge.node(), Int52RepUse));
} else {
- UseKind useKind = NotCellUse;
- if (edge->shouldSpeculateNumber())
+ UseKind useKind;
+ if (edge->shouldSpeculateDoubleReal())
+ useKind = RealNumberUse;
+ else if (edge->shouldSpeculateNumber())
useKind = NumberUse;
+ else
+ useKind = NotCellUse;
result = m_insertionSet.insertNode(
m_indexInBlock, SpecBytecodeDouble, DoubleRep, node->origin,
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (185238 => 185239)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2015-06-05 04:59:28 UTC (rev 185239)
@@ -1762,6 +1762,11 @@
return isDoubleSpeculation(prediction());
}
+ bool shouldSpeculateDoubleReal()
+ {
+ return isDoubleRealSpeculation(prediction());
+ }
+
bool shouldSpeculateNumber()
{
return isFullNumberSpeculation(prediction());
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (185238 => 185239)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2015-06-05 04:59:28 UTC (rev 185239)
@@ -50,6 +50,7 @@
case DoubleRepRealUse:
case Int52RepUse:
case NumberUse:
+ case RealNumberUse:
case BooleanUse:
case CellUse:
case ObjectUse:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (185238 => 185239)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-06-05 04:59:28 UTC (rev 185239)
@@ -2066,6 +2066,37 @@
void SpeculativeJIT::compileDoubleRep(Node* node)
{
switch (node->child1().useKind()) {
+ case RealNumberUse: {
+ JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
+ FPRTemporary result(this);
+
+ JSValueRegs op1Regs = op1.jsValueRegs();
+ FPRReg resultFPR = result.fpr();
+
+#if USE(JSVALUE64)
+ GPRTemporary temp(this);
+ GPRReg tempGPR = temp.gpr();
+ m_jit.move(op1Regs.gpr(), tempGPR);
+ m_jit.unboxDoubleWithoutAssertions(tempGPR, resultFPR);
+#else
+ FPRTemporary temp(this);
+ FPRReg tempFPR = temp.fpr();
+ unboxDouble(op1Regs.tagGPR(), op1Regs.payloadGPR(), resultFPR, tempFPR);
+#endif
+
+ JITCompiler::Jump done = m_jit.branchDouble(
+ JITCompiler::DoubleEqual, resultFPR, resultFPR);
+
+ DFG_TYPE_CHECK(
+ op1Regs, node->child1(), SpecBytecodeRealNumber, m_jit.branchIfNotInt32(op1Regs));
+ m_jit.convertInt32ToDouble(op1Regs.payloadGPR(), resultFPR);
+
+ done.link(&m_jit);
+
+ doubleResult(resultFPR, node);
+ return;
+ }
+
case NotCellUse:
case NumberUse: {
ASSERT(!node->child1()->isNumberConstant()); // This should have been constant folded.
@@ -5372,11 +5403,41 @@
#endif
}
-void SpeculativeJIT::speculateDoubleReal(Edge edge)
+void SpeculativeJIT::speculateRealNumber(Edge edge)
{
if (!needsTypeCheck(edge, SpecDoubleReal))
return;
+ JSValueOperand op1(this, edge, ManualOperandSpeculation);
+ FPRTemporary result(this);
+
+ JSValueRegs op1Regs = op1.jsValueRegs();
+ FPRReg resultFPR = result.fpr();
+
+#if USE(JSVALUE64)
+ GPRTemporary temp(this);
+ GPRReg tempGPR = temp.gpr();
+ m_jit.move(op1Regs.gpr(), tempGPR);
+ m_jit.unboxDoubleWithoutAssertions(tempGPR, resultFPR);
+#else
+ FPRTemporary temp(this);
+ FPRReg tempFPR = temp.fpr();
+ unboxDouble(op1Regs.tagGPR(), op1Regs.payloadGPR(), resultFPR, tempFPR);
+#endif
+
+ JITCompiler::Jump done = m_jit.branchDouble(
+ JITCompiler::DoubleEqual, resultFPR, resultFPR);
+
+ typeCheck(op1Regs, edge, SpecBytecodeRealNumber, m_jit.branchIfNotInt32(op1Regs));
+
+ done.link(&m_jit);
+}
+
+void SpeculativeJIT::speculateDoubleRepReal(Edge edge)
+{
+ if (!needsTypeCheck(edge, SpecDoubleReal))
+ return;
+
SpeculateDoubleOperand operand(this, edge);
FPRReg fpr = operand.fpr();
typeCheck(
@@ -5641,8 +5702,11 @@
case NumberUse:
speculateNumber(edge);
break;
+ case RealNumberUse:
+ speculateRealNumber(edge);
+ break;
case DoubleRepRealUse:
- speculateDoubleReal(edge);
+ speculateDoubleRepReal(edge);
break;
#if USE(JSVALUE64)
case MachineIntUse:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (185238 => 185239)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2015-06-05 04:59:28 UTC (rev 185239)
@@ -2372,7 +2372,8 @@
void speculateDoubleRepMachineInt(Edge);
#endif // USE(JSVALUE64)
void speculateNumber(Edge);
- void speculateDoubleReal(Edge);
+ void speculateRealNumber(Edge);
+ void speculateDoubleRepReal(Edge);
void speculateBoolean(Edge);
void speculateCell(Edge);
void speculateObject(Edge);
Modified: trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp (185238 => 185239)
--- trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp 2015-06-05 04:59:28 UTC (rev 185239)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -55,6 +55,9 @@
case NumberUse:
out.print("Number");
return;
+ case RealNumberUse:
+ out.print("RealNumber");
+ return;
case DoubleRepUse:
out.print("DoubleRep");
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGUseKind.h (185238 => 185239)
--- trunk/Source/_javascript_Core/dfg/DFGUseKind.h 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/dfg/DFGUseKind.h 2015-06-05 04:59:28 UTC (rev 185239)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -46,6 +46,7 @@
KnownInt32Use,
MachineIntUse,
NumberUse,
+ RealNumberUse,
BooleanUse,
CellUse,
KnownCellUse,
@@ -90,6 +91,8 @@
return SpecInt32 | SpecInt52AsDouble;
case NumberUse:
return SpecBytecodeNumber;
+ case RealNumberUse:
+ return SpecBytecodeRealNumber;
case DoubleRepUse:
return SpecFullDouble;
case DoubleRepRealUse:
@@ -158,6 +161,7 @@
case Int32Use:
case KnownInt32Use:
case NumberUse:
+ case RealNumberUse:
case Int52RepUse:
case DoubleRepUse:
case DoubleRepRealUse:
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (185238 => 185239)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-06-05 04:59:28 UTC (rev 185239)
@@ -400,6 +400,7 @@
case KnownInt32Use:
case Int52RepUse:
case NumberUse:
+ case RealNumberUse:
case DoubleRepUse:
case DoubleRepRealUse:
case BooleanUse:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (185238 => 185239)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-06-05 04:59:28 UTC (rev 185239)
@@ -958,12 +958,113 @@
void compileDoubleRep()
{
switch (m_node->child1().useKind()) {
+ case RealNumberUse: {
+ LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
+
+ LValue doubleValue = unboxDouble(value);
+
+ LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("DoubleRep RealNumberUse int case"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("DoubleRep continuation"));
+
+ ValueFromBlock fastResult = m_out.anchor(doubleValue);
+ m_out.branch(
+ m_out.doubleEqual(doubleValue, doubleValue),
+ usually(continuation), rarely(intCase));
+
+ LBasicBlock lastNext = m_out.appendTo(intCase, continuation);
+
+ FTL_TYPE_CHECK(
+ jsValueValue(value), m_node->child1(), SpecBytecodeRealNumber,
+ isNotInt32(value, provenType(m_node->child1()) & ~SpecFullDouble));
+ ValueFromBlock slowResult = m_out.anchor(m_out.intToDouble(unboxInt32(value)));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+
+ setDouble(m_out.phi(m_out.doubleType, fastResult, slowResult));
+ return;
+ }
+
case NotCellUse:
case NumberUse: {
bool shouldConvertNonNumber = m_node->child1().useKind() == NotCellUse;
+
+ LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
- LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
- setDouble(jsValueToDouble(m_node->child1(), value, shouldConvertNonNumber));
+ LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing int case"));
+ LBasicBlock doubleTesting = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing double case"));
+ LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing double case"));
+ LBasicBlock nonDoubleCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing undefined case"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing continuation"));
+
+ m_out.branch(
+ isNotInt32(value, provenType(m_node->child1())),
+ unsure(doubleTesting), unsure(intCase));
+
+ LBasicBlock lastNext = m_out.appendTo(intCase, doubleTesting);
+
+ ValueFromBlock intToDouble = m_out.anchor(
+ m_out.intToDouble(unboxInt32(value)));
+ m_out.jump(continuation);
+
+ m_out.appendTo(doubleTesting, doubleCase);
+ LValue valueIsNumber = isNumber(value, provenType(m_node->child1()));
+ m_out.branch(valueIsNumber, usually(doubleCase), rarely(nonDoubleCase));
+
+ m_out.appendTo(doubleCase, nonDoubleCase);
+ ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(value));
+ m_out.jump(continuation);
+
+ if (shouldConvertNonNumber) {
+ LBasicBlock undefinedCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble converting undefined case"));
+ LBasicBlock testNullCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing null case"));
+ LBasicBlock nullCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble converting null case"));
+ LBasicBlock testBooleanTrueCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing boolean true case"));
+ LBasicBlock convertBooleanTrueCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble convert boolean true case"));
+ LBasicBlock convertBooleanFalseCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble convert boolean false case"));
+
+ m_out.appendTo(nonDoubleCase, undefinedCase);
+ LValue valueIsUndefined = m_out.equal(value, m_out.constInt64(ValueUndefined));
+ m_out.branch(valueIsUndefined, unsure(undefinedCase), unsure(testNullCase));
+
+ m_out.appendTo(undefinedCase, testNullCase);
+ ValueFromBlock convertedUndefined = m_out.anchor(m_out.constDouble(PNaN));
+ m_out.jump(continuation);
+
+ m_out.appendTo(testNullCase, nullCase);
+ LValue valueIsNull = m_out.equal(value, m_out.constInt64(ValueNull));
+ m_out.branch(valueIsNull, unsure(nullCase), unsure(testBooleanTrueCase));
+
+ m_out.appendTo(nullCase, testBooleanTrueCase);
+ ValueFromBlock convertedNull = m_out.anchor(m_out.constDouble(0));
+ m_out.jump(continuation);
+
+ m_out.appendTo(testBooleanTrueCase, convertBooleanTrueCase);
+ LValue valueIsBooleanTrue = m_out.equal(value, m_out.constInt64(ValueTrue));
+ m_out.branch(valueIsBooleanTrue, unsure(convertBooleanTrueCase), unsure(convertBooleanFalseCase));
+
+ m_out.appendTo(convertBooleanTrueCase, convertBooleanFalseCase);
+ ValueFromBlock convertedTrue = m_out.anchor(m_out.constDouble(1));
+ m_out.jump(continuation);
+
+ m_out.appendTo(convertBooleanFalseCase, continuation);
+
+ LValue valueIsNotBooleanFalse = m_out.notEqual(value, m_out.constInt64(ValueFalse));
+ FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), ~SpecCell, valueIsNotBooleanFalse);
+ ValueFromBlock convertedFalse = m_out.anchor(m_out.constDouble(0));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setDouble(m_out.phi(m_out.doubleType, intToDouble, unboxedDouble, convertedUndefined, convertedNull, convertedTrue, convertedFalse));
+ return;
+ }
+ m_out.appendTo(nonDoubleCase, continuation);
+ FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), SpecBytecodeNumber, m_out.booleanTrue);
+ m_out.unreachable();
+
+ m_out.appendTo(continuation, lastNext);
+
+ setDouble(m_out.phi(m_out.doubleType, intToDouble, unboxedDouble));
return;
}
@@ -7293,87 +7394,6 @@
{
return m_out.sub(m_out.bitCast(doubleValue, m_out.int64), m_tagTypeNumber);
}
- LValue jsValueToDouble(Edge edge, LValue boxedValue, bool shouldConvertNonNumber)
- {
- LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing int case"));
- LBasicBlock doubleTesting = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing double case"));
- LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing double case"));
- LBasicBlock nonDoubleCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing undefined case"));
- LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing continuation"));
-
- LValue isNotInt32;
- if (!m_interpreter.needsTypeCheck(edge, SpecInt32))
- isNotInt32 = m_out.booleanFalse;
- else if (!m_interpreter.needsTypeCheck(edge, ~SpecInt32))
- isNotInt32 = m_out.booleanTrue;
- else
- isNotInt32 = this->isNotInt32(boxedValue);
- m_out.branch(isNotInt32, unsure(doubleTesting), unsure(intCase));
-
- LBasicBlock lastNext = m_out.appendTo(intCase, doubleTesting);
-
- ValueFromBlock intToDouble = m_out.anchor(
- m_out.intToDouble(unboxInt32(boxedValue)));
- m_out.jump(continuation);
-
- m_out.appendTo(doubleTesting, doubleCase);
- LValue valueIsNumber = isNumber(boxedValue);
- m_out.branch(valueIsNumber, usually(doubleCase), rarely(nonDoubleCase));
-
- m_out.appendTo(doubleCase, nonDoubleCase);
- ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedValue));
- m_out.jump(continuation);
-
- if (shouldConvertNonNumber) {
- LBasicBlock undefinedCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble converting undefined case"));
- LBasicBlock testNullCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing null case"));
- LBasicBlock nullCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble converting null case"));
- LBasicBlock testBooleanTrueCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing boolean true case"));
- LBasicBlock convertBooleanTrueCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble convert boolean true case"));
- LBasicBlock convertBooleanFalseCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble convert boolean false case"));
-
- m_out.appendTo(nonDoubleCase, undefinedCase);
- LValue valueIsUndefined = m_out.equal(boxedValue, m_out.constInt64(ValueUndefined));
- m_out.branch(valueIsUndefined, unsure(undefinedCase), unsure(testNullCase));
-
- m_out.appendTo(undefinedCase, testNullCase);
- ValueFromBlock convertedUndefined = m_out.anchor(m_out.constDouble(PNaN));
- m_out.jump(continuation);
-
- m_out.appendTo(testNullCase, nullCase);
- LValue valueIsNull = m_out.equal(boxedValue, m_out.constInt64(ValueNull));
- m_out.branch(valueIsNull, unsure(nullCase), unsure(testBooleanTrueCase));
-
- m_out.appendTo(nullCase, testBooleanTrueCase);
- ValueFromBlock convertedNull = m_out.anchor(m_out.constDouble(0));
- m_out.jump(continuation);
-
- m_out.appendTo(testBooleanTrueCase, convertBooleanTrueCase);
- LValue valueIsBooleanTrue = m_out.equal(boxedValue, m_out.constInt64(ValueTrue));
- m_out.branch(valueIsBooleanTrue, unsure(convertBooleanTrueCase), unsure(convertBooleanFalseCase));
-
- m_out.appendTo(convertBooleanTrueCase, convertBooleanFalseCase);
- ValueFromBlock convertedTrue = m_out.anchor(m_out.constDouble(1));
- m_out.jump(continuation);
-
- m_out.appendTo(convertBooleanFalseCase, continuation);
-
- LValue valueIsNotBooleanFalse = m_out.notEqual(boxedValue, m_out.constInt64(ValueFalse));
- FTL_TYPE_CHECK(jsValueValue(boxedValue), edge, ~SpecCell, valueIsNotBooleanFalse);
- ValueFromBlock convertedFalse = m_out.anchor(m_out.constDouble(0));
- m_out.jump(continuation);
-
- m_out.appendTo(continuation, lastNext);
- return m_out.phi(m_out.doubleType, intToDouble, unboxedDouble, convertedUndefined, convertedNull, convertedTrue, convertedFalse);
- }
- m_out.appendTo(nonDoubleCase, continuation);
- FTL_TYPE_CHECK(jsValueValue(boxedValue), edge, SpecBytecodeNumber, m_out.booleanTrue);
- m_out.unreachable();
-
- m_out.appendTo(continuation, lastNext);
-
- return m_out.phi(m_out.doubleType, intToDouble, unboxedDouble);
- }
LValue jsValueToStrictInt52(Edge edge, LValue boxedValue)
{
@@ -7590,8 +7610,11 @@
case NumberUse:
speculateNumber(edge);
break;
+ case RealNumberUse:
+ speculateRealNumber(edge);
+ break;
case DoubleRepRealUse:
- speculateDoubleReal(edge);
+ speculateDoubleRepReal(edge);
break;
case DoubleRepMachineIntUse:
speculateDoubleRepMachineInt(edge);
@@ -7917,12 +7940,38 @@
FTL_TYPE_CHECK(jsValueValue(value), edge, SpecBytecodeNumber, isNotNumber(value));
}
- void speculateDoubleReal(Edge edge)
+ void speculateRealNumber(Edge edge)
{
// Do an early return here because lowDouble() can create a lot of control flow.
if (!m_interpreter.needsTypeCheck(edge))
return;
+ LValue value = lowJSValue(edge, ManualOperandSpeculation);
+ LValue doubleValue = unboxDouble(value);
+
+ LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("speculateRealNumber int case"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("speculateRealNumber continuation"));
+
+ m_out.branch(
+ m_out.doubleEqual(doubleValue, doubleValue),
+ usually(continuation), rarely(intCase));
+
+ LBasicBlock lastNext = m_out.appendTo(intCase, continuation);
+
+ typeCheck(
+ jsValueValue(value), m_node->child1(), SpecBytecodeRealNumber,
+ isNotInt32(value, provenType(m_node->child1()) & ~SpecFullDouble));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ }
+
+ void speculateDoubleRepReal(Edge edge)
+ {
+ // Do an early return here because lowDouble() can create a lot of control flow.
+ if (!m_interpreter.needsTypeCheck(edge))
+ return;
+
LValue value = lowDouble(edge);
FTL_TYPE_CHECK(
doubleValue(value), edge, SpecDoubleReal,
Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.h (185238 => 185239)
--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.h 2015-06-05 04:46:17 UTC (rev 185238)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.h 2015-06-05 04:59:28 UTC (rev 185239)
@@ -457,6 +457,24 @@
#endif
}
+ Jump branchIfInt32(JSValueRegs regs)
+ {
+#if USE(JSVALUE64)
+ return branch64(AboveOrEqual, regs.gpr(), GPRInfo::tagTypeNumberRegister);
+#else
+ return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::Int32Tag));
+#endif
+ }
+
+ Jump branchIfNotInt32(JSValueRegs regs)
+ {
+#if USE(JSVALUE64)
+ return branch64(Below, regs.gpr(), GPRInfo::tagTypeNumberRegister);
+#else
+ return branch32(NotEqual, regs.tagGPR(), TrustedImm32(JSValue::Int32Tag));
+#endif
+ }
+
// Note that the tempGPR is not used in 64-bit mode.
Jump branchIfNumber(JSValueRegs regs, GPRReg tempGPR)
{
@@ -736,13 +754,17 @@
jitAssertIsJSDouble(gpr);
return gpr;
}
- FPRReg unboxDouble(GPRReg gpr, FPRReg fpr)
+ FPRReg unboxDoubleWithoutAssertions(GPRReg gpr, FPRReg fpr)
{
- jitAssertIsJSDouble(gpr);
add64(GPRInfo::tagTypeNumberRegister, gpr);
move64ToDouble(gpr, fpr);
return fpr;
}
+ FPRReg unboxDouble(GPRReg gpr, FPRReg fpr)
+ {
+ jitAssertIsJSDouble(gpr);
+ return unboxDoubleWithoutAssertions(gpr, fpr);
+ }
void boxDouble(FPRReg fpr, JSValueRegs regs)
{