001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package EDU.purdue.cs.bloat.benchmark;
022:
023: import java.io.*;
024: import java.util.*;
025:
026: import EDU.purdue.cs.bloat.context.*;
027: import EDU.purdue.cs.bloat.editor.*;
028: import EDU.purdue.cs.bloat.file.*;
029: import EDU.purdue.cs.bloat.reflect.*;
030:
031: public class CounterDecorate implements Opcode {
032: private static final String COUNTER_TYPE = "I";
033:
034: private static final String COUNTER_RCNAME = "rcCount";
035:
036: private static final String COUNTER_AUNAME = "auCount";
037:
038: private static final String COUNTER_SUNAME = "suCount";
039:
040: private static final String COUNTER_MAIN = "LEDU/purdue/cs/bloat/benchmark/Counter;";
041:
042: private static int VERBOSE = 0;
043:
044: private static boolean FORCE = false;
045:
046: private static boolean CLOSURE = false;
047:
048: private static final List SKIP = new ArrayList();
049:
050: private static final List ONLY = new ArrayList();
051:
052: public static void main(final String[] args) {
053: final ClassFileLoader loader = new ClassFileLoader();
054: List classes = new ArrayList();
055: boolean gotdir = false;
056:
057: for (int i = 0; i < args.length; i++) {
058: if (args[i].equals("-v") || args[i].equals("-verbose")) {
059: CounterDecorate.VERBOSE++;
060: } else if (args[i].equals("-help")) {
061: CounterDecorate.usage();
062: } else if (args[i].equals("-classpath")) {
063: if (++i >= args.length) {
064: CounterDecorate.usage();
065: }
066:
067: final String classpath = args[i];
068: loader.setClassPath(classpath);
069: } else if (args[i].equals("-skip")) {
070: if (++i >= args.length) {
071: CounterDecorate.usage();
072: }
073:
074: final String pkg = args[i].replace('.', '/');
075: CounterDecorate.SKIP.add(pkg);
076: } else if (args[i].equals("-only")) {
077: if (++i >= args.length) {
078: CounterDecorate.usage();
079: }
080:
081: final String pkg = args[i].replace('.', '/');
082: CounterDecorate.ONLY.add(pkg);
083: } else if (args[i].equals("-closure")) {
084: CounterDecorate.CLOSURE = true;
085: } else if (args[i].equals("-relax-loading")) {
086: ClassHierarchy.RELAX = true;
087: } else if (args[i].equals("-f")) {
088: CounterDecorate.FORCE = true;
089: } else if (args[i].startsWith("-")) {
090: CounterDecorate.usage();
091: } else if (i == args.length - 1) {
092: final File f = new File(args[i]);
093:
094: if (f.exists() && !f.isDirectory()) {
095: System.err.println("No such directory: "
096: + f.getPath());
097: System.exit(2);
098: }
099:
100: loader.setOutputDir(f);
101: gotdir = true;
102: } else {
103: classes.add(args[i]);
104: }
105: }
106:
107: if (!gotdir) {
108: CounterDecorate.usage();
109: }
110:
111: if (classes.size() == 0) {
112: CounterDecorate.usage();
113: }
114:
115: if (CounterDecorate.VERBOSE > 3) {
116: ClassFileLoader.DEBUG = true;
117: ClassEditor.DEBUG = true;
118: }
119:
120: boolean errors = false;
121:
122: final Iterator iter = classes.iterator();
123:
124: while (iter.hasNext()) {
125: final String name = (String) iter.next();
126:
127: try {
128: loader.loadClass(name);
129: } catch (final ClassNotFoundException ex) {
130: System.err.println("Couldn't find class: "
131: + ex.getMessage());
132: errors = true;
133: }
134: }
135:
136: if (errors) {
137: System.exit(1);
138: }
139:
140: final BloatContext context = new CachingBloatContext(loader,
141: classes, CounterDecorate.CLOSURE);
142:
143: if (!CounterDecorate.CLOSURE) {
144: final Iterator e = classes.iterator();
145:
146: while (e.hasNext()) {
147: final String name = (String) e.next();
148: try {
149: final ClassInfo info = loader.loadClass(name);
150: CounterDecorate.decorateClass(context, info);
151: } catch (final ClassNotFoundException ex) {
152: System.err.println("Couldn't find class: "
153: + ex.getMessage());
154: System.exit(1);
155: }
156: }
157: } else {
158: classes = null;
159:
160: final ClassHierarchy hier = context.getHierarchy();
161:
162: final Iterator e = hier.classes().iterator();
163:
164: while (e.hasNext()) {
165: final Type t = (Type) e.next();
166:
167: if (t.isObject()) {
168: try {
169: final ClassInfo info = loader.loadClass(t
170: .className());
171: CounterDecorate.decorateClass(context, info);
172: } catch (final ClassNotFoundException ex) {
173: System.err.println("Couldn't find class: "
174: + ex.getMessage());
175: System.exit(1);
176: }
177: }
178: }
179: }
180: }
181:
182: private static void usage() {
183: System.err
184: .println("Usage: java EDU.purdue.cs.bloat.count.Main "
185: + "\n [-options] classes output_dir"
186: + "\n"
187: + "\nwhere options include:"
188: + "\n -help print out this message"
189: + "\n -v -verbose turn on verbose mode "
190: + "(can be given multiple times)"
191: + "\n -classpath <directories separated by colons>"
192: + "\n list directories in which to look for classes"
193: + "\n -f decorate files even if up-to-date"
194: + "\n -closure recursively decorate referenced classes"
195: + "\n -relax-loading don't report errors if a class is not found"
196: + "\n -skip <class|package.*>"
197: + "\n skip the given class or package"
198: + "\n (this option can be given more than once)"
199: + "\n -only <class|package.*>"
200: + "\n skip all but the given class or package"
201: + "\n (this option can be given more than once)");
202: System.exit(0);
203: }
204:
205: private static void decorateClass(final EditorContext editor,
206: final ClassInfo info) {
207: final ClassFile classFile = (ClassFile) info;
208:
209: if (!CounterDecorate.FORCE) {
210: final File source = classFile.file();
211: final File target = classFile.outputFile();
212:
213: if ((source != null) && (target != null) && source.exists()
214: && target.exists()
215: && (source.lastModified() < target.lastModified())) {
216:
217: if (CounterDecorate.VERBOSE > 1) {
218: System.out.println(classFile.name()
219: + " is up to date");
220: }
221:
222: return;
223: }
224: }
225:
226: if (CounterDecorate.VERBOSE > 2) {
227: classFile.print(System.out);
228: }
229:
230: final ClassEditor c = editor.editClass(info);
231:
232: boolean skip = false;
233:
234: final String name = c.type().className();
235: final String qual = c.type().qualifier() + "/*";
236:
237: // Edit only classes explicitly mentioned.
238: if (CounterDecorate.ONLY.size() > 0) {
239: skip = true;
240:
241: // Only edit classes we explicitly don't name.
242: for (int i = 0; i < CounterDecorate.ONLY.size(); i++) {
243: final String pkg = (String) CounterDecorate.ONLY.get(i);
244:
245: if (name.equals(pkg) || qual.equals(pkg)) {
246: skip = false;
247: break;
248: }
249: }
250: }
251:
252: // Don't edit classes we explicitly skip.
253: if (!skip) {
254: for (int i = 0; i < CounterDecorate.SKIP.size(); i++) {
255: final String pkg = (String) CounterDecorate.SKIP.get(i);
256:
257: if (name.equals(pkg) || qual.equals(pkg)) {
258: skip = true;
259: break;
260: }
261: }
262: }
263:
264: if (skip) {
265: if (CounterDecorate.VERBOSE > 0) {
266: System.out.println("Skipping " + c.type().className());
267: }
268:
269: editor.release(info);
270: return;
271: }
272:
273: if (CounterDecorate.VERBOSE > 0) {
274: System.out.println("Decorating class "
275: + c.type().className());
276: }
277:
278: if (CounterDecorate.VERBOSE > 2) {
279: ((ClassFile) info).print(System.out);
280: }
281:
282: final MethodInfo[] methods = c.methods();
283:
284: for (int j = 0; j < methods.length; j++) {
285: MethodEditor m;
286:
287: try {
288: m = editor.editMethod(methods[j]);
289: } catch (final ClassFormatException ex) {
290: System.err.println(ex.getMessage());
291: continue;
292: }
293:
294: CounterDecorate.transform(m);
295: editor.commit(methods[j]);
296: }
297:
298: editor.commit(info);
299: }
300:
301: private static void transform(final MethodEditor method) {
302: if (CounterDecorate.VERBOSE > 1) {
303: System.out.println("Decorating method " + method);
304: }
305:
306: final MemberRef rcfield = new MemberRef(Type
307: .getType(CounterDecorate.COUNTER_MAIN),
308: new NameAndType(CounterDecorate.COUNTER_RCNAME, Type
309: .getType(CounterDecorate.COUNTER_TYPE)));
310: final MemberRef aufield = new MemberRef(Type
311: .getType(CounterDecorate.COUNTER_MAIN),
312: new NameAndType(CounterDecorate.COUNTER_AUNAME, Type
313: .getType(CounterDecorate.COUNTER_TYPE)));
314: final MemberRef sufield = new MemberRef(Type
315: .getType(CounterDecorate.COUNTER_MAIN),
316: new NameAndType(CounterDecorate.COUNTER_SUNAME, Type
317: .getType(CounterDecorate.COUNTER_TYPE)));
318:
319: final ListIterator iter = method.code().listIterator();
320:
321: while (iter.hasNext()) {
322: final Object ce = iter.next();
323:
324: if (CounterDecorate.VERBOSE > 2) {
325: System.out.println("Examining " + ce);
326: }
327:
328: if (ce instanceof Instruction) {
329: final Instruction inst = (Instruction) ce;
330:
331: if (inst.opcodeClass() == Opcode.opcx_aupdate) {
332: iter.remove();
333: iter.add(new Instruction(Opcode.opcx_getstatic,
334: aufield));
335: iter.next();
336: iter.add(new Instruction(Opcode.opcx_ldc,
337: new Integer(1)));
338: iter.next();
339: iter.add(new Instruction(Opcode.opcx_iadd));
340: iter.next();
341: iter.add(new Instruction(Opcode.opcx_putstatic,
342: aufield));
343: iter.next();
344: }
345: if (inst.opcodeClass() == Opcode.opcx_supdate) {
346: iter.remove();
347: iter.add(new Instruction(Opcode.opcx_getstatic,
348: sufield));
349: iter.next();
350: iter.add(new Instruction(Opcode.opcx_ldc,
351: new Integer(1)));
352: iter.next();
353: iter.add(new Instruction(Opcode.opcx_iadd));
354: iter.next();
355: iter.add(new Instruction(Opcode.opcx_putstatic,
356: sufield));
357: iter.next();
358: } else if (inst.opcodeClass() == Opcode.opcx_rc) {
359: iter.remove();
360: iter.add(new Instruction(Opcode.opcx_getstatic,
361: rcfield));
362: iter.next();
363: iter.add(new Instruction(Opcode.opcx_ldc,
364: new Integer(1)));
365: iter.next();
366: iter.add(new Instruction(Opcode.opcx_iadd));
367: iter.next();
368: iter.add(new Instruction(Opcode.opcx_putstatic,
369: rcfield));
370: iter.next();
371: }
372: }
373: }
374: }
375: }
|