15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (c) 2011, Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
32197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptProfiler.h"
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/RetainedDOMInfo.h"
35197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptValue.h"
36197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/V8Binding.h"
37f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "bindings/core/v8/V8Node.h"
38f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "bindings/core/v8/V8Window.h"
39197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/WrapperTypeInfo.h"
40e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)#include "core/dom/Document.h"
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/inspector/BindingVisitors.h"
42197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "wtf/ThreadSpecific.h"
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <v8-profiler.h>
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <v8.h>
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
47c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
49926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)typedef HashMap<String, double> ProfileNameIdleTimeMap;
50926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)void ScriptProfiler::setSamplingInterval(int intervalUs)
5206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
5306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
5406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    v8::CpuProfiler* profiler = isolate->GetCpuProfiler();
5506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (profiler)
5606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        profiler->SetSamplingInterval(intervalUs);
5706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
5806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
5993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void ScriptProfiler::start(const String& title)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
61926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ProfileNameIdleTimeMap* profileNameIdleTimeMap = ScriptProfiler::currentProfileNameIdleTimeMap();
62926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (profileNameIdleTimeMap->contains(title))
63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    profileNameIdleTimeMap->add(title, 0);
65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
6693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
6753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::CpuProfiler* profiler = isolate->GetCpuProfiler();
6853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!profiler)
6953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return;
7053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::HandleScope handleScope(isolate);
7143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    profiler->StartProfiling(v8String(isolate, title), true);
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
745d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)PassRefPtrWillBeRawPtr<ScriptProfile> ScriptProfiler::stop(const String& title)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
7753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::CpuProfiler* profiler = isolate->GetCpuProfiler();
7853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!profiler)
79d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
8053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::HandleScope handleScope(isolate);
8143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    v8::CpuProfile* profile = profiler->StopProfiling(v8String(isolate, title));
82926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!profile)
83d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
8509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    String profileTitle = toCoreString(profile->GetTitle());
86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    double idleTime = 0.0;
87926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ProfileNameIdleTimeMap* profileNameIdleTimeMap = ScriptProfiler::currentProfileNameIdleTimeMap();
88926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ProfileNameIdleTimeMap::iterator profileIdleTime = profileNameIdleTimeMap->find(profileTitle);
89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (profileIdleTime != profileNameIdleTimeMap->end()) {
90926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        idleTime = profileIdleTime->value * 1000.0;
91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        profileNameIdleTimeMap->remove(profileIdleTime);
92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
94926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return ScriptProfile::create(profile, idleTime);
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScriptProfiler::collectGarbage()
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
99c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    v8::Isolate::GetCurrent()->LowMemoryNotification();
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
102d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)ScriptValue ScriptProfiler::objectByHeapObjectId(unsigned id)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
10553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::HeapProfiler* profiler = isolate->GetHeapProfiler();
10653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::HandleScope handleScope(isolate);
10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    v8::Handle<v8::Value> value = profiler->FindObjectById(id);
10809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (value.IsEmpty() || !value->IsObject())
109d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return ScriptValue();
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    v8::Handle<v8::Object> object = value.As<v8::Object>();
112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount) {
1145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex);
1155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        // Skip wrapper boilerplates which are like regular wrappers but don't have
1165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        // native object.
1175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (!wrapper.IsEmpty() && wrapper->IsUndefined())
118d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            return ScriptValue();
1195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
1205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
121f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    ScriptState* scriptState = ScriptState::from(object->CreationContext());
122d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return ScriptValue(scriptState, object);
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned ScriptProfiler::getHeapObjectId(const ScriptValue& value)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
12853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::HeapProfiler* profiler = isolate->GetHeapProfiler();
12953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::SnapshotObjectId id = profiler->GetObjectId(value.v8Value());
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return id;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ScriptProfiler::clearHeapObjectIds()
13409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
13509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
13609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    v8::HeapProfiler* profiler = isolate->GetHeapProfiler();
13709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    profiler->ClearObjectIds();
13809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
13909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace {
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class ActivityControlAdapter FINAL : public v8::ActivityControl {
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ActivityControlAdapter(ScriptProfiler::HeapSnapshotProgress* progress)
145197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        : m_progress(progress), m_firstReport(true) { }
14609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual ControlOption ReportProgressValue(int done, int total) OVERRIDE
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ControlOption result = m_progress->isCanceled() ? kAbort : kContinue;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_firstReport) {
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_firstReport = false;
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_progress->Start(total);
152197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        } else {
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_progress->Worked(done);
154197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        }
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (done >= total)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_progress->Done();
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return result;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ScriptProfiler::HeapSnapshotProgress* m_progress;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool m_firstReport;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class GlobalObjectNameResolver FINAL : public v8::HeapProfiler::ObjectNameResolver {
165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)public:
16609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual const char* GetName(v8::Handle<v8::Object> object) OVERRIDE
167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
16876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        LocalDOMWindow* window = toDOMWindow(object, v8::Isolate::GetCurrent());
16909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (!window)
17009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return 0;
17109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        CString url = window->document()->url().string().utf8();
17209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_strings.append(url);
17309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return url.data();
174926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)private:
177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Vector<CString> m_strings;
178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void ScriptProfiler::startTrackingHeapObjects(bool trackAllocations)
18353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
18409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    v8::Isolate::GetCurrent()->GetHeapProfiler()->StartTrackingHeapObjects(trackAllocations);
18553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
18653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
18753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)namespace {
18853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
18953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)class HeapStatsStream : public v8::OutputStream {
19053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)public:
19153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    HeapStatsStream(ScriptProfiler::OutputStream* stream) : m_stream(stream) { }
19253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    virtual void EndOfStream() OVERRIDE { }
19353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
19453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    virtual WriteResult WriteAsciiChunk(char* data, int size) OVERRIDE
19553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
19653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        ASSERT(false);
19753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return kAbort;
19853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
19953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
20053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    virtual WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* updateData, int count) OVERRIDE
20153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    {
20253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        Vector<uint32_t> rawData(count * 3);
20353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        for (int i = 0; i < count; ++i) {
20453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            int offset = i * 3;
20553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            rawData[offset] = updateData[i].index;
20653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            rawData[offset + 1] = updateData[i].count;
20753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            rawData[offset + 2] = updateData[i].size;
20853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        }
20953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        m_stream->write(rawData.data(), rawData.size());
21053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return kContinue;
21153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
21253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
21353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)private:
21453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ScriptProfiler::OutputStream* m_stream;
21553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)};
21653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
21753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
21853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
21953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)unsigned ScriptProfiler::requestHeapStatsUpdate(ScriptProfiler::OutputStream* stream)
22053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
22153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    HeapStatsStream heapStatsStream(stream);
22253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return v8::Isolate::GetCurrent()->GetHeapProfiler()->GetHeapStats(&heapStatsStream);
22353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
22453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
22553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void ScriptProfiler::stopTrackingHeapObjects()
22653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
22753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::Isolate::GetCurrent()->GetHeapProfiler()->StopTrackingHeapObjects();
22853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
22953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// FIXME: This method should receive a ScriptState, from which we should retrieve an Isolate.
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<ScriptHeapSnapshot> ScriptProfiler::takeHeapSnapshot(const String& title, HeapSnapshotProgress* control)
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
23353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
23453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::HeapProfiler* profiler = isolate->GetHeapProfiler();
23553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!profiler)
236d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
23753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::HandleScope handleScope(isolate);
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(control);
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ActivityControlAdapter adapter(control);
240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    GlobalObjectNameResolver resolver;
241a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(v8String(isolate, title), &adapter, &resolver);
242d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return snapshot ? ScriptHeapSnapshot::create(snapshot) : nullptr;
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static v8::RetainedObjectInfo* retainedDOMInfo(uint16_t classId, v8::Handle<v8::Value> wrapper)
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(classId == WrapperTypeInfo::NodeClassId);
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!wrapper->IsObject())
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
2507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    Node* node = V8Node::toImpl(wrapper.As<v8::Object>());
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return node ? new RetainedDOMInfo(node) : 0;
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScriptProfiler::initialize()
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
25653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
25753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::HeapProfiler* profiler = isolate->GetHeapProfiler();
25853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (profiler)
2597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        profiler->SetWrapperClassInfoProvider(WrapperTypeInfo::NodeClassId, &retainedDOMInfo);
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScriptProfiler::visitNodeWrappers(WrappedNodeVisitor* visitor)
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // visitNodeWrappers() should receive a ScriptState and retrieve an Isolate
265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // from the ScriptState.
266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
26753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    v8::HandleScope handleScope(isolate);
268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    class DOMNodeWrapperVisitor : public v8::PersistentHandleVisitor {
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public:
271926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        DOMNodeWrapperVisitor(WrappedNodeVisitor* visitor, v8::Isolate* isolate)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            : m_visitor(visitor)
273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            , m_isolate(isolate)
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2775267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        virtual void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) OVERRIDE
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
2797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            if (classId != WrapperTypeInfo::NodeClassId)
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return;
2815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            // Casting to Handle is safe here, since the Persistent cannot get
2825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            // GCd during visiting.
2835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            v8::Handle<v8::Object>* wrapper = reinterpret_cast<v8::Handle<v8::Object>*>(value);
28409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            ASSERT_UNUSED(m_isolate, V8Node::hasInstance(*wrapper, m_isolate));
2855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            ASSERT((*wrapper)->IsObject());
2867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            m_visitor->visitNode(V8Node::toImpl(*wrapper));
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private:
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WrappedNodeVisitor* m_visitor;
291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        v8::Isolate* m_isolate;
292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } wrapperVisitor(visitor, isolate);
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    v8::V8::VisitHandlesWithClassIds(&wrapperVisitor);
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ProfileNameIdleTimeMap* ScriptProfiler::currentProfileNameIdleTimeMap()
298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    AtomicallyInitializedStatic(WTF::ThreadSpecific<ProfileNameIdleTimeMap>*, map = new WTF::ThreadSpecific<ProfileNameIdleTimeMap>);
300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return *map;
301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
303e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)void ScriptProfiler::setIdle(bool isIdle)
304e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
305e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
306e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    if (v8::CpuProfiler* profiler = isolate->GetCpuProfiler())
307e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        profiler->SetIdle(isIdle);
308e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
309e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
310c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
311