提交 6dbc8f33 编写于 作者: F Fadi Hanna 提交者: GitHub

Enable R2R compilation/inlining of PInvoke stubs where no marshalling is...

Enable R2R compilation/inlining of PInvoke stubs where no marshalling is required (dotnet/coreclr#22560)

* These changes enable the inlining of some PInvokes that do not require any marshalling. With inlined pinvokes, R2R performance should become slightly better, since we'll avoid jitting some of the pinvoke IL stubs that we jit today for S.P.CoreLib. Performance gains not yet measured.

* Added JIT_PInvokeBegin/End helpers for all architectures. Linux stubs not yet implemented
* Add INLINE_GETTHREAD for arm/arm64
* Set CORJIT_FLAG_USE_PINVOKE_HELPERS jit flag for ReadyToRun compilations
* Updating R2RDump tool to handle pinvokes


Commit migrated from https://github.com/dotnet/coreclr/commit/bc9248cad132fa01dd2b641b6b22849bc7a05457
上级 a4fd4cc4
......@@ -698,13 +698,14 @@ enum CORCOMPILE_FIXUP_BLOB_KIND
ENCODE_DECLARINGTYPE_HANDLE,
ENCODE_INDIRECT_PINVOKE_TARGET, /* For calling a pinvoke method ptr */
ENCODE_MODULE_HANDLE = 0x50, /* Module token */
ENCODE_STATIC_FIELD_ADDRESS, /* For accessing a static field */
ENCODE_MODULE_ID_FOR_STATICS, /* For accessing static fields */
ENCODE_MODULE_ID_FOR_GENERIC_STATICS, /* For accessing static fields */
ENCODE_CLASS_ID_FOR_STATICS, /* For accessing static fields */
ENCODE_SYNC_LOCK, /* For synchronizing access to a type */
ENCODE_INDIRECT_PINVOKE_TARGET, /* For calling a pinvoke method ptr */
ENCODE_PROFILING_HANDLE, /* For the method's profiling counter */
ENCODE_VARARGS_METHODDEF, /* For calling a varargs method */
ENCODE_VARARGS_METHODREF,
......
......@@ -159,7 +159,7 @@
JITHELPER(CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, JIT_VerificationRuntimeCheck,CORINFO_HELP_SIG_REG_ONLY)
// GC support
DYNAMICJITHELPER(CORINFO_HELP_STOP_FOR_GC, JIT_RareDisableHelper,CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_STOP_FOR_GC, JIT_RareDisableHelper, CORINFO_HELP_SIG_REG_ONLY)
#ifdef ENABLE_FAST_GCPOLL_HELPER
DYNAMICJITHELPER(CORINFO_HELP_POLL_GC, JIT_PollGC, CORINFO_HELP_SIG_REG_ONLY)
#else
......@@ -354,8 +354,8 @@
JITHELPER(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, JIT_ThrowPlatformNotSupportedException, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, JIT_ThrowTypeNotSupportedException, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_JIT_PINVOKE_BEGIN, NULL, CORINFO_HELP_SIG_UNDEF)
JITHELPER(CORINFO_HELP_JIT_PINVOKE_END, NULL, CORINFO_HELP_SIG_UNDEF)
JITHELPER(CORINFO_HELP_JIT_PINVOKE_BEGIN, JIT_PInvokeBegin, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_JIT_PINVOKE_END, JIT_PInvokeEnd, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, NULL, CORINFO_HELP_SIG_UNDEF)
JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, NULL, CORINFO_HELP_SIG_UNDEF)
......
......@@ -15,7 +15,7 @@
#define READYTORUN_SIGNATURE 0x00525452 // 'RTR'
#define READYTORUN_MAJOR_VERSION 0x0002
#define READYTORUN_MAJOR_VERSION 0x0003
#define READYTORUN_MINOR_VERSION 0x0002
// R2R Version 2.1 adds the READYTORUN_SECTION_INLINING_INFO section
// R2R Version 2.2 adds the READYTORUN_SECTION_PROFILEDATA_INFO section
......@@ -180,6 +180,8 @@ enum ReadyToRunFixupKind
READYTORUN_FIXUP_DelegateCtor = 0x2C, /* optimized delegate ctor */
READYTORUN_FIXUP_DeclaringTypeHandle = 0x2D,
READYTORUN_FIXUP_IndirectPInvokeTarget = 0x2E, /* Target of an inlined pinvoke */
};
//
......@@ -230,6 +232,10 @@ enum ReadyToRunHelper
READYTORUN_HELPER_MemSet = 0x40,
READYTORUN_HELPER_MemCpy = 0x41,
// PInvoke helpers
READYTORUN_HELPER_PInvokeBegin = 0x42,
READYTORUN_HELPER_PInvokeEnd = 0x43,
// Get string handle lazily
READYTORUN_HELPER_GetString = 0x50,
......
......@@ -111,5 +111,9 @@ HELPER(READYTORUN_HELPER_CheckedWriteBarrier_EBP, CORINFO_HELP_CHECKED_ASSIGN_
HELPER(READYTORUN_HELPER_EndCatch, CORINFO_HELP_ENDCATCH, OPTIMIZEFORSIZE)
#endif
HELPER(READYTORUN_HELPER_PInvokeBegin, CORINFO_HELP_JIT_PINVOKE_BEGIN, )
HELPER(READYTORUN_HELPER_PInvokeEnd, CORINFO_HELP_JIT_PINVOKE_END, )
#undef HELPER
#undef OPTIMIZEFORSPEED
......@@ -120,6 +120,8 @@ public enum ReadyToRunFixupKind
READYTORUN_FIXUP_DelegateCtor = 0x2C, /* optimized delegate ctor */
READYTORUN_FIXUP_DeclaringTypeHandle = 0x2D,
READYTORUN_FIXUP_IndirectPInvokeTarget = 0x2E, /* Target of an inlined pinvoke */
}
//
......@@ -171,6 +173,10 @@ public enum ReadyToRunHelper
READYTORUN_HELPER_MemSet = 0x40,
READYTORUN_HELPER_MemCpy = 0x41,
// PInvoke helpers
READYTORUN_HELPER_PInvokeBegin = 0x42,
READYTORUN_HELPER_PInvokeEnd = 0x43,
// Get string handle lazily
READYTORUN_HELPER_GetString = 0x50,
......
......@@ -679,6 +679,10 @@ private void ParseSignature(StringBuilder builder)
builder.Append(" (DECLARING_TYPE_HANDLE)");
break;
case ReadyToRunFixupKind.READYTORUN_FIXUP_IndirectPInvokeTarget:
ParseMethod(builder);
builder.Append(" (INDIRECT_PINVOKE_TARGET)");
break;
default:
builder.Append(string.Format("Unknown fixup type: {0:X2}", fixupType));
......@@ -1126,6 +1130,15 @@ private void ParseHelper(StringBuilder builder)
builder.Append("MEM_CPY");
break;
// PInvoke helpers
case ReadyToRunHelper.READYTORUN_HELPER_PInvokeBegin:
builder.Append("PINVOKE_BEGIN");
break;
case ReadyToRunHelper.READYTORUN_HELPER_PInvokeEnd:
builder.Append("PINVOKE_END");
break;
// Get string handle lazily
case ReadyToRunHelper.READYTORUN_HELPER_GetString:
builder.Append("GET_STRING");
......
......@@ -679,6 +679,7 @@ elseif(CLR_CMAKE_TARGET_ARCH_I386)
${ARCH_SOURCES_DIR}/asmhelpers.asm
${ARCH_SOURCES_DIR}/gmsasm.asm
${ARCH_SOURCES_DIR}/jithelp.asm
${ARCH_SOURCES_DIR}/PInvokeStubs.asm
)
set(VM_HEADERS_WKS_ARCH_ASM
......@@ -735,6 +736,7 @@ else(WIN32)
${ARCH_SOURCES_DIR}/asmhelpers.S
${ARCH_SOURCES_DIR}/jithelp.S
${ARCH_SOURCES_DIR}/gmsasm.S
${ARCH_SOURCES_DIR}/pinvokestubs.S
${ARCH_SOURCES_DIR}/umthunkstub.S
)
elseif(CLR_CMAKE_TARGET_ARCH_ARM)
......
......@@ -13,6 +13,14 @@ include AsmConstants.inc
extern GenericPInvokeCalliStubWorker:proc
extern VarargPInvokeStubWorker:proc
extern JIT_PInvokeEndRarePath:proc
extern s_gsCookie:QWORD
extern ??_7InlinedCallFrame@@6B@:QWORD
extern g_TrapReturningThreads:DWORD
; Min amount of stack space that a nested function should allocate.
MIN_SIZE equ 28h
;
; in:
......@@ -135,4 +143,78 @@ NESTED_ENTRY VarargPInvokeGenILStub, _TEXT
NESTED_END VarargPInvokeGenILStub, _TEXT
;
; in:
; InlinedCallFrame (rcx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
; before actual InlinedCallFrame data)
;
;
LEAF_ENTRY JIT_PInvokeBegin, _TEXT
mov rax, qword ptr [s_gsCookie]
mov qword ptr [rcx], rax
add rcx, SIZEOF_GSCookie
;; set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code)
lea rax,[??_7InlinedCallFrame@@6B@]
mov qword ptr [rcx], rax
mov qword ptr [rcx + OFFSETOF__InlinedCallFrame__m_Datum], 0
mov rax, rsp
add rax, 8
mov qword ptr [rcx + OFFSETOF__InlinedCallFrame__m_pCallSiteSP], rax
mov qword ptr [rcx + OFFSETOF__InlinedCallFrame__m_pCalleeSavedFP], rbp
mov rax, [rsp]
mov qword ptr [rcx + OFFSETOF__InlinedCallFrame__m_pCallerReturnAddress], rax
INLINE_GETTHREAD rax
;; pFrame->m_Next = pThread->m_pFrame;
mov rdx, qword ptr [rax + OFFSETOF__Thread__m_pFrame]
mov qword ptr [rcx + OFFSETOF__Frame__m_Next], rdx
;; pThread->m_pFrame = pFrame;
mov qword ptr [rax + OFFSETOF__Thread__m_pFrame], rcx
;; pThread->m_fPreemptiveGCDisabled = 0
mov dword ptr [rax + OFFSETOF__Thread__m_fPreemptiveGCDisabled], 0
ret
LEAF_END JIT_PInvokeBegin, _TEXT
;
; in:
; InlinedCallFrame (rcx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
; before actual InlinedCallFrame data)
;
;
LEAF_ENTRY JIT_PInvokeEnd, _TEXT
add rcx, SIZEOF_GSCookie
INLINE_GETTHREAD rdx
;; rcx = pFrame
;; rdx = pThread
;; pThread->m_fPreemptiveGCDisabled = 1
mov dword ptr [rdx + OFFSETOF__Thread__m_fPreemptiveGCDisabled], 1
;; Check return trap
cmp [g_TrapReturningThreads], 0
jnz RarePath
;; pThread->m_pFrame = pFrame->m_Next
mov rax, qword ptr [rcx + OFFSETOF__Frame__m_Next]
mov qword ptr [rdx + OFFSETOF__Thread__m_pFrame], rax
ret
RarePath:
jmp JIT_PInvokeEndRarePath
LEAF_END JIT_PInvokeEnd, _TEXT
end
......@@ -556,6 +556,24 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__StringObject__m_StringLength
ASMCONSTANTS_C_ASSERT(OFFSETOF__ArrayTypeDesc__m_Arg
== offsetof(ArrayTypeDesc, m_Arg));
// For JIT_PInvokeBegin and JIT_PInvokeEnd helpers
#define OFFSETOF__InlinedCallFrame__m_Datum 0x10
ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_Datum
== offsetof(InlinedCallFrame, m_Datum));
#define OFFSETOF__InlinedCallFrame__m_pCallSiteSP 0x20
ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pCallSiteSP
== offsetof(InlinedCallFrame, m_pCallSiteSP));
#define OFFSETOF__InlinedCallFrame__m_pCallerReturnAddress 0x28
ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pCallerReturnAddress
== offsetof(InlinedCallFrame, m_pCallerReturnAddress));
#define OFFSETOF__InlinedCallFrame__m_pCalleeSavedFP 0x30
ASMCONSTANTS_C_ASSERT(OFFSETOF__InlinedCallFrame__m_pCalleeSavedFP
== offsetof(InlinedCallFrame, m_pCalleeSavedFP));
#define CallDescrData__pSrc 0x00
#define CallDescrData__numStackSlots 0x08
#ifdef UNIX_AMD64_ABI
......
......@@ -127,3 +127,27 @@ NESTED_ENTRY VarargPInvokeGenILStub, _TEXT, NoHandler
jmp C_FUNC(VarargPInvokeStubHelper)
NESTED_END VarargPInvokeGenILStub, _TEXT
//
// IN:
// InlinedCallFrame (rcx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
// before actual InlinedCallFrame data)
//
//
LEAF_ENTRY JIT_PInvokeBegin, _TEXT
// Not yet supported
int 3
ret
LEAF_END JIT_PInvokeBegin, _TEXT
//
// IN:
// InlinedCallFrame (rcx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
// before actual InlinedCallFrame data)
//
//
LEAF_ENTRY JIT_PInvokeEnd, _TEXT
// Not yet supported
int 3
ret
LEAF_END JIT_PInvokeEnd, _TEXT
......@@ -16,7 +16,13 @@
IMPORT VarargPInvokeStubWorker
IMPORT GenericPInvokeCalliStubWorker
IMPORT JIT_PInvokeEndRarePath
IMPORT s_gsCookie
IMPORT g_TrapReturningThreads
SETALIAS InlinedCallFrame_vftable, ??_7InlinedCallFrame@@6B@
IMPORT $InlinedCallFrame_vftable
; ------------------------------------------------------------------
; Macro to generate PInvoke Stubs.
......@@ -105,8 +111,92 @@ __PInvokeGenStubFuncName SETS "$__PInvokeGenStubFuncName":CC:"_RetBuffArg"
MEND
TEXTAREA
; ------------------------------------------------------------------
; JIT_PInvokeBegin helper
;
; in:
; r0 = InlinedCallFrame*: pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
; before actual InlinedCallFrame data)
;
LEAF_ENTRY JIT_PInvokeBegin
ldr r1, =s_gsCookie
ldr r1, [r1]
str r1, [r0]
add r0, r0, SIZEOF__GSCookie
;; r0 = pFrame
;; set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code)
ldr r1, =$InlinedCallFrame_vftable
str r1, [r0]
mov r1, 0
str r1, [r0, #InlinedCallFrame__m_Datum]
str sp, [r0, #InlinedCallFrame__m_pCallSiteSP]
str r11, [r0, #InlinedCallFrame__m_pCalleeSavedFP]
str lr, [r0, #InlinedCallFrame__m_pCallerReturnAddress]
;; r1 = GetThread(), TRASHES r2
INLINE_GETTHREAD r1, r2
;; pFrame->m_Next = pThread->m_pFrame;
ldr r2, [r1, #Thread_m_pFrame]
str r2, [r0, #Frame__m_Next]
;; pThread->m_pFrame = pFrame;
str r0, [r1, #Thread_m_pFrame]
;; pThread->m_fPreemptiveGCDisabled = 0
mov r2, 0
str r2, [r1, #Thread_m_fPreemptiveGCDisabled]
bx lr
LEAF_END
; ------------------------------------------------------------------
; JIT_PInvokeEnd helper
;
; in:
; r0 = InlinedCallFrame*
;
LEAF_ENTRY JIT_PInvokeEnd
add r0, r0, SIZEOF__GSCookie
;; r1 = GetThread(), TRASHES r2
INLINE_GETTHREAD r1, r2
;; r0 = pFrame
;; r1 = pThread
;; pThread->m_fPreemptiveGCDisabled = 1
mov r2, 1
str r2, [r1, #Thread_m_fPreemptiveGCDisabled]
;; Check return trap
ldr r2, =g_TrapReturningThreads
ldr r2, [r2]
cbnz r2, RarePath
;; pThread->m_pFrame = pFrame->m_Next
ldr r2, [r0, #Frame__m_Next]
str r2, [r1, #Thread_m_pFrame]
bx lr
RarePath
b JIT_PInvokeEndRarePath
LEAF_END
INLINE_GETTHREAD_CONSTANT_POOL
; ------------------------------------------------------------------
; VarargPInvokeStub & VarargPInvokeGenILStub
; There is a separate stub when the method has a hidden return buffer arg.
;
......
......@@ -229,8 +229,25 @@ ASMCONSTANTS_C_ASSERT(CallDescrData__returnValue == offsetof(CallDescrD
#define SIZEOF__FaultingExceptionFrame (SIZEOF__Frame + 0x8 + SIZEOF__CONTEXT)
#define FaultingExceptionFrame__m_fFilterExecuted SIZEOF__Frame
ASMCONSTANTS_C_ASSERT(SIZEOF__FaultingExceptionFrame == sizeof(FaultingExceptionFrame));
ASMCONSTANTS_C_ASSERT(FaultingExceptionFrame__m_fFilterExecuted == offsetof(FaultingExceptionFrame, m_fFilterExecuted));
ASMCONSTANTS_C_ASSERT(SIZEOF__FaultingExceptionFrame == sizeof(FaultingExceptionFrame))
ASMCONSTANTS_C_ASSERT(FaultingExceptionFrame__m_fFilterExecuted == offsetof(FaultingExceptionFrame, m_fFilterExecuted))
// For JIT_PInvokeBegin and JIT_PInvokeEnd helpers
#define Frame__m_Next 0x04
ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next))
#define InlinedCallFrame__m_Datum 0x08
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum))
#define InlinedCallFrame__m_pCallSiteSP 0x0C
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP))
#define InlinedCallFrame__m_pCallerReturnAddress 0x10
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress))
#define InlinedCallFrame__m_pCalleeSavedFP 0x14
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP))
#undef ASMCONSTANTS_RUNTIME_ASSERT
#undef ASMCONSTANTS_C_ASSERT
......@@ -159,3 +159,39 @@ __PWTB_StackAlloc SETA __PWTB_TransitionBlock
EPILOG_RETURN
MEND
;-----------------------------------------------------------------------------
; Macro to get a pointer to the Thread* object for the currently executing thread
;
__tls_array equ 0x2C ;; offsetof(TEB, ThreadLocalStoragePointer)
GBLS __SECTIONREL_gCurrentThreadInfo
__SECTIONREL_gCurrentThreadInfo SETS "SECTIONREL_gCurrentThreadInfo"
MACRO
INLINE_GETTHREAD $destReg, $trashReg
EXTERN _tls_index
ldr $destReg, =_tls_index
ldr $destReg, [$destReg]
mrc p15, 0, $trashReg, c13, c0, 2
ldr $trashReg, [$trashReg, #__tls_array]
ldr $destReg, [$trashReg, $destReg, lsl #2]
ldr $trashReg, $__SECTIONREL_gCurrentThreadInfo
ldr $destReg,[$destReg, $trashReg] ; return gCurrentThreadInfo.m_pThread
MEND
;-----------------------------------------------------------------------------
; INLINE_GETTHREAD_CONSTANT_POOL macro has to be used after the last function in the .asm file that used
; INLINE_GETTHREAD. Optionally, it can be also used after any function that used INLINE_GETTHREAD
; to improve density, or to reduce distance betweeen the constant pool and its use.
;
MACRO
INLINE_GETTHREAD_CONSTANT_POOL
EXTERN gCurrentThreadInfo
$__SECTIONREL_gCurrentThreadInfo
DCDU gCurrentThreadInfo
RELOC 15 ;; SECREL
__SECTIONREL_gCurrentThreadInfo SETS "$__SECTIONREL_gCurrentThreadInfo":CC:"_"
MEND
......@@ -75,6 +75,30 @@
.endmacro
// ------------------------------------------------------------------
// IN:
// InlinedCallFrame (r0) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
// before actual InlinedCallFrame data)
//
//
LEAF_ENTRY JIT_PInvokeBegin, _TEXT
// Not yet supported
EMIT_BREAKPOINT
bx lr
LEAF_END JIT_PInvokeBegin, _TEXT
// ------------------------------------------------------------------
// IN:
// InlinedCallFrame (r0) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
// before actual InlinedCallFrame data)
//
//
LEAF_ENTRY JIT_PInvokeEnd, _TEXT
// Not yet supported
EMIT_BREAKPOINT
bx lr
LEAF_END JIT_PInvokeEnd, _TEXT
// ------------------------------------------------------------------
// VarargPInvokeStub & VarargPInvokeGenILStub
// There is a separate stub when the method has a hidden return buffer arg.
......
......@@ -16,6 +16,13 @@
IMPORT VarargPInvokeStubWorker
IMPORT GenericPInvokeCalliStubWorker
IMPORT JIT_PInvokeEndRarePath
IMPORT s_gsCookie
IMPORT g_TrapReturningThreads
SETALIAS InlinedCallFrame_vftable, ??_7InlinedCallFrame@@6B@
IMPORT $InlinedCallFrame_vftable
; ------------------------------------------------------------------
......@@ -107,8 +114,88 @@ __PInvokeStubWorkerName SETS "$FuncPrefix":CC:"StubWorker"
MEND
TEXTAREA
; ------------------------------------------------------------------
; JIT_PInvokeBegin helper
;
; in:
; x0 = InlinedCallFrame*
;
LEAF_ENTRY JIT_PInvokeBegin
ldr x9, =s_gsCookie
ldr x9, [x9]
str x9, [x0]
add x10, x0, SIZEOF__GSCookie
;; set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code)
ldr x9, =$InlinedCallFrame_vftable
str x9, [x10]
str xzr, [x10, #InlinedCallFrame__m_Datum]
mov x9, sp
str x9, [x10, #InlinedCallFrame__m_pCallSiteSP]
str fp, [x10, #InlinedCallFrame__m_pCalleeSavedFP]
str lr, [x10, #InlinedCallFrame__m_pCallerReturnAddress]
;; x0 = GetThread(), TRASHES x9
INLINE_GETTHREAD x0, x9
;; pFrame->m_Next = pThread->m_pFrame;
ldr x9, [x0, #Thread_m_pFrame]
str x9, [x10, #Frame__m_Next]
;; pThread->m_pFrame = pFrame;
str x10, [x0, #Thread_m_pFrame]
;; pThread->m_fPreemptiveGCDisabled = 0
str wzr, [x0, #Thread_m_fPreemptiveGCDisabled]
ret
LEAF_END
; ------------------------------------------------------------------
; JIT_PInvokeEnd helper
;
; in:
; x0 = InlinedCallFrame*
;
LEAF_ENTRY JIT_PInvokeEnd
add x0, x0, SIZEOF__GSCookie
;; x1 = GetThread(), TRASHES x2
INLINE_GETTHREAD x1, x2
;; x0 = pFrame
;; x1 = pThread
;; pThread->m_fPreemptiveGCDisabled = 1
mov x9, 1
str w9, [x1, #Thread_m_fPreemptiveGCDisabled]
;; Check return trap
ldr x9, =g_TrapReturningThreads
ldr x9, [x9]
cbnz x9, RarePath
;; pThread->m_pFrame = pFrame->m_Next
ldr x9, [x0, #Frame__m_Next]
str x9, [x1, #Thread_m_pFrame]
ret
RarePath
b JIT_PInvokeEndRarePath
LEAF_END
INLINE_GETTHREAD_CONSTANT_POOL
; ------------------------------------------------------------------
; VarargPInvokeStub & VarargPInvokeGenILStub
;
......
......@@ -210,5 +210,22 @@ ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pDataBlob == offsetof(DomainLocalModu
ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pGCStatics == offsetof(DomainLocalModule, m_pGCStatics));
// For JIT_PInvokeBegin and JIT_PInvokeEnd helpers
#define Frame__m_Next 0x08
ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next))
#define InlinedCallFrame__m_Datum 0x10
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum))
#define InlinedCallFrame__m_pCallSiteSP 0x20
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP))
#define InlinedCallFrame__m_pCallerReturnAddress 0x28
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress))
#define InlinedCallFrame__m_pCalleeSavedFP 0x30
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP))
#undef ASMCONSTANTS_RUNTIME_ASSERT
#undef ASMCONSTANTS_C_ASSERT
......@@ -299,3 +299,51 @@ $__RedirectionStubEndFuncName
MEND
;-----------------------------------------------------------------------------
; Macro to get a pointer to the Thread* object for the currently executing thread
;
__tls_array equ 0x58 ;; offsetof(TEB, ThreadLocalStoragePointer)
EXTERN _tls_index
GBLS __SECTIONREL_gCurrentThreadInfo
__SECTIONREL_gCurrentThreadInfo SETS "SECTIONREL_gCurrentThreadInfo"
MACRO
INLINE_GETTHREAD $destReg, $trashReg
;; The following macro variables are just some assembler magic to get the name of the 32-bit version
;; of $trashReg. It does it by string manipulation. Replaces something like x3 with w3.
LCLS TrashRegister32Bit
TrashRegister32Bit SETS "$trashReg"
TrashRegister32Bit SETS "w":CC:("$TrashRegister32Bit":RIGHT:((:LEN:TrashRegister32Bit) - 1))
ldr $trashReg, =_tls_index
ldr $TrashRegister32Bit, [$trashReg]
ldr $destReg, [xpr, #__tls_array]
ldr $destReg, [$destReg, $trashReg lsl #3]
ldr $trashReg, =$__SECTIONREL_gCurrentThreadInfo
ldr $trashReg, [$trashReg]
ldr $destReg, [$destReg, $trashReg] ; return gCurrentThreadInfo.m_pThread
MEND
;-----------------------------------------------------------------------------
; INLINE_GETTHREAD_CONSTANT_POOL macro has to be used after the last function in the .asm file that used
; INLINE_GETTHREAD. Optionally, it can be also used after any function that used INLINE_GETTHREAD
; to improve density, or to reduce distance betweeen the constant pool and its use.
;
MACRO
INLINE_GETTHREAD_CONSTANT_POOL
EXTERN gCurrentThreadInfo
;; Section relocs are 32 bits. Using an extra DCD initialized to zero for 8-byte alignment.
$__SECTIONREL_gCurrentThreadInfo
DCD gCurrentThreadInfo
RELOC 8, gCurrentThreadInfo ;; SECREL
DCD 0
__SECTIONREL_gCurrentThreadInfo SETS "$__SECTIONREL_gCurrentThreadInfo":CC:"_"
MEND
......@@ -86,6 +86,30 @@ LOCAL_LABEL(\__PInvokeStubFuncName\()_0):
NESTED_END \__PInvokeGenStubFuncName, _TEXT
.endm
// ------------------------------------------------------------------
// IN:
// InlinedCallFrame (x0) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
// before actual InlinedCallFrame data)
//
//
LEAF_ENTRY JIT_PInvokeBegin, _TEXT
// Not yet supported
EMIT_BREAKPOINT
ret lr
LEAF_END JIT_PInvokeBegin, _TEXT
// ------------------------------------------------------------------
// IN:
// InlinedCallFrame (x0) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
// before actual InlinedCallFrame data)
//
//
LEAF_ENTRY JIT_PInvokeEnd, _TEXT
// Not yet supported
EMIT_BREAKPOINT
ret lr
LEAF_END JIT_PInvokeEnd, _TEXT
// ------------------------------------------------------------------
// VarargPInvokeStub & VarargPInvokeGenILStub
//
......
......@@ -3472,6 +3472,14 @@ BOOL NDirect::MarshalingRequired(MethodDesc *pMD, PCCOR_SIGNATURE pSig /*= NULL*
return TRUE;
}
#ifdef FEATURE_READYTORUN_COMPILER
if (IsReadyToRunCompilation())
{
if (!hndArgType.AsMethodTable()->IsLayoutInCurrentVersionBubble())
return TRUE;
}
#endif
// return value is fine as long as it can be normalized to an integer
if (i == 0)
{
......
......@@ -3002,7 +3002,6 @@ public:
PTR_VOID m_StubSecretArg;
#endif // _WIN64
protected:
// X86: ESP after pushing the outgoing arguments, and just before calling
// out to unmanaged code.
// Other platforms: the field stays set throughout the declaring method.
......
......@@ -388,11 +388,7 @@ public:
//
// Similarly, inserting breakpoints can be avoided for JIT_PollGC() and JIT_StressGC().
#if defined(_TARGET_ARM_) || defined(_TARGET_AMD64_)
extern "C" FCDECL0(VOID, JIT_RareDisableHelper);
#else
FCDECL0(VOID, JIT_RareDisableHelper);
#endif
/****************************************************************************/
/* sprinkle interupt instructions that will stop on every GCSafe location
......
; Licensed to the .NET Foundation under one or more agreements.
; The .NET Foundation licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; Define macros to build unwind data for prologues.
;
__tls_array equ 2Ch ;; offsetof(TEB, ThreadLocalStoragePointer)
INLINE_GETTHREAD macro destReg, trashReg
ASSUME fs : NOTHING
EXTERN __tls_index:DWORD
EXTERN _gCurrentThreadInfo:DWORD
mov destReg, [__tls_index]
mov trashReg, fs:[__tls_array]
mov trashReg, [trashReg + destReg * 4]
add trashReg, SECTIONREL _gCurrentThreadInfo
mov destReg, [trashReg]
endm
; Licensed to the .NET Foundation under one or more agreements.
; The .NET Foundation licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
; ***********************************************************************
; File: PInvokeStubs.asm
;
; ***********************************************************************
;
; *** NOTE: If you make changes to this file, propagate the changes to
; PInvokeStubs.s in this directory
; This contains JITinterface routines that are 100% x86 assembly
.586
.model flat
include asmconstants.inc
include asmmacros.inc
option casemap:none
.code
extern _s_gsCookie:DWORD
extern ??_7InlinedCallFrame@@6B@:DWORD
extern _g_TrapReturningThreads:DWORD
extern @JIT_PInvokeEndRarePath@0:proc
.686P
.XMM
;
; in:
; InlinedCallFrame (ecx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
; before actual InlinedCallFrame data)
;
;
_JIT_PInvokeBegin@4 PROC public
mov eax, dword ptr [_s_gsCookie]
mov dword ptr [ecx], eax
add ecx, SIZEOF_GSCookie
;; set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code)
lea eax,[??_7InlinedCallFrame@@6B@]
mov dword ptr [ecx], eax
mov dword ptr [ecx + InlinedCallFrame__m_Datum], 0
mov eax, esp
add eax, 4
mov dword ptr [ecx + InlinedCallFrame__m_pCallSiteSP], eax
mov dword ptr [ecx + InlinedCallFrame__m_pCalleeSavedFP], ebp
mov eax, [esp]
mov dword ptr [ecx + InlinedCallFrame__m_pCallerReturnAddress], eax
;; edx = GetThread(). Trashes eax
INLINE_GETTHREAD edx, eax
;; pFrame->m_Next = pThread->m_pFrame;
mov eax, dword ptr [edx + Thread_m_pFrame]
mov dword ptr [ecx + Frame__m_Next], eax
;; pThread->m_pFrame = pFrame;
mov dword ptr [edx + Thread_m_pFrame], ecx
;; pThread->m_fPreemptiveGCDisabled = 0
mov dword ptr [edx + Thread_m_fPreemptiveGCDisabled], 0
ret
_JIT_PInvokeBegin@4 ENDP
;
; in:
; InlinedCallFrame (ecx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
; before actual InlinedCallFrame data)
;
;
_JIT_PInvokeEnd@4 PROC public
add ecx, SIZEOF_GSCookie
;; edx = GetThread(). Trashes eax
INLINE_GETTHREAD edx, eax
;; ecx = pFrame
;; edx = pThread
;; pThread->m_fPreemptiveGCDisabled = 1
mov dword ptr [edx + Thread_m_fPreemptiveGCDisabled], 1
;; Check return trap
cmp [_g_TrapReturningThreads], 0
jnz RarePath
;; pThread->m_pFrame = pFrame->m_Next
mov eax, dword ptr [ecx + Frame__m_Next]
mov dword ptr [edx + Thread_m_pFrame], eax
ret
RarePath:
jmp @JIT_PInvokeEndRarePath@0
_JIT_PInvokeEnd@4 ENDP
end
......@@ -339,6 +339,23 @@ ASMCONSTANTS_C_ASSERT(Thread__m_pDomain == offsetof(Thread, m_pDomain));
#endif
// For JIT_PInvokeBegin and JIT_PInvokeEnd helpers
#define Frame__m_Next 0x04
ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next));
#define InlinedCallFrame__m_Datum 0x08
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_Datum == offsetof(InlinedCallFrame, m_Datum));
#define InlinedCallFrame__m_pCallSiteSP 0x0C
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallSiteSP == offsetof(InlinedCallFrame, m_pCallSiteSP));
#define InlinedCallFrame__m_pCallerReturnAddress 0x10
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCallerReturnAddress == offsetof(InlinedCallFrame, m_pCallerReturnAddress));
#define InlinedCallFrame__m_pCalleeSavedFP 0x14
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP));
#ifdef FEATURE_STUBS_AS_IL
// DelegateObject from src/vm/object.h
#define DelegateObject___target 0x04 // offset 0 is m_pMethTab of base class Object
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
.intel_syntax noprefix
#include "unixasmmacros.inc"
#include "asmconstants.h"
//
// IN:
// InlinedCallFrame (ecx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
// before actual InlinedCallFrame data)
//
//
LEAF_ENTRY JIT_PInvokeBegin, _TEXT
// Not yet supported
int 3
ret
LEAF_END JIT_PInvokeBegin, _TEXT
//
// IN:
// InlinedCallFrame (ecx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
// before actual InlinedCallFrame data)
//
//
LEAF_ENTRY JIT_PInvokeEnd, _TEXT
// Not yet supported
int 3
ret
LEAF_END JIT_PInvokeEnd, _TEXT
......@@ -5591,15 +5591,50 @@ HCIMPL0(VOID, JIT_PollGC)
}
HCIMPLEND
/*************************************************************/
// This helper is similar to JIT_RareDisableHelper, but has more operations
// tailored to the post-pinvoke operations.
extern "C" FCDECL0(VOID, JIT_PInvokeEndRarePath);
HCIMPL0(void, JIT_PInvokeEndRarePath)
{
BEGIN_PRESERVE_LAST_ERROR;
FCALL_CONTRACT;
Thread *thread = GetThread();
// We need to disable the implicit FORBID GC region that exists inside an FCALL
// in order to call RareDisablePreemptiveGC().
FC_CAN_TRIGGER_GC();
thread->RareDisablePreemptiveGC();
FC_CAN_TRIGGER_GC_END();
FC_GC_POLL_NOT_NEEDED();
HELPER_METHOD_FRAME_BEGIN_NOPOLL(); // Set up a frame
thread->HandleThreadAbort();
HELPER_METHOD_FRAME_END();
InlinedCallFrame* frame = (InlinedCallFrame*)thread->m_pFrame;
thread->m_pFrame->Pop(thread);
END_PRESERVE_LAST_ERROR;
}
HCIMPLEND
/*************************************************************/
// For an inlined N/Direct call (and possibly for other places that need this service)
// we have noticed that the returning thread should trap for one reason or another.
// ECall sets up the frame.
extern "C" FCDECL0(VOID, JIT_RareDisableHelper);
#if defined(_TARGET_ARM_) || defined(_TARGET_AMD64_)
// The JIT expects this helper to preserve the return value on AMD64 and ARM. We should eventually
// switch other platforms to the same convention since it produces smaller code.
extern "C" FCDECL0(VOID, JIT_RareDisableHelper);
extern "C" FCDECL0(VOID, JIT_RareDisableHelperWorker);
HCIMPL0(void, JIT_RareDisableHelperWorker)
......@@ -5783,6 +5818,9 @@ Thread * __stdcall JIT_InitPInvokeFrame(InlinedCallFrame *pFrame, PTR_VOID StubS
#endif // _WIN64
EXTERN_C void JIT_PInvokeBegin(InlinedCallFrame* pFrame);
EXTERN_C void JIT_PInvokeEnd(InlinedCallFrame* pFrame);
//========================================================================
//
// JIT HELPERS IMPLEMENTED AS FCALLS
......
......@@ -10181,11 +10181,27 @@ void CEEInfo::getEEInfo(CORINFO_EE_INFO *pEEInfoOut)
}
else
{
// inlinedCallFrameInfo is not used for R2R compilation
// We'll declare a fixed size to use for the inlined call frame for R2R here. The size we declare
// is currently slightly larger that the actual size of the struct, just in case we decide to add
// more fields to the struct in the future, in an effort to not completely invalidate existing R2R images.
// The assert below ensures that this fixed size is at least large enough to hold the data structures
// used at runtime.
// ** IMPORTANT ** If you ever need to change the value of this fixed size, make sure to change the R2R
// version number, otherwise older R2R images will probably crash when used.
const int r2rInlinedCallFrameSize = TARGET_POINTER_SIZE * 11;
#if defined(_DEBUG) && !defined(CROSSBITNESS_COMPILE)
InlinedCallFrame::GetEEInfo(&pEEInfoOut->inlinedCallFrameInfo);
_ASSERTE(pEEInfoOut->inlinedCallFrameInfo.size <= r2rInlinedCallFrameSize);
#endif
// inlinedCallFrameInfo is mostly not used for R2R compilation (only the size field is used)
ZeroMemory(&pEEInfoOut->inlinedCallFrameInfo, sizeof(pEEInfoOut->inlinedCallFrameInfo));
pEEInfoOut->offsetOfThreadFrame = (DWORD)-1;
pEEInfoOut->offsetOfGCState = (DWORD)-1;
pEEInfoOut->offsetOfThreadFrame = (DWORD)-1;
pEEInfoOut->offsetOfGCState = (DWORD)-1;
pEEInfoOut->inlinedCallFrameInfo.size = r2rInlinedCallFrameSize;
}
#ifndef CROSSBITNESS_COMPILE
......
......@@ -5127,6 +5127,13 @@ FARPROC NDirectMethodDesc::FindEntryPointWithMangling(HINSTANCE hMod, PTR_CUTF8
if (IsStdCall())
{
if (GetModule()->IsReadyToRun())
{
// Computing if marshalling is required also computes the required stack size. We need the stack size to correctly form the
// name of the import pinvoke function on x86
((NDirectMethodDesc*)this)->MarshalingRequired();
}
DWORD probedEntrypointNameLength = (DWORD)(strlen(entryPointName) + 1); // 1 for null terminator
int dstbufsize = (int)(sizeof(char) * (probedEntrypointNameLength + 10)); // 10 for stdcall mangling
LPSTR szProbedEntrypointName = ((LPSTR)_alloca(dstbufsize + 1));
......
......@@ -10159,6 +10159,54 @@ static BOOL ComputeIsLayoutFixedInCurrentVersionBubble(MethodTable * pMT)
return TRUE;
}
static BOOL ComputeIsLayoutInCurrentVersionBubble(MethodTable* pMT)
{
if (pMT->IsTruePrimitive() || pMT->IsEnum())
return TRUE;
if (!pMT->GetModule()->IsInCurrentVersionBubble())
return FALSE;
ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS);
for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next())
{
MethodTable * pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable();
if (!pFieldMT->IsLayoutInCurrentVersionBubble())
return FALSE;
}
if (!pMT->IsValueType())
{
pMT = pMT->GetParentMethodTable();
while ((pMT != g_pObjectClass) && (pMT != NULL))
{
if (!pMT->IsLayoutInCurrentVersionBubble())
return FALSE;
pMT = pMT->GetParentMethodTable();
}
}
return TRUE;
}
BOOL MethodTable::IsLayoutInCurrentVersionBubble()
{
STANDARD_VM_CONTRACT;
const MethodTableWriteableData * pWriteableData = GetWriteableData();
if (!(pWriteableData->m_dwFlags & MethodTableWriteableData::enum_flag_NGEN_IsLayoutInCurrentVersionBubbleComputed))
{
MethodTableWriteableData * pWriteableDataForWrite = GetWriteableDataForWrite();
if (ComputeIsLayoutInCurrentVersionBubble(this))
*EnsureWritablePages(&pWriteableDataForWrite->m_dwFlags) |= MethodTableWriteableData::enum_flag_NGEN_IsLayoutInCurrentVersionBubble;
*EnsureWritablePages(&pWriteableDataForWrite->m_dwFlags) |= MethodTableWriteableData::enum_flag_NGEN_IsLayoutInCurrentVersionBubbleComputed;
}
return (pWriteableData->m_dwFlags & MethodTableWriteableData::enum_flag_NGEN_IsLayoutInCurrentVersionBubble) != 0;
}
//
// Is field layout in this type fixed within the current version bubble?
// This check does not take the inheritance chain into account.
......
......@@ -326,8 +326,10 @@ struct MethodTableWriteableData
enum_flag_NGEN_OverridingInterface = 0x00080000, // Overriding interface that we should generate WinRT CCW stubs for.
#ifdef FEATURE_READYTORUN_COMPILER
enum_flag_NGEN_IsLayoutFixedComputed = 0x0010000, // Set if we have cached the result of IsLayoutFixed computation
enum_flag_NGEN_IsLayoutFixed = 0x0020000, // The result of the IsLayoutFixed computation
enum_flag_NGEN_IsLayoutFixedComputed = 0x0010000, // Set if we have cached the result of IsLayoutFixed computation
enum_flag_NGEN_IsLayoutFixed = 0x0020000, // The result of the IsLayoutFixed computation
enum_flag_NGEN_IsLayoutInCurrentVersionBubbleComputed = 0x0040000, // Set if we have cached the result of IsLayoutInCurrentVersionBubble computation
enum_flag_NGEN_IsLayoutInCurrentVersionBubble = 0x0080000, // The result of the IsLayoutInCurrentVersionBubble computation
#endif
#endif // FEATURE_PREJIT
......@@ -4143,6 +4145,10 @@ public:
BOOL Validate ();
#ifdef FEATURE_READYTORUN_COMPILER
//
// Is field layout in this type within the current version bubble?
//
BOOL IsLayoutInCurrentVersionBubble();
//
// Is field layout in this type fixed within the current version bubble?
// This check does not take the inheritance chain into account.
......
......@@ -1132,14 +1132,21 @@ BOOL ZapSig::EncodeMethod(
// FUTURE: This condition should likely be changed or reevaluated once support for smaller version bubbles is implemented.
if (IsReadyToRunCompilation() && (!IsLargeVersionBubbleEnabled() || !pMethod->GetModule()->IsInCurrentVersionBubble()))
{
if (pResolvedToken == NULL)
if (pMethod->IsNDirect())
{
_ASSERTE(!"CORINFO_RESOLVED_TOKEN required to encode method!");
ThrowHR(E_FAIL);
ownerType = pMethod->GetMethodTable_NoLogging();
}
else
{
if (pResolvedToken == NULL)
{
_ASSERTE(!"CORINFO_RESOLVED_TOKEN required to encode method!");
ThrowHR(E_FAIL);
}
// Encode the referencing method type
ownerType = TypeHandle(pResolvedToken->hClass);
// Encode the referencing method type
ownerType = TypeHandle(pResolvedToken->hClass);
}
}
else
#endif
......@@ -1198,7 +1205,9 @@ BOOL ZapSig::EncodeMethod(
methodFlags |= ENCODE_METHOD_SIG_Constrained;
}
Module * pReferencingModule = (Module *)pResolvedToken->tokenScope;
Module * pReferencingModule = pMethod->IsNDirect() ?
pMethod->GetModule() :
(Module *)pResolvedToken->tokenScope;
if (!pReferencingModule->IsInCurrentVersionBubble())
{
......@@ -1208,7 +1217,9 @@ BOOL ZapSig::EncodeMethod(
ThrowHR(E_FAIL);
}
methodToken = pResolvedToken->token;
methodToken = pMethod->IsNDirect() ?
pMethod->GetMemberDef_NoLogging() :
pResolvedToken->token;
if (TypeFromToken(methodToken) == mdtMethodSpec)
{
......@@ -1218,7 +1229,7 @@ BOOL ZapSig::EncodeMethod(
switch (TypeFromToken(methodToken))
{
case mdtMethodDef:
_ASSERTE(pResolvedToken->pTypeSpec == NULL);
_ASSERTE(pMethod->IsNDirect() || pResolvedToken->pTypeSpec == NULL);
if (!ownerType.HasInstantiation() || ownerType.IsTypicalTypeDefinition())
{
methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
......@@ -1226,6 +1237,7 @@ BOOL ZapSig::EncodeMethod(
break;
case mdtMemberRef:
_ASSERTE(pResolvedToken != NULL);
methodFlags |= ENCODE_METHOD_SIG_MemberRefToken;
if (pResolvedToken->pTypeSpec == NULL)
......
......@@ -205,8 +205,14 @@ CORJIT_FLAGS ZapInfo::ComputeJitFlags(CORINFO_METHOD_HANDLE handle)
#ifdef FEATURE_READYTORUN_COMPILER
if (IsReadyToRunCompilation())
{
jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_READYTORUN);
#ifndef PLATFORM_UNIX
// PInvoke Helpers are not yet implemented on non-Windows platforms
jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_PINVOKE_HELPERS);
#endif
}
#endif // FEATURE_READYTORUN_COMPILER
return jitFlags;
}
......@@ -1988,12 +1994,15 @@ void * ZapInfo::getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method,void **ppI
m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(method);
CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(method);
if (moduleHandle == m_pImage->m_hModule
&& m_pImage->m_pPreloader->CanEmbedMethodHandle(method, m_currentMethodHandle))
if (!IsReadyToRunCompilation())
{
*ppIndirection = NULL;
return PVOID(m_pImage->GetWrappers()->GetAddrOfPInvokeFixup(method));
CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(method);
if (moduleHandle == m_pImage->m_hModule
&& m_pImage->m_pPreloader->CanEmbedMethodHandle(method, m_currentMethodHandle))
{
*ppIndirection = NULL;
return PVOID(m_pImage->GetWrappers()->GetAddrOfPInvokeFixup(method));
}
}
//
......@@ -3849,9 +3858,11 @@ CorInfoUnmanagedCallConv ZapInfo::getUnmanagedCallConv(CORINFO_METHOD_HANDLE met
BOOL ZapInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig)
{
// READYTORUN: FUTURE: P/Invoke
#ifdef PLATFORM_UNIX
// TODO: Support for pinvoke helpers on non-Windows platforms
if (IsReadyToRunCompilation())
return TRUE;
return TRUE;
#endif
return m_pEEJitInfo->pInvokeMarshalingRequired(method, sig);
}
......
......@@ -549,6 +549,8 @@ static_assert_no_msg((int)READYTORUN_FIXUP_DelegateCtor == (int)ENC
static_assert_no_msg((int)READYTORUN_FIXUP_DeclaringTypeHandle == (int)ENCODE_DECLARINGTYPE_HANDLE);
static_assert_no_msg((int)READYTORUN_FIXUP_IndirectPInvokeTarget == (int)ENCODE_INDIRECT_PINVOKE_TARGET);
//
// READYTORUN_EXCEPTION
//
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册