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.Label;
008: import com.tc.asm.Opcodes;
009: import com.tc.asm.tree.MethodNode;
010: import com.tc.util.runtime.Vm;
011:
012: public class HashtableClassAdapter implements Opcodes {
013:
014: /**
015: * Creates the following method code
016: *
017: * For Sun JRE:
018: *
019: * <pre>
020: * protected Map.Entry __tc_getEntry(Object obj) {
021: * Entry aentry[] = table;
022: * int i = obj.hashCode();
023: * int j = (i & 0x7fffffff) % aentry.length;
024: * for (Entry entry = aentry[j]; entry != null; entry = entry.next) {
025: * if (entry.hash == i && entry.key.equals(obj)) { return (Entry) entry; }
026: * }
027: * return null;
028: * }
029: * </pre>
030: *
031: * For IBM JRE:
032: *
033: * <pre>
034: * protected Map.Entry __tc_getEntry(Object obj) {
035: * return getEntry();
036: * }
037: * </pre>
038: *
039: */
040: private static MethodNode __tc_getEntryMethod() {
041: MethodNode mv = new MethodNode(ACC_PROTECTED, //
042: "__tc_getEntry", //
043: "(Ljava/lang/Object;)Ljava/util/Map$Entry;", null, null);
044: mv.visitCode();
045:
046: if (Vm.isIBM()) {
047: mv.visitVarInsn(ALOAD, 0);
048: mv.visitVarInsn(ALOAD, 1);
049: mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Hashtable",
050: "getEntry",
051: "(Ljava/lang/Object;)Ljava/util/Hashtable$Entry;");
052: } else {
053: mv.visitVarInsn(ALOAD, 0);
054: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable", "table",
055: "[Ljava/util/Hashtable$Entry;");
056: mv.visitVarInsn(ASTORE, 2);
057: mv.visitVarInsn(ALOAD, 1);
058: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
059: "hashCode", "()I");
060: mv.visitVarInsn(ISTORE, 3);
061: mv.visitVarInsn(ILOAD, 3);
062: mv.visitLdcInsn(new Integer(2147483647));
063: mv.visitInsn(IAND);
064: mv.visitVarInsn(ALOAD, 2);
065: mv.visitInsn(ARRAYLENGTH);
066: mv.visitInsn(IREM);
067: mv.visitVarInsn(ISTORE, 4);
068: mv.visitVarInsn(ALOAD, 2);
069: mv.visitVarInsn(ILOAD, 4);
070: mv.visitInsn(AALOAD);
071: mv.visitVarInsn(ASTORE, 5);
072: Label l4 = new Label();
073: mv.visitLabel(l4);
074: mv.visitVarInsn(ALOAD, 5);
075: Label l5 = new Label();
076: mv.visitJumpInsn(IFNULL, l5);
077: mv.visitVarInsn(ALOAD, 5);
078: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry",
079: "hash", "I");
080: mv.visitVarInsn(ILOAD, 3);
081: Label l7 = new Label();
082: mv.visitJumpInsn(IF_ICMPNE, l7);
083: mv.visitVarInsn(ALOAD, 5);
084: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry",
085: "key", "Ljava/lang/Object;");
086: mv.visitVarInsn(ALOAD, 1);
087: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
088: "equals", "(Ljava/lang/Object;)Z");
089: mv.visitJumpInsn(IFEQ, l7);
090: mv.visitVarInsn(ALOAD, 5);
091: mv.visitTypeInsn(CHECKCAST, "java/util/Hashtable$Entry");
092: mv.visitInsn(ARETURN);
093: mv.visitLabel(l7);
094: mv.visitVarInsn(ALOAD, 5);
095: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry",
096: "next", "Ljava/util/Hashtable$Entry;");
097: mv.visitVarInsn(ASTORE, 5);
098: mv.visitJumpInsn(GOTO, l4);
099: mv.visitLabel(l5);
100: mv.visitInsn(ACONST_NULL);
101: }
102:
103: mv.visitInsn(ARETURN);
104: mv.visitMaxs(0, 0);
105: mv.visitEnd();
106:
107: return mv;
108: }
109:
110: /**
111: * Just like Hashtable.remove(Object) except that it returns the entry (or null)
112: *
113: * <pre>
114: * protected synchronized Entry __tc_removeEntryForKey(Object key) {
115: * Entry tab[] = table;
116: * int hash = key.hashCode();
117: * int index = (hash & 0x7FFFFFFF) % tab.length;
118: * for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
119: * if ((e.hash == hash) && e.key.equals(key)) {
120: * modCount++;
121: * if (prev != null) {
122: * prev.next = e.next;
123: * } else {
124: * tab[index] = e.next;
125: * }
126: * count--;
127: * return e;
128: * }
129: * }
130: * return null;
131: * }
132: *
133: */
134: private static MethodNode __tc_removeEntryForKeyMethodSun() {
135: MethodNode mv = new MethodNode(
136: ACC_PROTECTED + ACC_SYNCHRONIZED,
137: "__tc_removeEntryForKey",
138: "(Ljava/lang/Object;)Ljava/util/Map$Entry;", null, null);
139: mv.visitCode();
140: mv.visitVarInsn(ALOAD, 0);
141: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable", "table",
142: "[Ljava/util/Hashtable$Entry;");
143: mv.visitVarInsn(ASTORE, 2);
144: mv.visitVarInsn(ALOAD, 1);
145: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
146: "hashCode", "()I");
147: mv.visitVarInsn(ISTORE, 3);
148: mv.visitVarInsn(ILOAD, 3);
149: mv.visitLdcInsn(new Integer(2147483647));
150: mv.visitInsn(IAND);
151: mv.visitVarInsn(ALOAD, 2);
152: mv.visitInsn(ARRAYLENGTH);
153: mv.visitInsn(IREM);
154: mv.visitVarInsn(ISTORE, 4);
155: mv.visitVarInsn(ALOAD, 2);
156: mv.visitVarInsn(ILOAD, 4);
157: mv.visitInsn(AALOAD);
158: mv.visitVarInsn(ASTORE, 5);
159: mv.visitInsn(ACONST_NULL);
160: mv.visitVarInsn(ASTORE, 6);
161: Label l4 = new Label();
162: mv.visitLabel(l4);
163: mv.visitVarInsn(ALOAD, 5);
164: Label l5 = new Label();
165: mv.visitJumpInsn(IFNULL, l5);
166: mv.visitVarInsn(ALOAD, 5);
167: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry",
168: "hash", "I");
169: mv.visitVarInsn(ILOAD, 3);
170: Label l7 = new Label();
171: mv.visitJumpInsn(IF_ICMPNE, l7);
172: mv.visitVarInsn(ALOAD, 5);
173: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry", "key",
174: "Ljava/lang/Object;");
175: mv.visitVarInsn(ALOAD, 1);
176: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals",
177: "(Ljava/lang/Object;)Z");
178: mv.visitJumpInsn(IFEQ, l7);
179: mv.visitVarInsn(ALOAD, 0);
180: mv.visitInsn(DUP);
181: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable", "modCount",
182: "I");
183: mv.visitInsn(ICONST_1);
184: mv.visitInsn(IADD);
185: mv.visitFieldInsn(PUTFIELD, "java/util/Hashtable", "modCount",
186: "I");
187: mv.visitVarInsn(ALOAD, 6);
188: Label l10 = new Label();
189: mv.visitJumpInsn(IFNULL, l10);
190: mv.visitVarInsn(ALOAD, 6);
191: mv.visitVarInsn(ALOAD, 5);
192: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry",
193: "next", "Ljava/util/Hashtable$Entry;");
194: mv.visitFieldInsn(PUTFIELD, "java/util/Hashtable$Entry",
195: "next", "Ljava/util/Hashtable$Entry;");
196: Label l12 = new Label();
197: mv.visitJumpInsn(GOTO, l12);
198: mv.visitLabel(l10);
199: mv.visitVarInsn(ALOAD, 2);
200: mv.visitVarInsn(ILOAD, 4);
201: mv.visitVarInsn(ALOAD, 5);
202: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry",
203: "next", "Ljava/util/Hashtable$Entry;");
204: mv.visitInsn(AASTORE);
205: mv.visitLabel(l12);
206: mv.visitVarInsn(ALOAD, 0);
207: mv.visitInsn(DUP);
208: mv
209: .visitFieldInsn(GETFIELD, "java/util/Hashtable",
210: "count", "I");
211: mv.visitInsn(ICONST_1);
212: mv.visitInsn(ISUB);
213: mv
214: .visitFieldInsn(PUTFIELD, "java/util/Hashtable",
215: "count", "I");
216: mv.visitVarInsn(ALOAD, 5);
217: mv.visitInsn(ARETURN);
218: mv.visitLabel(l7);
219: mv.visitVarInsn(ALOAD, 5);
220: mv.visitVarInsn(ASTORE, 6);
221: mv.visitVarInsn(ALOAD, 5);
222: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry",
223: "next", "Ljava/util/Hashtable$Entry;");
224: mv.visitVarInsn(ASTORE, 5);
225: mv.visitJumpInsn(GOTO, l4);
226: mv.visitLabel(l5);
227: mv.visitInsn(ACONST_NULL);
228: mv.visitInsn(ARETURN);
229: mv.visitMaxs(0, 0);
230: mv.visitEnd();
231:
232: return mv;
233: }
234:
235: private static MethodNode __tc_removeEntryForKeyMethodIBM() {
236: MethodNode mv = new MethodNode(
237: ACC_PROTECTED + ACC_SYNCHRONIZED,
238: "__tc_removeEntryForKey",
239: "(Ljava/lang/Object;)Ljava/util/Map$Entry;", null, null);
240: mv.visitCode();
241: mv.visitVarInsn(ALOAD, 1);
242: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
243: "hashCode", "()I");
244: mv.visitVarInsn(ISTORE, 2);
245: mv.visitVarInsn(ILOAD, 2);
246: mv.visitLdcInsn(new Integer(2147483647));
247: mv.visitInsn(IAND);
248: mv.visitVarInsn(ALOAD, 0);
249: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable",
250: "elementData", "[Ljava/util/Hashtable$Entry;");
251: mv.visitInsn(ARRAYLENGTH);
252: mv.visitInsn(IREM);
253: mv.visitVarInsn(ISTORE, 3);
254: mv.visitInsn(ACONST_NULL);
255: mv.visitVarInsn(ASTORE, 4);
256: mv.visitVarInsn(ALOAD, 0);
257: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable",
258: "elementData", "[Ljava/util/Hashtable$Entry;");
259: mv.visitVarInsn(ILOAD, 3);
260: mv.visitInsn(AALOAD);
261: mv.visitVarInsn(ASTORE, 5);
262: Label l4 = new Label();
263: mv.visitLabel(l4);
264: mv.visitVarInsn(ALOAD, 5);
265: Label l5 = new Label();
266: mv.visitJumpInsn(IFNULL, l5);
267: mv.visitVarInsn(ALOAD, 5);
268: mv.visitVarInsn(ALOAD, 1);
269: mv.visitVarInsn(ILOAD, 2);
270: mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Hashtable$Entry",
271: "equalsKey", "(Ljava/lang/Object;I)Z");
272: mv.visitJumpInsn(IFNE, l5);
273: mv.visitVarInsn(ALOAD, 5);
274: mv.visitVarInsn(ASTORE, 4);
275: mv.visitVarInsn(ALOAD, 5);
276: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry",
277: "next", "Ljava/util/Hashtable$Entry;");
278: mv.visitVarInsn(ASTORE, 5);
279: mv.visitJumpInsn(GOTO, l4);
280: mv.visitLabel(l5);
281: mv.visitVarInsn(ALOAD, 5);
282: Label l9 = new Label();
283: mv.visitJumpInsn(IFNULL, l9);
284: mv.visitVarInsn(ALOAD, 0);
285: mv.visitInsn(DUP);
286: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable", "modCount",
287: "I");
288: mv.visitInsn(ICONST_1);
289: mv.visitInsn(IADD);
290: mv.visitFieldInsn(PUTFIELD, "java/util/Hashtable", "modCount",
291: "I");
292: mv.visitVarInsn(ALOAD, 4);
293: Label l12 = new Label();
294: mv.visitJumpInsn(IFNONNULL, l12);
295: mv.visitVarInsn(ALOAD, 0);
296: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable",
297: "elementData", "[Ljava/util/Hashtable$Entry;");
298: mv.visitVarInsn(ILOAD, 3);
299: mv.visitVarInsn(ALOAD, 5);
300: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry",
301: "next", "Ljava/util/Hashtable$Entry;");
302: mv.visitInsn(AASTORE);
303: Label l13 = new Label();
304: mv.visitJumpInsn(GOTO, l13);
305: mv.visitLabel(l12);
306: mv.visitVarInsn(ALOAD, 4);
307: mv.visitVarInsn(ALOAD, 5);
308: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable$Entry",
309: "next", "Ljava/util/Hashtable$Entry;");
310: mv.visitFieldInsn(PUTFIELD, "java/util/Hashtable$Entry",
311: "next", "Ljava/util/Hashtable$Entry;");
312: mv.visitLabel(l13);
313: mv.visitVarInsn(ALOAD, 0);
314: mv.visitInsn(DUP);
315: mv.visitFieldInsn(GETFIELD, "java/util/Hashtable",
316: "elementCount", "I");
317: mv.visitInsn(ICONST_1);
318: mv.visitInsn(ISUB);
319: mv.visitFieldInsn(PUTFIELD, "java/util/Hashtable",
320: "elementCount", "I");
321: mv.visitVarInsn(ALOAD, 5);
322: mv.visitInsn(ARETURN);
323: mv.visitLabel(l9);
324: mv.visitInsn(ACONST_NULL);
325: mv.visitInsn(ARETURN);
326: mv.visitMaxs(0, 0);
327: mv.visitEnd();
328: return mv;
329: }
330:
331: public static MethodNode[] getMethods() {
332: return new MethodNode[] {
333: __tc_getEntryMethod(),
334: Vm.isIBM() ? __tc_removeEntryForKeyMethodIBM()
335: : __tc_removeEntryForKeyMethodSun() };
336: }
337:
338: }
|