summaryrefslogtreecommitdiff
path: root/src/vm/jitinterface.cpp
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2016-12-06 21:30:54 -0800
committerRussell C Hadley <rhadley@microsoft.com>2017-01-11 14:12:57 -0800
commit0bedde3a63f22b65155d5f369e75c448c6afb786 (patch)
treece0c00bd13c7b2e5ff727b3daabae789c059f7ec /src/vm/jitinterface.cpp
parentbaa998029e27b5927122d40f3a3a208e6e728421 (diff)
downloadcoreclr-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.cpp83
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();