72 private final Type stringBufferType; |
72 private final Type stringBufferType; |
73 private final Map<Type,Symbol> stringBufferAppend; |
73 private final Map<Type,Symbol> stringBufferAppend; |
74 private Name accessDollar; |
74 private Name accessDollar; |
75 private final Types types; |
75 private final Types types; |
76 private final Lower lower; |
76 private final Lower lower; |
|
77 private final Flow flow; |
77 |
78 |
78 /** Switch: GJ mode? |
79 /** Switch: GJ mode? |
79 */ |
80 */ |
80 private final boolean allowGenerics; |
81 private final boolean allowGenerics; |
81 |
82 |
123 ? syms.stringBuilderType |
124 ? syms.stringBuilderType |
124 : syms.stringBufferType; |
125 : syms.stringBufferType; |
125 stringBufferAppend = new HashMap<Type,Symbol>(); |
126 stringBufferAppend = new HashMap<Type,Symbol>(); |
126 accessDollar = names. |
127 accessDollar = names. |
127 fromString("access" + target.syntheticNameChar()); |
128 fromString("access" + target.syntheticNameChar()); |
|
129 flow = Flow.instance(context); |
128 lower = Lower.instance(context); |
130 lower = Lower.instance(context); |
129 |
131 |
130 Options options = Options.instance(context); |
132 Options options = Options.instance(context); |
131 lineDebugInfo = |
133 lineDebugInfo = |
132 options.isUnset(G_CUSTOM) || |
134 options.isUnset(G_CUSTOM) || |
2514 |
2516 |
2515 /* We must not analyze synthetic methods |
2517 /* We must not analyze synthetic methods |
2516 */ |
2518 */ |
2517 if (varDebugInfo && (cdef.sym.flags() & SYNTHETIC) == 0) { |
2519 if (varDebugInfo && (cdef.sym.flags() & SYNTHETIC) == 0) { |
2518 try { |
2520 try { |
2519 LVTAssignAnalyzer lvtAssignAnalyzer = LVTAssignAnalyzer.make( |
2521 new LVTAssignAnalyzer().analyzeTree(localEnv); |
2520 lvtRanges, syms, names); |
|
2521 lvtAssignAnalyzer.analyzeTree(localEnv); |
|
2522 } catch (Throwable e) { |
2522 } catch (Throwable e) { |
2523 throw e; |
2523 throw e; |
2524 } |
2524 } |
2525 } |
2525 } |
2526 |
2526 |
2607 void addCont(Chain c) { |
2607 void addCont(Chain c) { |
2608 cont = Code.mergeChains(c, cont); |
2608 cont = Code.mergeChains(c, cont); |
2609 } |
2609 } |
2610 } |
2610 } |
2611 |
2611 |
2612 static class LVTAssignAnalyzer |
2612 class LVTAssignAnalyzer |
2613 extends Flow.AbstractAssignAnalyzer<LVTAssignAnalyzer.LVTAssignPendingExit> { |
2613 extends Flow.AbstractAssignAnalyzer<LVTAssignAnalyzer.LVTAssignPendingExit> { |
2614 |
2614 |
2615 final LVTBits lvtInits; |
2615 final LVTBits lvtInits; |
2616 final LVTRanges lvtRanges; |
|
2617 |
2616 |
2618 /* This class is anchored to a context dependent tree. The tree can |
2617 /* This class is anchored to a context dependent tree. The tree can |
2619 * vary inside the same instruction for example in the switch instruction |
2618 * vary inside the same instruction for example in the switch instruction |
2620 * the same FlowBits instance can be anchored to the whole tree, or |
2619 * the same FlowBits instance can be anchored to the whole tree, or |
2621 * to a given case. The aim is to always anchor the bits to the tree |
2620 * to a given case. The aim is to always anchor the bits to the tree |
2622 * capable of closing a DA range. |
2621 * capable of closing a DA range. |
2623 */ |
2622 */ |
2624 static class LVTBits extends Bits { |
2623 class LVTBits extends Bits { |
2625 |
|
2626 enum BitsOpKind { |
|
2627 INIT, |
|
2628 CLEAR, |
|
2629 INCL_BIT, |
|
2630 EXCL_BIT, |
|
2631 ASSIGN, |
|
2632 AND_SET, |
|
2633 OR_SET, |
|
2634 DIFF_SET, |
|
2635 XOR_SET, |
|
2636 INCL_RANGE, |
|
2637 EXCL_RANGE, |
|
2638 } |
|
2639 |
2624 |
2640 JCTree currentTree; |
2625 JCTree currentTree; |
2641 LVTAssignAnalyzer analyzer; |
|
2642 private int[] oldBits = null; |
2626 private int[] oldBits = null; |
2643 BitsState stateBeforeOp; |
2627 BitsState stateBeforeOp; |
2644 |
|
2645 LVTBits() { |
|
2646 super(false); |
|
2647 } |
|
2648 |
|
2649 LVTBits(int[] bits, BitsState initState) { |
|
2650 super(bits, initState); |
|
2651 } |
|
2652 |
2628 |
2653 @Override |
2629 @Override |
2654 public void clear() { |
2630 public void clear() { |
2655 generalOp(null, -1, BitsOpKind.CLEAR); |
2631 generalOp(null, -1, BitsOpKind.CLEAR); |
2656 } |
2632 } |
2755 */ |
2731 */ |
2756 public void changed() { |
2732 public void changed() { |
2757 if (currentTree != null && |
2733 if (currentTree != null && |
2758 stateBeforeOp != BitsState.UNKNOWN && |
2734 stateBeforeOp != BitsState.UNKNOWN && |
2759 trackTree(currentTree)) { |
2735 trackTree(currentTree)) { |
2760 List<VarSymbol> locals = |
2736 List<VarSymbol> locals = lvtRanges |
2761 analyzer.lvtRanges |
2737 .getVars(currentMethod, currentTree); |
2762 .getVars(analyzer.currentMethod, currentTree); |
|
2763 locals = locals != null ? |
2738 locals = locals != null ? |
2764 locals : List.<VarSymbol>nil(); |
2739 locals : List.<VarSymbol>nil(); |
2765 for (JCVariableDecl vardecl : analyzer.vardecls) { |
2740 for (JCVariableDecl vardecl : vardecls) { |
2766 //once the first is null, the rest will be so. |
2741 //once the first is null, the rest will be so. |
2767 if (vardecl == null) { |
2742 if (vardecl == null) { |
2768 break; |
2743 break; |
2769 } |
2744 } |
2770 if (trackVar(vardecl.sym) && bitChanged(vardecl.sym.adr)) { |
2745 if (trackVar(vardecl.sym) && bitChanged(vardecl.sym.adr)) { |
2771 locals = locals.prepend(vardecl.sym); |
2746 locals = locals.prepend(vardecl.sym); |
2772 } |
2747 } |
2773 } |
2748 } |
2774 if (!locals.isEmpty()) { |
2749 if (!locals.isEmpty()) { |
2775 analyzer.lvtRanges.setEntry(analyzer.currentMethod, |
2750 lvtRanges.setEntry(currentMethod, |
2776 currentTree, locals); |
2751 currentTree, locals); |
2777 } |
2752 } |
2778 } |
2753 } |
2779 } |
2754 } |
2780 |
2755 |
2788 } |
2763 } |
2789 |
2764 |
2790 boolean trackVar(VarSymbol var) { |
2765 boolean trackVar(VarSymbol var) { |
2791 return (var.owner.kind == MTH && |
2766 return (var.owner.kind == MTH && |
2792 (var.flags() & PARAMETER) == 0 && |
2767 (var.flags() & PARAMETER) == 0 && |
2793 analyzer.trackable(var)); |
2768 trackable(var)); |
2794 } |
2769 } |
2795 |
2770 |
2796 boolean trackTree(JCTree tree) { |
2771 boolean trackTree(JCTree tree) { |
2797 switch (tree.getTag()) { |
2772 switch (tree.getTag()) { |
2798 // of course a method closes the alive range of a local variable. |
2773 // of course a method closes the alive range of a local variable. |
2804 return true; |
2779 return true; |
2805 } |
2780 } |
2806 |
2781 |
2807 } |
2782 } |
2808 |
2783 |
2809 public class LVTAssignPendingExit extends Flow.AssignAnalyzer.AssignPendingExit { |
2784 public class LVTAssignPendingExit extends |
|
2785 Flow.AbstractAssignAnalyzer<LVTAssignPendingExit>.AbstractAssignPendingExit { |
2810 |
2786 |
2811 LVTAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { |
2787 LVTAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { |
2812 super(tree, inits, uninits); |
2788 super(tree, inits, uninits); |
2813 } |
2789 } |
2814 |
2790 |
2817 lvtInits.at(tree); |
2793 lvtInits.at(tree); |
2818 super.resolveJump(tree); |
2794 super.resolveJump(tree); |
2819 } |
2795 } |
2820 } |
2796 } |
2821 |
2797 |
2822 private LVTAssignAnalyzer(LVTRanges lvtRanges, Symtab syms, Names names) { |
2798 private LVTAssignAnalyzer() { |
2823 super(new LVTBits(), syms, names, false); |
2799 flow.super(); |
2824 lvtInits = (LVTBits)inits; |
2800 lvtInits = new LVTBits(); |
2825 this.lvtRanges = lvtRanges; |
2801 inits = lvtInits; |
2826 } |
|
2827 |
|
2828 public static LVTAssignAnalyzer make(LVTRanges lvtRanges, Symtab syms, Names names) { |
|
2829 LVTAssignAnalyzer result = new LVTAssignAnalyzer(lvtRanges, syms, names); |
|
2830 result.lvtInits.analyzer = result; |
|
2831 return result; |
|
2832 } |
2802 } |
2833 |
2803 |
2834 @Override |
2804 @Override |
2835 protected void markDead(JCTree tree) { |
2805 protected void markDead(JCTree tree) { |
2836 lvtInits.at(tree).inclRange(returnadr, nextadr); |
2806 lvtInits.at(tree).inclRange(returnadr, nextadr); |