Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: src/cpu-profiler.cc

Issue 151163005: A64: Synchronize with r16356. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/cpu-profiler.h ('k') | src/cpu-profiler-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 22 matching lines...) Expand all
33 #include "frames-inl.h" 33 #include "frames-inl.h"
34 #include "hashmap.h" 34 #include "hashmap.h"
35 #include "log-inl.h" 35 #include "log-inl.h"
36 #include "vm-state-inl.h" 36 #include "vm-state-inl.h"
37 37
38 #include "../include/v8-profiler.h" 38 #include "../include/v8-profiler.h"
39 39
40 namespace v8 { 40 namespace v8 {
41 namespace internal { 41 namespace internal {
42 42
43 static const int kTickSamplesBufferChunkSize = 64 * KB;
44 static const int kTickSamplesBufferChunksCount = 16;
45 static const int kProfilerStackSize = 64 * KB; 43 static const int kProfilerStackSize = 64 * KB;
46 44
47 45
48 ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator) 46 ProfilerEventsProcessor::ProfilerEventsProcessor(
47 ProfileGenerator* generator,
48 Sampler* sampler,
49 int period_in_useconds)
49 : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)), 50 : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
50 generator_(generator), 51 generator_(generator),
52 sampler_(sampler),
51 running_(true), 53 running_(true),
52 ticks_buffer_(sizeof(TickSampleEventRecord), 54 period_in_useconds_(period_in_useconds),
53 kTickSamplesBufferChunkSize,
54 kTickSamplesBufferChunksCount),
55 last_code_event_id_(0), last_processed_code_event_id_(0) { 55 last_code_event_id_(0), last_processed_code_event_id_(0) {
56 } 56 }
57 57
58 58
59 void ProfilerEventsProcessor::Enqueue(const CodeEventsContainer& event) { 59 void ProfilerEventsProcessor::Enqueue(const CodeEventsContainer& event) {
60 event.generic.order = ++last_code_event_id_; 60 event.generic.order = ++last_code_event_id_;
61 events_buffer_.Enqueue(event); 61 events_buffer_.Enqueue(event);
62 } 62 }
63 63
64 64
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 bool ProfilerEventsProcessor::ProcessTicks() { 107 bool ProfilerEventsProcessor::ProcessTicks() {
108 while (true) { 108 while (true) {
109 while (!ticks_from_vm_buffer_.IsEmpty() 109 while (!ticks_from_vm_buffer_.IsEmpty()
110 && ticks_from_vm_buffer_.Peek()->order == 110 && ticks_from_vm_buffer_.Peek()->order ==
111 last_processed_code_event_id_) { 111 last_processed_code_event_id_) {
112 TickSampleEventRecord record; 112 TickSampleEventRecord record;
113 ticks_from_vm_buffer_.Dequeue(&record); 113 ticks_from_vm_buffer_.Dequeue(&record);
114 generator_->RecordTickSample(record.sample); 114 generator_->RecordTickSample(record.sample);
115 } 115 }
116 116
117 const TickSampleEventRecord* rec = 117 const TickSampleEventRecord* record = ticks_buffer_.StartDequeue();
118 TickSampleEventRecord::cast(ticks_buffer_.StartDequeue()); 118 if (record == NULL) return !ticks_from_vm_buffer_.IsEmpty();
119 if (rec == NULL) return !ticks_from_vm_buffer_.IsEmpty(); 119 if (record->order != last_processed_code_event_id_) return true;
120 // Make a local copy of tick sample record to ensure that it won't 120 generator_->RecordTickSample(record->sample);
121 // be modified as we are processing it. This is possible as the
122 // sampler writes w/o any sync to the queue, so if the processor
123 // will get far behind, a record may be modified right under its
124 // feet.
125 TickSampleEventRecord record = *rec;
126 if (record.order != last_processed_code_event_id_) return true;
127
128 // A paranoid check to make sure that we don't get a memory overrun
129 // in case of frames_count having a wild value.
130 if (record.sample.frames_count < 0
131 || record.sample.frames_count > TickSample::kMaxFramesCount)
132 record.sample.frames_count = 0;
133 generator_->RecordTickSample(record.sample);
134 ticks_buffer_.FinishDequeue(); 121 ticks_buffer_.FinishDequeue();
135 } 122 }
136 } 123 }
137 124
138 125
139 void ProfilerEventsProcessor::Run() { 126 void ProfilerEventsProcessor::ProcessEventsAndDoSample() {
140 while (running_) { 127 int64_t stop_time = OS::Ticks() + period_in_useconds_;
141 // Process ticks until we have any. 128 // Keep processing existing events until we need to do next sample.
129 while (OS::Ticks() < stop_time) {
142 if (ProcessTicks()) { 130 if (ProcessTicks()) {
143 // All ticks of the current last_processed_code_event_id_ are processed, 131 // All ticks of the current dequeue_order are processed,
144 // proceed to the next code event. 132 // proceed to the next code event.
145 ProcessCodeEvent(); 133 ProcessCodeEvent();
146 } 134 }
147 YieldCPU(); 135 }
136 // Schedule next sample. sampler_ is NULL in tests.
137 if (sampler_) sampler_->DoSample();
138 }
139
140
141 void ProfilerEventsProcessor::ProcessEventsAndYield() {
142 // Process ticks until we have any.
143 if (ProcessTicks()) {
144 // All ticks of the current dequeue_order are processed,
145 // proceed to the next code event.
146 ProcessCodeEvent();
147 }
148 YieldCPU();
149 }
150
151
152 void ProfilerEventsProcessor::Run() {
153 while (running_) {
154 if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
155 ProcessEventsAndDoSample();
156 } else {
157 ProcessEventsAndYield();
158 }
148 } 159 }
149 160
150 // Process remaining tick events. 161 // Process remaining tick events.
151 ticks_buffer_.FlushResidualRecords();
152 do { 162 do {
153 ProcessTicks(); 163 ProcessTicks();
154 } while (ProcessCodeEvent()); 164 } while (ProcessCodeEvent());
155 } 165 }
156 166
157 167
158 int CpuProfiler::GetProfilesCount() { 168 int CpuProfiler::GetProfilesCount() {
159 // The count of profiles doesn't depend on a security token. 169 // The count of profiles doesn't depend on a security token.
160 return profiles_->profiles()->length(); 170 return profiles_->profiles()->length();
161 } 171 }
162 172
163 173
164 CpuProfile* CpuProfiler::GetProfile(int index) { 174 CpuProfile* CpuProfiler::GetProfile(int index) {
165 return profiles_->profiles()->at(index); 175 return profiles_->profiles()->at(index);
166 } 176 }
167 177
168 178
169 TickSample* CpuProfiler::TickSampleEvent() {
170 if (is_profiling_) return processor_->TickSampleEvent();
171 return NULL;
172 }
173
174
175 void CpuProfiler::DeleteAllProfiles() { 179 void CpuProfiler::DeleteAllProfiles() {
176 if (is_profiling_) StopProcessor(); 180 if (is_profiling_) StopProcessor();
177 ResetProfiles(); 181 ResetProfiles();
178 } 182 }
179 183
180 184
181 void CpuProfiler::DeleteProfile(CpuProfile* profile) { 185 void CpuProfiler::DeleteProfile(CpuProfile* profile) {
182 profiles_->RemoveProfile(profile); 186 profiles_->RemoveProfile(profile);
183 delete profile; 187 delete profile;
184 } 188 }
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 } 425 }
422 426
423 427
424 void CpuProfiler::StartProcessorIfNotStarted() { 428 void CpuProfiler::StartProcessorIfNotStarted() {
425 if (processor_ == NULL) { 429 if (processor_ == NULL) {
426 Logger* logger = isolate_->logger(); 430 Logger* logger = isolate_->logger();
427 // Disable logging when using the new implementation. 431 // Disable logging when using the new implementation.
428 saved_logging_nesting_ = logger->logging_nesting_; 432 saved_logging_nesting_ = logger->logging_nesting_;
429 logger->logging_nesting_ = 0; 433 logger->logging_nesting_ = 0;
430 generator_ = new ProfileGenerator(profiles_); 434 generator_ = new ProfileGenerator(profiles_);
431 processor_ = new ProfilerEventsProcessor(generator_); 435 Sampler* sampler = logger->sampler();
436 processor_ = new ProfilerEventsProcessor(
437 generator_, sampler, FLAG_cpu_profiler_sampling_interval);
432 is_profiling_ = true; 438 is_profiling_ = true;
433 processor_->StartSynchronously();
434 // Enumerate stuff we already have in the heap. 439 // Enumerate stuff we already have in the heap.
435 ASSERT(isolate_->heap()->HasBeenSetUp()); 440 ASSERT(isolate_->heap()->HasBeenSetUp());
436 if (!FLAG_prof_browser_mode) { 441 if (!FLAG_prof_browser_mode) {
437 logger->LogCodeObjects(); 442 logger->LogCodeObjects();
438 } 443 }
439 logger->LogCompiledFunctions(); 444 logger->LogCompiledFunctions();
440 logger->LogAccessorCallbacks(); 445 logger->LogAccessorCallbacks();
441 LogBuiltins(); 446 LogBuiltins();
442 // Enable stack sampling. 447 // Enable stack sampling.
443 Sampler* sampler = logger->sampler(); 448 if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
449 sampler->SetHasProcessingThread(true);
450 }
444 sampler->IncreaseProfilingDepth(); 451 sampler->IncreaseProfilingDepth();
445 if (!sampler->IsActive()) { 452 if (!sampler->IsActive()) {
446 sampler->Start(); 453 sampler->Start();
447 need_to_stop_sampler_ = true; 454 need_to_stop_sampler_ = true;
448 } 455 }
456 processor_->StartSynchronously();
449 } 457 }
450 } 458 }
451 459
452 460
453 CpuProfile* CpuProfiler::StopProfiling(const char* title) { 461 CpuProfile* CpuProfiler::StopProfiling(const char* title) {
454 if (!is_profiling_) return NULL; 462 if (!is_profiling_) return NULL;
455 StopProcessorIfLastProfile(title); 463 StopProcessorIfLastProfile(title);
456 CpuProfile* result = profiles_->StopProfiling(title); 464 CpuProfile* result = profiles_->StopProfiling(title);
457 if (result != NULL) { 465 if (result != NULL) {
458 result->Print(); 466 result->Print();
(...skipping 12 matching lines...) Expand all
471 479
472 void CpuProfiler::StopProcessorIfLastProfile(const char* title) { 480 void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
473 if (profiles_->IsLastProfile(title)) StopProcessor(); 481 if (profiles_->IsLastProfile(title)) StopProcessor();
474 } 482 }
475 483
476 484
477 void CpuProfiler::StopProcessor() { 485 void CpuProfiler::StopProcessor() {
478 Logger* logger = isolate_->logger(); 486 Logger* logger = isolate_->logger();
479 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_); 487 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
480 sampler->DecreaseProfilingDepth(); 488 sampler->DecreaseProfilingDepth();
481 if (need_to_stop_sampler_) {
482 sampler->Stop();
483 need_to_stop_sampler_ = false;
484 }
485 is_profiling_ = false; 489 is_profiling_ = false;
486 processor_->StopSynchronously(); 490 processor_->StopSynchronously();
487 delete processor_; 491 delete processor_;
488 delete generator_; 492 delete generator_;
489 processor_ = NULL; 493 processor_ = NULL;
490 generator_ = NULL; 494 generator_ = NULL;
495 if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
496 sampler->SetHasProcessingThread(false);
497 }
498 if (need_to_stop_sampler_) {
499 sampler->Stop();
500 need_to_stop_sampler_ = false;
501 }
491 logger->logging_nesting_ = saved_logging_nesting_; 502 logger->logging_nesting_ = saved_logging_nesting_;
492 } 503 }
493 504
494 505
495 void CpuProfiler::LogBuiltins() { 506 void CpuProfiler::LogBuiltins() {
496 Builtins* builtins = isolate_->builtins(); 507 Builtins* builtins = isolate_->builtins();
497 ASSERT(builtins->is_initialized()); 508 ASSERT(builtins->is_initialized());
498 for (int i = 0; i < Builtins::builtin_count; i++) { 509 for (int i = 0; i < Builtins::builtin_count; i++) {
499 CodeEventsContainer evt_rec(CodeEventRecord::REPORT_BUILTIN); 510 CodeEventsContainer evt_rec(CodeEventRecord::REPORT_BUILTIN);
500 ReportBuiltinEventRecord* rec = &evt_rec.ReportBuiltinEventRecord_; 511 ReportBuiltinEventRecord* rec = &evt_rec.ReportBuiltinEventRecord_;
501 Builtins::Name id = static_cast<Builtins::Name>(i); 512 Builtins::Name id = static_cast<Builtins::Name>(i);
502 rec->start = builtins->builtin(id)->address(); 513 rec->start = builtins->builtin(id)->address();
503 rec->builtin_id = id; 514 rec->builtin_id = id;
504 processor_->Enqueue(evt_rec); 515 processor_->Enqueue(evt_rec);
505 } 516 }
506 } 517 }
507 518
508 519
509 } } // namespace v8::internal 520 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/cpu-profiler.h ('k') | src/cpu-profiler-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698