diff options
author | Jan Kotas <jkotas@microsoft.com> | 2016-12-06 21:30:54 -0800 |
---|---|---|
committer | Russell C Hadley <rhadley@microsoft.com> | 2017-01-11 14:12:57 -0800 |
commit | 0bedde3a63f22b65155d5f369e75c448c6afb786 (patch) | |
tree | ce0c00bd13c7b2e5ff727b3daabae789c059f7ec /src/vm/jitinterface.cpp | |
parent | baa998029e27b5927122d40f3a3a208e6e728421 (diff) | |
download | coreclr-0bedde3a63f22b65155d5f369e75c448c6afb786.tar.gz coreclr-0bedde3a63f22b65155d5f369e75c448c6afb786.tar.bz2 coreclr-0bedde3a63f22b65155d5f369e75c448c6afb786.zip |
Initial implementation of two field span.
Implements two field span struct which is comprised of a byref field
that may be an interior pointer to a managed object, or a native
pointer indicating the start of the span, and a length field which
describes the span of access.
Since there is no MSIL operation which assign a byref field, the jit
gets involved and treats the constructor and getter of a special struct
called ByReference that contains an declared IntPtr. This special
struct is then used as a field in the span implementation and recognized
by the runtime as a field that may contain a GC pointer. In
implementation, the ctor of ByReference is converted into an assignment
value is returned by a reverse assignment.
Since there are some dependencies on CoreFX for the span implementation
local testing of the implementation has been done using the
BasicSpanTest.cs in the CoreCLR tests. Once this is checked in and is
propagated to CoreFX the apporopate code in the packages will be enabled
and then may be referenced in CoreCLR tests. At that time more span
tests will be added.
Additional comments and fixes based on code review added.
Diffstat (limited to 'src/vm/jitinterface.cpp')
-rw-r--r-- | src/vm/jitinterface.cpp | 83 |
1 files changed, 80 insertions, 3 deletions
diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 9d57836bac..ee22e723e9 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -2286,6 +2286,58 @@ BOOL CEEInfo::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod, } /*********************************************************************/ +static unsigned ComputeGCLayout(MethodTable * pMT, BYTE* gcPtrs) +{ + STANDARD_VM_CONTRACT; + + unsigned result = 0; + + _ASSERTE(pMT->IsValueType()); + + ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS); + for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next()) + { + int fieldStartIndex = pFD->GetOffset() / sizeof(void*); + + if (pFD->GetFieldType() != ELEMENT_TYPE_VALUETYPE) + { + if (pFD->IsObjRef()) + { + if (gcPtrs[fieldStartIndex] == TYPE_GC_NONE) + { + gcPtrs[fieldStartIndex] = TYPE_GC_REF; + result++; + } + else if (gcPtrs[fieldStartIndex] != TYPE_GC_REF) + { + COMPlusThrowHR(COR_E_BADIMAGEFORMAT); + } + } + } + else + { + MethodTable * pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable(); + if (pFieldMT->HasSameTypeDefAs(g_pByReferenceClass)) + { + if (gcPtrs[fieldStartIndex] == TYPE_GC_NONE) + { + gcPtrs[fieldStartIndex] = TYPE_GC_BYREF; + result++; + } + else if (gcPtrs[fieldStartIndex] != TYPE_GC_BYREF) + { + COMPlusThrowHR(COR_E_BADIMAGEFORMAT); + } + } + else + { + result += ComputeGCLayout(pFieldMT, gcPtrs + fieldStartIndex); + } + } + } + return result; +} + unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs) { CONTRACTL { @@ -2313,10 +2365,12 @@ unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs) } else { - // TODO-SPAN: Proper GC reporting memset(gcPtrs, TYPE_GC_NONE, - (VMClsHnd.GetSize() + sizeof(void*) -1)/ sizeof(void*)); - result = 0; + (VMClsHnd.GetSize() + sizeof(void*) - 1) / sizeof(void*)); + // Note: This case is more complicated than the TypedReference case + // due to ByRefLike structs being included as fields in other value + // types (TypedReference can not be.) + result = ComputeGCLayout(VMClsHnd.AsMethodTable(), gcPtrs); } } else if (VMClsHnd.IsNativeValueType()) @@ -8764,6 +8818,29 @@ CorInfoIntrinsics CEEInfo::getIntrinsicID(CORINFO_METHOD_HANDLE methodHnd, { result = ECall::GetIntrinsicID(method); } + else + { + MethodTable * pMT = method->GetMethodTable(); + if (pMT->IsByRefLike() && pMT->GetModule()->IsSystem()) + { + if (pMT->HasSameTypeDefAs(g_pByReferenceClass)) + { + // ByReference<T> has just two methods: constructor and Value property + if (method->IsCtor()) + { + result = CORINFO_INTRINSIC_ByReference_Ctor; + } + else + { + _ASSERTE(strcmp(method->GetName(), "get_Value") == 0); + result = CORINFO_INTRINSIC_ByReference_Value; + } + *pMustExpand = true; + } + + // TODO-SPAN: Span<T> intrinsics for optimizations + } + } EE_TO_JIT_TRANSITION(); |