提交 85661013 编写于 作者: V vromero

8064857: javac generates LVT entry with length 0 for local variable

Reviewed-by: mcimadamore, jjg
上级 29e40c9c
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, 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
......@@ -1186,7 +1186,7 @@ public class ClassWriter extends ClassFile {
Assert.check(r.start_pc >= 0
&& r.start_pc <= code.cp);
databuf.appendChar(r.start_pc);
Assert.check(r.length >= 0
Assert.check(r.length > 0
&& (r.start_pc + r.length) <= code.cp);
databuf.appendChar(r.length);
VarSymbol sym = var.sym;
......
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, 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
......@@ -182,8 +182,6 @@ public class Code {
final MethodSymbol meth;
final LVTRanges lvtRanges;
/** Construct a code object, given the settings of the fatcode,
* debugging info switches and the CharacterRangeTable.
*/
......@@ -196,8 +194,7 @@ public class Code {
CRTable crt,
Symtab syms,
Types types,
Pool pool,
LVTRanges lvtRanges) {
Pool pool) {
this.meth = meth;
this.fatcode = fatcode;
this.lineMap = lineMap;
......@@ -219,7 +216,6 @@ public class Code {
state = new State();
lvar = new LocalVar[20];
this.pool = pool;
this.lvtRanges = lvtRanges;
}
......@@ -1193,7 +1189,9 @@ public class Code {
public int entryPoint(State state) {
int pc = curCP();
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;
......@@ -1206,7 +1204,9 @@ public class Code {
public int entryPoint(State state, Type pushed) {
int pc = curCP();
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);
......@@ -2008,27 +2008,6 @@ public class Code {
state.defined.excl(adr);
}
public void closeAliveRanges(JCTree tree) {
closeAliveRanges(tree, cp);
}
public void closeAliveRanges(JCTree tree, int closingCP) {
List<VarSymbol> locals = lvtRanges.getVars(meth, tree);
for (LocalVar localVar: lvar) {
for (VarSymbol aliveLocal : locals) {
if (localVar != null) {
if (localVar.sym == aliveLocal && localVar.lastRange() != null) {
char length = (char)(closingCP - localVar.lastRange().start_pc);
if (length < Character.MAX_VALUE) {
localVar.closeRange(length);
}
}
}
}
}
}
void adjustAliveRanges(int oldCP, int delta) {
for (LocalVar localVar: lvar) {
if (localVar != null) {
......
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, 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
......@@ -101,10 +101,6 @@ public class Gen extends JCTree.Visitor {
*/
private Pool pool;
/** LVTRanges info.
*/
private LVTRanges lvtRanges;
private final boolean typeAnnoAsserts;
protected Gen(Context context) {
......@@ -137,9 +133,6 @@ public class Gen extends JCTree.Visitor {
options.isUnset(G_CUSTOM)
? options.isSet(G)
: options.isSet(G_CUSTOM, "vars");
if (varDebugInfo) {
lvtRanges = LVTRanges.instance(context);
}
genCrt = options.isSet(XJCOV);
debugCode = options.isSet("debugcode");
allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
......@@ -1103,8 +1096,7 @@ public class Gen extends JCTree.Visitor {
: null,
syms,
types,
pool,
varDebugInfo ? lvtRanges : null);
pool);
items = new Items(pool, code, syms, types);
if (code.debugCode) {
System.err.println(meth + " for body " + tree);
......@@ -1207,30 +1199,14 @@ public class Gen extends JCTree.Visitor {
Chain loopDone = c.jumpFalse();
code.resolve(c.trueJumps);
genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
if (varDebugInfo) {
checkLoopLocalVarRangeEnding(loop, body,
LoopLocalVarRangeEndingPoint.BEFORE_STEPS);
}
code.resolve(loopEnv.info.cont);
genStats(step, loopEnv);
if (varDebugInfo) {
checkLoopLocalVarRangeEnding(loop, body,
LoopLocalVarRangeEndingPoint.AFTER_STEPS);
}
code.resolve(code.branch(goto_), startpc);
code.resolve(loopDone);
} else {
genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
if (varDebugInfo) {
checkLoopLocalVarRangeEnding(loop, body,
LoopLocalVarRangeEndingPoint.BEFORE_STEPS);
}
code.resolve(loopEnv.info.cont);
genStats(step, loopEnv);
if (varDebugInfo) {
checkLoopLocalVarRangeEnding(loop, body,
LoopLocalVarRangeEndingPoint.AFTER_STEPS);
}
CondItem c;
if (cond != null) {
code.statBegin(cond.pos);
......@@ -1247,44 +1223,6 @@ public class Gen extends JCTree.Visitor {
}
}
private enum LoopLocalVarRangeEndingPoint {
BEFORE_STEPS,
AFTER_STEPS,
}
/**
* Checks whether we have reached an alive range ending point for local
* variables after a loop.
*
* Local variables alive range ending point for loops varies depending
* on the loop type. The range can be closed before or after the code
* for the steps sentences has been generated.
*
* - While loops has no steps so in that case the range is closed just
* after the body of the loop.
*
* - For-like loops may have steps so as long as the steps sentences
* can possibly contain non-synthetic local variables, the alive range
* for local variables must be closed after the steps in this case.
*/
private void checkLoopLocalVarRangeEnding(JCTree loop, JCTree body,
LoopLocalVarRangeEndingPoint endingPoint) {
if (varDebugInfo && lvtRanges.containsKey(code.meth, body)) {
switch (endingPoint) {
case BEFORE_STEPS:
if (!loop.hasTag(FORLOOP)) {
code.closeAliveRanges(body);
}
break;
case AFTER_STEPS:
if (loop.hasTag(FORLOOP)) {
code.closeAliveRanges(body);
}
break;
}
}
}
public void visitForeachLoop(JCEnhancedForLoop tree) {
throw new AssertionError(); // should have been removed by Lower.
}
......@@ -1398,9 +1336,6 @@ public class Gen extends JCTree.Visitor {
// Generate code for the statements in this case.
genStats(c.stats, switchEnv, CRT_FLOW_TARGET);
if (varDebugInfo && lvtRanges.containsKey(code.meth, c.stats.last())) {
code.closeAliveRanges(c.stats.last());
}
}
// Resolve all breaks.
......@@ -1557,9 +1492,6 @@ public class Gen extends JCTree.Visitor {
genFinalizer(env);
code.statBegin(TreeInfo.endPos(env.tree));
Chain exitChain = code.branch(goto_);
if (varDebugInfo && lvtRanges.containsKey(code.meth, body)) {
code.closeAliveRanges(body);
}
endFinalizerGap(env);
if (startpc != endpc) for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) {
// start off with exception on stack
......@@ -1815,17 +1747,11 @@ public class Gen extends JCTree.Visitor {
code.resolve(c.trueJumps);
genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
thenExit = code.branch(goto_);
if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.thenpart)) {
code.closeAliveRanges(tree.thenpart, code.cp);
}
}
if (elseChain != null) {
code.resolve(elseChain);
if (tree.elsepart != null) {
genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET);
if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.elsepart)) {
code.closeAliveRanges(tree.elsepart);
}
}
}
code.resolve(thenExit);
......@@ -2514,16 +2440,6 @@ public class Gen extends JCTree.Visitor {
localEnv.toplevel = env.toplevel;
localEnv.enclClass = cdef;
/* We must not analyze synthetic methods
*/
if (varDebugInfo && (cdef.sym.flags() & SYNTHETIC) == 0) {
try {
new LVTAssignAnalyzer().analyzeTree(localEnv);
} catch (Throwable e) {
throw e;
}
}
for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
genDef(l.head, localEnv);
}
......@@ -2609,282 +2525,4 @@ public class Gen extends JCTree.Visitor {
}
}
class LVTAssignAnalyzer
extends Flow.AbstractAssignAnalyzer<LVTAssignAnalyzer.LVTAssignPendingExit> {
final LVTBits lvtInits;
/* This class is anchored to a context dependent tree. The tree can
* vary inside the same instruction for example in the switch instruction
* the same FlowBits instance can be anchored to the whole tree, or
* to a given case. The aim is to always anchor the bits to the tree
* capable of closing a DA range.
*/
class LVTBits extends Bits {
JCTree currentTree;
private int[] oldBits = null;
BitsState stateBeforeOp;
@Override
public void clear() {
generalOp(null, -1, BitsOpKind.CLEAR);
}
@Override
protected void internalReset() {
super.internalReset();
oldBits = null;
}
@Override
public Bits assign(Bits someBits) {
// bits can be null
oldBits = bits;
stateBeforeOp = currentState;
super.assign(someBits);
changed();
return this;
}
@Override
public void excludeFrom(int start) {
generalOp(null, start, BitsOpKind.EXCL_RANGE);
}
@Override
public void excl(int x) {
Assert.check(x >= 0);
generalOp(null, x, BitsOpKind.EXCL_BIT);
}
@Override
public Bits andSet(Bits xs) {
return generalOp(xs, -1, BitsOpKind.AND_SET);
}
@Override
public Bits orSet(Bits xs) {
return generalOp(xs, -1, BitsOpKind.OR_SET);
}
@Override
public Bits diffSet(Bits xs) {
return generalOp(xs, -1, BitsOpKind.DIFF_SET);
}
@Override
public Bits xorSet(Bits xs) {
return generalOp(xs, -1, BitsOpKind.XOR_SET);
}
private Bits generalOp(Bits xs, int i, BitsOpKind opKind) {
Assert.check(currentState != BitsState.UNKNOWN);
oldBits = dupBits();
stateBeforeOp = currentState;
switch (opKind) {
case AND_SET:
super.andSet(xs);
break;
case OR_SET:
super.orSet(xs);
break;
case XOR_SET:
super.xorSet(xs);
break;
case DIFF_SET:
super.diffSet(xs);
break;
case CLEAR:
super.clear();
break;
case EXCL_BIT:
super.excl(i);
break;
case EXCL_RANGE:
super.excludeFrom(i);
break;
}
changed();
return this;
}
/* The tree we need to anchor the bits instance to.
*/
LVTBits at(JCTree tree) {
this.currentTree = tree;
return this;
}
/* If the instance should be changed but the tree is not a closing
* tree then a reset is needed or the former tree can mistakingly be
* used.
*/
LVTBits resetTree() {
this.currentTree = null;
return this;
}
/** This method will be called after any operation that causes a change to
* the bits. Subclasses can thus override it in order to extract information
* from the changes produced to the bits by the given operation.
*/
public void changed() {
if (currentTree != null &&
stateBeforeOp != BitsState.UNKNOWN &&
trackTree(currentTree)) {
List<VarSymbol> locals = lvtRanges
.getVars(currentMethod, currentTree);
locals = locals != null ?
locals : List.<VarSymbol>nil();
for (JCVariableDecl vardecl : vardecls) {
//once the first is null, the rest will be so.
if (vardecl == null) {
break;
}
if (trackVar(vardecl.sym) && bitChanged(vardecl.sym.adr)) {
locals = locals.prepend(vardecl.sym);
}
}
if (!locals.isEmpty()) {
lvtRanges.setEntry(currentMethod,
currentTree, locals);
}
}
}
boolean bitChanged(int x) {
boolean isMemberOfBits = isMember(x);
int[] tmp = bits;
bits = oldBits;
boolean isMemberOfOldBits = isMember(x);
bits = tmp;
return (!isMemberOfBits && isMemberOfOldBits);
}
boolean trackVar(VarSymbol var) {
return (var.owner.kind == MTH &&
(var.flags() & PARAMETER) == 0 &&
trackable(var));
}
boolean trackTree(JCTree tree) {
switch (tree.getTag()) {
// of course a method closes the alive range of a local variable.
case METHODDEF:
// for while loops we want only the body
case WHILELOOP:
return false;
}
return true;
}
}
public class LVTAssignPendingExit extends
Flow.AbstractAssignAnalyzer<LVTAssignPendingExit>.AbstractAssignPendingExit {
LVTAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
super(tree, inits, uninits);
}
@Override
public void resolveJump(JCTree tree) {
lvtInits.at(tree);
super.resolveJump(tree);
}
}
private LVTAssignAnalyzer() {
flow.super();
lvtInits = new LVTBits();
inits = lvtInits;
}
@Override
protected void markDead(JCTree tree) {
lvtInits.at(tree).inclRange(returnadr, nextadr);
super.markDead(tree);
}
@Override
protected void merge(JCTree tree) {
lvtInits.at(tree);
super.merge(tree);
}
boolean isSyntheticOrMandated(Symbol sym) {
return (sym.flags() & (SYNTHETIC | MANDATED)) != 0;
}
@Override
protected boolean trackable(VarSymbol sym) {
if (isSyntheticOrMandated(sym)) {
//fast check to avoid tracking synthetic or mandated variables
return false;
}
return super.trackable(sym);
}
@Override
protected void initParam(JCVariableDecl def) {
if (!isSyntheticOrMandated(def.sym)) {
super.initParam(def);
}
}
@Override
protected void assignToInits(JCTree tree, Bits bits) {
lvtInits.at(tree);
lvtInits.assign(bits);
}
@Override
protected void andSetInits(JCTree tree, Bits bits) {
lvtInits.at(tree);
lvtInits.andSet(bits);
}
@Override
protected void orSetInits(JCTree tree, Bits bits) {
lvtInits.at(tree);
lvtInits.orSet(bits);
}
@Override
protected void exclVarFromInits(JCTree tree, int adr) {
lvtInits.at(tree);
lvtInits.excl(adr);
}
@Override
protected LVTAssignPendingExit createNewPendingExit(JCTree tree, Bits inits, Bits uninits) {
return new LVTAssignPendingExit(tree, inits, uninits);
}
MethodSymbol currentMethod;
@Override
public void visitMethodDef(JCMethodDecl tree) {
if ((tree.sym.flags() & (SYNTHETIC | GENERATEDCONSTR)) != 0
&& (tree.sym.flags() & LAMBDA_METHOD) == 0) {
return;
}
if (tree.name.equals(names.clinit)) {
return;
}
boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0;
if (enumClass &&
(tree.name.equals(names.valueOf) ||
tree.name.equals(names.values) ||
tree.name.equals(names.init))) {
return;
}
currentMethod = tree.sym;
super.visitMethodDef(tree);
}
}
}
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.javac.jvm;
import java.util.Map;
import java.util.Map.Entry;
import java.util.WeakHashMap;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
/** This class contains a one to many relation between a tree and a set of variables.
* The relation implies that the given tree closes the DA (definite assignment)
* range for the set of variables.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class LVTRanges {
/** The context key for the LVT ranges. */
protected static final Context.Key<LVTRanges> lvtRangesKey = new Context.Key<>();
/** Get the LVTRanges instance for this context. */
public static LVTRanges instance(Context context) {
LVTRanges instance = context.get(lvtRangesKey);
if (instance == null) {
instance = new LVTRanges(context);
}
return instance;
}
private static final long serialVersionUID = 1812267524140424433L;
protected Context context;
protected Map<MethodSymbol, Map<JCTree, List<VarSymbol>>>
aliveRangeClosingTrees = new WeakHashMap<>();
public LVTRanges(Context context) {
this.context = context;
context.put(lvtRangesKey, this);
}
public List<VarSymbol> getVars(MethodSymbol method, JCTree tree) {
Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method);
return (varMap != null) ? varMap.get(tree) : null;
}
public boolean containsKey(MethodSymbol method, JCTree tree) {
Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method);
if (varMap == null) {
return false;
}
return varMap.containsKey(tree);
}
public void setEntry(MethodSymbol method, JCTree tree, List<VarSymbol> vars) {
Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method);
if (varMap != null) {
varMap.put(tree, vars);
} else {
varMap = new WeakHashMap<>();
varMap.put(tree, vars);
aliveRangeClosingTrees.put(method, varMap);
}
}
public List<VarSymbol> removeEntry(MethodSymbol method, JCTree tree) {
Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method);
if (varMap != null) {
List<VarSymbol> result = varMap.remove(tree);
if (varMap.isEmpty()) {
aliveRangeClosingTrees.remove(method);
}
return result;
}
return null;
}
/* This method should be used for debugging LVT related issues.
*/
@Override
public String toString() {
String result = "";
for (Entry<MethodSymbol, Map<JCTree, List<VarSymbol>>> mainEntry: aliveRangeClosingTrees.entrySet()) {
result += "Method: \n" + mainEntry.getKey().flatName() + "\n";
int i = 1;
for (Entry<JCTree, List<VarSymbol>> treeEntry: mainEntry.getValue().entrySet()) {
result += " Tree " + i + ": \n" + treeEntry.getKey().toString() + "\n";
result += " Variables closed:\n";
for (VarSymbol var: treeEntry.getValue()) {
result += " " + var.toString();
}
result += "\n";
i++;
}
}
return result;
}
}
/*
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2015, 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
......@@ -23,7 +23,7 @@
/*
* @test
* @bug 7047734 8027660 8037937 8047719 8058708
* @bug 7047734 8027660 8037937 8047719 8058708 8064857
* @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
......@@ -144,7 +144,7 @@ public class LVTHarness {
}
void checkMethod(ConstantPool constantPool, Method method, AliveRanges ranges)
throws InvalidIndex, UnexpectedEntry {
throws InvalidIndex, UnexpectedEntry, ConstantPoolException {
Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code);
LocalVariableTable_attribute lvt =
(LocalVariableTable_attribute) (code.attributes.get(Attribute.LocalVariableTable));
......@@ -166,7 +166,7 @@ public class LVTHarness {
}
if (i < infoFromRanges.size()) {
error(infoFromLVT, infoFromRanges);
error(infoFromLVT, infoFromRanges, method.getName(constantPool).toString());
}
}
......@@ -202,9 +202,10 @@ public class LVTHarness {
return sb.toString();
}
protected void error(List<String> infoFromLVT, List<String> infoFromRanges) {
protected void error(List<String> infoFromLVT, List<String> infoFromRanges, String methodName) {
nerrors++;
System.err.printf("Error occurred while checking file: %s\n", jfo.getName());
System.err.printf("at method: %s\n", methodName);
System.err.println("The range info from the annotations is");
printStringListToErrOutput(infoFromRanges);
System.err.println();
......
......@@ -2,7 +2,7 @@
public class TestCaseFor {
@AliveRange(varName="o", bytecodeStart=10, bytecodeLength=8)
@AliveRange(varName="o", bytecodeStart=10, bytecodeLength=11)
@AliveRange(varName="o", bytecodeStart=24, bytecodeLength=1)
void m1(String[] args) {
Object o;
......@@ -13,7 +13,7 @@ public class TestCaseFor {
o = "";
}
@AliveRange(varName="o", bytecodeStart=10, bytecodeLength=8)
@AliveRange(varName="o", bytecodeStart=10, bytecodeLength=11)
@AliveRange(varName="o", bytecodeStart=24, bytecodeLength=1)
void m2(String[] args) {
Object o;
......
......@@ -2,7 +2,7 @@
public class TestCaseForEach {
@AliveRange(varName="o", bytecodeStart=25, bytecodeLength=8)
@AliveRange(varName="o", bytecodeStart=25, bytecodeLength=11)
@AliveRange(varName="o", bytecodeStart=39, bytecodeLength=1)
void m(String[] args) {
Object o;
......
......@@ -60,4 +60,19 @@ public class TestCaseIfElse {
}
return null;
}
@AliveRange(varName="i", bytecodeStart=6, bytecodeLength=2)
int m4(boolean flag) {
int i;
label:
{
if (flag) {
i = 1;
} else {
break label;
}
return i;
}
return -1;
}
}
......@@ -81,4 +81,26 @@ public class TestCaseSwitch {
o = "finish";
}
@AliveRange(varName="oCache", bytecodeStart=30, bytecodeLength=6)
@AliveRange(varName="cache", bytecodeStart=41, bytecodeLength=3)
@AliveRange(varName="cache", bytecodeStart=54, bytecodeLength=2)
@AliveRange(varName="service", bytecodeStart=39, bytecodeLength=5)
Object m4(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;
}
}
......@@ -17,7 +17,8 @@ public class TestCaseTry {
}
@AliveRange(varName="o", bytecodeStart=3, bytecodeLength=16)
@AliveRange(varName="o", bytecodeStart=23, bytecodeLength=23)
@AliveRange(varName="o", bytecodeStart=23, bytecodeLength=8)
@AliveRange(varName="o", bytecodeStart=35, bytecodeLength=11)
void m1() {
Object o;
try {
......@@ -33,7 +34,8 @@ public class TestCaseTry {
}
@AliveRange(varName="o", bytecodeStart=3, bytecodeLength=16)
@AliveRange(varName="o", bytecodeStart=23, bytecodeLength=31)
@AliveRange(varName="o", bytecodeStart=23, bytecodeLength=16)
@AliveRange(varName="o", bytecodeStart=43, bytecodeLength=11)
void m2() {
Object o;
try {
......@@ -51,7 +53,8 @@ public class TestCaseTry {
}
@AliveRange(varName="o", bytecodeStart=22, bytecodeLength=38)
@AliveRange(varName="o", bytecodeStart=103, bytecodeLength=8)
@AliveRange(varName="o", bytecodeStart=103, bytecodeLength=3)
@AliveRange(varName="o", bytecodeStart=110, bytecodeLength=1)
void m3() {
Object o;
try (BufferedReader br =
......
......@@ -2,7 +2,7 @@
public class TestCaseWhile {
@AliveRange(varName="o", bytecodeStart=9, bytecodeLength=5)
@AliveRange(varName="o", bytecodeStart=9, bytecodeLength=8)
@AliveRange(varName="o", bytecodeStart=20, bytecodeLength=1)
void m(String[] args) {
Object o;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册