Skip to content

Add support for string constructors to the interpreter #115914

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

kg
Copy link
Member

@kg kg commented May 22, 2025

No description provided.

@Copilot Copilot AI review requested due to automatic review settings May 22, 2025 22:26
@kg kg requested review from BrzVlad and janvorli as code owners May 22, 2025 22:26
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for string constructors in the interpreter and updates the associated call stub generation.

  • Added a new test case (TestStringCtor) to verify string constructor functionality
  • Updated interpreter execution logic to correctly handle fcalls for string constructors
  • Adjusted call stub generation to account for special string constructors

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/tests/JIT/interpreter/Interpreter.cs Added test method for string constructor support
src/coreclr/vm/interpexec.cpp Updated interpreter method call to support special string constructors
src/coreclr/vm/callstubgenerator.cpp Modified call stub generation for special constructor handling

@@ -1186,15 +1186,46 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
callArgsOffset = ip[2];
methodSlot = ip[3];

OBJECTREF objRef = AllocateObject((MethodTable*)pMethod->pDataItems[ip[4]]);
MethodTable *pClass = (MethodTable*)pMethod->pDataItems[ip[4]];
// FIXME: Duplicated code from CALL_INTERP_SLOT
Copy link
Preview

Copilot AI May 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider refactoring the duplicated code block for handling string constructor invocations to improve maintainability.

Suggested change
// FIXME: Duplicated code from CALL_INTERP_SLOT

Copilot uses AI. Check for mistakes.

Copy link
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

@kg
Copy link
Member Author

kg commented May 23, 2025

Anyone know what's up with this crossdac failure on CI?

  [458/464] Linking CXX static library unwinder\unwinder_dac.lib
  [459/464] Building RC object dlls\mscordbi\CMakeFiles\mscordbi.dir\Native.rc.res
  [460/464] Building C object D:\a\_work\1\s\artifacts\obj\external\libunwind\CMakeFiles\libunwind_xdac.dir\D_\a\_work\1\s\src\native\external\libunwind\src\dwarf\Gparser.c.obj
  FAILED: D:/a/_work/1/s/artifacts/obj/external/libunwind/CMakeFiles/libunwind_xdac.dir/D_/a/_work/1/s/src/native/external/libunwind/src/dwarf/Gparser.c.obj 
  C:\PROGRA~1\MICROS~1\2022\ENTERP~1\VC\Tools\MSVC\1443~1.348\bin\Hostx64\x64\cl.exe  /nologo -DBUILDENV_CHECKED=1 -DCROSS_COMPILE -DDEBUG -DDISABLE_CONTRACTS -DHAVE_CONFIG_H=1 -DHAVE_DL_ITERATE_PHDR=1 -DHAVE_UNW_GET_ACCESSORS -DHAVE___THREAD=0 -DHOST_64BIT -DHOST_AMD64 -DHOST_WINDOWS -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_STRING=\"\" -DTARGET_64BIT -DTARGET_AMD64 -DTARGET_LINUX -DTARGET_UNIX -DUNW_REMOTE_ONLY -DURTBLDENV_FRIENDLY=Checked -D_CRT_DECLARE_NONSTDC_NAMES -D_CRT_SECURE_NO_WARNINGS -D_DBG -D_DEBUG -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_TIME_BITS=64 -D_Thread_local="" -D__amd64__ -D__linux__ -D__x86_64__ -ID:\a\_work\1\s\artifacts\obj\external\libunwind -ID:\a\_work\1\s\src\native\external\libunwind_extras -ID:\a\_work\1\s\src\native -ID:\a\_work\1\s\src\native\inc -ID:\a\_work\1\s\src\native\external\libunwind\include\tdep -ID:\a\_work\1\s\src\native\external\libunwind\include -ID:\a\_work\1\s\artifacts\obj\external\libunwind\include\tdep -ID:\a\_work\1\s\artifacts\obj\external\libunwind\include -ID:\a\_work\1\s\src\native\external\libunwind\include\remote -ID:\a\_work\1\s\src\native\external\libunwind\include\remote\win -ID:\a\_work\1\s\src\native\external\libunwind\src /DWIN32 /D_WINDOWS -std:c11 -MTd /O2 /nologo /W4 /WX /Oi /Oy- /Gm- /Zp8 /Gy /GS /fp:precise /FC /MP /Zm200 /Zc:strictStrings /Zc:wchar_t /Zc:inline /Zc:forScope /wd4065 /wd4100 /wd4127 /wd4131 /wd4189 /wd4200 /wd4201 /wd4206 /wd4239 /wd4245 /wd4291 /wd4310 /wd4324 /wd4366 /wd4456 /wd4457 /wd4458 /wd4459 /wd4463 /wd4505 /wd4702 /wd4706 /wd4733 /wd4815 /wd4838 /wd4918 /wd4960 /wd4961 /wd5105 /wd5205 /we4007 /we4013 /we4102 /we4551 /we4640 /we4806 /we4055 /we4146 /we4242 /we4244 /we4267 /we4302 /we4308 /we4509 /we4510 /we4532 /we4533 /we4610 /we4611 /we4700 /we4701 /we4703 /we4789 /we4995 /we4996 /w34092 /w34121 /w34125 /w34130 /w34132 /w34212 /w34530 /w35038 /w44177 /Zi /ZH:SHA_256 /source-charset:utf-8 /guard:cf /guard:ehcont /permissive- -wd4068 -wd4334 -wd4311 -wd4475 -wd4477 /TC /showIncludes /FoD:\a\_work\1\s\artifacts\obj\external\libunwind\CMakeFiles\libunwind_xdac.dir\D_\a\_work\1\s\src\native\external\libunwind\src\dwarf\Gparser.c.obj /FdD:\a\_work\1\s\artifacts\obj\external\libunwind\CMakeFiles\libunwind_xdac.dir\ /FS -c D:\a\_work\1\s\src\native\external\libunwind\src\dwarf\Gparser.c
  D:\a\_work\1\s\src\native\external\libunwind\src\dwarf\Gparser.c(1181): fatal error C1090: PDB API call failed, error code '23': (0x00000005)
  [461/464] Building CXX object dlls\mscordbi\CMakeFiles\mscordbi.dir\mscordbi.cpp.obj
  ninja: build stopped: subcommand failed.
##[error]BUILD: Error: native component build failed. Refer to the build log files for details.

EDIT: Looks like https://developercommunity.visualstudio.com/t/C1090-PDB-API-call-failed-error-code-2/48897

@jkotas
Copy link
Member

jkotas commented May 23, 2025

Also tracked here: #48070 . Build analysis should flag it for you.

// fcall that is basically a static method that returns the new instance.
if (pMD && pClass->HasComponentSize())
{
// The compiler didn't know about this so it reserved space for a this-reference. We need to skip
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like a temporary workaround. The compiler can know about this (by checking CORINFO_FLG_VAROBJSIZE flag). What needs to happen to move this logic to the compiler?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_compHnd didn't appear to expose the things I needed to determine this. I can take another look.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the flag CORINFO_FLG_VAROBJSIZE that @jkotas mentioned offline yesterday:

if (opcode == CEE_NEWOBJ)
{
if (clsFlags & CORINFO_FLG_VAROBJSIZE)
{
assert(!(clsFlags & CORINFO_FLG_ARRAY)); // arrays handled separately
// This is a 'new' of a variable sized object, wher
// the constructor is to return the object. In this case
// the constructor claims to return VOID but we know it
// actually returns the new object
assert(callRetTyp == TYP_VOID);
callRetTyp = TYP_REF;
call->gtType = TYP_REF;
impSpillSpecialSideEff();
impPushOnStack(call, typeInfo(clsHnd));
}
else

You can get it by getClassAttribs or by the getCallInfo in the CORINFO_CALL_INFO::classFlags.

@@ -547,7 +547,14 @@ CallStubHeader *CallStubGenerator::GenerateCallStub(MethodDesc *pMD, AllocMemTra

_ASSERTE(pMD != NULL);

// Classes like System.String have special constructors that are fcalls. When invoking these, we need to override
// HasThis (there's no thisref) and the return type (the return value is the new instance, not void).
bool isSpecialConstructor = pMD->IsCtor() && pMD->GetMethodTable()->HasComponentSize();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The runtime uses a bit different condition to decide whether to clear the HasThis, it would be good to use the same one:

bool fCtorOfVariableSizedObject = msig.HasThis() && (pFunction->GetMethodTable() == g_pStringClass) && pFunction->IsCtor();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants