diff options
author | Swaroop Sridhar <swaroops@microsoft.com> | 2016-07-20 16:50:22 -0700 |
---|---|---|
committer | Swaroop Sridhar <swaroops@microsoft.com> | 2016-08-05 14:05:55 -0700 |
commit | d302e64bcb4ea445f6702c529f8a964df20ab494 (patch) | |
tree | 6fda2c392acf1d44aa4222ed6d9813533c455a0a /src/vm/amd64 | |
parent | 5b0953d50e9d0c6e388643210476d6a95a55a247 (diff) | |
download | coreclr-d302e64bcb4ea445f6702c529f8a964df20ab494.tar.gz coreclr-d302e64bcb4ea445f6702c529f8a964df20ab494.tar.bz2 coreclr-d302e64bcb4ea445f6702c529f8a964df20ab494.zip |
Implement GcInfo v2
Ref #4379
This change implements GcInfo version 2 for all platforms that use the
GcInfo library (all architectures other than X86).
Changes are:
1) Defines ReturnKind enumeration for all platforms
2) Change the GcInfo encoder library to encode the ReturnKind and ReversePInvokeFrame slot
3) Change the CM's GcInfo decoder to encode the ReturnKind and ReversePInvokeFrame slot for GCINFO_VERSION 2
4) Some corrections to GCINFO_MEASUREments
5) Changes to RYU Jit to provide the correct information to the encoder
6) Changes to the VM to use the ReturnKind information while hijacking a thread
- If ReturnKind is available from GcInfo, new hijack routines are used
- Otherwise, fall back to old method (for compatibility)
7) Rework and simplify the thread hijack routines by scanning HijackFrames directly for gcroots
8) Supporting code to implement the above features.
Returning Structs in multiple registers
Hijacking for StructInRegs is currently only implemented for
Unix SystemV ABI Multi-reg struct returns. However, the hijack-workers that use
ReturnKind are ready to handle other platforms (ex: ARM/ARM64 Windows)
once the corresponding HijackTripThread() assembly routines are defined.
The New feature flag: FEATURE_MULTIREG_RETURN is set for platforms where a struct value
can be returned in multiple registers [ex: Windows/Unix ARM/ARM64, Unix-AMD64]
FEATURE_UNIX_AMD64_STRUCT_PASSING is a specific kind of FEATURE_MULTIREG_RETURN
specified by SystemV ABI for AMD64
Compatibility with other JITs
- All new GCInfo generated by RYU Jit is in GcInfo version 2
- All Ngen images must be regenerated with the new GcInfo version.
- Ready-to-run images with old GcInfo will continue to work.
- Jit64/X64 uses the GcInfo library, so it generates GcInfo version 2.
However, it doesn't (yet) provide the data to encode the correct ReturnKind
Similar is the case for ARM32 code running on JIT32, and any other JITs
that may be using GcInfo library but not yet modified to use the new API.
So, compatibility is achived using RT_Unset flag.
When ReturnKind is RT_Unset, it means that the JIT did not set
the ReturnKind in the GCInfo, and therefore the VM cannot rely on it,
and must use other mechanisms (similar to GcInfo ver 1) to determine
the Return type's GC information.
Implement GC root scanning for Hijack-frames
This change implements GCScanRoots() method for Hijacke-frames
based on the ReturnKind information available from the GcInfo.
If the exact ReturnKind is not available in the GcInfo, the
thread-suspension logic will compute the ReturnKind based on
the method-signature.
As a result of this change, several hijack-helpers in the VM
are cleaned up. There's only one implementation of HijackWorker()
to handle all returnKinds.
This change also simplifies the thread-hijack logic by using a
single assembly helper OnHijackTripThread() in most cases.
The only other helper used is for X86 floating point return values
for save/restoring the top of the FP stack.
ARM64
Only GcIndfo v2 is reliably supported for ARM64 platform.
The changes to thread-hijack mechanism fixes #6494 for ARM64.
No measurable change in JIT throughput, performance or native-image
size from this change.
Diffstat (limited to 'src/vm/amd64')
-rw-r--r-- | src/vm/amd64/AsmHelpers.asm | 58 | ||||
-rw-r--r-- | src/vm/amd64/cgenamd64.cpp | 3 | ||||
-rw-r--r-- | src/vm/amd64/cgencpu.h | 6 | ||||
-rw-r--r-- | src/vm/amd64/unixasmhelpers.S | 110 |
4 files changed, 12 insertions, 165 deletions
diff --git a/src/vm/amd64/AsmHelpers.asm b/src/vm/amd64/AsmHelpers.asm index 1522670146..4563a060b3 100644 --- a/src/vm/amd64/AsmHelpers.asm +++ b/src/vm/amd64/AsmHelpers.asm @@ -23,9 +23,7 @@ extern ThePreStub:proc extern ProfileEnter:proc extern ProfileLeave:proc extern ProfileTailcall:proc -extern OnHijackObjectWorker:proc -extern OnHijackInteriorPointerWorker:proc -extern OnHijackScalarWorker:proc +extern OnHijackWorker:proc extern JIT_RareDisableHelperWorker:proc ifdef _DEBUG @@ -431,54 +429,8 @@ endif ; _DEBUG ; A JITted method's return address was hijacked to return to us here. -; -;VOID __stdcall OnHijackObjectTripThread(); -NESTED_ENTRY OnHijackObjectTripThread, _TEXT - - ; Don't fiddle with this unless you change HijackFrame::UpdateRegDisplay - ; and HijackObjectArgs - push rax ; make room for the real return address (Rip) - PUSH_CALLEE_SAVED_REGISTERS - push_vol_reg rax - mov rcx, rsp - - alloc_stack 20h - - END_PROLOGUE - - call OnHijackObjectWorker - - add rsp, 20h - pop rax - POP_CALLEE_SAVED_REGISTERS - ret ; return to the correct place, adjusted by our caller -NESTED_END OnHijackObjectTripThread, _TEXT - - -; VOID OnHijackInteriorPointerTripThread() -NESTED_ENTRY OnHijackInteriorPointerTripThread, _TEXT - - ; Don't fiddle with this unless you change HijackFrame::UpdateRegDisplay - ; and HijackObjectArgs - push rax ; make room for the real return address (Rip) - PUSH_CALLEE_SAVED_REGISTERS - push_vol_reg rax - mov rcx, rsp - - alloc_stack 20h - - END_PROLOGUE - - call OnHijackInteriorPointerWorker - - add rsp, 20h - pop rax - POP_CALLEE_SAVED_REGISTERS - ret ; return to the correct place, adjusted by our caller -NESTED_END OnHijackInteriorPointerTripThread, _TEXT - -; VOID OnHijackScalarTripThread() -NESTED_ENTRY OnHijackScalarTripThread, _TEXT +; VOID OnHijackTripThread() +NESTED_ENTRY OnHijackTripThread, _TEXT ; Don't fiddle with this unless you change HijackFrame::UpdateRegDisplay ; and HijackObjectArgs @@ -493,7 +445,7 @@ NESTED_ENTRY OnHijackScalarTripThread, _TEXT END_PROLOGUE - call OnHijackScalarWorker + call OnHijackWorker movdqa xmm0, [rsp + 20h] @@ -501,7 +453,7 @@ NESTED_ENTRY OnHijackScalarTripThread, _TEXT pop rax POP_CALLEE_SAVED_REGISTERS ret ; return to the correct place, adjusted by our caller -NESTED_END OnHijackScalarTripThread, _TEXT +NESTED_END OnHijackTripThread, _TEXT ; diff --git a/src/vm/amd64/cgenamd64.cpp b/src/vm/amd64/cgenamd64.cpp index d5698005be..1f7d20a4fb 100644 --- a/src/vm/amd64/cgenamd64.cpp +++ b/src/vm/amd64/cgenamd64.cpp @@ -304,8 +304,7 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD) RETURN; } -// The HijackFrame has to know the registers that are pushed by OnHijackObjectTripThread -// and OnHijackScalarTripThread, so all three are implemented together. +// The HijackFrame has to know the registers that are pushed by OnHijackTripThread void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD) { CONTRACTL { diff --git a/src/vm/amd64/cgencpu.h b/src/vm/amd64/cgencpu.h index 409b8e5159..258ac38915 100644 --- a/src/vm/amd64/cgencpu.h +++ b/src/vm/amd64/cgencpu.h @@ -479,13 +479,13 @@ struct DECLSPEC_ALIGN(8) UMEntryThunkCode struct HijackArgs { -#ifndef PLATFORM_UNIX +#ifndef FEATURE_MULTIREG_RETURN union { ULONG64 Rax; - ULONG64 ReturnValue; + ULONG64 ReturnValue[1]; }; -#else // PLATFORM_UNIX +#else // FEATURE_MULTIREG_RETURN union { struct diff --git a/src/vm/amd64/unixasmhelpers.S b/src/vm/amd64/unixasmhelpers.S index 7db8e526f1..837dcf9044 100644 --- a/src/vm/amd64/unixasmhelpers.S +++ b/src/vm/amd64/unixasmhelpers.S @@ -176,7 +176,7 @@ NESTED_END JIT_RareDisableHelper, _TEXT //------------------------------------------------ // OnHijackScalarTripThread // -NESTED_ENTRY OnHijackScalarTripThread, _TEXT, NoHandler +NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler // Make room for the real return address (rip) push_register rax @@ -198,7 +198,7 @@ NESTED_ENTRY OnHijackScalarTripThread, _TEXT, NoHandler END_PROLOGUE - call C_FUNC(OnHijackScalarWorker) + call C_FUNC(OnHijackWorker) movdqa xmm0, [rsp] movdqa xmm1, [rsp+0x10] @@ -209,111 +209,7 @@ NESTED_ENTRY OnHijackScalarTripThread, _TEXT, NoHandler POP_CALLEE_SAVED_REGISTERS ret -NESTED_END OnHijackScalarTripThread, _TEXT - -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING -//------------------------------------------------ -// OnHijackStructInRegsTripThread -// -NESTED_ENTRY OnHijackStructInRegsTripThread, _TEXT, NoHandler - - // Make room for the real return address (rip) - push_register rax - - PUSH_CALLEE_SAVED_REGISTERS - - push_register rdx - // Push rax again - this is where part of the struct gets returned - push_register rax - - mov rdi, rsp - - alloc_stack 0x28 - - // First float return register - movdqa [rsp], xmm0 - // Second float return register - movdqa [rsp+0x10], xmm1 - - END_PROLOGUE - - call C_FUNC(OnHijackStructInRegsWorker) - - movdqa xmm0, [rsp] - movdqa xmm1, [rsp+0x10] - free_stack 0x28 - pop_register rax - pop_register rdx - - POP_CALLEE_SAVED_REGISTERS - ret - -NESTED_END OnHijackStructInRegsTripThread, _TEXT -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING - -//------------------------------------------------ -// OnHijackObjectTripThread -// -NESTED_ENTRY OnHijackObjectTripThread, _TEXT, NoHandler - - // Make room for the real return address (rip) - push_register rax - - PUSH_CALLEE_SAVED_REGISTERS - - push_register rdx - // Push rax again - this is where integer/pointer return values are returned - push_register rax - - mov rdi, rsp - - // align stack - alloc_stack 0x8 - - END_PROLOGUE - - call C_FUNC(OnHijackObjectWorker) - - free_stack 0x8 - pop_register rax - pop_register rdx - - POP_CALLEE_SAVED_REGISTERS - ret - -NESTED_END OnHijackObjectTripThread, _TEXT - -//------------------------------------------------ -// OnHijackInteriorPointerTripThread -// -NESTED_ENTRY OnHijackInteriorPointerTripThread, _TEXT, NoHandler - - // Make room for the real return address (rip) - push_register rax - - PUSH_CALLEE_SAVED_REGISTERS - - push_register rdx - // Push rax again - this is where integer/pointer return values are returned - push_register rax - - mov rdi, rsp - - // align stack - alloc_stack 0x8 - - END_PROLOGUE - - call C_FUNC(OnHijackInteriorPointerWorker) - - free_stack 0x8 - pop_register rax - pop_register rdx - - POP_CALLEE_SAVED_REGISTERS - ret - -NESTED_END OnHijackInteriorPointerTripThread, _TEXT +NESTED_END OnHijackTripThread, _TEXT #endif // FEATURE_HIJACK |