Title: [269320] trunk
Revision
269320
Author
[email protected]
Date
2020-11-03 11:26:49 -0800 (Tue, 03 Nov 2020)

Log Message

REGRESSION (r254038): Simple.com money transfer UI is very laggy (multiple seconds per keypress)
https://bugs.webkit.org/show_bug.cgi?id=218348

Reviewed by Darin Adler.

JSTests:

* ChakraCore.yaml:
* ChakraCore/test/Date/DateCtr.baseline-jsc: Added. The time before America/Los_Angeles timezone is effective should be handled as UTC-0752.
* complex.yaml:
* complex/timezone-offset-before-america-los-angeles-is-defined.js: Added for UTC-0752.
(shouldBe):
* microbenchmarks/local-date-constructor.js: Added for microbenchmarking.
(test):
* mozilla/ecma/Date/15.9.5.16.js:
* mozilla/ecma/Date/15.9.5.18.js:
* mozilla/ecma/Date/15.9.5.22-1.js:
* mozilla/ecma/Date/15.9.5.22-2.js:
* mozilla/ecma/Date/15.9.5.35-1.js:
When year is 0, America/Los_Angeles timezone is not effective, and mozilla test harness does not handle this timezone difference correctly.

Source/_javascript_Core:

We have depth-1 LocalTimeOffset cache to avoid repeatedly calling `localtime_r`. But this depth-1 cache can be easily missed if
we parse Dates of multiple years. Instead of increasing depth as a work-around, this patch starts using ICU TimeZone cache.
This is used in SpiderMonkey and V8 too, and it is the right direction since ICU knows tzdata and can do more sophisticated caching.

Microbenchmark shows 24x improvement.

                                   ToT                     Patched

local-date-constructor     2026.8715+-11.2909    ^     85.0022+-1.0548        ^ definitely 23.8449x faster

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* Sources.txt:
* runtime/DateConstructor.cpp:
(JSC::millisecondsFromComponents):
(JSC::constructDate):
(JSC::JSC_DEFINE_HOST_FUNCTION):
* runtime/DateInstance.cpp:
(JSC::DateInstance::calculateGregorianDateTime const):
(JSC::DateInstance::calculateGregorianDateTimeUTC const):
* runtime/DateInstance.h:
* runtime/DatePrototype.cpp:
(JSC::setNewValueFromTimeArgs):
(JSC::setNewValueFromDateArgs):
(JSC::JSC_DEFINE_HOST_FUNCTION):
* runtime/JSDateMath.cpp:
(JSC::OpaqueICUTimeZoneDeleter::operator()):
(JSC::localTimeOffset):
(JSC::DateCache::gregorianDateTimeToMS):
(JSC::DateCache::msToGregorianDateTime):
(JSC::DateCache::parseDate):
(JSC::DateCache::cachedDateInstanceData):
(JSC::DateCache::timeZoneCacheSlow):
(JSC::DateCache::reset):
(JSC::gregorianDateTimeToMS): Deleted.
(JSC::msToGregorianDateTime): Deleted.
(JSC::parseDate): Deleted.
* runtime/JSDateMath.h:
(JSC::DateCache::timeZoneCache):
* runtime/VM.cpp:
(JSC::VM::resetDateCache): Deleted.
* runtime/VM.h:
(JSC::VM::resetDateCache):
* runtime/VMEntryScope.cpp:
(JSC::VMEntryScope::VMEntryScope):

LayoutTests:

* js/date-constructor-expected.txt: The time before America/Los_Angeles timezone is effective should be handled as UTC-0752. Use 1995 to test the intent correctly.
* js/date-timeClip-large-values-expected.txt: Ditto about old timezone.
* js/dom/script-tests/date-DST-time-cusps.js: Our timezone database was broken. Nov 02 2014 01:00:00 is not PDT.
(1.toString.match):
* js/dom/script-tests/date-big-setdate.js: Fix and adjust for right DST periods.
(1.toString.match):
* js/script-tests/date-constructor.js:
(object.valueOf):
* platform/mac/fast/AppleScript/date-expected.txt: Ditto, 1800 does not have America/Los_Angeles.
* platform/mac/fast/AppleScript/date.html:
* storage/indexeddb/modern/date-basic-expected.txt: Nov 04 1955 is PST, not PDT.
* storage/indexeddb/modern/date-basic-private-expected.txt: Ditto.
* storage/indexeddb/modern/get-keyrange-expected.txt: Ditto.
* storage/indexeddb/modern/get-keyrange-private-expected.txt: Ditto.

Modified Paths

Added Paths

Diff

Added: trunk/JSTests/ChakraCore/test/Date/DateCtr.baseline-jsc (0 => 269320)


--- trunk/JSTests/ChakraCore/test/Date/DateCtr.baseline-jsc	                        (rev 0)
+++ trunk/JSTests/ChakraCore/test/Date/DateCtr.baseline-jsc	2020-11-03 19:26:49 UTC (rev 269320)
@@ -0,0 +1,15 @@
+1970-01-10T00:00:01.000Z
+1974-01-01T00:00:00.000Z
+1970-01-01T00:00:01.974Z
+1974-10-01T07:00:00.000Z
+1974-10-24T07:00:00.000Z
+1974-10-24T07:00:00.000Z
+1974-10-24T07:20:00.000Z
+1974-10-24T07:20:30.000Z
+1974-10-24T07:20:30.040Z
+1974-10-24T07:20:30.040Z
+-098001-12-01T07:52:58.000Z
+1999-12-01T08:00:00.000Z
+Invalid Date
+Invalid Date
+Invalid Date

Modified: trunk/JSTests/ChakraCore.yaml (269319 => 269320)


--- trunk/JSTests/ChakraCore.yaml	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/ChakraCore.yaml	2020-11-03 19:26:49 UTC (rev 269320)
@@ -480,7 +480,7 @@
 - path: ChakraCore/test/Conversions/bug1.js
   cmd: runChakra :pass, "NoException", "", []
 - path: ChakraCore/test/Date/DateCtr.js
-  cmd: runChakra :baseline, "NoException", "DateCtr.baseline", []
+  cmd: runChakra :baseline, "NoException", "DateCtr.baseline-jsc", []
 - path: ChakraCore/test/Date/DateParse.js
   # JSC accepts different Date parsing syntax.
   cmd: runChakra :skip, "NoException", "DateParse_es5.baseline", []

Modified: trunk/JSTests/ChangeLog (269319 => 269320)


--- trunk/JSTests/ChangeLog	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/ChangeLog	2020-11-03 19:26:49 UTC (rev 269320)
@@ -1,3 +1,24 @@
+2020-11-03  Yusuke Suzuki  <[email protected]>
+
+        REGRESSION (r254038): Simple.com money transfer UI is very laggy (multiple seconds per keypress)
+        https://bugs.webkit.org/show_bug.cgi?id=218348
+
+        Reviewed by Darin Adler.
+
+        * ChakraCore.yaml:
+        * ChakraCore/test/Date/DateCtr.baseline-jsc: Added. The time before America/Los_Angeles timezone is effective should be handled as UTC-0752.
+        * complex.yaml:
+        * complex/timezone-offset-before-america-los-angeles-is-defined.js: Added for UTC-0752.
+        (shouldBe):
+        * microbenchmarks/local-date-constructor.js: Added for microbenchmarking.
+        (test):
+        * mozilla/ecma/Date/15.9.5.16.js:
+        * mozilla/ecma/Date/15.9.5.18.js:
+        * mozilla/ecma/Date/15.9.5.22-1.js:
+        * mozilla/ecma/Date/15.9.5.22-2.js:
+        * mozilla/ecma/Date/15.9.5.35-1.js:
+        When year is 0, America/Los_Angeles timezone is not effective, and mozilla test harness does not handle this timezone difference correctly.
+
 2020-10-28  Saam Barati  <[email protected]>
 
         Better cache our serialization of the outer TDZ environment when creating FunctionExecutables during bytecode generation

Added: trunk/JSTests/complex/timezone-offset-before-america-los-angeles-is-defined.js (0 => 269320)


--- trunk/JSTests/complex/timezone-offset-before-america-los-angeles-is-defined.js	                        (rev 0)
+++ trunk/JSTests/complex/timezone-offset-before-america-los-angeles-is-defined.js	2020-11-03 19:26:49 UTC (rev 269320)
@@ -0,0 +1,14 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+// When it is 1111, timezone America/Los_Angeles is not effective yet.
+// So, timezone offset is defined by America/Los_Angeles's longitude
+// (118.2347W), thus, UTC-0752. Its timezone offset is 472.
+shouldBe(new Date(1111, 1).getTimezoneOffset(), 472);
+// After timezone America/Los_Angeles is effective, its timezone offset is 480.
+shouldBe(new Date(2000, 1).getTimezoneOffset(), 480);
+
+shouldBe(new Date(1111, 1).getTime(), -27104774822000);
+shouldBe(new Date(2000, 1).getTime(), 949392000000);

Modified: trunk/JSTests/complex.yaml (269319 => 269320)


--- trunk/JSTests/complex.yaml	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/complex.yaml	2020-11-03 19:26:49 UTC (rev 269320)
@@ -31,3 +31,6 @@
 
 - path: complex/timezone-offset-apia.js
   cmd: runComplexTest [], [], "TZ=Pacific/Apia", "--useDollarVM=1"
+
+- path: complex/timezone-offset-before-america-los-angeles-is-defined.js
+  cmd: runComplexTest [], [], "TZ=America/Los_Angeles", "--useDollarVM=1"

Added: trunk/JSTests/microbenchmarks/local-date-constructor.js (0 => 269320)


--- trunk/JSTests/microbenchmarks/local-date-constructor.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/local-date-constructor.js	2020-11-03 19:26:49 UTC (rev 269320)
@@ -0,0 +1,50 @@
+function test() {
+    a = {
+        2016: {
+            begin: new Date("2016-03-13T00:00:00").getTime(),
+            end: new Date("2016-11-06T00:00:00").getTime()
+        },
+        2017: {
+            begin: new Date("2017-03-12T00:00:00").getTime(),
+            end: new Date("2017-11-05T00:00:00").getTime()
+        },
+        2018: {
+            begin: new Date("2018-03-11T00:00:00").getTime(),
+            end: new Date("2018-11-04T00:00:00").getTime()
+        },
+        2019: {
+            begin: new Date("2019-03-10T00:00:00").getTime(),
+            end: new Date("2019-11-03T00:00:00").getTime()
+        },
+        2020: {
+            begin: new Date("2020-03-08T00:00:00").getTime(),
+            end: new Date("2020-11-01T00:00:00").getTime()
+        },
+        2021: {
+            begin: new Date("2021-03-14T00:00:00").getTime(),
+            end: new Date("2021-11-07T00:00:00").getTime()
+        },
+        2022: {
+            begin: new Date("2022-03-13T00:00:00").getTime(),
+            end: new Date("2022-11-06T00:00:00").getTime()
+        },
+        2023: {
+            begin: new Date("2023-03-12T00:00:00").getTime(),
+            end: new Date("2023-11-05T00:00:00").getTime()
+        },
+        2024: {
+            begin: new Date("2024-03-10T00:00:00").getTime(),
+            end: new Date("2024-11-03T00:00:00").getTime()
+        },
+        2025: {
+            begin: new Date("2025-03-09T00:00:00").getTime(),
+            end: new Date("2025-11-02T00:00:00").getTime()
+        }
+    }
+    return a;
+}
+noInline(test);
+
+let count = 10000;
+for (var i = 0; i < count; i++)
+    test();

Modified: trunk/JSTests/mozilla/ecma/Date/15.9.5.16.js (269319 => 269320)


--- trunk/JSTests/mozilla/ecma/Date/15.9.5.16.js	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/mozilla/ecma/Date/15.9.5.16.js	2020-11-03 19:26:49 UTC (rev 269320)
@@ -55,7 +55,6 @@
     TimeInYear(2002)+TimeInYear(2003)+TimeInYear(2004);
 
     addTestCase( now );
-    addTestCase( TIME_YEAR_0 );
     addTestCase( TIME_1970 );
     addTestCase( TIME_1900 );
     addTestCase( TIME_2000 );

Modified: trunk/JSTests/mozilla/ecma/Date/15.9.5.18.js (269319 => 269320)


--- trunk/JSTests/mozilla/ecma/Date/15.9.5.18.js	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/mozilla/ecma/Date/15.9.5.18.js	2020-11-03 19:26:49 UTC (rev 269320)
@@ -56,7 +56,6 @@
     TimeInYear(2002)+TimeInYear(2003)+TimeInYear(2004);
 
     addTestCase( now );
-    addTestCase( TIME_YEAR_0 );
     addTestCase( TIME_1970 );
     addTestCase( TIME_1900 );
     addTestCase( TIME_2000 );

Modified: trunk/JSTests/mozilla/ecma/Date/15.9.5.22-1.js (269319 => 269320)


--- trunk/JSTests/mozilla/ecma/Date/15.9.5.22-1.js	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/mozilla/ecma/Date/15.9.5.22-1.js	2020-11-03 19:26:49 UTC (rev 269320)
@@ -58,7 +58,6 @@
 
 //    addTestCase( now );
 
-    addTestCase( TIME_YEAR_0 );
     addTestCase( TIME_1970 );
     addTestCase( TIME_1900 );
     addTestCase( TIME_2000 );

Modified: trunk/JSTests/mozilla/ecma/Date/15.9.5.22-2.js (269319 => 269320)


--- trunk/JSTests/mozilla/ecma/Date/15.9.5.22-2.js	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/mozilla/ecma/Date/15.9.5.22-2.js	2020-11-03 19:26:49 UTC (rev 269320)
@@ -56,8 +56,8 @@
     var UTC_JAN_1_2005 = TIME_2000 + TimeInYear(2000)+TimeInYear(2001)+
     TimeInYear(2002)+TimeInYear(2003)+TimeInYear(2004);
 
+/*
     addTestCase( TIME_YEAR_0 );
-/*
     addTestCase( TIME_1970 );
     addTestCase( TIME_1900 );
     addTestCase( TIME_2000 );

Modified: trunk/JSTests/mozilla/ecma/Date/15.9.5.35-1.js (269319 => 269320)


--- trunk/JSTests/mozilla/ecma/Date/15.9.5.35-1.js	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/mozilla/ecma/Date/15.9.5.35-1.js	2020-11-03 19:26:49 UTC (rev 269320)
@@ -58,9 +58,9 @@
                     UTCDateFromTime(SetUTCMonth(0,11)),
                     LocalDateFromTime(SetUTCMonth(0,11)) );
 
-    addNewTestCase( "TDATE = new Date(0);(TDATE).setUTCMonth(3,4);TDATE",
-                    UTCDateFromTime(SetUTCMonth(0,3,4)),
-                    LocalDateFromTime(SetUTCMonth(0,3,4)) );
+    addNewTestCase( "TDATE = new Date(0);(TDATE).setUTCMonth(3,27);TDATE",
+                    UTCDateFromTime(SetUTCMonth(0,3,27)),
+                    LocalDateFromTime(SetUTCMonth(0,3,27)) );
 
 }
 

Modified: trunk/LayoutTests/ChangeLog (269319 => 269320)


--- trunk/LayoutTests/ChangeLog	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/ChangeLog	2020-11-03 19:26:49 UTC (rev 269320)
@@ -1,3 +1,25 @@
+2020-11-03  Yusuke Suzuki  <[email protected]>
+
+        REGRESSION (r254038): Simple.com money transfer UI is very laggy (multiple seconds per keypress)
+        https://bugs.webkit.org/show_bug.cgi?id=218348
+
+        Reviewed by Darin Adler.
+
+        * js/date-constructor-expected.txt: The time before America/Los_Angeles timezone is effective should be handled as UTC-0752. Use 1995 to test the intent correctly.
+        * js/date-timeClip-large-values-expected.txt: Ditto about old timezone.
+        * js/dom/script-tests/date-DST-time-cusps.js: Our timezone database was broken. Nov 02 2014 01:00:00 is not PDT.
+        (1.toString.match):
+        * js/dom/script-tests/date-big-setdate.js: Fix and adjust for right DST periods.
+        (1.toString.match):
+        * js/script-tests/date-constructor.js:
+        (object.valueOf):
+        * platform/mac/fast/AppleScript/date-expected.txt: Ditto, 1800 does not have America/Los_Angeles.
+        * platform/mac/fast/AppleScript/date.html:
+        * storage/indexeddb/modern/date-basic-expected.txt: Nov 04 1955 is PST, not PDT.
+        * storage/indexeddb/modern/date-basic-private-expected.txt: Ditto.
+        * storage/indexeddb/modern/get-keyrange-expected.txt: Ditto.
+        * storage/indexeddb/modern/get-keyrange-private-expected.txt: Ditto.
+
 2020-11-03  Commit Queue  <[email protected]>
 
         Unreviewed, reverting r268564, r268957, and r268962.

Modified: trunk/LayoutTests/js/date-constructor-expected.txt (269319 => 269320)


--- trunk/LayoutTests/js/date-constructor-expected.txt	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/js/date-constructor-expected.txt	2020-11-03 19:26:49 UTC (rev 269320)
@@ -4,26 +4,26 @@
 
 
 PASS isNaN(new Date("")) is true
-PASS new Date(1111).getTime() is 1111
-PASS new Date(object).getTime() is 1111
-PASS new Date(new Date(1111)).getTime() is 1111
-PASS new Date(new Date(1111).toString()).getTime() is 1000
-PASS new Date(1111, 1).getTime() - timeZoneOffset is -27104803200000
-PASS new Date(1111, 1, 1).getTime() - timeZoneOffset is -27104803200000
-PASS new Date(1111, 1, 1, 1).getTime() - timeZoneOffset is -27104799600000
-PASS new Date(1111, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799540000
-PASS new Date(1111, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799539000
-PASS new Date(1111, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(1111, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(new Date(1111, 1)).getTime() - timeZoneOffset is -27104803200000
-PASS new Date(new Date(1111, 1, 1)).getTime() - timeZoneOffset is -27104803200000
-PASS new Date(new Date(1111, 1, 1, 1)).getTime() - timeZoneOffset is -27104799600000
-PASS new Date(new Date(1111, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is -27104799539000
-PASS new Date(new Date(1111, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(new Date(1111, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is -27104799538999
+PASS new Date(1995).getTime() is 1995
+PASS new Date(object).getTime() is 1995
+PASS new Date(new Date(1995)).getTime() is 1995
+PASS new Date(new Date(1995).toString()).getTime() is 1000
+PASS new Date(1995, 1).getTime() - timeZoneOffset is 791596800000
+PASS new Date(1995, 1, 1).getTime() - timeZoneOffset is 791596800000
+PASS new Date(1995, 1, 1, 1).getTime() - timeZoneOffset is 791600400000
+PASS new Date(1995, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600460000
+PASS new Date(1995, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600461000
+PASS new Date(1995, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600461001
+PASS new Date(1995, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600461001
+PASS new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600461001
+PASS new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600461001
+PASS new Date(new Date(1995, 1)).getTime() - timeZoneOffset is 791596800000
+PASS new Date(new Date(1995, 1, 1)).getTime() - timeZoneOffset is 791596800000
+PASS new Date(new Date(1995, 1, 1, 1)).getTime() - timeZoneOffset is 791600400000
+PASS new Date(new Date(1995, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is 791600461000
+PASS new Date(new Date(1995, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is 791600461001
+PASS new Date(new Date(1995, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is 791600461001
+PASS new Date(new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is 791600461001
 PASS Number(new Date(new Date(Infinity, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset) is Number.NaN
 PASS Number(new Date(new Date(1, Infinity, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset) is Number.NaN
 PASS Number(new Date(new Date(1, 1, Infinity, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset) is Number.NaN

Modified: trunk/LayoutTests/js/date-timeClip-large-values-expected.txt (269319 => 269320)


--- trunk/LayoutTests/js/date-timeClip-large-values-expected.txt	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/js/date-timeClip-large-values-expected.txt	2020-11-03 19:26:49 UTC (rev 269320)
@@ -52,14 +52,14 @@
 PASS new Date(8.64e15).setMonth(new Date(8.64e15).getMonth() + 1).valueOf() is NaN
 Testing setYear()
 PASS new Date(0).setYear(Infinity).valueOf() is NaN
-FAIL new Date(0).setYear(1.79769e+308).valueOf() should be NaN. Was -62135596800000.
-FAIL new Date(0).setYear(-1.79769e+308).valueOf() should be NaN. Was -62135596800000.
+FAIL new Date(0).setYear(1.79769e+308).valueOf() should be NaN. Was -62135597222000.
+FAIL new Date(0).setYear(-1.79769e+308).valueOf() should be NaN. Was -62135597222000.
 PASS new Date(8.64e15).setYear(new Date(8.64e15).getFullYear()).valueOf() is 8.64e15
 PASS new Date(8.64e15).setYear(new Date(8.64e15).getFullYear() + 1).valueOf() is NaN
 Testing setFullYear()
 PASS new Date(0).setFullYear(Infinity).valueOf() is NaN
-FAIL new Date(0).setFullYear(1.79769e+308).valueOf() should be NaN. Was -62135596800000.
-FAIL new Date(0).setFullYear(-1.79769e+308).valueOf() should be NaN. Was -62135596800000.
+FAIL new Date(0).setFullYear(1.79769e+308).valueOf() should be NaN. Was -62135597222000.
+FAIL new Date(0).setFullYear(-1.79769e+308).valueOf() should be NaN. Was -62135597222000.
 PASS new Date(8.64e15).setFullYear(new Date(8.64e15).getFullYear()).valueOf() is 8.64e15
 PASS new Date(8.64e15).setFullYear(new Date(8.64e15).getFullYear() + 1).valueOf() is NaN
 Testing setUTCMilliseconds()

Modified: trunk/LayoutTests/js/dom/script-tests/date-DST-time-cusps.js (269319 => 269320)


--- trunk/LayoutTests/js/dom/script-tests/date-DST-time-cusps.js	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/js/dom/script-tests/date-DST-time-cusps.js	2020-11-03 19:26:49 UTC (rev 269320)
@@ -11,7 +11,7 @@
     testCases.push(["(new Date('Mar 09 2014 03:00:00')).getHours()", "3"]);
     testCases.push(["(new Date('Mar 09 2014 03:00:00')).getTimezoneOffset()", "420"]);
     testCases.push(["(new Date('Nov 02 2014 01:00:00')).getHours()", "1"]);
-    testCases.push(["(new Date('Nov 02 2014 01:00:00')).getTimezoneOffset()", "480"]);
+    testCases.push(["(new Date('Nov 02 2014 01:00:00')).getTimezoneOffset()", "420"]);
 }
 
 var errors = [];

Modified: trunk/LayoutTests/js/dom/script-tests/date-big-setdate.js (269319 => 269320)


--- trunk/LayoutTests/js/dom/script-tests/date-big-setdate.js	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/js/dom/script-tests/date-big-setdate.js	2020-11-03 19:26:49 UTC (rev 269320)
@@ -23,17 +23,17 @@
 if ((new Date(2009, 9, 1)).toString().match("PDT")) {
     // Added a special case that should represent a change in DST.  DST did not actually
     // change on this date but because of the wierdness of how _javascript_Dates are
-// expected to interpolate DST as opposed to reflect acurate history, this day
+    // expected to interpolate DST as opposed to reflect acurate history, this day
     // (April 5th 1970) should show a DST change.
-    testCases.push([new Date(0), 97, 98]);
+    testCases.push([new Date(0), 146, 147]); // DST in 1970 is 4/26 14:00 - 10/25 14:00. And since epoch 0 is 16:00, 147 dates (4/26) is already in DST.
 
     // Added more special cases. These dates match the recent DST changes in the US.
     // These tests check that the new changes are correctly propogated to the past and
     // all of the tests should show DST occurring on the same date.
-    testCases.push([new Date(1970, 0,0,0,0,0,0), 98, 99]);
-    testCases.push([new Date(1998, 0,0,0,0,0,0), 98, 99]);
-    testCases.push([new Date(2026, 0,0,0,0,0,0), 98, 99]);
-    testCases.push([new Date(2054, 0,0,0,0,0,0), 98, 99]);
+    testCases.push([new Date(1970, 0,0,0,0,0,0), 147, 148]); // DST in 1970 is 4/26 14:00 - 10/25 14:00
+    testCases.push([new Date(1998, 0,0,0,0,0,0), 126, 127]); // DST in 1998 is 4/5 14:00 - 10/25 14:00
+    testCases.push([new Date(2026, 0,0,0,0,0,0), 98, 99]); // DST in 2026 is 3/8 14:00 - 11/1 14:00
+    testCases.push([new Date(2054, 0,0,0,0,0,0), 98, 99]); // DST in 2054 is 3/8 14:00 - 11/1 14:00
 }
 
 var errors = [];
@@ -42,7 +42,6 @@
     var d = new Date(c);
     c.setDate(testCases[i][1]);
     d.setDate(testCases[i][2]);
-
     var actual = d.valueOf() - c.valueOf();
     var expected = millisecondsPerDay - millisecondsPerHour;
     if (actual != expected) {

Modified: trunk/LayoutTests/js/script-tests/date-constructor.js (269319 => 269320)


--- trunk/LayoutTests/js/script-tests/date-constructor.js	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/js/script-tests/date-constructor.js	2020-11-03 19:26:49 UTC (rev 269320)
@@ -7,7 +7,7 @@
 );
 
 var object = new Object;
-object.valueOf = function() { return 1111; }
+object.valueOf = function() { return 1995; }
 object.toString = function() { return "2222"; }
 
 shouldBe('isNaN(new Date(""))', 'true');
@@ -14,28 +14,28 @@
 
 var timeZoneOffset = Date.parse("Dec 25 1995") - Date.parse("Dec 25 1995 GMT");
 
-shouldBe('new Date(1111).getTime()', '1111');
-shouldBe('new Date(object).getTime()', '1111');
-shouldBe('new Date(new Date(1111)).getTime()', '1111');
-shouldBe('new Date(new Date(1111).toString()).getTime()', '1000');
+shouldBe('new Date(1995).getTime()', '1995');
+shouldBe('new Date(object).getTime()', '1995');
+shouldBe('new Date(new Date(1995)).getTime()', '1995');
+shouldBe('new Date(new Date(1995).toString()).getTime()', '1000');
 
-shouldBe('new Date(1111, 1).getTime() - timeZoneOffset', '-27104803200000');
-shouldBe('new Date(1111, 1, 1).getTime() - timeZoneOffset', '-27104803200000');
-shouldBe('new Date(1111, 1, 1, 1).getTime() - timeZoneOffset', '-27104799600000');
-shouldBe('new Date(1111, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799540000');
-shouldBe('new Date(1111, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799539000');
-shouldBe('new Date(1111, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799538999');
-shouldBe('new Date(1111, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799538999');
-shouldBe('new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799538999');
-shouldBe('new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799538999');
+shouldBe('new Date(1995, 1).getTime() - timeZoneOffset', '791596800000');
+shouldBe('new Date(1995, 1, 1).getTime() - timeZoneOffset', '791596800000');
+shouldBe('new Date(1995, 1, 1, 1).getTime() - timeZoneOffset', '791600400000');
+shouldBe('new Date(1995, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600460000');
+shouldBe('new Date(1995, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600461000');
+shouldBe('new Date(1995, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600461001');
+shouldBe('new Date(1995, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600461001');
+shouldBe('new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600461001');
+shouldBe('new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600461001');
 
-shouldBe('new Date(new Date(1111, 1)).getTime() - timeZoneOffset', '-27104803200000');
-shouldBe('new Date(new Date(1111, 1, 1)).getTime() - timeZoneOffset', '-27104803200000');
-shouldBe('new Date(new Date(1111, 1, 1, 1)).getTime() - timeZoneOffset', '-27104799600000');
-shouldBe('new Date(new Date(1111, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '-27104799539000');
-shouldBe('new Date(new Date(1111, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '-27104799538999');
-shouldBe('new Date(new Date(1111, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '-27104799538999');
-shouldBe('new Date(new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '-27104799538999');
+shouldBe('new Date(new Date(1995, 1)).getTime() - timeZoneOffset', '791596800000');
+shouldBe('new Date(new Date(1995, 1, 1)).getTime() - timeZoneOffset', '791596800000');
+shouldBe('new Date(new Date(1995, 1, 1, 1)).getTime() - timeZoneOffset', '791600400000');
+shouldBe('new Date(new Date(1995, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '791600461000');
+shouldBe('new Date(new Date(1995, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '791600461001');
+shouldBe('new Date(new Date(1995, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '791600461001');
+shouldBe('new Date(new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '791600461001');
 
 shouldBe("Number(new Date(new Date(Infinity, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset)", 'Number.NaN');
 shouldBe("Number(new Date(new Date(1, Infinity, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset)", 'Number.NaN');
@@ -53,9 +53,9 @@
 shouldBe("new Date(Date.parse('1 Mar 1000 GMT')).toGMTString()", "\"Sat, 01 Mar 1000 00:00:00 GMT\"");
 
 // In Firefox, the results of the following tests are timezone-dependent, which likely implies that the implementation is not quite correct.
-// Our results are even worse, though, as the dates are clipped: (new Date(1111, 1201).getTime()) == (new Date(1111, 601).getTime())
-// shouldBe('new Date(1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111).getTime() - timeZoneOffset', '-24085894227889');
-// shouldBe('new Date(new Date(1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111)).getTime() - timeZoneOffset', '-24085894227889');
+// Our results are even worse, though, as the dates are clipped: (new Date(1995, 1201).getTime()) == (new Date(1995, 601).getTime())
+// shouldBe('new Date(1995, 1995, 1995, 1995, 1995, 1995, 1995, 1995).getTime() - timeZoneOffset', '-24085894227889');
+// shouldBe('new Date(new Date(1995, 1995, 1995, 1995, 1995, 1995, 1995, 1995)).getTime() - timeZoneOffset', '-24085894227889');
 
 // Regression test for Bug 26978 (https://bugs.webkit.org/show_bug.cgi?id=26978)
 var testStr = "";

Modified: trunk/LayoutTests/platform/mac/fast/AppleScript/date-expected.txt (269319 => 269320)


--- trunk/LayoutTests/platform/mac/fast/AppleScript/date-expected.txt	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/platform/mac/fast/AppleScript/date-expected.txt	2020-11-03 19:26:49 UTC (rev 269320)
@@ -4,5 +4,5 @@
 00000001383EC400 ('ldt ')
 0000000056871300 ('ldt ')
 0000000000000000 ('ldt ')
-FFFFFFFF3C637000 ('ldt ')
+FFFFFFFF3C636E5A ('ldt ')
 "Invalid Date" ('utxt')

Modified: trunk/LayoutTests/platform/mac/fast/AppleScript/date.html (269319 => 269320)


--- trunk/LayoutTests/platform/mac/fast/AppleScript/date.html	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/platform/mac/fast/AppleScript/date.html	2020-11-03 19:26:49 UTC (rev 269320)
@@ -37,7 +37,7 @@
             // 0x00000000 == Fri Jan 01 1904 00:00:00
             log(appleScriptController.doJavaScript("new Date(1904,0,1)"));
             
-            // 0xffffffff3c637000 == Wed Jan 01 1800 00:00:00
+            // 0xffffffff3c636e5a == Wed Jan 01 1800 00:00:00, this is because America/Los_Angeles timzeone is not effective at 1800.
             log(appleScriptController.doJavaScript("new Date(1800,0,1)"));
 
             // invalid date 

Modified: trunk/LayoutTests/storage/indexeddb/modern/date-basic-expected.txt (269319 => 269320)


--- trunk/LayoutTests/storage/indexeddb/modern/date-basic-expected.txt	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/storage/indexeddb/modern/date-basic-expected.txt	2020-11-03 19:26:49 UTC (rev 269320)
@@ -9,13 +9,13 @@
 indexedDB.open(dbname)
 Initial upgrade needed: Old version - 0 New version - 1
 Initial upgrade versionchange transaction complete
-Success getting key 'Fri Nov 04 1955 17:00:00 GMT-0700 (PDT)' of type object, result is 'Flux capacitor' of type string
+Success getting key 'Fri Nov 04 1955 16:00:00 GMT-0800 (PST)' of type object, result is 'Flux capacitor' of type string
 Key is a Date object, btw
 Success getting key 'Sat Nov 12 1955 10:00:00 GMT-0800 (PST)' of type object, result is 'Fish under the sea' of type string
 Key is a Date object, btw
 Success getting key 'Wed Oct 21 2015 09:00:00 GMT-0700 (PDT)' of type object, result is 'Hoverboards' of type string
 Key is a Date object, btw
-Success getting key 'a' of type string, result is 'Fri Nov 04 1955 17:00:00 GMT-0700 (PDT)' of type object
+Success getting key 'a' of type string, result is 'Fri Nov 04 1955 16:00:00 GMT-0800 (PST)' of type object
 Result is a Date object, btw
 Success getting key 'b' of type string, result is 'Sat Nov 12 1955 10:00:00 GMT-0800 (PST)' of type object
 Result is a Date object, btw

Modified: trunk/LayoutTests/storage/indexeddb/modern/date-basic-private-expected.txt (269319 => 269320)


--- trunk/LayoutTests/storage/indexeddb/modern/date-basic-private-expected.txt	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/storage/indexeddb/modern/date-basic-private-expected.txt	2020-11-03 19:26:49 UTC (rev 269320)
@@ -9,13 +9,13 @@
 indexedDB.open(dbname)
 Initial upgrade needed: Old version - 0 New version - 1
 Initial upgrade versionchange transaction complete
-Success getting key 'Fri Nov 04 1955 17:00:00 GMT-0700 (PDT)' of type object, result is 'Flux capacitor' of type string
+Success getting key 'Fri Nov 04 1955 16:00:00 GMT-0800 (PST)' of type object, result is 'Flux capacitor' of type string
 Key is a Date object, btw
 Success getting key 'Sat Nov 12 1955 10:00:00 GMT-0800 (PST)' of type object, result is 'Fish under the sea' of type string
 Key is a Date object, btw
 Success getting key 'Wed Oct 21 2015 09:00:00 GMT-0700 (PDT)' of type object, result is 'Hoverboards' of type string
 Key is a Date object, btw
-Success getting key 'a' of type string, result is 'Fri Nov 04 1955 17:00:00 GMT-0700 (PDT)' of type object
+Success getting key 'a' of type string, result is 'Fri Nov 04 1955 16:00:00 GMT-0800 (PST)' of type object
 Result is a Date object, btw
 Success getting key 'b' of type string, result is 'Sat Nov 12 1955 10:00:00 GMT-0800 (PST)' of type object
 Result is a Date object, btw

Modified: trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-expected.txt (269319 => 269320)


--- trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-expected.txt	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-expected.txt	2020-11-03 19:26:49 UTC (rev 269320)
@@ -123,13 +123,13 @@
 Result is PosInf
 Success getting keyRange [Infinity (Open), a (Open)]
 Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
 Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
 Result is Fish under the sea
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
 Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
 Result is Fish under the sea
 readonly transaction complete
 PASS successfullyParsed is true

Modified: trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-private-expected.txt (269319 => 269320)


--- trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-private-expected.txt	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-private-expected.txt	2020-11-03 19:26:49 UTC (rev 269320)
@@ -123,13 +123,13 @@
 Result is PosInf
 Success getting keyRange [Infinity (Open), a (Open)]
 Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
 Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
 Result is Fish under the sea
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
 Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
 Result is Fish under the sea
 readonly transaction complete
 PASS successfullyParsed is true

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (269319 => 269320)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2020-11-03 19:26:49 UTC (rev 269320)
@@ -911,6 +911,7 @@
     runtime/JSCell.h
     runtime/JSCellInlines.h
     runtime/JSDataView.h
+    runtime/JSDateMath.h
     runtime/JSDestructibleObject.h
     runtime/JSDestructibleObjectHeapCellType.h
     runtime/JSExportMacros.h

Modified: trunk/Source/_javascript_Core/ChangeLog (269319 => 269320)


--- trunk/Source/_javascript_Core/ChangeLog	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-11-03 19:26:49 UTC (rev 269320)
@@ -1,3 +1,56 @@
+2020-11-03  Yusuke Suzuki  <[email protected]>
+
+        REGRESSION (r254038): Simple.com money transfer UI is very laggy (multiple seconds per keypress)
+        https://bugs.webkit.org/show_bug.cgi?id=218348
+
+        Reviewed by Darin Adler.
+
+        We have depth-1 LocalTimeOffset cache to avoid repeatedly calling `localtime_r`. But this depth-1 cache can be easily missed if
+        we parse Dates of multiple years. Instead of increasing depth as a work-around, this patch starts using ICU TimeZone cache.
+        This is used in SpiderMonkey and V8 too, and it is the right direction since ICU knows tzdata and can do more sophisticated caching.
+
+        Microbenchmark shows 24x improvement.
+
+                                           ToT                     Patched
+
+        local-date-constructor     2026.8715+-11.2909    ^     85.0022+-1.0548        ^ definitely 23.8449x faster
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * runtime/DateConstructor.cpp:
+        (JSC::millisecondsFromComponents):
+        (JSC::constructDate):
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        * runtime/DateInstance.cpp:
+        (JSC::DateInstance::calculateGregorianDateTime const):
+        (JSC::DateInstance::calculateGregorianDateTimeUTC const):
+        * runtime/DateInstance.h:
+        * runtime/DatePrototype.cpp:
+        (JSC::setNewValueFromTimeArgs):
+        (JSC::setNewValueFromDateArgs):
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        * runtime/JSDateMath.cpp:
+        (JSC::OpaqueICUTimeZoneDeleter::operator()):
+        (JSC::localTimeOffset):
+        (JSC::DateCache::gregorianDateTimeToMS):
+        (JSC::DateCache::msToGregorianDateTime):
+        (JSC::DateCache::parseDate):
+        (JSC::DateCache::cachedDateInstanceData):
+        (JSC::DateCache::timeZoneCacheSlow):
+        (JSC::DateCache::reset):
+        (JSC::gregorianDateTimeToMS): Deleted.
+        (JSC::msToGregorianDateTime): Deleted.
+        (JSC::parseDate): Deleted.
+        * runtime/JSDateMath.h:
+        (JSC::DateCache::timeZoneCache):
+        * runtime/VM.cpp:
+        (JSC::VM::resetDateCache): Deleted.
+        * runtime/VM.h:
+        (JSC::VM::resetDateCache):
+        * runtime/VMEntryScope.cpp:
+        (JSC::VMEntryScope::VMEntryScope):
+
 2020-11-03  Keith Rollin  <[email protected]>
 
         Extend check-for-inappropriate-files-in-framework to WebKitLegacy and _javascript_Core

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (269319 => 269320)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2020-11-03 19:26:49 UTC (rev 269320)
@@ -1859,6 +1859,7 @@
 		E3850B15226ED641009ABF9C /* DFGMinifiedIDInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E3850B14226ED63E009ABF9C /* DFGMinifiedIDInlines.h */; };
 		E38652E3237CA0C900E1D5EE /* BlockDirectoryBits.h in Headers */ = {isa = PBXBuildFile; fileRef = E38652E2237CA0C800E1D5EE /* BlockDirectoryBits.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E3893A1D2203A7C600E79A74 /* AsyncFromSyncIteratorPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E3893A1C2203A7C600E79A74 /* AsyncFromSyncIteratorPrototype.lut.h */; };
+		E38E8790254B978400F6F9E4 /* JSDateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9788FC221471AD0C0068CE2D /* JSDateMath.cpp */; };
 		E39006212208BFC4001019CF /* SubspaceAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = E39006202208BFC3001019CF /* SubspaceAccess.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E392E6F824D25FA600B20767 /* B3BottomTupleValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E392E6F624D25FA600B20767 /* B3BottomTupleValue.cpp */; };
 		E392E6F924D25FA900B20767 /* B3BottomTupleValue.h in Headers */ = {isa = PBXBuildFile; fileRef = E392E6F724D25FA600B20767 /* B3BottomTupleValue.h */; };
@@ -11388,6 +11389,7 @@
 				33B2A548226543BF005A0F79 /* FTLLowerDFGToB3.cpp in Sources */,
 				5C4196622270E0000047B7CD /* InspectorBackendDispatcherCompatibility.cpp in Sources */,
 				E366441E254409B30001876F /* IntlListFormat.cpp in Sources */,
+				E38E8790254B978400F6F9E4 /* JSDateMath.cpp in Sources */,
 				536B319E1F735F160037FC33 /* LowLevelInterpreter.cpp in Sources */,
 				0FF4274A158EBE91004CB9FF /* udis86.c in Sources */,
 				0FF42740158EBE8B004CB9FF /* udis86_decode.c in Sources */,

Modified: trunk/Source/_javascript_Core/Sources.txt (269319 => 269320)


--- trunk/Source/_javascript_Core/Sources.txt	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/Sources.txt	2020-11-03 19:26:49 UTC (rev 269320)
@@ -864,7 +864,7 @@
 runtime/JSCustomGetterSetterFunction.cpp
 runtime/JSDataView.cpp
 runtime/JSDataViewPrototype.cpp
-runtime/JSDateMath.cpp
+runtime/JSDateMath.cpp @no-unify // Confine U_SHOW_CPLUSPLUS_API's effect to this file.
 runtime/JSDestructibleObjectHeapCellType.cpp
 runtime/JSFinalizationRegistry.cpp
 runtime/JSFunction.cpp

Modified: trunk/Source/_javascript_Core/runtime/DateConstructor.cpp (269319 => 269320)


--- trunk/Source/_javascript_Core/runtime/DateConstructor.cpp	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/DateConstructor.cpp	2020-11-03 19:26:49 UTC (rev 269320)
@@ -94,7 +94,7 @@
     t.setMinute(JSC::toInt32(doubleArguments[4]));
     t.setSecond(JSC::toInt32(doubleArguments[5]));
     t.setIsDST(-1);
-    return gregorianDateTimeToMS(vm.dateCache, t, doubleArguments[6], timeType);
+    return vm.dateCache.gregorianDateTimeToMS(t, doubleArguments[6], timeType);
 }
 
 // ECMA 15.9.3
@@ -118,7 +118,7 @@
             if (primitive.isString()) {
                 String primitiveString = asString(primitive)->value(globalObject);
                 RETURN_IF_EXCEPTION(scope, nullptr);
-                value = parseDate(globalObject, vm, primitiveString);
+                value = vm.dateCache.parseDate(globalObject, vm, primitiveString);
                 RETURN_IF_EXCEPTION(scope, nullptr);
             } else
                 value = primitive.toNumber(globalObject);
@@ -146,7 +146,7 @@
 {
     VM& vm = globalObject->vm();
     GregorianDateTime ts;
-    msToGregorianDateTime(vm.dateCache, WallTime::now().secondsSinceEpoch().milliseconds(), WTF::LocalTime, ts);
+    vm.dateCache.msToGregorianDateTime(WallTime::now().secondsSinceEpoch().milliseconds(), WTF::LocalTime, ts);
     return JSValue::encode(jsNontrivialString(vm, formatDateTime(ts, DateTimeFormatDateAndTime, false)));
 }
 
@@ -156,7 +156,7 @@
     auto scope = DECLARE_THROW_SCOPE(vm);
     String dateStr = callFrame->argument(0).toWTFString(globalObject);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
-    RELEASE_AND_RETURN(scope, JSValue::encode(jsNumber(parseDate(globalObject, vm, dateStr))));
+    RELEASE_AND_RETURN(scope, JSValue::encode(jsNumber(vm.dateCache.parseDate(globalObject, vm, dateStr))));
 }
 
 JSValue dateNowImpl()

Modified: trunk/Source/_javascript_Core/runtime/DateInstance.cpp (269319 => 269320)


--- trunk/Source/_javascript_Core/runtime/DateInstance.cpp	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/DateInstance.cpp	2020-11-03 19:26:49 UTC (rev 269320)
@@ -52,7 +52,7 @@
     return "Date"_s;
 }
 
-const GregorianDateTime* DateInstance::calculateGregorianDateTime(VM::DateCache& cache) const
+const GregorianDateTime* DateInstance::calculateGregorianDateTime(DateCache& cache) const
 {
     double milli = internalNumber();
     if (std::isnan(milli))
@@ -59,16 +59,16 @@
         return nullptr;
 
     if (!m_data)
-        m_data = cache.dateInstanceCache.add(milli);
+        m_data = cache.cachedDateInstanceData(milli);
 
     if (m_data->m_gregorianDateTimeCachedForMS != milli) {
-        msToGregorianDateTime(cache, milli, WTF::LocalTime, m_data->m_cachedGregorianDateTime);
+        cache.msToGregorianDateTime(milli, WTF::LocalTime, m_data->m_cachedGregorianDateTime);
         m_data->m_gregorianDateTimeCachedForMS = milli;
     }
     return &m_data->m_cachedGregorianDateTime;
 }
 
-const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(VM::DateCache& cache) const
+const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(DateCache& cache) const
 {
     double milli = internalNumber();
     if (std::isnan(milli))
@@ -75,10 +75,10 @@
         return nullptr;
 
     if (!m_data)
-        m_data = cache.dateInstanceCache.add(milli);
+        m_data = cache.cachedDateInstanceData(milli);
 
     if (m_data->m_gregorianDateTimeUTCCachedForMS != milli) {
-        msToGregorianDateTime(cache, milli, WTF::UTCTime, m_data->m_cachedGregorianDateTimeUTC);
+        cache.msToGregorianDateTime(milli, WTF::UTCTime, m_data->m_cachedGregorianDateTimeUTC);
         m_data->m_gregorianDateTimeUTCCachedForMS = milli;
     }
     return &m_data->m_cachedGregorianDateTimeUTC;

Modified: trunk/Source/_javascript_Core/runtime/DateInstance.h (269319 => 269320)


--- trunk/Source/_javascript_Core/runtime/DateInstance.h	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/DateInstance.h	2020-11-03 19:26:49 UTC (rev 269320)
@@ -60,7 +60,7 @@
 
     DECLARE_EXPORT_INFO;
 
-    const GregorianDateTime* gregorianDateTime(VM::DateCache& cache) const
+    const GregorianDateTime* gregorianDateTime(DateCache& cache) const
     {
         if (m_data && m_data->m_gregorianDateTimeCachedForMS == internalNumber())
             return &m_data->m_cachedGregorianDateTime;
@@ -67,7 +67,7 @@
         return calculateGregorianDateTime(cache);
     }
 
-    const GregorianDateTime* gregorianDateTimeUTC(VM::DateCache& cache) const
+    const GregorianDateTime* gregorianDateTimeUTC(DateCache& cache) const
     {
         if (m_data && m_data->m_gregorianDateTimeUTCCachedForMS == internalNumber())
             return &m_data->m_cachedGregorianDateTimeUTC;
@@ -86,8 +86,8 @@
     JS_EXPORT_PRIVATE DateInstance(VM&, Structure*);
     void finishCreation(VM&);
     JS_EXPORT_PRIVATE void finishCreation(VM&, double);
-    JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTime(VM::DateCache&) const;
-    JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTimeUTC(VM::DateCache&) const;
+    JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTime(DateCache&) const;
+    JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTimeUTC(DateCache&) const;
 
     double m_internalNumber { PNaN };
     mutable RefPtr<DateInstanceData> m_data;

Modified: trunk/Source/_javascript_Core/runtime/DatePrototype.cpp (269319 => 269320)


--- trunk/Source/_javascript_Core/runtime/DatePrototype.cpp	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/DatePrototype.cpp	2020-11-03 19:26:49 UTC (rev 269320)
@@ -696,7 +696,7 @@
         return JSValue::encode(jsNaN());
     } 
 
-    double newUTCDate = gregorianDateTimeToMS(cache, gregorianDateTime, ms, inputTimeType);
+    double newUTCDate = cache.gregorianDateTimeToMS(gregorianDateTime, ms, inputTimeType);
     double result = timeClip(newUTCDate);
     thisDateObj->setInternalNumber(result);
     return JSValue::encode(jsNumber(result));
@@ -723,7 +723,7 @@
 
     GregorianDateTime gregorianDateTime; 
     if (numArgsToUse == 3 && std::isnan(milli)) 
-        msToGregorianDateTime(cache, 0, WTF::UTCTime, gregorianDateTime);
+        cache.msToGregorianDateTime(0, WTF::UTCTime, gregorianDateTime);
     else { 
         ms = milli - floor(milli / msPerSecond) * msPerSecond; 
         const GregorianDateTime* other = inputTimeType == WTF::UTCTime
@@ -741,7 +741,7 @@
         return JSValue::encode(jsNaN());
     } 
 
-    double newUTCDate = gregorianDateTimeToMS(cache, gregorianDateTime, ms, inputTimeType);
+    double newUTCDate = cache.gregorianDateTimeToMS(gregorianDateTime, ms, inputTimeType);
     double result = timeClip(newUTCDate);
     thisDateObj->setInternalNumber(result);
     return JSValue::encode(jsNumber(result));
@@ -840,7 +840,7 @@
     if (std::isnan(milli))
         // Based on ECMA 262 B.2.5 (setYear)
         // the time must be reset to +0 if it is NaN.
-        msToGregorianDateTime(cache, 0, WTF::UTCTime, gregorianDateTime);
+        cache.msToGregorianDateTime(0, WTF::UTCTime, gregorianDateTime);
     else {
         double secs = floor(milli / msPerSecond);
         ms = milli - secs * msPerSecond;
@@ -856,7 +856,7 @@
     }
 
     gregorianDateTime.setYear(toInt32((year >= 0 && year <= 99) ? (year + 1900) : year));
-    double timeInMilliseconds = gregorianDateTimeToMS(cache, gregorianDateTime, ms, WTF::LocalTime);
+    double timeInMilliseconds = cache.gregorianDateTimeToMS(gregorianDateTime, ms, WTF::LocalTime);
     double result = timeClip(timeInMilliseconds);
     thisDateObj->setInternalNumber(result);
     return JSValue::encode(jsNumber(result));

Modified: trunk/Source/_javascript_Core/runtime/JSDateMath.cpp (269319 => 269320)


--- trunk/Source/_javascript_Core/runtime/JSDateMath.cpp	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/JSDateMath.cpp	2020-11-03 19:26:49 UTC (rev 269320)
@@ -76,70 +76,47 @@
 #include "VM.h"
 #include <limits>
 
+// icu::TimeZone and icu::BasicTimeZone features are only available in ICU C++ APIs.
+// We use these C++ APIs as an exception.
+#undef U_SHOW_CPLUSPLUS_API
+#define U_SHOW_CPLUSPLUS_API 1
+#include <unicode/basictz.h>
+#include <unicode/timezone.h>
+#undef U_SHOW_CPLUSPLUS_API
+#define U_SHOW_CPLUSPLUS_API 0
+
 namespace JSC {
 
+void OpaqueICUTimeZoneDeleter::operator()(OpaqueICUTimeZone* timeZone)
+{
+    if (timeZone)
+        delete bitwise_cast<icu::TimeZone*>(timeZone);
+}
+
 // Get the combined UTC + DST offset for the time passed in.
 //
 // NOTE: The implementation relies on the fact that no time zones have
 // more than one daylight savings offset change per month.
 // If this function is called with NaN it returns NaN.
-static LocalTimeOffset localTimeOffset(VM::DateCache& dateCache, double ms, WTF::TimeType inputTimeType = WTF::UTCTime)
+static LocalTimeOffset localTimeOffset(DateCache& dateCache, double millisecondsFromEpoch, WTF::TimeType inputTimeType = WTF::UTCTime)
 {
-    LocalTimeOffsetCache& cache = inputTimeType == WTF::LocalTime
-        ? dateCache.localTimeOffsetCache : dateCache.utcTimeOffsetCache;
-
-    double start = cache.start;
-    double end = cache.end;
-
-    if (start <= ms) {
-        // If the time fits in the cached interval, return the cached offset.
-        if (ms <= end)
-            return cache.offset;
-
-        // Compute a possible new interval end.
-        double newEnd = end + cache.increment;
-
-        if (ms <= newEnd) {
-            LocalTimeOffset endOffset = calculateLocalTimeOffset(newEnd, inputTimeType);
-            if (cache.offset == endOffset) {
-                // If the offset at the end of the new interval still matches
-                // the offset in the cache, we grow the cached time interval
-                // and return the offset.
-                cache.end = newEnd;
-                cache.increment = WTF::msPerMonth;
-                return endOffset;
-            }
-            LocalTimeOffset offset = calculateLocalTimeOffset(ms, inputTimeType);
-            if (offset == endOffset) {
-                // The offset at the given time is equal to the offset at the
-                // new end of the interval, so that means that we've just skipped
-                // the point in time where the DST offset change occurred. Updated
-                // the interval to reflect this and reset the increment.
-                cache.start = ms;
-                cache.end = newEnd;
-                cache.increment = WTF::msPerMonth;
-            } else {
-                // The interval contains a DST offset change and the given time is
-                // before it. Adjust the increment to avoid a linear search for
-                // the offset change point and change the end of the interval.
-                cache.increment /= 3;
-                cache.end = ms;
-            }
-            // Update the offset in the cache and return it.
-            cache.offset = offset;
-            return offset;
-        }
+    auto& timeZoneCache = *bitwise_cast<icu::TimeZone*>(dateCache.timeZoneCache());
+    int32_t rawOffset = 0;
+    int32_t dstOffset = 0;
+    UErrorCode status = U_ZERO_ERROR;
+    if (inputTimeType != WTF::LocalTime) {
+        constexpr bool isLocalTime = false;
+        timeZoneCache.getOffset(millisecondsFromEpoch, isLocalTime, rawOffset, dstOffset, status);
+    } else {
+        // icu::TimeZone is a timezone instance which inherits icu::BasicTimeZone.
+        // https://unicode-org.atlassian.net/browse/ICU-13705 will move getOffsetFromLocal to icu::TimeZone.
+        static_cast<const icu::BasicTimeZone&>(timeZoneCache).getOffsetFromLocal(millisecondsFromEpoch, icu::BasicTimeZone::kFormer, icu::BasicTimeZone::kFormer, rawOffset, dstOffset, status);
     }
-
-    // Compute the DST offset for the time and shrink the cache interval
-    // to only contain the time. This allows fast repeated DST offset
-    // computations for the same time.
-    LocalTimeOffset offset = calculateLocalTimeOffset(ms, inputTimeType);
-    cache.offset = offset;
-    cache.start = ms;
-    cache.end = ms;
-    cache.increment = WTF::msPerMonth;
-    return offset;
+    // The above can fail if input date is invalid: NaN etc.
+    // We can return any values in this case since later we fail when computing non timezone offset part anyway.
+    if (U_FAILURE(status))
+        return { false, 0 };
+    return { !!dstOffset, rawOffset + dstOffset };
 }
 
 static inline double timeToMS(double hour, double min, double sec, double ms)
@@ -147,49 +124,35 @@
     return (((hour * WTF::minutesPerHour + min) * WTF::secondsPerMinute + sec) * WTF::msPerSecond + ms);
 }
 
-double gregorianDateTimeToMS(VM::DateCache& cache, const GregorianDateTime& t, double milliSeconds, WTF::TimeType inputTimeType)
+double DateCache::gregorianDateTimeToMS(const GregorianDateTime& t, double milliseconds, WTF::TimeType inputTimeType)
 {
     double day = dateToDaysFrom1970(t.year(), t.month(), t.monthDay());
-    double ms = timeToMS(t.hour(), t.minute(), t.second(), milliSeconds);
+    double ms = timeToMS(t.hour(), t.minute(), t.second(), milliseconds);
     double localTimeResult = (day * WTF::msPerDay) + ms;
 
     double localToUTCTimeOffset = inputTimeType == WTF::LocalTime
-        ? localTimeOffset(cache, localTimeResult, inputTimeType).offset : 0;
+        ? localTimeOffset(*this, localTimeResult, inputTimeType).offset : 0;
 
     return localTimeResult - localToUTCTimeOffset;
 }
 
 // input is UTC
-void msToGregorianDateTime(VM::DateCache& cache, double ms, WTF::TimeType outputTimeType, GregorianDateTime& tm)
+void DateCache::msToGregorianDateTime(double millisecondsFromEpoch, WTF::TimeType outputTimeType, GregorianDateTime& tm)
 {
     LocalTimeOffset localTime;
     if (outputTimeType == WTF::LocalTime) {
-        localTime = localTimeOffset(cache, ms);
-        ms += localTime.offset;
+        localTime = localTimeOffset(*this, millisecondsFromEpoch);
+        millisecondsFromEpoch += localTime.offset;
     }
-    tm = GregorianDateTime(ms, localTime);
+    tm = GregorianDateTime(millisecondsFromEpoch, localTime);
 }
 
-static double parseDate(VM::DateCache& cache, const char* dateString)
+double DateCache::parseDate(JSGlobalObject* globalObject, VM& vm, const String& date)
 {
-    bool isLocalTime;
-    double value = WTF::parseES5DateFromNullTerminatedCharacters(dateString, isLocalTime);
-    if (std::isnan(value))
-        value = WTF::parseDateFromNullTerminatedCharacters(dateString, isLocalTime);
-
-    if (isLocalTime)
-        value -= localTimeOffset(cache, value, WTF::LocalTime).offset;
-
-    return value;
-}
-
-double parseDate(JSGlobalObject* globalObject, VM& vm, const String& date)
-{
     auto scope = DECLARE_THROW_SCOPE(vm);
-    auto& cache = vm.dateCache;
 
-    if (date == cache.cachedDateString)
-        return cache.cachedDateStringValue;
+    if (date == m_cachedDateString)
+        return m_cachedDateStringValue;
     auto expectedString = date.tryGetUtf8();
     if (!expectedString) {
         if (expectedString.error() == UTF8ConversionError::OutOfMemory)
@@ -200,11 +163,47 @@
         return std::numeric_limits<double>::quiet_NaN();
     }
 
+    auto parseDateImpl = [this] (const char* dateString) {
+        bool isLocalTime;
+        double value = WTF::parseES5DateFromNullTerminatedCharacters(dateString, isLocalTime);
+        if (std::isnan(value))
+            value = WTF::parseDateFromNullTerminatedCharacters(dateString, isLocalTime);
+
+        if (isLocalTime)
+            value -= localTimeOffset(*this, value, WTF::LocalTime).offset;
+
+        return value;
+    };
+
     auto dateUtf8 = expectedString.value();
-    double value = parseDate(cache, dateUtf8.data());
-    cache.cachedDateString = date;
-    cache.cachedDateStringValue = value;
+    double value = parseDateImpl(dateUtf8.data());
+    m_cachedDateString = date;
+    m_cachedDateStringValue = value;
     return value;
 }
 
+// To confine icu::TimeZone destructor invocation in this file.
+DateCache::DateCache() = default;
+DateCache::~DateCache() = default;
+
+Ref<DateInstanceData> DateCache::cachedDateInstanceData(double millisecondsFromEpoch)
+{
+    return *m_dateInstanceCache.add(millisecondsFromEpoch);
+}
+
+void DateCache::timeZoneCacheSlow()
+{
+    // Do not use icu::TimeZone::createDefault. ICU internally has a cache for timezone and createDefault returns this cached value.
+    ASSERT(!m_timeZoneCache);
+    m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(bitwise_cast<OpaqueICUTimeZone*>(icu::TimeZone::detectHostTimeZone()));
+}
+
+void DateCache::reset()
+{
+    m_timeZoneCache.reset();
+    m_cachedDateString = String();
+    m_cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
+    m_dateInstanceCache.reset();
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSDateMath.h (269319 => 269320)


--- trunk/Source/_javascript_Core/runtime/JSDateMath.h	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/JSDateMath.h	2020-11-03 19:26:49 UTC (rev 269320)
@@ -42,7 +42,7 @@
 
 #pragma once
 
-#include "VMInlines.h"
+#include "DateInstanceCache.h"
 #include <wtf/DateMath.h>
 #include <wtf/GregorianDateTime.h>
 
@@ -49,11 +49,44 @@
 namespace JSC {
 
 class JSGlobalObject;
+class OpaqueICUTimeZone;
 class VM;
 
-JS_EXPORT_PRIVATE void msToGregorianDateTime(VM::DateCache&, double, WTF::TimeType outputTimeType, GregorianDateTime&);
-JS_EXPORT_PRIVATE double gregorianDateTimeToMS(VM::DateCache&, const GregorianDateTime&, double, WTF::TimeType inputTimeType);
-JS_EXPORT_PRIVATE double getUTCOffset(VM::DateCache&);
-JS_EXPORT_PRIVATE double parseDate(JSGlobalObject*, VM&, const WTF::String&);
+// We do not expose icu::TimeZone in this header file. And we cannot use icu::TimeZone forward declaration
+// because icu namespace can be an alias to icu$verNum namespace.
+struct OpaqueICUTimeZoneDeleter {
+    JS_EXPORT_PRIVATE void operator()(OpaqueICUTimeZone*);
+};
 
+class DateCache {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(DateCache);
+public:
+    DateCache();
+    ~DateCache();
+
+    JS_EXPORT_PRIVATE void reset();
+
+    OpaqueICUTimeZone* timeZoneCache()
+    {
+        if (!m_timeZoneCache)
+            timeZoneCacheSlow();
+        return m_timeZoneCache.get();
+    }
+
+    Ref<DateInstanceData> cachedDateInstanceData(double millisecondsFromEpoch);
+
+    void msToGregorianDateTime(double millisecondsFromEpoch, WTF::TimeType outputTimeType, GregorianDateTime&);
+    double gregorianDateTimeToMS(const GregorianDateTime&, double milliseconds, WTF::TimeType inputTimeType);
+    double parseDate(JSGlobalObject*, VM&, const WTF::String&);
+
+private:
+    void timeZoneCacheSlow();
+
+    std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter> m_timeZoneCache;
+    String m_cachedDateString;
+    double m_cachedDateStringValue;
+    DateInstanceCache m_dateInstanceCache;
+};
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (269319 => 269320)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2020-11-03 19:26:49 UTC (rev 269320)
@@ -889,15 +889,6 @@
 {
 }
 
-void VM::resetDateCache()
-{
-    dateCache.utcTimeOffsetCache.reset();
-    dateCache.localTimeOffsetCache.reset();
-    dateCache.cachedDateString = String();
-    dateCache.cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
-    dateCache.dateInstanceCache.reset();
-}
-
 void VM::whenIdle(Function<void()>&& callback)
 {
     if (!entryScope) {

Modified: trunk/Source/_javascript_Core/runtime/VM.h (269319 => 269320)


--- trunk/Source/_javascript_Core/runtime/VM.h	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2020-11-03 19:26:49 UTC (rev 269320)
@@ -32,7 +32,6 @@
 #include "CodeSpecializationKind.h"
 #include "CompleteSubspace.h"
 #include "ConcurrentJSLock.h"
-#include "DateInstanceCache.h"
 #include "DeleteAllCodeEffort.h"
 #include "DisallowVMEntry.h"
 #include "ExceptionEventLocation.h"
@@ -44,6 +43,7 @@
 #include "IsoCellSet.h"
 #include "IsoSubspace.h"
 #include "JSCJSValue.h"
+#include "JSDateMath.h"
 #include "JSLock.h"
 #include "MacroAssemblerCodeRef.h"
 #include "Microtask.h"
@@ -981,14 +981,6 @@
     JSObject* stringRecursionCheckFirstObject { nullptr };
     HashSet<JSObject*> stringRecursionCheckVisitedObjects;
 
-    struct DateCache {
-        DateInstanceCache dateInstanceCache;
-        LocalTimeOffsetCache utcTimeOffsetCache;
-        LocalTimeOffsetCache localTimeOffsetCache;
-
-        String cachedDateString;
-        double cachedDateStringValue;
-    };
     DateCache dateCache;
 
     std::unique_ptr<Profiler::Database> m_perBytecodeProfiler;
@@ -1018,7 +1010,7 @@
     RTTraceList* m_rtTraceList;
 #endif
 
-    JS_EXPORT_PRIVATE void resetDateCache();
+    void resetDateCache() { dateCache.reset(); }
 
     RegExpCache* regExpCache() { return m_regExpCache; }
 #if ENABLE(REGEXP_TRACING)

Modified: trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp (269319 => 269320)


--- trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp	2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp	2020-11-03 19:26:49 UTC (rev 269320)
@@ -43,6 +43,8 @@
 
         // Reset the date cache between JS invocations to force the VM to
         // observe time zone changes.
+        // FIXME: We should clear it only when we know the timezone has been changed.
+        // https://bugs.webkit.org/show_bug.cgi?id=218365
         vm.resetDateCache();
 
         if (vm.watchdog())
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to