Class SAMweaver

java.lang.Object
kilim.analysis.SAMweaver
All Implemented Interfaces:
Constants, org.objectweb.asm.Opcodes

public class SAMweaver extends Object implements Constants
SAMweaver generates code to support functional interfaces (also known as SAM, for Single Abstract Method), where the SAM method is pausable. What makes SAM interfaces special compared to regular interfaces is that they can represent a lambda function in java8. More on this later. Imagine that a class called X uses a I of the following form:
 interface I {
     int foo(double d) throws Pausable;
 }
 
Since I is a SAM, CallWeaver replaces all invokeinterface I.foo(double) with a static invocation of a tiny wrapper method ('shim') in X like this:
      invokestatic X.$shim$2(I callee, double d, Fiber f)
 
The shim method in turn turns around and calls I.foo(double):
     private static int X.$shim$2(I callee, double d, Fiber f) {
        int ret = callee.f(d, f);
        f.setCallee(callee); // this is the purpose of the shim
        return ret;
     }
 
The purpose of SAMweaver is to generate the shim above.

Why?

Ordinarily, all hand-written code is modified by the weaver if it contains definitions or invocations of pausable methods. Lambda expressions however rely on the VM generating a class at run-time, which implements the functional interface (I in the example). The problem is that this class needs to be woven to support kilim Fibers, but we don't have an easy portable hook to weave it at run-time.

As it turns out, practically all the weaving work is already complete at compile time. This is because, the body of the lambda expression is already available to the weaver as an ordinary method in the host class X, and is treated like any another pausable method. In other words, the transformations at the calling site and in the body of the called method are as usual. All that this is left for the shim to do is to capture the object's reference (f.setCallee); the fiber needs it while resuming. The call to setCallee is redundant for ordinary hand-written implementations of SAM interfaces, but is necessary if the implementation happens to be generated by the VM as described above.

Of course, all this applies only if the functional method is pausable.

  • Field Details

  • Constructor Details

  • Method Details

    • setIndex

      public void setIndex(int index)
    • equals

      public boolean equals(Object obj)
      Overrides:
      equals in class Object
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
    • getShimMethodName

      String getShimMethodName()
    • getShimDesc

      String getShimDesc()
    • accept

      public void accept(org.objectweb.asm.ClassVisitor cv)
      Generate a method like this:
       private static $shim$1 (I callee, ...args..., f fiber) {
          load each arg
          call interface.method
          f.setCallee(arg0)
          xret
       }
       
      Parameters:
      cv -
    • internalName

      static String[] internalName(String[] words)
    • getExceptions

      private String[] getExceptions()