diff --git a/src/api.cc b/src/api.cc index ebd2b814ff..9c0ac7be86 100644 --- a/src/api.cc +++ b/src/api.cc @@ -7310,13 +7310,13 @@ const CpuProfileNode* CpuProfile::GetSample(int index) const { int64_t CpuProfile::GetStartTime() const { const i::CpuProfile* profile = reinterpret_cast(this); - return (profile->start_time() - i::Time::UnixEpoch()).InMicroseconds(); + return profile->start_time_us(); } int64_t CpuProfile::GetEndTime() const { const i::CpuProfile* profile = reinterpret_cast(this); - return (profile->end_time() - i::Time::UnixEpoch()).InMicroseconds(); + return profile->end_time_us(); } diff --git a/src/compiler.cc b/src/compiler.cc index 93898b18c5..6c2bdce26f 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -260,9 +260,10 @@ void OptimizingCompiler::RecordOptimizationStats() { Handle function = info()->closure(); int opt_count = function->shared()->opt_count(); function->shared()->set_opt_count(opt_count + 1); - double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF(); - double ms_optimize = time_taken_to_optimize_.InMillisecondsF(); - double ms_codegen = time_taken_to_codegen_.InMillisecondsF(); + double ms_creategraph = + static_cast(time_taken_to_create_graph_) / 1000; + double ms_optimize = static_cast(time_taken_to_optimize_) / 1000; + double ms_codegen = static_cast(time_taken_to_codegen_) / 1000; if (FLAG_trace_opt) { PrintF("[optimizing "); function->ShortPrint(); @@ -372,9 +373,9 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() { // performance of the hydrogen-based compiler. bool should_recompile = !info()->shared_info()->has_deoptimization_support(); if (should_recompile || FLAG_hydrogen_stats) { - ElapsedTimer timer; + int64_t start_ticks = 0; if (FLAG_hydrogen_stats) { - timer.Start(); + start_ticks = OS::Ticks(); } CompilationInfoWithZone unoptimized(info()->shared_info()); // Note that we use the same AST that we will use for generating the @@ -393,7 +394,8 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() { Logger::LAZY_COMPILE_TAG, &unoptimized, shared); } if (FLAG_hydrogen_stats) { - isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); + int64_t ticks = OS::Ticks() - start_ticks; + isolate()->GetHStatistics()->IncrementFullCodeGen(ticks); } } @@ -1242,7 +1244,7 @@ CompilationPhase::CompilationPhase(const char* name, CompilationInfo* info) : name_(name), info_(info), zone_(info->isolate()) { if (FLAG_hydrogen_stats) { info_zone_start_allocation_size_ = info->zone()->allocation_size(); - timer_.Start(); + start_ticks_ = OS::Ticks(); } } @@ -1251,7 +1253,8 @@ CompilationPhase::~CompilationPhase() { if (FLAG_hydrogen_stats) { unsigned size = zone()->allocation_size(); size += info_->zone()->allocation_size() - info_zone_start_allocation_size_; - isolate()->GetHStatistics()->SaveTiming(name_, timer_.Elapsed(), size); + int64_t ticks = OS::Ticks() - start_ticks_; + isolate()->GetHStatistics()->SaveTiming(name_, ticks, size); } } diff --git a/src/compiler.h b/src/compiler.h index bdb168fe0d..469698ed06 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -501,6 +501,9 @@ class OptimizingCompiler: public ZoneObject { graph_builder_(NULL), graph_(NULL), chunk_(NULL), + time_taken_to_create_graph_(0), + time_taken_to_optimize_(0), + time_taken_to_codegen_(0), last_status_(FAILED) { } enum Status { @@ -526,9 +529,9 @@ class OptimizingCompiler: public ZoneObject { HOptimizedGraphBuilder* graph_builder_; HGraph* graph_; LChunk* chunk_; - TimeDelta time_taken_to_create_graph_; - TimeDelta time_taken_to_optimize_; - TimeDelta time_taken_to_codegen_; + int64_t time_taken_to_create_graph_; + int64_t time_taken_to_optimize_; + int64_t time_taken_to_codegen_; Status last_status_; MUST_USE_RESULT Status SetLastStatus(Status status) { @@ -538,20 +541,18 @@ class OptimizingCompiler: public ZoneObject { void RecordOptimizationStats(); struct Timer { - Timer(OptimizingCompiler* compiler, TimeDelta* location) + Timer(OptimizingCompiler* compiler, int64_t* location) : compiler_(compiler), - location_(location) { - ASSERT(location_ != NULL); - timer_.Start(); - } + start_(OS::Ticks()), + location_(location) { } ~Timer() { - *location_ += timer_.Elapsed(); + *location_ += (OS::Ticks() - start_); } OptimizingCompiler* compiler_; - ElapsedTimer timer_; - TimeDelta* location_; + int64_t start_; + int64_t* location_; }; }; @@ -643,7 +644,7 @@ class CompilationPhase BASE_EMBEDDED { CompilationInfo* info_; Zone zone_; unsigned info_zone_start_allocation_size_; - ElapsedTimer timer_; + int64_t start_ticks_; DISALLOW_COPY_AND_ASSIGN(CompilationPhase); }; diff --git a/src/counters.cc b/src/counters.cc index e2530a8fc1..183941206e 100644 --- a/src/counters.cc +++ b/src/counters.cc @@ -60,7 +60,8 @@ void* Histogram::CreateHistogram() const { // Start the timer. void HistogramTimer::Start() { if (Enabled()) { - timer_.Start(); + stop_time_ = 0; + start_time_ = OS::Ticks(); } if (FLAG_log_internal_timer_events) { LOG(isolate(), TimerEvent(Logger::START, name())); @@ -71,9 +72,10 @@ void HistogramTimer::Start() { // Stop the timer and record the results. void HistogramTimer::Stop() { if (Enabled()) { + stop_time_ = OS::Ticks(); // Compute the delta between start and stop, in milliseconds. - AddSample(static_cast(timer_.Elapsed().InMilliseconds())); - timer_.Stop(); + int milliseconds = static_cast(stop_time_ - start_time_) / 1000; + AddSample(milliseconds); } if (FLAG_log_internal_timer_events) { LOG(isolate(), TimerEvent(Logger::END, name())); diff --git a/src/counters.h b/src/counters.h index 8cfe6c525c..a633fea779 100644 --- a/src/counters.h +++ b/src/counters.h @@ -245,7 +245,9 @@ class HistogramTimer : public Histogram { int max, int num_buckets, Isolate* isolate) - : Histogram(name, min, max, num_buckets, isolate) {} + : Histogram(name, min, max, num_buckets, isolate), + start_time_(0), + stop_time_(0) { } // Start the timer. void Start(); @@ -255,11 +257,12 @@ class HistogramTimer : public Histogram { // Returns true if the timer is running. bool Running() { - return Enabled() && timer_.IsStarted(); + return Enabled() && (start_time_ != 0) && (stop_time_ == 0); } private: - ElapsedTimer timer_; + int64_t start_time_; + int64_t stop_time_; }; // Helper class for scoping a HistogramTimer. diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc index 0802687a1c..f8698b3100 100644 --- a/src/cpu-profiler.cc +++ b/src/cpu-profiler.cc @@ -46,12 +46,12 @@ static const int kProfilerStackSize = 64 * KB; ProfilerEventsProcessor::ProfilerEventsProcessor( ProfileGenerator* generator, Sampler* sampler, - TimeDelta period) + int period_in_useconds) : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)), generator_(generator), sampler_(sampler), running_(true), - period_(period), + period_in_useconds_(period_in_useconds), last_code_event_id_(0), last_processed_code_event_id_(0) { } @@ -124,10 +124,9 @@ bool ProfilerEventsProcessor::ProcessTicks() { void ProfilerEventsProcessor::ProcessEventsAndDoSample() { - ElapsedTimer timer; - timer.Start(); + int64_t stop_time = OS::Ticks() + period_in_useconds_; // Keep processing existing events until we need to do next sample. - while (!timer.HasExpired(period_)) { + while (OS::Ticks() < stop_time) { if (ProcessTicks()) { // All ticks of the current dequeue_order are processed, // proceed to the next code event. @@ -435,8 +434,7 @@ void CpuProfiler::StartProcessorIfNotStarted() { generator_ = new ProfileGenerator(profiles_); Sampler* sampler = logger->sampler(); processor_ = new ProfilerEventsProcessor( - generator_, sampler, - TimeDelta::FromMicroseconds(FLAG_cpu_profiler_sampling_interval)); + generator_, sampler, FLAG_cpu_profiler_sampling_interval); is_profiling_ = true; // Enumerate stuff we already have in the heap. ASSERT(isolate_->heap()->HasBeenSetUp()); diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h index 41473d7955..84e34e422e 100644 --- a/src/cpu-profiler.h +++ b/src/cpu-profiler.h @@ -138,7 +138,7 @@ class ProfilerEventsProcessor : public Thread { public: ProfilerEventsProcessor(ProfileGenerator* generator, Sampler* sampler, - TimeDelta period); + int period_in_useconds); virtual ~ProfilerEventsProcessor() {} // Thread control. @@ -169,7 +169,7 @@ class ProfilerEventsProcessor : public Thread { Sampler* sampler_; bool running_; // Sampling period in microseconds. - const TimeDelta period_; + const int period_in_useconds_; UnboundQueue events_buffer_; static const size_t kTickSampleBufferSize = 1 * MB; static const size_t kTickSampleQueueLength = diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index f797565c31..dc9ffc5118 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -784,13 +784,12 @@ void Deoptimizer::DoComputeOutputFrames() { } // Print some helpful diagnostic information. + int64_t start = OS::Ticks(); if (FLAG_log_timer_events && compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { LOG(isolate(), CodeDeoptEvent(compiled_code_)); } - ElapsedTimer timer; if (trace_) { - timer.Start(); PrintF("[deoptimizing (DEOPT %s): begin 0x%08" V8PRIxPTR " ", MessageFor(bailout_type_), reinterpret_cast(function_)); @@ -871,7 +870,7 @@ void Deoptimizer::DoComputeOutputFrames() { // Print some helpful diagnostic information. if (trace_) { - double ms = timer.Elapsed().InMillisecondsF(); + double ms = static_cast(OS::Ticks() - start) / 1000; int index = output_count_ - 1; // Index of the topmost frame. JSFunction* function = output_[index]->GetFunction(); PrintF("[deoptimizing (%s): end 0x%08" V8PRIxPTR " ", diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 445a0a0fb1..ea6288e182 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -9815,15 +9815,15 @@ void HStatistics::Initialize(CompilationInfo* info) { void HStatistics::Print() { PrintF("Timing results:\n"); - TimeDelta sum; - for (int i = 0; i < times_.length(); ++i) { - sum += times_[i]; + int64_t sum = 0; + for (int i = 0; i < timing_.length(); ++i) { + sum += timing_[i]; } for (int i = 0; i < names_.length(); ++i) { PrintF("%32s", names_[i]); - double ms = times_[i].InMillisecondsF(); - double percent = times_[i].PercentOf(sum); + double ms = static_cast(timing_[i]) / 1000; + double percent = static_cast(timing_[i]) * 100 / sum; PrintF(" %8.3f ms / %4.1f %% ", ms, percent); unsigned size = sizes_[i]; @@ -9833,29 +9833,29 @@ void HStatistics::Print() { PrintF("----------------------------------------" "---------------------------------------\n"); - TimeDelta total = create_graph_ + optimize_graph_ + generate_code_; + int64_t total = create_graph_ + optimize_graph_ + generate_code_; PrintF("%32s %8.3f ms / %4.1f %% \n", "Create graph", - create_graph_.InMillisecondsF(), - create_graph_.PercentOf(total)); + static_cast(create_graph_) / 1000, + static_cast(create_graph_) * 100 / total); PrintF("%32s %8.3f ms / %4.1f %% \n", "Optimize graph", - optimize_graph_.InMillisecondsF(), - optimize_graph_.PercentOf(total)); + static_cast(optimize_graph_) / 1000, + static_cast(optimize_graph_) * 100 / total); PrintF("%32s %8.3f ms / %4.1f %% \n", "Generate and install code", - generate_code_.InMillisecondsF(), - generate_code_.PercentOf(total)); + static_cast(generate_code_) / 1000, + static_cast(generate_code_) * 100 / total); PrintF("----------------------------------------" "---------------------------------------\n"); PrintF("%32s %8.3f ms (%.1f times slower than full code gen)\n", "Total", - total.InMillisecondsF(), - total.TimesOf(full_code_gen_)); + static_cast(total) / 1000, + static_cast(total) / full_code_gen_); double source_size_in_kb = static_cast(source_size_) / 1024; double normalized_time = source_size_in_kb > 0 - ? total.InMillisecondsF() / source_size_in_kb + ? (static_cast(total) / 1000) / source_size_in_kb : 0; double normalized_size_in_kb = source_size_in_kb > 0 ? total_size_ / 1024 / source_size_in_kb @@ -9866,17 +9866,17 @@ void HStatistics::Print() { } -void HStatistics::SaveTiming(const char* name, TimeDelta time, unsigned size) { +void HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) { total_size_ += size; for (int i = 0; i < names_.length(); ++i) { if (strcmp(names_[i], name) == 0) { - times_[i] += time; + timing_[i] += ticks; sizes_[i] += size; return; } } names_.Add(name); - times_.Add(time); + timing_.Add(ticks); sizes_.Add(size); } diff --git a/src/hydrogen.h b/src/hydrogen.h index 369e092535..22bffd14a5 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -2165,37 +2165,41 @@ Zone* AstContext::zone() const { return owner_->zone(); } class HStatistics V8_FINAL: public Malloced { public: HStatistics() - : times_(5), + : timing_(5), names_(5), sizes_(5), + create_graph_(0), + optimize_graph_(0), + generate_code_(0), total_size_(0), + full_code_gen_(0), source_size_(0) { } void Initialize(CompilationInfo* info); void Print(); - void SaveTiming(const char* name, TimeDelta time, unsigned size); + void SaveTiming(const char* name, int64_t ticks, unsigned size); - void IncrementFullCodeGen(TimeDelta full_code_gen) { + void IncrementFullCodeGen(int64_t full_code_gen) { full_code_gen_ += full_code_gen; } - void IncrementSubtotals(TimeDelta create_graph, - TimeDelta optimize_graph, - TimeDelta generate_code) { + void IncrementSubtotals(int64_t create_graph, + int64_t optimize_graph, + int64_t generate_code) { create_graph_ += create_graph; optimize_graph_ += optimize_graph; generate_code_ += generate_code; } private: - List times_; + List timing_; List names_; List sizes_; - TimeDelta create_graph_; - TimeDelta optimize_graph_; - TimeDelta generate_code_; + int64_t create_graph_; + int64_t optimize_graph_; + int64_t generate_code_; unsigned total_size_; - TimeDelta full_code_gen_; + int64_t full_code_gen_; double source_size_; }; diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc index 3c5abd1984..2e2f802558 100644 --- a/src/lithium-allocator.cc +++ b/src/lithium-allocator.cc @@ -2189,7 +2189,7 @@ LAllocatorPhase::~LAllocatorPhase() { if (FLAG_hydrogen_stats) { unsigned size = allocator_->zone()->allocation_size() - allocator_zone_start_allocation_size_; - isolate()->GetHStatistics()->SaveTiming(name(), TimeDelta(), size); + isolate()->GetHStatistics()->SaveTiming(name(), 0, size); } if (ShouldProduceTraceOutput()) { diff --git a/src/log.cc b/src/log.cc index 59d494a149..ff67d10868 100644 --- a/src/log.cc +++ b/src/log.cc @@ -716,7 +716,8 @@ Logger::Logger(Isolate* isolate) ll_logger_(NULL), jit_logger_(NULL), listeners_(5), - is_initialized_(false) { + is_initialized_(false), + epoch_(0) { } @@ -867,7 +868,7 @@ void Logger::CodeDeoptEvent(Code* code) { if (!log_->IsEnabled()) return; ASSERT(FLAG_log_internal_timer_events); Log::MessageBuilder msg(log_); - int since_epoch = static_cast(timer_.Elapsed().InMicroseconds()); + int since_epoch = static_cast(OS::Ticks() - epoch_); msg.Append("code-deopt,%ld,%d\n", since_epoch, code->CodeSize()); msg.WriteToLogFile(); } @@ -877,7 +878,7 @@ void Logger::TimerEvent(StartEnd se, const char* name) { if (!log_->IsEnabled()) return; ASSERT(FLAG_log_internal_timer_events); Log::MessageBuilder msg(log_); - int since_epoch = static_cast(timer_.Elapsed().InMicroseconds()); + int since_epoch = static_cast(OS::Ticks() - epoch_); const char* format = (se == START) ? "timer-event-start,\"%s\",%ld\n" : "timer-event-end,\"%s\",%ld\n"; msg.Append(format, name, since_epoch); @@ -1500,7 +1501,7 @@ void Logger::TickEvent(TickSample* sample, bool overflow) { Log::MessageBuilder msg(log_); msg.Append("%s,", kLogEventsNames[TICK_EVENT]); msg.AppendAddress(sample->pc); - msg.Append(",%ld", static_cast(timer_.Elapsed().InMicroseconds())); + msg.Append(",%ld", static_cast(OS::Ticks() - epoch_)); if (sample->has_external_callback) { msg.Append(",1,"); msg.AppendAddress(sample->external_callback); @@ -1895,7 +1896,7 @@ bool Logger::SetUp(Isolate* isolate) { } } - if (FLAG_log_internal_timer_events || FLAG_prof) timer_.Start(); + if (FLAG_log_internal_timer_events || FLAG_prof) epoch_ = OS::Ticks(); return true; } diff --git a/src/log.h b/src/log.h index adf95ff9e2..76e3ceeecd 100644 --- a/src/log.h +++ b/src/log.h @@ -31,7 +31,6 @@ #include "allocation.h" #include "objects.h" #include "platform.h" -#include "platform/elapsed-timer.h" namespace v8 { namespace internal { @@ -451,7 +450,7 @@ class Logger { // 'true' between SetUp() and TearDown(). bool is_initialized_; - ElapsedTimer timer_; + int64_t epoch_; friend class CpuProfiler; }; diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc index added33882..788f027061 100644 --- a/src/optimizing-compiler-thread.cc +++ b/src/optimizing-compiler-thread.cc @@ -48,8 +48,8 @@ void OptimizingCompilerThread::Run() { DisallowHandleAllocation no_handles; DisallowHandleDereference no_deref; - ElapsedTimer total_timer; - if (FLAG_trace_concurrent_recompilation) total_timer.Start(); + int64_t epoch = 0; + if (FLAG_trace_concurrent_recompilation) epoch = OS::Ticks(); while (true) { input_queue_semaphore_->Wait(); @@ -65,7 +65,7 @@ void OptimizingCompilerThread::Run() { break; case STOP: if (FLAG_trace_concurrent_recompilation) { - time_spent_total_ = total_timer.Elapsed(); + time_spent_total_ = OS::Ticks() - epoch; } stop_semaphore_->Signal(); return; @@ -81,13 +81,13 @@ void OptimizingCompilerThread::Run() { continue; } - ElapsedTimer compiling_timer; - if (FLAG_trace_concurrent_recompilation) compiling_timer.Start(); + int64_t compiling_start = 0; + if (FLAG_trace_concurrent_recompilation) compiling_start = OS::Ticks(); CompileNext(); if (FLAG_trace_concurrent_recompilation) { - time_spent_compiling_ += compiling_timer.Elapsed(); + time_spent_compiling_ += OS::Ticks() - compiling_start; } } } @@ -175,7 +175,9 @@ void OptimizingCompilerThread::Stop() { } if (FLAG_trace_concurrent_recompilation) { - double percentage = time_spent_compiling_.PercentOf(time_spent_total_); + double compile_time = static_cast(time_spent_compiling_); + double total_time = static_cast(time_spent_total_); + double percentage = (compile_time * 100) / total_time; PrintF(" ** Compiler thread did %.2f%% useful work\n", percentage); } diff --git a/src/optimizing-compiler-thread.h b/src/optimizing-compiler-thread.h index 1b06208c40..aff94eddc2 100644 --- a/src/optimizing-compiler-thread.h +++ b/src/optimizing-compiler-thread.h @@ -31,7 +31,6 @@ #include "atomicops.h" #include "flags.h" #include "platform.h" -#include "platform/time.h" #include "unbound-queue-inl.h" namespace v8 { @@ -52,7 +51,9 @@ class OptimizingCompilerThread : public Thread { isolate_(isolate), stop_semaphore_(OS::CreateSemaphore(0)), input_queue_semaphore_(OS::CreateSemaphore(0)), - install_mutex_(OS::CreateMutex()) { + install_mutex_(OS::CreateMutex()), + time_spent_compiling_(0), + time_spent_total_(0) { NoBarrier_Store(&stop_thread_, static_cast(CONTINUE)); NoBarrier_Store(&queue_length_, static_cast(0)); } @@ -111,8 +112,8 @@ class OptimizingCompilerThread : public Thread { Mutex* install_mutex_; volatile AtomicWord stop_thread_; volatile Atomic32 queue_length_; - TimeDelta time_spent_compiling_; - TimeDelta time_spent_total_; + int64_t time_spent_compiling_; + int64_t time_spent_total_; }; } } // namespace v8::internal diff --git a/src/parser.cc b/src/parser.cc index e4a6bb2d3a..ccab7ec64c 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -569,13 +569,10 @@ Parser::Parser(CompilationInfo* info) FunctionLiteral* Parser::ParseProgram() { - HistogramTimerScope timer_scope(isolate()->counters()->parse()); + HistogramTimerScope timer(isolate()->counters()->parse()); Handle source(String::cast(script_->source())); isolate()->counters()->total_parse_size()->Increment(source->length()); - ElapsedTimer timer; - if (FLAG_trace_parse) { - timer.Start(); - } + int64_t start = FLAG_trace_parse ? OS::Ticks() : 0; fni_ = new(zone()) FuncNameInferrer(isolate(), zone()); // Initialize parser state. @@ -596,7 +593,7 @@ FunctionLiteral* Parser::ParseProgram() { } if (FLAG_trace_parse && result != NULL) { - double ms = timer.Elapsed().InMillisecondsF(); + double ms = static_cast(OS::Ticks() - start) / 1000; if (info()->is_eval()) { PrintF("[parsing eval"); } else if (info()->script()->name()->IsString()) { @@ -700,13 +697,10 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, FunctionLiteral* Parser::ParseLazy() { - HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy()); + HistogramTimerScope timer(isolate()->counters()->parse_lazy()); Handle source(String::cast(script_->source())); isolate()->counters()->total_parse_size()->Increment(source->length()); - ElapsedTimer timer; - if (FLAG_trace_parse) { - timer.Start(); - } + int64_t start = FLAG_trace_parse ? OS::Ticks() : 0; Handle shared_info = info()->shared_info(); // Initialize parser state. @@ -726,7 +720,7 @@ FunctionLiteral* Parser::ParseLazy() { } if (FLAG_trace_parse && result != NULL) { - double ms = timer.Elapsed().InMillisecondsF(); + double ms = static_cast(OS::Ticks() - start) / 1000; SmartArrayPointer name_chars = result->debug_name()->ToCString(); PrintF("[parsing function: %s - took %0.3f ms]\n", *name_chars, ms); } diff --git a/src/platform-linux.cc b/src/platform-linux.cc index b27c1fd1d8..ef97449b65 100644 --- a/src/platform-linux.cc +++ b/src/platform-linux.cc @@ -569,7 +569,7 @@ Semaphore* OS::CreateSemaphore(int count) { void OS::SetUp() { // Seed the random number generator. We preserve microsecond resolution. - uint64_t seed = static_cast(TimeCurrentMillis()) ^ (getpid() << 16); + uint64_t seed = Ticks() ^ (getpid() << 16); srandom(static_cast(seed)); limit_mutex = CreateMutex(); } diff --git a/src/platform-macos.cc b/src/platform-macos.cc index 9d8d076bb0..6135cd1374 100644 --- a/src/platform-macos.cc +++ b/src/platform-macos.cc @@ -441,7 +441,7 @@ Semaphore* OS::CreateSemaphore(int count) { void OS::SetUp() { // Seed the random number generator. We preserve microsecond resolution. - uint64_t seed = static_cast(TimeCurrentMillis()) ^ (getpid() << 16); + uint64_t seed = Ticks() ^ (getpid() << 16); srandom(static_cast(seed)); limit_mutex = CreateMutex(); } diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc index a027944145..e59160109f 100644 --- a/src/platform-openbsd.cc +++ b/src/platform-openbsd.cc @@ -500,7 +500,7 @@ Semaphore* OS::CreateSemaphore(int count) { void OS::SetUp() { // Seed the random number generator. We preserve microsecond resolution. - uint64_t seed = static_cast(TimeCurrentMillis()) ^ (getpid() << 16); + uint64_t seed = Ticks() ^ (getpid() << 16); srandom(static_cast(seed)); limit_mutex = CreateMutex(); } diff --git a/src/platform-posix.cc b/src/platform-posix.cc index dd6b77c265..58d0a2478d 100644 --- a/src/platform-posix.cc +++ b/src/platform-posix.cc @@ -313,7 +313,19 @@ int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { double OS::TimeCurrentMillis() { - return Time::Now().ToJsTime(); + struct timeval tv; + if (gettimeofday(&tv, NULL) < 0) return 0.0; + return (static_cast(tv.tv_sec) * 1000) + + (static_cast(tv.tv_usec) / 1000); +} + + +int64_t OS::Ticks() { + // gettimeofday has microsecond resolution. + struct timeval tv; + if (gettimeofday(&tv, NULL) < 0) + return 0; + return (static_cast(tv.tv_sec) * 1000000) + tv.tv_usec; } diff --git a/src/platform-win32.cc b/src/platform-win32.cc index cdd9a4fb46..c136631f00 100644 --- a/src/platform-win32.cc +++ b/src/platform-win32.cc @@ -38,6 +38,7 @@ #endif // MINGW_HAS_SECURE_API #endif // __MINGW32__ +#define V8_WIN32_HEADERS_FULL #include "win32-headers.h" #include "v8.h" @@ -245,15 +246,19 @@ void MathSetup() { // timestamps are represented as a doubles in milliseconds since 00:00:00 UTC, // January 1, 1970. -class Win32Time { +class Time { public: // Constructors. - explicit Win32Time(double jstime); - Win32Time(int year, int mon, int day, int hour, int min, int sec); + Time(); + explicit Time(double jstime); + Time(int year, int mon, int day, int hour, int min, int sec); // Convert timestamp to JavaScript representation. double ToJSTime(); + // Set timestamp to current time. + void SetToCurrentTime(); + // Returns the local timezone offset in milliseconds east of UTC. This is // the number of milliseconds you must add to UTC to get local time, i.e. // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This @@ -295,6 +300,10 @@ class Win32Time { // Return whether or not daylight savings time is in effect at this time. bool InDST(); + // Return the difference (in milliseconds) between this timestamp and + // another timestamp. + int64_t Diff(Time* other); + // Accessor for FILETIME representation. FILETIME& ft() { return time_.ft_; } @@ -316,20 +325,26 @@ class Win32Time { // Static variables. -bool Win32Time::tz_initialized_ = false; -TIME_ZONE_INFORMATION Win32Time::tzinfo_; -char Win32Time::std_tz_name_[kTzNameSize]; -char Win32Time::dst_tz_name_[kTzNameSize]; +bool Time::tz_initialized_ = false; +TIME_ZONE_INFORMATION Time::tzinfo_; +char Time::std_tz_name_[kTzNameSize]; +char Time::dst_tz_name_[kTzNameSize]; + + +// Initialize timestamp to start of epoc. +Time::Time() { + t() = 0; +} // Initialize timestamp from a JavaScript timestamp. -Win32Time::Win32Time(double jstime) { +Time::Time(double jstime) { t() = static_cast(jstime) * kTimeScaler + kTimeEpoc; } // Initialize timestamp from date/time components. -Win32Time::Win32Time(int year, int mon, int day, int hour, int min, int sec) { +Time::Time(int year, int mon, int day, int hour, int min, int sec) { SYSTEMTIME st; st.wYear = year; st.wMonth = mon; @@ -343,14 +358,14 @@ Win32Time::Win32Time(int year, int mon, int day, int hour, int min, int sec) { // Convert timestamp to JavaScript timestamp. -double Win32Time::ToJSTime() { +double Time::ToJSTime() { return static_cast((t() - kTimeEpoc) / kTimeScaler); } // Guess the name of the timezone from the bias. // The guess is very biased towards the northern hemisphere. -const char* Win32Time::GuessTimezoneNameFromBias(int bias) { +const char* Time::GuessTimezoneNameFromBias(int bias) { static const int kHour = 60; switch (-bias) { case -9*kHour: return "Alaska"; @@ -375,7 +390,7 @@ const char* Win32Time::GuessTimezoneNameFromBias(int bias) { // Initialize timezone information. The timezone information is obtained from // windows. If we cannot get the timezone information we fall back to CET. // Please notice that this code is not thread-safe. -void Win32Time::TzSet() { +void Time::TzSet() { // Just return if timezone information has already been initialized. if (tz_initialized_) return; @@ -424,16 +439,78 @@ void Win32Time::TzSet() { } +// Return the difference in milliseconds between this and another timestamp. +int64_t Time::Diff(Time* other) { + return (t() - other->t()) / kTimeScaler; +} + + +// Set timestamp to current time. +void Time::SetToCurrentTime() { + // The default GetSystemTimeAsFileTime has a ~15.5ms resolution. + // Because we're fast, we like fast timers which have at least a + // 1ms resolution. + // + // timeGetTime() provides 1ms granularity when combined with + // timeBeginPeriod(). If the host application for v8 wants fast + // timers, it can use timeBeginPeriod to increase the resolution. + // + // Using timeGetTime() has a drawback because it is a 32bit value + // and hence rolls-over every ~49days. + // + // To use the clock, we use GetSystemTimeAsFileTime as our base; + // and then use timeGetTime to extrapolate current time from the + // start time. To deal with rollovers, we resync the clock + // any time when more than kMaxClockElapsedTime has passed or + // whenever timeGetTime creates a rollover. + + static bool initialized = false; + static TimeStamp init_time; + static DWORD init_ticks; + static const int64_t kHundredNanosecondsPerSecond = 10000000; + static const int64_t kMaxClockElapsedTime = + 60*kHundredNanosecondsPerSecond; // 1 minute + + // If we are uninitialized, we need to resync the clock. + bool needs_resync = !initialized; + + // Get the current time. + TimeStamp time_now; + GetSystemTimeAsFileTime(&time_now.ft_); + DWORD ticks_now = timeGetTime(); + + // Check if we need to resync due to clock rollover. + needs_resync |= ticks_now < init_ticks; + + // Check if we need to resync due to elapsed time. + needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime; + + // Check if we need to resync due to backwards time change. + needs_resync |= time_now.t_ < init_time.t_; + + // Resync the clock if necessary. + if (needs_resync) { + GetSystemTimeAsFileTime(&init_time.ft_); + init_ticks = ticks_now = timeGetTime(); + initialized = true; + } + + // Finally, compute the actual time. Why is this so hard. + DWORD elapsed = ticks_now - init_ticks; + this->time_.t_ = init_time.t_ + (static_cast(elapsed) * 10000); +} + + // Return the local timezone offset in milliseconds east of UTC. This // takes into account whether daylight saving is in effect at the time. // Only times in the 32-bit Unix range may be passed to this function. // Also, adding the time-zone offset to the input must not overflow. // The function EquivalentTime() in date.js guarantees this. -int64_t Win32Time::LocalOffset() { +int64_t Time::LocalOffset() { // Initialize timezone information, if needed. TzSet(); - Win32Time rounded_to_second(*this); + Time rounded_to_second(*this); rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler * 1000 * kTimeScaler; // Convert to local time using POSIX localtime function. @@ -464,7 +541,7 @@ int64_t Win32Time::LocalOffset() { // Return whether or not daylight savings time is in effect at this time. -bool Win32Time::InDST() { +bool Time::InDST() { // Initialize timezone information, if needed. TzSet(); @@ -488,14 +565,14 @@ bool Win32Time::InDST() { // Return the daylight savings time offset for this time. -int64_t Win32Time::DaylightSavingsOffset() { +int64_t Time::DaylightSavingsOffset() { return InDST() ? 60 * kMsPerMinute : 0; } // Returns a string identifying the current timezone for the // timestamp taking into account daylight saving. -char* Win32Time::LocalTimezone() { +char* Time::LocalTimezone() { // Return the standard or DST time zone name based on whether daylight // saving is in effect at the given time. return InDST() ? dst_tz_name_ : std_tz_name_; @@ -537,14 +614,22 @@ int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { // Returns current time as the number of milliseconds since // 00:00:00 UTC, January 1, 1970. double OS::TimeCurrentMillis() { - return Time::Now().ToJsTime(); + Time t; + t.SetToCurrentTime(); + return t.ToJSTime(); +} + + +// Returns the tickcounter based on timeGetTime. +int64_t OS::Ticks() { + return timeGetTime() * 1000; // Convert to microseconds. } // Returns a string identifying the current timezone taking into // account daylight saving. const char* OS::LocalTimezone(double time) { - return Win32Time(time).LocalTimezone(); + return Time(time).LocalTimezone(); } @@ -552,7 +637,7 @@ const char* OS::LocalTimezone(double time) { // taking daylight savings time into account. double OS::LocalTimeOffset() { // Use current time, rounded to the millisecond. - Win32Time t(TimeCurrentMillis()); + Time t(TimeCurrentMillis()); // Time::LocalOffset inlcudes any daylight savings offset, so subtract it. return static_cast(t.LocalOffset() - t.DaylightSavingsOffset()); } @@ -561,7 +646,7 @@ double OS::LocalTimeOffset() { // Returns the daylight savings offset in milliseconds for the given // time. double OS::DaylightSavingsOffset(double time) { - int64_t offset = Win32Time(time).DaylightSavingsOffset(); + int64_t offset = Time(time).DaylightSavingsOffset(); return static_cast(offset); } diff --git a/src/platform.h b/src/platform.h index 44817b4b11..a42bb5a20e 100644 --- a/src/platform.h +++ b/src/platform.h @@ -192,6 +192,10 @@ class OS { // micro-second resolution. static int GetUserTime(uint32_t* secs, uint32_t* usecs); + // Get a tick counter normalized to one tick per microsecond. + // Used for calculating time intervals. + static int64_t Ticks(); + // Returns current time as the number of milliseconds since // 00:00:00 UTC, January 1, 1970. static double TimeCurrentMillis(); diff --git a/src/platform/elapsed-timer.h b/src/platform/elapsed-timer.h deleted file mode 100644 index e5bcf232f3..0000000000 --- a/src/platform/elapsed-timer.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2013 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef V8_PLATFORM_ELAPSED_TIMER_H_ -#define V8_PLATFORM_ELAPSED_TIMER_H_ - -#include "checks.h" -#include "platform/time.h" - -namespace v8 { -namespace internal { - -class ElapsedTimer V8_FINAL BASE_EMBEDDED { - public: -#ifdef DEBUG - ElapsedTimer() : started_(false) {} -#endif - - // Starts this timer. Once started a timer can be checked with - // |Elapsed()| or |HasExpired()|, and may be restarted using |Restart()|. - // This method must not be called on an already started timer. - void Start() { - ASSERT(!IsStarted()); - start_ticks_ = Now(); -#ifdef DEBUG - started_ = true; -#endif - ASSERT(IsStarted()); - } - - // Stops this timer. Must not be called on a timer that was not - // started before. - void Stop() { - ASSERT(IsStarted()); - start_ticks_ = TimeTicks(); -#ifdef DEBUG - started_ = false; -#endif - ASSERT(!IsStarted()); - } - - // Returns |true| if this timer was started previously. - bool IsStarted() const { - ASSERT(started_ || start_ticks_.IsNull()); - ASSERT(!started_ || !start_ticks_.IsNull()); - return !start_ticks_.IsNull(); - } - - // Restarts the timer and returns the time elapsed since the previous start. - // This method is equivalent to obtaining the elapsed time with |Elapsed()| - // and then starting the timer again, but does so in one single operation, - // avoiding the need to obtain the clock value twice. It may only be called - // on a previously started timer. - TimeDelta Restart() { - ASSERT(IsStarted()); - TimeTicks ticks = Now(); - TimeDelta elapsed = ticks - start_ticks_; - ASSERT(elapsed.InMicroseconds() >= 0); - start_ticks_ = ticks; - ASSERT(IsStarted()); - return elapsed; - } - - // Returns the time elapsed since the previous start. This method may only - // be called on a previously started timer. - MUST_USE_RESULT TimeDelta Elapsed() const { - ASSERT(IsStarted()); - TimeDelta elapsed = Now() - start_ticks_; - ASSERT(elapsed.InMicroseconds() >= 0); - return elapsed; - } - - // Returns |true| if the specified |time_delta| has elapsed since the - // previous start, or |false| if not. This method may only be called on - // a previously started timer. - MUST_USE_RESULT bool HasExpired(TimeDelta time_delta) const { - ASSERT(IsStarted()); - return Elapsed() >= time_delta; - } - - private: - MUST_USE_RESULT V8_INLINE(static TimeTicks Now()) { - TimeTicks now = TimeTicks::HighResNow(); - ASSERT(!now.IsNull()); - return now; - } - - TimeTicks start_ticks_; -#ifdef DEBUG - bool started_; -#endif -}; - -} } // namespace v8::internal - -#endif // V8_PLATFORM_ELAPSED_TIMER_H_ diff --git a/src/platform/time.cc b/src/platform/time.cc deleted file mode 100644 index a1b308a707..0000000000 --- a/src/platform/time.cc +++ /dev/null @@ -1,482 +0,0 @@ -// Copyright 2013 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "platform/time.h" - -#if V8_OS_POSIX -#include -#endif -#if V8_OS_MACOSX -#include -#endif - -#include - -#include "checks.h" -#include "cpu.h" -#include "platform.h" -#if V8_OS_WIN -#include "win32-headers.h" -#endif - -namespace v8 { -namespace internal { - -TimeDelta TimeDelta::FromDays(int days) { - return TimeDelta(days * Time::kMicrosecondsPerDay); -} - - -TimeDelta TimeDelta::FromHours(int hours) { - return TimeDelta(hours * Time::kMicrosecondsPerHour); -} - - -TimeDelta TimeDelta::FromMinutes(int minutes) { - return TimeDelta(minutes * Time::kMicrosecondsPerMinute); -} - - -TimeDelta TimeDelta::FromSeconds(int64_t seconds) { - return TimeDelta(seconds * Time::kMicrosecondsPerSecond); -} - - -TimeDelta TimeDelta::FromMilliseconds(int64_t milliseconds) { - return TimeDelta(milliseconds * Time::kMicrosecondsPerMillisecond); -} - - -TimeDelta TimeDelta::FromNanoseconds(int64_t nanoseconds) { - return TimeDelta(nanoseconds / Time::kNanosecondsPerMicrosecond); -} - - -int TimeDelta::InDays() const { - return static_cast(delta_ / Time::kMicrosecondsPerDay); -} - - -int TimeDelta::InHours() const { - return static_cast(delta_ / Time::kMicrosecondsPerHour); -} - - -int TimeDelta::InMinutes() const { - return static_cast(delta_ / Time::kMicrosecondsPerMinute); -} - - -double TimeDelta::InSecondsF() const { - return static_cast(delta_) / Time::kMicrosecondsPerSecond; -} - - -int64_t TimeDelta::InSeconds() const { - return delta_ / Time::kMicrosecondsPerSecond; -} - - -double TimeDelta::InMillisecondsF() const { - return static_cast(delta_) / Time::kMicrosecondsPerMillisecond; -} - - -int64_t TimeDelta::InMilliseconds() const { - return delta_ / Time::kMicrosecondsPerMillisecond; -} - - -int64_t TimeDelta::InNanoseconds() const { - return delta_ * Time::kNanosecondsPerMicrosecond; -} - - -#if V8_OS_WIN - -// We implement time using the high-resolution timers so that we can get -// timeouts which are smaller than 10-15ms. To avoid any drift, we -// periodically resync the internal clock to the system clock. -class Clock V8_FINAL { - public: - Clock() : initial_time_(CurrentWallclockTime()), - initial_ticks_(TimeTicks::Now()), - mutex_(OS::CreateMutex()) {} - - ~Clock() { delete mutex_; } - - Time Now() { - // This must be executed under lock. - ScopedLock sl(mutex_); - - // Calculate the time elapsed since we started our timer. - TimeDelta elapsed = TimeTicks::Now() - initial_ticks_; - - // Check if we don't need to synchronize with the wallclock yet. - if (elapsed.InMicroseconds() <= kMaxMicrosecondsToAvoidDrift) { - return initial_time_ + elapsed; - } - - // Resynchronize with the wallclock. - initial_ticks_ = TimeTicks::Now(); - initial_time_ = CurrentWallclockTime(); - return initial_time_; - } - - Time NowFromSystemTime() { - ScopedLock sl(mutex_); - initial_ticks_ = TimeTicks::Now(); - initial_time_ = CurrentWallclockTime(); - return initial_time_; - } - - private: - // Time between resampling the un-granular clock for this API (1 minute). - static const int64_t kMaxMicrosecondsToAvoidDrift = - Time::kMicrosecondsPerMinute; - - static Time CurrentWallclockTime() { - FILETIME ft; - ::GetSystemTimeAsFileTime(&ft); - return Time::FromFiletime(ft); - } - - TimeTicks initial_ticks_; - Time initial_time_; - Mutex* mutex_; -}; - - -static LazyDynamicInstance, - ThreadSafeInitOnceTrait>::type clock = LAZY_DYNAMIC_INSTANCE_INITIALIZER; - - -Time Time::Now() { - return clock.Pointer()->Now(); -} - - -Time Time::NowFromSystemTime() { - return clock.Pointer()->NowFromSystemTime(); -} - - -// Time between windows epoch and standard epoch. -static const int64_t kTimeToEpochInMicroseconds = V8_INT64_C(11644473600000000); - - -Time Time::FromFiletime(FILETIME ft) { - if (ft.dwLowDateTime == 0 && ft.dwHighDateTime == 0) { - return Time(); - } - if (ft.dwLowDateTime == std::numeric_limits::max() && - ft.dwHighDateTime == std::numeric_limits::max()) { - return Max(); - } - int64_t us = (static_cast(ft.dwLowDateTime) + - (static_cast(ft.dwHighDateTime) << 32)) / 10; - return Time(us - kTimeToEpochInMicroseconds); -} - - -FILETIME Time::ToFiletime() const { - ASSERT(us_ >= 0); - FILETIME ft; - if (IsNull()) { - ft.dwLowDateTime = 0; - ft.dwHighDateTime = 0; - return ft; - } - if (IsMax()) { - ft.dwLowDateTime = std::numeric_limits::max(); - ft.dwHighDateTime = std::numeric_limits::max(); - return ft; - } - uint64_t us = static_cast(us_ + kTimeToEpochInMicroseconds) * 10; - ft.dwLowDateTime = static_cast(us); - ft.dwHighDateTime = static_cast(us >> 32); - return ft; -} - -#elif V8_OS_POSIX - -Time Time::Now() { - struct timeval tv; - int result = gettimeofday(&tv, NULL); - ASSERT_EQ(0, result); - USE(result); - return FromTimeval(tv); -} - - -Time Time::NowFromSystemTime() { - return Now(); -} - - -Time Time::FromTimeval(struct timeval tv) { - ASSERT(tv.tv_usec >= 0); - ASSERT(tv.tv_usec < static_cast(kMicrosecondsPerSecond)); - if (tv.tv_usec == 0 && tv.tv_sec == 0) { - return Time(); - } - if (tv.tv_usec == static_cast(kMicrosecondsPerSecond - 1) && - tv.tv_sec == std::numeric_limits::max()) { - return Max(); - } - return Time(tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec); -} - - -struct timeval Time::ToTimeval() const { - struct timeval tv; - if (IsNull()) { - tv.tv_sec = 0; - tv.tv_usec = 0; - return tv; - } - if (IsMax()) { - tv.tv_sec = std::numeric_limits::max(); - tv.tv_usec = static_cast(kMicrosecondsPerSecond - 1); - return tv; - } - tv.tv_sec = us_ / kMicrosecondsPerSecond; - tv.tv_usec = us_ % kMicrosecondsPerSecond; - return tv; -} - -#endif // V8_OS_WIN - - -Time Time::FromJsTime(double ms_since_epoch) { - // The epoch is a valid time, so this constructor doesn't interpret - // 0 as the null time. - if (ms_since_epoch == std::numeric_limits::max()) { - return Max(); - } - return Time( - static_cast(ms_since_epoch * kMicrosecondsPerMillisecond)); -} - - -double Time::ToJsTime() const { - if (IsNull()) { - // Preserve 0 so the invalid result doesn't depend on the platform. - return 0; - } - if (IsMax()) { - // Preserve max without offset to prevent overflow. - return std::numeric_limits::max(); - } - return static_cast(us_) / kMicrosecondsPerMillisecond; -} - - -#if V8_OS_WIN - -class TickClock { - public: - virtual ~TickClock() {} - virtual int64_t Now() = 0; -}; - - -// Overview of time counters: -// (1) CPU cycle counter. (Retrieved via RDTSC) -// The CPU counter provides the highest resolution time stamp and is the least -// expensive to retrieve. However, the CPU counter is unreliable and should not -// be used in production. Its biggest issue is that it is per processor and it -// is not synchronized between processors. Also, on some computers, the counters -// will change frequency due to thermal and power changes, and stop in some -// states. -// -// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high- -// resolution (100 nanoseconds) time stamp but is comparatively more expensive -// to retrieve. What QueryPerformanceCounter actually does is up to the HAL. -// (with some help from ACPI). -// According to http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx -// in the worst case, it gets the counter from the rollover interrupt on the -// programmable interrupt timer. In best cases, the HAL may conclude that the -// RDTSC counter runs at a constant frequency, then it uses that instead. On -// multiprocessor machines, it will try to verify the values returned from -// RDTSC on each processor are consistent with each other, and apply a handful -// of workarounds for known buggy hardware. In other words, QPC is supposed to -// give consistent result on a multiprocessor computer, but it is unreliable in -// reality due to bugs in BIOS or HAL on some, especially old computers. -// With recent updates on HAL and newer BIOS, QPC is getting more reliable but -// it should be used with caution. -// -// (3) System time. The system time provides a low-resolution (typically 10ms -// to 55 milliseconds) time stamp but is comparatively less expensive to -// retrieve and more reliable. -class HighResolutionTickClock V8_FINAL : public TickClock { - public: - explicit HighResolutionTickClock(int64_t ticks_per_second) - : ticks_per_second_(ticks_per_second) { - ASSERT_LT(0, ticks_per_second); - } - virtual ~HighResolutionTickClock() {} - - virtual int64_t Now() V8_OVERRIDE { - LARGE_INTEGER now; - BOOL result = QueryPerformanceCounter(&now); - ASSERT(result); - USE(result); - - // Intentionally calculate microseconds in a round about manner to avoid - // overflow and precision issues. Think twice before simplifying! - int64_t whole_seconds = now.QuadPart / ticks_per_second_; - int64_t leftover_ticks = now.QuadPart % ticks_per_second_; - int64_t ticks = (whole_seconds * Time::kMicrosecondsPerSecond) + - ((leftover_ticks * Time::kMicrosecondsPerSecond) / ticks_per_second_); - - // Make sure we never return 0 here, so that TimeTicks::HighResNow() - // will never return 0. - return ticks + 1; - } - - private: - int64_t ticks_per_second_; -}; - - -class RolloverProtectedTickClock V8_FINAL : public TickClock { - public: - RolloverProtectedTickClock() - : mutex_(OS::CreateMutex()), last_seen_now_(0), rollover_ms_(1) { - // We initialize rollover_ms_ to 1 to ensure that we will never - // return 0 from TimeTicks::HighResNow() and TimeTicks::Now() below. - } - virtual ~RolloverProtectedTickClock() { delete mutex_; } - - virtual int64_t Now() V8_OVERRIDE { - ScopedLock sl(mutex_); - // We use timeGetTime() to implement TimeTicks::Now(), which rolls over - // every ~49.7 days. We try to track rollover ourselves, which works if - // TimeTicks::Now() is called at least every 49 days. - // Note that we do not use GetTickCount() here, since timeGetTime() gives - // more predictable delta values, as described here: - // http://blogs.msdn.com/b/larryosterman/archive/2009/09/02/what-s-the-difference-between-gettickcount-and-timegettime.aspx - DWORD now = timeGetTime(); - if (now < last_seen_now_) { - rollover_ms_ += V8_INT64_C(0x100000000); // ~49.7 days. - } - last_seen_now_ = now; - return now + rollover_ms_; - } - - private: - Mutex* mutex_; - DWORD last_seen_now_; - int64_t rollover_ms_; -}; - - -static LazyDynamicInstance, - ThreadSafeInitOnceTrait>::type tick_clock = - LAZY_DYNAMIC_INSTANCE_INITIALIZER; - - -struct CreateHighResTickClockTrait { - static TickClock* Create() { - // Check if the installed hardware supports a high-resolution performance - // counter, and if not fallback to the low-resolution tick clock. - LARGE_INTEGER ticks_per_second; - if (!QueryPerformanceFrequency(&ticks_per_second)) { - return tick_clock.Pointer(); - } - - // On Athlon X2 CPUs (e.g. model 15) the QueryPerformanceCounter - // is unreliable, fallback to the low-resolution tick clock. - CPU cpu; - if (strcmp(cpu.vendor(), "AuthenticAMD") == 0 && cpu.family() == 15) { - return tick_clock.Pointer(); - } - - return new HighResolutionTickClock(ticks_per_second.QuadPart); - } -}; - - -static LazyDynamicInstance::type high_res_tick_clock = - LAZY_DYNAMIC_INSTANCE_INITIALIZER; - - -TimeTicks TimeTicks::Now() { - // Make sure we never return 0 here. - TimeTicks ticks(tick_clock.Pointer()->Now()); - ASSERT(!ticks.IsNull()); - return ticks; -} - - -TimeTicks TimeTicks::HighResNow() { - // Make sure we never return 0 here. - TimeTicks ticks(high_res_tick_clock.Pointer()->Now()); - ASSERT(!ticks.IsNull()); - return ticks; -} - -#else // V8_OS_WIN - -TimeTicks TimeTicks::Now() { - return HighResNow(); -} - - -TimeTicks TimeTicks::HighResNow() { - int64_t ticks; -#if V8_OS_MACOSX - static struct mach_timebase_info info; - if (info.denom == 0) { - kern_return_t result = mach_timebase_info(&info); - ASSERT_EQ(KERN_SUCCESS, result); - USE(result); - } - ticks = (mach_absolute_time() / Time::kNanosecondsPerMicrosecond * - info.numer / info.denom); -#elif V8_OS_SOLARIS - ticks = (gethrtime() / Time::kNanosecondsPerMicrosecond); -#elif V8_OS_POSIX - struct timespec ts; - int result = clock_gettime(CLOCK_MONOTONIC, &ts); - ASSERT_EQ(0, result); - USE(result); - ticks = (ts.tv_sec * Time::kMicrosecondsPerSecond + - ts.tv_nsec / Time::kNanosecondsPerMicrosecond); -#endif // V8_OS_MACOSX - // Make sure we never return 0 here. - return TimeTicks(ticks + 1); -} - -#endif // V8_OS_WIN - -} } // namespace v8::internal diff --git a/src/platform/time.h b/src/platform/time.h deleted file mode 100644 index 57b894d814..0000000000 --- a/src/platform/time.h +++ /dev/null @@ -1,381 +0,0 @@ -// Copyright 2013 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef V8_PLATFORM_TIME_H_ -#define V8_PLATFORM_TIME_H_ - -#include -#include - -#include "allocation.h" - -// Forward declarations. -extern "C" { -struct _FILETIME; -struct timeval; -} - -namespace v8 { -namespace internal { - -class Time; -class TimeTicks; - -// ----------------------------------------------------------------------------- -// TimeDelta -// -// This class represents a duration of time, internally represented in -// microseonds. - -class TimeDelta V8_FINAL BASE_EMBEDDED { - public: - TimeDelta() : delta_(0) {} - - // Converts units of time to TimeDeltas. - static TimeDelta FromDays(int days); - static TimeDelta FromHours(int hours); - static TimeDelta FromMinutes(int minutes); - static TimeDelta FromSeconds(int64_t seconds); - static TimeDelta FromMilliseconds(int64_t milliseconds); - static TimeDelta FromMicroseconds(int64_t microseconds) { - return TimeDelta(microseconds); - } - static TimeDelta FromNanoseconds(int64_t nanoseconds); - - // Returns the time delta in some unit. The F versions return a floating - // point value, the "regular" versions return a rounded-down value. - // - // InMillisecondsRoundedUp() instead returns an integer that is rounded up - // to the next full millisecond. - int InDays() const; - int InHours() const; - int InMinutes() const; - double InSecondsF() const; - int64_t InSeconds() const; - double InMillisecondsF() const; - int64_t InMilliseconds() const; - int64_t InMillisecondsRoundedUp() const; - int64_t InMicroseconds() const { return delta_; } - int64_t InNanoseconds() const; - - TimeDelta& operator=(const TimeDelta& other) { - delta_ = other.delta_; - return *this; - } - - // Computations with other deltas. - TimeDelta operator+(const TimeDelta& other) const { - return TimeDelta(delta_ + other.delta_); - } - TimeDelta operator-(const TimeDelta& other) const { - return TimeDelta(delta_ - other.delta_); - } - - TimeDelta& operator+=(const TimeDelta& other) { - delta_ += other.delta_; - return *this; - } - TimeDelta& operator-=(const TimeDelta& other) { - delta_ -= other.delta_; - return *this; - } - TimeDelta operator-() const { - return TimeDelta(-delta_); - } - - double TimesOf(const TimeDelta& other) const { - return static_cast(delta_) / static_cast(other.delta_); - } - double PercentOf(const TimeDelta& other) const { - return TimesOf(other) * 100.0; - } - - // Computations with ints, note that we only allow multiplicative operations - // with ints, and additive operations with other deltas. - TimeDelta operator*(int64_t a) const { - return TimeDelta(delta_ * a); - } - TimeDelta operator/(int64_t a) const { - return TimeDelta(delta_ / a); - } - TimeDelta& operator*=(int64_t a) { - delta_ *= a; - return *this; - } - TimeDelta& operator/=(int64_t a) { - delta_ /= a; - return *this; - } - int64_t operator/(const TimeDelta& other) const { - return delta_ / other.delta_; - } - - // Comparison operators. - bool operator==(const TimeDelta& other) const { - return delta_ == other.delta_; - } - bool operator!=(const TimeDelta& other) const { - return delta_ != other.delta_; - } - bool operator<(const TimeDelta& other) const { - return delta_ < other.delta_; - } - bool operator<=(const TimeDelta& other) const { - return delta_ <= other.delta_; - } - bool operator>(const TimeDelta& other) const { - return delta_ > other.delta_; - } - bool operator>=(const TimeDelta& other) const { - return delta_ >= other.delta_; - } - - private: - // Constructs a delta given the duration in microseconds. This is private - // to avoid confusion by callers with an integer constructor. Use - // FromSeconds, FromMilliseconds, etc. instead. - explicit TimeDelta(int64_t delta) : delta_(delta) {} - - // Delta in microseconds. - int64_t delta_; -}; - - -// ----------------------------------------------------------------------------- -// Time -// -// This class represents an absolute point in time, internally represented as -// microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970. - -class Time V8_FINAL BASE_EMBEDDED { - public: - static const int64_t kMillisecondsPerSecond = 1000; - static const int64_t kMicrosecondsPerMillisecond = 1000; - static const int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond * - kMillisecondsPerSecond; - static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; - static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; - static const int64_t kMicrosecondsPerDay = kMicrosecondsPerHour * 24; - static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; - static const int64_t kNanosecondsPerMicrosecond = 1000; - static const int64_t kNanosecondsPerSecond = kNanosecondsPerMicrosecond * - kMicrosecondsPerSecond; - - // Contains the NULL time. Use Time::Now() to get the current time. - Time() : us_(0) {} - - // Returns true if the time object has not been initialized. - bool IsNull() const { return us_ == 0; } - - // Returns true if the time object is the maximum time. - bool IsMax() const { return us_ == std::numeric_limits::max(); } - - // Returns the current time. Watch out, the system might adjust its clock - // in which case time will actually go backwards. We don't guarantee that - // times are increasing, or that two calls to Now() won't be the same. - static Time Now(); - - // Returns the current time. Same as Now() except that this function always - // uses system time so that there are no discrepancies between the returned - // time and system time even on virtual environments including our test bot. - // For timing sensitive unittests, this function should be used. - static Time NowFromSystemTime(); - - // Returns the time for epoch in Unix-like system (Jan 1, 1970). - static Time UnixEpoch() { return Time(0); } - - // Returns the maximum time, which should be greater than any reasonable time - // with which we might compare it. - static Time Max() { return Time(std::numeric_limits::max()); } - - // Converts to/from POSIX time values. - static Time FromTimeval(struct timeval tv); - struct timeval ToTimeval() const; - - // Converts to/from Windows file times. - static Time FromFiletime(struct _FILETIME ft); - struct _FILETIME ToFiletime() const; - - // Converts to/from the Javascript convention for times, a number of - // milliseconds since the epoch: - static Time FromJsTime(double ms_since_epoch); - double ToJsTime() const; - - Time& operator=(const Time& other) { - us_ = other.us_; - return *this; - } - - // Compute the difference between two times. - TimeDelta operator-(const Time& other) const { - return TimeDelta::FromMicroseconds(us_ - other.us_); - } - - // Modify by some time delta. - Time& operator+=(const TimeDelta& delta) { - us_ += delta.InMicroseconds(); - return *this; - } - Time& operator-=(const TimeDelta& delta) { - us_ -= delta.InMicroseconds(); - return *this; - } - - // Return a new time modified by some delta. - Time operator+(const TimeDelta& delta) const { - return Time(us_ + delta.InMicroseconds()); - } - Time operator-(const TimeDelta& delta) const { - return Time(us_ - delta.InMicroseconds()); - } - - // Comparison operators - bool operator==(const Time& other) const { - return us_ == other.us_; - } - bool operator!=(const Time& other) const { - return us_ != other.us_; - } - bool operator<(const Time& other) const { - return us_ < other.us_; - } - bool operator<=(const Time& other) const { - return us_ <= other.us_; - } - bool operator>(const Time& other) const { - return us_ > other.us_; - } - bool operator>=(const Time& other) const { - return us_ >= other.us_; - } - - private: - explicit Time(int64_t us) : us_(us) {} - - // Time in microseconds in UTC. - int64_t us_; -}; - -inline Time operator+(const TimeDelta& delta, const Time& time) { - return time + delta; -} - - -// ----------------------------------------------------------------------------- -// TimeTicks -// -// This class represents an abstract time that is most of the time incrementing -// for use in measuring time durations. It is internally represented in -// microseconds. It can not be converted to a human-readable time, but is -// guaranteed not to decrease (if the user changes the computer clock, -// Time::Now() may actually decrease or jump). But note that TimeTicks may -// "stand still", for example if the computer suspended. - -class TimeTicks V8_FINAL BASE_EMBEDDED { - public: - TimeTicks() : ticks_(0) {} - - // Platform-dependent tick count representing "right now." - // The resolution of this clock is ~1-15ms. Resolution varies depending - // on hardware/operating system configuration. - // This method never returns a null TimeTicks. - static TimeTicks Now(); - - // Returns a platform-dependent high-resolution tick count. Implementation - // is hardware dependent and may or may not return sub-millisecond - // resolution. THIS CALL IS GENERALLY MUCH MORE EXPENSIVE THAN Now() AND - // SHOULD ONLY BE USED WHEN IT IS REALLY NEEDED. - // This method never returns a null TimeTicks. - static TimeTicks HighResNow(); - - // Returns true if this object has not been initialized. - bool IsNull() const { return ticks_ == 0; } - - TimeTicks& operator=(const TimeTicks other) { - ticks_ = other.ticks_; - return *this; - } - - // Compute the difference between two times. - TimeDelta operator-(const TimeTicks other) const { - return TimeDelta::FromMicroseconds(ticks_ - other.ticks_); - } - - // Modify by some time delta. - TimeTicks& operator+=(const TimeDelta& delta) { - ticks_ += delta.InMicroseconds(); - return *this; - } - TimeTicks& operator-=(const TimeDelta& delta) { - ticks_ -= delta.InMicroseconds(); - return *this; - } - - // Return a new TimeTicks modified by some delta. - TimeTicks operator+(const TimeDelta& delta) const { - return TimeTicks(ticks_ + delta.InMicroseconds()); - } - TimeTicks operator-(const TimeDelta& delta) const { - return TimeTicks(ticks_ - delta.InMicroseconds()); - } - - // Comparison operators - bool operator==(const TimeTicks& other) const { - return ticks_ == other.ticks_; - } - bool operator!=(const TimeTicks& other) const { - return ticks_ != other.ticks_; - } - bool operator<(const TimeTicks& other) const { - return ticks_ < other.ticks_; - } - bool operator<=(const TimeTicks& other) const { - return ticks_ <= other.ticks_; - } - bool operator>(const TimeTicks& other) const { - return ticks_ > other.ticks_; - } - bool operator>=(const TimeTicks& other) const { - return ticks_ >= other.ticks_; - } - - private: - // Please use Now() to create a new object. This is for internal use - // and testing. Ticks is in microseconds. - explicit TimeTicks(int64_t ticks) : ticks_(ticks) {} - - // Tick count in microseconds. - int64_t ticks_; -}; - -inline TimeTicks operator+(const TimeDelta& delta, const TimeTicks& ticks) { - return ticks + delta; -} - -} } // namespace v8::internal - -#endif // V8_PLATFORM_TIME_H_ diff --git a/src/profile-generator.cc b/src/profile-generator.cc index def0097464..b1dadc1a18 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -334,8 +334,8 @@ CpuProfile::CpuProfile(const char* title, unsigned uid, bool record_samples) : title_(title), uid_(uid), record_samples_(record_samples), - start_time_(Time::NowFromSystemTime()) { - timer_.Start(); + start_time_us_(OS::Ticks()), + end_time_us_(0) { } @@ -346,7 +346,7 @@ void CpuProfile::AddPath(const Vector& path) { void CpuProfile::CalculateTotalTicksAndSamplingRate() { - end_time_ = start_time_ + timer_.Elapsed(); + end_time_us_ = OS::Ticks(); } diff --git a/src/profile-generator.h b/src/profile-generator.h index 5edcac84b5..a282af2bd0 100644 --- a/src/profile-generator.h +++ b/src/profile-generator.h @@ -202,8 +202,8 @@ class CpuProfile { int samples_count() const { return samples_.length(); } ProfileNode* sample(int index) const { return samples_.at(index); } - Time start_time() const { return start_time_; } - Time end_time() const { return end_time_; } + int64_t start_time_us() const { return start_time_us_; } + int64_t end_time_us() const { return end_time_us_; } void UpdateTicksScale(); @@ -213,9 +213,8 @@ class CpuProfile { const char* title_; unsigned uid_; bool record_samples_; - Time start_time_; - Time end_time_; - ElapsedTimer timer_; + int64_t start_time_us_; + int64_t end_time_us_; List samples_; ProfileTree top_down_; diff --git a/src/win32-headers.h b/src/win32-headers.h index 2443685cbd..c83937c6da 100644 --- a/src/win32-headers.h +++ b/src/win32-headers.h @@ -25,9 +25,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef V8_WIN32_HEADERS_H_ -#define V8_WIN32_HEADERS_H_ - #ifndef WIN32_LEAN_AND_MEAN // WIN32_LEAN_AND_MEAN implies NOCRYPT and NOGDI. #define WIN32_LEAN_AND_MEAN @@ -58,6 +55,7 @@ #include +#ifdef V8_WIN32_HEADERS_FULL #include // For raise(). #include // For LocalOffset() implementation. #include // For timeGetTime(). @@ -83,6 +81,7 @@ #endif // __MINGW32__ #include // For _beginthreadex(). #include +#endif // V8_WIN32_HEADERS_FULL #undef VOID #undef DELETE @@ -98,5 +97,3 @@ #undef CreateMutex #undef CreateSemaphore #undef Yield - -#endif // V8_WIN32_HEADERS_H_ diff --git a/src/win32-math.cc b/src/win32-math.cc index 88fa3a684b..9ffc4ea73b 100644 --- a/src/win32-math.cc +++ b/src/win32-math.cc @@ -31,6 +31,8 @@ // (http://www.opengroup.org/onlinepubs/000095399/) #ifdef _MSC_VER +#undef V8_WIN32_LEAN_AND_MEAN +#define V8_WIN32_HEADERS_FULL #include "win32-headers.h" #include // Required for INT_MAX etc. #include // Required for DBL_MAX and on Win32 for finite() diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp index 47efae1f4c..b7e07712ae 100644 --- a/test/cctest/cctest.gyp +++ b/test/cctest/cctest.gyp @@ -100,7 +100,6 @@ 'test-strtod.cc', 'test-thread-termination.cc', 'test-threads.cc', - 'test-time.cc', 'test-types.cc', 'test-unbound-queue.cc', 'test-utils.cc', diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc index 6d66c5e92b..6d3c2ee136 100644 --- a/test/cctest/test-cpu-profiler.cc +++ b/test/cctest/test-cpu-profiler.cc @@ -44,15 +44,14 @@ using i::ProfileNode; using i::ProfilerEventsProcessor; using i::ScopedVector; using i::SmartPointer; -using i::TimeDelta; using i::Vector; TEST(StartStop) { CpuProfilesCollection profiles; ProfileGenerator generator(&profiles); - SmartPointer processor(new ProfilerEventsProcessor( - &generator, NULL, TimeDelta::FromMicroseconds(100))); + SmartPointer processor( + new ProfilerEventsProcessor(&generator, NULL, 100)); processor->Start(); processor->StopSynchronously(); } @@ -143,8 +142,8 @@ TEST(CodeEvents) { CpuProfilesCollection* profiles = new CpuProfilesCollection; profiles->StartProfiling("", 1, false); ProfileGenerator generator(profiles); - SmartPointer processor(new ProfilerEventsProcessor( - &generator, NULL, TimeDelta::FromMicroseconds(100))); + SmartPointer processor( + new ProfilerEventsProcessor(&generator, NULL, 100)); processor->Start(); CpuProfiler profiler(isolate, profiles, &generator, *processor); @@ -205,8 +204,8 @@ TEST(TickEvents) { CpuProfilesCollection* profiles = new CpuProfilesCollection; profiles->StartProfiling("", 1, false); ProfileGenerator generator(profiles); - SmartPointer processor(new ProfilerEventsProcessor( - &generator, NULL, TimeDelta::FromMicroseconds(100))); + SmartPointer processor( + new ProfilerEventsProcessor(&generator, NULL, 100)); processor->Start(); CpuProfiler profiler(isolate, profiles, &generator, *processor); @@ -274,8 +273,8 @@ TEST(Issue1398) { CpuProfilesCollection* profiles = new CpuProfilesCollection; profiles->StartProfiling("", 1, false); ProfileGenerator generator(profiles); - SmartPointer processor(new ProfilerEventsProcessor( - &generator, NULL, TimeDelta::FromMicroseconds(100))); + SmartPointer processor( + new ProfilerEventsProcessor(&generator, NULL, 100)); processor->Start(); CpuProfiler profiler(isolate, profiles, &generator, *processor); @@ -420,10 +419,13 @@ TEST(ProfileStartEndTime) { v8::HandleScope scope(env->GetIsolate()); v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); + int64_t time_before_profiling = i::OS::Ticks(); v8::Local profile_name = v8::String::New("test"); cpu_profiler->StartCpuProfiling(profile_name); const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); + CHECK(time_before_profiling <= profile->GetStartTime()); CHECK(profile->GetStartTime() <= profile->GetEndTime()); + CHECK(profile->GetEndTime() <= i::OS::Ticks()); } diff --git a/test/cctest/test-time.cc b/test/cctest/test-time.cc deleted file mode 100644 index b53ee73ce3..0000000000 --- a/test/cctest/test-time.cc +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2013 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include - -#include "v8.h" - -#include "cctest.h" -#if V8_OS_WIN -#include "win32-headers.h" -#endif - -using namespace v8::internal; - - -TEST(TimeDeltaFromAndIn) { - CHECK(TimeDelta::FromDays(2) == TimeDelta::FromHours(48)); - CHECK(TimeDelta::FromHours(3) == TimeDelta::FromMinutes(180)); - CHECK(TimeDelta::FromMinutes(2) == TimeDelta::FromSeconds(120)); - CHECK(TimeDelta::FromSeconds(2) == TimeDelta::FromMilliseconds(2000)); - CHECK(TimeDelta::FromMilliseconds(2) == TimeDelta::FromMicroseconds(2000)); - CHECK_EQ(static_cast(13), TimeDelta::FromDays(13).InDays()); - CHECK_EQ(static_cast(13), TimeDelta::FromHours(13).InHours()); - CHECK_EQ(static_cast(13), TimeDelta::FromMinutes(13).InMinutes()); - CHECK_EQ(static_cast(13), TimeDelta::FromSeconds(13).InSeconds()); - CHECK_EQ(13.0, TimeDelta::FromSeconds(13).InSecondsF()); - CHECK_EQ(static_cast(13), - TimeDelta::FromMilliseconds(13).InMilliseconds()); - CHECK_EQ(13.0, TimeDelta::FromMilliseconds(13).InMillisecondsF()); - CHECK_EQ(static_cast(13), - TimeDelta::FromMicroseconds(13).InMicroseconds()); -} - - -TEST(TimeJsTime) { - Time t = Time::FromJsTime(700000.3); - CHECK_EQ(700000.3, t.ToJsTime()); -} - - -#if V8_OS_POSIX -TEST(TimeFromTimeVal) { - Time null; - CHECK(null.IsNull()); - CHECK(null == Time::FromTimeval(null.ToTimeval())); - Time now = Time::Now(); - CHECK(now == Time::FromTimeval(now.ToTimeval())); - Time now_sys = Time::NowFromSystemTime(); - CHECK(now_sys == Time::FromTimeval(now_sys.ToTimeval())); - Time unix_epoch = Time::UnixEpoch(); - CHECK(unix_epoch == Time::FromTimeval(unix_epoch.ToTimeval())); - Time max = Time::Max(); - CHECK(max.IsMax()); - CHECK(max == Time::FromTimeval(max.ToTimeval())); -} -#endif - - -#if V8_OS_WIN -TEST(TimeFromFiletime) { - Time null; - CHECK(null.IsNull()); - CHECK(null == Time::FromFiletime(null.ToFiletime())); - Time now = Time::Now(); - CHECK(now == Time::FromFiletime(now.ToFiletime())); - Time now_sys = Time::NowFromSystemTime(); - CHECK(now_sys == Time::FromFiletime(now_sys.ToFiletime())); - Time unix_epoch = Time::UnixEpoch(); - CHECK(unix_epoch == Time::FromFiletime(unix_epoch.ToFiletime())); - Time max = Time::Max(); - CHECK(max.IsMax()); - CHECK(max == Time::FromFiletime(max.ToFiletime())); -} -#endif - - -TEST(TimeTicksIsMonotonic) { - TimeTicks previous_normal_ticks; - TimeTicks previous_highres_ticks; - ElapsedTimer timer; - timer.Start(); - while (!timer.HasExpired(TimeDelta::FromMilliseconds(100))) { - TimeTicks normal_ticks = TimeTicks::Now(); - TimeTicks highres_ticks = TimeTicks::HighResNow(); - CHECK_GE(normal_ticks, previous_normal_ticks); - CHECK_GE((normal_ticks - previous_normal_ticks).InMicroseconds(), 0); - CHECK_GE(highres_ticks, previous_highres_ticks); - CHECK_GE((highres_ticks - previous_highres_ticks).InMicroseconds(), 0); - previous_normal_ticks = normal_ticks; - previous_highres_ticks = highres_ticks; - } -} diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index 708defed9b..eefd142b70 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -436,9 +436,6 @@ '../../src/optimizing-compiler-thread.cc', '../../src/parser.cc', '../../src/parser.h', - '../../src/platform/elapsed-timer.h', - '../../src/platform/time.cc', - '../../src/platform/time.h', '../../src/platform-posix.h', '../../src/platform.h', '../../src/preparse-data-format.h', @@ -691,9 +688,6 @@ ] }], ], - 'libraries': [ - '-lrt' - ] }, 'sources': [ ### gcmole(os:linux) ### '../../src/platform-linux.cc', @@ -706,7 +700,7 @@ 'CAN_USE_VFP_INSTRUCTIONS', ], 'sources': [ - '../../src/platform-posix.cc' + '../../src/platform-posix.cc', ], 'conditions': [ ['host_os=="mac"', { @@ -722,15 +716,6 @@ }], ], }, { - 'link_settings': { - 'target_conditions': [ - ['_toolset=="host"', { - 'libraries': [ - '-lrt' - ] - }] - ] - }, 'sources': [ '../../src/platform-linux.cc' ] @@ -778,7 +763,7 @@ ]}, 'sources': [ '../../src/platform-solaris.cc', - '../../src/platform-posix.cc' + '../../src/platform-posix.cc', ], } ], @@ -801,13 +786,13 @@ ['build_env=="Cygwin"', { 'sources': [ '../../src/platform-cygwin.cc', - '../../src/platform-posix.cc' + '../../src/platform-posix.cc', ], }, { 'sources': [ '../../src/platform-win32.cc', + '../../src/win32-math.h', '../../src/win32-math.cc', - '../../src/win32-math.h' ], }], ], @@ -817,8 +802,8 @@ }, { 'sources': [ '../../src/platform-win32.cc', + '../../src/win32-math.h', '../../src/win32-math.cc', - '../../src/win32-math.h' ], 'msvs_disabled_warnings': [4351, 4355, 4800], 'link_settings': {