KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > object > bytecode > TransparencyClassAdapter


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

5 package com.tc.object.bytecode;
6
7 import com.tc.asm.ClassVisitor;
8 import com.tc.asm.FieldVisitor;
9 import com.tc.asm.Label;
10 import com.tc.asm.MethodVisitor;
11 import com.tc.asm.Type;
12 import com.tc.aspectwerkz.exception.DefinitionException;
13 import com.tc.aspectwerkz.reflect.ClassInfo;
14 import com.tc.logging.TCLogger;
15 import com.tc.logging.TCLogging;
16 import com.tc.object.Portability;
17 import com.tc.object.config.LockDefinition;
18 import com.tc.object.config.TransparencyClassSpec;
19 import com.tc.object.lockmanager.api.LockLevel;
20 import com.tc.object.logging.InstrumentationLogger;
21 import com.tc.util.Assert;
22
23 import java.lang.reflect.Modifier JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Set JavaDoc;
26
27 /**
28  * @author steve
29  */

30 public class TransparencyClassAdapter extends ClassAdapterBase {
31   private static final TCLogger logger = TCLogging.getLogger(TransparencyClassAdapter.class);
32
33   private final Set JavaDoc doNotInstrument = new HashSet JavaDoc();
34   private final PhysicalClassAdapterLogger physicalClassLogger;
35   private final InstrumentationLogger instrumentationLogger;
36
37   public TransparencyClassAdapter(ClassInfo classInfo, TransparencyClassSpec spec, final ClassVisitor cv, ManagerHelper mgrHelper,
38                                   InstrumentationLogger instrumentationLogger, ClassLoader JavaDoc caller,
39                                   Portability portability) {
40     super(classInfo, spec, cv, mgrHelper, caller, portability);
41     this.instrumentationLogger = instrumentationLogger;
42     this.physicalClassLogger = new PhysicalClassAdapterLogger(logger);
43   }
44
45   protected void basicVisit(final int version, final int access, final String JavaDoc name, String JavaDoc signature,
46                             final String JavaDoc superClassName, final String JavaDoc[] interfaces) {
47
48     try {
49       logger.debug("ADAPTING CLASS: " + name);
50       super.basicVisit(version, access, name, signature, superClassName, interfaces);
51       getTransparencyClassSpec().createClassSupportMethods(cv);
52     } catch (RuntimeException JavaDoc e) {
53       handleInstrumentationException(e);
54       throw e;
55     } catch (Error JavaDoc e) {
56       handleInstrumentationException(e);
57       throw e;
58     }
59   }
60
61   private void handleInstrumentationException(Throwable JavaDoc e) {
62     logger.fatal(e);
63     logger.fatal("Calling System.exit(1)");
64     System.exit(1);
65   }
66
67   private boolean isRoot(int access, String JavaDoc fieldName) {
68     try {
69       boolean isRoot = getTransparencyClassSpec().isRootInThisClass(fieldName);
70       boolean isTransient = getTransparencyClassSpec().isTransient(access, fieldName);
71       if (isTransient && isRoot) {
72         if (instrumentationLogger.transientRootWarning()) {
73           instrumentationLogger.transientRootWarning(this.spec.getClassNameDots(), fieldName);
74         }
75       }
76       return isRoot;
77     } catch (RuntimeException JavaDoc e) {
78       handleInstrumentationException(e);
79       throw e;
80     } catch (Error JavaDoc e) {
81       handleInstrumentationException(e);
82       throw e;
83     }
84   }
85
86   private String JavaDoc rootNameFor(String JavaDoc className, String JavaDoc fieldName) {
87     try {
88       return getTransparencyClassSpec().rootNameFor(fieldName);
89     } catch (RuntimeException JavaDoc e) {
90       handleInstrumentationException(e);
91       throw e;
92     } catch (Error JavaDoc e) {
93       handleInstrumentationException(e);
94       throw e;
95     }
96   }
97
98   protected FieldVisitor basicVisitField(final int access, final String JavaDoc name, final String JavaDoc desc, String JavaDoc signature,
99                                          final Object JavaDoc value) {
100
101     FieldVisitor fieldVisitor = null;
102     try {
103
104       if ((spec.isClassPortable() && spec.isPhysical() && !ByteCodeUtil.isTCSynthetic(name))
105           || (spec.isClassAdaptable() && isRoot(access, name))) {
106         // include the field, but remove final modifier for *most* fields
107
if (Modifier.isFinal(access) && !isMagicSerializationField(access, name, desc)) {
108           fieldVisitor = cv.visitField(~Modifier.FINAL & access, name, desc, signature, value);
109         } else {
110           fieldVisitor = cv.visitField(access, name, desc, signature, value);
111         }
112         generateGettersSetters(access, name, desc, Modifier.isStatic(access));
113       } else {
114         fieldVisitor = cv.visitField(access, name, desc, signature, value);
115       }
116     } catch (RuntimeException JavaDoc e) {
117       e.printStackTrace();
118       handleInstrumentationException(e);
119     } catch (Error JavaDoc e) {
120       handleInstrumentationException(e);
121       throw e;
122     }
123     return fieldVisitor;
124   }
125
126   private static boolean isStatic(int access) {
127     return Modifier.isStatic(access);
128   }
129
130   private static boolean isFinal(int access) {
131     return Modifier.isFinal(access);
132   }
133
134   private static boolean isPrivate(int access) {
135     return Modifier.isPrivate(access);
136   }
137
138   private boolean isMagicSerializationField(int access, String JavaDoc fieldName, String JavaDoc fieldDesc) {
139     // this method tests if the given field is the one the magic fields used by java serialization. If it is, we should
140
// not change any details about this field
141

142     boolean isStatic = isStatic(access);
143     boolean isFinal = isFinal(access);
144     boolean isPrivate = isPrivate(access);
145
146     if (isStatic && isFinal) {
147       if ("J".equals(fieldDesc) && "serialVersionUID".equals(fieldName)) { return true; }
148       if (isPrivate && "serialPersistentFields".equals(fieldName) && "[Ljava/io/ObjectStreamField;".equals(fieldDesc)) { return true; }
149     }
150
151     return false;
152   }
153
154   private void generateGettersSetters(final int fieldAccess, final String JavaDoc name, final String JavaDoc desc, boolean isStatic) {
155     boolean isTransient = getTransparencyClassSpec().isTransient(fieldAccess, name);
156     // Plain getter and setters are generated for transient fields as other instrumented classes might call them.
157
boolean createPlainAccessors = isTransient && !isStatic;
158     boolean createInstrumentedAccessors = !isTransient && !isStatic;
159     boolean createRootAccessors = isRoot(fieldAccess, name);
160
161     int methodAccess = fieldAccess & (~ACC_TRANSIENT);
162     methodAccess &= (~ACC_FINAL); // remove final modifier since variable might be shadowed
163
methodAccess &= (~ACC_VOLATILE);
164     methodAccess |= ACC_SYNTHETIC;
165
166     if (createRootAccessors) {
167       createRootGetter(methodAccess, name, desc);
168     } else if (createInstrumentedAccessors) {
169       if (!ByteCodeUtil.isPrimitive(Type.getType(desc))) {
170         createInstrumentedGetter(methodAccess, fieldAccess, name, desc);
171       } else {
172         createPlainGetter(methodAccess, fieldAccess, name, desc);
173       }
174     } else if (createPlainAccessors) {
175       createPlainGetter(methodAccess, fieldAccess, name, desc);
176     }
177
178     if (createInstrumentedAccessors || createRootAccessors) {
179       createInstrumentedSetter(methodAccess, fieldAccess, name, desc);
180     } else if (createPlainAccessors) {
181       createPlainSetter(methodAccess, fieldAccess, name, desc);
182     }
183   }
184
185   private boolean isPrimitive(Type t) {
186     return ByteCodeUtil.isPrimitive(t);
187   }
188
189   protected MethodVisitor basicVisitMethod(int access, String JavaDoc name, final String JavaDoc desc, String JavaDoc signature,
190                                            final String JavaDoc[] exceptions) {
191     String JavaDoc originalName = name;
192
193     try {
194       physicalClassLogger.logVisitMethodBegin(access, name, desc, signature, exceptions);
195
196       if (name.startsWith(ByteCodeUtil.TC_METHOD_PREFIX) || doNotInstrument.contains(name + desc)
197           || getTransparencyClassSpec().doNotInstrument(name)) {
198         if (!getTransparencyClassSpec().hasCustomMethodAdapter(access, name, desc, exceptions)) {
199           physicalClassLogger.logVisitMethodIgnoring(name, desc);
200           return cv.visitMethod(access, name, desc, signature, exceptions);
201         }
202       }
203
204       LockDefinition[] locks = getTransparencyClassSpec().lockDefinitionsFor(access, name, desc, exceptions);
205       LockDefinition ld = getTransparencyClassSpec().getAutolockDefinition(locks);
206       boolean isAutolock = (ld != null);
207       int lockLevel = -1;
208       if (isAutolock) {
209         lockLevel = ld.getLockLevelAsInt();
210         if (instrumentationLogger.lockInsertion()) {
211           instrumentationLogger.autolockInserted(this.spec.getClassNameDots(), name, desc, ld);
212         }
213       }
214       boolean isLockMethod = isAutolock && Modifier.isSynchronized(access) && !Modifier.isStatic(access);
215       physicalClassLogger.logVisitMethodCheckIsLockMethod();
216
217       if (!isLockMethod || spec.isClassAdaptable()) {
218         // LockDefinition methodLD = getTransparencyClassSpec().getLockMethodLockDefinition(access, locks);
219
LockDefinition namedLockDefinition = getTransparencyClassSpec().getNonAutoLockDefinition(locks);
220         isLockMethod = (namedLockDefinition != null);
221       }
222
223       // if (methodLD != null && (spec.isClassPortable() || (spec.isClassAdaptable() && !methodLD.isAutolock()))
224
// && !name.equals("<init>")) {
225
if (isLockMethod && (!name.equals("<init>"))) {
226         physicalClassLogger.logVisitMethodCreateLockMethod(name);
227         // This method is a lock method.
228
Assert.assertNotNull(locks);
229         Assert.eval(locks.length > 0 || isLockMethod);
230         createLockMethod(access, name, desc, signature, exceptions, locks);
231
232         logCustomerLockMethod(name, desc, locks);
233         name = ByteCodeUtil.METHOD_RENAME_PREFIX + name;
234         access |= ACC_PRIVATE;
235         access &= (~ACC_PUBLIC);
236         access &= (~ACC_PROTECTED);
237       } else {
238         physicalClassLogger.logVisitMethodNotALockMethod(access, this.spec.getClassNameDots(), name, desc, exceptions);
239       }
240       MethodVisitor mv = null;
241
242       boolean hasCustomMethodAdapter = getTransparencyClassSpec().hasCustomMethodAdapter(access, originalName, desc,
243                                                                                          exceptions);
244       if (hasCustomMethodAdapter) {
245         MethodAdapter ma = getTransparencyClassSpec().customMethodAdapterFor(spec.getManagerHelper(), access, name,
246                                                                              originalName, desc, signature, exceptions,
247                                                                              instrumentationLogger);
248         mv = ma.adapt(cv);
249
250         if (!ma.doesOriginalNeedAdapting()) return mv;
251       }
252
253       if (mv == null) {
254         mv = cv.visitMethod(access, name, desc, signature, exceptions);
255       }
256
257       return mv == null ? null : new TransparencyCodeAdapter(spec, isAutolock, lockLevel, mv, access, originalName,
258                                                              name, desc, signature, exceptions);
259     } catch (RuntimeException JavaDoc e) {
260       handleInstrumentationException(e);
261       throw e;
262     } catch (Error JavaDoc e) {
263       handleInstrumentationException(e);
264       throw e;
265     }
266   }
267
268 // protected void basicVisitEnd() {
269
// // if adaptee has DMI
270
// boolean hasCustomMethodAdapter = getTransparencyClassSpec().hasCustomMethodAdapter(access, originalName, desc,
271
// exceptions);
272
// super.basicVisitEnd();
273
// }
274

275   private void logCustomerLockMethod(String JavaDoc name, final String JavaDoc desc, LockDefinition[] locks) {
276     if (instrumentationLogger.lockInsertion()) {
277       instrumentationLogger.lockInserted(this.spec.getClassNameDots(), name, desc, locks);
278     }
279   }
280
281   private void createLockMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, final String JavaDoc[] exceptions,
282                                 LockDefinition[] locks) {
283     try {
284       physicalClassLogger.logCreateLockMethodBegin(access, name, desc, signature, exceptions, locks);
285       doNotInstrument.add(name + desc);
286       Type returnType = Type.getReturnType(desc);
287       if (returnType.getSort() == Type.VOID) {
288         createLockMethodVoid(access, name, desc, signature, exceptions, locks);
289       } else {
290         createLockMethodReturn(access, name, desc, signature, exceptions, locks, returnType);
291       }
292     } catch (RuntimeException JavaDoc e) {
293       handleInstrumentationException(e);
294       throw e;
295     } catch (Error JavaDoc e) {
296       handleInstrumentationException(e);
297       throw e;
298     }
299   }
300
301   /**
302    * Creates a tc lock method for the given method that returns void.
303    */

304   private void createLockMethodVoid(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, final String JavaDoc[] exceptions,
305                                     LockDefinition[] locks) {
306     try {
307       int localVariableOffset = ByteCodeUtil.getLocalVariableOffset(access);
308
309       physicalClassLogger.logCreateLockMethodVoidBegin(access, name, desc, signature, exceptions, locks);
310       MethodVisitor c = cv.visitMethod(access & (~Modifier.SYNCHRONIZED), name, desc, signature, exceptions);
311       callTCBeginWithLocks(access, name, desc, locks, c);
312       Label l0 = new Label();
313       c.visitLabel(l0);
314       callRenamedMethod(access, name, desc, c);
315       // This label creation has something to do with try/finally
316
Label l1 = new Label();
317       c.visitJumpInsn(GOTO, l1);
318       Label l2 = new Label();
319       c.visitLabel(l2);
320       c.visitVarInsn(ASTORE, 1 + localVariableOffset);
321       Label l3 = new Label();
322       c.visitJumpInsn(JSR, l3);
323       c.visitVarInsn(ALOAD, 1 + localVariableOffset);
324       c.visitInsn(ATHROW);
325       c.visitLabel(l3);
326       c.visitVarInsn(ASTORE, 0 + localVariableOffset);
327       callTCCommit(access, name, desc, locks, c);
328       c.visitVarInsn(RET, 0 + localVariableOffset);
329       c.visitLabel(l1);
330       c.visitJumpInsn(JSR, l3);
331       Label l4 = new Label();
332       c.visitLabel(l4);
333       c.visitInsn(RETURN);
334       c.visitTryCatchBlock(l0, l2, l2, null);
335       c.visitTryCatchBlock(l1, l4, l2, null);
336       c.visitMaxs(0, 0);
337     } catch (RuntimeException JavaDoc e) {
338       handleInstrumentationException(e);
339     } catch (Error JavaDoc e) {
340       handleInstrumentationException(e);
341       throw e;
342     }
343   }
344
345   private void handleInstrumentationException(RuntimeException JavaDoc e) {
346     // XXX: Yucky.
347
if (e instanceof DefinitionException) {
348       logger.fatal(e.getLocalizedMessage());
349     } else {
350       logger.fatal(e);
351     }
352     logger.fatal("Calling System.exit(1)");
353     System.exit(1);
354   }
355
356   private void callRenamedMethod(int callingMethodModifier, String JavaDoc name, String JavaDoc desc, MethodVisitor c) {
357     // Call the renamed original method.
358
ByteCodeUtil.prepareStackForMethodCall(callingMethodModifier, desc, c);
359     if (Modifier.isStatic(callingMethodModifier)) {
360       c.visitMethodInsn(INVOKESTATIC, spec.getClassNameSlashes(), ByteCodeUtil.METHOD_RENAME_PREFIX + name, desc);
361     } else {
362       c.visitMethodInsn(INVOKESPECIAL, spec.getClassNameSlashes(), ByteCodeUtil.METHOD_RENAME_PREFIX + name, desc);
363     }
364   }
365
366   /**
367    * Creates a tc lock method for the given method that returns a value (doesn't return void).
368    */

369   private void createLockMethodReturn(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature,
370                                       final String JavaDoc[] exceptions, LockDefinition[] locks, Type returnType) {
371     try {
372       physicalClassLogger.logCreateLockMethodReturnBegin(access, name, desc, signature, exceptions, locks);
373       int localVariableOffset = ByteCodeUtil.getLocalVariableOffset(access);
374       MethodVisitor c = cv.visitMethod(access & (~Modifier.SYNCHRONIZED), name, desc, signature, exceptions);
375
376       callTCBeginWithLocks(access, name, desc, locks, c);
377       Label l0 = new Label();
378       c.visitLabel(l0);
379       callRenamedMethod(access, name, desc, c);
380       c.visitVarInsn(returnType.getOpcode(ISTORE), 2 + localVariableOffset);
381       Label l1 = new Label();
382       c.visitJumpInsn(JSR, l1);
383       Label l2 = new Label();
384       c.visitLabel(l2);
385       c.visitVarInsn(returnType.getOpcode(ILOAD), 2 + localVariableOffset);
386       c.visitInsn(returnType.getOpcode(IRETURN));
387       Label l3 = new Label();
388       c.visitLabel(l3);
389       c.visitVarInsn(ASTORE, 1 + localVariableOffset);
390       c.visitJumpInsn(JSR, l1);
391       c.visitVarInsn(ALOAD, 1 + localVariableOffset);
392       c.visitInsn(ATHROW);
393       c.visitLabel(l1);
394       c.visitVarInsn(ASTORE, 0 + localVariableOffset);
395       callTCCommit(access, name, desc, locks, c);
396       c.visitVarInsn(RET, 0 + localVariableOffset);
397       c.visitTryCatchBlock(l0, l2, l3, null);
398       c.visitMaxs(0, 0);
399     } catch (RuntimeException JavaDoc e) {
400       handleInstrumentationException(e);
401     } catch (Error JavaDoc e) {
402       handleInstrumentationException(e);
403       throw e;
404     }
405
406   }
407
408   private void callTCBeginWithLocks(int access, String JavaDoc name, String JavaDoc desc, LockDefinition[] locks, MethodVisitor c) {
409     physicalClassLogger.logCallTCBeginWithLocksStart(access, name, desc, locks, c);
410     for (int i = 0; i < locks.length; i++) {
411       LockDefinition lock = locks[i];
412       if (lock.isAutolock() && spec.isClassPortable()) {
413         physicalClassLogger.logCallTCBeginWithLocksAutolock();
414         if (Modifier.isSynchronized(access) && !Modifier.isStatic(access)) {
415           physicalClassLogger.logCallTCBeginWithLocksAutolockSynchronized(name, desc);
416           callTCMonitorEnter(access, locks[i], c);
417         } else {
418           physicalClassLogger.logCallTCBeginWithLocksAutolockNotSynchronized(name, desc);
419         }
420       } else if (!lock.isAutolock()) {
421         physicalClassLogger.logCallTCBeginWithLocksNoAutolock(lock);
422         callTCBeginWithLock(lock, c);
423       }
424     }
425   }
426
427   private void callTCCommit(int access, String JavaDoc name, String JavaDoc desc, LockDefinition[] locks, MethodVisitor c) {
428     physicalClassLogger.logCallTCCommitBegin(access, name, desc, locks, c);
429     for (int i = 0; i < locks.length; i++) {
430       LockDefinition lock = locks[i];
431       if (lock.isAutolock() && spec.isClassPortable()) {
432         if (Modifier.isSynchronized(access) && !Modifier.isStatic(access)) {
433           callTCMonitorExit(access, c);
434         }
435       } else if (!lock.isAutolock()) {
436         c.visitLdcInsn(ByteCodeUtil.generateNamedLockName(lock.getLockName()));
437         spec.getManagerHelper().callManagerMethod("commitLock", c);
438       }
439     }
440   }
441
442   private void callTCCommitWithLockName(String JavaDoc lockName, MethodVisitor mv) {
443     mv.visitLdcInsn(lockName);
444     spec.getManagerHelper().callManagerMethod("commitLock", mv);
445   }
446
447   private void callTCBeginWithLock(LockDefinition lock, MethodVisitor c) {
448     c.visitLdcInsn(ByteCodeUtil.generateNamedLockName(lock.getLockName()));
449     c.visitLdcInsn(new Integer JavaDoc(lock.getLockLevelAsInt()));
450     spec.getManagerHelper().callManagerMethod("beginLock", c);
451   }
452
453   private void callTCBeginWithLockName(String JavaDoc lockName, int lockLevel, MethodVisitor mv) {
454     mv.visitLdcInsn(lockName);
455     mv.visitLdcInsn(new Integer JavaDoc(lockLevel));
456     spec.getManagerHelper().callManagerMethod("beginLock", mv);
457   }
458
459   private void callVolatileBegin(String JavaDoc fieldName, int lockLevel, MethodVisitor mv) {
460     getManaged(mv);
461     mv.visitLdcInsn(fieldName);
462     mv.visitIntInsn(BIPUSH, lockLevel);
463     spec.getManagerHelper().callManagerMethod("beginVolatile", mv);
464   }
465
466   private void callVolatileCommit(String JavaDoc fieldName, MethodVisitor mv) {
467     getManaged(mv);
468     mv.visitLdcInsn(fieldName);
469     spec.getManagerHelper().callManagerMethod("commitVolatile", mv);
470   }
471
472   private void createPlainGetter(int methodAccess, int fieldAccess, String JavaDoc name, String JavaDoc desc) {
473     boolean isVolatile = isVolatile(fieldAccess, name);
474
475     String JavaDoc gDesc = "()" + desc;
476     MethodVisitor gv = this.visitMethod(methodAccess, ByteCodeUtil.fieldGetterMethod(name), gDesc, null, null);
477     Type t = Type.getType(desc);
478
479     Label l4 = new Label();
480
481     if (isVolatile) {
482       getManaged(gv);
483       gv.visitInsn(DUP);
484       gv.visitVarInsn(ASTORE, 2);
485       gv.visitJumpInsn(IFNULL, l4);
486
487       Label l0 = new Label();
488       Label l1 = new Label();
489       Label l2 = new Label();
490       gv.visitTryCatchBlock(l0, l1, l2, null);
491       gv.visitLabel(l0);
492
493       callVolatileBegin(spec.getClassNameDots() + "." + name, LockLevel.READ, gv);
494
495       Label l6 = new Label();
496       gv.visitJumpInsn(JSR, l6);
497       gv.visitLabel(l1);
498       ByteCodeUtil.pushThis(gv);
499       gv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), name, desc);
500       gv.visitInsn(t.getOpcode(IRETURN));
501       gv.visitLabel(l2);
502       gv.visitVarInsn(ASTORE, 2);
503       gv.visitJumpInsn(JSR, l6);
504       gv.visitVarInsn(ALOAD, 2);
505       gv.visitInsn(ATHROW);
506       gv.visitLabel(l6);
507       gv.visitVarInsn(ASTORE, 1);
508
509       callVolatileCommit(spec.getClassNameDots() + "." + name, gv);
510       gv.visitVarInsn(RET, 1);
511     }
512
513     gv.visitLabel(l4);
514     ByteCodeUtil.pushThis(gv);
515     gv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), name, desc);
516     gv.visitInsn(t.getOpcode(IRETURN));
517
518     gv.visitMaxs(0, 0);
519   }
520
521   private void checkReturnObjectType(String JavaDoc fieldName, String JavaDoc rootName, String JavaDoc targetType, int loadVariableNumber,
522                                      Label matchLabel, MethodVisitor mv) {
523     mv.visitVarInsn(ALOAD, loadVariableNumber);
524     mv.visitTypeInsn(INSTANCEOF, targetType);
525     mv.visitJumpInsn(IFNE, matchLabel);
526     mv.visitTypeInsn(NEW, "java/lang/ClassCastException");
527     mv.visitInsn(DUP);
528     mv.visitTypeInsn(NEW, "java/lang/StringBuffer");
529     mv.visitInsn(DUP);
530     mv.visitLdcInsn("The field '");
531     mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuffer", "<init>", "(Ljava/lang/String;)V");
532     mv.visitLdcInsn(fieldName);
533     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append",
534                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
535     mv.visitLdcInsn("' with root name '");
536     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append",
537                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
538     mv.visitLdcInsn(rootName);
539     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append",
540                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
541     mv.visitLdcInsn("' cannot be assigned to a variable of type ");
542     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append",
543                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
544     mv.visitLdcInsn(targetType);
545     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append",
546                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
547     mv.visitLdcInsn(". This root has a type ");
548     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append",
549                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
550     mv.visitVarInsn(ALOAD, loadVariableNumber);
551     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
552     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;");
553     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append",
554                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
555     mv.visitLdcInsn(". ");
556     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append",
557                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
558     mv.visitLdcInsn("Perhaps you have the same root name assigned more than once to variables of different types.");
559     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append",
560                        "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
561     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "toString", "()Ljava/lang/String;");
562     mv.visitMethodInsn(INVOKESPECIAL, "java/lang/ClassCastException", "<init>", "(Ljava/lang/String;)V");
563     mv.visitInsn(ATHROW);
564
565   }
566
567   private void createRootGetter(int methodAccess, String JavaDoc name, String JavaDoc desc) {
568     Type t = Type.getType(desc);
569     boolean isPrimitive = isPrimitive(t);
570     boolean isDSOFinal = isRootDSOFinal(name, isPrimitive);
571
572     String JavaDoc rootName = rootNameFor(spec.getClassNameSlashes(), name);
573     String JavaDoc targetType = isPrimitive ? ByteCodeUtil.sortToWrapperName(t.getSort()) : convertToCheckCastDesc(desc);
574
575     boolean isStatic = Modifier.isStatic(methodAccess);
576
577     Label l1 = new Label();
578     Label l3 = new Label();
579     Label l5 = new Label();
580     Label l6 = new Label();
581     Label l7 = new Label();
582     Label l8 = new Label();
583
584     try {
585       MethodVisitor mv = cv.visitMethod(methodAccess, ByteCodeUtil.fieldGetterMethod(name), "()" + desc, null, null);
586
587       if (isDSOFinal) {
588         callGetFieldInsn(isStatic, name, desc, mv);
589         if (isPrimitive) {
590           addPrimitiveTypeZeroCompare(mv, t, l1);
591         } else {
592           mv.visitJumpInsn(IFNONNULL, l1);
593         }
594       }
595
596       callTCBeginWithLockName(rootName, LockLevel.WRITE, mv);
597
598       mv.visitLabel(l3);
599       mv.visitLdcInsn(rootName);
600       spec.getManagerHelper().callManagerMethod("lookupRoot", mv);
601       mv.visitVarInsn(ASTORE, 1);
602
603       mv.visitVarInsn(ALOAD, 1);
604       mv.visitJumpInsn(IFNULL, l5);
605
606       checkReturnObjectType(name, rootName, targetType, 1, l6, mv);
607
608       mv.visitLabel(l6);
609       callPutFieldInsn(isStatic, t, 1, name, desc, mv);
610       mv.visitJumpInsn(GOTO, l5);
611
612       mv.visitLabel(l7);
613       mv.visitVarInsn(ASTORE, 3);
614       mv.visitJumpInsn(JSR, l8);
615       mv.visitVarInsn(ALOAD, 3);
616       mv.visitInsn(ATHROW);
617
618       mv.visitLabel(l8);
619       mv.visitVarInsn(ASTORE, 2);
620       callTCCommitWithLockName(rootName, mv);
621       mv.visitVarInsn(RET, 2);
622
623       mv.visitLabel(l5);
624       mv.visitJumpInsn(JSR, l8);
625
626       mv.visitLabel(l1);
627       callGetFieldInsn(isStatic, name, desc, mv);
628       mv.visitInsn(t.getOpcode(IRETURN));
629       mv.visitTryCatchBlock(l3, l7, l7, null);
630       mv.visitMaxs(0, 0);
631     } catch (RuntimeException JavaDoc e) {
632       handleInstrumentationException(e);
633     } catch (Error JavaDoc e) {
634       handleInstrumentationException(e);
635       throw e;
636     }
637   }
638
639   private boolean isVolatile(int access, String JavaDoc fieldName) {
640     return getTransparencyClassSpec().isVolatile(access, fieldName);
641   }
642
643   private void createInstrumentedGetter(int methodAccess, int fieldAccess, String JavaDoc name, String JavaDoc desc) {
644     try {
645       Assert.eval(!getTransparencyClassSpec().isLogical());
646       boolean isVolatile = isVolatile(fieldAccess, name);
647
648       String JavaDoc gDesc = "()" + desc;
649       MethodVisitor gv = this.visitMethod(methodAccess, ByteCodeUtil.fieldGetterMethod(name), gDesc, null, null);
650       Type t = Type.getType(desc);
651
652       getManaged(gv);
653       gv.visitInsn(DUP);
654       gv.visitVarInsn(ASTORE, 3);
655
656       Label l0 = new Label();
657       gv.visitJumpInsn(IFNULL, l0);
658
659       if (isVolatile) {
660         callVolatileBegin(spec.getClassNameDots() + '.' + name, LockLevel.READ, gv);
661       }
662
663       gv.visitVarInsn(ALOAD, 3);
664       gv.visitMethodInsn(INVOKEINTERFACE, "com/tc/object/TCObject", "getResolveLock", "()Ljava/lang/Object;");
665       gv.visitInsn(DUP);
666       gv.visitVarInsn(ASTORE, 2);
667       gv.visitInsn(MONITORENTER);
668
669       Label l1 = new Label();
670       gv.visitLabel(l1);
671
672       gv.visitVarInsn(ALOAD, 0);
673       gv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), name, desc);
674       Label l5 = new Label();
675       gv.visitJumpInsn(IFNONNULL, l5);
676       gv.visitVarInsn(ALOAD, 3);
677       gv.visitLdcInsn(spec.getClassNameDots() + '.' + name);
678       gv.visitMethodInsn(INVOKEINTERFACE, "com/tc/object/TCObject", "resolveReference", "(Ljava/lang/String;)V");
679       gv.visitLabel(l5);
680
681       Label l2 = new Label();
682
683       gv.visitVarInsn(ALOAD, 0);
684       gv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), name, desc);
685       gv.visitVarInsn(ALOAD, 2);
686
687       gv.visitInsn(MONITOREXIT);
688       if (isVolatile) {
689         callVolatileCommit(spec.getClassNameDots() + "." + name, gv);
690       }
691       gv.visitInsn(ARETURN);
692       gv.visitJumpInsn(GOTO, l0);
693
694       gv.visitLabel(l2);
695       gv.visitVarInsn(ALOAD, 2);
696
697       gv.visitInsn(MONITOREXIT);
698       if (isVolatile) {
699         callVolatileCommit(spec.getClassNameDots() + "." + name, gv);
700       }
701       gv.visitInsn(ATHROW);
702
703       gv.visitLabel(l0);
704       gv.visitVarInsn(ALOAD, 0);
705       gv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), name, desc);
706       gv.visitInsn(t.getOpcode(IRETURN));
707
708       gv.visitTryCatchBlock(l1, l2, l2, null);
709
710       gv.visitMaxs(0, 0);
711     } catch (RuntimeException JavaDoc e) {
712       handleInstrumentationException(e);
713     } catch (Error JavaDoc e) {
714       handleInstrumentationException(e);
715       throw e;
716     }
717   }
718
719   private void getManaged(MethodVisitor mv) {
720     mv.visitVarInsn(ALOAD, 0);
721     mv.visitMethodInsn(INVOKEVIRTUAL, spec.getClassNameSlashes(), MANAGED_METHOD, "()" + MANAGED_FIELD_TYPE);
722   }
723
724   private void createPlainSetter(int methodAccess, int fieldAccess, String JavaDoc name, String JavaDoc desc) {
725     boolean isVolatile = isVolatile(fieldAccess, name);
726
727     String JavaDoc sDesc = "(" + desc + ")V";
728     MethodVisitor scv = cv.visitMethod(methodAccess, ByteCodeUtil.fieldSetterMethod(name), sDesc, null, null);
729     Type t = Type.getType(desc);
730
731     Label l4 = new Label();
732
733     if (isVolatile) {
734       getManaged(scv);
735       scv.visitInsn(DUP);
736       scv.visitVarInsn(ASTORE, 2);
737       scv.visitJumpInsn(IFNULL, l4);
738
739       Label l0 = new Label();
740       Label l1 = new Label();
741       Label l2 = new Label();
742       scv.visitTryCatchBlock(l0, l1, l2, null);
743       scv.visitLabel(l0);
744
745       callVolatileBegin(spec.getClassNameDots() + "." + name, LockLevel.WRITE, scv);
746
747       Label l6 = new Label();
748       scv.visitJumpInsn(JSR, l6);
749       scv.visitLabel(l1);
750       ByteCodeUtil.pushThis(scv);
751       scv.visitVarInsn(t.getOpcode(ILOAD), 1);
752
753       scv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(), name, desc);
754       scv.visitInsn(RETURN);
755       scv.visitLabel(l2);
756       scv.visitVarInsn(ASTORE, 2);
757       scv.visitJumpInsn(JSR, l6);
758       scv.visitVarInsn(ALOAD, 2);
759       scv.visitInsn(ATHROW);
760       scv.visitLabel(l6);
761       scv.visitVarInsn(ASTORE, 1);
762       callVolatileCommit(spec.getClassNameDots() + "." + name, scv);
763
764       scv.visitVarInsn(RET, 1);
765     }
766
767     scv.visitLabel(l4);
768     ByteCodeUtil.pushThis(scv);
769     scv.visitVarInsn(t.getOpcode(ILOAD), 1);
770
771     scv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(), name, desc);
772     scv.visitInsn(RETURN);
773     scv.visitMaxs(0, 0);
774   }
775
776   private void createInstrumentedSetter(int methodAccess, int fieldAccess, String JavaDoc name, String JavaDoc desc) {
777     try {
778       Type t = Type.getType(desc);
779       if (isRoot(methodAccess, name)) {
780         createObjectSetter(methodAccess, fieldAccess, name, desc);
781       }
782       // if (((t.getSort() == Type.OBJECT) || (t.getSort() == Type.ARRAY)) && !isLiteral(desc)) {
783
else if (((t.getSort() == Type.OBJECT) || (t.getSort() == Type.ARRAY)) && !isPrimitive(t)) {
784         createObjectSetter(methodAccess, fieldAccess, name, desc);
785       } else {
786         createLiteralSetter(methodAccess, fieldAccess, name, desc);
787       }
788     } catch (RuntimeException JavaDoc e) {
789       handleInstrumentationException(e);
790     } catch (Error JavaDoc e) {
791       handleInstrumentationException(e);
792       throw e;
793     }
794   }
795
796   private void createObjectSetter(int methodAccess, int fieldAccess, String JavaDoc name, String JavaDoc desc) {
797     try {
798       if (isRoot(methodAccess, name)) {
799         boolean isStaticRoot = Modifier.isStatic(methodAccess);
800         if (instrumentationLogger.rootInsertion()) {
801           instrumentationLogger.rootInserted(spec.getClassNameDots(), name, desc, isStaticRoot);
802         }
803
804         createRootSetter(methodAccess, name, desc, isStaticRoot);
805       } else {
806         createObjectFieldSetter(methodAccess, fieldAccess, name, desc);
807       }
808     } catch (RuntimeException JavaDoc e) {
809       handleInstrumentationException(e);
810     } catch (Error JavaDoc e) {
811       handleInstrumentationException(e);
812       throw e;
813     }
814   }
815
816   private boolean isRootDSOFinal(String JavaDoc name, boolean isPrimitive) {
817     return spec.getTransparencyClassSpec().isRootDSOFinal(name, isPrimitive);
818   }
819
820   private void createRootSetter(int methodAccess, String JavaDoc name, String JavaDoc desc, boolean isStatic) {
821     Type t = Type.getType(desc);
822     boolean isPrimitive = isPrimitive(t);
823     boolean isDSOFinal = isRootDSOFinal(name, isPrimitive);
824
825     try {
826       String JavaDoc sDesc = "(" + desc + ")V";
827       String JavaDoc targetType = isPrimitive ? ByteCodeUtil.sortToWrapperName(t.getSort()) : convertToCheckCastDesc(desc);
828       MethodVisitor scv = cv.visitMethod(methodAccess, ByteCodeUtil.fieldSetterMethod(name), sDesc, null, null);
829
830       Label tryStart = new Label();
831       Label end = new Label();
832       Label normalExit = new Label();
833       Label finallyStart = new Label();
834       Label exceptionHandler = new Label();
835
836       final int rootInstance = isStatic ? 0 : 1;
837
838       if (!isPrimitive) {
839         scv.visitVarInsn(ALOAD, rootInstance);
840         scv.visitJumpInsn(IFNULL, end); // Always ignore request to set roots to null
841
}
842
843       String JavaDoc rootName = rootNameFor(spec.getClassNameSlashes(), name);
844       callTCBeginWithLockName(rootName, LockLevel.WRITE, scv);
845
846       scv.visitLabel(tryStart);
847
848       scv.visitLdcInsn(rootName);
849       if (isPrimitive) {
850         ByteCodeUtil.addTypeSpecificParameterLoad(scv, t, rootInstance);
851       } else {
852         scv.visitVarInsn(ALOAD, rootInstance);
853       }
854       if (isDSOFinal) {
855         spec.getManagerHelper().callManagerMethod("lookupOrCreateRoot", scv);
856       } else {
857         spec.getManagerHelper().callManagerMethod("createOrReplaceRoot", scv);
858       }
859
860       int localVar = rootInstance + 1;
861       scv.visitVarInsn(ASTORE, localVar);
862
863       Label l0 = new Label();
864       checkReturnObjectType(name, rootName, targetType, localVar, l0, scv);
865
866       scv.visitLabel(l0);
867       callPutFieldInsn(isStatic, t, localVar, name, desc, scv);
868       scv.visitJumpInsn(GOTO, normalExit);
869
870       scv.visitLabel(exceptionHandler);
871       scv.visitVarInsn(ASTORE, 3);
872       scv.visitJumpInsn(JSR, finallyStart);
873       scv.visitVarInsn(ALOAD, 3);
874       scv.visitInsn(ATHROW);
875
876       scv.visitLabel(finallyStart);
877       scv.visitVarInsn(ASTORE, 2);
878       callTCCommitWithLockName(rootName, scv);
879       scv.visitVarInsn(RET, 2);
880
881       scv.visitLabel(normalExit);
882       scv.visitJumpInsn(JSR, finallyStart);
883       scv.visitLabel(end);
884       scv.visitInsn(RETURN);
885       scv.visitTryCatchBlock(tryStart, exceptionHandler, exceptionHandler, null);
886       scv.visitMaxs(0, 0);
887     } catch (RuntimeException JavaDoc e) {
888       handleInstrumentationException(e);
889     } catch (Error JavaDoc e) {
890       handleInstrumentationException(e);
891       throw e;
892     }
893   }
894
895   private void callGetFieldInsn(boolean isStatic, String JavaDoc name, String JavaDoc desc, MethodVisitor mv) {
896     int getInsn = isStatic ? GETSTATIC : GETFIELD;
897
898     if (!isStatic) ByteCodeUtil.pushThis(mv);
899     mv.visitFieldInsn(getInsn, spec.getClassNameSlashes(), name, desc);
900   }
901
902   private void callPutFieldInsn(boolean isStatic, Type targetType, int localVar, String JavaDoc name, String JavaDoc desc,
903                                 MethodVisitor mv) {
904     int putInsn = isStatic ? PUTSTATIC : PUTFIELD;
905
906     if (!isStatic) ByteCodeUtil.pushThis(mv);
907     mv.visitVarInsn(ALOAD, localVar);
908
909     if (isPrimitive(targetType)) {
910       mv.visitTypeInsn(CHECKCAST, ByteCodeUtil.sortToWrapperName(targetType.getSort()));
911       mv.visitMethodInsn(INVOKEVIRTUAL, ByteCodeUtil.sortToWrapperName(targetType.getSort()), ByteCodeUtil
912           .sortToPrimitiveMethodName(targetType.getSort()), "()" + desc);
913     } else {
914       mv.visitTypeInsn(CHECKCAST, convertToCheckCastDesc(desc));
915     }
916
917     mv.visitFieldInsn(putInsn, spec.getClassNameSlashes(), name, desc);
918   }
919
920   private void generateCodeForVolatileTransactionBegin(Label l1, Label l2, Label l3, Label l4, String JavaDoc fieldName,
921                                                        int lockLevel, MethodVisitor scv) {
922     scv.visitTryCatchBlock(l4, l1, l1, null);
923     scv.visitTryCatchBlock(l2, l3, l1, null);
924     scv.visitLabel(l4);
925     callVolatileBegin(fieldName, lockLevel, scv);
926   }
927
928   private void generateCodeForVolativeTransactionCommit(Label l1, Label l2, MethodVisitor scv, int newVar1,
929                                                         int newVar2, String JavaDoc fieldName) {
930     scv.visitJumpInsn(GOTO, l2);
931     scv.visitLabel(l1);
932     scv.visitVarInsn(ASTORE, newVar2);
933     Label l5 = new Label();
934     scv.visitJumpInsn(JSR, l5);
935     scv.visitVarInsn(ALOAD, newVar2);
936     scv.visitInsn(ATHROW);
937     scv.visitLabel(l5);
938     scv.visitVarInsn(ASTORE, newVar1);
939     callVolatileCommit(fieldName, scv);
940     scv.visitVarInsn(RET, newVar1);
941     scv.visitLabel(l2);
942     scv.visitJumpInsn(JSR, l5);
943   }
944
945   private void createObjectFieldSetter(int methodAccess, int fieldAccess, String JavaDoc name, String JavaDoc desc) {
946     try {
947       boolean isVolatile = isVolatile(fieldAccess, name);
948       Label l1 = new Label();
949       Label l2 = new Label();
950       Label l4 = new Label();
951
952       // generates setter method
953
String JavaDoc sDesc = "(" + desc + ")V";
954       MethodVisitor scv = cv.visitMethod(methodAccess, ByteCodeUtil.fieldSetterMethod(name), sDesc, null, null);
955       getManaged(scv);
956       scv.visitInsn(DUP);
957       scv.visitVarInsn(ASTORE, 2);
958       Label l0 = new Label();
959       scv.visitJumpInsn(IFNULL, l0);
960
961       if (isVolatile) {
962         generateCodeForVolatileTransactionBegin(l1, l2, l0, l4, spec.getClassNameDots() + "." + name, LockLevel.WRITE,
963                                                 scv);
964       }
965
966       scv.visitVarInsn(ALOAD, 2);
967       scv.visitLdcInsn(spec.getClassNameDots());
968       scv.visitLdcInsn(spec.getClassNameDots() + "." + name);
969       scv.visitVarInsn(ALOAD, 1);
970       scv.visitInsn(ICONST_M1);
971       scv.visitMethodInsn(INVOKEINTERFACE, "com/tc/object/TCObject", "objectFieldChanged",
972                           "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;I)V");
973
974       if (isVolatile) {
975         generateCodeForVolativeTransactionCommit(l1, l2, scv, 3, 4, spec.getClassNameDots() + "." + name);
976       }
977
978       scv.visitLabel(l0);
979       scv.visitVarInsn(ALOAD, 0);
980       scv.visitVarInsn(ALOAD, 1);
981       scv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(), name, desc);
982       scv.visitInsn(RETURN);
983       scv.visitMaxs(0, 0);
984     } catch (RuntimeException JavaDoc e) {
985       handleInstrumentationException(e);
986     } catch (Error JavaDoc e) {
987       handleInstrumentationException(e);
988       throw e;
989     }
990   }
991
992   private void createLiteralSetter(int methodAccess, int fieldAccess, String JavaDoc name, String JavaDoc desc) {
993     try {
994       // generates setter method
995
boolean isVolatile = isVolatile(fieldAccess, name);
996
997       Label l1 = new Label();
998       Label l2 = new Label();
999       Label l4 = new Label();
1000
1001      String JavaDoc sDesc = "(" + desc + ")V";
1002      Type t = Type.getType(desc);
1003
1004      MethodVisitor mv = cv.visitMethod(methodAccess, ByteCodeUtil.fieldSetterMethod(name), sDesc, null, null);
1005      getManaged(mv);
1006      mv.visitInsn(DUP);
1007      mv.visitVarInsn(ASTORE, 1 + t.getSize());
1008      Label l0 = new Label();
1009      mv.visitJumpInsn(IFNULL, l0);
1010
1011      if (isVolatile) {
1012        generateCodeForVolatileTransactionBegin(l1, l2, l0, l4, spec.getClassNameDots() + "." + name, LockLevel.WRITE,
1013                                                mv);
1014      }
1015
1016      mv.visitVarInsn(ALOAD, 1 + t.getSize());
1017      mv.visitLdcInsn(spec.getClassNameDots());
1018      mv.visitLdcInsn(spec.getClassNameDots() + "." + name);
1019      mv.visitVarInsn(t.getOpcode(ILOAD), 1);
1020      mv.visitInsn(ICONST_M1);
1021      String JavaDoc method = ByteCodeUtil.codeToName(desc) + "FieldChanged";
1022      mv.visitMethodInsn(INVOKEINTERFACE, "com/tc/object/TCObject", method, "(Ljava/lang/String;Ljava/lang/String;"
1023                                                                            + desc + "I)V");
1024
1025      if (isVolatile) {
1026        generateCodeForVolativeTransactionCommit(l1, l2, mv, 2 + t.getSize(), 3 + t.getSize(), spec.getClassNameDots()
1027                                                                                               + "." + name);
1028      }
1029
1030      mv.visitLabel(l0);
1031      mv.visitVarInsn(ALOAD, 0);
1032      mv.visitVarInsn(t.getOpcode(ILOAD), 1);
1033      mv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(), name, desc);
1034      mv.visitInsn(RETURN);
1035      mv.visitMaxs(0, 0);
1036    } catch (RuntimeException JavaDoc e) {
1037      handleInstrumentationException(e);
1038    } catch (Error JavaDoc e) {
1039      handleInstrumentationException(e);
1040      throw e;
1041    }
1042  }
1043
1044  private void callTCMonitorExit(int callingMethodModifier, MethodVisitor c) {
1045    Assert.eval("Can't call tc monitorenter from a static method.", !Modifier.isStatic(callingMethodModifier));
1046    ByteCodeUtil.pushThis(c);
1047    spec.getManagerHelper().callManagerMethod("monitorExit", c);
1048  }
1049
1050  private void callTCMonitorEnter(int callingMethodModifier, LockDefinition def, MethodVisitor c) {
1051    Assert.eval("Can't call tc monitorexit from a static method.", !Modifier.isStatic(callingMethodModifier));
1052    ByteCodeUtil.pushThis(c);
1053    c.visitLdcInsn(new Integer JavaDoc(def.getLockLevelAsInt()));
1054    spec.getManagerHelper().callManagerMethod("monitorEnter", c);
1055  }
1056
1057  private void addPrimitiveTypeZeroCompare(MethodVisitor mv, Type type, Label notZeroLabel) {
1058    switch (type.getSort()) {
1059      case Type.LONG:
1060        mv.visitInsn(LCONST_0);
1061        mv.visitInsn(LCMP);
1062        mv.visitJumpInsn(IFNE, notZeroLabel);
1063        break;
1064      case Type.DOUBLE:
1065        mv.visitInsn(DCONST_0);
1066        mv.visitInsn(DCMPL);
1067        mv.visitJumpInsn(IFNE, notZeroLabel);
1068        break;
1069      case Type.FLOAT:
1070        mv.visitInsn(FCONST_0);
1071        mv.visitInsn(FCMPL);
1072        mv.visitJumpInsn(IFNE, notZeroLabel);
1073        break;
1074      default:
1075        mv.visitJumpInsn(IFNE, notZeroLabel);
1076    }
1077  }
1078}
1079
Popular Tags