RCTProfileTrampoline-arm.S 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #include "RCTDefines.h"
  8. #include "RCTMacros.h"
  9. #if RCT_PROFILE && defined(__arm__)
  10. .thumb
  11. .thumb_func
  12. .globl SYMBOL_NAME(RCTProfileTrampoline)
  13. SYMBOL_NAME(RCTProfileTrampoline):
  14. /**
  15. * The explanation here is shorter, refer to the x86_64 implementation to a
  16. * richer explanation
  17. */
  18. /**
  19. * Save the parameter registers (r0-r3), r7 (frame pointer) and lr (link
  20. * register (contains the address of the caller of RCTProfileTrampoline)
  21. */
  22. push {r0-r3, r7, lr}
  23. /**
  24. * Allocate memory to store values across function calls: 12-bytes are
  25. * allocated to store 3 values: the previous value of the callee saved
  26. * register used to save the pointer to the allocated memory, the caller of
  27. * RCTProfileTrampoline and the address of the actual function we want to
  28. * profile
  29. */
  30. mov r0, #0xc
  31. bl SYMBOL_NAME(RCTProfileMalloc)
  32. /**
  33. * r4 is the callee saved register we'll use to refer to the allocated memory,
  34. * store its initial value, so we can restore it later
  35. */
  36. str r4, [r0]
  37. mov r4, r0
  38. /**
  39. * void RCTProfileGetImplementation(id object, SEL selector) in RCTProfile.m
  40. *
  41. * Load the first 2 argumenters (self and _cmd) used to call
  42. * RCTProfileTrampoline from the stack and put them on the appropriate registers.
  43. */
  44. ldr r0, [sp]
  45. ldr r1, [sp, #0x4]
  46. bl SYMBOL_NAME(RCTProfileGetImplementation)
  47. // store the actual function address in the allocated memory
  48. str r0, [r4, #0x4]
  49. /**
  50. * void RCTProfileGetImplementation(id object, SEL selector) in RCTProfile.m
  51. *
  52. * Load the first 2 arguments again to start the profiler
  53. */
  54. ldr r0, [sp]
  55. ldr r1, [sp, #0x4]
  56. bl SYMBOL_NAME(RCTProfileTrampolineStart)
  57. /**
  58. * Restore the state to call the actual function we want to profile: pop
  59. * all the registers
  60. */
  61. pop {r0-r3, r7, lr}
  62. // store lr (the caller) since it'll be overridden by `blx` (call)
  63. str lr, [r4, #0x8]
  64. ldr r12, [r4, #0x4] // load the function address
  65. blx r12 // call it
  66. push {r0} // save return value
  67. // void RCTProfileTrampolineEnd(void) in RCTProfile.m - just ends this profile
  68. bl SYMBOL_NAME(RCTProfileTrampolineEnd)
  69. /**
  70. * Save the value we still need from the allocated memory (caller address),
  71. * restore r4 and free the allocated memory (put its address in r0)
  72. */
  73. mov r0, r4
  74. ldr r1, [r4, #0x8]
  75. ldr r4, [r4]
  76. push {r1} // save the caller on the stack
  77. bl SYMBOL_NAME(RCTProfileFree)
  78. pop {lr} // pop the caller
  79. pop {r0} // pop the return value
  80. bx lr // jump to the calleer
  81. trap
  82. #endif