summaryrefslogtreecommitdiff
path: root/src/vm/ilmarshalers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/ilmarshalers.cpp')
-rw-r--r--src/vm/ilmarshalers.cpp36
1 files changed, 22 insertions, 14 deletions
diff --git a/src/vm/ilmarshalers.cpp b/src/vm/ilmarshalers.cpp
index d3869c28b1..1912e02e05 100644
--- a/src/vm/ilmarshalers.cpp
+++ b/src/vm/ilmarshalers.cpp
@@ -3777,10 +3777,6 @@ void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNative()
// the other. Since there is no enforcement of this, apps blithely depend
// on it.
//
-
- // The base offset should only be 0 for System.Array parameters for which
- // OleVariant::GetMarshalerForVarType(vt) should never return NULL.
- _ASSERTE(m_pargs->na.m_optionalbaseoffset != 0);
EmitSetupSigAndDefaultHomesCLRToNative();
@@ -3794,13 +3790,21 @@ void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNative()
EmitStoreNativeValue(m_pcsMarshal);
EmitLoadManagedValue(m_pcsMarshal);
- m_pcsMarshal->EmitBRFALSE(pNullRefLabel);
-
+ m_pcsMarshal->EmitBRFALSE(pNullRefLabel);
+
+ // COMPAT: We cannot generate the same code that the C# compiler generates for
+ // a fixed() statement on an array since we need to provide a non-null value
+ // for a 0-length array. For compat reasons, we need to preserve old behavior.
+ // Additionally, we need to ensure that we do not pass non-null for a zero-length
+ // array when interacting with GDI/GDI+ since they fail on null arrays but succeed
+ // on 0-length arrays.
EmitLoadManagedValue(m_pcsMarshal);
m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
m_pcsMarshal->EmitCONV_I();
- m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
+ // Optimize marshalling by emitting the data ptr offset directly into the IL stream
+ // instead of doing an FCall to recalulate it each time when possible.
+ m_pcsMarshal->EmitLDC(ArrayBase::GetDataPtrOffset(m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().MakeSZArray().GetMethodTable()));
m_pcsMarshal->EmitADD();
EmitStoreNativeValue(m_pcsMarshal);
@@ -4620,6 +4624,7 @@ LocalDesc ILHiddenLengthArrayMarshaler::GetNativeType()
LocalDesc ILHiddenLengthArrayMarshaler::GetManagedType()
{
LIMITED_METHOD_CONTRACT;
+
return LocalDesc(ELEMENT_TYPE_OBJECT);
}
@@ -4676,9 +4681,17 @@ void ILHiddenLengthArrayMarshaler::EmitMarshalArgumentCLRToNative()
m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
// native = pinnedLocal + dataOffset
+
+ // COMPAT: We cannot generate the same code that the C# compiler generates for
+ // a fixed() statement on an array since we need to provide a non-null value
+ // for a 0-length array. For compat reasons, we need to preserve old behavior.
+ EmitLoadManagedValue(m_pcsMarshal);
+ m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
m_pcsMarshal->EmitCONV_I();
- m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
+ // Optimize marshalling by emitting the data ptr offset directly into the IL stream
+ // instead of doing an FCall to recalulate it each time.
+ m_pcsMarshal->EmitLDC(ArrayBase::GetDataPtrOffset(m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().MakeSZArray().GetMethodTable()));
m_pcsMarshal->EmitADD();
EmitStoreNativeValue(m_pcsMarshal);
@@ -4974,11 +4987,6 @@ bool ILHiddenLengthArrayMarshaler::CanUsePinnedArray()
return false;
}
- if (m_pargs->na.m_optionalbaseoffset == 0)
- {
- return false;
- }
-
return true;
}
@@ -5123,7 +5131,7 @@ MethodDesc *ILHiddenLengthArrayMarshaler::GetExactMarshalerMethod(MethodDesc *pG
pGenericMD,
pGenericMD->GetMethodTable(),
FALSE, // forceBoxedEntryPoint
- m_pargs->na.m_pMT->GetInstantiation(), // methodInst
+ m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().GetInstantiation(), // methodInst
FALSE, // allowInstParam
TRUE); // forceRemotableMethod
}