Bug 1166492 - Return UniquePtr<char[]> from profiler_get_profile to avoid double copying. (r=mstange)
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2650,20 +2650,19 @@ ContentChild::RecvStopProfiler()
{
profiler_stop();
return true;
}
bool
ContentChild::RecvGetProfile(nsCString* aProfile)
{
- char* profile = profiler_get_profile();
+ UniquePtr<char[]> profile = profiler_get_profile();
if (profile) {
- *aProfile = nsCString(profile, strlen(profile));
- free(profile);
+ *aProfile = nsCString(profile.get(), strlen(profile.get()));
} else {
*aProfile = EmptyCString();
}
return true;
}
bool
ContentChild::RecvLoadPluginResult(const uint32_t& aPluginId, const bool& aResult)
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -2561,17 +2561,16 @@ PluginModuleChild::RecvStopProfiler()
{
profiler_stop();
return true;
}
bool
PluginModuleChild::AnswerGetProfile(nsCString* aProfile)
{
- char* profile = profiler_get_profile();
+ UniquePtr<char[]> profile = profiler_get_profile();
if (profile != nullptr) {
- *aProfile = nsCString(profile, strlen(profile));
- free(profile);
+ *aProfile = nsCString(profile.get(), strlen(profile.get()));
} else {
*aProfile = nsCString("", 0);
}
return true;
}
--- a/tools/profiler/GeckoProfiler.h
+++ b/tools/profiler/GeckoProfiler.h
@@ -45,16 +45,17 @@
* 't' - Elapse time since recording started.
*
*/
#ifndef SAMPLER_H
#define SAMPLER_H
#include "js/TypeDecls.h"
+#include "mozilla/UniquePtr.h"
namespace mozilla {
class TimeStamp;
}
enum TracingMetadata {
TRACING_DEFAULT,
TRACING_INTERVAL_START,
@@ -154,17 +155,19 @@ static inline bool profiler_feature_acti
// Internal-only. Used by the event tracer.
static inline void profiler_responsiveness(const mozilla::TimeStamp& aTime) {}
// Internal-only.
static inline void profiler_set_frame_number(int frameNumber) {}
// Get the profile encoded as a JSON string.
-static inline char* profiler_get_profile(float aSinceTime = 0) { return nullptr; }
+static inline mozilla::UniquePtr<char[]> profiler_get_profile(float aSinceTime = 0) {
+ return nullptr;
+}
// Get the profile encoded as a JSON object.
static inline JSObject* profiler_get_profile_jsobject(JSContext* aCx,
float aSinceTime = 0) {
return nullptr;
}
// Get the profile and write it into a file
--- a/tools/profiler/GeckoProfilerFunc.h
+++ b/tools/profiler/GeckoProfilerFunc.h
@@ -3,16 +3,17 @@
* 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 PROFILER_FUNCS_H
#define PROFILER_FUNCS_H
#include "js/TypeDecls.h"
#include "js/ProfilingStack.h"
+#include "mozilla/UniquePtr.h"
#include <stdint.h>
namespace mozilla {
class TimeStamp;
}
class ProfilerBacktrace;
class ProfilerMarkerPayload;
@@ -48,17 +49,17 @@ bool mozilla_sampler_feature_active(cons
void mozilla_sampler_responsiveness(const mozilla::TimeStamp& time);
void mozilla_sampler_frame_number(int frameNumber);
const double* mozilla_sampler_get_responsiveness();
void mozilla_sampler_save();
-char* mozilla_sampler_get_profile(float aSinceTime);
+mozilla::UniquePtr<char[]> mozilla_sampler_get_profile(float aSinceTime);
JSObject *mozilla_sampler_get_profile_data(JSContext *aCx, float aSinceTime);
// Make this function easily callable from a debugger in a build without
// debugging information (work around http://llvm.org/bugs/show_bug.cgi?id=22211)
extern "C" {
void mozilla_sampler_save_profile_to_file(const char* aFilename);
}
--- a/tools/profiler/GeckoProfilerImpl.h
+++ b/tools/profiler/GeckoProfilerImpl.h
@@ -139,17 +139,17 @@ void profiler_responsiveness(const mozil
static inline
void profiler_set_frame_number(int frameNumber)
{
return mozilla_sampler_frame_number(frameNumber);
}
static inline
-char* profiler_get_profile(float aSinceTime = 0)
+mozilla::UniquePtr<char[]> profiler_get_profile(float aSinceTime = 0)
{
return mozilla_sampler_get_profile(aSinceTime);
}
static inline
JSObject* profiler_get_profile_jsobject(JSContext* aCx, float aSinceTime = 0)
{
return mozilla_sampler_get_profile_data(aCx, aSinceTime);
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -213,26 +213,31 @@ void TableTicker::ToStreamAsJSON(std::os
SpliceableJSONWriter b(mozilla::MakeUnique<OStreamJSONWriteFunc>(stream));
StreamJSON(b, aSinceTime);
}
JSObject* TableTicker::ToJSObject(JSContext *aCx, float aSinceTime)
{
JS::RootedValue val(aCx);
{
- SpliceableChunkedJSONWriter b;
- StreamJSON(b, aSinceTime);
- UniquePtr<char[]> buf = b.WriteFunc()->CopyData();
+ UniquePtr<char[]> buf = ToJSON(aSinceTime);
NS_ConvertUTF8toUTF16 js_string(nsDependentCString(buf.get()));
MOZ_ALWAYS_TRUE(JS_ParseJSON(aCx, static_cast<const char16_t*>(js_string.get()),
js_string.Length(), &val));
}
return &val.toObject();
}
+UniquePtr<char[]> TableTicker::ToJSON(float aSinceTime)
+{
+ SpliceableChunkedJSONWriter b;
+ StreamJSON(b, aSinceTime);
+ return b.WriteFunc()->CopyData();
+}
+
struct SubprocessClosure {
explicit SubprocessClosure(SpliceableJSONWriter *aWriter)
: mWriter(aWriter)
{}
SpliceableJSONWriter* mWriter;
};
--- a/tools/profiler/TableTicker.h
+++ b/tools/profiler/TableTicker.h
@@ -189,16 +189,17 @@ class TableTicker: public Sampler {
}
}
return mPrimaryThreadProfile;
}
void ToStreamAsJSON(std::ostream& stream, float aSinceTime = 0);
virtual JSObject *ToJSObject(JSContext *aCx, float aSinceTime = 0);
+ mozilla::UniquePtr<char[]> ToJSON(float aSinceTime = 0);
void StreamMetaJSCustomObject(SpliceableJSONWriter& aWriter);
void StreamTaskTracer(SpliceableJSONWriter& aWriter);
void FlushOnJSShutdown(JSRuntime* aRuntime);
bool ProfileJS() const { return mProfileJS; }
bool ProfileJava() const { return mProfileJava; }
bool ProfileGPU() const { return mProfileGPU; }
bool ProfilePower() const { return mProfilePower; }
bool ProfileThreads() const override { return mProfileThreads; }
--- a/tools/profiler/nsProfiler.cpp
+++ b/tools/profiler/nsProfiler.cpp
@@ -114,24 +114,23 @@ nsProfiler::AddMarker(const char *aMarke
{
PROFILER_MARKER(aMarker);
return NS_OK;
}
NS_IMETHODIMP
nsProfiler::GetProfile(float aSinceTime, char **aProfile)
{
- char *profile = profiler_get_profile(aSinceTime);
+ mozilla::UniquePtr<char[]> profile = profiler_get_profile(aSinceTime);
if (profile) {
- size_t len = strlen(profile);
+ size_t len = strlen(profile.get());
char *profileStr = static_cast<char *>
- (nsMemory::Clone(profile, (len + 1) * sizeof(char)));
+ (nsMemory::Clone(profile.get(), (len + 1) * sizeof(char)));
profileStr[len] = '\0';
*aProfile = profileStr;
- free(profile);
}
return NS_OK;
}
static void
AddSharedLibraryInfoToStream(std::ostream& aStream, const SharedLibrary& aLib)
{
aStream << "{";
--- a/tools/profiler/platform.cpp
+++ b/tools/profiler/platform.cpp
@@ -556,27 +556,24 @@ void mozilla_sampler_save()
}
t->RequestSave();
// We're on the main thread already so we don't
// have to wait to handle the save request.
t->HandleSaveRequest();
}
-char* mozilla_sampler_get_profile(float aSinceTime)
+mozilla::UniquePtr<char[]> mozilla_sampler_get_profile(float aSinceTime)
{
TableTicker *t = tlsTicker.get();
if (!t) {
return nullptr;
}
- std::stringstream stream;
- t->ToStreamAsJSON(stream, aSinceTime);
- char* profile = strdup(stream.str().c_str());
- return profile;
+ return t->ToJSON(aSinceTime);
}
JSObject *mozilla_sampler_get_profile_data(JSContext *aCx, float aSinceTime)
{
TableTicker *t = tlsTicker.get();
if (!t) {
return nullptr;
}
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -1007,19 +1007,18 @@ Java_org_mozilla_gecko_ANRReporter_getNa
// Maybe profiler support is disabled?
return nullptr;
}
// Timeout if we don't get a profiler sample after 5 seconds.
const PRIntervalTime timeout = PR_SecondsToInterval(5);
const PRIntervalTime startTime = PR_IntervalNow();
- typedef struct { void operator()(void* p) { free(p); } } ProfilePtrPolicy;
// Pointer to a profile JSON string
- typedef mozilla::UniquePtr<char, ProfilePtrPolicy> ProfilePtr;
+ typedef mozilla::UniquePtr<char[]> ProfilePtr;
ProfilePtr profile(profiler_get_profile());
while (profile && !strstr(profile.get(), "\"samples\":[{")) {
// no sample yet?
if (PR_IntervalNow() - startTime >= timeout) {
return nullptr;
}