[code-reflection] RFR: Add support for local classes [v2]
Maurizio Cimadamore
mcimadamore at openjdk.org
Tue Jun 4 17:47:33 UTC 2024
On Tue, 4 Jun 2024 17:43:24 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:
>> This PR adds support for local and anonymous instance class creation in the code model.
>>
>> This is a bit trickier than inner classes in that local classes can also capture local variables from enclosing scopes. And, to make things even trickier, some local classes can be used in a *pre-construction* environment, that is in a location where `this` is not available yet (e.g. because we're in the middle of a `super` constructor call).
>>
>> In this PR, we only add support for local and anonymous class that do **not** appear in a pre-construction context. The logic to compute the set of captured local is shared with `Lower` (as part of Java 8 that logic has been somewhat generalized to accommodate different clients, as lambda generation also needs to know the set of variables captured by a local class). The resulting captures are then added as arguments of the `new` operation, and the constructor signature is tweaked accordingly.
>>
>> For instance, given this:
>>
>>
>> String testLocalCaptureParam(String s) {
>> class Foo {
>> String m() { return s; }
>> }
>> return new Foo().m();
>> }
>>
>>
>> The following model is now generated:
>>
>>
>> func @"testLocalCaptureParam" (%0 : LocalClassTest, %1 : java.lang.String)java.lang.String -> {
>> %2 : Var<java.lang.String> = var %1 @"s";
>> %3 : java.lang.String = var.load %2;
>> %4 : .<LocalClassTest, LocalClassTest$2Foo> = new %0 %3 @"func<.<LocalClassTest, LocalClassTest$2Foo>, LocalClassTest, java.lang.String>";
>> %5 : java.lang.String = invoke %4 @".<LocalClassTest, LocalClassTest$2Foo>::m()java.lang.String";
>> return %5;
>> };
>>
>>
>> I've added a bunch of tests to check the shape of the resulting code model, plus a dynamic test to make sure that we can indeed build local classes by interpreting said model.
>
> Maurizio Cimadamore has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains one commit:
>
> Initial push
test/langtools/tools/javac/reflect/CodeReflectionTester.java line 40:
> 38: public class CodeReflectionTester {
> 39:
> 40: static int nErrors = 0;
I've tweaked this test so that _all_ errors can be reported at once. This should make it easier to regenerate some of the expected test output when it breaks due to API/compiler changes.
test/langtools/tools/javac/reflect/MethodReferenceTest.java line 171:
> 169: func @"test7" (%0 : MethodReferenceTest)void -> {
> 170: %1 : java.util.function.Supplier<.<MethodReferenceTest, MethodReferenceTest$A<java.lang.String>>> = lambda ().<MethodReferenceTest, MethodReferenceTest$A<java.lang.String>> -> {
> 171: %2 : .<MethodReferenceTest, MethodReferenceTest$A<java.lang.String>> = new %0 @"func<.<MethodReferenceTest, MethodReferenceTest$A>, MethodReferenceTest>";
Note that for inner classes we used to generate incorrect constructor types (as the enclosing this type was missing). Since this is fixed now, some existing tests with inner classes have also been updated,
-------------
PR Review Comment: https://git.openjdk.org/babylon/pull/111#discussion_r1626396153
PR Review Comment: https://git.openjdk.org/babylon/pull/111#discussion_r1626397109
More information about the babylon-dev
mailing list