+2013-09-18 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r156019 and r156020.
+ http://trac.webkit.org/changeset/156019
+ http://trac.webkit.org/changeset/156020
+ https://bugs.webkit.org/show_bug.cgi?id=121540
+
+ Broke tests (Requested by ap on #webkit).
+
+ * js/regress/large-int-captured-expected.txt: Removed.
+ * js/regress/large-int-captured.html: Removed.
+ * js/regress/large-int-expected.txt: Removed.
+ * js/regress/large-int-neg-expected.txt: Removed.
+ * js/regress/large-int-neg.html: Removed.
+ * js/regress/large-int.html: Removed.
+ * js/regress/marsaglia-larger-ints-expected.txt: Removed.
+ * js/regress/marsaglia-larger-ints.html: Removed.
+ * js/regress/script-tests/large-int-captured.js: Removed.
+ * js/regress/script-tests/large-int-neg.js: Removed.
+ * js/regress/script-tests/large-int.js: Removed.
+ * js/regress/script-tests/marsaglia-larger-ints.js: Removed.
+
2013-09-17 Zoltan Horvath <zoltan@webkit.org>
[CSS Shapes] Use the float height to determine position in shape-inside
+++ /dev/null
-JSRegress/large-int-captured
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS no exception thrown
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
+++ /dev/null
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test-pre.js"></script>
-</head>
-<body>
-<script src="resources/regress-pre.js"></script>
-<script src="script-tests/large-int-captured.js"></script>
-<script src="resources/regress-post.js"></script>
-<script src="../../resources/js-test-post.js"></script>
-</body>
-</html>
+++ /dev/null
-JSRegress/large-int
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS no exception thrown
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
+++ /dev/null
-JSRegress/large-int-neg
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS no exception thrown
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
+++ /dev/null
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test-pre.js"></script>
-</head>
-<body>
-<script src="resources/regress-pre.js"></script>
-<script src="script-tests/large-int-neg.js"></script>
-<script src="resources/regress-post.js"></script>
-<script src="../../resources/js-test-post.js"></script>
-</body>
-</html>
+++ /dev/null
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test-pre.js"></script>
-</head>
-<body>
-<script src="resources/regress-pre.js"></script>
-<script src="script-tests/large-int.js"></script>
-<script src="resources/regress-post.js"></script>
-<script src="../../resources/js-test-post.js"></script>
-</body>
-</html>
+++ /dev/null
-JSRegress/marsaglia-larger-ints
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS no exception thrown
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
+++ /dev/null
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test-pre.js"></script>
-</head>
-<body>
-<script src="resources/regress-pre.js"></script>
-<script src="script-tests/marsaglia-larger-ints.js"></script>
-<script src="resources/regress-post.js"></script>
-<script src="../../resources/js-test-post.js"></script>
-</body>
-</html>
+++ /dev/null
-function foo(x, y) {
- var z = x;
- function bar() {
- return z;
- }
- for (var i = 0; i < 3; ++i)
- z += y;
- return bar();
-}
-
-eval("// Don't compile me");
-
-var result = 0;
-
-for (var i = 0; i < 100000; ++i)
- result += foo(1000000000, 1000000000);
-
-if (result != 400000000000000)
- throw "Error: bad result: " + result;
+++ /dev/null
-function foo(x, y) {
- var z = x;
- var w = 0;
- for (var i = 0; i < 3; ++i) {
- z += y;
- w = -z;
- }
- return w + 1;
-}
-
-eval("// Don't compile me");
-
-var result = 0;
-
-for (var i = 0; i < 1000000; ++i)
- result += foo(1000000000, 1000000000);
-
-if (result != -3999999999000000)
- throw "Error: bad result: " + result;
+++ /dev/null
-function foo(x, y) {
- var z = x;
- for (var i = 0; i < 3; ++i)
- z += y;
- return z;
-}
-
-eval("// Don't compile me");
-
-var result = 0;
-
-for (var i = 0; i < 1000000; ++i)
- result += foo(1000000000, 1000000000);
-
-if (result != 4000000000000000)
- throw "Error: bad result: " + result;
+++ /dev/null
-function uint(x) {
- if (x < 0)
- return x + 4294967296;
- return x;
-}
-
-function marsaglia(m_z, m_w, n) {
- var result;
- for (var i = 0; i < n; ++i) {
- m_z = (36969 * uint(m_z & 65535) + (m_z >> 16)) | 0;
- m_w = (18000 * uint(m_w & 65535) + (m_w >> 16)) | 0;
- result = ((m_z << 16) + m_w) | 0;
- }
- return result;
-}
-
-var result = marsaglia(5, 7, 10000000);
-
-if (result != -1047364056)
- throw "Error: bad result: " + result;
-
+2013-09-18 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r156019 and r156020.
+ http://trac.webkit.org/changeset/156019
+ http://trac.webkit.org/changeset/156020
+ https://bugs.webkit.org/show_bug.cgi?id=121540
+
+ Broke tests (Requested by ap on #webkit).
+
+ * assembler/MacroAssemblerX86_64.h:
+ * assembler/X86Assembler.h:
+ * bytecode/DataFormat.h:
+ (JSC::dataFormatToString):
+ * bytecode/ExitKind.cpp:
+ (JSC::exitKindToString):
+ * bytecode/ExitKind.h:
+ * bytecode/OperandsInlines.h:
+ (JSC::::dumpInContext):
+ * bytecode/SpeculatedType.cpp:
+ (JSC::dumpSpeculation):
+ (JSC::speculationToAbbreviatedString):
+ (JSC::speculationFromValue):
+ * bytecode/SpeculatedType.h:
+ (JSC::isInt32SpeculationForArithmetic):
+ (JSC::isInt48Speculation):
+ (JSC::isMachineIntSpeculationForArithmetic):
+ (JSC::isInt48AsDoubleSpeculation):
+ (JSC::isRealNumberSpeculation):
+ (JSC::isNumberSpeculation):
+ (JSC::isNumberSpeculationExpectingDefined):
+ * bytecode/ValueRecovery.h:
+ (JSC::ValueRecovery::inGPR):
+ (JSC::ValueRecovery::displacedInJSStack):
+ (JSC::ValueRecovery::isAlreadyInJSStack):
+ (JSC::ValueRecovery::gpr):
+ (JSC::ValueRecovery::virtualRegister):
+ (JSC::ValueRecovery::dumpInContext):
+ * dfg/DFGAbstractInterpreter.h:
+ (JSC::DFG::AbstractInterpreter::needsTypeCheck):
+ (JSC::DFG::AbstractInterpreter::filterByType):
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::::executeEffects):
+ * dfg/DFGAbstractValue.cpp:
+ (JSC::DFG::AbstractValue::set):
+ (JSC::DFG::AbstractValue::checkConsistency):
+ * dfg/DFGAbstractValue.h:
+ (JSC::DFG::AbstractValue::validateType):
+ * dfg/DFGArrayMode.cpp:
+ (JSC::DFG::ArrayMode::refine):
+ * dfg/DFGAssemblyHelpers.h:
+ (JSC::DFG::AssemblyHelpers::unboxDouble):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::makeSafe):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::canonicalize):
+ (JSC::DFG::CSEPhase::pureCSE):
+ (JSC::DFG::CSEPhase::getByValLoadElimination):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGCommon.h:
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::run):
+ (JSC::DFG::FixupPhase::fixupNode):
+ (JSC::DFG::FixupPhase::fixupSetLocalsInBlock):
+ (JSC::DFG::FixupPhase::observeUseKindOnNode):
+ (JSC::DFG::FixupPhase::fixEdge):
+ (JSC::DFG::FixupPhase::injectInt32ToDoubleNode):
+ (JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):
+ * dfg/DFGFlushFormat.cpp:
+ (WTF::printInternal):
+ * dfg/DFGFlushFormat.h:
+ (JSC::DFG::resultFor):
+ (JSC::DFG::useKindFor):
+ * dfg/DFGGenerationInfo.h:
+ (JSC::DFG::GenerationInfo::initInt32):
+ (JSC::DFG::GenerationInfo::fillInt32):
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::dump):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::addShouldSpeculateMachineInt):
+ (JSC::DFG::Graph::mulShouldSpeculateMachineInt):
+ (JSC::DFG::Graph::negateShouldSpeculateMachineInt):
+ * dfg/DFGInPlaceAbstractState.cpp:
+ (JSC::DFG::InPlaceAbstractState::mergeStateAtTail):
+ * dfg/DFGJITCode.cpp:
+ (JSC::DFG::JITCode::reconstruct):
+ * dfg/DFGMinifiedNode.h:
+ (JSC::DFG::belongsInMinifiedGraph):
+ (JSC::DFG::MinifiedNode::hasChild):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::shouldSpeculateNumber):
+ (JSC::DFG::Node::shouldSpeculateNumberExpectingDefined):
+ (JSC::DFG::Node::canSpeculateInt48):
+ * dfg/DFGNodeFlags.h:
+ (JSC::DFG::nodeCanSpeculateInt48):
+ * dfg/DFGNodeType.h:
+ (JSC::DFG::forwardRewiringSelectionScore):
+ * dfg/DFGOSRExitCompiler.cpp:
+ (JSC::DFG::shortOperandsDump):
+ * dfg/DFGOSRExitCompiler64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::speculatedDoubleTypeForPrediction):
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ (JSC::DFG::PredictionPropagationPhase::doDoubleVoting):
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::SafeToExecuteEdge::operator()):
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSilentRegisterSavePlan.h:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):
+ (JSC::DFG::SpeculativeJIT::silentFill):
+ (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
+ (JSC::DFG::SpeculativeJIT::compileInlineStart):
+ (JSC::DFG::SpeculativeJIT::compileDoublePutByVal):
+ (JSC::DFG::SpeculativeJIT::compileValueToInt32):
+ (JSC::DFG::SpeculativeJIT::compileInt32ToDouble):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
+ (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+ (JSC::DFG::SpeculativeJIT::compileAdd):
+ (JSC::DFG::SpeculativeJIT::compileArithSub):
+ (JSC::DFG::SpeculativeJIT::compileArithNegate):
+ (JSC::DFG::SpeculativeJIT::compileArithMul):
+ (JSC::DFG::SpeculativeJIT::compare):
+ (JSC::DFG::SpeculativeJIT::compileStrictEq):
+ (JSC::DFG::SpeculativeJIT::speculateNumber):
+ (JSC::DFG::SpeculativeJIT::speculateRealNumber):
+ (JSC::DFG::SpeculativeJIT::speculate):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::canReuse):
+ (JSC::DFG::SpeculativeJIT::isFilled):
+ (JSC::DFG::SpeculativeJIT::isFilledDouble):
+ (JSC::DFG::SpeculativeJIT::use):
+ (JSC::DFG::SpeculativeJIT::boxDouble):
+ (JSC::DFG::SpeculativeJIT::isKnownInteger):
+ (JSC::DFG::SpeculativeJIT::isKnownCell):
+ (JSC::DFG::SpeculativeJIT::isKnownNotNumber):
+ (JSC::DFG::SpeculativeJIT::int32Result):
+ (JSC::DFG::SpeculativeJIT::initConstantInfo):
+ (JSC::DFG::SpeculativeJIT::isInteger):
+ (JSC::DFG::SpeculativeJIT::generationInfoFromVirtualRegister):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::fillJSValue):
+ (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
+ (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
+ (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+ (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGUseKind.cpp:
+ (WTF::printInternal):
+ * dfg/DFGUseKind.h:
+ (JSC::DFG::typeFilterFor):
+ (JSC::DFG::isNumerical):
+ * dfg/DFGValueSource.cpp:
+ (JSC::DFG::ValueSource::dump):
+ * dfg/DFGValueSource.h:
+ (JSC::DFG::dataFormatToValueSourceKind):
+ (JSC::DFG::valueSourceKindToDataFormat):
+ (JSC::DFG::ValueSource::forFlushFormat):
+ (JSC::DFG::ValueSource::valueRecovery):
+ * dfg/DFGVariableAccessData.h:
+ (JSC::DFG::VariableAccessData::shouldUseDoubleFormatAccordingToVote):
+ (JSC::DFG::VariableAccessData::flushFormat):
+ * ftl/FTLCArgumentGetter.cpp:
+ (JSC::FTL::CArgumentGetter::loadNextAndBox):
+ * ftl/FTLCArgumentGetter.h:
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLExitValue.cpp:
+ (JSC::FTL::ExitValue::dumpInContext):
+ * ftl/FTLExitValue.h:
+ * ftl/FTLIntrinsicRepository.h:
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::createPhiVariables):
+ (JSC::FTL::LowerDFGToLLVM::compileNode):
+ (JSC::FTL::LowerDFGToLLVM::compileUpsilon):
+ (JSC::FTL::LowerDFGToLLVM::compilePhi):
+ (JSC::FTL::LowerDFGToLLVM::compileSetLocal):
+ (JSC::FTL::LowerDFGToLLVM::compileAdd):
+ (JSC::FTL::LowerDFGToLLVM::compileArithSub):
+ (JSC::FTL::LowerDFGToLLVM::compileArithMul):
+ (JSC::FTL::LowerDFGToLLVM::compileArithNegate):
+ (JSC::FTL::LowerDFGToLLVM::compilePutByVal):
+ (JSC::FTL::LowerDFGToLLVM::compileCompareEq):
+ (JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq):
+ (JSC::FTL::LowerDFGToLLVM::compileCompareLess):
+ (JSC::FTL::LowerDFGToLLVM::compileCompareLessEq):
+ (JSC::FTL::LowerDFGToLLVM::compileCompareGreater):
+ (JSC::FTL::LowerDFGToLLVM::compileCompareGreaterEq):
+ (JSC::FTL::LowerDFGToLLVM::lowInt32):
+ (JSC::FTL::LowerDFGToLLVM::lowCell):
+ (JSC::FTL::LowerDFGToLLVM::lowBoolean):
+ (JSC::FTL::LowerDFGToLLVM::lowDouble):
+ (JSC::FTL::LowerDFGToLLVM::lowJSValue):
+ (JSC::FTL::LowerDFGToLLVM::speculateRealNumber):
+ (JSC::FTL::LowerDFGToLLVM::initializeOSRExitStateForBlock):
+ (JSC::FTL::LowerDFGToLLVM::emitOSRExitCall):
+ (JSC::FTL::LowerDFGToLLVM::addExitArgumentForNode):
+ (JSC::FTL::LowerDFGToLLVM::setInt32):
+ * ftl/FTLOSRExitCompiler.cpp:
+ (JSC::FTL::compileStub):
+ * ftl/FTLOutput.h:
+ (JSC::FTL::Output::mulWithOverflow32):
+ * ftl/FTLValueFormat.cpp:
+ (WTF::printInternal):
+ * ftl/FTLValueFormat.h:
+ * ftl/FTLValueSource.cpp:
+ (JSC::FTL::ValueSource::dump):
+ * ftl/FTLValueSource.h:
+ * interpreter/Register.h:
+ * runtime/Arguments.cpp:
+ (JSC::Arguments::tearOffForInlineCallFrame):
+ * runtime/IndexingType.cpp:
+ (JSC::leastUpperBoundOfIndexingTypeAndType):
+ * runtime/JSCJSValue.h:
+ * runtime/JSCJSValueInlines.h:
+
2013-09-17 Filip Pizlo <fpizlo@apple.com>
Unreviewed, fix 32-bit build.
m_assembler.shlq_i8r(imm.m_value, dest);
}
- void rshift64(TrustedImm32 imm, RegisterID dest)
- {
- m_assembler.sarq_i8r(imm.m_value, dest);
- }
-
- void mul64(RegisterID src, RegisterID dest)
- {
- m_assembler.imulq_rr(src, dest);
- }
-
void neg64(RegisterID dest)
{
m_assembler.negq_r(dest);
return Jump(m_assembler.jCC(x86Condition(cond)));
}
- Jump branchMul64(ResultCondition cond, RegisterID src, RegisterID dest)
- {
- mul64(src, dest);
- if (cond != Overflow)
- m_assembler.testq_rr(dest, dest);
- return Jump(m_assembler.jCC(x86Condition(cond)));
- }
-
Jump branchSub64(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
{
sub64(imm, dest);
return branchSub64(cond, src2, dest);
}
- Jump branchNeg64(ResultCondition cond, RegisterID srcDest)
- {
- neg64(srcDest);
- return Jump(m_assembler.jCC(x86Condition(cond)));
- }
-
ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
{
ConvertibleLoadLabel result = ConvertibleLoadLabel(this);
return MacroAssemblerX86Common::branchTest8(cond, Address(scratchRegister), mask);
}
- void convertInt64ToDouble(RegisterID src, FPRegisterID dest)
- {
- m_assembler.cvtsi2sdq_rr(src, dest);
- }
-
static bool supportsFloatingPoint() { return true; }
// See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
static bool supportsFloatingPointTruncate() { return true; }
m_formatter.immediate8(imm);
}
}
-#endif // CPU(X86_64)
+#endif
void imull_rr(RegisterID src, RegisterID dst)
{
m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src);
}
-#if CPU(X86_64)
- void imulq_rr(RegisterID src, RegisterID dst)
- {
- m_formatter.twoByteOp64(OP2_IMUL_GvEv, dst, src);
- }
-#endif // CPU(X86_64)
-
void imull_mr(int offset, RegisterID base, RegisterID dst)
{
m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, base, offset);
m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
}
-#if CPU(X86_64)
- void cvtsi2sdq_rr(RegisterID src, XMMRegisterID dst)
- {
- m_formatter.prefix(PRE_SSE_F2);
- m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
- }
-#endif
-
void cvtsi2sd_mr(int offset, RegisterID base, XMMRegisterID dst)
{
m_formatter.prefix(PRE_SSE_F2);
enum DataFormat {
DataFormatNone = 0,
DataFormatInt32 = 1,
- DataFormatInt52 = 2, // Int52's are left-shifted by 16 by default.
- DataFormatStrictInt52 = 3, // "Strict" Int52 means it's not shifted.
- DataFormatDouble = 4,
- DataFormatBoolean = 5,
- DataFormatCell = 6,
- DataFormatStorage = 7,
+ DataFormatDouble = 2,
+ DataFormatBoolean = 3,
+ DataFormatCell = 4,
+ DataFormatStorage = 5,
DataFormatJS = 8,
DataFormatJSInt32 = DataFormatJS | DataFormatInt32,
DataFormatJSDouble = DataFormatJS | DataFormatDouble,
return "None";
case DataFormatInt32:
return "Int32";
- case DataFormatInt52:
- return "Int52";
- case DataFormatStrictInt52:
- return "StrictInt52";
case DataFormatDouble:
return "Double";
case DataFormatCell:
return "Overflow";
case NegativeZero:
return "NegativeZero";
- case Int52Overflow:
- return "Int52Overflow";
+ case Int48Overflow:
+ return "Int48Overflow";
case StoreToHole:
return "StoreToHole";
case LoadFromHole:
BadIndexingType, // We exited because an indexing type was wrong.
Overflow, // We exited because of overflow.
NegativeZero, // We exited because we encountered negative zero.
- Int52Overflow, // We exited because of an Int52 overflow.
+ Int48Overflow, // We exited because of an Int48 overflow.
StoreToHole, // We had a store to a hole.
LoadFromHole, // We had a load from a hole.
OutOfBounds, // We had an out-of-bounds access to an array.
for (size_t localIndex = 0; localIndex < numberOfLocals(); ++localIndex) {
if (Traits::isEmptyForDump(local(localIndex)))
continue;
- out.print(comma, "loc", localIndex, ":", inContext(local(localIndex), context));
+ out.print(comma, "r", localIndex, ":", inContext(local(localIndex), context));
}
}
}
if (value & SpecInt32)
- myOut.print("Int32");
+ myOut.print("Int");
else
isTop = false;
- if (value & SpecInt52)
- myOut.print("Int52");
-
if ((value & SpecDouble) == SpecDouble)
myOut.print("Double");
else {
- if (value & SpecInt52AsDouble)
- myOut.print("Int52asdouble");
+ if (value & SpecInt48AsDouble)
+ myOut.print("Int48asdouble");
+ else
+ isTop = false;
+
+ if (value & SpecInt48)
+ myOut.print("Int48");
else
isTop = false;
return "<Cell>";
if (isInt32Speculation(prediction))
return "<Int32>";
- if (isInt52AsDoubleSpeculation(prediction))
- return "<Int52AsDouble>";
- if (isInt52Speculation(prediction))
- return "<Int52>";
- if (isMachineIntSpeculation(prediction))
- return "<MachineInt>";
+ if (isInt48AsDoubleSpeculation(prediction))
+ return "<Int48AsDouble>";
+ if (isInt48Speculation(prediction))
+ return "<Int48>";
if (isDoubleSpeculation(prediction))
return "<Double>";
- if (isFullNumberSpeculation(prediction))
+ if (isNumberSpeculation(prediction))
return "<Number>";
if (isBooleanSpeculation(prediction))
return "<Boolean>";
return SpecInt32;
if (value.isDouble()) {
double number = value.asNumber();
- if (number != number)
- return SpecDoubleNaN;
- if (value.isMachineInt())
- return SpecInt52AsDouble;
- return SpecNonIntAsDouble;
+ if (number == number) {
+ int64_t asInt64 = static_cast<int64_t>(number);
+ if (asInt64 == number && (asInt64 || !std::signbit(number))
+ && asInt64 < (static_cast<int64_t>(1) << 47)
+ && asInt64 >= -(static_cast<int64_t>(1) << 47)) {
+ return SpecInt48AsDouble;
+ }
+ return SpecNonIntAsDouble;
+ }
+ return SpecDoubleNaN;
}
if (value.isCell())
return speculationFromCell(value.asCell());
class Structure;
typedef uint32_t SpeculatedType;
-static const SpeculatedType SpecNone = 0x00000000; // We don't know anything yet.
-static const SpeculatedType SpecFinalObject = 0x00000001; // It's definitely a JSFinalObject.
-static const SpeculatedType SpecArray = 0x00000002; // It's definitely a JSArray.
-static const SpeculatedType SpecFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses.
-static const SpeculatedType SpecInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses.
-static const SpeculatedType SpecInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses.
-static const SpeculatedType SpecInt32Array = 0x00000040; // It's definitely an Int32Array or one of its subclasses.
-static const SpeculatedType SpecUint8Array = 0x00000080; // It's definitely an Uint8Array or one of its subclasses.
-static const SpeculatedType SpecUint8ClampedArray = 0x00000100; // It's definitely an Uint8ClampedArray or one of its subclasses.
-static const SpeculatedType SpecUint16Array = 0x00000200; // It's definitely an Uint16Array or one of its subclasses.
-static const SpeculatedType SpecUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses.
-static const SpeculatedType SpecFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses.
-static const SpeculatedType SpecFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses.
-static const SpeculatedType SpecTypedArrayView = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array;
-static const SpeculatedType SpecArguments = 0x00002000; // It's definitely an Arguments object.
-static const SpeculatedType SpecStringObject = 0x00004000; // It's definitely a StringObject.
-static const SpeculatedType SpecObjectOther = 0x00008000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
-static const SpeculatedType SpecObject = 0x0000ffff; // Bitmask used for testing for any kind of object prediction.
-static const SpeculatedType SpecStringIdent = 0x00010000; // It's definitely a JSString, and it's an identifier.
-static const SpeculatedType SpecStringVar = 0x00020000; // It's definitely a JSString, and it's not an identifier.
-static const SpeculatedType SpecString = 0x00030000; // It's definitely a JSString.
-static const SpeculatedType SpecCellOther = 0x00040000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
-static const SpeculatedType SpecCell = 0x0007ffff; // It's definitely a JSCell.
-static const SpeculatedType SpecInt32 = 0x00800000; // It's definitely an Int32.
-static const SpeculatedType SpecInt52 = 0x01000000; // It's definitely an Int52 and we intend it to unbox it.
-static const SpeculatedType SpecMachineInt = 0x01800000; // It's something that we can do machine int arithmetic on.
-static const SpeculatedType SpecInt52AsDouble = 0x02000000; // It's definitely an Int52 and it's inside a double.
-static const SpeculatedType SpecInteger = 0x03800000; // It's definitely some kind of integer.
-static const SpeculatedType SpecNonIntAsDouble = 0x04000000; // It's definitely not an Int52 but it's a real number and it's a double.
-static const SpeculatedType SpecDoubleReal = 0x06000000; // It's definitely a non-NaN double.
-static const SpeculatedType SpecDoubleNaN = 0x08000000; // It's definitely a NaN.
-static const SpeculatedType SpecDouble = 0x0e000000; // It's either a non-NaN or a NaN double.
-static const SpeculatedType SpecBytecodeRealNumber = 0x06800000; // It's either an Int32 or a DoubleReal.
-static const SpeculatedType SpecFullRealNumber = 0x07800000; // It's either an Int32 or a DoubleReal, or a Int52.
-static const SpeculatedType SpecBytecodeNumber = 0x0e800000; // It's either an Int32 or a Double.
-static const SpeculatedType SpecFullNumber = 0x0f800000; // It's either an Int32, Int52, or a Double.
-static const SpeculatedType SpecBoolean = 0x10000000; // It's definitely a Boolean.
-static const SpeculatedType SpecOther = 0x20000000; // It's definitely none of the above.
-static const SpeculatedType SpecHeapTop = 0x3effffff; // It can be any of the above, except for SpecInt52.
-static const SpeculatedType SpecEmpty = 0x40000000; // It's definitely an empty value marker.
-static const SpeculatedType SpecBytecodeTop = 0x7effffff; // It can be any of the above, except for SpecInt52.
-static const SpeculatedType SpecFullTop = 0x7fffffff; // It can be any of the above plus anything the DFG chooses.
+static const SpeculatedType SpecNone = 0x00000000; // We don't know anything yet.
+static const SpeculatedType SpecFinalObject = 0x00000001; // It's definitely a JSFinalObject.
+static const SpeculatedType SpecArray = 0x00000002; // It's definitely a JSArray.
+static const SpeculatedType SpecFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses.
+static const SpeculatedType SpecInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses.
+static const SpeculatedType SpecInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses.
+static const SpeculatedType SpecInt32Array = 0x00000040; // It's definitely an Int32Array or one of its subclasses.
+static const SpeculatedType SpecUint8Array = 0x00000080; // It's definitely an Uint8Array or one of its subclasses.
+static const SpeculatedType SpecUint8ClampedArray = 0x00000100; // It's definitely an Uint8ClampedArray or one of its subclasses.
+static const SpeculatedType SpecUint16Array = 0x00000200; // It's definitely an Uint16Array or one of its subclasses.
+static const SpeculatedType SpecUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses.
+static const SpeculatedType SpecFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses.
+static const SpeculatedType SpecFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses.
+static const SpeculatedType SpecTypedArrayView = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array;
+static const SpeculatedType SpecArguments = 0x00002000; // It's definitely an Arguments object.
+static const SpeculatedType SpecStringObject = 0x00004000; // It's definitely a StringObject.
+static const SpeculatedType SpecObjectOther = 0x00008000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
+static const SpeculatedType SpecObject = 0x0000ffff; // Bitmask used for testing for any kind of object prediction.
+static const SpeculatedType SpecStringIdent = 0x00010000; // It's definitely a JSString, and it's an identifier.
+static const SpeculatedType SpecStringVar = 0x00020000; // It's definitely a JSString, and it's not an identifier.
+static const SpeculatedType SpecString = 0x00030000; // It's definitely a JSString.
+static const SpeculatedType SpecCellOther = 0x00040000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
+static const SpeculatedType SpecCell = 0x0007ffff; // It's definitely a JSCell.
+static const SpeculatedType SpecInt32 = 0x00800000; // It's definitely an Int32.
+static const SpeculatedType SpecInt48 = 0x01000000; // It's definitely an Int48, it's inside a double, but it doesn't need to be.
+static const SpeculatedType SpecMachineInt = 0x01800000; // It's something that we can do machine int arithmetic on.
+static const SpeculatedType SpecInt48AsDouble = 0x02000000; // It's definitely an Int48 and it's inside a double.
+static const SpeculatedType SpecInteger = 0x03800000; // It's definitely some kind of integer.
+static const SpeculatedType SpecNonIntAsDouble = 0x04000000; // It's definitely not an Int48 but it's a real number and it's a double.
+static const SpeculatedType SpecDoubleReal = 0x07000000; // It's definitely a non-NaN double.
+static const SpeculatedType SpecDoubleNaN = 0x08000000; // It's definitely a NaN.
+static const SpeculatedType SpecDouble = 0x0f000000; // It's either a non-NaN or a NaN double.
+static const SpeculatedType SpecRealNumber = 0x07800000; // It's either an Int32 or a DoubleReal.
+static const SpeculatedType SpecNumber = 0x0f800000; // It's either an Int32 or a Double.
+static const SpeculatedType SpecBoolean = 0x10000000; // It's definitely a Boolean.
+static const SpeculatedType SpecOther = 0x20000000; // It's definitely none of the above.
+static const SpeculatedType SpecHeapTop = 0x3fffffff; // It can be any of the above.
+static const SpeculatedType SpecEmpty = 0x40000000; // It's definitely an empty value marker.
+static const SpeculatedType SpecBytecodeTop = 0x7fffffff; // It can be any of the above.
+static const SpeculatedType SpecFullTop = 0x7fffffff; // It can be any of the above plus anything the DFG chooses.
typedef bool (*SpeculatedTypeChecker)(SpeculatedType);
inline bool isInt32SpeculationForArithmetic(SpeculatedType value)
{
- return !(value & (SpecDouble | SpecInt52));
+ return !(value & SpecDouble);
}
inline bool isInt32SpeculationExpectingDefined(SpeculatedType value)
return isInt32Speculation(value & ~SpecOther);
}
-inline bool isInt52Speculation(SpeculatedType value)
+inline bool isInt48Speculation(SpeculatedType value)
{
- return value == SpecInt52;
+ return value == SpecInt48;
}
inline bool isMachineIntSpeculation(SpeculatedType value)
inline bool isMachineIntSpeculationForArithmetic(SpeculatedType value)
{
- return !(value & SpecDouble);
+ return !(value & (SpecDouble & ~SpecMachineInt));
}
-inline bool isInt52AsDoubleSpeculation(SpeculatedType value)
+inline bool isInt48AsDoubleSpeculation(SpeculatedType value)
{
- return value == SpecInt52AsDouble;
+ return value == SpecInt48AsDouble;
}
inline bool isIntegerSpeculation(SpeculatedType value)
return !!(value & SpecDouble);
}
-inline bool isBytecodeRealNumberSpeculation(SpeculatedType value)
-{
- return !!(value & SpecBytecodeRealNumber) && !(value & ~SpecBytecodeRealNumber);
-}
-
-inline bool isFullRealNumberSpeculation(SpeculatedType value)
-{
- return !!(value & SpecFullRealNumber) && !(value & ~SpecFullRealNumber);
-}
-
-inline bool isBytecodeNumberSpeculation(SpeculatedType value)
-{
- return !!(value & SpecBytecodeNumber) && !(value & ~SpecBytecodeNumber);
-}
-
-inline bool isFullNumberSpeculation(SpeculatedType value)
+inline bool isRealNumberSpeculation(SpeculatedType value)
{
- return !!(value & SpecFullNumber) && !(value & ~SpecFullNumber);
+ return !!(value & SpecRealNumber) && !(value & ~SpecRealNumber);
}
-inline bool isBytecodeNumberSpeculationExpectingDefined(SpeculatedType value)
+inline bool isNumberSpeculation(SpeculatedType value)
{
- return isBytecodeNumberSpeculation(value & ~SpecOther);
+ return !!(value & SpecNumber) && !(value & ~SpecNumber);
}
-inline bool isFullNumberSpeculationExpectingDefined(SpeculatedType value)
+inline bool isNumberSpeculationExpectingDefined(SpeculatedType value)
{
- return isFullNumberSpeculation(value & ~SpecOther);
+ return isNumberSpeculation(value & ~SpecOther);
}
inline bool isBooleanSpeculation(SpeculatedType value)
AlreadyInJSStack,
// It's already in the stack but unboxed.
AlreadyInJSStackAsUnboxedInt32,
- AlreadyInJSStackAsUnboxedInt52,
AlreadyInJSStackAsUnboxedCell,
AlreadyInJSStackAsUnboxedBoolean,
AlreadyInJSStackAsUnboxedDouble,
// It's in a register.
InGPR,
UnboxedInt32InGPR,
- UnboxedInt52InGPR,
- UnboxedStrictInt52InGPR,
UnboxedBooleanInGPR,
#if USE(JSVALUE32_64)
InPair,
DisplacedInJSStack,
// It's in the stack, at a different location, and it's unboxed.
Int32DisplacedInJSStack,
- Int52DisplacedInJSStack,
- StrictInt52DisplacedInJSStack,
DoubleDisplacedInJSStack,
CellDisplacedInJSStack,
BooleanDisplacedInJSStack,
return result;
}
- static ValueRecovery alreadyInJSStackAsUnboxedInt52()
- {
- ValueRecovery result;
- result.m_technique = AlreadyInJSStackAsUnboxedInt52;
- return result;
- }
-
static ValueRecovery alreadyInJSStackAsUnboxedCell()
{
ValueRecovery result;
ValueRecovery result;
if (dataFormat == DataFormatInt32)
result.m_technique = UnboxedInt32InGPR;
- else if (dataFormat == DataFormatInt52)
- result.m_technique = UnboxedInt52InGPR;
- else if (dataFormat == DataFormatStrictInt52)
- result.m_technique = UnboxedStrictInt52InGPR;
else if (dataFormat == DataFormatBoolean)
result.m_technique = UnboxedBooleanInGPR;
else
result.m_technique = Int32DisplacedInJSStack;
break;
- case DataFormatInt52:
- result.m_technique = Int52DisplacedInJSStack;
- break;
-
- case DataFormatStrictInt52:
- result.m_technique = StrictInt52DisplacedInJSStack;
- break;
-
case DataFormatDouble:
result.m_technique = DoubleDisplacedInJSStack;
break;
switch (technique()) {
case AlreadyInJSStack:
case AlreadyInJSStackAsUnboxedInt32:
- case AlreadyInJSStackAsUnboxedInt52:
case AlreadyInJSStackAsUnboxedCell:
case AlreadyInJSStackAsUnboxedBoolean:
case AlreadyInJSStackAsUnboxedDouble:
MacroAssembler::RegisterID gpr() const
{
- ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR || m_technique == UnboxedInt52InGPR || m_technique == UnboxedStrictInt52InGPR);
+ ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR);
return m_source.gpr;
}
VirtualRegister virtualRegister() const
{
- ASSERT(m_technique == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack || m_technique == Int52DisplacedInJSStack || m_technique == StrictInt52DisplacedInJSStack);
+ ASSERT(m_technique == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack);
return m_source.virtualReg;
}
case AlreadyInJSStackAsUnboxedInt32:
out.printf("(int32)");
return;
- case AlreadyInJSStackAsUnboxedInt52:
- out.printf("(int52)");
- return;
case AlreadyInJSStackAsUnboxedCell:
out.printf("(cell)");
return;
case UnboxedInt32InGPR:
out.printf("int32(%%r%d)", gpr());
return;
- case UnboxedInt52InGPR:
- out.printf("int52(%%r%d)", gpr());
- return;
- case UnboxedStrictInt52InGPR:
- out.printf("strictInt52(%%r%d)", gpr());
- return;
case UnboxedBooleanInGPR:
out.printf("bool(%%r%d)", gpr());
return;
case Int32DisplacedInJSStack:
out.printf("*int32(%d)", virtualRegister());
return;
- case Int52DisplacedInJSStack:
- out.printf("*int52(%d)", virtualRegister());
- return;
- case StrictInt52DisplacedInJSStack:
- out.printf("*strictInt52(%d)", virtualRegister());
- return;
case DoubleDisplacedInJSStack:
out.printf("*double(%d)", virtualRegister());
return;
bool needsTypeCheck(Node* node, SpeculatedType typesPassedThrough)
{
- return !forNode(node).isType(typesPassedThrough);
+ return forNode(node).m_type & ~typesPassedThrough;
}
bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough)
ALWAYS_INLINE void filterByType(Node* node, Edge& edge, SpeculatedType type)
{
AbstractValue& value = forNode(edge);
- if (!value.isType(type)) {
+ if (value.m_type & ~type) {
node->setCanExit(true);
edge.setProofStatus(NeedsCheck);
} else
break;
}
- case Int52ToDouble: {
- JSValue child = forNode(node->child1()).value();
- if (child && child.isNumber()) {
- setConstant(node, child);
- break;
- }
- forNode(node).setType(SpecDouble);
- break;
- }
-
- case Int52ToValue: {
- JSValue child = forNode(node->child1()).value();
- if (child && child.isNumber()) {
- setConstant(node, child);
- break;
- }
- SpeculatedType type = forNode(node->child1()).m_type;
- if (type & SpecInt52)
- type = (type | SpecInt32 | SpecInt52AsDouble) & ~SpecInt52;
- forNode(node).setType(type);
- break;
- }
-
case ValueAdd:
case ArithAdd: {
JSValue left = forNode(node->child1()).value();
if (!bytecodeCanTruncateInteger(node->arithNodeFlags()))
node->setCanExit(true);
break;
- case MachineIntUse:
- forNode(node).setType(SpecInt52);
- if (!forNode(node->child1()).isType(SpecInt32)
- || !forNode(node->child2()).isType(SpecInt32))
- node->setCanExit(true);
- break;
case NumberUse:
- if (isFullRealNumberSpeculation(forNode(node->child1()).m_type)
- && isFullRealNumberSpeculation(forNode(node->child2()).m_type))
+ if (isRealNumberSpeculation(forNode(node->child1()).m_type)
+ && isRealNumberSpeculation(forNode(node->child2()).m_type))
forNode(node).setType(SpecDoubleReal);
else
forNode(node).setType(SpecDouble);
default:
RELEASE_ASSERT(node->op() == ValueAdd);
clobberWorld(node->codeOrigin, clobberLimit);
- forNode(node).setType(SpecString | SpecBytecodeNumber);
+ forNode(node).setType(SpecString | SpecInt32 | SpecNumber);
break;
}
break;
if (!bytecodeCanTruncateInteger(node->arithNodeFlags()))
node->setCanExit(true);
break;
- case MachineIntUse:
- forNode(node).setType(SpecInt52);
- if (!forNode(node->child1()).isType(SpecInt32)
- || !forNode(node->child2()).isType(SpecInt32))
- node->setCanExit(true);
- break;
case NumberUse:
forNode(node).setType(SpecDouble);
break;
if (!bytecodeCanTruncateInteger(node->arithNodeFlags()))
node->setCanExit(true);
break;
- case MachineIntUse:
- forNode(node).setType(SpecInt52);
- if (m_state.forNode(node->child1()).couldBeType(SpecInt52))
- node->setCanExit(true);
- if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
- node->setCanExit(true);
- break;
case NumberUse:
forNode(node).setType(SpecDouble);
break;
|| !bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
node->setCanExit(true);
break;
- case MachineIntUse:
- forNode(node).setType(SpecInt52);
- node->setCanExit(true);
- break;
case NumberUse:
- if (isFullRealNumberSpeculation(forNode(node->child1()).m_type)
- || isFullRealNumberSpeculation(forNode(node->child2()).m_type))
+ if (isRealNumberSpeculation(forNode(node->child1()).m_type)
+ || isRealNumberSpeculation(forNode(node->child2()).m_type))
forNode(node).setType(SpecDoubleReal);
else
forNode(node).setType(SpecDouble);
break;
}
- if (isFullNumberSpeculation(abstractChild.m_type)) {
+ if (isNumberSpeculation(abstractChild.m_type)) {
setConstant(node, vm->smallStrings.numberString());
break;
}
case Array::Uint32Array:
if (node->shouldSpeculateInt32())
forNode(node).setType(SpecInt32);
- else if (enableInt52() && node->shouldSpeculateMachineInt())
- forNode(node).setType(SpecInt52);
else
forNode(node).setType(SpecDouble);
break;
case ArrayPush:
node->setCanExit(true);
clobberWorld(node->codeOrigin, clobberLimit);
- forNode(node).setType(SpecBytecodeNumber);
+ forNode(node).setType(SpecNumber);
break;
case ArrayPop:
// NB. The more canonical way of writing this would have been:
//
// destination = source;
- // if (destination.m_type & !(SpecFullNumber | SpecString | SpecBoolean)) {
- // destination.filter(SpecFullNumber | SpecString | SpecBoolean);
+ // if (destination.m_type & !(SpecNumber | SpecString | SpecBoolean)) {
+ // destination.filter(SpecNumber | SpecString | SpecBoolean);
// AbstractValue string;
// string.set(vm->stringStructure);
// destination.merge(string);
clobberWorld(node->codeOrigin, clobberLimit);
SpeculatedType type = source.m_type;
- if (type & ~(SpecFullNumber | SpecString | SpecBoolean))
+ if (type & ~(SpecNumber | SpecString | SpecBoolean))
type = (SpecHeapTop & ~SpecCell) | SpecString;
destination.setType(type);
}
m_type = speculationFromValue(value);
- if (m_type == SpecInt52AsDouble)
- m_type = SpecInt52;
m_value = value;
checkConsistency();
return result;
}
-#if !ASSERT_DISABLED
void AbstractValue::checkConsistency() const
{
if (!(m_type & SpecCell)) {
if (isClear())
ASSERT(!m_value);
- if (!!m_value) {
- SpeculatedType type = m_type;
- if (type & SpecInt52)
- type |= SpecInt52AsDouble;
- ASSERT(mergeSpeculations(type, speculationFromValue(m_value)) == type);
- }
+ if (!!m_value)
+ ASSERT(mergeSpeculations(m_type, speculationFromValue(m_value)) == m_type);
// Note that it's possible for a prediction like (Final, []). This really means that
// the value is bottom and that any code that uses the value is unreachable. But
// we don't want to get pedantic about this as it would only increase the computational
// complexity of the code.
}
-#endif
void AbstractValue::dump(PrintStream& out) const
{
checkConsistency();
}
- bool couldBeType(SpeculatedType desiredType)
- {
- return !!(m_type & desiredType);
- }
-
- bool isType(SpeculatedType desiredType)
- {
- return !(m_type & ~desiredType);
- }
-
FiltrationResult filter(Graph&, const StructureSet&);
FiltrationResult filterArrayModes(ArrayModes arrayModes);
FiltrationResult filterByValue(JSValue value);
+ bool validateType(JSValue value) const
+ {
+ if (isHeapTop())
+ return true;
+
+ if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)
+ return false;
+
+ if (value.isEmpty()) {
+ ASSERT(m_type & SpecEmpty);
+ return true;
+ }
+
+ return true;
+ }
+
bool validate(JSValue value) const
{
if (isHeapTop())
|| !arrayModesAreClearOrTop(m_arrayModes);
}
-#if ASSERT_DISABLED
- void checkConsistency() const { }
-#else
void checkConsistency() const;
-#endif
void dumpInContext(PrintStream&, DumpContext*) const;
void dump(PrintStream&) const;
m_arrayModes = ALL_ARRAY_MODES;
}
- bool validateType(JSValue value) const
- {
- if (isHeapTop())
- return true;
-
- // Constant folding always represents Int52's in a double (i.e. Int52AsDouble).
- // So speculationFromValue(value) for an Int52 value will return Int52AsDouble,
- // and that's fine - the type validates just fine.
- SpeculatedType type = m_type;
- if (type & SpecInt52)
- type |= SpecInt52AsDouble;
-
- if (mergeSpeculations(type, speculationFromValue(value)) != type)
- return false;
-
- if (value.isEmpty()) {
- ASSERT(m_type & SpecEmpty);
- return true;
- }
-
- return true;
- }
-
void makeTop(SpeculatedType top)
{
m_type |= top;
return withType(Array::ForceExit);
if (isInt32Speculation(value))
return withTypeAndConversion(Array::Int32, Array::Convert);
- if (isFullNumberSpeculation(value))
+ if (isNumberSpeculation(value))
return withTypeAndConversion(Array::Double, Array::Convert);
return withTypeAndConversion(Array::Contiguous, Array::Convert);
case Array::Int32:
if (!value || isInt32Speculation(value))
return *this;
- if (isFullNumberSpeculation(value))
+ if (isNumberSpeculation(value))
return withTypeAndConversion(Array::Double, Array::Convert);
return withTypeAndConversion(Array::Contiguous, Array::Convert);
case Array::Double:
if (flags & NodeBytecodeUsesAsInt)
return withTypeAndConversion(Array::Contiguous, Array::RageConvert);
- if (!value || isFullNumberSpeculation(value))
+ if (!value || isNumberSpeculation(value))
return *this;
return withTypeAndConversion(Array::Contiguous, Array::Convert);
move64ToDouble(gpr, fpr);
return fpr;
}
-
- void boxInt52(GPRReg source, GPRReg target, GPRReg scratch, FPRReg fpScratch)
- {
- // Is it an int32?
- signExtend32ToPtr(source, scratch);
- Jump isInt32 = branch64(Equal, source, scratch);
-
- // Nope, it's not, but regT0 contains the int64 value.
- convertInt64ToDouble(source, fpScratch);
- boxDouble(fpScratch, target);
- Jump done = jump();
-
- isInt32.link(this);
- zeroExtend32ToPtr(source, target);
- or64(GPRInfo::tagTypeNumberRegister, target);
-
- done.link(this);
- }
#endif
#if USE(JSVALUE32_64)
case UInt32ToNumber:
case ArithAdd:
case ArithSub:
+ case ArithNegate:
case ValueAdd:
case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double.
node->mergeFlags(NodeMayOverflow);
break;
- case ArithNegate:
- // Currently we can't tell the difference between a negation overflowing
- // (i.e. -(1 << 31)) or generating negative zero (i.e. -0). If it took slow
- // path then we assume that it did both of those things.
- node->mergeFlags(NodeMayOverflow);
- node->mergeFlags(NodeMayNegZero);
- break;
-
case ArithMul:
if (m_inlineStackTop->m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex)
|| m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)) {
private:
+ Node* canonicalize(Node* node)
+ {
+ if (!node)
+ return 0;
+
+ if (node->op() == ValueToInt32)
+ node = node->child1().node();
+
+ return node;
+ }
+ Node* canonicalize(Edge edge)
+ {
+ return canonicalize(edge.node());
+ }
+
unsigned endIndexForPureCSE()
{
unsigned result = m_lastSeen[m_currentNode->op()];
Node* pureCSE(Node* node)
{
- Edge child1 = node->child1();
- Edge child2 = node->child2();
- Edge child3 = node->child3();
+ Node* child1 = canonicalize(node->child1());
+ Node* child2 = canonicalize(node->child2());
+ Node* child3 = canonicalize(node->child3());
for (unsigned i = endIndexForPureCSE(); i--;) {
Node* otherNode = m_currentBlock->at(i);
if (node->arithNodeFlags() != otherNode->arithNodeFlags())
continue;
- Edge otherChild = otherNode->child1();
+ Node* otherChild = canonicalize(otherNode->child1());
if (!otherChild)
return otherNode;
if (otherChild != child1)
continue;
- otherChild = otherNode->child2();
+ otherChild = canonicalize(otherNode->child2());
if (!otherChild)
return otherNode;
if (otherChild != child2)
continue;
- otherChild = otherNode->child3();
+ otherChild = canonicalize(otherNode->child3());
if (!otherChild)
return otherNode;
if (otherChild != child3)
{
for (unsigned i = m_indexInBlock; i--;) {
Node* node = m_currentBlock->at(i);
- if (node == child1 || node == child2)
+ if (node == child1 || node == canonicalize(child2))
break;
switch (node->op()) {
case GetByVal:
if (!m_graph.byValIsPure(node))
return 0;
- if (node->child1() == child1 && node->child2() == child2)
+ if (node->child1() == child1 && canonicalize(node->child2()) == canonicalize(child2))
return node;
break;
case PutByVal:
case PutByValAlias: {
if (!m_graph.byValIsPure(node))
return 0;
- if (m_graph.varArgChild(node, 0) == child1 && m_graph.varArgChild(node, 1) == child2)
+ if (m_graph.varArgChild(node, 0) == child1 && canonicalize(m_graph.varArgChild(node, 1)) == canonicalize(child2))
return m_graph.varArgChild(node, 2).node();
// We must assume that the PutByVal will clobber the location we're getting from.
// FIXME: We can do better; if we know that the PutByVal is accessing an array of a
case CompareEqConstant:
case ValueToInt32:
case MakeRope:
- case Int52ToDouble:
- case Int52ToValue:
if (cseMode == StoreElimination)
break;
setReplacement(pureCSE(node));
case LogicalNot:
case Int32ToDouble:
case ExtractOSREntryLocal:
- case Int52ToDouble:
- case Int52ToValue:
return;
case MovHintAndCheck:
switch (node->binaryUseKind()) {
case Int32Use:
case NumberUse:
- case MachineIntUse:
return;
case UntypedUse:
read(World);
#endif
}
-inline bool enableInt52()
-{
-#if USE(JSVALUE64)
- return true;
-#else
- return false;
-#endif
-}
-
enum SpillRegistersMode { NeedToSpill, DontSpill };
enum NoResultTag { NoResult };
fixupSetLocalsInBlock(m_graph.block(blockIndex));
}
- for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
- fixupUntypedSetLocalsInBlock(m_graph.block(blockIndex));
-
return true;
}
switch (op) {
case SetLocal: {
// This gets handled by fixupSetLocalsInBlock().
- return;
+ break;
}
case BitAnd:
break;
}
- if (node->child1()->shouldSpeculateMachineInt()) {
- fixEdge<MachineIntUse>(node->child1());
- break;
- }
-
if (node->child1()->shouldSpeculateNumber()) {
fixEdge<NumberUse>(node->child1());
break;
fixEdge<Int32Use>(node->child1());
break;
}
- if (m_graph.negateShouldSpeculateMachineInt(node)) {
- fixEdge<MachineIntUse>(node->child1());
- break;
- }
fixEdge<NumberUse>(node->child1());
break;
}
fixEdge<Int32Use>(node->child2());
break;
}
- if (m_graph.mulShouldSpeculateMachineInt(node)) {
- fixEdge<MachineIntUse>(node->child1());
- fixEdge<MachineIntUse>(node->child2());
- break;
- }
fixEdge<NumberUse>(node->child1());
fixEdge<NumberUse>(node->child2());
break;
fixEdge<Int32Use>(node->child2());
break;
}
- if (enableInt52()
- && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
- fixEdge<MachineIntUse>(node->child1());
- fixEdge<MachineIntUse>(node->child2());
- break;
- }
if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
fixEdge<NumberUse>(node->child1());
fixEdge<NumberUse>(node->child2());
fixEdge<Int32Use>(node->child2());
break;
}
- if (enableInt52()
- && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
- fixEdge<MachineIntUse>(node->child1());
- fixEdge<MachineIntUse>(node->child2());
- break;
- }
if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
fixEdge<NumberUse>(node->child1());
fixEdge<NumberUse>(node->child2());
fixEdge<KnownCellUse>(child1);
fixEdge<Int32Use>(child2);
fixEdge<Int32Use>(child3);
- if (child3->prediction() & SpecInt52)
- fixEdge<MachineIntUse>(child3);
- else
- fixEdge<Int32Use>(child3);
break;
case Array::Double:
fixEdge<KnownCellUse>(child1);
fixEdge<Int32Use>(child2);
if (child3->shouldSpeculateInt32())
fixEdge<Int32Use>(child3);
- else if (child3->shouldSpeculateMachineInt())
- fixEdge<MachineIntUse>(child3);
else
fixEdge<NumberUse>(child3);
break;
case CheckTierUpInLoop:
case CheckTierUpAtReturn:
case CheckTierUpAndOSREnter:
- case Int52ToDouble:
- case Int52ToValue:
RELEASE_ASSERT_NOT_REACHED();
break;
case FlushedInt32:
fixEdge<Int32Use>(node->child1());
break;
- case FlushedInt52:
- fixEdge<MachineIntUse>(node->child1());
- break;
case FlushedCell:
fixEdge<CellUse>(node->child1());
break;
m_insertionSet.execute(block);
}
- void fixupUntypedSetLocalsInBlock(BasicBlock* block)
- {
- if (!block)
- return;
- ASSERT(block->isReachable);
- m_block = block;
- for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
- Node* node = m_currentNode = block->at(m_indexInBlock);
- if (node->op() != SetLocal)
- continue;
-
- if (node->child1().useKind() == UntypedUse)
- fixEdge<UntypedUse>(node->child1());
- }
- m_insertionSet.execute(block);
- }
-
Node* checkArray(ArrayMode arrayMode, const CodeOrigin& codeOrigin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
{
ASSERT(arrayMode.isSpecific());
if (node->op() != GetLocal)
return;
- // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
- // https://bugs.webkit.org/show_bug.cgi?id=121518
-
VariableAccessData* variable = node->variableAccessData();
switch (useKind) {
case Int32Use:
|| isBooleanSpeculation(variable->prediction()))
m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
break;
- case MachineIntUse:
- if (isMachineIntSpeculation(variable->prediction()))
- m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
- break;
case CellUse:
case KnownCellUse:
case ObjectUse:
template<UseKind useKind>
void fixEdge(Edge& edge, SpeculationDirection direction = BackwardSpeculation)
{
- if (isDouble(useKind)) {
- if (edge->shouldSpeculateInt32ForArithmetic()) {
- injectInt32ToDoubleNode(edge, useKind, direction);
- return;
- }
-
- if (enableInt52() && edge->shouldSpeculateMachineInt()) {
- // Make all double uses of int52 values have an intermediate Int52ToDouble.
- // This is for the same reason as Int52ToValue (see below) except that
- // Int8ToDouble will convert int52's that fit in an int32 into a double
- // rather than trying to create a boxed int32 like Int52ToValue does.
-
- Node* result = m_insertionSet.insertNode(
- m_indexInBlock, SpecInt52AsDouble, Int52ToDouble,
- m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
- edge = Edge(result, useKind);
- return;
- }
- }
-
- if (enableInt52() && useKind != MachineIntUse
- && edge->shouldSpeculateMachineInt() && !edge->shouldSpeculateInt32()) {
- // We make all non-int52 uses of int52 values have an intermediate Int52ToValue
- // node to ensure that we handle this properly:
- //
- // a: SomeInt52
- // b: ArithAdd(@a, ...)
- // c: Call(..., @a)
- // d: ArithAdd(@a, ...)
- //
- // Without an intermediate node and just labeling the uses, we will get:
- //
- // a: SomeInt52
- // b: ArithAdd(Int52:@a, ...)
- // c: Call(..., Untyped:@a)
- // d: ArithAdd(Int52:@a, ...)
- //
- // And now the c->Untyped:@a edge will box the value of @a into a double. This
- // is bad, because now the d->Int52:@a edge will either have to do double-to-int
- // conversions, or will have to OSR exit unconditionally. Alternatively we could
- // have the c->Untyped:@a edge box the value by copying rather than in-place.
- // But these boxings are also costly so this wouldn't be great.
- //
- // The solution we use is to always have non-Int52 uses of predicted Int52's use
- // an intervening Int52ToValue node:
- //
- // a: SomeInt52
- // b: ArithAdd(Int52:@a, ...)
- // x: Int52ToValue(Int52:@a)
- // c: Call(..., Untyped:@x)
- // d: ArithAdd(Int52:@a, ...)
- //
- // Note that even if we had multiple non-int52 uses of @a, the multiple
- // Int52ToValue's would get CSE'd together. So the boxing would only happen once.
- // At the same time, @a would continue to be represented as a native int52.
- //
- // An alternative would have been to insert ToNativeInt52 nodes on int52 uses of
- // int52's. This would have handled the above example but would fall over for:
- //
- // a: SomeInt52
- // b: Call(..., @a)
- // c: ArithAdd(@a, ...)
- //
- // But the solution we use handles the above gracefully.
-
- Node* result = m_insertionSet.insertNode(
- m_indexInBlock, SpecInt52, Int52ToValue,
- m_currentNode->codeOrigin, Edge(edge.node(), UntypedUse));
- edge = Edge(result, useKind);
+ if (isDouble(useKind) && edge->shouldSpeculateInt32ForArithmetic()) {
+ injectInt32ToDoubleNode(edge, useKind, direction);
return;
}
observeUseKindOnNode<useKind>(edge.node());
-
edge.setUseKind(useKind);
}
void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation)
{
Node* result = m_insertionSet.insertNode(
- m_indexInBlock, SpecInt52AsDouble, Int32ToDouble,
+ m_indexInBlock, SpecInt48, Int32ToDouble,
m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
if (direction == ForwardSpeculation)
result->mergeFlags(NodeExitsForward);
bool attemptToMakeIntegerAdd(Node* node)
{
AddSpeculationMode mode = m_graph.addSpeculationMode(node);
- if (mode != DontSpeculateInt32) {
- truncateConstantsIfNecessary(node, mode);
- fixEdge<Int32Use>(node->child1());
- fixEdge<Int32Use>(node->child2());
- return true;
- }
-
- if (m_graph.addShouldSpeculateMachineInt(node)) {
- fixEdge<MachineIntUse>(node->child1());
- fixEdge<MachineIntUse>(node->child2());
- return true;
- }
+ if (mode == DontSpeculateInt32)
+ return false;
- return false;
+ truncateConstantsIfNecessary(node, mode);
+ fixEdge<Int32Use>(node->child1());
+ fixEdge<Int32Use>(node->child2());
+ return true;
}
bool attemptToMakeGetArrayLength(Node* node)
case FlushedInt32:
out.print("FlushedInt32");
return;
- case FlushedInt52:
- out.print("FlushedInt52");
- return;
case FlushedDouble:
out.print("FlushedDouble");
return;
enum FlushFormat {
DeadFlush,
FlushedInt32,
- FlushedInt52,
FlushedDouble,
FlushedCell,
FlushedBoolean,
return NodeResultJS;
case FlushedInt32:
return NodeResultInt32;
- case FlushedInt52:
- return NodeResultInt52;
case FlushedDouble:
return NodeResultNumber;
case FlushedBoolean:
return CellUse;
case FlushedInt32:
return Int32Use;
- case FlushedInt52:
- return MachineIntUse;
case FlushedDouble:
return NumberUse;
case FlushedBoolean:
{
initGPR(node, useCount, gpr, DataFormatInt32);
}
- void initInt52(Node* node, uint32_t useCount, GPRReg reg, DataFormat format)
- {
- ASSERT(format == DataFormatInt52 || format == DataFormatStrictInt52);
- initGPR(node, useCount, reg, format);
- }
- void initInt52(Node* node, uint32_t useCount, GPRReg reg)
- {
- initGPR(node, useCount, reg, DataFormatInt52);
- }
- void initStrictInt52(Node* node, uint32_t useCount, GPRReg reg)
- {
- initGPR(node, useCount, reg, DataFormatStrictInt52);
- }
#if USE(JSVALUE64)
void initJSValue(Node* node, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
{
// Get the format of the value as it is spilled in the JSStack (or 'none').
DataFormat spillFormat() { return m_spillFormat; }
- bool isFormat(DataFormat expectedFormat)
- {
- return registerFormat() == expectedFormat || spillFormat() == expectedFormat;
- }
-
bool isJSFormat(DataFormat expectedFormat)
{
return JSC::isJSFormat(registerFormat(), expectedFormat) || JSC::isJSFormat(spillFormat(), expectedFormat);
return isJSFormat(DataFormatJSInt32);
}
- bool isInt52()
- {
- return isFormat(DataFormatInt52);
- }
-
- bool isStrictInt52()
- {
- return isFormat(DataFormatStrictInt52);
- }
-
bool isJSDouble()
{
return isJSFormat(DataFormatJSDouble);
{
fillGPR(stream, gpr, DataFormatInt32);
}
- void fillInt52(VariableEventStream& stream, GPRReg gpr, DataFormat format)
- {
- ASSERT(format == DataFormatInt52 || format == DataFormatStrictInt52);
- fillGPR(stream, gpr, format);
- }
- void fillInt52(VariableEventStream& stream, GPRReg gpr)
- {
- fillGPR(stream, gpr, DataFormatInt52);
- }
- void fillStrictInt52(VariableEventStream& stream, GPRReg gpr)
- {
- fillGPR(stream, gpr, DataFormatStrictInt52);
- }
void fillBoolean(VariableEventStream& stream, GPRReg gpr)
{
fillGPR(stream, gpr, DataFormatBoolean);
if (operandIsArgument(operand))
out.print(comma, "arg", operandToArgument(operand), "(", VariableAccessDataDump(*this, variableAccessData), ")");
else
- out.print(comma, "loc", operandToLocal(operand), "(", VariableAccessDataDump(*this, variableAccessData), ")");
+ out.print(comma, "r", operand, "(", VariableAccessDataDump(*this, variableAccessData), ")");
}
if (node->hasUnlinkedLocal()) {
int operand = node->unlinkedLocal();
if (operandIsArgument(operand))
out.print(comma, "arg", operandToArgument(operand));
else
- out.print(comma, "loc", operandToLocal(operand));
+ out.print(comma, "r", operand);
}
if (node->hasConstantBuffer()) {
out.print(comma);
bool addShouldSpeculateMachineInt(Node* add)
{
- if (!enableInt52())
- return false;
-
Node* left = add->child1().node();
Node* right = add->child2().node();
bool speculation;
if (add->op() == ValueAdd)
- speculation = Node::shouldSpeculateMachineInt(left, right);
+ speculation = Node::shouldSpeculateMachineIntExpectingDefined(left, right);
else
- speculation = Node::shouldSpeculateMachineInt(left, right);
+ speculation = Node::shouldSpeculateMachineIntForArithmetic(left, right);
- return speculation && !hasExitSite(add, Int52Overflow);
+ return speculation && !hasExitSite(add, Int48Overflow);
}
bool mulShouldSpeculateInt32(Node* mul)
{
ASSERT(mul->op() == ArithMul);
- if (!enableInt52())
- return false;
-
Node* left = mul->child1().node();
Node* right = mul->child2().node();
- return Node::shouldSpeculateMachineInt(left, right)
- && mul->canSpeculateInt52()
- && !hasExitSite(mul, Int52Overflow);
+ return Node::shouldSpeculateMachineIntForArithmetic(left, right)
+ && mul->canSpeculateInt48()
+ && !hasExitSite(mul, Int48Overflow);
}
bool negateShouldSpeculateInt32(Node* negate)
bool negateShouldSpeculateMachineInt(Node* negate)
{
ASSERT(negate->op() == ArithNegate);
- if (!enableInt52())
- return false;
- return negate->child1()->shouldSpeculateMachineInt()
- && !hasExitSite(negate, Int52Overflow)
- && negate->canSpeculateInt52();
+ return negate->child1()->shouldSpeculateMachineIntForArithmetic()
+ && !hasExitSite(negate, Int48Overflow)
+ && negate->canSpeculateInt48();
}
// Helper methods to check nodes for constants.
// before and after setting it.
source = forNode(node->child1());
if (node->variableAccessData()->flushFormat() == FlushedDouble) {
- ASSERT(!(source.m_type & ~SpecFullNumber));
- ASSERT(!!(source.m_type & ~SpecDouble) == !!(source.m_type & SpecMachineInt));
+ ASSERT(!(source.m_type & ~SpecNumber));
+ ASSERT(!!(source.m_type & ~SpecDouble) == !!(source.m_type & SpecInt32));
if (!(source.m_type & ~SpecDouble)) {
- source.merge(SpecInt52AsDouble);
+ source.merge(SpecInt48AsDouble);
source.filter(SpecDouble);
}
}
case AlreadyInJSStackAsUnboxedInt32:
value = jsNumber(exec->r(operand).unboxedInt32());
break;
- case AlreadyInJSStackAsUnboxedInt52:
- value = jsNumber(exec->r(operand).unboxedInt52());
- break;
case AlreadyInJSStackAsUnboxedDouble:
value = jsDoubleNumber(exec->r(operand).unboxedDouble());
break;
case UInt32ToNumber:
case DoubleAsInt32:
case PhantomArguments:
- case Int52ToValue:
- case Int52ToDouble:
return true;
default:
ASSERT(!permitsOSRBackwardRewiring(type) && !permitsOSRForwardRewiring(type));
case Int32ToDouble:
case UInt32ToNumber:
case DoubleAsInt32:
- case Int52ToDouble:
- case Int52ToValue:
return true;
default:
return false;
bool shouldSpeculateNumber()
{
- return isFullNumberSpeculation(prediction());
+ return isNumberSpeculation(prediction());
}
bool shouldSpeculateNumberExpectingDefined()
{
- return isFullNumberSpeculationExpectingDefined(prediction());
+ return isNumberSpeculationExpectingDefined(prediction());
}
bool shouldSpeculateBoolean()
return nodeCanSpeculateInt32(arithNodeFlags());
}
- bool canSpeculateInt52()
+ bool canSpeculateInt48()
{
- return nodeCanSpeculateInt52(arithNodeFlags());
+ return nodeCanSpeculateInt48(arithNodeFlags());
}
void dumpChildren(PrintStream& out)
#define NodeResultJS 0x0001
#define NodeResultNumber 0x0002
#define NodeResultInt32 0x0003
-#define NodeResultInt52 0x0004
-#define NodeResultBoolean 0x0005
-#define NodeResultStorage 0x0006
+#define NodeResultBoolean 0x0004
+#define NodeResultStorage 0x0005
#define NodeMustGenerate 0x0008 // set on nodes that have side effects, and may not trivially be removed by DCE.
#define NodeHasVarArgs 0x0010
return true;
}
-static inline bool nodeCanSpeculateInt52(NodeFlags flags)
+static inline bool nodeCanSpeculateInt48(NodeFlags flags)
{
if (nodeMayNegZero(flags))
return bytecodeCanIgnoreNegativeZero(flags);
macro(Int32ToDouble, NodeResultNumber) \
/* Used to speculate that a double value is actually an integer. */\
macro(DoubleAsInt32, NodeResultInt32 | NodeExitsForward) \
- /* Used to separate representation and register allocation of Int52's represented */\
- /* as values. */\
- macro(Int52ToValue, NodeResultJS) \
- macro(Int52ToDouble, NodeResultNumber) \
\
/* Nodes for arithmetic operations. */\
macro(ArithAdd, NodeResultNumber | NodeMustGenerate) \
// This loses information. Only use it if there are no better alternatives.
return 25;
- case Int52ToValue:
- // Loses no information. It just boxes the value, which is what OSR wants
- // to do anyway.
- return 100;
-
- case Int52ToDouble:
- // This is like Int32ToDouble; we can use it because it gives a semantically
- // equivalent value but that value may be an int32 in a double, so we'd
- // rather not if we can avoid it.
- return 75;
-
default:
return 0;
}
namespace JSC { namespace DFG {
+static CString shortOperandsDump(const Operands<ValueRecovery>& operands)
+{
+ DumpContext context;
+ StringPrintStream out;
+ out.print(inContext(operands, &context));
+ return out.toCString();
+}
+
extern "C" {
void compileOSRExit(ExecState* exec)
("DFG OSR exit #%u (%s, %s) from %s, with operands = %s",
exitIndex, toCString(exit.m_codeOrigin).data(),
exitKindToString(exit.m_kind), toCString(*codeBlock).data(),
- toCString(ignoringContext<DumpContext>(operands)).data()));
+ shortOperandsDump(operands).data()));
}
{
case InGPR:
case UnboxedInt32InGPR:
case UInt32InGPR:
- case UnboxedInt52InGPR:
- case UnboxedStrictInt52InGPR:
m_jit.store64(recovery.gpr(), scratch + index);
break;
case DisplacedInJSStack:
case Int32DisplacedInJSStack:
case DoubleDisplacedInJSStack:
- case Int52DisplacedInJSStack:
- case StrictInt52DisplacedInJSStack:
m_jit.load64(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
m_jit.store64(GPRInfo::regT0, scratch + index);
break;
case AlreadyInJSStackAsUnboxedInt32:
case AlreadyInJSStackAsUnboxedDouble:
- case AlreadyInJSStackAsUnboxedInt52:
m_jit.load64(AssemblyHelpers::addressFor(operand), GPRInfo::regT0);
m_jit.store64(GPRInfo::regT0, scratch + index);
break;
m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
break;
- case AlreadyInJSStackAsUnboxedInt52:
- case UnboxedInt52InGPR:
- case Int52DisplacedInJSStack:
- m_jit.load64(scratch + index, GPRInfo::regT0);
- m_jit.rshift64(
- AssemblyHelpers::TrustedImm32(JSValue::int52ShiftAmount), GPRInfo::regT0);
- m_jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0);
- m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
- break;
-
- case UnboxedStrictInt52InGPR:
- case StrictInt52DisplacedInJSStack:
- m_jit.load64(scratch + index, GPRInfo::regT0);
- m_jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0);
- m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
- break;
-
- case UInt32InGPR:
- m_jit.load64(scratch + index, GPRInfo::regT0);
- m_jit.zeroExtend32ToPtr(GPRInfo::regT0, GPRInfo::regT0);
- m_jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0);
- m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
- break;
-
case AlreadyInJSStackAsUnboxedDouble:
case InFPR:
case DoubleDisplacedInJSStack:
m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
break;
+ case UInt32InGPR: {
+ m_jit.load64(scratch + index, GPRInfo::regT0);
+ m_jit.zeroExtend32ToPtr(GPRInfo::regT0, GPRInfo::regT0);
+ AssemblyHelpers::Jump positive = m_jit.branch32(
+ AssemblyHelpers::GreaterThanOrEqual,
+ GPRInfo::regT0, AssemblyHelpers::TrustedImm32(0));
+ m_jit.convertInt32ToDouble(GPRInfo::regT0, FPRInfo::fpRegT0);
+ m_jit.addDouble(
+ AssemblyHelpers::AbsoluteAddress(&AssemblyHelpers::twoToThe32),
+ FPRInfo::fpRegT0);
+ m_jit.boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);
+ AssemblyHelpers::Jump done = m_jit.jump();
+ positive.link(&m_jit);
+ m_jit.or64(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
+ done.link(&m_jit);
+ m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
+ break;
+ }
+
case Constant:
m_jit.store64(
AssemblyHelpers::TrustedImm64(JSValue::encode(recovery.constant())),
SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value)
{
- if (!isFullNumberSpeculation(value))
+ if (!isNumberSpeculation(value))
return SpecDouble;
if (value & SpecDoubleNaN)
return SpecDouble;
case JSConstant:
case WeakJSConstant: {
SpeculatedType type = speculationFromValue(m_graph.valueOfJSConstant(node));
- if (type == SpecInt52AsDouble)
- type = SpecInt52;
+ if (type == SpecInt48AsDouble)
+ type = SpecInt48;
changed |= setPrediction(type);
break;
}
case GetLocal: {
- VariableAccessData* variable = node->variableAccessData();
- SpeculatedType prediction = variable->prediction();
- if (variable->shouldNeverUnbox() && (prediction & SpecInt52))
- prediction = (prediction | SpecInt52AsDouble) & ~SpecInt52;
+ VariableAccessData* variableAccessData = node->variableAccessData();
+ SpeculatedType prediction = variableAccessData->prediction();
if (prediction)
changed |= mergePrediction(prediction);
break;
if (nodeCanSpeculateInt32(node->arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
else
- changed |= mergePrediction(SpecBytecodeNumber);
+ changed |= mergePrediction(SpecNumber);
break;
}
SpeculatedType right = node->child2()->prediction();
if (left && right) {
- if (isFullNumberSpeculationExpectingDefined(left) && isFullNumberSpeculationExpectingDefined(right)) {
+ if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) {
if (m_graph.addSpeculationMode(node) != DontSpeculateInt32)
changed |= mergePrediction(SpecInt32);
else if (m_graph.addShouldSpeculateMachineInt(node))
- changed |= mergePrediction(SpecInt52);
+ changed |= mergePrediction(SpecInt48);
else
changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
- } else if (!(left & SpecFullNumber) || !(right & SpecFullNumber)) {
+ } else if (!(left & SpecNumber) || !(right & SpecNumber)) {
// left or right is definitely something other than a number.
changed |= mergePrediction(SpecString);
} else
if (m_graph.addSpeculationMode(node) != DontSpeculateInt32)
changed |= mergePrediction(SpecInt32);
else if (m_graph.addShouldSpeculateMachineInt(node))
- changed |= mergePrediction(SpecInt52);
+ changed |= mergePrediction(SpecInt48);
else
changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
}
if (m_graph.addSpeculationMode(node) != DontSpeculateInt32)
changed |= mergePrediction(SpecInt32);
else if (m_graph.addShouldSpeculateMachineInt(node))
- changed |= mergePrediction(SpecInt52);
+ changed |= mergePrediction(SpecInt48);
else
changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
}
if (m_graph.negateShouldSpeculateInt32(node))
changed |= mergePrediction(SpecInt32);
else if (m_graph.negateShouldSpeculateMachineInt(node))
- changed |= mergePrediction(SpecInt52);
+ changed |= mergePrediction(SpecInt48);
else
changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction()));
}
if (m_graph.mulShouldSpeculateInt32(node))
changed |= mergePrediction(SpecInt32);
else if (m_graph.mulShouldSpeculateMachineInt(node))
- changed |= mergePrediction(SpecInt52);
+ changed |= mergePrediction(SpecInt48);
else
changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
}
}
case GetByVal: {
- if (!node->child1()->prediction())
- break;
- if (!node->getHeapPrediction())
- break;
-
if (node->child1()->shouldSpeculateFloat32Array()
|| node->child1()->shouldSpeculateFloat64Array())
changed |= mergePrediction(SpecDouble);
- else if (node->child1()->shouldSpeculateUint32Array()) {
- if (isInt32Speculation(node->getHeapPrediction()))
- changed |= mergePrediction(SpecInt32);
- else
- changed |= mergePrediction(SpecInt52);
- } else
+ else
changed |= mergePrediction(node->getHeapPrediction());
break;
}
case CheckWatchdogTimer:
case Unreachable:
case LoopHint:
- case Int52ToValue:
- case Int52ToDouble:
break;
// This gets ignored because it already has a prediction.
DoubleBallot ballot;
- if (isFullNumberSpeculationExpectingDefined(left) && isFullNumberSpeculationExpectingDefined(right)
- && !m_graph.addShouldSpeculateInt32(node)
- && !m_graph.addShouldSpeculateMachineInt(node))
+ if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)
+ && !m_graph.addShouldSpeculateInt32(node))
ballot = VoteDouble;
else
ballot = VoteValue;
DoubleBallot ballot;
- if (isFullNumberSpeculation(left) && isFullNumberSpeculation(right)
- && !m_graph.mulShouldSpeculateInt32(node)
- && !m_graph.mulShouldSpeculateMachineInt(node))
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
+ && !m_graph.mulShouldSpeculateInt32(node))
ballot = VoteDouble;
else
ballot = VoteValue;
DoubleBallot ballot;
- if (isFullNumberSpeculation(left) && isFullNumberSpeculation(right)
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
&& !(Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node()) && node->canSpeculateInt32()))
ballot = VoteDouble;
else
SpeculatedType prediction = node->child1()->prediction();
if (isDoubleSpeculation(prediction))
node->variableAccessData()->vote(VoteDouble);
- else if (
- !isFullNumberSpeculation(prediction)
- || isInt32Speculation(prediction) || isMachineIntSpeculation(prediction))
+ else if (!isNumberSpeculation(prediction) || isInt32Speculation(prediction))
node->variableAccessData()->vote(VoteValue);
break;
}
case StringOrStringObjectUse:
case NotCellUse:
case OtherUse:
- case MachineIntUse:
return;
case KnownInt32Use:
return;
case KnownNumberUse:
- if (m_state.forNode(edge).m_type & ~SpecFullNumber)
+ if (m_state.forNode(edge).m_type & ~SpecNumber)
m_result = false;
return;
case CheckTierUpAtReturn:
case CheckTierUpAndOSREnter:
case LoopHint:
- case Int52ToDouble:
- case Int52ToValue:
return true;
case GetByVal:
enum SilentFillAction {
DoNothingForFill,
SetInt32Constant,
- SetInt52Constant,
- SetStrictInt52Constant,
SetBooleanConstant,
SetCellConstant,
SetTrustedJSConstant,
Load32Tag,
Load32Payload,
Load32PayloadBoxInt,
- Load32PayloadConvertToInt52,
- Load32PayloadSignExtend,
LoadPtr,
Load64,
- Load64ShiftInt52Right,
- Load64ShiftInt52Left,
LoadDouble,
LoadDoubleBoxDouble,
LoadJSUnboxDouble
spillAction = Store32Payload;
else if (registerFormat == DataFormatCell || registerFormat == DataFormatStorage)
spillAction = StorePtr;
- else if (registerFormat == DataFormatInt52 || registerFormat == DataFormatStrictInt52)
- spillAction = Store64;
else {
ASSERT(registerFormat & DataFormatJS);
spillAction = Store64;
} else if (registerFormat == DataFormatStorage) {
ASSERT(info.gpr() == source);
fillAction = LoadPtr;
- } else if (registerFormat == DataFormatInt52) {
- if (node->hasConstant())
- fillAction = SetInt52Constant;
- else if (isJSInt32(info.spillFormat()) || info.spillFormat() == DataFormatJS)
- fillAction = Load32PayloadConvertToInt52;
- else if (info.spillFormat() == DataFormatInt52)
- fillAction = Load64;
- else if (info.spillFormat() == DataFormatStrictInt52)
- fillAction = Load64ShiftInt52Left;
- else if (info.spillFormat() == DataFormatNone)
- fillAction = Load64;
- else {
- // Should never happen. Anything that qualifies as an int32 will never
- // be turned into a cell (immediate spec fail) or a double (to-double
- // conversions involve a separate node).
- RELEASE_ASSERT_NOT_REACHED();
- fillAction = Load64; // Make GCC happy.
- }
- } else if (registerFormat == DataFormatStrictInt52) {
- if (node->hasConstant())
- fillAction = SetStrictInt52Constant;
- else if (isJSInt32(info.spillFormat()) || info.spillFormat() == DataFormatJS)
- fillAction = Load32PayloadSignExtend;
- else if (info.spillFormat() == DataFormatInt52)
- fillAction = Load64ShiftInt52Right;
- else if (info.spillFormat() == DataFormatStrictInt52)
- fillAction = Load64;
- else if (info.spillFormat() == DataFormatNone)
- fillAction = Load64;
- else {
- // Should never happen. Anything that qualifies as an int32 will never
- // be turned into a cell (immediate spec fail) or a double (to-double
- // conversions involve a separate node).
- RELEASE_ASSERT_NOT_REACHED();
- fillAction = Load64; // Make GCC happy.
- }
} else {
ASSERT(registerFormat & DataFormatJS);
#if USE(JSVALUE64)
if (node->hasConstant()) {
if (valueOfJSConstant(node).isCell())
fillAction = SetTrustedJSConstant;
+ else
fillAction = SetJSConstant;
} else if (info.spillFormat() == DataFormatInt32) {
ASSERT(registerFormat == DataFormatJSInt32);
case SetInt32Constant:
m_jit.move(Imm32(valueOfInt32Constant(plan.node())), plan.gpr());
break;
-#if USE(JSVALUE64)
- case SetInt52Constant:
- m_jit.move(Imm64(valueOfJSConstant(plan.node()).asMachineInt() << JSValue::int52ShiftAmount), plan.gpr());
- break;
- case SetStrictInt52Constant:
- m_jit.move(Imm64(valueOfJSConstant(plan.node()).asMachineInt()), plan.gpr());
- break;
-#endif // USE(JSVALUE64)
case SetBooleanConstant:
m_jit.move(TrustedImm32(valueOfBooleanConstant(plan.node())), plan.gpr());
break;
m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
m_jit.or64(GPRInfo::tagTypeNumberRegister, plan.gpr());
break;
- case Load32PayloadConvertToInt52:
- m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
- m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr());
- m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr());
- break;
- case Load32PayloadSignExtend:
- m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
- m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr());
- break;
case LoadDoubleBoxDouble:
m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
m_jit.sub64(GPRInfo::tagTypeNumberRegister, plan.gpr());
case Load64:
m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
break;
- case Load64ShiftInt52Right:
- m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
- m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr());
- break;
- case Load64ShiftInt52Left:
- m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
- m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr());
- break;
#endif
case LoadDouble:
m_jit.loadDouble(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.fpr());
if (node->isBinaryUseKind(Int32Use))
compilePeepHoleInt32Branch(node, branchNode, condition);
-#if USE(JSVALUE64)
- else if (node->isBinaryUseKind(MachineIntUse))
- compilePeepHoleInt52Branch(node, branchNode, condition);
-#endif // USE(JSVALUE64)
else if (node->isBinaryUseKind(NumberUse))
compilePeepHoleDoubleBranch(node, branchNode, doubleCondition);
else if (node->op() == CompareEq) {
case FlushedInt32:
valueSource = ValueSource(Int32InJSStack);
break;
- case FlushedInt52:
- valueSource = ValueSource(Int52InJSStack);
- break;
case FlushedCell:
valueSource = ValueSource(CellInJSStack);
break;
FPRReg valueReg = value.fpr();
DFG_TYPE_CHECK(
- JSValueRegs(), child3, SpecFullRealNumber,
+ JSValueRegs(), child3, SpecRealNumber,
m_jit.branchDouble(
MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg));
int32Result(result.gpr(), node, op1.format());
return;
}
-
-#if USE(JSVALUE64)
- case MachineIntUse: {
- SpeculateStrictInt52Operand op1(this, node->child1());
- GPRTemporary result(this, Reuse, op1);
- GPRReg op1GPR = op1.gpr();
- GPRReg resultGPR = result.gpr();
- m_jit.zeroExtend32ToPtr(op1GPR, resultGPR);
- int32Result(resultGPR, node, DataFormatInt32);
- return;
- }
-#endif // USE(JSVALUE64)
case NumberUse:
case NotCellUse: {
if (node->child1().useKind() == NumberUse) {
DFG_TYPE_CHECK(
- JSValueRegs(gpr), node->child1(), SpecFullNumber,
+ JSValueRegs(gpr), node->child1(), SpecNumber,
m_jit.branchTest64(
MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
} else {
if (node->child1().useKind() == NumberUse) {
DFG_TYPE_CHECK(
- JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecFullNumber,
+ JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecNumber,
m_jit.branch32(
MacroAssembler::AboveOrEqual, tagGPR,
TrustedImm32(JSValue::LowestTag)));
JITCompiler::Jump isInteger = m_jit.branch64(
MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
- if (needsTypeCheck(node->child1(), SpecFullNumber)) {
+ if (needsTypeCheck(node->child1(), SpecNumber)) {
if (node->flags() & NodeExitsForward) {
forwardTypeCheck(
- JSValueRegs(op1GPR), node->child1(), SpecFullNumber,
+ JSValueRegs(op1GPR), node->child1(), SpecNumber,
m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister),
ValueRecovery::inGPR(op1GPR, DataFormatJS));
} else {
backwardTypeCheck(
- JSValueRegs(op1GPR), node->child1(), SpecFullNumber,
+ JSValueRegs(op1GPR), node->child1(), SpecNumber,
m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
}
}
JITCompiler::Jump isInteger = m_jit.branch32(
MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
- if (needsTypeCheck(node->child1(), SpecFullNumber)) {
+ if (needsTypeCheck(node->child1(), SpecNumber)) {
if (node->flags() & NodeExitsForward) {
forwardTypeCheck(
- JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber,
+ JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecNumber,
m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)),
ValueRecovery::inPair(op1TagGPR, op1PayloadGPR));
} else {
backwardTypeCheck(
- JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber,
+ JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecNumber,
m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
}
}
return;
}
-#if USE(JSVALUE64)
- if (node->shouldSpeculateMachineInt()) {
- m_jit.zeroExtend32ToPtr(resultReg, resultReg);
- strictInt52Result(resultReg, node);
- return;
- }
-#endif
-
FPRTemporary fresult(this);
m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
break;
}
-#if USE(JSVALUE64)
- case MachineIntUse: {
- SpeculateStrictInt52Operand valueOp(this, valueUse);
- GPRTemporary scratch(this);
- GPRReg scratchReg = scratch.gpr();
- m_jit.move(valueOp.gpr(), scratchReg);
- if (isClamped(type)) {
- ASSERT(elementSize(type) == 1);
- MacroAssembler::Jump inBounds = m_jit.branch64(
- MacroAssembler::BelowOrEqual, scratchReg, JITCompiler::TrustedImm64(0xff));
- MacroAssembler::Jump tooBig = m_jit.branch64(
- MacroAssembler::GreaterThan, scratchReg, JITCompiler::TrustedImm64(0xff));
- m_jit.move(TrustedImm32(0), scratchReg);
- MacroAssembler::Jump clamped = m_jit.jump();
- tooBig.link(&m_jit);
- m_jit.move(JITCompiler::TrustedImm32(255), scratchReg);
- clamped.link(&m_jit);
- inBounds.link(&m_jit);
- }
- value.adopt(scratch);
- valueGPR = scratchReg;
- break;
- }
-#endif // USE(JSVALUE64)
-
case NumberUse: {
if (isClamped(type)) {
ASSERT(elementSize(type) == 1);
int32Result(result.gpr(), node);
return;
}
-
+
if (isNumberConstant(node->child2().node())) {
SpeculateInt32Operand op1(this, node->child1());
int32_t imm2 = valueOfInt32Constant(node->child2().node());
int32Result(gprResult, node);
return;
}
-
-#if USE(JSVALUE64)
- case MachineIntUse: {
- // Will we need an overflow check? If we can prove that neither input can be
- // Int52 then the overflow check will not be necessary.
- if (!m_state.forNode(node->child1()).couldBeType(SpecInt52)
- && !m_state.forNode(node->child2()).couldBeType(SpecInt52)) {
- SpeculateWhicheverInt52Operand op1(this, node->child1());
- SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
- GPRTemporary result(this, Reuse, op1);
- m_jit.move(op1.gpr(), result.gpr());
- m_jit.add64(op2.gpr(), result.gpr());
- int52Result(result.gpr(), node, op1.format());
- return;
- }
-
- SpeculateInt52Operand op1(this, node->child1());
- SpeculateInt52Operand op2(this, node->child2());
- GPRTemporary result(this, Reuse, op1, op2);
- m_jit.move(op1.gpr(), result.gpr());
- speculationCheck(
- Int52Overflow, JSValueRegs(), 0,
- m_jit.branchAdd64(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
- int52Result(result.gpr(), node);
- return;
- }
-#endif // USE(JSVALUE64)
case NumberUse: {
SpeculateDoubleOperand op1(this, node->child1());
return;
}
-#if USE(JSVALUE64)
- case MachineIntUse: {
- // Will we need an overflow check? If we can prove that neither input can be
- // Int52 then the overflow check will not be necessary.
- if (!m_state.forNode(node->child1()).couldBeType(SpecInt52)
- && !m_state.forNode(node->child2()).couldBeType(SpecInt52)) {
- SpeculateWhicheverInt52Operand op1(this, node->child1());
- SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
- GPRTemporary result(this, Reuse, op1);
- m_jit.move(op1.gpr(), result.gpr());
- m_jit.sub64(op2.gpr(), result.gpr());
- int52Result(result.gpr(), node, op1.format());
- return;
- }
-
- SpeculateInt52Operand op1(this, node->child1());
- SpeculateInt52Operand op2(this, node->child2());
- GPRTemporary result(this, Reuse, op1, op2);
- m_jit.move(op1.gpr(), result.gpr());
- speculationCheck(
- Int52Overflow, JSValueRegs(), 0,
- m_jit.branchSub64(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
- int52Result(result.gpr(), node);
- return;
- }
-#endif // USE(JSVALUE64)
-
case NumberUse: {
SpeculateDoubleOperand op1(this, node->child1());
SpeculateDoubleOperand op2(this, node->child2());
m_jit.move(op1.gpr(), result.gpr());
- // Note: there is no notion of being not used as a number, but someone
- // caring about negative zero.
-
if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
m_jit.neg32(result.gpr());
else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
int32Result(result.gpr(), node);
return;
}
-
-#if USE(JSVALUE64)
- case MachineIntUse: {
- if (!m_state.forNode(node->child1()).couldBeType(SpecInt52)) {
- SpeculateWhicheverInt52Operand op1(this, node->child1());
- GPRTemporary result(this);
- GPRReg op1GPR = op1.gpr();
- GPRReg resultGPR = result.gpr();
- m_jit.move(op1GPR, resultGPR);
- m_jit.neg64(resultGPR);
- if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
- speculationCheck(
- NegativeZero, JSValueRegs(), 0,
- m_jit.branchTest64(MacroAssembler::Zero, resultGPR));
- }
- int52Result(resultGPR, node, op1.format());
- return;
- }
-
- SpeculateInt52Operand op1(this, node->child1());
- GPRTemporary result(this);
- GPRReg op1GPR = op1.gpr();
- GPRReg resultGPR = result.gpr();
- m_jit.move(op1GPR, resultGPR);
- speculationCheck(
- Int52Overflow, JSValueRegs(), 0,
- m_jit.branchNeg64(MacroAssembler::Overflow, resultGPR));
- if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
- speculationCheck(
- NegativeZero, JSValueRegs(), 0,
- m_jit.branchTest64(MacroAssembler::Zero, resultGPR));
- }
- int52Result(resultGPR, node);
- return;
- }
-#endif // USE(JSVALUE64)
case NumberUse: {
SpeculateDoubleOperand op1(this, node->child1());
int32Result(result.gpr(), node);
return;
}
-
-#if USE(JSVALUE64)
- case MachineIntUse: {
- // This is super clever. We want to do an int52 multiplication and check the
- // int52 overflow bit. There is no direct hardware support for this, but we do
- // have the ability to do an int64 multiplication and check the int64 overflow
- // bit. We leverage that. Consider that a, b are int52 numbers inside int64
- // registers, with the high 12 bits being sign-extended. We can do:
- //
- // (a * (b << 12))
- //
- // This will give us a left-shifted int52 (value is in high 52 bits, low 16
- // bits are zero) plus the int52 overflow bit. I.e. whether this 64-bit
- // multiplication overflows is identical to whether the 'a * b' 52-bit
- // multiplication overflows.
- //
- // In our nomenclature, this is:
- //
- // strictInt52(a) * int52(b) => int52
- //
- // That is "strictInt52" means unshifted and "int52" means left-shifted by 16
- // bits.
- //
- // We don't care which of op1 or op2 serves as the left-shifted operand, so
- // we just do whatever is more convenient for op1 and have op2 do the
- // opposite. This ensures that we do at most one shift.
-
- SpeculateWhicheverInt52Operand op1(this, node->child1());
- SpeculateWhicheverInt52Operand op2(this, node->child2(), OppositeShift, op1);
- GPRTemporary result(this);
-
- GPRReg op1GPR = op1.gpr();
- GPRReg op2GPR = op2.gpr();
- GPRReg resultGPR = result.gpr();
-
- m_jit.move(op1GPR, resultGPR);
- speculationCheck(
- Int52Overflow, JSValueRegs(), 0,
- m_jit.branchMul64(MacroAssembler::Overflow, op2GPR, resultGPR));
-
- if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
- MacroAssembler::Jump resultNonZero = m_jit.branchTest64(
- MacroAssembler::NonZero, resultGPR);
- speculationCheck(
- NegativeZero, JSValueRegs(), 0,
- m_jit.branch64(MacroAssembler::LessThan, op1GPR, TrustedImm64(0)));
- speculationCheck(
- NegativeZero, JSValueRegs(), 0,
- m_jit.branch64(MacroAssembler::LessThan, op2GPR, TrustedImm64(0)));
- resultNonZero.link(&m_jit);
- }
-
- int52Result(resultGPR, node);
- return;
- }
-#endif // USE(JSVALUE64)
case NumberUse: {
SpeculateDoubleOperand op1(this, node->child1());
compileInt32Compare(node, condition);
return false;
}
-
-#if USE(JSVALUE64)
- if (node->isBinaryUseKind(MachineIntUse)) {
- compileInt52Compare(node, condition);
- return false;
- }
-#endif // USE(JSVALUE64)
-
+
if (node->isBinaryUseKind(NumberUse)) {
compileDoubleCompare(node, doubleCondition);
return false;
compileInt32Compare(node, MacroAssembler::Equal);
return false;
}
-
-#if USE(JSVALUE64)
- case MachineIntUse: {
- unsigned branchIndexInBlock = detectPeepHoleBranch();
- if (branchIndexInBlock != UINT_MAX) {
- Node* branchNode = m_block->at(branchIndexInBlock);
- compilePeepHoleInt52Branch(node, branchNode, MacroAssembler::Equal);
- use(node->child1());
- use(node->child2());
- m_indexInBlock = branchIndexInBlock;
- m_currentNode = branchNode;
- return true;
- }
- compileInt52Compare(node, MacroAssembler::Equal);
- return false;
- }
-#endif // USE(JSVALUE64)
case NumberUse: {
unsigned branchIndexInBlock = detectPeepHoleBranch();
(SpeculateInt32Operand(this, edge)).gpr();
}
-void SpeculativeJIT::speculateMachineInt(Edge edge)
-{
-#if USE(JSVALUE64)
- if (!needsTypeCheck(edge, SpecMachineInt))
- return;
-
- (SpeculateWhicheverInt52Operand(this, edge)).gpr();
-#else // USE(JSVALUE64)
- UNUSED_PARAM(edge);
- UNREACHABLE_FOR_PLATFORM();
-#endif // USE(JSVALUE64)
-}
-
void SpeculativeJIT::speculateNumber(Edge edge)
{
- if (!needsTypeCheck(edge, SpecFullNumber))
+ if (!needsTypeCheck(edge, SpecNumber))
return;
(SpeculateDoubleOperand(this, edge)).fpr();
void SpeculativeJIT::speculateRealNumber(Edge edge)
{
- if (!needsTypeCheck(edge, SpecFullRealNumber))
+ if (!needsTypeCheck(edge, SpecRealNumber))
return;
SpeculateDoubleOperand operand(this, edge);
FPRReg fpr = operand.fpr();
DFG_TYPE_CHECK(
- JSValueRegs(), edge, SpecFullRealNumber,
+ JSValueRegs(), edge, SpecRealNumber,
m_jit.branchDouble(
MacroAssembler::DoubleNotEqualOrUnordered, fpr, fpr));
}
ASSERT(!needsTypeCheck(edge, SpecInt32));
break;
case KnownNumberUse:
- ASSERT(!needsTypeCheck(edge, SpecFullNumber));
+ ASSERT(!needsTypeCheck(edge, SpecNumber));
break;
case KnownCellUse:
ASSERT(!needsTypeCheck(edge, SpecCell));
case Int32Use:
speculateInt32(edge);
break;
- case MachineIntUse:
- speculateMachineInt(edge);
- break;
case RealNumberUse:
speculateRealNumber(edge);
break;
// and its machine registers may be reused.
bool canReuse(Node* node)
{
- return generationInfo(node).canReuse();
+ VirtualRegister virtualRegister = node->virtualRegister();
+ GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
+ return info.canReuse();
}
bool canReuse(Edge nodeUse)
{
// avoid spilling values we will need immediately).
bool isFilled(Node* node)
{
- return generationInfo(node).registerFormat() != DataFormatNone;
+ VirtualRegister virtualRegister = node->virtualRegister();
+ GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
+ return info.registerFormat() != DataFormatNone;
}
bool isFilledDouble(Node* node)
{
- return generationInfo(node).registerFormat() == DataFormatDouble;
+ VirtualRegister virtualRegister = node->virtualRegister();
+ GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
+ return info.registerFormat() == DataFormatDouble;
}
// Called on an operand once it has been consumed by a parent node.
{
if (!node->hasResult())
return;
- GenerationInfo& info = generationInfo(node);
+ VirtualRegister virtualRegister = node->virtualRegister();
+ GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
// use() returns true when the value becomes dead, and any
// associated resources may be freed.
// machine registers, implicitly generating speculation checks as needed.
GPRReg fillSpeculateInt32(Edge, DataFormat& returnFormat);
GPRReg fillSpeculateInt32Strict(Edge);
- GPRReg fillSpeculateInt52(Edge, DataFormat desiredFormat);
FPRReg fillSpeculateDouble(Edge);
GPRReg fillSpeculateCell(Edge);
GPRReg fillSpeculateBoolean(Edge);
{
return boxDouble(fpr, allocate());
}
-
- void boxInt52(GPRReg sourceGPR, GPRReg targetGPR, DataFormat);
#elif USE(JSVALUE32_64)
void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
{
}
}
- bool isKnownInteger(Node* node) { return m_state.forNode(node).isType(SpecInt32); }
- bool isKnownCell(Node* node) { return m_state.forNode(node).isType(SpecCell); }
+ bool isKnownInteger(Node* node) { return !(m_state.forNode(node).m_type & ~SpecInt32); }
+ bool isKnownCell(Node* node) { return !(m_state.forNode(node).m_type & ~SpecCell); }
bool isKnownNotInteger(Node* node) { return !(m_state.forNode(node).m_type & SpecInt32); }
- bool isKnownNotNumber(Node* node) { return !(m_state.forNode(node).m_type & SpecFullNumber); }
+ bool isKnownNotNumber(Node* node) { return !(m_state.forNode(node).m_type & SpecNumber); }
bool isKnownNotCell(Node* node) { return !(m_state.forNode(node).m_type & SpecCell); }
// Checks/accessors for constant values.
{
int32Result(reg, node, DataFormatInt32, mode);
}
- void int52Result(GPRReg reg, Node* node, DataFormat format, UseChildrenMode mode = CallUseChildren)
- {
- if (mode == CallUseChildren)
- useChildren(node);
-
- VirtualRegister virtualRegister = node->virtualRegister();
- GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
-
- m_gprs.retain(reg, virtualRegister, SpillOrderJS);
- info.initInt52(node, node->refCount(), reg, format);
- }
- void int52Result(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
- {
- int52Result(reg, node, DataFormatInt52, mode);
- }
- void strictInt52Result(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
- {
- int52Result(reg, node, DataFormatStrictInt52, mode);
- }
void noResult(Node* node, UseChildrenMode mode = CallUseChildren)
{
if (mode == UseChildrenCalledExplicitly)
void initConstantInfo(Node* node)
{
ASSERT(isInt32Constant(node) || isNumberConstant(node) || isJSConstant(node));
- generationInfo(node).initConstant(node, node->refCount());
+ generationInfoFromVirtualRegister(node->virtualRegister()).initConstant(node, node->refCount());
}
// These methods add calls to C++ helper functions.
if (isInt32Constant(node))
return true;
- return generationInfo(node).isJSInt32();
- }
-
- bool betterUseStrictInt52(Node* node)
- {
- return !generationInfo(node).isInt52();
- }
- bool betterUseStrictInt52(Edge edge)
- {
- return betterUseStrictInt52(edge.node());
+ VirtualRegister virtualRegister = node->virtualRegister();
+ GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
+
+ return info.isJSInt32();
}
bool compare(Node*, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
bool compilePeepHoleBranch(Node*, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
void compilePeepHoleInt32Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
- void compilePeepHoleInt52Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
void compilePeepHoleBooleanBranch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
void compilePeepHoleDoubleBranch(Node*, Node* branchNode, JITCompiler::DoubleCondition);
void compilePeepHoleObjectEquality(Node*, Node* branchNode);
void compileNewTypedArray(Node*);
void compileInt32Compare(Node*, MacroAssembler::RelationalCondition);
- void compileInt52Compare(Node*, MacroAssembler::RelationalCondition);
void compileBooleanCompare(Node*, MacroAssembler::RelationalCondition);
void compileDoubleCompare(Node*, MacroAssembler::DoubleCondition);
void forwardTypeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, const ValueRecovery&);
void speculateInt32(Edge);
- void speculateMachineInt(Edge);
void speculateNumber(Edge);
void speculateRealNumber(Edge);
void speculateBoolean(Edge);
{
return m_generationInfo[operandToLocal(virtualRegister)];
}
-
- GenerationInfo& generationInfo(Node* node)
- {
- return generationInfoFromVirtualRegister(node->virtualRegister());
- }
-
- GenerationInfo& generationInfo(Edge edge)
- {
- return generationInfo(edge.node());
- }
// The JIT, while also provides MacroAssembler functionality.
JITCompiler& m_jit;
GPRReg m_gprOrInvalid;
};
-// Gives you a canonical Int52 (i.e. it's left-shifted by 16, low bits zero).
-class SpeculateInt52Operand {
-public:
- explicit SpeculateInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
- : m_jit(jit)
- , m_edge(edge)
- , m_gprOrInvalid(InvalidGPRReg)
- {
- ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
- if (jit->isFilled(node()))
- gpr();
- }
-
- ~SpeculateInt52Operand()
- {
- ASSERT(m_gprOrInvalid != InvalidGPRReg);
- m_jit->unlock(m_gprOrInvalid);
- }
-
- Edge edge() const
- {
- return m_edge;
- }
-
- Node* node() const
- {
- return edge().node();
- }
-
- GPRReg gpr()
- {
- if (m_gprOrInvalid == InvalidGPRReg)
- m_gprOrInvalid = m_jit->fillSpeculateInt52(edge(), DataFormatInt52);
- return m_gprOrInvalid;
- }
-
- void use()
- {
- m_jit->use(node());
- }
-
-private:
- SpeculativeJIT* m_jit;
- Edge m_edge;
- GPRReg m_gprOrInvalid;
-};
-
-// Gives you a strict Int52 (i.e. the payload is in the low 48 bits, high 16 bits are sign-extended).
-class SpeculateStrictInt52Operand {
-public:
- explicit SpeculateStrictInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
- : m_jit(jit)
- , m_edge(edge)
- , m_gprOrInvalid(InvalidGPRReg)
- {
- ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
- if (jit->isFilled(node()))
- gpr();
- }
-
- ~SpeculateStrictInt52Operand()
- {
- ASSERT(m_gprOrInvalid != InvalidGPRReg);
- m_jit->unlock(m_gprOrInvalid);
- }
-
- Edge edge() const
- {
- return m_edge;
- }
-
- Node* node() const
- {
- return edge().node();
- }
-
- GPRReg gpr()
- {
- if (m_gprOrInvalid == InvalidGPRReg)
- m_gprOrInvalid = m_jit->fillSpeculateInt52(edge(), DataFormatStrictInt52);
- return m_gprOrInvalid;
- }
-
- void use()
- {
- m_jit->use(node());
- }
-
-private:
- SpeculativeJIT* m_jit;
- Edge m_edge;
- GPRReg m_gprOrInvalid;
-};
-
-enum OppositeShiftTag { OppositeShift };
-
-class SpeculateWhicheverInt52Operand {
-public:
- explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
- : m_jit(jit)
- , m_edge(edge)
- , m_gprOrInvalid(InvalidGPRReg)
- , m_strict(jit->betterUseStrictInt52(edge))
- {
- ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
- if (jit->isFilled(node()))
- gpr();
- }
-
- explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, const SpeculateWhicheverInt52Operand& other, OperandSpeculationMode mode = AutomaticOperandSpeculation)
- : m_jit(jit)
- , m_edge(edge)
- , m_gprOrInvalid(InvalidGPRReg)
- , m_strict(other.m_strict)
- {
- ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
- if (jit->isFilled(node()))
- gpr();
- }
-
- explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OppositeShiftTag, const SpeculateWhicheverInt52Operand& other, OperandSpeculationMode mode = AutomaticOperandSpeculation)
- : m_jit(jit)
- , m_edge(edge)
- , m_gprOrInvalid(InvalidGPRReg)
- , m_strict(!other.m_strict)
- {
- ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
- if (jit->isFilled(node()))
- gpr();
- }
-
- ~SpeculateWhicheverInt52Operand()
- {
- ASSERT(m_gprOrInvalid != InvalidGPRReg);
- m_jit->unlock(m_gprOrInvalid);
- }
-
- Edge edge() const
- {
- return m_edge;
- }
-
- Node* node() const
- {
- return edge().node();
- }
-
- GPRReg gpr()
- {
- if (m_gprOrInvalid == InvalidGPRReg) {
- m_gprOrInvalid = m_jit->fillSpeculateInt52(
- edge(), m_strict ? DataFormatStrictInt52 : DataFormatInt52);
- }
- return m_gprOrInvalid;
- }
-
- void use()
- {
- m_jit->use(node());
- }
-
- DataFormat format() const
- {
- return m_strict ? DataFormatStrictInt52 : DataFormatInt52;
- }
-
-private:
- SpeculativeJIT* m_jit;
- Edge m_edge;
- GPRReg m_gprOrInvalid;
- bool m_strict;
-};
-
class SpeculateDoubleOperand {
public:
explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
#endif
AbstractValue& value = m_state.forNode(edge);
SpeculatedType type = value.m_type;
- ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecFullNumber));
- m_interpreter.filter(value, SpecFullNumber);
+ ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecNumber));
+ m_interpreter.filter(value, SpecNumber);
VirtualRegister virtualRegister = edge->virtualRegister();
GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
if (spillFormat != DataFormatJSInt32 && spillFormat != DataFormatInt32) {
JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
- if (type & ~SpecFullNumber)
+ if (type & ~SpecNumber)
speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag)));
m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
hasUnboxedDouble = m_jit.jump();
if (info.registerFormat() != DataFormatJSInt32) {
FPRTemporary scratch(this);
JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
- if (type & ~SpecFullNumber)
+ if (type & ~SpecNumber)
speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
hasUnboxedDouble = m_jit.jump();
FPRReg valueFPR = value.fpr();
DFG_TYPE_CHECK(
- JSValueRegs(), node->child2(), SpecFullRealNumber,
+ JSValueRegs(), node->child2(), SpecRealNumber,
m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
op1.use();
- if (!(m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean))) {
+ if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean))) {
m_jit.move(op1TagGPR, resultTagGPR);
m_jit.move(op1PayloadGPR, resultPayloadGPR);
} else {
SpeculateDoubleOperand operand(this, use);
FPRReg opFPR = operand.fpr();
DFG_TYPE_CHECK(
- JSValueRegs(), use, SpecFullRealNumber,
+ JSValueRegs(), use, SpecRealNumber,
m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx));
SpeculateDoubleOperand operand(this, use);
FPRReg opFPR = operand.fpr();
DFG_TYPE_CHECK(
- JSValueRegs(), use, SpecFullRealNumber,
+ JSValueRegs(), use, SpecRealNumber,
m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
m_jit.storeDouble(opFPR, reinterpret_cast<char*>(buffer + operandIdx));
case CheckTierUpInLoop:
case CheckTierUpAtReturn:
case CheckTierUpAndOSREnter:
- case Int52ToDouble:
- case Int52ToValue:
RELEASE_ASSERT_NOT_REACHED();
break;
}
#if USE(JSVALUE64)
-void SpeculativeJIT::boxInt52(GPRReg sourceGPR, GPRReg targetGPR, DataFormat format)
-{
- GPRReg tempGPR;
- if (sourceGPR == targetGPR)
- tempGPR = allocate();
- else
- tempGPR = targetGPR;
-
- FPRReg fpr = fprAllocate();
-
- if (format == DataFormatInt52)
- m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), sourceGPR);
- else
- ASSERT(format == DataFormatStrictInt52);
-
- m_jit.boxInt52(sourceGPR, targetGPR, tempGPR, fpr);
-
- if (tempGPR != targetGPR)
- unlock(tempGPR);
-
- unlock(fpr);
-}
-
GPRReg SpeculativeJIT::fillJSValue(Edge edge)
{
VirtualRegister virtualRegister = edge->virtualRegister();
} else {
DataFormat spillFormat = info.spillFormat();
m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
- switch (spillFormat) {
- case DataFormatInt32: {
+ if (spillFormat == DataFormatInt32) {
m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
spillFormat = DataFormatJSInt32;
- break;
- }
-
- case DataFormatInt52:
- case DataFormatStrictInt52: {
- m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
- boxInt52(gpr, gpr, spillFormat);
- return gpr;
- }
-
- default:
+ } else {
m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
if (spillFormat == DataFormatDouble) {
// Need to box the double, since we want a JSValue.
spillFormat = DataFormatJSDouble;
} else
RELEASE_ASSERT(spillFormat & DataFormatJS);
- break;
}
info.fillJSValue(*m_stream, gpr, spillFormat);
}
return gpr;
}
-
- case DataFormatInt52:
- case DataFormatStrictInt52: {
- GPRReg gpr = info.gpr();
- lock(gpr);
- GPRReg resultGPR = allocate();
- boxInt52(gpr, resultGPR, info.registerFormat());
- unlock(gpr);
- return resultGPR;
- }
case DataFormatCell:
// No retag required on JSVALUE64!
DataFormat spillFormat = info.spillFormat();
- RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
+ RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
returnFormat = DataFormatJSInt32;
return gpr;
}
- if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) {
- // Generally, this can only happen if we've already proved that the
- // value is an int32. That's because if a value originated as a JSValue
- // then we would speculate that it's an int32 before representing it as
- // an int52. Otherwise, if we knowingly produced an int52, then we would
- // be boxing it into a value using Int52ToValue. This assertion is valid
- // only because Int52 is something that we introduce at prediction time.
- // However: we may have an int32-producing node replaced by an
- // int52-producing node due to CSE. So we must do a check.
- RELEASE_ASSERT(!(type & ~SpecMachineInt));
- if (type & SpecInt52) {
- GPRReg temp = allocate();
- m_jit.signExtend32ToPtr(gpr, temp);
- // Currently, we can't supply value profiling information here. :-/
- speculationCheck(
- BadType, JSValueRegs(), 0,
- m_jit.branch64(MacroAssembler::NotEqual, gpr, temp));
- unlock(temp);
- }
- if (spillFormat == DataFormatStrictInt52)
- m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
- else {
- m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
- m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
- m_jit.zeroExtend32ToPtr(gpr, gpr);
- }
- info.fillInt32(*m_stream, gpr);
- returnFormat = DataFormatInt32;
- return gpr;
- }
m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
// Fill as JSValue, and fall through.
}
case DataFormatJS: {
- RELEASE_ASSERT(!(type & SpecInt52));
// Check the value is an integer.
GPRReg gpr = info.gpr();
m_gprs.lock(gpr);
returnFormat = DataFormatInt32;
return gpr;
}
-
- case DataFormatStrictInt52:
- case DataFormatInt52: {
- GPRReg gpr = info.gpr();
- GPRReg result;
- if (m_gprs.isLocked(gpr)) {
- result = allocate();
- m_jit.move(gpr, result);
- } else {
- lock(gpr);
- info.fillInt32(*m_stream, gpr);
- result = gpr;
- }
- RELEASE_ASSERT(!(type & ~SpecMachineInt));
- if (info.registerFormat() == DataFormatInt52)
- m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
- if (type & SpecInt52) {
- GPRReg temp = allocate();
- m_jit.signExtend32ToPtr(result, temp);
- // Currently, we can't supply value profiling information here. :-/
- speculationCheck(
- BadType, JSValueRegs(), 0,
- m_jit.branch64(MacroAssembler::NotEqual, result, temp));
- unlock(temp);
- }
- m_jit.zeroExtend32ToPtr(result, result);
- returnFormat = DataFormatInt32;
- return gpr;
- }
case DataFormatDouble:
case DataFormatJSDouble: {
return result;
}
-GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
-{
- ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
- AbstractValue& value = m_state.forNode(edge);
- SpeculatedType type = value.m_type;
- m_interpreter.filter(value, SpecMachineInt);
- VirtualRegister virtualRegister = edge->virtualRegister();
- GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
-
- switch (info.registerFormat()) {
- case DataFormatNone: {
- if ((edge->hasConstant() && !valueOfJSConstant(edge.node()).isMachineInt()) || info.spillFormat() == DataFormatDouble) {
- terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
- return allocate();
- }
-
- GPRReg gpr = allocate();
-
- if (edge->hasConstant()) {
- JSValue jsValue = valueOfJSConstant(edge.node());
- ASSERT(jsValue.isMachineInt());
- m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
- int64_t value = jsValue.asMachineInt();
- if (desiredFormat == DataFormatInt52)
- value = value << JSValue::int52ShiftAmount;
- m_jit.move(MacroAssembler::Imm64(value), gpr);
- info.fillGPR(*m_stream, gpr, desiredFormat);
- return gpr;
- }
-
- DataFormat spillFormat = info.spillFormat();
-
- RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
-
- m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
-
- if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {
- // If we know this was spilled as an integer we can fill without checking.
- m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
- m_jit.signExtend32ToPtr(gpr, gpr);
- if (desiredFormat == DataFormatStrictInt52) {
- info.fillStrictInt52(*m_stream, gpr);
- return gpr;
- }
- m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
- info.fillInt52(*m_stream, gpr);
- return gpr;
- }
- if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) {
- m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
- if (desiredFormat == DataFormatStrictInt52) {
- if (spillFormat == DataFormatInt52)
- m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
- info.fillStrictInt52(*m_stream, gpr);
- return gpr;
- }
- if (spillFormat == DataFormatStrictInt52)
- m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
- info.fillInt52(*m_stream, gpr);
- return gpr;
- }
- m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
-
- // Fill as JSValue, and fall through.
- info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
- m_gprs.unlock(gpr);
- }
-
- case DataFormatJS: {
- // Check the value is an integer. Note that we would *like* to unbox an Int52
- // at this point but this is too costly. We only *prove* that this is an Int52
- // even though we check if it's an int32.
- GPRReg gpr = info.gpr();
- GPRReg result;
- if (m_gprs.isLocked(gpr)) {
- result = allocate();
- m_jit.move(gpr, result);
- } else {
- m_gprs.lock(gpr);
- result = gpr;
- }
- if (type & ~SpecInt32)
- speculationCheck(BadType, JSValueRegs(result), edge, m_jit.branch64(MacroAssembler::Below, result, GPRInfo::tagTypeNumberRegister));
- if (result == gpr) // The not-already-locked, so fill in-place, case.
- info.fillInt52(*m_stream, gpr, desiredFormat);
- m_jit.signExtend32ToPtr(result, result);
- if (desiredFormat == DataFormatInt52)
- m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
- return result;
- }
-
- case DataFormatInt32:
- case DataFormatJSInt32: {
- GPRReg gpr = info.gpr();
- GPRReg result;
- if (m_gprs.isLocked(gpr)) {
- result = allocate();
- m_jit.move(gpr, result);
- } else {
- m_gprs.lock(gpr);
- info.fillInt52(*m_stream, gpr, desiredFormat);
- result = gpr;
- }
- m_jit.signExtend32ToPtr(result, result);
- if (desiredFormat == DataFormatInt52)
- m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
- return result;
- }
-
- case DataFormatStrictInt52: {
- GPRReg gpr = info.gpr();
- bool wasLocked = m_gprs.isLocked(gpr);
- lock(gpr);
- if (desiredFormat == DataFormatStrictInt52)
- return gpr;
- if (wasLocked) {
- GPRReg result = allocate();
- m_jit.move(gpr, result);
- unlock(gpr);
- gpr = result;
- } else
- info.fillStrictInt52(*m_stream, gpr);
- m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
- return gpr;
- }
-
- case DataFormatInt52: {
- GPRReg gpr = info.gpr();
- bool wasLocked = m_gprs.isLocked(gpr);
- lock(gpr);
- if (desiredFormat == DataFormatInt52)
- return gpr;
- if (wasLocked) {
- GPRReg result = allocate();
- m_jit.move(gpr, result);
- unlock(gpr);
- gpr = result;
- } else
- info.fillInt52(*m_stream, gpr);
- m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
- return gpr;
- }
-
- case DataFormatDouble:
- case DataFormatJSDouble:
- if (edge->hasConstant()) {
- JSValue jsValue = valueOfJSConstant(edge.node());
- if (jsValue.isMachineInt()) {
- int64_t value = jsValue.asMachineInt();
- if (desiredFormat == DataFormatInt52)
- value = value << JSValue::int52ShiftAmount;
- GPRReg gpr = allocate();
- m_jit.move(MacroAssembler::Imm64(value), gpr);
- return gpr;
- }
- }
-
- case DataFormatCell:
- case DataFormatBoolean:
- case DataFormatJSCell:
- case DataFormatJSBoolean: {
- terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
- return allocate();
- }
-
- case DataFormatStorage:
- RELEASE_ASSERT_NOT_REACHED();
-
- default:
- RELEASE_ASSERT_NOT_REACHED();
- return InvalidGPRReg;
- }
-}
-
FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
{
#if DFG_ENABLE(DEBUG_VERBOSE)
#endif
AbstractValue& value = m_state.forNode(edge);
SpeculatedType type = value.m_type;
- ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecFullNumber));
- m_interpreter.filter(value, SpecFullNumber);
+ ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecNumber));
+ m_interpreter.filter(value, SpecNumber);
VirtualRegister virtualRegister = edge->virtualRegister();
GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
unlock(gpr);
break;
}
-
- case DataFormatInt52: {
- GPRReg gpr = allocate();
- m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
- m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
- info.fillInt52(*m_stream, gpr);
- unlock(gpr);
- break;
- }
-
- case DataFormatStrictInt52: {
- GPRReg gpr = allocate();
- m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
- m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
- info.fillStrictInt52(*m_stream, gpr);
- unlock(gpr);
- break;
- }
default:
GPRReg gpr = allocate();
JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
- if (type & ~SpecFullNumber)
+ if (type & ~SpecNumber)
speculationCheck(BadType, JSValueRegs(jsValueGpr), edge, m_jit.branchTest64(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
// First, if we get here we have a double encoded as a JSValue
m_gprs.unlock(gpr);
return fpr;
}
-
- case DataFormatInt52: {
- FPRReg fpr = fprAllocate();
- GPRReg gpr = info.gpr();
- m_gprs.lock(gpr);
- GPRReg temp = allocate();
- m_jit.move(gpr, temp);
- m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), temp);
- m_jit.convertInt64ToDouble(temp, fpr);
- unlock(temp);
- m_gprs.unlock(gpr);
- return fpr;
- }
-
- case DataFormatStrictInt52: {
- FPRReg fpr = fprAllocate();
- GPRReg gpr = info.gpr();
- m_gprs.lock(gpr);
- m_jit.convertInt64ToDouble(gpr, fpr);
- m_gprs.unlock(gpr);
- return fpr;
- }
// Unbox the double
case DataFormatJSDouble: {
case DataFormatJSDouble:
case DataFormatDouble:
case DataFormatJSBoolean:
- case DataFormatBoolean:
- case DataFormatInt52:
- case DataFormatStrictInt52: {
+ case DataFormatBoolean: {
terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
return allocate();
}
case DataFormatJSDouble:
case DataFormatDouble:
case DataFormatJSCell:
- case DataFormatCell:
- case DataFormatInt52:
- case DataFormatStrictInt52: {
+ case DataFormatCell: {
terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
return allocate();
}
jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
}
-void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
-{
- SpeculateWhicheverInt52Operand op1(this, node->child1());
- SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
- GPRTemporary result(this, Reuse, op1, op2);
-
- m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
-
- // If we add a DataFormatBool, we should use it here.
- m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
- jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
-}
-
-void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
-{
- BasicBlock* taken = branchNode->takenBlock();
- BasicBlock* notTaken = branchNode->notTakenBlock();
-
- // The branch instruction will branch to the taken block.
- // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
- if (taken == nextBlock()) {
- condition = JITCompiler::invert(condition);
- BasicBlock* tmp = taken;
- taken = notTaken;
- notTaken = tmp;
- }
-
- SpeculateWhicheverInt52Operand op1(this, node->child1());
- SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
-
- branch64(condition, op1.gpr(), op2.gpr(), taken);
- jump(notTaken);
-}
-
void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition)
{
SpeculateDoubleOperand op1(this, node->child1());
break;
}
- case FlushedInt52: {
- GPRTemporary result(this);
- m_jit.load64(JITCompiler::addressFor(node->local()), result.gpr());
-
- VirtualRegister virtualRegister = node->virtualRegister();
- m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
- generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
- break;
- }
-
default:
GPRTemporary result(this);
m_jit.load64(JITCompiler::addressFor(node->local()), result.gpr());
break;
}
- case FlushedInt52: {
- SpeculateInt52Operand value(this, node->child1());
- m_jit.store64(value.gpr(), JITCompiler::addressFor(node->local()));
- noResult(node);
- recordSetLocal(node->local(), ValueSource(Int52InJSStack));
- break;
- }
-
case FlushedCell: {
SpeculateCellOperand cell(this, node->child1());
GPRReg cellGPR = cell.gpr();
break;
}
- case Int52ToValue: {
- JSValueOperand operand(this, node->child1());
- GPRTemporary result(this, Reuse, operand);
- m_jit.move(operand.gpr(), result.gpr());
- jsValueResult(result.gpr(), node);
- break;
- }
-
- case Int52ToDouble: {
- SpeculateDoubleOperand operand(this, node->child1());
- FPRTemporary result(this, operand);
- m_jit.moveDouble(operand.fpr(), result.fpr());
- doubleResult(result.fpr(), node);
- break;
- }
-
case ValueAdd:
case ArithAdd:
compileAdd(node);
FPRReg valueFPR = value.fpr();
DFG_TYPE_CHECK(
- JSValueRegs(), node->child2(), SpecFullRealNumber,
+ JSValueRegs(), node->child2(), SpecRealNumber,
m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
op1.use();
- if (!(m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean)))
+ if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean)))
m_jit.move(op1GPR, resultGPR);
else {
MacroAssembler::Jump alreadyPrimitive = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
SpeculateDoubleOperand operand(this, use);
FPRReg opFPR = operand.fpr();
DFG_TYPE_CHECK(
- JSValueRegs(), use, SpecFullRealNumber,
+ JSValueRegs(), use, SpecRealNumber,
m_jit.branchDouble(
MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx));
FPRReg opFPR = operand.fpr();
GPRReg scratchGPR = scratch.gpr();
DFG_TYPE_CHECK(
- JSValueRegs(), use, SpecFullRealNumber,
+ JSValueRegs(), use, SpecRealNumber,
m_jit.branchDouble(
MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
m_jit.boxDouble(opFPR, scratchGPR);
case KnownInt32Use:
out.print("KnownInt32");
break;
- case MachineIntUse:
- out.print("MachineInt");
- break;
case RealNumberUse:
out.print("RealNumber");
break;
UntypedUse,
Int32Use,
KnownInt32Use,
- MachineIntUse,
RealNumberUse,
NumberUse,
KnownNumberUse,
case Int32Use:
case KnownInt32Use:
return SpecInt32;
- case MachineIntUse:
- return SpecMachineInt;
case RealNumberUse:
- return SpecFullRealNumber;
+ return SpecRealNumber;
case NumberUse:
case KnownNumberUse:
- return SpecFullNumber;
+ return SpecNumber;
case BooleanUse:
return SpecBoolean;
case CellUse:
switch (kind) {
case Int32Use:
case KnownInt32Use:
- case MachineIntUse:
case RealNumberUse:
case NumberUse:
case KnownNumberUse:
case Int32InJSStack:
out.print("Int32");
break;
- case Int52InJSStack:
- out.print("Int52");
- break;
case CellInJSStack:
out.print("Cell");
break;
SourceNotSet,
ValueInJSStack,
Int32InJSStack,
- Int52InJSStack,
CellInJSStack,
BooleanInJSStack,
DoubleInJSStack,
switch (dataFormat) {
case DataFormatInt32:
return Int32InJSStack;
- case DataFormatInt52:
- return Int52InJSStack;
case DataFormatDouble:
return DoubleInJSStack;
case DataFormatBoolean:
return DataFormatJS;
case Int32InJSStack:
return DataFormatInt32;
- case Int52InJSStack:
- return DataFormatInt52;
case CellInJSStack:
return DataFormatCell;
case BooleanInJSStack:
return ValueSource(DoubleInJSStack);
case FlushedInt32:
return ValueSource(Int32InJSStack);
- case FlushedInt52:
- return ValueSource(Int52InJSStack);
case FlushedCell:
return ValueSource(CellInJSStack);
case FlushedBoolean:
case Int32InJSStack:
return ValueRecovery::alreadyInJSStackAsUnboxedInt32();
- case Int52InJSStack:
- return ValueRecovery::alreadyInJSStackAsUnboxedInt52();
-
case CellInJSStack:
return ValueRecovery::alreadyInJSStackAsUnboxedCell();
// If the variable is not a number prediction, then this doesn't
// make any sense.
- if (!isFullNumberSpeculation(prediction())) {
+ if (!isNumberSpeculation(prediction())) {
// FIXME: we may end up forcing a local in inlined argument position to be a double even
// if it is sometimes not even numeric, since this never signals the fact that it doesn't
// want doubles. https://bugs.webkit.org/show_bug.cgi?id=109511
if (isInt32Speculation(prediction))
return FlushedInt32;
- if (enableInt52() && !operandIsArgument(m_local) && isMachineIntSpeculation(prediction))
- return FlushedInt52;
-
if (isCellSpeculation(prediction))
return FlushedCell;
using namespace DFG;
-void CArgumentGetter::loadNextAndBox(
- ValueFormat format, GPRReg destination, GPRReg scratch1, GPRReg scratch2)
+void CArgumentGetter::loadNextAndBox(ValueFormat format, GPRReg destination, GPRReg scratch)
{
- if (scratch1 == InvalidGPRReg) {
- ASSERT(scratch2 == InvalidGPRReg);
+ if (scratch == InvalidGPRReg) {
if (destination == GPRInfo::nonArgGPR0)
- scratch1 = GPRInfo::nonArgGPR1;
+ scratch = GPRInfo::nonArgGPR1;
else
- scratch1 = GPRInfo::nonArgGPR0;
- }
- if (scratch2 == InvalidGPRReg) {
- if (destination != GPRInfo::nonArgGPR0 && scratch1 != GPRInfo::nonArgGPR0)
- scratch2 = GPRInfo::nonArgGPR0;
- else if (destination != GPRInfo::nonArgGPR1 && scratch1 != GPRInfo::nonArgGPR1)
- scratch2 = GPRInfo::nonArgGPR1;
- else
- scratch2 = GPRInfo::nonArgGPR2;
+ scratch = GPRInfo::nonArgGPR0;
}
switch (format) {
case ValueFormatUInt32: {
loadNext32(destination);
- m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2);
- m_jit.boxInt52(destination, destination, scratch1, FPRInfo::fpRegT0);
- m_jit.move64ToDouble(scratch2, FPRInfo::fpRegT0);
- break;
- }
-
- case ValueFormatInt52: {
- loadNext64(destination);
- m_jit.rshift64(AssemblyHelpers::TrustedImm32(JSValue::int52ShiftAmount), destination);
- m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2);
- m_jit.boxInt52(destination, destination, scratch1, FPRInfo::fpRegT0);
- m_jit.move64ToDouble(scratch2, FPRInfo::fpRegT0);
- break;
- }
+ MacroAssembler::Jump isInt = m_jit.branch32(
+ MacroAssembler::GreaterThanOrEqual,
+ destination, MacroAssembler::TrustedImm32(0));
- case ValueFormatStrictInt52: {
- loadNext64(destination);
- m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2);
- m_jit.boxInt52(destination, destination, scratch1, FPRInfo::fpRegT0);
- m_jit.move64ToDouble(scratch2, FPRInfo::fpRegT0);
+ m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch);
+ m_jit.convertInt32ToDouble(destination, FPRInfo::fpRegT0);
+ m_jit.boxDouble(FPRInfo::fpRegT0, destination);
+ m_jit.move64ToDouble(scratch, FPRInfo::fpRegT0);
+
+ MacroAssembler::Jump done = m_jit.jump();
+
+ isInt.link(&m_jit);
+ m_jit.or64(GPRInfo::tagTypeNumberRegister, destination);
+
+ done.link(&m_jit);
break;
}
}
case ValueFormatDouble: {
- m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch1);
+ m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch);
loadNextDouble(FPRInfo::fpRegT0);
m_jit.boxDouble(FPRInfo::fpRegT0, destination);
- m_jit.move64ToDouble(scratch1, FPRInfo::fpRegT0);
+ m_jit.move64ToDouble(scratch, FPRInfo::fpRegT0);
break;
}
}
void loadNextAndBox(
- ValueFormat, DFG::GPRReg destination,
- DFG::GPRReg scratch1 = InvalidGPRReg, DFG::GPRReg scratch2 = InvalidGPRReg);
+ ValueFormat format, DFG::GPRReg destination, DFG::GPRReg scratch = InvalidGPRReg);
private:
MacroAssembler::Address nextAddress()
case CompareStrictEq:
if (node->isBinaryUseKind(Int32Use))
break;
- if (node->isBinaryUseKind(MachineIntUse))
- break;
if (node->isBinaryUseKind(NumberUse))
break;
if (node->isBinaryUseKind(ObjectUse))
case CompareGreaterEq:
if (node->isBinaryUseKind(Int32Use))
break;
- if (node->isBinaryUseKind(MachineIntUse))
- break;
if (node->isBinaryUseKind(NumberUse))
break;
return CannotCompile;
case UntypedUse:
case Int32Use:
case KnownInt32Use:
- case MachineIntUse:
case NumberUse:
case KnownNumberUse:
case RealNumberUse:
case ExitValueInJSStackAsInt32:
out.print("InJSStackAsInt32");
return;
- case ExitValueInJSStackAsInt52:
- out.print("InJSStackAsInt52");
- return;
case ExitValueInJSStackAsDouble:
out.print("InJSStackAsDouble");
return;
ExitValueConstant,
ExitValueInJSStack,
ExitValueInJSStackAsInt32,
- ExitValueInJSStackAsInt52,
ExitValueInJSStackAsDouble
};
return result;
}
- static ExitValue inJSStackAsInt52()
- {
- ExitValue result;
- result.m_kind = ExitValueInJSStackAsInt52;
- return result;
- }
-
static ExitValue inJSStackAsDouble()
{
ExitValue result;
#define FOR_EACH_FTL_INTRINSIC(macro) \
macro(addWithOverflow32, "llvm.sadd.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \
- macro(addWithOverflow64, "llvm.sadd.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \
macro(doubleAbs, "llvm.fabs.f64", functionType(doubleType, doubleType)) \
macro(mulWithOverflow32, "llvm.smul.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \
- macro(mulWithOverflow64, "llvm.smul.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \
macro(subWithOverflow32, "llvm.ssub.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \
- macro(subWithOverflow64, "llvm.ssub.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \
macro(trap, "llvm.trap", functionType(voidType)) \
macro(osrExit, "webkit_osr_exit", functionType(voidType, boolean, int32, Variadic))
case NodeResultInt32:
type = m_out.int32;
break;
- case NodeResultInt52:
- type = m_out.int64;
- break;
case NodeResultBoolean:
type = m_out.boolean;
break;
compilePhi();
break;
case JSConstant:
+ compileJSConstant();
break;
case WeakJSConstant:
compileWeakJSConstant();
case Int32Use:
m_out.set(lowInt32(m_node->child1()), destination);
break;
- case MachineIntUse:
- m_out.set(lowInt52(m_node->child1()), destination);
- break;
case BooleanUse:
m_out.set(lowBoolean(m_node->child1()), destination);
break;
case NodeResultInt32:
setInt32(m_out.get(source));
break;
- case NodeResultInt52:
- setInt52(m_out.get(source));
- break;
case NodeResultBoolean:
setBoolean(m_out.get(source));
break;
return;
}
- case FlushedInt52: {
- LValue value = lowInt52(m_node->child1());
- m_out.store64(value, addressFor(variable->local()));
- m_valueSources.operand(variable->local()) = ValueSource(Int52InJSStack);
- return;
- }
-
case FlushedCell: {
LValue value = lowCell(m_node->child1());
m_out.store64(value, addressFor(variable->local()));
break;
}
- case MachineIntUse: {
- if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)
- && !m_state.forNode(m_node->child2()).couldBeType(SpecInt52)) {
- Int52Kind kind;
- LValue left = lowWhicheverInt52(m_node->child1(), kind);
- LValue right = lowInt52(m_node->child2(), kind);
- setInt52(m_out.add(left, right), kind);
- break;
- }
-
- LValue left = lowInt52(m_node->child1());
- LValue right = lowInt52(m_node->child2());
- LValue result = m_out.addWithOverflow64(left, right);
- speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1));
- setInt52(m_out.extractValue(result, 0));
- break;
- }
-
case NumberUse: {
setDouble(
m_out.doubleAdd(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
break;
}
- case MachineIntUse: {
- if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)
- && !m_state.forNode(m_node->child2()).couldBeType(SpecInt52)) {
- Int52Kind kind;
- LValue left = lowWhicheverInt52(m_node->child1(), kind);
- LValue right = lowInt52(m_node->child2(), kind);
- setInt52(m_out.sub(left, right), kind);
- break;
- }
-
- LValue left = lowInt52(m_node->child1());
- LValue right = lowInt52(m_node->child2());
- LValue result = m_out.subWithOverflow64(left, right);
- speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1));
- setInt52(m_out.extractValue(result, 0));
- break;
- }
-
case NumberUse: {
setDouble(
m_out.doubleSub(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
break;
}
- case MachineIntUse: {
- Int52Kind kind;
- LValue left = lowWhicheverInt52(m_node->child1(), kind);
- LValue right = lowInt52(m_node->child2(), opposite(kind));
-
- LValue overflowResult = m_out.mulWithOverflow64(left, right);
- speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
- LValue result = m_out.extractValue(overflowResult, 0);
-
- if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
- LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
- LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation"));
-
- m_out.branch(m_out.notZero64(result), continuation, slowCase);
-
- LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
- speculate(NegativeZero, noValue(), 0, m_out.lessThan(left, m_out.int64Zero));
- speculate(NegativeZero, noValue(), 0, m_out.lessThan(right, m_out.int64Zero));
- m_out.jump(continuation);
- m_out.appendTo(continuation, lastNext);
- }
-
- setInt52(result);
- break;
- }
-
case NumberUse: {
setDouble(
m_out.doubleMul(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
break;
}
- case MachineIntUse: {
- if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)) {
- Int52Kind kind;
- LValue value = lowWhicheverInt52(m_node->child1(), kind);
- LValue result = m_out.neg(value);
- if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags()))
- speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
- setInt52(result, kind);
- break;
- }
-
- LValue value = lowInt52(m_node->child1());
- LValue overflowResult = m_out.subWithOverflow64(m_out.int64Zero, value);
- speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
- LValue result = m_out.extractValue(overflowResult, 0);
- speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
- setInt52(result);
- break;
- }
-
case NumberUse: {
setDouble(m_out.doubleNeg(lowDouble(m_node->child1())));
break;
LValue value = lowDouble(child3);
FTL_TYPE_CHECK(
- doubleValue(value), child3, SpecFullRealNumber,
+ doubleValue(value), child3, SpecRealNumber,
m_out.doubleNotEqualOrUnordered(value, value));
TypedPointer elementPointer = m_out.baseIndex(
void compileCompareEq()
{
if (m_node->isBinaryUseKind(Int32Use)
- || m_node->isBinaryUseKind(MachineIntUse)
|| m_node->isBinaryUseKind(NumberUse)
|| m_node->isBinaryUseKind(ObjectUse)) {
compileCompareStrictEq();
return;
}
- if (m_node->isBinaryUseKind(MachineIntUse)) {
- Int52Kind kind;
- LValue left = lowWhicheverInt52(m_node->child1(), kind);
- LValue right = lowInt52(m_node->child2(), kind);
- setBoolean(m_out.equal(left, right));
- return;
- }
-
if (m_node->isBinaryUseKind(NumberUse)) {
setBoolean(
m_out.doubleEqual(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
return;
}
- if (m_node->isBinaryUseKind(MachineIntUse)) {
- Int52Kind kind;
- LValue left = lowWhicheverInt52(m_node->child1(), kind);
- LValue right = lowInt52(m_node->child2(), kind);
- setBoolean(m_out.lessThan(left, right));
- return;
- }
-
if (m_node->isBinaryUseKind(NumberUse)) {
setBoolean(
m_out.doubleLessThan(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
return;
}
- if (m_node->isBinaryUseKind(MachineIntUse)) {
- Int52Kind kind;
- LValue left = lowWhicheverInt52(m_node->child1(), kind);
- LValue right = lowInt52(m_node->child2(), kind);
- setBoolean(m_out.lessThanOrEqual(left, right));
- return;
- }
-
if (m_node->isBinaryUseKind(NumberUse)) {
setBoolean(
m_out.doubleLessThanOrEqual(
return;
}
- if (m_node->isBinaryUseKind(MachineIntUse)) {
- Int52Kind kind;
- LValue left = lowWhicheverInt52(m_node->child1(), kind);
- LValue right = lowInt52(m_node->child2(), kind);
- setBoolean(m_out.greaterThan(left, right));
- return;
- }
-
if (m_node->isBinaryUseKind(NumberUse)) {
setBoolean(
m_out.doubleGreaterThan(
return;
}
- if (m_node->isBinaryUseKind(MachineIntUse)) {
- Int52Kind kind;
- LValue left = lowWhicheverInt52(m_node->child1(), kind);
- LValue right = lowInt52(m_node->child2(), kind);
- setBoolean(m_out.greaterThanOrEqual(left, right));
- return;
- }
-
if (m_node->isBinaryUseKind(NumberUse)) {
setBoolean(
m_out.doubleGreaterThanOrEqual(
{
ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
- if (edge->hasConstant()) {
- JSValue value = m_graph.valueOfJSConstant(edge.node());
- if (!value.isInt32()) {
- terminate(Uncountable);
- return m_out.int32Zero;
- }
- return m_out.constInt32(value.asInt32());
- }
-
LoweredNodeValue value = m_int32Values.get(edge.node());
if (isValid(value))
return value.value();
- value = m_strictInt52Values.get(edge.node());
- if (isValid(value))
- return strictInt52ToInt32(edge, value.value());
-
- value = m_int52Values.get(edge.node());
- if (isValid(value))
- return strictInt52ToInt32(edge, int52ToStrictInt52(value.value()));
-
value = m_jsValueValues.get(edge.node());
if (isValid(value)) {
LValue boxedResult = value.value();
return m_out.int32Zero;
}
- enum Int52Kind { StrictInt52, Int52 };
- LValue lowInt52(Edge edge, Int52Kind kind, OperandSpeculationMode mode = AutomaticOperandSpeculation)
- {
- ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
-
- if (edge->hasConstant()) {
- JSValue value = m_graph.valueOfJSConstant(edge.node());
- if (!value.isMachineInt()) {
- terminate(Uncountable);
- return m_out.int64Zero;
- }
- int64_t result = value.asMachineInt();
- if (kind == Int52)
- result <<= JSValue::int52ShiftAmount;
- return m_out.constInt64(result);
- }
-
- LoweredNodeValue value;
-
- switch (kind) {
- case Int52:
- value = m_int52Values.get(edge.node());
- if (isValid(value))
- return value.value();
-
- value = m_strictInt52Values.get(edge.node());
- if (isValid(value))
- return strictInt52ToInt52(value.value());
- break;
-
- case StrictInt52:
- value = m_strictInt52Values.get(edge.node());
- if (isValid(value))
- return value.value();
-
- value = m_int52Values.get(edge.node());
- if (isValid(value))
- return int52ToStrictInt52(value.value());
- break;
- }
-
- value = m_int32Values.get(edge.node());
- if (isValid(value)) {
- return setInt52WithStrictValue(
- edge.node(), m_out.signExt(value.value(), m_out.int64), kind);
- }
-
- RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecInt52));
-
- value = m_jsValueValues.get(edge.node());
- if (isValid(value)) {
- LValue boxedResult = value.value();
- FTL_TYPE_CHECK(
- jsValueValue(boxedResult), edge, SpecMachineInt, isNotInt32(boxedResult));
- return setInt52WithStrictValue(
- edge.node(), m_out.signExt(unboxInt32(boxedResult), m_out.int64), kind);
- }
-
- RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecMachineInt));
- terminate(Uncountable);
- return m_out.int64Zero;
- }
-
- LValue lowInt52(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
- {
- return lowInt52(edge, Int52, mode);
- }
-
- LValue lowStrictInt52(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
- {
- return lowInt52(edge, StrictInt52, mode);
- }
-
- bool betterUseStrictInt52(Node* node)
- {
- return !isValid(m_int52Values.get(node));
- }
- bool betterUseStrictInt52(Edge edge)
- {
- return betterUseStrictInt52(edge.node());
- }
- template<typename T>
- Int52Kind bestInt52Kind(T node)
- {
- return betterUseStrictInt52(node) ? StrictInt52 : Int52;
- }
- Int52Kind opposite(Int52Kind kind)
- {
- switch (kind) {
- case Int52:
- return StrictInt52;
- case StrictInt52:
- return Int52;
- }
- RELEASE_ASSERT_NOT_REACHED();
- }
-
- LValue lowWhicheverInt52(Edge edge, Int52Kind& kind, OperandSpeculationMode mode = AutomaticOperandSpeculation)
- {
- kind = bestInt52Kind(edge);
- return lowInt52(edge, kind, mode);
- }
-
LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
{
ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind()));
- if (edge->op() == JSConstant) {
- JSValue value = m_graph.valueOfJSConstant(edge.node());
- if (!value.isCell()) {
- terminate(Uncountable);
- return m_out.intPtrZero;
- }
- return m_out.constIntPtr(value.asCell());
- }
-
LoweredNodeValue value = m_jsValueValues.get(edge.node());
if (isValid(value)) {
LValue uncheckedValue = value.value();
{
ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse);
- if (edge->hasConstant()) {
- JSValue value = m_graph.valueOfJSConstant(edge.node());
- if (!value.isBoolean()) {
- terminate(Uncountable);
- return m_out.booleanFalse;
- }
- return m_out.constBool(value.asBoolean());
- }
-
LoweredNodeValue value = m_booleanValues.get(edge.node());
if (isValid(value))
return value.value();
{
ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind()));
- if (edge->hasConstant()) {
- JSValue value = m_graph.valueOfJSConstant(edge.node());
- if (!value.isNumber()) {
- terminate(Uncountable);
- return m_out.doubleZero;
- }
- return m_out.constDouble(value.asNumber());
- }
-
LoweredNodeValue value = m_doubleValues.get(edge.node());
if (isValid(value))
return value.value();
return result;
}
- value = m_strictInt52Values.get(edge.node());
- if (isValid(value))
- return strictInt52ToDouble(edge, value.value());
-
- value = m_int52Values.get(edge.node());
- if (isValid(value))
- return strictInt52ToDouble(edge, int52ToStrictInt52(value.value()));
-
value = m_jsValueValues.get(edge.node());
if (isValid(value)) {
LValue boxedResult = value.value();
m_out.appendTo(doubleCase, continuation);
FTL_TYPE_CHECK(
- jsValueValue(boxedResult), edge, SpecFullNumber, isCellOrMisc(boxedResult));
+ jsValueValue(boxedResult), edge, SpecNumber, isCellOrMisc(boxedResult));
ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedResult));
m_out.jump(continuation);
return result;
}
- RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecFullNumber));
+ RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecNumber));
terminate(Uncountable);
return m_out.doubleZero;
}
{
ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
- if (edge->hasConstant())
- return m_out.constInt64(JSValue::encode(m_graph.valueOfJSConstant(edge.node())));
-
LoweredNodeValue value = m_jsValueValues.get(edge.node());
if (isValid(value))
return value.value();
return result;
}
- value = m_strictInt52Values.get(edge.node());
- if (isValid(value))
- return strictInt52ToJSValue(value.value());
-
- value = m_int52Values.get(edge.node());
- if (isValid(value))
- return strictInt52ToJSValue(int52ToStrictInt52(value.value()));
-
value = m_booleanValues.get(edge.node());
if (isValid(value)) {
LValue result = boxBoolean(value.value());
return result;
}
- LValue strictInt52ToInt32(Edge edge, LValue value)
- {
- LValue result = m_out.castToInt32(value);
- FTL_TYPE_CHECK(
- noValue(), edge, SpecInt32,
- m_out.notEqual(m_out.signExt(result, m_out.int64), value));
- setInt32(edge.node(), result);
- return result;
- }
-
- LValue strictInt52ToDouble(Edge edge, LValue value)
- {
- LValue result = m_out.intToDouble(value);
- setDouble(edge.node(), result);
- return result;
- }
-
- LValue strictInt52ToJSValue(LValue value)
- {
- LBasicBlock isInt32 = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue isInt32 case"));
- LBasicBlock isDouble = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue isDouble case"));
- LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue continuation"));
-
- Vector<ValueFromBlock, 2> results;
-
- LValue int32Value = m_out.castToInt32(value);
- m_out.branch(
- m_out.equal(m_out.signExt(int32Value, m_out.int64), value),
- isInt32, isDouble);
-
- LBasicBlock lastNext = m_out.appendTo(isInt32, isDouble);
-
- results.append(m_out.anchor(boxInt32(int32Value)));
- m_out.jump(continuation);
-
- m_out.appendTo(isDouble, continuation);
-
- results.append(m_out.anchor(boxDouble(m_out.intToDouble(value))));
- m_out.jump(continuation);
-
- m_out.appendTo(continuation, lastNext);
- return m_out.phi(m_out.int64, results);
- }
-
- LValue setInt52WithStrictValue(Node* node, LValue value, Int52Kind kind)
- {
- switch (kind) {
- case StrictInt52:
- setStrictInt52(node, value);
- return value;
-
- case Int52:
- value = strictInt52ToInt52(value);
- setInt52(node, value);
- return value;
- }
-
- RELEASE_ASSERT_NOT_REACHED();
- return 0;
- }
-
- LValue strictInt52ToInt52(LValue value)
- {
- return m_out.shl(value, m_out.constInt64(JSValue::int52ShiftAmount));
- }
-
- LValue int52ToStrictInt52(LValue value)
- {
- return m_out.aShr(value, m_out.constInt64(JSValue::int52ShiftAmount));
- }
-
LValue isNotInt32(LValue jsValue)
{
return m_out.below(jsValue, m_tagTypeNumber);
LValue value = lowDouble(edge);
FTL_TYPE_CHECK(
- doubleValue(value), edge, SpecFullRealNumber,
+ doubleValue(value), edge, SpecRealNumber,
m_out.doubleNotEqualOrUnordered(value, value));
}
{
lowBoolean(edge);
}
-
+
bool masqueradesAsUndefinedWatchpointIsStillValid()
{
return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->codeOrigin);
m_valueSources[i] = ValueSource(Int32InJSStack);
break;
- case FlushedInt52:
- m_valueSources[i] = ValueSource(Int52InJSStack);
- break;
-
case FlushedDouble:
m_valueSources[i] = ValueSource(DoubleInJSStack);
break;
case Int32InJSStack:
exit.m_values[i] = ExitValue::inJSStackAsInt32();
break;
- case Int52InJSStack:
- exit.m_values[i] = ExitValue::inJSStackAsInt52();
- break;
case DoubleInJSStack:
exit.m_values[i] = ExitValue::inJSStackAsDouble();
break;
return;
}
- value = m_int52Values.get(node);
- if (isValid(value)) {
- addExitArgument(exit, arguments, index, ValueFormatInt52, value.value());
- return;
- }
-
- value = m_strictInt52Values.get(node);
- if (isValid(value)) {
- addExitArgument(exit, arguments, index, ValueFormatStrictInt52, value.value());
- return;
- }
-
value = m_booleanValues.get(node);
if (isValid(value)) {
addExitArgument(exit, arguments, index, ValueFormatBoolean, value.value());
{
m_int32Values.set(node, LoweredNodeValue(value, m_highBlock));
}
- void setInt52(Node* node, LValue value)
- {
- m_int52Values.set(node, LoweredNodeValue(value, m_highBlock));
- }
- void setStrictInt52(Node* node, LValue value)
- {
- m_strictInt52Values.set(node, LoweredNodeValue(value, m_highBlock));
- }
- void setInt52(Node* node, LValue value, Int52Kind kind)
- {
- switch (kind) {
- case Int52:
- setInt52(node, value);
- return;
-
- case StrictInt52:
- setStrictInt52(node, value);
- return;
- }
-
- RELEASE_ASSERT_NOT_REACHED();
- }
void setJSValue(Node* node, LValue value)
{
m_jsValueValues.set(node, LoweredNodeValue(value, m_highBlock));
{
setInt32(m_node, value);
}
- void setInt52(LValue value)
- {
- setInt52(m_node, value);
- }
- void setStrictInt52(LValue value)
- {
- setStrictInt52(m_node, value);
- }
- void setInt52(LValue value, Int52Kind kind)
- {
- setInt52(m_node, value, kind);
- }
void setJSValue(LValue value)
{
setJSValue(m_node, value);
LValue m_tagMask;
HashMap<Node*, LoweredNodeValue> m_int32Values;
- HashMap<Node*, LoweredNodeValue> m_strictInt52Values;
- HashMap<Node*, LoweredNodeValue> m_int52Values;
HashMap<Node*, LoweredNodeValue> m_jsValueValues;
HashMap<Node*, LoweredNodeValue> m_booleanValues;
HashMap<Node*, LoweredNodeValue> m_storageValues;
jit.store64(GPRInfo::nonArgGPR0, AssemblyHelpers::addressFor(argument.operand()));
}
- // All temp registers are free at this point.
-
// Box anything that is already on the stack, or that is a constant.
for (unsigned i = exit.m_values.size(); i--;) {
jit.or64(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
jit.store64(GPRInfo::regT0, address);
break;
- case ExitValueInJSStackAsInt52:
- jit.load64(address, GPRInfo::regT0);
- jit.rshift64(
- AssemblyHelpers::TrustedImm32(JSValue::int52ShiftAmount), GPRInfo::regT0);
- jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0);
- jit.store64(GPRInfo::regT0, address);
- break;
case ExitValueInJSStackAsDouble:
jit.loadDouble(address, FPRInfo::fpRegT0);
jit.boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);
exit.m_code = FINALIZE_CODE_IF(
shouldShowDisassembly(),
patchBuffer,
- ("FTL OSR exit #%u (bc#%u, %s) from %s, with operands = %s",
+ ("FTL OSR exit #%u (bc#%u, %s) from %s",
exitID, exit.m_codeOrigin.bytecodeIndex,
- exitKindToString(exit.m_kind), toCString(*codeBlock).data(),
- toCString(ignoringContext<DumpContext>(exit.m_values)).data()));
+ exitKindToString(exit.m_kind), toCString(*codeBlock).data()));
}
extern "C" void* compileFTLOSRExit(ExecState* exec, unsigned exitID)
{
return call(mulWithOverflow32Intrinsic(), left, right);
}
- LValue addWithOverflow64(LValue left, LValue right)
- {
- return call(addWithOverflow64Intrinsic(), left, right);
- }
- LValue subWithOverflow64(LValue left, LValue right)
- {
- return call(subWithOverflow64Intrinsic(), left, right);
- }
- LValue mulWithOverflow64(LValue left, LValue right)
- {
- return call(mulWithOverflow64Intrinsic(), left, right);
- }
LValue doubleAbs(LValue value)
{
return call(doubleAbsIntrinsic(), value);
case ValueFormatUInt32:
out.print("UInt32");
return;
- case ValueFormatInt52:
- out.print("Int52");
- return;
- case ValueFormatStrictInt52:
- out.print("StrictInt52");
- return;
case ValueFormatBoolean:
out.print("Boolean");
return;
InvalidValueFormat,
ValueFormatInt32,
ValueFormatUInt32,
- ValueFormatInt52,
- ValueFormatStrictInt52,
ValueFormatBoolean,
ValueFormatJSValue,
ValueFormatDouble
case Int32InJSStack:
out.print("Int32InJSStack");
return;
- case Int52InJSStack:
- out.print("Int52InJSStack");
- return;
case DoubleInJSStack:
out.print("DoubleInJSStack");
return;
SourceNotSet,
ValueInJSStack,
Int32InJSStack,
- Int52InJSStack,
DoubleInJSStack,
SourceIsDead,
HaveNode
Instruction* vPC() const;
InlineCallFrame* asInlineCallFrame() const;
int32_t unboxedInt32() const;
- int64_t unboxedInt52() const;
bool unboxedBoolean() const;
double unboxedDouble() const;
JSCell* unboxedCell() const;
InlineCallFrame* inlineCallFrame;
EncodedValueDescriptor encodedValue;
double number;
- int64_t integer;
} u;
};
return payload();
}
- ALWAYS_INLINE int64_t Register::unboxedInt52() const
- {
- return u.integer >> JSValue::int52ShiftAmount;
- }
-
ALWAYS_INLINE bool Register::unboxedBoolean() const
{
return !!payload();
case AlreadyInJSStackAsUnboxedInt32:
value = jsNumber(location->unboxedInt32());
break;
- case AlreadyInJSStackAsUnboxedInt52:
- value = jsNumber(location->unboxedInt52());
- break;
case AlreadyInJSStackAsUnboxedCell:
value = location->unboxedCell();
break;
case ALL_INT32_INDEXING_TYPES:
if (isInt32Speculation(type))
return (indexingType & ~IndexingShapeMask) | Int32Shape;
- if (isFullNumberSpeculation(type))
+ if (isNumberSpeculation(type))
return (indexingType & ~IndexingShapeMask) | DoubleShape;
return (indexingType & ~IndexingShapeMask) | ContiguousShape;
case ALL_DOUBLE_INDEXING_TYPES:
- if (isFullNumberSpeculation(type))
+ if (isNumberSpeculation(type))
return indexingType;
return (indexingType & ~IndexingShapeMask) | ContiguousShape;
case ALL_CONTIGUOUS_INDEXING_TYPES:
int32_t asInt32() const;
uint32_t asUInt32() const;
- int64_t asMachineInt() const;
double asDouble() const;
bool asBoolean() const;
double asNumber() const;
bool isNull() const;
bool isUndefinedOrNull() const;
bool isBoolean() const;
- bool isMachineInt() const;
bool isNumber() const;
bool isString() const;
bool isPrimitive() const;
JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const;
- // Constants used for Int52. Int52 isn't part of JSValue right now, but JSValues may be
- // converted to Int52s and back again.
- static const unsigned numberOfInt52Bits = 52;
- static const unsigned int52ShiftAmount = 12;
-
private:
template <class T> JSValue(WriteBarrierBase<T>);
#endif // USE(JSVALUE64)
-inline bool JSValue::isMachineInt() const
-{
- if (isInt32())
- return true;
- if (!isNumber())
- return false;
- double number = asDouble();
- if (number != number)
- return false;
- int64_t asInt64 = static_cast<int64_t>(number);
- if (asInt64 != number)
- return false;
- if (!asInt64 && std::signbit(number))
- return false;
- if (asInt64 >= (static_cast<int64_t>(1) << (numberOfInt52Bits - 1)))
- return false;
- if (asInt64 < -(static_cast<int64_t>(1) << (numberOfInt52Bits - 1)))
- return false;
- return true;
-}
-
-inline int64_t JSValue::asMachineInt() const
-{
- ASSERT(isMachineInt());
- if (isInt32())
- return asInt32();
- return static_cast<int64_t>(asDouble());
-}
-
inline bool JSValue::isString() const
{
return isCell() && asCell()->isString();
+2013-09-18 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r156019 and r156020.
+ http://trac.webkit.org/changeset/156019
+ http://trac.webkit.org/changeset/156020
+ https://bugs.webkit.org/show_bug.cgi?id=121540
+
+ Broke tests (Requested by ap on #webkit).
+
+ * wtf/PrintStream.h:
+
2013-09-16 Filip Pizlo <fpizlo@apple.com>
DFG should support Int52 for local variables
return ValueInContext<T, U>(value, context);
}
-template<typename T, typename U>
-class ValueIgnoringContext {
-public:
- ValueIgnoringContext(const U& value)
- : m_value(&value)
- {
- }
-
- void dump(PrintStream& out) const
- {
- T context;
- m_value->dumpInContext(out, &context);
- }
-
-private:
- const U* m_value;
-};
-
-template<typename T, typename U>
-ValueIgnoringContext<T, U> ignoringContext(const U& value)
-{
- return ValueIgnoringContext<T, U>(value);
-}
-
} // namespace WTF
using WTF::CharacterDump;
using WTF::PointerDump;
using WTF::PrintStream;
-using WTF::ignoringContext;
using WTF::inContext;
using WTF::pointerDump;
+2013-09-18 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r156019 and r156020.
+ http://trac.webkit.org/changeset/156019
+ http://trac.webkit.org/changeset/156020
+ https://bugs.webkit.org/show_bug.cgi?id=121540
+
+ Broke tests (Requested by ap on #webkit).
+
+ * Scripts/run-jsc-stress-tests:
+
2013-09-17 Gwang Yoon Hwang <ryumiel@company100.net>
Unreviewed. Add myself as a committer.
runDefault
runAlwaysTriggerCopyPhase
runNoCJIT
- runDFGEager
if $enableFTL
runDefaultFTL
runFTLNoCJIT
runFTLEager
+ else
+ runDFGEager
end
end