Skip to content

Conversation

@BrzVlad
Copy link
Member

@BrzVlad BrzVlad commented Mar 30, 2025

This PR adds support for creating new objects and for loading and storing into instance and static fields. As an experiment on what it would be necessary, support was added also for ThreadStatic fields. Support for indirect loads and stores was also added.

PR can be reviewed commit by commit.

Copilot AI review requested due to automatic review settings March 30, 2025 17:15
@ghost ghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 30, 2025
Copy link
Contributor

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 introduces support for field access in the CoreCLR Interpreter by adding object creation, instance/static field operations, and ThreadStatic field handling.

  • Added new structs and classes (MyStruct, MyObj, MyStruct2) to facilitate the tests
  • Introduced tests (TestJitFields, TestFields, TestSpecialFields) to verify field access behavior
  • Included helper methods to read and write integers via references
Files not reviewed (4)
  • src/coreclr/interpreter/compiler.h: Language not supported
  • src/coreclr/interpreter/intops.def: Language not supported
  • src/coreclr/interpreter/intops.h: Language not supported
  • src/coreclr/vm/interpexec.cpp: Language not supported
Comments suppressed due to low confidence (2)

src/tests/JIT/interpreter/Interpreter.cs:19

  • [nitpick] Consider renaming 'ct' to a more descriptive name like 'counter' to improve code clarity.
public int ct;

src/tests/JIT/interpreter/Interpreter.cs:178

  • [nitpick] TestSpecialFields currently verifies ThreadStatic field behavior only on the main thread; consider adding tests with multiple threads to ensure proper isolation.
public static bool TestSpecialFields()

@dotnet-policy-service
Copy link
Contributor

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

@BrzVlad BrzVlad mentioned this pull request Mar 30, 2025
66 tasks
@BrzVlad BrzVlad added area-CodeGen-Interpreter-coreclr and removed area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Mar 30, 2025
@BrzVlad BrzVlad force-pushed the feature-clr-interp3 branch from 802ebeb to 6931c95 Compare March 31, 2025 10:25
ctorClass = m_compHnd->getMethodClass(ctorMethod);
int32_t numArgs = ctorSignature.numArgs;

// TODO Special case array ctor / string ctor
Copy link
Member

Choose a reason for hiding this comment

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

A nit - I've been using Interpreter-TODO instead of just TODO so that we can quickly search through the code base for them. It seems it would make sense to use it in the interpreter code too.

BrzVlad added 9 commits April 2, 2025 11:29
The newobj instruction receives the set of arguments and it needs to create the object in question, add it as the `this` argument to the constructor and return it as well. All this work is done by a single interpreter newobj instruction. Once handling the creation of the new object, the already existing call path is reused for executing the constructor. The newobj instruction thinks it receives the `this` pointer as an argument, so we can reuse the offset allocator to generate the exact offsets for each argument. We dummy initialize `this` via an intermediary opcode, so the offset allocator handles this pattern cleanly.
We currently have limited control over what is interpreted and what is jitted. When creating a new object in the interpreter we have the problem of having to call to object ctor which is jitted. A simple work around, at least for now, is to ignore this call.
Loading and storing into instance and static fields, as well as loading the address of fields. For instance fields, this is achieved via ldind/stind opcodes, that have the offset embedded into the instruction. For static fields, we first compute the field address and then we reuse the same ldind/stind opcodes for the field access.

When loading a field from a valuetype from the interpreter stack, we use a separate opcode INTOP_MOV_SRC_OFF, which will be emitted as a normal move (with already existing opcodes), but the source offset that it operates on can point inside a VT var.
Special static fields can have a bunch of accessors. This commit handles a few accessor types for thread static fields. In order to obtain the address of such a field, we emit an interpreter opcode that can call a helper of a certain signature, with the slot containing the helper code pointer and argument embedded in the code stream. It seems like the helpers can either point to native code or to jit compiled code.
Reuse the instructions used for loading/storing into fields
For simplicity we emit full memory barriers each time
Some of them are allocating objects so we disable them currently just to be safe on CI.
@BrzVlad BrzVlad force-pushed the feature-clr-interp3 branch from b48a187 to 0acc620 Compare April 2, 2025 08:30
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
Copy link
Member

janvorli commented Apr 2, 2025

/ba-g the failures are unrelated to this change, they happen on every PR for the past few days.

@janvorli janvorli merged commit 883f747 into dotnet:main Apr 2, 2025
101 of 104 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators May 3, 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.

3 participants