Mercurial > hg > release > icedtea7-forest-2.6 > langtools
changeset 1994:979f55cda0e2
8065674: javac generates incorrect LVT table for trivial cases
Reviewed-by: jjg
Contributed-by: vicente.romero@oracle.com
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Thu Nov 20 14:01:11 2014 -0800 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Wed Nov 26 17:03:13 2014 +0000 @@ -1012,25 +1012,29 @@ if (code.varBufferSize > 0) { int alenIdx = writeAttr(names.LocalVariableTable); - databuf.appendChar(code.varBufferSize); + databuf.appendChar(code.getLVTSize()); for (int i=0; i<code.varBufferSize; i++) { Code.LocalVar var = code.varBuffer[i]; - - // write variable info - Assert.check(var.start_pc >= 0 - && var.start_pc <= code.cp); - databuf.appendChar(var.start_pc); - Assert.check(var.length >= 0 - && (var.start_pc + var.length) <= code.cp); - databuf.appendChar(var.length); - VarSymbol sym = var.sym; - databuf.appendChar(pool.put(sym.name)); - Type vartype = sym.erasure(types); - if (needsLocalVariableTypeEntry(sym.type)) - nGenericVars++; - databuf.appendChar(pool.put(typeSig(vartype))); - databuf.appendChar(var.reg); + for (Code.LocalVar.Range r: var.aliveRanges) { + // write variable info + if (!(r.start_pc >= 0 && r.start_pc <= code.cp)) { + throw new AssertionError(); + } + databuf.appendChar(r.start_pc); + if (!(r.length >= 0 && (r.start_pc + r.length) <= code.cp)) { + throw new AssertionError(); + } + databuf.appendChar(r.length); + VarSymbol sym = var.sym; + databuf.appendChar(pool.put(sym.name)); + Type vartype = sym.erasure(types); + databuf.appendChar(pool.put(typeSig(vartype))); + databuf.appendChar(var.reg); + if (needsLocalVariableTypeEntry(var.sym.type)) { + nGenericVars++; + } + } } endAttr(alenIdx); acount++; @@ -1046,13 +1050,15 @@ VarSymbol sym = var.sym; if (!needsLocalVariableTypeEntry(sym.type)) continue; - count++; - // write variable info - databuf.appendChar(var.start_pc); - databuf.appendChar(var.length); - databuf.appendChar(pool.put(sym.name)); - databuf.appendChar(pool.put(typeSig(sym.type))); - databuf.appendChar(var.reg); + for (Code.LocalVar.Range r : var.aliveRanges) { + // write variable info + databuf.appendChar(r.start_pc); + databuf.appendChar(r.length); + databuf.appendChar(pool.put(sym.name)); + databuf.appendChar(pool.put(typeSig(sym.type))); + databuf.appendChar(var.reg); + count++; + } } Assert.check(count == nGenericVars); endAttr(alenIdx);
--- a/src/share/classes/com/sun/tools/javac/jvm/Code.java Thu Nov 20 14:01:11 2014 -0800 +++ b/src/share/classes/com/sun/tools/javac/jvm/Code.java Wed Nov 26 17:03:13 2014 +0000 @@ -1151,7 +1151,9 @@ public int entryPoint(State state) { int pc = curPc(); alive = true; - this.state = state.dup(); + State newState = state.dup(); + setDefined(newState.defined); + this.state = newState; Assert.check(state.stacksize <= max_stack); if (debugCode) System.err.println("entry point " + state); pendingStackMap = needStackMap; @@ -1164,7 +1166,9 @@ public int entryPoint(State state, Type pushed) { int pc = curPc(); alive = true; - this.state = state.dup(); + State newState = state.dup(); + setDefined(newState.defined); + this.state = newState; Assert.check(state.stacksize <= max_stack); this.state.push(pushed); if (debugCode) System.err.println("entry point " + state); @@ -1452,6 +1456,10 @@ chain.pc + 3 == target && target == cp && !fixedPc) { // If goto the next instruction, the jump is not needed: // compact the code. + if (varDebugInfo) { + adjustAliveRanges(cp, -3); + } + cp = cp - 3; target = target - 3; if (chain.next == null) { @@ -1736,8 +1744,7 @@ sym = sym.clone(sym.owner); sym.type = newtype; LocalVar newlv = lvar[i] = new LocalVar(sym); - // should the following be initialized to cp? - newlv.start_pc = lv.start_pc; + newlv.aliveRanges = lv.aliveRanges; } } } @@ -1825,18 +1832,118 @@ static class LocalVar { final VarSymbol sym; final char reg; - char start_pc = Character.MAX_VALUE; - char length = Character.MAX_VALUE; + + class Range { + char start_pc = Character.MAX_VALUE; + char length = Character.MAX_VALUE; + + Range() {} + + Range(char start) { + this.start_pc = start; + } + + Range(char start, char length) { + this.start_pc = start; + this.length = length; + } + + boolean closed() { + return start_pc != Character.MAX_VALUE && length != Character.MAX_VALUE; + } + + @Override + public String toString() { + int currentStartPC = start_pc; + int currentLength = length; + return "startpc = " + currentStartPC + " length " + currentLength; + } + } + + java.util.List<Range> aliveRanges = new java.util.ArrayList<Range>(); + LocalVar(VarSymbol v) { this.sym = v; this.reg = (char)v.adr; } + public LocalVar dup() { return new LocalVar(sym); } + + Range firstRange() { + return aliveRanges.isEmpty() ? null : aliveRanges.get(0); + } + + Range lastRange() { + return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1); + } + + void removeLastRange() { + Range lastRange = lastRange(); + if (lastRange != null) { + aliveRanges.remove(lastRange); + } + } + + @Override public String toString() { - return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length); + if (aliveRanges == null) { + return "empty local var"; + } + StringBuilder sb = new StringBuilder().append(sym) + .append(" in register ").append((int)reg).append(" \n"); + for (Range r : aliveRanges) { + sb.append(" starts at pc=").append(Integer.toString(((int)r.start_pc))) + .append(" length=").append(Integer.toString(((int)r.length))) + .append("\n"); + } + return sb.toString(); + } + + public void openRange(char start) { + if (!hasOpenRange()) { + aliveRanges.add(new Range(start)); + } } + + public void closeRange(char length) { + if (isLastRangeInitialized() && length > 0) { + Range range = lastRange(); + if (range != null) { + if (range.length == Character.MAX_VALUE) { + range.length = length; + } + } + } else { + removeLastRange(); + } + } + + public boolean hasOpenRange() { + if (aliveRanges.isEmpty()) { + return false; + } + return lastRange().length == Character.MAX_VALUE; + } + + public boolean isLastRangeInitialized() { + if (aliveRanges.isEmpty()) { + return false; + } + return lastRange().start_pc != Character.MAX_VALUE; + } + + public Range getWidestRange() { + if (aliveRanges.isEmpty()) { + return new Range(); + } else { + Range firstRange = firstRange(); + Range lastRange = lastRange(); + char length = (char)(lastRange.length + (lastRange.start_pc - firstRange.start_pc)); + return new Range(firstRange.start_pc, length); + } + } }; /** Local variables, indexed by register. */ @@ -1858,6 +1965,30 @@ state.defined.excl(adr); } + void adjustAliveRanges(int oldCP, int delta) { + for (LocalVar localVar: lvar) { + if (localVar != null) { + for (LocalVar.Range range: localVar.aliveRanges) { + if (range.closed() && range.start_pc + range.length >= oldCP) { + range.length += delta; + } + } + } + } + } + + /** + * Calculates the size of the LocalVariableTable. + */ + public int getLVTSize() { + int result = varBufferSize; + for (int i = 0; i < varBufferSize; i++) { + LocalVar var = varBuffer[i]; + result += var.aliveRanges.size() - 1; + } + return result; + } + /** Set the current variable defined state. */ public void setDefined(Bits newDefined) { if (alive && newDefined != state.defined) { @@ -1883,8 +2014,7 @@ } else { state.defined.incl(adr); if (cp < Character.MAX_VALUE) { - if (v.start_pc == Character.MAX_VALUE) - v.start_pc = (char)cp; + v.openRange((char)cp); } } } @@ -1894,15 +2024,15 @@ state.defined.excl(adr); if (adr < lvar.length && lvar[adr] != null && - lvar[adr].start_pc != Character.MAX_VALUE) { + lvar[adr].isLastRangeInitialized()) { LocalVar v = lvar[adr]; - char length = (char)(curPc() - v.start_pc); + char length = (char)(curPc()- v.lastRange().start_pc); if (length > 0 && length < Character.MAX_VALUE) { lvar[adr] = v.dup(); - v.length = length; + v.closeRange(length); putVar(v); } else { - v.start_pc = Character.MAX_VALUE; + v.removeLastRange(); } } } @@ -1912,10 +2042,10 @@ LocalVar v = lvar[adr]; if (v != null) { lvar[adr] = null; - if (v.start_pc != Character.MAX_VALUE) { - char length = (char)(curPc() - v.start_pc); + if (v.isLastRangeInitialized()) { + char length = (char)(curPc()- v.lastRange().start_pc); if (length < Character.MAX_VALUE) { - v.length = length; + v.closeRange(length); putVar(v); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/DARanges.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.lang.annotation.*; + +@Target({ElementType.METHOD}) +@interface DARange { + String varName(); + int bytecodeStart(); + int bytecodeLength(); +} + +@Target({ElementType.METHOD}) +@interface DARanges {DARange[] value();}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/LVTHarness.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058708 + * @summary The LVT is not generated correctly during some try/catch scenarios + * javac crash while creating LVT entry for a local variable defined in + * an inner block + * @library /tools/javac/lib + * @build JavacTestingAbstractProcessor LVTHarness + * @run main LVTHarness + */ + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.Set; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.ConstantPool.InvalidIndex; +import com.sun.tools.classfile.ConstantPool.UnexpectedEntry; +import com.sun.tools.classfile.Descriptor.InvalidDescriptor; +import com.sun.tools.classfile.LocalVariableTable_attribute; +import com.sun.tools.classfile.Method; + +import static javax.tools.StandardLocation.*; +import static com.sun.tools.classfile.LocalVariableTable_attribute.Entry; +import static javax.tools.JavaFileObject.Kind.SOURCE; + +public class LVTHarness { + + static int nerrors = 0; + + static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + static final StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + + public static void main(String[] args) throws Exception { + + String testDir = System.getProperty("test.src"); + fm.setLocation(SOURCE_PATH, Arrays.asList(new File(testDir, "tests"))); + + // Make sure classes are written to scratch dir. + fm.setLocation(CLASS_OUTPUT, Arrays.asList(new File("."))); + + for (JavaFileObject jfo : fm.list(SOURCE_PATH, "", Collections.singleton(SOURCE), true)) { + new LVTHarness(jfo).check(); + } + if (nerrors > 0) { + throw new AssertionError("Errors were found"); + } + } + + + JavaFileObject jfo; + Map<ElementKey, DARanges> aliveRangeMap = new HashMap<ElementKey, DARanges>(); + Set<String> declaredKeys = new HashSet<String>(); + List<ElementKey> seenDARanges = new ArrayList<ElementKey>(); + + protected LVTHarness(JavaFileObject jfo) { + this.jfo = jfo; + } + + protected void check() throws Exception { + + JavacTask ct = (JavacTask) comp.getTask(null, fm, null, Arrays.asList("-g"), + null, Arrays.asList(jfo)); + System.err.println("compiling code " + jfo); + ct.setProcessors(Collections.singleton(new DARangeFinder())); + if (!ct.call()) { + throw new AssertionError("Error during compilation"); + } + + + File javaFile = new File(jfo.getName()); + File classFile = new File(javaFile.getName().replace(".java", ".class")); + checkClassFile(classFile); + + //check all candidates have been used up + for (Map.Entry<ElementKey, DARanges> entry : aliveRangeMap.entrySet()) { + if (!seenDARanges.contains(entry.getKey())) { + error("Redundant @DARanges annotation on method " + + entry.getKey().elem + " with key " + entry.getKey()); + } + } + } + + void checkClassFile(File file) + throws IOException, ConstantPoolException, InvalidDescriptor { + ClassFile classFile = ClassFile.read(file); + ConstantPool constantPool = classFile.constant_pool; + + //lets get all the methods in the class file. + for (Method method : classFile.methods) { + for (ElementKey elementKey: aliveRangeMap.keySet()) { + String methodDesc = method.getName(constantPool) + + method.descriptor.getParameterTypes(constantPool).replace(" ", ""); + if (methodDesc.equals(elementKey.elem.toString())) { + checkMethod(constantPool, method, aliveRangeMap.get(elementKey)); + seenDARanges.add(elementKey); + } + } + } + } + + void checkMethod(ConstantPool constantPool, Method method, DARanges ranges) + throws InvalidIndex, UnexpectedEntry { + Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code); + LocalVariableTable_attribute lvt = + (LocalVariableTable_attribute) (code.attributes.get(Attribute.LocalVariableTable)); + List<String> infoFromRanges = convertToStringList(ranges); + List<String> infoFromLVT = convertToStringList(constantPool, lvt); + + // infoFromRanges most be contained in infoFromLVT + int i = 0; + int j = 0; + while (i < infoFromRanges.size() && j < infoFromLVT.size()) { + int comparison = infoFromRanges.get(i).compareTo(infoFromLVT.get(j)); + if (comparison == 0) { + i++; j++; + } else if (comparison > 0) { + j++; + } else { + break; + } + } + + if (i < infoFromRanges.size()) { + error(infoFromLVT, infoFromRanges); + } + } + + List<String> convertToStringList(DARanges ranges) { + List<String> result = new ArrayList<String>(); + for (Annotation anno : ranges.value()) { + DARange range = (DARange)anno; + String str = formatLocalVariableData(range.varName(), + range.bytecodeStart(), range.bytecodeLength()); + result.add(str); + } + Collections.sort(result); + return result; + } + + List<String> convertToStringList(ConstantPool constantPool, + LocalVariableTable_attribute lvt) throws InvalidIndex, UnexpectedEntry { + List<String> result = new ArrayList<String>(); + for (Entry entry : lvt.local_variable_table) { + String str = formatLocalVariableData(constantPool.getUTF8Value(entry.name_index), + entry.start_pc, entry.length); + result.add(str); + } + Collections.sort(result); + return result; + } + + String formatLocalVariableData(String varName, int start, int length) { + StringBuilder sb = new StringBuilder() + .append("var name: ").append(varName) + .append(" start: ").append(start) + .append(" length: ").append(length); + return sb.toString(); + } + + protected void error(List<String> infoFromLVT, List<String> infoFromRanges) { + nerrors++; + System.err.printf("Error occurred while checking file: %s\n", jfo.getName()); + System.err.println("The range info from the annotations is"); + printStringListToErrOutput(infoFromRanges); + System.err.println(); + System.err.println("And the range info from the class file is"); + printStringListToErrOutput(infoFromLVT); + System.err.println(); + } + + void printStringListToErrOutput(List<String> list) { + for (String s : list) { + System.err.println("\t" + s); + } + } + + protected void error(String msg) { + nerrors++; + System.err.printf("Error occurred while checking file: %s\nreason: %s\n", + jfo.getName(), msg); + } + + class DARangeFinder extends JavacTestingAbstractProcessor { + + @Override + public boolean process(Set<? extends TypeElement> annotations, + RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) + return true; + + TypeElement aliveRangeAnno = elements.getTypeElement("DARanges"); + + if (!annotations.contains(aliveRangeAnno)) { + error("no @DARanges annotation found in test class"); + } + + for (Element elem: roundEnv.getElementsAnnotatedWith(aliveRangeAnno)) { + Annotation annotation = elem.getAnnotation(DARanges.class); + aliveRangeMap.put(new ElementKey(elem), (DARanges)annotation); + } + return true; + } + } + + class ElementKey { + + String key; + Element elem; + + public ElementKey(Element elem) { + this.elem = elem; + this.key = computeKey(elem); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ElementKey) { + ElementKey other = (ElementKey)obj; + return other.key.equals(key); + } + return false; + } + + @Override + public int hashCode() { + return key.hashCode(); + } + + String computeKey(Element e) { + StringBuilder buf = new StringBuilder(); + while (e != null) { + buf.append(e.toString()); + e = e.getEnclosingElement(); + } + buf.append(jfo.getName()); + return buf.toString(); + } + + @Override + public String toString() { + return "Key{" + key + "}"; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseConditional.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,15 @@ +public class TestCaseConditional { + @DARanges({ + @DARange(varName="o", bytecodeStart=5, bytecodeLength=33), + @DARange(varName="oo", bytecodeStart=23, bytecodeLength=15) + }) + void m(String[] args) { + Boolean o; + Boolean oo = ((o = Boolean.TRUE).booleanValue()) ? + o = Boolean.TRUE : + Boolean.FALSE; + oo.hashCode(); + o = Boolean.FALSE; + o.hashCode(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseDoLoop.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,15 @@ +public class TestCaseDoLoop { + + @DARanges({ + @DARange(varName="o", bytecodeStart=3, bytecodeLength=15), + @DARange(varName="args", bytecodeStart=0, bytecodeLength=18) + }) + void m(String[] args) { + Object o; + do { + o = ""; + o.hashCode(); + } while (args[0] != null); + o = ""; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseFor.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,29 @@ +public class TestCaseFor { + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=11), + @DARange(varName="o", bytecodeStart=24, bytecodeLength=1) + }) + void m1(String[] args) { + Object o; + for (int i = 0; i < 5; i++) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=11), + @DARange(varName="o", bytecodeStart=24, bytecodeLength=1) + }) + void m2(String[] args) { + Object o; + for (int i = 0; i < 5; i++) { + o = ""; + o.hashCode(); + continue; + } + o = ""; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseForEach.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,15 @@ +public class TestCaseForEach { + + @DARanges({ + @DARange(varName="o", bytecodeStart=25, bytecodeLength=11), + @DARange(varName="o", bytecodeStart=39, bytecodeLength=1) + }) + void m(String[] args) { + Object o; + for (String s : args) { + o = ""; + o.hashCode(); + } + o = ""; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseIf.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,84 @@ +public class TestCaseIf { + @DARanges({ + @DARange(varName="o", bytecodeStart=9, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=17, bytecodeLength=1) + }) + void m0(String[] args) { + Object o; + if (args[0] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=18, bytecodeLength=1) + }) + void m1() { + Object o; + int i = 5; + if (i == 5) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=18, bytecodeLength=1) + }) + void m2() { + Object o; + int i = 5; + if (!(i == 5)) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=15, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=23, bytecodeLength=1) + }) + void m3(String[] args) { + Object o; + if (args[0] != null && args[1] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=15, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=23, bytecodeLength=1) + }) + void m4(String[] args) { + Object o; + if (args[0] != null || args[1] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="finalLocal", bytecodeStart=11, bytecodeLength=6), + @DARange(varName="used", bytecodeStart=13, bytecodeLength=4) + }) + void m5(Object o) { + if (o != null) { + Object notUsed; + Object used; + if (o != null) { + final Object finalLocal = null; + used = null; + if (o == null) {} + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseIfElse.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,69 @@ +public class TestCaseIfElse { + + @DARanges({ + @DARange(varName="o", bytecodeStart=9, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=20, bytecodeLength=9) + }) + void m0(String[] args) { + Object o; + if (args[0] != null) { + o = "then"; + o.hashCode(); + } else { + o = "else"; + o.hashCode(); + } + o = "finish"; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=21, bytecodeLength=9) + }) + void m1() { + Object o; + int i = 5; + if (i == 5) { + o = "then"; + o.hashCode(); + } else { + o = "else"; + o.hashCode(); + } + o = "finish"; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=21, bytecodeLength=9) + }) + void m2() { + Object o; + int i = 5; + if (i != 5) { + o = "then"; + o.hashCode(); + } else { + o = "else"; + o.hashCode(); + } + o = "finish"; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=11, bytecodeLength=3), + @DARange(varName="o", bytecodeStart=17, bytecodeLength=2) + }) + Object m3(boolean cond1, boolean cond2) { + Object o; + if (cond1) { + if (cond2) { + o = "then"; + } else { + o = "else"; + return null; + } + } + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseLocalInInnerBlock.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,20 @@ +public class TestCaseLocalInInnerBlock { + + @DARanges({ + @DARange(varName="fm", bytecodeStart=23, bytecodeLength=10), + @DARange(varName="newWidth", bytecodeStart=2, bytecodeLength=33), + @DARange(varName="tc", bytecodeStart=5, bytecodeLength=30) + }) + int m() { + int newWidth = 0; + String tc = "b"; + if (tc != null) { + String fm; + if (tc.trim() != null) { + } else if ((fm = "b") != null) { + newWidth += fm.length(); + } + } + return newWidth; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseSwitch.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,86 @@ +public class TestCaseSwitch { + + @DARanges({ + @DARange(varName="o", bytecodeStart=31, bytecodeLength=16), + @DARange(varName="o", bytecodeStart=50, bytecodeLength=15), + @DARange(varName="o", bytecodeStart=68, bytecodeLength=1), + @DARange(varName="oo", bytecodeStart=39, bytecodeLength=8), + @DARange(varName="uu", bytecodeStart=59, bytecodeLength=6) + }) + void m1(String[] args) { + Object o; + switch (args.length) { + case 0: + o = "0"; + o.hashCode(); + Object oo = "oo"; + oo.hashCode(); + break; + case 1: + o = "1"; + o.hashCode(); + Object uu = "uu"; + uu.hashCode(); + break; + } + o = "return"; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=35, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=46, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=78, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=86, bytecodeLength=1), + @DARange(varName="oo", bytecodeStart=56, bytecodeLength=16) + }) + void m3(int i) { + Object o; + switch (i) { + case 0: + o = "0"; + o.hashCode(); + break; + case 1: + o = "1"; + o.hashCode(); + break; + case 2: + int oo = i; + if (oo > 1) { + System.out.println("greater"); + } + break; + case 3: + int uu = i; + default: + o = "default"; + o.hashCode(); + } + o = "finish"; + } + + @DARanges({ + @DARange(varName="oCache", bytecodeStart=30, bytecodeLength=6), + @DARange(varName="cache", bytecodeStart=41, bytecodeLength=3), + @DARange(varName="cache", bytecodeStart=54, bytecodeLength=2), + @DARange(varName="service", bytecodeStart=39, bytecodeLength=5) + }) + public Object m(int i) { + Object cache; + switch (i) { + case 0: + Object oCache = null; + if (oCache != null) { + return oCache; + } + case 1: + Object service = null; + cache = null; + break; + default: + throw new AssertionError(""); + } + return cache; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseTry.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,55 @@ +public class TestCaseTry { + + @DARanges({ + @DARange(varName="o", bytecodeStart=3, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=15, bytecodeLength=1) + }) + void m0(String[] args) { + Object o; + try { + o = ""; + o.hashCode(); + } catch (RuntimeException e) {} + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=3, bytecodeLength=16), + @DARange(varName="o", bytecodeStart=23, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=35, bytecodeLength=11) + }) + void m1() { + Object o; + try { + o = ""; + o.hashCode(); + } catch (RuntimeException e) { + } + finally { + o = "finally"; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=3, bytecodeLength=16), + @DARange(varName="o", bytecodeStart=23, bytecodeLength=16), + @DARange(varName="o", bytecodeStart=43, bytecodeLength=11) + }) + void m2() { + Object o; + try { + o = ""; + o.hashCode(); + } catch (RuntimeException e) { + o = "catch"; + o.hashCode(); + } + finally { + o = "finally"; + o.hashCode(); + } + o = ""; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseWhile.java Wed Nov 26 17:03:13 2014 +0000 @@ -0,0 +1,15 @@ +public class TestCaseWhile { + + @DARanges({ + @DARange(varName="o", bytecodeStart=9, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=20, bytecodeLength=1) + }) + void m(String[] args) { + Object o; + while (args[0] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } +}