Skip to content

Add capturing method references#18818

Merged
rmuir merged 3 commits intoelastic:masterfrom
rmuir:capturingReferences
Jun 10, 2016
Merged

Add capturing method references#18818
rmuir merged 3 commits intoelastic:masterfrom
rmuir:capturingReferences

Conversation

@rmuir
Copy link
Copy Markdown
Contributor

@rmuir rmuir commented Jun 10, 2016

#18748 added non-capturing method references of the forms (Class::virtualMethod, Class::staticMethod, Class::new).

This PR adds support for capturing references such as instance::virtualMethod. The main benefit is enhancing our lambda support, especially on the dynamic side. I also cleaned up DefBootstrap to be less confusing, it takes varargs (depending on flavor), and has error checks around this.

For any lambda we have two main parts: the interface type of the parameter, and the implementation method. For this to work, we add a new flavor to DefBootstrap called REFERENCE. Its basically just a dynamic LambdaMetaFactory, taking expected interface type as a parameter, but it resolves the implementation method with a dynamic lookup based on receiver's class. Then it calls LambdaMetaFactory. Its cached on receiver's class just like anything else.

There are 4 cases, based on what we know at compile time.

  1. interface type is known, implementation method is known: type.foo(anothertype::bar)
  2. interface type is known, implementation method is unknown: type.foo(def::bar)
  3. interface type is unknown, implementation method is known: def.foo(type::bar)
  4. interface type is unknown, implementation method is unknown: def.foo(def::bar)

cases 4 and 3 are just like 2 and 1, respectively, except deferred. The placeholder signature on the stack was extended, to support the number of capture arguments.

case 1 is completely static. We just call LambdaMetaFactory like java would, only we capture the reference of the instance.
case 2 is very similar, except instead of calling LambdaMetaFactory, we use the new REFERENCE DefBootstrap.
case 3 defers the call to LambdaMetaFactory until the interface type is resolved.
case 4 defers the call to DefBootstrap until the interface is resolved.

case 4 does mean we nest a cache inside a cache, but its what we need: the two things are really independent. Our scripts are small, its contained and does not recurse, and we don't want bad performance.

import java.lang.invoke.LambdaMetafactory;

/**
* Represents a capturing function reference.
Copy link
Copy Markdown
Contributor

@jdconrad jdconrad Jun 10, 2016

Choose a reason for hiding this comment

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

Please add this to the package-info as well.

@jdconrad
Copy link
Copy Markdown
Contributor

jdconrad commented Jun 10, 2016

LGTM! Thanks for tackling this, I realize it's quite complicated. (Added one important comment after the fact.)

if (defInterface && captured.type.sort == Definition.Sort.DEF) {
// dynamic interface, dynamic implementation
writer.push("D" + type + "." + call + ",1");
writer.loadLocal(captured.slot);
Copy link
Copy Markdown
Contributor

@jdconrad jdconrad Jun 10, 2016

Choose a reason for hiding this comment

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

I don't think you can use this method because it won't necessarily store the type correctly since we do the slots ourself to avoid trash being on the stack with variables scopes and such. Instead you'll have to use writer.visitVarInsn(asmtype.getOpcode(Opcodes.ILOAD), slot);

@rmuir
Copy link
Copy Markdown
Contributor Author

rmuir commented Jun 10, 2016

@jdconrad I pushed some commits and merged master.

@jdconrad
Copy link
Copy Markdown
Contributor

+1. Merge it!

@rmuir rmuir merged commit 200af0c into elastic:master Jun 10, 2016
@clintongormley clintongormley changed the title painless: add capturing method references Add capturing method references Jun 13, 2016
@clintongormley clintongormley added :Core/Infra/Scripting Scripting abstractions, Painless, and Mustache and removed :Plugin Lang Painless labels Feb 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Core/Infra/Scripting Scripting abstractions, Painless, and Mustache >enhancement v5.0.0-alpha4

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants