1 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 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 m_aspectQName; 63 64 73 public RuntimeCheckVisitor(final MethodVisitor cv, 74 final ExpressionInfo info, 75 final CompilerInput input, 76 final int perObjectType, 77 final String 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 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 141 public Object visit(ASTOr node, Object data) { 142 Boolean matchL = (Boolean ) node.jjtGetChild(0).jjtAccept(this, data); 143 Boolean matchR = (Boolean ) node.jjtGetChild(1).jjtAccept(this, data); 144 Boolean intermediate = Undeterministic.or(matchL, matchR); 145 cv.visitInsn(IOR); 146 for (int i = 2; i < node.jjtGetNumChildren(); i++) { 147 Boolean matchNext = (Boolean ) 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 visit(ASTAnd node, Object data) { 155 Boolean matchL = (Boolean ) node.jjtGetChild(0).jjtAccept(this, data); 156 Boolean matchR = (Boolean ) node.jjtGetChild(1).jjtAccept(this, data); 157 Boolean intermediate = Undeterministic.and(matchL, matchR); 158 cv.visitInsn(IAND); 159 for (int i = 2; i < node.jjtGetNumChildren(); i++) { 160 Boolean matchNext = (Boolean ) 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 visit(ASTNot node, Object data) { 168 Boolean match = (Boolean ) node.jjtGetChild(0).jjtAccept(this, data); 169 cv.visitInsn(INEG); 170 return Undeterministic.not(match); 171 } 172 173 public Object visit(ASTTarget node, Object data) { 174 Boolean match = (Boolean ) super.visit(node, data); 175 if (match != null) { 176 push(match); 177 } else { 178 String 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 visit(ASTThis node, Object data) { 187 Boolean match = (Boolean ) super.visit(node, data); 188 push(match); 189 return match; 190 } 191 192 public Object visit(ASTCflow node, Object data) { 193 String 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 visit(ASTCflowBelow node, Object data) { 205 String 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 visit(ASTArgs node, Object data) { 218 Boolean match = (Boolean ) super.visit(node, data); 219 push(match); 220 return match; 221 } 222 223 public Object visit(ASTPointcutReference node, Object data) { 224 ExpressionContext context = (ExpressionContext) data; 225 ExpressionNamespace namespace = ExpressionNamespace.getNamespace(m_namespace); 226 ExpressionVisitor expression = namespace.getExpression(node.getName()); 227 228 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 visit(ASTExecution node, Object data) { 240 Boolean match = (Boolean ) super.visit(node, data); 241 push(match); 242 return match; 243 } 244 245 public Object visit(ASTCall node, Object data) { 246 Boolean match = (Boolean ) super.visit(node, data); 247 push(match); 248 return match; 249 } 250 251 public Object visit(ASTSet node, Object data) { 252 Boolean match = (Boolean ) super.visit(node, data); 253 push(match); 254 return match; 255 } 256 257 public Object visit(ASTGet node, Object data) { 258 Boolean match = (Boolean ) super.visit(node, data); 259 push(match); 260 return match; 261 } 262 263 public Object visit(ASTHandler node, Object data) { 264 Boolean match = (Boolean ) super.visit(node, data); 265 push(match); 266 return match; 267 } 268 269 public Object visit(ASTStaticInitialization node, Object data) { 270 Boolean match = (Boolean ) super.visit(node, data); 271 push(match); 272 return match; 273 } 274 275 public Object visit(ASTWithin node, Object data) { 276 Boolean match = (Boolean ) super.visit(node, data); 277 push(match); 278 return match; 279 } 280 281 public Object visit(ASTWithinCode node, Object data) { 282 Boolean match = (Boolean ) super.visit(node, data); 283 push(match); 284 return match; 285 } 286 287 public Object visit(ASTHasMethod node, Object data) { 288 Boolean match = (Boolean ) super.visit(node, data); 289 push(match); 290 return match; 291 } 292 293 public Object visit(ASTHasField node, Object data) { 294 Boolean match = (Boolean ) super.visit(node, data); 295 push(match); 296 return match; 297 } 298 299 300 private void push(Boolean b) { 301 if (b == null) { 302 throw new Error ("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 |