Source Code Cross Referenced for Instruction.java in  » Development » jode » jode » bytecode » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » jode » jode.bytecode 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* Instruction Copyright (C) 1999-2002 Jochen Hoenicke.
002:         *
003:         * This program is free software; you can redistribute it and/or modify
004:         * it under the terms of the GNU Lesser General Public License as published by
005:         * the Free Software Foundation; either version 2, or (at your option)
006:         * any later version.
007:         *
008:         * This program is distributed in the hope that it will be useful,
009:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
010:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011:         * GNU General Public License for more details.
012:         *
013:         * You should have received a copy of the GNU Lesser General Public License
014:         * along with this program; see the file COPYING.LESSER.  If not, write to
015:         * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
016:         *
017:         * $Id: Instruction.java,v 1.9.2.1 2002/05/28 17:34:00 hoenicke Exp $
018:         */
019:
020:        package jode.bytecode;
021:
022:        /**
023:         * This class represents an instruction in the byte code.
024:         *
025:         */
026:        public final class Instruction implements  Opcodes {
027:            /**
028:             * The opcode of the instruction.  We map some opcodes, e.g.
029:             * <pre>
030:             * iload_[0-3] -> iload, ldc_w -> ldc, wide iinc -> iinc.
031:             * </pre>
032:             */
033:            // a byte would be enough, but then we would need an unsigned convert.
034:            private int opcode;
035:            /**
036:             * If this opcode uses a local this gives the slot.  For multianewarray
037:             * this gives the dimension.
038:             */
039:            private int shortData;
040:            /**
041:             * The address of this opcode.
042:             */
043:            private int addr;
044:            /**
045:             * Optional object data for this opcode.  There are four different
046:             * usages of this field:
047:             * <dl>
048:             * <dt>opc_ldc / opc_ldc2_w</dt>
049:             * <dd>The constant of type Integer/Long/Float/Double/String. </dd>
050:             * <dt>opc_invokexxx / opc_xxxfield / opc_xxxstatic</dt>
051:             * <dd>The field/method Reference</dd>
052:             * <dt>opc_new / opc_checkcast / opc_instanceof / opc_multianewarray</dt>
053:             * <dd>The typesignature of the class/array</dd>
054:             * <dt>opc_lookupswitch</dt>
055:             * <dd>The array of values of type int[]</dd>
056:             * </dl>
057:             */
058:            private Object objData;
059:            /**
060:             * The successors of this opcodes, where flow may lead to
061:             * (except that nextByAddr is implicit if !alwaysJump).  The
062:             * value null means no successor, if there is one succesor, this
063:             * is of type Instruction, otherwise, this is an array of Instruction.
064:             */
065:            private Object succs;
066:            /**
067:             * The predecessors of this opcode, orthogonal to the succs array.
068:             * This must be null or a non empty array.
069:             */
070:            private Instruction[] preds;
071:            /**
072:             * The next instruction in code order.
073:             */
074:            Instruction nextByAddr;
075:            /**
076:             * The previous instruction in code order, useful when changing
077:             * the order.
078:             */
079:            Instruction prevByAddr;
080:
081:            /**
082:             * You can use this field to add some info to each instruction.
083:             * After using, you must set it to null again.
084:             * @XXX Do we really need this.  Every field here can quickly take 
085:             * half a megabyte!
086:             */
087:            private Object tmpInfo;
088:
089:            public Instruction(int opcode) {
090:                this .opcode = opcode;
091:            }
092:
093:            /**
094:             * Returns the opcode of the instruction.  We map some opcodes:
095:             * <pre>
096:             * [iflda]load_x           -&gt; [iflda]load
097:             * [iflda]store_x          -&gt; [iflda]store
098:             * [ifa]const_xx, ldc_w    -&gt; ldc
099:             * [dl]const_xx            -&gt; ldc2_w
100:             * wide opcode             -&gt; opcode
101:             * tableswitch             -&gt; lookupswitch
102:             * [a]newarray             -&gt; multianewarray
103:             * </pre>
104:             */
105:            public final int getOpcode() {
106:                return opcode;
107:            }
108:
109:            /**
110:             * Returns the address of this opcode.  As long as you don't remove
111:             * or insert instructions, you can be sure, that the addresses of the
112:             * opcodes are unique, and that 
113:             * <pre>
114:             * instr.getAddr() + instr.getLength() == instr.getNextByAddr().getAddr()
115:             * <pre>
116:             *
117:             * If you insert/remove Instructions, you should be aware that the
118:             * above property is not guaranteed anymore.
119:             */
120:            public final int getAddr() {
121:                return addr;
122:            }
123:
124:            public final int getNextAddr() {
125:                return nextByAddr.addr;
126:            }
127:
128:            /**
129:             * Returns the length of this opcode.  See getAddr() for some
130:             * notes.  Note that the length doesn't necessarily reflect the
131:             * real length, when this bytecode is written again, since the
132:             * length of an ldc instruction depends on the number of entries
133:             * in constant pool, and the order they are allocated.  
134:             */
135:            public final int getLength() {
136:                return getNextAddr() - addr;
137:            }
138:
139:            final void setAddr(int addr) {
140:                this .addr = addr;
141:            }
142:
143:            public final boolean hasLocalSlot() {
144:                return opcode == opc_iinc || opcode == opc_ret
145:                        || opcode >= opc_iload && opcode <= opc_aload
146:                        || opcode >= opc_istore && opcode <= opc_astore;
147:            }
148:
149:            public final int getLocalSlot()
150:            /*{ require { hasLocalSlot()
151:                          :: "Instruction has no slot" } }*/
152:            {
153:                return shortData;
154:            }
155:
156:            public final void setLocalSlot(int slot)
157:            /*{ require { hasLocalSlot()
158:                          :: "Instruction has no slot" } }*/
159:            {
160:                shortData = slot;
161:            }
162:
163:            /**
164:             * Optional integer data for this opcode.  There are various uses
165:             * for this:
166:             * <dl>
167:             * <dt>opc_iinc</dt>
168:             * <dd>The value by which the constant is increased/decreased. (short)</dd>
169:             * <dt>opc_multianewarray</dt>
170:             * <dd>The number of dimensions (1..255)</dd>
171:             * </dl>
172:             */
173:            public final int getIncrement()
174:            /*{ require { opcode == opc_iinc || opcode == opc_multianewarray
175:                          || opcode == opc_tableswitch
176:                          :: "Instruction has no int data" } }*/
177:            {
178:                /* shortData already used for local slot */
179:                return ((Short) objData).shortValue();
180:            }
181:
182:            /**
183:             * Optional integer data for this opcode.  There are various uses
184:             * for this:
185:             * <dl>
186:             * <dt>opc_iinc</dt>
187:             * <dd>The value by which the constant is increased/decreased. (short)</dd>
188:             * <dt>opc_multianewarray</dt>
189:             * <dd>The number of dimensions (1..255)</dd>
190:             * </dl>
191:             */
192:            public final void setIncrement(int incr)
193:            /*{ require { opcode == opc_iinc || opcode == opc_multianewarray
194:                          :: "Instruction has no int data" } }*/
195:            {
196:                /* shortData already used for local slot */
197:                objData = new Short((short) incr);
198:            }
199:
200:            /**
201:             *
202:             */
203:            public final int getDimensions()
204:            /*{ require { opcode == opc_multianewarray
205:                          :: "Instruction has no dimensions" } }*/
206:            {
207:                return shortData;
208:            }
209:
210:            /**
211:             *
212:             */
213:            public final void setDimensions(int dims)
214:            /*{ require { opcode == opc_multianewarray
215:                          :: "Instruction has no dimensions" } }*/
216:            {
217:                shortData = dims;
218:            }
219:
220:            public final Object getConstant()
221:            /*{ require { opcode == opc_ldc || opcode == opc_ldc2_w
222:                          :: "Instruction has no constant" } }*/
223:            {
224:                return objData;
225:            }
226:
227:            public final void setConstant(Object constant)
228:            /*{ require { opcode == opc_ldc || opcode == opc_ldc2_w
229:                          :: "Instruction has no constant" } }*/
230:            {
231:                objData = constant;
232:            }
233:
234:            public final Reference getReference()
235:            /*{ require { opcode >= opc_getstatic && opcode <= opc_invokeinterface
236:                          :: "Instruction has no reference" } }*/
237:            {
238:                return (Reference) objData;
239:            }
240:
241:            public final void setReference(Reference ref)
242:            /*{ require { opcode >= opc_getstatic && opcode <= opc_invokeinterface
243:                          :: "Instruction has no reference" } }*/
244:            {
245:                objData = ref;
246:            }
247:
248:            public final String getClazzType()
249:            /*{ require { opcode == opc_new 
250:                          || opcode == opc_checkcast
251:                          || opcode == opc_instanceof
252:                          || opcode == opc_multianewarray
253:            	  :: "Instruction has no typesig" } }*/
254:            {
255:                return (String) objData;
256:            }
257:
258:            public final void setClazzType(String type)
259:            /*{ require { opcode == opc_new 
260:                          || opcode == opc_checkcast
261:                          || opcode == opc_instanceof
262:                          || opcode == opc_multianewarray
263:            	  :: "Instruction has no typesig" } }*/
264:            {
265:                objData = type;
266:            }
267:
268:            public final int[] getValues()
269:            /*{ require { opcode == opc_lookupswitch
270:                          :: "Instruction has no values" } }*/
271:            {
272:                return (int[]) objData;
273:            }
274:
275:            public final void setValues(int[] values)
276:            /*{ require { opcode == opc_lookupswitch
277:                          :: "Instruction has no values" } }*/
278:            {
279:                objData = values;
280:            }
281:
282:            public final boolean doesAlwaysJump() {
283:                switch (opcode) {
284:                case opc_ret:
285:                case opc_goto:
286:                case opc_jsr:
287:                case opc_tableswitch:
288:                case opc_lookupswitch:
289:                case opc_ireturn:
290:                case opc_lreturn:
291:                case opc_freturn:
292:                case opc_dreturn:
293:                case opc_areturn:
294:                case opc_return:
295:                case opc_athrow:
296:                    return true;
297:                default:
298:                    return false;
299:                }
300:            }
301:
302:            public final Instruction[] getPreds() {
303:                return preds;
304:            }
305:
306:            /**
307:             * Returns true if this opcode has successors, other than the implicit
308:             * getNextByAddr().
309:             */
310:            public boolean hasSuccs() {
311:                return succs != null;
312:            }
313:
314:            /**
315:             * Returns the successors of this opcodes, where flow may lead to
316:             * (except that nextByAddr is implicit if !alwaysJump).  The
317:             * value null means that there is no successor.
318:             */
319:            public final Instruction[] getSuccs() {
320:                if (succs instanceof  Instruction)
321:                    return new Instruction[] { (Instruction) succs };
322:                return (Instruction[]) succs;
323:            }
324:
325:            /**
326:             * Returns the single successor of this opcodes.  This gives the
327:             * target of a goto, jsr, or if opcode.
328:             * @return null if there is no successor, otherwise the successor.
329:             * @exception ClassCastException if this has more than one succ.
330:             */
331:            public final Instruction getSingleSucc() {
332:                return (Instruction) succs;
333:            }
334:
335:            public final Instruction getPrevByAddr() {
336:                if (prevByAddr.opcode == opc_impdep1)
337:                    return null;
338:                return prevByAddr;
339:            }
340:
341:            public final Instruction getNextByAddr() {
342:                if (nextByAddr.opcode == opc_impdep1)
343:                    return null;
344:                return nextByAddr;
345:            }
346:
347:            public final Object getTmpInfo() {
348:                return tmpInfo;
349:            }
350:
351:            public final void setTmpInfo(Object info) {
352:                tmpInfo = info;
353:            }
354:
355:            // INTERNAL FUNCTIONS TO KEEP PREDS AND SUCCS CONSISTENT 
356:
357:            final void removeSuccs() {
358:                if (succs == null)
359:                    return;
360:                if (succs instanceof  Instruction[]) {
361:                    Instruction[] ss = (Instruction[]) succs;
362:                    for (int i = 0; i < ss.length; i++)
363:                        if (ss[i] != null)
364:                            ss[i].removePredecessor(this );
365:                } else
366:                    ((Instruction) succs).removePredecessor(this );
367:                succs = null;
368:            }
369:
370:            /**
371:             * @param to may be null
372:             */
373:            private final void promoteSuccs(Instruction from, Instruction to) {
374:                if (succs == from)
375:                    succs = to;
376:                else if (succs instanceof  Instruction[]) {
377:                    Instruction[] ss = (Instruction[]) succs;
378:                    for (int i = 0; i < ss.length; i++)
379:                        if (ss[i] == from)
380:                            ss[i] = to;
381:                }
382:            }
383:
384:            /**
385:             * @exception ClassCastException if newSuccs is neither an Instruction
386:             * nor an array of instructions.
387:             */
388:            public final void setSuccs(Object newSuccs) {
389:                if (succs == newSuccs)
390:                    return;
391:                removeSuccs();
392:                if (newSuccs == null)
393:                    return;
394:                if (newSuccs instanceof  Instruction[]) {
395:                    Instruction[] ns = (Instruction[]) newSuccs;
396:                    switch (ns.length) {
397:                    case 0:
398:                        break;
399:                    case 1:
400:                        succs = ns[0];
401:                        ns[0].addPredecessor(this );
402:                        break;
403:                    default:
404:                        succs = ns;
405:                        for (int i = 0; i < ns.length; i++)
406:                            ns[i].addPredecessor(this );
407:                        break;
408:                    }
409:                } else {
410:                    succs = newSuccs;
411:                    ((Instruction) newSuccs).addPredecessor(this );
412:                }
413:            }
414:
415:            void addPredecessor(Instruction pred) {
416:                if (preds == null) {
417:                    preds = new Instruction[] { pred };
418:                    return;
419:                }
420:                int predsLength = preds.length;
421:                Instruction[] newPreds = new Instruction[predsLength + 1];
422:                System.arraycopy(preds, 0, newPreds, 0, predsLength);
423:                newPreds[predsLength] = pred;
424:                preds = newPreds;
425:            }
426:
427:            void removePredecessor(Instruction pred) {
428:                /* Hopefully it doesn't matter if this is slow */
429:                int predLength = preds.length;
430:                if (predLength == 1) {
431:                    if (preds[0] != pred)
432:                        throw new jode.AssertError(
433:                                "removing not existing predecessor");
434:                    preds = null;
435:                } else {
436:                    Instruction[] newPreds = new Instruction[predLength - 1];
437:                    int j;
438:                    for (j = 0; preds[j] != pred; j++)
439:                        newPreds[j] = preds[j];
440:                    System.arraycopy(preds, j + 1, newPreds, j, predLength - j
441:                            - 1);
442:                    preds = newPreds;
443:                }
444:            }
445:
446:            // ADDING, REMOVING AND REPLACING INSTRUCTIONS
447:
448:            /**
449:             * Replaces the opcode of this instruction.  You should only use the
450:             * mapped opcodes:
451:             * <pre>
452:             * [iflda]load_x           -&gt; [iflda]load
453:             * [iflda]store_x          -&gt; [iflda]store
454:             * [ifa]const_xx, ldc_w    -&gt; ldc
455:             * [dl]const_xx            -&gt; ldc2_w
456:             * wide opcode             -&gt; opcode
457:             * tableswitch             -&gt; lookupswitch
458:             * [a]newarray             -&gt; multianewarray
459:             * </pre>
460:             */
461:            public final void replaceInstruction(Instruction newInstr,
462:                    BytecodeInfo codeinfo) {
463:                /* remove predecessors of successors */
464:                removeSuccs();
465:
466:                newInstr.addr = addr;
467:                nextByAddr.prevByAddr = newInstr;
468:                newInstr.nextByAddr = nextByAddr;
469:                prevByAddr.nextByAddr = newInstr;
470:                newInstr.prevByAddr = prevByAddr;
471:                prevByAddr = null;
472:                nextByAddr = null;
473:
474:                /* promote the successors of the predecessors to newInstr */
475:                if (preds != null) {
476:                    for (int j = 0; j < preds.length; j++)
477:                        preds[j].promoteSuccs(this , newInstr);
478:                    newInstr.preds = preds;
479:                    preds = null;
480:                }
481:
482:                /* adjust exception handlers */
483:                Handler[] handlers = codeinfo.getExceptionHandlers();
484:                for (int i = 0; i < handlers.length; i++) {
485:                    if (handlers[i].start == this )
486:                        handlers[i].start = newInstr;
487:                    if (handlers[i].end == this )
488:                        handlers[i].end = newInstr;
489:                    if (handlers[i].catcher == this )
490:                        handlers[i].catcher = newInstr;
491:                }
492:
493:                /* adjust local variable table and line number table */
494:                LocalVariableInfo[] lvt = codeinfo.getLocalVariableTable();
495:                if (lvt != null) {
496:                    for (int i = 0; i < lvt.length; i++) {
497:                        if (lvt[i].start == this )
498:                            lvt[i].start = newInstr;
499:                        if (lvt[i].end == this )
500:                            lvt[i].end = newInstr;
501:                    }
502:                }
503:                LineNumber[] lnt = codeinfo.getLineNumberTable();
504:                if (lnt != null) {
505:                    for (int i = 0; i < lnt.length; i++) {
506:                        if (lnt[i].start == this )
507:                            lnt[i].start = newInstr;
508:                    }
509:                }
510:            }
511:
512:            void appendInstruction(Instruction newInstr, BytecodeInfo codeinfo) {
513:                newInstr.addr = nextByAddr.addr;
514:
515:                newInstr.nextByAddr = nextByAddr;
516:                nextByAddr.prevByAddr = newInstr;
517:                newInstr.prevByAddr = this ;
518:                nextByAddr = newInstr;
519:
520:                /* adjust exception handlers end */
521:                Handler[] handlers = codeinfo.getExceptionHandlers();
522:                if (handlers != null) {
523:                    for (int i = 0; i < handlers.length; i++) {
524:                        if (handlers[i].end == this )
525:                            handlers[i].end = newInstr;
526:                    }
527:                }
528:            }
529:
530:            /**
531:             * Removes this instruction (as if it would be replaced by a nop).
532:             */
533:            void removeInstruction(BytecodeInfo codeinfo) {
534:
535:                /* remove from chained list and adjust addr / length */
536:                prevByAddr.nextByAddr = nextByAddr;
537:                nextByAddr.prevByAddr = prevByAddr;
538:
539:                /* remove predecessors of successors */
540:                removeSuccs();
541:
542:                /* promote the predecessors to next instruction */
543:                if (preds != null) {
544:                    for (int j = 0; j < preds.length; j++)
545:                        preds[j].promoteSuccs(this , nextByAddr);
546:                    if (nextByAddr.preds == null)
547:                        nextByAddr.preds = preds;
548:                    else {
549:                        Instruction[] newPreds = new Instruction[nextByAddr.preds.length
550:                                + preds.length];
551:                        System.arraycopy(nextByAddr.preds, 0, newPreds, 0,
552:                                nextByAddr.preds.length);
553:                        System.arraycopy(preds, 0, newPreds,
554:                                nextByAddr.preds.length, preds.length);
555:                        nextByAddr.preds = newPreds;
556:                    }
557:                    preds = null;
558:                }
559:
560:                /* adjust exception handlers */
561:                Handler[] handlers = codeinfo.getExceptionHandlers();
562:                for (int i = 0; i < handlers.length; i++) {
563:                    if (handlers[i].start == this  && handlers[i].end == this ) {
564:                        /* Remove the handler.
565:                         * This is very seldom, so we can make it slow */
566:                        Handler[] newHandlers = new Handler[handlers.length - 1];
567:                        System.arraycopy(handlers, 0, newHandlers, 0, i);
568:                        System.arraycopy(handlers, i + 1, newHandlers, i,
569:                                handlers.length - (i + 1));
570:                        handlers = newHandlers;
571:                        codeinfo.setExceptionHandlers(newHandlers);
572:                        i--;
573:                    } else {
574:                        if (handlers[i].start == this )
575:                            handlers[i].start = nextByAddr;
576:                        if (handlers[i].end == this )
577:                            handlers[i].end = prevByAddr;
578:                        if (handlers[i].catcher == this )
579:                            handlers[i].catcher = nextByAddr;
580:                    }
581:                }
582:
583:                /* adjust local variable table and line number table */
584:                LocalVariableInfo[] lvt = codeinfo.getLocalVariableTable();
585:                if (lvt != null) {
586:                    for (int i = 0; i < lvt.length; i++) {
587:                        if (lvt[i].start == this  && lvt[i].end == this ) {
588:                            /* Remove the local variable info.
589:                             * This is very seldom, so we can make it slow
590:                             */
591:                            LocalVariableInfo[] newLVT = new LocalVariableInfo[lvt.length - 1];
592:                            System.arraycopy(lvt, 0, newLVT, 0, i);
593:                            System.arraycopy(lvt, i + 1, newLVT, i,
594:                                    newLVT.length - i);
595:                            lvt = newLVT;
596:                            codeinfo.setLocalVariableTable(newLVT);
597:                            i--;
598:                        } else {
599:                            if (lvt[i].start == this )
600:                                lvt[i].start = nextByAddr;
601:                            if (lvt[i].end == this )
602:                                lvt[i].end = prevByAddr;
603:                        }
604:                    }
605:                }
606:                LineNumber[] lnt = codeinfo.getLineNumberTable();
607:                if (lnt != null) {
608:                    for (int i = 0; i < lnt.length; i++) {
609:                        if (lnt[i].start == this ) {
610:                            if (nextByAddr.opcode == opc_impdep1
611:                                    || (i + 1 < lnt.length && lnt[i + 1].start == nextByAddr)) {
612:                                /* Remove the line number.
613:                                 * This is very seldom, so we can make it slow */
614:                                LineNumber[] newLNT = new LineNumber[lnt.length - 1];
615:                                System.arraycopy(lnt, 0, newLNT, 0, i);
616:                                System.arraycopy(lnt, i + 1, newLNT, i,
617:                                        newLNT.length - i);
618:                                lnt = newLNT;
619:                                codeinfo.setLineNumberTable(newLNT);
620:                                i--;
621:                            } else
622:                                lnt[i].start = nextByAddr;
623:                        }
624:                    }
625:                }
626:
627:                prevByAddr = null;
628:                nextByAddr = null;
629:            }
630:
631:            public int compareTo(Instruction instr) {
632:                if (addr != instr.addr)
633:                    return addr - instr.addr;
634:                if (this  == instr)
635:                    return 0;
636:                do {
637:                    instr = instr.nextByAddr;
638:                    if (instr.addr > addr)
639:                        return -1;
640:                } while (instr != this );
641:                return 1;
642:            }
643:
644:            /**
645:             * This returns the number of stack entries this instruction
646:             * pushes and pops from the stack.  The result fills the given
647:             * array.
648:             *
649:             * @param poppush an array of two ints.  The first element will
650:             * get the number of pops, the second the number of pushes.  
651:             */
652:            public void getStackPopPush(int[] poppush)
653:            /*{ require { poppush != null && poppush.length == 2
654:                :: "poppush must be an array of two ints" } } */
655:            {
656:                byte delta = (byte) stackDelta.charAt(opcode);
657:                if (delta < 0x40) {
658:                    poppush[0] = delta & 7;
659:                    poppush[1] = delta >> 3;
660:                } else {
661:                    switch (opcode) {
662:                    case opc_invokevirtual:
663:                    case opc_invokespecial:
664:                    case opc_invokestatic:
665:                    case opc_invokeinterface: {
666:                        Reference ref = getReference();
667:                        String typeSig = ref.getType();
668:                        poppush[0] = opcode != opc_invokestatic ? 1 : 0;
669:                        poppush[0] += TypeSignature.getArgumentSize(typeSig);
670:                        poppush[1] = TypeSignature.getReturnSize(typeSig);
671:                        break;
672:                    }
673:
674:                    case opc_putfield:
675:                    case opc_putstatic: {
676:                        Reference ref = getReference();
677:                        poppush[1] = 0;
678:                        poppush[0] = TypeSignature.getTypeSize(ref.getType());
679:                        if (opcode == opc_putfield)
680:                            poppush[0]++;
681:                        break;
682:                    }
683:                    case opc_getstatic:
684:                    case opc_getfield: {
685:                        Reference ref = getReference();
686:                        poppush[1] = TypeSignature.getTypeSize(ref.getType());
687:                        poppush[0] = opcode == opc_getfield ? 1 : 0;
688:                        break;
689:                    }
690:
691:                    case opc_multianewarray: {
692:                        poppush[1] = 1;
693:                        poppush[0] = getDimensions();
694:                        break;
695:                    }
696:                    default:
697:                        throw new jode.AssertError("Unknown Opcode: " + opcode);
698:                    }
699:                }
700:            }
701:
702:            public Instruction findMatchingPop() {
703:                int poppush[] = new int[2];
704:                getStackPopPush(poppush);
705:
706:                int count = poppush[1];
707:                Instruction instr = this ;
708:                while (true) {
709:                    if (instr.succs != null || instr.doesAlwaysJump())
710:                        return null;
711:                    instr = instr.nextByAddr;
712:                    if (instr.preds != null)
713:                        return null;
714:
715:                    instr.getStackPopPush(poppush);
716:                    if (count == poppush[0])
717:                        return instr;
718:                    count += poppush[1] - poppush[0];
719:                }
720:            }
721:
722:            public Instruction findMatchingPush() {
723:                int count = 0;
724:                Instruction instr = this ;
725:                int poppush[] = new int[2];
726:                while (true) {
727:                    if (instr.preds != null)
728:                        return null;
729:                    instr = instr.prevByAddr;
730:                    if (instr == null || instr.succs != null
731:                            || instr.doesAlwaysJump())
732:                        return null;
733:
734:                    instr.getStackPopPush(poppush);
735:                    if (count < poppush[1]) {
736:                        return count == 0 ? instr : null;
737:                    }
738:                    count += poppush[0] - poppush[1];
739:                }
740:            }
741:
742:            public String getDescription() {
743:                StringBuffer result = new StringBuffer(String.valueOf(addr))
744:                        .append('_').append(Integer.toHexString(hashCode()))
745:                        .append(": ").append(opcodeString[opcode]);
746:                if (opcode != opc_lookupswitch) {
747:                    if (hasLocalSlot())
748:                        result.append(' ').append(getLocalSlot());
749:                    if (succs != null)
750:                        result.append(' ').append(((Instruction) succs).addr);
751:                    if (objData != null)
752:                        result.append(' ').append(objData);
753:                    if (opcode == opc_multianewarray)
754:                        result.append(' ').append(getDimensions());
755:                } else {
756:                    int[] values = getValues();
757:                    Instruction[] succs = getSuccs();
758:                    for (int i = 0; i < values.length; i++) {
759:                        result.append(' ').append(values[i]).append("->")
760:                                .append(((Instruction) succs[i]).addr);
761:                    }
762:                    result.append(' ').append("default: ").append(
763:                            ((Instruction) succs[values.length]).addr);
764:                }
765:                return result.toString();
766:            }
767:
768:            public String toString() {
769:                return "" + addr + "_" + Integer.toHexString(hashCode());
770:            }
771:
772:            private final static String stackDelta = "\000\010\010\010\010\010\010\010\010\020\020\010\010\010\020\020\010\010\010\010\020\010\020\010\020\010\010\010\010\010\020\020\020\020\010\010\010\010\020\020\020\020\010\010\010\010\012\022\012\022\012\012\012\012\001\002\001\002\001\001\001\001\001\002\002\002\002\001\001\001\001\002\002\002\002\001\001\001\001\003\004\003\004\003\003\003\003\001\002\021\032\043\042\053\064\022\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\011\022\011\022\012\023\012\023\012\023\012\024\012\024\012\024\000\021\011\021\012\012\022\011\021\021\012\022\012\011\011\011\014\012\012\014\014\001\001\001\001\001\001\002\002\002\002\002\002\002\002\000\010\000\001\001\001\002\001\002\001\000\100\100\100\100\100\100\100\100\177\010\011\011\011\001\011\011\001\001\177\100\001\001\000\010";
773:
774:            /* stackDelta contains \100 if stack count of opcode is variable
775:             * \177 if opcode is illegal, or 8*stack_push + stack_pop otherwise
776:             * The above values are extracted from following list with: 
777:             *    perl -ne'/"(.*)"/ and print $1' 
778:             *
779:             * "\000"                             // nop
780:             * "\010\010\010\010\010\010\010\010" // aconst_null, iconst_m?[0-5]
781:             * "\020\020\010\010\010\020\020"     // [lfd]const_[0-2]
782:             * "\010\010\010\010\020"             // sipush bipush ldcx
783:             * "\010\020\010\020\010"             // [ilfda]load
784:             * "\010\010\010\010"
785:             * "\020\020\020\020"
786:             * "\010\010\010\010"
787:             * "\020\020\020\020"
788:             * "\010\010\010\010"
789:             * "\012\022\012\022\012\012\012\012" // [ilfdabcs]aload
790:             * "\001\002\001\002\001"             // [ilfda]store
791:             * "\001\001\001\001"
792:             * "\002\002\002\002"
793:             * "\001\001\001\001"
794:             * "\002\002\002\002"
795:             * "\001\001\001\001"
796:             * "\003\004\003\004\003\003\003\003" // [ilfdabcs]astore
797:             * "\001\002"                         // pop
798:             * "\021\032\043\042\053\064"         // dup2?(_x[12])?
799:             * "\022"                             // swap
800:             * "\012\024\012\024"                 // [ilfd]add
801:             * "\012\024\012\024"                 // [ilfd]sub
802:             * "\012\024\012\024"                 // [ilfd]mul
803:             * "\012\024\012\024"                 // [ilfd]div
804:             * "\012\024\012\024"                 // [ilfd]rem
805:             * "\011\022\011\022"                 // [ilfd]neg
806:             * "\012\023\012\023\012\023"         // [il]u?sh[lr]
807:             * "\012\024\012\024\012\024"         // [il](and|or|xor)
808:             * "\000"                             // opc_iinc
809:             * "\021\011\021"                     // i2[lfd]
810:             * "\012\012\022"                     // l2[ifd]
811:             * "\011\021\021"                     // f2[ild]
812:             * "\012\022\012"                     // d2[ilf]
813:             * "\011\011\011"                     // i2[bcs]
814:             * "\014\012\012\014\014"             // [lfd]cmp.?
815:             * "\001\001\001\001\001\001"         // if..
816:             * "\002\002\002\002\002\002"         // if_icmp..
817:             * "\002\002"                         // if_acmp..
818:             * "\000\010\000\001\001"             // goto,jsr,ret, .*switch
819:             * "\001\002\001\002\001\000"         // [ilfda]?return
820:             * "\100\100\100\100"                 // (get/put)(static|field)
821:             * "\100\100\100\100"                 // invoke.*
822:             * "\177\010\011\011\011"             // 186 - 190
823:             * "\001\011\011\001\001"             // 191 - 195
824:             * "\177\100\001\001"                 // 196 - 199
825:             * "\000\010"                         // goto_w, jsr_w
826:             */
827:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.