Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lambda meta-factory for dynamic property access #2338

Open
homedirectory opened this issue Oct 17, 2024 · 1 comment
Open

Lambda meta-factory for dynamic property access #2338

homedirectory opened this issue Oct 17, 2024 · 1 comment
Assignees

Comments

@homedirectory
Copy link
Contributor

homedirectory commented Oct 17, 2024

Description

#2061 modified the implementation of dynamic property access to use Method Handles instead of Reflection to improve performance.

Lambda meta-factory is a Java API that builds on method handles and promises even better performance.
This API is described in depth by the javadoc of java.lang.invoke.LambdaMetafactory.
In short, it leverages the JVM's instruction invokedynamic and enables its users to dynamically create lambda instances.
Performance improvements are expected to be gained from the optimisations on lambdas applied by the JVM.

Property accessors and setters can be represented by interfaces, which will be used by lambda meta-factories.

interface PropertyAccessor<E extends AbstractEntity, T> {

  T get(E entity);
  
}

interface PropertySetter<E extends AbstractEntity, T> {
  
  // return type is void because this is interface is never used by developers directly
  void set(E entity, T value);
  
}

The performance of this approach should be compared to that of method handles.

Prerequisites

This issue depends on features described in #2336, #2337.

#2337 is required because lambda meta-factory cannot be used with method handles that read from a field directly.
Lambda meta-factories support only certain kinds of method handles:

  • REF_getField - no
  • REF_getStatic - no
  • REF_putField - no
  • REF_putStatic - no
  • REF_invokeVirtual - yes
  • REF_invokeStatic - yes
  • REF_invokeSpecial - yes
  • REF_newInvokeSpecial - yes
  • REF_invokeInterface - yes

Expected outcome

Improved performance of dynamic property access due to the usage of lambda meta-factories.

Resources

@homedirectory
Copy link
Contributor Author

Lambda meta-factory for generated entity types

The following error is observed when lambda meta-factories are being created for methods in generated types:

Invalid caller: ua.com.fielden.platform.reflection.asm.impl.entities.EntityBeingEnhanced$$TgEntity_3a134641124f4b56a1274a3d33031787

This is caused by the Lookup object, which is given to java.lang.invoke.LambdaMetafactory.metafactory, lacking full privilege access.
This, in turn, is caused by the generated class residing in a different module than PropertyIndexerImpl, which creates the Lookup.
In general, because Java modules are not used in TG, all classes reside in the unnamed module.
However, each class loader has a unique unnamed module (citation needed).
This explains the observed error, since generated entity types are loaded by DynamicEntityClassLoader, but PropertyIndexerImpl is loaded by the default class loader.

A Lookup with full privilege access means that it has both PRIVATE and MODULE access (see MethodHandles.Lookup#hasFullPrivilegeAccess).

Lookup MethodHandles.privateLookupIn(Class<?> targetClass, Lookup caller)

If targetClass and the underlying class of caller are in different modules, the resulting lookup will have PRIVATE access but no MODULE access.

Possible solutions:

  • We need a placeholder class loaded by DynamicEntityClassLoader to obtain a lookup from.
    But for that we need to call the lookup method from that generated class, which means we need to generate the code that does it (e.g., a static field initialised with MethodHandles.lookup()).
    Then, we could use the value of that field for the caller argument of MethodHandles.privateLookupIn.

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

No branches or pull requests

1 participant