KickJava   Java API By Example, From Geeks To Geeks.

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


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.ClassAdapter;
8 import com.tc.asm.ClassVisitor;
9 import com.tc.asm.MethodAdapter;
10 import com.tc.asm.MethodVisitor;
11 import com.tc.asm.Opcodes;
12 import com.tc.asm.Type;
13
14 public class JavaUtilWeakHashMapAdapter extends ClassAdapter implements Opcodes, ClassAdapterFactory {
15   private static final String JavaDoc HASH_MAP_CLASS = "java/util/HashMap";
16   private static final String JavaDoc WEAK_HASH_MAP_CLASS = "java/util/WeakHashMap";
17
18   private static final int SYNTHETIC_METHOD_ACCESS = ACC_PROTECTED | ACC_SYNTHETIC;
19
20   private static final String JavaDoc HASH_MAP_HASH_METHOD_NAME = "hash";
21
22   private static final String JavaDoc TC_HASH_METHOD_NAME = ByteCodeUtil.TC_METHOD_PREFIX + "hash";
23   private static final String JavaDoc HASH_METHOD_DESCRIPTION = "(Ljava/lang/Object;)I";
24
25   private static final String JavaDoc TC_EQUAL_METHOD_NAME = ByteCodeUtil.TC_METHOD_PREFIX + "equal";
26   private static final String JavaDoc EQ_METHOD_DESCRIPTION = "(Ljava/lang/Object;Ljava/lang/Object;)Z";
27
28   private static final String JavaDoc EQ_METHOD_NAME = "eq";
29
30   private String JavaDoc hashMapHashMethodDesc = null;
31
32   public JavaUtilWeakHashMapAdapter() {
33     super(null);
34   }
35
36   private JavaUtilWeakHashMapAdapter(ClassVisitor cv, ClassLoader JavaDoc caller) {
37     super(cv);
38   }
39
40   public ClassAdapter create(ClassVisitor visitor, ClassLoader JavaDoc loader) {
41     return new JavaUtilWeakHashMapAdapter(visitor, loader);
42   }
43
44   public void visitEnd() {
45     generateSyntheticHashMethod();
46     generateSyntheticEqualMethod();
47     super.visitEnd();
48   }
49
50   private void generateSyntheticHashMethod() {
51     MethodVisitor mv = super.visitMethod(SYNTHETIC_METHOD_ACCESS, TC_HASH_METHOD_NAME, HASH_METHOD_DESCRIPTION, null,
52                                          null);
53     mv.visitCode();
54     mv.visitVarInsn(ALOAD, 1);
55
56     if (hashMapHashMethodDesc == null) { throw new AssertionError JavaDoc(); }
57     Type[] args = Type.getArgumentTypes(hashMapHashMethodDesc);
58     if (args.length != 1) { throw new AssertionError JavaDoc("unexpected HashMap.hash() signature: " + hashMapHashMethodDesc); }
59
60     if (args[0].getSort() == Type.INT) {
61       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I");
62     } else if (!args[0].getInternalName().equals("java/lang/Object")) { throw new AssertionError JavaDoc("unexpected type: "
63                                                                                                  + args[0]); }
64
65     mv.visitMethodInsn(INVOKESTATIC, HASH_MAP_CLASS, HASH_MAP_HASH_METHOD_NAME, hashMapHashMethodDesc);
66     mv.visitInsn(IRETURN);
67     mv.visitMaxs(0, 0);
68     mv.visitEnd();
69   }
70
71   private void generateSyntheticEqualMethod() {
72     MethodVisitor mv = super.visitMethod(SYNTHETIC_METHOD_ACCESS, TC_EQUAL_METHOD_NAME, EQ_METHOD_DESCRIPTION, null,
73                                          null);
74     mv.visitCode();
75     mv.visitVarInsn(ALOAD, 1);
76     mv.visitVarInsn(ALOAD, 2);
77     mv.visitMethodInsn(INVOKESTATIC, WEAK_HASH_MAP_CLASS, EQ_METHOD_NAME, EQ_METHOD_DESCRIPTION);
78     mv.visitInsn(IRETURN);
79     mv.visitMaxs(1, 2);
80     mv.visitEnd();
81   }
82
83   public MethodVisitor visitMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
84     MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
85     return new JavaUtilWeakHashMapMethodAdapter(mv);
86   }
87
88   private class JavaUtilWeakHashMapMethodAdapter extends MethodAdapter {
89     public JavaUtilWeakHashMapMethodAdapter(MethodVisitor mv) {
90       super(mv);
91     }
92
93     public void visitMethodInsn(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
94       if ((INVOKEVIRTUAL == opcode) && "java/lang/Object".equals(owner) && "hashCode".equals(name)) { return; }
95
96       if (INVOKESTATIC == opcode && HASH_MAP_CLASS.equals(owner) && HASH_MAP_HASH_METHOD_NAME.equals(name)) {
97         hashMapHashMethodDesc = desc;
98         ByteCodeUtil.pushThis(this);
99         super.visitInsn(SWAP);
100         super.visitMethodInsn(INVOKEVIRTUAL, WEAK_HASH_MAP_CLASS, TC_HASH_METHOD_NAME, HASH_METHOD_DESCRIPTION);
101       } else if (INVOKESTATIC == opcode && WEAK_HASH_MAP_CLASS.equals(owner) && EQ_METHOD_NAME.equals(name)
102                  && EQ_METHOD_DESCRIPTION.equals(desc)) {
103         ByteCodeUtil.pushThis(mv);
104         super.visitInsn(SWAP);
105         super.visitInsn(DUP2_X1);
106         super.visitInsn(POP2);
107         super.visitInsn(SWAP);
108         super.visitMethodInsn(INVOKEVIRTUAL, WEAK_HASH_MAP_CLASS, TC_EQUAL_METHOD_NAME, desc);
109       } else {
110         super.visitMethodInsn(opcode, owner, name, desc);
111       }
112     }
113   }
114 }
Popular Tags