123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- /**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
- #include "RCTDefines.h"
- #include "RCTMacros.h"
- #if RCT_PROFILE && defined(__arm64__)
- .align 5
- .globl SYMBOL_NAME(RCTProfileTrampoline)
- SYMBOL_NAME(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 SYMBOL_NAME(RCTProfileMalloc)
- // 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 SYMBOL_NAME(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 SYMBOL_NAME(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 SYMBOL_NAME(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 SYMBOL_NAME(RCTProfileFree)
- // 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
|