// UINT64 r8;
// UINT64 r9;
// UINT32 flags;
+// UINT64 buffer[PROFILE_PLATFORM_SPECIFIC_DATA_BUFFER_SIZE];
// } PROFILE_PLATFORM_SPECIFIC_DATA, *PPROFILE_PLATFORM_SPECIFIC_DATA;
-//
-.equ SIZEOF_PROFILE_PLATFORM_SPECIFIC_DATA, 0x8*22 + 0x8 // includes fudge to make FP_SPILL right
+
+// Buffer to copy structs sequentially
+.equ SIZEOF_PROFILE_STRUCT_BUFFER, 0x8*16
+.equ SIZEOF_PROFILE_PLATFORM_SPECIFIC_DATA, 0x8*22 + 0x8 + SIZEOF_PROFILE_STRUCT_BUFFER // includes fudge to make FP_SPILL right
.equ SIZEOF_FP_ARG_SPILL, 0x10*2
.equ SIZEOF_STACK_FRAME, SIZEOF_PROFILE_PLATFORM_SPECIFIC_DATA + SIZEOF_FP_ARG_SPILL
movsd real8 ptr [rsp + 0x60], xmm5 // -- struct flt5 field
movsd real8 ptr [rsp + 0x68], xmm6 // -- struct flt6 field
movsd real8 ptr [rsp + 0x70], xmm7 // -- struct flt7 field
- mov [rsp + 0x78], rdi // -- struct rdi field
- mov [rsp + 0x80], rsi // -- struct rsi field
- mov [rsp + 0x88], rdx // -- struct rdx field
- mov [rsp + 0x90], rcx // -- struct rcx field
- mov [rsp + 0x98], r8 // -- struct r8 field
- mov [rsp + 0xa0], r9 // -- struct r9 field
+ mov [rsp + 0x78], rdi // -- struct rdi field
+ mov [rsp + 0x80], rsi // -- struct rsi field
+ mov [rsp + 0x88], rdx // -- struct rdx field
+ mov [rsp + 0x90], rcx // -- struct rcx field
+ mov [rsp + 0x98], r8 // -- struct r8 field
+ mov [rsp + 0xa0], r9 // -- struct r9 field
mov r10, 0x1 // PROFILE_ENTER
- mov [rsp + 0xa8], r10d // -- struct flags field
+ mov [rsp + 0xa8], r10d // -- struct flags field
// get aligned stack ptr (rsp + FRAME_SIZE) & (-16)
lea rax, [rsp + 0xb8]
#ifdef PROFILING_SUPPORTED
#include "proftoeeinterfaceimpl.h"
+#include "argdestination.h"
MethodDesc *FunctionIdToMethodDesc(FunctionID functionID);
#define PROFILE_LEAVE 0x2
#define PROFILE_TAILCALL 0x4
+#define PROFILE_PLATFORM_SPECIFIC_DATA_BUFFER_SIZE 16
+
typedef struct _PROFILE_PLATFORM_SPECIFIC_DATA
{
FunctionID functionId;
UINT64 r9;
#endif
UINT32 flags;
+#if defined(UNIX_AMD64_ABI)
+ // A buffer to copy structs in to so they are sequential for GetFunctionEnter3Info.
+ UINT64 buffer[PROFILE_PLATFORM_SPECIFIC_DATA_BUFFER_SIZE];
+#endif
} PROFILE_PLATFORM_SPECIFIC_DATA, *PPROFILE_PLATFORM_SPECIFIC_DATA;
m_handle = platformSpecificHandle;
PROFILE_PLATFORM_SPECIFIC_DATA* pData = (PROFILE_PLATFORM_SPECIFIC_DATA*)m_handle;
+#ifdef UNIX_AMD64_ABI
+ m_bufferPos = 0;
+#endif // UNIX_AMD64_ABI
// unwind a frame and get the Rsp for the profiled method to make sure it matches
// what the JIT gave us
m_handle = NULL;
}
+#ifdef UNIX_AMD64_ABI
+LPVOID ProfileArgIterator::CopyStructFromRegisters()
+{
+ STATIC_CONTRACT_NOTHROW;
+ STATIC_CONTRACT_GC_NOTRIGGER;
+ STATIC_CONTRACT_FORBID_FAULT;
+ STATIC_CONTRACT_MODE_COOPERATIVE;
+
+
+ PROFILE_PLATFORM_SPECIFIC_DATA* pData = (PROFILE_PLATFORM_SPECIFIC_DATA*)m_handle;
+ ArgLocDesc *argLocDesc = m_argIterator.GetArgLocDescForStructInRegs();
+
+ LPVOID dest = (LPVOID)&pData->buffer[m_bufferPos];
+ BYTE* genRegSrc = (BYTE*)&pData->rdi + argLocDesc->m_idxGenReg * 8;
+ BYTE* floatRegSrc = (BYTE*)&pData->flt0 + argLocDesc->m_idxFloatReg * 8;
+
+ TypeHandle th;
+ m_argIterator.GetArgType(&th);
+ int fieldBytes = th.AsMethodTable()->GetNumInstanceFieldBytes();
+ INDEBUG(int remainingBytes = fieldBytes;)
+
+ EEClass* eeClass = argLocDesc->m_eeClass;
+ _ASSERTE(eeClass != NULL);
+
+ for (int i = 0; i < eeClass->GetNumberEightBytes(); i++)
+ {
+ int eightByteSize = eeClass->GetEightByteSize(i);
+ SystemVClassificationType eightByteClassification = eeClass->GetEightByteClassification(i);
+
+ _ASSERTE(remainingBytes >= eightByteSize);
+
+ if (eightByteClassification == SystemVClassificationTypeSSE)
+ {
+ if (eightByteSize == 8)
+ {
+ *(UINT64*)dest = *(UINT64*)floatRegSrc ;
+ }
+ else
+ {
+ _ASSERTE(eightByteSize == 4);
+ *(UINT32*)dest = *(UINT32*)floatRegSrc;
+ }
+ floatRegSrc += 8;
+ }
+ else
+ {
+ if (eightByteSize == 8)
+ {
+ _ASSERTE((eightByteClassification == SystemVClassificationTypeInteger) ||
+ (eightByteClassification == SystemVClassificationTypeIntegerReference) ||
+ (eightByteClassification == SystemVClassificationTypeIntegerByRef));
+
+ _ASSERTE(IS_ALIGNED((SIZE_T)genRegSrc, 8));
+ *(UINT64*)dest = *(UINT64*)genRegSrc;
+ }
+ else
+ {
+ _ASSERTE(eightByteClassification == SystemVClassificationTypeInteger);
+ memcpyNoGCRefs(dest, genRegSrc, eightByteSize);
+ }
+
+ genRegSrc += eightByteSize;
+ }
+
+ dest = (BYTE*)dest + eightByteSize;
+ INDEBUG(remainingBytes -= eightByteSize;)
+ }
+
+ _ASSERTE(remainingBytes == 0);
+ LPVOID destOrig = (LPVOID)&pData->buffer[m_bufferPos];
+ //Increase bufferPos by ceiling(fieldBytes/8)
+ m_bufferPos += (fieldBytes + 7) / 8;
+ _ASSERTE(m_bufferPos <= PROFILE_PLATFORM_SPECIFIC_DATA_BUFFER_SIZE);
+
+ return destOrig;
+}
+#endif // UNIX_AMD64_ABI
+
/*
* ProfileArgIterator::GetNextArgAddr
*
}
// if we're here we have an enregistered argument
+ CorElementType argType = m_argIterator.GetArgType();
+#if defined(UNIX_AMD64_ABI)
+ if (argOffset == TransitionBlock::StructInRegsOffset)
+ {
+ LPVOID argPtr = CopyStructFromRegisters();
+ return argPtr;
+ }
+ else
+ {
+ ArgLocDesc argLocDesc;
+ m_argIterator.GetArgLoc(argOffset, &argLocDesc);
+
+ if (argLocDesc.m_cFloatReg > 0)
+ {
+ return (LPBYTE)&pData->flt0 + (argLocDesc.m_idxFloatReg * 8);
+ }
+ else
+ {
+ // Stack arguments and float registers are already dealt with,
+ // so it better be a general purpose register
+ _ASSERTE(argLocDesc.m_cGenReg > 0);
+ return (LPBYTE)&pData->rdi + (argLocDesc.m_idxGenReg * 8);
+ }
+ }
+#else // UNIX_AMD64_ABI
unsigned int regStructOfs = (argOffset - TransitionBlock::GetOffsetOfArgumentRegisters());
_ASSERTE(regStructOfs < ARGUMENTREGISTERS_SIZE);
- CorElementType t = m_argIterator.GetArgType();
_ASSERTE(IS_ALIGNED(regStructOfs, sizeof(SLOT)));
- if (t == ELEMENT_TYPE_R4 || t == ELEMENT_TYPE_R8)
+ if (argType == ELEMENT_TYPE_R4 || argType == ELEMENT_TYPE_R8)
{
return (LPBYTE)&pData->flt0 + regStructOfs;
}
return pArg;
}
-
+#endif // UNIX_AMD64_ABI
+
return NULL;
}