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 AtomicLongAdapter extends ClassAdapter implements Opcodes {
014:
015: public static final String VALUE_FIELD_NAME = "java.util.concurrent.atomic.AtomicLong.value";
016:
017: public AtomicLongAdapter(ClassVisitor cv) {
018: super (cv);
019: }
020:
021: public MethodVisitor visitMethod(int access, String name,
022: String desc, String signature, String[] exceptions) {
023: MethodVisitor mv = super .visitMethod(access, name, desc,
024: signature, exceptions);
025: if ("set".equals(name) && "(J)V".equals(desc)) {
026: return new SetMethodVisitor(mv);
027: } else if ("get".equals(name) && "()J".equals(desc)) {
028: return new GetMethodVisitor(mv);
029: }
030:
031: return mv;
032: }
033:
034: private static class SetMethodVisitor extends
035: AbstractVolatileFieldMethodVisitor {
036: private int long_var_store;
037:
038: private SetMethodVisitor(MethodVisitor mv) {
039: super (mv);
040: }
041:
042: public void modifyVolatileValue(int tcobjectVarStore,
043: Label labelCommitVolatile) {
044: // if the TCObject instance is not null, obtain it again so
045: // that it can be used to signal the new value for the local 'value'
046: // variable
047: mv.visitVarInsn(ALOAD, tcobjectVarStore);
048: mv.visitLdcInsn("java.util.concurrent.atomic.AtomicLong");
049: mv.visitLdcInsn(VALUE_FIELD_NAME);
050: mv.visitVarInsn(LLOAD, long_var_store);
051: mv.visitInsn(ICONST_M1);
052: mv.visitMethodInsn(INVOKEINTERFACE,
053: "com/tc/object/TCObject", "longFieldChanged",
054: "(Ljava/lang/String;Ljava/lang/String;JI)V");
055: mv.visitJumpInsn(GOTO, labelCommitVolatile);
056: }
057:
058: public void visitFieldInsn(int opcode, String owner,
059: String name, String desc) {
060: if (PUTFIELD == opcode
061: && owner
062: .equals("java/util/concurrent/atomic/AtomicLong")
063: && name.equals("value") && desc.equals("J")) {
064:
065: long_var_store = getMaxLocalVarStore() + 1;
066:
067: // make a copy of the long that's currently on the stack,
068: // ready to be assigned to the 'value' field
069: mv.visitInsn(DUP2);
070:
071: // store the long value in the appropriate local variable slot
072: mv.visitVarInsn(LSTORE, long_var_store);
073:
074: doVolatileBeginCommitLogic(VALUE_FIELD_NAME,
075: long_var_store + 1);
076:
077: // setup stack for original putfield operation
078: mv.visitVarInsn(ALOAD, 0);
079: mv.visitVarInsn(LLOAD, long_var_store);
080: }
081:
082: super .visitFieldInsn(opcode, owner, name, desc);
083: }
084: }
085:
086: private static class GetMethodVisitor extends
087: AbstractVolatileFieldMethodVisitor {
088:
089: private GetMethodVisitor(MethodVisitor mv) {
090: super (mv);
091: }
092:
093: public void modifyVolatileValue(int tcobjectVarStore,
094: Label labelCommitVolatile) {
095: // do nothing since this is a getter
096: }
097:
098: public void visitFieldInsn(int opcode, String owner,
099: String name, String desc) {
100: if (GETFIELD == opcode
101: && owner
102: .equals("java/util/concurrent/atomic/AtomicLong")
103: && name.equals("value") && desc.equals("J")) {
104:
105: doVolatileBeginCommitLogic(VALUE_FIELD_NAME,
106: getMaxLocalVarStore() + 1);
107: }
108:
109: super.visitFieldInsn(opcode, owner, name, desc);
110: }
111: }
112: }
|