[ 
https://issues.apache.org/jira/browse/GROOVY-12488?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18131903#comment-18131903
 ] 

ASF GitHub Bot commented on GROOVY-12488:
-----------------------------------------

codeconsole commented on PR #3022:
URL: https://github.com/apache/groovy/pull/3022#issuecomment-6400832477

   Pushed 51893aeb83. Several points refer to code that changed after 
f35e7257b6; replies describe the current head, in the order of the review:
   
   1. Since 0b89f6c523 the check is `AsmClassGenerator.isInSameRuntimePackage`, 
and only compilations a `GroovyClassLoader` defines in memory treat another 
compilation's class as another run-time package; class files, incremental and 
joint compilation keep direct access. Its Javadoc now says that 
`isPrimaryClassNode()` stands for "defined by the class loader of the accessing 
class", not "compiled from source" (932d9e698d).
   2. Documented on `StaticInvocationWriter.isDirectlyAccessible` (932d9e698d): 
there is no subclass rule, since only `super(...)` and anonymous classes may 
call a protected constructor of another package. `new` of one is now a type 
checking error (fe92a5fc2e), and `::new` keeps run-time selection. a358ba1983 
adds the anonymous-subclass case (`testFunctionCN27`, 
`testProtectedConstructorOfAnotherPackageIsSelectedAtRuntimeFromAnonymousSubclass`).
   3. Done in this PR, 416969588d: the synthetic method of an array constructor 
reference is compiled as statically compiled code. Its bytecode does not 
change: it already used `NEWARRAY`/`ANEWARRAY`/`MULTIANEWARRAY` with the size 
unboxed as a statically compiled `new String[s]` does. 
`testArrayConstructorReferenceCreatesArrayLikeStaticallyCompiledNewArray` pins 
the bytecode, `testArrayConstructorReferencesWithEachSizeType` the behavior.
   4. The constructors generated for default arguments are not synthetic: 
`Verifier.addConstructor` copies the declared constructor's modifiers (javap: 
`flags: (0x0001) ACC_PUBLIC`). Every class of the compilation is verified 
before any is generated, so the writer always sees them. a358ba1983 pins direct 
calls for a class declared after the reference, all-default and package-private 
constructors, and a class of an earlier parse 
(`testConstructorReferenceCallsConstructorGeneratedForDefaultArgumentsDirectly`,
 
`testConstructorReferenceCallsConstructorGeneratedForDefaultArgumentsOfClassCompiledBefore`,
 `testFunctionCN26`). The first fails if generated constructors are filtered 
out.
   5. All helper kinds share `addSyntheticMethod`; the comment now cites JVMS 
4.6 (932d9e698d). f85f7e24d1 tests the array, static-extension 
(`Thread::startDaemon`), `Class` method (`String::getName`) and 
other-class-loader (`M::spm`, `M::pm`) helpers in static and default interface 
methods; with `ACC_FINAL` put back they fail with `ClassFormatError` (0x101A).
   6. Added to the Javadoc of `findConstructorReferenceTarget` (932d9e698d); 
`testFunctionCN24` pins it.
   7. No change; the split is pinned by 
`testPrivateConstructorOfNestedClassIsCalledDirectlyFromClosureOrLambda`, which 
reads the helpers from the closure and lambda classes.
   
   Test gaps:
   - Array `::new`: item 3.
   - Default-parameter constructor chosen by arity: item 4.
   - Enum: `testEnumConstructorReferenceSelectsConstructorAtRuntime` 
(a358ba1983). `E::new` as `Function<String,E>` does not type-check (the 
constructor is rewritten to take name and ordinal), so the test uses an 
interface matching `(String, int, String)` inside the enum, where the private 
constructor would be callable: the reference stays `INVOKEDYNAMIC init`, and 
the test fails without the enum guard.
   - Abstract class: a reference to its constructor is a type checking error, 
also in an anonymous subclass ("Cannot instantiate the type p.A", 
GROOVY-11385), so there is no run-time path. For a concrete class with a 
protected constructor of another package, the anonymous subclass's `p.B::new` 
is selected at run time (`testFunctionCN27`).
   
   Nits:
   - Kept.
   - Moved to `AbstractBytecodeTestCase` as `compileAgainstLibrary`, 
`extractMethodSequence` and `selectMethod` (51893aeb83); 
`StaticCompileRuntimePackageTest` uses them too.
   - No change.
   
   16 of the 35 new `MethodReferenceTest` tests and the updated test fail on 
master, and 21 of the 30 `StaticCompileRuntimePackageTest` tests.
   




> SC: constructor reference calls the constructor through the meta-class 
> instead of directly
> ------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12488
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12488
>             Project: Groovy
>          Issue Type: Improvement
>          Components: Static compilation
>    Affects Versions: 6.0.0
>            Reporter: Scott Murphy Heiberg
>            Priority: Major
>
> Under {{@CompileStatic}}, a constructor reference such as {{Made::new}} is 
> implemented by a synthetic method {{ctorRef$<method>$<n>}} on the enclosing 
> class, which the LambdaMetafactory call site targets. That method is not 
> statically compiled:
> {noformat}
> private static final Made ctorRef$ctorRef$0();
>    0: ldc           class Made
>    2: invokedynamic init:(Ljava/lang/Class;)Ljava/lang/Object;
>    7: invokedynamic cast:(Ljava/lang/Object;)LMade;
>   12: areturn
> {noformat}
> So every call selects the constructor through the meta-class at run time, 
> while other method references ({{String::length}}, {{Math::abs}}) link their 
> target directly. In a GraalVM native image the constructor also needs 
> reflection metadata although the code is statically compiled.
> The cause is 
> {{StaticTypesMethodReferenceExpressionWriter.addSyntheticMethodForConstructorReference}}:
>  it builds the constructor call without a target constructor and sets 
> {{STATIC_COMPILE_NODE}} to false (there is a TODO for it).
> Proposed fix: select the constructor at compile time among the constructors 
> visible from the enclosing class, matched against the functional interface's 
> parameter types as for a constructor call expression, and call it directly. 
> Keep the run-time selection when no single constructor matches 
> (GROOVY-10971), for a protected constructor in another package, and for a 
> protected or package-private constructor of a class compiled in another 
> compilation unit, which may come from another class loader. As with other 
> method references and with Java, the constructor is then chosen from the 
> declared parameter types rather than the run-time argument types.
> PR: https://github.com/apache/groovy/pull/3022



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to