Chromium Code Reviews| Index: content/renderer/memory_benchmarking_extension.cc |
| diff --git a/content/renderer/memory_benchmarking_extension.cc b/content/renderer/memory_benchmarking_extension.cc |
| index 8ed0185b58f07cd62d23dd2e556c6d3e814fce3c..0ddd7cfbf4a52c150b474e2213d872b3941b26c3 100644 |
| --- a/content/renderer/memory_benchmarking_extension.cc |
| +++ b/content/renderer/memory_benchmarking_extension.cc |
| @@ -4,6 +4,11 @@ |
| #include "content/renderer/memory_benchmarking_extension.h" |
| +#include "base/format_macros.h" |
| +#include "base/strings/stringprintf.h" |
| +#include "base/thread_task_runner_handle.h" |
| +#include "base/trace_event/memory_dump_manager.h" |
| +#include "base/trace_event/memory_dump_request_args.h" |
| #include "content/common/memory_benchmark_messages.h" |
| #include "content/renderer/chrome_object_extensions_utils.h" |
| #include "content/renderer/render_thread_impl.h" |
| @@ -12,6 +17,7 @@ |
| #include "gin/object_template_builder.h" |
| #include "third_party/WebKit/public/web/WebFrame.h" |
| #include "third_party/WebKit/public/web/WebKit.h" |
| +#include "third_party/WebKit/public/web/WebLocalFrame.h" |
| #if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID)) |
| #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" |
| @@ -19,6 +25,81 @@ |
| namespace content { |
| +namespace { |
| + |
| +class CallbackWithContext { |
| + public: |
| + CallbackWithContext(v8::Isolate* isolate, v8::Local<v8::Function> callback) |
| + : task_runner_(base::ThreadTaskRunnerHandle::Get()), isolate_(isolate) { |
| + callback_.Reset(isolate, callback); |
| + context_.Reset(isolate, isolate->GetCurrentContext()); |
| + } |
| + |
| + virtual ~CallbackWithContext() { |
| + callback_.Reset(); |
| + context_.Reset(); |
| + } |
| + |
| + base::SingleThreadTaskRunner* task_runner() { return task_runner_.get(); } |
|
Primiano Tucci (use gerrit)
2015/07/24 14:29:14
nit +const between ) and {
|
| + |
| + v8::Isolate* isolate() { return isolate_; } |
|
Primiano Tucci (use gerrit)
2015/07/24 14:29:14
ditto (here and below)
|
| + |
| + v8::Local<v8::Function> GetCallback() { |
| + return v8::Local<v8::Function>::New(isolate_, callback_); |
| + } |
| + |
| + v8::Local<v8::Context> GetContext() { |
| + return v8::Local<v8::Context>::New(isolate_, context_); |
| + } |
| + |
| + private: |
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| + v8::Isolate* isolate_; |
| + v8::Persistent<v8::Function> callback_; |
| + v8::Persistent<v8::Context> context_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(CallbackWithContext); |
| +}; |
| + |
| +void OnMemoryDumpFinishedInternal( |
| + scoped_ptr<CallbackWithContext> callback_with_context, |
| + uint64 dump_guid, |
| + bool success) { |
| + DCHECK(callback_with_context->task_runner()->BelongsToCurrentThread()); |
| + |
| + v8::Isolate* isolate = callback_with_context->isolate(); |
| + v8::HandleScope handle_scope(isolate); |
| + v8::Context::Scope context_scope(callback_with_context->GetContext()); |
| + |
| + v8::Local<v8::Function> callback = callback_with_context->GetCallback(); |
| + v8::Local<v8::Value> args[] = { |
| + gin::StringToV8(isolate, base::StringPrintf("0x%" PRIx64, dump_guid)), |
| + gin::Converter<bool>::ToV8(isolate, success)}; |
| + |
| + blink::WebLocalFrame* frame = blink::WebLocalFrame::frameForCurrentContext(); |
| + if (!frame) |
| + return; |
| + |
| + (void)frame->callFunctionEvenIfScriptDisabled( |
| + callback, v8::Object::New(isolate), 2, args); |
| +} |
| + |
| +void OnMemoryDumpFinished(scoped_ptr<CallbackWithContext> callback_with_context, |
|
Primiano Tucci (use gerrit)
2015/07/24 14:29:14
You don't need to split the function in OnMemoryDu
|
| + uint64 dump_guid, |
| + bool success) { |
| + if (!callback_with_context->task_runner()->BelongsToCurrentThread()) { |
| + callback_with_context->task_runner()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&OnMemoryDumpFinishedInternal, |
| + base::Passed(&callback_with_context), dump_guid, success)); |
| + return; |
| + } |
| + OnMemoryDumpFinishedInternal(callback_with_context.Pass(), dump_guid, |
| + success); |
| +} |
| + |
| +} // namespace |
| + |
| gin::WrapperInfo MemoryBenchmarkingExtension::kWrapperInfo = { |
| gin::kEmbedderNativeGin}; |
| @@ -53,7 +134,9 @@ MemoryBenchmarkingExtension::GetObjectTemplateBuilder(v8::Isolate* isolate) { |
| .SetMethod("isHeapProfilerRunning", |
| &MemoryBenchmarkingExtension::IsHeapProfilerRunning) |
| .SetMethod("heapProfilerDump", |
| - &MemoryBenchmarkingExtension::HeapProfilerDump); |
| + &MemoryBenchmarkingExtension::HeapProfilerDump) |
| + .SetMethod("requestMemoryDump", |
| + &MemoryBenchmarkingExtension::RequestMemoryDump); |
| } |
| bool MemoryBenchmarkingExtension::IsHeapProfilerRunning() { |
| @@ -84,4 +167,22 @@ void MemoryBenchmarkingExtension::HeapProfilerDump(gin::Arguments* args) { |
| #endif |
| } |
| +void MemoryBenchmarkingExtension::RequestMemoryDump(gin::Arguments* args) { |
| + v8::Local<v8::Function> callback; |
| + if (!args->PeekNext().IsEmpty() && args->PeekNext()->IsFunction()) |
| + args->GetNext(&callback); |
| + |
| + if (callback.IsEmpty()) { |
| + base::trace_event::MemoryDumpManager::GetInstance()->RequestGlobalDump( |
| + base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED); |
| + } else { |
| + scoped_ptr<CallbackWithContext> callback_with_context( |
| + new CallbackWithContext(args->isolate(), callback)); |
| + base::trace_event::MemoryDumpManager::GetInstance()->RequestGlobalDump( |
| + base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED, |
| + base::Bind(&OnMemoryDumpFinished, |
| + base::Passed(&callback_with_context))); |
| + } |
| +} |
| + |
| } // namespace content |