1 4 package com.tc.aspectwerkz.transform.inlining.weaver; 5 6 import com.tc.asm.ClassAdapter; 7 import com.tc.asm.ClassVisitor; 8 import com.tc.asm.MethodVisitor; 9 import com.tc.asm.Type; 10 import com.tc.asm.MethodAdapter; 11 12 import com.tc.aspectwerkz.definition.SystemDefinition; 13 import com.tc.aspectwerkz.joinpoint.management.JoinPointType; 14 import com.tc.aspectwerkz.transform.InstrumentationContext; 15 import com.tc.aspectwerkz.transform.TransformationConstants; 16 import com.tc.aspectwerkz.transform.TransformationUtil; 17 import com.tc.aspectwerkz.transform.inlining.AsmHelper; 18 import com.tc.aspectwerkz.transform.inlining.EmittedJoinPoint; 19 import com.tc.aspectwerkz.reflect.ClassInfo; 20 import com.tc.aspectwerkz.reflect.ConstructorInfo; 21 import com.tc.aspectwerkz.expression.ExpressionContext; 22 import com.tc.aspectwerkz.expression.PointcutType; 23 24 import java.util.Iterator ; 25 import java.util.Set ; 26 27 37 public class ConstructorBodyVisitor extends ClassAdapter implements TransformationConstants { 38 39 private final InstrumentationContext m_ctx; 40 private final ClassInfo m_calleeClassInfo; 41 private String m_declaringTypeName; 42 private Set m_addedMethods; 43 44 52 public ConstructorBodyVisitor(final ClassVisitor cv, 53 final ClassInfo classInfo, 54 final InstrumentationContext ctx, 55 final Set addedMethods) { 56 super(cv); 57 m_calleeClassInfo = classInfo; 58 m_ctx = (InstrumentationContext) ctx; 59 m_addedMethods = addedMethods; 60 } 61 62 71 public void visit(final int version, 72 final int access, 73 final String name, 74 final String signature, 75 final String superName, 76 final String [] interfaces) { 77 m_declaringTypeName = name; 78 super.visit(version, access, name, signature, superName, interfaces); 79 } 80 81 89 public MethodVisitor visitMethod(int access, 90 String name, 91 String desc, 92 String signature, 93 String [] exceptions) { 94 if (!INIT_METHOD_NAME.equals(name)) { 95 return super.visitMethod(access, name, desc, signature, exceptions); 96 } 97 98 int hash = AsmHelper.calculateConstructorHash(desc); 99 ConstructorInfo constructorInfo = m_calleeClassInfo.getConstructor(hash); 100 if (constructorInfo == null) { 101 System.err.println( 102 "AW::WARNING " + 103 "metadata structure could not be build for constructor [" 104 + m_calleeClassInfo.getName().replace('/', '.') 105 + ".<init>: " + desc + ']' 106 ); 107 return cv.visitMethod(access, name, desc, signature, exceptions); 108 } 109 110 ExpressionContext ctx = new ExpressionContext(PointcutType.EXECUTION, constructorInfo, constructorInfo); 111 112 if (constructorFilter(m_ctx.getDefinitions(), ctx)) { 113 return cv.visitMethod(access, name, desc, signature, exceptions); 114 } else { 115 String wrapperName = TransformationUtil.getConstructorBodyMethodName(m_declaringTypeName); 116 String wrapperDesc = TransformationUtil.getConstructorBodyMethodSignature(desc, m_declaringTypeName); 117 if (m_addedMethods.contains(AlreadyAddedMethodAdapter.getMethodKey(wrapperName, wrapperDesc))) { 118 return cv.visitMethod(access, name, desc, signature, exceptions); 119 } 120 121 m_ctx.markAsAdvised(); 122 123 MethodVisitor proxyCtorMethodVisitor = cv.visitMethod(access, name, desc, signature, exceptions); 125 int modifiers = ACC_SYNTHETIC | ACC_STATIC; 127 MethodVisitor ctorBodyMethodMethodVisitor = cv.visitMethod( 128 modifiers, wrapperName, wrapperDesc, signature, exceptions 129 ); 130 131 return new DispatchCtorBodyCodeAdapter(proxyCtorMethodVisitor, ctorBodyMethodMethodVisitor, access, desc); 133 } 134 } 135 136 137 144 private void insertJoinPointInvoke(final MethodVisitor ctorProxy, 145 final int access, 146 final String desc) { 147 ctorProxy.visitVarInsn(ALOAD, 0); AsmHelper.loadArgumentTypes(ctorProxy, Type.getArgumentTypes(desc), false); 151 152 ctorProxy.visitVarInsn(ALOAD, 0); 154 155 int joinPointHash = AsmHelper.calculateConstructorHash(desc); 156 String joinPointClassName = TransformationUtil.getJoinPointClassName( 157 m_declaringTypeName, 158 INIT_METHOD_NAME, 159 desc, 160 m_declaringTypeName, 161 JoinPointType.CONSTRUCTOR_EXECUTION_INT, 162 joinPointHash 163 ); 164 165 ctorProxy.visitMethodInsn( 166 INVOKESTATIC, 167 joinPointClassName, 168 INVOKE_METHOD_NAME, 169 TransformationUtil.getInvokeSignatureForCodeJoinPoints( 170 access, desc, m_declaringTypeName, m_declaringTypeName 171 ) 172 ); 173 174 m_ctx.addEmittedJoinPoint( 176 new EmittedJoinPoint( 177 JoinPointType.CONSTRUCTOR_EXECUTION_INT, 178 m_declaringTypeName, 179 TransformationConstants.INIT_METHOD_NAME, 180 desc, 181 access, 182 m_declaringTypeName, 183 TransformationConstants.INIT_METHOD_NAME, 184 desc, 185 access, 186 joinPointHash, 187 joinPointClassName, 188 EmittedJoinPoint.NO_LINE_NUMBER 189 ) 190 ); 191 } 192 193 200 public static boolean constructorFilter(final Set definitions, 201 final ExpressionContext ctx) { 202 for (Iterator it = definitions.iterator(); it.hasNext();) { 203 if (((SystemDefinition) it.next()).hasPointcut(ctx)) { 204 return false; 205 } else { 206 continue; 207 } 208 } 209 return true; 210 } 211 212 226 private class DispatchCtorBodyCodeAdapter extends MethodAdapter { 227 private MethodVisitor m_ctorBodyMethodMethodVisitor; 228 private MethodVisitor m_proxyCtorMethodVisitor; 229 private final int m_constructorAccess; 230 private final String m_constructorDesc; 231 232 private int m_newCount = 0; 233 234 private boolean m_proxyCtorCodeDone = false; 235 private boolean m_isALOADDUPHeuristic = false; 236 private int m_index = -1; 237 238 public DispatchCtorBodyCodeAdapter(MethodVisitor proxyCtor, MethodVisitor ctorBodyMethod, final int access, 239 final String desc) { 240 super(proxyCtor); 241 m_proxyCtorMethodVisitor = proxyCtor; 242 m_ctorBodyMethodMethodVisitor = ctorBodyMethod; 243 m_constructorAccess = access; 244 m_constructorDesc = desc; 245 } 246 247 public void visitInsn(int opcode) { 248 super.visitInsn(opcode); 249 if (!m_proxyCtorCodeDone && opcode == DUP && m_index == 0) { 250 m_isALOADDUPHeuristic = true; 252 m_index++; 253 } 254 } 255 256 public void visitIntInsn(int i, int i1) { 257 super.visitIntInsn(i, i1); 258 } 259 260 public void visitVarInsn(int opcode, int i1) { 261 super.visitVarInsn(opcode, i1); 262 if (!m_proxyCtorCodeDone) { 263 if (opcode == ALOAD && i1 == 0) { 264 m_index++; 265 } 266 } 267 } 268 269 public void visitFieldInsn(int i, String s, String s1, String s2) { 270 super.visitFieldInsn(i, s, s1, s2); 271 } 272 273 public void visitLdcInsn(Object o) { 274 super.visitLdcInsn(o); 275 } 276 277 public void visitIincInsn(int i, int i1) { 278 super.visitIincInsn(i, i1); 279 } 280 281 public void visitMultiANewArrayInsn(String s, int i) { 282 super.visitMultiANewArrayInsn(s, i); 283 } 284 285 291 public void visitTypeInsn(int opcode, String name) { 292 super.visitTypeInsn(opcode, name); 293 if (opcode == NEW) { 294 m_newCount++; 295 } 296 } 297 298 public void visitMethodInsn(int opcode, 299 String owner, 300 String name, 301 String desc) { 302 if (!m_proxyCtorCodeDone) { 303 if (opcode == INVOKESPECIAL) { 304 if (m_newCount == 0) { 305 m_proxyCtorMethodVisitor.visitMethodInsn(opcode, owner, name, desc); 307 insertJoinPointInvoke(m_proxyCtorMethodVisitor, m_constructorAccess, m_constructorDesc); 309 m_proxyCtorMethodVisitor.visitInsn(RETURN); 310 m_proxyCtorMethodVisitor.visitMaxs(0, 0); 311 m_proxyCtorMethodVisitor = null; 312 m_proxyCtorCodeDone = true; 313 mv = m_ctorBodyMethodMethodVisitor; 314 if (m_isALOADDUPHeuristic) { 316 m_ctorBodyMethodMethodVisitor.visitVarInsn(ALOAD, 0); 317 } 318 } else { 319 m_newCount--; 320 mv.visitMethodInsn(opcode, owner, name, desc); 321 } 322 } else { 323 mv.visitMethodInsn(opcode, owner, name, desc); 324 } 325 } else { 326 mv.visitMethodInsn(opcode, owner, name, desc); 327 } 328 } 329 330 } 331 } 332 | Popular Tags |