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

Commit

Permalink
Merge pull request #13075 from stephentoub/string_span_ctor
Browse files Browse the repository at this point in the history
Add new String(ReadOnlySpan<char>) ctor
  • Loading branch information
stephentoub authored Jul 28, 2017
2 parents 78931c8 + 5f2fb65 commit 9b7e736
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 47 deletions.
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

0 comments on commit 9b7e736

Please sign in to comment.