This commit is contained in:
Ryan VanderMeulen 2013-03-19 18:01:10 -04:00
Родитель 8575ddfb20 5f97458fab
Коммит 4de0c7f60e
11 изменённых файлов: 354 добавлений и 42 удалений

Просмотреть файл

@ -9,6 +9,8 @@ ac_add_options --enable-codesighs
ac_add_options --disable-install-strip
ac_add_options --enable-signmar
ac_add_options --enable-profiling
ac_add_options --enable-instruments
ac_add_options --enable-dtrace
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics

Просмотреть файл

@ -293,12 +293,3 @@
fun:_ZN7mozilla3dom7workers13WorkerPrivate9DoRunLoopEP9JSContext
...
}
{
Bug 824647
Memcheck:Leak
fun:malloc
...
fun:_ZN12_GLOBAL__N_112HistogramGetEPKcjjjjPPN4base9HistogramE
fun:_ZN12_GLOBAL__N_113TelemetryImpl13HistogramFromERK19nsACString_internalS3_P9JSContextPN2JS5ValueE
...
}

Просмотреть файл

@ -1725,6 +1725,18 @@ if test -n "$MOZ_SHARK"; then
AC_DEFINE(MOZ_SHARK)
fi
dnl ========================================================
dnl instruments
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(instruments,
[ --enable-instruments Enable instruments remote profiling. Implies --enable-profiling.],
MOZ_INSTRUMENTS=1,
MOZ_INSTRUMENTS= )
if test -n "$MOZ_INSTRUMENTS"; then
MOZ_PROFILING=1
AC_DEFINE(MOZ_INSTRUMENTS)
fi
dnl ========================================================
dnl callgrind
dnl ========================================================
@ -8511,6 +8523,7 @@ AC_SUBST(MOZ_JSDEBUGGER)
AC_SUBST(MOZ_ENABLE_PROFILER_SPS)
AC_SUBST(MOZ_JPROF)
AC_SUBST(MOZ_SHARK)
AC_SUBST(MOZ_INSTRUMENTS)
AC_SUBST(MOZ_CALLGRIND)
AC_SUBST(MOZ_VTUNE)
AC_SUBST(MOZ_ETW)

Просмотреть файл

@ -7807,7 +7807,7 @@ class CGBindingImplClass(CGClass):
def getGetParentObjectReturnType(self):
return ("// TODO: return something sensible here, and change the return type\n"
"%s*" % self.descriptor.name)
"%s*" % self.descriptor.nativeType.split('::')[-1])
def getGetParentObjectBody(self):
return None
@ -7827,9 +7827,9 @@ class CGExampleClass(CGBindingImplClass):
"public:\n"
" NS_DECL_CYCLE_COLLECTING_ISUPPORTS\n"
" NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(%s)\n"
"\n" % descriptor.name)
"\n" % descriptor.nativeType.split('::')[-1])
CGClass.__init__(self, descriptor.name,
CGClass.__init__(self, descriptor.nativeType.split('::')[-1],
bases=[ClassBase("nsISupports /* Change nativeOwnership in the binding configuration if you don't want this */"),
ClassBase("nsWrapperCache /* Change wrapperCache in the binding configuration if you don't want this */")],
constructors=[ClassConstructor([],
@ -7842,27 +7842,27 @@ class CGExampleClass(CGBindingImplClass):
def define(self):
# Just override CGClass and do our own thing
classImpl = """
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(${ifaceName})
NS_IMPL_CYCLE_COLLECTING_ADDREF(${ifaceName})
NS_IMPL_CYCLE_COLLECTING_RELEASE(${ifaceName})
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(${ifaceName})
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(${nativeType})
NS_IMPL_CYCLE_COLLECTING_ADDREF(${nativeType})
NS_IMPL_CYCLE_COLLECTING_RELEASE(${nativeType})
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(${nativeType})
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
${ifaceName}::${ifaceName}()
${nativeType}::${nativeType}()
{
SetIsDOMBinding();
}
${ifaceName}::~${ifaceName}()
${nativeType}::~${nativeType}()
{
}
"""
if self.descriptor.wrapperCache:
classImpl += """
JSObject*
${ifaceName}::WrapObject(JSContext* aCx, JSObject* aScope)
${nativeType}::WrapObject(JSContext* aCx, JSObject* aScope)
{
return ${ifaceName}Binding::Wrap(aCx, aScope, this);
}
@ -7871,14 +7871,16 @@ ${ifaceName}::WrapObject(JSContext* aCx, JSObject* aScope)
else:
classImpl += """
JSObject*
${ifaceName}::WrapObject(JSContext* aCx, JSObject* aScope)
${nativeType}::WrapObject(JSContext* aCx, JSObject* aScope)
{
return ${ifaceName}Binding::Wrap(aCx, aScope, this);
}
"""
return string.Template(classImpl).substitute(
{ "ifaceName": self.descriptor.name }
{ "ifaceName": self.descriptor.name,
"nativeType": self.descriptor.nativeType.split('::')[-1] }
)

Просмотреть файл

@ -144,6 +144,7 @@ CPPSRCS = \
Unicode.cpp \
Xdr.cpp \
Module.cpp \
Instruments.cpp \
$(NULL)
# Changes to internal header files, used externally, massively slow down

Просмотреть файл

@ -21,6 +21,7 @@
#ifdef __APPLE__
#include "devtools/sharkctl.h"
#include "devtools/Instruments.h"
#endif
using namespace js;
@ -51,15 +52,37 @@ JS_UnsafeGetLastProfilingError()
return gLastError;
}
#ifdef __APPLE__
static bool
StartOSXProfiling(const char *profileName = NULL)
{
bool ok = true;
const char* profiler = NULL;
#ifdef MOZ_SHARK
ok = Shark::Start();
profiler = "Shark";
#endif
#ifdef MOZ_INSTRUMENTS
ok = Instruments::Start();
profiler = "Instruments";
#endif
if (!ok) {
if (profileName)
UnsafeError("Failed to start %s for %s", profiler, profileName);
else
UnsafeError("Failed to start %s", profiler);
return false;
}
return true;
}
#endif
JS_PUBLIC_API(JSBool)
JS_StartProfiling(const char *profileName)
{
JSBool ok = JS_TRUE;
#if defined(MOZ_SHARK) && defined(__APPLE__)
if (!Shark::Start()) {
UnsafeError("Failed to start Shark for %s", profileName);
ok = JS_FALSE;
}
#ifdef __APPLE__
ok = StartOSXProfiling(profileName);
#endif
#ifdef __linux__
if (!js_StartPerf())
@ -72,9 +95,14 @@ JS_PUBLIC_API(JSBool)
JS_StopProfiling(const char *profileName)
{
JSBool ok = JS_TRUE;
#if defined(MOZ_SHARK) && defined(__APPLE__)
#ifdef __APPLE__
#ifdef MOZ_SHARK
Shark::Stop();
#endif
#ifdef MOZ_INSTRUMENTS
Instruments::Stop(profileName);
#endif
#endif
#ifdef __linux__
if (!js_StopPerf())
ok = JS_FALSE;
@ -92,12 +120,22 @@ ControlProfilers(bool toState)
JSBool ok = JS_TRUE;
if (! Probes::ProfilingActive && toState) {
#if defined(MOZ_SHARK) && defined(__APPLE__)
if (!Shark::Start()) {
UnsafeError("Failed to start Shark");
ok = JS_FALSE;
#ifdef __APPLE__
#if defined(MOZ_SHARK) || defined(MOZ_INSTRUMENTS)
const char* profiler;
#ifdef MOZ_SHARK
ok = Shark::Start();
profiler = "Shark";
#endif
#ifdef MOZ_INSTRUMENTS
ok = Instruments::Resume();
profiler = "Instruments";
#endif
if (!ok) {
UnsafeError("Failed to start %s", profiler);
}
#endif
#endif
#ifdef MOZ_CALLGRIND
if (! js_StartCallgrind()) {
UnsafeError("Failed to start Callgrind");
@ -105,9 +143,14 @@ ControlProfilers(bool toState)
}
#endif
} else if (Probes::ProfilingActive && ! toState) {
#if defined(MOZ_SHARK) && defined(__APPLE__)
#ifdef __APPLE__
#ifdef MOZ_SHARK
Shark::Stop();
#endif
#ifdef MOZ_INSTRUMENTS
Instruments::Pause();
#endif
#endif
#ifdef MOZ_CALLGRIND
if (! js_StopCallgrind()) {
UnsafeError("failed to stop Callgrind");
@ -263,7 +306,7 @@ DumpProfile(JSContext *cx, unsigned argc, jsval *vp)
return true;
}
#ifdef MOZ_SHARK
#if defined(MOZ_SHARK) || defined(MOZ_INSTRUMENTS)
static JSBool
IgnoreAndReturnTrue(JSContext *cx, unsigned argc, jsval *vp)
@ -312,7 +355,7 @@ static JSFunctionSpec profiling_functions[] = {
JS_FN("pauseProfilers", PauseProfilers, 1,0),
JS_FN("resumeProfilers", ResumeProfilers, 1,0),
JS_FN("dumpProfile", DumpProfile, 2,0),
#ifdef MOZ_SHARK
#if defined(MOZ_SHARK) || defined(MOZ_INSTRUMENTS)
/* Keep users of the old shark API happy. */
JS_FN("connectShark", IgnoreAndReturnTrue, 0,0),
JS_FN("disconnectShark", IgnoreAndReturnTrue, 0,0),

Просмотреть файл

@ -3645,6 +3645,19 @@ if test -n "$MOZ_SHARK"; then
AC_DEFINE(MOZ_SHARK)
fi
dnl ========================================================
dnl instruments
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(instruments,
[ --enable-instruments Enable instruments remote profiling. Implies --enable-profiling.],
MOZ_INSTRUMENTS=1,
MOZ_INSTRUMENTS= )
if test -n "$MOZ_INSTRUMENTS"; then
MOZ_PROFILING=1
AC_DEFINE(MOZ_INSTRUMENTS)
LIBS="$LIBS -framework CoreFoundation"
fi
dnl ========================================================
dnl callgrind
dnl ========================================================
@ -4140,6 +4153,7 @@ AC_SUBST(MOZ_DEBUG_LDFLAGS)
AC_SUBST(WARNINGS_AS_ERRORS)
AC_SUBST(MOZ_JPROF)
AC_SUBST(MOZ_SHARK)
AC_SUBST(MOZ_INSTRUMENTS)
AC_SUBST(MOZ_CALLGRIND)
AC_SUBST(MOZ_VTUNE)
AC_SUBST(MOZ_ETW)

Просмотреть файл

@ -0,0 +1,233 @@
/* 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 "Instruments.h"
#ifdef __APPLE__
#include "jsapi.h"
#include <dlfcn.h>
#include <CoreFoundation/CoreFoundation.h>
// There are now 2 paths to the DTPerformanceSession framework. We try to load
// the one contained in /Applications/Xcode.app first, falling back to the one
// contained in /Library/Developer/4.0/Instruments.
#define DTPerformanceLibraryPath "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/DTPerformanceSession.framework/Versions/Current/DTPerformanceSession"
#define OldDTPerformanceLibraryPath "/Library/Developer/4.0/Instruments/Frameworks/DTPerformanceSession.framework/Versions/Current/DTPerformanceSession"
extern "C" {
typedef CFTypeRef DTPerformanceSessionRef;
#define DTPerformanceSession_TimeProfiler "com.apple.instruments.dtps.timeprofiler"
// DTPerformanceSession_Option_SamplingInterval is measured in microseconds
#define DTPerformanceSession_Option_SamplingInterval "com.apple.instruments.dtps.option.samplinginterval"
typedef void (*dtps_errorcallback_t)(CFStringRef, CFErrorRef);
typedef DTPerformanceSessionRef (*DTPerformanceSessionCreateFunction)(CFStringRef, CFStringRef, CFDictionaryRef, CFErrorRef*);
typedef bool (*DTPerformanceSessionAddInstrumentFunction)(DTPerformanceSessionRef, CFStringRef, CFDictionaryRef, dtps_errorcallback_t, CFErrorRef*);
typedef bool (*DTPerformanceSessionIsRecordingFunction)(DTPerformanceSessionRef);
typedef bool (*DTPerformanceSessionStartFunction)(DTPerformanceSessionRef, CFArrayRef, CFErrorRef*);
typedef bool (*DTPerformanceSessionStopFunction)(DTPerformanceSessionRef, CFArrayRef, CFErrorRef*);
typedef bool (*DTPerformanceSessionSaveFunction)(DTPerformanceSessionRef, CFStringRef, CFErrorRef*);
} // extern "C"
namespace Instruments {
static const int kSamplingInterval = 20; // microseconds
template<typename T>
class AutoReleased
{
public:
AutoReleased(T aTypeRef) : mTypeRef(aTypeRef)
{
}
~AutoReleased()
{
if (mTypeRef) {
CFRelease(mTypeRef);
}
}
operator T()
{
return mTypeRef;
}
private:
T mTypeRef;
};
#define DTPERFORMANCE_SYMBOLS \
SYMBOL(DTPerformanceSessionCreate) \
SYMBOL(DTPerformanceSessionAddInstrument) \
SYMBOL(DTPerformanceSessionIsRecording) \
SYMBOL(DTPerformanceSessionStart) \
SYMBOL(DTPerformanceSessionStop) \
SYMBOL(DTPerformanceSessionSave)
#define SYMBOL(_sym) \
_sym##Function _sym = NULL;
DTPERFORMANCE_SYMBOLS
#undef SYMBOL
void*
LoadDTPerformanceLibraries(bool dontLoad)
{
int flags = RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE;
if (dontLoad) {
flags |= RTLD_NOLOAD;
}
void *DTPerformanceLibrary = dlopen(DTPerformanceLibraryPath, flags);
if (!DTPerformanceLibrary) {
DTPerformanceLibrary = dlopen(OldDTPerformanceLibraryPath, flags);
}
return DTPerformanceLibrary;
}
bool
LoadDTPerformanceLibrary()
{
void *DTPerformanceLibrary = LoadDTPerformanceLibraries(true);
if (!DTPerformanceLibrary) {
DTPerformanceLibrary = LoadDTPerformanceLibraries(false);
if (!DTPerformanceLibrary) {
return false;
}
}
#define SYMBOL(_sym) \
_sym = reinterpret_cast<_sym##Function>(dlsym(DTPerformanceLibrary, #_sym)); \
if (!_sym) { \
dlclose(DTPerformanceLibrary); \
DTPerformanceLibrary = NULL; \
return false; \
}
DTPERFORMANCE_SYMBOLS
#undef SYMBOL
dlclose(DTPerformanceLibrary);
return true;
}
static DTPerformanceSessionRef gSession;
bool
Error(CFErrorRef error)
{
if (gSession) {
CFErrorRef unused = NULL;
DTPerformanceSessionStop(gSession, NULL, &unused);
CFRelease(gSession);
gSession = NULL;
}
#ifdef DEBUG
AutoReleased<CFDataRef> data =
CFStringCreateExternalRepresentation(NULL, CFErrorCopyDescription(error),
kCFStringEncodingUTF8, '?');
if (data != NULL) {
printf("%.*s\n\n", (int)CFDataGetLength(data), CFDataGetBytePtr(data));
}
#endif
return false;
}
bool
Start()
{
if (gSession) {
return false;
}
if (!LoadDTPerformanceLibrary()) {
return false;
}
AutoReleased<CFStringRef> process =
CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), getpid());
if (!process) {
return false;
}
CFErrorRef error = NULL;
gSession = DTPerformanceSessionCreate(NULL, process, NULL, &error);
if (!gSession) {
return Error(error);
}
AutoReleased<CFNumberRef> interval =
CFNumberCreate(0, kCFNumberIntType, &kSamplingInterval);
if (!interval) {
return false;
}
CFStringRef keys[1] = { CFSTR(DTPerformanceSession_Option_SamplingInterval) };
CFNumberRef values[1] = { interval };
AutoReleased<CFDictionaryRef> options =
CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys,
(const void**)values, 1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (!options) {
return false;
}
if (!DTPerformanceSessionAddInstrument(gSession,
CFSTR(DTPerformanceSession_TimeProfiler),
options, NULL, &error)) {
return Error(error);
}
return Resume();
}
void
Pause()
{
if (gSession && DTPerformanceSessionIsRecording(gSession)) {
CFErrorRef error = NULL;
if (!DTPerformanceSessionStop(gSession, NULL, &error)) {
Error(error);
}
}
}
bool
Resume()
{
if (!gSession) {
return false;
}
CFErrorRef error = NULL;
return DTPerformanceSessionStart(gSession, NULL, &error) ||
Error(error);
}
void
Stop(const char* profileName)
{
Pause();
CFErrorRef error = NULL;
AutoReleased<CFStringRef> name =
CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s"), "/tmp/",
profileName ? profileName : "mozilla");
if (!DTPerformanceSessionSave(gSession, name, &error)) {
Error(error);
return;
}
CFRelease(gSession);
gSession = NULL;
}
} // namespace Instruments
#endif /* __APPLE__ */

Просмотреть файл

@ -0,0 +1,21 @@
/* 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 Instruments_h__
#define Instruments_h__
#ifdef __APPLE__
namespace Instruments {
bool Start();
void Pause();
bool Resume();
void Stop(const char* profileName);
}
#endif /* __APPLE__ */
#endif /* Instruments_h__ */

Просмотреть файл

@ -59,12 +59,6 @@ SHELL_INSTALL_AUTOLOAD_DEST := $(DIST)/bin
include $(topsrcdir)/config/rules.mk
ifdef MOZ_SHARK
CFLAGS += -F/System/Library/PrivateFrameworks
CXXFLAGS += -F/System/Library/PrivateFrameworks
LDFLAGS += -F/System/Library/PrivateFrameworks -framework CHUD
endif
# People expect the js shell to wind up in the top-level JS dir.
libs::
$(INSTALL) $(IFLAGS2) $(PROGRAM) $(DEPTH)

Просмотреть файл

@ -70,8 +70,6 @@ DEFINES += -DJS_THREADSAFE
ifdef MOZ_SHARK
DEFINES += -DMOZ_SHARK
CFLAGS += -F/System/Library/PrivateFrameworks
LDFLAGS += -F/System/Library/PrivateFrameworks -framework CHUD
endif
ifdef MOZ_CALLGRIND
DEFINES += -DMOZ_CALLGRIND