src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java

Print this page




1413             ctanns = aw;
1414         } else {
1415             aw.next = ictanns;
1416             ictanns = aw;
1417         }
1418         return aw;
1419     }
1420 
1421     @Override
1422     public void visitLineNumber(final int line, final Label start) {
1423         if (lineNumber == null) {
1424             lineNumber = new ByteVector();
1425         }
1426         ++lineNumberCount;
1427         lineNumber.putShort(start.position);
1428         lineNumber.putShort(line);
1429     }
1430 
1431     @Override
1432     public void visitMaxs(final int maxStack, final int maxLocals) {








1433         if (ClassReader.FRAMES && compute == FRAMES) {
1434             // completes the control flow graph with exception handler blocks
1435             Handler handler = firstHandler;
1436             while (handler != null) {
1437                 Label l = handler.start.getFirst();
1438                 Label h = handler.handler.getFirst();
1439                 Label e = handler.end.getFirst();
1440                 // computes the kind of the edges to 'h'
1441                 String t = handler.desc == null ? "java/lang/Throwable"
1442                         : handler.desc;
1443                 int kind = Frame.OBJECT | cw.addType(t);
1444                 // h is an exception handler
1445                 h.status |= Label.TARGET;
1446                 // adds 'h' as a successor of labels between 'start' and 'end'
1447                 while (l != e) {
1448                     // creates an edge to 'h'
1449                     Edge b = new Edge();
1450                     b.info = kind;
1451                     b.successor = h;
1452                     // adds it to the successors of 'l'


1970      *            index of last type in {@link #frame} to write (exclusive).
1971      */
1972     private void writeFrameTypes(final int start, final int end) {
1973         for (int i = start; i < end; ++i) {
1974             int t = frame[i];
1975             int d = t & Frame.DIM;
1976             if (d == 0) {
1977                 int v = t & Frame.BASE_VALUE;
1978                 switch (t & Frame.BASE_KIND) {
1979                 case Frame.OBJECT:
1980                     stackMap.putByte(7).putShort(
1981                             cw.newClass(cw.typeTable[v].strVal1));
1982                     break;
1983                 case Frame.UNINITIALIZED:
1984                     stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
1985                     break;
1986                 default:
1987                     stackMap.putByte(v);
1988                 }
1989             } else {
1990                 StringBuffer buf = new StringBuffer();
1991                 d >>= 28;
1992                 while (d-- > 0) {
1993                     buf.append('[');
1994                 }
1995                 if ((t & Frame.BASE_KIND) == Frame.OBJECT) {
1996                     buf.append('L');
1997                     buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);
1998                     buf.append(';');
1999                 } else {
2000                     switch (t & 0xF) {
2001                     case 1:
2002                         buf.append('I');
2003                         break;
2004                     case 2:
2005                         buf.append('F');
2006                         break;
2007                     case 3:
2008                         buf.append('D');
2009                         break;
2010                     case 9:
2011                         buf.append('Z');
2012                         break;
2013                     case 10:
2014                         buf.append('B');
2015                         break;
2016                     case 11:
2017                         buf.append('C');
2018                         break;
2019                     case 12:
2020                         buf.append('S');
2021                         break;
2022                     default:
2023                         buf.append('J');
2024                     }
2025                 }
2026                 stackMap.putByte(7).putShort(cw.newClass(buf.toString()));
2027             }
2028         }
2029     }
2030 
2031     private void writeFrameType(final Object type) {
2032         if (type instanceof String) {
2033             stackMap.putByte(7).putShort(cw.newClass((String) type));
2034         } else if (type instanceof Integer) {
2035             stackMap.putByte(((Integer) type).intValue());
2036         } else {
2037             stackMap.putByte(8).putShort(((Label) type).position);
2038         }
2039     }
2040 
2041     // ------------------------------------------------------------------------
2042     // Utility methods: dump bytecode array
2043     // ------------------------------------------------------------------------
2044 
2045     /**
2046      * Returns the size of the bytecode of this method.
2047      *
2048      * @return the size of the bytecode of this method.
2049      */
2050     final int getSize() {
2051         if (classReaderOffset != 0) {
2052             return 6 + classReaderLength;
2053         }
2054         if (resize) {
2055             // replaces the temporary jump opcodes introduced by Label.resolve.
2056             if (ClassReader.RESIZE) {
2057                 resizeInstructions();
2058             } else {
2059                 throw new RuntimeException("Method code too large!");
2060             }
2061         }
2062         int size = 8;
2063         if (code.length > 0) {
2064             if (code.length > 65536) {
2065                 throw new RuntimeException("Method code too large!");
2066             }
2067             cw.newUTF8("Code");
2068             size += 18 + code.length + 8 * handlerCount;
2069             if (localVar != null) {
2070                 cw.newUTF8("LocalVariableTable");
2071                 size += 8 + localVar.length;
2072             }
2073             if (localVarType != null) {
2074                 cw.newUTF8("LocalVariableTypeTable");
2075                 size += 8 + localVarType.length;
2076             }
2077             if (lineNumber != null) {
2078                 cw.newUTF8("LineNumberTable");
2079                 size += 8 + lineNumber.length;
2080             }
2081             if (stackMap != null) {


2698             case ClassWriter.LDCW_INSN:
2699             case ClassWriter.FIELDORMETH_INSN:
2700             case ClassWriter.TYPE_INSN:
2701             case ClassWriter.IINC_INSN:
2702                 newCode.putByteArray(b, u, 3);
2703                 u += 3;
2704                 break;
2705             case ClassWriter.ITFMETH_INSN:
2706             case ClassWriter.INDYMETH_INSN:
2707                 newCode.putByteArray(b, u, 5);
2708                 u += 5;
2709                 break;
2710             // case MANA_INSN:
2711             default:
2712                 newCode.putByteArray(b, u, 4);
2713                 u += 4;
2714                 break;
2715             }
2716         }
2717 
2718         // recomputes the stack map frames
2719         if (frameCount > 0) {
2720             if (compute == FRAMES) {
2721                 frameCount = 0;
2722                 stackMap = null;
2723                 previousFrame = null;
2724                 frame = null;
2725                 Frame f = new Frame();
2726                 f.owner = labels;
2727                 Type[] args = Type.getArgumentTypes(descriptor);
2728                 f.initInputFrame(cw, access, args, maxLocals);
2729                 visitFrame(f);
2730                 Label l = labels;
2731                 while (l != null) {
2732                     /*
2733                      * here we need the original label position. getNewOffset
2734                      * must therefore never have been called for this label.




2735                      */
2736                     u = l.position - 3;
2737                     if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u])) {
2738                         getNewOffset(allIndexes, allSizes, l);
2739                         // TODO update offsets in UNINITIALIZED values
2740                         visitFrame(l.frame);
2741                     }

2742                     l = l.successor;
2743                 }
2744             } else {










2745                 /*
2746                  * Resizing an existing stack map frame table is really hard.
2747                  * Not only the table must be parsed to update the offets, but
2748                  * new frames may be needed for jump instructions that were
2749                  * inserted by this method. And updating the offsets or
2750                  * inserting frames can change the format of the following
2751                  * frames, in case of packed frames. In practice the whole table
2752                  * must be recomputed. For this the frames are marked as
2753                  * potentially invalid. This will cause the whole class to be
2754                  * reread and rewritten with the COMPUTE_FRAMES option (see the
2755                  * ClassWriter.toByteArray method). This is not very efficient
2756                  * but is much easier and requires much less code than any other
2757                  * method I can think of.
2758                  */
2759                 cw.invalidFrames = true;
2760             }
2761         }
2762         // updates the exception handler block labels
2763         Handler h = firstHandler;
2764         while (h != null) {
2765             getNewOffset(allIndexes, allSizes, h.start);
2766             getNewOffset(allIndexes, allSizes, h.end);
2767             getNewOffset(allIndexes, allSizes, h.handler);
2768             h = h.next;
2769         }
2770         // updates the instructions addresses in the
2771         // local var and line number tables
2772         for (i = 0; i < 2; ++i) {
2773             ByteVector bv = i == 0 ? localVar : localVarType;
2774             if (bv != null) {
2775                 b = bv.data;
2776                 u = 0;
2777                 while (u < bv.length) {
2778                     label = readUnsignedShort(b, u);
2779                     newOffset = getNewOffset(allIndexes, allSizes, 0, label);
2780                     writeShort(b, u, newOffset);
2781                     label += readUnsignedShort(b, u + 2);




1413             ctanns = aw;
1414         } else {
1415             aw.next = ictanns;
1416             ictanns = aw;
1417         }
1418         return aw;
1419     }
1420 
1421     @Override
1422     public void visitLineNumber(final int line, final Label start) {
1423         if (lineNumber == null) {
1424             lineNumber = new ByteVector();
1425         }
1426         ++lineNumberCount;
1427         lineNumber.putShort(start.position);
1428         lineNumber.putShort(line);
1429     }
1430 
1431     @Override
1432     public void visitMaxs(final int maxStack, final int maxLocals) {
1433         if (resize) {
1434             // replaces the temporary jump opcodes introduced by Label.resolve.
1435             if (ClassReader.RESIZE) {
1436                 resizeInstructions();
1437             } else {
1438                 throw new RuntimeException("Method code too large!");
1439             }
1440         }
1441         if (ClassReader.FRAMES && compute == FRAMES) {
1442             // completes the control flow graph with exception handler blocks
1443             Handler handler = firstHandler;
1444             while (handler != null) {
1445                 Label l = handler.start.getFirst();
1446                 Label h = handler.handler.getFirst();
1447                 Label e = handler.end.getFirst();
1448                 // computes the kind of the edges to 'h'
1449                 String t = handler.desc == null ? "java/lang/Throwable"
1450                         : handler.desc;
1451                 int kind = Frame.OBJECT | cw.addType(t);
1452                 // h is an exception handler
1453                 h.status |= Label.TARGET;
1454                 // adds 'h' as a successor of labels between 'start' and 'end'
1455                 while (l != e) {
1456                     // creates an edge to 'h'
1457                     Edge b = new Edge();
1458                     b.info = kind;
1459                     b.successor = h;
1460                     // adds it to the successors of 'l'


1978      *            index of last type in {@link #frame} to write (exclusive).
1979      */
1980     private void writeFrameTypes(final int start, final int end) {
1981         for (int i = start; i < end; ++i) {
1982             int t = frame[i];
1983             int d = t & Frame.DIM;
1984             if (d == 0) {
1985                 int v = t & Frame.BASE_VALUE;
1986                 switch (t & Frame.BASE_KIND) {
1987                 case Frame.OBJECT:
1988                     stackMap.putByte(7).putShort(
1989                             cw.newClass(cw.typeTable[v].strVal1));
1990                     break;
1991                 case Frame.UNINITIALIZED:
1992                     stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
1993                     break;
1994                 default:
1995                     stackMap.putByte(v);
1996                 }
1997             } else {
1998                 StringBuilder sb = new StringBuilder();
1999                 d >>= 28;
2000                 while (d-- > 0) {
2001                     sb.append('[');
2002                 }
2003                 if ((t & Frame.BASE_KIND) == Frame.OBJECT) {
2004                     sb.append('L');
2005                     sb.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);
2006                     sb.append(';');
2007                 } else {
2008                     switch (t & 0xF) {
2009                     case 1:
2010                         sb.append('I');
2011                         break;
2012                     case 2:
2013                         sb.append('F');
2014                         break;
2015                     case 3:
2016                         sb.append('D');
2017                         break;
2018                     case 9:
2019                         sb.append('Z');
2020                         break;
2021                     case 10:
2022                         sb.append('B');
2023                         break;
2024                     case 11:
2025                         sb.append('C');
2026                         break;
2027                     case 12:
2028                         sb.append('S');
2029                         break;
2030                     default:
2031                         sb.append('J');
2032                     }
2033                 }
2034                 stackMap.putByte(7).putShort(cw.newClass(sb.toString()));
2035             }
2036         }
2037     }
2038 
2039     private void writeFrameType(final Object type) {
2040         if (type instanceof String) {
2041             stackMap.putByte(7).putShort(cw.newClass((String) type));
2042         } else if (type instanceof Integer) {
2043             stackMap.putByte(((Integer) type).intValue());
2044         } else {
2045             stackMap.putByte(8).putShort(((Label) type).position);
2046         }
2047     }
2048 
2049     // ------------------------------------------------------------------------
2050     // Utility methods: dump bytecode array
2051     // ------------------------------------------------------------------------
2052 
2053     /**
2054      * Returns the size of the bytecode of this method.
2055      *
2056      * @return the size of the bytecode of this method.
2057      */
2058     final int getSize() {
2059         if (classReaderOffset != 0) {
2060             return 6 + classReaderLength;
2061         }








2062         int size = 8;
2063         if (code.length > 0) {
2064             if (code.length > 65536) {
2065                 throw new RuntimeException("Method code too large!");
2066             }
2067             cw.newUTF8("Code");
2068             size += 18 + code.length + 8 * handlerCount;
2069             if (localVar != null) {
2070                 cw.newUTF8("LocalVariableTable");
2071                 size += 8 + localVar.length;
2072             }
2073             if (localVarType != null) {
2074                 cw.newUTF8("LocalVariableTypeTable");
2075                 size += 8 + localVarType.length;
2076             }
2077             if (lineNumber != null) {
2078                 cw.newUTF8("LineNumberTable");
2079                 size += 8 + lineNumber.length;
2080             }
2081             if (stackMap != null) {


2698             case ClassWriter.LDCW_INSN:
2699             case ClassWriter.FIELDORMETH_INSN:
2700             case ClassWriter.TYPE_INSN:
2701             case ClassWriter.IINC_INSN:
2702                 newCode.putByteArray(b, u, 3);
2703                 u += 3;
2704                 break;
2705             case ClassWriter.ITFMETH_INSN:
2706             case ClassWriter.INDYMETH_INSN:
2707                 newCode.putByteArray(b, u, 5);
2708                 u += 5;
2709                 break;
2710             // case MANA_INSN:
2711             default:
2712                 newCode.putByteArray(b, u, 4);
2713                 u += 4;
2714                 break;
2715             }
2716         }
2717 
2718         // updates the stack map frame labels

2719         if (compute == FRAMES) {









2720             Label l = labels;
2721             while (l != null) {
2722                 /*
2723                  * Detects the labels that are just after an IF instruction that
2724                  * has been resized with the IFNOT GOTO_W pattern. These labels
2725                  * are now the target of a jump instruction (the IFNOT
2726                  * instruction). Note that we need the original label position
2727                  * here. getNewOffset must therefore never have been called for
2728                  * this label.
2729                  */
2730                 u = l.position - 3;
2731                 if (u >= 0 && resize[u]) {
2732                     l.status |= Label.TARGET;


2733                 }
2734                 getNewOffset(allIndexes, allSizes, l);
2735                 l = l.successor;
2736             }
2737             // Update the offsets in the uninitialized types
2738             for (i = 0; i < cw.typeTable.length; ++i) {
2739                 Item item = cw.typeTable[i];
2740                 if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
2741                     item.intVal = getNewOffset(allIndexes, allSizes, 0,
2742                             item.intVal);
2743                 }
2744             }
2745             // The stack map frames are not serialized yet, so we don't need
2746             // to update them. They will be serialized in visitMaxs.
2747         } else if (frameCount > 0) {
2748             /*
2749              * Resizing an existing stack map frame table is really hard. Not
2750              * only the table must be parsed to update the offets, but new
2751              * frames may be needed for jump instructions that were inserted by
2752              * this method. And updating the offsets or inserting frames can
2753              * change the format of the following frames, in case of packed
2754              * frames. In practice the whole table must be recomputed. For this
2755              * the frames are marked as potentially invalid. This will cause the
2756              * whole class to be reread and rewritten with the COMPUTE_FRAMES
2757              * option (see the ClassWriter.toByteArray method). This is not very
2758              * efficient but is much easier and requires much less code than any
2759              * other method I can think of.

2760              */
2761             cw.invalidFrames = true;
2762         }

2763         // updates the exception handler block labels
2764         Handler h = firstHandler;
2765         while (h != null) {
2766             getNewOffset(allIndexes, allSizes, h.start);
2767             getNewOffset(allIndexes, allSizes, h.end);
2768             getNewOffset(allIndexes, allSizes, h.handler);
2769             h = h.next;
2770         }
2771         // updates the instructions addresses in the
2772         // local var and line number tables
2773         for (i = 0; i < 2; ++i) {
2774             ByteVector bv = i == 0 ? localVar : localVarType;
2775             if (bv != null) {
2776                 b = bv.data;
2777                 u = 0;
2778                 while (u < bv.length) {
2779                     label = readUnsignedShort(b, u);
2780                     newOffset = getNewOffset(allIndexes, allSizes, 0, label);
2781                     writeShort(b, u, newOffset);
2782                     label += readUnsignedShort(b, u + 2);