Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Add new String(ReadOnlySpan<char>) ctor #13075

Merged
merged 2 commits into from
Jul 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/mscorlib/src/System/String.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<char> value);

private unsafe string CtorReadOnlySpanOfChar(ReadOnlySpan<char> 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()
Expand Down
101 changes: 55 additions & 46 deletions src/vm/binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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++;
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/vm/binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
4 changes: 3 additions & 1 deletion src/vm/ecall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
{
Expand Down
1 change: 1 addition & 0 deletions src/vm/ecall.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions src/vm/metasig.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// T -- TypedReference -- TypedReference
// G -- -- Generic type variable
// M -- -- Generic method variable
// GI -- -- Generic type instantiation
//

//#DEFINE_METASIG
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -382,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))
Expand All @@ -393,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))
Expand Down Expand Up @@ -608,6 +615,7 @@ DEFINE_METASIG_T(IM(IAsyncResult_RetVoid, C(IASYNCRESULT), v))
#undef T
#undef G
#undef M
#undef GI

#undef _

Expand Down
1 change: 1 addition & 0 deletions src/vm/mscorlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down