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.ClassVisitor;
008: import com.tc.asm.Label;
009: import com.tc.asm.MethodVisitor;
010: import com.tc.asm.Opcodes;
011: import com.tc.asm.Type;
012: import com.tc.aspectwerkz.reflect.MemberInfo;
013: import com.tc.object.logging.InstrumentationLogger;
014:
015: public class DistributedMethodCallAdapter implements MethodAdapter,
016: Opcodes {
017: private ManagerHelper managerHelper;
018: private int access;
019: private String className;
020: private String methodName;
021: private String originalMethodname;
022: private String description;
023: private String[] exceptions;
024: private String signature;
025: private InstrumentationLogger instrumentationLogger;
026:
027: private final boolean runOnAllNodes;
028:
029: public DistributedMethodCallAdapter(boolean runOnAllNodes) {
030: this .runOnAllNodes = runOnAllNodes;
031: }
032:
033: public MethodVisitor adapt(ClassVisitor classVisitor) {
034: final String newMethodName = ByteCodeUtil.DMI_METHOD_RENAME_PREFIX
035: + methodName;
036: MethodVisitor codeVisitor = classVisitor.visitMethod(access,
037: newMethodName, description, signature, exceptions);
038: addDmiMethodWrapper(classVisitor, newMethodName);
039: // addDistributedCall(codeVisitor, newMethodName, description);
040: return codeVisitor;
041: }
042:
043: private void addDmiMethodWrapper(ClassVisitor classVisitor,
044: String newMethodName) {
045: MethodVisitor mv = classVisitor.visitMethod(access, methodName,
046: description, signature, exceptions);
047: final int boolPos = ByteCodeUtil.getFirstLocalVariableOffset(
048: access, description);
049: final int exceptionPos = boolPos + 1;
050: final int pcPos = exceptionPos + 1;
051: final int rvPos = pcPos + 1;
052:
053: mv.visitCode();
054: Label l0 = new Label();
055: Label l1 = new Label();
056: Label l2 = new Label();
057: mv.visitTryCatchBlock(l0, l1, l2, null);
058:
059: addDistributedCall(mv, originalMethodname, description);
060:
061: mv.visitVarInsn(ISTORE, boolPos);
062: mv.visitLabel(l0);
063:
064: // call the renamed method and store it's return value
065: mv.visitVarInsn(ALOAD, 0);
066: ByteCodeUtil.pushMethodArguments(access, description, mv);
067: mv.visitMethodInsn(INVOKEVIRTUAL, className.replace('.', '/'),
068: newMethodName, description);
069: final Type rvType = Type.getReturnType(description);
070: final boolean returnVoid = rvType == Type.VOID_TYPE;
071: if (!returnVoid)
072: mv.visitVarInsn(rvType.getOpcode(ISTORE), rvPos);
073:
074: Label l4 = new Label();
075: mv.visitJumpInsn(JSR, l4);
076: mv.visitLabel(l1);
077: if (!returnVoid)
078: mv.visitVarInsn(rvType.getOpcode(ILOAD), rvPos);
079: mv.visitInsn(rvType.getOpcode(IRETURN));
080:
081: mv.visitLabel(l2);
082: mv.visitVarInsn(ASTORE, exceptionPos);
083: mv.visitJumpInsn(JSR, l4);
084:
085: mv.visitVarInsn(ALOAD, exceptionPos);
086: mv.visitInsn(ATHROW);
087: mv.visitLabel(l4);
088: mv.visitVarInsn(ASTORE, pcPos);
089:
090: mv.visitVarInsn(ILOAD, boolPos);
091: Label l7 = new Label();
092: mv.visitJumpInsn(IFEQ, l7);
093: managerHelper.callManagerMethod("distributedMethodCallCommit",
094: mv);
095: mv.visitLabel(l7);
096: mv.visitVarInsn(RET, pcPos);
097: mv.visitMaxs(0, 0);
098: mv.visitEnd();
099: }
100:
101: private void addDistributedCall(MethodVisitor mv, String name,
102: String desc) {
103: if (instrumentationLogger.distMethodCallInsertion()) {
104: instrumentationLogger.distMethodCallInserted(className,
105: name, desc);
106: }
107:
108: ByteCodeUtil.pushThis(mv);
109: mv.visitLdcInsn(name + desc);
110: ByteCodeUtil.createParametersToArrayByteCode(mv, Type
111: .getArgumentTypes(desc));
112: final String managerMethodName = (runOnAllNodes) ? "distributedMethodCall"
113: : "prunedDistributedMethodCall";
114: managerHelper.callManagerMethod(managerMethodName, mv);
115: }
116:
117: public boolean doesOriginalNeedAdapting() {
118: return true;
119: }
120:
121: public void initialize(ManagerHelper aManagerHelper, int anAccess,
122: String aClassName, String aMethodName,
123: String aOriginalMethodName, String aDescription,
124: String sig, String[] anExceptions,
125: InstrumentationLogger logger, MemberInfo info) {
126: this.managerHelper = aManagerHelper;
127: this.access = anAccess;
128: this.className = aClassName;
129: this.methodName = aMethodName;
130: this.originalMethodname = aOriginalMethodName;
131: this.description = aDescription;
132: this.exceptions = anExceptions;
133: this.signature = sig;
134: this.instrumentationLogger = logger;
135: }
136:
137: }
|