Commit 55a9f014 authored by David Jean's avatar David Jean Committed by Commit Bot

Reland "[ios] Use posix TimeExploded"

This is a reland of 34445e49

CoreFoundations APIs usage was preserved since Cronet still requires
32-bit support.

Original change's description:
> [ios] Use posix TimeExploded
>
> With 32 bits build gone, iOS can use the posix implementation of
> TimeExploded, which is faster.
>
> Bug: 985061
> Change-Id: Ic1d42ebddfa2d0bb0d37bb7b2086683914aa87a5
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1763679
> Commit-Queue: David Jean <djean@chromium.org>
> Reviewed-by: Mark Cogan <marq@chromium.org>
> Reviewed-by: Yuri Wiitala <miu@chromium.org>
> Reviewed-by: John Budorick <jbudorick@chromium.org>
> Reviewed-by: kylechar <kylechar@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#691094}

Bug: 985061
Change-Id: I42ee2b64a3ed7b6c3c98d1593cd4d762377f7b33
Cq-Include-Trybots: luci.chromium.try:ios-simulator-cronet
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1856961
Commit-Queue: Yuri Wiitala <miu@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Reviewed-by: default avatarYuri Wiitala <miu@chromium.org>
Reviewed-by: default avatarDavid Jean <djean@chromium.org>
Reviewed-by: default avatarJohn Budorick <jbudorick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#711923}
parent d4035196
......@@ -2019,6 +2019,12 @@ jumbo_component("base") {
"time/time_conversion_posix.cc",
"time/time_mac.cc",
]
if (current_cpu == "x64" || current_cpu == "arm64") {
sources += [ "time/time_exploded_posix.cc" ]
} else {
sources += [ "time/time_exploded_ios.cc" ]
}
}
if (dep_libevent) {
......
......@@ -513,7 +513,7 @@ class BASE_EXPORT Time : public time_internal::TimeBase<Time> {
#if defined(OS_WIN)
static constexpr int kExplodedMinYear = 1601;
static constexpr int kExplodedMaxYear = 30827;
#elif defined(OS_IOS)
#elif defined(OS_IOS) && !__LP64__
static constexpr int kExplodedMinYear = std::numeric_limits<int>::min();
static constexpr int kExplodedMaxYear = std::numeric_limits<int>::max();
#elif defined(OS_MACOSX)
......
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/time/time.h"
#include <CoreFoundation/CFDate.h>
#include <CoreFoundation/CFCalendar.h>
#include <CoreFoundation/CFTimeZone.h>
#include "base/mac/scoped_cftyperef.h"
#if __LP64__
#error Use posix implementation on 64-bit platforms.
#endif // __LP64__
namespace base {
// Note: These implementations of Time::FromExploded() and Time::Explode() are
// only used on iOS now. Since Mac is now always 64-bit, we can use the POSIX
// versions of these functions as time_t is not capped at year 2038 on 64-bit
// builds. The POSIX functions are preferred since they don't suffer from some
// performance problems that are present in these implementations.
// See crbug.com/781601, crbug.com/985061 for more details.
// static
bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
base::ScopedCFTypeRef<CFTimeZoneRef> time_zone(
is_local
? CFTimeZoneCopySystem()
: CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0));
base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier(
kCFAllocatorDefault, kCFGregorianCalendar));
CFCalendarSetTimeZone(gregorian, time_zone);
CFAbsoluteTime absolute_time;
// 'S' is not defined in componentDesc in Apple documentation, but can be
// found at http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c
CFCalendarComposeAbsoluteTime(
gregorian, &absolute_time, "yMdHmsS", exploded.year, exploded.month,
exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
exploded.millisecond);
CFAbsoluteTime seconds = absolute_time + kCFAbsoluteTimeIntervalSince1970;
// CFAbsolutTime is typedef of double. Convert seconds to
// microseconds and then cast to int64. If
// it cannot be suited to int64, then fail to avoid overflows.
double microseconds =
(seconds * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset;
if (microseconds > std::numeric_limits<int64_t>::max() ||
microseconds < std::numeric_limits<int64_t>::min()) {
*time = Time(0);
return false;
}
base::Time converted_time = Time(static_cast<int64_t>(microseconds));
// If |exploded.day_of_month| is set to 31
// on a 28-30 day month, it will return the first day of the next month.
// Thus round-trip the time and compare the initial |exploded| with
// |utc_to_exploded| time.
base::Time::Exploded to_exploded;
if (!is_local)
converted_time.UTCExplode(&to_exploded);
else
converted_time.LocalExplode(&to_exploded);
if (ExplodedMostlyEquals(to_exploded, exploded)) {
*time = converted_time;
return true;
}
*time = Time(0);
return false;
}
void Time::Explode(bool is_local, Exploded* exploded) const {
// Avoid rounding issues, by only putting the integral number of seconds
// (rounded towards -infinity) into a |CFAbsoluteTime| (which is a |double|).
int64_t microsecond = us_ % kMicrosecondsPerSecond;
if (microsecond < 0)
microsecond += kMicrosecondsPerSecond;
CFAbsoluteTime seconds = ((us_ - microsecond - kTimeTToMicrosecondsOffset) /
kMicrosecondsPerSecond) -
kCFAbsoluteTimeIntervalSince1970;
base::ScopedCFTypeRef<CFTimeZoneRef> time_zone(
is_local
? CFTimeZoneCopySystem()
: CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0));
base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier(
kCFAllocatorDefault, kCFGregorianCalendar));
CFCalendarSetTimeZone(gregorian, time_zone);
int second, day_of_week;
// 'E' sets the day of week, but is not defined in componentDesc in Apple
// documentation. It can be found in open source code here:
// http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c
CFCalendarDecomposeAbsoluteTime(gregorian, seconds, "yMdHmsE",
&exploded->year, &exploded->month,
&exploded->day_of_month, &exploded->hour,
&exploded->minute, &second, &day_of_week);
// Make sure seconds are rounded down towards -infinity.
exploded->second = floor(second);
// |Exploded|'s convention for day of week is 0 = Sunday, i.e. different
// from CF's 1 = Sunday.
exploded->day_of_week = (day_of_week - 1) % 7;
// Calculate milliseconds ourselves, since we rounded the |seconds|, making
// sure to round towards -infinity.
exploded->millisecond =
(microsecond >= 0) ? microsecond / kMicrosecondsPerMillisecond :
(microsecond - kMicrosecondsPerMillisecond + 1) /
kMicrosecondsPerMillisecond;
}
} // namespace base
......@@ -33,7 +33,7 @@
#include "base/numerics/clamped_math.h"
#endif
#if defined(OS_MACOSX)
#if defined(OS_MACOSX) || defined(OS_IOS)
static_assert(sizeof(time_t) >= 8, "Y2038 problem!");
#endif
......
......@@ -5,7 +5,6 @@
#include "base/time/time.h"
#include <CoreFoundation/CFDate.h>
#include <CoreFoundation/CFTimeZone.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <stddef.h>
......@@ -175,102 +174,6 @@ CFAbsoluteTime Time::ToCFAbsoluteTime() const {
kCFAbsoluteTimeIntervalSince1970;
}
// Note: These implementations of Time::FromExploded() and Time::Explode() are
// only used on iOS now. Since Mac is now always 64-bit, we can use the POSIX
// versions of these functions as time_t is not capped at year 2038 on 64-bit
// builds. The POSIX functions are preferred since they don't suffer from some
// performance problems that are present in these implementations.
// See crbug.com/781601 for more details.
#if defined(OS_IOS)
// static
bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
base::ScopedCFTypeRef<CFTimeZoneRef> time_zone(
is_local
? CFTimeZoneCopySystem()
: CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0));
base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier(
kCFAllocatorDefault, kCFGregorianCalendar));
CFCalendarSetTimeZone(gregorian, time_zone);
CFAbsoluteTime absolute_time;
// 'S' is not defined in componentDesc in Apple documentation, but can be
// found at http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c
CFCalendarComposeAbsoluteTime(
gregorian, &absolute_time, "yMdHmsS", exploded.year, exploded.month,
exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
exploded.millisecond);
CFAbsoluteTime seconds = absolute_time + kCFAbsoluteTimeIntervalSince1970;
// CFAbsolutTime is typedef of double. Convert seconds to
// microseconds and then cast to int64. If
// it cannot be suited to int64, then fail to avoid overflows.
double microseconds =
(seconds * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset;
if (microseconds > std::numeric_limits<int64_t>::max() ||
microseconds < std::numeric_limits<int64_t>::min()) {
*time = Time(0);
return false;
}
base::Time converted_time = Time(static_cast<int64_t>(microseconds));
// If |exploded.day_of_month| is set to 31
// on a 28-30 day month, it will return the first day of the next month.
// Thus round-trip the time and compare the initial |exploded| with
// |utc_to_exploded| time.
base::Time::Exploded to_exploded;
if (!is_local)
converted_time.UTCExplode(&to_exploded);
else
converted_time.LocalExplode(&to_exploded);
if (ExplodedMostlyEquals(to_exploded, exploded)) {
*time = converted_time;
return true;
}
*time = Time(0);
return false;
}
void Time::Explode(bool is_local, Exploded* exploded) const {
// Avoid rounding issues, by only putting the integral number of seconds
// (rounded towards -infinity) into a |CFAbsoluteTime| (which is a |double|).
int64_t microsecond = us_ % kMicrosecondsPerSecond;
if (microsecond < 0)
microsecond += kMicrosecondsPerSecond;
CFAbsoluteTime seconds = ((us_ - microsecond - kTimeTToMicrosecondsOffset) /
kMicrosecondsPerSecond) -
kCFAbsoluteTimeIntervalSince1970;
base::ScopedCFTypeRef<CFTimeZoneRef> time_zone(
is_local
? CFTimeZoneCopySystem()
: CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0));
base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier(
kCFAllocatorDefault, kCFGregorianCalendar));
CFCalendarSetTimeZone(gregorian, time_zone);
int second, day_of_week;
// 'E' sets the day of week, but is not defined in componentDesc in Apple
// documentation. It can be found in open source code here:
// http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c
CFCalendarDecomposeAbsoluteTime(gregorian, seconds, "yMdHmsE",
&exploded->year, &exploded->month,
&exploded->day_of_month, &exploded->hour,
&exploded->minute, &second, &day_of_week);
// Make sure seconds are rounded down towards -infinity.
exploded->second = floor(second);
// |Exploded|'s convention for day of week is 0 = Sunday, i.e. different
// from CF's 1 = Sunday.
exploded->day_of_week = (day_of_week - 1) % 7;
// Calculate milliseconds ourselves, since we rounded the |seconds|, making
// sure to round towards -infinity.
exploded->millisecond =
(microsecond >= 0) ? microsecond / kMicrosecondsPerMillisecond :
(microsecond - kMicrosecondsPerMillisecond + 1) /
kMicrosecondsPerMillisecond;
}
#endif // OS_IOS
// TimeTicks ------------------------------------------------------------------
namespace subtle {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment