mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-29 04:35:36 +08:00
Add more profiling markers to RCTJSCExecutor
Summary: Add some additional perf markers, and remove the usage of RCTProfileBlock as it completely breaks debugging / stepping in those blocks. Reviewed By: majak Differential Revision: D3579900 fbshipit-source-id: 8846dfc39b2448daa3669d5e1e8efb9096f183c5
This commit is contained in:
committed by
Facebook Github Bot 4
parent
46417dd26a
commit
63e0e6c7e4
@@ -311,12 +311,15 @@ static NSThread *newJavaScriptThread(void)
|
||||
|
||||
- (instancetype)initWithUseCustomJSCLibrary:(BOOL)useCustomJSCLibrary
|
||||
{
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTJSCExecutor init]", nil);
|
||||
|
||||
if (self = [super init]) {
|
||||
_useCustomJSCLibrary = useCustomJSCLibrary;
|
||||
_valid = YES;
|
||||
_javaScriptThread = newJavaScriptThread();
|
||||
}
|
||||
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -635,30 +638,32 @@ static void installBasicSynchronousHooksOnContext(JSContext *context)
|
||||
{
|
||||
RCTAssert(onComplete != nil, @"onComplete block should not be nil");
|
||||
__weak RCTJSCExecutor *weakSelf = self;
|
||||
[self executeBlockOnJavaScriptQueue:RCTProfileBlock((^{
|
||||
[self executeBlockOnJavaScriptQueue:^{
|
||||
RCTJSCExecutor *strongSelf = weakSelf;
|
||||
if (!strongSelf || !strongSelf.isValid) {
|
||||
return;
|
||||
}
|
||||
NSError *error;
|
||||
|
||||
JSValueRef errorJSRef = NULL;
|
||||
JSValueRef resultJSRef = NULL;
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"executeJSCall", @{@"method": method, @"args": arguments});
|
||||
|
||||
RCTJSCWrapper *jscWrapper = strongSelf->_jscWrapper;
|
||||
JSGlobalContextRef ctx = strongSelf->_context.context.JSGlobalContextRef;
|
||||
JSGlobalContextRef contextJSRef = jscWrapper->JSContextGetGlobalContext(ctx);
|
||||
JSContext *context = strongSelf->_context.context;
|
||||
JSObjectRef globalObjectJSRef = jscWrapper->JSContextGetGlobalObject(ctx);
|
||||
JSGlobalContextRef ctx = context.JSGlobalContextRef;
|
||||
JSGlobalContextRef contextJSRef = jscWrapper->JSContextGetGlobalContext(ctx);
|
||||
|
||||
// get the BatchedBridge object
|
||||
JSValueRef errorJSRef = NULL;
|
||||
JSValueRef batchedBridgeRef = strongSelf->_batchedBridgeRef;
|
||||
if (!batchedBridgeRef) {
|
||||
JSStringRef moduleNameJSStringRef = jscWrapper->JSStringCreateWithUTF8CString("__fbBatchedBridge");
|
||||
JSObjectRef globalObjectJSRef = jscWrapper->JSContextGetGlobalObject(ctx);
|
||||
batchedBridgeRef = jscWrapper->JSObjectGetProperty(contextJSRef, globalObjectJSRef, moduleNameJSStringRef, &errorJSRef);
|
||||
jscWrapper->JSStringRelease(moduleNameJSStringRef);
|
||||
strongSelf->_batchedBridgeRef = batchedBridgeRef;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
JSValueRef resultJSRef = NULL;
|
||||
if (batchedBridgeRef != NULL && errorJSRef == NULL && !jscWrapper->JSValueIsUndefined(contextJSRef, batchedBridgeRef)) {
|
||||
// get method
|
||||
JSStringRef methodNameJSStringRef = jscWrapper->JSStringCreateWithCFString((__bridge CFStringRef)method);
|
||||
@@ -682,22 +687,24 @@ static void installBasicSynchronousHooksOnContext(JSContext *context)
|
||||
}
|
||||
}
|
||||
|
||||
id objcValue;
|
||||
if (errorJSRef || error) {
|
||||
if (!error) {
|
||||
error = RCTNSErrorFromJSError(jscWrapper, contextJSRef, errorJSRef);
|
||||
}
|
||||
onComplete(nil, error);
|
||||
} else {
|
||||
id objcValue = nil;
|
||||
// We often return `null` from JS when there is nothing for native side. [JSValue toValue]
|
||||
// returns [NSNull null] in this case, which we don't want.
|
||||
if (!jscWrapper->JSValueIsNull(contextJSRef, resultJSRef)) {
|
||||
JSValue *result = [jscWrapper->JSValue valueWithJSValueRef:resultJSRef inContext:context];
|
||||
objcValue = unwrapResult ? [result toObject] : result;
|
||||
}
|
||||
onComplete(objcValue, nil);
|
||||
}
|
||||
}), 0, @"js_call", (@{@"method": method, @"args": arguments}))];
|
||||
|
||||
RCT_PROFILE_END_EVENT(0, @"js_call", nil);
|
||||
|
||||
onComplete(objcValue, error);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)executeApplicationScript:(NSData *)script
|
||||
@@ -719,19 +726,23 @@ static void installBasicSynchronousHooksOnContext(JSContext *context)
|
||||
}
|
||||
}
|
||||
|
||||
[self executeBlockOnJavaScriptQueue:RCTProfileBlock((^{
|
||||
RCTProfileBeginFlowEvent();
|
||||
[self executeBlockOnJavaScriptQueue:^{
|
||||
RCTProfileEndFlowEvent();
|
||||
if (!self.isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRAMBundle) {
|
||||
registerNativeRequire(self.context.context, self);
|
||||
}
|
||||
|
||||
NSError *error = executeApplicationScript(script, sourceURL, self->_jscWrapper, self->_performanceLogger,
|
||||
self->_context.context.JSGlobalContextRef);
|
||||
if (onComplete) {
|
||||
onComplete(error);
|
||||
}
|
||||
}), 0, @"js_call", (@{ @"url": sourceURL.absoluteString }))];
|
||||
}];
|
||||
}
|
||||
|
||||
static NSData *loadPossiblyBundledApplicationScript(NSData *script, NSURL *sourceURL,
|
||||
@@ -739,6 +750,8 @@ static NSData *loadPossiblyBundledApplicationScript(NSData *script, NSURL *sourc
|
||||
BOOL &isRAMBundle, RandomAccessBundleData &randomAccessBundle,
|
||||
NSError **error)
|
||||
{
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"executeApplicationScript / prepare bundle", nil);
|
||||
|
||||
// The RAM bundle has a magic number in the 4 first bytes `(0xFB0BD1E5)`.
|
||||
uint32_t magicNumber = 0;
|
||||
[script getBytes:&magicNumber length:sizeof(magicNumber)];
|
||||
@@ -753,16 +766,17 @@ static NSData *loadPossiblyBundledApplicationScript(NSData *script, NSURL *sourc
|
||||
[performanceLogger setValue:0 forTag:RCTPLRAMNativeRequires];
|
||||
[performanceLogger setValue:0 forTag:RCTPLRAMNativeRequiresCount];
|
||||
[performanceLogger setValue:0 forTag:RCTPLRAMNativeRequiresSize];
|
||||
|
||||
return script;
|
||||
} else {
|
||||
// JSStringCreateWithUTF8CString expects a null terminated C string.
|
||||
// RAM Bundling already provides a null terminated one.
|
||||
NSMutableData *nullTerminatedScript = [NSMutableData dataWithCapacity:script.length + 1];
|
||||
[nullTerminatedScript appendData:script];
|
||||
[nullTerminatedScript appendBytes:"" length:1];
|
||||
return nullTerminatedScript;
|
||||
script = nullTerminatedScript;
|
||||
}
|
||||
|
||||
RCT_PROFILE_END_EVENT(0, @"", nil);
|
||||
return script;
|
||||
}
|
||||
|
||||
static void registerNativeRequire(JSContext *context, RCTJSCExecutor *executor)
|
||||
@@ -774,6 +788,8 @@ static void registerNativeRequire(JSContext *context, RCTJSCExecutor *executor)
|
||||
static NSError *executeApplicationScript(NSData *script, NSURL *sourceURL, RCTJSCWrapper *jscWrapper,
|
||||
RCTPerformanceLogger *performanceLogger, JSGlobalContextRef ctx)
|
||||
{
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"executeApplicationScript / execute script",
|
||||
@{ @"url": sourceURL.absoluteString, @"size": @(script.length) });
|
||||
[performanceLogger markStartForTag:RCTPLScriptExecution];
|
||||
JSValueRef jsError = NULL;
|
||||
JSStringRef execJSString = jscWrapper->JSStringCreateWithUTF8CString((const char *)script.bytes);
|
||||
@@ -782,7 +798,9 @@ static NSError *executeApplicationScript(NSData *script, NSURL *sourceURL, RCTJS
|
||||
jscWrapper->JSStringRelease(bundleURL);
|
||||
jscWrapper->JSStringRelease(execJSString);
|
||||
[performanceLogger markStopForTag:RCTPLScriptExecution];
|
||||
return result ? nil : RCTNSErrorFromJSError(jscWrapper, ctx, jsError);
|
||||
NSError *error = result ? nil : RCTNSErrorFromJSError(jscWrapper, ctx, jsError);
|
||||
RCT_PROFILE_END_EVENT(0, @"js_call", nil);
|
||||
return error;
|
||||
}
|
||||
|
||||
- (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block
|
||||
@@ -812,37 +830,44 @@ static NSError *executeApplicationScript(NSData *script, NSURL *sourceURL, RCTJS
|
||||
}
|
||||
|
||||
__weak RCTJSCExecutor *weakSelf = self;
|
||||
[self executeBlockOnJavaScriptQueue:RCTProfileBlock((^{
|
||||
RCTProfileBeginFlowEvent();
|
||||
[self executeBlockOnJavaScriptQueue:^{
|
||||
RCTProfileEndFlowEvent();
|
||||
|
||||
RCTJSCExecutor *strongSelf = weakSelf;
|
||||
if (!strongSelf || !strongSelf.isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"injectJSONText", @{@"objectName": objectName});
|
||||
RCTJSCWrapper *jscWrapper = strongSelf->_jscWrapper;
|
||||
JSStringRef execJSString = jscWrapper->JSStringCreateWithCFString((__bridge CFStringRef)script);
|
||||
JSGlobalContextRef ctx = strongSelf->_context.context.JSGlobalContextRef;
|
||||
JSValueRef valueToInject = jscWrapper->JSValueMakeFromJSONString(ctx, execJSString);
|
||||
jscWrapper->JSStringRelease(execJSString);
|
||||
|
||||
NSError *error;
|
||||
if (!valueToInject) {
|
||||
NSString *errorDesc = [NSString stringWithFormat:@"Can't make JSON value from script '%@'", script];
|
||||
RCTLogError(@"%@", errorDesc);
|
||||
NSString *errorMessage = [NSString stringWithFormat:@"Can't make JSON value from script '%@'", script];
|
||||
error = [NSError errorWithDomain:RCTErrorDomain code:2 userInfo:@{NSLocalizedDescriptionKey: errorMessage}];
|
||||
RCTLogError(@"%@", errorMessage);
|
||||
} else {
|
||||
JSObjectRef globalObject = jscWrapper->JSContextGetGlobalObject(ctx);
|
||||
JSStringRef JSName = jscWrapper->JSStringCreateWithCFString((__bridge CFStringRef)objectName);
|
||||
JSValueRef jsError = NULL;
|
||||
jscWrapper->JSObjectSetProperty(ctx, globalObject, JSName, valueToInject, kJSPropertyAttributeNone, &jsError);
|
||||
jscWrapper->JSStringRelease(JSName);
|
||||
|
||||
if (onComplete) {
|
||||
NSError *error = [NSError errorWithDomain:RCTErrorDomain code:2 userInfo:@{NSLocalizedDescriptionKey: errorDesc}];
|
||||
onComplete(error);
|
||||
if (jsError) {
|
||||
error = RCTNSErrorFromJSError(jscWrapper, ctx, jsError);
|
||||
}
|
||||
return;
|
||||
}
|
||||
RCT_PROFILE_END_EVENT(0, @"js_call,json_call", nil);
|
||||
|
||||
JSObjectRef globalObject = jscWrapper->JSContextGetGlobalObject(ctx);
|
||||
JSStringRef JSName = jscWrapper->JSStringCreateWithCFString((__bridge CFStringRef)objectName);
|
||||
jscWrapper->JSObjectSetProperty(ctx, globalObject, JSName, valueToInject, kJSPropertyAttributeNone, NULL);
|
||||
jscWrapper->JSStringRelease(JSName);
|
||||
if (onComplete) {
|
||||
onComplete(nil);
|
||||
onComplete(error);
|
||||
}
|
||||
}), 0, @"js_call,json_call", (@{@"objectName": objectName}))];
|
||||
}];
|
||||
}
|
||||
|
||||
static bool readRandomAccessModule(const RandomAccessBundleData &bundleData, size_t offset, size_t size, char *data)
|
||||
|
||||
@@ -132,6 +132,8 @@ RCT_EXTERN void RCTProfileImmediateEvent(uint64_t tag,
|
||||
* self and _cmd to name this event for simplicity sake.
|
||||
*
|
||||
* NOTE: The block can't expect any argument
|
||||
*
|
||||
* DEPRECATED: this approach breaks debugging and stepping through instrumented block functions
|
||||
*/
|
||||
#define RCTProfileBlock(block, tag, category, arguments) \
|
||||
^{ \
|
||||
|
||||
Reference in New Issue
Block a user