summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKyungwoo Lee <kyulee@microsoft.com>2016-07-20 08:50:22 -0700
committerKyungwoo Lee <kyulee@microsoft.com>2016-07-20 08:50:22 -0700
commitb37e6fc8f5cd72eaae9258df2158bb85e5ff43dc (patch)
tree86823d60dc4b835e1210a2dba5ec7116ef5601a5 /src
parente9774389f13862104605a092921d4e3872524096 (diff)
downloadcoreclr-b37e6fc8f5cd72eaae9258df2158bb85e5ff43dc.tar.gz
coreclr-b37e6fc8f5cd72eaae9258df2158bb85e5ff43dc.tar.bz2
coreclr-b37e6fc8f5cd72eaae9258df2158bb85e5ff43dc.zip
ARM64: Enable Function Fragment
Fixes https://github.com/dotnet/coreclr/issues/6064 Fixes https://github.com/dotnet/coreclr/issues/6122 Basically this enable function fragment. Unwind data for arm64 can express only 1MB range. For the large function, we should split unwind data for each fragment of function. Other than the first fragment (the host region), each fragment has a phantom prolog starting with "end_c(0xe5)". I confirmed that this implementation aligns with window's unwinder, and tested with COMPlus_JitSplitFunctionSize=32 for a few test cases which split both main and funclets.
Diffstat (limited to 'src')
-rw-r--r--src/jit/unwind.h1
-rw-r--r--src/jit/unwindarm.cpp4
-rw-r--r--src/vm/codeman.cpp29
3 files changed, 16 insertions, 18 deletions
diff --git a/src/jit/unwind.h b/src/jit/unwind.h
index 68a06fc15c..0327e97c24 100644
--- a/src/jit/unwind.h
+++ b/src/jit/unwind.h
@@ -30,6 +30,7 @@ const unsigned MAX_EPILOG_SIZE_BYTES = 40;
const unsigned MAX_PROLOG_SIZE_BYTES = 100;
const unsigned MAX_EPILOG_SIZE_BYTES = 100;
#define UWC_END 0xE4 // "end" unwind code
+#define UWC_END_C 0xE5 // "end_c" unwind code
#define UW_MAX_FRAGMENT_SIZE_BYTES (1U << 20)
#define UW_MAX_CODE_WORDS_COUNT 31
#define UW_MAX_EPILOG_START_INDEX 0x3FFU
diff --git a/src/jit/unwindarm.cpp b/src/jit/unwindarm.cpp
index 745c3ac57a..29cbdcfa0e 100644
--- a/src/jit/unwindarm.cpp
+++ b/src/jit/unwindarm.cpp
@@ -996,9 +996,11 @@ void UnwindFragmentInfo::AddEpilog()
void UnwindFragmentInfo::CopyPrologCodes(UnwindFragmentInfo* pCopyFrom)
{
ufiPrologCodes.CopyFrom(&pCopyFrom->ufiPrologCodes);
+#ifdef _TARGET_ARM64_
+ ufiPrologCodes.AddCode(UWC_END_C);
+#endif
}
-
// Split the epilog codes that currently exist in 'pSplitFrom'. The ones that represent
// epilogs that start at or after the location represented by 'emitLoc' are removed
// from 'pSplitFrom' and moved to this fragment. Note that this fragment should not have
diff --git a/src/vm/codeman.cpp b/src/vm/codeman.cpp
index 7eea254646..9fce5b542f 100644
--- a/src/vm/codeman.cpp
+++ b/src/vm/codeman.cpp
@@ -858,39 +858,34 @@ BOOL IsFunctionFragment(TADDR baseAddress, PTR_RUNTIME_FUNCTION pFunctionEntry)
// 1. Prolog only: The host record. Epilog Count and E bit are all 0.
// 2. Prolog and some epilogs: The host record with acompannying epilog-only records
// 3. Epilogs only: First unwind code is Phantom prolog (Starting with an end_c, indicating an empty prolog)
- // 4. No prologs or epilogs: Epilog Count = 1 and Epilog Start Index points end_c. (as if it's case #2 with empty epilog codes)
+ // 4. No prologs or epilogs: First unwind code is Phantom prolog (Starting with an end_c, indicating an empty prolog)
//
int EpilogCount = (int)(unwindHeader >> 22) & 0x1F;
int CodeWords = unwindHeader >> 27;
PTR_DWORD pUnwindCodes = (PTR_DWORD)(baseAddress + pFunctionEntry->UnwindData);
+ // Skip header.
+ pUnwindCodes++;
+
+ // Skip extended header.
if ((CodeWords == 0) && (EpilogCount == 0))
- pUnwindCodes++;
- BOOL Ebit = (unwindHeader >> 21) & 0x1;
- if (Ebit)
{
- // EpilogCount is the index of the first unwind code that describes the one and only epilog
- // The unwind codes immediatelly follow the unwindHeader
+ EpilogCount = (*pUnwindCodes) & 0xFFFF;
pUnwindCodes++;
}
- else if (EpilogCount != 0)
+
+ // Skip epilog scopes.
+ BOOL Ebit = (unwindHeader >> 21) & 0x1;
+ if (!Ebit && (EpilogCount != 0))
{
// EpilogCount is the number of exception scopes defined right after the unwindHeader
- pUnwindCodes += EpilogCount+1;
+ pUnwindCodes += EpilogCount;
}
- else
- {
- return FALSE;
- }
-
- if ((*pUnwindCodes & 0xFF) == 0xE5) // Phantom prolog
- return TRUE;
-
+ return ((*pUnwindCodes & 0xFF) == 0xE5);
#else
PORTABILITY_ASSERT("IsFunctionFragnent - NYI on this platform");
#endif
- return FALSE;
}
#endif // EXCEPTION_DATA_SUPPORTS_FUNCTION_FRAGMENTS