Remove legacy JSC profiler
Reviewed By: bnham Differential Revision: D5433406 fbshipit-source-id: 8cbea8b9b46a0d9f29c57a5bcf605e6bb61ed8a7
This commit is contained in:
parent
bf752014a9
commit
ed3c018ee4
|
@ -1,13 +0,0 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#import "JSContextRef.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void nativeProfilerEnableBytecode(void);
|
||||
void nativeProfilerStart(JSContextRef ctx, const char *title);
|
||||
void nativeProfilerEnd(JSContextRef ctx, const char *title, const char *filename);
|
||||
|
||||
}
|
|
@ -1,311 +0,0 @@
|
|||
#include "JSCLegacyProfiler.h"
|
||||
|
||||
#include "APICast.h"
|
||||
#include "LegacyProfiler.h"
|
||||
#include "OpaqueJSString.h"
|
||||
#include "JSProfilerPrivate.h"
|
||||
#include "JSStringRef.h"
|
||||
#include "String.h"
|
||||
#include "Options.h"
|
||||
|
||||
enum json_gen_status {
|
||||
json_gen_status_ok = 0,
|
||||
json_gen_status_error = 1,
|
||||
};
|
||||
|
||||
enum json_entry {
|
||||
json_entry_key,
|
||||
json_entry_value,
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
struct json_state {
|
||||
FILE *fileOut;
|
||||
bool hasFirst;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
typedef json_state *json_gen;
|
||||
|
||||
static void json_escaped_cstring_printf(json_gen gen, const char *str) {
|
||||
const char *cursor = str;
|
||||
fputc('"', gen->fileOut);
|
||||
while (*cursor) {
|
||||
const char *escape = nullptr;
|
||||
switch (*cursor) {
|
||||
case '"':
|
||||
escape = "\\\"";
|
||||
break;
|
||||
case '\b':
|
||||
escape = "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
escape = "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
escape = "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
escape = "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
escape = "\\t";
|
||||
break;
|
||||
case '\\':
|
||||
escape = "\\\\";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (escape != nullptr) {
|
||||
fwrite(escape, 1, strlen(escape), gen->fileOut);
|
||||
} else {
|
||||
fputc(*cursor, gen->fileOut);
|
||||
}
|
||||
cursor++;
|
||||
}
|
||||
fputc('"', gen->fileOut);
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_key_cstring(json_gen gen, const char *buffer) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
gen->hasFirst = true;
|
||||
|
||||
json_escaped_cstring_printf(gen, buffer);
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_map_open(json_gen gen, json_entry entryType) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (entryType == json_entry_value) {
|
||||
fprintf(gen->fileOut, ":");
|
||||
} else if (entryType == json_entry_key) {
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
}
|
||||
fprintf(gen->fileOut, "{");
|
||||
gen->hasFirst = false;
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_map_close(json_gen gen) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
fprintf(gen->fileOut, "}");
|
||||
gen->hasFirst = true;
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_array_open(json_gen gen, json_entry entryType) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (entryType == json_entry_value) {
|
||||
fprintf(gen->fileOut, ":");
|
||||
} else if (entryType == json_entry_key) {
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
}
|
||||
fprintf(gen->fileOut, "[");
|
||||
gen->hasFirst = false;
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_array_close(json_gen gen) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
fprintf(gen->fileOut, "]");
|
||||
gen->hasFirst = true;
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_keyvalue_cstring(json_gen gen, const char *key, const char *value) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
gen->hasFirst = true;
|
||||
|
||||
fprintf(gen->fileOut, "\"%s\" : ", key);
|
||||
json_escaped_cstring_printf(gen, value);
|
||||
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
|
||||
static json_gen_status json_gen_keyvalue_integer(json_gen gen, const char *key, int value) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
gen->hasFirst = true;
|
||||
|
||||
fprintf(gen->fileOut, "\"%s\": %d", key, value);
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status json_gen_keyvalue_double(json_gen gen, const char *key, double value) {
|
||||
if (gen->fileOut == nullptr) {
|
||||
return json_gen_status_error;
|
||||
}
|
||||
|
||||
if (gen->hasFirst) {
|
||||
fprintf(gen->fileOut, ",");
|
||||
}
|
||||
gen->hasFirst = true;
|
||||
|
||||
fprintf(gen->fileOut, "\"%s\": %.20g", key, value);
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen json_gen_alloc(const char *fileName) {
|
||||
json_gen gen = (json_gen)malloc(sizeof(json_state));
|
||||
memset(gen, 0, sizeof(json_state));
|
||||
gen->fileOut = fopen(fileName, "wb");
|
||||
return gen;
|
||||
}
|
||||
|
||||
static void json_gen_free(json_gen gen) {
|
||||
if (gen->fileOut) {
|
||||
fclose(gen->fileOut);
|
||||
}
|
||||
free(gen);
|
||||
}
|
||||
|
||||
#define GEN_AND_CHECK(expr) \
|
||||
do { \
|
||||
json_gen_status GEN_AND_CHECK_status = (expr); \
|
||||
if (GEN_AND_CHECK_status != json_gen_status_ok) { \
|
||||
return GEN_AND_CHECK_status; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
|
||||
static json_gen_status append_children_array_json(json_gen gen, const JSC::ProfileNode *node);
|
||||
static json_gen_status append_node_json(json_gen gen, const JSC::ProfileNode *node);
|
||||
|
||||
static json_gen_status append_root_json(json_gen gen, const JSC::Profile *profile) {
|
||||
GEN_AND_CHECK(json_gen_map_open(gen, json_entry_key));
|
||||
GEN_AND_CHECK(json_gen_key_cstring(gen, "rootNodes"));
|
||||
#if IOS8
|
||||
GEN_AND_CHECK(append_children_array_json(gen, profile->head()));
|
||||
#else
|
||||
GEN_AND_CHECK(append_children_array_json(gen, profile->rootNode()));
|
||||
#endif
|
||||
GEN_AND_CHECK(json_gen_map_close(gen));
|
||||
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status append_children_array_json(json_gen gen, const JSC::ProfileNode *node) {
|
||||
GEN_AND_CHECK(json_gen_array_open(gen, json_entry_value));
|
||||
for (RefPtr<JSC::ProfileNode> child : node->children()) {
|
||||
GEN_AND_CHECK(append_node_json(gen, child.get()));
|
||||
}
|
||||
GEN_AND_CHECK(json_gen_array_close(gen));
|
||||
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static json_gen_status append_node_json(json_gen gen, const JSC::ProfileNode *node) {
|
||||
GEN_AND_CHECK(json_gen_map_open(gen, json_entry_key));
|
||||
GEN_AND_CHECK(json_gen_keyvalue_integer(gen, "id", node->id()));
|
||||
|
||||
if (!node->functionName().isEmpty()) {
|
||||
GEN_AND_CHECK(json_gen_keyvalue_cstring(gen, "functionName", node->functionName().utf8().data()));
|
||||
}
|
||||
|
||||
if (!node->url().isEmpty()) {
|
||||
GEN_AND_CHECK(json_gen_keyvalue_cstring(gen, "url", node->url().utf8().data()));
|
||||
GEN_AND_CHECK(json_gen_keyvalue_integer(gen, "lineNumber", node->lineNumber()));
|
||||
GEN_AND_CHECK(json_gen_keyvalue_integer(gen, "columnNumber", node->columnNumber()));
|
||||
}
|
||||
|
||||
GEN_AND_CHECK(json_gen_key_cstring(gen, "calls"));
|
||||
GEN_AND_CHECK(json_gen_array_open(gen, json_entry_value));
|
||||
for (const JSC::ProfileNode::Call &call : node->calls()) {
|
||||
GEN_AND_CHECK(json_gen_map_open(gen, json_entry_key));
|
||||
GEN_AND_CHECK(json_gen_keyvalue_double(gen, "startTime", call.startTime()));
|
||||
#if IOS8
|
||||
GEN_AND_CHECK(json_gen_keyvalue_double(gen, "totalTime", call.totalTime()));
|
||||
#else
|
||||
GEN_AND_CHECK(json_gen_keyvalue_double(gen, "totalTime", call.elapsedTime()));
|
||||
#endif
|
||||
GEN_AND_CHECK(json_gen_map_close(gen));
|
||||
}
|
||||
GEN_AND_CHECK(json_gen_array_close(gen));
|
||||
|
||||
if (!node->children().isEmpty()) {
|
||||
GEN_AND_CHECK(json_gen_key_cstring(gen, "children"));
|
||||
GEN_AND_CHECK(append_children_array_json(gen, node));
|
||||
}
|
||||
|
||||
GEN_AND_CHECK(json_gen_map_close(gen));
|
||||
|
||||
return json_gen_status_ok;
|
||||
}
|
||||
|
||||
static void convert_to_json(const JSC::Profile *profile, const char *filename) {
|
||||
json_gen_status status;
|
||||
json_gen gen = json_gen_alloc(filename);
|
||||
|
||||
status = append_root_json(gen, profile);
|
||||
if (status != json_gen_status_ok) {
|
||||
FILE *fileOut = fopen(filename, "wb");
|
||||
if (fileOut != nullptr) {
|
||||
fprintf(fileOut, "{\"error\": %d}", (int)status);
|
||||
fclose(fileOut);
|
||||
}
|
||||
}
|
||||
json_gen_free(gen);
|
||||
}
|
||||
|
||||
// Based on JSEndProfiling, with a little extra code to return the profile as JSON.
|
||||
static void JSEndProfilingAndRender(JSContextRef ctx, const char *title, const char *filename)
|
||||
{
|
||||
JSC::ExecState *exec = toJS(ctx);
|
||||
JSC::LegacyProfiler *profiler = JSC::LegacyProfiler::profiler();
|
||||
RefPtr<JSC::Profile> rawProfile = profiler->stopProfiling(exec, WTF::String(title));
|
||||
convert_to_json(rawProfile.get(), filename);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void nativeProfilerEnableBytecode(void)
|
||||
{
|
||||
JSC::Options::setOption("forceProfilerBytecodeGeneration=true");
|
||||
}
|
||||
|
||||
void nativeProfilerStart(JSContextRef ctx, const char *title) {
|
||||
JSStartProfiling(ctx, JSStringCreateWithUTF8CString(title));
|
||||
}
|
||||
|
||||
void nativeProfilerEnd(JSContextRef ctx, const char *title, const char *filename) {
|
||||
JSEndProfilingAndRender(ctx, title, filename);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
ios9:
|
||||
IOS_VERSION=9 \
|
||||
JSC_VERSION=7601.1.46.3 \
|
||||
WEB_CORE_VERSION=7601.1.46.10 \
|
||||
WTF_VERSION=7601.1.46.3 \
|
||||
make -f Makefile.base
|
||||
|
||||
ios8:
|
||||
IOS_VERSION=8 \
|
||||
JSC_VERSION=7600.1.17 \
|
||||
WEB_CORE_VERSION=7600.1.25 \
|
||||
WTF_VERSION=7600.1.24 \
|
||||
make -f Makefile.base
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -rf $(wildcard *.dylib)
|
||||
-rm -rf download
|
|
@ -1,80 +0,0 @@
|
|||
HEADER_PATHS := `find download/JavaScriptCore/JavaScriptCore-$(JSC_VERSION) -name '*.h' | xargs -I{} dirname {} | uniq | xargs -I{} echo "-I {}"`
|
||||
|
||||
XCODE_PATH ?= $(shell xcode-select -p)
|
||||
SDK_PATH = $(XCODE_PATH)/Platforms/$1.platform/Developer/SDKs/$1.sdk
|
||||
SDK_VERSION = $(shell plutil -convert json -o - $(call SDK_PATH,iPhoneOS)/SDKSettings.plist | awk -f parseSDKVersion.awk)
|
||||
|
||||
CERT ?= iPhone Developer
|
||||
|
||||
ARCHS = x86_64 arm64 armv7 i386
|
||||
|
||||
PLATFORM = \
|
||||
if [[ "$*" = "x86_64" || "$*" = "i386" ]]; then \
|
||||
PLATFORM=iPhoneSimulator; \
|
||||
else \
|
||||
PLATFORM=iPhoneOS; \
|
||||
fi;
|
||||
|
||||
SYSROOT = -isysroot $(call SDK_PATH,$${PLATFORM})
|
||||
|
||||
IOS_LIBS = \
|
||||
download/JavaScriptCore/JavaScriptCore-$(JSC_VERSION) \
|
||||
download/WebCore/WebCore-$(WEB_CORE_VERSION) \
|
||||
download/WTF/WTF-$(WTF_VERSION) \
|
||||
download/JavaScriptCore/JavaScriptCore-$(JSC_VERSION)/Bytecodes.h
|
||||
|
||||
IOS_EXT=ios$(IOS_VERSION)
|
||||
|
||||
ifneq ($(SDK_VERSION), $(IOS_VERSION))
|
||||
|
||||
all:
|
||||
$(error "Expected to be compiled with iOS SDK version 8, found $(SDK_VERSION)")
|
||||
|
||||
else
|
||||
|
||||
all: RCTJSCProfiler.$(IOS_EXT).dylib /tmp/RCTJSCProfiler
|
||||
cp $^
|
||||
|
||||
endif
|
||||
|
||||
/tmp/RCTJSCProfiler:
|
||||
mkdir -p $@
|
||||
|
||||
RCTJSCProfiler.$(IOS_EXT).dylib: RCTJSCProfiler_unsigned.$(IOS_EXT).dylib
|
||||
cp $< $@
|
||||
codesign -f -s "${CERT}" $@
|
||||
|
||||
.PRECIOUS: RCTJSCProfiler_unsigned.$(IOS_EXT).dylib
|
||||
RCTJSCProfiler_unsigned.$(IOS_EXT).dylib: $(patsubst %,RCTJSCProfiler_%.$(IOS_EXT).dylib,$(ARCHS))
|
||||
lipo -create -output $@ $^
|
||||
|
||||
.PRECIOUS: RCTJSCProfiler_%.$(IOS_EXT).dylib
|
||||
RCTJSCProfiler_%.$(IOS_EXT).dylib: $(IOS_LIBS)
|
||||
$(PLATFORM) \
|
||||
clang -w -dynamiclib -o RCTJSCProfiler_$*.$(IOS_EXT).dylib -std=c++11 \
|
||||
-arch $* \
|
||||
-install_name RCTJSCProfiler.$(IOS_EXT).dylib \
|
||||
-include ./download/JavaScriptCore/JavaScriptCore-$(JSC_VERSION)/config.h \
|
||||
-I download \
|
||||
-I download/WebCore/WebCore-$(WEB_CORE_VERSION)/icu \
|
||||
-I download/WTF/WTF-$(WTF_VERSION) \
|
||||
-DNDEBUG=1 \
|
||||
-DIOS$(IOS_VERSION)=1 \
|
||||
-miphoneos-version-min=8.0 \
|
||||
$(SYSROOT) \
|
||||
$(HEADER_PATHS) \
|
||||
-undefined dynamic_lookup \
|
||||
JSCLegacyProfiler.mm
|
||||
|
||||
.PRECIOUS: %/Bytecodes.h
|
||||
%/Bytecodes.h:
|
||||
python $*/generate-bytecode-files --bytecodes_h $@ $*/bytecode/BytecodeList.json
|
||||
|
||||
.PRECIOUS: download/%
|
||||
download/%: download/%.tar.gz
|
||||
tar -zxvf $< -C `dirname $@` > /dev/null
|
||||
|
||||
.PRECIOUS: %.tar.gz
|
||||
%.tar.gz:
|
||||
mkdir -p `dirname $@`
|
||||
curl -o $@ http://www.opensource.apple.com/tarballs/$(patsubst download/%,%,$@)
|
|
@ -1,254 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import smap
|
||||
import trace_data
|
||||
import urllib
|
||||
|
||||
SECONDS_TO_NANOSECONDS = (1000*1000)
|
||||
SAMPLE_DELTA_IN_SECONDS = 0.0001
|
||||
|
||||
class Marker(object):
|
||||
def __init__(self, _name, _timestamp, _depth, _is_end, _ident, url, line, col):
|
||||
self.name = _name
|
||||
self.timestamp = _timestamp
|
||||
self.depth = _depth
|
||||
self.is_end = _is_end
|
||||
self.ident = _ident
|
||||
self.url = url
|
||||
self.line = line
|
||||
self.col = col
|
||||
|
||||
# sort markers making sure they are ordered by timestamp then depth of function call
|
||||
# and finally that markers of the same ident are sorted in the order begin then end
|
||||
def __cmp__(self, other):
|
||||
if self.timestamp < other.timestamp:
|
||||
return -1
|
||||
if self.timestamp > other.timestamp:
|
||||
return 1
|
||||
if self.depth < other.depth:
|
||||
return -1
|
||||
if self.depth > other.depth:
|
||||
return 1
|
||||
if self.ident == other.ident:
|
||||
if self.is_end:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# calculate marker name based on combination of function name and location
|
||||
def _calcname(entry):
|
||||
funcname = ""
|
||||
if "functionName" in entry:
|
||||
funcname = funcname + entry["functionName"]
|
||||
return funcname
|
||||
|
||||
def _calcurl(mapcache, entry, map_file):
|
||||
if entry.url not in mapcache:
|
||||
map_url = entry.url.replace('.bundle', '.map')
|
||||
|
||||
if map_url != entry.url:
|
||||
if map_file:
|
||||
print('Loading sourcemap from:' + map_file)
|
||||
map_url = map_file
|
||||
|
||||
try:
|
||||
url_file = urllib.urlopen(map_url)
|
||||
if url_file != None:
|
||||
entries = smap.parse(url_file)
|
||||
mapcache[entry.url] = entries
|
||||
except Exception, e:
|
||||
mapcache[entry.url] = []
|
||||
|
||||
if entry.url in mapcache:
|
||||
source_entry = smap.find(mapcache[entry.url], entry.line, entry.col)
|
||||
if source_entry:
|
||||
entry.url = 'file://' + source_entry.src
|
||||
entry.line = source_entry.src_line
|
||||
entry.col = source_entry.src_col
|
||||
|
||||
def _compute_markers(markers, call_point, depth):
|
||||
name = _calcname(call_point)
|
||||
ident = len(markers)
|
||||
url = ""
|
||||
lineNumber = -1
|
||||
columnNumber = -1
|
||||
if "url" in call_point:
|
||||
url = call_point["url"]
|
||||
if "lineNumber" in call_point:
|
||||
lineNumber = call_point["lineNumber"]
|
||||
if "columnNumber" in call_point:
|
||||
columnNumber = call_point["columnNumber"]
|
||||
|
||||
for call in call_point["calls"]:
|
||||
markers.append(Marker(name, call["startTime"], depth, 0, ident, url, lineNumber, columnNumber))
|
||||
markers.append(Marker(name, call["startTime"] + call["totalTime"], depth, 1, ident, url, lineNumber, columnNumber))
|
||||
ident = ident + 2
|
||||
if "children" in call_point:
|
||||
for child in call_point["children"]:
|
||||
_compute_markers(markers, child, depth+1);
|
||||
|
||||
def _find_child(children, name):
|
||||
for child in children:
|
||||
if child['functionName'] == name:
|
||||
return child
|
||||
return None
|
||||
|
||||
def _add_entry_cpuprofiler_program(newtime, cpuprofiler):
|
||||
curnode = _find_child(cpuprofiler['head']['children'], '(program)')
|
||||
if cpuprofiler['lastTime'] != None:
|
||||
lastTime = cpuprofiler['lastTime']
|
||||
while lastTime < newtime:
|
||||
curnode['hitCount'] += 1
|
||||
cpuprofiler['samples'].append(curnode['callUID'])
|
||||
cpuprofiler['timestamps'].append(int(lastTime*SECONDS_TO_NANOSECONDS))
|
||||
lastTime += SAMPLE_DELTA_IN_SECONDS
|
||||
cpuprofiler['lastTime'] = lastTime
|
||||
else:
|
||||
cpuprofiler['lastTime'] = newtime
|
||||
|
||||
|
||||
def _add_entry_cpuprofiler(stack, newtime, cpuprofiler):
|
||||
index = len(stack) - 1
|
||||
marker = stack[index]
|
||||
|
||||
if marker.name not in cpuprofiler['markers']:
|
||||
cpuprofiler['markers'][marker.name] = cpuprofiler['id']
|
||||
cpuprofiler['callUID'] += 1
|
||||
callUID = cpuprofiler['markers'][marker.name]
|
||||
|
||||
curnode = cpuprofiler['head']
|
||||
index = 0
|
||||
while index < len(stack):
|
||||
newnode = _find_child(curnode['children'], stack[index].name)
|
||||
if newnode == None:
|
||||
newnode = {}
|
||||
newnode['callUID'] = callUID
|
||||
newnode['url'] = marker.url
|
||||
newnode['functionName'] = stack[index].name
|
||||
newnode['hitCount'] = 0
|
||||
newnode['lineNumber'] = marker.line
|
||||
newnode['columnNumber'] = marker.col
|
||||
newnode['scriptId'] = callUID
|
||||
newnode['positionTicks'] = []
|
||||
newnode['id'] = cpuprofiler['id']
|
||||
cpuprofiler['id'] += 1
|
||||
newnode['children'] = []
|
||||
curnode['children'].append(newnode)
|
||||
curnode['deoptReason'] = ''
|
||||
curnode = newnode
|
||||
index += 1
|
||||
|
||||
if cpuprofiler['lastTime'] == None:
|
||||
cpuprofiler['lastTime'] = newtime
|
||||
|
||||
if cpuprofiler['lastTime'] != None:
|
||||
lastTime = cpuprofiler['lastTime']
|
||||
while lastTime < newtime:
|
||||
curnode['hitCount'] += 1
|
||||
if len(curnode['positionTicks']) == 0:
|
||||
ticks = {}
|
||||
ticks['line'] = curnode['callUID']
|
||||
ticks['ticks'] = 0
|
||||
curnode['positionTicks'].append(ticks)
|
||||
curnode['positionTicks'][0]['ticks'] += 1
|
||||
cpuprofiler['samples'].append(curnode['callUID'])
|
||||
cpuprofiler['timestamps'].append(int(lastTime*1000*1000))
|
||||
lastTime += 0.0001
|
||||
cpuprofiler['lastTime'] = lastTime
|
||||
|
||||
def _create_default_cpuprofiler_node(name, _id, _uid):
|
||||
return {'functionName': name,
|
||||
'scriptId':'0',
|
||||
'url':'',
|
||||
'lineNumber':0,
|
||||
'columnNumber':0,
|
||||
'positionTicks':[],
|
||||
'id':_id,
|
||||
'callUID':_uid,
|
||||
'children': [],
|
||||
'hitCount': 0,
|
||||
'deoptReason':''}
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Converts JSON profile format to fbsystrace text output")
|
||||
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
dest = "output_file",
|
||||
default = None,
|
||||
help = "Output file for trace data")
|
||||
parser.add_argument(
|
||||
"-cpuprofiler",
|
||||
dest = "output_cpuprofiler",
|
||||
default = None,
|
||||
help = "Output file for cpuprofiler data")
|
||||
parser.add_argument(
|
||||
"-map",
|
||||
dest = "map_file",
|
||||
default = None,
|
||||
help = "Map file for symbolicating")
|
||||
parser.add_argument( "file", help = "JSON trace input_file")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
markers = []
|
||||
with open(args.file, "r") as trace_file:
|
||||
trace = json.load(trace_file)
|
||||
for root_entry in trace["rootNodes"]:
|
||||
_compute_markers(markers, root_entry, 0)
|
||||
|
||||
mapcache = {}
|
||||
for m in markers:
|
||||
_calcurl(mapcache, m, args.map_file)
|
||||
|
||||
sorted_markers = list(sorted(markers));
|
||||
|
||||
if args.output_cpuprofiler != None:
|
||||
cpuprofiler = {}
|
||||
cpuprofiler['startTime'] = None
|
||||
cpuprofiler['endTime'] = None
|
||||
cpuprofiler['lastTime'] = None
|
||||
cpuprofiler['id'] = 4
|
||||
cpuprofiler['callUID'] = 4
|
||||
cpuprofiler['samples'] = []
|
||||
cpuprofiler['timestamps'] = []
|
||||
cpuprofiler['markers'] = {}
|
||||
cpuprofiler['head'] = _create_default_cpuprofiler_node('(root)', 1, 1)
|
||||
cpuprofiler['head']['children'].append(_create_default_cpuprofiler_node('(root)', 2, 2))
|
||||
cpuprofiler['head']['children'].append(_create_default_cpuprofiler_node('(program)', 3, 3))
|
||||
marker_stack = []
|
||||
with open(args.output_cpuprofiler, 'w') as file_out:
|
||||
for marker in sorted_markers:
|
||||
if len(marker_stack):
|
||||
_add_entry_cpuprofiler(marker_stack, marker.timestamp, cpuprofiler)
|
||||
else:
|
||||
_add_entry_cpuprofiler_program(marker.timestamp, cpuprofiler)
|
||||
if marker.is_end:
|
||||
marker_stack.pop()
|
||||
else:
|
||||
marker_stack.append(marker)
|
||||
cpuprofiler['startTime'] = cpuprofiler['timestamps'][0] / 1000000.0
|
||||
cpuprofiler['endTime'] = cpuprofiler['timestamps'][len(cpuprofiler['timestamps']) - 1] / 1000000.0
|
||||
json.dump(cpuprofiler, file_out, sort_keys=False, indent=4, separators=(',', ': '))
|
||||
|
||||
|
||||
if args.output_file != None:
|
||||
with open(args.output_file,"w") as trace_file:
|
||||
for marker in sorted_markers:
|
||||
start_or_end = None
|
||||
if marker.is_end:
|
||||
start_or_end = "E"
|
||||
else:
|
||||
start_or_end = "B"
|
||||
#output with timestamp at high level of precision
|
||||
trace_file.write("json-0 [000] .... {0:.12f}: tracing_mark_write: {1}|0|{2}\n".format(
|
||||
marker.timestamp,
|
||||
start_or_end,
|
||||
marker.name))
|
||||
|
||||
main()
|
|
@ -1,10 +0,0 @@
|
|||
BEGIN {
|
||||
FS = ":"
|
||||
RS = ","
|
||||
}
|
||||
|
||||
/"Version"/ {
|
||||
version = substr($2, 2, length($2) - 2)
|
||||
print int(version)
|
||||
exit 0
|
||||
}
|
|
@ -1,343 +0,0 @@
|
|||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
"""
|
||||
adapted from https://github.com/martine/python-sourcemap into a reuasable module
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2010
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
"""A module for parsing source maps, as output by the Closure and
|
||||
CoffeeScript compilers and consumed by browsers. See
|
||||
http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/
|
||||
"""
|
||||
|
||||
import collections
|
||||
import json
|
||||
import sys
|
||||
import bisect
|
||||
|
||||
class entry(object):
|
||||
def __init__(self, dst_line, dst_col, src, src_line, src_col):
|
||||
self.dst_line = dst_line
|
||||
self.dst_col = dst_col
|
||||
self.src = src
|
||||
self.src_line = src_line
|
||||
self.src_col = src_col
|
||||
|
||||
def __cmp__(self, other):
|
||||
#print(self)
|
||||
#print(other)
|
||||
if self.dst_line < other.dst_line:
|
||||
return -1
|
||||
if self.dst_line > other.dst_line:
|
||||
return 1
|
||||
if self.dst_col < other.dst_col:
|
||||
return -1
|
||||
if self.dst_col > other.dst_col:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
SmapState = collections.namedtuple(
|
||||
'SmapState', ['dst_line', 'dst_col',
|
||||
'src', 'src_line', 'src_col',
|
||||
'name'])
|
||||
|
||||
# Mapping of base64 letter -> integer value.
|
||||
B64 = dict((c, i) for i, c in
|
||||
enumerate('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
||||
'0123456789+/'))
|
||||
|
||||
|
||||
def _parse_vlq(segment):
|
||||
"""Parse a string of VLQ-encoded data.
|
||||
|
||||
Returns:
|
||||
a list of integers.
|
||||
"""
|
||||
|
||||
values = []
|
||||
|
||||
cur, shift = 0, 0
|
||||
for c in segment:
|
||||
val = B64[c]
|
||||
# Each character is 6 bits:
|
||||
# 5 of value and the high bit is the continuation.
|
||||
val, cont = val & 0b11111, val >> 5
|
||||
cur += val << shift
|
||||
shift += 5
|
||||
|
||||
if not cont:
|
||||
# The low bit of the unpacked value is the sign.
|
||||
cur, sign = cur >> 1, cur & 1
|
||||
if sign:
|
||||
cur = -cur
|
||||
values.append(cur)
|
||||
cur, shift = 0, 0
|
||||
|
||||
if cur or shift:
|
||||
raise Exception('leftover cur/shift in vlq decode')
|
||||
|
||||
return values
|
||||
|
||||
|
||||
def _parse_smap(file):
|
||||
"""Given a file-like object, yield SmapState()s as they are read from it."""
|
||||
|
||||
smap = json.load(file)
|
||||
sources = smap['sources']
|
||||
names = smap['names']
|
||||
mappings = smap['mappings']
|
||||
lines = mappings.split(';')
|
||||
|
||||
dst_col, src_id, src_line, src_col, name_id = 0, 0, 0, 0, 0
|
||||
for dst_line, line in enumerate(lines):
|
||||
segments = line.split(',')
|
||||
dst_col = 0
|
||||
for segment in segments:
|
||||
if not segment:
|
||||
continue
|
||||
parsed = _parse_vlq(segment)
|
||||
dst_col += parsed[0]
|
||||
|
||||
src = None
|
||||
name = None
|
||||
if len(parsed) > 1:
|
||||
src_id += parsed[1]
|
||||
src = sources[src_id]
|
||||
src_line += parsed[2]
|
||||
src_col += parsed[3]
|
||||
|
||||
if len(parsed) > 4:
|
||||
name_id += parsed[4]
|
||||
name = names[name_id]
|
||||
|
||||
assert dst_line >= 0
|
||||
assert dst_col >= 0
|
||||
assert src_line >= 0
|
||||
assert src_col >= 0
|
||||
|
||||
yield SmapState(dst_line, dst_col, src, src_line, src_col, name)
|
||||
|
||||
def find(entries, line, col):
|
||||
test = entry(line, col, '', 0, 0)
|
||||
index = bisect.bisect_right(entries, test)
|
||||
if index == 0:
|
||||
return None
|
||||
return entries[index - 1]
|
||||
|
||||
def parse(file):
|
||||
# Simple demo that shows files that most contribute to total size.
|
||||
lookup = []
|
||||
for state in _parse_smap(file):
|
||||
lookup.append(entry(state.dst_line, state.dst_col, state.src, state.src_line, state.src_col))
|
||||
|
||||
sorted_lookup = list(sorted(lookup))
|
||||
return sorted_lookup
|
|
@ -1,244 +0,0 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import re
|
||||
import unittest
|
||||
|
||||
"""
|
||||
# _-----=> irqs-off
|
||||
# / _----=> need-resched
|
||||
# | / _---=> hardirq/softirq
|
||||
# || / _--=> preempt-depth
|
||||
# ||| / delay
|
||||
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
|
||||
# | | | |||| | |
|
||||
<idle>-0 [001] ...2 3269.291072: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=mmcqd/0 next_pid=120 next_prio=120
|
||||
"""
|
||||
TRACE_LINE_PATTERN = re.compile(
|
||||
r'^\s*(?P<task>.+)-(?P<pid>\d+)\s+(?:\((?P<tgid>.+)\)\s+)?\[(?P<cpu>\d+)\]\s+(?:(?P<flags>\S{4})\s+)?(?P<timestamp>[0-9.]+):\s+(?P<function>.+)$')
|
||||
|
||||
"""
|
||||
Example lines from custom app traces:
|
||||
0: B|27295|providerRemove
|
||||
0: E
|
||||
tracing_mark_write: S|27311|NNFColdStart<D-7744962>|1112249168
|
||||
"""
|
||||
APP_TRACE_LINE_PATTERN = re.compile(
|
||||
r'^(?P<type>.+?): (?P<args>.+)$')
|
||||
|
||||
"""
|
||||
Example section names:
|
||||
NNFColdStart
|
||||
NNFColdStart<0><T7744962>
|
||||
NNFColdStart<X>
|
||||
NNFColdStart<T7744962>
|
||||
"""
|
||||
DECORATED_SECTION_NAME_PATTERN = re.compile(r'^(?P<section_name>.*?)(?:<0>)?(?:<(?P<command>.)(?P<argument>.*?)>)?$')
|
||||
|
||||
SYSTRACE_LINE_TYPES = set(['0', 'tracing_mark_write'])
|
||||
|
||||
class TraceLine(object):
|
||||
def __init__(self, task, pid, tgid, cpu, flags, timestamp, function):
|
||||
self.task = task
|
||||
self.pid = pid
|
||||
self.tgid = tgid
|
||||
self.cpu = cpu
|
||||
self.flags = flags
|
||||
self.timestamp = timestamp
|
||||
self.function = function
|
||||
self.canceled = False
|
||||
|
||||
@property
|
||||
def is_app_trace_line(self):
|
||||
return isinstance(self.function, AppTraceFunction)
|
||||
|
||||
def cancel(self):
|
||||
self.canceled = True
|
||||
|
||||
def __str__(self):
|
||||
if self.canceled:
|
||||
return ""
|
||||
elif self.tgid:
|
||||
return "{task:>16s}-{pid:<5d} ({tgid:5s}) [{cpu:03d}] {flags:4s} {timestamp:12f}: {function}\n".format(**vars(self))
|
||||
elif self.flags:
|
||||
return "{task:>16s}-{pid:<5d} [{cpu:03d}] {flags:4s} {timestamp:12f}: {function}\n".format(**vars(self))
|
||||
else:
|
||||
return "{task:>16s}-{pid:<5d} [{cpu:03d}] {timestamp:12.6f}: {function}\n".format(**vars(self))
|
||||
|
||||
|
||||
class AppTraceFunction(object):
|
||||
def __init__(self, type, args):
|
||||
self.type = type
|
||||
self.args = args
|
||||
self.operation = args[0]
|
||||
|
||||
if len(args) >= 2 and args[1]:
|
||||
self.pid = int(args[1])
|
||||
if len(args) >= 3:
|
||||
self._section_name, self.command, self.argument = _parse_section_name(args[2])
|
||||
args[2] = self._section_name
|
||||
else:
|
||||
self._section_name = None
|
||||
self.command = None
|
||||
self.argument = None
|
||||
self.cookie = None
|
||||
|
||||
@property
|
||||
def section_name(self):
|
||||
return self._section_name
|
||||
|
||||
@section_name.setter
|
||||
def section_name(self, value):
|
||||
self._section_name = value
|
||||
self.args[2] = value
|
||||
|
||||
def __str__(self):
|
||||
return "{type}: {args}".format(type=self.type, args='|'.join(self.args))
|
||||
|
||||
|
||||
class AsyncTraceFunction(AppTraceFunction):
|
||||
def __init__(self, type, args):
|
||||
super(AsyncTraceFunction, self).__init__(type, args)
|
||||
|
||||
self.cookie = int(args[3])
|
||||
|
||||
|
||||
TRACE_TYPE_MAP = {
|
||||
'S': AsyncTraceFunction,
|
||||
'T': AsyncTraceFunction,
|
||||
'F': AsyncTraceFunction,
|
||||
}
|
||||
|
||||
def parse_line(line):
|
||||
match = TRACE_LINE_PATTERN.match(line.strip())
|
||||
if not match:
|
||||
return None
|
||||
|
||||
task = match.group("task")
|
||||
pid = int(match.group("pid"))
|
||||
tgid = match.group("tgid")
|
||||
cpu = int(match.group("cpu"))
|
||||
flags = match.group("flags")
|
||||
timestamp = float(match.group("timestamp"))
|
||||
function = match.group("function")
|
||||
|
||||
app_trace = _parse_function(function)
|
||||
if app_trace:
|
||||
function = app_trace
|
||||
|
||||
return TraceLine(task, pid, tgid, cpu, flags, timestamp, function)
|
||||
|
||||
def parse_dextr_line(line):
|
||||
task = line["name"]
|
||||
pid = line["pid"]
|
||||
tgid = line["tid"]
|
||||
cpu = None
|
||||
flags = None
|
||||
timestamp = line["ts"]
|
||||
function = AppTraceFunction("DextrTrace", [line["ph"], line["pid"], line["name"]])
|
||||
|
||||
return TraceLine(task, pid, tgid, cpu, flags, timestamp, function)
|
||||
|
||||
|
||||
def _parse_function(function):
|
||||
line_match = APP_TRACE_LINE_PATTERN.match(function)
|
||||
if not line_match:
|
||||
return None
|
||||
|
||||
type = line_match.group("type")
|
||||
if not type in SYSTRACE_LINE_TYPES:
|
||||
return None
|
||||
|
||||
args = line_match.group("args").split('|')
|
||||
if len(args) == 1 and len(args[0]) == 0:
|
||||
args = None
|
||||
|
||||
constructor = TRACE_TYPE_MAP.get(args[0], AppTraceFunction)
|
||||
return constructor(type, args)
|
||||
|
||||
|
||||
def _parse_section_name(section_name):
|
||||
if section_name is None:
|
||||
return section_name, None, None
|
||||
|
||||
section_name_match = DECORATED_SECTION_NAME_PATTERN.match(section_name)
|
||||
section_name = section_name_match.group("section_name")
|
||||
command = section_name_match.group("command")
|
||||
argument = section_name_match.group("argument")
|
||||
return section_name, command, argument
|
||||
|
||||
|
||||
def _format_section_name(section_name, command, argument):
|
||||
if not command:
|
||||
return section_name
|
||||
|
||||
return "{section_name}<{command}{argument}>".format(**vars())
|
||||
|
||||
|
||||
class RoundTripFormattingTests(unittest.TestCase):
|
||||
def testPlainSectionName(self):
|
||||
section_name = "SectionName12345-5562342fas"
|
||||
|
||||
self.assertEqual(section_name, _format_section_name(*_parse_section_name(section_name)))
|
||||
|
||||
def testDecoratedSectionName(self):
|
||||
section_name = "SectionName12345-5562342fas<D-123456>"
|
||||
|
||||
self.assertEqual(section_name, _format_section_name(*_parse_section_name(section_name)))
|
||||
|
||||
def testSimpleFunction(self):
|
||||
function = "0: E"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testFunctionWithoutCookie(self):
|
||||
function = "0: B|27295|providerRemove"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testFunctionWithCookie(self):
|
||||
function = "0: S|27311|NNFColdStart|1112249168"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testFunctionWithCookieAndArgs(self):
|
||||
function = "0: T|27311|NNFColdStart|1122|Start"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testFunctionWithArgsButNoPid(self):
|
||||
function = "0: E|||foo=bar"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testKitKatFunction(self):
|
||||
function = "tracing_mark_write: B|14127|Looper.dispatchMessage|arg=>>>>> Dispatching to Handler (android.os.Handler) {422ae980} null: 0|Java"
|
||||
|
||||
self.assertEqual(function, str(_parse_function(function)))
|
||||
|
||||
def testNonSysTraceFunctionIgnored(self):
|
||||
function = "sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=mmcqd/0 next_pid=120 next_prio=120"
|
||||
|
||||
self.assertEqual(None, _parse_function(function))
|
||||
|
||||
def testLineWithFlagsAndTGID(self):
|
||||
line = " <idle>-0 ( 550) [000] d..2 7953.258473: cpu_idle: state=1 cpu_id=0\n"
|
||||
|
||||
self.assertEqual(line, str(parse_line(line)))
|
||||
|
||||
def testLineWithFlagsAndNoTGID(self):
|
||||
line = " <idle>-0 (-----) [000] d..2 7953.258473: cpu_idle: state=1 cpu_id=0\n"
|
||||
|
||||
self.assertEqual(line, str(parse_line(line)))
|
||||
|
||||
def testLineWithFlags(self):
|
||||
line = " <idle>-0 [001] ...2 3269.291072: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=mmcqd/0 next_pid=120 next_prio=120\n"
|
||||
|
||||
self.assertEqual(line, str(parse_line(line)))
|
||||
|
||||
def testLineWithoutFlags(self):
|
||||
line = " <idle>-0 [001] 3269.291072: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=mmcqd/0 next_pid=120 next_prio=120\n"
|
||||
|
||||
self.assertEqual(line, str(parse_line(line)))
|
|
@ -1,43 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, 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.
|
||||
*
|
||||
* @providesModule CPUProfiler
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var _label;
|
||||
var _nestingLevel = 0;
|
||||
|
||||
var CPUProfiler = {
|
||||
|
||||
start(profileName: string) {
|
||||
if (_nestingLevel === 0) {
|
||||
if (global.nativeProfilerStart) {
|
||||
_label = profileName;
|
||||
global.nativeProfilerStart(profileName);
|
||||
} else if (console.profile) {
|
||||
console.profile(profileName);
|
||||
}
|
||||
}
|
||||
_nestingLevel++;
|
||||
},
|
||||
end() {
|
||||
_nestingLevel--;
|
||||
if (_nestingLevel === 0) {
|
||||
if (global.nativeProfilerEnd) {
|
||||
global.nativeProfilerEnd(_label);
|
||||
} else if (console.profileEnd) {
|
||||
console.profileEnd();
|
||||
}
|
||||
_label = undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CPUProfiler;
|
|
@ -117,13 +117,6 @@ public:
|
|||
callback:m_errorBlock];
|
||||
}
|
||||
|
||||
virtual bool supportsProfiling() override {
|
||||
return false;
|
||||
};
|
||||
virtual void startProfiler(const std::string &titleString) override {};
|
||||
virtual void stopProfiler(const std::string &titleString,
|
||||
const std::string &filename) override {};
|
||||
|
||||
private:
|
||||
id<RCTJavaScriptExecutor> m_jse;
|
||||
RCTJavaScriptCompleteBlock m_errorBlock;
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#import <React/RCTProfile.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
#import "RCTJSCProfiler.h"
|
||||
|
||||
#if (RCT_PROFILE || RCT_DEV) && __has_include("RCTDevMenu.h")
|
||||
#import "RCTDevMenu.h"
|
||||
#endif
|
||||
|
@ -164,34 +162,6 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init)
|
|||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
#if RCT_DEV
|
||||
static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
|
||||
{
|
||||
#if __has_include("RCTDevMenu.h")
|
||||
__weak RCTBridge *weakBridge = bridge;
|
||||
__weak RCTDevSettings *devSettings = bridge.devSettings;
|
||||
if (RCTJSCProfilerIsSupported()) {
|
||||
[bridge.devMenu addItem:[RCTDevMenuItem buttonItemWithTitleBlock:^NSString *{
|
||||
return devSettings.isJSCProfilingEnabled ? @"Stop Profiling" : @"Start Profiling";
|
||||
} handler:^{
|
||||
BOOL shouldStart = !devSettings.isJSCProfilingEnabled;
|
||||
devSettings.isJSCProfilingEnabled = shouldStart;
|
||||
if (shouldStart != RCTJSCProfilerIsProfiling(context)) {
|
||||
if (shouldStart) {
|
||||
RCTJSCProfilerStart(context);
|
||||
} else {
|
||||
NSString *outputFile = RCTJSCProfilerStop(context);
|
||||
NSData *profileData = [NSData dataWithContentsOfFile:outputFile options:NSDataReadingMappedIfSafe error:NULL];
|
||||
RCTProfileSendResult(weakBridge, @"cpu-profile", profileData);
|
||||
}
|
||||
}
|
||||
}]];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+ (void)runRunLoopThread
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
@ -420,8 +390,6 @@ static NSThread *newJavaScriptThread(void)
|
|||
#endif
|
||||
|
||||
#if RCT_DEV
|
||||
RCTInstallJSCProfiler(self->_bridge, context.JSGlobalContextRef);
|
||||
|
||||
// Inject handler used by HMR
|
||||
context[@"nativeInjectHMRUpdate"] = ^(NSString *sourceCode, NSString *sourceCodeURL) {
|
||||
RCTJSCExecutor *strongSelf = weakSelf;
|
||||
|
|
|
@ -92,11 +92,6 @@
|
|||
*/
|
||||
@property (nonatomic, assign) BOOL isPerfMonitorShown;
|
||||
|
||||
/**
|
||||
* Whether JSC profiling is enabled.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL isJSCProfilingEnabled;
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
- (void)addHandler:(id<RCTPackagerClientMethod>)handler forPackagerMethod:(NSString *)name;
|
||||
|
|
|
@ -32,7 +32,6 @@ NSString *const kRCTDevSettingIsDebuggingRemotely = @"isDebuggingRemotely";
|
|||
NSString *const kRCTDevSettingExecutorOverrideClass = @"executor-override";
|
||||
NSString *const kRCTDevSettingShakeToShowDevMenu = @"shakeToShow";
|
||||
NSString *const kRCTDevSettingIsPerfMonitorShown = @"RCTPerfMonitorKey";
|
||||
NSString *const kRCTDevSettingIsJSCProfilingEnabled = @"RCTJSCProfilerEnabled";
|
||||
NSString *const kRCTDevSettingStartSamplingProfilerOnLaunch = @"startSamplingProfilerOnLaunch";
|
||||
|
||||
NSString *const kRCTDevSettingsUserDefaultsKey = @"RCTDevMenu";
|
||||
|
@ -373,16 +372,6 @@ RCT_EXPORT_METHOD(toggleElementInspector)
|
|||
return [[self settingForKey:kRCTDevSettingIsPerfMonitorShown] boolValue];
|
||||
}
|
||||
|
||||
- (void)setIsJSCProfilingEnabled:(BOOL)isJSCProfilingEnabled
|
||||
{
|
||||
[self _updateSettingWithValue:@(isJSCProfilingEnabled) forKey:kRCTDevSettingIsJSCProfilingEnabled];
|
||||
}
|
||||
|
||||
- (BOOL)isJSCProfilingEnabled
|
||||
{
|
||||
return [[self settingForKey:kRCTDevSettingIsJSCProfilingEnabled] boolValue];
|
||||
}
|
||||
|
||||
- (void)setStartSamplingProfilerOnLaunch:(BOOL)startSamplingProfilerOnLaunch
|
||||
{
|
||||
[self _updateSettingWithValue:@(startSamplingProfilerOnLaunch) forKey:kRCTDevSettingStartSamplingProfilerOnLaunch];
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, 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.
|
||||
*/
|
||||
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
#import <React/RCTDefines.h>
|
||||
|
||||
/** The API is not thread-safe. */
|
||||
|
||||
/** The context is not retained. */
|
||||
RCT_EXTERN void RCTJSCProfilerStart(JSContextRef ctx);
|
||||
/** Returns a file path containing the profiler data. */
|
||||
RCT_EXTERN NSString *RCTJSCProfilerStop(JSContextRef ctx);
|
||||
|
||||
RCT_EXTERN BOOL RCTJSCProfilerIsProfiling(JSContextRef ctx);
|
||||
RCT_EXTERN BOOL RCTJSCProfilerIsSupported(void);
|
|
@ -1,135 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, 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.
|
||||
*/
|
||||
|
||||
#import "RCTJSCProfiler.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTLog.h>
|
||||
|
||||
#ifndef RCT_JSC_PROFILER
|
||||
#define RCT_JSC_PROFILER RCT_PROFILE
|
||||
#endif
|
||||
|
||||
#if RCT_JSC_PROFILER
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifndef RCT_JSC_PROFILER_DYLIB
|
||||
#define RCT_JSC_PROFILER_DYLIB [[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"RCTJSCProfiler.ios%zd", [[[UIDevice currentDevice] systemVersion] integerValue]] ofType:@"dylib" inDirectory:@"RCTJSCProfiler"] UTF8String]
|
||||
#endif
|
||||
|
||||
static const char *const JSCProfileName = "profile";
|
||||
|
||||
typedef void (*JSCProfilerStartFunctionType)(JSContextRef, const char *);
|
||||
typedef void (*JSCProfilerEndFunctionType)(JSContextRef, const char *, const char *);
|
||||
typedef void (*JSCProfilerEnableFunctionType)(void);
|
||||
|
||||
static NSMutableDictionary<NSValue *, NSNumber *> *RCTJSCProfilerStateMap;
|
||||
|
||||
static JSCProfilerStartFunctionType RCTNativeProfilerStart = NULL;
|
||||
static JSCProfilerEndFunctionType RCTNativeProfilerEnd = NULL;
|
||||
|
||||
NS_INLINE NSValue *RCTJSContextRefKey(JSContextRef ref) {
|
||||
return [NSValue valueWithPointer:ref];
|
||||
}
|
||||
|
||||
static void RCTJSCProfilerStateInit()
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
RCTJSCProfilerStateMap = [NSMutableDictionary new];
|
||||
|
||||
void *JSCProfiler = dlopen(RCT_JSC_PROFILER_DYLIB, RTLD_NOW);
|
||||
|
||||
RCTNativeProfilerStart = (JSCProfilerStartFunctionType)dlsym(JSCProfiler, "nativeProfilerStart");
|
||||
RCTNativeProfilerEnd = (JSCProfilerEndFunctionType)dlsym(JSCProfiler, "nativeProfilerEnd");
|
||||
JSCProfilerEnableFunctionType enableBytecode = (__typeof__(enableBytecode))dlsym(JSCProfiler, "nativeProfilerEnableBytecode");
|
||||
|
||||
if (RCTNativeProfilerStart && RCTNativeProfilerEnd && enableBytecode) {
|
||||
enableBytecode();
|
||||
} else {
|
||||
RCTNativeProfilerStart = NULL;
|
||||
RCTNativeProfilerEnd = NULL;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void RCTJSCProfilerStart(JSContextRef ctx)
|
||||
{
|
||||
#if RCT_JSC_PROFILER
|
||||
if (ctx != NULL) {
|
||||
if (RCTJSCProfilerIsSupported()) {
|
||||
NSValue *key = RCTJSContextRefKey(ctx);
|
||||
BOOL isProfiling = [RCTJSCProfilerStateMap[key] boolValue];
|
||||
if (!isProfiling) {
|
||||
RCTLogInfo(@"Starting JSC profiler for context: %p", ctx);
|
||||
RCTJSCProfilerStateMap[key] = @YES;
|
||||
RCTNativeProfilerStart(ctx, JSCProfileName);
|
||||
} else {
|
||||
RCTLogWarn(@"Trying to start JSC profiler on a context which is already profiled.");
|
||||
}
|
||||
} else {
|
||||
RCTLogWarn(@"Cannot start JSC profiler as it's not supported.");
|
||||
}
|
||||
} else {
|
||||
RCTLogWarn(@"Trying to start JSC profiler for NULL context.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NSString *RCTJSCProfilerStop(JSContextRef ctx)
|
||||
{
|
||||
NSString *outputFile = nil;
|
||||
#if RCT_JSC_PROFILER
|
||||
if (ctx != NULL) {
|
||||
RCTJSCProfilerStateInit();
|
||||
NSValue *key = RCTJSContextRefKey(ctx);
|
||||
BOOL isProfiling = [RCTJSCProfilerStateMap[key] boolValue];
|
||||
if (isProfiling) {
|
||||
NSString *filename = [NSString stringWithFormat:@"cpu_profile_%ld.json", (long)CFAbsoluteTimeGetCurrent()];
|
||||
outputFile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
|
||||
if (RCTNativeProfilerEnd) {
|
||||
RCTNativeProfilerEnd(ctx, JSCProfileName, outputFile.UTF8String);
|
||||
}
|
||||
RCTLogInfo(@"Stopped JSC profiler for context: %p", ctx);
|
||||
} else {
|
||||
RCTLogWarn(@"Trying to stop JSC profiler on a context which is not being profiled.");
|
||||
}
|
||||
[RCTJSCProfilerStateMap removeObjectForKey:key];
|
||||
} else {
|
||||
RCTLogWarn(@"Trying to stop JSC profiler for NULL context.");
|
||||
}
|
||||
#endif
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
BOOL RCTJSCProfilerIsProfiling(JSContextRef ctx)
|
||||
{
|
||||
BOOL isProfiling = NO;
|
||||
#if RCT_JSC_PROFILER
|
||||
if (ctx != NULL) {
|
||||
RCTJSCProfilerStateInit();
|
||||
isProfiling = [RCTJSCProfilerStateMap[RCTJSContextRefKey(ctx)] boolValue];
|
||||
}
|
||||
#endif
|
||||
return isProfiling;
|
||||
}
|
||||
|
||||
BOOL RCTJSCProfilerIsSupported(void)
|
||||
{
|
||||
BOOL isSupported = NO;
|
||||
#if RCT_JSC_PROFILER
|
||||
RCTJSCProfilerStateInit();
|
||||
isSupported = (RCTNativeProfilerStart != NULL);
|
||||
#endif
|
||||
return isSupported;
|
||||
}
|
|
@ -160,7 +160,6 @@
|
|||
13F887701E29726200C3C7A1 /* Instance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0AE1E03699D0018521A /* Instance.cpp */; };
|
||||
13F887711E29726200C3C7A1 /* JSBundleType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AC70D2EB1DE48A22002E6351 /* JSBundleType.cpp */; };
|
||||
13F887721E29726200C3C7A1 /* JSCExecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0B21E03699D0018521A /* JSCExecutor.cpp */; };
|
||||
13F887731E29726200C3C7A1 /* JSCLegacyProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0B41E03699D0018521A /* JSCLegacyProfiler.cpp */; };
|
||||
13F887741E29726200C3C7A1 /* JSCLegacyTracing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0B61E03699D0018521A /* JSCLegacyTracing.cpp */; };
|
||||
13F887751E29726200C3C7A1 /* JSCMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0B81E03699D0018521A /* JSCMemory.cpp */; };
|
||||
13F887761E29726200C3C7A1 /* JSCNativeModules.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0BA1E03699D0018521A /* JSCNativeModules.cpp */; };
|
||||
|
@ -176,7 +175,6 @@
|
|||
13F887821E29726300C3C7A1 /* CxxNativeModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0A81E03699D0018521A /* CxxNativeModule.cpp */; };
|
||||
13F887841E29726300C3C7A1 /* Instance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0AE1E03699D0018521A /* Instance.cpp */; };
|
||||
13F887851E29726300C3C7A1 /* JSCExecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0B21E03699D0018521A /* JSCExecutor.cpp */; };
|
||||
13F887861E29726300C3C7A1 /* JSCLegacyProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0B41E03699D0018521A /* JSCLegacyProfiler.cpp */; };
|
||||
13F887871E29726300C3C7A1 /* JSCLegacyTracing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0B61E03699D0018521A /* JSCLegacyTracing.cpp */; };
|
||||
13F887881E29726300C3C7A1 /* JSCMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0B81E03699D0018521A /* JSCMemory.cpp */; };
|
||||
13F887891E29726300C3C7A1 /* JSCNativeModules.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D92B0BA1E03699D0018521A /* JSCNativeModules.cpp */; };
|
||||
|
@ -229,7 +227,6 @@
|
|||
27595AAA1E575C7800CCE2B1 /* JsArgumentHelpers-inl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B01E03699D0018521A /* JsArgumentHelpers-inl.h */; };
|
||||
27595AAB1E575C7800CCE2B1 /* JsArgumentHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B11E03699D0018521A /* JsArgumentHelpers.h */; };
|
||||
27595AAC1E575C7800CCE2B1 /* JSCExecutor.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B31E03699D0018521A /* JSCExecutor.h */; };
|
||||
27595AAD1E575C7800CCE2B1 /* JSCLegacyProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B51E03699D0018521A /* JSCLegacyProfiler.h */; };
|
||||
27595AAE1E575C7800CCE2B1 /* JSCLegacyTracing.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B71E03699D0018521A /* JSCLegacyTracing.h */; };
|
||||
27595AAF1E575C7800CCE2B1 /* JSCMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B91E03699D0018521A /* JSCMemory.h */; };
|
||||
27595AB01E575C7800CCE2B1 /* JSCNativeModules.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BB1E03699D0018521A /* JSCNativeModules.h */; };
|
||||
|
@ -252,7 +249,6 @@
|
|||
27595AC51E575C7800CCE2B1 /* JsArgumentHelpers-inl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B01E03699D0018521A /* JsArgumentHelpers-inl.h */; };
|
||||
27595AC61E575C7800CCE2B1 /* JsArgumentHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B11E03699D0018521A /* JsArgumentHelpers.h */; };
|
||||
27595AC71E575C7800CCE2B1 /* JSCExecutor.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B31E03699D0018521A /* JSCExecutor.h */; };
|
||||
27595AC81E575C7800CCE2B1 /* JSCLegacyProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B51E03699D0018521A /* JSCLegacyProfiler.h */; };
|
||||
27595AC91E575C7800CCE2B1 /* JSCLegacyTracing.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B71E03699D0018521A /* JSCLegacyTracing.h */; };
|
||||
27595ACA1E575C7800CCE2B1 /* JSCMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B91E03699D0018521A /* JSCMemory.h */; };
|
||||
27595ACB1E575C7800CCE2B1 /* JSCNativeModules.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BB1E03699D0018521A /* JSCNativeModules.h */; };
|
||||
|
@ -805,7 +801,6 @@
|
|||
3DA981A81E5B0E34004F2374 /* JSBigString.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D7454781E54757500E74ADD /* JSBigString.h */; };
|
||||
3DA981A91E5B0E34004F2374 /* JSBundleType.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D3CD8F51DE5FB2300167DC4 /* JSBundleType.h */; };
|
||||
3DA981AA1E5B0E34004F2374 /* JSCExecutor.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B31E03699D0018521A /* JSCExecutor.h */; };
|
||||
3DA981AB1E5B0E34004F2374 /* JSCLegacyProfiler.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B51E03699D0018521A /* JSCLegacyProfiler.h */; };
|
||||
3DA981AC1E5B0E34004F2374 /* JSCLegacyTracing.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B71E03699D0018521A /* JSCLegacyTracing.h */; };
|
||||
3DA981AD1E5B0E34004F2374 /* JSCMemory.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B91E03699D0018521A /* JSCMemory.h */; };
|
||||
3DA981AE1E5B0E34004F2374 /* JSCNativeModules.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BB1E03699D0018521A /* JSCNativeModules.h */; };
|
||||
|
@ -944,7 +939,6 @@
|
|||
3DA982431E5B1053004F2374 /* JSBigString.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D7454781E54757500E74ADD /* JSBigString.h */; };
|
||||
3DA982441E5B1053004F2374 /* JSBundleType.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D3CD8F51DE5FB2300167DC4 /* JSBundleType.h */; };
|
||||
3DA982451E5B1053004F2374 /* JSCExecutor.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B31E03699D0018521A /* JSCExecutor.h */; };
|
||||
3DA982461E5B1053004F2374 /* JSCLegacyProfiler.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B51E03699D0018521A /* JSCLegacyProfiler.h */; };
|
||||
3DA982471E5B1053004F2374 /* JSCLegacyTracing.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B71E03699D0018521A /* JSCLegacyTracing.h */; };
|
||||
3DA982481E5B1053004F2374 /* JSCMemory.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0B91E03699D0018521A /* JSCMemory.h */; };
|
||||
3DA982491E5B1053004F2374 /* JSCNativeModules.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D92B0BB1E03699D0018521A /* JSCNativeModules.h */; };
|
||||
|
@ -1350,7 +1344,6 @@
|
|||
3DA982431E5B1053004F2374 /* JSBigString.h in Copy Headers */,
|
||||
3DA982441E5B1053004F2374 /* JSBundleType.h in Copy Headers */,
|
||||
3DA982451E5B1053004F2374 /* JSCExecutor.h in Copy Headers */,
|
||||
3DA982461E5B1053004F2374 /* JSCLegacyProfiler.h in Copy Headers */,
|
||||
3DA982471E5B1053004F2374 /* JSCLegacyTracing.h in Copy Headers */,
|
||||
3DA982481E5B1053004F2374 /* JSCMemory.h in Copy Headers */,
|
||||
3DA982491E5B1053004F2374 /* JSCNativeModules.h in Copy Headers */,
|
||||
|
@ -1568,7 +1561,6 @@
|
|||
3DA981A81E5B0E34004F2374 /* JSBigString.h in Copy Headers */,
|
||||
3DA981A91E5B0E34004F2374 /* JSBundleType.h in Copy Headers */,
|
||||
3DA981AA1E5B0E34004F2374 /* JSCExecutor.h in Copy Headers */,
|
||||
3DA981AB1E5B0E34004F2374 /* JSCLegacyProfiler.h in Copy Headers */,
|
||||
3DA981AC1E5B0E34004F2374 /* JSCLegacyTracing.h in Copy Headers */,
|
||||
3DA981AD1E5B0E34004F2374 /* JSCMemory.h in Copy Headers */,
|
||||
3DA981AE1E5B0E34004F2374 /* JSCNativeModules.h in Copy Headers */,
|
||||
|
@ -1900,8 +1892,6 @@
|
|||
3D92B0B11E03699D0018521A /* JsArgumentHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JsArgumentHelpers.h; sourceTree = "<group>"; };
|
||||
3D92B0B21E03699D0018521A /* JSCExecutor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCExecutor.cpp; sourceTree = "<group>"; };
|
||||
3D92B0B31E03699D0018521A /* JSCExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCExecutor.h; sourceTree = "<group>"; };
|
||||
3D92B0B41E03699D0018521A /* JSCLegacyProfiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCLegacyProfiler.cpp; sourceTree = "<group>"; };
|
||||
3D92B0B51E03699D0018521A /* JSCLegacyProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCLegacyProfiler.h; sourceTree = "<group>"; };
|
||||
3D92B0B61E03699D0018521A /* JSCLegacyTracing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCLegacyTracing.cpp; sourceTree = "<group>"; };
|
||||
3D92B0B71E03699D0018521A /* JSCLegacyTracing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCLegacyTracing.h; sourceTree = "<group>"; };
|
||||
3D92B0B81E03699D0018521A /* JSCMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCMemory.cpp; sourceTree = "<group>"; };
|
||||
|
@ -2654,8 +2644,6 @@
|
|||
3D3CD8F51DE5FB2300167DC4 /* JSBundleType.h */,
|
||||
3D92B0B21E03699D0018521A /* JSCExecutor.cpp */,
|
||||
3D92B0B31E03699D0018521A /* JSCExecutor.h */,
|
||||
3D92B0B41E03699D0018521A /* JSCLegacyProfiler.cpp */,
|
||||
3D92B0B51E03699D0018521A /* JSCLegacyProfiler.h */,
|
||||
3D92B0B61E03699D0018521A /* JSCLegacyTracing.cpp */,
|
||||
3D92B0B71E03699D0018521A /* JSCLegacyTracing.h */,
|
||||
3D92B0B81E03699D0018521A /* JSCMemory.cpp */,
|
||||
|
@ -2882,7 +2870,6 @@
|
|||
files = (
|
||||
3D74547E1E54759A00E74ADD /* JSModulesUnbundle.h in Headers */,
|
||||
27595AD51E575C7800CCE2B1 /* NativeToJsBridge.h in Headers */,
|
||||
27595AC81E575C7800CCE2B1 /* JSCLegacyProfiler.h in Headers */,
|
||||
27595AC41E575C7800CCE2B1 /* Instance.h in Headers */,
|
||||
27595AD11E575C7800CCE2B1 /* MessageQueueThread.h in Headers */,
|
||||
27595ACE1E575C7800CCE2B1 /* JSCUtils.h in Headers */,
|
||||
|
@ -2971,7 +2958,6 @@
|
|||
files = (
|
||||
3D74547F1E54759E00E74ADD /* JSModulesUnbundle.h in Headers */,
|
||||
27595ABA1E575C7800CCE2B1 /* NativeToJsBridge.h in Headers */,
|
||||
27595AAD1E575C7800CCE2B1 /* JSCLegacyProfiler.h in Headers */,
|
||||
27595AA91E575C7800CCE2B1 /* Instance.h in Headers */,
|
||||
27595AB61E575C7800CCE2B1 /* MessageQueueThread.h in Headers */,
|
||||
27595AB31E575C7800CCE2B1 /* JSCUtils.h in Headers */,
|
||||
|
@ -3788,7 +3774,6 @@
|
|||
13F887741E29726200C3C7A1 /* JSCLegacyTracing.cpp in Sources */,
|
||||
13F887771E29726200C3C7A1 /* JSCPerfStats.cpp in Sources */,
|
||||
13F887711E29726200C3C7A1 /* JSBundleType.cpp in Sources */,
|
||||
13F887731E29726200C3C7A1 /* JSCLegacyProfiler.cpp in Sources */,
|
||||
13F887791E29726200C3C7A1 /* JSCUtils.cpp in Sources */,
|
||||
13F887781E29726200C3C7A1 /* JSCSamplingProfiler.cpp in Sources */,
|
||||
13F887751E29726200C3C7A1 /* JSCMemory.cpp in Sources */,
|
||||
|
@ -3812,7 +3797,6 @@
|
|||
13F887871E29726300C3C7A1 /* JSCLegacyTracing.cpp in Sources */,
|
||||
13F8878A1E29726300C3C7A1 /* JSCPerfStats.cpp in Sources */,
|
||||
13F887841E29726300C3C7A1 /* Instance.cpp in Sources */,
|
||||
13F887861E29726300C3C7A1 /* JSCLegacyProfiler.cpp in Sources */,
|
||||
13F8878C1E29726300C3C7A1 /* JSCUtils.cpp in Sources */,
|
||||
13F8878B1E29726300C3C7A1 /* JSCSamplingProfiler.cpp in Sources */,
|
||||
13F887881E29726300C3C7A1 /* JSCMemory.cpp in Sources */,
|
||||
|
|
|
@ -68,7 +68,6 @@
|
|||
1450FF871BCFF28A00208362 /* RCTProfileTrampoline-arm.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF821BCFF28A00208362 /* RCTProfileTrampoline-arm.S */; };
|
||||
1450FF881BCFF28A00208362 /* RCTProfileTrampoline-arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF831BCFF28A00208362 /* RCTProfileTrampoline-arm64.S */; };
|
||||
1450FF8A1BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF851BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S */; };
|
||||
14A43DF31C20B1C900794BC8 /* RCTJSCProfiler.m in Sources */ = {isa = PBXBuildFile; fileRef = 14A43DF21C20B1C900794BC8 /* RCTJSCProfiler.m */; };
|
||||
14C2CA711B3AC63800E6CBB2 /* RCTModuleMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C2CA701B3AC63800E6CBB2 /* RCTModuleMethod.m */; };
|
||||
14C2CA741B3AC64300E6CBB2 /* RCTModuleData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 14C2CA731B3AC64300E6CBB2 /* RCTModuleData.mm */; };
|
||||
14C2CA761B3AC64F00E6CBB2 /* RCTFrameUpdate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C2CA751B3AC64F00E6CBB2 /* RCTFrameUpdate.m */; };
|
||||
|
@ -120,7 +119,6 @@
|
|||
2D3B5EBC1D9B092600451313 /* RCTKeyboardObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 13D9FEED1CDCD93000158BD7 /* RCTKeyboardObserver.m */; };
|
||||
2D3B5EBD1D9B092A00451313 /* RCTTiming.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FEE1A69327A00A75B9A /* RCTTiming.m */; };
|
||||
2D3B5EBE1D9B092D00451313 /* RCTUIManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067491A70F434002CDEE1 /* RCTUIManager.m */; };
|
||||
2D3B5EBF1D9B093300451313 /* RCTJSCProfiler.m in Sources */ = {isa = PBXBuildFile; fileRef = 14A43DF21C20B1C900794BC8 /* RCTJSCProfiler.m */; };
|
||||
2D3B5EC01D9B093600451313 /* RCTPerfMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F7A0EB1BDA3B3C003C6C10 /* RCTPerfMonitor.m */; };
|
||||
2D3B5EC11D9B093900451313 /* RCTFPSGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F7A0EF1BDA714B003C6C10 /* RCTFPSGraph.m */; };
|
||||
2D3B5EC21D9B093B00451313 /* RCTProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF811BCFF28A00208362 /* RCTProfile.m */; };
|
||||
|
@ -235,7 +233,6 @@
|
|||
3D302F641DF828F800D6DDAE /* RCTTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 13B07FED1A69327A00A75B9A /* RCTTiming.h */; };
|
||||
3D302F651DF828F800D6DDAE /* RCTUIManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 13E067481A70F434002CDEE1 /* RCTUIManager.h */; };
|
||||
3D302F661DF828F800D6DDAE /* RCTFPSGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F7A0EE1BDA714B003C6C10 /* RCTFPSGraph.h */; };
|
||||
3D302F671DF828F800D6DDAE /* RCTJSCProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A43DF11C20B1C900794BC8 /* RCTJSCProfiler.h */; };
|
||||
3D302F681DF828F800D6DDAE /* RCTMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BF71811C04795500C97D0C /* RCTMacros.h */; };
|
||||
3D302F691DF828F800D6DDAE /* RCTProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 1450FF801BCFF28A00208362 /* RCTProfile.h */; };
|
||||
3D302F6A1DF828F800D6DDAE /* RCTActivityIndicatorView.h in Headers */ = {isa = PBXBuildFile; fileRef = B95154301D1B34B200FE7B80 /* RCTActivityIndicatorView.h */; };
|
||||
|
@ -344,7 +341,6 @@
|
|||
3D302FE01DF8290600D6DDAE /* RCTTiming.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13B07FED1A69327A00A75B9A /* RCTTiming.h */; };
|
||||
3D302FE11DF8290600D6DDAE /* RCTUIManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13E067481A70F434002CDEE1 /* RCTUIManager.h */; };
|
||||
3D302FE21DF8290600D6DDAE /* RCTFPSGraph.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 14F7A0EE1BDA714B003C6C10 /* RCTFPSGraph.h */; };
|
||||
3D302FE31DF8290600D6DDAE /* RCTJSCProfiler.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 14A43DF11C20B1C900794BC8 /* RCTJSCProfiler.h */; };
|
||||
3D302FE41DF8290600D6DDAE /* RCTMacros.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 14BF71811C04795500C97D0C /* RCTMacros.h */; };
|
||||
3D302FE51DF8290600D6DDAE /* RCTProfile.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 1450FF801BCFF28A00208362 /* RCTProfile.h */; };
|
||||
3D302FE61DF8290600D6DDAE /* RCTActivityIndicatorView.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = B95154301D1B34B200FE7B80 /* RCTActivityIndicatorView.h */; };
|
||||
|
@ -493,7 +489,6 @@
|
|||
3D80D95F1DF6FA890028D040 /* RCTTiming.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13B07FED1A69327A00A75B9A /* RCTTiming.h */; };
|
||||
3D80D9601DF6FA890028D040 /* RCTUIManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13E067481A70F434002CDEE1 /* RCTUIManager.h */; };
|
||||
3D80D9611DF6FA890028D040 /* RCTFPSGraph.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 14F7A0EE1BDA714B003C6C10 /* RCTFPSGraph.h */; };
|
||||
3D80D9621DF6FA890028D040 /* RCTJSCProfiler.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 14A43DF11C20B1C900794BC8 /* RCTJSCProfiler.h */; };
|
||||
3D80D9631DF6FA890028D040 /* RCTMacros.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 14BF71811C04795500C97D0C /* RCTMacros.h */; };
|
||||
3D80D9641DF6FA890028D040 /* RCTProfile.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 1450FF801BCFF28A00208362 /* RCTProfile.h */; };
|
||||
3D80D9651DF6FA890028D040 /* RCTActivityIndicatorView.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = B95154301D1B34B200FE7B80 /* RCTActivityIndicatorView.h */; };
|
||||
|
@ -610,7 +605,6 @@
|
|||
3D80DA591DF820620028D040 /* RCTTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 13B07FED1A69327A00A75B9A /* RCTTiming.h */; };
|
||||
3D80DA5A1DF820620028D040 /* RCTUIManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 13E067481A70F434002CDEE1 /* RCTUIManager.h */; };
|
||||
3D80DA5B1DF820620028D040 /* RCTFPSGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F7A0EE1BDA714B003C6C10 /* RCTFPSGraph.h */; };
|
||||
3D80DA5C1DF820620028D040 /* RCTJSCProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A43DF11C20B1C900794BC8 /* RCTJSCProfiler.h */; };
|
||||
3D80DA5D1DF820620028D040 /* RCTMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BF71811C04795500C97D0C /* RCTMacros.h */; };
|
||||
3D80DA5E1DF820620028D040 /* RCTProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 1450FF801BCFF28A00208362 /* RCTProfile.h */; };
|
||||
3D80DA5F1DF820620028D040 /* RCTActivityIndicatorView.h in Headers */ = {isa = PBXBuildFile; fileRef = B95154301D1B34B200FE7B80 /* RCTActivityIndicatorView.h */; };
|
||||
|
@ -899,7 +893,6 @@
|
|||
3D302FE01DF8290600D6DDAE /* RCTTiming.h in Copy Headers */,
|
||||
3D302FE11DF8290600D6DDAE /* RCTUIManager.h in Copy Headers */,
|
||||
3D302FE21DF8290600D6DDAE /* RCTFPSGraph.h in Copy Headers */,
|
||||
3D302FE31DF8290600D6DDAE /* RCTJSCProfiler.h in Copy Headers */,
|
||||
3D302FE41DF8290600D6DDAE /* RCTMacros.h in Copy Headers */,
|
||||
3D302FE51DF8290600D6DDAE /* RCTProfile.h in Copy Headers */,
|
||||
3D302FE61DF8290600D6DDAE /* RCTActivityIndicatorView.h in Copy Headers */,
|
||||
|
@ -1059,7 +1052,6 @@
|
|||
3D80D95F1DF6FA890028D040 /* RCTTiming.h in Copy Headers */,
|
||||
3D80D9601DF6FA890028D040 /* RCTUIManager.h in Copy Headers */,
|
||||
3D80D9611DF6FA890028D040 /* RCTFPSGraph.h in Copy Headers */,
|
||||
3D80D9621DF6FA890028D040 /* RCTJSCProfiler.h in Copy Headers */,
|
||||
3D80D9631DF6FA890028D040 /* RCTMacros.h in Copy Headers */,
|
||||
3D80D9641DF6FA890028D040 /* RCTProfile.h in Copy Headers */,
|
||||
3D80D9651DF6FA890028D040 /* RCTActivityIndicatorView.h in Copy Headers */,
|
||||
|
@ -1279,8 +1271,6 @@
|
|||
1450FF851BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "RCTProfileTrampoline-x86_64.S"; sourceTree = "<group>"; };
|
||||
1482F9E61B55B927000ADFF3 /* RCTBridgeDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTBridgeDelegate.h; sourceTree = "<group>"; };
|
||||
14A43DB81C1F849600794BC8 /* RCTBridge+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RCTBridge+Private.h"; sourceTree = "<group>"; };
|
||||
14A43DF11C20B1C900794BC8 /* RCTJSCProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJSCProfiler.h; sourceTree = "<group>"; };
|
||||
14A43DF21C20B1C900794BC8 /* RCTJSCProfiler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTJSCProfiler.m; sourceTree = "<group>"; };
|
||||
14BF717F1C04793D00C97D0C /* RCTProfileTrampoline-i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "RCTProfileTrampoline-i386.S"; sourceTree = "<group>"; };
|
||||
14BF71811C04795500C97D0C /* RCTMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMacros.h; sourceTree = "<group>"; };
|
||||
14C2CA6F1B3AC63800E6CBB2 /* RCTModuleMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTModuleMethod.h; sourceTree = "<group>"; };
|
||||
|
@ -1633,8 +1623,6 @@
|
|||
children = (
|
||||
14F7A0EE1BDA714B003C6C10 /* RCTFPSGraph.h */,
|
||||
14F7A0EF1BDA714B003C6C10 /* RCTFPSGraph.m */,
|
||||
14A43DF11C20B1C900794BC8 /* RCTJSCProfiler.h */,
|
||||
14A43DF21C20B1C900794BC8 /* RCTJSCProfiler.m */,
|
||||
14BF71811C04795500C97D0C /* RCTMacros.h */,
|
||||
14F7A0EB1BDA3B3C003C6C10 /* RCTPerfMonitor.m */,
|
||||
1450FF801BCFF28A00208362 /* RCTProfile.h */,
|
||||
|
@ -1965,7 +1953,6 @@
|
|||
3D302F641DF828F800D6DDAE /* RCTTiming.h in Headers */,
|
||||
3D302F651DF828F800D6DDAE /* RCTUIManager.h in Headers */,
|
||||
3D302F661DF828F800D6DDAE /* RCTFPSGraph.h in Headers */,
|
||||
3D302F671DF828F800D6DDAE /* RCTJSCProfiler.h in Headers */,
|
||||
3D302F681DF828F800D6DDAE /* RCTMacros.h in Headers */,
|
||||
3D302F691DF828F800D6DDAE /* RCTProfile.h in Headers */,
|
||||
3D302F6A1DF828F800D6DDAE /* RCTActivityIndicatorView.h in Headers */,
|
||||
|
@ -2157,7 +2144,6 @@
|
|||
3D80DA591DF820620028D040 /* RCTTiming.h in Headers */,
|
||||
3D80DA5A1DF820620028D040 /* RCTUIManager.h in Headers */,
|
||||
3D80DA5B1DF820620028D040 /* RCTFPSGraph.h in Headers */,
|
||||
3D80DA5C1DF820620028D040 /* RCTJSCProfiler.h in Headers */,
|
||||
A12E9E2B1E5DEB860029001B /* RCTSRWebSocket.h in Headers */,
|
||||
3D80DA5D1DF820620028D040 /* RCTMacros.h in Headers */,
|
||||
3D80DA5E1DF820620028D040 /* RCTProfile.h in Headers */,
|
||||
|
@ -2489,7 +2475,6 @@
|
|||
2D3B5EC91D9B095C00451313 /* RCTBorderDrawing.m in Sources */,
|
||||
B50558411E43E13D00F71A00 /* RCTDevMenu.m in Sources */,
|
||||
2D3B5E991D9B089A00451313 /* RCTDisplayLink.m in Sources */,
|
||||
2D3B5EBF1D9B093300451313 /* RCTJSCProfiler.m in Sources */,
|
||||
2D3B5EA11D9B08B600451313 /* RCTModuleData.mm in Sources */,
|
||||
2D3B5EEA1D9B09CD00451313 /* RCTTabBar.m in Sources */,
|
||||
3D7BFCEA1EA8E1F4008DFB7A /* RCTPackagerConnection.m in Sources */,
|
||||
|
@ -2645,7 +2630,6 @@
|
|||
597AD1BF1E577D7800152581 /* RCTRootContentView.m in Sources */,
|
||||
13723B501A82FD3C00F88898 /* RCTStatusBarManager.m in Sources */,
|
||||
000E6CEB1AB0E980000CDF4D /* RCTSourceCode.m in Sources */,
|
||||
14A43DF31C20B1C900794BC8 /* RCTJSCProfiler.m in Sources */,
|
||||
001BFCD01D8381DE008E587E /* RCTMultipartStreamReader.m in Sources */,
|
||||
133CAE8E1B8E5CFD00F6AD92 /* RCTDatePicker.m in Sources */,
|
||||
14C2CA761B3AC64F00E6CBB2 /* RCTFrameUpdate.m in Sources */,
|
||||
|
|
|
@ -88,10 +88,6 @@ public interface CatalystInstance
|
|||
*/
|
||||
void removeBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener);
|
||||
|
||||
boolean supportsProfiling();
|
||||
void startProfiler(String title);
|
||||
void stopProfiler(String title, String filename);
|
||||
|
||||
@VisibleForTesting
|
||||
void setGlobalVariable(String propName, String jsonValue);
|
||||
|
||||
|
|
|
@ -429,17 +429,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
|||
@Override
|
||||
public native long getJavaScriptContext();
|
||||
|
||||
// TODO mhorowitz: add mDestroyed checks to the next three methods
|
||||
|
||||
@Override
|
||||
public native boolean supportsProfiling();
|
||||
|
||||
@Override
|
||||
public native void startProfiler(String title);
|
||||
|
||||
@Override
|
||||
public native void stopProfiler(String title, String filename);
|
||||
|
||||
private void incrementPendingJSCalls() {
|
||||
int oldPendingCalls = mPendingJSCalls.getAndIncrement();
|
||||
boolean wasIdle = oldPendingCalls == 0;
|
||||
|
|
|
@ -104,9 +104,6 @@ void CatalystInstanceImpl::registerNatives() {
|
|||
makeNativeMethod("setGlobalVariable", CatalystInstanceImpl::setGlobalVariable),
|
||||
makeNativeMethod("getJavaScriptContext", CatalystInstanceImpl::getJavaScriptContext),
|
||||
makeNativeMethod("jniHandleMemoryPressure", CatalystInstanceImpl::handleMemoryPressure),
|
||||
makeNativeMethod("supportsProfiling", CatalystInstanceImpl::supportsProfiling),
|
||||
makeNativeMethod("startProfiler", CatalystInstanceImpl::startProfiler),
|
||||
makeNativeMethod("stopProfiler", CatalystInstanceImpl::stopProfiler),
|
||||
});
|
||||
|
||||
JNativeRunnable::registerNatives();
|
||||
|
@ -266,25 +263,4 @@ void CatalystInstanceImpl::handleMemoryPressure(int pressureLevel) {
|
|||
#endif
|
||||
}
|
||||
|
||||
jboolean CatalystInstanceImpl::supportsProfiling() {
|
||||
if (!instance_) {
|
||||
return false;
|
||||
}
|
||||
return instance_->supportsProfiling();
|
||||
}
|
||||
|
||||
void CatalystInstanceImpl::startProfiler(const std::string& title) {
|
||||
if (!instance_) {
|
||||
return;
|
||||
}
|
||||
return instance_->startProfiler(title);
|
||||
}
|
||||
|
||||
void CatalystInstanceImpl::stopProfiler(const std::string& title, const std::string& filename) {
|
||||
if (!instance_) {
|
||||
return;
|
||||
}
|
||||
return instance_->stopProfiler(title, filename);
|
||||
}
|
||||
|
||||
}}
|
||||
|
|
|
@ -69,9 +69,6 @@ class CatalystInstanceImpl : public jni::HybridClass<CatalystInstanceImpl> {
|
|||
std::string&& jsonValue);
|
||||
jlong getJavaScriptContext();
|
||||
void handleMemoryPressure(int pressureLevel);
|
||||
jboolean supportsProfiling();
|
||||
void startProfiler(const std::string& title);
|
||||
void stopProfiler(const std::string& title, const std::string& filename);
|
||||
|
||||
// This should be the only long-lived strong reference, but every C++ class
|
||||
// will have a weak reference.
|
||||
|
|
|
@ -10,7 +10,6 @@ LOCAL_SRC_FILES := \
|
|||
JSCExecutor.cpp \
|
||||
JSBigString.cpp \
|
||||
JSBundleType.cpp \
|
||||
JSCLegacyProfiler.cpp \
|
||||
JSCLegacyTracing.cpp \
|
||||
JSCMemory.cpp \
|
||||
JSCNativeModules.cpp \
|
||||
|
|
|
@ -100,18 +100,6 @@ void Instance::loadUnbundle(std::unique_ptr<JSModulesUnbundle> unbundle,
|
|||
loadApplication(std::move(unbundle), std::move(startupScript),
|
||||
std::move(startupScriptSourceURL));
|
||||
}
|
||||
}
|
||||
|
||||
bool Instance::supportsProfiling() {
|
||||
return nativeToJsBridge_->supportsProfiling();
|
||||
}
|
||||
|
||||
void Instance::startProfiler(const std::string& title) {
|
||||
return nativeToJsBridge_->startProfiler(title);
|
||||
}
|
||||
|
||||
void Instance::stopProfiler(const std::string& title, const std::string& filename) {
|
||||
return nativeToJsBridge_->stopProfiler(title, filename);
|
||||
}
|
||||
|
||||
void Instance::setGlobalVariable(std::string propName,
|
||||
|
|
|
@ -53,8 +53,6 @@ class RN_EXPORT Instance {
|
|||
std::string startupScriptSourceURL,
|
||||
bool loadSynchronously);
|
||||
bool supportsProfiling();
|
||||
void startProfiler(const std::string& title);
|
||||
void stopProfiler(const std::string& title, const std::string& filename);
|
||||
void setGlobalVariable(std::string propName, std::unique_ptr<const JSBigString> jsonValue);
|
||||
void *getJavaScriptContext();
|
||||
void callJSFunction(std::string&& module, std::string&& method, folly::dynamic&& params);
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#endif
|
||||
|
||||
#ifdef WITH_JSC_EXTRA_TRACING
|
||||
#include "JSCLegacyProfiler.h"
|
||||
#include "JSCLegacyTracing.h"
|
||||
#endif
|
||||
|
||||
|
@ -240,7 +239,6 @@ void JSCExecutor::initOnJSVMThread() throw(JSException) {
|
|||
#endif
|
||||
|
||||
#ifdef WITH_JSC_EXTRA_TRACING
|
||||
addNativeProfilingHooks(m_context);
|
||||
addNativeTracingLegacyHooks(m_context);
|
||||
#endif
|
||||
|
||||
|
@ -554,32 +552,6 @@ void* JSCExecutor::getJavaScriptContext() {
|
|||
return m_context;
|
||||
}
|
||||
|
||||
bool JSCExecutor::supportsProfiling() {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void JSCExecutor::startProfiler(const std::string &titleString) {
|
||||
#ifdef WITH_JSC_EXTRA_TRACING
|
||||
String title(m_context, titleString.c_str());
|
||||
#if WITH_REACT_INTERNAL_SETTINGS
|
||||
JSStartProfiling(m_context, title, false);
|
||||
#else
|
||||
JSStartProfiling(m_context, title);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void JSCExecutor::stopProfiler(const std::string &titleString, const std::string& filename) {
|
||||
#ifdef WITH_JSC_EXTRA_TRACING
|
||||
String title(m_context, titleString.c_str());
|
||||
facebook::react::stopAndOutputProfilingFile(m_context, title, filename.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_JSC_MEMORY_PRESSURE
|
||||
void JSCExecutor::handleMemoryPressure(int pressureLevel) {
|
||||
JSHandleMemoryPressure(this, m_context, static_cast<JSMemoryPressure>(pressureLevel));
|
||||
|
|
|
@ -79,10 +79,6 @@ public:
|
|||
|
||||
virtual void* getJavaScriptContext() override;
|
||||
|
||||
virtual bool supportsProfiling() override;
|
||||
virtual void startProfiler(const std::string &titleString) override;
|
||||
virtual void stopProfiler(const std::string &titleString, const std::string &filename) override;
|
||||
|
||||
#ifdef WITH_JSC_MEMORY_PRESSURE
|
||||
virtual void handleMemoryPressure(int pressureLevel) override;
|
||||
#endif
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#ifdef WITH_JSC_EXTRA_TRACING
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <JavaScriptCore/API/JSProfilerPrivate.h>
|
||||
#include <jsc_legacy_profiler.h>
|
||||
#include <jschelpers/JavaScriptCore.h>
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
#include <jschelpers/Value.h>
|
||||
#include "JSCLegacyProfiler.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
static JSValueRef nativeProfilerStart(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef* exception) {
|
||||
if (argumentCount < 1) {
|
||||
if (exception) {
|
||||
*exception = Value::makeError(
|
||||
ctx,
|
||||
"nativeProfilerStart: requires at least 1 argument");
|
||||
}
|
||||
return Value::makeUndefined(ctx);
|
||||
}
|
||||
|
||||
auto title = String::adopt(ctx, JSValueToStringCopy(ctx, arguments[0], exception));
|
||||
#if WITH_REACT_INTERNAL_SETTINGS
|
||||
JSStartProfiling(ctx, title, false);
|
||||
#else
|
||||
JSStartProfiling(ctx, title);
|
||||
#endif
|
||||
return Value::makeUndefined(ctx);
|
||||
}
|
||||
|
||||
static JSValueRef nativeProfilerEnd(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef* exception) {
|
||||
if (argumentCount < 1) {
|
||||
if (exception) {
|
||||
*exception = Value::makeError(
|
||||
ctx,
|
||||
"nativeProfilerEnd: requires at least 1 argument");
|
||||
}
|
||||
return Value::makeUndefined(ctx);
|
||||
}
|
||||
|
||||
std::string writeLocation("/sdcard/");
|
||||
if (argumentCount > 1) {
|
||||
auto fileName = String::adopt(
|
||||
ctx, JSC_JSValueToStringCopy(ctx, arguments[1], exception));
|
||||
writeLocation += fileName.str();
|
||||
} else {
|
||||
writeLocation += "profile.json";
|
||||
}
|
||||
auto title = String::adopt(
|
||||
ctx, JSC_JSValueToStringCopy(ctx, arguments[0], exception));
|
||||
JSEndProfilingAndRender(ctx, title, writeLocation.c_str());
|
||||
return Value::makeUndefined(ctx);
|
||||
}
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
void stopAndOutputProfilingFile(
|
||||
JSContextRef ctx,
|
||||
JSStringRef title,
|
||||
const char *filename) {
|
||||
JSEndProfilingAndRender(ctx, title, filename);
|
||||
}
|
||||
|
||||
void addNativeProfilingHooks(JSGlobalContextRef ctx) {
|
||||
// JSEnableByteCodeProfiling();
|
||||
installGlobalFunction(ctx, "nativeProfilerStart", nativeProfilerStart);
|
||||
installGlobalFunction(ctx, "nativeProfilerEnd", nativeProfilerEnd);
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef WITH_JSC_EXTRA_TRACING
|
||||
|
||||
#include <jschelpers/JavaScriptCore.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
void addNativeProfilingHooks(JSGlobalContextRef ctx);
|
||||
void stopAndOutputProfilingFile(
|
||||
JSContextRef ctx,
|
||||
JSStringRef title,
|
||||
const char *filename);
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
|
@ -72,11 +72,6 @@ public:
|
|||
virtual void* getJavaScriptContext() {
|
||||
return nullptr;
|
||||
}
|
||||
virtual bool supportsProfiling() {
|
||||
return false;
|
||||
}
|
||||
virtual void startProfiler(const std::string &titleString) {}
|
||||
virtual void stopProfiler(const std::string &titleString, const std::string &filename) {}
|
||||
|
||||
#ifdef WITH_JSC_MEMORY_PRESSURE
|
||||
virtual void handleMemoryPressure(int pressureLevel) {}
|
||||
|
|
|
@ -184,23 +184,6 @@ void* NativeToJsBridge::getJavaScriptContext() {
|
|||
return m_executor->getJavaScriptContext();
|
||||
}
|
||||
|
||||
bool NativeToJsBridge::supportsProfiling() {
|
||||
// Intentionally doesn't post to jsqueue. supportsProfiling() can be called from any thread.
|
||||
return m_executor->supportsProfiling();
|
||||
}
|
||||
|
||||
void NativeToJsBridge::startProfiler(const std::string& title) {
|
||||
runOnExecutorQueue([=] (JSExecutor* executor) {
|
||||
executor->startProfiler(title);
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::stopProfiler(const std::string& title, const std::string& filename) {
|
||||
runOnExecutorQueue([=] (JSExecutor* executor) {
|
||||
executor->stopProfiler(title, filename);
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef WITH_JSC_MEMORY_PRESSURE
|
||||
void NativeToJsBridge::handleMemoryPressure(int pressureLevel) {
|
||||
runOnExecutorQueue([=] (JSExecutor* executor) {
|
||||
|
|
|
@ -100,9 +100,6 @@ public:
|
|||
|
||||
void setGlobalVariable(std::string propName, std::unique_ptr<const JSBigString> jsonValue);
|
||||
void* getJavaScriptContext();
|
||||
bool supportsProfiling();
|
||||
void startProfiler(const std::string& title);
|
||||
void stopProfiler(const std::string& title, const std::string& filename);
|
||||
|
||||
#ifdef WITH_JSC_MEMORY_PRESSURE
|
||||
void handleMemoryPressure(int pressureLevel);
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, 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.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const execFile = require('child_process').execFile;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function(req, res, next) {
|
||||
if (req.url !== '/cpu-profile') {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Dumping CPU profile information...');
|
||||
var dumpName = '/tmp/cpu-profile_' + Date.now();
|
||||
fs.writeFileSync(dumpName + '.json', req.rawBody);
|
||||
|
||||
var cmdPath = path.join(
|
||||
__dirname,
|
||||
'../../../JSCLegacyProfiler/json2trace'
|
||||
);
|
||||
execFile(
|
||||
cmdPath,
|
||||
[
|
||||
'-cpuprofiler',
|
||||
dumpName + '.cpuprofile',
|
||||
dumpName + '.json',
|
||||
],
|
||||
function(error) {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
res.end('Unknown error: ' + error.message);
|
||||
} else {
|
||||
var response = 'Your profile was generated at\n\n' + dumpName + '.cpuprofile\n\n' +
|
||||
'Open `Chrome Dev Tools > Profiles > Load` and select the profile to visualize it.';
|
||||
console.log(response);
|
||||
res.end(response);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
|
@ -19,7 +19,6 @@ const Terminal = require('metro-bundler/src/lib/Terminal');
|
|||
const attachHMRServer = require('./util/attachHMRServer');
|
||||
const connect = require('connect');
|
||||
const copyToClipBoardMiddleware = require('./middleware/copyToClipBoardMiddleware');
|
||||
const cpuProfilerMiddleware = require('./middleware/cpuProfilerMiddleware');
|
||||
const defaultAssetExts = require('metro-bundler/src/defaults').assetExts;
|
||||
const defaultSourceExts = require('metro-bundler/src/defaults').sourceExts;
|
||||
const defaultPlatforms = require('metro-bundler/src/defaults').platforms;
|
||||
|
@ -78,7 +77,6 @@ function runServer(
|
|||
.use(copyToClipBoardMiddleware)
|
||||
.use(statusPageMiddleware)
|
||||
.use(systraceProfileMiddleware)
|
||||
.use(cpuProfilerMiddleware)
|
||||
.use(indexPageMiddleware)
|
||||
.use(packagerServer.processRequest.bind(packagerServer));
|
||||
|
||||
|
|
Loading…
Reference in New Issue