react-native/React/Profiler/RCTProfileTrampoline-i386.S

100 lines
3.1 KiB
ArmAsm

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#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(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 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(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