KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > transform > inlining > compiler > RuntimeCheckVisitor


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.transform.inlining.compiler;
5
6 import com.tc.asm.MethodVisitor;
7 import com.tc.asm.Opcodes;
8
9 import com.tc.aspectwerkz.aspect.AdviceInfo;
10 import com.tc.aspectwerkz.aspect.container.AspectFactoryManager;
11 import com.tc.aspectwerkz.cflow.CflowCompiler;
12 import com.tc.aspectwerkz.expression.ast.ASTAnd;
13 import com.tc.aspectwerkz.expression.ast.ASTArgs;
14 import com.tc.aspectwerkz.expression.ast.ASTCall;
15 import com.tc.aspectwerkz.expression.ast.ASTCflow;
16 import com.tc.aspectwerkz.expression.ast.ASTCflowBelow;
17 import com.tc.aspectwerkz.expression.ast.ASTExecution;
18 import com.tc.aspectwerkz.expression.ast.ASTGet;
19 import com.tc.aspectwerkz.expression.ast.ASTHandler;
20 import com.tc.aspectwerkz.expression.ast.ASTHasField;
21 import com.tc.aspectwerkz.expression.ast.ASTHasMethod;
22 import com.tc.aspectwerkz.expression.ast.ASTNot;
23 import com.tc.aspectwerkz.expression.ast.ASTOr;
24 import com.tc.aspectwerkz.expression.ast.ASTPointcutReference;
25 import com.tc.aspectwerkz.expression.ast.ASTSet;
26 import com.tc.aspectwerkz.expression.ast.ASTStaticInitialization;
27 import com.tc.aspectwerkz.expression.ast.ASTTarget;
28 import com.tc.aspectwerkz.expression.ast.ASTThis;
29 import com.tc.aspectwerkz.expression.ast.ASTWithin;
30 import com.tc.aspectwerkz.expression.ast.ASTWithinCode;
31 import com.tc.aspectwerkz.expression.ExpressionVisitor;
32 import com.tc.aspectwerkz.expression.ExpressionInfo;
33 import com.tc.aspectwerkz.expression.Undeterministic;
34 import com.tc.aspectwerkz.expression.ExpressionNamespace;
35 import com.tc.aspectwerkz.expression.ExpressionContext;
36 import com.tc.aspectwerkz.transform.TransformationConstants;
37 import com.tc.aspectwerkz.transform.inlining.AsmHelper;
38 import com.tc.aspectwerkz.transform.inlining.compiler.AbstractJoinPointCompiler;
39
40 /**
41  * Visit an expression and push on the bytecode stack the boolean expression that corresponds to the residual
42  * part for the target(CALLEE) filtering and cflow / cflowbelow runtime checks
43  * <p/>
44  * TODO: for now OR / AND / NOT are turned in IAND etc, ie "&" and not "&&" that is more efficient but is using labels.
45  * <p/>
46  * Note: we have to override here (and maintain) every visit Method that visit a node that appears in an expression
47  * (f.e. set , getDefault, etc, but not ASTParameter), since we cannot rely on AND/OR/NOT nodes to push the boolean expressions.
48  *
49  * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur</a>
50  */

51 public class RuntimeCheckVisitor extends ExpressionVisitor implements Opcodes {
52   public static final int NULL_PER_OBJECT_TYPE = -1;
53   public static final int PER_THIS_TYPE = 1;
54   public static final int PER_TARGET_TYPE = 2;
55
56   private MethodVisitor cv;
57
58   private CompilerInput m_input;
59
60   private int m_perObjectCheckType = NULL_PER_OBJECT_TYPE;
61
62   private String JavaDoc m_aspectQName;
63
64   /**
65    * Create a new visitor given a specific AdviceInfo
66    *
67    * @param cv of the method block we are compiling
68    * @param info expression info
69    * @param input
70    * @param perObjectType
71    * @param aspectQName
72    */

73   public RuntimeCheckVisitor(final MethodVisitor cv,
74                              final ExpressionInfo info,
75                              final CompilerInput input,
76                              final int perObjectType,
77                              final String JavaDoc aspectQName) {
78     super(
79             info,
80             info.toString(),
81             info.getNamespace(),
82             info.getExpression().getASTRoot()
83     );
84     m_input = input;
85     m_perObjectCheckType = perObjectType;
86     m_aspectQName = aspectQName;
87
88     this.cv = cv;
89   }
90
91   /**
92    * Push the boolean typed expression on the stack.
93    *
94    * @param adviceInfo
95    */

96   public void pushCheckOnStack(AdviceInfo adviceInfo) {
97     super.match(adviceInfo.getExpressionContext());
98
99     switch (m_perObjectCheckType) {
100       case PER_THIS_TYPE: {
101         AbstractJoinPointCompiler.loadCaller(cv, m_input);
102         cv.visitMethodInsn(
103                 INVOKESTATIC,
104                 AspectFactoryManager.getAspectFactoryClassName(
105                         adviceInfo.getAspectClassName(),
106                         adviceInfo.getAspectQualifiedName()
107                 ),
108                 TransformationConstants.FACTORY_HASASPECT_METHOD_NAME,
109                 TransformationConstants.FACTORY_HASASPECT_PEROBJECT_METHOD_SIGNATURE
110         );
111         cv.visitInsn(IAND);
112
113         break;
114       }
115
116       case PER_TARGET_TYPE: {
117         AbstractJoinPointCompiler.loadCallee(cv, m_input);
118         cv.visitMethodInsn(
119                 INVOKESTATIC,
120                 AspectFactoryManager.getAspectFactoryClassName(
121                         adviceInfo.getAspectClassName(),
122                         adviceInfo.getAspectQualifiedName()
123                 ),
124                 TransformationConstants.FACTORY_HASASPECT_METHOD_NAME,
125                 TransformationConstants.FACTORY_HASASPECT_PEROBJECT_METHOD_SIGNATURE
126         );
127         cv.visitInsn(IAND);
128
129         break;
130       }
131     }
132   }
133
134   /**
135    * Handles OR expression
136    *
137    * @param node
138    * @param data
139    * @return
140    */

141   public Object JavaDoc visit(ASTOr node, Object JavaDoc data) {
142     Boolean JavaDoc matchL = (Boolean JavaDoc) node.jjtGetChild(0).jjtAccept(this, data);
143     Boolean JavaDoc matchR = (Boolean JavaDoc) node.jjtGetChild(1).jjtAccept(this, data);
144     Boolean JavaDoc intermediate = Undeterministic.or(matchL, matchR);
145     cv.visitInsn(IOR);
146     for (int i = 2; i < node.jjtGetNumChildren(); i++) {
147       Boolean JavaDoc matchNext = (Boolean JavaDoc) node.jjtGetChild(i).jjtAccept(this, data);
148       intermediate = Undeterministic.or(intermediate, matchNext);
149       cv.visitInsn(IOR);
150     }
151     return intermediate;
152   }
153
154   public Object JavaDoc visit(ASTAnd node, Object JavaDoc data) {
155     Boolean JavaDoc matchL = (Boolean JavaDoc) node.jjtGetChild(0).jjtAccept(this, data);
156     Boolean JavaDoc matchR = (Boolean JavaDoc) node.jjtGetChild(1).jjtAccept(this, data);
157     Boolean JavaDoc intermediate = Undeterministic.and(matchL, matchR);
158     cv.visitInsn(IAND);
159     for (int i = 2; i < node.jjtGetNumChildren(); i++) {
160       Boolean JavaDoc matchNext = (Boolean JavaDoc) node.jjtGetChild(i).jjtAccept(this, data);
161       intermediate = Undeterministic.and(intermediate, matchNext);
162       cv.visitInsn(IAND);
163     }
164     return intermediate;
165   }
166
167   public Object JavaDoc visit(ASTNot node, Object JavaDoc data) {
168     Boolean JavaDoc match = (Boolean JavaDoc) node.jjtGetChild(0).jjtAccept(this, data);
169     cv.visitInsn(INEG);
170     return Undeterministic.not(match);
171   }
172
173   public Object JavaDoc visit(ASTTarget node, Object JavaDoc data) {
174     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
175     if (match != null) {
176       push(match);
177     } else {
178       // runtime check
179
String JavaDoc boundedTypeDesc = AsmHelper.convertReflectDescToTypeDesc(node.getBoundedType(m_expressionInfo));
180       AbstractJoinPointCompiler.loadCallee(cv, m_input);
181       cv.visitTypeInsn(INSTANCEOF, boundedTypeDesc.substring(1, boundedTypeDesc.length() - 1));
182     }
183     return match;
184   }
185
186   public Object JavaDoc visit(ASTThis node, Object JavaDoc data) {
187     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
188     push(match);
189     return match;
190   }
191
192   public Object JavaDoc visit(ASTCflow node, Object JavaDoc data) {
193     // runtime check
194
String JavaDoc cflowClassName = CflowCompiler.getCflowAspectClassName(node.hashCode());
195     cv.visitMethodInsn(
196             INVOKESTATIC,
197             cflowClassName,
198             TransformationConstants.IS_IN_CFLOW_METOD_NAME,
199             TransformationConstants.IS_IN_CFLOW_METOD_SIGNATURE
200     );
201     return super.visit(node, data);
202   }
203
204   public Object JavaDoc visit(ASTCflowBelow node, Object JavaDoc data) {
205     // runtime check
206
//TODO: cflowbelow ID will differ from cflow one.. => not optimized
207
String JavaDoc cflowClassName = CflowCompiler.getCflowAspectClassName(node.hashCode());
208     cv.visitMethodInsn(
209             INVOKESTATIC,
210             cflowClassName,
211             TransformationConstants.IS_IN_CFLOW_METOD_NAME,
212             TransformationConstants.IS_IN_CFLOW_METOD_SIGNATURE
213     );
214     return super.visit(node, data);
215   }
216
217   public Object JavaDoc visit(ASTArgs node, Object JavaDoc data) {
218     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
219     push(match);
220     return match;
221   }
222
223   public Object JavaDoc visit(ASTPointcutReference node, Object JavaDoc data) {
224     ExpressionContext context = (ExpressionContext) data;
225     ExpressionNamespace namespace = ExpressionNamespace.getNamespace(m_namespace);
226     ExpressionVisitor expression = namespace.getExpression(node.getName());
227
228     // build a new RuntimeCheckVisitor to visit the sub expression
229
RuntimeCheckVisitor referenced = new RuntimeCheckVisitor(
230             cv,
231             expression.getExpressionInfo(),
232             m_input,
233             m_perObjectCheckType,
234             m_aspectQName
235     );
236     return referenced.matchUndeterministic(context);
237   }
238
239   public Object JavaDoc visit(ASTExecution node, Object JavaDoc data) {
240     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
241     push(match);
242     return match;
243   }
244
245   public Object JavaDoc visit(ASTCall node, Object JavaDoc data) {
246     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
247     push(match);
248     return match;
249   }
250
251   public Object JavaDoc visit(ASTSet node, Object JavaDoc data) {
252     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
253     push(match);
254     return match;
255   }
256
257   public Object JavaDoc visit(ASTGet node, Object JavaDoc data) {
258     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
259     push(match);
260     return match;
261   }
262
263   public Object JavaDoc visit(ASTHandler node, Object JavaDoc data) {
264     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
265     push(match);
266     return match;
267   }
268
269   public Object JavaDoc visit(ASTStaticInitialization node, Object JavaDoc data) {
270     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
271     push(match);
272     return match;
273   }
274
275   public Object JavaDoc visit(ASTWithin node, Object JavaDoc data) {
276     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
277     push(match);
278     return match;
279   }
280
281   public Object JavaDoc visit(ASTWithinCode node, Object JavaDoc data) {
282     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
283     push(match);
284     return match;
285   }
286
287   public Object JavaDoc visit(ASTHasMethod node, Object JavaDoc data) {
288     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
289     push(match);
290     return match;
291   }
292
293   public Object JavaDoc visit(ASTHasField node, Object JavaDoc data) {
294     Boolean JavaDoc match = (Boolean JavaDoc) super.visit(node, data);
295     push(match);
296     return match;
297   }
298
299
300   private void push(Boolean JavaDoc b) {
301     if (b == null) {
302       throw new Error JavaDoc("attempt to push an undetermined match result");
303     } else if (b.booleanValue()) {
304       cv.visitInsn(ICONST_1);
305     } else {
306       cv.visitInsn(ICONST_M1);
307     }
308   }
309 }
310
Popular Tags