98 lines
3.0 KiB
ArmAsm
98 lines
3.0 KiB
ArmAsm
/**
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
*
|
|
* 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(__i386__)
|
|
|
|
.globl SYMBOL_NAME(RCTProfileTrampoline)
|
|
SYMBOL_NAME(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 SYMBOL_NAME(RCTProfileMalloc)
|
|
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 SYMBOL_NAME(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 SYMBOL_NAME(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 SYMBOL_NAME(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 SYMBOL_NAME(RCTProfileFree)
|
|
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
|