summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/CMakeLists.txt2
-rw-r--r--src/vm/amd64/JitHelpers_SingleAppDomain.asm64
-rw-r--r--src/vm/amd64/jithelpers_singleappdomain.S49
-rw-r--r--src/vm/amd64/unixstubs.cpp6
-rw-r--r--src/vm/appdomain.cpp26
-rw-r--r--src/vm/appdomain.hpp26
-rw-r--r--src/vm/argdestination.h43
-rw-r--r--src/vm/arm64/asmconstants.h6
-rw-r--r--src/vm/arm64/asmhelpers.S65
-rw-r--r--src/vm/arm64/asmhelpers.asm60
-rw-r--r--src/vm/arm64/stubs.cpp15
-rw-r--r--src/vm/assembly.cpp5
-rw-r--r--src/vm/callingconvention.h43
-rw-r--r--src/vm/ceemain.cpp14
-rw-r--r--src/vm/codeman.cpp100
-rw-r--r--src/vm/codeman.h1
-rw-r--r--src/vm/compile.cpp4
-rw-r--r--src/vm/corhost.cpp43
-rw-r--r--src/vm/dynamicmethod.cpp25
-rw-r--r--src/vm/dynamicmethod.h3
-rw-r--r--src/vm/ecalllist.h1
-rw-r--r--src/vm/eetwain.cpp100
-rw-r--r--src/vm/exceptionhandling.cpp38
-rw-r--r--src/vm/exceptionhandling.h11
-rw-r--r--src/vm/exstate.cpp6
-rw-r--r--src/vm/exstate.h2
-rw-r--r--src/vm/frames.h6
-rw-r--r--src/vm/gcenv.ee.cpp14
-rw-r--r--src/vm/gcenv.os.cpp209
-rw-r--r--src/vm/gchandletableutilities.h354
-rw-r--r--src/vm/gchandleutilities.h495
-rw-r--r--src/vm/gcheaputilities.cpp33
-rw-r--r--src/vm/gdbjit.cpp2
-rw-r--r--src/vm/hosting.cpp10
-rw-r--r--src/vm/i386/asmhelpers.S23
-rw-r--r--src/vm/i386/cgenx86.cpp62
-rw-r--r--src/vm/i386/ehhelpers.S2
-rw-r--r--src/vm/i386/excepx86.cpp12
-rw-r--r--src/vm/i386/gmsx86.cpp8
-rw-r--r--src/vm/jitinterface.cpp36
-rw-r--r--src/vm/jitinterfacegen.cpp15
-rw-r--r--src/vm/method.cpp2
-rw-r--r--src/vm/methodtable.h8
-rw-r--r--src/vm/methodtable.inl4
-rw-r--r--src/vm/mscorlib.h5
-rw-r--r--src/vm/object.cpp8
-rw-r--r--src/vm/object.h10
-rw-r--r--src/vm/peimagelayout.cpp26
-rw-r--r--src/vm/safehandle.cpp4
-rw-r--r--src/vm/siginfo.cpp5
-rw-r--r--src/vm/stubhelpers.cpp2
-rw-r--r--src/vm/stubhelpers.h2
-rw-r--r--src/vm/threads.cpp2
-rw-r--r--src/vm/threads.h27
-rw-r--r--src/vm/threadsuspend.cpp4
-rw-r--r--src/vm/typedesc.cpp6
-rw-r--r--src/vm/util.cpp10
57 files changed, 1536 insertions, 628 deletions
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt
index 26fcacf4af..da1aa8fe62 100644
--- a/src/vm/CMakeLists.txt
+++ b/src/vm/CMakeLists.txt
@@ -317,6 +317,7 @@ if(CLR_CMAKE_TARGET_ARCH_AMD64)
${ARCH_SOURCES_DIR}/JitHelpers_FastWriteBarriers.asm
${ARCH_SOURCES_DIR}/JitHelpers_InlineGetAppDomain.asm
${ARCH_SOURCES_DIR}/JitHelpers_InlineGetThread.asm
+ ${ARCH_SOURCES_DIR}/JitHelpers_SingleAppDomain.asm
${ARCH_SOURCES_DIR}/JitHelpers_Slow.asm
${ARCH_SOURCES_DIR}/PInvokeStubs.asm
${ARCH_SOURCES_DIR}/RedirectedHandledJITCase.asm
@@ -363,6 +364,7 @@ else(WIN32)
${ARCH_SOURCES_DIR}/getstate.S
${ARCH_SOURCES_DIR}/jithelpers_fast.S
${ARCH_SOURCES_DIR}/jithelpers_fastwritebarriers.S
+ ${ARCH_SOURCES_DIR}/jithelpers_singleappdomain.S
${ARCH_SOURCES_DIR}/jithelpers_slow.S
${ARCH_SOURCES_DIR}/pinvokestubs.S
${ARCH_SOURCES_DIR}/theprestubamd64.S
diff --git a/src/vm/amd64/JitHelpers_SingleAppDomain.asm b/src/vm/amd64/JitHelpers_SingleAppDomain.asm
new file mode 100644
index 0000000000..f1b267435a
--- /dev/null
+++ b/src/vm/amd64/JitHelpers_SingleAppDomain.asm
@@ -0,0 +1,64 @@
+; 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: JitHelpers_SingleAppDomain.asm
+;
+; Notes: JIT Static access helpers when coreclr host specifies single
+; appdomain flag
+; ***********************************************************************
+
+include AsmMacros.inc
+include asmconstants.inc
+
+; Min amount of stack space that a nested function should allocate.
+MIN_SIZE equ 28h
+
+extern JIT_GetSharedNonGCStaticBase_Helper:proc
+extern JIT_GetSharedGCStaticBase_Helper:proc
+
+LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
+ ; If class is not initialized, bail to C++ helper
+ test byte ptr [rcx + OFFSETOF__DomainLocalModule__m_pDataBlob + rdx], 1
+ jz CallHelper
+ mov rax, rcx
+ REPRET
+
+ align 16
+ CallHelper:
+ ; Tail call JIT_GetSharedNonGCStaticBase_Helper
+ jmp JIT_GetSharedNonGCStaticBase_Helper
+LEAF_END JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
+
+LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+ mov rax, rcx
+ ret
+LEAF_END JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+
+LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
+ ; If class is not initialized, bail to C++ helper
+ test byte ptr [rcx + OFFSETOF__DomainLocalModule__m_pDataBlob + rdx], 1
+ jz CallHelper
+
+ mov rax, [rcx + OFFSETOF__DomainLocalModule__m_pGCStatics]
+ REPRET
+
+ align 16
+ CallHelper:
+ ; Tail call Jit_GetSharedGCStaticBase_Helper
+ jmp JIT_GetSharedGCStaticBase_Helper
+LEAF_END JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
+
+LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+ mov rax, [rcx + OFFSETOF__DomainLocalModule__m_pGCStatics]
+ ret
+LEAF_END JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+
+ end
+
diff --git a/src/vm/amd64/jithelpers_singleappdomain.S b/src/vm/amd64/jithelpers_singleappdomain.S
new file mode 100644
index 0000000000..307d86b7fe
--- /dev/null
+++ b/src/vm/amd64/jithelpers_singleappdomain.S
@@ -0,0 +1,49 @@
+// 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"
+
+//
+// JIT Static access helpers when coreclr host specifies single
+// appdomain flag
+//
+
+LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
+ // If class is not initialized, bail to C++ helper
+ test byte ptr [rdi + OFFSETOF__DomainLocalModule__m_pDataBlob + rsi], 1
+ jz CallHelper
+ mov rax, rdi
+ rep ret
+
+.balign 16
+CallHelper:
+ // Tail call JIT_GetSharedNonGCStaticBase_Helper
+ jmp C_FUNC(JIT_GetSharedNonGCStaticBase_Helper)
+LEAF_END_MARKED JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
+
+LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+ mov rax, rdi
+ ret
+LEAF_END JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+
+LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
+ // If class is not initialized, bail to C++ helper
+ test byte ptr [rdi + OFFSETOF__DomainLocalModule__m_pDataBlob + rsi], 1
+ jz CallHelper1
+
+ mov rax, [rdi + OFFSETOF__DomainLocalModule__m_pGCStatics]
+ rep ret
+
+.balign 16
+CallHelper1:
+ // Tail call Jit_GetSharedGCStaticBase_Helper
+ jmp C_FUNC(JIT_GetSharedGCStaticBase_Helper)
+LEAF_END JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
+
+LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+ mov rax, [rdi + OFFSETOF__DomainLocalModule__m_pGCStatics]
+ ret
+LEAF_END JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
diff --git a/src/vm/amd64/unixstubs.cpp b/src/vm/amd64/unixstubs.cpp
index 2904149084..76d3cf1890 100644
--- a/src/vm/amd64/unixstubs.cpp
+++ b/src/vm/amd64/unixstubs.cpp
@@ -37,7 +37,7 @@ extern "C"
" mov %%edx, 12(%[result])\n" \
: "=a"(eax) /*output in eax*/\
: "a"(arg), [result]"r"(result) /*inputs - arg in eax, result in any register*/\
- : "eax", "rbx", "ecx", "edx", "memory" /* registers that are clobbered, *result is clobbered */
+ : "rbx", "ecx", "edx", "memory" /* registers that are clobbered, *result is clobbered */
);
return eax;
}
@@ -52,7 +52,7 @@ extern "C"
" mov %%edx, 12(%[result])\n" \
: "=a"(eax) /*output in eax*/\
: "c"(arg1), "a"(arg2), [result]"r"(result) /*inputs - arg1 in ecx, arg2 in eax, result in any register*/\
- : "eax", "rbx", "ecx", "edx", "memory" /* registers that are clobbered, *result is clobbered */
+ : "rbx", "edx", "memory" /* registers that are clobbered, *result is clobbered */
);
return eax;
}
@@ -63,7 +63,7 @@ extern "C"
__asm(" xgetbv\n" \
: "=a"(eax) /*output in eax*/\
: "c"(0) /*inputs - 0 in ecx*/\
- : "eax", "edx" /* registers that are clobbered*/
+ : "edx" /* registers that are clobbered*/
);
// check OS has enabled both XMM and YMM state support
return ((eax & 0x06) == 0x06) ? 1 : 0;
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp
index 5bfb12fc6b..bd05991ea2 100644
--- a/src/vm/appdomain.cpp
+++ b/src/vm/appdomain.cpp
@@ -741,7 +741,7 @@ BaseDomain::BaseDomain()
#ifndef CROSSGEN_COMPILE
// Note that m_handleStore is overridden by app domains
- m_handleStore = GCHandleTableUtilities::GetGCHandleTable()->GetGlobalHandleStore();
+ m_handleStore = GCHandleUtilities::GetGCHandleManager()->GetGlobalHandleStore();
#else
m_handleStore = NULL;
#endif
@@ -4273,11 +4273,16 @@ void AppDomain::Init()
// default domain cannot be unloaded.
if (GetId().m_dwId == DefaultADID)
{
- m_handleStore = GCHandleTableUtilities::GetGCHandleTable()->GetGlobalHandleStore();
+ m_handleStore = GCHandleUtilities::GetGCHandleManager()->GetGlobalHandleStore();
}
else
{
- m_handleStore = GCHandleTableUtilities::GetGCHandleTable()->CreateHandleStore((void*)(uintptr_t)m_dwIndex.m_dwIndex);
+ m_handleStore = GCHandleUtilities::GetGCHandleManager()->CreateHandleStore((void*)(uintptr_t)m_dwIndex.m_dwIndex);
+ }
+
+ if (!m_handleStore)
+ {
+ COMPlusThrowOM();
}
#endif // CROSSGEN_COMPILE
@@ -4578,9 +4583,9 @@ void AppDomain::Terminate()
BaseDomain::Terminate();
- if (m_handleStore)
+ if (m_handleStore)
{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleStore(m_handleStore);
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleStore(m_handleStore);
m_handleStore = NULL;
}
@@ -4679,7 +4684,8 @@ OBJECTREF AppDomain::GetExposedObject()
obj = (APPDOMAINREF) AllocateObject(pMT);
obj->SetDomain(this);
- if(StoreFirstObjectInHandle(m_ExposedObject, (OBJECTREF) obj) == FALSE) {
+ if (!StoreFirstObjectInHandle(m_ExposedObject, (OBJECTREF) obj))
+ {
obj = (APPDOMAINREF) GetRawExposedObject();
_ASSERTE(obj);
}
@@ -9197,8 +9203,8 @@ void AppDomain::ClearGCHandles()
// Keep async pin handles alive by moving them to default domain
HandleAsyncPinHandles();
- // Remove our handle table as a source of GC roots
- GCHandleTableUtilities::GetGCHandleTable()->UprootHandleStore(m_handleStore);
+ // Remove our handle store as a source of GC roots
+ m_handleStore->Uproot();
}
// When an AD is unloaded, we will release all objects in this AD.
@@ -9247,15 +9253,13 @@ void AppDomain::ClearGCRoots()
// this point, so only need to synchronize the preemptive mode threads.
ExecutionManager::Unload(GetLoaderAllocator());
- IGCHandleTable* pHandleTable = GCHandleTableUtilities::GetGCHandleTable();
-
while ((pThread = ThreadStore::GetAllThreadList(pThread, 0, 0)) != NULL)
{
// Delete the thread local static store
pThread->DeleteThreadStaticData(this);
// <TODO>@TODO: A pre-allocated AppDomainUnloaded exception might be better.</TODO>
- if (pHandleTable->ContainsHandle(m_handleStore, pThread->m_LastThrownObjectHandle))
+ if (m_handleStore->ContainsHandle(pThread->m_LastThrownObjectHandle))
{
// Never delete a handle to a preallocated exception object.
if (!CLRException::IsPreallocatedExceptionHandle(pThread->m_LastThrownObjectHandle))
diff --git a/src/vm/appdomain.hpp b/src/vm/appdomain.hpp
index 898e50f1c2..a5bd00d36b 100644
--- a/src/vm/appdomain.hpp
+++ b/src/vm/appdomain.hpp
@@ -28,7 +28,7 @@
#include "ilstubcache.h"
#include "testhookmgr.h"
#include "gcheaputilities.h"
-#include "gchandletableutilities.h"
+#include "gchandleutilities.h"
#include "../binder/inc/applicationcontext.hpp"
#include "rejit.h"
@@ -1245,8 +1245,13 @@ public:
{
WRAPPER_NO_CONTRACT;
- IGCHandleTable *pHandleTable = GCHandleTableUtilities::GetGCHandleTable();
- return pHandleTable->CreateHandleOfType(m_handleStore, OBJECTREFToObject(object), type);
+ OBJECTHANDLE hnd = m_handleStore->CreateHandleOfType(OBJECTREFToObject(object), type);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
}
OBJECTHANDLE CreateHandle(OBJECTREF object)
@@ -1319,7 +1324,7 @@ public:
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_NOTRIGGER;
MODE_COOPERATIVE;
}
@@ -1339,14 +1344,19 @@ public:
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_NOTRIGGER;
MODE_COOPERATIVE;
}
CONTRACTL_END;
- IGCHandleTable *pHandleTable = GCHandleTableUtilities::GetGCHandleTable();
- return pHandleTable->CreateDependentHandle(m_handleStore, OBJECTREFToObject(primary), OBJECTREFToObject(secondary));
+ OBJECTHANDLE hnd = m_handleStore->CreateDependentHandle(OBJECTREFToObject(primary), OBJECTREFToObject(secondary));
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
}
#endif // DACCESS_COMPILE && !CROSSGEN_COMPILE
@@ -1402,7 +1412,7 @@ protected:
CLRPrivBinderCoreCLR *m_pTPABinderContext; // Reference to the binding context that holds TPA list details
- void* m_handleStore;
+ IGCHandleStore* m_handleStore;
// The large heap handle table.
LargeHeapHandleTable *m_pLargeHeapHandleTable;
diff --git a/src/vm/argdestination.h b/src/vm/argdestination.h
index 8a3fb4fdf2..8ab0a5664b 100644
--- a/src/vm/argdestination.h
+++ b/src/vm/argdestination.h
@@ -30,6 +30,9 @@ public:
LIMITED_METHOD_CONTRACT;
#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
_ASSERTE((argLocDescForStructInRegs != NULL) || (offset != TransitionBlock::StructInRegsOffset));
+#elif defined(_TARGET_ARM64_)
+ // This assert is not interesting on arm64. argLocDescForStructInRegs could be
+ // initialized if the args are being enregistered.
#else
_ASSERTE(argLocDescForStructInRegs == NULL);
#endif
@@ -42,6 +45,46 @@ public:
return dac_cast<PTR_VOID>(dac_cast<TADDR>(m_base) + m_offset);
}
+#if defined(_TARGET_ARM64_)
+#ifndef DACCESS_COMPILE
+
+ // Returns true if the ArgDestination represents an HFA struct
+ bool IsHFA()
+ {
+ return m_argLocDescForStructInRegs != NULL;
+ }
+
+ // Copy struct argument into registers described by the current ArgDestination.
+ // Arguments:
+ // src = source data of the structure
+ // fieldBytes - size of the structure
+ void CopyHFAStructToRegister(void *src, int fieldBytes)
+ {
+ // We are either copying either a float or double HFA and need to
+ // enregister each field.
+
+ int floatRegCount = m_argLocDescForStructInRegs->m_cFloatReg;
+ bool typeFloat = m_argLocDescForStructInRegs->m_isSinglePrecision;
+ void* dest = this->GetDestinationAddress();
+
+ if (typeFloat)
+ {
+ for (int i = 0; i < floatRegCount; ++i)
+ {
+ // Copy 4 bytes on 8 bytes alignment
+ *((UINT64*)dest + i) = *((UINT32*)src + i);
+ }
+ }
+ else
+ {
+ // We can just do a memcpy.
+ memcpyNoGCRefs(dest, src, fieldBytes);
+ }
+ }
+
+#endif // !DACCESS_COMPILE
+#endif // defined(_TARGET_ARM64_)
+
#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
// Returns true if the ArgDestination represents a struct passed in registers.
diff --git a/src/vm/arm64/asmconstants.h b/src/vm/arm64/asmconstants.h
index b0300ca324..12b72f9249 100644
--- a/src/vm/arm64/asmconstants.h
+++ b/src/vm/arm64/asmconstants.h
@@ -167,5 +167,11 @@ ASMCONSTANTS_C_ASSERT(ResolveCacheElem__target == offsetof(ResolveCacheElem, tar
ASMCONSTANTS_C_ASSERT(ResolveCacheElem__pNext == offsetof(ResolveCacheElem, pNext));
#endif // CROSSGEN_COMPILE
+#define DomainLocalModule__m_pDataBlob 0x30
+#define DomainLocalModule__m_pGCStatics 0x20
+ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pDataBlob == offsetof(DomainLocalModule, m_pDataBlob));
+ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pGCStatics == offsetof(DomainLocalModule, m_pGCStatics));
+
+
#undef ASMCONSTANTS_RUNTIME_ASSERT
#undef ASMCONSTANTS_C_ASSERT
diff --git a/src/vm/arm64/asmhelpers.S b/src/vm/arm64/asmhelpers.S
index ef6b5cfffe..15b8057ed6 100644
--- a/src/vm/arm64/asmhelpers.S
+++ b/src/vm/arm64/asmhelpers.S
@@ -1192,9 +1192,9 @@ NESTED_END StubDispatchFixupStub, _TEXT
// On exit:
// buffer pointed to by x1 on entry contains the float or double argument as appropriate
//
- LEAF_ENTRY getFPReturn
+LEAF_ENTRY getFPReturn, _TEXT
str d0, [x1]
- LEAF_END
+LEAF_END getFPReturn, _TEXT
// ------------------------------------------------------------------
// Function used by COM interop to set floating point return value (since it's not in the same
@@ -1208,7 +1208,64 @@ NESTED_END StubDispatchFixupStub, _TEXT
// s0 : float result if x0 == 4
// d0 : double result if x0 == 8
//
- LEAF_ENTRY setFPReturn
+LEAF_ENTRY setFPReturn, _TEXT
fmov d0, x1
- LEAF_END
+LEAF_END setFPReturn, _TEXT
#endif
+
+//
+// JIT Static access helpers when coreclr host specifies single appdomain flag
+//
+
+// ------------------------------------------------------------------
+// void* JIT_GetSharedNonGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
+
+LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
+ // If class is not initialized, bail to C++ helper
+ add x2, x0, #DomainLocalModule__m_pDataBlob
+ ldrb w2, [x2, w1, UXTW]
+ tst w2, #1
+ beq LOCAL_LABEL(JIT_GetSharedNonGCStaticBase_SingleAppDomain_CallHelper)
+
+ ret lr
+
+LOCAL_LABEL(JIT_GetSharedNonGCStaticBase_SingleAppDomain_CallHelper):
+ // Tail call JIT_GetSharedNonGCStaticBase_Helper
+ b C_FUNC(JIT_GetSharedNonGCStaticBase_Helper)
+LEAF_END JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
+
+
+// ------------------------------------------------------------------
+// void* JIT_GetSharedNonGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
+
+LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+ ret lr
+LEAF_END JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+
+
+// ------------------------------------------------------------------
+// void* JIT_GetSharedGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
+
+LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
+ // If class is not initialized, bail to C++ helper
+ add x2, x0, #DomainLocalModule__m_pDataBlob
+ ldrb w2, [x2, w1, UXTW]
+ tst w2, #1
+ beq LOCAL_LABEL(JIT_GetSharedGCStaticBase_SingleAppDomain_CallHelper)
+
+ ldr x0, [x0, #DomainLocalModule__m_pGCStatics]
+ ret lr
+
+LOCAL_LABEL(JIT_GetSharedGCStaticBase_SingleAppDomain_CallHelper):
+ // Tail call Jit_GetSharedGCStaticBase_Helper
+ b C_FUNC(JIT_GetSharedGCStaticBase_Helper)
+LEAF_END JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
+
+
+// ------------------------------------------------------------------
+// void* JIT_GetSharedGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
+
+LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+ ldr x0, [x0, #DomainLocalModule__m_pGCStatics]
+ ret lr
+LEAF_END JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
diff --git a/src/vm/arm64/asmhelpers.asm b/src/vm/arm64/asmhelpers.asm
index e8b16ded6a..24b26eb1c9 100644
--- a/src/vm/arm64/asmhelpers.asm
+++ b/src/vm/arm64/asmhelpers.asm
@@ -52,6 +52,9 @@
IMPORT $g_GCShadowEnd
#endif // WRITE_BARRIER_CHECK
+ IMPORT JIT_GetSharedNonGCStaticBase_Helper
+ IMPORT JIT_GetSharedGCStaticBase_Helper
+
TEXTAREA
;; LPVOID __stdcall GetCurrentIP(void);
@@ -1326,5 +1329,62 @@ Fail
LEAF_END
#endif
+;
+; JIT Static access helpers when coreclr host specifies single appdomain flag
+;
+
+; ------------------------------------------------------------------
+; void* JIT_GetSharedNonGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
+
+ LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain
+ ; If class is not initialized, bail to C++ helper
+ add x2, x0, #DomainLocalModule__m_pDataBlob
+ ldrb w2, [x2, w1]
+ tst w2, #1
+ beq CallHelper1
+
+ ret lr
+
+CallHelper1
+ ; Tail call JIT_GetSharedNonGCStaticBase_Helper
+ b JIT_GetSharedNonGCStaticBase_Helper
+ LEAF_END
+
+
+; ------------------------------------------------------------------
+; void* JIT_GetSharedNonGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
+
+ LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain
+ ret lr
+ LEAF_END
+
+
+; ------------------------------------------------------------------
+; void* JIT_GetSharedGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
+
+ LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain
+ ; If class is not initialized, bail to C++ helper
+ add x2, x0, #DomainLocalModule__m_pDataBlob
+ ldrb w2, [x2, w1]
+ tst w2, #1
+ beq CallHelper2
+
+ ldr x0, [x0, #DomainLocalModule__m_pGCStatics]
+ ret lr
+
+CallHelper2
+ ; Tail call Jit_GetSharedGCStaticBase_Helper
+ b JIT_GetSharedGCStaticBase_Helper
+ LEAF_END
+
+
+; ------------------------------------------------------------------
+; void* JIT_GetSharedGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
+
+ LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain
+ ldr x0, [x0, #DomainLocalModule__m_pGCStatics]
+ ret lr
+ LEAF_END
+
; Must be at very end of file
END
diff --git a/src/vm/arm64/stubs.cpp b/src/vm/arm64/stubs.cpp
index f56f6ab625..0c7eb4dfba 100644
--- a/src/vm/arm64/stubs.cpp
+++ b/src/vm/arm64/stubs.cpp
@@ -15,6 +15,11 @@
#include "virtualcallstub.h"
#include "jitinterface.h"
+EXTERN_C void JIT_GetSharedNonGCStaticBase_SingleAppDomain();
+EXTERN_C void JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain();
+EXTERN_C void JIT_GetSharedGCStaticBase_SingleAppDomain();
+EXTERN_C void JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain();
+
#ifndef DACCESS_COMPILE
//-----------------------------------------------------------------------
// InstructionFormat for B.cond
@@ -1078,10 +1083,18 @@ void JIT_TailCall()
_ASSERTE(!"ARM64:NYI");
}
+#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
void InitJITHelpers1()
{
- return;
+ if(IsSingleAppDomain())
+ {
+ SetJitHelperFunction(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, JIT_GetSharedGCStaticBase_SingleAppDomain);
+ SetJitHelperFunction(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, JIT_GetSharedNonGCStaticBase_SingleAppDomain);
+ SetJitHelperFunction(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain);
+ SetJitHelperFunction(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR,JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain);
+ }
}
+#endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
EXTERN_C void __stdcall ProfileEnterNaked(UINT_PTR clientData)
{
diff --git a/src/vm/assembly.cpp b/src/vm/assembly.cpp
index 75430644c3..92c1ebd817 100644
--- a/src/vm/assembly.cpp
+++ b/src/vm/assembly.cpp
@@ -1849,10 +1849,7 @@ HRESULT RunMain(MethodDesc *pFD ,
else
{
*pParam->piRetVal = (INT32)threadStart.Call_RetArgSlot(&stackVar);
- if (pParam->stringArgs == NULL)
- {
- SetLatchedExitCode(*pParam->piRetVal);
- }
+ SetLatchedExitCode(*pParam->piRetVal);
}
GCPROTECT_END();
diff --git a/src/vm/callingconvention.h b/src/vm/callingconvention.h
index cde2ba465a..b707b4bc8c 100644
--- a/src/vm/callingconvention.h
+++ b/src/vm/callingconvention.h
@@ -34,21 +34,26 @@ BOOL IsRetBuffPassedAsFirstArg();
// and possibly on to the stack as well.
struct ArgLocDesc
{
- int m_idxFloatReg; // First floating point register used (or -1)
- int m_cFloatReg; // Count of floating point registers used (or 0)
+ int m_idxFloatReg; // First floating point register used (or -1)
+ int m_cFloatReg; // Count of floating point registers used (or 0)
- int m_idxGenReg; // First general register used (or -1)
- int m_cGenReg; // Count of general registers used (or 0)
+ int m_idxGenReg; // First general register used (or -1)
+ int m_cGenReg; // Count of general registers used (or 0)
- int m_idxStack; // First stack slot used (or -1)
- int m_cStack; // Count of stack slots used (or 0)
+ int m_idxStack; // First stack slot used (or -1)
+ int m_cStack; // Count of stack slots used (or 0)
#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
- EEClass* m_eeClass; // For structs passed in register, it points to the EEClass of the struct
+ EEClass* m_eeClass; // For structs passed in register, it points to the EEClass of the struct
#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
+#if defined(_TARGET_ARM64_)
+ bool m_isSinglePrecision; // For determining if HFA is single or double
+ // precision
+#endif // defined(_TARGET_ARM64_)
+
#if defined(_TARGET_ARM_)
BOOL m_fRequires64BitAlignment; // True if the argument should always be aligned (in registers or on the stack
#endif
@@ -70,6 +75,9 @@ struct ArgLocDesc
#if defined(_TARGET_ARM_)
m_fRequires64BitAlignment = FALSE;
#endif
+#if defined(_TARGET_ARM64_)
+ m_isSinglePrecision = FALSE;
+#endif // defined(_TARGET_ARM64_)
#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
m_eeClass = NULL;
#endif
@@ -490,7 +498,7 @@ public:
ArgLocDesc* GetArgLocDescForStructInRegs()
{
-#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+#if (defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)) || defined (_TARGET_ARM64_)
return m_hasArgLocDescForStructInRegs ? &m_argLocDescForStructInRegs : NULL;
#else
return NULL;
@@ -556,7 +564,10 @@ public:
if (!m_argTypeHandle.IsNull() && m_argTypeHandle.IsHFA())
{
CorElementType type = m_argTypeHandle.GetHFAType();
- pLoc->m_cFloatReg = (type == ELEMENT_TYPE_R4)? GetArgSize()/sizeof(float): GetArgSize()/sizeof(double);
+ bool isFloatType = (type == ELEMENT_TYPE_R4);
+
+ pLoc->m_cFloatReg = isFloatType ? GetArgSize()/sizeof(float): GetArgSize()/sizeof(double);
+ pLoc->m_isSinglePrecision = isFloatType;
}
else
{
@@ -639,7 +650,7 @@ protected:
CorElementType m_argType;
int m_argSize;
TypeHandle m_argTypeHandle;
-#if defined(_TARGET_AMD64_) && defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+#if (defined(_TARGET_AMD64_) && defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)) || defined(_TARGET_ARM64_)
ArgLocDesc m_argLocDescForStructInRegs;
bool m_hasArgLocDescForStructInRegs;
#endif // _TARGET_AMD64_ && UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
@@ -1103,7 +1114,9 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetNextOffset()
// Handle HFAs: packed structures of 1-4 floats or doubles that are passed in FP argument
// registers if possible.
if (thValueType.IsHFA())
+ {
fFloatingPoint = true;
+ }
#endif
break;
@@ -1255,7 +1268,17 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetNextOffset()
if (thValueType.IsHFA())
{
CorElementType type = thValueType.GetHFAType();
+ bool isFloatType = (type == ELEMENT_TYPE_R4);
+
cFPRegs = (type == ELEMENT_TYPE_R4)? (argSize/sizeof(float)): (argSize/sizeof(double));
+
+ m_argLocDescForStructInRegs.Init();
+ m_argLocDescForStructInRegs.m_cFloatReg = cFPRegs;
+ m_argLocDescForStructInRegs.m_idxFloatReg = m_idxFPReg;
+
+ m_argLocDescForStructInRegs.m_isSinglePrecision = isFloatType;
+
+ m_hasArgLocDescForStructInRegs = true;
}
else
{
diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp
index 6b0c0dfbba..9cce46d2f0 100644
--- a/src/vm/ceemain.cpp
+++ b/src/vm/ceemain.cpp
@@ -869,7 +869,7 @@ void EEStartupHelper(COINITIEE fFlags)
// Initialize remoting
- if (!GCHandleTableUtilities::GetGCHandleTable()->Initialize())
+ if (!GCHandleUtilities::GetGCHandleManager()->Initialize())
{
IfFailGo(E_OUTOFMEMORY);
}
@@ -1880,7 +1880,7 @@ part2:
#ifdef SHOULD_WE_CLEANUP
if (!g_fFastExitProcess)
{
- GCHandleTableUtilities::GetGCHandleTable()->Shutdown();
+ GCHandleUtilities::GetGCHandleManager()->Shutdown();
}
#endif /* SHOULD_WE_CLEANUP */
@@ -2386,7 +2386,7 @@ BOOL CanRunManagedCode(LoaderLockCheck::kind checkKind, HINSTANCE hInst /*= 0*/)
// no longer maintains a ref count since the EE doesn't support being
// unloaded and re-loaded. It simply ensures the EE has been started.
// ---------------------------------------------------------------------------
-HRESULT STDMETHODCALLTYPE CoInitializeEE(DWORD fFlags)
+HRESULT STDAPICALLTYPE CoInitializeEE(DWORD fFlags)
{
CONTRACTL
{
@@ -2417,7 +2417,7 @@ HRESULT STDMETHODCALLTYPE CoInitializeEE(DWORD fFlags)
// Description:
// Must be called by client on shut down in order to free up the system.
// ---------------------------------------------------------------------------
-void STDMETHODCALLTYPE CoUninitializeEE(BOOL fIsDllUnloading)
+void STDAPICALLTYPE CoUninitializeEE(BOOL fIsDllUnloading)
{
LIMITED_METHOD_CONTRACT;
//BEGIN_ENTRYPOINT_VOIDRET;
@@ -2483,17 +2483,17 @@ void InitializeGarbageCollector()
IGCToCLR* gcToClr = nullptr;
#endif
- IGCHandleTable *pGcHandleTable;
+ IGCHandleManager *pGcHandleManager;
IGCHeap *pGCHeap;
- if (!InitializeGarbageCollector(gcToClr, &pGCHeap, &pGcHandleTable, &g_gc_dac_vars))
+ if (!InitializeGarbageCollector(gcToClr, &pGCHeap, &pGcHandleManager, &g_gc_dac_vars))
{
ThrowOutOfMemory();
}
assert(pGCHeap != nullptr);
g_pGCHeap = pGCHeap;
- g_pGCHandleTable = pGcHandleTable;
+ g_pGCHandleManager = pGcHandleManager;
g_gcDacGlobals = &g_gc_dac_vars;
// Apparently the Windows linker removes global variables if they are never
diff --git a/src/vm/codeman.cpp b/src/vm/codeman.cpp
index 73b4c06565..a30e70e7fa 100644
--- a/src/vm/codeman.cpp
+++ b/src/vm/codeman.cpp
@@ -3177,8 +3177,8 @@ void EEJitManager::RemoveJitData (CodeHeader * pCHdr, size_t GCinfo_len, size_t
LCGMethodResolver * pResolver = pMD->AsDynamicMethodDesc()->GetLCGMethodResolver();
- // Clear the pointer only if it matches what we are about to free. There may be cases where the JIT is reentered and
- // the method JITed multiple times.
+ // Clear the pointer only if it matches what we are about to free.
+ // There can be cases where the JIT is reentered and we JITed the method multiple times.
if (pResolver->m_recordCodePointer == codeStart)
pResolver->m_recordCodePointer = NULL;
}
@@ -4885,7 +4885,7 @@ void ExecutionManager::Unload(LoaderAllocator *pLoaderAllocator)
*/
StackwalkCache::Invalidate(pLoaderAllocator);
- JumpStubCache * pJumpStubCache = (JumpStubCache *)pLoaderAllocator->m_pJumpStubCache;
+ JumpStubCache * pJumpStubCache = (JumpStubCache *) pLoaderAllocator->m_pJumpStubCache;
if (pJumpStubCache != NULL)
{
delete pJumpStubCache;
@@ -4954,18 +4954,33 @@ PCODE ExecutionManager::jumpStub(MethodDesc* pMD, PCODE target,
PCODE jumpStub = NULL;
if (pLoaderAllocator == NULL)
+ {
pLoaderAllocator = pMD->GetLoaderAllocatorForCode();
+ }
_ASSERTE(pLoaderAllocator != NULL);
- bool isLCG = pMD && pMD->IsLCGMethod();
+ bool isLCG = pMD && pMD->IsLCGMethod();
+ LCGMethodResolver * pResolver = nullptr;
+ JumpStubCache * pJumpStubCache = (JumpStubCache *) pLoaderAllocator->m_pJumpStubCache;
- CrstHolder ch(&m_JumpStubCrst);
+ if (isLCG)
+ {
+ pResolver = pMD->AsDynamicMethodDesc()->GetLCGMethodResolver();
+ pJumpStubCache = pResolver->m_pJumpStubCache;
+ }
- JumpStubCache * pJumpStubCache = (JumpStubCache *)pLoaderAllocator->m_pJumpStubCache;
+ CrstHolder ch(&m_JumpStubCrst);
if (pJumpStubCache == NULL)
{
pJumpStubCache = new JumpStubCache();
- pLoaderAllocator->m_pJumpStubCache = pJumpStubCache;
+ if (isLCG)
+ {
+ pResolver->m_pJumpStubCache = pJumpStubCache;
+ }
+ else
+ {
+ pLoaderAllocator->m_pJumpStubCache = pJumpStubCache;
+ }
}
if (isLCG)
@@ -5018,9 +5033,19 @@ PCODE ExecutionManager::getNextJumpStub(MethodDesc* pMD, PCODE target,
POSTCONDITION(RETVAL != NULL);
} CONTRACT_END;
- BYTE * jumpStub = NULL;
- bool isLCG = pMD && pMD->IsLCGMethod();
- JumpStubBlockHeader ** ppHead = isLCG ? &(pMD->AsDynamicMethodDesc()->GetLCGMethodResolver()->m_jumpStubBlock) : &(((JumpStubCache *)(pLoaderAllocator->m_pJumpStubCache))->m_pBlocks);
+ DWORD numJumpStubs = DEFAULT_JUMPSTUBS_PER_BLOCK; // a block of 32 JumpStubs
+ BYTE * jumpStub = NULL;
+ bool isLCG = pMD && pMD->IsLCGMethod();
+ JumpStubCache * pJumpStubCache = (JumpStubCache *) pLoaderAllocator->m_pJumpStubCache;
+
+ if (isLCG)
+ {
+ LCGMethodResolver * pResolver;
+ pResolver = pMD->AsDynamicMethodDesc()->GetLCGMethodResolver();
+ pJumpStubCache = pResolver->m_pJumpStubCache;
+ }
+
+ JumpStubBlockHeader ** ppHead = &(pJumpStubCache->m_pBlocks);
JumpStubBlockHeader * curBlock = *ppHead;
// allocate a new jumpstub from 'curBlock' if it is not fully allocated
@@ -5039,7 +5064,6 @@ PCODE ExecutionManager::getNextJumpStub(MethodDesc* pMD, PCODE target,
goto DONE;
}
}
-
curBlock = curBlock->m_next;
}
@@ -5047,6 +5071,24 @@ PCODE ExecutionManager::getNextJumpStub(MethodDesc* pMD, PCODE target,
if (isLCG)
{
+ // For LCG we request a small block of 4 jumpstubs, because we can not share them
+ // with any other methods and very frequently our method only needs one jump stub.
+ // Using 4 gives a request size of (32 + 4*12) or 80 bytes.
+ // Also note that request sizes are rounded up to a multiples of 16.
+ // The request size is calculated into 'blockSize' in allocJumpStubBlock.
+ // For x64 the value of BACK_TO_BACK_JUMP_ALLOCATE_SIZE is 12 bytes
+ // and the sizeof(JumpStubBlockHeader) is 32.
+ //
+
+ numJumpStubs = 4;
+
+#ifdef _TARGET_AMD64_
+ // Note this these values are not requirements, instead we are
+ // just confirming the values that are mentioned in the comments.
+ _ASSERTE(BACK_TO_BACK_JUMP_ALLOCATE_SIZE == 12);
+ _ASSERTE(sizeof(JumpStubBlockHeader) == 32);
+#endif
+
// Increment counter of LCG jump stub block allocations
m_LCG_JumpStubBlockAllocCount++;
}
@@ -5056,9 +5098,12 @@ PCODE ExecutionManager::getNextJumpStub(MethodDesc* pMD, PCODE target,
m_normal_JumpStubBlockAllocCount++;
}
- // allocJumpStubBlock will allocate from the LoaderCodeHeap for normal methods and HostCodeHeap for LCG methods
- // this can throw an OM exception
- curBlock = ExecutionManager::GetEEJitManager()->allocJumpStubBlock(pMD, DEFAULT_JUMPSTUBS_PER_BLOCK, loAddr, hiAddr, pLoaderAllocator);
+ // allocJumpStubBlock will allocate from the LoaderCodeHeap for normal methods
+ // and will alocate from a HostCodeHeap for LCG methods.
+ //
+ // note that this can throw an OOM exception
+
+ curBlock = ExecutionManager::GetEEJitManager()->allocJumpStubBlock(pMD, numJumpStubs, loAddr, hiAddr, pLoaderAllocator);
jumpStub = (BYTE *) curBlock + sizeof(JumpStubBlockHeader) + ((size_t) curBlock->m_used * BACK_TO_BACK_JUMP_ALLOCATE_SIZE);
@@ -5078,25 +5123,16 @@ DONE:
emitBackToBackJump(jumpStub, (void*) target);
- if (isLCG)
- {
- // always get a new jump stub for LCG method
- // We don't share jump stubs among different LCG methods so that the jump stubs used
- // by every LCG method can be cleaned up individually
- // There is not much benefit to share jump stubs within one LCG method anyway.
- }
- else
- {
- JumpStubCache * pJumpStubCache = (JumpStubCache *)pLoaderAllocator->m_pJumpStubCache;
- _ASSERTE(pJumpStubCache != NULL);
+ // We always add the new jumpstub to the jumpStubCache
+ //
+ _ASSERTE(pJumpStubCache != NULL);
- JumpStubEntry entry;
+ JumpStubEntry entry;
- entry.m_target = target;
- entry.m_jumpStub = (PCODE)jumpStub;
+ entry.m_target = target;
+ entry.m_jumpStub = (PCODE)jumpStub;
- pJumpStubCache->m_Table.Add(entry);
- }
+ pJumpStubCache->m_Table.Add(entry);
curBlock->m_used++; // record that we have used up one more jumpStub in the block
@@ -5556,9 +5592,9 @@ BOOL NativeImageJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection,
g_IBCLogger.LogMethodCodeAccess(*ppMethodDesc);
}
- //Get the function entry that corresponds to the real method desc.
+ // Get the function entry that corresponds to the real method desc.
_ASSERTE((RelativePc >= RUNTIME_FUNCTION__BeginAddress(FunctionEntry)));
-
+
if (pCodeInfo)
{
pCodeInfo->m_relOffset = (DWORD)
diff --git a/src/vm/codeman.h b/src/vm/codeman.h
index 5fbddea875..9d7ed4d62f 100644
--- a/src/vm/codeman.h
+++ b/src/vm/codeman.h
@@ -1490,6 +1490,7 @@ private:
static unsigned m_LCG_JumpStubBlockAllocCount;
static unsigned m_LCG_JumpStubBlockFullCount;
+public:
struct JumpStubCache
{
JumpStubCache()
diff --git a/src/vm/compile.cpp b/src/vm/compile.cpp
index 09925cd219..91615851c7 100644
--- a/src/vm/compile.cpp
+++ b/src/vm/compile.cpp
@@ -3140,8 +3140,8 @@ HRESULT NGenModulePdbWriter::WritePDBData()
SString dllPath = pLoadedLayout->GetPath();
if (!dllPath.EndsWithCaseInsensitive(L".ni.dll") && !dllPath.EndsWithCaseInsensitive(L".ni.exe"))
{
- SString::Iterator fileNameStart = dllPath.Begin();
- dllPath.FindBack(fileNameStart, '\\');
+ SString::Iterator fileNameStart = dllPath.End();
+ dllPath.FindBack(fileNameStart, DIRECTORY_SEPARATOR_STR_W);
SString::Iterator ext = dllPath.End();
dllPath.FindBack(ext, '.');
diff --git a/src/vm/corhost.cpp b/src/vm/corhost.cpp
index 75adbada94..fd27a7a4e7 100644
--- a/src/vm/corhost.cpp
+++ b/src/vm/corhost.cpp
@@ -75,7 +75,7 @@ SVAL_IMPL_INIT(ECustomDumpFlavor, CCLRErrorReportingManager, g_ECustomDumpFlavor
#ifndef DACCESS_COMPILE
extern void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading);
-extern HRESULT STDMETHODCALLTYPE CoInitializeEE(DWORD fFlags);
+extern HRESULT STDAPICALLTYPE CoInitializeEE(DWORD fFlags);
extern void PrintToStdOutA(const char *pszString);
extern void PrintToStdOutW(const WCHAR *pwzString);
extern BOOL g_fEEHostedStartup;
@@ -1201,6 +1201,11 @@ HRESULT GetCLRRuntimeHost(REFIID riid, IUnknown **ppUnk)
STDMETHODIMP CorHost2::UnloadAppDomain(DWORD dwDomainId, BOOL fWaitUntilDone)
{
+ return UnloadAppDomain2(dwDomainId, fWaitUntilDone, nullptr);
+}
+
+STDMETHODIMP CorHost2::UnloadAppDomain2(DWORD dwDomainId, BOOL fWaitUntilDone, int *pLatchedExitCode)
+{
WRAPPER_NO_CONTRACT;
STATIC_CONTRACT_SO_TOLERANT;
@@ -1249,14 +1254,23 @@ STDMETHODIMP CorHost2::UnloadAppDomain(DWORD dwDomainId, BOOL fWaitUntilDone)
}
END_ENTRYPOINT_NOTHROW;
+ if (pLatchedExitCode)
+ {
+ *pLatchedExitCode = GetLatchedExitCode();
+ }
+
return hr;
}
- else
- return CorRuntimeHostBase::UnloadAppDomain(dwDomainId, fWaitUntilDone);
+ return CorRuntimeHostBase::UnloadAppDomain2(dwDomainId, fWaitUntilDone, pLatchedExitCode);
}
-HRESULT CorRuntimeHostBase::UnloadAppDomain(DWORD dwDomainId, BOOL fSync)
+HRESULT CorRuntimeHostBase::UnloadAppDomain(DWORD dwDomainId, BOOL fWaitUntilDone)
+{
+ return UnloadAppDomain2(dwDomainId, fWaitUntilDone, nullptr);
+}
+
+HRESULT CorRuntimeHostBase::UnloadAppDomain2(DWORD dwDomainId, BOOL fWaitUntilDone, int *pLatchedExitCode)
{
CONTRACTL
{
@@ -1282,7 +1296,7 @@ HRESULT CorRuntimeHostBase::UnloadAppDomain(DWORD dwDomainId, BOOL fSync)
//
// However, for a thread that holds the loader lock, unloading the appDomain is
// not a supported scenario. Thus, we should not be ending up in this code
- // path for the FAULT violation.
+ // path for the FAULT violation.
//
// Hence, the CONTRACT_VIOLATION below for overriding the FORBID_FAULT
// for this scope only.
@@ -1292,18 +1306,23 @@ HRESULT CorRuntimeHostBase::UnloadAppDomain(DWORD dwDomainId, BOOL fSync)
)
{
return HOST_E_CLRNOTAVAILABLE;
- }
+ }
}
-
+
BEGIN_ENTRYPOINT_NOTHROW;
// We do not use BEGIN_EXTERNAL_ENTRYPOINT here because
// we do not want to setup Thread. Process may be OOM, and we want Unload
// to work.
- hr = AppDomain::UnloadById(ADID(dwDomainId), fSync);
+ hr = AppDomain::UnloadById(ADID(dwDomainId), fWaitUntilDone);
END_ENTRYPOINT_NOTHROW;
+ if (pLatchedExitCode)
+ {
+ *pLatchedExitCode = GetLatchedExitCode();
+ }
+
return hr;
}
@@ -1404,6 +1423,14 @@ HRESULT CorHost2::QueryInterface(REFIID riid, void **ppUnk)
*ppUnk = static_cast<ICLRRuntimeHost2 *>(this);
}
+ else if (riid == IID_ICLRRuntimeHost4)
+ {
+ ULONG version = 4;
+ if (m_Version == 0)
+ FastInterlockCompareExchange((LONG*)&m_Version, version, 0);
+
+ *ppUnk = static_cast<ICLRRuntimeHost4 *>(this);
+ }
else if (riid == IID_ICLRExecutionManager)
{
ULONG version = 2;
diff --git a/src/vm/dynamicmethod.cpp b/src/vm/dynamicmethod.cpp
index 3eec125247..2a61f97afd 100644
--- a/src/vm/dynamicmethod.cpp
+++ b/src/vm/dynamicmethod.cpp
@@ -917,7 +917,7 @@ void LCGMethodResolver::Reset()
m_DynamicStringLiterals = NULL;
m_recordCodePointer = NULL;
m_UsedIndCellList = NULL;
- m_jumpStubBlock = NULL;
+ m_pJumpStubCache = NULL;
m_next = NULL;
m_Code = NULL;
}
@@ -1035,19 +1035,24 @@ void LCGMethodResolver::Destroy(BOOL fDomainUnload)
m_recordCodePointer = NULL;
}
- JumpStubBlockHeader* current = m_jumpStubBlock;
- JumpStubBlockHeader* next;
- while (current)
+ if (m_pJumpStubCache != NULL)
{
- next = current->m_next;
+ JumpStubBlockHeader* current = m_pJumpStubCache->m_pBlocks;
+ while (current)
+ {
+ JumpStubBlockHeader* next = current->m_next;
+
+ HostCodeHeap *pHeap = current->GetHostCodeHeap();
+ LOG((LF_BCL, LL_INFO1000, "Level3 - Resolver {0x%p} - Release reference to heap {%p, vt(0x%x)} \n", current, pHeap, *(size_t*)pHeap));
+ pHeap->m_pJitManager->FreeCodeMemory(pHeap, current);
- HostCodeHeap *pHeap = current->GetHostCodeHeap();
- LOG((LF_BCL, LL_INFO1000, "Level3 - Resolver {0x%p} - Release reference to heap {%p, vt(0x%x)} \n", current, pHeap, *(size_t*)pHeap));
- pHeap->m_pJitManager->FreeCodeMemory(pHeap, current);
+ current = next;
+ }
+ m_pJumpStubCache->m_pBlocks = NULL;
- current = next;
+ delete m_pJumpStubCache;
+ m_pJumpStubCache = NULL;
}
- m_jumpStubBlock = NULL;
if (m_managedResolver)
{
diff --git a/src/vm/dynamicmethod.h b/src/vm/dynamicmethod.h
index a96200ba4f..f9a92b0af0 100644
--- a/src/vm/dynamicmethod.h
+++ b/src/vm/dynamicmethod.h
@@ -107,6 +107,7 @@ class LCGMethodResolver : public DynamicResolver
friend class ExecutionManager;
friend class EEJitManager;
friend class HostCodeHeap;
+ friend struct ExecutionManager::JumpStubCache;
public:
void Destroy(BOOL fDomainUnload = FALSE);
@@ -162,7 +163,7 @@ private:
ChunkAllocator m_jitTempData;
DynamicStringLiteral* m_DynamicStringLiterals;
IndCellList * m_UsedIndCellList; // list to keep track of all the indirection cells used by the jitted code
- JumpStubBlockHeader* m_jumpStubBlock;
+ ExecutionManager::JumpStubCache * m_pJumpStubCache;
}; // class LCGMethodResolver
//---------------------------------------------------------------------------------------
diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h
index 6ed29b8611..5c3e5f82ba 100644
--- a/src/vm/ecalllist.h
+++ b/src/vm/ecalllist.h
@@ -946,6 +946,7 @@ FCFuncStart(gInteropMarshalFuncs)
FCFuncElement("DestroyStructure", MarshalNative::DestroyStructure)
FCFuncElement("UnsafeAddrOfPinnedArrayElement", MarshalNative::FCUnsafeAddrOfPinnedArrayElement)
FCFuncElement("GetExceptionCode", ExceptionNative::GetExceptionCode)
+ FCFuncElement("GetExceptionPointers", ExceptionNative::GetExceptionPointers)
QCFuncElement("GetHINSTANCE", COMModule::GetHINSTANCE)
FCFuncElement("OffsetOfHelper", MarshalNative::OffsetOfHelper)
diff --git a/src/vm/eetwain.cpp b/src/vm/eetwain.cpp
index 2886daa8f6..4a02be7b82 100644
--- a/src/vm/eetwain.cpp
+++ b/src/vm/eetwain.cpp
@@ -4368,7 +4368,6 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pContext,
}
}
-
bool willContinueExecution = !(flags & ExecutionAborted);
unsigned pushedSize = 0;
@@ -4663,60 +4662,69 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pContext,
/* Process the untracked frame variable table */
- count = info.untrackedCnt;
- int lastStkOffs = 0;
- while (count-- > 0)
+#if defined(WIN64EXCEPTIONS) // funclets
+ // Filters are the only funclet that run during the 1st pass, and must have
+ // both the leaf and the parent frame reported. In order to avoid double
+ // reporting of the untracked variables, do not report them for the filter.
+ if (!pCodeInfo->GetJitManager()->IsFilterFunclet(pCodeInfo))
+#endif // WIN64EXCEPTIONS
{
- int stkOffs = fastDecodeSigned(table);
- stkOffs = lastStkOffs - stkOffs;
- lastStkOffs = stkOffs;
-
- _ASSERTE(0 == ~OFFSET_MASK % sizeof(void*));
-
- lowBits = OFFSET_MASK & stkOffs;
- stkOffs &= ~OFFSET_MASK;
-
- ptrAddr = argBase + stkOffs;
- if (info.doubleAlign && stkOffs >= int(info.stackSize - sizeof(void*))) {
- // We encode the arguments as if they were ESP based variables even though they aren't
- // If this frame would have ben an ESP based frame, This fake frame is one DWORD
- // smaller than the real frame because it did not push EBP but the real frame did.
- // Thus to get the correct EBP relative offset we have to ajust by info.stackSize-sizeof(void*)
- ptrAddr = EBP + (stkOffs-(info.stackSize - sizeof(void*)));
- }
+ count = info.untrackedCnt;
+ int lastStkOffs = 0;
+ while (count-- > 0)
+ {
+ int stkOffs = fastDecodeSigned(table);
+ stkOffs = lastStkOffs - stkOffs;
+ lastStkOffs = stkOffs;
+
+ _ASSERTE(0 == ~OFFSET_MASK % sizeof(void*));
+
+ lowBits = OFFSET_MASK & stkOffs;
+ stkOffs &= ~OFFSET_MASK;
+
+ ptrAddr = argBase + stkOffs;
+ if (info.doubleAlign && stkOffs >= int(info.stackSize - sizeof(void*))) {
+ // We encode the arguments as if they were ESP based variables even though they aren't
+ // If this frame would have ben an ESP based frame, This fake frame is one DWORD
+ // smaller than the real frame because it did not push EBP but the real frame did.
+ // Thus to get the correct EBP relative offset we have to ajust by info.stackSize-sizeof(void*)
+ ptrAddr = EBP + (stkOffs-(info.stackSize - sizeof(void*)));
+ }
#ifdef _DEBUG
- if (dspPtr)
- {
- printf(" Untracked %s%s local at [E",
- (lowBits & pinned_OFFSET_FLAG) ? "pinned " : "",
- (lowBits & byref_OFFSET_FLAG) ? "byref" : "");
+ if (dspPtr)
+ {
+ printf(" Untracked %s%s local at [E",
+ (lowBits & pinned_OFFSET_FLAG) ? "pinned " : "",
+ (lowBits & byref_OFFSET_FLAG) ? "byref" : "");
- int dspOffs = ptrAddr;
- char frameType;
+ int dspOffs = ptrAddr;
+ char frameType;
- if (info.ebpFrame) {
- dspOffs -= EBP;
- frameType = 'B';
- }
- else {
- dspOffs -= ESP;
- frameType = 'S';
+ if (info.ebpFrame) {
+ dspOffs -= EBP;
+ frameType = 'B';
+ }
+ else {
+ dspOffs -= ESP;
+ frameType = 'S';
+ }
+
+ if (dspOffs < 0)
+ printf("%cP-%02XH]: ", frameType, -dspOffs);
+ else
+ printf("%cP+%02XH]: ", frameType, +dspOffs);
}
+#endif
- if (dspOffs < 0)
- printf("%cP-%02XH]: ", frameType, -dspOffs);
- else
- printf("%cP+%02XH]: ", frameType, +dspOffs);
+ _ASSERTE((pinned_OFFSET_FLAG == GC_CALL_PINNED) &&
+ (byref_OFFSET_FLAG == GC_CALL_INTERIOR));
+ pCallBack(hCallBack, (OBJECTREF*)(size_t)ptrAddr, lowBits | CHECK_APP_DOMAIN
+ DAC_ARG(DacSlotLocation(info.ebpFrame ? REGI_EBP : REGI_ESP,
+ info.ebpFrame ? EBP - ptrAddr : ptrAddr - ESP,
+ true)));
}
-#endif
- _ASSERTE((pinned_OFFSET_FLAG == GC_CALL_PINNED) &&
- (byref_OFFSET_FLAG == GC_CALL_INTERIOR));
- pCallBack(hCallBack, (OBJECTREF*)(size_t)ptrAddr, lowBits | CHECK_APP_DOMAIN
- DAC_ARG(DacSlotLocation(info.ebpFrame ? REGI_EBP : REGI_ESP,
- info.ebpFrame ? EBP - ptrAddr : ptrAddr - ESP,
- true)));
}
#if VERIFY_GC_TABLES
diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp
index 31b85bdb0a..7030ef5e91 100644
--- a/src/vm/exceptionhandling.cpp
+++ b/src/vm/exceptionhandling.cpp
@@ -135,7 +135,7 @@ void FixContext(PCONTEXT pContextRecord)
#ifdef _TARGET_X86_
size_t resumeSp = EECodeManager::GetResumeSp(pContextRecord);
- FIXUPREG(ResumeEsp, resumeSp);
+ FIXUPREG(Esp, resumeSp);
#endif // _TARGET_X86_
#undef FIXUPREG
@@ -1011,6 +1011,10 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord
CEHelper::SetupCorruptionSeverityForActiveException((STState == ExceptionTracker::STS_FirstRethrowFrame), (pTracker->GetPreviousExceptionTracker() != NULL),
CEHelper::ShouldTreatActiveExceptionAsNonCorrupting());
}
+
+ // Failfast if exception indicates corrupted process state
+ if (pTracker->GetCorruptionSeverity() == ProcessCorrupting)
+ EEPOLICY_HANDLE_FATAL_ERROR(pExceptionRecord->ExceptionCode);
}
#endif // FEATURE_CORRUPTING_EXCEPTIONS
@@ -1071,9 +1075,11 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord
CLRUnwindStatus status;
+#ifdef USE_PER_FRAME_PINVOKE_INIT
// Refer to comment in ProcessOSExceptionNotification about ICF and codegen difference.
- ARM_ONLY(InlinedCallFrame *pICFSetAsLimitFrame = NULL;)
-
+ InlinedCallFrame *pICFSetAsLimitFrame = NULL;
+#endif // USE_PER_FRAME_PINVOKE_INIT
+
status = pTracker->ProcessOSExceptionNotification(
pExceptionRecord,
pContextRecord,
@@ -1081,7 +1087,11 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord
dwExceptionFlags,
sf,
pThread,
- STState ARM_ARG((PVOID)pICFSetAsLimitFrame));
+ STState
+#ifdef USE_PER_FRAME_PINVOKE_INIT
+ , (PVOID)pICFSetAsLimitFrame
+#endif // USE_PER_FRAME_PINVOKE_INIT
+ );
if (FirstPassComplete == status)
{
@@ -1184,7 +1194,7 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord
CONSISTENCY_CHECK(pLimitFrame > dac_cast<PTR_VOID>(GetSP(pContextRecord)));
-#if defined(_TARGET_ARM_)
+#ifdef USE_PER_FRAME_PINVOKE_INIT
if (pICFSetAsLimitFrame != NULL)
{
_ASSERTE(pICFSetAsLimitFrame == pLimitFrame);
@@ -1196,7 +1206,7 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord
// the next pinvoke callsite does not see the frame as active.
pICFSetAsLimitFrame->Reset();
}
-#endif // defined(_TARGET_ARM_)
+#endif // USE_PER_FRAME_PINVOKE_INIT
pThread->SetFrame(pLimitFrame);
@@ -1653,7 +1663,11 @@ CLRUnwindStatus ExceptionTracker::ProcessOSExceptionNotification(
DWORD dwExceptionFlags,
StackFrame sf,
Thread* pThread,
- StackTraceState STState ARM_ARG(PVOID pICFSetAsLimitFrame))
+ StackTraceState STState
+#ifdef USE_PER_FRAME_PINVOKE_INIT
+ , PVOID pICFSetAsLimitFrame
+#endif // USE_PER_FRAME_PINVOKE_INIT
+)
{
CONTRACTL
{
@@ -1719,10 +1733,10 @@ CLRUnwindStatus ExceptionTracker::ProcessOSExceptionNotification(
this->m_EnclosingClauseInfoForGCReporting.SetEnclosingClauseCallerSP(uCallerSP);
}
-#if defined(_TARGET_ARM_)
+#ifdef USE_PER_FRAME_PINVOKE_INIT
// Refer to detailed comment below.
PTR_Frame pICFForUnwindTarget = NULL;
-#endif // defined(_TARGET_ARM_)
+#endif // USE_PER_FRAME_PINVOKE_INIT
CheckForRudeAbort(pThread, fIsFirstPass);
@@ -1751,7 +1765,7 @@ CLRUnwindStatus ExceptionTracker::ProcessOSExceptionNotification(
while (((UINT_PTR)pFrame) < uCallerSP)
{
-#if defined(_TARGET_ARM_)
+#ifdef USE_PER_FRAME_PINVOKE_INIT
// InlinedCallFrames (ICF) are allocated, initialized and linked to the Frame chain
// by the code generated by the JIT for a method containing a PInvoke.
//
@@ -1956,7 +1970,7 @@ lExit:
if (fTargetUnwind && (status == SecondPassComplete))
{
-#if defined(_TARGET_ARM_)
+#ifdef USE_PER_FRAME_PINVOKE_INIT
// If we have got a ICF to set as the LimitFrame, do that now.
// The Frame chain is still intact and would be updated using
// the LimitFrame (done after the catch handler returns).
@@ -1968,7 +1982,7 @@ lExit:
m_pLimitFrame = pICFForUnwindTarget;
pICFSetAsLimitFrame = (PVOID)pICFForUnwindTarget;
}
-#endif // _TARGET_ARM_
+#endif // USE_PER_FRAME_PINVOKE_INIT
// Since second pass is complete and we have reached
// the frame containing the catch funclet, reset the enclosing
diff --git a/src/vm/exceptionhandling.h b/src/vm/exceptionhandling.h
index 97f1526621..6d1f2b42a8 100644
--- a/src/vm/exceptionhandling.h
+++ b/src/vm/exceptionhandling.h
@@ -10,6 +10,11 @@
#ifdef WIN64EXCEPTIONS
+#if defined(_TARGET_ARM_) || defined(_TARGET_X86_)
+#define USE_PER_FRAME_PINVOKE_INIT
+#endif // _TARGET_ARM_ || _TARGET_X86_
+
+
// This address lies in the NULL pointer partition of the process memory.
// Accessing it will result in AV.
#define INVALID_RESUME_ADDRESS 0x000000000000bad0
@@ -203,7 +208,11 @@ public:
DWORD dwExceptionFlags,
StackFrame sf,
Thread* pThread,
- StackTraceState STState ARM_ARG(PVOID pICFSetAsLimitFrame));
+ StackTraceState STState
+#ifdef USE_PER_FRAME_PINVOKE_INIT
+ , PVOID pICFSetAsLimitFrame
+#endif // USE_PER_FRAME_PINVOKE_INIT
+ );
CLRUnwindStatus ProcessExplicitFrame(
CrawlFrame* pcfThisFrame,
diff --git a/src/vm/exstate.cpp b/src/vm/exstate.cpp
index c598412547..0dc902a1f1 100644
--- a/src/vm/exstate.cpp
+++ b/src/vm/exstate.cpp
@@ -102,7 +102,7 @@ void ThreadExceptionState::FreeAllStackTraces()
}
}
-void ThreadExceptionState::ClearThrowablesForUnload(void* handleStore)
+void ThreadExceptionState::ClearThrowablesForUnload(IGCHandleStore* handleStore)
{
WRAPPER_NO_CONTRACT;
@@ -112,13 +112,11 @@ void ThreadExceptionState::ClearThrowablesForUnload(void* handleStore)
ExInfo* pNode = &m_currentExInfo;
#endif // WIN64EXCEPTIONS
- IGCHandleTable *pHandleTable = GCHandleTableUtilities::GetGCHandleTable();
-
for ( ;
pNode != NULL;
pNode = pNode->m_pPrevNestedInfo)
{
- if (pHandleTable->ContainsHandle(handleStore, pNode->m_hThrowable))
+ if (handleStore->ContainsHandle(pNode->m_hThrowable))
{
pNode->DestroyExceptionHandle();
}
diff --git a/src/vm/exstate.h b/src/vm/exstate.h
index 104c76c77b..ba2ce2dba5 100644
--- a/src/vm/exstate.h
+++ b/src/vm/exstate.h
@@ -56,7 +56,7 @@ class ThreadExceptionState
public:
void FreeAllStackTraces();
- void ClearThrowablesForUnload(void* handleStore);
+ void ClearThrowablesForUnload(IGCHandleStore* handleStore);
#ifdef _DEBUG
typedef enum
diff --git a/src/vm/frames.h b/src/vm/frames.h
index 747cbd6d68..681e566e2b 100644
--- a/src/vm/frames.h
+++ b/src/vm/frames.h
@@ -2330,11 +2330,7 @@ public:
virtual void GcScanRoots(promote_func *fn, ScanContext* sc);
#ifdef _TARGET_X86_
- virtual void UpdateRegDisplay(const PREGDISPLAY pRD)
- {
- WRAPPER_NO_CONTRACT;
- UpdateRegDisplayHelper(pRD, 0);
- }
+ virtual void UpdateRegDisplay(const PREGDISPLAY pRD);
#endif
virtual ETransitionType GetTransitionType()
diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp
index 54c7991ee9..63c4ffea10 100644
--- a/src/vm/gcenv.ee.cpp
+++ b/src/vm/gcenv.ee.cpp
@@ -1275,9 +1275,17 @@ void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args)
// We need to make sure that other threads executing checked write barriers
// will see the g_card_table update before g_lowest/highest_address updates.
// Otherwise, the checked write barrier may AV accessing the old card table
- // with address that it does not cover. Write barriers access card table
- // without memory barriers for performance reasons, so we need to flush
- // the store buffers here.
+ // with address that it does not cover.
+ //
+ // Even x86's total store ordering is insufficient here because threads reading
+ // g_card_table do so via the instruction cache, whereas g_lowest/highest_address
+ // are read via the data cache.
+ //
+ // The g_card_table update is covered by section 8.1.3 of the Intel Software
+ // Development Manual, Volume 3A (System Programming Guide, Part 1), about
+ // "cross-modifying code": We need all _executing_ threads to invalidate
+ // their instruction cache, which FlushProcessWriteBuffers achieves by sending
+ // an IPI (inter-process interrupt).
FlushProcessWriteBuffers();
g_lowest_address = args->lowest_address;
diff --git a/src/vm/gcenv.os.cpp b/src/vm/gcenv.os.cpp
index 6c08558e03..77be88c96d 100644
--- a/src/vm/gcenv.os.cpp
+++ b/src/vm/gcenv.os.cpp
@@ -329,11 +329,7 @@ bool GCToOSInterface::GetCurrentProcessAffinityMask(uintptr_t* processMask, uint
{
LIMITED_METHOD_CONTRACT;
-#ifndef FEATURE_PAL
return !!::GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)processMask, (PDWORD_PTR)systemMask);
-#else
- return false;
-#endif
}
// Get number of processors assigned to the current process
@@ -700,3 +696,208 @@ void CLRCriticalSection::Leave()
WRAPPER_NO_CONTRACT;
UnsafeLeaveCriticalSection(&m_cs);
}
+
+// An implementatino of GCEvent that delegates to
+// a CLREvent, which in turn delegates to the PAL. This event
+// is also host-aware.
+class GCEvent::Impl
+{
+private:
+ CLREvent m_event;
+
+public:
+ Impl() = default;
+
+ bool IsValid()
+ {
+ WRAPPER_NO_CONTRACT;
+
+ return !!m_event.IsValid();
+ }
+
+ void CloseEvent()
+ {
+ WRAPPER_NO_CONTRACT;
+
+ assert(m_event.IsValid());
+ m_event.CloseEvent();
+ }
+
+ void Set()
+ {
+ WRAPPER_NO_CONTRACT;
+
+ assert(m_event.IsValid());
+ m_event.Set();
+ }
+
+ void Reset()
+ {
+ WRAPPER_NO_CONTRACT;
+
+ assert(m_event.IsValid());
+ m_event.Reset();
+ }
+
+ uint32_t Wait(uint32_t timeout, bool alertable)
+ {
+ WRAPPER_NO_CONTRACT;
+
+ assert(m_event.IsValid());
+ return m_event.Wait(timeout, alertable);
+ }
+
+ bool CreateAutoEvent(bool initialState)
+ {
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ } CONTRACTL_END;
+
+ return !!m_event.CreateAutoEventNoThrow(initialState);
+ }
+
+ bool CreateManualEvent(bool initialState)
+ {
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ } CONTRACTL_END;
+
+ return !!m_event.CreateManualEventNoThrow(initialState);
+ }
+
+ bool CreateOSAutoEvent(bool initialState)
+ {
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ } CONTRACTL_END;
+
+ return !!m_event.CreateOSAutoEventNoThrow(initialState);
+ }
+
+ bool CreateOSManualEvent(bool initialState)
+ {
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ } CONTRACTL_END;
+
+ return !!m_event.CreateOSManualEventNoThrow(initialState);
+ }
+};
+
+GCEvent::GCEvent()
+ : m_impl(nullptr)
+{
+}
+
+void GCEvent::CloseEvent()
+{
+ WRAPPER_NO_CONTRACT;
+
+ assert(m_impl != nullptr);
+ m_impl->CloseEvent();
+}
+
+void GCEvent::Set()
+{
+ WRAPPER_NO_CONTRACT;
+
+ assert(m_impl != nullptr);
+ m_impl->Set();
+}
+
+void GCEvent::Reset()
+{
+ WRAPPER_NO_CONTRACT;
+
+ assert(m_impl != nullptr);
+ m_impl->Reset();
+}
+
+uint32_t GCEvent::Wait(uint32_t timeout, bool alertable)
+{
+ WRAPPER_NO_CONTRACT;
+
+ assert(m_impl != nullptr);
+ return m_impl->Wait(timeout, alertable);
+}
+
+bool GCEvent::CreateManualEventNoThrow(bool initialState)
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ } CONTRACTL_END;
+
+ assert(m_impl == nullptr);
+ NewHolder<GCEvent::Impl> event = new (nothrow) GCEvent::Impl();
+ if (!event)
+ {
+ return false;
+ }
+
+ event->CreateManualEvent(initialState);
+ m_impl = event.Extract();
+ return true;
+}
+
+bool GCEvent::CreateAutoEventNoThrow(bool initialState)
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ } CONTRACTL_END;
+
+ assert(m_impl == nullptr);
+ NewHolder<GCEvent::Impl> event = new (nothrow) GCEvent::Impl();
+ if (!event)
+ {
+ return false;
+ }
+
+ event->CreateAutoEvent(initialState);
+ m_impl = event.Extract();
+ return IsValid();
+}
+
+bool GCEvent::CreateOSAutoEventNoThrow(bool initialState)
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ } CONTRACTL_END;
+
+ assert(m_impl == nullptr);
+ NewHolder<GCEvent::Impl> event = new (nothrow) GCEvent::Impl();
+ if (!event)
+ {
+ return false;
+ }
+
+ event->CreateOSAutoEvent(initialState);
+ m_impl = event.Extract();
+ return IsValid();
+}
+
+bool GCEvent::CreateOSManualEventNoThrow(bool initialState)
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ } CONTRACTL_END;
+
+ assert(m_impl == nullptr);
+ NewHolder<GCEvent::Impl> event = new (nothrow) GCEvent::Impl();
+ if (!event)
+ {
+ return false;
+ }
+
+ event->CreateOSManualEvent(initialState);
+ m_impl = event.Extract();
+ return IsValid();
+}
+
diff --git a/src/vm/gchandletableutilities.h b/src/vm/gchandletableutilities.h
deleted file mode 100644
index 6e32add8ac..0000000000
--- a/src/vm/gchandletableutilities.h
+++ /dev/null
@@ -1,354 +0,0 @@
-// 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.
-
-#ifndef _GCHANDLETABLEUTILITIES_H_
-#define _GCHANDLETABLEUTILITIES_H_
-
-#include "gcinterface.h"
-
-#ifdef FEATURE_COMINTEROP
-#include <weakreference.h>
-#endif
-
-extern "C" IGCHandleTable* g_pGCHandleTable;
-
-class GCHandleTableUtilities
-{
-public:
- // Retrieves the GC handle table.
- static IGCHandleTable* GetGCHandleTable()
- {
- LIMITED_METHOD_CONTRACT;
-
- assert(g_pGCHandleTable != nullptr);
- return g_pGCHandleTable;
- }
-
-private:
- // This class should never be instantiated.
- GCHandleTableUtilities() = delete;
-};
-
-void ValidateHandleAndAppDomain(OBJECTHANDLE handle);
-
-// Given a handle, returns an OBJECTREF for the object it refers to.
-inline OBJECTREF ObjectFromHandle(OBJECTHANDLE handle)
-{
- _ASSERTE(handle);
-
-#ifdef _DEBUG_IMPL
- ValidateHandleAndAppDomain(handle);
-#endif // _DEBUG_IMPL
-
- // Wrap the raw OBJECTREF and return it
- return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle));
-}
-
-// Quick inline check for whether a handle is null
-inline BOOL IsHandleNullUnchecked(OBJECTHANDLE handle)
-{
- LIMITED_METHOD_CONTRACT;
-
- return (handle == NULL || (*(_UNCHECKED_OBJECTREF *)handle) == NULL);
-}
-
-inline BOOL ObjectHandleIsNull(OBJECTHANDLE handle)
-{
- LIMITED_METHOD_CONTRACT;
-
- return *(Object **)handle == NULL;
-}
-
-#ifndef DACCESS_COMPILE
-
-// Handle creation convenience functions
-
-inline OBJECTHANDLE CreateHandle(void* table, OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_DEFAULT);
-}
-
-inline OBJECTHANDLE CreateWeakHandle(void* table, OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_WEAK_DEFAULT);
-}
-
-inline OBJECTHANDLE CreateShortWeakHandle(void* table, OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_WEAK_SHORT);
-}
-
-inline OBJECTHANDLE CreateLongWeakHandle(void* table, OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_WEAK_LONG);
-}
-
-inline OBJECTHANDLE CreateStrongHandle(void* table, OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_STRONG);
-}
-
-inline OBJECTHANDLE CreatePinningHandle(void* table, OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_PINNED);
-}
-
-inline OBJECTHANDLE CreateAsyncPinningHandle(void* table, OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_ASYNCPINNED);
-}
-
-inline OBJECTHANDLE CreateRefcountedHandle(void* table, OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_REFCOUNTED);
-}
-
-inline OBJECTHANDLE CreateSizedRefHandle(void* table, OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_SIZEDREF);
-}
-
-inline OBJECTHANDLE CreateSizedRefHandle(void* table, OBJECTREF object, int heapToAffinitizeTo)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_SIZEDREF, heapToAffinitizeTo);
-}
-
-// Global handle creation convenience functions
-
-inline OBJECTHANDLE CreateGlobalHandle(OBJECTREF object)
-{
- CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL);
- return GCHandleTableUtilities::GetGCHandleTable()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_DEFAULT);
-}
-
-inline OBJECTHANDLE CreateGlobalWeakHandle(OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_DEFAULT);
-}
-
-inline OBJECTHANDLE CreateGlobalShortWeakHandle(OBJECTREF object)
-{
- CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL);
- return GCHandleTableUtilities::GetGCHandleTable()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_SHORT);
-}
-
-inline OBJECTHANDLE CreateGlobalLongWeakHandle(OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_LONG);
-}
-
-inline OBJECTHANDLE CreateGlobalStrongHandle(OBJECTREF object)
-{
- CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL);
- return GCHandleTableUtilities::GetGCHandleTable()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_STRONG);
-}
-
-inline OBJECTHANDLE CreateGlobalPinningHandle(OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_PINNED);
-}
-
-inline OBJECTHANDLE CreateGlobalRefcountedHandle(OBJECTREF object)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_REFCOUNTED);
-}
-
-// Special handle creation convenience functions
-
-#ifdef FEATURE_COMINTEROP
-inline OBJECTHANDLE CreateWinRTWeakHandle(void* table, OBJECTREF object, IWeakReference* pWinRTWeakReference)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleWithExtraInfo(table,
- OBJECTREFToObject(object),
- HNDTYPE_WEAK_WINRT,
- (void*)pWinRTWeakReference);
-}
-#endif // FEATURE_COMINTEROP
-
-// Creates a variable-strength handle
-inline OBJECTHANDLE CreateVariableHandle(void* table, OBJECTREF object, uint32_t type)
-{
- return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleWithExtraInfo(table,
- OBJECTREFToObject(object),
- HNDTYPE_VARIABLE,
- (void*)((uintptr_t)type));
-}
-
-// Handle destruction convenience functions
-
-inline void DestroyHandle(OBJECTHANDLE handle)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- CAN_TAKE_LOCK;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_DEFAULT);
-}
-
-inline void DestroyWeakHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_WEAK_DEFAULT);
-}
-
-inline void DestroyShortWeakHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_WEAK_SHORT);
-}
-
-inline void DestroyLongWeakHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_WEAK_LONG);
-}
-
-inline void DestroyStrongHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_STRONG);
-}
-
-inline void DestroyPinningHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_PINNED);
-}
-
-inline void DestroyAsyncPinningHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_ASYNCPINNED);
-}
-
-inline void DestroyRefcountedHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_REFCOUNTED);
-}
-
-inline void DestroyDependentHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_DEPENDENT);
-}
-
-inline void DestroyVariableHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_VARIABLE);
-}
-
-inline void DestroyGlobalHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_DEFAULT);
-}
-
-inline void DestroyGlobalWeakHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_WEAK_DEFAULT);
-}
-
-inline void DestroyGlobalShortWeakHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_WEAK_SHORT);
-}
-
-inline void DestroyGlobalLongWeakHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_WEAK_LONG);
-}
-
-inline void DestroyGlobalStrongHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_STRONG);
-}
-
-inline void DestroyGlobalPinningHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_PINNED);
-}
-
-inline void DestroyGlobalRefcountedHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_REFCOUNTED);
-}
-
-inline void DestroyTypedHandle(OBJECTHANDLE handle)
-{
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfUnknownType(handle);
-}
-
-#ifdef FEATURE_COMINTEROP
-inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- CAN_TAKE_LOCK;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- // Release the WinRT weak reference if we have one. We're assuming that this will not reenter the
- // runtime, since if we are pointing at a managed object, we should not be using HNDTYPE_WEAK_WINRT
- // but rather HNDTYPE_WEAK_SHORT or HNDTYPE_WEAK_LONG.
- void* pExtraInfo = GCHandleTableUtilities::GetGCHandleTable()->GetExtraInfoFromHandle(handle);
- IWeakReference* pWinRTWeakReference = reinterpret_cast<IWeakReference*>(pExtraInfo);
- if (pWinRTWeakReference != nullptr)
- {
- pWinRTWeakReference->Release();
- }
-
- GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleOfType(handle, HNDTYPE_WEAK_WINRT);
-}
-#endif
-
-// Handle holders/wrappers
-
-#ifndef FEATURE_REDHAWK
-typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyHandle> OHWrapper;
-typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyPinningHandle, NULL> PinningHandleHolder;
-typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyAsyncPinningHandle, NULL> AsyncPinningHandleHolder;
-typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyRefcountedHandle> RefCountedOHWrapper;
-
-typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyLongWeakHandle> LongWeakHandleHolder;
-typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalStrongHandle> GlobalStrongHandleHolder;
-typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalShortWeakHandle> GlobalShortWeakHandleHolder;
-
-class RCOBJECTHANDLEHolder : public RefCountedOHWrapper
-{
-public:
- FORCEINLINE RCOBJECTHANDLEHolder(OBJECTHANDLE p = NULL) : RefCountedOHWrapper(p)
- {
- LIMITED_METHOD_CONTRACT;
- }
- FORCEINLINE void operator=(OBJECTHANDLE p)
- {
- WRAPPER_NO_CONTRACT;
-
- RefCountedOHWrapper::operator=(p);
- }
-};
-
-class OBJECTHANDLEHolder : public OHWrapper
-{
-public:
- FORCEINLINE OBJECTHANDLEHolder(OBJECTHANDLE p = NULL) : OHWrapper(p)
- {
- LIMITED_METHOD_CONTRACT;
- }
- FORCEINLINE void operator=(OBJECTHANDLE p)
- {
- WRAPPER_NO_CONTRACT;
-
- OHWrapper::operator=(p);
- }
-};
-
-#endif // !FEATURE_REDHAWK
-
-#endif // !DACCESS_COMPILE
-
-#endif // _GCHANDLETABLEUTILITIES_H_
-
diff --git a/src/vm/gchandleutilities.h b/src/vm/gchandleutilities.h
new file mode 100644
index 0000000000..665c1da453
--- /dev/null
+++ b/src/vm/gchandleutilities.h
@@ -0,0 +1,495 @@
+// 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.
+
+#ifndef _GCHANDLEUTILITIES_H_
+#define _GCHANDLEUTILITIES_H_
+
+#include "gcinterface.h"
+
+#ifdef FEATURE_COMINTEROP
+#include <weakreference.h>
+#endif
+
+extern "C" IGCHandleManager* g_pGCHandleManager;
+
+class GCHandleUtilities
+{
+public:
+ // Retrieves the GC handle table.
+ static IGCHandleManager* GetGCHandleManager()
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ assert(g_pGCHandleManager != nullptr);
+ return g_pGCHandleManager;
+ }
+
+private:
+ // This class should never be instantiated.
+ GCHandleUtilities() = delete;
+};
+
+void ValidateObjectAndAppDomain(OBJECTREF objRef, ADIndex appDomainIndex);
+void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef);
+
+// Given a handle, returns an OBJECTREF for the object it refers to.
+inline OBJECTREF ObjectFromHandle(OBJECTHANDLE handle)
+{
+ _ASSERTE(handle);
+
+#ifdef _DEBUG_IMPL
+ DWORD context = (DWORD)GCHandleUtilities::GetGCHandleManager()->GetHandleContext(handle);
+ OBJECTREF objRef = ObjectToOBJECTREF(*(Object**)handle);
+
+ ValidateObjectAndAppDomain(objRef, ADIndex(context));
+#endif // _DEBUG_IMPL
+
+ // Wrap the raw OBJECTREF and return it
+ return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle));
+}
+
+// Quick inline check for whether a handle is null
+inline BOOL IsHandleNullUnchecked(OBJECTHANDLE handle)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return (handle == NULL || (*(_UNCHECKED_OBJECTREF *)handle) == NULL);
+}
+
+inline BOOL ObjectHandleIsNull(OBJECTHANDLE handle)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return *(Object **)handle == NULL;
+}
+
+#ifndef DACCESS_COMPILE
+
+// Handle creation convenience functions
+
+inline OBJECTHANDLE CreateHandle(IGCHandleStore* store, OBJECTREF object)
+{
+ OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_DEFAULT);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateWeakHandle(IGCHandleStore* store, OBJECTREF object)
+{
+ OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_DEFAULT);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateShortWeakHandle(IGCHandleStore* store, OBJECTREF object)
+{
+ OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_SHORT);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateLongWeakHandle(IGCHandleStore* store, OBJECTREF object)
+{
+ OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_LONG);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateStrongHandle(IGCHandleStore* store, OBJECTREF object)
+{
+ OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_STRONG);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreatePinningHandle(IGCHandleStore* store, OBJECTREF object)
+{
+ OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_PINNED);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateAsyncPinningHandle(IGCHandleStore* store, OBJECTREF object)
+{
+ OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_ASYNCPINNED);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateRefcountedHandle(IGCHandleStore* store, OBJECTREF object)
+{
+ OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_REFCOUNTED);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateSizedRefHandle(IGCHandleStore* store, OBJECTREF object)
+{
+ OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_SIZEDREF);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateSizedRefHandle(IGCHandleStore* store, OBJECTREF object, int heapToAffinitizeTo)
+{
+ OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_SIZEDREF, heapToAffinitizeTo);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+// Global handle creation convenience functions
+
+inline OBJECTHANDLE CreateGlobalHandle(OBJECTREF object)
+{
+ CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL);
+ OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_DEFAULT);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateGlobalWeakHandle(OBJECTREF object)
+{
+ OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_DEFAULT);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateGlobalShortWeakHandle(OBJECTREF object)
+{
+ CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL);
+ OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_SHORT);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateGlobalLongWeakHandle(OBJECTREF object)
+{
+ OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_LONG);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateGlobalStrongHandle(OBJECTREF object)
+{
+ CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL);
+ OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_STRONG);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateGlobalPinningHandle(OBJECTREF object)
+{
+ OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_PINNED);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+inline OBJECTHANDLE CreateGlobalRefcountedHandle(OBJECTREF object)
+{
+ OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_REFCOUNTED);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+// Special handle creation convenience functions
+
+#ifdef FEATURE_COMINTEROP
+inline OBJECTHANDLE CreateWinRTWeakHandle(IGCHandleStore* store, OBJECTREF object, IWeakReference* pWinRTWeakReference)
+{
+ OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_WEAK_WINRT, (void*)pWinRTWeakReference);
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+#endif // FEATURE_COMINTEROP
+
+// Creates a variable-strength handle
+inline OBJECTHANDLE CreateVariableHandle(IGCHandleStore* store, OBJECTREF object, uint32_t type)
+{
+ OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_VARIABLE, (void*)((uintptr_t)type));
+ if (!hnd)
+ {
+ COMPlusThrowOM();
+ }
+
+ return hnd;
+}
+
+// Handle object manipulation convenience functions
+
+inline void StoreObjectInHandle(OBJECTHANDLE handle, OBJECTREF object)
+{
+ ValidateHandleAssignment(handle, object);
+
+ GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandle(handle, OBJECTREFToObject(object));
+}
+
+inline bool StoreFirstObjectInHandle(OBJECTHANDLE handle, OBJECTREF object)
+{
+ ValidateHandleAssignment(handle, object);
+
+ return GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandleIfNull(handle, OBJECTREFToObject(object));
+}
+
+inline void* InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE handle, OBJECTREF object, OBJECTREF comparandObject)
+{
+ ValidateHandleAssignment(handle, object);
+
+ return GCHandleUtilities::GetGCHandleManager()->InterlockedCompareExchangeObjectInHandle(handle, OBJECTREFToObject(object), OBJECTREFToObject(comparandObject));
+}
+
+inline void ResetOBJECTHANDLE(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandle(handle, NULL);
+}
+
+// Handle destruction convenience functions
+
+inline void DestroyHandle(OBJECTHANDLE handle)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ CAN_TAKE_LOCK;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_DEFAULT);
+}
+
+inline void DestroyWeakHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_DEFAULT);
+}
+
+inline void DestroyShortWeakHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_SHORT);
+}
+
+inline void DestroyLongWeakHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_LONG);
+}
+
+inline void DestroyStrongHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_STRONG);
+}
+
+inline void DestroyPinningHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_PINNED);
+}
+
+inline void DestroyAsyncPinningHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_ASYNCPINNED);
+}
+
+inline void DestroyRefcountedHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_REFCOUNTED);
+}
+
+inline void DestroyDependentHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_DEPENDENT);
+}
+
+inline void DestroyVariableHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_VARIABLE);
+}
+
+inline void DestroyGlobalHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_DEFAULT);
+}
+
+inline void DestroyGlobalWeakHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_DEFAULT);
+}
+
+inline void DestroyGlobalShortWeakHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_SHORT);
+}
+
+inline void DestroyGlobalLongWeakHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_LONG);
+}
+
+inline void DestroyGlobalStrongHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_STRONG);
+}
+
+inline void DestroyGlobalPinningHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_PINNED);
+}
+
+inline void DestroyGlobalRefcountedHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_REFCOUNTED);
+}
+
+inline void DestroyTypedHandle(OBJECTHANDLE handle)
+{
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfUnknownType(handle);
+}
+
+#ifdef FEATURE_COMINTEROP
+inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ CAN_TAKE_LOCK;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+
+ // Release the WinRT weak reference if we have one. We're assuming that this will not reenter the
+ // runtime, since if we are pointing at a managed object, we should not be using HNDTYPE_WEAK_WINRT
+ // but rather HNDTYPE_WEAK_SHORT or HNDTYPE_WEAK_LONG.
+ void* pExtraInfo = GCHandleUtilities::GetGCHandleManager()->GetExtraInfoFromHandle(handle);
+ IWeakReference* pWinRTWeakReference = reinterpret_cast<IWeakReference*>(pExtraInfo);
+ if (pWinRTWeakReference != nullptr)
+ {
+ pWinRTWeakReference->Release();
+ }
+
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_WINRT);
+}
+#endif
+
+// Handle holders/wrappers
+
+#ifndef FEATURE_REDHAWK
+typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyHandle> OHWrapper;
+typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyPinningHandle, NULL> PinningHandleHolder;
+typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyAsyncPinningHandle, NULL> AsyncPinningHandleHolder;
+typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyRefcountedHandle> RefCountedOHWrapper;
+
+typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyLongWeakHandle> LongWeakHandleHolder;
+typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalStrongHandle> GlobalStrongHandleHolder;
+typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalShortWeakHandle> GlobalShortWeakHandleHolder;
+typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, ResetOBJECTHANDLE> ObjectInHandleHolder;
+
+class RCOBJECTHANDLEHolder : public RefCountedOHWrapper
+{
+public:
+ FORCEINLINE RCOBJECTHANDLEHolder(OBJECTHANDLE p = NULL) : RefCountedOHWrapper(p)
+ {
+ LIMITED_METHOD_CONTRACT;
+ }
+ FORCEINLINE void operator=(OBJECTHANDLE p)
+ {
+ WRAPPER_NO_CONTRACT;
+
+ RefCountedOHWrapper::operator=(p);
+ }
+};
+
+class OBJECTHANDLEHolder : public OHWrapper
+{
+public:
+ FORCEINLINE OBJECTHANDLEHolder(OBJECTHANDLE p = NULL) : OHWrapper(p)
+ {
+ LIMITED_METHOD_CONTRACT;
+ }
+ FORCEINLINE void operator=(OBJECTHANDLE p)
+ {
+ WRAPPER_NO_CONTRACT;
+
+ OHWrapper::operator=(p);
+ }
+};
+
+#endif // !FEATURE_REDHAWK
+
+#endif // !DACCESS_COMPILE
+
+#endif // _GCHANDLEUTILITIES_H_
+
diff --git a/src/vm/gcheaputilities.cpp b/src/vm/gcheaputilities.cpp
index e15558335e..cd7afede70 100644
--- a/src/vm/gcheaputilities.cpp
+++ b/src/vm/gcheaputilities.cpp
@@ -25,7 +25,7 @@ uint32_t* g_card_bundle_table = nullptr;
// This is the global GC heap, maintained by the VM.
GPTR_IMPL(IGCHeap, g_pGCHeap);
-IGCHandleTable* g_pGCHandleTable = nullptr;
+IGCHandleManager* g_pGCHandleManager = nullptr;
GcDacVars g_gc_dac_vars;
GPTR_IMPL(GcDacVars, g_gcDacGlobals);
@@ -40,17 +40,12 @@ bool g_sw_ww_enabled_for_gc_heap = false;
gc_alloc_context g_global_alloc_context = {};
// Debug-only validation for handle.
-void ValidateHandleAndAppDomain(OBJECTHANDLE handle)
+
+void ValidateObjectAndAppDomain(OBJECTREF objRef, ADIndex appDomainIndex)
{
#ifdef _DEBUG_IMPL
- OBJECTREF objRef = ObjectToOBJECTREF(*(Object**)handle);
VALIDATEOBJECTREF(objRef);
- IGCHandleTable *pHandleTable = GCHandleTableUtilities::GetGCHandleTable();
-
- DWORD context = (DWORD)pHandleTable->GetHandleContext(handle);
-
- ADIndex appDomainIndex = ADIndex(context);
AppDomain *domain = SystemDomain::GetAppDomainAtIndex(appDomainIndex);
// Access to a handle in an unloaded domain is not allowed
@@ -72,3 +67,25 @@ void ValidateHandleAndAppDomain(OBJECTHANDLE handle)
#endif // CHECK_APP_DOMAIN_LEAKS
#endif // _DEBUG_IMPL
}
+
+void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef)
+{
+#ifdef _DEBUG_IMPL
+ _ASSERTE(handle);
+
+#ifdef DEBUG_DestroyedHandleValue
+ // Verify that we are not trying to access a freed handle.
+ _ASSERTE("Attempt to access destroyed handle." && *(_UNCHECKED_OBJECTREF*)handle != DEBUG_DestroyedHandleValue);
+#endif
+
+ ADIndex appDomainIndex = HndGetHandleADIndex(handle);
+
+ AppDomain *unloadingDomain = SystemDomain::AppDomainBeingUnloaded();
+ if (unloadingDomain && unloadingDomain->GetIndex() == appDomainIndex && unloadingDomain->NoAccessToHandleTable())
+ {
+ _ASSERTE (!"Access to a handle in unloaded domain is not allowed");
+ }
+
+ ValidateObjectAndAppDomain(objRef, appDomainIndex);
+#endif // _DEBUG_IMPL
+} \ No newline at end of file
diff --git a/src/vm/gdbjit.cpp b/src/vm/gdbjit.cpp
index fe8e211e5b..ace6b76d97 100644
--- a/src/vm/gdbjit.cpp
+++ b/src/vm/gdbjit.cpp
@@ -1095,7 +1095,7 @@ ClassTypeInfo::ClassTypeInfo(TypeHandle typeHandle, int num_members, FunctionMem
{
case ELEMENT_TYPE_VALUETYPE:
case ELEMENT_TYPE_CLASS:
- m_type_size = pMT->IsValueType() ? typeHandle.GetSize() : typeHandle.AsMethodTable()->GetClass()->GetSize();
+ m_type_size = pMT->IsValueType() ? typeHandle.GetSize() : typeHandle.AsMethodTable()->GetBaseSize();
break;
case ELEMENT_TYPE_ARRAY:
case ELEMENT_TYPE_SZARRAY:
diff --git a/src/vm/hosting.cpp b/src/vm/hosting.cpp
index 620b9d6800..d47bc28238 100644
--- a/src/vm/hosting.cpp
+++ b/src/vm/hosting.cpp
@@ -444,6 +444,11 @@ LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
WRAPPER_NO_CONTRACT;
STATIC_CONTRACT_SO_TOLERANT;
+#ifdef _DEBUG
+ // Check whether (indispensable) implicit casting in ClrAllocInProcessHeapBootstrap is safe.
+ static FastAllocInProcessHeapFunc pFunc = EEHeapAllocInProcessHeap;
+#endif
+
static HANDLE ProcessHeap = NULL;
// We need to guarentee a very small stack consumption in allocating. And we can't allow
@@ -506,6 +511,11 @@ BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem)
}
CONTRACTL_END;
+#ifdef _DEBUG
+ // Check whether (indispensable) implicit casting in ClrFreeInProcessHeapBootstrap is safe.
+ static FastFreeInProcessHeapFunc pFunc = EEHeapFreeInProcessHeap;
+#endif
+
// Take a look at comment in EEHeapFree and EEHeapAllocInProcessHeap, obviously someone
// needs to take a little time to think more about this code.
//CONTRACT_VIOLATION(SOToleranceViolation);
diff --git a/src/vm/i386/asmhelpers.S b/src/vm/i386/asmhelpers.S
index 98525aceee..75f4a26a80 100644
--- a/src/vm/i386/asmhelpers.S
+++ b/src/vm/i386/asmhelpers.S
@@ -439,6 +439,7 @@ NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler
sub esp,12
push esp
+ CHECK_STACK_ALIGNMENT
call C_FUNC(OnHijackWorker)
// unused space for floating point state
@@ -474,6 +475,7 @@ NESTED_ENTRY OnHijackFPTripThread, _TEXT, NoHandler
fstp QWORD PTR [esp]
push esp
+ CHECK_STACK_ALIGNMENT
call C_FUNC(OnHijackWorker)
// restore top of the floating point stack
@@ -752,8 +754,10 @@ NESTED_ENTRY StubDispatchFixupStub, _TEXT, NoHandler
mov esi, esp
- push 0
- push 0
+.att_syntax
+ pushl $0
+ pushl $0
+.intel_syntax noprefix
push eax // siteAddrForRegisterIndirect (for tailcalls)
push esi // pTransitionBlock
@@ -784,8 +788,10 @@ NESTED_ENTRY ExternalMethodFixupStub, _TEXT_ NoHandler
// EAX is return address into CORCOMPILE_EXTERNAL_METHOD_THUNK. Subtract 5 to get start address.
sub eax, 5
- push 0
- push 0
+.att_syntax
+ pushl $0
+ pushl $0
+.intel_syntax noprefix
push eax
@@ -811,6 +817,14 @@ PATCH_LABEL ExternalMethodFixupPatchLabel
NESTED_END ExternalMethodFixupStub, _TEXT
#ifdef FEATURE_READYTORUN
+NESTED_ENTRY DynamicHelperArgsStub, _TEXT, NoHandler
+ .cfi_def_cfa_offset 16
+ CHECK_STACK_ALIGNMENT
+ call eax
+ add esp, 12
+ ret
+NESTED_END DynamicHelperArgsStub, _TEXT
+
// ==========================================================================
NESTED_ENTRY DelayLoad_MethodCall, _TEXT, NoHandler
STUB_PROLOG_2_HIDDEN_ARGS
@@ -967,6 +981,7 @@ NESTED_ENTRY DelayLoad_Helper\suffix, _TEXT, NoHandler
push eax // indirection cell address.
push esi // pTransitionBlock
+ CHECK_STACK_ALIGNMENT
call C_FUNC(DynamicHelperWorker)
test eax,eax
jnz LOCAL_LABEL(TailCallDelayLoad_Helper\suffix)
diff --git a/src/vm/i386/cgenx86.cpp b/src/vm/i386/cgenx86.cpp
index 4c83265ff4..14909b93e5 100644
--- a/src/vm/i386/cgenx86.cpp
+++ b/src/vm/i386/cgenx86.cpp
@@ -331,7 +331,6 @@ void TransitionFrame::UpdateRegDisplayHelper(const PREGDISPLAY pRD, UINT cbStack
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);;
pRD->pCurrentContext->Esp = CallerSP;
- pRD->pCurrentContext->ResumeEsp = CallerSP + cbStackPop;
UpdateRegDisplayFromCalleeSavedRegisters(pRD, regs);
ClearRegDisplayArgumentAndScratchRegisters(pRD);
@@ -384,7 +383,7 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
#endif // DACCESS_COMPILE
pRD->pCurrentContext->Eip = pRD->ControlPC = m_MachState.GetRetAddr();
- pRD->pCurrentContext->Esp = pRD->pCurrentContext->ResumeEsp = pRD->SP = (DWORD) m_MachState.esp();
+ pRD->pCurrentContext->Esp = pRD->SP = (DWORD) m_MachState.esp();
#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContext->regname = *((DWORD*) m_MachState.p##regname());
ENUM_CALLEE_SAVED_REGISTERS();
@@ -689,7 +688,6 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);
pRD->pCurrentContext->Esp = (DWORD) dac_cast<TADDR>(m_pCallSiteSP);
- pRD->pCurrentContext->ResumeEsp = (DWORD) dac_cast<TADDR>(m_pCallSiteSP) + stackArgSize;
pRD->pCurrentContext->Ebp = (DWORD) m_pCalleeSavedFP;
ClearRegDisplayArgumentAndScratchRegisters(pRD);
@@ -829,7 +827,7 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary.
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);
- pRD->pCurrentContext->Esp = pRD->pCurrentContext->ResumeEsp = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
+ pRD->pCurrentContext->Esp = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
#define RESTORE_REG(reg) { pRD->pCurrentContext->reg = m_Args->reg; pRD->pCurrentContextPointers->reg = &m_Args->reg; }
#define CALLEE_SAVED_REGISTER(reg) RESTORE_REG(reg)
@@ -908,7 +906,7 @@ void TailCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary.
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);
- pRD->pCurrentContext->Esp = pRD->pCurrentContext->ResumeEsp = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
+ pRD->pCurrentContext->Esp = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
UpdateRegDisplayFromCalleeSavedRegisters(pRD, &m_regs);
ClearRegDisplayArgumentAndScratchRegisters(pRD);
@@ -934,6 +932,14 @@ void TailCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
RETURN;
}
+#ifdef FEATURE_READYTORUN
+void DynamicHelperFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
+{
+ WRAPPER_NO_CONTRACT;
+ UpdateRegDisplayHelper(pRD, 0);
+}
+#endif // FEATURE_READYTORUN
+
//------------------------------------------------------------------------
// This is declared as returning WORD instead of PRD_TYPE because of
// header issues with cgencpu.h including dbginterface.h.
@@ -1878,23 +1884,47 @@ PCODE DynamicHelpers::CreateReturnIndirConst(LoaderAllocator * pAllocator, TADDR
END_DYNAMIC_HELPER_EMIT();
}
+EXTERN_C VOID DynamicHelperArgsStub();
+
PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADDR arg, PCODE target)
{
+#ifdef UNIX_X86_ABI
+ BEGIN_DYNAMIC_HELPER_EMIT(18);
+#else
BEGIN_DYNAMIC_HELPER_EMIT(12);
+#endif
+#ifdef UNIX_X86_ABI
+ // sub esp, 8
+ *p++ = 0x83;
+ *p++ = 0xec;
+ *p++ = 0x8;
+#else
// pop eax
*p++ = 0x58;
+#endif
// push arg
*p++ = 0x68;
*(INT32 *)p = arg;
p += 4;
+#ifdef UNIX_X86_ABI
+ // mov eax, target
+ *p++ = 0xB8;
+ *(INT32 *)p = target;
+ p += 4;
+#else
// push eax
*p++ = 0x50;
+#endif
*p++ = X86_INSTR_JMP_REL32; // jmp rel32
+#ifdef UNIX_X86_ABI
+ *(INT32 *)p = rel32UsingJumpStub((INT32 *)p, (PCODE)DynamicHelperArgsStub);
+#else
*(INT32 *)p = rel32UsingJumpStub((INT32 *)p, target);
+#endif
p += 4;
END_DYNAMIC_HELPER_EMIT();
@@ -1902,10 +1932,21 @@ PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADD
PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADDR arg, TADDR arg2, PCODE target)
{
+#ifdef UNIX_X86_ABI
+ BEGIN_DYNAMIC_HELPER_EMIT(23);
+#else
BEGIN_DYNAMIC_HELPER_EMIT(17);
+#endif
+#ifdef UNIX_X86_ABI
+ // sub esp, 4
+ *p++ = 0x83;
+ *p++ = 0xec;
+ *p++ = 0x4;
+#else
// pop eax
*p++ = 0x58;
+#endif
// push arg
*p++ = 0x68;
@@ -1917,11 +1958,22 @@ PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADD
*(INT32 *)p = arg2;
p += 4;
+#ifdef UNIX_X86_ABI
+ // mov eax, target
+ *p++ = 0xB8;
+ *(INT32 *)p = target;
+ p += 4;
+#else
// push eax
*p++ = 0x50;
+#endif
*p++ = X86_INSTR_JMP_REL32; // jmp rel32
+#ifdef UNIX_X86_ABI
+ *(INT32 *)p = rel32UsingJumpStub((INT32 *)p, (PCODE)DynamicHelperArgsStub);
+#else
*(INT32 *)p = rel32UsingJumpStub((INT32 *)p, target);
+#endif
p += 4;
END_DYNAMIC_HELPER_EMIT();
diff --git a/src/vm/i386/ehhelpers.S b/src/vm/i386/ehhelpers.S
index 43ef37fa24..7516db5019 100644
--- a/src/vm/i386/ehhelpers.S
+++ b/src/vm/i386/ehhelpers.S
@@ -100,4 +100,4 @@ NESTED_ENTRY CallEHFilterFunclet, _TEXT, NoHandler
ret 16
-NESTED_END CallEHFunclet, _TEXT
+NESTED_END CallEHFilterFunclet, _TEXT
diff --git a/src/vm/i386/excepx86.cpp b/src/vm/i386/excepx86.cpp
index 2c863b2ec3..8c65db75a7 100644
--- a/src/vm/i386/excepx86.cpp
+++ b/src/vm/i386/excepx86.cpp
@@ -1088,6 +1088,11 @@ CPFH_RealFirstPassHandler( // ExceptionContinueSearch, etc.
// of the active exception.
CEHelper::SetupCorruptionSeverityForActiveException(bRethrownException, bNestedException,
CEHelper::ShouldTreatActiveExceptionAsNonCorrupting());
+
+ // Failfast if exception indicates corrupted process state
+ if (pExInfo->GetCorruptionSeverity() == ProcessCorrupting)
+ EEPOLICY_HANDLE_FATAL_ERROR(exceptionCode);
+
END_SO_INTOLERANT_CODE;
}
#endif // FEATURE_CORRUPTING_EXCEPTIONS
@@ -3703,6 +3708,13 @@ AdjustContextForVirtualStub(
pExceptionRecord->ExceptionAddress = (PVOID)callsite;
SetIP(pContext, callsite);
+#ifdef HAVE_GCCOVER
+ // Modify LastAVAddress saved in thread to distinguish between fake & real AV
+ // See comments in IsGcMarker in file excep.cpp for more details
+ pThread->SetLastAVAddress((LPVOID)GetIP(pContext));
+#endif
+
+
// put ESP back to what it was before the call.
SetSP(pContext, dac_cast<PCODE>(dac_cast<PTR_BYTE>(GetSP(pContext)) + sizeof(void*)));
diff --git a/src/vm/i386/gmsx86.cpp b/src/vm/i386/gmsx86.cpp
index 840a50d045..2852b924ab 100644
--- a/src/vm/i386/gmsx86.cpp
+++ b/src/vm/i386/gmsx86.cpp
@@ -1295,10 +1295,10 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState,
ctx.Esi = lazyState->_esi = baseState->_esi;
ctx.Ebx = lazyState->_ebx = baseState->_ebx;
- nonVolRegPtrs.Edi = &(lazyState->_edi);
- nonVolRegPtrs.Esi = &(lazyState->_esi);
- nonVolRegPtrs.Ebx = &(lazyState->_ebx);
- nonVolRegPtrs.Ebp = &(lazyState->_ebp);
+ nonVolRegPtrs.Edi = &(baseState->_edi);
+ nonVolRegPtrs.Esi = &(baseState->_esi);
+ nonVolRegPtrs.Ebx = &(baseState->_ebx);
+ nonVolRegPtrs.Ebp = &(baseState->_ebp);
PCODE pvControlPc;
diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp
index 338c274014..5ef7700896 100644
--- a/src/vm/jitinterface.cpp
+++ b/src/vm/jitinterface.cpp
@@ -6921,18 +6921,7 @@ bool getILIntrinsicImplementation(MethodDesc * ftn,
return true;
}
}
- else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__BYREF_LESSTHAN)->GetMemberDef())
- {
- // Compare the two arguments
- static const BYTE ilcode[] = { CEE_LDARG_0, CEE_LDARG_1, CEE_PREFIX1, (CEE_CLT & 0xFF), CEE_RET };
- methInfo->ILCode = const_cast<BYTE*>(ilcode);
- methInfo->ILCodeSize = sizeof(ilcode);
- methInfo->maxStack = 2;
- methInfo->EHcount = 0;
- methInfo->options = (CorInfoOptions)0;
- return true;
- }
- else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__GET_ARRAY_DATA)->GetMemberDef())
+ else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__GET_RAW_SZ_ARRAY_DATA)->GetMemberDef())
{
mdToken tokArrayPinningHelper = MscorlibBinder::GetField(FIELD__ARRAY_PINNING_HELPER__M_ARRAY_DATA)->GetMemberDef();
@@ -8634,7 +8623,7 @@ CorInfoIntrinsics CEEInfo::getIntrinsicID(CORINFO_METHOD_HANDLE methodHnd,
else
{
MethodTable * pMT = method->GetMethodTable();
- if (pMT->IsByRefLike() && pMT->GetModule()->IsSystem())
+ if (pMT->GetModule()->IsSystem() && pMT->IsByRefLike())
{
if (pMT->HasSameTypeDefAs(g_pByReferenceClass))
{
@@ -8648,10 +8637,25 @@ CorInfoIntrinsics CEEInfo::getIntrinsicID(CORINFO_METHOD_HANDLE methodHnd,
_ASSERTE(strcmp(method->GetName(), "get_Value") == 0);
result = CORINFO_INTRINSIC_ByReference_Value;
}
- *pMustExpand = true;
+ if (pMustExpand != nullptr)
+ {
+ *pMustExpand = true;
+ }
+ }
+ else if (pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__SPAN)))
+ {
+ if (method->HasSameMethodDefAs(MscorlibBinder::GetMethod(METHOD__SPAN__GET_ITEM)))
+ {
+ result = CORINFO_INTRINSIC_Span_GetItem;
+ }
+ }
+ else if (pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__READONLY_SPAN)))
+ {
+ if (method->HasSameMethodDefAs(MscorlibBinder::GetMethod(METHOD__READONLY_SPAN__GET_ITEM)))
+ {
+ result = CORINFO_INTRINSIC_ReadOnlySpan_GetItem;
+ }
}
-
- // TODO-SPAN: Span<T> intrinsics for optimizations
}
}
diff --git a/src/vm/jitinterfacegen.cpp b/src/vm/jitinterfacegen.cpp
index ce4c1e90e3..8d1c8cdf67 100644
--- a/src/vm/jitinterfacegen.cpp
+++ b/src/vm/jitinterfacegen.cpp
@@ -61,6 +61,11 @@ extern "C" void* JIT_GetSharedNonGCStaticBaseNoCtor_Slow(SIZE_T moduleDomainID,
extern "C" void* JIT_GetSharedGCStaticBase_Slow(SIZE_T moduleDomainID, DWORD dwModuleClassID);
extern "C" void* JIT_GetSharedGCStaticBaseNoCtor_Slow(SIZE_T moduleDomainID, DWORD dwModuleClassID);
+extern "C" void* JIT_GetSharedNonGCStaticBase_SingleAppDomain(SIZE_T moduleDomainID, DWORD dwModuleClassID);
+extern "C" void* JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain(SIZE_T moduleDomainID, DWORD dwModuleClassID);
+extern "C" void* JIT_GetSharedGCStaticBase_SingleAppDomain(SIZE_T moduleDomainID, DWORD dwModuleClassID);
+extern "C" void* JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain(SIZE_T moduleDomainID, DWORD dwModuleClassID);
+
#ifdef _TARGET_AMD64_
extern WriteBarrierManager g_WriteBarrierManager;
#endif // _TARGET_AMD64_
@@ -283,7 +288,17 @@ void InitJITHelpers1()
SetJitHelperFunction(CORINFO_HELP_MON_ENTER_STATIC, JIT_MonEnterStatic_Slow);
SetJitHelperFunction(CORINFO_HELP_MON_EXIT_STATIC, JIT_MonExitStatic_Slow);
}
+#endif
+ if(IsSingleAppDomain())
+ {
+ SetJitHelperFunction(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, JIT_GetSharedGCStaticBase_SingleAppDomain);
+ SetJitHelperFunction(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, JIT_GetSharedNonGCStaticBase_SingleAppDomain);
+ SetJitHelperFunction(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain);
+ SetJitHelperFunction(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR,JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain);
+ }
+#ifndef FEATURE_IMPLICIT_TLS
+ else
if (gAppDomainTLSIndex >= TLS_MINIMUM_AVAILABLE)
{
SetJitHelperFunction(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, JIT_GetSharedGCStaticBase_Slow);
diff --git a/src/vm/method.cpp b/src/vm/method.cpp
index a72b07b404..77a6a0d37f 100644
--- a/src/vm/method.cpp
+++ b/src/vm/method.cpp
@@ -2404,7 +2404,7 @@ BOOL MethodDesc::IsFCallOrIntrinsic()
if (IsFCall() || IsArray())
return TRUE;
- // Intrinsic methods on ByReference<T> or Span<T>
+ // Intrinsic methods on ByReference<T>, Span<T>, or ReadOnlySpan<T>
MethodTable * pMT = GetMethodTable();
if (pMT->IsByRefLike() && pMT->GetModule()->IsSystem())
return TRUE;
diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h
index d5cb5ba866..df60fca09d 100644
--- a/src/vm/methodtable.h
+++ b/src/vm/methodtable.h
@@ -414,19 +414,13 @@ struct MethodTableWriteableData
};
DWORD m_dwFlags; // Lot of empty bits here.
-private:
/*
* m_hExposedClassObject is LoaderAllocator slot index to
- * a RuntimeType instance for this class. But
- * do NOT use it for Arrays or remoted objects! All arrays of objects
- * share the same MethodTable/EEClass.
- * @GENERICS: this used to live in EEClass but now lives here because it is per-instantiation data
- * only set in code:MethodTable.GetManagedClassObject
+ * a RuntimeType instance for this class.
*/
LOADERHANDLE m_hExposedClassObject;
#ifdef _DEBUG
-public:
// to avoid verify same method table too many times when it's not changing, we cache the GC count
// on which the method table is verified. When fast GC STRESS is turned on, we only verify the MT if
// current GC count is bigger than the number. Note most thing which will invalidate a MT will require a
diff --git a/src/vm/methodtable.inl b/src/vm/methodtable.inl
index c762512bf1..9b72d24d0f 100644
--- a/src/vm/methodtable.inl
+++ b/src/vm/methodtable.inl
@@ -1770,10 +1770,6 @@ FORCEINLINE OBJECTREF MethodTable::GetManagedClassObjectIfExists()
return NULL;
}
- // Only code:MethodTable::GetManagedClassObject sets m_pExposedClassObject and it insures that
- // remoted objects and arrays don't get in.
- _ASSERTE(!IsArray() && !IsTransparentProxy());
-
COMPILER_ASSUME(retVal != NULL);
return retVal;
}
diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h
index 244b6900ba..87927f687d 100644
--- a/src/vm/mscorlib.h
+++ b/src/vm/mscorlib.h
@@ -653,7 +653,9 @@ DEFINE_CLASS(NULLABLE, System, Nullable`1)
DEFINE_CLASS(BYREFERENCE, System, ByReference`1)
DEFINE_CLASS(SPAN, System, Span`1)
+DEFINE_METHOD(SPAN, GET_ITEM, get_Item, NoSig)
DEFINE_CLASS(READONLY_SPAN, System, ReadOnlySpan`1)
+DEFINE_METHOD(READONLY_SPAN, GET_ITEM, get_Item, NoSig)
// Keep this in sync with System.Globalization.NumberFormatInfo
DEFINE_CLASS_U(Globalization, NumberFormatInfo, NumberFormatInfo)
@@ -805,8 +807,7 @@ DEFINE_METHOD(JIT_HELPERS, UNSAFE_ENUM_CAST, UnsafeEnumCast, NoSi
DEFINE_METHOD(JIT_HELPERS, UNSAFE_ENUM_CAST_LONG, UnsafeEnumCastLong, NoSig)
DEFINE_METHOD(JIT_HELPERS, UNSAFE_CAST_TO_STACKPTR,UnsafeCastToStackPointer, NoSig)
#endif // _DEBUG
-DEFINE_METHOD(JIT_HELPERS, BYREF_LESSTHAN, ByRefLessThan, NoSig)
-DEFINE_METHOD(JIT_HELPERS, GET_ARRAY_DATA, GetArrayData, NoSig)
+DEFINE_METHOD(JIT_HELPERS, GET_RAW_SZ_ARRAY_DATA, GetRawSzArrayData, NoSig)
DEFINE_CLASS(UNSAFE, CompilerServices, Unsafe)
DEFINE_METHOD(UNSAFE, AS_POINTER, AsPointer, NoSig)
diff --git a/src/vm/object.cpp b/src/vm/object.cpp
index 1725ef7db4..3e3f6d120a 100644
--- a/src/vm/object.cpp
+++ b/src/vm/object.cpp
@@ -1592,6 +1592,14 @@ void STDCALL CopyValueClassArgUnchecked(ArgDestination *argDest, void* src, Meth
return;
}
+#elif defined(_TARGET_ARM64_)
+
+ if (argDest->IsHFA())
+ {
+ argDest->CopyHFAStructToRegister(src, pMT->GetAlignedNumInstanceFieldBytes());
+ return;
+ }
+
#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
// destOffset is only valid for Nullable<T> passed in registers
_ASSERTE(destOffset == 0);
diff --git a/src/vm/object.h b/src/vm/object.h
index fad5f74f39..cb3743cdb9 100644
--- a/src/vm/object.h
+++ b/src/vm/object.h
@@ -634,10 +634,10 @@ class Object
LIMITED_METHOD_CONTRACT;
SUPPORTS_DAC;
- // lose GC marking bit and the pinning bit
+ // lose GC marking bit and the reserved bit
// A method table pointer should always be aligned. During GC we set the least
- // significant bit for marked objects and we set the second to least significant
- // bit for pinned objects. So if we want the actual MT pointer during a GC
+ // significant bit for marked objects, and the second to least significant
+ // bit is reserved. So if we want the actual MT pointer during a GC
// we must zero out the lowest 2 bits.
return dac_cast<PTR_MethodTable>((dac_cast<TADDR>(m_pMethTab)) & ~((UINT_PTR)3));
}
@@ -3012,8 +3012,8 @@ class SafeBuffer : SafeHandle
public:
static FCDECL1(UINT, SizeOfType, ReflectClassBaseObject* typeUNSAFE);
static FCDECL1(UINT, AlignedSizeOfType, ReflectClassBaseObject* typeUNSAFE);
- static FCDECL3(void, PtrToStructure, BYTE* ptr, FC_TypedByRef structure, UINT32 sizeofT);
- static FCDECL3(void, StructureToPtr, FC_TypedByRef structure, BYTE* ptr, UINT32 sizeofT);
+ static FCDECL3_IVI(void, PtrToStructure, BYTE* ptr, FC_TypedByRef structure, UINT32 sizeofT);
+ static FCDECL3_VII(void, StructureToPtr, FC_TypedByRef structure, BYTE* ptr, UINT32 sizeofT);
};
#ifdef USE_CHECKED_OBJECTREFS
diff --git a/src/vm/peimagelayout.cpp b/src/vm/peimagelayout.cpp
index fb2ce5760c..24166817bb 100644
--- a/src/vm/peimagelayout.cpp
+++ b/src/vm/peimagelayout.cpp
@@ -155,6 +155,17 @@ void PEImageLayout::ApplyBaseRelocations()
{
PIMAGE_BASE_RELOCATION r = (PIMAGE_BASE_RELOCATION)(dir + dirPos);
+ COUNT_T fixupsSize = VAL32(r->SizeOfBlock);
+
+ USHORT *fixups = (USHORT *) (r + 1);
+
+ _ASSERTE(fixupsSize > sizeof(IMAGE_BASE_RELOCATION));
+ _ASSERTE((fixupsSize - sizeof(IMAGE_BASE_RELOCATION)) % 2 == 0);
+
+ COUNT_T fixupsCount = (fixupsSize - sizeof(IMAGE_BASE_RELOCATION)) / 2;
+
+ _ASSERTE((BYTE *)(fixups + fixupsCount) <= (BYTE *)(dir + dirSize));
+
DWORD rva = VAL32(r->VirtualAddress);
BYTE * pageAddress = (BYTE *)GetBase() + rva;
@@ -172,7 +183,9 @@ void PEImageLayout::ApplyBaseRelocations()
dwOldProtection = 0;
}
- IMAGE_SECTION_HEADER *pSection = RvaToSection(rva);
+ USHORT fixup = VAL16(fixups[0]);
+
+ IMAGE_SECTION_HEADER *pSection = RvaToSection(rva + (fixup & 0xfff));
PREFIX_ASSUME(pSection != NULL);
pWriteableRegion = (BYTE*)GetRvaData(VAL32(pSection->VirtualAddress));
@@ -199,17 +212,6 @@ void PEImageLayout::ApplyBaseRelocations()
}
}
- COUNT_T fixupsSize = VAL32(r->SizeOfBlock);
-
- USHORT *fixups = (USHORT *) (r + 1);
-
- _ASSERTE(fixupsSize > sizeof(IMAGE_BASE_RELOCATION));
- _ASSERTE((fixupsSize - sizeof(IMAGE_BASE_RELOCATION)) % 2 == 0);
-
- COUNT_T fixupsCount = (fixupsSize - sizeof(IMAGE_BASE_RELOCATION)) / 2;
-
- _ASSERTE((BYTE *)(fixups + fixupsCount) <= (BYTE *)(dir + dirSize));
-
for (COUNT_T fixupIndex = 0; fixupIndex < fixupsCount; fixupIndex++)
{
USHORT fixup = VAL16(fixups[fixupIndex]);
diff --git a/src/vm/safehandle.cpp b/src/vm/safehandle.cpp
index 828b221025..d79c5a749a 100644
--- a/src/vm/safehandle.cpp
+++ b/src/vm/safehandle.cpp
@@ -483,7 +483,7 @@ FCIMPL1(UINT, SafeBuffer::AlignedSizeOfType, ReflectClassBaseObject* typeUNSAFE)
}
FCIMPLEND
-FCIMPL3(void, SafeBuffer::PtrToStructure, BYTE* ptr, FC_TypedByRef structure, UINT32 sizeofT)
+FCIMPL3_IVI(void, SafeBuffer::PtrToStructure, BYTE* ptr, FC_TypedByRef structure, UINT32 sizeofT)
{
FCALL_CONTRACT;
@@ -494,7 +494,7 @@ FCIMPL3(void, SafeBuffer::PtrToStructure, BYTE* ptr, FC_TypedByRef structure, UI
}
FCIMPLEND
-FCIMPL3(void, SafeBuffer::StructureToPtr, FC_TypedByRef structure, BYTE* ptr, UINT32 sizeofT)
+FCIMPL3_VII(void, SafeBuffer::StructureToPtr, FC_TypedByRef structure, BYTE* ptr, UINT32 sizeofT)
{
FCALL_CONTRACT;
diff --git a/src/vm/siginfo.cpp b/src/vm/siginfo.cpp
index b9955eca68..82aef45026 100644
--- a/src/vm/siginfo.cpp
+++ b/src/vm/siginfo.cpp
@@ -1199,7 +1199,10 @@ TypeHandle SigPointer::GetTypeHandleThrowing(
PREFIX_ASSUME(pZapSigContext != NULL);
pModule = pZapSigContext->GetZapSigModule()->GetModuleFromIndex(ix);
- if (pModule != NULL)
+
+ // For ReadyToRunCompilation we return a null TypeHandle when we reference a non-local module
+ //
+ if ((pModule != NULL) && pModule->IsInCurrentVersionBubble())
{
thRet = psig.GetTypeHandleThrowing(pModule,
pTypeContext,
diff --git a/src/vm/stubhelpers.cpp b/src/vm/stubhelpers.cpp
index 0a5c143bf4..db593c66e9 100644
--- a/src/vm/stubhelpers.cpp
+++ b/src/vm/stubhelpers.cpp
@@ -182,7 +182,7 @@ void StubHelpers::ProcessByrefValidationList()
#endif // VERIFY_HEAP
-FCIMPL1(double, StubHelpers::DateMarshaler__ConvertToNative, INT64 managedDate)
+FCIMPL1_V(double, StubHelpers::DateMarshaler__ConvertToNative, INT64 managedDate)
{
FCALL_CONTRACT;
diff --git a/src/vm/stubhelpers.h b/src/vm/stubhelpers.h
index f7577d7a44..31693be38a 100644
--- a/src/vm/stubhelpers.h
+++ b/src/vm/stubhelpers.h
@@ -46,7 +46,7 @@ public:
// PInvoke stub helpers
//-------------------------------------------------------
- static FCDECL1(double, DateMarshaler__ConvertToNative, INT64 managedDate);
+ static FCDECL1_V(double, DateMarshaler__ConvertToNative, INT64 managedDate);
static FCDECL1_V(INT64, DateMarshaler__ConvertToManaged, double nativeDate);
static FCDECL4(void, ValueClassMarshaler__ConvertToNative, LPVOID pDest, LPVOID pSrc, MethodTable* pMT, OBJECTREF *ppCleanupWorkListOnStack);
diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp
index a126d1c816..c36232ecb5 100644
--- a/src/vm/threads.cpp
+++ b/src/vm/threads.cpp
@@ -5074,7 +5074,7 @@ void Thread::SafeUpdateLastThrownObject(void)
{
EX_TRY
{
- IGCHandleTable *pHandleTable = GCHandleTableUtilities::GetGCHandleTable();
+ IGCHandleManager *pHandleTable = GCHandleUtilities::GetGCHandleManager();
// Creating a duplicate handle here ensures that the AD of the last thrown object
// matches the domain of the current throwable.
diff --git a/src/vm/threads.h b/src/vm/threads.h
index a055f2e9e0..34fca24c4f 100644
--- a/src/vm/threads.h
+++ b/src/vm/threads.h
@@ -143,7 +143,7 @@
#include "mscoree.h"
#include "appdomainstack.h"
#include "gcheaputilities.h"
-#include "gchandletableutilities.h"
+#include "gchandleutilities.h"
#include "gcinfotypes.h"
#include <clrhost.h>
@@ -6735,30 +6735,29 @@ public:
Thread::TriggersGC(GetThread()); \
} while(0)
+#else // ENABLE_CONTRACTS_IMPL
+
+#define BEGINFORBIDGC()
+#define ENDFORBIDGC()
+#define TRIGGERSGC_NOSTOMP() ANNOTATION_GC_TRIGGERS
+#define TRIGGERSGC() ANNOTATION_GC_TRIGGERS
+
+#endif // ENABLE_CONTRACTS_IMPL
inline BOOL GC_ON_TRANSITIONS(BOOL val) {
WRAPPER_NO_CONTRACT;
+#ifdef _DEBUG
Thread* thread = GetThread();
if (thread == 0)
return(FALSE);
BOOL ret = thread->m_GCOnTransitionsOK;
thread->m_GCOnTransitionsOK = val;
return(ret);
+#else // _DEBUG
+ return FALSE;
+#endif // !_DEBUG
}
-#else // _DEBUG_IMPL
-
-#define BEGINFORBIDGC()
-#define ENDFORBIDGC()
-#define TRIGGERSGC_NOSTOMP() ANNOTATION_GC_TRIGGERS
-#define TRIGGERSGC() ANNOTATION_GC_TRIGGERS
-
-inline BOOL GC_ON_TRANSITIONS(BOOL val) {
- return FALSE;
-}
-
-#endif // _DEBUG_IMPL
-
#ifdef _DEBUG
inline void ENABLESTRESSHEAP() {
WRAPPER_NO_CONTRACT;
diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp
index ab1f2bbff5..65495940ed 100644
--- a/src/vm/threadsuspend.cpp
+++ b/src/vm/threadsuspend.cpp
@@ -7181,7 +7181,7 @@ void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceded)
//
// Any threads that are waiting in WaitUntilGCComplete will continue now.
//
- GCHeapUtilities::GetGCHeap()->GetWaitForGCEvent()->Set();
+ GCHeapUtilities::GetGCHeap()->SetWaitForGCEvent();
_ASSERTE(IsGCSpecialThread() || ThreadStore::HoldingThreadStore());
ResumeRuntime(bFinishedGC, SuspendSucceded);
@@ -7307,7 +7307,7 @@ retry_for_debugger:
//
// First, we reset the event that we're about to tell other threads to wait for.
//
- GCHeapUtilities::GetGCHeap()->GetWaitForGCEvent()->Reset();
+ GCHeapUtilities::GetGCHeap()->ResetWaitForGCEvent();
//
// Remember that we're the one doing the GC. Actually, maybe we're not doing a GC -
diff --git a/src/vm/typedesc.cpp b/src/vm/typedesc.cpp
index 9d84c01488..d05cb558bc 100644
--- a/src/vm/typedesc.cpp
+++ b/src/vm/typedesc.cpp
@@ -837,6 +837,12 @@ OBJECTREF ParamTypeDesc::GetManagedClassObject()
pLoaderAllocator->ClearHandle(hExposedClassObject);
}
+ if (OwnsTemplateMethodTable())
+ {
+ // Set the handle on template methodtable as well to make Object.GetType for arrays take the fast path
+ EnsureWritablePages(m_TemplateMT.GetValue()->GetWriteableDataForWrite())->m_hExposedClassObject = m_hExposedClassObject;
+ }
+
// Log the TypeVarTypeDesc access
g_IBCLogger.LogTypeMethodTableWriteableAccess(&th);
diff --git a/src/vm/util.cpp b/src/vm/util.cpp
index 70ed0e27ca..da7d18c390 100644
--- a/src/vm/util.cpp
+++ b/src/vm/util.cpp
@@ -2525,12 +2525,12 @@ HMODULE CLRGetCurrentModuleHandle()
#endif // !FEATURE_PAL
-extern LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes);
-extern BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem);
-extern void ShutdownRuntimeWithoutExiting(int exitCode);
-extern BOOL IsRuntimeStarted(DWORD *pdwStartupFlags);
+LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes);
+BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem);
+void ShutdownRuntimeWithoutExiting(int exitCode);
+BOOL IsRuntimeStarted(DWORD *pdwStartupFlags);
-void * __stdcall GetCLRFunction(LPCSTR FunctionName)
+void *GetCLRFunction(LPCSTR FunctionName)
{
void* func = NULL;