From 045335bb661be28cbdffa3b1e2d8ccbc2667fd58 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 28 Jul 2017 11:53:01 -0400 Subject: [PATCH 1/2] Add generic encoding support to metasig --- src/vm/binder.cpp | 101 +++++++++++++++++++++++++--------------------- src/vm/binder.h | 1 + src/vm/metasig.h | 6 +++ 3 files changed, 62 insertions(+), 46 deletions(-) diff --git a/src/vm/binder.cpp b/src/vm/binder.cpp index 9ce1584c31b4..6a60712e3f8f 100644 --- a/src/vm/binder.cpp +++ b/src/vm/binder.cpp @@ -311,6 +311,58 @@ Signature MscorlibBinder::GetSignatureLocal(LPHARDCODEDMETASIG pHardcodedSig) #ifndef DACCESS_COMPILE +bool MscorlibBinder::ConvertType(const BYTE*& pSig, SigBuilder * pSigBuilder) +{ + bool bSomethingResolved = false; + + CorElementType type = (CorElementType)*pSig++; + + switch (type) + { + case ELEMENT_TYPE_GENERICINST: + { + pSigBuilder->AppendElementType(type); + if (ConvertType(pSig, pSigBuilder)) + bSomethingResolved = true; + int arity = *pSig++; + pSigBuilder->AppendData(arity); + for (int i = 0; i < arity; i++) + { + if (ConvertType(pSig, pSigBuilder)) + bSomethingResolved = true; + } + } + break; + + case ELEMENT_TYPE_BYREF: + case ELEMENT_TYPE_PTR: + case ELEMENT_TYPE_SZARRAY: + pSigBuilder->AppendElementType(type); + if (ConvertType(pSig, pSigBuilder)) + bSomethingResolved = true; + break; + + case ELEMENT_TYPE_CLASS: + case ELEMENT_TYPE_VALUETYPE: + { + // The binder class id may overflow 1 byte. Use 2 bytes to encode it. + BinderClassID id = (BinderClassID)(*pSig + 0x100 * *(pSig + 1)); + pSig += 2; + + pSigBuilder->AppendElementType(type); + pSigBuilder->AppendToken(GetClassLocal(id)->GetCl()); + bSomethingResolved = true; + } + break; + + default: + pSigBuilder->AppendElementType(type); + break; + } + + return bSomethingResolved; +} + //------------------------------------------------------------------ // Resolve type references in the hardcoded metasig. // Returns a new signature with type refences resolved. @@ -327,7 +379,7 @@ void MscorlibBinder::BuildConvertedSignature(const BYTE* pSig, SigBuilder * pSig unsigned argCount; unsigned callConv; - INDEBUG(bool bSomethingResolved = false;) + bool bSomethingResolved = false; // calling convention callConv = *pSig++; @@ -346,51 +398,8 @@ void MscorlibBinder::BuildConvertedSignature(const BYTE* pSig, SigBuilder * pSig // <= because we want to include the return value or the field for (unsigned i = 0; i <= argCount; i++) { - - for (;;) { - BinderClassID id = CLASS__NIL; - bool again = false; - - CorElementType type = (CorElementType)*pSig++; - - switch (type) - { - case ELEMENT_TYPE_BYREF: - case ELEMENT_TYPE_PTR: - case ELEMENT_TYPE_SZARRAY: - again = true; - break; - - case ELEMENT_TYPE_CLASS: - case ELEMENT_TYPE_VALUETYPE: - // The binder class id may overflow 1 byte. Use 2 bytes to encode it. - id = (BinderClassID) (*pSig + 0x100 * *(pSig + 1)); - pSig += 2; - break; - - case ELEMENT_TYPE_VOID: - if (i != 0) { - if (pSig[-2] != ELEMENT_TYPE_PTR) - THROW_BAD_FORMAT(BFA_ONLY_VOID_PTR_IN_ARGS, (Module*)NULL); // only pointer to void allowed in arguments - } - break; - - default: - break; - } - - pSigBuilder->AppendElementType(type); - - if (id != CLASS__NIL) - { - pSigBuilder->AppendToken(GetClassLocal(id)->GetCl()); - - INDEBUG(bSomethingResolved = true;) - } - - if (!again) - break; - } + if (ConvertType(pSig, pSigBuilder)) + bSomethingResolved = true; } _ASSERTE(bSomethingResolved); diff --git a/src/vm/binder.h b/src/vm/binder.h index 8e26bdd25506..ad80292ea0a4 100644 --- a/src/vm/binder.h +++ b/src/vm/binder.h @@ -277,6 +277,7 @@ class MscorlibBinder Signature GetSignatureLocal(LPHARDCODEDMETASIG pHardcodedSig); + bool ConvertType(const BYTE*& pSig, SigBuilder * pSigBuilder); void BuildConvertedSignature(const BYTE* pSig, SigBuilder * pSigBuilder); const BYTE* ConvertSignature(LPHARDCODEDMETASIG pHardcodedSig, const BYTE* pSig); diff --git a/src/vm/metasig.h b/src/vm/metasig.h index c2dc42fb9d9a..f8d9cfe5e121 100644 --- a/src/vm/metasig.h +++ b/src/vm/metasig.h @@ -56,6 +56,7 @@ // T -- TypedReference -- TypedReference // G -- -- Generic type variable // M -- -- Generic method variable +// GI -- -- Generic type instantiation // //#DEFINE_METASIG @@ -128,6 +129,8 @@ #define G(n) METASIG_ATOM(ELEMENT_TYPE_VAR) METASIG_ATOM(n) #define M(n) METASIG_ATOM(ELEMENT_TYPE_MVAR) METASIG_ATOM(n) +#define GI(type, n, x) METASIG_ATOM(ELEMENT_TYPE_GENERICINST) type METASIG_ATOM(n) x + // The references to other types have special definition in some cases #ifndef C #define C(x) METASIG_ATOM(ELEMENT_TYPE_CLASS) METASIG_ATOM(CLASS__ ## x % 0x100) METASIG_ATOM(CLASS__ ## x / 0x100) @@ -145,6 +148,8 @@ #define G(n) METASIG_ATOM(ELEMENT_TYPE_VAR) #define M(n) METASIG_ATOM(ELEMENT_TYPE_MVAR) +#define GI(type, n, x) METASIG_ATOM(ELEMENT_TYPE_GENERICINST) + // The references to other types have special definition in some cases #ifndef C #define C(x) METASIG_ATOM(ELEMENT_TYPE_CLASS) @@ -608,6 +613,7 @@ DEFINE_METASIG_T(IM(IAsyncResult_RetVoid, C(IASYNCRESULT), v)) #undef T #undef G #undef M +#undef GI #undef _ From 5f2fb65bcf76354ea6ec43c00714e230378d4e4d Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 28 Jul 2017 12:00:09 -0400 Subject: [PATCH 2/2] Add String(ReadOnlySpan) ctor --- src/mscorlib/src/System/String.cs | 17 +++++++++++++++++ src/vm/ecall.cpp | 4 +++- src/vm/ecall.h | 1 + src/vm/ecalllist.h | 1 + src/vm/metasig.h | 2 ++ src/vm/mscorlib.h | 1 + 6 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/mscorlib/src/System/String.cs b/src/mscorlib/src/System/String.cs index a34ea2142362..9520cce6641e 100644 --- a/src/mscorlib/src/System/String.cs +++ b/src/mscorlib/src/System/String.cs @@ -666,6 +666,23 @@ private unsafe String CtorCharPtrStartLength(char* ptr, int startIndex, int leng [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern String(char c, int count); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern String(ReadOnlySpan value); + + private unsafe string CtorReadOnlySpanOfChar(ReadOnlySpan value) + { + if (value.Length == 0) + { + return Empty; + } + + string result = FastAllocateString(value.Length); + fixed (char* dest = &result._firstChar, src = &value.DangerousGetPinnableReference()) + { + wstrcpy(dest, src, value.Length); + } + return result; + } // Returns this string. public override String ToString() diff --git a/src/vm/ecall.cpp b/src/vm/ecall.cpp index f3b0099e5794..97255e15a1bc 100644 --- a/src/vm/ecall.cpp +++ b/src/vm/ecall.cpp @@ -36,6 +36,7 @@ static_assert_no_msg(METHOD__STRING__CTORF_FIRST + 1 == METHOD__STRING__CTORF_CH static_assert_no_msg(METHOD__STRING__CTORF_FIRST + 2 == METHOD__STRING__CTORF_CHAR_COUNT); static_assert_no_msg(METHOD__STRING__CTORF_FIRST + 3 == METHOD__STRING__CTORF_CHARPTR); static_assert_no_msg(METHOD__STRING__CTORF_FIRST + 4 == METHOD__STRING__CTORF_CHARPTR_START_LEN); +static_assert_no_msg(METHOD__STRING__CTORF_FIRST + 5 == METHOD__STRING__CTORF_READONLYSPANOFCHAR); // ECall::CtorCharXxx has to be in same order as METHOD__STRING__CTORF_XXX #define ECallCtor_First ECall::CtorCharArrayManaged @@ -44,8 +45,9 @@ static_assert_no_msg(ECallCtor_First + 1 == ECall::CtorCharArrayStartLengthManag static_assert_no_msg(ECallCtor_First + 2 == ECall::CtorCharCountManaged); static_assert_no_msg(ECallCtor_First + 3 == ECall::CtorCharPtrManaged); static_assert_no_msg(ECallCtor_First + 4 == ECall::CtorCharPtrStartLengthManaged); +static_assert_no_msg(ECallCtor_First + 5 == ECall::CtorReadOnlySpanOfCharManaged); -#define NumberOfStringConstructors 5 +#define NumberOfStringConstructors 6 void ECall::PopulateManagedStringConstructors() { diff --git a/src/vm/ecall.h b/src/vm/ecall.h index c4fed1ff42f2..26fa9eb47810 100644 --- a/src/vm/ecall.h +++ b/src/vm/ecall.h @@ -110,6 +110,7 @@ class ECall DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorCharCountManaged, NULL) \ DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorCharPtrManaged, NULL) \ DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorCharPtrStartLengthManaged, NULL) \ + DYNAMICALLY_ASSIGNED_FCALL_IMPL(CtorReadOnlySpanOfCharManaged, NULL) \ DYNAMICALLY_ASSIGNED_FCALL_IMPL(InternalGetCurrentThread, NULL) \ enum diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index 13cd6d58dfd4..5bac53635d65 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -109,6 +109,7 @@ FCFuncStart(gStringFuncs) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrChar_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharPtrManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrChar_Int_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharPtrStartLengthManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_Char_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharCountManaged) + FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_ReadOnlySpanOfChar_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorReadOnlySpanOfCharManaged) FCFuncElementSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrSByt_RetVoid, COMString::StringInitCharPtr) FCFuncElementSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrSByt_Int_Int_RetVoid, COMString::StringInitCharPtrPartial) FCFuncElementSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrSByt_Int_Int_Encoding_RetVoid, COMString::StringInitSBytPtrPartialEx) diff --git a/src/vm/metasig.h b/src/vm/metasig.h index f8d9cfe5e121..9a037aa3e08f 100644 --- a/src/vm/metasig.h +++ b/src/vm/metasig.h @@ -387,6 +387,7 @@ DEFINE_METASIG(IM(Bool_Bool_RetStr, F F, s)) DEFINE_METASIG(IM(PtrChar_RetVoid, P(u), v)) DEFINE_METASIG(IM(PtrChar_Int_Int_RetVoid, P(u) i i, v)) +DEFINE_METASIG_T(IM(ReadOnlySpanOfChar_RetVoid, GI(g(READONLY_SPAN), 1, u), v)) DEFINE_METASIG(IM(PtrSByt_RetVoid, P(B), v)) DEFINE_METASIG(IM(PtrSByt_Int_Int_RetVoid, P(B) i i, v)) DEFINE_METASIG_T(IM(PtrSByt_Int_Int_Encoding_RetVoid, P(B) i i C(ENCODING), v)) @@ -398,6 +399,7 @@ DEFINE_METASIG(IM(ArrChar_Int_Int_RetStr, a(u) i i, s)) DEFINE_METASIG(IM(Char_Int_RetStr, u i, s)) DEFINE_METASIG(IM(PtrChar_RetStr, P(u), s)) DEFINE_METASIG(IM(PtrChar_Int_Int_RetStr, P(u) i i, s)) +DEFINE_METASIG_T(IM(ReadOnlySpanOfChar_RetStr, GI(g(READONLY_SPAN), 1, u), s)) DEFINE_METASIG(IM(Obj_Int_RetIntPtr, j i, I)) DEFINE_METASIG(IM(Char_Char_RetStr, u u, s)) diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index a9574213afd0..1753149a0e6d 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -881,6 +881,7 @@ DEFINE_METHOD(STRING, CTORF_CHARARRAY_START_LEN,CtorCharArrayStart DEFINE_METHOD(STRING, CTORF_CHAR_COUNT, CtorCharCount, IM_Char_Int_RetStr) DEFINE_METHOD(STRING, CTORF_CHARPTR, CtorCharPtr, IM_PtrChar_RetStr) DEFINE_METHOD(STRING, CTORF_CHARPTR_START_LEN,CtorCharPtrStartLength, IM_PtrChar_Int_Int_RetStr) +DEFINE_METHOD(STRING, CTORF_READONLYSPANOFCHAR,CtorReadOnlySpanOfChar, IM_ReadOnlySpanOfChar_RetStr) DEFINE_METHOD(STRING, INTERNAL_COPY, InternalCopy, SM_Str_IntPtr_Int_RetVoid) DEFINE_METHOD(STRING, WCSLEN, wcslen, SM_PtrChar_RetInt) DEFINE_PROPERTY(STRING, LENGTH, Length, Int)