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

Print this page




 340      *  switches.
 341      *
 342      *  <p>For each enum that appears as the type of a switch
 343      *  expression, we maintain an EnumMapping to assist in the
 344      *  translation, as exemplified by the following example:
 345      *
 346      *  <p>we translate
 347      *  <pre>
 348      *          switch(colorExpression) {
 349      *          case red: stmt1;
 350      *          case green: stmt2;
 351      *          }
 352      *  </pre>
 353      *  into
 354      *  <pre>
 355      *          switch(Outer$0.$EnumMap$Color[colorExpression.ordinal()]) {
 356      *          case 1: stmt1;
 357      *          case 2: stmt2
 358      *          }
 359      *  </pre>
 360      *  with the auxilliary table intialized as follows:
 361      *  <pre>
 362      *          class Outer$0 {
 363      *              synthetic final int[] $EnumMap$Color = new int[Color.values().length];
 364      *              static {
 365      *                  try { $EnumMap$Color[red.ordinal()] = 1; } catch (NoSuchFieldError ex) {}
 366      *                  try { $EnumMap$Color[green.ordinal()] = 2; } catch (NoSuchFieldError ex) {}
 367      *              }
 368      *          }
 369      *  </pre>
 370      *  class EnumMapping provides mapping data and support methods for this translation.
 371      */
 372     class EnumMapping {
 373         EnumMapping(DiagnosticPosition pos, TypeSymbol forEnum) {
 374             this.forEnum = forEnum;
 375             this.values = new LinkedHashMap<VarSymbol,Integer>();
 376             this.pos = pos;
 377             Name varName = names
 378                 .fromString(target.syntheticNameChar() +
 379                             "SwitchMap" +
 380                             target.syntheticNameChar() +


 841 
 842         Symbol vsym = sym;
 843         if (sym.owner != accOwner) {
 844             vsym = sym.clone(accOwner);
 845             actualSymbols.put(vsym, sym);
 846         }
 847 
 848         Integer anum              // The access number of the access method.
 849             = accessNums.get(vsym);
 850         if (anum == null) {
 851             anum = accessed.length();
 852             accessNums.put(vsym, anum);
 853             accessSyms.put(vsym, new MethodSymbol[NCODES]);
 854             accessed.append(vsym);
 855             // System.out.println("accessing " + vsym + " in " + vsym.location());
 856         }
 857 
 858         int acode;                // The access code of the access method.
 859         List<Type> argtypes;      // The argument types of the access method.
 860         Type restype;             // The result type of the access method.
 861         List<Type> thrown;        // The thrown execeptions of the access method.
 862         switch (vsym.kind) {
 863         case VAR:
 864             acode = accessCode(tree, enclOp);
 865             if (acode >= FIRSTASGOPcode) {
 866                 OperatorSymbol operator = binaryAccessOperator(acode);
 867                 if (operator.opcode == string_add)
 868                     argtypes = List.of(syms.objectType);
 869                 else
 870                     argtypes = operator.type.getParameterTypes().tail;
 871             } else if (acode == ASSIGNcode)
 872                 argtypes = List.of(vsym.erasure(types));
 873             else
 874                 argtypes = List.nil();
 875             restype = vsym.erasure(types);
 876             thrown = List.nil();
 877             break;
 878         case MTH:
 879             acode = DEREFcode;
 880             argtypes = vsym.erasure(types).getParameterTypes();
 881             restype = vsym.erasure(types).getReturnType();


2446         }
2447         tree.encl = null;
2448 
2449         // If we have an anonymous class, create its flat version, rather
2450         // than the class or interface following new.
2451         if (tree.def != null) {
2452             translate(tree.def);
2453             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
2454             tree.def = null;
2455         } else {
2456             tree.clazz = access(c, tree.clazz, enclOp, false);
2457         }
2458         result = tree;
2459     }
2460 
2461     // Simplify conditionals with known constant controlling expressions.
2462     // This allows us to avoid generating supporting declarations for
2463     // the dead code, which will not be eliminated during code generation.
2464     // Note that Flow.isFalse and Flow.isTrue only return true
2465     // for constant expressions in the sense of JLS 15.27, which
2466     // are guaranteed to have no side-effects.  More agressive
2467     // constant propagation would require that we take care to
2468     // preserve possible side-effects in the condition expression.
2469 
2470     /** Visitor method for conditional expressions.
2471      */
2472     public void visitConditional(JCConditional tree) {
2473         JCTree cond = tree.cond = translate(tree.cond, syms.booleanType);
2474         if (cond.type.isTrue()) {
2475             result = convert(translate(tree.truepart, tree.type), tree.type);
2476         } else if (cond.type.isFalse()) {
2477             result = convert(translate(tree.falsepart, tree.type), tree.type);
2478         } else {
2479             // Condition is not a compile-time constant.
2480             tree.truepart = translate(tree.truepart, tree.type);
2481             tree.falsepart = translate(tree.falsepart, tree.type);
2482             result = tree;
2483         }
2484     }
2485 //where
2486         private JCTree convert(JCTree tree, Type pt) {


2833                     return;
2834                 }
2835             case JCTree.POSTINC:           // e ++
2836             case JCTree.POSTDEC:           // e --
2837                 {
2838                     result = translate(lowerBoxedPostop(tree), tree.type);
2839                     return;
2840                 }
2841             }
2842             throw new AssertionError(tree);
2843         }
2844 
2845         tree.arg = boxIfNeeded(translate(tree.arg, tree), tree.type);
2846 
2847         if (tree.getTag() == JCTree.NOT && tree.arg.type.constValue() != null) {
2848             tree.type = cfolder.fold1(bool_not, tree.arg.type);
2849         }
2850 
2851         // If translated left hand side is an Apply, we are
2852         // seeing an access method invocation. In this case, return
2853         // that access method invokation as result.
2854         if (isUpdateOperator && tree.arg.getTag() == JCTree.APPLY) {
2855             result = tree.arg;
2856         } else {
2857             result = tree;
2858         }
2859     }
2860 
2861     public void visitBinary(JCBinary tree) {
2862         List<Type> formals = tree.operator.type.getParameterTypes();
2863         JCTree lhs = tree.lhs = translate(tree.lhs, formals.head);
2864         switch (tree.getTag()) {
2865         case JCTree.OR:
2866             if (lhs.type.isTrue()) {
2867                 result = lhs;
2868                 return;
2869             }
2870             if (lhs.type.isFalse()) {
2871                 result = translate(tree.rhs, formals.tail.head);
2872                 return;
2873             }


2883             }
2884             break;
2885         }
2886         tree.rhs = translate(tree.rhs, formals.tail.head);
2887         result = tree;
2888     }
2889 
2890     public void visitIdent(JCIdent tree) {
2891         result = access(tree.sym, tree, enclOp, false);
2892     }
2893 
2894     /** Translate away the foreach loop.  */
2895     public void visitForeachLoop(JCEnhancedForLoop tree) {
2896         if (types.elemtype(tree.expr.type) == null)
2897             visitIterableForeachLoop(tree);
2898         else
2899             visitArrayForeachLoop(tree);
2900     }
2901         // where
2902         /**
2903          * A statment of the form
2904          *
2905          * <pre>
2906          *     for ( T v : arrayexpr ) stmt;
2907          * </pre>
2908          *
2909          * (where arrayexpr is of an array type) gets translated to
2910          *
2911          * <pre>
2912          *     for ( { arraytype #arr = arrayexpr;
2913          *             int #len = array.length;
2914          *             int #i = 0; };
2915          *           #i < #len; i$++ ) {
2916          *         T v = arr$[#i];
2917          *         stmt;
2918          *     }
2919          * </pre>
2920          *
2921          * where #arr, #len, and #i are freshly named synthetic local variables.
2922          */
2923         private void visitArrayForeachLoop(JCEnhancedForLoop tree) {


3092         tree.init = translate(tree.init);
3093         if (tree.cond != null)
3094             tree.cond = translate(tree.cond, syms.booleanType);
3095         tree.step = translate(tree.step);
3096         tree.body = translate(tree.body);
3097         result = tree;
3098     }
3099 
3100     public void visitReturn(JCReturn tree) {
3101         if (tree.expr != null)
3102             tree.expr = translate(tree.expr,
3103                                   types.erasure(currentMethodDef
3104                                                 .restype.type));
3105         result = tree;
3106     }
3107 
3108     public void visitSwitch(JCSwitch tree) {
3109         Type selsuper = types.supertype(tree.selector.type);
3110         boolean enumSwitch = selsuper != null &&
3111             (tree.selector.type.tsym.flags() & ENUM) != 0;
3112         Type target = enumSwitch ? tree.selector.type : syms.intType;



3113         tree.selector = translate(tree.selector, target);
3114         tree.cases = translateCases(tree.cases);
3115         if (enumSwitch) {
3116             result = visitEnumSwitch(tree);
3117             patchTargets(result, tree, result);


3118         } else {
3119             result = tree;
3120         }
3121     }
3122 
3123     public JCTree visitEnumSwitch(JCSwitch tree) {
3124         TypeSymbol enumSym = tree.selector.type.tsym;
3125         EnumMapping map = mapForEnum(tree.pos(), enumSym);
3126         make_at(tree.pos());
3127         Symbol ordinalMethod = lookupMethod(tree.pos(),
3128                                             names.ordinal,
3129                                             tree.selector.type,
3130                                             List.<Type>nil());
3131         JCArrayAccess selector = make.Indexed(map.mapVar,
3132                                         make.App(make.Select(tree.selector,
3133                                                              ordinalMethod)));
3134         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
3135         for (JCCase c : tree.cases) {
3136             if (c.pat != null) {
3137                 VarSymbol label = (VarSymbol)TreeInfo.symbol(c.pat);
3138                 JCLiteral pat = map.forConstant(label);
3139                 cases.append(make.Case(pat, c.stats));
3140             } else {
3141                 cases.append(c);
3142             }
3143         }
3144         return make.Switch(selector, cases.toList());
3145     }
3146 


















































































































































































3147     public void visitNewArray(JCNewArray tree) {
3148         tree.elemtype = translate(tree.elemtype);
3149         for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
3150             if (t.head != null) t.head = translate(t.head, syms.intType);
3151         tree.elems = translate(tree.elems, types.elemtype(tree.type));
3152         result = tree;
3153     }
3154 
3155     public void visitSelect(JCFieldAccess tree) {
3156         // need to special case-access of the form C.super.x
3157         // these will always need an access method.
3158         boolean qualifiedSuperAccess =
3159             tree.selected.getTag() == JCTree.SELECT &&
3160             TreeInfo.name(tree.selected) == names._super;
3161         tree.selected = translate(tree.selected);
3162         if (tree.name == names._class)
3163             result = classOf(tree.selected);
3164         else if (tree.name == names._this || tree.name == names._super)
3165             result = makeThis(tree.pos(), tree.selected.type.tsym);
3166         else




 340      *  switches.
 341      *
 342      *  <p>For each enum that appears as the type of a switch
 343      *  expression, we maintain an EnumMapping to assist in the
 344      *  translation, as exemplified by the following example:
 345      *
 346      *  <p>we translate
 347      *  <pre>
 348      *          switch(colorExpression) {
 349      *          case red: stmt1;
 350      *          case green: stmt2;
 351      *          }
 352      *  </pre>
 353      *  into
 354      *  <pre>
 355      *          switch(Outer$0.$EnumMap$Color[colorExpression.ordinal()]) {
 356      *          case 1: stmt1;
 357      *          case 2: stmt2
 358      *          }
 359      *  </pre>
 360      *  with the auxiliary table initialized as follows:
 361      *  <pre>
 362      *          class Outer$0 {
 363      *              synthetic final int[] $EnumMap$Color = new int[Color.values().length];
 364      *              static {
 365      *                  try { $EnumMap$Color[red.ordinal()] = 1; } catch (NoSuchFieldError ex) {}
 366      *                  try { $EnumMap$Color[green.ordinal()] = 2; } catch (NoSuchFieldError ex) {}
 367      *              }
 368      *          }
 369      *  </pre>
 370      *  class EnumMapping provides mapping data and support methods for this translation.
 371      */
 372     class EnumMapping {
 373         EnumMapping(DiagnosticPosition pos, TypeSymbol forEnum) {
 374             this.forEnum = forEnum;
 375             this.values = new LinkedHashMap<VarSymbol,Integer>();
 376             this.pos = pos;
 377             Name varName = names
 378                 .fromString(target.syntheticNameChar() +
 379                             "SwitchMap" +
 380                             target.syntheticNameChar() +


 841 
 842         Symbol vsym = sym;
 843         if (sym.owner != accOwner) {
 844             vsym = sym.clone(accOwner);
 845             actualSymbols.put(vsym, sym);
 846         }
 847 
 848         Integer anum              // The access number of the access method.
 849             = accessNums.get(vsym);
 850         if (anum == null) {
 851             anum = accessed.length();
 852             accessNums.put(vsym, anum);
 853             accessSyms.put(vsym, new MethodSymbol[NCODES]);
 854             accessed.append(vsym);
 855             // System.out.println("accessing " + vsym + " in " + vsym.location());
 856         }
 857 
 858         int acode;                // The access code of the access method.
 859         List<Type> argtypes;      // The argument types of the access method.
 860         Type restype;             // The result type of the access method.
 861         List<Type> thrown;        // The thrown exceptions of the access method.
 862         switch (vsym.kind) {
 863         case VAR:
 864             acode = accessCode(tree, enclOp);
 865             if (acode >= FIRSTASGOPcode) {
 866                 OperatorSymbol operator = binaryAccessOperator(acode);
 867                 if (operator.opcode == string_add)
 868                     argtypes = List.of(syms.objectType);
 869                 else
 870                     argtypes = operator.type.getParameterTypes().tail;
 871             } else if (acode == ASSIGNcode)
 872                 argtypes = List.of(vsym.erasure(types));
 873             else
 874                 argtypes = List.nil();
 875             restype = vsym.erasure(types);
 876             thrown = List.nil();
 877             break;
 878         case MTH:
 879             acode = DEREFcode;
 880             argtypes = vsym.erasure(types).getParameterTypes();
 881             restype = vsym.erasure(types).getReturnType();


2446         }
2447         tree.encl = null;
2448 
2449         // If we have an anonymous class, create its flat version, rather
2450         // than the class or interface following new.
2451         if (tree.def != null) {
2452             translate(tree.def);
2453             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
2454             tree.def = null;
2455         } else {
2456             tree.clazz = access(c, tree.clazz, enclOp, false);
2457         }
2458         result = tree;
2459     }
2460 
2461     // Simplify conditionals with known constant controlling expressions.
2462     // This allows us to avoid generating supporting declarations for
2463     // the dead code, which will not be eliminated during code generation.
2464     // Note that Flow.isFalse and Flow.isTrue only return true
2465     // for constant expressions in the sense of JLS 15.27, which
2466     // are guaranteed to have no side-effects.  More aggressive
2467     // constant propagation would require that we take care to
2468     // preserve possible side-effects in the condition expression.
2469 
2470     /** Visitor method for conditional expressions.
2471      */
2472     public void visitConditional(JCConditional tree) {
2473         JCTree cond = tree.cond = translate(tree.cond, syms.booleanType);
2474         if (cond.type.isTrue()) {
2475             result = convert(translate(tree.truepart, tree.type), tree.type);
2476         } else if (cond.type.isFalse()) {
2477             result = convert(translate(tree.falsepart, tree.type), tree.type);
2478         } else {
2479             // Condition is not a compile-time constant.
2480             tree.truepart = translate(tree.truepart, tree.type);
2481             tree.falsepart = translate(tree.falsepart, tree.type);
2482             result = tree;
2483         }
2484     }
2485 //where
2486         private JCTree convert(JCTree tree, Type pt) {


2833                     return;
2834                 }
2835             case JCTree.POSTINC:           // e ++
2836             case JCTree.POSTDEC:           // e --
2837                 {
2838                     result = translate(lowerBoxedPostop(tree), tree.type);
2839                     return;
2840                 }
2841             }
2842             throw new AssertionError(tree);
2843         }
2844 
2845         tree.arg = boxIfNeeded(translate(tree.arg, tree), tree.type);
2846 
2847         if (tree.getTag() == JCTree.NOT && tree.arg.type.constValue() != null) {
2848             tree.type = cfolder.fold1(bool_not, tree.arg.type);
2849         }
2850 
2851         // If translated left hand side is an Apply, we are
2852         // seeing an access method invocation. In this case, return
2853         // that access method invocation as result.
2854         if (isUpdateOperator && tree.arg.getTag() == JCTree.APPLY) {
2855             result = tree.arg;
2856         } else {
2857             result = tree;
2858         }
2859     }
2860 
2861     public void visitBinary(JCBinary tree) {
2862         List<Type> formals = tree.operator.type.getParameterTypes();
2863         JCTree lhs = tree.lhs = translate(tree.lhs, formals.head);
2864         switch (tree.getTag()) {
2865         case JCTree.OR:
2866             if (lhs.type.isTrue()) {
2867                 result = lhs;
2868                 return;
2869             }
2870             if (lhs.type.isFalse()) {
2871                 result = translate(tree.rhs, formals.tail.head);
2872                 return;
2873             }


2883             }
2884             break;
2885         }
2886         tree.rhs = translate(tree.rhs, formals.tail.head);
2887         result = tree;
2888     }
2889 
2890     public void visitIdent(JCIdent tree) {
2891         result = access(tree.sym, tree, enclOp, false);
2892     }
2893 
2894     /** Translate away the foreach loop.  */
2895     public void visitForeachLoop(JCEnhancedForLoop tree) {
2896         if (types.elemtype(tree.expr.type) == null)
2897             visitIterableForeachLoop(tree);
2898         else
2899             visitArrayForeachLoop(tree);
2900     }
2901         // where
2902         /**
2903          * A statement of the form
2904          *
2905          * <pre>
2906          *     for ( T v : arrayexpr ) stmt;
2907          * </pre>
2908          *
2909          * (where arrayexpr is of an array type) gets translated to
2910          *
2911          * <pre>
2912          *     for ( { arraytype #arr = arrayexpr;
2913          *             int #len = array.length;
2914          *             int #i = 0; };
2915          *           #i < #len; i$++ ) {
2916          *         T v = arr$[#i];
2917          *         stmt;
2918          *     }
2919          * </pre>
2920          *
2921          * where #arr, #len, and #i are freshly named synthetic local variables.
2922          */
2923         private void visitArrayForeachLoop(JCEnhancedForLoop tree) {


3092         tree.init = translate(tree.init);
3093         if (tree.cond != null)
3094             tree.cond = translate(tree.cond, syms.booleanType);
3095         tree.step = translate(tree.step);
3096         tree.body = translate(tree.body);
3097         result = tree;
3098     }
3099 
3100     public void visitReturn(JCReturn tree) {
3101         if (tree.expr != null)
3102             tree.expr = translate(tree.expr,
3103                                   types.erasure(currentMethodDef
3104                                                 .restype.type));
3105         result = tree;
3106     }
3107 
3108     public void visitSwitch(JCSwitch tree) {
3109         Type selsuper = types.supertype(tree.selector.type);
3110         boolean enumSwitch = selsuper != null &&
3111             (tree.selector.type.tsym.flags() & ENUM) != 0;
3112         boolean stringSwitch = selsuper != null &&
3113             types.isSameType(tree.selector.type, syms.stringType);
3114         Type target = enumSwitch ? tree.selector.type :
3115             (stringSwitch? syms.stringType : syms.intType);
3116         tree.selector = translate(tree.selector, target);
3117         tree.cases = translateCases(tree.cases);
3118         if (enumSwitch) {
3119             result = visitEnumSwitch(tree);
3120             patchTargets(result, tree, result);
3121         } else if (stringSwitch) {
3122             result = visitStringSwitch(tree);
3123         } else {
3124             result = tree;
3125         }
3126     }
3127 
3128     public JCTree visitEnumSwitch(JCSwitch tree) {
3129         TypeSymbol enumSym = tree.selector.type.tsym;
3130         EnumMapping map = mapForEnum(tree.pos(), enumSym);
3131         make_at(tree.pos());
3132         Symbol ordinalMethod = lookupMethod(tree.pos(),
3133                                             names.ordinal,
3134                                             tree.selector.type,
3135                                             List.<Type>nil());
3136         JCArrayAccess selector = make.Indexed(map.mapVar,
3137                                         make.App(make.Select(tree.selector,
3138                                                              ordinalMethod)));
3139         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
3140         for (JCCase c : tree.cases) {
3141             if (c.pat != null) {
3142                 VarSymbol label = (VarSymbol)TreeInfo.symbol(c.pat);
3143                 JCLiteral pat = map.forConstant(label);
3144                 cases.append(make.Case(pat, c.stats));
3145             } else {
3146                 cases.append(c);
3147             }
3148         }
3149         return make.Switch(selector, cases.toList());
3150     }
3151 
3152     public JCTree visitStringSwitch(JCSwitch tree) {
3153         List<JCCase> caseList = tree.getCases();
3154         int alternatives = caseList.size();
3155 
3156         if (alternatives == 0) { // Strange but legal possibility
3157             return make.at(tree.pos()).Exec(attr.makeNullCheck(tree.getExpression()));
3158         } else {
3159             /*
3160              * The general approach used is to translate a single
3161              * string switch statement into a series of two chained
3162              * switch statements: the first a synthesized statement
3163              * switching on the argument string's hash value and
3164              * computing a string's position in the list of original
3165              * case labels, if any, followed by a second switch on the
3166              * computed integer value.  The second switch has the same
3167              * code structure as the original string switch statement
3168              * except that the string case labels are replaced with
3169              * positional integer constants starting at 0.
3170              *
3171              * The first switch statement can be thought of as an
3172              * inlined map from strings to their position in the case
3173              * label list.  An alternate implementation would use an
3174              * actual Map for this purpose, as done for enum switches.
3175              *
3176              * With some additional effort, it would be possible to
3177              * use a single switch statement on the hash code of the
3178              * argument, but care would need to be taken to preserve
3179              * the proper control flow in the presence of hash
3180              * collisions and other complications, such as
3181              * fallthroughs.  Switch statements with one or two
3182              * alternatives could also be specially translated into
3183              * if-then statements to omit the computation of the hash
3184              * code.
3185              *
3186              * The generated code assumes that the hashing algorithm
3187              * of String is the same in the compilation environment as
3188              * in the environment the code will run in.  The string
3189              * hashing algorithm in the SE JDK has been unchanged
3190              * since at least JDK 1.2.
3191              */
3192 
3193             ListBuffer<JCStatement> stmtList = new ListBuffer<JCStatement>();
3194 
3195             // Map from String case labels to their original position in
3196             // the list of case labels.
3197             Map<String, Integer> caseLabelToPosition =
3198                 new LinkedHashMap<String, Integer>(alternatives + 1, 1.0f);
3199 
3200             // Map of hash codes to the string case labels having that hashCode.
3201             Map<Integer, Set<String>> hashToString =
3202                 new LinkedHashMap<Integer, Set<String>>(alternatives + 1, 1.0f);
3203 
3204             int casePosition = 0;
3205             for(JCCase oneCase : caseList) {
3206                 JCExpression expression = oneCase.getExpression();
3207 
3208                 if (expression != null) { // expression for a "default" case is null
3209                     String labelExpr = (String) expression.type.constValue();
3210                     Integer mapping = caseLabelToPosition.put(labelExpr, casePosition);
3211                     assert mapping == null;
3212                     int hashCode = labelExpr.hashCode();
3213 
3214                     Set<String> stringSet = hashToString.get(hashCode);
3215                     if (stringSet == null) {
3216                         stringSet = new LinkedHashSet<String>(1, 1.0f);
3217                         stringSet.add(labelExpr);
3218                         hashToString.put(hashCode, stringSet);
3219                     } else {
3220                         boolean added = stringSet.add(labelExpr);
3221                         assert added;
3222                     }
3223                 }
3224                 casePosition++;
3225             }
3226 
3227             // Synthesize a switch statement that has the effect of
3228             // mapping from a string to the integer position of that
3229             // string in the list of case labels.  This is done by
3230             // switching on the hashCode of the string followed by an
3231             // if-then-else chain comparing the input for equality
3232             // with all the case labels having that hash value.
3233 
3234             /*
3235              * s$ = top of stack;
3236              * tmp$ = -1;
3237              * switch($s.hashCode()) {
3238              *     case caseLabel.hashCode:
3239              *         if (s$.equals("caseLabel_1")
3240              *           tmp$ = caseLabelToPosition("caseLabel_1");
3241              *         else if (s$.equals("caseLabel_2"))
3242              *           tmp$ = caseLabelToPosition("caseLabel_2");
3243              *         ...
3244              *         break;
3245              * ...
3246              * }
3247              */
3248 
3249             VarSymbol dollar_s = new VarSymbol(FINAL|SYNTHETIC,
3250                                                names.fromString("s" + tree.pos + target.syntheticNameChar()),
3251                                                syms.stringType,
3252                                                currentMethodSym);
3253             stmtList.append(make.at(tree.pos()).VarDef(dollar_s, tree.getExpression()).setType(dollar_s.type));
3254 
3255             VarSymbol dollar_tmp = new VarSymbol(SYNTHETIC,
3256                                                  names.fromString("tmp" + tree.pos + target.syntheticNameChar()),
3257                                                  syms.intType,
3258                                                  currentMethodSym);
3259             JCVariableDecl dollar_tmp_def =
3260                 (JCVariableDecl)make.VarDef(dollar_tmp, make.Literal(INT, -1)).setType(dollar_tmp.type);
3261             dollar_tmp_def.init.type = dollar_tmp.type = syms.intType;
3262             stmtList.append(dollar_tmp_def);
3263             ListBuffer<JCCase> caseBuffer = ListBuffer.lb();
3264             // hashCode will trigger nullcheck on original switch expression
3265             JCMethodInvocation hashCodeCall = makeCall(make.Ident(dollar_s),
3266                                                        names.hashCode,
3267                                                        List.<JCExpression>nil()).setType(syms.intType);
3268             JCSwitch switch1 = make.Switch(hashCodeCall,
3269                                         caseBuffer.toList());
3270             for(Map.Entry<Integer, Set<String>> entry : hashToString.entrySet()) {
3271                 int hashCode = entry.getKey();
3272                 Set<String> stringsWithHashCode = entry.getValue();
3273                 assert stringsWithHashCode.size() >= 1;
3274 
3275                 JCStatement elsepart = null;
3276                 for(String caseLabel : stringsWithHashCode ) {
3277                     JCMethodInvocation stringEqualsCall = makeCall(make.Ident(dollar_s),
3278                                                                    names.equals,
3279                                                                    List.<JCExpression>of(make.Literal(caseLabel)));
3280                     elsepart = make.If(stringEqualsCall,
3281                                        make.Exec(make.Assign(make.Ident(dollar_tmp),
3282                                                              make.Literal(caseLabelToPosition.get(caseLabel))).
3283                                                  setType(dollar_tmp.type)),
3284                                        elsepart);
3285                 }
3286 
3287                 ListBuffer<JCStatement> lb = ListBuffer.lb();
3288                 JCBreak breakStmt = make.Break(null);
3289                 breakStmt.target = switch1;
3290                 lb.append(elsepart).append(breakStmt);
3291 
3292                 caseBuffer.append(make.Case(make.Literal(hashCode), lb.toList()));
3293             }
3294 
3295             switch1.cases = caseBuffer.toList();
3296             stmtList.append(switch1);
3297 
3298             // Make isomorphic switch tree replacing string labels
3299             // with corresponding integer ones from the label to
3300             // position map.
3301 
3302             ListBuffer<JCCase> lb = ListBuffer.lb();
3303             JCSwitch switch2 = make.Switch(make.Ident(dollar_tmp), lb.toList());
3304             for(JCCase oneCase : caseList ) {
3305                 // Rewire up old unlabeled break statements to the
3306                 // replacement switch being created.
3307                 patchTargets(oneCase, tree, switch2);
3308 
3309                 boolean isDefault = (oneCase.getExpression() == null);
3310                 JCExpression caseExpr;
3311                 if (isDefault)
3312                     caseExpr = null;
3313                 else {
3314                     caseExpr = make.Literal(caseLabelToPosition.get((String)oneCase.
3315                                                                     getExpression().
3316                                                                     type.constValue()));
3317                 }
3318 
3319                 lb.append(make.Case(caseExpr,
3320                                     oneCase.getStatements()));
3321             }
3322 
3323             switch2.cases = lb.toList();
3324             stmtList.append(switch2);
3325 
3326             return make.Block(0L, stmtList.toList());
3327         }
3328     }
3329 
3330     public void visitNewArray(JCNewArray tree) {
3331         tree.elemtype = translate(tree.elemtype);
3332         for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
3333             if (t.head != null) t.head = translate(t.head, syms.intType);
3334         tree.elems = translate(tree.elems, types.elemtype(tree.type));
3335         result = tree;
3336     }
3337 
3338     public void visitSelect(JCFieldAccess tree) {
3339         // need to special case-access of the form C.super.x
3340         // these will always need an access method.
3341         boolean qualifiedSuperAccess =
3342             tree.selected.getTag() == JCTree.SELECT &&
3343             TreeInfo.name(tree.selected) == names._super;
3344         tree.selected = translate(tree.selected);
3345         if (tree.name == names._class)
3346             result = classOf(tree.selected);
3347         else if (tree.name == names._this || tree.name == names._super)
3348             result = makeThis(tree.pos(), tree.selected.type.tsym);
3349         else