< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java

Print this page




  76  */
  77 public class Lower extends TreeTranslator {
  78     protected static final Context.Key<Lower> lowerKey = new Context.Key<>();
  79 
  80     public static Lower instance(Context context) {
  81         Lower instance = context.get(lowerKey);
  82         if (instance == null)
  83             instance = new Lower(context);
  84         return instance;
  85     }
  86 
  87     private final Names names;
  88     private final Log log;
  89     private final Symtab syms;
  90     private final Resolve rs;
  91     private final Operators operators;
  92     private final Check chk;
  93     private final Attr attr;
  94     private TreeMaker make;
  95     private DiagnosticPosition make_pos;

  96     private final ConstFold cfolder;
  97     private final Target target;
  98     private final Source source;
  99     private final TypeEnvs typeEnvs;
 100     private final Name dollarAssertionsDisabled;
 101     private final Name classDollar;
 102     private final Name dollarCloseResource;
 103     private final Types types;
 104     private final boolean debugLower;
 105     private final boolean disableProtectedAccessors; // experimental
 106     private final PkgInfo pkginfoOpt;
 107 
 108     protected Lower(Context context) {
 109         context.put(lowerKey, this);
 110         names = Names.instance(context);
 111         log = Log.instance(context);
 112         syms = Symtab.instance(context);
 113         rs = Resolve.instance(context);
 114         operators = Operators.instance(context);
 115         chk = Check.instance(context);
 116         attr = Attr.instance(context);
 117         make = TreeMaker.instance(context);

 118         cfolder = ConstFold.instance(context);
 119         target = Target.instance(context);
 120         source = Source.instance(context);
 121         typeEnvs = TypeEnvs.instance(context);
 122         dollarAssertionsDisabled = names.
 123             fromString(target.syntheticNameChar() + "assertionsDisabled");
 124         classDollar = names.
 125             fromString("class" + target.syntheticNameChar());
 126         dollarCloseResource = names.
 127             fromString(target.syntheticNameChar() + "closeResource");
 128 
 129         types = Types.instance(context);
 130         Options options = Options.instance(context);
 131         debugLower = options.isSet("debuglower");
 132         pkginfoOpt = PkgInfo.get(options);
 133         disableProtectedAccessors = options.isSet("disableProtectedAccessors");
 134     }
 135 
 136     /** The currently enclosing class.
 137      */


 456      *  <pre>
 457      *          class Outer$0 {
 458      *              synthetic final int[] $EnumMap$Color = new int[Color.values().length];
 459      *              static {
 460      *                  try { $EnumMap$Color[red.ordinal()] = 1; } catch (NoSuchFieldError ex) {}
 461      *                  try { $EnumMap$Color[green.ordinal()] = 2; } catch (NoSuchFieldError ex) {}
 462      *              }
 463      *          }
 464      *  </pre>
 465      *  class EnumMapping provides mapping data and support methods for this translation.
 466      */
 467     class EnumMapping {
 468         EnumMapping(DiagnosticPosition pos, TypeSymbol forEnum) {
 469             this.forEnum = forEnum;
 470             this.values = new LinkedHashMap<>();
 471             this.pos = pos;
 472             Name varName = names
 473                 .fromString(target.syntheticNameChar() +
 474                             "SwitchMap" +
 475                             target.syntheticNameChar() +
 476                             names.fromUtf(ClassWriter.externalize(forEnum.type.tsym.flatName())).toString()
 477                             .replace('/', '.')
 478                             .replace('.', target.syntheticNameChar()));
 479             ClassSymbol outerCacheClass = outerCacheClass();
 480             this.mapVar = new VarSymbol(STATIC | SYNTHETIC | FINAL,
 481                                         varName,
 482                                         new ArrayType(syms.intType, syms.arrayClass),
 483                                         outerCacheClass);
 484             enterSynthetic(pos, mapVar, outerCacheClass.members());
 485         }
 486 
 487         DiagnosticPosition pos = null;
 488 
 489         // the next value to use
 490         int next = 1; // 0 (unused map elements) go to the default label
 491 
 492         // the enum for which this is a map
 493         final TypeSymbol forEnum;
 494 
 495         // the field containing the map
 496         final VarSymbol mapVar;


2618     }
2619 
2620     // Simplify conditionals with known constant controlling expressions.
2621     // This allows us to avoid generating supporting declarations for
2622     // the dead code, which will not be eliminated during code generation.
2623     // Note that Flow.isFalse and Flow.isTrue only return true
2624     // for constant expressions in the sense of JLS 15.27, which
2625     // are guaranteed to have no side-effects.  More aggressive
2626     // constant propagation would require that we take care to
2627     // preserve possible side-effects in the condition expression.
2628 
2629     // One common case is equality expressions involving a constant and null.
2630     // Since null is not a constant expression (because null cannot be
2631     // represented in the constant pool), equality checks involving null are
2632     // not captured by Flow.isTrue/isFalse.
2633     // Equality checks involving a constant and null, e.g.
2634     //     "" == null
2635     // are safe to simplify as no side-effects can occur.
2636 
2637     private boolean isTrue(JCTree exp) {
2638         if (exp.type.isTrue())
2639             return true;
2640         Boolean b = expValue(exp);
2641         return b == null ? false : b;
2642     }
2643     private boolean isFalse(JCTree exp) {
2644         if (exp.type.isFalse())
2645             return true;
2646         Boolean b = expValue(exp);
2647         return b == null ? false : !b;
2648     }
2649     /* look for (in)equality relations involving null.
2650      * return true - if expression is always true
2651      *       false - if expression is always false
2652      *        null - if expression cannot be eliminated
2653      */
2654     private Boolean expValue(JCTree exp) {
2655         while (exp.hasTag(PARENS))
2656             exp = ((JCParens)exp).expr;
2657 
2658         boolean eq;
2659         switch (exp.getTag()) {
2660         case EQ: eq = true;  break;
2661         case NE: eq = false; break;
2662         default:
2663             return null;
2664         }


2713             addPrunedInfo(cond);
2714         } else if (isFalse(cond)) {
2715             if (tree.elsepart != null) {
2716                 result = translate(tree.elsepart);
2717             } else {
2718                 result = make.Skip();
2719             }
2720             addPrunedInfo(cond);
2721         } else {
2722             // Condition is not a compile-time constant.
2723             tree.thenpart = translate(tree.thenpart);
2724             tree.elsepart = translate(tree.elsepart);
2725             result = tree;
2726         }
2727     }
2728 
2729     /** Visitor method for assert statements. Translate them away.
2730      */
2731     public void visitAssert(JCAssert tree) {
2732         tree.cond = translate(tree.cond, syms.booleanType);
2733         if (!tree.cond.type.isTrue()) {
2734             JCExpression cond = assertFlagTest(tree.pos());
2735             List<JCExpression> exnArgs = (tree.detail == null) ?
2736                 List.nil() : List.of(translate(tree.detail));
2737             if (!tree.cond.type.isFalse()) {
2738                 cond = makeBinary
2739                     (AND,
2740                      cond,
2741                      makeUnary(NOT, tree.cond));
2742             }
2743             result =
2744                 make.If(cond,
2745                         make_at(tree).
2746                            Throw(makeNewClass(syms.assertionErrorType, exnArgs)),
2747                         null);
2748         } else {
2749             result = make.Skip();
2750         }
2751     }
2752 
2753     public void visitApply(JCMethodInvocation tree) {
2754         Symbol meth = TreeInfo.symbol(tree.meth);
2755         List<Type> argtypes = meth.type.getParameterTypes();
2756         if (meth.name == names.init && meth.owner == syms.enumSym)
2757             argtypes = argtypes.tail.tail;


3081                         ? PLUS_ASG : MINUS_ASG;
3082                     JCAssignOp newTree = makeAssignop(opcode,
3083                                                     tree.arg,
3084                                                     make.Literal(1));
3085                     result = translate(newTree, tree.type);
3086                     return;
3087                 }
3088             case POSTINC:           // e ++
3089             case POSTDEC:           // e --
3090                 {
3091                     result = translate(lowerBoxedPostop(tree), tree.type);
3092                     return;
3093                 }
3094             }
3095             throw new AssertionError(tree);
3096         }
3097 
3098         tree.arg = boxIfNeeded(translate(tree.arg, tree), tree.type);
3099 
3100         if (tree.hasTag(NOT) && tree.arg.type.constValue() != null) {
3101             tree.type = cfolder.fold1(bool_not, tree.arg.type);
3102         }
3103 
3104         // If translated left hand side is an Apply, we are
3105         // seeing an access method invocation. In this case, return
3106         // that access method invocation as result.
3107         if (isUpdateOperator && tree.arg.hasTag(APPLY)) {
3108             result = tree.arg;
3109         } else {
3110             result = tree;
3111         }
3112     }
3113 
3114     public void visitBinary(JCBinary tree) {
3115         List<Type> formals = tree.operator.type.getParameterTypes();
3116         JCTree lhs = tree.lhs = translate(tree.lhs, formals.head);
3117         switch (tree.getTag()) {
3118         case OR:
3119             if (isTrue(lhs)) {
3120                 result = lhs;
3121                 return;




  76  */
  77 public class Lower extends TreeTranslator {
  78     protected static final Context.Key<Lower> lowerKey = new Context.Key<>();
  79 
  80     public static Lower instance(Context context) {
  81         Lower instance = context.get(lowerKey);
  82         if (instance == null)
  83             instance = new Lower(context);
  84         return instance;
  85     }
  86 
  87     private final Names names;
  88     private final Log log;
  89     private final Symtab syms;
  90     private final Resolve rs;
  91     private final Operators operators;
  92     private final Check chk;
  93     private final Attr attr;
  94     private TreeMaker make;
  95     private DiagnosticPosition make_pos;
  96     private final ClassWriter writer;
  97     private final ConstFold cfolder;
  98     private final Target target;
  99     private final Source source;
 100     private final TypeEnvs typeEnvs;
 101     private final Name dollarAssertionsDisabled;
 102     private final Name classDollar;
 103     private final Name dollarCloseResource;
 104     private final Types types;
 105     private final boolean debugLower;
 106     private final boolean disableProtectedAccessors; // experimental
 107     private final PkgInfo pkginfoOpt;
 108 
 109     protected Lower(Context context) {
 110         context.put(lowerKey, this);
 111         names = Names.instance(context);
 112         log = Log.instance(context);
 113         syms = Symtab.instance(context);
 114         rs = Resolve.instance(context);
 115         operators = Operators.instance(context);
 116         chk = Check.instance(context);
 117         attr = Attr.instance(context);
 118         make = TreeMaker.instance(context);
 119         writer = ClassWriter.instance(context);
 120         cfolder = ConstFold.instance(context);
 121         target = Target.instance(context);
 122         source = Source.instance(context);
 123         typeEnvs = TypeEnvs.instance(context);
 124         dollarAssertionsDisabled = names.
 125             fromString(target.syntheticNameChar() + "assertionsDisabled");
 126         classDollar = names.
 127             fromString("class" + target.syntheticNameChar());
 128         dollarCloseResource = names.
 129             fromString(target.syntheticNameChar() + "closeResource");
 130 
 131         types = Types.instance(context);
 132         Options options = Options.instance(context);
 133         debugLower = options.isSet("debuglower");
 134         pkginfoOpt = PkgInfo.get(options);
 135         disableProtectedAccessors = options.isSet("disableProtectedAccessors");
 136     }
 137 
 138     /** The currently enclosing class.
 139      */


 458      *  <pre>
 459      *          class Outer$0 {
 460      *              synthetic final int[] $EnumMap$Color = new int[Color.values().length];
 461      *              static {
 462      *                  try { $EnumMap$Color[red.ordinal()] = 1; } catch (NoSuchFieldError ex) {}
 463      *                  try { $EnumMap$Color[green.ordinal()] = 2; } catch (NoSuchFieldError ex) {}
 464      *              }
 465      *          }
 466      *  </pre>
 467      *  class EnumMapping provides mapping data and support methods for this translation.
 468      */
 469     class EnumMapping {
 470         EnumMapping(DiagnosticPosition pos, TypeSymbol forEnum) {
 471             this.forEnum = forEnum;
 472             this.values = new LinkedHashMap<>();
 473             this.pos = pos;
 474             Name varName = names
 475                 .fromString(target.syntheticNameChar() +
 476                             "SwitchMap" +
 477                             target.syntheticNameChar() +
 478                             writer.xClassName(forEnum.type).toString()
 479                             .replace('/', '.')
 480                             .replace('.', target.syntheticNameChar()));
 481             ClassSymbol outerCacheClass = outerCacheClass();
 482             this.mapVar = new VarSymbol(STATIC | SYNTHETIC | FINAL,
 483                                         varName,
 484                                         new ArrayType(syms.intType, syms.arrayClass),
 485                                         outerCacheClass);
 486             enterSynthetic(pos, mapVar, outerCacheClass.members());
 487         }
 488 
 489         DiagnosticPosition pos = null;
 490 
 491         // the next value to use
 492         int next = 1; // 0 (unused map elements) go to the default label
 493 
 494         // the enum for which this is a map
 495         final TypeSymbol forEnum;
 496 
 497         // the field containing the map
 498         final VarSymbol mapVar;


2620     }
2621 
2622     // Simplify conditionals with known constant controlling expressions.
2623     // This allows us to avoid generating supporting declarations for
2624     // the dead code, which will not be eliminated during code generation.
2625     // Note that Flow.isFalse and Flow.isTrue only return true
2626     // for constant expressions in the sense of JLS 15.27, which
2627     // are guaranteed to have no side-effects.  More aggressive
2628     // constant propagation would require that we take care to
2629     // preserve possible side-effects in the condition expression.
2630 
2631     // One common case is equality expressions involving a constant and null.
2632     // Since null is not a constant expression (because null cannot be
2633     // represented in the constant pool), equality checks involving null are
2634     // not captured by Flow.isTrue/isFalse.
2635     // Equality checks involving a constant and null, e.g.
2636     //     "" == null
2637     // are safe to simplify as no side-effects can occur.
2638 
2639     private boolean isTrue(JCTree exp) {
2640         if (ConstFold.isTrue(exp.type.getTag(), exp.type.constValue()))
2641             return true;
2642         Boolean b = expValue(exp);
2643         return b == null ? false : b;
2644     }
2645     private boolean isFalse(JCTree exp) {
2646         if (ConstFold.isFalse(exp.type.getTag(), exp.type.constValue()))
2647             return true;
2648         Boolean b = expValue(exp);
2649         return b == null ? false : !b;
2650     }
2651     /* look for (in)equality relations involving null.
2652      * return true - if expression is always true
2653      *       false - if expression is always false
2654      *        null - if expression cannot be eliminated
2655      */
2656     private Boolean expValue(JCTree exp) {
2657         while (exp.hasTag(PARENS))
2658             exp = ((JCParens)exp).expr;
2659 
2660         boolean eq;
2661         switch (exp.getTag()) {
2662         case EQ: eq = true;  break;
2663         case NE: eq = false; break;
2664         default:
2665             return null;
2666         }


2715             addPrunedInfo(cond);
2716         } else if (isFalse(cond)) {
2717             if (tree.elsepart != null) {
2718                 result = translate(tree.elsepart);
2719             } else {
2720                 result = make.Skip();
2721             }
2722             addPrunedInfo(cond);
2723         } else {
2724             // Condition is not a compile-time constant.
2725             tree.thenpart = translate(tree.thenpart);
2726             tree.elsepart = translate(tree.elsepart);
2727             result = tree;
2728         }
2729     }
2730 
2731     /** Visitor method for assert statements. Translate them away.
2732      */
2733     public void visitAssert(JCAssert tree) {
2734         tree.cond = translate(tree.cond, syms.booleanType);
2735         if (!ConstFold.isTrue(tree.cond.type.getTag(), tree.cond.type.constValue())) {
2736             JCExpression cond = assertFlagTest(tree.pos());
2737             List<JCExpression> exnArgs = (tree.detail == null) ?
2738                 List.nil() : List.of(translate(tree.detail));
2739             if (!ConstFold.isFalse(tree.cond.type.getTag(), tree.cond.type.constValue())) {
2740                 cond = makeBinary
2741                     (AND,
2742                      cond,
2743                      makeUnary(NOT, tree.cond));
2744             }
2745             result =
2746                 make.If(cond,
2747                         make_at(tree).
2748                            Throw(makeNewClass(syms.assertionErrorType, exnArgs)),
2749                         null);
2750         } else {
2751             result = make.Skip();
2752         }
2753     }
2754 
2755     public void visitApply(JCMethodInvocation tree) {
2756         Symbol meth = TreeInfo.symbol(tree.meth);
2757         List<Type> argtypes = meth.type.getParameterTypes();
2758         if (meth.name == names.init && meth.owner == syms.enumSym)
2759             argtypes = argtypes.tail.tail;


3083                         ? PLUS_ASG : MINUS_ASG;
3084                     JCAssignOp newTree = makeAssignop(opcode,
3085                                                     tree.arg,
3086                                                     make.Literal(1));
3087                     result = translate(newTree, tree.type);
3088                     return;
3089                 }
3090             case POSTINC:           // e ++
3091             case POSTDEC:           // e --
3092                 {
3093                     result = translate(lowerBoxedPostop(tree), tree.type);
3094                     return;
3095                 }
3096             }
3097             throw new AssertionError(tree);
3098         }
3099 
3100         tree.arg = boxIfNeeded(translate(tree.arg, tree), tree.type);
3101 
3102         if (tree.hasTag(NOT) && tree.arg.type.constValue() != null) {
3103             tree.type = cfolder.fold1(tree.operator, tree.arg.type);
3104         }
3105 
3106         // If translated left hand side is an Apply, we are
3107         // seeing an access method invocation. In this case, return
3108         // that access method invocation as result.
3109         if (isUpdateOperator && tree.arg.hasTag(APPLY)) {
3110             result = tree.arg;
3111         } else {
3112             result = tree;
3113         }
3114     }
3115 
3116     public void visitBinary(JCBinary tree) {
3117         List<Type> formals = tree.operator.type.getParameterTypes();
3118         JCTree lhs = tree.lhs = translate(tree.lhs, formals.head);
3119         switch (tree.getTag()) {
3120         case OR:
3121             if (isTrue(lhs)) {
3122                 result = lhs;
3123                 return;


< prev index next >