Fri, 14 Jun 2013 16:25:09 +0100
8016569: javac, add new flag for polymorphic method signatures
Reviewed-by: jjg
Contributed-by: maurizio.cimadamore@oracle.com
1 /*
2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javac.jvm;
28 import java.util.*;
30 import com.sun.tools.javac.tree.*;
31 import com.sun.tools.javac.util.*;
32 import com.sun.tools.javac.util.List;
33 import com.sun.tools.javac.tree.JCTree.*;
34 import com.sun.tools.javac.tree.EndPosTable;
36 /** This class contains the CharacterRangeTable for some method
37 * and the hashtable for mapping trees or lists of trees to their
38 * ending positions.
39 *
40 * <p><b>This is NOT part of any supported API.
41 * If you write code that depends on this, you do so at your own risk.
42 * This code and its internal interfaces are subject to change or
43 * deletion without notice.</b>
44 */
45 public class CRTable
46 implements CRTFlags {
48 private final boolean crtDebug = false;
50 /** The list of CRTable entries.
51 */
52 private ListBuffer<CRTEntry> entries = new ListBuffer<CRTEntry>();
54 /** The hashtable for source positions.
55 */
56 private Map<Object,SourceRange> positions = new HashMap<Object,SourceRange>();
58 /** The object for ending positions stored in the parser.
59 */
60 private EndPosTable endPosTable;
62 /** The tree of the method this table is intended for.
63 * We should traverse this tree to get source ranges.
64 */
65 JCTree.JCMethodDecl methodTree;
67 /** Constructor
68 */
69 public CRTable(JCTree.JCMethodDecl tree, EndPosTable endPosTable) {
70 this.methodTree = tree;
71 this.endPosTable = endPosTable;
72 }
74 /** Create a new CRTEntry and add it to the entries.
75 * @param tree The tree or the list of trees for which
76 * we are storing the code pointers.
77 * @param flags The set of flags designating type of the entry.
78 * @param startPc The starting code position.
79 * @param endPc The ending code position.
80 */
81 public void put(Object tree, int flags, int startPc, int endPc) {
82 entries.append(new CRTEntry(tree, flags, startPc, endPc));
83 }
85 /** Compute source positions and write CRT to the databuf.
86 * @param databuf The buffer to write bytecodes to.
87 */
88 public int writeCRT(ByteBuffer databuf, Position.LineMap lineMap, Log log) {
90 int crtEntries = 0;
92 // compute source positions for the method
93 new SourceComputer().csp(methodTree);
95 for (List<CRTEntry> l = entries.toList(); l.nonEmpty(); l = l.tail) {
97 CRTEntry entry = l.head;
99 // eliminate entries that do not produce bytecodes:
100 // for example, empty blocks and statements
101 if (entry.startPc == entry.endPc)
102 continue;
104 SourceRange pos = positions.get(entry.tree);
105 Assert.checkNonNull(pos, "CRT: tree source positions are undefined");
106 if ((pos.startPos == Position.NOPOS) || (pos.endPos == Position.NOPOS))
107 continue;
109 if (crtDebug) {
110 System.out.println("Tree: " + entry.tree + ", type:" + getTypes(entry.flags));
111 System.out.print("Start: pos = " + pos.startPos + ", pc = " + entry.startPc);
112 }
114 // encode startPos into line/column representation
115 int startPos = encodePosition(pos.startPos, lineMap, log);
116 if (startPos == Position.NOPOS)
117 continue;
119 if (crtDebug) {
120 System.out.print("End: pos = " + pos.endPos + ", pc = " + (entry.endPc - 1));
121 }
123 // encode endPos into line/column representation
124 int endPos = encodePosition(pos.endPos, lineMap, log);
125 if (endPos == Position.NOPOS)
126 continue;
128 // write attribute
129 databuf.appendChar(entry.startPc);
130 // 'endPc - 1' because endPc actually points to start of the next command
131 databuf.appendChar(entry.endPc - 1);
132 databuf.appendInt(startPos);
133 databuf.appendInt(endPos);
134 databuf.appendChar(entry.flags);
136 crtEntries++;
137 }
139 return crtEntries;
140 }
142 /** Return the number of the entries.
143 */
144 public int length() {
145 return entries.length();
146 }
148 /** Return string describing flags enabled.
149 */
150 private String getTypes(int flags) {
151 String types = "";
152 if ((flags & CRT_STATEMENT) != 0) types += " CRT_STATEMENT";
153 if ((flags & CRT_BLOCK) != 0) types += " CRT_BLOCK";
154 if ((flags & CRT_ASSIGNMENT) != 0) types += " CRT_ASSIGNMENT";
155 if ((flags & CRT_FLOW_CONTROLLER) != 0) types += " CRT_FLOW_CONTROLLER";
156 if ((flags & CRT_FLOW_TARGET) != 0) types += " CRT_FLOW_TARGET";
157 if ((flags & CRT_INVOKE) != 0) types += " CRT_INVOKE";
158 if ((flags & CRT_CREATE) != 0) types += " CRT_CREATE";
159 if ((flags & CRT_BRANCH_TRUE) != 0) types += " CRT_BRANCH_TRUE";
160 if ((flags & CRT_BRANCH_FALSE) != 0) types += " CRT_BRANCH_FALSE";
161 return types;
162 }
164 /** Source file positions in CRT are integers in the format:
165 * {@literal line-number << LINESHIFT + column-number }
166 */
167 private int encodePosition(int pos, Position.LineMap lineMap, Log log) {
168 int line = lineMap.getLineNumber(pos);
169 int col = lineMap.getColumnNumber(pos);
170 int new_pos = Position.encodePosition(line, col);
171 if (crtDebug) {
172 System.out.println(", line = " + line + ", column = " + col +
173 ", new_pos = " + new_pos);
174 }
175 if (new_pos == Position.NOPOS)
176 log.warning(pos, "position.overflow", line);
178 return new_pos;
179 }
181 /* ************************************************************************
182 * Traversal methods
183 *************************************************************************/
185 /**
186 * This class contains methods to compute source positions for trees.
187 * Extends Tree.Visitor to traverse the abstract syntax tree.
188 */
189 class SourceComputer extends JCTree.Visitor {
191 /** The result of the tree traversal methods.
192 */
193 SourceRange result;
195 /** Visitor method: compute source positions for a single node.
196 */
197 public SourceRange csp(JCTree tree) {
198 if (tree == null) return null;
199 tree.accept(this);
200 if (result != null) {
201 positions.put(tree, result);
202 }
203 return result;
204 }
206 /** Visitor method: compute source positions for a list of nodes.
207 */
208 public SourceRange csp(List<? extends JCTree> trees) {
209 if ((trees == null) || !(trees.nonEmpty())) return null;
210 SourceRange list_sr = new SourceRange();
211 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) {
212 list_sr.mergeWith(csp(l.head));
213 }
214 positions.put(trees, list_sr);
215 return list_sr;
216 }
218 /** Visitor method: compute source positions for
219 * a list of case blocks of switch statements.
220 */
221 public SourceRange cspCases(List<JCCase> trees) {
222 if ((trees == null) || !(trees.nonEmpty())) return null;
223 SourceRange list_sr = new SourceRange();
224 for (List<JCCase> l = trees; l.nonEmpty(); l = l.tail) {
225 list_sr.mergeWith(csp(l.head));
226 }
227 positions.put(trees, list_sr);
228 return list_sr;
229 }
231 /** Visitor method: compute source positions for
232 * a list of catch clauses in try statements.
233 */
234 public SourceRange cspCatchers(List<JCCatch> trees) {
235 if ((trees == null) || !(trees.nonEmpty())) return null;
236 SourceRange list_sr = new SourceRange();
237 for (List<JCCatch> l = trees; l.nonEmpty(); l = l.tail) {
238 list_sr.mergeWith(csp(l.head));
239 }
240 positions.put(trees, list_sr);
241 return list_sr;
242 }
244 public void visitMethodDef(JCMethodDecl tree) {
245 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
246 sr.mergeWith(csp(tree.body));
247 result = sr;
248 }
250 public void visitVarDef(JCVariableDecl tree) {
251 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
252 csp(tree.vartype);
253 sr.mergeWith(csp(tree.init));
254 result = sr;
255 }
257 public void visitSkip(JCSkip tree) {
258 // endPos is the same as startPos for the empty statement
259 SourceRange sr = new SourceRange(startPos(tree), startPos(tree));
260 result = sr;
261 }
263 public void visitBlock(JCBlock tree) {
264 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
265 csp(tree.stats); // doesn't compare because block's ending position is defined
266 result = sr;
267 }
269 public void visitDoLoop(JCDoWhileLoop tree) {
270 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
271 sr.mergeWith(csp(tree.body));
272 sr.mergeWith(csp(tree.cond));
273 result = sr;
274 }
276 public void visitWhileLoop(JCWhileLoop tree) {
277 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
278 sr.mergeWith(csp(tree.cond));
279 sr.mergeWith(csp(tree.body));
280 result = sr;
281 }
283 public void visitForLoop(JCForLoop tree) {
284 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
285 sr.mergeWith(csp(tree.init));
286 sr.mergeWith(csp(tree.cond));
287 sr.mergeWith(csp(tree.step));
288 sr.mergeWith(csp(tree.body));
289 result = sr;
290 }
292 public void visitForeachLoop(JCEnhancedForLoop tree) {
293 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
294 sr.mergeWith(csp(tree.var));
295 sr.mergeWith(csp(tree.expr));
296 sr.mergeWith(csp(tree.body));
297 result = sr;
298 }
300 public void visitLabelled(JCLabeledStatement tree) {
301 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
302 sr.mergeWith(csp(tree.body));
303 result = sr;
304 }
306 public void visitSwitch(JCSwitch tree) {
307 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
308 sr.mergeWith(csp(tree.selector));
309 sr.mergeWith(cspCases(tree.cases));
310 result = sr;
311 }
313 public void visitCase(JCCase tree) {
314 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
315 sr.mergeWith(csp(tree.pat));
316 sr.mergeWith(csp(tree.stats));
317 result = sr;
318 }
320 public void visitSynchronized(JCSynchronized tree) {
321 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
322 sr.mergeWith(csp(tree.lock));
323 sr.mergeWith(csp(tree.body));
324 result = sr;
325 }
327 public void visitTry(JCTry tree) {
328 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
329 sr.mergeWith(csp(tree.resources));
330 sr.mergeWith(csp(tree.body));
331 sr.mergeWith(cspCatchers(tree.catchers));
332 sr.mergeWith(csp(tree.finalizer));
333 result = sr;
334 }
336 public void visitCatch(JCCatch tree) {
337 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
338 sr.mergeWith(csp(tree.param));
339 sr.mergeWith(csp(tree.body));
340 result = sr;
341 }
343 public void visitConditional(JCConditional tree) {
344 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
345 sr.mergeWith(csp(tree.cond));
346 sr.mergeWith(csp(tree.truepart));
347 sr.mergeWith(csp(tree.falsepart));
348 result = sr;
349 }
351 public void visitIf(JCIf tree) {
352 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
353 sr.mergeWith(csp(tree.cond));
354 sr.mergeWith(csp(tree.thenpart));
355 sr.mergeWith(csp(tree.elsepart));
356 result = sr;
357 }
359 public void visitExec(JCExpressionStatement tree) {
360 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
361 sr.mergeWith(csp(tree.expr));
362 result = sr;
363 }
365 public void visitBreak(JCBreak tree) {
366 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
367 result = sr;
368 }
370 public void visitContinue(JCContinue tree) {
371 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
372 result = sr;
373 }
375 public void visitReturn(JCReturn tree) {
376 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
377 sr.mergeWith(csp(tree.expr));
378 result = sr;
379 }
381 public void visitThrow(JCThrow tree) {
382 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
383 sr.mergeWith(csp(tree.expr));
384 result = sr;
385 }
387 public void visitAssert(JCAssert tree) {
388 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
389 sr.mergeWith(csp(tree.cond));
390 sr.mergeWith(csp(tree.detail));
391 result = sr;
392 }
394 public void visitApply(JCMethodInvocation tree) {
395 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
396 sr.mergeWith(csp(tree.meth));
397 sr.mergeWith(csp(tree.args));
398 result = sr;
399 }
401 public void visitNewClass(JCNewClass tree) {
402 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
403 sr.mergeWith(csp(tree.encl));
404 sr.mergeWith(csp(tree.clazz));
405 sr.mergeWith(csp(tree.args));
406 sr.mergeWith(csp(tree.def));
407 result = sr;
408 }
410 public void visitNewArray(JCNewArray tree) {
411 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
412 sr.mergeWith(csp(tree.elemtype));
413 sr.mergeWith(csp(tree.dims));
414 sr.mergeWith(csp(tree.elems));
415 result = sr;
416 }
418 public void visitParens(JCParens tree) {
419 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
420 sr.mergeWith(csp(tree.expr));
421 result = sr;
422 }
424 public void visitAssign(JCAssign tree) {
425 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
426 sr.mergeWith(csp(tree.lhs));
427 sr.mergeWith(csp(tree.rhs));
428 result = sr;
429 }
431 public void visitAssignop(JCAssignOp tree) {
432 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
433 sr.mergeWith(csp(tree.lhs));
434 sr.mergeWith(csp(tree.rhs));
435 result = sr;
436 }
438 public void visitUnary(JCUnary tree) {
439 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
440 sr.mergeWith(csp(tree.arg));
441 result = sr;
442 }
444 public void visitBinary(JCBinary tree) {
445 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
446 sr.mergeWith(csp(tree.lhs));
447 sr.mergeWith(csp(tree.rhs));
448 result = sr;
449 }
451 public void visitTypeCast(JCTypeCast tree) {
452 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
453 sr.mergeWith(csp(tree.clazz));
454 sr.mergeWith(csp(tree.expr));
455 result = sr;
456 }
458 public void visitTypeTest(JCInstanceOf tree) {
459 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
460 sr.mergeWith(csp(tree.expr));
461 sr.mergeWith(csp(tree.clazz));
462 result = sr;
463 }
465 public void visitIndexed(JCArrayAccess tree) {
466 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
467 sr.mergeWith(csp(tree.indexed));
468 sr.mergeWith(csp(tree.index));
469 result = sr;
470 }
472 public void visitSelect(JCFieldAccess tree) {
473 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
474 sr.mergeWith(csp(tree.selected));
475 result = sr;
476 }
478 public void visitIdent(JCIdent tree) {
479 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
480 result = sr;
481 }
483 public void visitLiteral(JCLiteral tree) {
484 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
485 result = sr;
486 }
488 public void visitTypeIdent(JCPrimitiveTypeTree tree) {
489 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
490 result = sr;
491 }
493 public void visitTypeArray(JCArrayTypeTree tree) {
494 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
495 sr.mergeWith(csp(tree.elemtype));
496 result = sr;
497 }
499 public void visitTypeApply(JCTypeApply tree) {
500 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
501 sr.mergeWith(csp(tree.clazz));
502 sr.mergeWith(csp(tree.arguments));
503 result = sr;
504 }
506 @Override
507 public void visitLetExpr(LetExpr tree) {
508 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
509 sr.mergeWith(csp(tree.defs));
510 sr.mergeWith(csp(tree.expr));
511 result = sr;
512 }
514 public void visitTypeParameter(JCTypeParameter tree) {
515 SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
516 sr.mergeWith(csp(tree.bounds));
517 result = sr;
518 }
520 public void visitWildcard(JCWildcard tree) {
521 result = null;
522 }
524 public void visitErroneous(JCErroneous tree) {
525 result = null;
526 }
528 public void visitTree(JCTree tree) {
529 Assert.error();
530 }
532 /** The start position of given tree.
533 */
534 public int startPos(JCTree tree) {
535 if (tree == null) return Position.NOPOS;
536 return TreeInfo.getStartPos(tree);
537 }
539 /** The end position of given tree, if it has
540 * defined endpos, NOPOS otherwise.
541 */
542 public int endPos(JCTree tree) {
543 if (tree == null) return Position.NOPOS;
544 return TreeInfo.getEndPos(tree, endPosTable);
545 }
546 }
548 /** This class contains a CharacterRangeTableEntry.
549 */
550 static class CRTEntry {
552 /** A tree or a list of trees to obtain source positions.
553 */
554 Object tree;
556 /** The flags described in the CharacterRangeTable spec.
557 */
558 int flags;
560 /** The starting code position of this entry.
561 */
562 int startPc;
564 /** The ending code position of this entry.
565 */
566 int endPc;
568 /** Constructor */
569 CRTEntry(Object tree, int flags, int startPc, int endPc) {
570 this.tree = tree;
571 this.flags = flags;
572 this.startPc = startPc;
573 this.endPc = endPc;
574 }
575 }
578 /** This class contains source positions
579 * for some tree or list of trees.
580 */
581 static class SourceRange {
583 /** The starting source position.
584 */
585 int startPos;
587 /** The ending source position.
588 */
589 int endPos;
591 /** Constructor */
592 SourceRange() {
593 startPos = Position.NOPOS;
594 endPos = Position.NOPOS;
595 }
597 /** Constructor */
598 SourceRange(int startPos, int endPos) {
599 this.startPos = startPos;
600 this.endPos = endPos;
601 }
603 /** Compare the starting and the ending positions
604 * of the source range and combines them assigning
605 * the widest range to this.
606 */
607 SourceRange mergeWith(SourceRange sr) {
608 if (sr == null) return this;
609 if (startPos == Position.NOPOS)
610 startPos = sr.startPos;
611 else if (sr.startPos != Position.NOPOS)
612 startPos = (startPos < sr.startPos ? startPos : sr.startPos);
613 if (endPos == Position.NOPOS)
614 endPos = sr.endPos;
615 else if (sr.endPos != Position.NOPOS)
616 endPos = (endPos > sr.endPos ? endPos : sr.endPos);
617 return this;
618 }
619 }
621 }