OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/date.h" | 5 #include "src/date.h" |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/objects.h" | 9 #include "src/objects.h" |
10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | 24 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
25 | 25 |
26 | 26 |
27 void DateCache::ResetDateCache() { | 27 void DateCache::ResetDateCache() { |
28 static const int kMaxStamp = Smi::kMaxValue; | 28 static const int kMaxStamp = Smi::kMaxValue; |
29 if (stamp_->value() >= kMaxStamp) { | 29 if (stamp_->value() >= kMaxStamp) { |
30 stamp_ = Smi::FromInt(0); | 30 stamp_ = Smi::FromInt(0); |
31 } else { | 31 } else { |
32 stamp_ = Smi::FromInt(stamp_->value() + 1); | 32 stamp_ = Smi::FromInt(stamp_->value() + 1); |
33 } | 33 } |
34 ASSERT(stamp_ != Smi::FromInt(kInvalidStamp)); | 34 DCHECK(stamp_ != Smi::FromInt(kInvalidStamp)); |
35 for (int i = 0; i < kDSTSize; ++i) { | 35 for (int i = 0; i < kDSTSize; ++i) { |
36 ClearSegment(&dst_[i]); | 36 ClearSegment(&dst_[i]); |
37 } | 37 } |
38 dst_usage_counter_ = 0; | 38 dst_usage_counter_ = 0; |
39 before_ = &dst_[0]; | 39 before_ = &dst_[0]; |
40 after_ = &dst_[1]; | 40 after_ = &dst_[1]; |
41 local_offset_ms_ = kInvalidLocalOffsetInMs; | 41 local_offset_ms_ = kInvalidLocalOffsetInMs; |
42 ymd_valid_ = false; | 42 ymd_valid_ = false; |
43 base::OS::ClearTimezoneCache(tz_cache_); | 43 base::OS::ClearTimezoneCache(tz_cache_); |
44 } | 44 } |
(...skipping 21 matching lines...) Expand all Loading... |
66 *day = new_day; | 66 *day = new_day; |
67 return; | 67 return; |
68 } | 68 } |
69 } | 69 } |
70 int save_days = days; | 70 int save_days = days; |
71 | 71 |
72 days += kDaysOffset; | 72 days += kDaysOffset; |
73 *year = 400 * (days / kDaysIn400Years) - kYearsOffset; | 73 *year = 400 * (days / kDaysIn400Years) - kYearsOffset; |
74 days %= kDaysIn400Years; | 74 days %= kDaysIn400Years; |
75 | 75 |
76 ASSERT(DaysFromYearMonth(*year, 0) + days == save_days); | 76 DCHECK(DaysFromYearMonth(*year, 0) + days == save_days); |
77 | 77 |
78 days--; | 78 days--; |
79 int yd1 = days / kDaysIn100Years; | 79 int yd1 = days / kDaysIn100Years; |
80 days %= kDaysIn100Years; | 80 days %= kDaysIn100Years; |
81 *year += 100 * yd1; | 81 *year += 100 * yd1; |
82 | 82 |
83 days++; | 83 days++; |
84 int yd2 = days / kDaysIn4Years; | 84 int yd2 = days / kDaysIn4Years; |
85 days %= kDaysIn4Years; | 85 days %= kDaysIn4Years; |
86 *year += 4 * yd2; | 86 *year += 4 * yd2; |
87 | 87 |
88 days--; | 88 days--; |
89 int yd3 = days / 365; | 89 int yd3 = days / 365; |
90 days %= 365; | 90 days %= 365; |
91 *year += yd3; | 91 *year += yd3; |
92 | 92 |
93 | 93 |
94 bool is_leap = (!yd1 || yd2) && !yd3; | 94 bool is_leap = (!yd1 || yd2) && !yd3; |
95 | 95 |
96 ASSERT(days >= -1); | 96 DCHECK(days >= -1); |
97 ASSERT(is_leap || (days >= 0)); | 97 DCHECK(is_leap || (days >= 0)); |
98 ASSERT((days < 365) || (is_leap && (days < 366))); | 98 DCHECK((days < 365) || (is_leap && (days < 366))); |
99 ASSERT(is_leap == ((*year % 4 == 0) && (*year % 100 || (*year % 400 == 0)))); | 99 DCHECK(is_leap == ((*year % 4 == 0) && (*year % 100 || (*year % 400 == 0)))); |
100 ASSERT(is_leap || ((DaysFromYearMonth(*year, 0) + days) == save_days)); | 100 DCHECK(is_leap || ((DaysFromYearMonth(*year, 0) + days) == save_days)); |
101 ASSERT(!is_leap || ((DaysFromYearMonth(*year, 0) + days + 1) == save_days)); | 101 DCHECK(!is_leap || ((DaysFromYearMonth(*year, 0) + days + 1) == save_days)); |
102 | 102 |
103 days += is_leap; | 103 days += is_leap; |
104 | 104 |
105 // Check if the date is after February. | 105 // Check if the date is after February. |
106 if (days >= 31 + 28 + is_leap) { | 106 if (days >= 31 + 28 + is_leap) { |
107 days -= 31 + 28 + is_leap; | 107 days -= 31 + 28 + is_leap; |
108 // Find the date starting from March. | 108 // Find the date starting from March. |
109 for (int i = 2; i < 12; i++) { | 109 for (int i = 2; i < 12; i++) { |
110 if (days < kDaysInMonths[i]) { | 110 if (days < kDaysInMonths[i]) { |
111 *month = i; | 111 *month = i; |
112 *day = days + 1; | 112 *day = days + 1; |
113 break; | 113 break; |
114 } | 114 } |
115 days -= kDaysInMonths[i]; | 115 days -= kDaysInMonths[i]; |
116 } | 116 } |
117 } else { | 117 } else { |
118 // Check January and February. | 118 // Check January and February. |
119 if (days < 31) { | 119 if (days < 31) { |
120 *month = 0; | 120 *month = 0; |
121 *day = days + 1; | 121 *day = days + 1; |
122 } else { | 122 } else { |
123 *month = 1; | 123 *month = 1; |
124 *day = days - 31 + 1; | 124 *day = days - 31 + 1; |
125 } | 125 } |
126 } | 126 } |
127 ASSERT(DaysFromYearMonth(*year, *month) + *day - 1 == save_days); | 127 DCHECK(DaysFromYearMonth(*year, *month) + *day - 1 == save_days); |
128 ymd_valid_ = true; | 128 ymd_valid_ = true; |
129 ymd_year_ = *year; | 129 ymd_year_ = *year; |
130 ymd_month_ = *month; | 130 ymd_month_ = *month; |
131 ymd_day_ = *day; | 131 ymd_day_ = *day; |
132 ymd_days_ = save_days; | 132 ymd_days_ = save_days; |
133 } | 133 } |
134 | 134 |
135 | 135 |
136 int DateCache::DaysFromYearMonth(int year, int month) { | 136 int DateCache::DaysFromYearMonth(int year, int month) { |
137 static const int day_from_month[] = {0, 31, 59, 90, 120, 151, | 137 static const int day_from_month[] = {0, 31, 59, 90, 120, 151, |
138 181, 212, 243, 273, 304, 334}; | 138 181, 212, 243, 273, 304, 334}; |
139 static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152, | 139 static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152, |
140 182, 213, 244, 274, 305, 335}; | 140 182, 213, 244, 274, 305, 335}; |
141 | 141 |
142 year += month / 12; | 142 year += month / 12; |
143 month %= 12; | 143 month %= 12; |
144 if (month < 0) { | 144 if (month < 0) { |
145 year--; | 145 year--; |
146 month += 12; | 146 month += 12; |
147 } | 147 } |
148 | 148 |
149 ASSERT(month >= 0); | 149 DCHECK(month >= 0); |
150 ASSERT(month < 12); | 150 DCHECK(month < 12); |
151 | 151 |
152 // year_delta is an arbitrary number such that: | 152 // year_delta is an arbitrary number such that: |
153 // a) year_delta = -1 (mod 400) | 153 // a) year_delta = -1 (mod 400) |
154 // b) year + year_delta > 0 for years in the range defined by | 154 // b) year + year_delta > 0 for years in the range defined by |
155 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of | 155 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of |
156 // Jan 1 1970. This is required so that we don't run into integer | 156 // Jan 1 1970. This is required so that we don't run into integer |
157 // division of negative numbers. | 157 // division of negative numbers. |
158 // c) there shouldn't be an overflow for 32-bit integers in the following | 158 // c) there shouldn't be an overflow for 32-bit integers in the following |
159 // operations. | 159 // operations. |
160 static const int year_delta = 399999; | 160 static const int year_delta = 399999; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 // Optimistic fast check. | 215 // Optimistic fast check. |
216 if (before_->start_sec <= time_sec && | 216 if (before_->start_sec <= time_sec && |
217 time_sec <= before_->end_sec) { | 217 time_sec <= before_->end_sec) { |
218 // Cache hit. | 218 // Cache hit. |
219 before_->last_used = ++dst_usage_counter_; | 219 before_->last_used = ++dst_usage_counter_; |
220 return before_->offset_ms; | 220 return before_->offset_ms; |
221 } | 221 } |
222 | 222 |
223 ProbeDST(time_sec); | 223 ProbeDST(time_sec); |
224 | 224 |
225 ASSERT(InvalidSegment(before_) || before_->start_sec <= time_sec); | 225 DCHECK(InvalidSegment(before_) || before_->start_sec <= time_sec); |
226 ASSERT(InvalidSegment(after_) || time_sec < after_->start_sec); | 226 DCHECK(InvalidSegment(after_) || time_sec < after_->start_sec); |
227 | 227 |
228 if (InvalidSegment(before_)) { | 228 if (InvalidSegment(before_)) { |
229 // Cache miss. | 229 // Cache miss. |
230 before_->start_sec = time_sec; | 230 before_->start_sec = time_sec; |
231 before_->end_sec = time_sec; | 231 before_->end_sec = time_sec; |
232 before_->offset_ms = GetDaylightSavingsOffsetFromOS(time_sec); | 232 before_->offset_ms = GetDaylightSavingsOffsetFromOS(time_sec); |
233 before_->last_used = ++dst_usage_counter_; | 233 before_->last_used = ++dst_usage_counter_; |
234 return before_->offset_ms; | 234 return before_->offset_ms; |
235 } | 235 } |
236 | 236 |
(...skipping 20 matching lines...) Expand all Loading... |
257 // Update the usage counter of before_ since it is going to be used. | 257 // Update the usage counter of before_ since it is going to be used. |
258 before_->last_used = ++dst_usage_counter_; | 258 before_->last_used = ++dst_usage_counter_; |
259 | 259 |
260 // Check if after_ segment is invalid or starts too late. | 260 // Check if after_ segment is invalid or starts too late. |
261 // Note that start_sec of invalid segments is kMaxEpochTimeInSec. | 261 // Note that start_sec of invalid segments is kMaxEpochTimeInSec. |
262 if (before_->end_sec + kDefaultDSTDeltaInSec <= after_->start_sec) { | 262 if (before_->end_sec + kDefaultDSTDeltaInSec <= after_->start_sec) { |
263 int new_after_start_sec = before_->end_sec + kDefaultDSTDeltaInSec; | 263 int new_after_start_sec = before_->end_sec + kDefaultDSTDeltaInSec; |
264 int new_offset_ms = GetDaylightSavingsOffsetFromOS(new_after_start_sec); | 264 int new_offset_ms = GetDaylightSavingsOffsetFromOS(new_after_start_sec); |
265 ExtendTheAfterSegment(new_after_start_sec, new_offset_ms); | 265 ExtendTheAfterSegment(new_after_start_sec, new_offset_ms); |
266 } else { | 266 } else { |
267 ASSERT(!InvalidSegment(after_)); | 267 DCHECK(!InvalidSegment(after_)); |
268 // Update the usage counter of after_ since it is going to be used. | 268 // Update the usage counter of after_ since it is going to be used. |
269 after_->last_used = ++dst_usage_counter_; | 269 after_->last_used = ++dst_usage_counter_; |
270 } | 270 } |
271 | 271 |
272 // Now the time_sec is between before_->end_sec and after_->start_sec. | 272 // Now the time_sec is between before_->end_sec and after_->start_sec. |
273 // Only one daylight savings offset change can occur in this interval. | 273 // Only one daylight savings offset change can occur in this interval. |
274 | 274 |
275 if (before_->offset_ms == after_->offset_ms) { | 275 if (before_->offset_ms == after_->offset_ms) { |
276 // Merge two segments if they have the same offset. | 276 // Merge two segments if they have the same offset. |
277 before_->end_sec = after_->end_sec; | 277 before_->end_sec = after_->end_sec; |
278 ClearSegment(after_); | 278 ClearSegment(after_); |
279 return before_->offset_ms; | 279 return before_->offset_ms; |
280 } | 280 } |
281 | 281 |
282 // Binary search for daylight savings offset change point, | 282 // Binary search for daylight savings offset change point, |
283 // but give up if we don't find it in four iterations. | 283 // but give up if we don't find it in four iterations. |
284 for (int i = 4; i >= 0; --i) { | 284 for (int i = 4; i >= 0; --i) { |
285 int delta = after_->start_sec - before_->end_sec; | 285 int delta = after_->start_sec - before_->end_sec; |
286 int middle_sec = (i == 0) ? time_sec : before_->end_sec + delta / 2; | 286 int middle_sec = (i == 0) ? time_sec : before_->end_sec + delta / 2; |
287 int offset_ms = GetDaylightSavingsOffsetFromOS(middle_sec); | 287 int offset_ms = GetDaylightSavingsOffsetFromOS(middle_sec); |
288 if (before_->offset_ms == offset_ms) { | 288 if (before_->offset_ms == offset_ms) { |
289 before_->end_sec = middle_sec; | 289 before_->end_sec = middle_sec; |
290 if (time_sec <= before_->end_sec) { | 290 if (time_sec <= before_->end_sec) { |
291 return offset_ms; | 291 return offset_ms; |
292 } | 292 } |
293 } else { | 293 } else { |
294 ASSERT(after_->offset_ms == offset_ms); | 294 DCHECK(after_->offset_ms == offset_ms); |
295 after_->start_sec = middle_sec; | 295 after_->start_sec = middle_sec; |
296 if (time_sec >= after_->start_sec) { | 296 if (time_sec >= after_->start_sec) { |
297 // This swap helps the optimistic fast check in subsequent invocations. | 297 // This swap helps the optimistic fast check in subsequent invocations. |
298 DST* temp = before_; | 298 DST* temp = before_; |
299 before_ = after_; | 299 before_ = after_; |
300 after_ = temp; | 300 after_ = temp; |
301 return offset_ms; | 301 return offset_ms; |
302 } | 302 } |
303 } | 303 } |
304 } | 304 } |
305 UNREACHABLE(); | 305 UNREACHABLE(); |
306 return 0; | 306 return 0; |
307 } | 307 } |
308 | 308 |
309 | 309 |
310 void DateCache::ProbeDST(int time_sec) { | 310 void DateCache::ProbeDST(int time_sec) { |
311 DST* before = NULL; | 311 DST* before = NULL; |
312 DST* after = NULL; | 312 DST* after = NULL; |
313 ASSERT(before_ != after_); | 313 DCHECK(before_ != after_); |
314 | 314 |
315 for (int i = 0; i < kDSTSize; ++i) { | 315 for (int i = 0; i < kDSTSize; ++i) { |
316 if (dst_[i].start_sec <= time_sec) { | 316 if (dst_[i].start_sec <= time_sec) { |
317 if (before == NULL || before->start_sec < dst_[i].start_sec) { | 317 if (before == NULL || before->start_sec < dst_[i].start_sec) { |
318 before = &dst_[i]; | 318 before = &dst_[i]; |
319 } | 319 } |
320 } else if (time_sec < dst_[i].end_sec) { | 320 } else if (time_sec < dst_[i].end_sec) { |
321 if (after == NULL || after->end_sec > dst_[i].end_sec) { | 321 if (after == NULL || after->end_sec > dst_[i].end_sec) { |
322 after = &dst_[i]; | 322 after = &dst_[i]; |
323 } | 323 } |
324 } | 324 } |
325 } | 325 } |
326 | 326 |
327 // If before or after segments were not found, | 327 // If before or after segments were not found, |
328 // then set them to any invalid segment. | 328 // then set them to any invalid segment. |
329 if (before == NULL) { | 329 if (before == NULL) { |
330 before = InvalidSegment(before_) ? before_ : LeastRecentlyUsedDST(after); | 330 before = InvalidSegment(before_) ? before_ : LeastRecentlyUsedDST(after); |
331 } | 331 } |
332 if (after == NULL) { | 332 if (after == NULL) { |
333 after = InvalidSegment(after_) && before != after_ | 333 after = InvalidSegment(after_) && before != after_ |
334 ? after_ : LeastRecentlyUsedDST(before); | 334 ? after_ : LeastRecentlyUsedDST(before); |
335 } | 335 } |
336 | 336 |
337 ASSERT(before != NULL); | 337 DCHECK(before != NULL); |
338 ASSERT(after != NULL); | 338 DCHECK(after != NULL); |
339 ASSERT(before != after); | 339 DCHECK(before != after); |
340 ASSERT(InvalidSegment(before) || before->start_sec <= time_sec); | 340 DCHECK(InvalidSegment(before) || before->start_sec <= time_sec); |
341 ASSERT(InvalidSegment(after) || time_sec < after->start_sec); | 341 DCHECK(InvalidSegment(after) || time_sec < after->start_sec); |
342 ASSERT(InvalidSegment(before) || InvalidSegment(after) || | 342 DCHECK(InvalidSegment(before) || InvalidSegment(after) || |
343 before->end_sec < after->start_sec); | 343 before->end_sec < after->start_sec); |
344 | 344 |
345 before_ = before; | 345 before_ = before; |
346 after_ = after; | 346 after_ = after; |
347 } | 347 } |
348 | 348 |
349 | 349 |
350 DateCache::DST* DateCache::LeastRecentlyUsedDST(DST* skip) { | 350 DateCache::DST* DateCache::LeastRecentlyUsedDST(DST* skip) { |
351 DST* result = NULL; | 351 DST* result = NULL; |
352 for (int i = 0; i < kDSTSize; ++i) { | 352 for (int i = 0; i < kDSTSize; ++i) { |
353 if (&dst_[i] == skip) continue; | 353 if (&dst_[i] == skip) continue; |
354 if (result == NULL || result->last_used > dst_[i].last_used) { | 354 if (result == NULL || result->last_used > dst_[i].last_used) { |
355 result = &dst_[i]; | 355 result = &dst_[i]; |
356 } | 356 } |
357 } | 357 } |
358 ClearSegment(result); | 358 ClearSegment(result); |
359 return result; | 359 return result; |
360 } | 360 } |
361 | 361 |
362 } } // namespace v8::internal | 362 } } // namespace v8::internal |
OLD | NEW |