Skip to content

Commit ad25cc4

Browse files
committedApr 2, 2021
Keep blittable layout class In/Out by default (dotnet#50655)
1 parent a3785ea commit ad25cc4

File tree

3 files changed

+63
-39
lines changed

3 files changed

+63
-39
lines changed
 

Diff for: ‎src/coreclr/src/vm/mlinfo.cpp

+12-12
Original file line numberDiff line numberDiff line change
@@ -1231,8 +1231,8 @@ MarshalInfo::MarshalInfo(Module* pModule,
12311231
m_pMT = NULL;
12321232
m_pMD = pMD;
12331233
m_onInstanceMethod = onInstanceMethod;
1234-
// [Compat] For backward compatibility reasons, some marshalers imply [In, Out] behavior when marked as [Out].
1235-
BOOL outImpliesInOut = FALSE;
1234+
// [Compat] For backward compatibility reasons, some marshalers imply [In, Out] behavior when marked as [In], [Out], or not marked with either.
1235+
BOOL byValAlwaysInOut = FALSE;
12361236

12371237
#ifdef FEATURE_COMINTEROP
12381238
m_fDispItf = FALSE;
@@ -2009,7 +2009,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
20092009
}
20102010
m_type = IsFieldScenario() ? MARSHAL_TYPE_BLITTABLE_LAYOUTCLASS : MARSHAL_TYPE_BLITTABLEPTR;
20112011
m_args.m_pMT = m_pMT;
2012-
outImpliesInOut = TRUE;
2012+
byValAlwaysInOut = TRUE;
20132013
}
20142014
else if (m_pMT->HasLayout())
20152015
{
@@ -2517,10 +2517,16 @@ MarshalInfo::MarshalInfo(Module* pModule,
25172517
}
25182518
}
25192519

2520-
// If neither IN nor OUT are true, this signals the URT to use the default
2521-
// rules.
2522-
if (!m_in && !m_out)
2520+
if (!m_byref && byValAlwaysInOut)
25232521
{
2522+
// Some marshalers expect [In, Out] behavior with [In], [Out], or no directional attributes.
2523+
m_in = TRUE;
2524+
m_out = TRUE;
2525+
}
2526+
else if (!m_in && !m_out)
2527+
{
2528+
// If neither IN nor OUT are true, this signals the URT to use the default
2529+
// rules.
25242530
if (m_byref ||
25252531
(mtype == ELEMENT_TYPE_CLASS
25262532
&& !(sig.IsStringType(pModule, pTypeContext))
@@ -2536,12 +2542,6 @@ MarshalInfo::MarshalInfo(Module* pModule,
25362542
}
25372543

25382544
}
2539-
2540-
// For marshalers that expect [Out] behavior to match [In, Out] behavior, update that here.
2541-
if (m_out && outImpliesInOut)
2542-
{
2543-
m_in = TRUE;
2544-
}
25452545
}
25462546

25472547
lReallyExit:

Diff for: ‎src/tests/Interop/LayoutClass/LayoutClassNative.cpp

+1-9
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,13 @@ DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleExpLayoutClassByRef(ExpClass* p)
7878
}
7979

8080
extern "C"
81-
DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleBlittableSeqLayoutClassByRef(BlittableClass* p)
81+
DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleBlittableSeqLayoutClass_UpdateField(BlittableClass* p)
8282
{
8383
if(p->a != 10)
8484
{
8585
printf("FAIL: p->a=%d\n", p->a);
8686
return FALSE;
8787
}
88-
return TRUE;
89-
}
90-
91-
extern "C"
92-
DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleBlittableSeqLayoutClassByOutAttr(BlittableClass* p)
93-
{
94-
if(!SimpleBlittableSeqLayoutClassByRef(p))
95-
return FALSE;
9688

9789
p->a++;
9890
return TRUE;

Diff for: ‎src/tests/Interop/LayoutClass/LayoutClassTest.cs

+50-18
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ public struct RecursiveTestStruct
123123

124124
class StructureTests
125125
{
126+
private const string SimpleBlittableSeqLayoutClass_UpdateField = nameof(SimpleBlittableSeqLayoutClass_UpdateField);
127+
126128
[DllImport("LayoutClassNative")]
127129
private static extern bool SimpleSeqLayoutClassByRef(SeqClass p);
128130

@@ -132,17 +134,23 @@ class StructureTests
132134
[DllImport("LayoutClassNative")]
133135
private static extern bool SimpleExpLayoutClassByRef(ExpClass p);
134136

135-
[DllImport("LayoutClassNative")]
137+
[DllImport("LayoutClassNative", EntryPoint = SimpleBlittableSeqLayoutClass_UpdateField)]
136138
private static extern bool SimpleBlittableSeqLayoutClassByRef(Blittable p);
137139

138-
[DllImport("LayoutClassNative")]
140+
[DllImport("LayoutClassNative", EntryPoint = SimpleBlittableSeqLayoutClass_UpdateField)]
141+
private static extern bool SimpleBlittableSeqLayoutClassByInAttr([In] Blittable p);
142+
143+
[DllImport("LayoutClassNative", EntryPoint = SimpleBlittableSeqLayoutClass_UpdateField)]
139144
private static extern bool SimpleBlittableSeqLayoutClassByOutAttr([Out] Blittable p);
140145

141-
[DllImport("LayoutClassNative")]
142-
private static extern bool SimpleBlittableSeqLayoutClassByRef(SealedBlittable p);
146+
[DllImport("LayoutClassNative", EntryPoint = SimpleBlittableSeqLayoutClass_UpdateField)]
147+
private static extern bool SealedBlittableSeqLayoutClassByRef(SealedBlittable p);
143148

144-
[DllImport("LayoutClassNative")]
145-
private static extern bool SimpleBlittableSeqLayoutClassByOutAttr([Out] SealedBlittable p);
149+
[DllImport("LayoutClassNative", EntryPoint = SimpleBlittableSeqLayoutClass_UpdateField)]
150+
private static extern bool SealedBlittableSeqLayoutClassByInAttr([In] SealedBlittable p);
151+
152+
[DllImport("LayoutClassNative", EntryPoint = SimpleBlittableSeqLayoutClass_UpdateField)]
153+
private static extern bool SealedBlittableSeqLayoutClassByOutAttr([Out] SealedBlittable p);
146154

147155
[DllImport("LayoutClassNative")]
148156
private static extern bool SimpleNestedLayoutClassByValue(NestedLayout p);
@@ -176,42 +184,64 @@ public static void ExplicitClass()
176184
Assert.IsTrue(SimpleExpLayoutClassByRef(p));
177185
}
178186

187+
private static void ValidateBlittableClassInOut(Func<Blittable, bool> pinvoke)
188+
{
189+
int a = 10;
190+
int expected = a + 1;
191+
Blittable p = new Blittable(a);
192+
Assert.IsTrue(pinvoke(p));
193+
Assert.AreEqual(expected, p.a);
194+
}
195+
179196
public static void BlittableClass()
180197
{
198+
// [Compat] Marshalled with [In, Out] behaviour by default
181199
Console.WriteLine($"Running {nameof(BlittableClass)}...");
200+
ValidateBlittableClassInOut(SimpleBlittableSeqLayoutClassByRef);
201+
}
182202

183-
Blittable p = new Blittable(10);
184-
Assert.IsTrue(SimpleBlittableSeqLayoutClassByRef(p));
203+
public static void BlittableClassByInAttr()
204+
{
205+
// [Compat] Marshalled with [In, Out] behaviour even when only [In] is specified
206+
Console.WriteLine($"Running {nameof(BlittableClassByInAttr)}...");
207+
ValidateBlittableClassInOut(SimpleBlittableSeqLayoutClassByInAttr);
185208
}
186209

187210
public static void BlittableClassByOutAttr()
188211
{
212+
// [Compat] Marshalled with [In, Out] behaviour even when only [Out] is specified
189213
Console.WriteLine($"Running {nameof(BlittableClassByOutAttr)}...");
214+
ValidateBlittableClassInOut(SimpleBlittableSeqLayoutClassByOutAttr);
215+
}
190216

217+
private static void ValidateSealedBlittableClassInOut(Func<SealedBlittable, bool> pinvoke)
218+
{
191219
int a = 10;
192220
int expected = a + 1;
193-
Blittable p = new Blittable(a);
194-
Assert.IsTrue(SimpleBlittableSeqLayoutClassByOutAttr(p));
221+
SealedBlittable p = new SealedBlittable(a);
222+
Assert.IsTrue(pinvoke(p));
195223
Assert.AreEqual(expected, p.a);
196224
}
197225

198226
public static void SealedBlittableClass()
199227
{
228+
// [Compat] Marshalled with [In, Out] behaviour by default
200229
Console.WriteLine($"Running {nameof(SealedBlittableClass)}...");
230+
ValidateSealedBlittableClassInOut(SealedBlittableSeqLayoutClassByRef);
231+
}
201232

202-
SealedBlittable p = new SealedBlittable(10);
203-
Assert.IsTrue(SimpleBlittableSeqLayoutClassByRef(p));
233+
public static void SealedBlittableClassByInAttr()
234+
{
235+
// [Compat] Marshalled with [In, Out] behaviour even when only [In] is specified
236+
Console.WriteLine($"Running {nameof(SealedBlittableClassByOutAttr)}...");
237+
ValidateSealedBlittableClassInOut(SealedBlittableSeqLayoutClassByInAttr);
204238
}
205239

206240
public static void SealedBlittableClassByOutAttr()
207241
{
242+
// [Compat] Marshalled with [In, Out] behaviour even when only [Out] is specified
208243
Console.WriteLine($"Running {nameof(SealedBlittableClassByOutAttr)}...");
209-
210-
int a = 10;
211-
int expected = a + 1;
212-
SealedBlittable p = new SealedBlittable(a);
213-
Assert.IsTrue(SimpleBlittableSeqLayoutClassByOutAttr(p));
214-
Assert.AreEqual(expected, p.a);
244+
ValidateSealedBlittableClassInOut(SealedBlittableSeqLayoutClassByOutAttr);
215245
}
216246

217247
public static void NestedLayoutClass()
@@ -243,6 +273,8 @@ public static int Main(string[] argv)
243273
ExplicitClass();
244274
BlittableClass();
245275
SealedBlittableClass();
276+
BlittableClassByInAttr();
277+
SealedBlittableClassByInAttr();
246278
BlittableClassByOutAttr();
247279
SealedBlittableClassByOutAttr();
248280
NestedLayoutClass();

0 commit comments

Comments
 (0)
Please sign in to comment.