KickJava   Java API By Example, From Geeks To Geeks.

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


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.MethodVisitor;
8 import com.tc.asm.Opcodes;
9 import com.tc.asm.Type;
10 import com.tc.object.LiteralValues;
11 import com.tc.object.ObjectID;
12 import com.tc.util.Assert;
13
14 import java.lang.reflect.Modifier JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Arrays JavaDoc;
17 import java.util.Collections JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Set JavaDoc;
21
22 public class ByteCodeUtil implements Opcodes {
23   private static final String JavaDoc AUTOLOCK_PREFIX = "@";
24   private static final String JavaDoc NAMED_LOCK_PREFIX = "^";
25   private static final String JavaDoc LITERAL_LOCK_PREFIX = "#";
26
27   public static final String JavaDoc TC_FIELD_PREFIX = "$__tc_";
28   public static final String JavaDoc TC_METHOD_PREFIX = "__tc_";
29   public static final String JavaDoc METHOD_RENAME_PREFIX = TC_METHOD_PREFIX + "wrapped_";
30   public static final String JavaDoc DMI_METHOD_RENAME_PREFIX = TC_METHOD_PREFIX + "dmi_";
31
32   public static final String JavaDoc VALUES_GETTER = TC_METHOD_PREFIX + "getallfields";
33   public static final String JavaDoc VALUES_GETTER_DESCRIPTION = "(Ljava/util/Map;)V";
34   public static final String JavaDoc VALUES_SETTER = TC_METHOD_PREFIX + "setfield";
35   public static final String JavaDoc VALUES_SETTER_DESCRIPTION = "(Ljava/lang/String;Ljava/lang/Object;)V";
36   public static final String JavaDoc MANAGED_VALUES_GETTER = TC_METHOD_PREFIX + "getmanagedfield";
37   public static final String JavaDoc MANAGED_VALUES_GETTER_DESCRIPTION = "(Ljava/lang/String;)Ljava/lang/Object;";
38   public static final String JavaDoc MANAGED_VALUES_SETTER = TC_METHOD_PREFIX + "setmanagedfield";
39
40   private static final LiteralValues LITERAL_VALUES = new LiteralValues();
41
42   public static String JavaDoc[] addInterfaces(String JavaDoc[] existing, String JavaDoc[] toAdd) {
43     if (existing == null) { return toAdd; }
44     if (toAdd == null) { return existing; }
45
46     List JavaDoc newList = new ArrayList JavaDoc(Arrays.asList(existing));
47     Set JavaDoc existingAsSet = Collections.unmodifiableSet(new HashSet JavaDoc(newList));
48
49     for (int i = 0, n = toAdd.length; i < n; i++) {
50       if (!existingAsSet.contains(toAdd[i])) {
51         newList.add(toAdd[i]);
52       }
53     }
54
55     return (String JavaDoc[]) newList.toArray(new String JavaDoc[newList.size()]);
56   }
57
58   public static boolean isPrimitive(Type t) {
59     final int sort = t.getSort();
60     switch (sort) {
61       case Type.BOOLEAN:
62       case Type.BYTE:
63       case Type.CHAR:
64       case Type.DOUBLE:
65       case Type.FLOAT:
66       case Type.INT:
67       case Type.LONG:
68       case Type.SHORT:
69         return true;
70       default:
71         return false;
72     }
73
74     // unreachable
75
}
76
77   public static String JavaDoc sortToWrapperName(int sort) {
78     switch (sort) {
79       case Type.BOOLEAN: // '\001'
80
return "java/lang/Boolean";
81
82       case Type.CHAR: // '\002'
83
return "java/lang/Character";
84
85       case Type.BYTE: // '\003'
86
return "java/lang/Byte";
87
88       case Type.SHORT: // '\004'
89
return "java/lang/Short";
90
91       case Type.INT: // '\005'
92
return "java/lang/Integer";
93
94       case Type.FLOAT: // '\006'
95
return "java/lang/Float";
96
97       case Type.LONG: // '\007'
98
return "java/lang/Long";
99
100       case Type.DOUBLE: // '\b'
101
return "java/lang/Double";
102       default:
103         throw new AssertionError JavaDoc();
104     }
105
106   }
107
108   public static String JavaDoc codeToName(String JavaDoc typeCode) {
109     if ((typeCode == null) || (typeCode.length() != 1)) { throw new IllegalArgumentException JavaDoc("invalid type code: "
110                                                                                              + typeCode); }
111     char code = typeCode.charAt(0);
112
113     switch (code) {
114       case 'B': {
115         return "byte";
116       }
117       case 'C': {
118         return "char";
119       }
120       case 'D': {
121         return "double";
122       }
123       case 'F': {
124         return "float";
125       }
126       case 'I': {
127         return "int";
128       }
129       case 'J': {
130         return "long";
131       }
132       case 'S': {
133         return "short";
134       }
135       case 'Z': {
136         return "boolean";
137       }
138       default: {
139         throw new IllegalArgumentException JavaDoc("unknown code: " + code);
140       }
141
142         // unreachable
143
}
144   }
145
146   public static boolean isAutolockName(String JavaDoc lockName) {
147     return lockName == null ? false : lockName.startsWith(AUTOLOCK_PREFIX);
148   }
149
150   public static long objectIdFromLockName(String JavaDoc lockName) {
151     if (lockName == null || (!lockName.startsWith(AUTOLOCK_PREFIX))) {
152       // make formatter sane
153
throw new IllegalArgumentException JavaDoc("not an autolock name: " + lockName);
154     }
155     return Long.valueOf(lockName.substring(AUTOLOCK_PREFIX.length())).longValue();
156
157   }
158
159   public static boolean isSynthetic(String JavaDoc fieldName) {
160     return fieldName.indexOf("$") >= 0;
161   }
162
163   public static boolean isTCSynthetic(String JavaDoc fieldName) {
164     return fieldName.startsWith(TC_FIELD_PREFIX) || isParent(fieldName);
165   }
166
167   public static boolean isSynthetic(int access) {
168     return (ACC_SYNTHETIC & access) > 0;
169   }
170
171   public static boolean isParent(String JavaDoc fieldName) {
172     return fieldName.matches("^this\\$\\d+$");
173
174     // return SERIALIZATION_UTIL.isParent(fieldName);
175
}
176
177   public static void pushThis(MethodVisitor c) {
178     c.visitVarInsn(ALOAD, 0);
179   }
180
181   public static void pushInstanceVariable(MethodVisitor c, String JavaDoc className, String JavaDoc fieldName, String JavaDoc description) {
182     c.visitFieldInsn(GETFIELD, className, fieldName, description);
183   }
184
185   public static void createParametersToArrayByteCode(MethodVisitor c, Type[] parameters) {
186     createParametersToArrayByteCode(c, parameters, 1);
187   }
188
189   public static void createParametersToArrayByteCode(MethodVisitor c, Type[] parameters, int offset) {
190     c.visitLdcInsn(new Integer JavaDoc(parameters.length));
191     c.visitTypeInsn(ANEWARRAY, "java/lang/Object");
192     for (int i = 0; i < parameters.length; i++) {
193       c.visitInsn(DUP);
194       c.visitLdcInsn(new Integer JavaDoc(i));
195       addTypeSpecificParameterLoad(c, parameters[i], offset);
196       c.visitInsn(AASTORE);
197       offset += parameters[i].getSize();
198     }
199   }
200
201   public static void addTypeSpecificParameterLoad(MethodVisitor c, Type type, int offset) {
202
203     switch (type.getSort()) {
204       case Type.ARRAY:
205       case Type.OBJECT:
206         c.visitVarInsn(type.getOpcode(ILOAD), offset);
207         break;
208       case Type.BOOLEAN:
209         c.visitTypeInsn(NEW, "java/lang/Boolean");
210         c.visitInsn(DUP);
211         c.visitVarInsn(type.getOpcode(ILOAD), offset);
212         c.visitMethodInsn(INVOKESPECIAL, "java/lang/Boolean", "<init>", "(Z)V");
213         break;
214       case Type.BYTE:
215         c.visitTypeInsn(NEW, "java/lang/Byte");
216         c.visitInsn(DUP);
217         c.visitVarInsn(type.getOpcode(ILOAD), offset);
218         c.visitMethodInsn(INVOKESPECIAL, "java/lang/Byte", "<init>", "(B)V");
219         break;
220       case Type.CHAR:
221         c.visitTypeInsn(NEW, "java/lang/Character");
222         c.visitInsn(DUP);
223         c.visitVarInsn(type.getOpcode(ILOAD), offset);
224         c.visitMethodInsn(INVOKESPECIAL, "java/lang/Character", "<init>", "(C)V");
225         break;
226       case Type.DOUBLE:
227         c.visitTypeInsn(NEW, "java/lang/Double");
228         c.visitInsn(DUP);
229         c.visitVarInsn(type.getOpcode(ILOAD), offset);
230         c.visitMethodInsn(INVOKESPECIAL, "java/lang/Double", "<init>", "(D)V");
231         break;
232       case Type.FLOAT:
233         c.visitTypeInsn(NEW, "java/lang/Float");
234         c.visitInsn(DUP);
235         c.visitVarInsn(type.getOpcode(ILOAD), offset);
236         c.visitMethodInsn(INVOKESPECIAL, "java/lang/Float", "<init>", "(F)V");
237         break;
238       case Type.INT:
239         c.visitTypeInsn(NEW, "java/lang/Integer");
240         c.visitInsn(DUP);
241         c.visitVarInsn(type.getOpcode(ILOAD), offset);
242         c.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer", "<init>", "(I)V");
243         break;
244       case Type.LONG:
245         c.visitTypeInsn(NEW, "java/lang/Long");
246         c.visitInsn(DUP);
247         c.visitVarInsn(type.getOpcode(ILOAD), offset);
248         c.visitMethodInsn(INVOKESPECIAL, "java/lang/Long", "<init>", "(J)V");
249         break;
250       case Type.SHORT:
251         c.visitTypeInsn(NEW, "java/lang/Short");
252         c.visitInsn(DUP);
253         c.visitVarInsn(type.getOpcode(ILOAD), offset);
254         c.visitMethodInsn(INVOKESPECIAL, "java/lang/Short", "<init>", "(S)V");
255         break;
256       default:
257         throw new AssertionError JavaDoc("can't happen:" + type);
258     }
259   }
260
261   public static void pushMethodArguments(int callingMethodModifier, String JavaDoc desc, MethodVisitor c) {
262     int localVariableOffset = getLocalVariableOffset(callingMethodModifier);
263     Type[] args = Type.getArgumentTypes(desc);
264
265     int pos = 0;
266     for (int i = 0; i < args.length; i++) {
267       c.visitVarInsn(args[i].getOpcode(ILOAD), pos + localVariableOffset);
268       pos += args[i].getSize();
269     }
270   }
271
272   public static int getFirstLocalVariableOffset(int callingMethodModifier, String JavaDoc desc) {
273     int localVariableOffset = getLocalVariableOffset(callingMethodModifier);
274     Type[] args = Type.getArgumentTypes(desc);
275     for (int i = 0; i < args.length; i++) {
276       localVariableOffset += args[i].getSize();
277     }
278     return localVariableOffset;
279   }
280
281   public static void prepareStackForMethodCall(int callingMethodModifier, String JavaDoc desc, MethodVisitor c) {
282     if (!Modifier.isStatic(callingMethodModifier)) {
283       pushThis(c);
284     }
285     pushMethodArguments(callingMethodModifier, desc, c);
286   }
287
288   /**
289    * Returns 0 if the method is static. 1 If the method is not.
290    */

291   public static int getLocalVariableOffset(int methodModifier) {
292     return Modifier.isStatic(methodModifier) ? 0 : 1;
293   }
294
295   public static String JavaDoc generateVolatileLockName(ObjectID id, String JavaDoc fieldName) {
296     Assert.assertNotNull(id);
297     return AUTOLOCK_PREFIX + id.toLong() + fieldName;
298   }
299
300   public static String JavaDoc generateAutolockName(ObjectID id) {
301     Assert.assertNotNull(id);
302     return generateAutolockName(id.toLong());
303   }
304
305   public static String JavaDoc generateNamedLockName(Object JavaDoc obj) {
306     Assert.assertNotNull(obj);
307     return NAMED_LOCK_PREFIX + obj;
308   }
309
310   public static String JavaDoc generateLiteralLockName(Object JavaDoc obj) {
311     Assert.assertNotNull(obj);
312     return LITERAL_VALUES.valueFor(obj) + LITERAL_LOCK_PREFIX + obj;
313   }
314
315   private static String JavaDoc generateAutolockName(long objectId) {
316     return AUTOLOCK_PREFIX + objectId;
317   }
318
319   public static String JavaDoc stripGeneratedLockHeader(String JavaDoc lockName) {
320     int index = lockName.indexOf(LITERAL_LOCK_PREFIX);
321     index = index < 0 ? 1 : index;
322     return lockName.substring(index);
323   }
324
325   public static String JavaDoc sortToPrimitiveMethodName(int sort) {
326     switch (sort) {
327       case Type.BOOLEAN: // '\001'
328
return "booleanValue";
329
330       case Type.CHAR: // '\002'
331
return "charValue";
332
333       case Type.BYTE: // '\003'
334
return "byteValue";
335
336       case Type.SHORT: // '\004'
337
return "shortValue";
338
339       case Type.INT: // '\005'
340
return "intValue";
341
342       case Type.FLOAT: // '\006'
343
return "floatValue";
344
345       case Type.LONG: // '\007'
346
return "longValue";
347
348       case Type.DOUBLE: // '\b'
349
return "doubleValue";
350       default:
351         throw new AssertionError JavaDoc();
352     }
353   }
354
355   public static String JavaDoc methodDescriptionToReturnType(String JavaDoc desc) {
356     Type type = Type.getReturnType(desc);
357     return type.getClassName();
358   }
359
360   public static String JavaDoc methodDescriptionToMethodArgument(String JavaDoc desc) {
361     Type[] types = Type.getArgumentTypes(desc);
362     StringBuffer JavaDoc sb = new StringBuffer JavaDoc("(");
363     for (int i = 0; i < types.length; i++) {
364       sb.append(types[i].getClassName());
365       if (i < types.length - 1) {
366         sb.append(",");
367       }
368     }
369     sb.append(")");
370     return sb.toString();
371   }
372
373   public static String JavaDoc fieldGetterMethod(String JavaDoc fieldName) {
374     return TC_METHOD_PREFIX + "get" + fieldName;
375   }
376
377   public static String JavaDoc fieldSetterMethod(String JavaDoc fieldName) {
378     return TC_METHOD_PREFIX + "set" + fieldName;
379   }
380
381 }
Popular Tags