Skip to content

Conversation

kotlarmilos
Copy link
Member

@kotlarmilos kotlarmilos commented Jun 6, 2025

Description

This PR adds support for array operations in the interpreter, including both ref and value types.

Changes

  • Implemented the following opcodes:
    • LDELEM_REF, LDELEM_VT
    • STELEM_REF, STELEM_VT, STELEM_VT_NOREF
    • LDELEMA, LDELEMA_REF
  • Added support for calling constructors of MD arrays

Out-of-scope

  • LDELEMA_MD and multi-dimensional array getters will be implemented as follow-up.

@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 6, 2025
@kotlarmilos kotlarmilos added this to the 10.0.0 milestone Jun 6, 2025
@kotlarmilos kotlarmilos added area-CodeGen-Interpreter-coreclr NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 6, 2025
Copy link
Contributor

Tagging subscribers to this area: @BrzVlad, @janvorli, @kg
See info in area-owners.md if you want to be subscribed.

@kotlarmilos kotlarmilos mentioned this pull request Jun 2, 2025
65 tasks
break;
}

assert(!"Array constructor with <= 1 args is not allowed");
Copy link
Member

Choose a reason for hiding this comment

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

It is not possible to call array constructor with 1 arg in C#, but it is valid in IL. I am sure we will have some test cases for it,

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, removed the assert.

// TODO: Stack slot is 8 bytes aligned and
// AllocateArrayEx expects the dimensions to be in int32_t array
// so we need to convert the stack slots to int32_t
int32_t* dims = (int32_t*)alloca(rank * sizeof(int32_t));
Copy link
Member

Choose a reason for hiding this comment

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

alloca will overflow the stack when called in the loop. Is it what the TODO above is about? I think this should just be moved to a helper method, so that the alloca buffer gets de-allocated once the opcode executes.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, I’ve moved it to a helper function. An alternative would be to pack argCalls into an int32_t* array, but that would require a series of mov and shift opcodes.

@@ -1252,6 +1252,31 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr

goto CALL_INTERP_SLOT;
}
case INTOP_NEWOBJ_ARR:
Copy link
Member

Choose a reason for hiding this comment

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

I would call the opcode INTOP_NEW_MDARR to make it clear that it allocates multi-dimensional arrays.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated to INTOP_NEWMDARR to match INTOP_NEWARR.

ip += 5;
break;
}
case INTOP_LDELEMA1:
Copy link
Member

Choose a reason for hiding this comment

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

What is the 1 suffix trying to say? I think this should be INTOP_LDELEMA.

Copy link
Member

Choose a reason for hiding this comment

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

This might be a mono-ism, the mono interp has an opcode named this

Copy link
Member

@filipnavara filipnavara Jun 7, 2025

Choose a reason for hiding this comment

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

Mono has three different opcodes for different situations:

  • LDELEMA_TC is the most generic one with type checks for reference types (see the LDELEMA_REF suggestion in comments below)
  • LDELEMA and LDELEMA1 for arrays of value types, LDELEMA1 seems to be the specialized variant for SZARRAYs (0-based, 1-rank)

Copy link
Member

@filipnavara filipnavara Jun 7, 2025

Choose a reason for hiding this comment

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

I'd personally prefer to use an unified convention across opcodes like this. This could be LDELEMA (for SZARRAY), LDELEMA_MD (for all other arrays) and LDELEMA_REF (for arrays of reference types).

We have some prior art in CoreCLR for treating SZARRAY as just "array" and using a prefix/suffix for other arrays. I don't have any preference for a specific naming convention as long as it's consistent between the opcodes.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, I agree with LDELEMA/LDELEMA_REF/LDELEMA_MD suggestion.

if (elemRef != NULL)
{
MethodTable* arrayElemMT = (MethodTable*)pMethod->pDataItems[ip[4]];
if (arrayElemMT != NULL && !ObjIsInstanceOf(OBJECTREFToObject(elemRef), arrayElemMT))
Copy link
Member

Choose a reason for hiding this comment

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

ObjIsInstanceOf can trigger GC, so the object references have to be protected around the call; or re-fetched from the interpterer stack after the call. The latter is probably more efficient.

@kotlarmilos kotlarmilos marked this pull request as ready for review June 9, 2025 07:31
@kotlarmilos kotlarmilos removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jun 9, 2025
@kotlarmilos kotlarmilos changed the title [WIP][clr-interp] Implement array support for reference and value types [clr-interp] Implement array support for reference and value types Jun 9, 2025
Copy link
Member

@janvorli janvorli left a comment

Choose a reason for hiding this comment

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

LGTM, thank you!

@janvorli janvorli merged commit b581381 into dotnet:main Jun 9, 2025
102 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Jul 10, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants