org.objectweb.fractal.julia.asm
Class MetaCodeGenerator

java.lang.Object
  extended by org.objectweb.fractal.julia.asm.MetaCodeGenerator
All Implemented Interfaces:
Opcodes, CodeGenerator, Initializable

public abstract class MetaCodeGenerator
extends Object
implements Initializable, CodeGenerator, Opcodes

A CodeGenerator to generate interception code that reifies method calls. This abstract code generator can be used to easily generate interceptors of the following form, without knowing the Java bytecode instructions and ASM:

Figure 1: an interceptor and an associated controller object (see also here)

where the interceptor calls a void handleMethodCall (Method m, Object[] args) method on the controller object at each intercepted method. This abstract code generator can be configured in many ways:

The code adapters returned by the generateInterceptionCode method (see CodeGenerator) transform the original methods into methods of the following form:

 method-signature {
   return (...)delegate.handleMethodCall(
     _Mid, new Object[] { ... });
 }
 

The _Mid static fields are initialized by a static initializer whose code is generated by this code generator. This initializer has the following form:

 static {
   _M0 = Class.forName(...).getMethod(... , new Class[] { ... });
   _M1 = Class.forName(...).getMethod(... , new Class[] { ... });
  ...
 }
 

The generateInitCode method adds a delegate field to the interceptor class, and adds a code fragment of the following form to the generated generateInitCode method (recall that N can be configured with the getControllerInterfaceName method):

 delegate = (...)ic.getFcInterface(N);
 
Finally this code generator takes into account the Julia optimizations options. So, for example, if the interceptors and controller objects are merged, the delegate field is not generated, and this is used instead. Moreover, if the content, the controller and the interceptor classes are merged, then the interception code that is generated takes the following form:

 method-signature {
   if (!isReflectedCall()) {
     return (...)handleMethodCall(
       _Mid, new Object[] { ... });
   } else {
     // original method code
   }
 }
 
The first time this method is called the isReflectedCall method (which must be provided by the associated controller object) must return false. The call is therefore reifed and passed to the handleMethodCall method. This method will then call the method back, through the Java Reflection API, and this time the isReflectedCall must return true, so that the original method code is executed. The name of the isReflectedCall method can be configured with the getIsReflectedCallMethodName method.


Field Summary
 
Fields inherited from interface org.objectweb.fractal.julia.asm.CodeGenerator
IN, IN_OUT, OUT
 
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_NATIVE, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_STATIC, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_TRANSIENT, ACC_VARARGS, ACC_VOLATILE, ACONST_NULL, ALOAD, ANEWARRAY, ARETURN, ARRAYLENGTH, ASTORE, ATHROW, BALOAD, BASTORE, BIPUSH, CALOAD, CASTORE, CHECKCAST, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DMUL, DNEG, DREM, DRETURN, DSTORE, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FMUL, FNEG, FREM, FRETURN, FSTORE, FSUB, GETFIELD, GETSTATIC, GOTO, 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, 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, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSUB, LUSHR, LXOR, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, NEW, NEWARRAY, NOP, POP, POP2, PUTFIELD, PUTSTATIC, RET, RETURN, SALOAD, SASTORE, SIPUSH, SWAP, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_SHORT, TABLESWITCH, V1_1, V1_2, V1_3, V1_4, V1_5
 
Constructor Summary
MetaCodeGenerator()
           
 
Method Summary
 void close()
          Closes this code generator.
 void generateCloneCode(MethodVisitor cv)
          Generates the cloning code for this code generator.
 void generateInitCode(MethodVisitor cv)
          Generates the initialization code for this code generator.
 MethodVisitor generateInterceptionCode(Method m, MethodVisitor cv)
          Generates the interception code for the given method.
static void generateMethodInitializerCode(Method m, String owner, String field, ClassVisitor cv, MethodVisitor mv)
          Generates code to initialize a static field containing the Method object.
static void generateParameterReifierCode(Method m, MethodVisitor cv)
          Generates the code to reify the arguments of the given method.
static void generateReturnCode(Method m, MethodVisitor cv)
          Generates the code to unreify the result of the given method.
protected abstract  String getControllerInterfaceName()
          Returns the name of the interface provided by the controller object to be associated to the interceptor.
protected abstract  String getHandleMethodCallMethodName()
          Returns the name of the method to be called on the associated controller object, for each intercepted call.
 List getImplementedInterfaces()
          Returns the list of interfaces to be added to be implemented by the generated interceptor.
protected abstract  String getIsReflectedCallMethodName()
          Returns the name of the method to be called on the associated controller object to identify reflected calls.
 int init(InterceptorClassGenerator icg)
          Initializes this code generator.
 void initialize(Tree args)
          Initializes this object with the given arguments.
protected  boolean intercept(Method m)
          Returns true if this code generator must generate interception code for the given method.
protected  boolean reifyInterfaceName()
          Returns true if the target interface name must be passed as argument to the handleMethodCall method.
protected  boolean reifyTargetObject()
          Returns true if the target object must be passed as argument to the handleMethodCall method.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

MetaCodeGenerator

public MetaCodeGenerator()
Method Detail

initialize

public void initialize(Tree args)
Description copied from interface: Initializable
Initializes this object with the given arguments.

Specified by:
initialize in interface Initializable
Parameters:
args - the arguments to be used to initialize this object. The format of these arguments depends on the class of this object.

init

public int init(InterceptorClassGenerator icg)
Description copied from interface: CodeGenerator
Initializes this code generator.

Specified by:
init in interface CodeGenerator
Parameters:
icg - the interceptor class generator to which this code generator belongs.
Returns:
the type of this code generator, i.e., either IN, OUT or IN_OUT.

generateInitCode

public void generateInitCode(MethodVisitor cv)
                      throws ClassGenerationException
Description copied from interface: CodeGenerator
Generates the initialization code for this code generator. This code is added to the initFcController method by the interceptor class generator that calls this method. By hypothesis, the stack is empty at the beginning of the generated code. Moreover, the stack must also be empty at the end of the code generated by this method.

Specified by:
generateInitCode in interface CodeGenerator
Parameters:
cv - the method visitor to be used to generate the initialization code.
Throws:
ClassGenerationException - if a problem occurs.

generateInterceptionCode

public MethodVisitor generateInterceptionCode(Method m,
                                              MethodVisitor cv)
Description copied from interface: CodeGenerator
Generates the interception code for the given method.

Specified by:
generateInterceptionCode in interface CodeGenerator
Parameters:
m - the method for which the interception code must be generated.
cv - the method visitor to be used to generate the interception code.
Returns:
a method visitor to be used to visit the original method code. This method visitor should be a kind of CodeAdapter, that should add the interception code to the visited code on the fly. See CodeGenerator.

generateCloneCode

public void generateCloneCode(MethodVisitor cv)
Description copied from interface: CodeGenerator
Generates the cloning code for this code generator. This code is added to the clone method by the interceptor class generator that calls this method. By hypothesis, the stack is empty at the beginning of the generated code. Moreover, the stack must also be empty at the end of the code generated by this method.

Specified by:
generateCloneCode in interface CodeGenerator
Parameters:
cv - the method visitor to be used to generate the cloning code.

close

public void close()
Description copied from interface: CodeGenerator
Closes this code generator. This method can be used to do some cleanup before computing the bytecode of the interceptor class.

Specified by:
close in interface CodeGenerator

getControllerInterfaceName

protected abstract String getControllerInterfaceName()
Returns the name of the interface provided by the controller object to be associated to the interceptor.

Returns:
the name of the interface provided by the controller object to be associated to the interceptor (called N in the above figure).

intercept

protected boolean intercept(Method m)
Returns true if this code generator must generate interception code for the given method. The default implementation of this method returns true for all methods.

Parameters:
m - a method object.
Returns:
true if this code generator must generate interception code for the given method, or false if the given method must be left unchanged.

getHandleMethodCallMethodName

protected abstract String getHandleMethodCallMethodName()
Returns the name of the method to be called on the associated controller object, for each intercepted call.

Returns:
the name of the method to be called on the associated controller object, for each intercepted call (called handleMethodCall above).

reifyInterfaceName

protected boolean reifyInterfaceName()
Returns true if the target interface name must be passed as argument to the handleMethodCall method. The default implementation of this method returns false.

Returns:
true if the name of the fractal interface associated to the generated interceptor must be passed as argument to the handleMethodCall method.

reifyTargetObject

protected boolean reifyTargetObject()
Returns true if the target object must be passed as argument to the handleMethodCall method. The default implementation of this method returns false.

Returns:
true if the target object of intercepted method calls must be passed as argument to the handleMethodCall method.

getIsReflectedCallMethodName

protected abstract String getIsReflectedCallMethodName()
Returns the name of the method to be called on the associated controller object to identify reflected calls.

Returns:
the name of the method to be called on the associated controller object to identify reflected calls. (called isReflectedCall above).

generateMethodInitializerCode

public static void generateMethodInitializerCode(Method m,
                                                 String owner,
                                                 String field,
                                                 ClassVisitor cv,
                                                 MethodVisitor mv)
Generates code to initialize a static field containing the Method object.

Parameters:
m - the static field's value.
owner - the internal name of the owner class of the static field.
field - the static field's name.
cv - the class visitor to be used to generate the static field.
mv - the code visitor to be used to generate the static field's initialization code.

generateParameterReifierCode

public static void generateParameterReifierCode(Method m,
                                                MethodVisitor cv)
Generates the code to reify the arguments of the given method. For a method "int m (int i, String s)", this code is the bytecode corresponding to the "new Object[] { new Integer(i), s}" expression.

Parameters:
m - a method object.
cv - the code visitor to be used to generate the bytecode.

generateReturnCode

public static void generateReturnCode(Method m,
                                      MethodVisitor cv)
Generates the code to unreify the result of the given method. For a method "int m (int i, String s)", this code is the bytecode corresponding to the "((Integer)...).intValue()" expression.

Parameters:
m - a method object.
cv - the code visitor to be used to generate the bytecode.

getImplementedInterfaces

public List getImplementedInterfaces()
                              throws ClassGenerationException
Returns the list of interfaces to be added to be implemented by the generated interceptor.

This method provides an empty implementation, returning an empty List.

Subclasses which need to add interfaces to be implemented by the generated interceptor should override this method.

Specified by:
getImplementedInterfaces in interface CodeGenerator
Returns:
the names of all the interfaces this CodeGenerator requires to be implemented by the generated class.
Throws:
ClassGenerationException - if a problem occurs.
See Also:
CodeGenerator.getImplementedInterfaces()