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.
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.
Constants.UtilALOAD_0, ASTORE_0, D_ARRAY_BOOLEAN, D_ARRAY_BYTE, D_ARRAY_CHAR, D_ARRAY_DOUBLE, D_ARRAY_FLOAT, D_ARRAY_INT, D_ARRAY_LONG, D_ARRAY_SHORT, D_BOOLEAN, D_BYTE, D_CHAR, D_DOUBLE, D_FIBER, D_FIBER_LAST_ARG, D_FLOAT, D_INT, D_LONG, D_NULL, D_OBJECT, D_PAUSABLE, D_RETURN_ADDRESS, D_SHORT, D_STATE, D_STRING, D_TASK, D_THROWABLE, D_UNDEFINED, D_VOID, DLOAD_0, DSTORE_0, FIBER_CLASS, FLOAD_0, FSTORE_0, ILOAD_0, ISTORE_0, KILIM_ASM, KILIM_VERSION, LDC2_W, LLOAD_0, LSTORE_0, NOT_PAUSABLE_CLASS, PAUSABLE_CLASS, SAM_SHIM_PREFIX, STATE_CLASS, TASK_CLASS, THROWABLE_CLASS, WOVEN_FIELD| Constructor and Description |
|---|
SAMweaver(KilimContext context,
java.lang.String interfaceName,
java.lang.String methodName,
java.lang.String desc,
boolean itf) |
| Modifier and Type | Method and Description |
|---|---|
void |
accept(ClassVisitor cv)
Generate a method like this:
|
boolean |
equals(java.lang.Object obj) |
int |
hashCode() |
void |
setIndex(int index) |
java.lang.String |
toString() |
public SAMweaver(KilimContext context, java.lang.String interfaceName, java.lang.String methodName, java.lang.String desc, boolean itf)
public void setIndex(int index)
public boolean equals(java.lang.Object obj)
equals in class java.lang.Objectpublic java.lang.String toString()
toString in class java.lang.Objectpublic int hashCode()
hashCode in class java.lang.Objectpublic void accept(ClassVisitor cv)
private static $shim$1 (I callee, ...args..., f fiber) {
load each arg
call interface.method
f.setCallee(arg0)
xret
}
cv -