001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.bytecode;
006:
007: import com.tc.asm.ClassAdapter;
008: import com.tc.asm.ClassVisitor;
009: import com.tc.asm.Label;
010: import com.tc.asm.MethodVisitor;
011: import com.tc.asm.Opcodes;
012:
013: public class AtomicIntegerAdapter extends ClassAdapter implements
014: Opcodes {
015:
016: public static final String VALUE_FIELD_NAME = "java.util.concurrent.atomic.AtomicInteger.value";
017:
018: public AtomicIntegerAdapter(ClassVisitor cv) {
019: super (cv);
020: }
021:
022: public MethodVisitor visitMethod(int access, String name,
023: String desc, String signature, String[] exceptions) {
024: MethodVisitor mv = super .visitMethod(access, name, desc,
025: signature, exceptions);
026: if ("set".equals(name) && "(I)V".equals(desc)) {
027: return new SetMethodVisitor(mv);
028: } else if ("get".equals(name) && "()I".equals(desc)) {
029: return new GetMethodVisitor(mv);
030: }
031:
032: return mv;
033: }
034:
035: private static class SetMethodVisitor extends
036: AbstractVolatileFieldMethodVisitor {
037: private int int_var_store;
038:
039: private SetMethodVisitor(MethodVisitor mv) {
040: super (mv);
041: }
042:
043: public void modifyVolatileValue(int tcobjectVarStore,
044: Label labelCommitVolatile) {
045: // if the TCObject instance is not null, obtain it again so
046: // that it can be used to signal the new value for the local 'value'
047: // variable
048: mv.visitVarInsn(ALOAD, tcobjectVarStore);
049: mv
050: .visitLdcInsn("java.util.concurrent.atomic.AtomicInteger");
051: mv.visitLdcInsn(VALUE_FIELD_NAME);
052: mv.visitVarInsn(ILOAD, int_var_store);
053: mv.visitInsn(ICONST_M1);
054: mv.visitMethodInsn(INVOKEINTERFACE,
055: "com/tc/object/TCObject", "intFieldChanged",
056: "(Ljava/lang/String;Ljava/lang/String;II)V");
057: mv.visitJumpInsn(GOTO, labelCommitVolatile);
058: }
059:
060: public void visitFieldInsn(int opcode, String owner,
061: String name, String desc) {
062: if (PUTFIELD == opcode
063: && owner
064: .equals("java/util/concurrent/atomic/AtomicInteger")
065: && name.equals("value") && desc.equals("I")) {
066:
067: int_var_store = getMaxLocalVarStore() + 1;
068:
069: // make a copy of the int that's currently on the stack,
070: // ready to be assigned to the 'value' field
071: mv.visitInsn(DUP);
072:
073: // store the int value in the appropriate local variable slot
074: mv.visitVarInsn(ISTORE, int_var_store);
075:
076: doVolatileBeginCommitLogic(VALUE_FIELD_NAME,
077: int_var_store + 1);
078:
079: // setup stack for original putfield operation
080: mv.visitVarInsn(ALOAD, 0);
081: mv.visitVarInsn(ILOAD, int_var_store);
082: }
083:
084: super .visitFieldInsn(opcode, owner, name, desc);
085: }
086: }
087:
088: private static class GetMethodVisitor extends
089: AbstractVolatileFieldMethodVisitor {
090:
091: private GetMethodVisitor(MethodVisitor mv) {
092: super (mv);
093: }
094:
095: public void modifyVolatileValue(int tcobjectVarStore,
096: Label labelCommitVolatile) {
097: // do nothing since this is a getter
098: }
099:
100: public void visitFieldInsn(int opcode, String owner,
101: String name, String desc) {
102: if (GETFIELD == opcode
103: && owner
104: .equals("java/util/concurrent/atomic/AtomicInteger")
105: && name.equals("value") && desc.equals("I")) {
106:
107: doVolatileBeginCommitLogic(VALUE_FIELD_NAME,
108: getMaxLocalVarStore() + 1);
109: }
110:
111: super.visitFieldInsn(opcode, owner, name, desc);
112: }
113: }
114: }
|