mirror of
https://github.com/facebook/react.git
synced 2026-02-25 21:35:10 +00:00
* Facebook -> Meta in copyright rg --files | xargs sed -i 's#Copyright (c) Facebook, Inc. and its affiliates.#Copyright (c) Meta Platforms, Inc. and affiliates.#g' * Manual tweaks
203 lines
4.6 KiB
C++
203 lines
4.6 KiB
C++
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#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);
|
|
}
|