KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > cflow > CflowCompiler


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.aspectwerkz.cflow;
5
6 import com.tc.asm.Opcodes;
7 import com.tc.asm.ClassWriter;
8 import com.tc.asm.MethodVisitor;
9 import com.tc.asm.Label;
10
11 import com.tc.aspectwerkz.transform.TransformationConstants;
12 import com.tc.aspectwerkz.transform.inlining.AsmHelper;
13 import com.tc.aspectwerkz.transform.inlining.compiler.AbstractJoinPointCompiler;
14
15 /**
16  * Compiler for the JIT cflow Aspect
17  *
18  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
19  */

20 public class CflowCompiler implements Opcodes, TransformationConstants {
21
22   public final static String JavaDoc JIT_CFLOW_CLASS = "com/tc/aspectwerkz/cflow/Cflow_";
23   private final static String JavaDoc ABSTRACT_CFLOW_CLASS = "com/tc/aspectwerkz/cflow/AbstractCflowSystemAspect";
24   private final static String JavaDoc INSTANCE_CFLOW_FIELD_NAME = "INSTANCE";
25   public static final String JavaDoc IN_CFLOW_METOD_NAME = "inCflow";
26   public static final String JavaDoc IN_CFLOW_METOD_SIGNATURE = "()Z";
27   public static final String JavaDoc CFLOW_ASPECTOF_METHOD_NAME = "aspectOf";
28
29   /**
30    * Checks if a class name (ASM style) is a cflow name
31    *
32    * @param className
33    * @return
34    */

35   public static boolean isCflowClass(String JavaDoc className) {
36     return className.indexOf(JIT_CFLOW_CLASS) >= 0;
37   }
38
39   /**
40    * The jit cflow aspect class name (with /)
41    */

42   private final String JavaDoc m_className;
43
44   /**
45    * The jit cflow aspect class name (with /)
46    */

47   private final String JavaDoc m_classSignature;
48
49   private ClassWriter m_cw;
50
51   /**
52    * private ctor
53    *
54    * @param cflowId
55    */

56   private CflowCompiler(int cflowId) {
57     m_className = getCflowAspectClassName(cflowId);
58     m_classSignature = "L" + m_className + ";";
59   }
60
61   /**
62    * compile the jit cflow aspect
63    *
64    * @return bytecode for the concrete jit cflow aspect
65    */

66   private byte[] compile() {
67     m_cw = AsmHelper.newClassWriter(true);
68
69     // class extends AbstractCflowsystemAspect
70
m_cw.visit(
71             AsmHelper.JAVA_VERSION,
72             ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC,
73             m_className,
74             null,
75             ABSTRACT_CFLOW_CLASS,
76             EMPTY_STRING_ARRAY
77     );
78
79     // static INSTANCE field
80
m_cw.visitField(
81             ACC_PRIVATE + ACC_STATIC,
82             INSTANCE_CFLOW_FIELD_NAME,
83             m_classSignature,
84             null,
85             null
86     );
87
88     // private ctor
89
MethodVisitor ctor = m_cw.visitMethod(
90             ACC_PRIVATE,
91             INIT_METHOD_NAME,
92             NO_PARAM_RETURN_VOID_SIGNATURE,
93             null,
94             EMPTY_STRING_ARRAY
95     );
96     // invoke the constructor of abstract
97
ctor.visitVarInsn(ALOAD, 0);
98     ctor.visitMethodInsn(INVOKESPECIAL, ABSTRACT_CFLOW_CLASS, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
99     ctor.visitInsn(RETURN);
100     ctor.visitMaxs(0, 0);
101
102     // static isInCflow() delegators
103
MethodVisitor isInCflow = m_cw.visitMethod(
104             ACC_PUBLIC + ACC_STATIC,
105             IS_IN_CFLOW_METOD_NAME,
106             IS_IN_CFLOW_METOD_SIGNATURE,
107             null,
108             EMPTY_STRING_ARRAY
109     );
110     isInCflow.visitFieldInsn(GETSTATIC, m_className, INSTANCE_CFLOW_FIELD_NAME, m_classSignature);
111     Label isNull = new Label();
112     isInCflow.visitJumpInsn(IFNULL, isNull);
113     isInCflow.visitFieldInsn(GETSTATIC, m_className, INSTANCE_CFLOW_FIELD_NAME, m_classSignature);
114     isInCflow.visitMethodInsn(INVOKEVIRTUAL, ABSTRACT_CFLOW_CLASS, IN_CFLOW_METOD_NAME, IN_CFLOW_METOD_SIGNATURE);
115     isInCflow.visitInsn(IRETURN);
116     isInCflow.visitLabel(isNull);
117     isInCflow.visitInsn(ICONST_0);
118     isInCflow.visitInsn(IRETURN);
119     isInCflow.visitMaxs(0, 0);
120
121     // static aspectOf()
122
MethodVisitor aspectOf = m_cw.visitMethod(
123             ACC_PUBLIC + ACC_STATIC,
124             CFLOW_ASPECTOF_METHOD_NAME,
125             "()" + m_classSignature,
126             null,
127             EMPTY_STRING_ARRAY
128     );
129     aspectOf.visitFieldInsn(GETSTATIC, m_className, INSTANCE_CFLOW_FIELD_NAME, m_classSignature);
130     Label isNotNull = new Label();
131     aspectOf.visitJumpInsn(IFNONNULL, isNotNull);
132     aspectOf.visitTypeInsn(NEW, m_className);
133     aspectOf.visitInsn(DUP);
134     aspectOf.visitMethodInsn(INVOKESPECIAL, m_className, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
135     aspectOf.visitFieldInsn(PUTSTATIC, m_className, INSTANCE_CFLOW_FIELD_NAME, m_classSignature);
136     aspectOf.visitLabel(isNotNull);
137     aspectOf.visitFieldInsn(GETSTATIC, m_className, INSTANCE_CFLOW_FIELD_NAME, m_classSignature);
138     aspectOf.visitInsn(ARETURN);
139     aspectOf.visitMaxs(0, 0);
140
141     m_cw.visitEnd();
142
143     return m_cw.toByteArray();
144   }
145
146   /**
147    * The naming strategy for jit cflow aspect
148    *
149    * @param cflowID
150    * @return com.tc.aspectwerkz.cflow.Cflow_cflowID
151    */

152   public static String JavaDoc getCflowAspectClassName(int cflowID) {
153     return JIT_CFLOW_CLASS + cflowID;
154   }
155
156   /**
157    * If necessary, compile a jit cflow aspect and attach it to the given classloader
158    *
159    * @param loader
160    * @param cflowID
161    * @return
162    */

163   public static Class JavaDoc compileCflowAspectAndAttachToClassLoader(ClassLoader JavaDoc loader, int cflowID) {
164     // System.out.println("------------------> compileCflowAspectAndAttachToClassLoader: loader = " + loader);
165
//TODO we need a Class.forName check first to avoid unecessary compilation
166
// else it will fail in defineClass and fallback on Class.forName ie uneeded compilation
167
// -> price to pay between compilation + exception in the worse case vs Class.forName each time
168
CompiledCflowAspect cflowAspect = compileCflowAspect(cflowID);
169
170     if (AbstractJoinPointCompiler.DUMP_JP_CLASSES) {
171       try {
172         AsmHelper.dumpClass("_dump", getCflowAspectClassName(cflowID), cflowAspect.bytecode);
173       } catch (Throwable JavaDoc t) {
174         ;
175       }
176     }
177
178     Class JavaDoc cflowAspectClass = AsmHelper.defineClass(
179             loader,
180             cflowAspect.bytecode,
181             getCflowAspectClassName(cflowID)
182     );
183     return cflowAspectClass;
184   }
185
186   /**
187    * Compile a jit cflow aspect
188    *
189    * @param cflowID
190    * @return
191    */

192   public static CompiledCflowAspect compileCflowAspect(int cflowID) {
193     CompiledCflowAspect cflowAspect = new CompiledCflowAspect();
194     CflowCompiler compiler = new CflowCompiler(cflowID);
195     cflowAspect.bytecode = compiler.compile();
196     cflowAspect.className = compiler.m_className;
197     return cflowAspect;
198   }
199
200   /**
201    * Information about a compiled Cflow Aspect
202    */

203   public static class CompiledCflowAspect {
204     public byte[] bytecode;
205     public String JavaDoc className;// ASM style
206

207     public boolean equals(Object JavaDoc o) {
208       if (this == o) return true;
209       if (!(o instanceof CompiledCflowAspect)) return false;
210
211       final CompiledCflowAspect compiledCflowAspect = (CompiledCflowAspect) o;
212
213       if (!className.equals(compiledCflowAspect.className)) return false;
214
215       return true;
216     }
217
218     public int hashCode() {
219       return className.hashCode();
220     }
221   }
222 }
223
Popular Tags