Ignore:
Timestamp:
Oct 30, 2019, 5:37:03 PM (6 years ago)
Author:
[email protected]
Message:

[JSC] Date functions should have intrinsic
https://bugs.webkit.org/show_bug.cgi?id=202187

Reviewed by Keith Miller.

JSTests:

  • stress/date-cse.js: Added.

(shouldBe):
(test):
(test2):
(test3):

  • stress/date-get-date-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-day-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-full-year-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-hours-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-milliseconds-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-minutes-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-month-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-seconds-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-time-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-timezone-offset-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-utc-date-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-utc-day-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-utc-full-year-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-utc-hours-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-utc-milliseconds-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-utc-minutes-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-utc-month-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-utc-seconds-jit.js: Added.

(shouldBe):
(test):

  • stress/date-get-year-jit.js: Added.

(shouldBe):
(test):

  • stress/date-value-of-jit.js: Added.

(shouldBe):
(test):

Source/JavaScriptCore:

This patch adds intrinsic to Date object getter functions to make it inlined in DFG and FTL.
We add two DFG nodes, DateGetInt32OrNaN and DateGetTime. DateGetTime is used when we know
that the result is always machine double. On the other hand, DateGetInt32OrNaN is used when the result is Int32 or NaN.

Run SunSpider 100 times and get the solid improvement in Date related benchmarks.

ToT Patched

date-format-tofte 5.3511+-0.0260 5.2747+-0.0273 definitely 1.0145x faster
date-format-xparb 4.9196+-0.0265 4.7067+-0.0200 definitely 1.0452x faster

  • bytecode/SpeculatedType.cpp:

(JSC::dumpSpeculation):
(JSC::speculationFromClassInfo):
(JSC::speculationFromJSType):
(JSC::speculationFromString):

  • bytecode/SpeculatedType.h:
  • dfg/DFGAbstractHeap.h:
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleIntrinsicCall):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGHeapLocation.cpp:

(WTF::printInternal):

  • dfg/DFGHeapLocation.h:
  • dfg/DFGNode.h:

(JSC::DFG::Node::hasIntrinsic):
(JSC::DFG::Node::intrinsic):
(JSC::DFG::Node::hasHeapPrediction):

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::SafeToExecuteEdge::operator()):
(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::speculateDateObject):
(JSC::DFG::SpeculativeJIT::speculate):

  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileDateGet):

  • dfg/DFGUseKind.cpp:

(WTF::printInternal):

  • dfg/DFGUseKind.h:

(JSC::DFG::typeFilterFor):
(JSC::DFG::isCell):

  • ftl/FTLAbstractHeapRepository.cpp:
  • ftl/FTLAbstractHeapRepository.h:
  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileDateGet):
(JSC::FTL::DFG::LowerDFGToB3::lowDateObject):
(JSC::FTL::DFG::LowerDFGToB3::speculate):
(JSC::FTL::DFG::LowerDFGToB3::speculateDateObject):

  • runtime/DateConversion.cpp:

(JSC::formatDateTime):

  • runtime/DateInstance.cpp:

(JSC::DateInstance::calculateGregorianDateTime const):
(JSC::DateInstance::calculateGregorianDateTimeUTC const):

  • runtime/DateInstance.h:
  • runtime/DateInstanceCache.h:

(JSC::DateInstanceData::offsetOfGregorianDateTimeCachedForMS):
(JSC::DateInstanceData::offsetOfCachedGregorianDateTime):
(JSC::DateInstanceData::offsetOfGregorianDateTimeUTCCachedForMS):
(JSC::DateInstanceData::offsetOfCachedGregorianDateTimeUTC):
(JSC::DateInstanceData::DateInstanceData): Deleted.

  • runtime/DatePrototype.cpp:

(JSC::formatLocaleDate):
(JSC::formateDateInstance):
(JSC::dateProtoFuncToISOString):
(JSC::dateProtoFuncGetFullYear):
(JSC::dateProtoFuncGetUTCFullYear):
(JSC::dateProtoFuncGetMonth):
(JSC::dateProtoFuncGetUTCMonth):
(JSC::dateProtoFuncGetDate):
(JSC::dateProtoFuncGetUTCDate):
(JSC::dateProtoFuncGetDay):
(JSC::dateProtoFuncGetUTCDay):
(JSC::dateProtoFuncGetHours):
(JSC::dateProtoFuncGetUTCHours):
(JSC::dateProtoFuncGetMinutes):
(JSC::dateProtoFuncGetUTCMinutes):
(JSC::dateProtoFuncGetSeconds):
(JSC::dateProtoFuncGetUTCSeconds):
(JSC::dateProtoFuncGetMilliSeconds):
(JSC::dateProtoFuncGetUTCMilliseconds):
(JSC::dateProtoFuncGetTimezoneOffset):
(JSC::setNewValueFromTimeArgs):
(JSC::setNewValueFromDateArgs):
(JSC::dateProtoFuncSetYear):
(JSC::dateProtoFuncGetYear):

  • runtime/Intrinsic.cpp:

(JSC::intrinsicName):

  • runtime/Intrinsic.h:
  • runtime/JSDateMath.cpp:

(JSC::msToGregorianDateTime):

  • runtime/JSType.cpp:

(WTF::printInternal):

  • runtime/JSType.h:

Source/WebCore:

  • loader/archive/mhtml/MHTMLArchive.cpp:

(WebCore::MHTMLArchive::generateMHTMLData):

Source/WTF:

  • wtf/DateMath.h:
  • wtf/GregorianDateTime.cpp:

(WTF::GregorianDateTime::setToCurrentLocalTime):

  • wtf/GregorianDateTime.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r251669 r251826  
    15461546            compileFilterICStatus();
    15471547            break;
     1548        case DateGetInt32OrNaN:
     1549        case DateGetTime:
     1550            compileDateGet();
     1551            break;
    15481552        case DataViewGetInt:
    15491553        case DataViewGetFloat:
     
    1340613410                RELEASE_ASSERT_NOT_REACHED();
    1340713411            }
     13412        }
     13413    }
     13414
     13415    void compileDateGet()
     13416    {
     13417        LValue base = lowDateObject(m_node->child1());
     13418
     13419        auto emitGetCodeWithCallback = [&] (const AbstractHeap& cachedDoubleOffset, const AbstractHeap& cachedDataOffset, auto* operation, auto callback) {
     13420            LBasicBlock dataExistsCase = m_out.newBlock();
     13421            LBasicBlock fastCase = m_out.newBlock();
     13422            LBasicBlock slowCase = m_out.newBlock();
     13423            LBasicBlock continuation = m_out.newBlock();
     13424
     13425            LValue data = m_out.loadPtr(base, m_heaps.DateInstance_data);
     13426            m_out.branch(m_out.notZero64(data), unsure(dataExistsCase), unsure(slowCase));
     13427
     13428            LBasicBlock lastNext = m_out.appendTo(dataExistsCase, fastCase);
     13429            LValue milliseconds = m_out.loadDouble(base, m_heaps.DateInstance_internalNumber);
     13430            LValue cachedMilliseconds = m_out.loadDouble(data, cachedDoubleOffset);
     13431            m_out.branch(m_out.doubleNotEqualOrUnordered(milliseconds, cachedMilliseconds), unsure(slowCase), unsure(fastCase));
     13432
     13433            m_out.appendTo(fastCase, slowCase);
     13434            ValueFromBlock fastResult = m_out.anchor(boxInt32(callback(m_out.load32(data, cachedDataOffset))));
     13435            m_out.jump(continuation);
     13436
     13437            m_out.appendTo(slowCase, continuation);
     13438            ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, operation, m_vmValue, base));
     13439            m_out.jump(continuation);
     13440
     13441            m_out.appendTo(continuation, lastNext);
     13442            setJSValue(m_out.phi(Int64, fastResult, slowResult));
     13443        };
     13444
     13445        auto emitGetCode = [&] (const AbstractHeap& cachedDoubleOffset, const AbstractHeap& cachedDataOffset, auto* operation) {
     13446            emitGetCodeWithCallback(cachedDoubleOffset, cachedDataOffset, operation, [] (LValue value) { return value; });
     13447        };
     13448
     13449        switch (m_node->intrinsic()) {
     13450        case DatePrototypeGetTimeIntrinsic:
     13451            setDouble(m_out.loadDouble(base, m_heaps.DateInstance_internalNumber));
     13452            break;
     13453
     13454        case DatePrototypeGetMillisecondsIntrinsic:
     13455        case DatePrototypeGetUTCMillisecondsIntrinsic: {
     13456            LValue milliseconds = m_out.loadDouble(base, m_heaps.DateInstance_internalNumber);
     13457            LValue msPerSecondConstant = m_out.constDouble(msPerSecond);
     13458            LValue seconds = m_out.doubleFloor(m_out.doubleDiv(milliseconds, msPerSecondConstant));
     13459            LValue result = m_out.doubleToInt(m_out.doubleSub(milliseconds, m_out.doubleMul(seconds, msPerSecondConstant)));
     13460            setJSValue(m_out.select(m_out.doubleNotEqualOrUnordered(milliseconds, milliseconds), m_out.constInt64(JSValue::encode(jsNaN())), boxInt32(result)));
     13461            break;
     13462        }
     13463
     13464        case DatePrototypeGetFullYearIntrinsic:
     13465            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTime_year, operationDateGetFullYear);
     13466            break;
     13467        case DatePrototypeGetUTCFullYearIntrinsic:
     13468            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeUTCCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTimeUTC_year, operationDateGetUTCFullYear);
     13469            break;
     13470        case DatePrototypeGetMonthIntrinsic:
     13471            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTime_month, operationDateGetMonth);
     13472            break;
     13473        case DatePrototypeGetUTCMonthIntrinsic:
     13474            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeUTCCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTimeUTC_month, operationDateGetUTCMonth);
     13475            break;
     13476        case DatePrototypeGetDateIntrinsic:
     13477            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTime_monthDay, operationDateGetDate);
     13478            break;
     13479        case DatePrototypeGetUTCDateIntrinsic:
     13480            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeUTCCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTimeUTC_monthDay, operationDateGetUTCDate);
     13481            break;
     13482        case DatePrototypeGetDayIntrinsic:
     13483            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTime_weekDay, operationDateGetDay);
     13484            break;
     13485        case DatePrototypeGetUTCDayIntrinsic:
     13486            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeUTCCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTimeUTC_weekDay, operationDateGetUTCDay);
     13487            break;
     13488        case DatePrototypeGetHoursIntrinsic:
     13489            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTime_hour, operationDateGetHours);
     13490            break;
     13491        case DatePrototypeGetUTCHoursIntrinsic:
     13492            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeUTCCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTimeUTC_hour, operationDateGetUTCHours);
     13493            break;
     13494        case DatePrototypeGetMinutesIntrinsic:
     13495            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTime_minute, operationDateGetMinutes);
     13496            break;
     13497        case DatePrototypeGetUTCMinutesIntrinsic:
     13498            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeUTCCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTimeUTC_minute, operationDateGetUTCMinutes);
     13499            break;
     13500        case DatePrototypeGetSecondsIntrinsic:
     13501            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTime_second, operationDateGetSeconds);
     13502            break;
     13503        case DatePrototypeGetUTCSecondsIntrinsic:
     13504            emitGetCode(m_heaps.DateInstanceData_gregorianDateTimeUTCCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTimeUTC_second, operationDateGetUTCSeconds);
     13505            break;
     13506
     13507        case DatePrototypeGetTimezoneOffsetIntrinsic:
     13508            emitGetCodeWithCallback(m_heaps.DateInstanceData_gregorianDateTimeCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTime_utcOffsetInMinute, operationDateGetTimezoneOffset, [&] (LValue offset) {
     13509                return m_out.neg(offset);
     13510            });
     13511            break;
     13512
     13513        case DatePrototypeGetYearIntrinsic:
     13514            emitGetCodeWithCallback(m_heaps.DateInstanceData_gregorianDateTimeCachedForMS, m_heaps.DateInstanceData_cachedGregorianDateTime_year, operationDateGetYear, [&] (LValue year) {
     13515                return m_out.sub(year, m_out.constInt32(1900));
     13516            });
     13517            break;
     13518
     13519        default:
     13520            RELEASE_ASSERT_NOT_REACHED();
    1340813521        }
    1340913522    }
     
    1575715870        return result;
    1575815871    }
     15872
     15873    LValue lowDateObject(Edge edge)
     15874    {
     15875        LValue result = lowCell(edge);
     15876        speculateDateObject(edge, result);
     15877        return result;
     15878    }
    1575915879   
    1576015880    LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     
    1624016360        case DerivedArrayUse:
    1624116361            speculateDerivedArray(edge);
     16362            break;
     16363        case DateObjectUse:
     16364            speculateDateObject(edge);
    1624216365            break;
    1624316366        case MapObjectUse:
     
    1676516888    {
    1676616889        speculatePromiseObject(edge, lowCell(edge));
     16890    }
     16891
     16892    void speculateDateObject(Edge edge, LValue cell)
     16893    {
     16894        FTL_TYPE_CHECK(
     16895            jsValueValue(cell), edge, SpecDateObject, isNotType(cell, JSDateType));
     16896    }
     16897
     16898    void speculateDateObject(Edge edge)
     16899    {
     16900        speculateDateObject(edge, lowCell(edge));
    1676716901    }
    1676816902
Note: See TracChangeset for help on using the changeset viewer.