Fix RCTProfileHookModules instantiating all modules
Reviewed By: tadeuzagallo Differential Revision: D3235048 fb-gh-sync-id: bdcd72fb241c5136e884c1705e027f178939970b fbshipit-source-id: bdcd72fb241c5136e884c1705e027f178939970b
This commit is contained in:
parent
aebf4db45a
commit
a9a90aa2f0
|
@ -111,11 +111,6 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
|
|||
// Synchronously initialize all native modules that cannot be loaded lazily
|
||||
[self initModulesWithDispatchGroup:initModulesAndLoadSource];
|
||||
|
||||
if (RCTProfileIsProfiling()) {
|
||||
// Depends on moduleDataByID being loaded
|
||||
RCTProfileHookModules(self);
|
||||
}
|
||||
|
||||
__block NSString *config;
|
||||
dispatch_group_enter(initModulesAndLoadSource);
|
||||
dispatch_async(bridgeQueue, ^{
|
||||
|
|
|
@ -98,6 +98,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
|
|||
"bridge.", _moduleClass);
|
||||
}
|
||||
}
|
||||
|
||||
if (RCTProfileIsProfiling()) {
|
||||
RCTProfileHookInstance(_instance);
|
||||
}
|
||||
|
||||
// Bridge must be set before methodQueue is set up, as methodQueue
|
||||
// initialization requires it (View Managers get their queue by calling
|
||||
// self.bridge.uiManager.methodQueue)
|
||||
|
|
|
@ -15,6 +15,11 @@
|
|||
#import "RCTViewManager.h"
|
||||
#import "RCTRootView.h"
|
||||
|
||||
/**
|
||||
* Default name for the UIManager queue
|
||||
*/
|
||||
RCT_EXTERN char *const RCTUIManagerQueueName;
|
||||
|
||||
/**
|
||||
* Posted right before re-render happens. This is a chance for views to invalidate their state so
|
||||
* next render cycle will pick up updated views and layout appropriately.
|
||||
|
|
|
@ -46,6 +46,7 @@ static void RCTTraverseViewNodes(id<RCTComponent> view, void (^block)(id<RCTComp
|
|||
}
|
||||
}
|
||||
|
||||
char *const RCTUIManagerQueueName = "com.facebook.react.ShadowQueue";
|
||||
NSString *const RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification = @"RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification";
|
||||
NSString *const RCTUIManagerDidRegisterRootViewNotification = @"RCTUIManagerDidRegisterRootViewNotification";
|
||||
NSString *const RCTUIManagerDidRemoveRootViewNotification = @"RCTUIManagerDidRemoveRootViewNotification";
|
||||
|
@ -321,13 +322,11 @@ RCT_EXPORT_MODULE()
|
|||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
if (!_shadowQueue) {
|
||||
const char *queueName = "com.facebook.react.ShadowQueue";
|
||||
|
||||
if ([NSOperation instancesRespondToSelector:@selector(qualityOfService)]) {
|
||||
dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INTERACTIVE, 0);
|
||||
_shadowQueue = dispatch_queue_create(queueName, attr);
|
||||
_shadowQueue = dispatch_queue_create(RCTUIManagerQueueName, attr);
|
||||
} else {
|
||||
_shadowQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL);
|
||||
_shadowQueue = dispatch_queue_create(RCTUIManagerQueueName, DISPATCH_QUEUE_SERIAL);
|
||||
dispatch_set_target_queue(_shadowQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
|
||||
}
|
||||
}
|
||||
|
@ -1090,7 +1089,7 @@ RCT_EXPORT_METHOD(dispatchViewManagerCommand:(nonnull NSNumber *)reactTag
|
|||
RCTProfileBeginFlowEvent();
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
RCTProfileEndFlowEvent();
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"UIManager flushUIBlocks", nil);
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"-[UIManager flushUIBlocks]", nil);
|
||||
@try {
|
||||
for (dispatch_block_t block in previousPendingUIBlocks) {
|
||||
block();
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTDefines.h"
|
||||
#import "RCTAssert.h"
|
||||
|
||||
/**
|
||||
* RCTProfile
|
||||
|
@ -151,6 +152,11 @@ RCT_EXTERN void RCTProfileHookModules(RCTBridge *);
|
|||
*/
|
||||
RCT_EXTERN void RCTProfileUnhookModules(RCTBridge *);
|
||||
|
||||
/**
|
||||
* Hook into all of a module's methods
|
||||
*/
|
||||
RCT_EXTERN void RCTProfileHookInstance(id instance);
|
||||
|
||||
/**
|
||||
* Send systrace or cpu profiling information to the packager
|
||||
* to present to the user
|
||||
|
@ -217,6 +223,7 @@ RCT_EXTERN void RCTProfileHideControls(void);
|
|||
#define RCTProfileBlock(block, ...) block
|
||||
|
||||
#define RCTProfileHookModules(...)
|
||||
#define RCTProfileHookInstance(...)
|
||||
#define RCTProfileUnhookModules(...)
|
||||
|
||||
#define RCTProfileSendResult(...)
|
||||
|
|
|
@ -214,7 +214,31 @@ void RCTProfileTrampolineEnd(void)
|
|||
RCT_PROFILE_END_EVENT(0, @"objc_call,modules,auto", nil);
|
||||
}
|
||||
|
||||
static void RCTProfileHookInstance(id instance)
|
||||
static UIView *(*originalCreateView)(RCTComponentData *, SEL, NSNumber *);
|
||||
static UIView *RCTProfileCreateView(RCTComponentData *self, SEL _cmd, NSNumber *tag)
|
||||
{
|
||||
UIView *view = originalCreateView(self, _cmd, tag);
|
||||
RCTProfileHookInstance(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
static void RCTProfileHookUIManager(RCTUIManager *uiManager)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
for (id view in [uiManager valueForKey:@"viewRegistry"]) {
|
||||
RCTProfileHookInstance([uiManager viewForReactTag:view]);
|
||||
}
|
||||
|
||||
Method createView = class_getInstanceMethod([RCTComponentData class], @selector(createViewWithTag:));
|
||||
|
||||
if (method_getImplementation(createView) != (IMP)RCTProfileCreateView) {
|
||||
originalCreateView = (typeof(originalCreateView))method_getImplementation(createView);
|
||||
method_setImplementation(createView, (IMP)RCTProfileCreateView);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void RCTProfileHookInstance(id instance)
|
||||
{
|
||||
Class moduleClass = object_getClass(instance);
|
||||
|
||||
|
@ -279,18 +303,10 @@ static void RCTProfileHookInstance(id instance)
|
|||
|
||||
objc_registerClassPair(proxyClass);
|
||||
object_setClass(instance, proxyClass);
|
||||
}
|
||||
|
||||
static UIView *(*originalCreateView)(RCTComponentData *, SEL, NSNumber *);
|
||||
|
||||
RCT_EXTERN UIView *RCTProfileCreateView(RCTComponentData *self, SEL _cmd, NSNumber *tag);
|
||||
UIView *RCTProfileCreateView(RCTComponentData *self, SEL _cmd, NSNumber *tag)
|
||||
{
|
||||
UIView *view = originalCreateView(self, _cmd, tag);
|
||||
|
||||
RCTProfileHookInstance(view);
|
||||
|
||||
return view;
|
||||
if (moduleClass == [RCTUIManager class]) {
|
||||
RCTProfileHookUIManager((RCTUIManager *)instance);
|
||||
}
|
||||
}
|
||||
|
||||
void RCTProfileHookModules(RCTBridge *bridge)
|
||||
|
@ -305,23 +321,13 @@ void RCTProfileHookModules(RCTBridge *bridge)
|
|||
#pragma clang diagnostic pop
|
||||
|
||||
for (RCTModuleData *moduleData in [bridge valueForKey:@"moduleDataByID"]) {
|
||||
[bridge dispatchBlock:^{
|
||||
RCTProfileHookInstance(moduleData.instance);
|
||||
} queue:moduleData.methodQueue];
|
||||
// Only hook modules with an instance, to prevent initializing everything
|
||||
if ([moduleData hasInstance]) {
|
||||
[bridge dispatchBlock:^{
|
||||
RCTProfileHookInstance(moduleData.instance);
|
||||
} queue:moduleData.methodQueue];
|
||||
}
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
for (id view in [bridge.uiManager valueForKey:@"viewRegistry"]) {
|
||||
RCTProfileHookInstance([bridge.uiManager viewForReactTag:view]);
|
||||
}
|
||||
|
||||
Method createView = class_getInstanceMethod([RCTComponentData class], @selector(createViewWithTag:));
|
||||
|
||||
if (method_getImplementation(createView) != (IMP)RCTProfileCreateView) {
|
||||
originalCreateView = (typeof(originalCreateView))method_getImplementation(createView);
|
||||
method_setImplementation(createView, (IMP)RCTProfileCreateView);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void RCTProfileUnhookInstance(id instance)
|
||||
|
@ -337,17 +343,22 @@ void RCTProfileUnhookModules(RCTBridge *bridge)
|
|||
|
||||
dispatch_group_enter(RCTProfileGetUnhookGroup());
|
||||
|
||||
for (RCTModuleData *moduleData in [bridge valueForKey:@"moduleDataByID"]) {
|
||||
RCTProfileUnhookInstance(moduleData.instance);
|
||||
NSDictionary *moduleDataByID = [bridge valueForKey:@"moduleDataByID"];
|
||||
for (RCTModuleData *moduleData in moduleDataByID) {
|
||||
if ([moduleData hasInstance]) {
|
||||
RCTProfileUnhookInstance(moduleData.instance);
|
||||
}
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
for (id view in [bridge.uiManager valueForKey:@"viewRegistry"]) {
|
||||
RCTProfileUnhookInstance(view);
|
||||
}
|
||||
if ([bridge moduleIsInitialized:[RCTUIManager class]]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
for (id view in [bridge.uiManager valueForKey:@"viewRegistry"]) {
|
||||
RCTProfileUnhookInstance(view);
|
||||
}
|
||||
|
||||
dispatch_group_leave(RCTProfileGetUnhookGroup());
|
||||
});
|
||||
dispatch_group_leave(RCTProfileGetUnhookGroup());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private ObjC class only used for the vSYNC CADisplayLink target
|
||||
|
@ -457,8 +468,7 @@ void RCTProfileInit(RCTBridge *bridge)
|
|||
|
||||
// Set up thread ordering
|
||||
dispatch_async(RCTProfileGetQueue(), ^{
|
||||
NSString *shadowQueue = @(dispatch_queue_get_label([[bridge uiManager] methodQueue]));
|
||||
NSArray *orderedThreads = @[@"JS async", RCTJSCThreadName, shadowQueue, @"main"];
|
||||
NSArray *orderedThreads = @[@"JS async", @"RCTPerformanceLogger", RCTJSCThreadName, @(RCTUIManagerQueueName), @"main"];
|
||||
[orderedThreads enumerateObjectsUsingBlock:^(NSString *thread, NSUInteger idx, __unused BOOL *stop) {
|
||||
RCTProfileAddEvent(RCTProfileTraceEvents,
|
||||
@"ph": @"M", // metadata event
|
||||
|
|
Loading…
Reference in New Issue