зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 3 changesets (bug 799640) on the suspicion of regressing Tp5 by 50%
Backed out changeset 133c704dbcc6 (bug 799640) Backed out changeset b130bb991d84 (bug 799640) Backed out changeset e47b059493cf (bug 799640)
This commit is contained in:
Родитель
d5cd2613c8
Коммит
33a9b305c1
|
@ -26,7 +26,6 @@
|
|||
#include "nsAutoPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "sampler.h"
|
||||
|
||||
#include "prprf.h"
|
||||
#include "nsCRT.h"
|
||||
|
@ -388,7 +387,6 @@ nsAppStartup::Quit(uint32_t aMode)
|
|||
if (mShuttingDown)
|
||||
return NS_OK;
|
||||
|
||||
SAMPLE_MARKER("Shutdown start");
|
||||
RecordShutdownStartTimeStamp();
|
||||
|
||||
// If we're considering quitting, we will only do so if:
|
||||
|
|
|
@ -1117,7 +1117,6 @@ ScopedXPCOMStartup::~ScopedXPCOMStartup()
|
|||
appStartup->DestroyHiddenWindow();
|
||||
|
||||
gDirServiceProvider->DoShutdown();
|
||||
SAMPLE_MARKER("Shutdown early");
|
||||
|
||||
WriteConsoleLog();
|
||||
|
||||
|
@ -3938,7 +3937,6 @@ XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
|||
MOZ_gdk_display_close(mGdkDisplay);
|
||||
#endif
|
||||
|
||||
SAMPLER_SHUTDOWN();
|
||||
rv = LaunchChild(mNativeApp, true);
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
|
@ -3961,8 +3959,6 @@ XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
|||
|
||||
XRE_DeinitCommandLine();
|
||||
|
||||
SAMPLER_SHUTDOWN();
|
||||
|
||||
return NS_FAILED(rv) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
@ -4074,7 +4070,6 @@ XRE_mainMetro(int argc, char* argv[], const nsXREAppData* aAppData)
|
|||
// thread that called XRE_metroStartup.
|
||||
NS_ASSERTION(!xreMainPtr->mScopedXPCom,
|
||||
"XPCOM Shutdown hasn't occured, and we are exiting.");
|
||||
SAMPLER_SHUTDOWN();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -1,311 +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/. */
|
||||
|
||||
#include "JSCustomObjectBuilder.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsUTF8Utils.h"
|
||||
|
||||
#if _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
// These are owned and deleted by JSCustomObject
|
||||
struct PropertyValue {
|
||||
virtual ~PropertyValue() {}
|
||||
virtual void SendToStream(std::ostream& stream) = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct finalizer_impl
|
||||
{
|
||||
static void run(T) {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct finalizer_impl<T*>
|
||||
{
|
||||
static void run(T* p) {
|
||||
delete p;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct finalizer_impl<char *>
|
||||
{
|
||||
static void run(char* p) {
|
||||
free(p);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class TemplatePropertyValue : public PropertyValue {
|
||||
public:
|
||||
TemplatePropertyValue(T aValue)
|
||||
: mValue(aValue)
|
||||
{}
|
||||
|
||||
~TemplatePropertyValue() {
|
||||
finalizer_impl<T>::run(mValue);
|
||||
}
|
||||
|
||||
virtual void SendToStream(std::ostream& stream);
|
||||
private:
|
||||
T mValue;
|
||||
};
|
||||
|
||||
// Escape a UTF8 string to a stream. When an illegal encoding
|
||||
// is found it will insert "INVALID" and the function will return.
|
||||
void EscapeToStream(std::ostream& stream, const char* str) {
|
||||
stream << "\"";
|
||||
|
||||
size_t len = strlen(str);
|
||||
const char* end = &str[len];
|
||||
while (str < end) {
|
||||
bool err;
|
||||
const char* utf8CharStart = str;
|
||||
uint32_t ucs4Char = UTF8CharEnumerator::NextChar(&str, end, &err);
|
||||
|
||||
if (err) {
|
||||
// Encoding error
|
||||
stream << "INVALID\"";
|
||||
return;
|
||||
}
|
||||
|
||||
// See http://www.ietf.org/rfc/rfc4627.txt?number=4627
|
||||
// characters that must be escaped: quotation mark,
|
||||
// reverse solidus, and the control characters
|
||||
// (U+0000 through U+001F).
|
||||
if (ucs4Char == '\"') {
|
||||
stream << "\\\"";
|
||||
} else if (ucs4Char == '\\') {
|
||||
stream << "\\\\";
|
||||
} else if (ucs4Char > 0xFF) {
|
||||
PRUnichar chr[2];
|
||||
ConvertUTF8toUTF16 encoder(chr);
|
||||
encoder.write(utf8CharStart, str-utf8CharStart);
|
||||
char escChar[13];
|
||||
snprintf(escChar, mozilla::ArrayLength(escChar), "\\u%04X\\u%04X", chr[0], chr[1]);
|
||||
stream << escChar;
|
||||
} else if (ucs4Char < 0x1F || ucs4Char > 0xFF) {
|
||||
char escChar[7];
|
||||
snprintf(escChar, mozilla::ArrayLength(escChar), "\\u%04X", ucs4Char);
|
||||
stream << escChar;
|
||||
} else {
|
||||
stream << char(ucs4Char);
|
||||
}
|
||||
}
|
||||
stream << "\"";
|
||||
}
|
||||
|
||||
class JSCustomObject {
|
||||
public:
|
||||
JSCustomObject() {
|
||||
mProperties.Init();
|
||||
}
|
||||
~JSCustomObject();
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& stream, JSCustomObject* entry);
|
||||
|
||||
template<class T>
|
||||
void AddProperty(const char* aName, T aValue) {
|
||||
mProperties.Put(nsDependentCString(aName), new TemplatePropertyValue<T>(aValue));
|
||||
}
|
||||
|
||||
nsDataHashtable<nsCStringHashKey, PropertyValue*> mProperties;
|
||||
};
|
||||
|
||||
class JSCustomArray {
|
||||
public:
|
||||
nsTArray<PropertyValue*> mValues;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& stream, JSCustomArray* entry);
|
||||
|
||||
template<class T>
|
||||
void AppendElement(T aValue) {
|
||||
mValues.AppendElement(new TemplatePropertyValue<T>(aValue));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SendToStreamImpl
|
||||
{
|
||||
static void run(std::ostream& stream, const T& t) {
|
||||
stream << t;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct SendToStreamImpl<T*>
|
||||
{
|
||||
static void run(std::ostream& stream, T* t) {
|
||||
stream << *t;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SendToStreamImpl<char *>
|
||||
{
|
||||
static void run(std::ostream& stream, char* p) {
|
||||
EscapeToStream(stream, p);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SendToStreamImpl<JSCustomObject*>
|
||||
{
|
||||
static void run(std::ostream& stream, JSCustomObject* p) {
|
||||
stream << p;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SendToStreamImpl<JSCustomArray*>
|
||||
{
|
||||
static void run(std::ostream& stream, JSCustomArray* p) {
|
||||
stream << p;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> void
|
||||
TemplatePropertyValue<T>::SendToStream(std::ostream& stream)
|
||||
{
|
||||
SendToStreamImpl<T>::run(stream, mValue);
|
||||
}
|
||||
|
||||
struct JSONStreamClosure {
|
||||
std::ostream& mStream;
|
||||
bool mNeedsComma;
|
||||
};
|
||||
|
||||
PLDHashOperator HashTableOutput(const nsACString& aKey, PropertyValue* aValue, void* stream)
|
||||
{
|
||||
JSONStreamClosure& streamClosure = *(JSONStreamClosure*)stream;
|
||||
if (streamClosure.mNeedsComma) {
|
||||
streamClosure.mStream << ",";
|
||||
}
|
||||
streamClosure.mNeedsComma = true;
|
||||
EscapeToStream(streamClosure.mStream, (const char*)aKey.BeginReading());
|
||||
streamClosure.mStream << ":";
|
||||
aValue->SendToStream(streamClosure.mStream);
|
||||
return PLDHashOperator::PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& stream, JSCustomObject* entry)
|
||||
{
|
||||
JSONStreamClosure streamClosure = {stream, false};
|
||||
stream << "{";
|
||||
entry->mProperties.EnumerateRead(HashTableOutput, &streamClosure);
|
||||
stream << "}";
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& stream, JSCustomArray* entry)
|
||||
{
|
||||
bool needsComma = false;
|
||||
stream << "[";
|
||||
for (int i = 0; i < entry->mValues.Length(); i++) {
|
||||
if (needsComma) {
|
||||
stream << ",";
|
||||
}
|
||||
entry->mValues[i]->SendToStream(stream);
|
||||
needsComma = true;
|
||||
}
|
||||
stream << "]";
|
||||
return stream;
|
||||
}
|
||||
|
||||
PLDHashOperator HashTableFree(const nsACString& aKey, PropertyValue* aValue, void* stream)
|
||||
{
|
||||
delete aValue;
|
||||
return PLDHashOperator::PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
JSCustomObject::~JSCustomObject()
|
||||
{
|
||||
mProperties.EnumerateRead(HashTableFree, nullptr);
|
||||
}
|
||||
|
||||
JSAObjectBuilder::~JSAObjectBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
JSCustomObjectBuilder::JSCustomObjectBuilder()
|
||||
{}
|
||||
|
||||
void
|
||||
JSCustomObjectBuilder::DeleteObject(JSCustomObject* aObject)
|
||||
{
|
||||
delete aObject;
|
||||
}
|
||||
|
||||
void
|
||||
JSCustomObjectBuilder::Serialize(JSCustomObject* aObject, std::ostream& stream)
|
||||
{
|
||||
stream << aObject;
|
||||
}
|
||||
|
||||
void
|
||||
JSCustomObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, JSCustomObject *aValue)
|
||||
{
|
||||
aObject->AddProperty(name, aValue);
|
||||
}
|
||||
|
||||
void
|
||||
JSCustomObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, JSCustomArray *aValue)
|
||||
{
|
||||
aObject->AddProperty(name, aValue);
|
||||
}
|
||||
|
||||
void
|
||||
JSCustomObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, int aValue)
|
||||
{
|
||||
aObject->AddProperty(name, aValue);
|
||||
}
|
||||
|
||||
void
|
||||
JSCustomObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, double aValue)
|
||||
{
|
||||
aObject->AddProperty(name, aValue);
|
||||
}
|
||||
|
||||
void
|
||||
JSCustomObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, const char *aValue)
|
||||
{
|
||||
// aValue copy will be freed by the property desctructor (template specialization)
|
||||
aObject->AddProperty(name, strdup(aValue));
|
||||
}
|
||||
|
||||
void
|
||||
JSCustomObjectBuilder::ArrayPush(JSCustomArray *aArray, int aValue)
|
||||
{
|
||||
aArray->AppendElement(aValue);
|
||||
}
|
||||
|
||||
void
|
||||
JSCustomObjectBuilder::ArrayPush(JSCustomArray *aArray, const char *aValue)
|
||||
{
|
||||
// aValue copy will be freed by the property desctructor (template specialization)
|
||||
aArray->AppendElement(strdup(aValue));
|
||||
}
|
||||
|
||||
void
|
||||
JSCustomObjectBuilder::ArrayPush(JSCustomArray *aArray, JSCustomObject *aObject)
|
||||
{
|
||||
aArray->AppendElement(aObject);
|
||||
}
|
||||
|
||||
JSCustomArray*
|
||||
JSCustomObjectBuilder::CreateArray() {
|
||||
return new JSCustomArray();
|
||||
}
|
||||
|
||||
JSCustomObject*
|
||||
JSCustomObjectBuilder::CreateObject() {
|
||||
return new JSCustomObject();
|
||||
}
|
||||
|
|
@ -1,57 +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 JSCUSTOMOBJECTBUILDER_H
|
||||
#define JSCUSTOMOBJECTBUILDER_H
|
||||
|
||||
#include <ostream>
|
||||
#include "JSAObjectBuilder.h"
|
||||
|
||||
class JSCustomObject;
|
||||
class JSCustomArray;
|
||||
class JSCustomObjectBuilder;
|
||||
|
||||
class JSCustomObjectBuilder : public JSAObjectBuilder
|
||||
{
|
||||
public:
|
||||
|
||||
// We need to ensure that this object lives on the stack so that GC sees it properly
|
||||
JSCustomObjectBuilder();
|
||||
|
||||
void Serialize(JSCustomObject* aObject, std::ostream& stream);
|
||||
|
||||
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, 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, JSCustomObject *aObject);
|
||||
JSCustomArray *CreateArray();
|
||||
JSCustomObject *CreateObject();
|
||||
|
||||
// Delete this object and all of its descendant
|
||||
void DeleteObject(JSCustomObject* aObject);
|
||||
|
||||
private:
|
||||
// This class can't be copied
|
||||
JSCustomObjectBuilder(const JSCustomObjectBuilder&);
|
||||
JSCustomObjectBuilder& operator=(const JSCustomObjectBuilder&);
|
||||
|
||||
void* operator new(size_t);
|
||||
void* operator new[](size_t);
|
||||
void operator delete(void*) {
|
||||
// Since JSCustomObjectBuilder has a virtual destructor the compiler
|
||||
// has to provide a destructor in the object file that will call
|
||||
// operate delete in case there is a derived class since its
|
||||
// destructor wont know how to free this instance.
|
||||
abort();
|
||||
}
|
||||
void operator delete[](void*);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,153 +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/. */
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "JSObjectBuilder.h"
|
||||
|
||||
JSObjectBuilder::JSObjectBuilder(JSContext *aCx) : mCx(aCx), mOk(JS_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)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_DefineProperty(mCx, (JSObject*)aObject, name, OBJECT_TO_JSVAL((JSObject*)aValue), nullptr, nullptr, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
void
|
||||
JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, int value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_DefineProperty(mCx, (JSObject*)aObject, name, INT_TO_JSVAL(value), nullptr, nullptr, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
void
|
||||
JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, double value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_DefineProperty(mCx, (JSObject*)aObject, name, DOUBLE_TO_JSVAL(value), nullptr, nullptr, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
void
|
||||
JSObjectBuilder::DefineProperty(JSCustomObject *aObject, const char *name, nsAString &value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
const nsString &flat = PromiseFlatString(value);
|
||||
JSString *string = JS_NewUCStringCopyN(mCx, static_cast<const jschar*>(flat.get()), flat.Length());
|
||||
if (!string)
|
||||
mOk = JS_FALSE;
|
||||
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
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, size_t valueLength)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
JSString *string = JS_InternStringN(mCx, value, valueLength);
|
||||
if (!string) {
|
||||
mOk = JS_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
DefineProperty(aObject, name, value, strlen(value));
|
||||
}
|
||||
|
||||
void
|
||||
JSObjectBuilder::ArrayPush(JSCustomArray *aArray, int value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
jsval objval = INT_TO_JSVAL(value);
|
||||
uint32_t length;
|
||||
mOk = JS_GetArrayLength(mCx, (JSObject*)aArray, &length);
|
||||
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_SetElement(mCx, (JSObject*)aArray, length, &objval);
|
||||
}
|
||||
|
||||
void
|
||||
JSObjectBuilder::ArrayPush(JSCustomArray *aArray, const char *value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
JSString *string = JS_NewStringCopyN(mCx, value, strlen(value));
|
||||
if (!string) {
|
||||
mOk = JS_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
jsval objval = STRING_TO_JSVAL(string);
|
||||
uint32_t length;
|
||||
mOk = JS_GetArrayLength(mCx, (JSObject*)aArray, &length);
|
||||
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_SetElement(mCx, (JSObject*)aArray, length, &objval);
|
||||
}
|
||||
|
||||
void
|
||||
JSObjectBuilder::ArrayPush(JSCustomArray *aArray, JSCustomObject *aObject)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
jsval objval = OBJECT_TO_JSVAL((JSObject*)aObject); uint32_t length;
|
||||
mOk = JS_GetArrayLength(mCx, (JSObject*)aArray, &length);
|
||||
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_SetElement(mCx, (JSObject*)aArray, length, &objval);
|
||||
}
|
||||
|
||||
JSCustomArray*
|
||||
JSObjectBuilder::CreateArray() {
|
||||
JSCustomArray *array = (JSCustomArray*)JS_NewArrayObject(mCx, 0, nullptr);
|
||||
if (!array)
|
||||
mOk = JS_FALSE;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
JSCustomObject*
|
||||
JSObjectBuilder::CreateObject() {
|
||||
JSCustomObject *obj = (JSCustomObject*)JS_NewObject(mCx, nullptr, nullptr, nullptr);
|
||||
if (!obj)
|
||||
mOk = JS_FALSE;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
|
@ -3,60 +3,151 @@
|
|||
* 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 JSOBJECTBUILDER_H
|
||||
#define JSOBJECTBUILDER_H
|
||||
|
||||
#include "JSAObjectBuilder.h"
|
||||
|
||||
class JSCustomObject;
|
||||
class JSCustomObjectBuilder;
|
||||
class JSContext;
|
||||
class nsAString;
|
||||
#include "jsapi.h"
|
||||
|
||||
/* 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:
|
||||
// We need to ensure that this object lives on the stack so that GC sees it properly
|
||||
explicit JSObjectBuilder(JSContext *aCx);
|
||||
~JSObjectBuilder() {}
|
||||
public:
|
||||
|
||||
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(JSObject *aObject, const char *name, JSObject *aValue)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
JSObject* GetJSObject(JSCustomObject* aObject) { return (JSObject*)aObject; }
|
||||
|
||||
private:
|
||||
JSObjectBuilder(const JSObjectBuilder&);
|
||||
JSObjectBuilder& operator=(const JSObjectBuilder&);
|
||||
|
||||
void* operator new(size_t);
|
||||
void* operator new[](size_t);
|
||||
void operator delete(void*) {
|
||||
// Since JSObjectBuilder has a virtual destructor the compiler
|
||||
// has to provide a destructor in the object file that will call
|
||||
// operate delete in case there is a derived class since its
|
||||
// destructor wont know how to free this instance.
|
||||
abort();
|
||||
mOk = JS_DefineProperty(mCx, aObject, name, OBJECT_TO_JSVAL(aValue), NULL, NULL, JSPROP_ENUMERATE);
|
||||
}
|
||||
void operator delete[](void*);
|
||||
|
||||
void DefineProperty(JSObject *aObject, const char *name, int value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_DefineProperty(mCx, aObject, name, INT_TO_JSVAL(value), NULL, NULL, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
void DefineProperty(JSObject *aObject, const char *name, double value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_DefineProperty(mCx, aObject, name, DOUBLE_TO_JSVAL(value), NULL, NULL, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
void DefineProperty(JSObject *aObject, const char *name, nsAString &value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
const nsString &flat = PromiseFlatString(value);
|
||||
JSString *string = JS_NewUCStringCopyN(mCx, static_cast<const jschar*>(flat.get()), flat.Length());
|
||||
if (!string)
|
||||
mOk = JS_FALSE;
|
||||
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_DefineProperty(mCx, aObject, name, STRING_TO_JSVAL(string), NULL, NULL, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
void DefineProperty(JSObject *aObject, const char *name, const char *value, size_t valueLength)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
JSString *string = JS_InternStringN(mCx, value, valueLength);
|
||||
if (!string) {
|
||||
mOk = JS_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
mOk = JS_DefineProperty(mCx, aObject, name, STRING_TO_JSVAL(string), NULL, NULL, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
void DefineProperty(JSObject *aObject, const char *name, const char *value)
|
||||
{
|
||||
DefineProperty(aObject, name, value, strlen(value));
|
||||
}
|
||||
|
||||
void ArrayPush(JSObject *aArray, int value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
jsval objval = INT_TO_JSVAL(value);
|
||||
uint32_t length;
|
||||
mOk = JS_GetArrayLength(mCx, aArray, &length);
|
||||
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_SetElement(mCx, aArray, length, &objval);
|
||||
}
|
||||
|
||||
void ArrayPush(JSObject *aArray, const char *value)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
JSString *string = JS_NewStringCopyN(mCx, value, strlen(value));
|
||||
if (!string) {
|
||||
mOk = JS_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
jsval objval = STRING_TO_JSVAL(string);
|
||||
uint32_t length;
|
||||
mOk = JS_GetArrayLength(mCx, aArray, &length);
|
||||
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_SetElement(mCx, aArray, length, &objval);
|
||||
}
|
||||
|
||||
void ArrayPush(JSObject *aArray, JSObject *aObject)
|
||||
{
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
jsval objval = OBJECT_TO_JSVAL(aObject);
|
||||
uint32_t length;
|
||||
mOk = JS_GetArrayLength(mCx, aArray, &length);
|
||||
|
||||
if (!mOk)
|
||||
return;
|
||||
|
||||
mOk = JS_SetElement(mCx, aArray, length, &objval);
|
||||
}
|
||||
|
||||
JSObject *CreateArray() {
|
||||
JSObject *array = JS_NewArrayObject(mCx, 0, NULL);
|
||||
if (!array)
|
||||
mOk = JS_FALSE;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
JSObject *CreateObject() {
|
||||
JSObject *obj = JS_NewObject(mCx, NULL, NULL, NULL);
|
||||
if (!obj)
|
||||
mOk = JS_FALSE;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
// We need to ensure that this object lives on the stack so that GC sees it properly
|
||||
JSObjectBuilder(JSContext *aCx) : mCx(aCx), mOk(JS_TRUE)
|
||||
{
|
||||
}
|
||||
private:
|
||||
JSObjectBuilder(JSObjectBuilder&);
|
||||
|
||||
JSContext *mCx;
|
||||
JSObject *mObj;
|
||||
int mOk;
|
||||
JSBool mOk;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -63,8 +63,6 @@ CPPSRCS = \
|
|||
nsProfilerFactory.cpp \
|
||||
nsProfiler.cpp \
|
||||
TableTicker.cpp \
|
||||
JSObjectBuilder.cpp \
|
||||
JSCustomObjectBuilder.cpp \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include "sps_sampler.h"
|
||||
|
@ -17,7 +18,6 @@
|
|||
|
||||
// JSON
|
||||
#include "JSObjectBuilder.h"
|
||||
#include "JSCustomObjectBuilder.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
|
||||
// Meta
|
||||
|
@ -307,31 +307,17 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void ToStreamAsJSON(std::ostream& stream)
|
||||
{
|
||||
JSCustomObjectBuilder b;
|
||||
JSCustomObject *profile = b.CreateObject();
|
||||
BuildJSObject(b, profile);
|
||||
b.Serialize(profile, stream);
|
||||
b.DeleteObject(profile);
|
||||
}
|
||||
|
||||
JSCustomObject *ToJSObject(JSContext *aCx)
|
||||
JSObject *ToJSObject(JSContext *aCx)
|
||||
{
|
||||
JSObjectBuilder b(aCx);
|
||||
JSCustomObject *profile = b.CreateObject();
|
||||
BuildJSObject(b, profile);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
void BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile) {
|
||||
JSCustomArray *samples = b.CreateArray();
|
||||
JSObject *profile = b.CreateObject();
|
||||
JSObject *samples = b.CreateArray();
|
||||
b.DefineProperty(profile, "samples", samples);
|
||||
|
||||
JSCustomObject *sample = nullptr;
|
||||
JSCustomArray *frames = nullptr;
|
||||
JSCustomArray *marker = nullptr;
|
||||
JSObject *sample = NULL;
|
||||
JSObject *frames = NULL;
|
||||
JSObject *marker = NULL;
|
||||
|
||||
int readPos = mReadPos;
|
||||
while (readPos != mLastFlushPos) {
|
||||
|
@ -396,7 +382,7 @@ public:
|
|||
case 'l':
|
||||
{
|
||||
if (sample) {
|
||||
JSCustomObject *frame = b.CreateObject();
|
||||
JSObject *frame = b.CreateObject();
|
||||
if (entry.mTagName == 'l') {
|
||||
// Bug 753041
|
||||
// We need a double cast here to tell GCC that we don't want to sign
|
||||
|
@ -420,6 +406,8 @@ public:
|
|||
}
|
||||
readPos = (readPos + incBy) % mEntrySize;
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
ProfileStack* GetStack()
|
||||
|
@ -485,9 +473,8 @@ class TableTicker: public Sampler {
|
|||
return &mPrimaryThreadProfile;
|
||||
}
|
||||
|
||||
void ToStreamAsJSON(std::ostream& stream);
|
||||
JSObject *ToJSObject(JSContext *aCx);
|
||||
JSCustomObject *GetMetaJSCustomObject(JSAObjectBuilder& b);
|
||||
JSObject *GetMetaJSObject(JSObjectBuilder& b);
|
||||
|
||||
const bool ProfileJS() { return mProfileJS; }
|
||||
|
||||
|
@ -495,7 +482,6 @@ private:
|
|||
// Not implemented on platforms which do not support backtracing
|
||||
void doBacktrace(ThreadProfile &aProfile, TickSample* aSample);
|
||||
|
||||
void BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile);
|
||||
private:
|
||||
// This represent the application's main thread (SAMPLER_INIT)
|
||||
ThreadProfile mPrimaryThreadProfile;
|
||||
|
@ -527,6 +513,7 @@ public:
|
|||
|
||||
NS_IMETHOD Run() {
|
||||
TableTicker *t = tlsTicker.get();
|
||||
|
||||
// Pause the profiler during saving.
|
||||
// This will prevent us from recording sampling
|
||||
// regarding profile saving. This will also
|
||||
|
@ -556,7 +543,7 @@ public:
|
|||
return rv;
|
||||
#endif
|
||||
|
||||
// Create a JSContext to run a JSCustomObjectBuilder :(
|
||||
// Create a JSContext to run a JSObjectBuilder :(
|
||||
// Based on XPCShellEnvironment
|
||||
JSRuntime *rt;
|
||||
JSContext *cx;
|
||||
|
@ -588,6 +575,7 @@ public:
|
|||
// regarding profile saving. This will also
|
||||
// prevent bugs caused by the circular buffer not
|
||||
// being thread safe. Bug 750989.
|
||||
t->SetPaused(true);
|
||||
if (stream.is_open()) {
|
||||
JSAutoCompartment autoComp(cx, obj);
|
||||
JSObject* profileObj = mozilla_sampler_get_profile_data(cx);
|
||||
|
@ -602,6 +590,8 @@ public:
|
|||
JS_EndRequest(cx);
|
||||
JS_DestroyContext(cx);
|
||||
|
||||
t->SetPaused(false);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
@ -618,9 +608,9 @@ void TableTicker::HandleSaveRequest()
|
|||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
|
||||
JSCustomObject* TableTicker::GetMetaJSCustomObject(JSAObjectBuilder& b)
|
||||
JSObject* TableTicker::GetMetaJSObject(JSObjectBuilder& b)
|
||||
{
|
||||
JSCustomObject *meta = b.CreateObject();
|
||||
JSObject *meta = b.CreateObject();
|
||||
|
||||
b.DefineProperty(meta, "version", 2);
|
||||
b.DefineProperty(meta, "interval", interval());
|
||||
|
@ -671,44 +661,30 @@ JSCustomObject* TableTicker::GetMetaJSCustomObject(JSAObjectBuilder& b)
|
|||
return meta;
|
||||
}
|
||||
|
||||
void TableTicker::ToStreamAsJSON(std::ostream& stream)
|
||||
{
|
||||
JSCustomObjectBuilder b;
|
||||
JSCustomObject* profile = b.CreateObject();
|
||||
BuildJSObject(b, profile);
|
||||
b.Serialize(profile, stream);
|
||||
b.DeleteObject(profile);
|
||||
}
|
||||
|
||||
JSObject* TableTicker::ToJSObject(JSContext *aCx)
|
||||
{
|
||||
JSObjectBuilder b(aCx);
|
||||
JSCustomObject* profile = b.CreateObject();
|
||||
BuildJSObject(b, profile);
|
||||
JSObject* jsProfile = b.GetJSObject(profile);
|
||||
|
||||
return jsProfile;
|
||||
}
|
||||
JSObject *profile = b.CreateObject();
|
||||
|
||||
void TableTicker::BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile)
|
||||
{
|
||||
// Put shared library info
|
||||
b.DefineProperty(profile, "libs", GetSharedLibraryInfoString().c_str());
|
||||
|
||||
// Put meta data
|
||||
JSCustomObject *meta = GetMetaJSCustomObject(b);
|
||||
JSObject *meta = GetMetaJSObject(b);
|
||||
b.DefineProperty(profile, "meta", meta);
|
||||
|
||||
// Lists the samples for each ThreadProfile
|
||||
JSCustomArray *threads = b.CreateArray();
|
||||
JSObject *threads = b.CreateArray();
|
||||
b.DefineProperty(profile, "threads", threads);
|
||||
|
||||
// For now we only have one thread
|
||||
SetPaused(true);
|
||||
JSCustomObject* threadSamples = b.CreateObject();
|
||||
GetPrimaryThreadProfile()->BuildJSObject(b, threadSamples);
|
||||
JSObject* threadSamples = GetPrimaryThreadProfile()->ToJSObject(aCx);
|
||||
b.ArrayPush(threads, threadSamples);
|
||||
SetPaused(false);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -1086,21 +1062,8 @@ void mozilla_sampler_init()
|
|||
features, sizeof(features)/sizeof(const char*));
|
||||
}
|
||||
|
||||
void mozilla_sampler_shutdown()
|
||||
void mozilla_sampler_deinit()
|
||||
{
|
||||
TableTicker *t = tlsTicker.get();
|
||||
if (t) {
|
||||
const char *val = PR_GetEnv("MOZ_PROFILER_SHUTDOWN");
|
||||
if (val) {
|
||||
std::ofstream stream;
|
||||
stream.open(val);
|
||||
if (stream.is_open()) {
|
||||
t->ToStreamAsJSON(stream);
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mozilla_sampler_stop();
|
||||
// We can't delete the Stack because we can be between a
|
||||
// sampler call_enter/call_exit point.
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
#include <stdarg.h>
|
||||
#include "mozilla/ThreadLocal.h"
|
||||
#include "nscore.h"
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsAlgorithm.h"
|
||||
|
||||
|
||||
/* QT has a #define for the word "slots" and jsfriendapi.h has a struct with
|
||||
* this variable name, causing compilation problems. Alleviate this for now by
|
||||
* removing this #define */
|
||||
|
@ -26,7 +26,6 @@ using mozilla::TimeDuration;
|
|||
|
||||
struct ProfileStack;
|
||||
class TableTicker;
|
||||
class JSCustomObject;
|
||||
|
||||
extern mozilla::ThreadLocal<ProfileStack *> tlsStack;
|
||||
extern mozilla::ThreadLocal<TableTicker *> tlsTicker;
|
||||
|
@ -43,7 +42,7 @@ extern bool stack_key_initialized;
|
|||
#endif
|
||||
|
||||
#define SAMPLER_INIT() mozilla_sampler_init()
|
||||
#define SAMPLER_SHUTDOWN() mozilla_sampler_shutdown()
|
||||
#define SAMPLER_DEINIT() mozilla_sampler_deinit()
|
||||
#define SAMPLER_START(entries, interval, features, featureCount) mozilla_sampler_start(entries, interval, features, featureCount)
|
||||
#define SAMPLER_STOP() mozilla_sampler_stop()
|
||||
#define SAMPLER_IS_ACTIVE() mozilla_sampler_is_active()
|
||||
|
@ -173,7 +172,6 @@ char* mozilla_sampler_get_profile();
|
|||
JSObject *mozilla_sampler_get_profile_data(JSContext *aCx);
|
||||
const char** mozilla_sampler_get_features();
|
||||
void mozilla_sampler_init();
|
||||
void mozilla_sampler_shutdown();
|
||||
|
||||
void mozilla_sampler_print_location();
|
||||
|
||||
|
|
|
@ -618,7 +618,6 @@ ShutdownXPCOM(nsIServiceManager* servMgr)
|
|||
|
||||
nsCycleCollector_shutdown();
|
||||
|
||||
SAMPLE_MARKER("Shutdown xpcom");
|
||||
mozilla::PoisonWrite();
|
||||
|
||||
if (moduleLoaders) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче