IDS_EE_CANNOTCAST_NOMARSHAL "The Windows Runtime Object can only be used in the threading context where it was created, because it implements INoMarshal or has MarshalingBehaviorAttribute(MarshalingType.None) set."
IDS_EE_WINRT_WEAKREF_BAD_TYPE "The object resolved by a native IWeakReference has an incompatible type for its managed WeakReference instance.\r\nExpected WeakReference target type: '%1'\r\nNative IWeakReference returned type: '%2'"
#endif // FEATURE_COMINTEROP
-
+
+ IDS_EE_INTEROP_CODE_SIZE_COMMENT "Code size"
+
IDS_EE_ADUNLOAD_IN_FINALIZER "AppDomain cannot be unloaded during object finalization."
IDS_EE_ADUNLOAD_DEFAULT "The default domain cannot be unloaded."
IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD "AppDomain cannot be unloaded because the thread '%1' cannot be unwound out of it."
#define IDS_EE_INTEROP_STUB_CA_NO_ACCESS_TO_STUB_METHOD 0x2111
#endif
+#define IDS_EE_INTEROP_CODE_SIZE_COMMENT 0x2112
+
#define BFA_REFERENCE_ASSEMBLY 0x2113
#define IDS_E_FIELDACCESS 0x2114
cbz x0, COMToCLRDispatchHelper_RegSetup
add x9, x1, #SIZEOF__ComMethodFrame
- add x9, x9, x0, LSL #3
+
+ ; Compute number of 8 bytes slots to copy. This is done by rounding up the
+ ; dwStackSlots value to the nearest even value
+ add x0, x0, #1
+ bic x0, x0, #1
+
+ ; Compute how many slots to adjust the address to copy from. Since we
+ ; are copying 16 bytes at a time, adjust by -1 from the rounded value
+ sub x6, x0, #1
+ add x9, x9, x6, LSL #3
+
COMToCLRDispatchHelper_StackLoop
- ldr x8, [x9, #-8]!
- str x8, [sp, #-8]!
- sub x0, x0, #1
- cbnz x0, COMToCLRDispatchHelper_StackLoop
+ ldp x7, x8, [x9], #-16 ; post-index
+ stp x7, x8, [sp, #-16]! ; pre-index
+ subs x0, x0, #2
+ bne COMToCLRDispatchHelper_StackLoop
COMToCLRDispatchHelper_RegSetup
}
LOG((LF_STUBS, LL_INFO1000, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"));
#endif // LOGGING
+
+ //
+ // Publish ETW events for IL stubs
+ //
+ // If the category and the event is enabled...
+ if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ILStubGenerated))
+ {
+ EtwOnILStubGenerated(
+ pStubMD,
+ pbLocalSig,
+ cbSig,
+ jitFlags,
+ &convertToHRTryCatch,
+ &cleanupTryFinally,
+ maxStack,
+ (DWORD)cbCode
+ );
+ }
+
}
+ //---------------------------------------------------------------------------------------
+ //
+ void
+ EtwOnILStubGenerated(
+ MethodDesc * pStubMD,
+ PCCOR_SIGNATURE pbLocalSig,
+ DWORD cbSig,
+ CORJIT_FLAGS jitFlags,
+ ILStubEHClause * pConvertToHRTryCatchBounds,
+ ILStubEHClause * pCleanupTryFinallyBounds,
+ DWORD maxStack,
+ DWORD cbCode)
+ {
+ STANDARD_VM_CONTRACT;
+
+ //
+ // Interop Method Information
+ //
+ MethodDesc *pTargetMD = m_slIL.GetTargetMD();
+ SString strNamespaceOrClassName, strMethodName, strMethodSignature;
+ UINT64 uModuleId = 0;
+
+ if (pTargetMD)
+ {
+ pTargetMD->GetMethodInfoWithNewSig(strNamespaceOrClassName, strMethodName, strMethodSignature);
+ uModuleId = (UINT64)pTargetMD->GetModule()->GetAddrModuleID();
+ }
+
+ //
+ // Stub Method Signature
+ //
+ SString stubNamespaceOrClassName, stubMethodName, stubMethodSignature;
+ pStubMD->GetMethodInfoWithNewSig(stubNamespaceOrClassName, stubMethodName, stubMethodSignature);
+
+ IMDInternalImport *pStubImport = pStubMD->GetModule()->GetMDImport();
+
+ CQuickBytes qbLocal;
+ PrettyPrintSig(pbLocalSig, (DWORD)cbSig, NULL, &qbLocal, pStubImport, NULL);
+
+ SString strLocalSig(SString::Utf8, (LPCUTF8)qbLocal.Ptr());
+
+ //
+ // Native Signature
+ //
+ SString strNativeSignature(SString::Utf8);
+ if (m_dwStubFlags & NDIRECTSTUB_FL_REVERSE_INTEROP)
+ {
+ // Reverse interop. Use StubSignature
+ strNativeSignature = stubMethodSignature;
+ }
+ else
+ {
+ // Forward interop. Use StubTarget siganture
+ PCCOR_SIGNATURE pCallTargetSig = GetStubTargetMethodSig();
+ DWORD cCallTargetSig = GetStubTargetMethodSigLength();
+
+ CQuickBytes qbCallTargetSig;
+
+ PrettyPrintSig(pCallTargetSig, cCallTargetSig, "", &qbCallTargetSig, pStubImport, NULL);
+
+ strNativeSignature.SetUTF8((LPCUTF8)qbCallTargetSig.Ptr());
+ }
+
+ //
+ // Dump IL stub code
+ //
+ SString strILStubCode;
+ strILStubCode.Preallocate(4096); // Preallocate 4K bytes to avoid unnecessary growth
+
+ SString codeSizeFormat;
+ codeSizeFormat.LoadResource(CCompRC::Optional, IDS_EE_INTEROP_CODE_SIZE_COMMENT);
+ strILStubCode.AppendPrintf(W("// %s\t%d (0x%04x)\n"), codeSizeFormat.GetUnicode(), cbCode, cbCode);
+ strILStubCode.AppendPrintf(W(".maxstack %d \n"), maxStack);
+ strILStubCode.AppendPrintf(W(".locals %s\n"), strLocalSig.GetUnicode());
+
+ m_slIL.LogILStub(jitFlags, &strILStubCode);
+
+ if (pConvertToHRTryCatchBounds->cbTryLength != 0 && pConvertToHRTryCatchBounds->cbHandlerLength != 0)
+ {
+ strILStubCode.AppendPrintf(
+ W(".try IL_%04x to IL_%04x catch handler IL_%04x to IL_%04x\n"),
+ pConvertToHRTryCatchBounds->dwTryBeginOffset,
+ pConvertToHRTryCatchBounds->dwTryBeginOffset + pConvertToHRTryCatchBounds->cbTryLength,
+ pConvertToHRTryCatchBounds->dwHandlerBeginOffset,
+ pConvertToHRTryCatchBounds->dwHandlerBeginOffset + pConvertToHRTryCatchBounds->cbHandlerLength);
+ }
+
+ if (pCleanupTryFinallyBounds->cbTryLength != 0 && pCleanupTryFinallyBounds->cbHandlerLength != 0)
+ {
+ strILStubCode.AppendPrintf(
+ W(".try IL_%04x to IL_%04x finally handler IL_%04x to IL_%04x\n"),
+ pCleanupTryFinallyBounds->dwTryBeginOffset,
+ pCleanupTryFinallyBounds->dwTryBeginOffset + pCleanupTryFinallyBounds->cbTryLength,
+ pCleanupTryFinallyBounds->dwHandlerBeginOffset,
+ pCleanupTryFinallyBounds->dwHandlerBeginOffset + pCleanupTryFinallyBounds->cbHandlerLength);
+ }
+
+ //
+ // Fire the event
+ //
+ DWORD dwFlags = 0;
+ if (m_dwStubFlags & NDIRECTSTUB_FL_REVERSE_INTEROP)
+ dwFlags |= ETW_IL_STUB_FLAGS_REVERSE_INTEROP;
+#ifdef FEATURE_COMINTEROP
+ if (m_dwStubFlags & NDIRECTSTUB_FL_COM)
+ dwFlags |= ETW_IL_STUB_FLAGS_COM_INTEROP;
+#endif // FEATURE_COMINTEROP
+ if (m_dwStubFlags & NDIRECTSTUB_FL_NGENEDSTUB)
+ dwFlags |= ETW_IL_STUB_FLAGS_NGENED_STUB;
+ if (m_dwStubFlags & NDIRECTSTUB_FL_DELEGATE)
+ dwFlags |= ETW_IL_STUB_FLAGS_DELEGATE;
+ if (m_dwStubFlags & NDIRECTSTUB_FL_CONVSIGASVARARG)
+ dwFlags |= ETW_IL_STUB_FLAGS_VARARG;
+ if (m_dwStubFlags & NDIRECTSTUB_FL_UNMANAGED_CALLI)
+ dwFlags |= ETW_IL_STUB_FLAGS_UNMANAGED_CALLI;
+
+ DWORD dwToken = 0;
+ if (pTargetMD)
+ dwToken = pTargetMD->GetMemberDef();
+
+
+ //
+ // Truncate string fields. Make sure the whole event is less than 64KB
+ //
+ TruncateUnicodeString(strNamespaceOrClassName, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE);
+ TruncateUnicodeString(strMethodName, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE);
+ TruncateUnicodeString(strMethodSignature, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE);
+ TruncateUnicodeString(strNativeSignature, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE);
+ TruncateUnicodeString(stubMethodSignature, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE);
+ TruncateUnicodeString(strILStubCode, ETW_IL_STUB_EVENT_CODE_STRING_FIELD_MAXSIZE);
+
+ //
+ // Fire ETW event
+ //
+ FireEtwILStubGenerated(
+ GetClrInstanceId(), // ClrInstanceId
+ uModuleId, // ModuleIdentifier
+ (UINT64)pStubMD, // StubMethodIdentifier
+ dwFlags, // StubFlags
+ dwToken, // ManagedInteropMethodToken
+ strNamespaceOrClassName.GetUnicode(), // ManagedInteropMethodNamespace
+ strMethodName.GetUnicode(), // ManagedInteropMethodName
+ strMethodSignature.GetUnicode(), // ManagedInteropMethodSignature
+ strNativeSignature.GetUnicode(), // NativeSignature
+ stubMethodSignature.GetUnicode(), // StubMethodSigature
+ strILStubCode.GetUnicode() // StubMethodILCode
+ );
+ } // EtwOnILStubGenerated
#ifdef LOGGING
//---------------------------------------------------------------------------------------
this.Marshal_Float(a / 100f, b / 100f);
this.Marshal_Double(a / 100.0, b / 100.0);
+ this.Marshal_ManyInts();
}
static private bool EqualByBound(float expected, float actual)
this.server.Add_Double_Out(a, b, out c);
Assert.IsTrue(EqualByBound(expected, c));
}
+
+ private void Marshal_ManyInts()
+ {
+ var expected = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11;
+ Console.WriteLine($"{expected.GetType().Name} 11 test invariant: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 = {expected}");
+ Assert.IsTrue(expected == this.server.Add_ManyInts11(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
+ expected = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12;
+ Console.WriteLine($"{expected.GetType().Name} 12 test invariant: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 = {expected}");
+ Assert.IsTrue(expected == this.server.Add_ManyInts12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
+ }
}
}
{
c = a + b;
}
+
+ public int Add_ManyInts11(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11)
+ {
+ return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11;
+ }
+
+ public int Add_ManyInts12(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12)
+ {
+ return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12;
+ }
}
\ No newline at end of file
THROW_IF_FAILED(numericTesting->Add_Double_Out(a, b, &c));
THROW_FAIL_IF_FALSE(EqualByBound(expected, c));
}
+
+ void MarshalManyInts(_In_ INumericTesting *numericTesting)
+ {
+ HRESULT hr;
+
+ int expected = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11;
+ ::printf("Many ints 11 test invariant: 1 + 2 + 3 + 4... + 11 = %d\n", expected);
+
+ int result = 0;
+ THROW_IF_FAILED(numericTesting->Add_ManyInts11(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, &result));
+ THROW_FAIL_IF_FALSE(result == expected);
+
+ expected = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12;
+ ::printf("Many ints 12 test invariant: 1 + 2 + 3 + 4... + 11 + 12= %d\n", expected);
+
+ result = 0;
+ THROW_IF_FAILED(numericTesting->Add_ManyInts12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &result));
+ THROW_FAIL_IF_FALSE(result == expected);
+ }
}
void Run_NumericTests()
MarshalULong(numericTesting, (uint64_t)a, (uint64_t)b);
MarshalFloat(numericTesting, (float)a / 100.f, (float)b / 100.f);
MarshalDouble(numericTesting, (double)a / 100.0, (double)b / 100.0);
+ MarshalManyInts(numericTesting);
}
return S_OK;
}
+ DEF_FUNC(Add_ManyInts11)(
+ /*[in]*/ int i1,
+ /*[in]*/ int i2,
+ /*[in]*/ int i3,
+ /*[in]*/ int i4,
+ /*[in]*/ int i5,
+ /*[in]*/ int i6,
+ /*[in]*/ int i7,
+ /*[in]*/ int i8,
+ /*[in]*/ int i9,
+ /*[in]*/ int i10,
+ /*[in]*/ int i11,
+ /*[out]*/ int * result )
+ {
+ *result = i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11;
+ return S_OK;
+ }
+
+ DEF_FUNC(Add_ManyInts12)(
+ /*[in]*/ int i1,
+ /*[in]*/ int i2,
+ /*[in]*/ int i3,
+ /*[in]*/ int i4,
+ /*[in]*/ int i5,
+ /*[in]*/ int i6,
+ /*[in]*/ int i7,
+ /*[in]*/ int i8,
+ /*[in]*/ int i9,
+ /*[in]*/ int i10,
+ /*[in]*/ int i11,
+ /*[in]*/ int i12,
+ /*[out]*/ int * result )
+ {
+ *result = i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12;
+ return S_OK;
+ }
+
public: // IUnknown
STDMETHOD(QueryInterface)(
/* [in] */ REFIID riid,
void Add_ULong_Out(ulong a, ulong b, out ulong c);
void Add_Float_Out(float a, float b, out float c);
void Add_Double_Out(double a, double b, out double c);
+
+ int Add_ManyInts11(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11);
+ int Add_ManyInts12(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12);
}
[ComVisible(true)]
/*[in]*/ double a,
/*[in]*/ double b,
/*[out]*/ double * c ) = 0;
+ virtual HRESULT STDMETHODCALLTYPE Add_ManyInts11 (
+ /*[in]*/ int i1,
+ /*[in]*/ int i2,
+ /*[in]*/ int i3,
+ /*[in]*/ int i4,
+ /*[in]*/ int i5,
+ /*[in]*/ int i6,
+ /*[in]*/ int i7,
+ /*[in]*/ int i8,
+ /*[in]*/ int i9,
+ /*[in]*/ int i10,
+ /*[in]*/ int i11,
+ /*[out]*/ int * result ) = 0;
+ virtual HRESULT STDMETHODCALLTYPE Add_ManyInts12 (
+ /*[in]*/ int i1,
+ /*[in]*/ int i2,
+ /*[in]*/ int i3,
+ /*[in]*/ int i4,
+ /*[in]*/ int i5,
+ /*[in]*/ int i6,
+ /*[in]*/ int i7,
+ /*[in]*/ int i8,
+ /*[in]*/ int i9,
+ /*[in]*/ int i10,
+ /*[in]*/ int i11,
+ /*[in]*/ int i12,
+ /*[out]*/ int * result ) = 0;
};
struct __declspec(uuid("7731cb31-e063-4cc8-bcd2-d151d6bc8f43"))