@@ -1448,31 +1448,44 @@ protected override void TransformManagedToNative(ILCodeStream codeStream)
1448
1448
if ( ShouldBePinned )
1449
1449
{
1450
1450
//
1451
- // Pin the string and push a pointer to the first character on the stack.
1451
+ // Pin the char& and push a pointer to the first character on the stack.
1452
1452
//
1453
- TypeDesc stringType = Context . GetWellKnownType ( WellKnownType . String ) ;
1453
+ TypeDesc charRefType = Context . GetWellKnownType ( WellKnownType . Char ) . MakeByRefType ( ) ;
1454
1454
1455
- ILLocalVariable vPinnedString = emitter . NewLocal ( stringType , true ) ;
1456
- ILCodeLabel lNullString = emitter . NewCodeLabel ( ) ;
1455
+ ILLocalVariable vPinnedCharRef = emitter . NewLocal ( charRefType , true ) ;
1457
1456
1458
- LoadManagedValue ( codeStream ) ;
1459
- codeStream . EmitStLoc ( vPinnedString ) ;
1460
- codeStream . EmitLdLoc ( vPinnedString ) ;
1457
+ ILCodeLabel lNonNullString = emitter . NewCodeLabel ( ) ;
1458
+ ILCodeLabel lCommonExit = emitter . NewCodeLabel ( ) ;
1461
1459
1462
- codeStream . Emit ( ILOpcode . conv_i ) ;
1463
- codeStream . Emit ( ILOpcode . dup ) ;
1460
+ LoadManagedValue ( codeStream ) ;
1461
+ codeStream . Emit ( ILOpcode . brtrue , lNonNullString ) ;
1464
1462
1465
- // Marshalling a null string?
1466
- codeStream . Emit ( ILOpcode . brfalse , lNullString ) ;
1463
+ //
1464
+ // Null input case
1465
+ // Don't pin anything - load a zero-value nuint (void*) onto the stack
1466
+ //
1467
+ codeStream . Emit ( ILOpcode . ldc_i4_0 ) ;
1468
+ codeStream . Emit ( ILOpcode . conv_u ) ;
1469
+ codeStream . Emit ( ILOpcode . br , lCommonExit ) ;
1467
1470
1471
+ //
1472
+ // Non-null input case
1473
+ // Extract the char& from the string, pin it, then convert it to a nuint (void*)
1474
+ //
1475
+ codeStream . EmitLabel ( lNonNullString ) ;
1476
+ LoadManagedValue ( codeStream ) ;
1468
1477
codeStream . Emit ( ILOpcode . call , emitter . NewToken (
1469
- Context . SystemModule .
1470
- GetKnownType ( "System.Runtime.CompilerServices ", "RuntimeHelpers" ) .
1471
- GetKnownMethod ( "get_OffsetToStringData" , null ) ) ) ;
1472
-
1473
- codeStream . Emit ( ILOpcode . add ) ;
1478
+ Context . GetWellKnownType ( WellKnownType . String ) .
1479
+ GetKnownMethod ( "GetPinnableReference ", null ) ) ) ;
1480
+ codeStream . EmitStLoc ( vPinnedCharRef ) ;
1481
+ codeStream . EmitLdLoc ( vPinnedCharRef ) ;
1482
+ codeStream . Emit ( ILOpcode . conv_u ) ;
1474
1483
1475
- codeStream . EmitLabel ( lNullString ) ;
1484
+ //
1485
+ // Common exit
1486
+ // Top of stack contains a nuint (void*) pointing to start of char data, or nullptr
1487
+ //
1488
+ codeStream . EmitLabel ( lCommonExit ) ;
1476
1489
StoreNativeValue ( codeStream ) ;
1477
1490
}
1478
1491
else
0 commit comments