Skip to content

Inline compile-time constant values into the code model - #1203

Open
asotona wants to merge 21 commits into
openjdk:code-reflectionfrom
asotona:inline-constants
Open

asotona wants to merge 21 commits into
openjdk:code-reflectionfrom
asotona:inline-constants

Conversation

@asotona

@asotona asotona commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

This PR puts constants known to javac directly into the model instead of loading them from variables or fields.
OpWriter required a fix related to byte and short constants.
Affected tests are updated.



Progress

  • Change must not contain extraneous whitespace

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/babylon.git pull/1203/head:pull/1203
$ git checkout pull/1203

Update a local copy of the PR:
$ git checkout pull/1203
$ git pull https://git.openjdk.org/babylon.git pull/1203/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 1203

View PR using the GUI difftool:
$ git pr show -t 1203

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/babylon/pull/1203.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper

bridgekeeper Bot commented Oct 2, 2026

Copy link
Copy Markdown

👋 Welcome back asotona! A progress list of the required criteria for merging this PR into code-reflection will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk

openjdk Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

@asotona This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

Inline compile-time constant values into the code model

You can use pull request commands such as /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 3 new commits pushed to the code-reflection branch:

  • 01756cc: Fix specification of Reflect
  • 8eb9611: 8392553: javac crashes on an inferred recursive intersection
  • f03b08d: Support Interpretation of switch operation

Please see this link for an up-to-date comparison between the source branch of this pull request and the code-reflection branch.
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the code-reflection branch, type /integrate in a new comment.

@openjdk openjdk Bot added ready Pull request is ready to be integrated rfr Pull request is ready for review labels Oct 2, 2026
@mlbridge

mlbridge Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

* variable.
*</ul>
*
* @apiNote Compiler-generated Java code models may inline constant-variable reads as {@link ConstantOp} operations.

@PaulSandoz PaulSandoz Oct 5, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We can link to the definition of "Java code model" in the jdk.incubator.code package doc and state:

Java code models(<- link) model access to a constant variable as a constant operation whose constant value is the same as the constant variable's value

%88 : java.type:"boolean" = eq %86 %87;
yield %88;
(%85 : java.type:"int")java.type:"boolean" -> {
%86 : java.type:"int" = constant @11;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

value %4 is not used, instead a new constant op is appended, is that deliberate ?

case FIELD, ENUM_CONSTANT -> {
if (sym.name.equals(names._this) || sym.name.equals(names._super)) {
result = thisValue();
} else if (top.localToOp.containsKey(sym)) {

@mabbay mabbay Oct 6, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

else-if at line 1053 can be removed

Method intfMethod = funcIntfMethod(intfClass, mtd);
List<Value> captures = lop.capturedValues();
// filter out constant captures
List<Value> captures = lop.capturedValues().stream().filter(v -> constants.evaluate(v).isEmpty()).toList();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should avoid evaluating constants three times.

@asotona asotona Oct 7, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The evaluation cached in a map, there is no need to construct arbitrary maps on top of it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah, I missed that, although computing the captured values is not cached.

lambdaMetafactory = DMHD_REFLECTABLE_LAMBDA_METAFACTORY;
intfMethodName = intfMethodName + "=" + modelName;
}
functions.add(lambdaToFuncOp(implName, lop).transform(this));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be preferable to have just one lambda model to work from i.e. the quoting function model. That complicates the "purity" of the functions added and the bytecode transformation of those quoting functions, but I believe the quoting function model has all that is needed to generate the same bytecode. Follow on work?

import jdk.incubator.code.dialect.java.JavaType;
import jdk.incubator.code.dialect.java.PrimitiveType;

public final class ConstantValueAnalysis {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As follow on work we can consider adding a method to JavaExpression that evaluates constants without a lookup, which shares the same underlying code as those that do.

}

/**
* Embeds the given operation into a quoting code model whose behavior quotes the operation.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The specification needs adjustment to say how it uses embeddedConstants.

Let's rename embeddedConstants to capturedConstants, then it becomes easier to state that there is an intersection between the set of the lambda's captured values and the given key set of capturedConstants, and then what happens to the capture values that are members of that intersection.


public final class ConstantValueAnalysis {
private final Function<Block, List<List<Value>>> incomingArguments;
private final Map<Value, Optional<Object>> cache = new IdentityHashMap<>();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No need to use IdentityHashMap. Value instances and CodeElements instances are identity-based objects whose equals/hashCode methods use identity.

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

Labels

ready Pull request is ready to be integrated rfr Pull request is ready for review

Development

Successfully merging this pull request may close these issues.

3 participants