Changeset 262535 in webkit


Ignore:
Timestamp:
Jun 4, 2020 7:40:48 AM (4 years ago)
Author:
mark.lam@apple.com
Message:

SpeculativeJIT::compileDateGet()'s slow path does not need an exception check.
https://bugs.webkit.org/show_bug.cgi?id=212645

Reviewed by Yusuke Suzuki.

SpeculativeJIT::compileDateGet() implements a bunch of Date intrinsics which call
into a C++ operation function do their work. However, the call to these operation
functions were done using a slow path generator configured to automatically
emit exception checks after the call. These exception checks are unneeded because
those functions will not throw any exceptions.

This issue was found with JSC stress test runs on a debug build. The doesGC
verifier was failing on the exceptionFuzz/date-format-xparb.js test. The reason
is because doesGC does not expect any these Date intrinsics to throw any exceptions,
but SpeculativeJIT was emitting the unneeded exception checks there. These
exception check sites get turned into throw sites by the exceptionFuzzer, and
they allocate an Error object there. This allocation made the doesGC verifier
not happy.

This patch fixes this issue by changing SpeculativeJIT::compileDateGet() to
pass ExceptionCheckRequirement::CheckNotNeeded to the slow path generator.

The patch also proves that all the operation functions cannot throw any exceptions.
Previously, the operations passes a VM& to the Date functions. The purpose for
doing this is so that the Date functions can work with a few date cache data
structures stored as VM fields.

This patch refactors those VM fields into a VM::DateCache struct, and changed all
those Date functions to take a VM::DateCache& instead of a VM&. Since the Date
functions no longer take a VM&, this proves that they cannot throw because they
would need a VM& to make a ThrowScope in order to throw.

Update: Yusuke pointed out that the lack of a JSGlobalObject* argument is sufficient
to guarantee that the Date functions cannot throw. However, we'll keep this
DateCache refactoring since it provides additional info that the Date functions
only operate on the DateCache fields and nothing else in VM.

Also removed DFG::JITCompile's fastExceptionCheck() which is unused.

  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::fastExceptionCheck): Deleted.

  • dfg/DFGOperations.cpp:
  • dfg/DFGSpeculativeJIT64.cpp:

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

  • runtime/DateConstructor.cpp:

(JSC::millisecondsFromComponents):
(JSC::callDate):

  • runtime/DateInstance.cpp:

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

  • runtime/DateInstance.h:
  • 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::dateProtoFuncGetTimezoneOffset):
(JSC::setNewValueFromTimeArgs):
(JSC::setNewValueFromDateArgs):
(JSC::dateProtoFuncSetYear):
(JSC::dateProtoFuncGetYear):

  • runtime/JSDateMath.cpp:

(JSC::localTimeOffset):
(JSC::gregorianDateTimeToMS):
(JSC::msToGregorianDateTime):
(JSC::parseDate):

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

(JSC::VM::resetDateCache):

  • runtime/VM.h:
Location:
trunk/Source/JavaScriptCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r262534 r262535  
     12020-06-04  Mark Lam  <mark.lam@apple.com>
     2
     3        SpeculativeJIT::compileDateGet()'s slow path does not need an exception check.
     4        https://bugs.webkit.org/show_bug.cgi?id=212645
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        SpeculativeJIT::compileDateGet() implements a bunch of Date intrinsics which call
     9        into a C++ operation function do their work.  However, the call to these operation
     10        functions were done using a slow path generator configured to automatically
     11        emit exception checks after the call.  These exception checks are unneeded because
     12        those functions will not throw any exceptions.
     13
     14        This issue was found with JSC stress test runs on a debug build.  The doesGC
     15        verifier was failing on the exceptionFuzz/date-format-xparb.js test.  The reason
     16        is because doesGC does not expect any these Date intrinsics to throw any exceptions,
     17        but SpeculativeJIT was emitting the unneeded exception checks there.  These
     18        exception check sites get turned into throw sites by the exceptionFuzzer, and
     19        they allocate an Error object there.  This allocation made the doesGC verifier
     20        not happy.
     21
     22        This patch fixes this issue by changing SpeculativeJIT::compileDateGet() to
     23        pass ExceptionCheckRequirement::CheckNotNeeded to the slow path generator.
     24
     25        The patch also proves that all the operation functions cannot throw any exceptions.
     26        Previously, the operations passes a VM& to the Date functions.  The purpose for
     27        doing this is so that the Date functions can work with a few date cache data
     28        structures stored as VM fields.
     29
     30        This patch refactors those VM fields into a VM::DateCache struct, and changed all
     31        those Date functions to take a VM::DateCache& instead of a VM&.  Since the Date
     32        functions no longer take a VM&, this proves that they cannot throw because they
     33        would need a VM& to make a ThrowScope in order to throw.
     34
     35        Update: Yusuke pointed out that the lack of a JSGlobalObject* argument is sufficient
     36        to guarantee that the Date functions cannot throw.  However, we'll keep this
     37        DateCache refactoring since it provides additional info that the Date functions
     38        only operate on the DateCache fields and nothing else in VM.
     39
     40        Also removed DFG::JITCompile's fastExceptionCheck() which is unused.
     41
     42        * dfg/DFGJITCompiler.h:
     43        (JSC::DFG::JITCompiler::fastExceptionCheck): Deleted.
     44        * dfg/DFGOperations.cpp:
     45        * dfg/DFGSpeculativeJIT64.cpp:
     46        (JSC::DFG::SpeculativeJIT::compileDateGet):
     47        * runtime/DateConstructor.cpp:
     48        (JSC::millisecondsFromComponents):
     49        (JSC::callDate):
     50        * runtime/DateInstance.cpp:
     51        (JSC::DateInstance::calculateGregorianDateTime const):
     52        (JSC::DateInstance::calculateGregorianDateTimeUTC const):
     53        * runtime/DateInstance.h:
     54        * runtime/DatePrototype.cpp:
     55        (JSC::formatLocaleDate):
     56        (JSC::formateDateInstance):
     57        (JSC::dateProtoFuncToISOString):
     58        (JSC::dateProtoFuncGetFullYear):
     59        (JSC::dateProtoFuncGetUTCFullYear):
     60        (JSC::dateProtoFuncGetMonth):
     61        (JSC::dateProtoFuncGetUTCMonth):
     62        (JSC::dateProtoFuncGetDate):
     63        (JSC::dateProtoFuncGetUTCDate):
     64        (JSC::dateProtoFuncGetDay):
     65        (JSC::dateProtoFuncGetUTCDay):
     66        (JSC::dateProtoFuncGetHours):
     67        (JSC::dateProtoFuncGetUTCHours):
     68        (JSC::dateProtoFuncGetMinutes):
     69        (JSC::dateProtoFuncGetUTCMinutes):
     70        (JSC::dateProtoFuncGetSeconds):
     71        (JSC::dateProtoFuncGetUTCSeconds):
     72        (JSC::dateProtoFuncGetTimezoneOffset):
     73        (JSC::setNewValueFromTimeArgs):
     74        (JSC::setNewValueFromDateArgs):
     75        (JSC::dateProtoFuncSetYear):
     76        (JSC::dateProtoFuncGetYear):
     77        * runtime/JSDateMath.cpp:
     78        (JSC::localTimeOffset):
     79        (JSC::gregorianDateTimeToMS):
     80        (JSC::msToGregorianDateTime):
     81        (JSC::parseDate):
     82        * runtime/JSDateMath.h:
     83        * runtime/VM.cpp:
     84        (JSC::VM::resetDateCache):
     85        * runtime/VM.h:
     86
    1872020-06-04  Paulo Matos  <pmatos@igalia.com>
    288
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r257399 r262535  
    11/*
    2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    154154    }
    155155
    156     // Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
    157     void fastExceptionCheck()
    158     {
    159         callExceptionFuzz(vm());
    160         m_exceptionChecks.append(branchTestPtr(Zero, GPRInfo::returnValueGPR));
    161     }
    162    
    163156    OSRExitCompilationInfo& appendExitInfo(MacroAssembler::JumpList jumpsToFail = MacroAssembler::JumpList())
    164157    {
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r262233 r262535  
    32933293    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    32943294
    3295     const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
     3295    const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm.dateCache);
    32963296    if (!gregorianDateTime)
    32973297        return JSValue::encode(jsNaN());
     
    33053305    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    33063306
    3307     const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
     3307    const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm.dateCache);
    33083308    if (!gregorianDateTime)
    33093309        return JSValue::encode(jsNaN());
     
    33173317    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    33183318
    3319     const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
     3319    const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm.dateCache);
    33203320    if (!gregorianDateTime)
    33213321        return JSValue::encode(jsNaN());
     
    33293329    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    33303330
    3331     const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
     3331    const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm.dateCache);
    33323332    if (!gregorianDateTime)
    33333333        return JSValue::encode(jsNaN());
     
    33413341    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    33423342
    3343     const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
     3343    const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm.dateCache);
    33443344    if (!gregorianDateTime)
    33453345        return JSValue::encode(jsNaN());
     
    33533353    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    33543354
    3355     const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
     3355    const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm.dateCache);
    33563356    if (!gregorianDateTime)
    33573357        return JSValue::encode(jsNaN());
     
    33653365    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    33663366
    3367     const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
     3367    const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm.dateCache);
    33683368    if (!gregorianDateTime)
    33693369        return JSValue::encode(jsNaN());
     
    33773377    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    33783378
    3379     const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
     3379    const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm.dateCache);
    33803380    if (!gregorianDateTime)
    33813381        return JSValue::encode(jsNaN());
     
    33893389    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    33903390
    3391     const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
     3391    const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm.dateCache);
    33923392    if (!gregorianDateTime)
    33933393        return JSValue::encode(jsNaN());
     
    34013401    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    34023402
    3403     const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
     3403    const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm.dateCache);
    34043404    if (!gregorianDateTime)
    34053405        return JSValue::encode(jsNaN());
     
    34133413    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    34143414
    3415     const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
     3415    const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm.dateCache);
    34163416    if (!gregorianDateTime)
    34173417        return JSValue::encode(jsNaN());
     
    34253425    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    34263426
    3427     const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
     3427    const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm.dateCache);
    34283428    if (!gregorianDateTime)
    34293429        return JSValue::encode(jsNaN());
     
    34373437    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    34383438
    3439     const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
     3439    const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm.dateCache);
    34403440    if (!gregorianDateTime)
    34413441        return JSValue::encode(jsNaN());
     
    34493449    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    34503450
    3451     const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
     3451    const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm.dateCache);
    34523452    if (!gregorianDateTime)
    34533453        return JSValue::encode(jsNaN());
     
    34613461    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    34623462
    3463     const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
     3463    const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm.dateCache);
    34643464    if (!gregorianDateTime)
    34653465        return JSValue::encode(jsNaN());
     
    34733473    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    34743474
    3475     const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
     3475    const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm.dateCache);
    34763476    if (!gregorianDateTime)
    34773477        return JSValue::encode(jsNaN());
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r262513 r262535  
    57385738        m_jit.boxInt32(resultRegs.payloadGPR(), resultRegs);
    57395739
    5740         addSlowPathGenerator(slowPathCall(slowCases, this, operation, resultRegs, &vm(), baseGPR));
     5740        addSlowPathGenerator(slowPathCall(slowCases, this, operation, NeedToSpill, ExceptionCheckRequirement::CheckNotNeeded, resultRegs, &vm(), baseGPR));
    57415741
    57425742        jsValueResult(resultRegs, node);
  • trunk/Source/JavaScriptCore/runtime/DateConstructor.cpp

    r261895 r262535  
    11/*
    22 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2004-2019 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2004-2020 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    9696    t.setSecond(JSC::toInt32(doubleArguments[5]));
    9797    t.setIsDST(-1);
    98     return gregorianDateTimeToMS(vm, t, doubleArguments[6], timeType);
     98    return gregorianDateTimeToMS(vm.dateCache, t, doubleArguments[6], timeType);
    9999}
    100100
     
    148148    VM& vm = globalObject->vm();
    149149    GregorianDateTime ts;
    150     msToGregorianDateTime(vm, WallTime::now().secondsSinceEpoch().milliseconds(), WTF::LocalTime, ts);
     150    msToGregorianDateTime(vm.dateCache, WallTime::now().secondsSinceEpoch().milliseconds(), WTF::LocalTime, ts);
    151151    return JSValue::encode(jsNontrivialString(vm, formatDateTime(ts, DateTimeFormatDateAndTime, false)));
    152152}
  • trunk/Source/JavaScriptCore/runtime/DateInstance.cpp

    r261895 r262535  
    11/*
    22 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2004-2020 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    5353}
    5454
    55 const GregorianDateTime* DateInstance::calculateGregorianDateTime(VM& vm) const
     55const GregorianDateTime* DateInstance::calculateGregorianDateTime(VM::DateCache& cache) const
    5656{
    5757    double milli = internalNumber();
     
    6060
    6161    if (!m_data)
    62         m_data = vm.dateInstanceCache.add(milli);
     62        m_data = cache.dateInstanceCache.add(milli);
    6363
    6464    if (m_data->m_gregorianDateTimeCachedForMS != milli) {
    65         msToGregorianDateTime(vm, milli, WTF::LocalTime, m_data->m_cachedGregorianDateTime);
     65        msToGregorianDateTime(cache, milli, WTF::LocalTime, m_data->m_cachedGregorianDateTime);
    6666        m_data->m_gregorianDateTimeCachedForMS = milli;
    6767    }
     
    6969}
    7070
    71 const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(VM& vm) const
     71const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(VM::DateCache& cache) const
    7272{
    7373    double milli = internalNumber();
     
    7676
    7777    if (!m_data)
    78         m_data = vm.dateInstanceCache.add(milli);
     78        m_data = cache.dateInstanceCache.add(milli);
    7979
    8080    if (m_data->m_gregorianDateTimeUTCCachedForMS != milli) {
    81         msToGregorianDateTime(vm, milli, WTF::UTCTime, m_data->m_cachedGregorianDateTimeUTC);
     81        msToGregorianDateTime(cache, milli, WTF::UTCTime, m_data->m_cachedGregorianDateTimeUTC);
    8282        m_data->m_gregorianDateTimeUTCCachedForMS = milli;
    8383    }
  • trunk/Source/JavaScriptCore/runtime/DateInstance.h

    r261159 r262535  
    11/*
    22 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2008-2018 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2008-2020 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    6161    DECLARE_EXPORT_INFO;
    6262
    63     const GregorianDateTime* gregorianDateTime(VM& vm) const
     63    const GregorianDateTime* gregorianDateTime(VM::DateCache& cache) const
    6464    {
    6565        if (m_data && m_data->m_gregorianDateTimeCachedForMS == internalNumber())
    6666            return &m_data->m_cachedGregorianDateTime;
    67         return calculateGregorianDateTime(vm);
     67        return calculateGregorianDateTime(cache);
    6868    }
    6969
    70     const GregorianDateTime* gregorianDateTimeUTC(VM& vm) const
     70    const GregorianDateTime* gregorianDateTimeUTC(VM::DateCache& cache) const
    7171    {
    7272        if (m_data && m_data->m_gregorianDateTimeUTCCachedForMS == internalNumber())
    7373            return &m_data->m_cachedGregorianDateTimeUTC;
    74         return calculateGregorianDateTimeUTC(vm);
     74        return calculateGregorianDateTimeUTC(cache);
    7575    }
    7676
     
    8787    void finishCreation(VM&);
    8888    JS_EXPORT_PRIVATE void finishCreation(VM&, double);
    89     JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTime(VM&) const;
    90     JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTimeUTC(VM&) const;
     89    JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTime(VM::DateCache&) const;
     90    JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTimeUTC(VM::DateCache&) const;
    9191
    9292    double m_internalNumber { PNaN };
  • trunk/Source/JavaScriptCore/runtime/DatePrototype.cpp

    r261755 r262535  
    295295    Integrity::auditStructureID(vm, dateObject->structureID());
    296296
    297     const GregorianDateTime* gregorianDateTime = dateObject->gregorianDateTime(vm);
     297    const GregorianDateTime* gregorianDateTime = dateObject->gregorianDateTime(vm.dateCache);
    298298    if (!gregorianDateTime)
    299299        return jsNontrivialString(vm, "Invalid Date"_s);
     
    307307    VM& vm = globalObject->vm();
    308308    auto scope = DECLARE_THROW_SCOPE(vm);
     309    auto& cache = vm.dateCache;
     310
    309311    JSValue thisValue = callFrame->thisValue();
    310312    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
     
    314316    Integrity::auditStructureID(vm, thisDateObj->structureID());
    315317    const GregorianDateTime* gregorianDateTime = asUTCVariant
    316         ? thisDateObj->gregorianDateTimeUTC(vm)
    317         : thisDateObj->gregorianDateTime(vm);
     318        ? thisDateObj->gregorianDateTimeUTC(cache)
     319        : thisDateObj->gregorianDateTime(cache);
    318320    if (!gregorianDateTime)
    319321        return JSValue::encode(jsNontrivialString(vm, String("Invalid Date"_s)));
     
    531533        return throwVMError(globalObject, scope, createRangeError(globalObject, "Invalid Date"_s));
    532534
    533     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm);
     535    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache);
    534536    if (!gregorianDateTime)
    535537        return JSValue::encode(jsNontrivialString(vm, String("Invalid Date"_s)));
     
    647649        return throwVMTypeError(globalObject, scope);
    648650
    649     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm);
     651    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm.dateCache);
    650652    if (!gregorianDateTime)
    651653        return JSValue::encode(jsNaN());
     
    662664        return throwVMTypeError(globalObject, scope);
    663665
    664     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm);
     666    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache);
    665667    if (!gregorianDateTime)
    666668        return JSValue::encode(jsNaN());
     
    677679        return throwVMTypeError(globalObject, scope);
    678680
    679     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm);
     681    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm.dateCache);
    680682    if (!gregorianDateTime)
    681683        return JSValue::encode(jsNaN());
     
    692694        return throwVMTypeError(globalObject, scope);
    693695
    694     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm);
     696    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache);
    695697    if (!gregorianDateTime)
    696698        return JSValue::encode(jsNaN());
     
    707709        return throwVMTypeError(globalObject, scope);
    708710
    709     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm);
     711    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm.dateCache);
    710712    if (!gregorianDateTime)
    711713        return JSValue::encode(jsNaN());
     
    722724        return throwVMTypeError(globalObject, scope);
    723725
    724     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm);
     726    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache);
    725727    if (!gregorianDateTime)
    726728        return JSValue::encode(jsNaN());
     
    737739        return throwVMTypeError(globalObject, scope);
    738740
    739     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm);
     741    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm.dateCache);
    740742    if (!gregorianDateTime)
    741743        return JSValue::encode(jsNaN());
     
    752754        return throwVMTypeError(globalObject, scope);
    753755
    754     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm);
     756    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache);
    755757    if (!gregorianDateTime)
    756758        return JSValue::encode(jsNaN());
     
    767769        return throwVMTypeError(globalObject, scope);
    768770
    769     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm);
     771    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm.dateCache);
    770772    if (!gregorianDateTime)
    771773        return JSValue::encode(jsNaN());
     
    782784        return throwVMTypeError(globalObject, scope);
    783785
    784     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm);
     786    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache);
    785787    if (!gregorianDateTime)
    786788        return JSValue::encode(jsNaN());
     
    797799        return throwVMTypeError(globalObject, scope);
    798800
    799     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm);
     801    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm.dateCache);
    800802    if (!gregorianDateTime)
    801803        return JSValue::encode(jsNaN());
     
    812814        return throwVMTypeError(globalObject, scope);
    813815
    814     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm);
     816    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache);
    815817    if (!gregorianDateTime)
    816818        return JSValue::encode(jsNaN());
     
    827829        return throwVMTypeError(globalObject, scope);
    828830
    829     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm);
     831    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm.dateCache);
    830832    if (!gregorianDateTime)
    831833        return JSValue::encode(jsNaN());
     
    842844        return throwVMTypeError(globalObject, scope);
    843845
    844     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm);
     846    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache);
    845847    if (!gregorianDateTime)
    846848        return JSValue::encode(jsNaN());
     
    895897        return throwVMTypeError(globalObject, scope);
    896898
    897     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm);
     899    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm.dateCache);
    898900    if (!gregorianDateTime)
    899901        return JSValue::encode(jsNaN());
     
    920922    VM& vm = globalObject->vm();
    921923    auto scope = DECLARE_THROW_SCOPE(vm);
     924    auto& cache = vm.dateCache;
     925
    922926    JSValue thisValue = callFrame->thisValue();
    923927    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
     
    936940
    937941    const GregorianDateTime* other = inputTimeType == WTF::UTCTime
    938         ? thisDateObj->gregorianDateTimeUTC(vm)
    939         : thisDateObj->gregorianDateTime(vm);
     942        ? thisDateObj->gregorianDateTimeUTC(cache)
     943        : thisDateObj->gregorianDateTime(cache);
    940944    if (!other)
    941945        return JSValue::encode(jsNaN());
     
    949953    }
    950954
    951     double newUTCDate = gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputTimeType);
     955    double newUTCDate = gregorianDateTimeToMS(cache, gregorianDateTime, ms, inputTimeType);
    952956    double result = timeClip(newUTCDate);
    953957    thisDateObj->setInternalNumber(result);
     
    959963    VM& vm = globalObject->vm();
    960964    auto scope = DECLARE_THROW_SCOPE(vm);
     965    auto& cache = vm.dateCache;
     966
    961967    JSValue thisValue = callFrame->thisValue();
    962968    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
     
    974980    GregorianDateTime gregorianDateTime;
    975981    if (numArgsToUse == 3 && std::isnan(milli))
    976         msToGregorianDateTime(vm, 0, WTF::UTCTime, gregorianDateTime);
     982        msToGregorianDateTime(cache, 0, WTF::UTCTime, gregorianDateTime);
    977983    else {
    978984        ms = milli - floor(milli / msPerSecond) * msPerSecond;
    979985        const GregorianDateTime* other = inputTimeType == WTF::UTCTime
    980             ? thisDateObj->gregorianDateTimeUTC(vm)
    981             : thisDateObj->gregorianDateTime(vm);
     986            ? thisDateObj->gregorianDateTimeUTC(cache)
     987            : thisDateObj->gregorianDateTime(cache);
    982988        if (!other)
    983989            return JSValue::encode(jsNaN());
     
    992998    }
    993999
    994     double newUTCDate = gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputTimeType);
     1000    double newUTCDate = gregorianDateTimeToMS(cache, gregorianDateTime, ms, inputTimeType);
    9951001    double result = timeClip(newUTCDate);
    9961002    thisDateObj->setInternalNumber(result);
     
    10721078    VM& vm = globalObject->vm();
    10731079    auto scope = DECLARE_THROW_SCOPE(vm);
     1080    auto& cache = vm.dateCache;
     1081
    10741082    JSValue thisValue = callFrame->thisValue();
    10751083    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
     
    10891097        // Based on ECMA 262 B.2.5 (setYear)
    10901098        // the time must be reset to +0 if it is NaN.
    1091         msToGregorianDateTime(vm, 0, WTF::UTCTime, gregorianDateTime);
     1099        msToGregorianDateTime(cache, 0, WTF::UTCTime, gregorianDateTime);
    10921100    else {
    10931101        double secs = floor(milli / msPerSecond);
    10941102        ms = milli - secs * msPerSecond;
    1095         if (const GregorianDateTime* other = thisDateObj->gregorianDateTime(vm))
     1103        if (const GregorianDateTime* other = thisDateObj->gregorianDateTime(cache))
    10961104            gregorianDateTime = *other;
    10971105    }
     
    11051113
    11061114    gregorianDateTime.setYear(toInt32((year >= 0 && year <= 99) ? (year + 1900) : year));
    1107     double timeInMilliseconds = gregorianDateTimeToMS(vm, gregorianDateTime, ms, WTF::LocalTime);
     1115    double timeInMilliseconds = gregorianDateTimeToMS(cache, gregorianDateTime, ms, WTF::LocalTime);
    11081116    double result = timeClip(timeInMilliseconds);
    11091117    thisDateObj->setInternalNumber(result);
     
    11201128        return throwVMTypeError(globalObject, scope);
    11211129
    1122     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm);
     1130    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(vm.dateCache);
    11231131    if (!gregorianDateTime)
    11241132        return JSValue::encode(jsNaN());
  • trunk/Source/JavaScriptCore/runtime/JSDateMath.cpp

    r261755 r262535  
    11/*
    22 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
     3 * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
    44 * Copyright (C) 2009 Google Inc. All rights reserved.
    55 * Copyright (C) 2007-2009 Torch Mobile, Inc.
     
    8484// more than one daylight savings offset change per month.
    8585// If this function is called with NaN it returns NaN.
    86 static LocalTimeOffset localTimeOffset(VM& vm, double ms, WTF::TimeType inputTimeType = WTF::UTCTime)
     86static LocalTimeOffset localTimeOffset(VM::DateCache& dateCache, double ms, WTF::TimeType inputTimeType = WTF::UTCTime)
    8787{
    8888    LocalTimeOffsetCache& cache = inputTimeType == WTF::LocalTime
    89         ? vm.localTimeOffsetCache : vm.utcTimeOffsetCache;
     89        ? dateCache.localTimeOffsetCache : dateCache.utcTimeOffsetCache;
    9090
    9191    double start = cache.start;
     
    148148}
    149149
    150 double gregorianDateTimeToMS(VM& vm, const GregorianDateTime& t, double milliSeconds, WTF::TimeType inputTimeType)
     150double gregorianDateTimeToMS(VM::DateCache& cache, const GregorianDateTime& t, double milliSeconds, WTF::TimeType inputTimeType)
    151151{
    152152    double day = dateToDaysFrom1970(t.year(), t.month(), t.monthDay());
     
    155155
    156156    double localToUTCTimeOffset = inputTimeType == WTF::LocalTime
    157         ? localTimeOffset(vm, localTimeResult, inputTimeType).offset : 0;
     157        ? localTimeOffset(cache, localTimeResult, inputTimeType).offset : 0;
    158158
    159159    return localTimeResult - localToUTCTimeOffset;
     
    161161
    162162// input is UTC
    163 void msToGregorianDateTime(VM& vm, double ms, WTF::TimeType outputTimeType, GregorianDateTime& tm)
     163void msToGregorianDateTime(VM::DateCache& cache, double ms, WTF::TimeType outputTimeType, GregorianDateTime& tm)
    164164{
    165165    LocalTimeOffset localTime;
    166166    if (outputTimeType == WTF::LocalTime) {
    167         localTime = localTimeOffset(vm, ms);
     167        localTime = localTimeOffset(cache, ms);
    168168        ms += localTime.offset;
    169169    }
     
    171171}
    172172
    173 static double parseDate(VM& vm, const char* dateString)
     173static double parseDate(VM::DateCache& cache, const char* dateString)
    174174{
    175175    bool isLocalTime;
     
    179179
    180180    if (isLocalTime)
    181         value -= localTimeOffset(vm, value, WTF::LocalTime).offset;
     181        value -= localTimeOffset(cache, value, WTF::LocalTime).offset;
    182182
    183183    return value;
     
    187187{
    188188    auto scope = DECLARE_THROW_SCOPE(vm);
    189 
    190     if (date == vm.cachedDateString)
    191         return vm.cachedDateStringValue;
     189    auto& cache = vm.dateCache;
     190
     191    if (date == cache.cachedDateString)
     192        return cache.cachedDateStringValue;
    192193    auto expectedString = date.tryGetUtf8();
    193194    if (!expectedString) {
     
    201202
    202203    auto dateUtf8 = expectedString.value();
    203     double value = parseDate(vm, dateUtf8.data());
    204     vm.cachedDateString = date;
    205     vm.cachedDateStringValue = value;
     204    double value = parseDate(cache, dateUtf8.data());
     205    cache.cachedDateString = date;
     206    cache.cachedDateStringValue = value;
    206207    return value;
    207208}
  • trunk/Source/JavaScriptCore/runtime/JSDateMath.h

    r254038 r262535  
    11/*
    22 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
     3 * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
    44 * Copyright (C) 2009 Google Inc. All rights reserved.
    55 * Copyright (C) 2010 Research In Motion Limited. All rights reserved.
     
    5151class VM;
    5252
    53 JS_EXPORT_PRIVATE void msToGregorianDateTime(VM&, double, WTF::TimeType outputTimeType, GregorianDateTime&);
    54 JS_EXPORT_PRIVATE double gregorianDateTimeToMS(VM&, const GregorianDateTime&, double, WTF::TimeType inputTimeType);
    55 JS_EXPORT_PRIVATE double getUTCOffset(VM&);
     53JS_EXPORT_PRIVATE void msToGregorianDateTime(VM::DateCache&, double, WTF::TimeType outputTimeType, GregorianDateTime&);
     54JS_EXPORT_PRIVATE double gregorianDateTimeToMS(VM::DateCache&, const GregorianDateTime&, double, WTF::TimeType inputTimeType);
     55JS_EXPORT_PRIVATE double getUTCOffset(VM::DateCache&);
    5656JS_EXPORT_PRIVATE double parseDate(JSGlobalObject*, VM&, const WTF::String&);
    5757
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r262342 r262535  
    856856void VM::resetDateCache()
    857857{
    858     utcTimeOffsetCache.reset();
    859     localTimeOffsetCache.reset();
    860     cachedDateString = String();
    861     cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
    862     dateInstanceCache.reset();
     858    dateCache.utcTimeOffsetCache.reset();
     859    dateCache.localTimeOffsetCache.reset();
     860    dateCache.cachedDateString = String();
     861    dateCache.cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
     862    dateCache.dateInstanceCache.reset();
    863863}
    864864
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r261233 r262535  
    724724    SmallStrings smallStrings;
    725725    NumericStrings numericStrings;
    726     DateInstanceCache dateInstanceCache;
    727726    std::unique_ptr<SimpleStats> machineCodeBytesPerBytecodeWordForBaselineJIT;
    728727    WeakGCMap<std::pair<CustomGetterSetter*, int>, JSCustomGetterSetterFunction> customGetterSetterFunctionMap;
     
    963962    JSObject* stringRecursionCheckFirstObject { nullptr };
    964963    HashSet<JSObject*> stringRecursionCheckVisitedObjects;
    965    
    966     LocalTimeOffsetCache utcTimeOffsetCache;
    967     LocalTimeOffsetCache localTimeOffsetCache;
    968 
    969     String cachedDateString;
    970     double cachedDateStringValue;
     964
     965    struct DateCache {
     966        DateInstanceCache dateInstanceCache;
     967        LocalTimeOffsetCache utcTimeOffsetCache;
     968        LocalTimeOffsetCache localTimeOffsetCache;
     969
     970        String cachedDateString;
     971        double cachedDateStringValue;
     972    };
     973    DateCache dateCache;
    971974
    972975    std::unique_ptr<Profiler::Database> m_perBytecodeProfiler;
Note: See TracChangeset for help on using the changeset viewer.