Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/src/TypeSystem/Interop/IL/Marshaller.cs')
-rw-r--r--src/Common/src/TypeSystem/Interop/IL/Marshaller.cs159
1 files changed, 89 insertions, 70 deletions
diff --git a/src/Common/src/TypeSystem/Interop/IL/Marshaller.cs b/src/Common/src/TypeSystem/Interop/IL/Marshaller.cs
index ef75539f1..d7e88915d 100644
--- a/src/Common/src/TypeSystem/Interop/IL/Marshaller.cs
+++ b/src/Common/src/TypeSystem/Interop/IL/Marshaller.cs
@@ -718,6 +718,9 @@ namespace Internal.TypeSystem.Interop
PropagateToByRefArg(_ilCodeStreams.UnmarshallingCodestream, _managedHome);
}
}
+
+ // TODO This should be in finally block
+ // https://github.com/dotnet/corert/issues/6075
EmitCleanupManaged(_ilCodeStreams.UnmarshallingCodestream);
}
@@ -1634,9 +1637,9 @@ namespace Internal.TypeSystem.Interop
}
- class SafeHandleMarshaller : ReferenceMarshaller
+ class SafeHandleMarshaller : Marshaller
{
- protected override void AllocNativeToManaged(ILCodeStream codeStream)
+ private void AllocSafeHandle(ILCodeStream codeStream)
{
var ctor = ManagedType.GetParameterlessConstructor();
if (ctor == null)
@@ -1651,11 +1654,29 @@ namespace Internal.TypeSystem.Interop
codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(String.Format("'{0}' does not have a default constructor. Subclasses of SafeHandle must have a default constructor to support marshaling a Windows HANDLE into managed code.", name)));
codeStream.Emit(ILOpcode.newobj, emitter.NewToken(exceptionCtor));
codeStream.Emit(ILOpcode.throw_);
+ return;
}
- else
- {
- base.AllocNativeToManaged(codeStream);
- }
+
+ codeStream.Emit(ILOpcode.newobj, _ilCodeStreams.Emitter.NewToken(ctor));
+ }
+
+ protected override void EmitMarshalReturnValueManagedToNative()
+ {
+ ILEmitter emitter = _ilCodeStreams.Emitter;
+ ILCodeStream marshallingCodeStream = _ilCodeStreams.MarshallingCodeStream;
+ ILCodeStream returnValueMarshallingCodeStream = _ilCodeStreams.ReturnValueMarshallingCodeStream;
+
+ SetupArgumentsForReturnValueMarshalling();
+
+ AllocSafeHandle(marshallingCodeStream);
+ StoreManagedValue(marshallingCodeStream);
+
+ StoreNativeValue(returnValueMarshallingCodeStream);
+
+ LoadManagedValue(returnValueMarshallingCodeStream);
+ LoadNativeValue(returnValueMarshallingCodeStream);
+ returnValueMarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
+ InteropTypes.GetSafeHandle(Context).GetKnownMethod("SetHandle", null)));
}
protected override void EmitMarshalArgumentManagedToNative()
@@ -1672,42 +1693,13 @@ namespace Internal.TypeSystem.Interop
PropagateFromByRefArg(marshallingCodeStream, _managedHome);
}
- // TODO: https://github.com/dotnet/corert/issues/3291
- // We don't support [IN,OUT] together yet, either IN or OUT.
- if (Out && In)
- {
- throw new NotSupportedException("Marshalling an argument as both in and out not yet implemented");
- }
-
var safeHandleType = InteropTypes.GetSafeHandle(Context);
- if (Out && IsManagedByRef)
+ if (In)
{
- // 1) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We
- // must allocate this before the native call to avoid a failure point when we already have a native resource
- // allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native
- // handles need to be tracked and released by a SafeHandle.
- // 2) Initialize a local IntPtr that will be passed to the native call.
- // 3) After the native call, the new handle value is written into the output SafeHandle and that SafeHandle
- // is propagated back to the caller.
- var vOutValue = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.IntPtr));
- var vSafeHandle = emitter.NewLocal(ManagedType);
- marshallingCodeStream.Emit(ILOpcode.newobj, emitter.NewToken(ManagedType.GetParameterlessConstructor()));
- marshallingCodeStream.EmitStLoc(vSafeHandle);
- _ilCodeStreams.CallsiteSetupCodeStream.EmitLdLoca(vOutValue);
-
- unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
- unmarshallingCodeStream.EmitLdLoc(vOutValue);
- unmarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
- safeHandleType.GetKnownMethod("SetHandle", null)));
-
- unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
- StoreManagedValue(unmarshallingCodeStream);
+ if (IsManagedByRef)
+ PropagateFromByRefArg(marshallingCodeStream, _managedHome);
- PropagateToByRefArg(unmarshallingCodeStream, _managedHome);
- }
- else
- {
var vAddRefed = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Boolean));
LoadManagedValue(marshallingCodeStream);
marshallingCodeStream.EmitLdLoca(vAddRefed);
@@ -1719,44 +1711,56 @@ namespace Internal.TypeSystem.Interop
safeHandleType.GetKnownMethod("DangerousGetHandle", null)));
StoreNativeValue(marshallingCodeStream);
- // TODO: This should be inside finally block and only executed it the handle was addrefed
+ // TODO: This should be inside finally block and only executed if the handle was addrefed
+ // https://github.com/dotnet/corert/issues/6075
LoadManagedValue(unmarshallingCodeStream);
unmarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
safeHandleType.GetKnownMethod("DangerousRelease", null)));
-
- LoadNativeArg(_ilCodeStreams.CallsiteSetupCodeStream);
}
- }
+ if (Out && IsManagedByRef)
+ {
+ // 1) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We
+ // must allocate this before the native call to avoid a failure point when we already have a native resource
+ // allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native
+ // handles need to be tracked and released by a SafeHandle.
+ // 2) Initialize a local IntPtr that will be passed to the native call.
+ // 3) After the native call, the new handle value is written into the output SafeHandle and that SafeHandle
+ // is propagated back to the caller.
+ var vSafeHandle = emitter.NewLocal(ManagedType);
+ AllocSafeHandle(marshallingCodeStream);
+ marshallingCodeStream.EmitStLoc(vSafeHandle);
- protected override void TransformNativeToManaged(ILCodeStream codeStream)
- {
- LoadManagedValue(codeStream);
- LoadNativeValue(codeStream);
- codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken(
- InteropTypes.GetSafeHandle(Context).GetKnownMethod("SetHandle", null)));
- }
- }
+ var lSkipPropagation = emitter.NewCodeLabel();
+ if (In)
+ {
+ // Propagate the value only if it has changed
+ ILLocalVariable vOriginalValue = emitter.NewLocal(NativeType);
+ LoadNativeValue(marshallingCodeStream);
+ marshallingCodeStream.EmitStLoc(vOriginalValue);
+
+ unmarshallingCodeStream.EmitLdLoc(vOriginalValue);
+ LoadNativeValue(unmarshallingCodeStream);
+ unmarshallingCodeStream.Emit(ILOpcode.beq, lSkipPropagation);
+ }
- class ReferenceMarshaller : Marshaller
- {
- protected override void AllocNativeToManaged(ILCodeStream codeStream)
- {
- var emitter = _ilCodeStreams.Emitter;
- var lNull = emitter.NewCodeLabel();
+ unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
+ LoadNativeValue(unmarshallingCodeStream);
+ unmarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
+ safeHandleType.GetKnownMethod("SetHandle", null)));
- // Check for null
- LoadNativeValue(codeStream);
- codeStream.Emit(ILOpcode.brfalse, lNull);
+ unmarshallingCodeStream.EmitLdArg(Index - 1);
+ unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
+ unmarshallingCodeStream.EmitStInd(ManagedType);
- codeStream.Emit(ILOpcode.newobj, emitter.NewToken(
- ManagedType.GetParameterlessConstructor()));
- StoreManagedValue(codeStream);
- codeStream.EmitLabel(lNull);
+ unmarshallingCodeStream.EmitLabel(lSkipPropagation);
+ }
+
+ LoadNativeArg(callsiteCodeStream);
}
}
- class StringBuilderMarshaller : ReferenceMarshaller
+ class StringBuilderMarshaller : Marshaller
{
private bool _isAnsi;
public StringBuilderMarshaller(bool isAnsi)
@@ -1778,6 +1782,21 @@ namespace Internal.TypeSystem.Interop
Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree")));
}
+ protected override void AllocNativeToManaged(ILCodeStream codeStream)
+ {
+ var emitter = _ilCodeStreams.Emitter;
+ var lNull = emitter.NewCodeLabel();
+
+ // Check for null
+ LoadNativeValue(codeStream);
+ codeStream.Emit(ILOpcode.brfalse, lNull);
+
+ codeStream.Emit(ILOpcode.newobj, emitter.NewToken(
+ ManagedType.GetParameterlessConstructor()));
+ StoreManagedValue(codeStream);
+ codeStream.EmitLabel(lNull);
+ }
+
protected override void AllocManagedToNative(ILCodeStream codeStream)
{
ILEmitter emitter = _ilCodeStreams.Emitter;
@@ -1877,8 +1896,8 @@ namespace Internal.TypeSystem.Interop
protected override void TransformNativeToManaged(ILCodeStream codeStream)
{
- LoadManagedAddr(codeStream);
LoadNativeAddr(codeStream);
+ LoadManagedAddr(codeStream);
codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken(
InteropStateManager.GetStructMarshallingNativeToManagedThunk(ManagedType)));
}
@@ -2072,7 +2091,7 @@ namespace Internal.TypeSystem.Interop
var managedElementType = ((ArrayType)ManagedType).ElementType;
ILLocalVariable vLength = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));
- codeStream.EmitLdArg(0);
+ codeStream.EmitLdArg(1);
// load the length
EmitElementCount(codeStream, MarshalDirection.Reverse);
codeStream.EmitStLoc(vLength);
@@ -2092,13 +2111,13 @@ namespace Internal.TypeSystem.Interop
codeStream.EmitLabel(lLoopHeader);
// load managed type
- codeStream.EmitLdArg(0);
+ codeStream.EmitLdArg(1);
codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField));
codeStream.EmitLdLoc(vIndex);
// load native type
- codeStream.EmitLdArg(1);
+ codeStream.EmitLdArg(0);
codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField));
codeStream.EmitLdLoc(vIndex);
@@ -2172,9 +2191,9 @@ namespace Internal.TypeSystem.Interop
ILEmitter emitter = _ilCodeStreams.Emitter;
ILCodeStream codeStream = _ilCodeStreams.UnmarshallingCodestream;
- codeStream.EmitLdArg(0);
-
codeStream.EmitLdArg(1);
+
+ codeStream.EmitLdArg(0);
codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField));
codeStream.Emit(ILOpcode.conv_u);