@@ -2149,14 +2149,30 @@ void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNative(ILCodeStream* ps
2149
2149
2150
2150
EmitLoadManagedValue (pslILEmit);
2151
2151
pslILEmit->EmitBRFALSE (pNullRefLabel);
2152
+ ILCodeLabel* pTypeMismatchedLabel = pslILEmit->NewCodeLabel ();
2153
+ bool emittedTypeCheck = EmitExactTypeCheck (pslILEmit, pTypeMismatchedLabel);
2154
+ DWORD sizeLocal = pslILEmit->NewLocal (LocalDesc (ELEMENT_TYPE_I4));
2155
+
2152
2156
pslILEmit->EmitLDC (uNativeSize);
2157
+ if (emittedTypeCheck)
2158
+ {
2159
+ ILCodeLabel* pHaveSizeLabel = pslILEmit->NewCodeLabel ();
2160
+ pslILEmit->EmitBR (pHaveSizeLabel);
2161
+ pslILEmit->EmitLabel (pTypeMismatchedLabel);
2162
+ EmitLoadManagedValue (pslILEmit);
2163
+ pslILEmit->EmitCALL (METHOD__OBJECT__GET_TYPE, 1 , 1 );
2164
+ pslILEmit->EmitCALL (METHOD__MARSHAL__SIZEOF_TYPE, 1 , 1 );
2165
+ pslILEmit->EmitLabel (pHaveSizeLabel);
2166
+ }
2167
+ pslILEmit->EmitSTLOC (sizeLocal);
2168
+ pslILEmit->EmitLDLOC (sizeLocal);
2153
2169
pslILEmit->EmitCALL (METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1 , 1 );
2154
2170
pslILEmit->EmitDUP (); // for INITBLK
2155
2171
EmitStoreNativeValue (pslILEmit);
2156
2172
2157
2173
// initialize local block we just allocated
2158
2174
pslILEmit->EmitLDC (0 );
2159
- pslILEmit->EmitLDC (uNativeSize );
2175
+ pslILEmit->EmitLDLOC (sizeLocal );
2160
2176
pslILEmit->EmitINITBLK ();
2161
2177
2162
2178
pslILEmit->EmitLabel (pNullRefLabel);
@@ -2180,15 +2196,30 @@ void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNativeTemp(ILCodeStream
2180
2196
2181
2197
EmitLoadManagedValue (pslILEmit);
2182
2198
pslILEmit->EmitBRFALSE (pNullRefLabel);
2199
+ ILCodeLabel* pTypeMismatchedLabel = pslILEmit->NewCodeLabel ();
2200
+ bool emittedTypeCheck = EmitExactTypeCheck (pslILEmit, pTypeMismatchedLabel);
2201
+ DWORD sizeLocal = pslILEmit->NewLocal (LocalDesc (ELEMENT_TYPE_I4));
2183
2202
2184
2203
pslILEmit->EmitLDC (uNativeSize);
2204
+ if (emittedTypeCheck)
2205
+ {
2206
+ ILCodeLabel* pHaveSizeLabel = pslILEmit->NewCodeLabel ();
2207
+ pslILEmit->EmitBR (pHaveSizeLabel);
2208
+ pslILEmit->EmitLabel (pTypeMismatchedLabel);
2209
+ EmitLoadManagedValue (pslILEmit);
2210
+ pslILEmit->EmitCALL (METHOD__OBJECT__GET_TYPE, 1 , 1 );
2211
+ pslILEmit->EmitCALL (METHOD__MARSHAL__SIZEOF_TYPE, 1 , 1 );
2212
+ pslILEmit->EmitLabel (pHaveSizeLabel);
2213
+ }
2214
+ pslILEmit->EmitSTLOC (sizeLocal);
2215
+ pslILEmit->EmitLDLOC (sizeLocal);
2185
2216
pslILEmit->EmitLOCALLOC ();
2186
2217
pslILEmit->EmitDUP (); // for INITBLK
2187
2218
EmitStoreNativeValue (pslILEmit);
2188
2219
2189
2220
// initialize local block we just allocated
2190
2221
pslILEmit->EmitLDC (0 );
2191
- pslILEmit->EmitLDC (uNativeSize );
2222
+ pslILEmit->EmitLDLOC (sizeLocal );
2192
2223
pslILEmit->EmitINITBLK ();
2193
2224
2194
2225
pslILEmit->EmitLabel (pNullRefLabel);
@@ -2264,7 +2295,24 @@ void ILLayoutClassPtrMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
2264
2295
}
2265
2296
}
2266
2297
2298
+ bool ILLayoutClassPtrMarshalerBase::EmitExactTypeCheck (ILCodeStream* pslILEmit, ILCodeLabel* isNotMatchingTypeLabel)
2299
+ {
2300
+ STANDARD_VM_CONTRACT;
2267
2301
2302
+ if (m_pargs->m_pMT ->IsSealed ())
2303
+ {
2304
+ // If the provided type cannot be derived from, then we don't need to emit the type check.
2305
+ return false ;
2306
+ }
2307
+ EmitLoadManagedValue (pslILEmit);
2308
+ pslILEmit->EmitCALL (METHOD__OBJECT__GET_TYPE, 1 , 1 );
2309
+ pslILEmit->EmitLDTOKEN (pslILEmit->GetToken (m_pargs->m_pMT ));
2310
+ pslILEmit->EmitCALL (METHOD__TYPE__GET_TYPE_FROM_HANDLE, 1 , 1 );
2311
+ pslILEmit->EmitCALLVIRT (pslILEmit->GetToken (CoreLibBinder::GetMethod (METHOD__OBJECT__EQUALS)), 1 , 1 );
2312
+ pslILEmit->EmitBRFALSE (isNotMatchingTypeLabel);
2313
+
2314
+ return true ;
2315
+ }
2268
2316
2269
2317
void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative (ILCodeStream* pslILEmit)
2270
2318
{
@@ -2281,6 +2329,9 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* psl
2281
2329
pslILEmit->EmitLDC (uNativeSize);
2282
2330
pslILEmit->EmitINITBLK ();
2283
2331
2332
+ ILCodeLabel* isNotMatchingTypeLabel = pslILEmit->NewCodeLabel ();
2333
+ bool emittedTypeCheck = EmitExactTypeCheck (pslILEmit, isNotMatchingTypeLabel);
2334
+
2284
2335
MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub (m_pargs->m_pMT );
2285
2336
2286
2337
EmitLoadManagedValue (pslILEmit);
@@ -2290,6 +2341,18 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* psl
2290
2341
EmitLoadCleanupWorkList (pslILEmit);
2291
2342
2292
2343
pslILEmit->EmitCALL (pslILEmit->GetToken (pStructMarshalStub), 4 , 0 );
2344
+
2345
+ if (emittedTypeCheck)
2346
+ {
2347
+ pslILEmit->EmitBR (pNullRefLabel);
2348
+
2349
+ pslILEmit->EmitLabel (isNotMatchingTypeLabel);
2350
+ EmitLoadManagedValue (pslILEmit);
2351
+ EmitLoadNativeValue (pslILEmit);
2352
+ pslILEmit->EmitLDC (0 );
2353
+ pslILEmit->EmitCALL (METHOD__MARSHAL__STRUCTURE_TO_PTR, 3 , 0 );
2354
+ }
2355
+
2293
2356
pslILEmit->EmitLabel (pNullRefLabel);
2294
2357
}
2295
2358
@@ -2302,6 +2365,9 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* psl
2302
2365
EmitLoadManagedValue (pslILEmit);
2303
2366
pslILEmit->EmitBRFALSE (pNullRefLabel);
2304
2367
2368
+ ILCodeLabel* isNotMatchingTypeLabel = pslILEmit->NewCodeLabel ();
2369
+ bool emittedTypeCheck = EmitExactTypeCheck (pslILEmit, isNotMatchingTypeLabel);
2370
+
2305
2371
MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub (m_pargs->m_pMT );
2306
2372
2307
2373
EmitLoadManagedValue (pslILEmit);
@@ -2311,13 +2377,26 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* psl
2311
2377
EmitLoadCleanupWorkList (pslILEmit);
2312
2378
2313
2379
pslILEmit->EmitCALL (pslILEmit->GetToken (pStructMarshalStub), 4 , 0 );
2380
+ if (emittedTypeCheck)
2381
+ {
2382
+ pslILEmit->EmitBR (pNullRefLabel);
2383
+
2384
+ pslILEmit->EmitLabel (isNotMatchingTypeLabel);
2385
+ EmitLoadNativeValue (pslILEmit);
2386
+ EmitLoadManagedValue (pslILEmit);
2387
+ pslILEmit->EmitCALL (METHOD__MARSHAL__PTR_TO_STRUCTURE, 2 , 0 );
2388
+ }
2314
2389
pslILEmit->EmitLabel (pNullRefLabel);
2315
2390
}
2316
2391
2317
2392
void ILLayoutClassPtrMarshaler::EmitClearNativeContents (ILCodeStream * pslILEmit)
2318
2393
{
2319
2394
STANDARD_VM_CONTRACT;
2320
2395
2396
+ ILCodeLabel* isNotMatchingTypeLabel = pslILEmit->NewCodeLabel ();
2397
+ ILCodeLabel* cleanedUpLabel = pslILEmit->NewCodeLabel ();
2398
+ bool emittedTypeCheck = EmitExactTypeCheck (pslILEmit, isNotMatchingTypeLabel);
2399
+
2321
2400
MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub (m_pargs->m_pMT );
2322
2401
2323
2402
EmitLoadManagedValue (pslILEmit);
@@ -2327,6 +2406,19 @@ void ILLayoutClassPtrMarshaler::EmitClearNativeContents(ILCodeStream * pslILEmit
2327
2406
EmitLoadCleanupWorkList (pslILEmit);
2328
2407
2329
2408
pslILEmit->EmitCALL (pslILEmit->GetToken (pStructMarshalStub), 4 , 0 );
2409
+
2410
+ if (emittedTypeCheck)
2411
+ {
2412
+ pslILEmit->EmitBR (cleanedUpLabel);
2413
+
2414
+ pslILEmit->EmitLabel (isNotMatchingTypeLabel);
2415
+ EmitLoadNativeValue (pslILEmit);
2416
+ EmitLoadManagedValue (pslILEmit);
2417
+ pslILEmit->EmitCALL (METHOD__OBJECT__GET_TYPE, 1 , 1 );
2418
+ pslILEmit->EmitCALL (METHOD__MARSHAL__DESTROY_STRUCTURE, 2 , 0 );
2419
+ }
2420
+
2421
+ pslILEmit->EmitLabel (cleanedUpLabel);
2330
2422
}
2331
2423
2332
2424
@@ -2341,6 +2433,9 @@ void ILBlittablePtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslIL
2341
2433
EmitLoadNativeValue (pslILEmit);
2342
2434
pslILEmit->EmitBRFALSE (pNullRefLabel);
2343
2435
2436
+ ILCodeLabel* isNotMatchingTypeLabel = pslILEmit->NewCodeLabel ();
2437
+ bool emittedTypeCheck = EmitExactTypeCheck (pslILEmit, isNotMatchingTypeLabel);
2438
+
2344
2439
EmitLoadNativeValue (pslILEmit); // dest
2345
2440
2346
2441
EmitLoadManagedValue (pslILEmit);
@@ -2349,6 +2444,17 @@ void ILBlittablePtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslIL
2349
2444
pslILEmit->EmitLDC (uNativeSize); // size
2350
2445
2351
2446
pslILEmit->EmitCPBLK ();
2447
+
2448
+ if (emittedTypeCheck)
2449
+ {
2450
+ pslILEmit->EmitBR (pNullRefLabel);
2451
+
2452
+ pslILEmit->EmitLabel (isNotMatchingTypeLabel);
2453
+ EmitLoadManagedValue (pslILEmit);
2454
+ EmitLoadNativeValue (pslILEmit);
2455
+ pslILEmit->EmitLDC (0 );
2456
+ pslILEmit->EmitCALL (METHOD__MARSHAL__STRUCTURE_TO_PTR, 3 , 0 );
2457
+ }
2352
2458
pslILEmit->EmitLabel (pNullRefLabel);
2353
2459
}
2354
2460
@@ -2363,6 +2469,9 @@ void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslIL
2363
2469
EmitLoadManagedValue (pslILEmit);
2364
2470
pslILEmit->EmitBRFALSE (pNullRefLabel);
2365
2471
2472
+ ILCodeLabel* isNotMatchingTypeLabel = pslILEmit->NewCodeLabel ();
2473
+ bool emittedTypeCheck = EmitExactTypeCheck (pslILEmit, isNotMatchingTypeLabel);
2474
+
2366
2475
EmitLoadManagedValue (pslILEmit);
2367
2476
pslILEmit->EmitLDFLDA (fieldDef); // dest
2368
2477
@@ -2371,12 +2480,26 @@ void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslIL
2371
2480
pslILEmit->EmitLDC (uNativeSize); // size
2372
2481
2373
2482
pslILEmit->EmitCPBLK ();
2483
+
2484
+ if (emittedTypeCheck)
2485
+ {
2486
+ pslILEmit->EmitBR (pNullRefLabel);
2487
+
2488
+ pslILEmit->EmitLabel (isNotMatchingTypeLabel);
2489
+ EmitLoadNativeValue (pslILEmit);
2490
+ EmitLoadManagedValue (pslILEmit);
2491
+ pslILEmit->EmitCALL (METHOD__MARSHAL__PTR_TO_STRUCTURE, 2 , 0 );
2492
+ }
2493
+
2374
2494
pslILEmit->EmitLabel (pNullRefLabel);
2375
2495
}
2376
2496
2377
2497
bool ILBlittablePtrMarshaler::CanMarshalViaPinning ()
2378
2498
{
2379
- return IsCLRToNative (m_dwMarshalFlags) && !IsByref (m_dwMarshalFlags) && !IsFieldMarshal (m_dwMarshalFlags);
2499
+ return IsCLRToNative (m_dwMarshalFlags) &&
2500
+ !IsByref (m_dwMarshalFlags) &&
2501
+ !IsFieldMarshal (m_dwMarshalFlags) &&
2502
+ m_pargs->m_pMT ->IsSealed (); // We can't marshal via pinning if we might need to marshal differently at runtime. See calls to EmitExactTypeCheck where we check the runtime type of the object being marshalled.
2380
2503
}
2381
2504
2382
2505
void ILBlittablePtrMarshaler::EmitMarshalViaPinning (ILCodeStream* pslILEmit)
0 commit comments