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

changeset 2027
4932bb04c4b8
parent 1853
831467c4c6a7
child 2047
5f915a0c9615
equal deleted inserted replaced
2026:03c26c60499c 2027:4932bb04c4b8
26 package com.sun.tools.javac.jvm; 26 package com.sun.tools.javac.jvm;
27 27
28 import com.sun.tools.javac.code.*; 28 import com.sun.tools.javac.code.*;
29 import com.sun.tools.javac.code.Symbol.*; 29 import com.sun.tools.javac.code.Symbol.*;
30 import com.sun.tools.javac.code.Types.UniqueType; 30 import com.sun.tools.javac.code.Types.UniqueType;
31 import com.sun.tools.javac.tree.JCTree;
31 import com.sun.tools.javac.util.*; 32 import com.sun.tools.javac.util.*;
32 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 33 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
33 34
34 import static com.sun.tools.javac.code.TypeTag.BOT; 35 import static com.sun.tools.javac.code.TypeTag.BOT;
35 import static com.sun.tools.javac.code.TypeTag.INT; 36 import static com.sun.tools.javac.code.TypeTag.INT;
179 */ 180 */
180 final Pool pool; 181 final Pool pool;
181 182
182 final MethodSymbol meth; 183 final MethodSymbol meth;
183 184
185 final LVTRanges lvtRanges;
186
184 /** Construct a code object, given the settings of the fatcode, 187 /** Construct a code object, given the settings of the fatcode,
185 * debugging info switches and the CharacterRangeTable. 188 * debugging info switches and the CharacterRangeTable.
186 */ 189 */
187 public Code(MethodSymbol meth, 190 public Code(MethodSymbol meth,
188 boolean fatcode, 191 boolean fatcode,
191 StackMapFormat stackMap, 194 StackMapFormat stackMap,
192 boolean debugCode, 195 boolean debugCode,
193 CRTable crt, 196 CRTable crt,
194 Symtab syms, 197 Symtab syms,
195 Types types, 198 Types types,
196 Pool pool) { 199 Pool pool,
200 LVTRanges lvtRanges) {
197 this.meth = meth; 201 this.meth = meth;
198 this.fatcode = fatcode; 202 this.fatcode = fatcode;
199 this.lineMap = lineMap; 203 this.lineMap = lineMap;
200 this.lineDebugInfo = lineMap != null; 204 this.lineDebugInfo = lineMap != null;
201 this.varDebugInfo = varDebugInfo; 205 this.varDebugInfo = varDebugInfo;
213 this.needStackMap = false; 217 this.needStackMap = false;
214 } 218 }
215 state = new State(); 219 state = new State();
216 lvar = new LocalVar[20]; 220 lvar = new LocalVar[20];
217 this.pool = pool; 221 this.pool = pool;
222 this.lvtRanges = lvtRanges;
218 } 223 }
219 224
220 225
221 /* ************************************************************************** 226 /* **************************************************************************
222 * Typecodes & related stuff 227 * Typecodes & related stuff
303 * Emit code 308 * Emit code
304 ****************************************************************************/ 309 ****************************************************************************/
305 310
306 /** The current output code pointer. 311 /** The current output code pointer.
307 */ 312 */
308 public int curPc() { 313 public int curCP() {
309 if (pendingJumps != null) resolvePending(); 314 /*
310 if (pendingStatPos != Position.NOPOS) markStatBegin(); 315 * This method has side-effects because calling it can indirectly provoke
316 * extra code generation, like goto instructions, depending on the context
317 * where it's called.
318 * Use with care or even better avoid using it.
319 */
320 if (pendingJumps != null) {
321 resolvePending();
322 }
323 if (pendingStatPos != Position.NOPOS) {
324 markStatBegin();
325 }
311 fixedPc = true; 326 fixedPc = true;
312 return cp; 327 return cp;
313 } 328 }
314 329
315 /** Emit a byte of code. 330 /** Emit a byte of code.
1173 } 1188 }
1174 1189
1175 /** Declare an entry point; return current code pointer 1190 /** Declare an entry point; return current code pointer
1176 */ 1191 */
1177 public int entryPoint() { 1192 public int entryPoint() {
1178 int pc = curPc(); 1193 int pc = curCP();
1179 alive = true; 1194 alive = true;
1180 pendingStackMap = needStackMap; 1195 pendingStackMap = needStackMap;
1181 return pc; 1196 return pc;
1182 } 1197 }
1183 1198
1184 /** Declare an entry point with initial state; 1199 /** Declare an entry point with initial state;
1185 * return current code pointer 1200 * return current code pointer
1186 */ 1201 */
1187 public int entryPoint(State state) { 1202 public int entryPoint(State state) {
1188 int pc = curPc(); 1203 int pc = curCP();
1189 alive = true; 1204 alive = true;
1190 this.state = state.dup(); 1205 this.state = state.dup();
1191 Assert.check(state.stacksize <= max_stack); 1206 Assert.check(state.stacksize <= max_stack);
1192 if (debugCode) System.err.println("entry point " + state); 1207 if (debugCode) System.err.println("entry point " + state);
1193 pendingStackMap = needStackMap; 1208 pendingStackMap = needStackMap;
1196 1211
1197 /** Declare an entry point with initial state plus a pushed value; 1212 /** Declare an entry point with initial state plus a pushed value;
1198 * return current code pointer 1213 * return current code pointer
1199 */ 1214 */
1200 public int entryPoint(State state, Type pushed) { 1215 public int entryPoint(State state, Type pushed) {
1201 int pc = curPc(); 1216 int pc = curCP();
1202 alive = true; 1217 alive = true;
1203 this.state = state.dup(); 1218 this.state = state.dup();
1204 Assert.check(state.stacksize <= max_stack); 1219 Assert.check(state.stacksize <= max_stack);
1205 this.state.push(pushed); 1220 this.state.push(pushed);
1206 if (debugCode) System.err.println("entry point " + state); 1221 if (debugCode) System.err.println("entry point " + state);
1236 /** The stack map frame before the last one. */ 1251 /** The stack map frame before the last one. */
1237 StackMapFrame frameBeforeLast = null; 1252 StackMapFrame frameBeforeLast = null;
1238 1253
1239 /** Emit a stack map entry. */ 1254 /** Emit a stack map entry. */
1240 public void emitStackMap() { 1255 public void emitStackMap() {
1241 int pc = curPc(); 1256 int pc = curCP();
1242 if (!needStackMap) return; 1257 if (!needStackMap) return;
1243 1258
1244 1259
1245 1260
1246 switch (stackMap) { 1261 switch (stackMap) {
1480 } 1495 }
1481 if (get1(chain.pc) == goto_ && 1496 if (get1(chain.pc) == goto_ &&
1482 chain.pc + 3 == target && target == cp && !fixedPc) { 1497 chain.pc + 3 == target && target == cp && !fixedPc) {
1483 // If goto the next instruction, the jump is not needed: 1498 // If goto the next instruction, the jump is not needed:
1484 // compact the code. 1499 // compact the code.
1500 if (varDebugInfo) {
1501 adjustAliveRanges(cp, -3);
1502 }
1485 cp = cp - 3; 1503 cp = cp - 3;
1486 target = target - 3; 1504 target = target - 3;
1487 if (chain.next == null) { 1505 if (chain.next == null) {
1488 // This is the only jump to the target. Exit the loop 1506 // This is the only jump to the target. Exit the loop
1489 // without setting new state. The code is reachable 1507 // without setting new state. The code is reachable
1779 if (lv != null && lv.sym.type == old) { 1797 if (lv != null && lv.sym.type == old) {
1780 VarSymbol sym = lv.sym; 1798 VarSymbol sym = lv.sym;
1781 sym = sym.clone(sym.owner); 1799 sym = sym.clone(sym.owner);
1782 sym.type = newtype; 1800 sym.type = newtype;
1783 LocalVar newlv = lvar[i] = new LocalVar(sym); 1801 LocalVar newlv = lvar[i] = new LocalVar(sym);
1784 // should the following be initialized to cp? 1802 newlv.aliveRanges = lv.aliveRanges;
1785 newlv.start_pc = lv.start_pc;
1786 } 1803 }
1787 } 1804 }
1788 } 1805 }
1789 1806
1790 State join(State other) { 1807 State join(State other) {
1868 1885
1869 /** A live range of a local variable. */ 1886 /** A live range of a local variable. */
1870 static class LocalVar { 1887 static class LocalVar {
1871 final VarSymbol sym; 1888 final VarSymbol sym;
1872 final char reg; 1889 final char reg;
1873 char start_pc = Character.MAX_VALUE; 1890
1874 char length = Character.MAX_VALUE; 1891 class Range {
1892 char start_pc = Character.MAX_VALUE;
1893 char length = Character.MAX_VALUE;
1894
1895 Range() {}
1896
1897 Range(char start) {
1898 this.start_pc = start;
1899 }
1900
1901 Range(char start, char length) {
1902 this.start_pc = start;
1903 this.length = length;
1904 }
1905
1906 boolean closed() {
1907 return start_pc != Character.MAX_VALUE && length != Character.MAX_VALUE;
1908 }
1909
1910 @Override
1911 public String toString() {
1912 int currentStartPC = start_pc;
1913 int currentLength = length;
1914 return "startpc = " + currentStartPC + " length " + currentLength;
1915 }
1916 }
1917
1918 java.util.List<Range> aliveRanges = new java.util.ArrayList<>();
1919
1875 LocalVar(VarSymbol v) { 1920 LocalVar(VarSymbol v) {
1876 this.sym = v; 1921 this.sym = v;
1877 this.reg = (char)v.adr; 1922 this.reg = (char)v.adr;
1878 } 1923 }
1879 public LocalVar dup() { 1924 public LocalVar dup() {
1880 return new LocalVar(sym); 1925 return new LocalVar(sym);
1881 } 1926 }
1927
1928 Range firstRange() {
1929 return aliveRanges.isEmpty() ? null : aliveRanges.get(0);
1930 }
1931
1932 Range lastRange() {
1933 return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1);
1934 }
1935
1936 @Override
1882 public String toString() { 1937 public String toString() {
1883 return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length); 1938 if (aliveRanges == null) {
1884 } 1939 return "empty local var";
1940 }
1941 StringBuilder sb = new StringBuilder().append(sym)
1942 .append(" in register ").append((int)reg).append(" \n");
1943 for (Range r : aliveRanges) {
1944 sb.append(" starts at pc=").append(Integer.toString(((int)r.start_pc)))
1945 .append(" length=").append(Integer.toString(((int)r.length)))
1946 .append("\n");
1947 }
1948 return sb.toString();
1949 }
1950
1951 public void openRange(char start) {
1952 if (!hasOpenRange()) {
1953 aliveRanges.add(new Range(start));
1954 }
1955 }
1956
1957 public void closeRange(char end) {
1958 if (isLastRangeInitialized()) {
1959 Range range = lastRange();
1960 if (range != null) {
1961 if (range.length == Character.MAX_VALUE) {
1962 range.length = end;
1963 }
1964 }
1965 } else {
1966 if (!aliveRanges.isEmpty()) {
1967 aliveRanges.remove(aliveRanges.size() - 1);
1968 }
1969 }
1970 }
1971
1972 public boolean hasOpenRange() {
1973 if (aliveRanges.isEmpty()) {
1974 return false;
1975 }
1976 Range range = lastRange();
1977 return range.length == Character.MAX_VALUE;
1978 }
1979
1980 public boolean isLastRangeInitialized() {
1981 if (aliveRanges.isEmpty()) {
1982 return false;
1983 }
1984 Range range = lastRange();
1985 return range.start_pc != Character.MAX_VALUE;
1986 }
1987
1988 public Range getWidestRange() {
1989 if (aliveRanges.isEmpty()) {
1990 return new Range();
1991 } else {
1992 Range firstRange = firstRange();
1993 Range lastRange = lastRange();
1994 char length = (char)(lastRange.length + (lastRange.start_pc - firstRange.start_pc));
1995 return new Range(firstRange.start_pc, length);
1996 }
1997 }
1998
1885 }; 1999 };
1886 2000
1887 /** Local variables, indexed by register. */ 2001 /** Local variables, indexed by register. */
1888 LocalVar[] lvar; 2002 LocalVar[] lvar;
1889 2003
1890 /** Add a new local variable. */ 2004 /** Add a new local variable. */
1891 private void addLocalVar(VarSymbol v) { 2005 private void addLocalVar(VarSymbol v) {
1892 int adr = v.adr; 2006 int adr = v.adr;
1893 lvar = ArrayUtils.ensureCapacity(lvar, adr+1); 2007 lvar = ArrayUtils.ensureCapacity(lvar, adr+1);
1894 Assert.checkNull(lvar[adr]); 2008 Assert.checkNull(lvar[adr]);
1895 if (pendingJumps != null) resolvePending(); 2009 if (pendingJumps != null) {
2010 resolvePending();
2011 }
1896 lvar[adr] = new LocalVar(v); 2012 lvar[adr] = new LocalVar(v);
1897 state.defined.excl(adr); 2013 state.defined.excl(adr);
2014 }
2015
2016
2017 public void closeAliveRanges(JCTree tree) {
2018 closeAliveRanges(tree, cp);
2019 }
2020
2021 public void closeAliveRanges(JCTree tree, int closingCP) {
2022 List<VarSymbol> locals = lvtRanges.getVars(meth, tree);
2023 for (LocalVar localVar: lvar) {
2024 for (VarSymbol aliveLocal : locals) {
2025 if (localVar == null) {
2026 return;
2027 }
2028 if (localVar.sym == aliveLocal && localVar.lastRange() != null) {
2029 char length = (char)(closingCP - localVar.lastRange().start_pc);
2030 if (length > 0 && length < Character.MAX_VALUE) {
2031 localVar.closeRange(length);
2032 }
2033 }
2034 }
2035 }
2036 }
2037
2038 void adjustAliveRanges(int oldCP, int delta) {
2039 for (LocalVar localVar: lvar) {
2040 if (localVar == null) {
2041 return;
2042 }
2043 for (LocalVar.Range range: localVar.aliveRanges) {
2044 if (range.closed() && range.start_pc + range.length >= oldCP) {
2045 range.length += delta;
2046 }
2047 }
2048 }
2049 }
2050
2051 /**
2052 * Calculates the size of the LocalVariableTable.
2053 */
2054 public int getLVTSize() {
2055 int result = varBufferSize;
2056 for (int i = 0; i < varBufferSize; i++) {
2057 LocalVar var = varBuffer[i];
2058 result += var.aliveRanges.size() - 1;
2059 }
2060 return result;
1898 } 2061 }
1899 2062
1900 /** Set the current variable defined state. */ 2063 /** Set the current variable defined state. */
1901 public void setDefined(Bits newDefined) { 2064 public void setDefined(Bits newDefined) {
1902 if (alive && newDefined != state.defined) { 2065 if (alive && newDefined != state.defined) {
1920 if (v == null) { 2083 if (v == null) {
1921 state.defined.excl(adr); 2084 state.defined.excl(adr);
1922 } else { 2085 } else {
1923 state.defined.incl(adr); 2086 state.defined.incl(adr);
1924 if (cp < Character.MAX_VALUE) { 2087 if (cp < Character.MAX_VALUE) {
1925 if (v.start_pc == Character.MAX_VALUE) 2088 v.openRange((char)cp);
1926 v.start_pc = (char)cp;
1927 } 2089 }
1928 } 2090 }
1929 } 2091 }
1930 2092
1931 /** Mark a register as being undefined. */ 2093 /** Mark a register as being undefined. */
1932 public void setUndefined(int adr) { 2094 public void setUndefined(int adr) {
1933 state.defined.excl(adr); 2095 state.defined.excl(adr);
1934 if (adr < lvar.length && 2096 if (adr < lvar.length &&
1935 lvar[adr] != null && 2097 lvar[adr] != null &&
1936 lvar[adr].start_pc != Character.MAX_VALUE) { 2098 lvar[adr].isLastRangeInitialized()) {
1937 LocalVar v = lvar[adr]; 2099 LocalVar v = lvar[adr];
1938 char length = (char)(curPc() - v.start_pc); 2100 char length = (char)(curCP() - v.lastRange().start_pc);
1939 if (length > 0 && length < Character.MAX_VALUE) { 2101 if (length > 0 && length < Character.MAX_VALUE) {
1940 lvar[adr] = v.dup(); 2102 lvar[adr] = v.dup();
1941 v.length = length; 2103 v.closeRange(length);
1942 putVar(v); 2104 putVar(v);
1943 } else { 2105 } else {
1944 v.start_pc = Character.MAX_VALUE; 2106 v.lastRange().start_pc = Character.MAX_VALUE;
1945 } 2107 }
1946 } 2108 }
1947 } 2109 }
1948 2110
1949 /** End the scope of a variable. */ 2111 /** End the scope of a variable. */
1950 private void endScope(int adr) { 2112 private void endScope(int adr) {
1951 LocalVar v = lvar[adr]; 2113 LocalVar v = lvar[adr];
1952 if (v != null) { 2114 if (v != null) {
1953 lvar[adr] = null; 2115 lvar[adr] = null;
1954 if (v.start_pc != Character.MAX_VALUE) { 2116 if (v.isLastRangeInitialized()) {
1955 char length = (char)(curPc() - v.start_pc); 2117 char length = (char)(curCP() - v.lastRange().start_pc);
1956 if (length < Character.MAX_VALUE) { 2118 if (length < Character.MAX_VALUE) {
1957 v.length = length; 2119 v.closeRange(length);
1958 putVar(v); 2120 putVar(v);
1959 fillLocalVarPosition(v); 2121 fillLocalVarPosition(v);
1960 } 2122 }
1961 } 2123 }
1962 } 2124 }
1966 private void fillLocalVarPosition(LocalVar lv) { 2128 private void fillLocalVarPosition(LocalVar lv) {
1967 if (lv == null || lv.sym == null || !lv.sym.hasTypeAnnotations()) 2129 if (lv == null || lv.sym == null || !lv.sym.hasTypeAnnotations())
1968 return; 2130 return;
1969 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { 2131 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
1970 TypeAnnotationPosition p = ta.position; 2132 TypeAnnotationPosition p = ta.position;
1971 p.lvarOffset = new int[] { (int)lv.start_pc }; 2133 LocalVar.Range widestRange = lv.getWidestRange();
1972 p.lvarLength = new int[] { (int)lv.length }; 2134 p.lvarOffset = new int[] { (int)widestRange.start_pc };
2135 p.lvarLength = new int[] { (int)widestRange.length };
1973 p.lvarIndex = new int[] { (int)lv.reg }; 2136 p.lvarIndex = new int[] { (int)lv.reg };
1974 p.isValidOffset = true; 2137 p.isValidOffset = true;
1975 } 2138 }
1976 } 2139 }
1977 2140

mercurial