KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jarg > BytecodeOptimizer


1 /* ====================================================================
2  * Copyright (c) 2002, Hidetoshi Ohuchi <hchacha@users.sourceforge.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the hchacha nor the names of its contributors
17  * may be used to endorse or promote products derived from this
18  * software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  * ====================================================================
33  */

34 package jarg;
35
36 import java.util.*;
37 import org.apache.bcel.classfile.*;
38 import org.apache.bcel.generic.*;
39 import org.apache.bcel.Constants;
40
41 /**
42  * The class for optimizing the byte-code of the java class.
43  *
44  * @version $Id: BytecodeOptimizer.java,v 1.8 2003/01/28 17:30:52 hchacha Exp $
45  * @author Hidetoshi Ohuchi &lt;hchacha@users.sourceforge.net&gt;
46  */

47 class BytecodeOptimizer {
48    private Jarg app;
49    private PackageHandler pkgh;
50    private DataflowOptimizer dfopt;
51
52    BytecodeOptimizer(Jarg app, PackageHandler pkgh) {
53       this.app = app;
54       this.pkgh = pkgh;
55       this.dfopt = new DataflowOptimizer(app);
56    }
57
58    JavaClass optimizeBytecodeOfJavaClass(JavaClass jcls) {
59       ClassGen cg = new ClassGen(jcls);
60       String JavaDoc clsnm = cg.getClassName();
61       ConstantPoolGen cpg = cg.getConstantPool();
62       Method[] ms = cg.getMethods();
63       for (int i=0; i<ms.length; i++) {
64          Method m = ms[i];
65          Code code = m.getCode();
66          if (code != null) {
67             MethodGen mg = new MethodGen(m, clsnm, cpg);
68             // optimize byte code
69
optimizeCode(mg);
70             m = mg.getMethod();
71             cg.setMethodAt(m, i);
72          }
73       }
74       return cg.getJavaClass();
75    }
76
77    private void optimizeCode(MethodGen mg) {
78       for (;;) {
79          int counter = 0;
80
81          //
82
counter += dfopt.optimizingByDataflow(mg);
83
84          // replacing IFxx/GOTO --> IFyy
85
counter += replaceIFxxGOTO(mg);
86
87          // replacing IFxx>>next --> POP
88
counter += replaceIFxxnext(mg);
89
90          // replacing GOTO>>RETURN --> RETURN
91
counter += replaceGOTORETURN(mg);
92
93          // redirecting IFxx>>GOTO>>yyyy --> IFxx>>yyyy
94
counter += redirectIFxxGOTO(mg);
95
96          // replacing IFxx/RETURN --> IFyy
97
counter += replaceIFxxRETURN(mg);
98
99 // buggy
100
// // replacing xSTOREn/GOTO --> GOTO
101
// counter += replaceSTOREGOTO(mg);
102

103          // replacing xSTOREn/xLOADm/xLOADn/IF_xCMPxx --> xSTOREn/xLOADn/xLOADm/IF_xCMPxx
104
counter += replaceSTORELOADLOADIFxCMPxx(mg);
105
106          // replacing xSTOREn/xLOADn --> DUP/xSTOREn
107
counter += replaceSTORELOAD(mg);
108
109          // replacing xLOADn/xLOADn --> xLOADn/DUP
110
counter += replaceLOADLOAD(mg);
111
112          // replacing xxxx/IMUL --> ICONST_n/ISHL
113
counter += replaceIMULISHL(mg);
114
115          // analize local slot
116
counter += analizeLocalSlot(mg);
117
118          // remove XXX/POP (DUP/POP,CONST/POP,LOAD/POP)
119
counter += removeXXXPOP(mg);
120
121          // remove NOP
122
counter += removeNOP(mg);
123
124          // remove GOTO next
125
counter += removeGOTOnext(mg);
126
127          // remove double RETURN
128
counter += removeRETURNs(mg);
129
130          // remove double GOTO
131
counter += removeGOTOs(mg);
132
133          // remove unused GOTO
134
counter += removeUnusedGOTO(mg);
135
136          if (counter == 0) {
137             break;
138          }
139       }
140    }
141
142    // replacing GOTO>>RETURN --> RETURN
143
//
144
// goto Label1 return
145
// ... ...
146
// Label1: return
147
private int replaceGOTORETURN(MethodGen mg) {
148       InstructionList il = mg.getInstructionList();
149       int count = 0;
150
151       for (InstructionHandle first = il.getStart(); first != null;) {
152          Instruction ins1 = first.getInstruction();
153          if (ins1 instanceof GotoInstruction) {
154             InstructionHandle gotoTarget = ((GotoInstruction)ins1).getTarget();
155             Instruction ins2 = gotoTarget.getInstruction();
156             if (ins2 instanceof ReturnInstruction) {
157                InstructionHandle next = first.getNext();
158                count ++;
159                InstructionHandle newIh = il.insert(first, ins2);
160                if (first.hasTargeters()) {
161                   updateTargets(first, newIh, newIh.getPrev());
162                }
163                deleteInstruction(il, first, first.getNext());
164                first = next;
165                continue;
166             }
167          }
168          first = first.getNext();
169       }
170
171       if (count > 0 && app.isVerboseBCO) {
172          System.out.println("Replaced " + count + " GOTO>>RETURN --> RETURN : " + mg.getClassName() + '#' + mg.getName());
173       }
174       return count;
175    }
176
177    // redirecting IFxx>>GOTO>>yyyy --> IFxx>>yyyy
178
//
179
// ifeq Label1 ifeq Label2
180
// ... ...
181
// Label1: goto Label2 Label1: goto Label2
182
// ... ...
183
// Label2: xxxx Label2: xxxx
184
private int redirectIFxxGOTO(MethodGen mg) {
185       InstructionList il = mg.getInstructionList();
186       int count = 0;
187
188       for (InstructionHandle first = il.getStart(); first != null;) {
189          Instruction ins1 = first.getInstruction();
190          if (ins1 instanceof IfInstruction) {
191             InstructionHandle ifTarget = ((IfInstruction)ins1).getTarget();
192             Instruction ins2 = ifTarget.getInstruction();
193             if (ins2 instanceof GotoInstruction) {
194                InstructionHandle gotoTarget = ((GotoInstruction)ins2).getTarget();
195                count ++;
196                ((IfInstruction)ins1).setTarget(gotoTarget);
197             }
198          }
199          first = first.getNext();
200       }
201
202       if (count > 0 && app.isVerboseBCO) {
203          System.out.println("Replaced " + count + " IFxx>>GOTO>>yyyy --> IFxx>>yyyy : " + mg.getClassName() + '#' + mg.getName());
204       }
205       return count;
206    }
207
208    // replacing IFxx/RETURN --> IFyy
209
//
210
// ifeq Label0 ifne Label2
211
// ... ...
212
// ifeq Label1 ifne Label2
213
// Label0 return Label1: xxxx
214
// Label1: xxxx ...
215
// ...
216
// Label2: return Label2: return
217
private int replaceIFxxRETURN(MethodGen mg) {
218       InstructionList il = mg.getInstructionList();
219       int count = 0;
220
221       for (InstructionHandle first = il.getStart(); first != null;) {
222          Instruction ins1 = first.getInstruction();
223          if (ins1 instanceof IfInstruction) {
224             InstructionHandle second = first.getNext();
225             Instruction ins2 = second.getInstruction();
226             if (ins2 instanceof RETURN) {
227                InstructionHandle ifTarget = ((IfInstruction)ins1).getTarget();
228                InstructionHandle next = second.getNext();
229                if (ifTarget == next) {
230 // if (ins1 instanceof IFEQ
231
// || ins1 instanceof IFNE
232
// ) {
233
{
234                      InstructionHandle newIfTarget = null;
235                      for (InstructionHandle last = il.getEnd(); last != null; last = last.getPrev()) {
236                         Instruction lastIns = last.getInstruction();
237                         if (lastIns instanceof RETURN && last != second) {
238                            newIfTarget = last;
239                            break;
240                         }
241                      }
242                      if (newIfTarget != null) {
243                         count ++;
244                         BranchInstruction newIns = ((IfInstruction)ins1).negate();
245                         newIns.setTarget(newIfTarget);
246                         InstructionHandle newIh = il.insert(first, newIns);
247                         if (first.hasTargeters()) {
248                            updateTargets(first, newIh, newIh.getPrev());
249                         }
250                         if (second.hasTargeters()) {
251                            updateTargets(second, newIfTarget, newIfTarget.getPrev());
252                         }
253                         deleteInstruction(il, first, next);
254                         deleteInstruction(il, second, next);
255                         first = next;
256                         continue;
257                      }
258                   }
259                }
260             }
261          }
262          first = first.getNext();
263       }
264
265       if (count > 0 && app.isVerboseBCO) {
266          System.out.println("Replaced " + count + " IFxx/RETURN --> IFyy : " + mg.getClassName() + '#' + mg.getName());
267       }
268       return count;
269    }
270
271    // replacing IFxx/GOTO --> IFyy
272
//
273
// ifeq Label1 ifne Label2
274
// goto Label2 Label1: xxxx
275
// Label1: xxxx ...
276
// ...
277
// Label2: yyyy Label2: yyyy
278
// ... ...
279
private int replaceIFxxGOTO(MethodGen mg) {
280       InstructionList il = mg.getInstructionList();
281       int count = 0;
282
283       for (InstructionHandle first = il.getStart(); first != null;) {
284          Instruction ins1 = first.getInstruction();
285          if (ins1 instanceof IfInstruction) {
286             InstructionHandle second = first.getNext();
287             Instruction ins2 = second.getInstruction();
288             if (ins2 instanceof GotoInstruction) {
289                InstructionHandle ifTarget = ((IfInstruction)ins1).getTarget();
290                InstructionHandle gotoTarget = ((GotoInstruction)ins2).getTarget();
291                InstructionHandle next = second.getNext();
292                if (ifTarget == next) {
293                   count ++;
294                   BranchInstruction newIns = ((IfInstruction)ins1).negate();
295                   newIns.setTarget(gotoTarget);
296                   InstructionHandle newIh = il.insert(first, newIns);
297                   if (first.hasTargeters()) {
298                      updateTargets(first, newIh, newIh.getPrev());
299                   }
300                   deleteInstruction(il, first, next);
301                   deleteInstruction(il, second, next);
302                   first = next;
303                   continue;
304                }
305             }
306          }
307          first = first.getNext();
308       }
309
310       if (count > 0 && app.isVerboseBCO) {
311          System.out.println("Replaced " + count + " IFxx/GOTO --> IFyy : " + mg.getClassName() + '#' + mg.getName());
312       }
313       return count;
314    }
315
316    // replacing IFxx>>next --> POP
317
//
318
// ifeq Label1 pop
319
// Label1: xxxx Label1: xxxx
320
// ... ...
321
//
322
// if_icmpeq Label1 pop
323
// Label1: xxxx pop
324
// ... Label1: xxxx
325
// ...
326
private int replaceIFxxnext(MethodGen mg) {
327       InstructionList il = mg.getInstructionList();
328       int count = 0;
329
330       for (InstructionHandle first = il.getStart(); first != null;) {
331          Instruction ins1 = first.getInstruction();
332          if (ins1 instanceof IfInstruction) {
333             InstructionHandle ifTarget = ((IfInstruction)ins1).getTarget();
334             InstructionHandle next = first.getNext();
335             if (ifTarget == next) {
336                count ++;
337                InstructionHandle newIh = il.insert(first, InstructionConstants.POP);
338                if (first.hasTargeters()) {
339                   updateTargets(first, newIh, newIh.getPrev());
340                }
341                if (ins1 instanceof IF_ACMPEQ
342                 || ins1 instanceof IF_ACMPNE
343                 || ins1 instanceof IF_ICMPEQ
344                 || ins1 instanceof IF_ICMPGE
345                 || ins1 instanceof IF_ICMPGT
346                 || ins1 instanceof IF_ICMPLE
347                 || ins1 instanceof IF_ICMPLT
348                 || ins1 instanceof IF_ICMPNE
349                ) {
350                   InstructionHandle newIh2 = il.insert(first, InstructionConstants.POP);
351                }
352                deleteInstruction(il, first, next);
353                first = next;
354                continue;
355             }
356          }
357          first = first.getNext();
358       }
359
360       if (count > 0 && app.isVerboseBCO) {
361          System.out.println("Replaced " + count + " IFxx>>next --> POP : " + mg.getClassName() + '#' + mg.getName());
362       }
363       return count;
364    }
365
366    // replacing xSTOREn/GOTO --> GOTO
367
//
368
// ASTORE %4 goto Label0
369
// goto Label1 ...
370
// ... ...
371
// ASTORE %4 Label0: ASTORE %4
372
// Label1: xxxx Label1: xxxx
373
// ... ...
374
// private int replaceSTOREGOTO(MethodGen mg) {
375
// InstructionList il = mg.getInstructionList();
376
// int count = 0;
377
//
378
// for (InstructionHandle first = il.getStart(); first != null;) {
379
// Instruction ins1 = first.getInstruction();
380
// if (ins1 instanceof StoreInstruction) {
381
// InstructionHandle second = first.getNext();
382
// Instruction ins2 = second.getInstruction();
383
// if (ins2 instanceof GotoInstruction) {
384
// InstructionHandle gotoTarget = ((GotoInstruction)ins2).getTarget();
385
// InstructionHandle preGotoTarget = gotoTarget.getPrev();
386
// Instruction ins3 = preGotoTarget.getInstruction();
387
// if (ins3 instanceof StoreInstruction) {
388
// int vn1 = ((StoreInstruction)ins1).getIndex();
389
// int vn3 = ((StoreInstruction)ins3).getIndex();
390
// if (vn1 == vn3 && ins1.getClass() == ins3.getClass()) {
391
// InstructionHandle next = second.getNext();
392
// count ++;
393
// ((GotoInstruction)ins2).setTarget(preGotoTarget);
394
// deleteInstruction(il, first, second);
395
// first = next;
396
// continue;
397
// }
398
// }
399
// }
400
// }
401
// first = first.getNext();
402
// }
403
//
404
// if (count > 0) {
405
// System.out.println("Replaced " + count + " xSTOREn/GOTO --> GOTO : " + mg.getClassName() + '#' + mg.getName());
406
// }
407
// return count;
408
// }
409

410    // replacing xSTOREn/xLOADm/xLOADn/IF_xCMPxx --> xSTOREn/xLOADn/xLOADm/IF_xCMPxx
411
//
412
// ASTORE %4 ASTORE %4
413
// ALOAD %5 ALOAD %4
414
// ALOAD %4 ALOAD %5
415
// IF_ACMPEQ Label1 IF_ACMPEQ Label1
416
// ... ...
417
//
418
// ASTORE %4 ASTORE %4
419
// ALOAD %5 ALOAD %4
420
// ALOAD %4 ALOAD %5
421
// IF_ACMPGT Label1 IF_ACMPLE Label1
422
// ... ...
423
private int replaceSTORELOADLOADIFxCMPxx(MethodGen mg) {
424       InstructionList il = mg.getInstructionList();
425       int count = 0;
426
427       for (InstructionHandle first = il.getStart(); first != null;) {
428          Instruction ins1 = first.getInstruction();
429          if (ins1 instanceof StoreInstruction) {
430             InstructionHandle second = first.getNext();
431             Instruction ins2 = second.getInstruction();
432             if (ins2 instanceof LoadInstruction) {
433                InstructionHandle third = second.getNext();
434                Instruction ins3 = third.getInstruction();
435                if (ins3 instanceof LoadInstruction) {
436                   InstructionHandle fourth = third.getNext();
437                   Instruction ins4 = fourth.getInstruction();
438                   if (ins4 instanceof IfInstruction) {
439                      if (ins4 instanceof IF_ACMPEQ
440                       || ins4 instanceof IF_ACMPNE
441                       || ins4 instanceof IF_ICMPEQ
442                       || ins4 instanceof IF_ICMPGE
443                       || ins4 instanceof IF_ICMPGT
444                       || ins4 instanceof IF_ICMPLE
445                       || ins4 instanceof IF_ICMPLT
446                       || ins4 instanceof IF_ICMPNE
447                      ) {
448                         int vn1 = ((StoreInstruction)ins1).getIndex();
449                         int vn2 = ((LoadInstruction)ins2).getIndex();
450                         int vn3 = ((LoadInstruction)ins3).getIndex();
451                         if (vn1 == vn3 && vn1 != vn2) {
452                            InstructionHandle next = fourth.getNext();
453                            count ++;
454                            ((LoadInstruction)ins2).setIndex(vn3);
455                            ((LoadInstruction)ins3).setIndex(vn2);
456                            if (ins4 instanceof IF_ICMPGE
457                             || ins4 instanceof IF_ICMPGT
458                             || ins4 instanceof IF_ICMPLE
459                             || ins4 instanceof IF_ICMPLT
460                            ) {
461                               InstructionHandle newIh = il.insert(fourth, ((IfInstruction)ins4).negate());
462                               deleteInstruction(il, fourth, next);
463                            }
464                            first = next;
465                            continue;
466                         }
467                      }
468                   }
469                }
470             }
471          }
472          first = first.getNext();
473       }
474
475       if (count > 0 && app.isVerboseBCO) {
476          System.out.println("Replaced " + count + " xSTOREn/xLOADm/xLOADn/IF_xCMPxx --> xSTOREn/xLOADn/xLOADm/IF_xCMPxx : " + mg.getClassName() + '#' + mg.getName());
477       }
478       return count;
479    }
480
481    // replacing xLOADn/xLOADn --> xLOADn/DUP
482
//
483
// ALOAD %4 ALOAD %4
484
// ALOAD %4 DUP
485
// ... ...
486
private int replaceLOADLOAD(MethodGen mg) {
487       InstructionList il = mg.getInstructionList();
488       int count = 0;
489
490       for (InstructionHandle first = il.getStart(); first != null;) {
491          Instruction ins1 = first.getInstruction();
492          if (ins1 instanceof LoadInstruction) {
493             InstructionHandle second = first.getNext();
494             Instruction ins2 = second.getInstruction();
495             if (ins2 instanceof LoadInstruction) {
496                InstructionHandle next = second.getNext();
497                int vn1 = ((LoadInstruction)ins1).getIndex();
498                int vn2 = ((LoadInstruction)ins2).getIndex();
499                if (vn1 == vn2) {
500                   count ++;
501                   boolean isDUP2 = false;
502                   if (ins1 instanceof LLOAD || ins1 instanceof DLOAD) {
503                      isDUP2 = true;
504                   }
505                   InstructionHandle newIh = il.insert(second, (isDUP2) ? InstructionConstants.DUP2 : InstructionConstants.DUP);
506                   if (second.hasTargeters()) {
507                      updateTargets(second, newIh, newIh.getPrev());
508                   }
509                   deleteInstruction(il, second, second.getNext());
510                   first = next;
511                   continue;
512                }
513             }
514          }
515          first = first.getNext();
516       }
517
518       if (count > 0 && app.isVerboseBCO) {
519          System.out.println("Replaced " + count + " xLOADn/xLOADn --> xLOADn/DUP : " + mg.getClassName() + '#' + mg.getName());
520       }
521       return count;
522    }
523
524    // xSTOREn/xLOADn --> DUP/xSTOREn
525
//
526
// ASTORE %4 DUP
527
// ALOAD %4 ASTORE %4
528
// ... ...
529
private int replaceSTORELOAD(MethodGen mg) {
530       InstructionList il = mg.getInstructionList();
531       int count = 0;
532
533       for (InstructionHandle first = il.getStart(); first != null; first = first.getNext()) {
534          Instruction ins1 = first.getInstruction();
535          if (ins1 instanceof StoreInstruction) {
536             InstructionHandle second = first.getNext();
537             Instruction ins2 = second.getInstruction();
538             if (ins1 instanceof ASTORE && ins2 instanceof ALOAD) {
539                int locNo1 = ((LocalVariableInstruction)ins1).getIndex();
540                int locNo2 = ((LocalVariableInstruction)ins2).getIndex();
541                if (locNo1 == locNo2) {
542                   if (checkTargetersOfSecond(second)) {
543                      count ++;
544                      replaceSTORELOAD0(il, first, second, false);
545                   }
546                }
547             } else if (ins1 instanceof ISTORE && ins2 instanceof ILOAD) {
548                int locNo1 = ((LocalVariableInstruction)ins1).getIndex();
549                int locNo2 = ((LocalVariableInstruction)ins2).getIndex();
550                if (locNo1 == locNo2) {
551                   if (checkTargetersOfSecond(second)) {
552                      count ++;
553                      replaceSTORELOAD0(il, first, second, false);
554                   }
555                }
556             } else if (ins1 instanceof LSTORE && ins2 instanceof LLOAD) {
557                int locNo1 = ((LocalVariableInstruction)ins1).getIndex();
558                int locNo2 = ((LocalVariableInstruction)ins2).getIndex();
559                if (locNo1 == locNo2) {
560                   if (checkTargetersOfSecond(second)) {
561                      count ++;
562                      replaceSTORELOAD0(il, first, second, true);
563                   }
564                }
565             } else if (ins1 instanceof FSTORE && ins2 instanceof FLOAD) {
566                int locNo1 = ((LocalVariableInstruction)ins1).getIndex();
567                int locNo2 = ((LocalVariableInstruction)ins2).getIndex();
568                if (locNo1 == locNo2) {
569                   if (checkTargetersOfSecond(second)) {
570                      count ++;
571                      replaceSTORELOAD0(il, first, second, false);
572                   }
573                }
574             } else if (ins1 instanceof DSTORE && ins2 instanceof DLOAD) {
575                int locNo1 = ((LocalVariableInstruction)ins1).getIndex();
576                int locNo2 = ((LocalVariableInstruction)ins2).getIndex();
577                if (locNo1 == locNo2) {
578                   if (checkTargetersOfSecond(second)) {
579                      count ++;
580                      replaceSTORELOAD0(il, first, second, true);
581                   }
582                }
583             }
584          }
585       }
586
587       if (count > 0 && app.isVerboseBCO) {
588          System.out.println("Replaced " + count + " xSTOREn/xLOADn --> DUP/xSTOREn : " + mg.getClassName() + '#' + mg.getName());
589       }
590       return count;
591    }
592
593    private boolean checkTargetersOfSecond(InstructionHandle second) {
594       if (second.hasTargeters()) {
595          InstructionTargeter[] ts = second.getTargeters();
596          for (int i=0; i<ts.length; i++) {
597             InstructionTargeter t = ts[i];
598             if (t instanceof BranchInstruction) {
599                return false;
600             } else if (t instanceof CodeExceptionGen) {
601             } else if (t instanceof LocalVariableGen) {
602             }
603          }
604       }
605       return true;
606    }
607
608    // replacing xxxx/IMUL --> ICONST_n/ISHL
609
//
610
// BIPUSH 8 ICONST_3
611
// IMUL ISHL
612
// ... ...
613
private int replaceIMULISHL(MethodGen mg) {
614       InstructionList il = mg.getInstructionList();
615       int count = 0;
616
617       for (InstructionHandle first = il.getStart(); first != null;) {
618          Instruction ins1 = first.getInstruction();
619          if (ins1 instanceof BIPUSH || ins1 instanceof SIPUSH || ins1 instanceof ICONST) {
620             InstructionHandle second = first.getNext();
621             Instruction ins2 = second.getInstruction();
622             if (ins2 instanceof IMUL && !second.hasTargeters()) {
623                InstructionHandle next = second.getNext();
624                int vn1 = 0;
625                if (ins1 instanceof BIPUSH) {
626                   Integer JavaDoc int1 = (Integer JavaDoc)((BIPUSH)ins1).getValue();
627                   vn1 = int1.intValue();
628                } else if (ins1 instanceof SIPUSH) {
629                   Integer JavaDoc int1 = (Integer JavaDoc)((SIPUSH)ins1).getValue();
630                   vn1 = int1.intValue();
631                } else if (ins1 instanceof ICONST) {
632                   Integer JavaDoc int1 = (Integer JavaDoc)((ICONST)ins1).getValue();
633                   vn1 = int1.intValue();
634                }
635                int icn = 0;
636                switch (vn1) {
637                case 2: icn = 1; break;
638                case 4: icn = 2; break;
639                case 8: icn = 3; break;
640                }
641                if (icn > 0) {
642                   count ++;
643                   InstructionHandle newIh1 = il.insert(first, new ICONST(icn));
644                   InstructionHandle newIh2 = il.insert(second, new ISHL());
645                   deleteInstruction(il, first, next);
646                   deleteInstruction(il, second, next);
647                   first = next;
648                   continue;
649                }
650             }
651          }
652          first = first.getNext();
653       }
654
655       if (count > 0 && app.isVerboseBCO) {
656          System.out.println("Replaced " + count + " xxxx/IMUL --> ICONST_n/ISHL : " + mg.getClassName() + '#' + mg.getName());
657       }
658       return count;
659    }
660
661    private void replaceSTORELOAD0(InstructionList il, InstructionHandle first, InstructionHandle second, boolean isDUP2) {
662       InstructionHandle newIh = il.insert(first, (isDUP2) ? InstructionConstants.DUP2 : InstructionConstants.DUP);
663       if (first.hasTargeters()) {
664          updateTargets(first, newIh, newIh.getPrev());
665       }
666       deleteInstruction(il, second, second.getNext());
667    }
668
669    // analize local slot
670
//
671
// ISTORE %4 POP
672
// ... ...
673
private int analizeLocalSlot(MethodGen mg) {
674       int count = 0;
675       CodeExceptionGen[] ceg = mg.getExceptionHandlers();
676       InstructionList il = mg.getInstructionList();
677
678       count += analizeLocalSlot0(il, ceg, il.getStart());
679       for (int i=0; i<ceg.length; i++) {
680          count += analizeLocalSlot0(il, ceg, ceg[i].getHandlerPC());
681       }
682
683       if (count > 0 && app.isVerboseBCO) {
684          System.out.println("Replaced " + count + " xSTOREn --> POP unused local slot : " + mg.getClassName() + '#' + mg.getName());
685       }
686       return count;
687    }
688
689    private int analizeLocalSlot0(InstructionList il, CodeExceptionGen[] ceg, InstructionHandle first) {
690       int count = 0;
691       for (; first != null; ) {
692          Instruction ins1 = first.getInstruction();
693          if (ins1 instanceof StoreInstruction) {
694             int vn = ((StoreInstruction)ins1).getIndex();
695             HashSet hset = new HashSet();
696             boolean isUsed = checkUsedLocalSlot(first.getNext(), vn, hset);
697             if (!isUsed) {
698                for (int j=0; j<ceg.length; j++) {
699                   isUsed = checkUsedLocalSlot(ceg[j].getHandlerPC(), vn, hset);
700                   if (isUsed) {
701                      break;
702                   }
703                }
704             }
705             if (!isUsed) {
706                InstructionHandle next = first.getNext();
707                count ++;
708                Instruction ins2 = InstructionConstants.POP;
709                if (ins1 instanceof LSTORE || ins1 instanceof DSTORE) {
710                   ins2 = InstructionConstants.POP2;
711                }
712                InstructionHandle newIh = il.insert(first, ins2);
713                if (first.hasTargeters()) {
714                   updateTargets(first, newIh, newIh.getPrev());
715                }
716                deleteInstruction(il, first, first.getNext());
717                first = next;
718                continue;
719             }
720          }
721          first = first.getNext();
722       }
723       return count;
724    }
725
726    // return true : used
727
// return false : unused
728
private boolean checkUsedLocalSlot(InstructionHandle first, int slotNo, HashSet hset) {
729       for (; first != null; first = first.getNext()) {
730          Instruction ins1 = first.getInstruction();
731          if (ins1 instanceof ReturnInstruction) {
732             break;
733          } else if (ins1 instanceof RET) {
734             int vn = ((RET)ins1).getIndex();
735             if (vn == slotNo) {
736                return true;
737             }
738             break;
739          } else if (ins1 instanceof IINC) {
740             int vn = ((IINC)ins1).getIndex();
741             if (vn == slotNo) {
742                return true;
743             }
744          } else if (ins1 instanceof LoadInstruction) {
745             int vn = ((LoadInstruction)ins1).getIndex();
746             if (vn == slotNo) {
747                return true;
748             }
749          } else if (ins1 instanceof StoreInstruction) {
750             int vn = ((StoreInstruction)ins1).getIndex();
751             if (vn == slotNo) {
752                return false;
753             }
754          } else if (ins1 instanceof BranchInstruction) {
755             InstructionHandle target = ((BranchInstruction)ins1).getTarget();
756             if (!hset.contains(target)) {
757                hset.add(target);
758                boolean isUsed = checkUsedLocalSlot(target, slotNo, hset);
759                if (isUsed) {
760                   return true;
761                }
762             }
763             if (ins1 instanceof GotoInstruction) {
764                break;
765             } else if (ins1 instanceof Select) {
766                InstructionHandle[] targets = ((Select)ins1).getTargets();
767                for (int i=0; i<targets.length; i++) {
768                   InstructionHandle targetn = targets[i];
769                   if (!hset.contains(targetn)) {
770                      hset.add(targetn);
771                      boolean isUsed = checkUsedLocalSlot(targetn, slotNo, hset);
772                      if (isUsed) {
773                         return true;
774                      }
775                   }
776                }
777             }
778          } else if (ins1 instanceof ATHROW) {
779             break;
780          }
781       }
782       return false;
783    }
784
785    // remove XXX/POP (DUP/POP,CONST/POP,LOAD/POP.LDC/POP)
786
//
787
// DUP ...
788
// POP
789
// ...
790
private int removeXXXPOP(MethodGen mg) {
791       InstructionList il = mg.getInstructionList();
792       int count = 0;
793
794       for (InstructionHandle second = il.getStart(); second != null;) {
795          Instruction ins2 = second.getInstruction();
796          if (ins2 instanceof POP) {
797             if (!second.hasTargeters()) {
798                InstructionHandle first = second.getPrev();
799                Instruction ins1 = first.getInstruction();
800                if (ins1 instanceof DUP
801                 || ins1 instanceof ACONST_NULL
802                 || ins1 instanceof ICONST
803                 || ins1 instanceof FCONST
804                 || ins1 instanceof LoadInstruction
805                 || ins1 instanceof LDC
806                 || ins1 instanceof LDC_W
807                 ) {
808                   InstructionHandle next = second.getNext();
809                   count ++;
810                   deleteInstruction(il, first, next);
811                   deleteInstruction(il, second, next);
812                   second = next;
813                   continue;
814                }
815             }
816          } else if (ins2 instanceof POP2) {
817             if (!second.hasTargeters()) {
818                InstructionHandle first = second.getPrev();
819                Instruction ins1 = first.getInstruction();
820                if (ins1 instanceof DUP2
821                 || ins1 instanceof LCONST
822                 || ins1 instanceof DCONST
823                 || ins1 instanceof LoadInstruction
824                 || ins1 instanceof LDC2_W
825                 ) {
826                   InstructionHandle next = second.getNext();
827                   count ++;
828                   deleteInstruction(il, first, next);
829                   deleteInstruction(il, second, next);
830                   second = next;
831                   continue;
832                }
833             }
834          }
835          second = second.getNext();
836       }
837
838       if (count > 0 && app.isVerboseBCO) {
839          System.out.println("Removed " + count + " XXX/POP : " + mg.getClassName() + '#' + mg.getName());
840       }
841       return count;
842    }
843
844    // remove NOP
845
//
846
// NOP ...
847
// ...
848
private int removeNOP(MethodGen mg) {
849       InstructionList il = mg.getInstructionList();
850       int count = 0;
851
852       for (InstructionHandle first = il.getStart(); first != null; ) {
853          Instruction ins = first.getInstruction();
854          if (ins instanceof NOP) {
855             InstructionHandle next = first.getNext();
856             if (next != null) {
857                count ++;
858                deleteInstruction(il, first, next);
859                first = next;
860                continue;
861             }
862          }
863          first = first.getNext();
864       }
865
866       if (count > 0 && app.isVerboseBCO) {
867          System.out.println("Removed " + count + " NOP : " + mg.getClassName() + '#' + mg.getName());
868       }
869       return count;
870    }
871
872    // remove GOTO next
873
//
874
// goto Label1 Label1: xxxx
875
// Label1: xxxx ...
876
// ...
877
private int removeGOTOnext(MethodGen mg) {
878       InstructionList il = mg.getInstructionList();
879       int count = 0;
880
881       for (InstructionHandle first = il.getStart(); first != null; ) {
882          Instruction ins = first.getInstruction();
883          if (ins instanceof GotoInstruction) {
884             InstructionHandle next = first.getNext();
885             if (next != null) {
886                InstructionHandle gotoTarget = ((GotoInstruction)ins).getTarget();
887                if (gotoTarget == next) {
888                   count ++;
889                   deleteInstruction(il, first, next);
890                   first = next;
891                   continue;
892                }
893             }
894          }
895          first = first.getNext();
896       }
897
898       if (count > 0 && app.isVerboseBCO) {
899          System.out.println("Removed " + count + " GOTO next : " + mg.getClassName() + '#' + mg.getName());
900       }
901       return count;
902    }
903
904    // remove double RETURN
905
//
906
// RETURN RETURN
907
// RETURN ...
908
// ...
909
private int removeRETURNs(MethodGen mg) {
910       InstructionList il = mg.getInstructionList();
911       int count = 0;
912
913       for (InstructionHandle first = il.getStart(); first != null; ) {
914          Instruction ins1 = first.getInstruction();
915          if (ins1 instanceof ReturnInstruction) {
916             InstructionHandle next = first.getNext();
917             if (next != null) {
918                Instruction ins2 = next.getInstruction();
919                if (ins2 instanceof ReturnInstruction) {
920                   count ++;
921                   deleteInstruction(il, first, next);
922                   first = next;
923                   continue;
924                }
925             }
926          }
927          first = first.getNext();
928       }
929
930       if (count > 0 && app.isVerboseBCO) {
931          System.out.println("Removed " + count + " double RETURN : " + mg.getClassName() + '#' + mg.getName());
932       }
933       return count;
934    }
935
936    // remove double GOTO
937
//
938
// GOTO Label1 GOTO Label1
939
// GOTO Label2 ...
940
// ...
941
private int removeGOTOs(MethodGen mg) {
942       InstructionList il = mg.getInstructionList();
943       int count = 0;
944
945       for (InstructionHandle first = il.getStart(); first != null; ) {
946          Instruction ins1 = first.getInstruction();
947          if (ins1 instanceof GotoInstruction) {
948             InstructionHandle second = first.getNext();
949             if (second != null) {
950                InstructionHandle next = second.getNext();
951                if (next != null) {
952                   Instruction ins2 = second.getInstruction();
953                   if (ins2 instanceof GotoInstruction) {
954                      if (!second.hasTargeters()) {
955                         count ++;
956                         deleteInstruction(il, second, next);
957                         first = next;
958                         continue;
959                      }
960                   }
961                }
962             }
963          }
964          first = first.getNext();
965       }
966
967       if (count > 0 && app.isVerboseBCO) {
968          System.out.println("Removed " + count + " double GOTO : " + mg.getClassName() + '#' + mg.getName());
969       }
970       return count;
971    }
972
973    // remove unused GOTO
974
//
975
// RETURN RETURN
976
// GOTO Label1 ...
977
// ...
978
private int removeUnusedGOTO(MethodGen mg) {
979       InstructionList il = mg.getInstructionList();
980       int count = 0;
981
982       for (InstructionHandle first = il.getStart(); first != null; ) {
983          Instruction ins1 = first.getInstruction();
984          if (ins1 instanceof GotoInstruction) {
985             InstructionHandle preIh = first.getPrev();
986             InstructionHandle next = first.getNext();
987             if (preIh != null && next != null) {
988                Instruction ins0 = preIh.getInstruction();
989                if (ins0 instanceof GotoInstruction
990                 || ins0 instanceof ReturnInstruction
991                 || ins0 instanceof ATHROW
992                ) {
993                   if (!first.hasTargeters()) {
994                      count ++;
995                      deleteInstruction(il, first, next);
996                      first = next;
997                      continue;
998                   }
999                }
1000            }
1001         }
1002         first = first.getNext();
1003      }
1004
1005      if (count > 0 && app.isVerboseBCO) {
1006         System.out.println("Removed " + count + " unused GOTO : " + mg.getClassName() + '#' + mg.getName());
1007      }
1008      return count;
1009   }
1010
1011   private void deleteInstruction(InstructionList il, InstructionHandle ih, InstructionHandle next) {
1012      InstructionHandle prev = ih.getPrev();
1013      if (prev == null) {
1014         prev = ih.getNext();
1015      }
1016
1017      try {
1018         il.delete(ih);
1019      } catch (TargetLostException ex) {
1020         InstructionHandle[] targets = ex.getTargets();
1021         for (int i=0; i < targets.length; i++) {
1022            updateTargets(targets[i], next, prev);
1023         }
1024      }
1025   }
1026
1027   private void updateTargets(InstructionHandle oldTarget, InstructionHandle newTarget, InstructionHandle newTargetPrev) {
1028      InstructionTargeter[] targeters = oldTarget.getTargeters();
1029      for (int j=0; j < targeters.length; j++) {
1030         InstructionHandle curTarget = newTarget;
1031         InstructionTargeter targeter = targeters[j];
1032         if (targeter instanceof CodeExceptionGen) {
1033            if (((CodeExceptionGen)targeter).getEndPC() == oldTarget) {
1034               curTarget = newTargetPrev;
1035            }
1036         }
1037         targeter.updateTarget(oldTarget, curTarget);
1038      }
1039   }
1040}
1041
Popular Tags