3

Think of a dynamic, predicated aspect language. Aspects could be invoked (i.e., methods) instead of or before and after an original method. These aspects are switched on and off which happens at runtime. It could even be, that multiple aspects want to change the same method, which will result in a composition of these aspects into a chain of method calls.

The original method is changed by a loadtime compiler (JPLIS and ASM). I got some bytecode looking something like this:

//## baseMethod ##
aload 0         // this
aload ...       // some more arguments
invokedynamic # // call the bootstrap method which returns a callsite to be invoked

The interesting part is that the bootstrap method should work in a specific way:

  • Return a concatenation of methods with compatible parameter lists. These MethodHandles are bound to different instances of different types on which they are invoked.
  • It may be that the resulting MethodHandleis just bind to other instances, but not to the instance that is calling the bootstrap method. As such, the invocation of the resulting callsite using this should be omitted (the first branch in the alternative below).

It may also happen that the original method is directly called, which is totally okay.

enter image description here

It seems to me that MethodHandles are the right thing to achieve this. My question would be if everything is achievable in a single bootstrap method as such that I can chain the method calls as shown in the sequence diagram using a chain of method handles returned from the bootstrap method that are bound to the callsite.

lschuetze
  • 1,218
  • 10
  • 25
  • 1
    There is no “instance that is calling the bootstrap method”. A bootstrap method is executed *exactly once* for an `invokedynamic` instruction and has to return a `CallSite` appropriate to handle *all* instances for which the `invokedynamic` instruction may get executed subsequently. Also, “the invocation of the resulting callsite using this should be omitted” indicates some confusion. There is only one callsite and there is only one invocation, which is precisely this one given by `aload 0, aload ... (some more arguments) invokedynamic #` which always includes `this`. – Holger Sep 22 '17 at 16:45
  • Thanks for your clarification. With instance I meant the things I put on the stack which will be used by the JVM to invokeExact the callsite. – lschuetze Sep 22 '17 at 16:56
  • I know that there will be one invocation. The MethodHandles API allows to put MethodHandles together. This I want to use to construct MethodHandles. If this is not possible I might have to use the MetaLambdaFactory. – lschuetze Sep 22 '17 at 16:59
  • 1
    But the things you put on the stack prior to the `invokedynamic` instruction will not be available to the bootstrap method. Therefore, it is impossible to decide anything beforehand that would require these values. You can compose method handles which will do this decision before calling into another handle, but I would avoid this for performance reasons. It would be much simpler to let the `invokedynamic` return a `boolean` telling whether the original method ought to be invoked and use `aload 0, aload ... (some more arguments) invokedynamic #, ifeq .end, invoke original code, .end, return`… – Holger Sep 22 '17 at 17:01
  • 1
    I'm not sure what you mean when you ask if this is "achievable in a single bootstrap method". If you want to use `invokedynamic`, you are inherently limited to a single bootstrap method, so you don't really have a choice in the matter. If I understand the premise, the 'aspects' that might be applied are not specific to a call site, but to the method being invoked, or perhaps the method *and* the target instance. In either case, I think you'd bootstrap a mutable call site that would be updated by the manager as various aspects are (de)activated. – Mike Strobel Sep 22 '17 at 18:15
  • Thanks @MikeStrobel. However, how can I combine the several advices into a chain of `MethodHandle` that will be bound to the `CallSite` returned by the bootstrap method? I can use `guardWithTest` to guard advices with their predicates. – lschuetze Oct 04 '17 at 13:46

1 Answers1

3

Any branching logic that will decide which aspects to apply to a method invocation have to run at method handle execution time, not at bootstrap time.

You can combine the various handles and the branching logic via
MethodHandles.guardWithTest​(test, target, fallback)

The this on the stack will be one of the arguments for the handles.

the8472
  • 40,999
  • 5
  • 70
  • 122
  • Okay, with that I can combine the guards with their respective advice. However, how can I combine the several advices into a chain of `MethodHandle` that will be bound to the `CallSite`? – lschuetze Oct 04 '17 at 13:43