Tue, 20 Jan 2015 14:14:33 -0800
8064857: javac generates LVT entry with length 0 for local variable
Reviewed-by: mcimadamore, jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Tue Jan 13 12:41:16 2015 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Tue Jan 20 14:14:33 2015 -0800 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -1186,7 +1186,7 @@ 1.11 Assert.check(r.start_pc >= 0 1.12 && r.start_pc <= code.cp); 1.13 databuf.appendChar(r.start_pc); 1.14 - Assert.check(r.length >= 0 1.15 + Assert.check(r.length > 0 1.16 && (r.start_pc + r.length) <= code.cp); 1.17 databuf.appendChar(r.length); 1.18 VarSymbol sym = var.sym;
2.1 --- a/src/share/classes/com/sun/tools/javac/jvm/Code.java Tue Jan 13 12:41:16 2015 -0800 2.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/Code.java Tue Jan 20 14:14:33 2015 -0800 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -182,8 +182,6 @@ 2.11 2.12 final MethodSymbol meth; 2.13 2.14 - final LVTRanges lvtRanges; 2.15 - 2.16 /** Construct a code object, given the settings of the fatcode, 2.17 * debugging info switches and the CharacterRangeTable. 2.18 */ 2.19 @@ -196,8 +194,7 @@ 2.20 CRTable crt, 2.21 Symtab syms, 2.22 Types types, 2.23 - Pool pool, 2.24 - LVTRanges lvtRanges) { 2.25 + Pool pool) { 2.26 this.meth = meth; 2.27 this.fatcode = fatcode; 2.28 this.lineMap = lineMap; 2.29 @@ -219,7 +216,6 @@ 2.30 state = new State(); 2.31 lvar = new LocalVar[20]; 2.32 this.pool = pool; 2.33 - this.lvtRanges = lvtRanges; 2.34 } 2.35 2.36 2.37 @@ -1193,7 +1189,9 @@ 2.38 public int entryPoint(State state) { 2.39 int pc = curCP(); 2.40 alive = true; 2.41 - this.state = state.dup(); 2.42 + State newState = state.dup(); 2.43 + setDefined(newState.defined); 2.44 + this.state = newState; 2.45 Assert.check(state.stacksize <= max_stack); 2.46 if (debugCode) System.err.println("entry point " + state); 2.47 pendingStackMap = needStackMap; 2.48 @@ -1206,7 +1204,9 @@ 2.49 public int entryPoint(State state, Type pushed) { 2.50 int pc = curCP(); 2.51 alive = true; 2.52 - this.state = state.dup(); 2.53 + State newState = state.dup(); 2.54 + setDefined(newState.defined); 2.55 + this.state = newState; 2.56 Assert.check(state.stacksize <= max_stack); 2.57 this.state.push(pushed); 2.58 if (debugCode) System.err.println("entry point " + state); 2.59 @@ -2008,27 +2008,6 @@ 2.60 state.defined.excl(adr); 2.61 } 2.62 2.63 - 2.64 - public void closeAliveRanges(JCTree tree) { 2.65 - closeAliveRanges(tree, cp); 2.66 - } 2.67 - 2.68 - public void closeAliveRanges(JCTree tree, int closingCP) { 2.69 - List<VarSymbol> locals = lvtRanges.getVars(meth, tree); 2.70 - for (LocalVar localVar: lvar) { 2.71 - for (VarSymbol aliveLocal : locals) { 2.72 - if (localVar != null) { 2.73 - if (localVar.sym == aliveLocal && localVar.lastRange() != null) { 2.74 - char length = (char)(closingCP - localVar.lastRange().start_pc); 2.75 - if (length < Character.MAX_VALUE) { 2.76 - localVar.closeRange(length); 2.77 - } 2.78 - } 2.79 - } 2.80 - } 2.81 - } 2.82 - } 2.83 - 2.84 void adjustAliveRanges(int oldCP, int delta) { 2.85 for (LocalVar localVar: lvar) { 2.86 if (localVar != null) {
3.1 --- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java Tue Jan 13 12:41:16 2015 -0800 3.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java Tue Jan 20 14:14:33 2015 -0800 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -101,10 +101,6 @@ 3.11 */ 3.12 private Pool pool; 3.13 3.14 - /** LVTRanges info. 3.15 - */ 3.16 - private LVTRanges lvtRanges; 3.17 - 3.18 private final boolean typeAnnoAsserts; 3.19 3.20 protected Gen(Context context) { 3.21 @@ -137,9 +133,6 @@ 3.22 options.isUnset(G_CUSTOM) 3.23 ? options.isSet(G) 3.24 : options.isSet(G_CUSTOM, "vars"); 3.25 - if (varDebugInfo) { 3.26 - lvtRanges = LVTRanges.instance(context); 3.27 - } 3.28 genCrt = options.isSet(XJCOV); 3.29 debugCode = options.isSet("debugcode"); 3.30 allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic"); 3.31 @@ -1103,8 +1096,7 @@ 3.32 : null, 3.33 syms, 3.34 types, 3.35 - pool, 3.36 - varDebugInfo ? lvtRanges : null); 3.37 + pool); 3.38 items = new Items(pool, code, syms, types); 3.39 if (code.debugCode) { 3.40 System.err.println(meth + " for body " + tree); 3.41 @@ -1207,30 +1199,14 @@ 3.42 Chain loopDone = c.jumpFalse(); 3.43 code.resolve(c.trueJumps); 3.44 genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET); 3.45 - if (varDebugInfo) { 3.46 - checkLoopLocalVarRangeEnding(loop, body, 3.47 - LoopLocalVarRangeEndingPoint.BEFORE_STEPS); 3.48 - } 3.49 code.resolve(loopEnv.info.cont); 3.50 genStats(step, loopEnv); 3.51 - if (varDebugInfo) { 3.52 - checkLoopLocalVarRangeEnding(loop, body, 3.53 - LoopLocalVarRangeEndingPoint.AFTER_STEPS); 3.54 - } 3.55 code.resolve(code.branch(goto_), startpc); 3.56 code.resolve(loopDone); 3.57 } else { 3.58 genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET); 3.59 - if (varDebugInfo) { 3.60 - checkLoopLocalVarRangeEnding(loop, body, 3.61 - LoopLocalVarRangeEndingPoint.BEFORE_STEPS); 3.62 - } 3.63 code.resolve(loopEnv.info.cont); 3.64 genStats(step, loopEnv); 3.65 - if (varDebugInfo) { 3.66 - checkLoopLocalVarRangeEnding(loop, body, 3.67 - LoopLocalVarRangeEndingPoint.AFTER_STEPS); 3.68 - } 3.69 CondItem c; 3.70 if (cond != null) { 3.71 code.statBegin(cond.pos); 3.72 @@ -1247,44 +1223,6 @@ 3.73 } 3.74 } 3.75 3.76 - private enum LoopLocalVarRangeEndingPoint { 3.77 - BEFORE_STEPS, 3.78 - AFTER_STEPS, 3.79 - } 3.80 - 3.81 - /** 3.82 - * Checks whether we have reached an alive range ending point for local 3.83 - * variables after a loop. 3.84 - * 3.85 - * Local variables alive range ending point for loops varies depending 3.86 - * on the loop type. The range can be closed before or after the code 3.87 - * for the steps sentences has been generated. 3.88 - * 3.89 - * - While loops has no steps so in that case the range is closed just 3.90 - * after the body of the loop. 3.91 - * 3.92 - * - For-like loops may have steps so as long as the steps sentences 3.93 - * can possibly contain non-synthetic local variables, the alive range 3.94 - * for local variables must be closed after the steps in this case. 3.95 - */ 3.96 - private void checkLoopLocalVarRangeEnding(JCTree loop, JCTree body, 3.97 - LoopLocalVarRangeEndingPoint endingPoint) { 3.98 - if (varDebugInfo && lvtRanges.containsKey(code.meth, body)) { 3.99 - switch (endingPoint) { 3.100 - case BEFORE_STEPS: 3.101 - if (!loop.hasTag(FORLOOP)) { 3.102 - code.closeAliveRanges(body); 3.103 - } 3.104 - break; 3.105 - case AFTER_STEPS: 3.106 - if (loop.hasTag(FORLOOP)) { 3.107 - code.closeAliveRanges(body); 3.108 - } 3.109 - break; 3.110 - } 3.111 - } 3.112 - } 3.113 - 3.114 public void visitForeachLoop(JCEnhancedForLoop tree) { 3.115 throw new AssertionError(); // should have been removed by Lower. 3.116 } 3.117 @@ -1398,9 +1336,6 @@ 3.118 3.119 // Generate code for the statements in this case. 3.120 genStats(c.stats, switchEnv, CRT_FLOW_TARGET); 3.121 - if (varDebugInfo && lvtRanges.containsKey(code.meth, c.stats.last())) { 3.122 - code.closeAliveRanges(c.stats.last()); 3.123 - } 3.124 } 3.125 3.126 // Resolve all breaks. 3.127 @@ -1557,9 +1492,6 @@ 3.128 genFinalizer(env); 3.129 code.statBegin(TreeInfo.endPos(env.tree)); 3.130 Chain exitChain = code.branch(goto_); 3.131 - if (varDebugInfo && lvtRanges.containsKey(code.meth, body)) { 3.132 - code.closeAliveRanges(body); 3.133 - } 3.134 endFinalizerGap(env); 3.135 if (startpc != endpc) for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) { 3.136 // start off with exception on stack 3.137 @@ -1815,17 +1747,11 @@ 3.138 code.resolve(c.trueJumps); 3.139 genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET); 3.140 thenExit = code.branch(goto_); 3.141 - if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.thenpart)) { 3.142 - code.closeAliveRanges(tree.thenpart, code.cp); 3.143 - } 3.144 } 3.145 if (elseChain != null) { 3.146 code.resolve(elseChain); 3.147 if (tree.elsepart != null) { 3.148 genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET); 3.149 - if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.elsepart)) { 3.150 - code.closeAliveRanges(tree.elsepart); 3.151 - } 3.152 } 3.153 } 3.154 code.resolve(thenExit); 3.155 @@ -2514,16 +2440,6 @@ 3.156 localEnv.toplevel = env.toplevel; 3.157 localEnv.enclClass = cdef; 3.158 3.159 - /* We must not analyze synthetic methods 3.160 - */ 3.161 - if (varDebugInfo && (cdef.sym.flags() & SYNTHETIC) == 0) { 3.162 - try { 3.163 - new LVTAssignAnalyzer().analyzeTree(localEnv); 3.164 - } catch (Throwable e) { 3.165 - throw e; 3.166 - } 3.167 - } 3.168 - 3.169 for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) { 3.170 genDef(l.head, localEnv); 3.171 } 3.172 @@ -2609,282 +2525,4 @@ 3.173 } 3.174 } 3.175 3.176 - class LVTAssignAnalyzer 3.177 - extends Flow.AbstractAssignAnalyzer<LVTAssignAnalyzer.LVTAssignPendingExit> { 3.178 - 3.179 - final LVTBits lvtInits; 3.180 - 3.181 - /* This class is anchored to a context dependent tree. The tree can 3.182 - * vary inside the same instruction for example in the switch instruction 3.183 - * the same FlowBits instance can be anchored to the whole tree, or 3.184 - * to a given case. The aim is to always anchor the bits to the tree 3.185 - * capable of closing a DA range. 3.186 - */ 3.187 - class LVTBits extends Bits { 3.188 - 3.189 - JCTree currentTree; 3.190 - private int[] oldBits = null; 3.191 - BitsState stateBeforeOp; 3.192 - 3.193 - @Override 3.194 - public void clear() { 3.195 - generalOp(null, -1, BitsOpKind.CLEAR); 3.196 - } 3.197 - 3.198 - @Override 3.199 - protected void internalReset() { 3.200 - super.internalReset(); 3.201 - oldBits = null; 3.202 - } 3.203 - 3.204 - @Override 3.205 - public Bits assign(Bits someBits) { 3.206 - // bits can be null 3.207 - oldBits = bits; 3.208 - stateBeforeOp = currentState; 3.209 - super.assign(someBits); 3.210 - changed(); 3.211 - return this; 3.212 - } 3.213 - 3.214 - @Override 3.215 - public void excludeFrom(int start) { 3.216 - generalOp(null, start, BitsOpKind.EXCL_RANGE); 3.217 - } 3.218 - 3.219 - @Override 3.220 - public void excl(int x) { 3.221 - Assert.check(x >= 0); 3.222 - generalOp(null, x, BitsOpKind.EXCL_BIT); 3.223 - } 3.224 - 3.225 - @Override 3.226 - public Bits andSet(Bits xs) { 3.227 - return generalOp(xs, -1, BitsOpKind.AND_SET); 3.228 - } 3.229 - 3.230 - @Override 3.231 - public Bits orSet(Bits xs) { 3.232 - return generalOp(xs, -1, BitsOpKind.OR_SET); 3.233 - } 3.234 - 3.235 - @Override 3.236 - public Bits diffSet(Bits xs) { 3.237 - return generalOp(xs, -1, BitsOpKind.DIFF_SET); 3.238 - } 3.239 - 3.240 - @Override 3.241 - public Bits xorSet(Bits xs) { 3.242 - return generalOp(xs, -1, BitsOpKind.XOR_SET); 3.243 - } 3.244 - 3.245 - private Bits generalOp(Bits xs, int i, BitsOpKind opKind) { 3.246 - Assert.check(currentState != BitsState.UNKNOWN); 3.247 - oldBits = dupBits(); 3.248 - stateBeforeOp = currentState; 3.249 - switch (opKind) { 3.250 - case AND_SET: 3.251 - super.andSet(xs); 3.252 - break; 3.253 - case OR_SET: 3.254 - super.orSet(xs); 3.255 - break; 3.256 - case XOR_SET: 3.257 - super.xorSet(xs); 3.258 - break; 3.259 - case DIFF_SET: 3.260 - super.diffSet(xs); 3.261 - break; 3.262 - case CLEAR: 3.263 - super.clear(); 3.264 - break; 3.265 - case EXCL_BIT: 3.266 - super.excl(i); 3.267 - break; 3.268 - case EXCL_RANGE: 3.269 - super.excludeFrom(i); 3.270 - break; 3.271 - } 3.272 - changed(); 3.273 - return this; 3.274 - } 3.275 - 3.276 - /* The tree we need to anchor the bits instance to. 3.277 - */ 3.278 - LVTBits at(JCTree tree) { 3.279 - this.currentTree = tree; 3.280 - return this; 3.281 - } 3.282 - 3.283 - /* If the instance should be changed but the tree is not a closing 3.284 - * tree then a reset is needed or the former tree can mistakingly be 3.285 - * used. 3.286 - */ 3.287 - LVTBits resetTree() { 3.288 - this.currentTree = null; 3.289 - return this; 3.290 - } 3.291 - 3.292 - /** This method will be called after any operation that causes a change to 3.293 - * the bits. Subclasses can thus override it in order to extract information 3.294 - * from the changes produced to the bits by the given operation. 3.295 - */ 3.296 - public void changed() { 3.297 - if (currentTree != null && 3.298 - stateBeforeOp != BitsState.UNKNOWN && 3.299 - trackTree(currentTree)) { 3.300 - List<VarSymbol> locals = lvtRanges 3.301 - .getVars(currentMethod, currentTree); 3.302 - locals = locals != null ? 3.303 - locals : List.<VarSymbol>nil(); 3.304 - for (JCVariableDecl vardecl : vardecls) { 3.305 - //once the first is null, the rest will be so. 3.306 - if (vardecl == null) { 3.307 - break; 3.308 - } 3.309 - if (trackVar(vardecl.sym) && bitChanged(vardecl.sym.adr)) { 3.310 - locals = locals.prepend(vardecl.sym); 3.311 - } 3.312 - } 3.313 - if (!locals.isEmpty()) { 3.314 - lvtRanges.setEntry(currentMethod, 3.315 - currentTree, locals); 3.316 - } 3.317 - } 3.318 - } 3.319 - 3.320 - boolean bitChanged(int x) { 3.321 - boolean isMemberOfBits = isMember(x); 3.322 - int[] tmp = bits; 3.323 - bits = oldBits; 3.324 - boolean isMemberOfOldBits = isMember(x); 3.325 - bits = tmp; 3.326 - return (!isMemberOfBits && isMemberOfOldBits); 3.327 - } 3.328 - 3.329 - boolean trackVar(VarSymbol var) { 3.330 - return (var.owner.kind == MTH && 3.331 - (var.flags() & PARAMETER) == 0 && 3.332 - trackable(var)); 3.333 - } 3.334 - 3.335 - boolean trackTree(JCTree tree) { 3.336 - switch (tree.getTag()) { 3.337 - // of course a method closes the alive range of a local variable. 3.338 - case METHODDEF: 3.339 - // for while loops we want only the body 3.340 - case WHILELOOP: 3.341 - return false; 3.342 - } 3.343 - return true; 3.344 - } 3.345 - 3.346 - } 3.347 - 3.348 - public class LVTAssignPendingExit extends 3.349 - Flow.AbstractAssignAnalyzer<LVTAssignPendingExit>.AbstractAssignPendingExit { 3.350 - 3.351 - LVTAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { 3.352 - super(tree, inits, uninits); 3.353 - } 3.354 - 3.355 - @Override 3.356 - public void resolveJump(JCTree tree) { 3.357 - lvtInits.at(tree); 3.358 - super.resolveJump(tree); 3.359 - } 3.360 - } 3.361 - 3.362 - private LVTAssignAnalyzer() { 3.363 - flow.super(); 3.364 - lvtInits = new LVTBits(); 3.365 - inits = lvtInits; 3.366 - } 3.367 - 3.368 - @Override 3.369 - protected void markDead(JCTree tree) { 3.370 - lvtInits.at(tree).inclRange(returnadr, nextadr); 3.371 - super.markDead(tree); 3.372 - } 3.373 - 3.374 - @Override 3.375 - protected void merge(JCTree tree) { 3.376 - lvtInits.at(tree); 3.377 - super.merge(tree); 3.378 - } 3.379 - 3.380 - boolean isSyntheticOrMandated(Symbol sym) { 3.381 - return (sym.flags() & (SYNTHETIC | MANDATED)) != 0; 3.382 - } 3.383 - 3.384 - @Override 3.385 - protected boolean trackable(VarSymbol sym) { 3.386 - if (isSyntheticOrMandated(sym)) { 3.387 - //fast check to avoid tracking synthetic or mandated variables 3.388 - return false; 3.389 - } 3.390 - return super.trackable(sym); 3.391 - } 3.392 - 3.393 - @Override 3.394 - protected void initParam(JCVariableDecl def) { 3.395 - if (!isSyntheticOrMandated(def.sym)) { 3.396 - super.initParam(def); 3.397 - } 3.398 - } 3.399 - 3.400 - @Override 3.401 - protected void assignToInits(JCTree tree, Bits bits) { 3.402 - lvtInits.at(tree); 3.403 - lvtInits.assign(bits); 3.404 - } 3.405 - 3.406 - @Override 3.407 - protected void andSetInits(JCTree tree, Bits bits) { 3.408 - lvtInits.at(tree); 3.409 - lvtInits.andSet(bits); 3.410 - } 3.411 - 3.412 - @Override 3.413 - protected void orSetInits(JCTree tree, Bits bits) { 3.414 - lvtInits.at(tree); 3.415 - lvtInits.orSet(bits); 3.416 - } 3.417 - 3.418 - @Override 3.419 - protected void exclVarFromInits(JCTree tree, int adr) { 3.420 - lvtInits.at(tree); 3.421 - lvtInits.excl(adr); 3.422 - } 3.423 - 3.424 - @Override 3.425 - protected LVTAssignPendingExit createNewPendingExit(JCTree tree, Bits inits, Bits uninits) { 3.426 - return new LVTAssignPendingExit(tree, inits, uninits); 3.427 - } 3.428 - 3.429 - MethodSymbol currentMethod; 3.430 - 3.431 - @Override 3.432 - public void visitMethodDef(JCMethodDecl tree) { 3.433 - if ((tree.sym.flags() & (SYNTHETIC | GENERATEDCONSTR)) != 0 3.434 - && (tree.sym.flags() & LAMBDA_METHOD) == 0) { 3.435 - return; 3.436 - } 3.437 - if (tree.name.equals(names.clinit)) { 3.438 - return; 3.439 - } 3.440 - boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0; 3.441 - if (enumClass && 3.442 - (tree.name.equals(names.valueOf) || 3.443 - tree.name.equals(names.values) || 3.444 - tree.name.equals(names.init))) { 3.445 - return; 3.446 - } 3.447 - currentMethod = tree.sym; 3.448 - 3.449 - super.visitMethodDef(tree); 3.450 - } 3.451 - 3.452 - } 3.453 - 3.454 }
4.1 --- a/src/share/classes/com/sun/tools/javac/jvm/LVTRanges.java Tue Jan 13 12:41:16 2015 -0800 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,129 +0,0 @@ 4.4 -/* 4.5 - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 4.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 - * 4.8 - * This code is free software; you can redistribute it and/or modify it 4.9 - * under the terms of the GNU General Public License version 2 only, as 4.10 - * published by the Free Software Foundation. Oracle designates this 4.11 - * particular file as subject to the "Classpath" exception as provided 4.12 - * by Oracle in the LICENSE file that accompanied this code. 4.13 - * 4.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 4.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.17 - * version 2 for more details (a copy is included in the LICENSE file that 4.18 - * accompanied this code). 4.19 - * 4.20 - * You should have received a copy of the GNU General Public License version 4.21 - * 2 along with this work; if not, write to the Free Software Foundation, 4.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.23 - * 4.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.25 - * or visit www.oracle.com if you need additional information or have any 4.26 - * questions. 4.27 - */ 4.28 - 4.29 -package com.sun.tools.javac.jvm; 4.30 - 4.31 -import java.util.Map; 4.32 -import java.util.Map.Entry; 4.33 -import java.util.WeakHashMap; 4.34 - 4.35 -import com.sun.tools.javac.code.Symbol.MethodSymbol; 4.36 -import com.sun.tools.javac.code.Symbol.VarSymbol; 4.37 -import com.sun.tools.javac.tree.JCTree; 4.38 -import com.sun.tools.javac.util.Context; 4.39 -import com.sun.tools.javac.util.List; 4.40 - 4.41 -/** This class contains a one to many relation between a tree and a set of variables. 4.42 - * The relation implies that the given tree closes the DA (definite assignment) 4.43 - * range for the set of variables. 4.44 - * 4.45 - * <p><b>This is NOT part of any supported API. 4.46 - * If you write code that depends on this, you do so at your own risk. 4.47 - * This code and its internal interfaces are subject to change or 4.48 - * deletion without notice.</b> 4.49 - */ 4.50 -public class LVTRanges { 4.51 - /** The context key for the LVT ranges. */ 4.52 - protected static final Context.Key<LVTRanges> lvtRangesKey = new Context.Key<>(); 4.53 - 4.54 - /** Get the LVTRanges instance for this context. */ 4.55 - public static LVTRanges instance(Context context) { 4.56 - LVTRanges instance = context.get(lvtRangesKey); 4.57 - if (instance == null) { 4.58 - instance = new LVTRanges(context); 4.59 - } 4.60 - return instance; 4.61 - } 4.62 - 4.63 - private static final long serialVersionUID = 1812267524140424433L; 4.64 - 4.65 - protected Context context; 4.66 - 4.67 - protected Map<MethodSymbol, Map<JCTree, List<VarSymbol>>> 4.68 - aliveRangeClosingTrees = new WeakHashMap<>(); 4.69 - 4.70 - public LVTRanges(Context context) { 4.71 - this.context = context; 4.72 - context.put(lvtRangesKey, this); 4.73 - } 4.74 - 4.75 - public List<VarSymbol> getVars(MethodSymbol method, JCTree tree) { 4.76 - Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method); 4.77 - return (varMap != null) ? varMap.get(tree) : null; 4.78 - } 4.79 - 4.80 - public boolean containsKey(MethodSymbol method, JCTree tree) { 4.81 - Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method); 4.82 - if (varMap == null) { 4.83 - return false; 4.84 - } 4.85 - return varMap.containsKey(tree); 4.86 - } 4.87 - 4.88 - public void setEntry(MethodSymbol method, JCTree tree, List<VarSymbol> vars) { 4.89 - Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method); 4.90 - if (varMap != null) { 4.91 - varMap.put(tree, vars); 4.92 - } else { 4.93 - varMap = new WeakHashMap<>(); 4.94 - varMap.put(tree, vars); 4.95 - aliveRangeClosingTrees.put(method, varMap); 4.96 - } 4.97 - } 4.98 - 4.99 - public List<VarSymbol> removeEntry(MethodSymbol method, JCTree tree) { 4.100 - Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method); 4.101 - if (varMap != null) { 4.102 - List<VarSymbol> result = varMap.remove(tree); 4.103 - if (varMap.isEmpty()) { 4.104 - aliveRangeClosingTrees.remove(method); 4.105 - } 4.106 - return result; 4.107 - } 4.108 - return null; 4.109 - } 4.110 - 4.111 - /* This method should be used for debugging LVT related issues. 4.112 - */ 4.113 - @Override 4.114 - public String toString() { 4.115 - String result = ""; 4.116 - for (Entry<MethodSymbol, Map<JCTree, List<VarSymbol>>> mainEntry: aliveRangeClosingTrees.entrySet()) { 4.117 - result += "Method: \n" + mainEntry.getKey().flatName() + "\n"; 4.118 - int i = 1; 4.119 - for (Entry<JCTree, List<VarSymbol>> treeEntry: mainEntry.getValue().entrySet()) { 4.120 - result += " Tree " + i + ": \n" + treeEntry.getKey().toString() + "\n"; 4.121 - result += " Variables closed:\n"; 4.122 - for (VarSymbol var: treeEntry.getValue()) { 4.123 - result += " " + var.toString(); 4.124 - } 4.125 - result += "\n"; 4.126 - i++; 4.127 - } 4.128 - } 4.129 - return result; 4.130 - } 4.131 - 4.132 -}
5.1 --- a/test/tools/javac/flow/LVTHarness.java Tue Jan 13 12:41:16 2015 -0800 5.2 +++ b/test/tools/javac/flow/LVTHarness.java Tue Jan 20 14:14:33 2015 -0800 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. 5.6 + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 5.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 * 5.9 * This code is free software; you can redistribute it and/or modify it 5.10 @@ -23,7 +23,7 @@ 5.11 5.12 /* 5.13 * @test 5.14 - * @bug 7047734 8027660 8037937 8047719 8058708 5.15 + * @bug 7047734 8027660 8037937 8047719 8058708 8064857 5.16 * @summary The LVT is not generated correctly during some try/catch scenarios 5.17 * javac crash while creating LVT entry for a local variable defined in 5.18 * an inner block 5.19 @@ -144,7 +144,7 @@ 5.20 } 5.21 5.22 void checkMethod(ConstantPool constantPool, Method method, AliveRanges ranges) 5.23 - throws InvalidIndex, UnexpectedEntry { 5.24 + throws InvalidIndex, UnexpectedEntry, ConstantPoolException { 5.25 Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code); 5.26 LocalVariableTable_attribute lvt = 5.27 (LocalVariableTable_attribute) (code.attributes.get(Attribute.LocalVariableTable)); 5.28 @@ -166,7 +166,7 @@ 5.29 } 5.30 5.31 if (i < infoFromRanges.size()) { 5.32 - error(infoFromLVT, infoFromRanges); 5.33 + error(infoFromLVT, infoFromRanges, method.getName(constantPool).toString()); 5.34 } 5.35 } 5.36 5.37 @@ -202,9 +202,10 @@ 5.38 return sb.toString(); 5.39 } 5.40 5.41 - protected void error(List<String> infoFromLVT, List<String> infoFromRanges) { 5.42 + protected void error(List<String> infoFromLVT, List<String> infoFromRanges, String methodName) { 5.43 nerrors++; 5.44 System.err.printf("Error occurred while checking file: %s\n", jfo.getName()); 5.45 + System.err.printf("at method: %s\n", methodName); 5.46 System.err.println("The range info from the annotations is"); 5.47 printStringListToErrOutput(infoFromRanges); 5.48 System.err.println();
6.1 --- a/test/tools/javac/flow/tests/TestCaseFor.java Tue Jan 13 12:41:16 2015 -0800 6.2 +++ b/test/tools/javac/flow/tests/TestCaseFor.java Tue Jan 20 14:14:33 2015 -0800 6.3 @@ -2,7 +2,7 @@ 6.4 6.5 public class TestCaseFor { 6.6 6.7 - @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=8) 6.8 + @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=11) 6.9 @AliveRange(varName="o", bytecodeStart=24, bytecodeLength=1) 6.10 void m1(String[] args) { 6.11 Object o; 6.12 @@ -13,7 +13,7 @@ 6.13 o = ""; 6.14 } 6.15 6.16 - @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=8) 6.17 + @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=11) 6.18 @AliveRange(varName="o", bytecodeStart=24, bytecodeLength=1) 6.19 void m2(String[] args) { 6.20 Object o;
7.1 --- a/test/tools/javac/flow/tests/TestCaseForEach.java Tue Jan 13 12:41:16 2015 -0800 7.2 +++ b/test/tools/javac/flow/tests/TestCaseForEach.java Tue Jan 20 14:14:33 2015 -0800 7.3 @@ -2,7 +2,7 @@ 7.4 7.5 public class TestCaseForEach { 7.6 7.7 - @AliveRange(varName="o", bytecodeStart=25, bytecodeLength=8) 7.8 + @AliveRange(varName="o", bytecodeStart=25, bytecodeLength=11) 7.9 @AliveRange(varName="o", bytecodeStart=39, bytecodeLength=1) 7.10 void m(String[] args) { 7.11 Object o;
8.1 --- a/test/tools/javac/flow/tests/TestCaseIfElse.java Tue Jan 13 12:41:16 2015 -0800 8.2 +++ b/test/tools/javac/flow/tests/TestCaseIfElse.java Tue Jan 20 14:14:33 2015 -0800 8.3 @@ -60,4 +60,19 @@ 8.4 } 8.5 return null; 8.6 } 8.7 + 8.8 + @AliveRange(varName="i", bytecodeStart=6, bytecodeLength=2) 8.9 + int m4(boolean flag) { 8.10 + int i; 8.11 + label: 8.12 + { 8.13 + if (flag) { 8.14 + i = 1; 8.15 + } else { 8.16 + break label; 8.17 + } 8.18 + return i; 8.19 + } 8.20 + return -1; 8.21 + } 8.22 }
9.1 --- a/test/tools/javac/flow/tests/TestCaseSwitch.java Tue Jan 13 12:41:16 2015 -0800 9.2 +++ b/test/tools/javac/flow/tests/TestCaseSwitch.java Tue Jan 20 14:14:33 2015 -0800 9.3 @@ -81,4 +81,26 @@ 9.4 o = "finish"; 9.5 } 9.6 9.7 + @AliveRange(varName="oCache", bytecodeStart=30, bytecodeLength=6) 9.8 + @AliveRange(varName="cache", bytecodeStart=41, bytecodeLength=3) 9.9 + @AliveRange(varName="cache", bytecodeStart=54, bytecodeLength=2) 9.10 + @AliveRange(varName="service", bytecodeStart=39, bytecodeLength=5) 9.11 + Object m4(int i) { 9.12 + Object cache; 9.13 + switch (i) { 9.14 + case 0: 9.15 + Object oCache = null; 9.16 + if (oCache != null) { 9.17 + return oCache; 9.18 + } 9.19 + case 1: 9.20 + Object service = null; 9.21 + cache = null; 9.22 + break; 9.23 + default: 9.24 + throw new AssertionError(""); 9.25 + } 9.26 + return cache; 9.27 + } 9.28 + 9.29 }
10.1 --- a/test/tools/javac/flow/tests/TestCaseTry.java Tue Jan 13 12:41:16 2015 -0800 10.2 +++ b/test/tools/javac/flow/tests/TestCaseTry.java Tue Jan 20 14:14:33 2015 -0800 10.3 @@ -17,7 +17,8 @@ 10.4 } 10.5 10.6 @AliveRange(varName="o", bytecodeStart=3, bytecodeLength=16) 10.7 - @AliveRange(varName="o", bytecodeStart=23, bytecodeLength=23) 10.8 + @AliveRange(varName="o", bytecodeStart=23, bytecodeLength=8) 10.9 + @AliveRange(varName="o", bytecodeStart=35, bytecodeLength=11) 10.10 void m1() { 10.11 Object o; 10.12 try { 10.13 @@ -33,7 +34,8 @@ 10.14 } 10.15 10.16 @AliveRange(varName="o", bytecodeStart=3, bytecodeLength=16) 10.17 - @AliveRange(varName="o", bytecodeStart=23, bytecodeLength=31) 10.18 + @AliveRange(varName="o", bytecodeStart=23, bytecodeLength=16) 10.19 + @AliveRange(varName="o", bytecodeStart=43, bytecodeLength=11) 10.20 void m2() { 10.21 Object o; 10.22 try { 10.23 @@ -51,7 +53,8 @@ 10.24 } 10.25 10.26 @AliveRange(varName="o", bytecodeStart=22, bytecodeLength=38) 10.27 - @AliveRange(varName="o", bytecodeStart=103, bytecodeLength=8) 10.28 + @AliveRange(varName="o", bytecodeStart=103, bytecodeLength=3) 10.29 + @AliveRange(varName="o", bytecodeStart=110, bytecodeLength=1) 10.30 void m3() { 10.31 Object o; 10.32 try (BufferedReader br =
11.1 --- a/test/tools/javac/flow/tests/TestCaseWhile.java Tue Jan 13 12:41:16 2015 -0800 11.2 +++ b/test/tools/javac/flow/tests/TestCaseWhile.java Tue Jan 20 14:14:33 2015 -0800 11.3 @@ -2,7 +2,7 @@ 11.4 11.5 public class TestCaseWhile { 11.6 11.7 - @AliveRange(varName="o", bytecodeStart=9, bytecodeLength=5) 11.8 + @AliveRange(varName="o", bytecodeStart=9, bytecodeLength=8) 11.9 @AliveRange(varName="o", bytecodeStart=20, bytecodeLength=1) 11.10 void m(String[] args) { 11.11 Object o;