Implement asm trampoline rather forwardInvocation
Summary: public The profiler overrides all the methods of all the BridgeModules, and in order to `start` and `end` the profiler at the function invocation time it used `NSInvocation`, which is slow. Replace it with a simple assembly method based on `objc_msgSend`. Reviewed By: jspahrsummers Differential Revision: D2550807 fb-gh-sync-id: 88ca08f9d6bfcd3035bda9304c93566c8818b46f
This commit is contained in:
parent
1b29690496
commit
89c1747c33
|
@ -7,7 +7,9 @@
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#if __OBJC__
|
||||||
|
# import <Foundation/Foundation.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make global functions usable in C++
|
* Make global functions usable in C++
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#import "RCTProfile.h"
|
#import "RCTProfile.h"
|
||||||
|
|
||||||
|
#import <dlfcn.h>
|
||||||
|
|
||||||
#import <mach/mach.h>
|
#import <mach/mach.h>
|
||||||
#import <objc/message.h>
|
#import <objc/message.h>
|
||||||
#import <objc/runtime.h>
|
#import <objc/runtime.h>
|
||||||
|
@ -153,21 +155,11 @@ static NSDictionary *RCTProfileMergeArgs(NSDictionary *args0, NSDictionary *args
|
||||||
|
|
||||||
#pragma mark - Module hooks
|
#pragma mark - Module hooks
|
||||||
|
|
||||||
static const char *RCTProfileProxyClassName(Class);
|
|
||||||
static const char *RCTProfileProxyClassName(Class class)
|
static const char *RCTProfileProxyClassName(Class class)
|
||||||
{
|
{
|
||||||
return [RCTProfilePrefix stringByAppendingString:NSStringFromClass(class)].UTF8String;
|
return [RCTProfilePrefix stringByAppendingString:NSStringFromClass(class)].UTF8String;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SEL RCTProfileProxySelector(SEL);
|
|
||||||
static SEL RCTProfileProxySelector(SEL selector)
|
|
||||||
{
|
|
||||||
NSString *selectorName = NSStringFromSelector(selector);
|
|
||||||
return NSSelectorFromString([RCTProfilePrefix stringByAppendingString:selectorName]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static dispatch_group_t RCTProfileGetUnhookGroup(void);
|
|
||||||
static dispatch_group_t RCTProfileGetUnhookGroup(void)
|
static dispatch_group_t RCTProfileGetUnhookGroup(void)
|
||||||
{
|
{
|
||||||
static dispatch_group_t unhookGroup;
|
static dispatch_group_t unhookGroup;
|
||||||
|
@ -179,45 +171,55 @@ static dispatch_group_t RCTProfileGetUnhookGroup(void)
|
||||||
return unhookGroup;
|
return unhookGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RCTProfileForwardInvocation(NSObject *, SEL, NSInvocation *);
|
RCT_EXTERN IMP RCTProfileGetImplementation(id obj, SEL cmd);
|
||||||
static void RCTProfileForwardInvocation(NSObject *self, __unused SEL cmd, NSInvocation *invocation)
|
IMP RCTProfileGetImplementation(id obj, SEL cmd)
|
||||||
{
|
{
|
||||||
/**
|
return class_getMethodImplementation([obj class], cmd);
|
||||||
* This is still not thread safe, but should reduce reasonably the number of crashes
|
|
||||||
*/
|
|
||||||
dispatch_group_wait(RCTProfileGetUnhookGroup(), DISPATCH_TIME_FOREVER);
|
|
||||||
|
|
||||||
NSString *name = [NSString stringWithFormat:@"-[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(invocation.selector)];
|
|
||||||
SEL newSel = RCTProfileProxySelector(invocation.selector);
|
|
||||||
|
|
||||||
if ([object_getClass(self) instancesRespondToSelector:newSel]) {
|
|
||||||
invocation.selector = newSel;
|
|
||||||
RCTProfileBeginEvent(0, name, nil);
|
|
||||||
[invocation invoke];
|
|
||||||
RCTProfileEndEvent(0, @"objc_call,modules,auto", nil);
|
|
||||||
} else if ([self respondsToSelector:invocation.selector]) {
|
|
||||||
[invocation invoke];
|
|
||||||
} else {
|
|
||||||
// Use original selector to don't change error message
|
|
||||||
[self doesNotRecognizeSelector:invocation.selector];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static IMP RCTProfileMsgForward(NSObject *, SEL);
|
/**
|
||||||
static IMP RCTProfileMsgForward(NSObject *self, SEL selector)
|
* For the profiling we have to execute some code before and after every
|
||||||
|
* function being profiled, the only way of doing that with pure Objective-C is
|
||||||
|
* by using `-forwardInvocation:`, which is slow and could skew the profile
|
||||||
|
* results.
|
||||||
|
*
|
||||||
|
* The alternative in assembly is much simpler, we just need to store all the
|
||||||
|
* state at the beginning of the function, start the profiler, restore all the
|
||||||
|
* state, call the actual function we want to profile and stop the profiler.
|
||||||
|
*
|
||||||
|
* The implementation can be found in RCTProfileTrampoline-<arch>.s where arch
|
||||||
|
* is one of: x86, x86_64, arm, arm64.
|
||||||
|
*/
|
||||||
|
static IMP RCTProfileGetTrampoline(void)
|
||||||
{
|
{
|
||||||
IMP imp = (IMP)_objc_msgForward;
|
static void (*RCTProfileTrampoline)(void);
|
||||||
#if !defined(__arm64__)
|
static dispatch_once_t onceToken;
|
||||||
NSMethodSignature *signature = [self methodSignatureForSelector:selector];
|
dispatch_once(&onceToken, ^{
|
||||||
if (signature.methodReturnType[0] == _C_STRUCT_B && signature.methodReturnLength > 8) {
|
RCTProfileTrampoline = dlsym(RTLD_DEFAULT, "RCTProfileTrampoline");
|
||||||
imp = (IMP)_objc_msgForward_stret;
|
});
|
||||||
}
|
|
||||||
#endif
|
return (IMP)RCTProfileTrampoline;
|
||||||
return imp;
|
}
|
||||||
|
|
||||||
|
RCT_EXTERN void RCTProfileTrampolineStart(id, SEL);
|
||||||
|
void RCTProfileTrampolineStart(id self, SEL cmd)
|
||||||
|
{
|
||||||
|
NSString *name = [NSString stringWithFormat:@"-[%s %s]", class_getName([self class]), sel_getName(cmd)];
|
||||||
|
RCTProfileBeginEvent(0, name, nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXTERN void RCTProfileTrampolineEnd(void);
|
||||||
|
void RCTProfileTrampolineEnd(void)
|
||||||
|
{
|
||||||
|
RCTProfileEndEvent(0, @"objc_call,modules,auto", nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RCTProfileHookModules(RCTBridge *bridge)
|
void RCTProfileHookModules(RCTBridge *bridge)
|
||||||
{
|
{
|
||||||
|
if (RCTProfileGetTrampoline() == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (RCTModuleData *moduleData in [bridge valueForKey:@"moduleDataByID"]) {
|
for (RCTModuleData *moduleData in [bridge valueForKey:@"moduleDataByID"]) {
|
||||||
[moduleData dispatchBlock:^{
|
[moduleData dispatchBlock:^{
|
||||||
Class moduleClass = moduleData.moduleClass;
|
Class moduleClass = moduleData.moduleClass;
|
||||||
|
@ -235,10 +237,9 @@ void RCTProfileHookModules(RCTBridge *bridge)
|
||||||
if ([NSStringFromSelector(selector) hasPrefix:@"rct"] || [NSObject instancesRespondToSelector:selector]) {
|
if ([NSStringFromSelector(selector) hasPrefix:@"rct"] || [NSObject instancesRespondToSelector:selector]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
IMP originalIMP = method_getImplementation(method);
|
const char *types = method_getTypeEncoding(method);
|
||||||
const char *returnType = method_getTypeEncoding(method);
|
|
||||||
class_addMethod(proxyClass, selector, RCTProfileMsgForward(moduleData.instance, selector), returnType);
|
class_addMethod(proxyClass, selector, RCTProfileGetTrampoline(), types);
|
||||||
class_addMethod(proxyClass, RCTProfileProxySelector(selector), originalIMP, returnType);
|
|
||||||
}
|
}
|
||||||
free(methods);
|
free(methods);
|
||||||
|
|
||||||
|
@ -249,11 +250,6 @@ void RCTProfileHookModules(RCTBridge *bridge)
|
||||||
class_replaceMethod(cls, @selector(class), imp_implementationWithBlock(^{ return moduleClass; }), method_getTypeEncoding(oldImp));
|
class_replaceMethod(cls, @selector(class), imp_implementationWithBlock(^{ return moduleClass; }), method_getTypeEncoding(oldImp));
|
||||||
}
|
}
|
||||||
|
|
||||||
IMP originalFwd = class_replaceMethod(moduleClass, @selector(forwardInvocation:), (IMP)RCTProfileForwardInvocation, "v@:@");
|
|
||||||
if (originalFwd != NULL) {
|
|
||||||
class_addMethod(proxyClass, RCTProfileProxySelector(@selector(forwardInvocation:)), originalFwd, "v@:@");
|
|
||||||
}
|
|
||||||
|
|
||||||
objc_registerClassPair(proxyClass);
|
objc_registerClassPair(proxyClass);
|
||||||
object_setClass(moduleData.instance, proxyClass);
|
object_setClass(moduleData.instance, proxyClass);
|
||||||
}];
|
}];
|
|
@ -0,0 +1,85 @@
|
||||||
|
#include "RCTDefines.h"
|
||||||
|
|
||||||
|
#if RCT_DEV && defined(__arm__)
|
||||||
|
|
||||||
|
.align 5
|
||||||
|
.globl _RCTProfileTrampoline
|
||||||
|
_RCTProfileTrampoline:
|
||||||
|
/**
|
||||||
|
* The explanation here is shorter, refer to the x86_64 implementation to a
|
||||||
|
* richer explanation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the parameter registers (r0-r3), r7 (frame pointer) and lr (link
|
||||||
|
* register (contains the address of the caller of RCTProfileTrampoline)
|
||||||
|
*/
|
||||||
|
push {r0-r3, r7, lr}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate memory to store values across function calls: 12-bytes are
|
||||||
|
* allocated to store 3 values: the previous value of the callee saved
|
||||||
|
* register used to save the pointer to the allocated memory, the caller of
|
||||||
|
* RCTProfileTrampoline and the address of the actual function we want to
|
||||||
|
* profile
|
||||||
|
*/
|
||||||
|
mov r0, #0xc
|
||||||
|
bl _malloc
|
||||||
|
/**
|
||||||
|
* r4 is the callee saved register we'll use to refer to the allocated memory,
|
||||||
|
* store its initial value, so we can restore it later
|
||||||
|
*/
|
||||||
|
str r4, [r0]
|
||||||
|
mov r4, r0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* void RCTProfileGetImplementation(id object, SEL selector) in RCTProfile.m
|
||||||
|
*
|
||||||
|
* Load the first 2 argumenters (self and _cmd) used to call
|
||||||
|
* RCTProfileTrampoline from the stack and put them on the appropriate registers.
|
||||||
|
*/
|
||||||
|
ldr r0, [sp]
|
||||||
|
ldr r1, [sp, #0x4]
|
||||||
|
bl _RCTProfileGetImplementation
|
||||||
|
// store the actual function address in the allocated memory
|
||||||
|
str r0, [r4, #0x4]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* void RCTProfileGetImplementation(id object, SEL selector) in RCTProfile.m
|
||||||
|
*
|
||||||
|
* Load the first 2 arguments again to start the profiler
|
||||||
|
*/
|
||||||
|
ldr r0, [sp]
|
||||||
|
ldr r1, [sp, #0x4]
|
||||||
|
bl _RCTProfileTrampolineStart
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the state to call the actual function we want to profile: pop
|
||||||
|
* all the registers
|
||||||
|
*/
|
||||||
|
pop {r0-r3, r7, lr}
|
||||||
|
|
||||||
|
// store lr (the caller) since it'll be overridden by `blx` (call)
|
||||||
|
str lr, [r4, #0x8]
|
||||||
|
ldr r12, [r4, #0x4] // load the function address
|
||||||
|
blx r12 // call it
|
||||||
|
push {r0} // save return value
|
||||||
|
|
||||||
|
// void RCTProfileTrampolineEnd(void) in RCTProfile.m - just ends this profile
|
||||||
|
bl _RCTProfileTrampolineEnd
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the value we still need from the allocated memory (caller address),
|
||||||
|
* restore r4 and free the allocated memory (put its address in r0)
|
||||||
|
*/
|
||||||
|
mov r0, r4
|
||||||
|
ldr r1, [r4, #0x8]
|
||||||
|
ldr r4, [r4]
|
||||||
|
push {r1} // save the caller on the stack
|
||||||
|
bl _free
|
||||||
|
|
||||||
|
pop {lr} // pop the caller
|
||||||
|
pop {r0} // pop the return value
|
||||||
|
bx lr // jump to the calleer
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,117 @@
|
||||||
|
#include "RCTDefines.h"
|
||||||
|
|
||||||
|
#if RCT_DEV && defined(__arm64__)
|
||||||
|
|
||||||
|
.align 5
|
||||||
|
.globl _RCTProfileTrampoline
|
||||||
|
_RCTProfileTrampoline:
|
||||||
|
/**
|
||||||
|
* The explanation here is shorter, refer to the x86_64 implementation to a
|
||||||
|
* richer explanation
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Basic prolog: save the frame pointer and the link register (caller address)
|
||||||
|
stp fp, lr, [sp, #-16]!
|
||||||
|
mov fp, sp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the value of all the parameter registers (x0-x8, q0-q7) so we can
|
||||||
|
* restore everything to the initial state at the time of the actual function
|
||||||
|
* call
|
||||||
|
*/
|
||||||
|
sub sp, sp, #(10*8 + 8*16)
|
||||||
|
stp q0, q1, [sp, #(0*16)]
|
||||||
|
stp q2, q3, [sp, #(2*16)]
|
||||||
|
stp q4, q5, [sp, #(4*16)]
|
||||||
|
stp q6, q7, [sp, #(6*16)]
|
||||||
|
stp x0, x1, [sp, #(8*16+0*8)]
|
||||||
|
stp x2, x3, [sp, #(8*16+2*8)]
|
||||||
|
stp x4, x5, [sp, #(8*16+4*8)]
|
||||||
|
stp x6, x7, [sp, #(8*16+6*8)]
|
||||||
|
str x8, [sp, #(8*16+8*8)]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate 16-bytes for the values that have to be preserved across the call
|
||||||
|
* to the actual function, since the stack has to be in the exact initial
|
||||||
|
* state. During its lifetimewe use it to store the initial value of the
|
||||||
|
* callee saved registers we use to point the memory, the actual address of
|
||||||
|
* the implementation and the caller address.
|
||||||
|
*/
|
||||||
|
mov x0, #0x10
|
||||||
|
bl _malloc
|
||||||
|
// store the initial value of r19, the callee saved register we'll use
|
||||||
|
str x19, [x0]
|
||||||
|
mov x19, x0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* void RCTProfileGetImplementation(id object, SEL selector)
|
||||||
|
*
|
||||||
|
* Load the 2 first arguments from the stack, they are the same used to call
|
||||||
|
* this function
|
||||||
|
*/
|
||||||
|
ldp x0, x1, [sp, #(8*16+0*8)]
|
||||||
|
bl _RCTProfileGetImplementation
|
||||||
|
str x0, [x19, #0x8] // store the actual function address
|
||||||
|
|
||||||
|
/**
|
||||||
|
* void RCTProfileTrampolineStart(id, SEL) in RCTProfile.m
|
||||||
|
*
|
||||||
|
* start the profile, it takes the same first 2 arguments as above.
|
||||||
|
*/
|
||||||
|
ldp x0, x1, [sp, #(8*16+0*8)]
|
||||||
|
bl _RCTProfileTrampolineStart
|
||||||
|
|
||||||
|
// Restore all the parameter registers to the initial state.
|
||||||
|
ldp q0, q1, [sp, #(0*16)]
|
||||||
|
ldp q2, q3, [sp, #(2*16)]
|
||||||
|
ldp q4, q5, [sp, #(4*16)]
|
||||||
|
ldp q6, q7, [sp, #(6*16)]
|
||||||
|
ldp x0, x1, [sp, #(8*16+0*8)]
|
||||||
|
ldp x2, x3, [sp, #(8*16+2*8)]
|
||||||
|
ldp x4, x5, [sp, #(8*16+4*8)]
|
||||||
|
ldp x6, x7, [sp, #(8*16+6*8)]
|
||||||
|
ldr x8, [sp, #(8*16+8*8)]
|
||||||
|
|
||||||
|
// Restore the stack pointer, frame pointer and link register
|
||||||
|
mov sp, fp
|
||||||
|
ldp fp, lr, [sp], #16
|
||||||
|
|
||||||
|
|
||||||
|
ldr x9, [x19, #0x8] // Load the function
|
||||||
|
str lr, [x19, #0x8] // store the address of the caller
|
||||||
|
|
||||||
|
blr x9 // call the actual function
|
||||||
|
|
||||||
|
/**
|
||||||
|
* allocate 32-bytes on the stack, for the 2 return values + the caller
|
||||||
|
* address that has to preserved across the call to `free`
|
||||||
|
*/
|
||||||
|
sub sp, sp, #0x20
|
||||||
|
str q0, [sp, #0x0] // 16-byte return value
|
||||||
|
str x0, [sp, #0x10] // 8-byte return value
|
||||||
|
|
||||||
|
// void RCTProfileTrampolineEnd(void) in RCTProfile.m - just ends this profile
|
||||||
|
bl _RCTProfileTrampolineEnd
|
||||||
|
|
||||||
|
/**
|
||||||
|
* restore the callee saved registers, move the values we still need to the
|
||||||
|
* stack and free the allocated memory
|
||||||
|
*/
|
||||||
|
mov x0, x19 // move the address of the memory to x0, first argument
|
||||||
|
ldr x10, [x19, #0x8] // load the caller address
|
||||||
|
ldr x19, [x19] // restore x19
|
||||||
|
str x10, [sp, #0x18] // store x10 on the stack space allocated above
|
||||||
|
bl _free
|
||||||
|
|
||||||
|
// Load both return values and link register from the stack
|
||||||
|
ldr q0, [sp, #0x0]
|
||||||
|
ldr x0, [sp, #0x10]
|
||||||
|
ldr lr, [sp, #0x18]
|
||||||
|
|
||||||
|
// restore the stack pointer
|
||||||
|
add sp, sp, #0x20
|
||||||
|
|
||||||
|
// jump to the calleer, without a link
|
||||||
|
br lr
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,89 @@
|
||||||
|
#include "RCTDefines.h"
|
||||||
|
|
||||||
|
#if RCT_DEV && defined(__i386__)
|
||||||
|
|
||||||
|
.globl _RCTProfileTrampoline
|
||||||
|
_RCTProfileTrampoline:
|
||||||
|
/**
|
||||||
|
* The x86 version is much simpler, since all the arguments are passed in the
|
||||||
|
* stack, so we just have to preserve the stack pointer (%esp) and the callee
|
||||||
|
* saved register used to keep the memory allocated
|
||||||
|
*
|
||||||
|
* The explanation here is also shorter, refer to the x86_64 implementation to
|
||||||
|
* a richer explanation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate memory to save the caller of RCTProfileTrampoline (used afterwards
|
||||||
|
* to return at the end of the function) and the initial value for the callee
|
||||||
|
* saved register (%edi) that will be used to point to the memory allocated.
|
||||||
|
*/
|
||||||
|
subl $0x8, %esp // stack padding (16-byte alignment for function calls)
|
||||||
|
pushl $0xc // allocate 12-bytes
|
||||||
|
calll _malloc
|
||||||
|
addl $0xc, %esp // restore stack (8-byte padding + 4-byte argument)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* actually store the values in the memory allocated
|
||||||
|
*/
|
||||||
|
movl %edi, 0x0(%eax) // previous value of edi
|
||||||
|
popl 0x4(%eax) // caller of RCTProfileTrampoline
|
||||||
|
|
||||||
|
// save the pointer to the allocated memory in %edi
|
||||||
|
movl %eax, %edi
|
||||||
|
|
||||||
|
/**
|
||||||
|
* void RCTProfileGetImplementation(id object, SEL selector) in RCTProfile.m
|
||||||
|
*
|
||||||
|
* Get the address of the actual C function we have to profile
|
||||||
|
*/
|
||||||
|
calll _RCTProfileGetImplementation
|
||||||
|
movl %eax, 0x8(%edi) // Save it in the allocated memory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* void RCTProfileTrampolineStart(id, SEL) in RCTProfile.m
|
||||||
|
*
|
||||||
|
* start profile - the arguments are already in the right position in the
|
||||||
|
* stack since it takes the same first 2 arguments as the any ObjC function -
|
||||||
|
* "self" and "_cmd"
|
||||||
|
*/
|
||||||
|
calll _RCTProfileTrampolineStart
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the actual function and save it's return value, since it should be the
|
||||||
|
* return value of RCTProfileTrampoline
|
||||||
|
*/
|
||||||
|
calll *0x8(%edi)
|
||||||
|
pushl %eax
|
||||||
|
|
||||||
|
// Align stack and end profile
|
||||||
|
subl $0xc, %esp
|
||||||
|
calll _RCTProfileTrampolineEnd
|
||||||
|
addl $0xc, %esp // restore the stack
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the values from the allocated memory to the stack, restore the
|
||||||
|
* value of %edi, and prepare to free the allocated memory.
|
||||||
|
*/
|
||||||
|
pushl 0x4(%edi) // caller of RCTProfileTrampoline
|
||||||
|
subl $0x4, %esp // Stack padding
|
||||||
|
pushl %edi // push the memory address
|
||||||
|
movl 0x0(%edi), %edi // restore the value of %edi
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually free the memory used to store the values across function calls,
|
||||||
|
* the stack has already been padded and the first and only argument, the
|
||||||
|
* memory address, is already in the bottom of the stack.
|
||||||
|
*/
|
||||||
|
calll _free
|
||||||
|
addl $0x8, %esp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pop the caller address to %ecx and the actual function return value to
|
||||||
|
* %eax, so it's the return value of RCTProfileTrampoline
|
||||||
|
*/
|
||||||
|
popl %ecx
|
||||||
|
popl %eax
|
||||||
|
jmpl *%ecx
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,170 @@
|
||||||
|
#include "RCTDefines.h"
|
||||||
|
|
||||||
|
#if RCT_DEV && defined(__x86_64__)
|
||||||
|
|
||||||
|
.globl _RCTProfileTrampoline
|
||||||
|
_RCTProfileTrampoline:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves all the state so we can restore it before calling the functions being
|
||||||
|
* profiled. Registers have the same value at the point of the function call,
|
||||||
|
* the only thing we can change is the return value, so we return to
|
||||||
|
* `RCTProfileTrampoline` rather than to its caller.
|
||||||
|
*
|
||||||
|
* Save all the parameters registers (%rdi, %rsi, %rdx, %rcx, %r8, %r9), they
|
||||||
|
* have the 6 first arguments of the function call, and %rax which in special
|
||||||
|
* cases might be a pointer used for struct returns.
|
||||||
|
*
|
||||||
|
* We have to save %r12 since its value should be preserved across function
|
||||||
|
* calls and we'll use it to keep the stack pointer
|
||||||
|
*/
|
||||||
|
pushq %rdi
|
||||||
|
pushq %rsi
|
||||||
|
pushq %rdx
|
||||||
|
pushq %rcx
|
||||||
|
pushq %r8
|
||||||
|
pushq %r9
|
||||||
|
pushq %rax
|
||||||
|
pushq %r12
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the stack pointer in the callee saved register %r12 and align the
|
||||||
|
* stack - it has to 16-byte aligned at the point of the function call
|
||||||
|
*/
|
||||||
|
movq %rsp, %r12
|
||||||
|
andq $-0x10, %rsp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* void RCTProfileGetImplementation(id object, SEL selector)
|
||||||
|
*
|
||||||
|
* This is a C function defined in `RCTProfile.m`, the object and the selector
|
||||||
|
* already have to be on %rdi and %rsi respectively, as in any ObjC call.
|
||||||
|
*/
|
||||||
|
callq _RCTProfileGetImplementation
|
||||||
|
|
||||||
|
// Restore/unalign the stack pointer, so we can access the registers we stored
|
||||||
|
movq %r12, %rsp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pop %r12 before pushing %rax, which contains the address of the actual
|
||||||
|
* function we have to call, than we keep %r12 at the bottom of the stack to
|
||||||
|
* reference the stack pointer
|
||||||
|
*/
|
||||||
|
popq %r12
|
||||||
|
pushq %rax
|
||||||
|
pushq %r12
|
||||||
|
|
||||||
|
// align stack
|
||||||
|
movq %rsp, %r12
|
||||||
|
andq $-0x10, %rsp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate memory to save parent before start profiling: the address is put
|
||||||
|
* at the bottom of the stack at the function call, so ret can actually return
|
||||||
|
* to the caller. In this case it has the address of RCTProfileTrampoline's
|
||||||
|
* caller where we'll have to return to after we're finished.
|
||||||
|
*
|
||||||
|
* We can't store it on the stack or in any register, since we have to be in
|
||||||
|
* the exact same state we were at the moment we were called, so the solution
|
||||||
|
* is to allocate a tiny bit of memory to save this address
|
||||||
|
*/
|
||||||
|
|
||||||
|
// allocate 16 bytes
|
||||||
|
movq $0x10, %rdi
|
||||||
|
callq _malloc
|
||||||
|
|
||||||
|
// store the initial value of calle saved registers %r13 and %r14
|
||||||
|
movq %r13, 0x0(%rax)
|
||||||
|
movq %r14, 0x8(%rax)
|
||||||
|
|
||||||
|
// mov the pointers we need to the callee saved registers
|
||||||
|
movq 0x48(%rsp), %r13 // caller of RCTProfileTrampoline
|
||||||
|
movq %rax, %r14 // allocated memory's address
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move self and cmd back to the registers and call start profile: it uses
|
||||||
|
* the object and the selector to label the call in the profile.
|
||||||
|
*/
|
||||||
|
movq 0x40(%r12), %rdi // object
|
||||||
|
movq 0x38(%r12), %rsi // selector
|
||||||
|
|
||||||
|
// void RCTProfileTrampolineStart(id, SEL) in RCTProfile.m
|
||||||
|
callq _RCTProfileTrampolineStart
|
||||||
|
|
||||||
|
// unalign the stack and restore %r12
|
||||||
|
movq %r12, %rsp
|
||||||
|
popq %r12
|
||||||
|
|
||||||
|
// Restore registers for actual function call
|
||||||
|
popq %r11
|
||||||
|
popq %rax
|
||||||
|
popq %r9
|
||||||
|
popq %r8
|
||||||
|
popq %rcx
|
||||||
|
popq %rdx
|
||||||
|
popq %rsi
|
||||||
|
popq %rdi
|
||||||
|
|
||||||
|
/**
|
||||||
|
* delete parent caller (saved in %r13) `call` will add the new address so
|
||||||
|
* we return to RCTProfileTrampoline rather than to its caller
|
||||||
|
*/
|
||||||
|
addq $0x8, %rsp
|
||||||
|
|
||||||
|
// call the actual function and save the return value
|
||||||
|
callq *%r11
|
||||||
|
pushq %rax
|
||||||
|
|
||||||
|
// align stack
|
||||||
|
pushq %r12
|
||||||
|
movq %rsp, %r12
|
||||||
|
andq $-0x10, %rsp
|
||||||
|
|
||||||
|
// void RCTProfileTrampolineEnd(void) in RCTProfile.m - just ends this profile
|
||||||
|
callq _RCTProfileTrampolineEnd
|
||||||
|
|
||||||
|
// unalign stack and restore %r12
|
||||||
|
movq %r12, %rsp
|
||||||
|
popq %r12
|
||||||
|
|
||||||
|
// save the return of the actual function call
|
||||||
|
popq %rax
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the initial value of the callee saved registers, saved in the
|
||||||
|
* memory allocated.
|
||||||
|
*/
|
||||||
|
movq %r13, %rcx
|
||||||
|
movq %r14, %rdx
|
||||||
|
movq 0x0(%r14), %r13
|
||||||
|
movq 0x8(%r14), %r14
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save caller address and actual function return (previously in the allocated
|
||||||
|
* memory) and align the stack
|
||||||
|
*/
|
||||||
|
pushq %rcx
|
||||||
|
pushq %rax
|
||||||
|
pushq %r12
|
||||||
|
movq %rsp, %r12
|
||||||
|
andq $-0x10, %rsp
|
||||||
|
|
||||||
|
// Free the memory allocated to stash callee saved registers
|
||||||
|
movq %rdx, %rdi
|
||||||
|
callq _free
|
||||||
|
|
||||||
|
// unalign stack and restore %r12
|
||||||
|
movq %r12, %rsp
|
||||||
|
popq %r12
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pop the caller address to %rcx and the actual function return value to
|
||||||
|
* %rax, so it's the return value of RCTProfileTrampoline
|
||||||
|
*/
|
||||||
|
popq %rax
|
||||||
|
popq %rcx
|
||||||
|
|
||||||
|
// jump to caller
|
||||||
|
jmpq *%rcx
|
||||||
|
|
||||||
|
#endif
|
|
@ -54,6 +54,11 @@
|
||||||
142014191B32094000CC17BA /* RCTPerformanceLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 142014171B32094000CC17BA /* RCTPerformanceLogger.m */; };
|
142014191B32094000CC17BA /* RCTPerformanceLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 142014171B32094000CC17BA /* RCTPerformanceLogger.m */; };
|
||||||
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE21AAC4AE100FC20F4 /* RCTMap.m */; };
|
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE21AAC4AE100FC20F4 /* RCTMap.m */; };
|
||||||
14435CE61AAC4AE100FC20F4 /* RCTMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */; };
|
14435CE61AAC4AE100FC20F4 /* RCTMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */; };
|
||||||
|
1450FF861BCFF28A00208362 /* RCTProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF811BCFF28A00208362 /* RCTProfile.m */; settings = {ASSET_TAGS = (); }; };
|
||||||
|
1450FF871BCFF28A00208362 /* RCTProfileTrampoline-arm.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF821BCFF28A00208362 /* RCTProfileTrampoline-arm.S */; settings = {ASSET_TAGS = (); }; };
|
||||||
|
1450FF881BCFF28A00208362 /* RCTProfileTrampoline-arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF831BCFF28A00208362 /* RCTProfileTrampoline-arm64.S */; settings = {ASSET_TAGS = (); }; };
|
||||||
|
1450FF891BCFF28A00208362 /* RCTProfileTrampoline-x86.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF841BCFF28A00208362 /* RCTProfileTrampoline-x86.S */; settings = {ASSET_TAGS = (); }; };
|
||||||
|
1450FF8A1BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF851BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S */; settings = {ASSET_TAGS = (); }; };
|
||||||
146459261B06C49500B389AA /* RCTFPSGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 146459251B06C49500B389AA /* RCTFPSGraph.m */; };
|
146459261B06C49500B389AA /* RCTFPSGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 146459251B06C49500B389AA /* RCTFPSGraph.m */; };
|
||||||
14C2CA711B3AC63800E6CBB2 /* RCTModuleMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C2CA701B3AC63800E6CBB2 /* RCTModuleMethod.m */; };
|
14C2CA711B3AC63800E6CBB2 /* RCTModuleMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C2CA701B3AC63800E6CBB2 /* RCTModuleMethod.m */; };
|
||||||
14C2CA741B3AC64300E6CBB2 /* RCTModuleData.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C2CA731B3AC64300E6CBB2 /* RCTModuleData.m */; };
|
14C2CA741B3AC64300E6CBB2 /* RCTModuleData.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C2CA731B3AC64300E6CBB2 /* RCTModuleData.m */; };
|
||||||
|
@ -62,7 +67,6 @@
|
||||||
14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F362081AABD06A001CE568 /* RCTSwitch.m */; };
|
14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F362081AABD06A001CE568 /* RCTSwitch.m */; };
|
||||||
14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */; };
|
14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */; };
|
||||||
14F484561AABFCE100FDF6B9 /* RCTSliderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */; };
|
14F484561AABFCE100FDF6B9 /* RCTSliderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */; };
|
||||||
14F4D38B1AE1B7E40049C042 /* RCTProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F4D38A1AE1B7E40049C042 /* RCTProfile.m */; };
|
|
||||||
58114A161AAE854800E7D092 /* RCTPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A131AAE854800E7D092 /* RCTPicker.m */; };
|
58114A161AAE854800E7D092 /* RCTPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A131AAE854800E7D092 /* RCTPicker.m */; };
|
||||||
58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A151AAE854800E7D092 /* RCTPickerManager.m */; };
|
58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A151AAE854800E7D092 /* RCTPickerManager.m */; };
|
||||||
58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A4E1AAE93D500E7D092 /* RCTAsyncLocalStorage.m */; };
|
58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A4E1AAE93D500E7D092 /* RCTAsyncLocalStorage.m */; };
|
||||||
|
@ -203,6 +207,12 @@
|
||||||
14435CE21AAC4AE100FC20F4 /* RCTMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMap.m; sourceTree = "<group>"; };
|
14435CE21AAC4AE100FC20F4 /* RCTMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMap.m; sourceTree = "<group>"; };
|
||||||
14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMapManager.h; sourceTree = "<group>"; };
|
14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMapManager.h; sourceTree = "<group>"; };
|
||||||
14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMapManager.m; sourceTree = "<group>"; };
|
14435CE41AAC4AE100FC20F4 /* RCTMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMapManager.m; sourceTree = "<group>"; };
|
||||||
|
1450FF801BCFF28A00208362 /* RCTProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTProfile.h; sourceTree = "<group>"; };
|
||||||
|
1450FF811BCFF28A00208362 /* RCTProfile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTProfile.m; sourceTree = "<group>"; };
|
||||||
|
1450FF821BCFF28A00208362 /* RCTProfileTrampoline-arm.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "RCTProfileTrampoline-arm.S"; sourceTree = "<group>"; };
|
||||||
|
1450FF831BCFF28A00208362 /* RCTProfileTrampoline-arm64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "RCTProfileTrampoline-arm64.S"; sourceTree = "<group>"; };
|
||||||
|
1450FF841BCFF28A00208362 /* RCTProfileTrampoline-x86.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "RCTProfileTrampoline-x86.S"; sourceTree = "<group>"; };
|
||||||
|
1450FF851BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "RCTProfileTrampoline-x86_64.S"; sourceTree = "<group>"; };
|
||||||
146459241B06C49500B389AA /* RCTFPSGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTFPSGraph.h; sourceTree = "<group>"; };
|
146459241B06C49500B389AA /* RCTFPSGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTFPSGraph.h; sourceTree = "<group>"; };
|
||||||
146459251B06C49500B389AA /* RCTFPSGraph.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTFPSGraph.m; sourceTree = "<group>"; };
|
146459251B06C49500B389AA /* RCTFPSGraph.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTFPSGraph.m; sourceTree = "<group>"; };
|
||||||
1482F9E61B55B927000ADFF3 /* RCTBridgeDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTBridgeDelegate.h; sourceTree = "<group>"; };
|
1482F9E61B55B927000ADFF3 /* RCTBridgeDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTBridgeDelegate.h; sourceTree = "<group>"; };
|
||||||
|
@ -218,8 +228,6 @@
|
||||||
14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSwitchManager.m; sourceTree = "<group>"; };
|
14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSwitchManager.m; sourceTree = "<group>"; };
|
||||||
14F484541AABFCE100FDF6B9 /* RCTSliderManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSliderManager.h; sourceTree = "<group>"; };
|
14F484541AABFCE100FDF6B9 /* RCTSliderManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSliderManager.h; sourceTree = "<group>"; };
|
||||||
14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSliderManager.m; sourceTree = "<group>"; };
|
14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSliderManager.m; sourceTree = "<group>"; };
|
||||||
14F4D3891AE1B7E40049C042 /* RCTProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTProfile.h; sourceTree = "<group>"; };
|
|
||||||
14F4D38A1AE1B7E40049C042 /* RCTProfile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTProfile.m; sourceTree = "<group>"; };
|
|
||||||
58114A121AAE854800E7D092 /* RCTPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPicker.h; sourceTree = "<group>"; };
|
58114A121AAE854800E7D092 /* RCTPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPicker.h; sourceTree = "<group>"; };
|
||||||
58114A131AAE854800E7D092 /* RCTPicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPicker.m; sourceTree = "<group>"; };
|
58114A131AAE854800E7D092 /* RCTPicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPicker.m; sourceTree = "<group>"; };
|
||||||
58114A141AAE854800E7D092 /* RCTPickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPickerManager.h; sourceTree = "<group>"; };
|
58114A141AAE854800E7D092 /* RCTPickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPickerManager.h; sourceTree = "<group>"; };
|
||||||
|
@ -422,6 +430,19 @@
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
1450FF7F1BCFF28A00208362 /* Profiler */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1450FF801BCFF28A00208362 /* RCTProfile.h */,
|
||||||
|
1450FF811BCFF28A00208362 /* RCTProfile.m */,
|
||||||
|
1450FF821BCFF28A00208362 /* RCTProfileTrampoline-arm.S */,
|
||||||
|
1450FF831BCFF28A00208362 /* RCTProfileTrampoline-arm64.S */,
|
||||||
|
1450FF841BCFF28A00208362 /* RCTProfileTrampoline-x86.S */,
|
||||||
|
1450FF851BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S */,
|
||||||
|
);
|
||||||
|
path = Profiler;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
83CBB9F61A601CBA00E9B192 = {
|
83CBB9F61A601CBA00E9B192 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -447,6 +468,7 @@
|
||||||
134FCB381A6E7F0800051CC8 /* Executors */,
|
134FCB381A6E7F0800051CC8 /* Executors */,
|
||||||
13B07FC41A68125100A75B9A /* Layout */,
|
13B07FC41A68125100A75B9A /* Layout */,
|
||||||
13B07FE01A69315300A75B9A /* Modules */,
|
13B07FE01A69315300A75B9A /* Modules */,
|
||||||
|
1450FF7F1BCFF28A00208362 /* Profiler */,
|
||||||
13B07FF31A6947C200A75B9A /* Views */,
|
13B07FF31A6947C200A75B9A /* Views */,
|
||||||
);
|
);
|
||||||
name = React;
|
name = React;
|
||||||
|
@ -491,8 +513,6 @@
|
||||||
142014171B32094000CC17BA /* RCTPerformanceLogger.m */,
|
142014171B32094000CC17BA /* RCTPerformanceLogger.m */,
|
||||||
1403F2B11B0AE60700C2A9A4 /* RCTPerfStats.h */,
|
1403F2B11B0AE60700C2A9A4 /* RCTPerfStats.h */,
|
||||||
1403F2B21B0AE60700C2A9A4 /* RCTPerfStats.m */,
|
1403F2B21B0AE60700C2A9A4 /* RCTPerfStats.m */,
|
||||||
14F4D3891AE1B7E40049C042 /* RCTProfile.h */,
|
|
||||||
14F4D38A1AE1B7E40049C042 /* RCTProfile.m */,
|
|
||||||
830A229C1A66C68A008503DA /* RCTRootView.h */,
|
830A229C1A66C68A008503DA /* RCTRootView.h */,
|
||||||
830A229D1A66C68A008503DA /* RCTRootView.m */,
|
830A229D1A66C68A008503DA /* RCTRootView.m */,
|
||||||
83BEE46C1A6D19BC00B5863B /* RCTSparseArray.h */,
|
83BEE46C1A6D19BC00B5863B /* RCTSparseArray.h */,
|
||||||
|
@ -614,13 +634,14 @@
|
||||||
8385CF351B8B77CD00C6273E /* RCTKeyboardObserver.m in Sources */,
|
8385CF351B8B77CD00C6273E /* RCTKeyboardObserver.m in Sources */,
|
||||||
58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */,
|
58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */,
|
||||||
832348161A77A5AA00B55238 /* Layout.c in Sources */,
|
832348161A77A5AA00B55238 /* Layout.c in Sources */,
|
||||||
14F4D38B1AE1B7E40049C042 /* RCTProfile.m in Sources */,
|
|
||||||
13513F3C1B1F43F400FCE529 /* RCTProgressViewManager.m in Sources */,
|
13513F3C1B1F43F400FCE529 /* RCTProgressViewManager.m in Sources */,
|
||||||
14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */,
|
14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */,
|
||||||
14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */,
|
14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */,
|
||||||
13B080201A69489C00A75B9A /* RCTActivityIndicatorViewManager.m in Sources */,
|
13B080201A69489C00A75B9A /* RCTActivityIndicatorViewManager.m in Sources */,
|
||||||
13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */,
|
13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */,
|
||||||
58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */,
|
58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */,
|
||||||
|
1450FF8A1BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S in Sources */,
|
||||||
|
1450FF881BCFF28A00208362 /* RCTProfileTrampoline-arm64.S in Sources */,
|
||||||
13B080061A6947C200A75B9A /* RCTScrollViewManager.m in Sources */,
|
13B080061A6947C200A75B9A /* RCTScrollViewManager.m in Sources */,
|
||||||
146459261B06C49500B389AA /* RCTFPSGraph.m in Sources */,
|
146459261B06C49500B389AA /* RCTFPSGraph.m in Sources */,
|
||||||
14200DAA1AC179B3008EE6BA /* RCTJavaScriptLoader.m in Sources */,
|
14200DAA1AC179B3008EE6BA /* RCTJavaScriptLoader.m in Sources */,
|
||||||
|
@ -654,6 +675,7 @@
|
||||||
137327E81AA5CF210034F82E /* RCTTabBarItem.m in Sources */,
|
137327E81AA5CF210034F82E /* RCTTabBarItem.m in Sources */,
|
||||||
83A1FE8C1B62640A00BE0E65 /* RCTModalHostView.m in Sources */,
|
83A1FE8C1B62640A00BE0E65 /* RCTModalHostView.m in Sources */,
|
||||||
13E067551A70F44B002CDEE1 /* RCTShadowView.m in Sources */,
|
13E067551A70F44B002CDEE1 /* RCTShadowView.m in Sources */,
|
||||||
|
1450FF871BCFF28A00208362 /* RCTProfileTrampoline-arm.S in Sources */,
|
||||||
131B6AF51AF1093D00FFC3E0 /* RCTSegmentedControlManager.m in Sources */,
|
131B6AF51AF1093D00FFC3E0 /* RCTSegmentedControlManager.m in Sources */,
|
||||||
58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */,
|
58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */,
|
||||||
13B0801A1A69489C00A75B9A /* RCTNavigator.m in Sources */,
|
13B0801A1A69489C00A75B9A /* RCTNavigator.m in Sources */,
|
||||||
|
@ -662,6 +684,7 @@
|
||||||
13F17A851B8493E5007D4C75 /* RCTRedBox.m in Sources */,
|
13F17A851B8493E5007D4C75 /* RCTRedBox.m in Sources */,
|
||||||
83392EB31B6634E10013B15F /* RCTModalHostViewController.m in Sources */,
|
83392EB31B6634E10013B15F /* RCTModalHostViewController.m in Sources */,
|
||||||
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */,
|
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */,
|
||||||
|
1450FF891BCFF28A00208362 /* RCTProfileTrampoline-x86.S in Sources */,
|
||||||
134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */,
|
134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */,
|
||||||
13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */,
|
13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */,
|
||||||
1385D0341B665AAE000A309B /* RCTModuleMap.m in Sources */,
|
1385D0341B665AAE000A309B /* RCTModuleMap.m in Sources */,
|
||||||
|
@ -669,6 +692,7 @@
|
||||||
83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */,
|
83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */,
|
||||||
83A1FE8F1B62643A00BE0E65 /* RCTModalHostViewManager.m in Sources */,
|
83A1FE8F1B62643A00BE0E65 /* RCTModalHostViewManager.m in Sources */,
|
||||||
13E0674A1A70F434002CDEE1 /* RCTUIManager.m in Sources */,
|
13E0674A1A70F434002CDEE1 /* RCTUIManager.m in Sources */,
|
||||||
|
1450FF861BCFF28A00208362 /* RCTProfile.m in Sources */,
|
||||||
13AB90C11B6FA36700713B4F /* RCTComponentData.m in Sources */,
|
13AB90C11B6FA36700713B4F /* RCTComponentData.m in Sources */,
|
||||||
13B0801B1A69489C00A75B9A /* RCTNavigatorManager.m in Sources */,
|
13B0801B1A69489C00A75B9A /* RCTNavigatorManager.m in Sources */,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue