~evarlast/ubuntu/trusty/mongodb/upstart-workaround-debian-bug-718702

« back to all changes in this revision

Viewing changes to src/third_party/v8/src/cpu-profiler.cc

  • Committer: Package Import Robot
  • Author(s): James Page, James Page, Robie Basak
  • Date: 2013-05-29 17:44:42 UTC
  • mfrom: (44.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20130529174442-z0a4qmoww4y0t458
Tags: 1:2.4.3-1ubuntu1
[ James Page ]
* Merge from Debian unstable, remaining changes:
  - Enable SSL support:
    + d/control: Add libssl-dev to BD's.
    + d/rules: Enabled --ssl option.
    + d/mongodb.conf: Add example SSL configuration options.
  - d/mongodb-server.mongodb.upstart: Add upstart configuration.
  - d/rules: Don't strip binaries during scons build for Ubuntu.
  - d/control: Add armhf to target archs.
  - d/p/SConscript.client.patch: fixup install of client libraries.
  - d/p/0010-install-libs-to-usr-lib-not-usr-lib64-Closes-588557.patch:
    Install libraries to lib not lib64.
* Dropped changes:
  - d/p/arm-support.patch: Included in Debian.
  - d/p/double-alignment.patch: Included in Debian.
  - d/rules,control: Debian also builds with avaliable system libraries
    now.
* Fix FTBFS due to gcc and boost upgrades in saucy:
  - d/p/0008-ignore-unused-local-typedefs.patch: Add -Wno-unused-typedefs
    to unbreak building with g++-4.8.
  - d/p/0009-boost-1.53.patch: Fixup signed/unsigned casting issue.

[ Robie Basak ]
* d/p/0011-Use-a-signed-char-to-store-BSONType-enumerations.patch: Fixup
  build failure on ARM due to missing signed'ness of char cast.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012 the V8 project authors. All rights reserved.
 
2
// Redistribution and use in source and binary forms, with or without
 
3
// modification, are permitted provided that the following conditions are
 
4
// met:
 
5
//
 
6
//     * Redistributions of source code must retain the above copyright
 
7
//       notice, this list of conditions and the following disclaimer.
 
8
//     * Redistributions in binary form must reproduce the above
 
9
//       copyright notice, this list of conditions and the following
 
10
//       disclaimer in the documentation and/or other materials provided
 
11
//       with the distribution.
 
12
//     * Neither the name of Google Inc. nor the names of its
 
13
//       contributors may be used to endorse or promote products derived
 
14
//       from this software without specific prior written permission.
 
15
//
 
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 
 
28
#include "v8.h"
 
29
 
 
30
#include "cpu-profiler-inl.h"
 
31
 
 
32
#include "frames-inl.h"
 
33
#include "hashmap.h"
 
34
#include "log-inl.h"
 
35
#include "vm-state-inl.h"
 
36
 
 
37
#include "../include/v8-profiler.h"
 
38
 
 
39
namespace v8 {
 
40
namespace internal {
 
41
 
 
42
static const int kEventsBufferSize = 256 * KB;
 
43
static const int kTickSamplesBufferChunkSize = 64 * KB;
 
44
static const int kTickSamplesBufferChunksCount = 16;
 
45
static const int kProfilerStackSize = 64 * KB;
 
46
 
 
47
 
 
48
ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
 
49
    : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
 
50
      generator_(generator),
 
51
      running_(true),
 
52
      ticks_buffer_(sizeof(TickSampleEventRecord),
 
53
                    kTickSamplesBufferChunkSize,
 
54
                    kTickSamplesBufferChunksCount),
 
55
      enqueue_order_(0) {
 
56
}
 
57
 
 
58
 
 
59
void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
 
60
                                                  const char* prefix,
 
61
                                                  String* name,
 
62
                                                  Address start) {
 
63
  if (FilterOutCodeCreateEvent(tag)) return;
 
64
  CodeEventsContainer evt_rec;
 
65
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
 
66
  rec->type = CodeEventRecord::CODE_CREATION;
 
67
  rec->order = ++enqueue_order_;
 
68
  rec->start = start;
 
69
  rec->entry = generator_->NewCodeEntry(tag, prefix, name);
 
70
  rec->size = 1;
 
71
  rec->shared = NULL;
 
72
  events_buffer_.Enqueue(evt_rec);
 
73
}
 
74
 
 
75
 
 
76
void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
 
77
                                              String* name,
 
78
                                              String* resource_name,
 
79
                                              int line_number,
 
80
                                              Address start,
 
81
                                              unsigned size,
 
82
                                              Address shared) {
 
83
  if (FilterOutCodeCreateEvent(tag)) return;
 
84
  CodeEventsContainer evt_rec;
 
85
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
 
86
  rec->type = CodeEventRecord::CODE_CREATION;
 
87
  rec->order = ++enqueue_order_;
 
88
  rec->start = start;
 
89
  rec->entry = generator_->NewCodeEntry(tag, name, resource_name, line_number);
 
90
  rec->size = size;
 
91
  rec->shared = shared;
 
92
  events_buffer_.Enqueue(evt_rec);
 
93
}
 
94
 
 
95
 
 
96
void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
 
97
                                              const char* name,
 
98
                                              Address start,
 
99
                                              unsigned size) {
 
100
  if (FilterOutCodeCreateEvent(tag)) return;
 
101
  CodeEventsContainer evt_rec;
 
102
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
 
103
  rec->type = CodeEventRecord::CODE_CREATION;
 
104
  rec->order = ++enqueue_order_;
 
105
  rec->start = start;
 
106
  rec->entry = generator_->NewCodeEntry(tag, name);
 
107
  rec->size = size;
 
108
  rec->shared = NULL;
 
109
  events_buffer_.Enqueue(evt_rec);
 
110
}
 
111
 
 
112
 
 
113
void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
 
114
                                              int args_count,
 
115
                                              Address start,
 
116
                                              unsigned size) {
 
117
  if (FilterOutCodeCreateEvent(tag)) return;
 
118
  CodeEventsContainer evt_rec;
 
119
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
 
120
  rec->type = CodeEventRecord::CODE_CREATION;
 
121
  rec->order = ++enqueue_order_;
 
122
  rec->start = start;
 
123
  rec->entry = generator_->NewCodeEntry(tag, args_count);
 
124
  rec->size = size;
 
125
  rec->shared = NULL;
 
126
  events_buffer_.Enqueue(evt_rec);
 
127
}
 
128
 
 
129
 
 
130
void ProfilerEventsProcessor::CodeMoveEvent(Address from, Address to) {
 
131
  CodeEventsContainer evt_rec;
 
132
  CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
 
133
  rec->type = CodeEventRecord::CODE_MOVE;
 
134
  rec->order = ++enqueue_order_;
 
135
  rec->from = from;
 
136
  rec->to = to;
 
137
  events_buffer_.Enqueue(evt_rec);
 
138
}
 
139
 
 
140
 
 
141
void ProfilerEventsProcessor::SharedFunctionInfoMoveEvent(Address from,
 
142
                                                          Address to) {
 
143
  CodeEventsContainer evt_rec;
 
144
  SharedFunctionInfoMoveEventRecord* rec =
 
145
      &evt_rec.SharedFunctionInfoMoveEventRecord_;
 
146
  rec->type = CodeEventRecord::SHARED_FUNC_MOVE;
 
147
  rec->order = ++enqueue_order_;
 
148
  rec->from = from;
 
149
  rec->to = to;
 
150
  events_buffer_.Enqueue(evt_rec);
 
151
}
 
152
 
 
153
 
 
154
void ProfilerEventsProcessor::RegExpCodeCreateEvent(
 
155
    Logger::LogEventsAndTags tag,
 
156
    const char* prefix,
 
157
    String* name,
 
158
    Address start,
 
159
    unsigned size) {
 
160
  if (FilterOutCodeCreateEvent(tag)) return;
 
161
  CodeEventsContainer evt_rec;
 
162
  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
 
163
  rec->type = CodeEventRecord::CODE_CREATION;
 
164
  rec->order = ++enqueue_order_;
 
165
  rec->start = start;
 
166
  rec->entry = generator_->NewCodeEntry(tag, prefix, name);
 
167
  rec->size = size;
 
168
  events_buffer_.Enqueue(evt_rec);
 
169
}
 
170
 
 
171
 
 
172
void ProfilerEventsProcessor::AddCurrentStack() {
 
173
  TickSampleEventRecord record(enqueue_order_);
 
174
  TickSample* sample = &record.sample;
 
175
  Isolate* isolate = Isolate::Current();
 
176
  sample->state = isolate->current_vm_state();
 
177
  sample->pc = reinterpret_cast<Address>(sample);  // Not NULL.
 
178
  for (StackTraceFrameIterator it(isolate);
 
179
       !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
 
180
       it.Advance()) {
 
181
    sample->stack[sample->frames_count++] = it.frame()->pc();
 
182
  }
 
183
  ticks_from_vm_buffer_.Enqueue(record);
 
184
}
 
185
 
 
186
 
 
187
bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
 
188
  if (!events_buffer_.IsEmpty()) {
 
189
    CodeEventsContainer record;
 
190
    events_buffer_.Dequeue(&record);
 
191
    switch (record.generic.type) {
 
192
#define PROFILER_TYPE_CASE(type, clss)                          \
 
193
      case CodeEventRecord::type:                               \
 
194
        record.clss##_.UpdateCodeMap(generator_->code_map());   \
 
195
        break;
 
196
 
 
197
      CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
 
198
 
 
199
#undef PROFILER_TYPE_CASE
 
200
      default: return true;  // Skip record.
 
201
    }
 
202
    *dequeue_order = record.generic.order;
 
203
    return true;
 
204
  }
 
205
  return false;
 
206
}
 
207
 
 
208
 
 
209
bool ProfilerEventsProcessor::ProcessTicks(unsigned dequeue_order) {
 
210
  while (true) {
 
211
    if (!ticks_from_vm_buffer_.IsEmpty()
 
212
        && ticks_from_vm_buffer_.Peek()->order == dequeue_order) {
 
213
      TickSampleEventRecord record;
 
214
      ticks_from_vm_buffer_.Dequeue(&record);
 
215
      generator_->RecordTickSample(record.sample);
 
216
    }
 
217
 
 
218
    const TickSampleEventRecord* rec =
 
219
        TickSampleEventRecord::cast(ticks_buffer_.StartDequeue());
 
220
    if (rec == NULL) return !ticks_from_vm_buffer_.IsEmpty();
 
221
    // Make a local copy of tick sample record to ensure that it won't
 
222
    // be modified as we are processing it. This is possible as the
 
223
    // sampler writes w/o any sync to the queue, so if the processor
 
224
    // will get far behind, a record may be modified right under its
 
225
    // feet.
 
226
    TickSampleEventRecord record = *rec;
 
227
    if (record.order == dequeue_order) {
 
228
      // A paranoid check to make sure that we don't get a memory overrun
 
229
      // in case of frames_count having a wild value.
 
230
      if (record.sample.frames_count < 0
 
231
          || record.sample.frames_count > TickSample::kMaxFramesCount)
 
232
        record.sample.frames_count = 0;
 
233
      generator_->RecordTickSample(record.sample);
 
234
      ticks_buffer_.FinishDequeue();
 
235
    } else {
 
236
      return true;
 
237
    }
 
238
  }
 
239
}
 
240
 
 
241
 
 
242
void ProfilerEventsProcessor::Run() {
 
243
  unsigned dequeue_order = 0;
 
244
 
 
245
  while (running_) {
 
246
    // Process ticks until we have any.
 
247
    if (ProcessTicks(dequeue_order)) {
 
248
      // All ticks of the current dequeue_order are processed,
 
249
      // proceed to the next code event.
 
250
      ProcessCodeEvent(&dequeue_order);
 
251
    }
 
252
    YieldCPU();
 
253
  }
 
254
 
 
255
  // Process remaining tick events.
 
256
  ticks_buffer_.FlushResidualRecords();
 
257
  // Perform processing until we have tick events, skip remaining code events.
 
258
  while (ProcessTicks(dequeue_order) && ProcessCodeEvent(&dequeue_order)) { }
 
259
}
 
260
 
 
261
 
 
262
void CpuProfiler::StartProfiling(const char* title) {
 
263
  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
 
264
  Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
 
265
}
 
266
 
 
267
 
 
268
void CpuProfiler::StartProfiling(String* title) {
 
269
  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
 
270
  Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
 
271
}
 
272
 
 
273
 
 
274
CpuProfile* CpuProfiler::StopProfiling(const char* title) {
 
275
  Isolate* isolate = Isolate::Current();
 
276
  return is_profiling(isolate) ?
 
277
      isolate->cpu_profiler()->StopCollectingProfile(title) : NULL;
 
278
}
 
279
 
 
280
 
 
281
CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
 
282
  Isolate* isolate = Isolate::Current();
 
283
  return is_profiling(isolate) ?
 
284
      isolate->cpu_profiler()->StopCollectingProfile(
 
285
          security_token, title) : NULL;
 
286
}
 
287
 
 
288
 
 
289
int CpuProfiler::GetProfilesCount() {
 
290
  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
 
291
  // The count of profiles doesn't depend on a security token.
 
292
  return Isolate::Current()->cpu_profiler()->profiles_->Profiles(
 
293
      TokenEnumerator::kNoSecurityToken)->length();
 
294
}
 
295
 
 
296
 
 
297
CpuProfile* CpuProfiler::GetProfile(Object* security_token, int index) {
 
298
  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
 
299
  CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
 
300
  const int token = profiler->token_enumerator_->GetTokenId(security_token);
 
301
  return profiler->profiles_->Profiles(token)->at(index);
 
302
}
 
303
 
 
304
 
 
305
CpuProfile* CpuProfiler::FindProfile(Object* security_token, unsigned uid) {
 
306
  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
 
307
  CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
 
308
  const int token = profiler->token_enumerator_->GetTokenId(security_token);
 
309
  return profiler->profiles_->GetProfile(token, uid);
 
310
}
 
311
 
 
312
 
 
313
TickSample* CpuProfiler::TickSampleEvent(Isolate* isolate) {
 
314
  if (CpuProfiler::is_profiling(isolate)) {
 
315
    return isolate->cpu_profiler()->processor_->TickSampleEvent();
 
316
  } else {
 
317
    return NULL;
 
318
  }
 
319
}
 
320
 
 
321
 
 
322
void CpuProfiler::DeleteAllProfiles() {
 
323
  Isolate* isolate = Isolate::Current();
 
324
  ASSERT(isolate->cpu_profiler() != NULL);
 
325
  if (is_profiling(isolate)) {
 
326
    isolate->cpu_profiler()->StopProcessor();
 
327
  }
 
328
  isolate->cpu_profiler()->ResetProfiles();
 
329
}
 
330
 
 
331
 
 
332
void CpuProfiler::DeleteProfile(CpuProfile* profile) {
 
333
  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
 
334
  Isolate::Current()->cpu_profiler()->profiles_->RemoveProfile(profile);
 
335
  delete profile;
 
336
}
 
337
 
 
338
 
 
339
bool CpuProfiler::HasDetachedProfiles() {
 
340
  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
 
341
  return Isolate::Current()->cpu_profiler()->profiles_->HasDetachedProfiles();
 
342
}
 
343
 
 
344
 
 
345
void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
 
346
  Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
 
347
      Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
 
348
}
 
349
 
 
350
 
 
351
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
 
352
                           Code* code, const char* comment) {
 
353
  Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
 
354
      tag, comment, code->address(), code->ExecutableSize());
 
355
}
 
356
 
 
357
 
 
358
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
 
359
                           Code* code, String* name) {
 
360
  Isolate* isolate = Isolate::Current();
 
361
  isolate->cpu_profiler()->processor_->CodeCreateEvent(
 
362
      tag,
 
363
      name,
 
364
      isolate->heap()->empty_string(),
 
365
      v8::CpuProfileNode::kNoLineNumberInfo,
 
366
      code->address(),
 
367
      code->ExecutableSize(),
 
368
      NULL);
 
369
}
 
370
 
 
371
 
 
372
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
 
373
                                  Code* code,
 
374
                                  SharedFunctionInfo* shared,
 
375
                                  String* name) {
 
376
  Isolate* isolate = Isolate::Current();
 
377
  isolate->cpu_profiler()->processor_->CodeCreateEvent(
 
378
      tag,
 
379
      name,
 
380
      isolate->heap()->empty_string(),
 
381
      v8::CpuProfileNode::kNoLineNumberInfo,
 
382
      code->address(),
 
383
      code->ExecutableSize(),
 
384
      shared->address());
 
385
}
 
386
 
 
387
 
 
388
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
 
389
                                  Code* code,
 
390
                                  SharedFunctionInfo* shared,
 
391
                                  String* source, int line) {
 
392
  Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
 
393
      tag,
 
394
      shared->DebugName(),
 
395
      source,
 
396
      line,
 
397
      code->address(),
 
398
      code->ExecutableSize(),
 
399
      shared->address());
 
400
}
 
401
 
 
402
 
 
403
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
 
404
                           Code* code, int args_count) {
 
405
  Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
 
406
      tag,
 
407
      args_count,
 
408
      code->address(),
 
409
      code->ExecutableSize());
 
410
}
 
411
 
 
412
 
 
413
void CpuProfiler::CodeMoveEvent(Address from, Address to) {
 
414
  Isolate::Current()->cpu_profiler()->processor_->CodeMoveEvent(from, to);
 
415
}
 
416
 
 
417
 
 
418
void CpuProfiler::CodeDeleteEvent(Address from) {
 
419
}
 
420
 
 
421
 
 
422
void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
 
423
  CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
 
424
  profiler->processor_->SharedFunctionInfoMoveEvent(from, to);
 
425
}
 
426
 
 
427
 
 
428
void CpuProfiler::GetterCallbackEvent(String* name, Address entry_point) {
 
429
  Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
 
430
      Logger::CALLBACK_TAG, "get ", name, entry_point);
 
431
}
 
432
 
 
433
 
 
434
void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
 
435
  Isolate::Current()->cpu_profiler()->processor_->RegExpCodeCreateEvent(
 
436
      Logger::REG_EXP_TAG,
 
437
      "RegExp: ",
 
438
      source,
 
439
      code->address(),
 
440
      code->ExecutableSize());
 
441
}
 
442
 
 
443
 
 
444
void CpuProfiler::SetterCallbackEvent(String* name, Address entry_point) {
 
445
  Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
 
446
      Logger::CALLBACK_TAG, "set ", name, entry_point);
 
447
}
 
448
 
 
449
 
 
450
CpuProfiler::CpuProfiler()
 
451
    : profiles_(new CpuProfilesCollection()),
 
452
      next_profile_uid_(1),
 
453
      token_enumerator_(new TokenEnumerator()),
 
454
      generator_(NULL),
 
455
      processor_(NULL),
 
456
      need_to_stop_sampler_(false),
 
457
      is_profiling_(false) {
 
458
}
 
459
 
 
460
 
 
461
CpuProfiler::~CpuProfiler() {
 
462
  delete token_enumerator_;
 
463
  delete profiles_;
 
464
}
 
465
 
 
466
 
 
467
void CpuProfiler::ResetProfiles() {
 
468
  delete profiles_;
 
469
  profiles_ = new CpuProfilesCollection();
 
470
}
 
471
 
 
472
void CpuProfiler::StartCollectingProfile(const char* title) {
 
473
  if (profiles_->StartProfiling(title, next_profile_uid_++)) {
 
474
    StartProcessorIfNotStarted();
 
475
  }
 
476
  processor_->AddCurrentStack();
 
477
}
 
478
 
 
479
 
 
480
void CpuProfiler::StartCollectingProfile(String* title) {
 
481
  StartCollectingProfile(profiles_->GetName(title));
 
482
}
 
483
 
 
484
 
 
485
void CpuProfiler::StartProcessorIfNotStarted() {
 
486
  if (processor_ == NULL) {
 
487
    Isolate* isolate = Isolate::Current();
 
488
 
 
489
    // Disable logging when using the new implementation.
 
490
    saved_logging_nesting_ = isolate->logger()->logging_nesting_;
 
491
    isolate->logger()->logging_nesting_ = 0;
 
492
    generator_ = new ProfileGenerator(profiles_);
 
493
    processor_ = new ProfilerEventsProcessor(generator_);
 
494
    NoBarrier_Store(&is_profiling_, true);
 
495
    processor_->Start();
 
496
    // Enumerate stuff we already have in the heap.
 
497
    if (isolate->heap()->HasBeenSetUp()) {
 
498
      if (!FLAG_prof_browser_mode) {
 
499
        bool saved_log_code_flag = FLAG_log_code;
 
500
        FLAG_log_code = true;
 
501
        isolate->logger()->LogCodeObjects();
 
502
        FLAG_log_code = saved_log_code_flag;
 
503
      }
 
504
      isolate->logger()->LogCompiledFunctions();
 
505
      isolate->logger()->LogAccessorCallbacks();
 
506
    }
 
507
    // Enable stack sampling.
 
508
    Sampler* sampler = reinterpret_cast<Sampler*>(isolate->logger()->ticker_);
 
509
    if (!sampler->IsActive()) {
 
510
      sampler->Start();
 
511
      need_to_stop_sampler_ = true;
 
512
    }
 
513
    sampler->IncreaseProfilingDepth();
 
514
  }
 
515
}
 
516
 
 
517
 
 
518
CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) {
 
519
  const double actual_sampling_rate = generator_->actual_sampling_rate();
 
520
  StopProcessorIfLastProfile(title);
 
521
  CpuProfile* result =
 
522
      profiles_->StopProfiling(TokenEnumerator::kNoSecurityToken,
 
523
                               title,
 
524
                               actual_sampling_rate);
 
525
  if (result != NULL) {
 
526
    result->Print();
 
527
  }
 
528
  return result;
 
529
}
 
530
 
 
531
 
 
532
CpuProfile* CpuProfiler::StopCollectingProfile(Object* security_token,
 
533
                                               String* title) {
 
534
  const double actual_sampling_rate = generator_->actual_sampling_rate();
 
535
  const char* profile_title = profiles_->GetName(title);
 
536
  StopProcessorIfLastProfile(profile_title);
 
537
  int token = token_enumerator_->GetTokenId(security_token);
 
538
  return profiles_->StopProfiling(token, profile_title, actual_sampling_rate);
 
539
}
 
540
 
 
541
 
 
542
void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
 
543
  if (profiles_->IsLastProfile(title)) StopProcessor();
 
544
}
 
545
 
 
546
 
 
547
void CpuProfiler::StopProcessor() {
 
548
  Logger* logger = Isolate::Current()->logger();
 
549
  Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
 
550
  sampler->DecreaseProfilingDepth();
 
551
  if (need_to_stop_sampler_) {
 
552
    sampler->Stop();
 
553
    need_to_stop_sampler_ = false;
 
554
  }
 
555
  NoBarrier_Store(&is_profiling_, false);
 
556
  processor_->Stop();
 
557
  processor_->Join();
 
558
  delete processor_;
 
559
  delete generator_;
 
560
  processor_ = NULL;
 
561
  generator_ = NULL;
 
562
  logger->logging_nesting_ = saved_logging_nesting_;
 
563
}
 
564
 
 
565
 
 
566
void CpuProfiler::SetUp() {
 
567
  Isolate* isolate = Isolate::Current();
 
568
  if (isolate->cpu_profiler() == NULL) {
 
569
    isolate->set_cpu_profiler(new CpuProfiler());
 
570
  }
 
571
}
 
572
 
 
573
 
 
574
void CpuProfiler::TearDown() {
 
575
  Isolate* isolate = Isolate::Current();
 
576
  if (isolate->cpu_profiler() != NULL) {
 
577
    delete isolate->cpu_profiler();
 
578
  }
 
579
  isolate->set_cpu_profiler(NULL);
 
580
}
 
581
 
 
582
} }  // namespace v8::internal