mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Merge pull request #5023 from spicyj/jsc-perf
Add rudimentary jsc perf-counters runner
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
build/jsc-perf: src/*
|
||||
mkdir -p build
|
||||
g++ -std=c++11 -I/usr/include/webkitgtk-1.0/ -ljavascriptcoregtk-1.0 src/jsc-perf.cpp src/hardware-counter.cpp src/thread-local.cpp -o build/jsc-perf
|
||||
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* Copyright 2015, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <JavaScriptCore/JavaScript.h>
|
||||
|
||||
#include "hardware-counter.h"
|
||||
|
||||
using HPHP::HardwareCounter;
|
||||
|
||||
void add_native_hook(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef obj,
|
||||
const char *name,
|
||||
JSObjectCallAsFunctionCallback hook
|
||||
) {
|
||||
JSStringRef jsName = JSStringCreateWithUTF8CString(name);
|
||||
JSObjectSetProperty(
|
||||
ctx,
|
||||
obj,
|
||||
jsName,
|
||||
JSObjectMakeFunctionWithCallback(ctx, jsName, hook),
|
||||
kJSPropertyAttributeNone,
|
||||
NULL
|
||||
);
|
||||
JSStringRelease(jsName);
|
||||
}
|
||||
|
||||
static void fprint_value(
|
||||
FILE *file,
|
||||
JSContextRef context,
|
||||
JSValueRef obj
|
||||
) {
|
||||
JSStringRef jsStr = JSValueToStringCopy(context, obj, NULL);
|
||||
size_t size = JSStringGetMaximumUTF8CStringSize(jsStr);
|
||||
char *str = (char *) calloc(
|
||||
size,
|
||||
1
|
||||
);
|
||||
JSStringGetUTF8CString(
|
||||
jsStr,
|
||||
str,
|
||||
size
|
||||
);
|
||||
JSStringRelease(jsStr);
|
||||
fprintf(file, "%s", str);
|
||||
free(str);
|
||||
}
|
||||
|
||||
static JSValueRef js_print(
|
||||
JSContextRef context,
|
||||
JSObjectRef object,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef *exception
|
||||
) {
|
||||
for (int i = 0; i < argumentCount; i++) {
|
||||
if (i != 0) {
|
||||
printf(" ");
|
||||
}
|
||||
fprint_value(stdout, context, arguments[i]);
|
||||
}
|
||||
printf("\n");
|
||||
return JSValueMakeUndefined(context);
|
||||
}
|
||||
|
||||
static JSValueRef js_perf_counters_init(
|
||||
JSContextRef context,
|
||||
JSObjectRef object,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef *exception
|
||||
) {
|
||||
// TODO: Allow customizing recorded events
|
||||
bool enable = true;
|
||||
std::string events = "";
|
||||
bool recordSubprocesses = false;
|
||||
HardwareCounter::Init(enable, events, recordSubprocesses);
|
||||
HardwareCounter::s_counter.getCheck();
|
||||
|
||||
return JSValueMakeUndefined(context);
|
||||
}
|
||||
|
||||
static JSValueRef js_perf_counters_get_counters(
|
||||
JSContextRef context,
|
||||
JSObjectRef object,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef *exception
|
||||
) {
|
||||
JSObjectRef result = JSObjectMake(context, NULL, NULL);
|
||||
std::pair<JSContextRef, JSObjectRef> pair(context, result);
|
||||
|
||||
HardwareCounter::GetPerfEvents(
|
||||
[](const std::string& key, int64_t value, void* data) {
|
||||
std::pair<JSContextRef, JSObjectRef>& pair =
|
||||
*reinterpret_cast<std::pair<JSContextRef, JSObjectRef>*>(data);
|
||||
JSContextRef context = pair.first;
|
||||
JSObjectRef result = pair.second;
|
||||
|
||||
JSObjectSetProperty(
|
||||
context,
|
||||
result,
|
||||
JSStringCreateWithUTF8CString(key.c_str()),
|
||||
JSValueMakeNumber(context, value),
|
||||
kJSPropertyAttributeNone,
|
||||
NULL
|
||||
);
|
||||
},
|
||||
&pair);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: jsc-runner file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *filename = argv[1];
|
||||
std::ifstream ifs(filename);
|
||||
if (ifs.fail()) {
|
||||
std::cerr << "Error opening \"" << filename << "\": " << strerror(errno) << "\n";
|
||||
exit(1);
|
||||
}
|
||||
std::string script(
|
||||
(std::istreambuf_iterator<char>(ifs)),
|
||||
(std::istreambuf_iterator<char>())
|
||||
);
|
||||
JSStringRef jsScript = JSStringCreateWithUTF8CString(script.c_str());
|
||||
JSStringRef jsURL = JSStringCreateWithUTF8CString(argv[1]);
|
||||
|
||||
JSGlobalContextRef ctx = JSGlobalContextCreate(NULL);
|
||||
add_native_hook(
|
||||
ctx,
|
||||
JSContextGetGlobalObject(ctx),
|
||||
"print",
|
||||
js_print
|
||||
);
|
||||
|
||||
JSObjectRef jsPerfCounters = JSObjectMake(ctx, NULL, NULL);
|
||||
add_native_hook(
|
||||
ctx,
|
||||
jsPerfCounters,
|
||||
"init",
|
||||
js_perf_counters_init
|
||||
);
|
||||
add_native_hook(
|
||||
ctx,
|
||||
jsPerfCounters,
|
||||
"getCounters",
|
||||
js_perf_counters_get_counters
|
||||
);
|
||||
JSObjectSetProperty(
|
||||
ctx,
|
||||
JSContextGetGlobalObject(ctx),
|
||||
JSStringCreateWithUTF8CString("PerfCounters"),
|
||||
jsPerfCounters,
|
||||
kJSPropertyAttributeNone,
|
||||
NULL
|
||||
);
|
||||
|
||||
JSValueRef jsError = NULL;
|
||||
JSValueRef result = JSEvaluateScript(
|
||||
ctx,
|
||||
jsScript,
|
||||
NULL,
|
||||
jsURL,
|
||||
0,
|
||||
&jsError
|
||||
);
|
||||
if (!result) {
|
||||
fprintf(stderr, "Exception: ");
|
||||
fprint_value(stderr, ctx, jsError);
|
||||
fprintf(stderr, "\n");
|
||||
JSStringRef jsStackStr = JSStringCreateWithUTF8CString("stack");
|
||||
if (JSValueIsObject(ctx, jsError)) {
|
||||
JSValueRef jsStack = JSObjectGetProperty(ctx, (JSObjectRef)jsError, jsStackStr, NULL);
|
||||
JSStringRelease(jsStackStr);
|
||||
fprint_value(stderr, ctx, jsStack);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
JSGlobalContextRelease(ctx);
|
||||
}
|
||||
Reference in New Issue
Block a user