| 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 | 
|---|