Bug 877658 - Exactly root tools/profiler/; r=BenWa

--HG--
extra : rebase_source : a7c5bbcb64d7b670e170e3c20dda53d03a4f2cc1
This commit is contained in:
Terrence Cole 2013-09-05 16:10:37 -07:00
parent 79d748a476
commit 193cf598ae
9 changed files with 103 additions and 121 deletions

View File

@ -1,30 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef JSAOBJECTBUILDER_H
#define JSAOBJECTBUILDER_H
class JSCustomObject;
class JSCustomArray;
class nsAString;
class JSAObjectBuilder
{
public:
virtual ~JSAObjectBuilder() = 0;
virtual void DefineProperty(JSCustomObject *aObject, const char *name, JSCustomObject *aValue) = 0;
virtual void DefineProperty(JSCustomObject *aObject, const char *name, JSCustomArray *aValue) = 0;
virtual void DefineProperty(JSCustomObject *aObject, const char *name, int value) = 0;
virtual void DefineProperty(JSCustomObject *aObject, const char *name, double value) = 0;
virtual void DefineProperty(JSCustomObject *aObject, const char *name, const char *value) = 0;
virtual void ArrayPush(JSCustomArray *aArray, int value) = 0;
virtual void ArrayPush(JSCustomArray *aArray, const char *value) = 0;
virtual void ArrayPush(JSCustomArray *aArray, JSCustomObject *aObject) = 0;
virtual JSCustomArray *CreateArray() = 0;
virtual JSCustomObject *CreateObject() = 0;
};
#endif

View File

@ -231,10 +231,6 @@ JSCustomObject::~JSCustomObject()
mProperties.EnumerateRead(HashTableFree, nullptr);
}
JSAObjectBuilder::~JSAObjectBuilder()
{
}
JSCustomObjectBuilder::JSCustomObjectBuilder()
{}

View File

@ -8,15 +8,20 @@
#include <ostream>
#include <stdlib.h>
#include "JSAObjectBuilder.h"
#include "js/RootingAPI.h"
class JSCustomObject;
class JSCustomArray;
class JSCustomObjectBuilder;
class JSCustomObjectBuilder : public JSAObjectBuilder
class JSCustomObjectBuilder
{
public:
typedef JSCustomObject* Object;
typedef JSCustomArray* Array;
typedef JSCustomObject* ObjectHandle;
typedef JSCustomArray* ArrayHandle;
typedef js::FakeRooted<JSCustomObject*> RootedObject;
typedef js::FakeRooted<JSCustomArray*> RootedArray;
// We need to ensure that this object lives on the stack so that GC sees it properly
JSCustomObjectBuilder();
@ -38,6 +43,8 @@ public:
// Delete this object and all of its descendant
void DeleteObject(JSCustomObject* aObject);
JSContext *context() const { return nullptr; }
private:
// This class can't be copied
JSCustomObjectBuilder(const JSCustomObjectBuilder&);

View File

@ -11,40 +11,34 @@ JSObjectBuilder::JSObjectBuilder(JSContext *aCx) : mCx(aCx), mOk(true)
{}
void
JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, JSCustomArray *aValue)
{
DefineProperty(aObject, name, (JSCustomObject*)aValue);
}
void
JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, JSCustomObject *aValue)
JSObjectBuilder::DefineProperty(JS::HandleObject aObject, const char *name, JS::HandleObject aValue)
{
if (!mOk)
return;
mOk = JS_DefineProperty(mCx, (JSObject*)aObject, name, OBJECT_TO_JSVAL((JSObject*)aValue), nullptr, nullptr, JSPROP_ENUMERATE);
mOk = JS_DefineProperty(mCx, aObject, name, OBJECT_TO_JSVAL(aValue), nullptr, nullptr, JSPROP_ENUMERATE);
}
void
JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, int value)
JSObjectBuilder::DefineProperty(JS::HandleObject aObject, const char *name, int value)
{
if (!mOk)
return;
mOk = JS_DefineProperty(mCx, (JSObject*)aObject, name, INT_TO_JSVAL(value), nullptr, nullptr, JSPROP_ENUMERATE);
mOk = JS_DefineProperty(mCx, aObject, name, INT_TO_JSVAL(value), nullptr, nullptr, JSPROP_ENUMERATE);
}
void
JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, double value)
JSObjectBuilder::DefineProperty(JS::HandleObject aObject, const char *name, double value)
{
if (!mOk)
return;
mOk = JS_DefineProperty(mCx, (JSObject*)aObject, name, DOUBLE_TO_JSVAL(value), nullptr, nullptr, JSPROP_ENUMERATE);
mOk = JS_DefineProperty(mCx, aObject, name, DOUBLE_TO_JSVAL(value), nullptr, nullptr, JSPROP_ENUMERATE);
}
void
JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, nsAString &value)
JSObjectBuilder::DefineProperty(JS::HandleObject aObject, const char *name, nsAString &value)
{
if (!mOk)
return;
@ -57,11 +51,11 @@ JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, nsASt
if (!mOk)
return;
mOk = JS_DefineProperty(mCx, (JSObject*)aObject, name, STRING_TO_JSVAL(string), nullptr, nullptr, JSPROP_ENUMERATE);
mOk = JS_DefineProperty(mCx, aObject, name, STRING_TO_JSVAL(string), nullptr, nullptr, JSPROP_ENUMERATE);
}
void
JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, const char *value, size_t valueLength)
JSObjectBuilder::DefineProperty(JS::HandleObject aObject, const char *name, const char *value, size_t valueLength)
{
if (!mOk)
return;
@ -75,13 +69,13 @@ JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, const
mOk = JS_DefineProperty(mCx, (JSObject*)aObject, name, STRING_TO_JSVAL(string), nullptr, nullptr, JSPROP_ENUMERATE); }
void
JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, const char *value)
JSObjectBuilder::DefineProperty(JS::HandleObject aObject, const char *name, const char *value)
{
DefineProperty(aObject, name, value, strlen(value));
}
void
JSObjectBuilder::ArrayPush(JSCustomArray *aArray, int value)
JSObjectBuilder::ArrayPush(JS::HandleObject aArray, int value)
{
if (!mOk)
return;
@ -92,12 +86,12 @@ JSObjectBuilder::ArrayPush(JSCustomArray *aArray, int value)
if (!mOk)
return;
JS::Rooted<JS::Value> objval(mCx, INT_TO_JSVAL(value));
mOk = JS_SetElement(mCx, (JSObject*)aArray, length, &objval);
JS::RootedValue objval(mCx, INT_TO_JSVAL(value));
mOk = JS_SetElement(mCx, aArray, length, &objval);
}
void
JSObjectBuilder::ArrayPush(JSCustomArray *aArray, const char *value)
JSObjectBuilder::ArrayPush(JS::HandleObject aArray, const char *value)
{
if (!mOk)
return;
@ -114,38 +108,38 @@ JSObjectBuilder::ArrayPush(JSCustomArray *aArray, const char *value)
if (!mOk)
return;
JS::Rooted<JS::Value> objval(mCx, STRING_TO_JSVAL(string));
mOk = JS_SetElement(mCx, (JSObject*)aArray, length, &objval);
JS::RootedValue objval(mCx, STRING_TO_JSVAL(string));
mOk = JS_SetElement(mCx, aArray, length, &objval);
}
void
JSObjectBuilder::ArrayPush(JSCustomArray *aArray, JSCustomObject *aObject)
JSObjectBuilder::ArrayPush(JS::HandleObject aArray, JS::HandleObject aObject)
{
if (!mOk)
return;
uint32_t length;
mOk = JS_GetArrayLength(mCx, (JSObject*)aArray, &length);
mOk = JS_GetArrayLength(mCx, aArray, &length);
if (!mOk)
return;
JS::Rooted<JS::Value> objval(mCx, OBJECT_TO_JSVAL((JSObject*)aObject));
mOk = JS_SetElement(mCx, (JSObject*)aArray, length, &objval);
JS::RootedValue objval(mCx, OBJECT_TO_JSVAL(aObject));
mOk = JS_SetElement(mCx, aArray, length, &objval);
}
JSCustomArray*
JSObject*
JSObjectBuilder::CreateArray() {
JSCustomArray *array = (JSCustomArray*)JS_NewArrayObject(mCx, 0, nullptr);
JSObject *array = JS_NewArrayObject(mCx, 0, nullptr);
if (!array)
mOk = false;
return array;
}
JSCustomObject*
JSObject*
JSObjectBuilder::CreateObject() {
JSCustomObject *obj = (JSCustomObject*)JS_NewObject(mCx, nullptr, nullptr, nullptr);
JSObject *obj = JS_NewObject(mCx, nullptr, nullptr, nullptr);
if (!obj)
mOk = false;

View File

@ -6,37 +6,43 @@
#ifndef JSOBJECTBUILDER_H
#define JSOBJECTBUILDER_H
#include "JSAObjectBuilder.h"
#include "js/TypeDecls.h"
#include "js/RootingAPI.h"
class JSCustomArray;
class JSCustomObject;
class JSCustomObjectBuilder;
class nsAString;
/* this is handy wrapper around JSAPI to make it more pleasant to use.
* We collect the JSAPI errors and so that callers don't need to */
class JSObjectBuilder : public JSAObjectBuilder
class JSObjectBuilder
{
public:
typedef JS::Handle<JSObject*> ObjectHandle;
typedef JS::Handle<JSObject*> ArrayHandle;
typedef JS::Rooted<JSObject*> RootedObject;
typedef JS::Rooted<JSObject*> RootedArray;
typedef JSObject* Object;
typedef JSObject* Array;
// We need to ensure that this object lives on the stack so that GC sees it properly
explicit JSObjectBuilder(JSContext *aCx);
~JSObjectBuilder() {}
void DefineProperty(JSCustomObject *aObject, const char *name, JSCustomObject *aValue);
void DefineProperty(JSCustomObject *aObject, const char *name, JSCustomArray *aValue);
void DefineProperty(JSCustomObject *aObject, const char *name, int value);
void DefineProperty(JSCustomObject *aObject, const char *name, double value);
void DefineProperty(JSCustomObject *aObject, const char *name, nsAString &value);
void DefineProperty(JSCustomObject *aObject, const char *name, const char *value, size_t valueLength);
void DefineProperty(JSCustomObject *aObject, const char *name, const char *value);
void ArrayPush(JSCustomArray *aArray, int value);
void ArrayPush(JSCustomArray *aArray, const char *value);
void ArrayPush(JSCustomArray *aArray, JSCustomArray *aObject);
void ArrayPush(JSCustomArray *aArray, JSCustomObject *aObject);
JSCustomArray *CreateArray();
JSCustomObject *CreateObject();
void DefineProperty(JS::HandleObject aObject, const char *name, JS::HandleObject aValue);
void DefineProperty(JS::HandleObject aObject, const char *name, int value);
void DefineProperty(JS::HandleObject aObject, const char *name, double value);
void DefineProperty(JS::HandleObject aObject, const char *name, nsAString &value);
void DefineProperty(JS::HandleObject aObject, const char *name, const char *value, size_t valueLength);
void DefineProperty(JS::HandleObject aObject, const char *name, const char *value);
void ArrayPush(JS::HandleObject aArray, int value);
void ArrayPush(JS::HandleObject aArray, const char *value);
void ArrayPush(JS::HandleObject aArray, JS::HandleObject aObject);
JSObject *CreateArray();
JSObject *CreateObject();
JSObject* GetJSObject(JSCustomObject* aObject) { return (JSObject*)aObject; }
JSContext *context() const { return mCx; }
private:
JSObjectBuilder(const JSObjectBuilder&);

View File

@ -299,16 +299,16 @@ void ThreadProfile::ToStreamAsJSON(std::ostream& stream)
b.DeleteObject(profile);
}
JSCustomObject* ThreadProfile::ToJSObject(JSContext *aCx)
JSObject* ThreadProfile::ToJSObject(JSContext *aCx)
{
JSObjectBuilder b(aCx);
JSCustomObject *profile = b.CreateObject();
JS::RootedObject profile(aCx, b.CreateObject());
BuildJSObject(b, profile);
return profile;
}
void ThreadProfile::BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile) {
template <typename Builder>
void ThreadProfile::BuildJSObject(Builder& b, typename Builder::ObjectHandle profile) {
// Thread meta data
if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
@ -320,12 +320,12 @@ void ThreadProfile::BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile)
b.DefineProperty(profile, "tid", mThreadId);
JSCustomArray *samples = b.CreateArray();
typename Builder::RootedArray samples(b.context(), b.CreateArray());
b.DefineProperty(profile, "samples", samples);
JSCustomObject *sample = nullptr;
JSCustomArray *frames = nullptr;
JSCustomArray *marker = nullptr;
typename Builder::RootedObject sample(b.context());
typename Builder::RootedArray frames(b.context());
typename Builder::RootedArray marker(b.context());
int readPos = mReadPos;
while (readPos != mLastFlushPos) {
@ -391,7 +391,7 @@ void ThreadProfile::BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile)
case 'l':
{
if (sample) {
JSCustomObject *frame = b.CreateObject();
typename Builder::RootedObject frame(b.context(), b.CreateObject());
if (entry.mTagName == 'l') {
// Bug 753041
// We need a double cast here to tell GCC that we don't want to sign
@ -417,6 +417,11 @@ void ThreadProfile::BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile)
}
}
template void ThreadProfile::BuildJSObject<JSObjectBuilder>(JSObjectBuilder& b,
JS::HandleObject profile);
template void ThreadProfile::BuildJSObject<JSCustomObjectBuilder>(JSCustomObjectBuilder& b,
JSCustomObject *profile);
PseudoStack* ThreadProfile::GetPseudoStack()
{
return mPseudoStack;

View File

@ -8,7 +8,6 @@
#include <ostream>
#include "GeckoProfilerImpl.h"
#include "JSAObjectBuilder.h"
#include "platform.h"
#include "mozilla/Mutex.h"
@ -68,10 +67,10 @@ public:
friend std::ostream& operator<<(std::ostream& stream,
const ThreadProfile& profile);
void ToStreamAsJSON(std::ostream& stream);
JSCustomObject *ToJSObject(JSContext *aCx);
JSObject *ToJSObject(JSContext *aCx);
PseudoStack* GetPseudoStack();
mozilla::Mutex* GetMutex();
void BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile);
template <typename Builder> void BuildJSObject(Builder& b, typename Builder::ObjectHandle profile);
bool IsMainThread() const { return mIsMainThread; }
const char* Name() const { return mName; }

View File

@ -91,9 +91,10 @@ void TableTicker::HandleSaveRequest()
NS_DispatchToMainThread(runnable);
}
JSCustomObject* TableTicker::GetMetaJSCustomObject(JSAObjectBuilder& b)
template <typename Builder>
typename Builder::Object TableTicker::GetMetaJSCustomObject(Builder& b)
{
JSCustomObject *meta = b.CreateObject();
typename Builder::RootedObject meta(b.context(), b.CreateObject());
b.DefineProperty(meta, "version", 2);
b.DefineProperty(meta, "interval", interval());
@ -156,42 +157,47 @@ void TableTicker::ToStreamAsJSON(std::ostream& stream)
JSObject* TableTicker::ToJSObject(JSContext *aCx)
{
JSObjectBuilder b(aCx);
JSCustomObject* profile = b.CreateObject();
JS::RootedObject profile(aCx, b.CreateObject());
BuildJSObject(b, profile);
JSObject* jsProfile = b.GetJSObject(profile);
return jsProfile;
return profile;
}
template <typename Builder>
struct SubprocessClosure {
JSAObjectBuilder* mBuilder;
JSCustomArray* mThreads;
SubprocessClosure(Builder *aBuilder, typename Builder::ArrayHandle aThreads)
: mBuilder(aBuilder), mThreads(aThreads)
{}
Builder* mBuilder;
typename Builder::ArrayHandle mThreads;
};
template <typename Builder>
void SubProcessCallback(const char* aProfile, void* aClosure)
{
// Called by the observer to get their profile data included
// as a sub profile
SubprocessClosure* closure = (SubprocessClosure*)aClosure;
SubprocessClosure<Builder>* closure = (SubprocessClosure<Builder>*)aClosure;
closure->mBuilder->ArrayPush(closure->mThreads, aProfile);
}
#if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
template <typename Builder>
static
JSCustomObject* BuildJavaThreadJSObject(JSAObjectBuilder& b)
typename Builder::Object BuildJavaThreadJSObject(Builder& b)
{
JSCustomObject* javaThread = b.CreateObject();
typename Builder::RootedObject javaThread(b.context(), b.CreateObject());
b.DefineProperty(javaThread, "name", "Java Main Thread");
JSCustomArray *samples = b.CreateArray();
typename Builder::RootedArray samples(b.context(), b.CreateArray());
b.DefineProperty(javaThread, "samples", samples);
int sampleId = 0;
while (true) {
int frameId = 0;
JSCustomObject *sample = nullptr;
JSCustomArray *frames = nullptr;
typename Builder::RootedObject sample(b.context());
typename Builder::RootedArray frames(b.context());
while (true) {
nsCString result;
bool hasFrame = AndroidBridge::Bridge()->GetFrameNameJavaProfiling(0, sampleId, frameId, result);
@ -210,7 +216,7 @@ JSCustomObject* BuildJavaThreadJSObject(JSAObjectBuilder& b)
double sampleTime = AndroidBridge::Bridge()->GetSampleTimeJavaProfiling(0, sampleId);
b.DefineProperty(sample, "time", sampleTime);
}
JSCustomObject *frame = b.CreateObject();
typename Builder::RootedObject frame(b.context(), b.CreateObject());
b.DefineProperty(frame, "location", result.BeginReading());
b.ArrayPush(frames, frame);
frameId++;
@ -225,17 +231,18 @@ JSCustomObject* BuildJavaThreadJSObject(JSAObjectBuilder& b)
}
#endif
void TableTicker::BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile)
template <typename Builder>
void TableTicker::BuildJSObject(Builder& b, typename Builder::ObjectHandle profile)
{
// Put shared library info
b.DefineProperty(profile, "libs", GetSharedLibraryInfoString().c_str());
// Put meta data
JSCustomObject *meta = GetMetaJSCustomObject(b);
typename Builder::RootedObject meta(b.context(), GetMetaJSCustomObject(b));
b.DefineProperty(profile, "meta", meta);
// Lists the samples for each ThreadProfile
JSCustomArray *threads = b.CreateArray();
typename Builder::RootedArray threads(b.context(), b.CreateArray());
b.DefineProperty(profile, "threads", threads);
SetPaused(true);
@ -250,7 +257,7 @@ void TableTicker::BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile)
MutexAutoLock lock(*sRegisteredThreads->at(i)->Profile()->GetMutex());
JSCustomObject* threadSamples = b.CreateObject();
typename Builder::RootedObject threadSamples(b.context(), b.CreateObject());
sRegisteredThreads->at(i)->Profile()->BuildJSObject(b, threadSamples);
b.ArrayPush(threads, threadSamples);
}
@ -260,7 +267,7 @@ void TableTicker::BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile)
if (ProfileJava()) {
AndroidBridge::Bridge()->PauseJavaProfiling();
JSCustomObject* javaThread = BuildJavaThreadJSObject(b);
typename Builder::RootedObject javaThread(b.context(), BuildJavaThreadJSObject(b));
b.ArrayPush(threads, javaThread);
AndroidBridge::Bridge()->UnpauseJavaProfiling();
@ -271,12 +278,10 @@ void TableTicker::BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile)
// Send a event asking any subprocesses (plugins) to
// give us their information
SubprocessClosure closure;
closure.mBuilder = &b;
closure.mThreads = threads;
SubprocessClosure<Builder> closure(&b, threads);
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
nsRefPtr<ProfileSaveEvent> pse = new ProfileSaveEvent(SubProcessCallback, &closure);
nsRefPtr<ProfileSaveEvent> pse = new ProfileSaveEvent(SubProcessCallback<Builder>, &closure);
os->NotifyObservers(pse, "profiler-subprocess", nullptr);
}
}

View File

@ -157,7 +157,7 @@ class TableTicker: public Sampler {
void ToStreamAsJSON(std::ostream& stream);
virtual JSObject *ToJSObject(JSContext *aCx);
JSCustomObject *GetMetaJSCustomObject(JSAObjectBuilder& b);
template <typename Builder> typename Builder::Object GetMetaJSCustomObject(Builder& b);
bool HasUnwinderThread() const { return mUnwinderThread; }
bool ProfileJS() const { return mProfileJS; }
@ -176,7 +176,7 @@ protected:
// Not implemented on platforms which do not support backtracing
void doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample);
void BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile);
template <typename Builder> void BuildJSObject(Builder& b, typename Builder::ObjectHandle profile);
// This represent the application's main thread (SAMPLER_INIT)
ThreadProfile* mPrimaryThreadProfile;