39 static const int kDays4Years[] = {0, 365, 2 * 365, 3 * 365 + 1};
40 static const int kDaysIn4Years = 4 * 365 + 1;
41 static const int kDaysIn100Years = 25 * kDaysIn4Years - 1;
42 static const int kDaysIn400Years = 4 * kDaysIn100Years + 1;
43 static const int kDays1970to2000 = 30 * 365 + 7;
44 static const int kDaysOffset = 1000 * kDaysIn400Years + 5 * kDaysIn400Years -
46 static const int kYearsOffset = 400000;
47 static const char kDaysInMonths[] =
48 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
54 if (stamp_->
value() > kMaxStamp) {
58 for (
int i = 0; i < kDSTSize; ++i) {
59 ClearSegment(&dst_[i]);
61 dst_usage_counter_ = 0;
69 void DateCache::ClearSegment(DST* segment) {
72 segment->offset_ms = 0;
73 segment->last_used = 0;
78 int days,
int* year,
int* month,
int* day) {
82 int new_day = ymd_day_ + (days - ymd_days_);
83 if (new_day >= 1 && new_day <= 28) {
95 *year = 400 * (days / kDaysIn400Years) - kYearsOffset;
96 days %= kDaysIn400Years;
101 int yd1 = days / kDaysIn100Years;
102 days %= kDaysIn100Years;
106 int yd2 = days / kDaysIn4Years;
107 days %= kDaysIn4Years;
111 int yd3 = days / 365;
116 bool is_leap = (!yd1 || yd2) && !yd3;
119 ASSERT(is_leap || (days >= 0));
120 ASSERT((days < 365) || (is_leap && (days < 366)));
121 ASSERT(is_leap == ((*year % 4 == 0) && (*year % 100 || (*year % 400 == 0))));
128 if (days >= 31 + 28 + is_leap) {
129 days -= 31 + 28 + is_leap;
131 for (
int i = 2; i < 12; i++) {
132 if (days < kDaysInMonths[i]) {
137 days -= kDaysInMonths[i];
146 *day = days - 31 + 1;
154 ymd_days_ = save_days;
159 static const int day_from_month[] = {0, 31, 59, 90, 120, 151,
160 181, 212, 243, 273, 304, 334};
161 static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152,
162 182, 213, 244, 274, 305, 335};
182 static const int year_delta = 399999;
183 static const int base_day = 365 * (1970 + year_delta) +
184 (1970 + year_delta) / 4 -
185 (1970 + year_delta) / 100 +
186 (1970 + year_delta) / 400;
188 int year1 = year + year_delta;
189 int day_from_year = 365 * year1 +
195 if ((year % 4 != 0) || (year % 100 == 0 && year % 400 != 0)) {
196 return day_from_year + day_from_month[month];
198 return day_from_year + day_from_month_leap[month];
202 void DateCache::ExtendTheAfterSegment(
int time_sec,
int offset_ms) {
203 if (after_->offset_ms == offset_ms &&
204 after_->start_sec <= time_sec + kDefaultDSTDeltaInSec &&
205 time_sec <= after_->end_sec) {
207 after_->start_sec = time_sec;
210 if (after_->start_sec <= after_->end_sec) {
212 after_ = LeastRecentlyUsedDST(before_);
214 after_->start_sec = time_sec;
215 after_->end_sec = time_sec;
216 after_->offset_ms = offset_ms;
217 after_->last_used = ++dst_usage_counter_;
222 int DateCache::DaylightSavingsOffsetInMs(int64_t time_ms) {
224 ? static_cast<int>(time_ms / 1000)
230 if (dst_usage_counter_ >=
kMaxInt - 10) {
231 dst_usage_counter_ = 0;
232 for (
int i = 0; i < kDSTSize; ++i) {
233 ClearSegment(&dst_[i]);
238 if (before_->start_sec <= time_sec &&
239 time_sec <= before_->end_sec) {
241 before_->last_used = ++dst_usage_counter_;
242 return before_->offset_ms;
247 ASSERT(InvalidSegment(before_) || before_->start_sec <= time_sec);
248 ASSERT(InvalidSegment(after_) || time_sec < after_->start_sec);
250 if (InvalidSegment(before_)) {
252 before_->start_sec = time_sec;
253 before_->end_sec = time_sec;
255 before_->last_used = ++dst_usage_counter_;
256 return before_->offset_ms;
259 if (time_sec <= before_->end_sec) {
261 before_->last_used = ++dst_usage_counter_;
262 return before_->offset_ms;
265 if (time_sec > before_->end_sec + kDefaultDSTDeltaInSec) {
269 ExtendTheAfterSegment(time_sec, offset_ms);
280 before_->last_used = ++dst_usage_counter_;
284 if (before_->end_sec + kDefaultDSTDeltaInSec <= after_->start_sec) {
285 int new_after_start_sec = before_->end_sec + kDefaultDSTDeltaInSec;
287 ExtendTheAfterSegment(new_after_start_sec, new_offset_ms);
289 ASSERT(!InvalidSegment(after_));
291 after_->last_used = ++dst_usage_counter_;
297 if (before_->offset_ms == after_->offset_ms) {
299 before_->end_sec = after_->end_sec;
300 ClearSegment(after_);
301 return before_->offset_ms;
306 for (
int i = 4; i >= 0; --i) {
307 int delta = after_->start_sec - before_->end_sec;
308 int middle_sec = (i == 0) ? time_sec : before_->end_sec + delta / 2;
310 if (before_->offset_ms == offset_ms) {
311 before_->end_sec = middle_sec;
312 if (time_sec <= before_->end_sec) {
316 ASSERT(after_->offset_ms == offset_ms);
317 after_->start_sec = middle_sec;
318 if (time_sec >= after_->start_sec) {
332 void DateCache::ProbeDST(
int time_sec) {
335 ASSERT(before_ != after_);
337 for (
int i = 0; i < kDSTSize; ++i) {
338 if (dst_[i].start_sec <= time_sec) {
339 if (before ==
NULL || before->start_sec < dst_[i].start_sec) {
342 }
else if (time_sec < dst_[i].end_sec) {
343 if (after ==
NULL || after->end_sec > dst_[i].end_sec) {
351 if (before ==
NULL) {
352 before = InvalidSegment(before_) ? before_ : LeastRecentlyUsedDST(after);
355 after = InvalidSegment(after_) && before != after_
356 ? after_ : LeastRecentlyUsedDST(before);
362 ASSERT(InvalidSegment(before) || before->start_sec <= time_sec);
363 ASSERT(InvalidSegment(after) || time_sec < after->start_sec);
364 ASSERT(InvalidSegment(before) || InvalidSegment(after) ||
365 before->end_sec < after->start_sec);
372 DateCache::DST* DateCache::LeastRecentlyUsedDST(DST* skip) {
374 for (
int i = 0; i < kDSTSize; ++i) {
375 if (&dst_[i] == skip)
continue;
376 if (result ==
NULL || result->last_used > dst_[i].last_used) {
380 ClearSegment(result);
static Smi * FromInt(int value)
static const int64_t kMaxEpochTimeInMs
#define ASSERT(condition)
static const int kInvalidStamp
static const int kMaxEpochTimeInSec
virtual int GetDaylightSavingsOffsetFromOS(int64_t time_sec)
static const int kInvalidLocalOffsetInMs
int DaysFromYearMonth(int year, int month)
void YearMonthDayFromDays(int days, int *year, int *month, int *day)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
static const int kMaxValue
int64_t EquivalentTime(int64_t time_ms)