V8 Project
date.h
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_DATE_H_
6 #define V8_DATE_H_
7 
8 #include "src/allocation.h"
10 #include "src/globals.h"
11 
12 
13 namespace v8 {
14 namespace internal {
15 
16 class DateCache {
17  public:
18  static const int kMsPerMin = 60 * 1000;
19  static const int kSecPerDay = 24 * 60 * 60;
20  static const int64_t kMsPerDay = kSecPerDay * 1000;
21 
22  // The largest time that can be passed to OS date-time library functions.
23  static const int kMaxEpochTimeInSec = kMaxInt;
24  static const int64_t kMaxEpochTimeInMs =
25  static_cast<int64_t>(kMaxInt) * 1000;
26 
27  // The largest time that can be stored in JSDate.
28  static const int64_t kMaxTimeInMs =
29  static_cast<int64_t>(864000000) * 10000000;
30 
31  // Conservative upper bound on time that can be stored in JSDate
32  // before UTC conversion.
33  static const int64_t kMaxTimeBeforeUTCInMs =
34  kMaxTimeInMs + 10 * kMsPerDay;
35 
36  // Sentinel that denotes an invalid local offset.
37  static const int kInvalidLocalOffsetInMs = kMaxInt;
38  // Sentinel that denotes an invalid cache stamp.
39  // It is an invariant of DateCache that cache stamp is non-negative.
40  static const int kInvalidStamp = -1;
41 
42  DateCache() : stamp_(0), tz_cache_(base::OS::CreateTimezoneCache()) {
44  }
45 
46  virtual ~DateCache() {
48  tz_cache_ = NULL;
49  }
50 
51 
52  // Clears cached timezone information and increments the cache stamp.
53  void ResetDateCache();
54 
55 
56  // Computes floor(time_ms / kMsPerDay).
57  static int DaysFromTime(int64_t time_ms) {
58  if (time_ms < 0) time_ms -= (kMsPerDay - 1);
59  return static_cast<int>(time_ms / kMsPerDay);
60  }
61 
62 
63  // Computes modulo(time_ms, kMsPerDay) given that
64  // days = floor(time_ms / kMsPerDay).
65  static int TimeInDay(int64_t time_ms, int days) {
66  return static_cast<int>(time_ms - days * kMsPerDay);
67  }
68 
69 
70  // Given the number of days since the epoch, computes the weekday.
71  // ECMA 262 - 15.9.1.6.
72  int Weekday(int days) {
73  int result = (days + 4) % 7;
74  return result >= 0 ? result : result + 7;
75  }
76 
77 
78  bool IsLeap(int year) {
79  return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
80  }
81 
82 
83  // ECMA 262 - 15.9.1.7.
87  }
88  return local_offset_ms_;
89  }
90 
91 
92  const char* LocalTimezone(int64_t time_ms) {
93  if (time_ms < 0 || time_ms > kMaxEpochTimeInMs) {
94  time_ms = EquivalentTime(time_ms);
95  }
96  return base::OS::LocalTimezone(static_cast<double>(time_ms), tz_cache_);
97  }
98 
99  // ECMA 262 - 15.9.5.26
100  int TimezoneOffset(int64_t time_ms) {
101  int64_t local_ms = ToLocal(time_ms);
102  return static_cast<int>((time_ms - local_ms) / kMsPerMin);
103  }
104 
105  // ECMA 262 - 15.9.1.9
106  // LocalTime(t) = t + LocalTZA + DaylightSavingTA(t)
107  // ECMA 262 assumes that DaylightSavingTA is computed using UTC time,
108  // but we fetch DST from OS using local time, therefore we need:
109  // LocalTime(t) = t + LocalTZA + DaylightSavingTA(t + LocalTZA).
110  int64_t ToLocal(int64_t time_ms) {
111  time_ms += LocalOffsetInMs();
112  return time_ms + DaylightSavingsOffsetInMs(time_ms);
113  }
114 
115  // ECMA 262 - 15.9.1.9
116  // UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
117  // ECMA 262 assumes that DaylightSavingTA is computed using UTC time,
118  // but we fetch DST from OS using local time, therefore we need:
119  // UTC(t) = t - LocalTZA - DaylightSavingTA(t).
120  int64_t ToUTC(int64_t time_ms) {
121  return time_ms - LocalOffsetInMs() - DaylightSavingsOffsetInMs(time_ms);
122  }
123 
124 
125  // Computes a time equivalent to the given time according
126  // to ECMA 262 - 15.9.1.9.
127  // The issue here is that some library calls don't work right for dates
128  // that cannot be represented using a non-negative signed 32 bit integer
129  // (measured in whole seconds based on the 1970 epoch).
130  // We solve this by mapping the time to a year with same leap-year-ness
131  // and same starting day for the year. The ECMAscript specification says
132  // we must do this, but for compatibility with other browsers, we use
133  // the actual year if it is in the range 1970..2037
134  int64_t EquivalentTime(int64_t time_ms) {
135  int days = DaysFromTime(time_ms);
136  int time_within_day_ms = static_cast<int>(time_ms - days * kMsPerDay);
137  int year, month, day;
138  YearMonthDayFromDays(days, &year, &month, &day);
139  int new_days = DaysFromYearMonth(EquivalentYear(year), month) + day - 1;
140  return static_cast<int64_t>(new_days) * kMsPerDay + time_within_day_ms;
141  }
142 
143  // Returns an equivalent year in the range [2008-2035] matching
144  // - leap year,
145  // - week day of first day.
146  // ECMA 262 - 15.9.1.9.
147  int EquivalentYear(int year) {
148  int week_day = Weekday(DaysFromYearMonth(year, 0));
149  int recent_year = (IsLeap(year) ? 1956 : 1967) + (week_day * 12) % 28;
150  // Find the year in the range 2008..2037 that is equivalent mod 28.
151  // Add 3*28 to give a positive argument to the modulus operator.
152  return 2008 + (recent_year + 3 * 28 - 2008) % 28;
153  }
154 
155  // Given the number of days since the epoch, computes
156  // the corresponding year, month, and day.
157  void YearMonthDayFromDays(int days, int* year, int* month, int* day);
158 
159  // Computes the number of days since the epoch for
160  // the first day of the given month in the given year.
161  int DaysFromYearMonth(int year, int month);
162 
163  // Cache stamp is used for invalidating caches in JSDate.
164  // We increment the stamp each time when the timezone information changes.
165  // JSDate objects perform stamp check and invalidate their caches if
166  // their saved stamp is not equal to the current stamp.
167  Smi* stamp() { return stamp_; }
168  void* stamp_address() { return &stamp_; }
169 
170  // These functions are virtual so that we can override them when testing.
171  virtual int GetDaylightSavingsOffsetFromOS(int64_t time_sec) {
172  double time_ms = static_cast<double>(time_sec * 1000);
173  return static_cast<int>(
175  }
176 
177  virtual int GetLocalOffsetFromOS() {
178  double offset = base::OS::LocalTimeOffset(tz_cache_);
180  return static_cast<int>(offset);
181  }
182 
183  private:
184  // The implementation relies on the fact that no time zones have
185  // more than one daylight savings offset change per 19 days.
186  // In Egypt in 2010 they decided to suspend DST during Ramadan. This
187  // led to a short interval where DST is in effect from September 10 to
188  // September 30.
189  static const int kDefaultDSTDeltaInSec = 19 * kSecPerDay;
190 
191  // Size of the Daylight Savings Time cache.
192  static const int kDSTSize = 32;
193 
194  // Daylight Savings Time segment stores a segment of time where
195  // daylight savings offset does not change.
196  struct DST {
198  int end_sec;
201  };
202 
203  // Computes the daylight savings offset for the given time.
204  // ECMA 262 - 15.9.1.8
205  int DaylightSavingsOffsetInMs(int64_t time_ms);
206 
207  // Sets the before_ and the after_ segments from the DST cache such that
208  // the before_ segment starts earlier than the given time and
209  // the after_ segment start later than the given time.
210  // Both segments might be invalid.
211  // The last_used counters of the before_ and after_ are updated.
212  void ProbeDST(int time_sec);
213 
214  // Finds the least recently used segment from the DST cache that is not
215  // equal to the given 'skip' segment.
216  DST* LeastRecentlyUsedDST(DST* skip);
217 
218  // Extends the after_ segment with the given point or resets it
219  // if it starts later than the given time + kDefaultDSTDeltaInSec.
220  inline void ExtendTheAfterSegment(int time_sec, int offset_ms);
221 
222  // Makes the given segment invalid.
223  inline void ClearSegment(DST* segment);
224 
225  bool InvalidSegment(DST* segment) {
226  return segment->start_sec > segment->end_sec;
227  }
228 
230 
231  // Daylight Saving Time cache.
236 
238 
239  // Year/Month/Day cache.
244  int ymd_day_;
245 
247 };
248 
249 } } // namespace v8::internal
250 
251 #endif
static double DaylightSavingsOffset(double time, TimezoneCache *cache)
static const char * LocalTimezone(double time, TimezoneCache *cache)
static double LocalTimeOffset(TimezoneCache *cache)
static void DisposeTimezoneCache(TimezoneCache *cache)
virtual int GetDaylightSavingsOffsetFromOS(int64_t time_sec)
Definition: date.h:171
int EquivalentYear(int year)
Definition: date.h:147
void ExtendTheAfterSegment(int time_sec, int offset_ms)
Definition: date.cc:180
int LocalOffsetInMs()
Definition: date.h:84
virtual int GetLocalOffsetFromOS()
Definition: date.h:177
int DaysFromYearMonth(int year, int month)
Definition: date.cc:136
bool IsLeap(int year)
Definition: date.h:78
void ResetDateCache()
Definition: date.cc:27
DST * LeastRecentlyUsedDST(DST *skip)
Definition: date.cc:350
static int TimeInDay(int64_t time_ms, int days)
Definition: date.h:65
static const int kMsPerMin
Definition: date.h:18
int DaylightSavingsOffsetInMs(int64_t time_ms)
Definition: date.cc:200
void YearMonthDayFromDays(int days, int *year, int *month, int *day)
Definition: date.cc:55
static const int kInvalidStamp
Definition: date.h:40
bool InvalidSegment(DST *segment)
Definition: date.h:225
const char * LocalTimezone(int64_t time_ms)
Definition: date.h:92
static const int kSecPerDay
Definition: date.h:19
static const int kDefaultDSTDeltaInSec
Definition: date.h:189
static const int64_t kMaxEpochTimeInMs
Definition: date.h:24
base::TimezoneCache * tz_cache_
Definition: date.h:246
int64_t ToLocal(int64_t time_ms)
Definition: date.h:110
static const int kMaxEpochTimeInSec
Definition: date.h:23
static const int64_t kMaxTimeInMs
Definition: date.h:28
void ProbeDST(int time_sec)
Definition: date.cc:310
int Weekday(int days)
Definition: date.h:72
int64_t ToUTC(int64_t time_ms)
Definition: date.h:120
static int DaysFromTime(int64_t time_ms)
Definition: date.h:57
static const int kInvalidLocalOffsetInMs
Definition: date.h:37
DST dst_[kDSTSize]
Definition: date.h:232
static const int64_t kMsPerDay
Definition: date.h:20
static const int kDSTSize
Definition: date.h:192
int TimezoneOffset(int64_t time_ms)
Definition: date.h:100
void ClearSegment(DST *segment)
Definition: date.cc:47
void * stamp_address()
Definition: date.h:168
static const int64_t kMaxTimeBeforeUTCInMs
Definition: date.h:33
virtual ~DateCache()
Definition: date.h:46
int64_t EquivalentTime(int64_t time_ms)
Definition: date.h:134
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
Definition: logging.h:205
const int kMaxInt
Definition: globals.h:109
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20