< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java

Print this page




  33 
  34 import java.util.function.ToIntBiFunction;
  35 import java.util.function.ToIntFunction;
  36 
  37 import static com.sun.tools.javac.code.TypeTag.BOT;
  38 import static com.sun.tools.javac.code.TypeTag.INT;
  39 import static com.sun.tools.javac.jvm.ByteCodes.*;
  40 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
  41 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
  42 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
  43 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
  44 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Integer;
  45 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InterfaceMethodref;
  46 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Long;
  47 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodHandle;
  48 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
  49 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Methodref;
  50 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_String;
  51 import static com.sun.tools.javac.jvm.UninitializedType.*;
  52 import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;

  53 
  54 /** An internal structure that corresponds to the code attribute of
  55  *  methods in a classfile. The class also provides some utility operations to
  56  *  generate bytecode instructions.
  57  *
  58  *  <p><b>This is NOT part of any supported API.
  59  *  If you write code that depends on this, you do so at your own risk.
  60  *  This code and its internal interfaces are subject to change or
  61  *  deletion without notice.</b>
  62  */
  63 public class Code {
  64 
  65     public final boolean debugCode;
  66     public final boolean needStackMap;
  67 
  68     public enum StackMapFormat {
  69         NONE,
  70         CLDC {
  71             Name getAttributeName(Names names) {
  72                 return names.StackMap;


2058         } else {
2059             state.defined.incl(adr);
2060             if (cp < Character.MAX_VALUE) {
2061                 v.openRange((char)cp);
2062             }
2063         }
2064     }
2065 
2066     /** Mark a register as being undefined. */
2067     public void setUndefined(int adr) {
2068         state.defined.excl(adr);
2069         if (adr < lvar.length &&
2070             lvar[adr] != null &&
2071             lvar[adr].isLastRangeInitialized()) {
2072             LocalVar v = lvar[adr];
2073             char length = (char)(curCP() - v.lastRange().start_pc);
2074             if (length < Character.MAX_VALUE) {
2075                 lvar[adr] = v.dup();
2076                 v.closeRange(length);
2077                 putVar(v);

2078             } else {
2079                 v.removeLastRange();
2080             }
2081         }
2082     }
2083 
2084     /** End the scope of a variable. */
2085     private void endScope(int adr) {
2086         LocalVar v = lvar[adr];
2087         if (v != null) {
2088             if (v.isLastRangeInitialized()) {
2089                 char length = (char)(curCP() - v.lastRange().start_pc);
2090                 if (length < Character.MAX_VALUE) {
2091                     v.closeRange(length);
2092                     putVar(v);
2093                     fillLocalVarPosition(v);
2094                 }
2095             }
2096             /** the call to curCP() can implicitly adjust the current cp, if so
2097              * the alive range of local variables may be modified. Thus we need
2098              * all of them. For this reason assigning null to the given address
2099              * should be the last action to do.
2100              */
2101             lvar[adr] = null;
2102         }
2103         state.defined.excl(adr);
2104     }
2105 
2106     private void fillLocalVarPosition(LocalVar lv) {
2107         if (lv == null || lv.sym == null || lv.sym.isExceptionParameter()|| !lv.sym.hasTypeAnnotations())
2108             return;
2109         LocalVar.Range widestRange = lv.getWidestRange();





2110         for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
2111             TypeAnnotationPosition p = ta.position;
2112             if (widestRange.closed() && widestRange.length > 0) {
2113                 p.lvarOffset = new int[] { (int)widestRange.start_pc };
2114                 p.lvarLength = new int[] { (int)widestRange.length };
2115                 p.lvarIndex = new int[] { (int)lv.reg };
2116                 p.isValidOffset = true;
2117             } else {
2118                 p.isValidOffset = false;
2119             }
2120         }










2121     }
2122 
2123     // Method to be called after compressCatchTable to
2124     // fill in the exception table index for type
2125     // annotations on exception parameters.
2126     public void fillExceptionParameterPositions() {
2127         for (int i = 0; i < varBufferSize; ++i) {
2128             LocalVar lv = varBuffer[i];
2129             if (lv == null || lv.sym == null
2130                     || !lv.sym.hasTypeAnnotations()
2131                     || !lv.sym.isExceptionParameter())
2132                 continue;
2133 
2134             for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
2135                 TypeAnnotationPosition p = ta.position;
2136                 if (p.hasCatchType()) {
2137                     final int idx = findExceptionIndex(p);
2138                     if (idx == -1)
2139                         Assert.error("Could not find exception index for type annotation " +
2140                                      ta + " on exception parameter");




  33 
  34 import java.util.function.ToIntBiFunction;
  35 import java.util.function.ToIntFunction;
  36 
  37 import static com.sun.tools.javac.code.TypeTag.BOT;
  38 import static com.sun.tools.javac.code.TypeTag.INT;
  39 import static com.sun.tools.javac.jvm.ByteCodes.*;
  40 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
  41 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
  42 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
  43 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
  44 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Integer;
  45 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InterfaceMethodref;
  46 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Long;
  47 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodHandle;
  48 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
  49 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Methodref;
  50 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_String;
  51 import static com.sun.tools.javac.jvm.UninitializedType.*;
  52 import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
  53 import java.util.Arrays;
  54 
  55 /** An internal structure that corresponds to the code attribute of
  56  *  methods in a classfile. The class also provides some utility operations to
  57  *  generate bytecode instructions.
  58  *
  59  *  <p><b>This is NOT part of any supported API.
  60  *  If you write code that depends on this, you do so at your own risk.
  61  *  This code and its internal interfaces are subject to change or
  62  *  deletion without notice.</b>
  63  */
  64 public class Code {
  65 
  66     public final boolean debugCode;
  67     public final boolean needStackMap;
  68 
  69     public enum StackMapFormat {
  70         NONE,
  71         CLDC {
  72             Name getAttributeName(Names names) {
  73                 return names.StackMap;


2059         } else {
2060             state.defined.incl(adr);
2061             if (cp < Character.MAX_VALUE) {
2062                 v.openRange((char)cp);
2063             }
2064         }
2065     }
2066 
2067     /** Mark a register as being undefined. */
2068     public void setUndefined(int adr) {
2069         state.defined.excl(adr);
2070         if (adr < lvar.length &&
2071             lvar[adr] != null &&
2072             lvar[adr].isLastRangeInitialized()) {
2073             LocalVar v = lvar[adr];
2074             char length = (char)(curCP() - v.lastRange().start_pc);
2075             if (length < Character.MAX_VALUE) {
2076                 lvar[adr] = v.dup();
2077                 v.closeRange(length);
2078                 putVar(v);
2079                 fillLocalVarPosition(v);
2080             } else {
2081                 v.removeLastRange();
2082             }
2083         }
2084     }
2085 
2086     /** End the scope of a variable. */
2087     private void endScope(int adr) {
2088         LocalVar v = lvar[adr];
2089         if (v != null) {
2090             if (v.isLastRangeInitialized()) {
2091                 char length = (char)(curCP() - v.lastRange().start_pc);
2092                 if (length < Character.MAX_VALUE) {
2093                     v.closeRange(length);
2094                     putVar(v);
2095                     fillLocalVarPosition(v);
2096                 }
2097             }
2098             /** the call to curCP() can implicitly adjust the current cp, if so
2099              * the alive range of local variables may be modified. Thus we need
2100              * all of them. For this reason assigning null to the given address
2101              * should be the last action to do.
2102              */
2103             lvar[adr] = null;
2104         }
2105         state.defined.excl(adr);
2106     }
2107 
2108     private void fillLocalVarPosition(LocalVar lv) {
2109         if (lv == null || lv.sym == null || lv.sym.isExceptionParameter()|| !lv.sym.hasTypeAnnotations())
2110             return;
2111         LocalVar.Range[] validRanges = lv.aliveRanges.stream().filter(r -> r.closed() && r.length > 0).toArray(s -> new LocalVar.Range[s]);
2112         if (validRanges.length == 0)
2113             return ;
2114         int[] lvarOffset = Arrays.stream(validRanges).mapToInt(r -> r.start_pc).toArray();
2115         int[] lvarLength = Arrays.stream(validRanges).mapToInt(r -> r.length).toArray();
2116         int[] lvarIndex = Arrays.stream(validRanges).mapToInt(r -> lv.reg).toArray();
2117         for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
2118             TypeAnnotationPosition p = ta.position;
2119             p.lvarOffset = appendArray(p.lvarOffset, lvarOffset);
2120             p.lvarLength = appendArray(p.lvarLength, lvarLength);
2121             p.lvarIndex = appendArray(p.lvarIndex, lvarIndex);
2122             p.isValidOffset = true;




2123         }
2124     }
2125 
2126     private int[] appendArray(int[] source, int[] append) {
2127         if (source == null || source.length == 0) return append;
2128 
2129         int[] result = new int[source.length + append.length];
2130 
2131         System.arraycopy(source, 0, result, 0, source.length);
2132         System.arraycopy(append, 0, result, source.length, append.length);
2133         return result;
2134     }
2135 
2136     // Method to be called after compressCatchTable to
2137     // fill in the exception table index for type
2138     // annotations on exception parameters.
2139     public void fillExceptionParameterPositions() {
2140         for (int i = 0; i < varBufferSize; ++i) {
2141             LocalVar lv = varBuffer[i];
2142             if (lv == null || lv.sym == null
2143                     || !lv.sym.hasTypeAnnotations()
2144                     || !lv.sym.isExceptionParameter())
2145                 continue;
2146 
2147             for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
2148                 TypeAnnotationPosition p = ta.position;
2149                 if (p.hasCatchType()) {
2150                     final int idx = findExceptionIndex(p);
2151                     if (idx == -1)
2152                         Assert.error("Could not find exception index for type annotation " +
2153                                      ta + " on exception parameter");


< prev index next >