Class SAMweaver

  • All Implemented Interfaces:
    Constants, org.objectweb.asm.Opcodes

    public class SAMweaver
    extends java.lang.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 Summary

      Fields 
      Modifier and Type Field Description
      (package private) KilimContext context  
      (package private) java.lang.String desc  
      (package private) int index  
      (package private) java.lang.String interfaceName  
      (package private) boolean itf  
      (package private) java.lang.String methodName  
      • Fields inherited from interface org.objectweb.asm.Opcodes

        AALOAD, AASTORE, ACC_ABSTRACT, ACC_ANNOTATION, ACC_BRIDGE, ACC_DEPRECATED, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_MANDATED, ACC_MODULE, ACC_NATIVE, ACC_OPEN, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_RECORD, ACC_STATIC, ACC_STATIC_PHASE, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_TRANSIENT, ACC_TRANSITIVE, ACC_VARARGS, ACC_VOLATILE, ACONST_NULL, ALOAD, ANEWARRAY, ARETURN, ARRAYLENGTH, ASM10_EXPERIMENTAL, ASM4, ASM5, ASM6, ASM7, ASM8, ASM9, ASTORE, ATHROW, BALOAD, BASTORE, BIPUSH, CALOAD, CASTORE, CHECKCAST, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DMUL, DNEG, DOUBLE, DREM, DRETURN, DSTORE, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F_APPEND, F_CHOP, F_FULL, F_NEW, F_SAME, F_SAME1, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAT, FMUL, FNEG, FREM, FRETURN, FSTORE, FSUB, GETFIELD, GETSTATIC, GOTO, H_GETFIELD, H_GETSTATIC, H_INVOKEINTERFACE, H_INVOKESPECIAL, H_INVOKESTATIC, H_INVOKEVIRTUAL, H_NEWINVOKESPECIAL, H_PUTFIELD, H_PUTSTATIC, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILOAD, IMUL, INEG, INSTANCEOF, INTEGER, INVOKEDYNAMIC, INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC, INVOKEVIRTUAL, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISUB, IUSHR, IXOR, JSR, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDIV, LLOAD, LMUL, LNEG, LONG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSUB, LUSHR, LXOR, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, NEW, NEWARRAY, NOP, NULL, POP, POP2, PUTFIELD, PUTSTATIC, RET, RETURN, SALOAD, SASTORE, SIPUSH, SOURCE_DEPRECATED, SOURCE_MASK, SWAP, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_SHORT, TABLESWITCH, TOP, UNINITIALIZED_THIS, V_PREVIEW, V1_1, V1_2, V1_3, V1_4, V1_5, V1_6, V1_7, V1_8, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V9
    • Constructor Summary

      Constructors 
      Constructor Description
      SAMweaver​(KilimContext context, java.lang.String interfaceName, java.lang.String methodName, java.lang.String desc, boolean itf)  
    • Field Detail

      • interfaceName

        java.lang.String interfaceName
      • methodName

        java.lang.String methodName
      • desc

        java.lang.String desc
      • itf

        boolean itf
      • index

        int index
    • Constructor Detail

      • SAMweaver

        public SAMweaver​(KilimContext context,
                         java.lang.String interfaceName,
                         java.lang.String methodName,
                         java.lang.String desc,
                         boolean itf)
    • Method Detail

      • setIndex

        public void setIndex​(int index)
      • equals

        public boolean equals​(java.lang.Object obj)
        Overrides:
        equals in class java.lang.Object
      • toString

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

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

        java.lang.String getShimMethodName()
      • getShimDesc

        java.lang.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 java.lang.String[] internalName​(java.lang.String[] words)
      • getExceptions

        private java.lang.String[] getExceptions()