1 5 package com.tc.object.bytecode; 6 7 import com.tc.asm.ClassAdapter; 8 import com.tc.asm.ClassVisitor; 9 import com.tc.asm.FieldVisitor; 10 import com.tc.asm.Label; 11 import com.tc.asm.MethodVisitor; 12 import com.tc.asm.Opcodes; 13 import com.tc.asm.Type; 14 import com.tc.asm.commons.LocalVariablesSorter; 15 import com.tc.aspectwerkz.reflect.ClassInfo; 16 import com.tc.object.Portability; 17 import com.tc.object.config.TransparencyClassSpec; 18 19 import java.lang.reflect.Method ; 20 import java.lang.reflect.Modifier ; 21 import java.util.Arrays ; 22 import java.util.Collection ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.LinkedHashSet ; 26 import java.util.Map ; 27 import java.util.Set ; 28 29 32 public abstract class ClassAdapterBase extends ClassAdapter implements Opcodes { 33 public static final String MANAGED_FIELD_NAME = ByteCodeUtil.TC_FIELD_PREFIX 34 + "MANAGED"; 35 public static final String MANAGED_FIELD_TYPE = "Lcom/tc/object/TCObject;"; 36 public static final String MANAGED_METHOD = ByteCodeUtil.TC_METHOD_PREFIX 37 + "managed"; 38 public static final String IS_MANAGED_METHOD = ByteCodeUtil.TC_METHOD_PREFIX 39 + "isManaged"; 40 public static final String IS_MANAGED_DESCRIPTION = "()Z"; 41 42 public static final String VALUES_GETTER = ByteCodeUtil.VALUES_GETTER; 43 public static final String VALUES_GETTER_DESCRIPTION = ByteCodeUtil.VALUES_GETTER_DESCRIPTION; 44 public static final String VALUES_SETTER = ByteCodeUtil.VALUES_SETTER; 45 public static final String VALUES_SETTER_DESCRIPTION = ByteCodeUtil.VALUES_SETTER_DESCRIPTION; 46 public static final String MANAGED_VALUES_GETTER = ByteCodeUtil.MANAGED_VALUES_GETTER; 47 public static final String MANAGED_VALUES_GETTER_DESCRIPTION = ByteCodeUtil.MANAGED_VALUES_GETTER_DESCRIPTION; 48 public static final String MANAGED_VALUES_SETTER = ByteCodeUtil.MANAGED_VALUES_SETTER; 49 50 private static final String LOGICAL_TYPE_DELEGATE_FIELD_NAME_PREFIX = "__delegate_tc_"; 51 private static final int LOGICAL_TYPE_DELEGATE_FIELD_MODIFIER = ACC_PRIVATE + ACC_TRANSIENT; 52 53 private final Map fields = new HashMap (); 54 protected final InstrumentationSpec spec; 55 private final Portability portability; 56 private boolean hasVisitedDelegateField = false; 57 58 public static String getDelegateFieldName(String logicalExtendingClassName) { 59 return LOGICAL_TYPE_DELEGATE_FIELD_NAME_PREFIX 60 + logicalExtendingClassName.replace('.', '_').replace('/', '_').replace('$', '_'); 61 } 62 63 public static boolean isDelegateFieldName(String fieldName) { 64 return fieldName.startsWith(LOGICAL_TYPE_DELEGATE_FIELD_NAME_PREFIX); 65 } 66 67 protected TransparencyClassSpec getTransparencyClassSpec() { 68 return spec.getTransparencyClassSpec(); 69 } 70 71 protected InstrumentationSpec getInstrumentationSpec() { 72 return spec; 73 } 74 75 private boolean isRoot(String fieldName) { 76 return getTransparencyClassSpec().isRootInThisClass(fieldName); 77 } 78 79 public ClassAdapterBase(ClassInfo classInfo, TransparencyClassSpec spec, ClassVisitor delegate, ManagerHelper mgrHelper, 80 ClassLoader caller, Portability p) { 81 super(delegate); 82 this.portability = p; 83 this.spec = new InstrumentationSpec(classInfo, spec, mgrHelper, caller); 84 } 85 86 public final void visit(int version, int access, String name, String signature, String superName, String [] interfaces) { 87 spec.initialize(version, access, name, signature, superName, interfaces, portability); 88 89 if (spec.isClassNotAdaptable()) { 90 super.visit(version, access, name, signature, superName, interfaces); 91 return; 92 } 93 94 if (spec.isClassPortable()) { 95 interfaces = getNewInterfacesForPortableObject(interfaces); 96 } 97 98 basicVisit(version, access, name, signature, superName, interfaces); 99 } 100 101 private void visitDelegateFieldIfNecessary() { 102 if (!hasVisitedDelegateField) { 103 hasVisitedDelegateField = true; 104 String superClassNameSlashes = spec.getSuperClassNameSlashes(); 105 String delegateFieldName = getDelegateFieldName(superClassNameSlashes); 106 String delegateFieldType = "L" + superClassNameSlashes + ";"; 107 visitField(LOGICAL_TYPE_DELEGATE_FIELD_MODIFIER, delegateFieldName, delegateFieldType, null, null); 108 } 109 } 110 111 private String [] getNewInterfacesForPortableObject(String [] interfaces) { 112 Set ifaces = new LinkedHashSet (Arrays.asList(interfaces)); 113 if (!ifaces.contains(Manageable.CLASS)) { 114 ifaces.add(Manageable.CLASS); 115 } 116 117 if (!spec.isLogical() && !ifaces.contains(TransparentAccess.CLASS)) { 118 ifaces.add(TransparentAccess.CLASS); 119 } 120 121 return (String []) ifaces.toArray(interfaces); 122 } 123 124 public final FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { 125 spec.handleSubclassOfLogicalClassWithFieldsIfNecessary(access); 126 if (spec.needDelegateField()) { 127 visitDelegateFieldIfNecessary(); 128 } 129 130 spec.recordExistingFields(name, desc, signature); 131 132 if (spec.isClassNotAdaptable() || name.startsWith(ByteCodeUtil.TC_FIELD_PREFIX)) { return super 133 .visitField(access, name, desc, signature, value); } 134 if (!Modifier.isStatic(access)) { 135 fields.put(name, desc); 136 } 137 return basicVisitField(access, name, desc, signature, value); 138 } 139 140 144 private class LogicalInitMethodAdapter extends LocalVariablesSorter implements Opcodes { 145 private boolean methodEnter = false; 146 private int[] localVariablesForMethodCall; 147 148 public LogicalInitMethodAdapter(int access, String methodDesc, MethodVisitor mv) { 149 super(access, methodDesc, mv); 150 } 151 152 private void storeStackValuesToLocalVariables(String methodInsnDesc) { 153 Type[] types = Type.getArgumentTypes(methodInsnDesc); 154 localVariablesForMethodCall = new int[types.length]; 155 for (int i = 0; i < types.length; i++) { 156 localVariablesForMethodCall[i] = newLocal(types[i].getSize()); 157 } 158 for (int i = types.length - 1; i >= 0; i--) { 159 super.visitVarInsn(types[i].getOpcode(ISTORE), localVariablesForMethodCall[i]); 160 } 161 } 162 163 private void loadLocalVariables(String methodInsnDesc) { 164 Type[] types = Type.getArgumentTypes(methodInsnDesc); 165 for (int i = 0; i < types.length; i++) { 166 super.visitVarInsn(types[i].getOpcode(ILOAD), localVariablesForMethodCall[i]); 167 } 168 } 169 170 public void visitMethodInsn(int opcode, String owner, String name, String desc) { 171 String superClassNameSlashes = spec.getSuperClassNameSlashes(); 172 if (!methodEnter && INVOKESPECIAL == opcode && owner.equals(superClassNameSlashes) && "<init>".equals(name)) { 173 methodEnter = true; 174 storeStackValuesToLocalVariables(desc); 175 loadLocalVariables(desc); 176 super.visitMethodInsn(opcode, owner, name, desc); 177 super.visitVarInsn(ALOAD, 0); 178 super.visitTypeInsn(NEW, spec.getSuperClassNameSlashes()); 179 super.visitInsn(DUP); 180 loadLocalVariables(desc); 181 182 String delegateFieldName = getDelegateFieldName(superClassNameSlashes); 183 super.visitMethodInsn(INVOKESPECIAL, superClassNameSlashes, "<init>", desc); 184 super.visitMethodInsn(INVOKESPECIAL, spec.getClassNameSlashes(), 185 ByteCodeUtil.fieldSetterMethod(delegateFieldName), "(L" + superClassNameSlashes + ";)V"); 186 187 } else { 188 super.visitMethodInsn(opcode, owner, name, desc); 189 } 190 } 191 } 192 193 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String [] exceptions) { 194 spec.shouldProceedInstrumentation(access, name, desc); 195 196 if (spec.isClassNotAdaptable()) { return super.visitMethod(access, name, desc, signature, exceptions); } 197 MethodVisitor mv; 198 199 spec.recordExistingMethods(name, desc, signature); 200 201 if (spec.shouldVisitMethod(access, name)) { 202 mv = basicVisitMethod(access, name, desc, signature, exceptions); 203 if (spec.hasDelegatedToLogicalClass()) { 204 String logicalExtendingClassName = spec.getSuperClassNameSlashes(); 205 mv = new LogicalClassSerializationAdapter.LogicalSubclassSerializationMethodAdapter(mv, name + desc, spec 206 .getClassNameSlashes(), logicalExtendingClassName, getDelegateFieldName(logicalExtendingClassName)); 207 } 208 } else { 209 mv = super.visitMethod(access, name, desc, signature, exceptions); 210 } 211 212 if (spec.hasDelegatedToLogicalClass() && "<init>".equals(name)) { 213 mv = new LogicalInitMethodAdapter(access, desc, mv); 214 } 215 216 return mv; 217 } 218 219 private void revisitLogicalSubclassDefinition() { 220 spec.moveToLogicalIfNecessary(); 221 222 String [] interfaces = spec.getClassInterfaces(); 223 interfaces = getNewInterfacesForPortableObject(interfaces); 224 225 basicVisit(spec.getClassVersion(), spec.getClassAccess(), spec.getClassNameSlashes(), spec.getClassSignature(), 226 spec.getSuperClassNameSlashes(), interfaces); 227 } 228 229 public final void visitEnd() { 230 if (spec.isClassNotAdaptable()) { 231 super.visitEnd(); 232 return; 233 } 234 235 if (spec.isSubclassofLogicalClass()) { 236 revisitLogicalSubclassDefinition(); 240 } 241 242 addOverridenLogicalMethods(); 245 246 addRetrieveValuesMethod(); 247 addSetValueMethod(); 248 addRetrieveManagedValueMethod(); 249 addSetManagedValueMethod(); 250 251 if (spec.isManagedFieldNeeded() && spec.generateNonStaticTCFields()) { 253 addCachedManagedMethods(); 254 255 visitField(ACC_PRIVATE | ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC, MANAGED_FIELD_NAME, MANAGED_FIELD_TYPE, 256 null, null); 257 } 258 259 basicVisitEnd(); 260 } 261 262 private void addOverridenLogicalMethods() { 263 Collection needToOverrideMethods = spec.getShouldOverrideMethods(); 264 for (Iterator i = needToOverrideMethods.iterator(); i.hasNext();) { 265 Method m = (Method ) i.next(); 266 int modifier = m.getModifiers(); 267 String methodName = m.getName(); 268 if (!spec.shouldVisitMethod(modifier, methodName) || Modifier.isFinal(modifier)) { 269 continue; 270 } 271 272 String methodDesc = Type.getMethodDescriptor(m); 273 Type returnType = Type.getReturnType(m); 274 275 Class [] exceptionTypes = m.getExceptionTypes(); 276 String [] exceptions = new String [exceptionTypes.length]; 277 for (int j = 0; j < exceptionTypes.length; j++) { 278 exceptions[j] = Type.getInternalName(exceptionTypes[j]); 279 } 280 281 String logicalExtendingClassName = spec.getSuperClassNameSlashes(); 282 283 MethodVisitor mv = cv.visitMethod(modifier & ~ACC_ABSTRACT, methodName, methodDesc, null, exceptions); 284 mv.visitVarInsn(ALOAD, 0); 285 mv.visitMethodInsn(INVOKESPECIAL, spec.getClassNameSlashes(), ByteCodeUtil 286 .fieldGetterMethod(getDelegateFieldName(logicalExtendingClassName)), "()L" + logicalExtendingClassName + ";"); 287 ByteCodeUtil.pushMethodArguments(ACC_PUBLIC, methodDesc, mv); 288 mv.visitMethodInsn(INVOKEVIRTUAL, logicalExtendingClassName, methodName, methodDesc); 289 290 mv.visitInsn(returnType.getOpcode(IRETURN)); 291 mv.visitMaxs(0, 0); 292 mv.visitEnd(); 293 } 294 if (spec.hasDelegatedToLogicalClass()) { 295 addReadObjectMethod(); 296 addWriteObjectMethod(); 297 addSerializationOverrideMethod(); 298 } 299 } 300 301 private void addSerializationOverrideMethod() { 302 LogicalClassSerializationAdapter.addCheckSerializationOverrideMethod(cv, true); 303 } 304 305 private void addWriteObjectMethod() { 306 if (!spec.isWriteObjectMethodNeeded()) { return; } 307 String logicalExtendingClassName = spec.getSuperClassNameSlashes(); 308 309 MethodVisitor mv = cv.visitMethod(ACC_PRIVATE, "writeObject", "(Ljava/io/ObjectOutputStream;)V", null, 310 new String [] { "java/io/IOException" }); 311 mv.visitCode(); 312 LogicalClassSerializationAdapter.addDelegateFieldWriteObjectCode(mv, spec.getClassNameSlashes(), 313 logicalExtendingClassName, 314 getDelegateFieldName(logicalExtendingClassName)); 315 mv.visitInsn(RETURN); 316 mv.visitMaxs(0, 0); 317 mv.visitEnd(); 318 } 319 320 private void addReadObjectMethod() { 321 if (!spec.isReadObjectMethodNeeded()) { return; } 322 String logicalExtendingClassName = spec.getSuperClassNameSlashes(); 323 324 MethodVisitor mv = cv.visitMethod(ACC_PRIVATE, "readObject", "(Ljava/io/ObjectInputStream;)V", null, new String [] { 325 "java/io/IOException", "java/lang/ClassNotFoundException" }); 326 mv.visitCode(); 327 LogicalClassSerializationAdapter.addDelegateFieldReadObjectCode(mv, spec.getClassNameSlashes(), 328 logicalExtendingClassName, 329 getDelegateFieldName(logicalExtendingClassName)); 330 mv.visitInsn(RETURN); 331 mv.visitMaxs(0, 0); 332 mv.visitEnd(); 333 } 334 335 private void addCachedManagedMethods() { 336 if (spec.isManagedMethodsNeeded()) { 337 MethodVisitor mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, MANAGED_METHOD, "()" + MANAGED_FIELD_TYPE, null, null); 339 if (spec.generateNonStaticTCFields()) { 340 mv.visitVarInsn(ALOAD, 0); 341 mv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), MANAGED_FIELD_NAME, MANAGED_FIELD_TYPE); 342 mv.visitInsn(ARETURN); 343 mv.visitMaxs(0, 0); 344 } else { 345 mv.visitInsn(ACONST_NULL); 346 mv.visitInsn(ARETURN); 347 mv.visitMaxs(0, 0); 348 } 349 350 mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, MANAGED_METHOD, "(" + MANAGED_FIELD_TYPE + ")V", null, null); 352 if (spec.generateNonStaticTCFields()) { 353 mv.visitVarInsn(ALOAD, 0); 354 mv.visitVarInsn(ALOAD, 1); 355 mv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(), MANAGED_FIELD_NAME, MANAGED_FIELD_TYPE); 356 mv.visitInsn(RETURN); 357 mv.visitMaxs(0, 0); 358 } else { 359 mv.visitInsn(RETURN); 360 mv.visitMaxs(0, 0); 361 } 362 363 mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, IS_MANAGED_METHOD, IS_MANAGED_DESCRIPTION, null, null); 366 if (spec.generateNonStaticTCFields()) { 367 mv.visitVarInsn(ALOAD, 0); 368 mv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), MANAGED_FIELD_NAME, MANAGED_FIELD_TYPE); 369 Label l1 = new Label(); 370 mv.visitJumpInsn(IFNULL, l1); 371 mv.visitInsn(ICONST_1); 372 mv.visitInsn(IRETURN); 373 mv.visitLabel(l1); 374 mv.visitInsn(ICONST_0); 375 mv.visitInsn(IRETURN); 376 mv.visitMaxs(1, 1); 377 } else { 378 mv.visitInsn(ICONST_0); 379 mv.visitInsn(IRETURN); 380 mv.visitMaxs(1, 1); 381 } 382 } 383 } 384 385 389 private void addRetrieveValuesMethod() { 390 if (spec.isValuesGetterMethodNeeded()) { 391 MethodVisitor mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, VALUES_GETTER, VALUES_GETTER_DESCRIPTION, null, null); 392 if (!portability.isInstrumentationNotNeeded(spec.getSuperClassNameDots()) 393 && getTransparencyClassSpec().hasPhysicallyPortableSpecs(spec.getClassInfo().getSuperclass())) { 394 mv.visitVarInsn(ALOAD, 0); 395 mv.visitVarInsn(ALOAD, 1); 396 mv.visitMethodInsn(INVOKESPECIAL, spec.getSuperClassNameSlashes(), VALUES_GETTER, VALUES_GETTER_DESCRIPTION); 397 } 398 399 for (Iterator i = fields.keySet().iterator(); i.hasNext();) { 400 String fieldName = (String ) i.next(); 401 String fieldDescription = (String ) fields.get(fieldName); 402 403 mv.visitVarInsn(ALOAD, 1); 404 mv.visitLdcInsn(spec.getClassNameDots() + "." + fieldName); 405 addValueToStackForField(mv, fieldName, fieldDescription); 406 mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put", 407 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 408 mv.visitInsn(POP); 409 } 410 mv.visitInsn(RETURN); 411 mv.visitMaxs(0, 0); 412 } 413 } 414 415 private void addRetrieveManagedValueMethod() { 416 if (spec.isManagedValuesGetterMethodNeeded()) { 417 MethodVisitor mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, MANAGED_VALUES_GETTER, 418 MANAGED_VALUES_GETTER_DESCRIPTION, null, null); 419 420 for (Iterator i = fields.keySet().iterator(); i.hasNext();) { 421 String fieldName = (String ) i.next(); 422 String fieldDescription = (String ) fields.get(fieldName); 423 mv.visitVarInsn(ALOAD, 1); 424 mv.visitLdcInsn(spec.getClassNameDots() + "." + fieldName); 425 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z"); 426 Label l1 = new Label(); 427 mv.visitJumpInsn(IFEQ, l1); 428 429 if (ByteCodeUtil.isSynthetic(fieldName)) { 430 addValueToStackForField(mv, fieldName, fieldDescription); 431 } else { 432 addManagedValueToStackForField(mv, fieldName, fieldDescription); 433 } 434 mv.visitInsn(ARETURN); 435 mv.visitLabel(l1); 436 } 437 438 439 if (!portability.isInstrumentationNotNeeded(spec.getSuperClassNameDots()) 440 && getTransparencyClassSpec().hasPhysicallyPortableSpecs(spec.getClassInfo().getSuperclass())) { 441 mv.visitVarInsn(ALOAD, 0); 442 mv.visitVarInsn(ALOAD, 1); 443 mv.visitMethodInsn(INVOKESPECIAL, spec.getSuperClassNameSlashes(), MANAGED_VALUES_GETTER, 444 MANAGED_VALUES_GETTER_DESCRIPTION); 445 } else { 446 mv.visitInsn(ACONST_NULL); 447 } 448 mv.visitInsn(ARETURN); 449 mv.visitMaxs(0, 0); 450 } 451 } 452 453 456 private void addSetValueMethod() { 457 if (spec.isValuesSetterMethodNeeded()) { 458 MethodVisitor mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, VALUES_SETTER, VALUES_SETTER_DESCRIPTION, null, null); 459 Label l1 = new Label(); 460 for (Iterator i = fields.keySet().iterator(); i.hasNext();) { 461 String fieldName = (String ) i.next(); 462 if (ByteCodeUtil.isTCSynthetic(fieldName)) { 463 continue; 464 } 465 466 String fieldDescription = (String ) fields.get(fieldName); 467 Type t = Type.getType(fieldDescription); 468 mv.visitVarInsn(ALOAD, 1); 469 mv.visitLdcInsn(spec.getClassNameDots() + "." + fieldName); 470 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z"); 471 Label l2 = new Label(); 472 mv.visitJumpInsn(IFEQ, l2); 473 mv.visitVarInsn(ALOAD, 0); 474 mv.visitVarInsn(ALOAD, 2); 475 if (t.getSort() != Type.OBJECT && t.getSort() != Type.ARRAY) { 476 mv.visitTypeInsn(CHECKCAST, ByteCodeUtil.sortToWrapperName(t.getSort())); 477 mv.visitMethodInsn(INVOKEVIRTUAL, ByteCodeUtil.sortToWrapperName(t.getSort()), ByteCodeUtil 478 .sortToPrimitiveMethodName(t.getSort()), "()" + fieldDescription); 479 } else { 480 mv.visitTypeInsn(CHECKCAST, convertToCheckCastDesc(fieldDescription)); 481 } 482 mv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(), fieldName, fieldDescription); 483 mv.visitJumpInsn(GOTO, l1); 484 mv.visitLabel(l2); 485 } 486 if (!portability.isInstrumentationNotNeeded(spec.getSuperClassNameDots()) 487 && getTransparencyClassSpec().hasPhysicallyPortableSpecs(spec.getClassInfo().getSuperclass())) { 488 mv.visitVarInsn(ALOAD, 0); 489 mv.visitVarInsn(ALOAD, 1); 490 mv.visitVarInsn(ALOAD, 2); 491 mv.visitMethodInsn(INVOKESPECIAL, spec.getSuperClassNameSlashes(), VALUES_SETTER, VALUES_SETTER_DESCRIPTION); 492 } 493 mv.visitLabel(l1); 494 495 mv.visitInsn(RETURN); 496 mv.visitMaxs(0, 0); 497 } 498 } 499 500 private void addSetManagedValueMethod() { 501 if (spec.isManagedValuesSetterMethodNeeded()) { 502 MethodVisitor mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, MANAGED_VALUES_SETTER, VALUES_SETTER_DESCRIPTION, 503 null, null); 504 505 Label l1 = new Label(); 506 for (Iterator i = fields.keySet().iterator(); i.hasNext();) { 507 String fieldName = (String ) i.next(); 508 if (ByteCodeUtil.isSynthetic(fieldName)) { 509 continue; 510 } 511 512 String fieldDescription = (String ) fields.get(fieldName); 513 Type t = Type.getType(fieldDescription); 514 mv.visitVarInsn(ALOAD, 1); 515 mv.visitLdcInsn(spec.getClassNameDots() + "." + fieldName); 516 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z"); 517 Label l2 = new Label(); 518 mv.visitJumpInsn(IFEQ, l2); 519 mv.visitVarInsn(ALOAD, 0); 520 mv.visitVarInsn(ALOAD, 2); 521 if (t.getSort() != Type.OBJECT && t.getSort() != Type.ARRAY) { 522 mv.visitTypeInsn(CHECKCAST, ByteCodeUtil.sortToWrapperName(t.getSort())); 523 mv.visitMethodInsn(INVOKEVIRTUAL, ByteCodeUtil.sortToWrapperName(t.getSort()), ByteCodeUtil 524 .sortToPrimitiveMethodName(t.getSort()), "()" + fieldDescription); 525 } else { 526 mv.visitTypeInsn(CHECKCAST, convertToCheckCastDesc(fieldDescription)); 527 } 528 mv.visitMethodInsn(INVOKEVIRTUAL, spec.getClassNameSlashes(), ByteCodeUtil.fieldSetterMethod(fieldName), 529 "(" + fieldDescription + ")V"); 530 mv.visitJumpInsn(GOTO, l1); 531 mv.visitLabel(l2); 532 } 533 534 if (!portability.isInstrumentationNotNeeded(spec.getSuperClassNameDots()) 535 && getTransparencyClassSpec().hasPhysicallyPortableSpecs(spec.getClassInfo().getSuperclass())) { 536 mv.visitVarInsn(ALOAD, 0); 537 mv.visitVarInsn(ALOAD, 1); 538 mv.visitVarInsn(ALOAD, 2); 539 mv.visitMethodInsn(INVOKESPECIAL, spec.getSuperClassNameSlashes(), MANAGED_VALUES_SETTER, 540 VALUES_SETTER_DESCRIPTION); 541 } 542 543 mv.visitLabel(l1); 544 mv.visitInsn(RETURN); 545 mv.visitMaxs(0, 0); 546 } 547 } 548 549 protected String convertToCheckCastDesc(String desc) { 550 if (desc.startsWith("[")) return desc; 551 return desc.substring(1, desc.length() - 1); 552 } 553 554 private void addValueToStackForField(MethodVisitor mv, String fieldName, String fieldDescription) { 555 Type t = Type.getType(fieldDescription); 556 557 if (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY) { 558 ByteCodeUtil.pushThis(mv); 559 mv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), fieldName, fieldDescription); 560 } else { 561 mv.visitTypeInsn(NEW, ByteCodeUtil.sortToWrapperName(t.getSort())); 562 mv.visitInsn(DUP); 563 ByteCodeUtil.pushThis(mv); 564 mv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), fieldName, fieldDescription); 565 mv.visitMethodInsn(INVOKESPECIAL, ByteCodeUtil.sortToWrapperName(t.getSort()), "<init>", "(" + fieldDescription 566 + ")V"); 567 } 568 } 569 570 private void addManagedValueToStackForField(MethodVisitor mv, String fieldName, String fieldDescription) { 571 Type t = Type.getType(fieldDescription); 572 if (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY) { 573 ByteCodeUtil.pushThis(mv); 574 mv.visitMethodInsn(INVOKESPECIAL, spec.getClassNameSlashes(), ByteCodeUtil.fieldGetterMethod(fieldName), 575 "()" + fieldDescription); 576 } else { 577 mv.visitTypeInsn(NEW, ByteCodeUtil.sortToWrapperName(t.getSort())); 578 mv.visitInsn(DUP); 579 ByteCodeUtil.pushThis(mv); 580 if (isRoot(fieldName)) { 581 mv.visitMethodInsn(INVOKESPECIAL, spec.getClassNameSlashes(), ByteCodeUtil.fieldGetterMethod(fieldName), 582 "()" + fieldDescription); 583 } else { 584 mv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), fieldName, fieldDescription); 585 } 586 mv.visitMethodInsn(INVOKESPECIAL, ByteCodeUtil.sortToWrapperName(t.getSort()), "<init>", "(" + fieldDescription 587 + ")V"); 588 } 589 } 590 591 protected void basicVisit(int version, int access, String name, String signature, String superName, 592 String [] interfaces) { 593 cv.visit(version, access, name, signature, superName, interfaces); 595 } 596 597 protected FieldVisitor basicVisitField(int access, String name, String desc, String signature, Object value) { 598 return cv.visitField(access, name, desc, signature, value); 600 } 601 602 protected MethodVisitor basicVisitMethod(int access, String name, String desc, String signature, String [] exceptions) { 603 return cv.visitMethod(access, name, desc, signature, exceptions); 605 } 606 607 protected void basicVisitEnd() { 608 cv.visitEnd(); 610 } 611 612 } 613 | Popular Tags |