< prev index next >

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

Print this page
rev 52724 : imported patch 8214031


  46 import com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode;
  47 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  48 import com.sun.tools.javac.tree.JCTree.*;
  49 import com.sun.tools.javac.code.Type.*;
  50 
  51 import com.sun.tools.javac.jvm.Target;
  52 import com.sun.tools.javac.tree.EndPosTable;
  53 
  54 import static com.sun.tools.javac.code.Flags.*;
  55 import static com.sun.tools.javac.code.Flags.BLOCK;
  56 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  57 import static com.sun.tools.javac.code.TypeTag.*;
  58 import static com.sun.tools.javac.code.Kinds.Kind.*;
  59 import static com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode.DEREF;
  60 import static com.sun.tools.javac.jvm.ByteCodes.*;
  61 import com.sun.tools.javac.tree.JCTree.JCBreak;
  62 import com.sun.tools.javac.tree.JCTree.JCCase;
  63 import com.sun.tools.javac.tree.JCTree.JCExpression;
  64 import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
  65 import static com.sun.tools.javac.tree.JCTree.JCOperatorExpression.OperandPos.LEFT;

  66 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  67 
  68 /** This pass translates away some syntactic sugar: inner classes,
  69  *  class literals, assertions, foreach loops, etc.
  70  *
  71  *  <p><b>This is NOT part of any supported API.
  72  *  If you write code that depends on this, you do so at your own risk.
  73  *  This code and its internal interfaces are subject to change or
  74  *  deletion without notice.</b>
  75  */
  76 public class Lower extends TreeTranslator {
  77     protected static final Context.Key<Lower> lowerKey = new Context.Key<>();
  78 
  79     public static Lower instance(Context context) {
  80         Lower instance = context.get(lowerKey);
  81         if (instance == null)
  82             instance = new Lower(context);
  83         return instance;
  84     }
  85 


3345     }
3346 
3347     public void visitForLoop(JCForLoop tree) {
3348         tree.init = translate(tree.init);
3349         if (tree.cond != null)
3350             tree.cond = translate(tree.cond, syms.booleanType);
3351         tree.step = translate(tree.step);
3352         tree.body = translate(tree.body);
3353         result = tree;
3354     }
3355 
3356     public void visitReturn(JCReturn tree) {
3357         if (tree.expr != null)
3358             tree.expr = translate(tree.expr,
3359                                   types.erasure(currentMethodDef
3360                                                 .restype.type));
3361         result = tree;
3362     }
3363 
3364     public void visitSwitch(JCSwitch tree) {















3365         //expand multiple label cases:
3366         ListBuffer<JCCase> cases = new ListBuffer<>();
3367 
3368         for (JCCase c : tree.cases) {
3369             switch (c.pats.size()) {
3370                 case 0: //default
3371                 case 1: //single label
3372                     cases.append(c);
3373                     break;
3374                 default: //multiple labels, expand:
3375                     //case C1, C2, C3: ...
3376                     //=>
3377                     //case C1:
3378                     //case C2:
3379                     //case C3: ...
3380                     List<JCExpression> patterns = c.pats;
3381                     while (patterns.tail.nonEmpty()) {
3382                         cases.append(make_at(c.pos()).Case(JCCase.STATEMENT,
3383                                                            List.of(patterns.head),
3384                                                            List.nil(),
3385                                                            null));
3386                         patterns = patterns.tail;
3387                     }
3388                     c.pats = patterns;
3389                     cases.append(c);
3390                     break;
3391             }
3392         }
3393 
3394         for (JCCase c : cases) {
3395             if (c.caseKind == JCCase.RULE && c.completesNormally) {
3396                 JCBreak b = make_at(c.pos()).Break(null);
3397                 b.target = tree;
3398                 c.stats = c.stats.append(b);
3399             }
3400         }
3401 
3402         tree.cases = cases.toList();
3403 
3404         Type selsuper = types.supertype(tree.selector.type);
3405         boolean enumSwitch = selsuper != null &&
3406             (tree.selector.type.tsym.flags() & ENUM) != 0;
3407         boolean stringSwitch = selsuper != null &&
3408             types.isSameType(tree.selector.type, syms.stringType);
3409         Type target = enumSwitch ? tree.selector.type :
3410             (stringSwitch? syms.stringType : syms.intType);
3411         tree.selector = translate(tree.selector, target);
3412         tree.cases = translateCases(tree.cases);









3413         if (enumSwitch) {
3414             result = visitEnumSwitch(tree);
3415         } else if (stringSwitch) {
3416             result = visitStringSwitch(tree);
3417         } else {
3418             result = tree;
3419         }
3420     }
3421 
3422     public JCTree visitEnumSwitch(JCSwitch tree) {
3423         TypeSymbol enumSym = tree.selector.type.tsym;
3424         EnumMapping map = mapForEnum(tree.pos(), enumSym);
3425         make_at(tree.pos());
3426         Symbol ordinalMethod = lookupMethod(tree.pos(),
3427                                             names.ordinal,
3428                                             tree.selector.type,
3429                                             List.nil());
3430         JCArrayAccess selector = make.Indexed(map.mapVar,
3431                                         make.App(make.Select(tree.selector,
3432                                                              ordinalMethod)));
3433         ListBuffer<JCCase> cases = new ListBuffer<>();
3434         for (JCCase c : tree.cases) {
3435             if (c.pats.nonEmpty()) {
3436                 VarSymbol label = (VarSymbol)TreeInfo.symbol(c.pats.head);
3437                 JCLiteral pat = map.forConstant(label);
3438                 cases.append(make.Case(JCCase.STATEMENT, List.of(pat), c.stats, null));
3439             } else {
3440                 cases.append(c);
3441             }
3442         }
3443         JCSwitch enumSwitch = make.Switch(selector, cases.toList());









3444         patchTargets(enumSwitch, tree, enumSwitch);
3445         return enumSwitch;
3446     }
3447 
3448     public JCTree visitStringSwitch(JCSwitch tree) {
3449         List<JCCase> caseList = tree.getCases();
3450         int alternatives = caseList.size();
3451 
3452         if (alternatives == 0) { // Strange but legal possibility
3453             return make.at(tree.pos()).Exec(attr.makeNullCheck(tree.getExpression()));
3454         } else {
3455             /*
3456              * The general approach used is to translate a single
3457              * string switch statement into a series of two chained
3458              * switch statements: the first a synthesized statement
3459              * switching on the argument string's hash value and
3460              * computing a string's position in the list of original
3461              * case labels, if any, followed by a second switch on the
3462              * computed integer value.  The second switch has the same
3463              * code structure as the original string switch statement
3464              * except that the string case labels are replaced with
3465              * positional integer constants starting at 0.
3466              *
3467              * The first switch statement can be thought of as an
3468              * inlined map from strings to their position in the case
3469              * label list.  An alternate implementation would use an
3470              * actual Map for this purpose, as done for enum switches.
3471              *
3472              * With some additional effort, it would be possible to
3473              * use a single switch statement on the hash code of the


3534 
3535             /*
3536              * s$ = top of stack;
3537              * tmp$ = -1;
3538              * switch($s.hashCode()) {
3539              *     case caseLabel.hashCode:
3540              *         if (s$.equals("caseLabel_1")
3541              *           tmp$ = caseLabelToPosition("caseLabel_1");
3542              *         else if (s$.equals("caseLabel_2"))
3543              *           tmp$ = caseLabelToPosition("caseLabel_2");
3544              *         ...
3545              *         break;
3546              * ...
3547              * }
3548              */
3549 
3550             VarSymbol dollar_s = new VarSymbol(FINAL|SYNTHETIC,
3551                                                names.fromString("s" + tree.pos + target.syntheticNameChar()),
3552                                                syms.stringType,
3553                                                currentMethodSym);
3554             stmtList.append(make.at(tree.pos()).VarDef(dollar_s, tree.getExpression()).setType(dollar_s.type));
3555 
3556             VarSymbol dollar_tmp = new VarSymbol(SYNTHETIC,
3557                                                  names.fromString("tmp" + tree.pos + target.syntheticNameChar()),
3558                                                  syms.intType,
3559                                                  currentMethodSym);
3560             JCVariableDecl dollar_tmp_def =
3561                 (JCVariableDecl)make.VarDef(dollar_tmp, make.Literal(INT, -1)).setType(dollar_tmp.type);
3562             dollar_tmp_def.init.type = dollar_tmp.type = syms.intType;
3563             stmtList.append(dollar_tmp_def);
3564             ListBuffer<JCCase> caseBuffer = new ListBuffer<>();
3565             // hashCode will trigger nullcheck on original switch expression
3566             JCMethodInvocation hashCodeCall = makeCall(make.Ident(dollar_s),
3567                                                        names.hashCode,
3568                                                        List.nil()).setType(syms.intType);
3569             JCSwitch switch1 = make.Switch(hashCodeCall,
3570                                         caseBuffer.toList());
3571             for(Map.Entry<Integer, Set<String>> entry : hashToString.entrySet()) {
3572                 int hashCode = entry.getKey();
3573                 Set<String> stringsWithHashCode = entry.getValue();
3574                 Assert.check(stringsWithHashCode.size() >= 1);


3584                                                  setType(dollar_tmp.type)),
3585                                        elsepart);
3586                 }
3587 
3588                 ListBuffer<JCStatement> lb = new ListBuffer<>();
3589                 JCBreak breakStmt = make.Break(null);
3590                 breakStmt.target = switch1;
3591                 lb.append(elsepart).append(breakStmt);
3592 
3593                 caseBuffer.append(make.Case(JCCase.STATEMENT, List.of(make.Literal(hashCode)), lb.toList(), null));
3594             }
3595 
3596             switch1.cases = caseBuffer.toList();
3597             stmtList.append(switch1);
3598 
3599             // Make isomorphic switch tree replacing string labels
3600             // with corresponding integer ones from the label to
3601             // position map.
3602 
3603             ListBuffer<JCCase> lb = new ListBuffer<>();
3604             JCSwitch switch2 = make.Switch(make.Ident(dollar_tmp), lb.toList());
3605             for(JCCase oneCase : caseList ) {
3606                 // Rewire up old unlabeled break statements to the
3607                 // replacement switch being created.
3608                 patchTargets(oneCase, tree, switch2);
3609 
3610                 boolean isDefault = (oneCase.pats.isEmpty());
3611                 JCExpression caseExpr;
3612                 if (isDefault)
3613                     caseExpr = null;
3614                 else {
3615                     caseExpr = make.Literal(caseLabelToPosition.get((String)TreeInfo.skipParens(oneCase.pats.head).
3616                                                                     type.constValue()));
3617                 }
3618 
3619                 lb.append(make.Case(JCCase.STATEMENT, caseExpr == null ? List.nil() : List.of(caseExpr),
3620                                     oneCase.getStatements(), null));
3621             }
3622 
3623             switch2.cases = lb.toList();





3624             stmtList.append(switch2);
3625 
3626             return make.Block(0L, stmtList.toList());
3627         }
3628     }
3629 
3630     @Override
3631     public void visitSwitchExpression(JCSwitchExpression tree) {
3632         //translates switch expression to statement switch:
3633         //switch (selector) {
3634         //    case C: break value;
3635         //    ...
3636         //}
3637         //=>
3638         //(letexpr T exprswitch$;
3639         //         switch (selector) {
3640         //             case C: { exprswitch$ = value; break; }
3641         //         }
3642         //         exprswitch$
3643         //)
3644         VarSymbol dollar_switchexpr = new VarSymbol(Flags.FINAL|Flags.SYNTHETIC,
3645                            names.fromString("exprswitch" + tree.pos + target.syntheticNameChar()),
3646                            tree.type,
3647                            currentMethodSym);
3648 
3649         ListBuffer<JCStatement> stmtList = new ListBuffer<>();
3650 
3651         stmtList.append(make.at(tree.pos()).VarDef(dollar_switchexpr, null).setType(dollar_switchexpr.type));
3652         JCSwitch switchStatement = make.Switch(tree.selector, null);
3653         switchStatement.cases =
3654                 tree.cases.stream()
3655                           .map(c -> convertCase(dollar_switchexpr, switchStatement, tree, c))
3656                           .collect(List.collector());
3657         if (tree.cases.stream().noneMatch(c -> c.pats.isEmpty())) {
3658             JCThrow thr = make.Throw(makeNewClass(syms.incompatibleClassChangeErrorType,
3659                                                   List.nil()));
3660             JCCase c = make.Case(JCCase.STATEMENT, List.nil(), List.of(thr), null);
3661             switchStatement.cases = switchStatement.cases.append(c);
3662         }
3663 
3664         stmtList.append(translate(switchStatement));

3665 
3666         result = make.LetExpr(stmtList.toList(), make.Ident(dollar_switchexpr))
3667                      .setType(dollar_switchexpr.type);
3668     }
3669         //where:
3670         private JCCase convertCase(VarSymbol dollar_switchexpr, JCSwitch switchStatement,
3671                                    JCSwitchExpression switchExpr, JCCase c) {
3672             make.at(c.pos());
3673             ListBuffer<JCStatement> statements = new ListBuffer<>();
3674             statements.addAll(new TreeTranslator() {
3675                 @Override
3676                 public void visitLambda(JCLambda tree) {}
3677                 @Override
3678                 public void visitClassDef(JCClassDecl tree) {}
3679                 @Override
3680                 public void visitMethodDef(JCMethodDecl tree) {}
3681                 @Override
3682                 public void visitBreak(JCBreak tree) {
3683                     if (tree.target == switchExpr) {
3684                         tree.target = switchStatement;
3685                         JCExpressionStatement assignment =
3686                                 make.Exec(make.Assign(make.Ident(dollar_switchexpr),
3687                                                       translate(tree.value))
3688                                               .setType(dollar_switchexpr.type));
3689                         result = make.Block(0, List.of(assignment,
3690                                                        tree));
3691                         tree.value = null;
3692                     } else {
3693                         result = tree;
3694                     }
3695                 }
3696             }.translate(c.stats));
3697             return make.Case(JCCase.STATEMENT, c.pats, statements.toList(), null);
3698         }
3699 
3700     public void visitNewArray(JCNewArray tree) {
3701         tree.elemtype = translate(tree.elemtype);
3702         for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
3703             if (t.head != null) t.head = translate(t.head, syms.intType);
3704         tree.elems = translate(tree.elems, types.elemtype(tree.type));
3705         result = tree;
3706     }
3707 
3708     public void visitSelect(JCFieldAccess tree) {
3709         // need to special case-access of the form C.super.x
3710         // these will always need an access method, unless C
3711         // is a default interface subclassed by the current class.
3712         boolean qualifiedSuperAccess =
3713             tree.selected.hasTag(SELECT) &&
3714             TreeInfo.name(tree.selected) == names._super &&
3715             !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
3716         tree.selected = translate(tree.selected);
3717         if (tree.name == names._class) {




  46 import com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode;
  47 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  48 import com.sun.tools.javac.tree.JCTree.*;
  49 import com.sun.tools.javac.code.Type.*;
  50 
  51 import com.sun.tools.javac.jvm.Target;
  52 import com.sun.tools.javac.tree.EndPosTable;
  53 
  54 import static com.sun.tools.javac.code.Flags.*;
  55 import static com.sun.tools.javac.code.Flags.BLOCK;
  56 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  57 import static com.sun.tools.javac.code.TypeTag.*;
  58 import static com.sun.tools.javac.code.Kinds.Kind.*;
  59 import static com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode.DEREF;
  60 import static com.sun.tools.javac.jvm.ByteCodes.*;
  61 import com.sun.tools.javac.tree.JCTree.JCBreak;
  62 import com.sun.tools.javac.tree.JCTree.JCCase;
  63 import com.sun.tools.javac.tree.JCTree.JCExpression;
  64 import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
  65 import static com.sun.tools.javac.tree.JCTree.JCOperatorExpression.OperandPos.LEFT;
  66 import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
  67 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  68 
  69 /** This pass translates away some syntactic sugar: inner classes,
  70  *  class literals, assertions, foreach loops, etc.
  71  *
  72  *  <p><b>This is NOT part of any supported API.
  73  *  If you write code that depends on this, you do so at your own risk.
  74  *  This code and its internal interfaces are subject to change or
  75  *  deletion without notice.</b>
  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 


3346     }
3347 
3348     public void visitForLoop(JCForLoop tree) {
3349         tree.init = translate(tree.init);
3350         if (tree.cond != null)
3351             tree.cond = translate(tree.cond, syms.booleanType);
3352         tree.step = translate(tree.step);
3353         tree.body = translate(tree.body);
3354         result = tree;
3355     }
3356 
3357     public void visitReturn(JCReturn tree) {
3358         if (tree.expr != null)
3359             tree.expr = translate(tree.expr,
3360                                   types.erasure(currentMethodDef
3361                                                 .restype.type));
3362         result = tree;
3363     }
3364 
3365     public void visitSwitch(JCSwitch tree) {
3366         handleSwitch(tree, tree.selector, tree.cases);
3367     }
3368 
3369     @Override
3370     public void visitSwitchExpression(JCSwitchExpression tree) {
3371         if (tree.cases.stream().noneMatch(c -> c.pats.isEmpty())) {
3372             JCThrow thr = make.Throw(makeNewClass(syms.incompatibleClassChangeErrorType,
3373                                                   List.nil()));
3374             JCCase c = make.Case(JCCase.STATEMENT, List.nil(), List.of(thr), null);
3375             tree.cases = tree.cases.append(c);
3376         }
3377         handleSwitch(tree, tree.selector, tree.cases);
3378     }
3379 
3380     private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
3381         //expand multiple label cases:
3382         ListBuffer<JCCase> convertedCases = new ListBuffer<>();
3383 
3384         for (JCCase c : cases) {
3385             switch (c.pats.size()) {
3386                 case 0: //default
3387                 case 1: //single label
3388                     convertedCases.append(c);
3389                     break;
3390                 default: //multiple labels, expand:
3391                     //case C1, C2, C3: ...
3392                     //=>
3393                     //case C1:
3394                     //case C2:
3395                     //case C3: ...
3396                     List<JCExpression> patterns = c.pats;
3397                     while (patterns.tail.nonEmpty()) {
3398                         convertedCases.append(make_at(c.pos()).Case(JCCase.STATEMENT,
3399                                                            List.of(patterns.head),
3400                                                            List.nil(),
3401                                                            null));
3402                         patterns = patterns.tail;
3403                     }
3404                     c.pats = patterns;
3405                     convertedCases.append(c);
3406                     break;
3407             }
3408         }
3409 
3410         for (JCCase c : convertedCases) {
3411             if (c.caseKind == JCCase.RULE && c.completesNormally) {
3412                 JCBreak b = make_at(c.pos()).Break(null);
3413                 b.target = tree;
3414                 c.stats = c.stats.append(b);
3415             }
3416         }
3417 
3418         cases = convertedCases.toList();
3419 
3420         Type selsuper = types.supertype(selector.type);
3421         boolean enumSwitch = selsuper != null &&
3422             (selector.type.tsym.flags() & ENUM) != 0;
3423         boolean stringSwitch = selsuper != null &&
3424             types.isSameType(selector.type, syms.stringType);
3425         Type target = enumSwitch ? selector.type :
3426             (stringSwitch? syms.stringType : syms.intType);
3427         selector = translate(selector, target);
3428         cases = translateCases(cases);
3429         if (tree.hasTag(SWITCH)) {
3430             ((JCSwitch) tree).selector = selector;
3431             ((JCSwitch) tree).cases = cases;
3432         } else if (tree.hasTag(SWITCH_EXPRESSION)) {
3433             ((JCSwitchExpression) tree).selector = selector;
3434             ((JCSwitchExpression) tree).cases = cases;
3435         } else {
3436             Assert.error();
3437         }
3438         if (enumSwitch) {
3439             result = visitEnumSwitch(tree, selector, cases);
3440         } else if (stringSwitch) {
3441             result = visitStringSwitch(tree, selector, cases);
3442         } else {
3443             result = tree;
3444         }
3445     }
3446 
3447     public JCTree visitEnumSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
3448         TypeSymbol enumSym = selector.type.tsym;
3449         EnumMapping map = mapForEnum(tree.pos(), enumSym);
3450         make_at(tree.pos());
3451         Symbol ordinalMethod = lookupMethod(tree.pos(),
3452                                             names.ordinal,
3453                                             selector.type,
3454                                             List.nil());
3455         JCArrayAccess newSelector = make.Indexed(map.mapVar,
3456                                         make.App(make.Select(selector,
3457                                                              ordinalMethod)));
3458         ListBuffer<JCCase> newCases = new ListBuffer<>();
3459         for (JCCase c : cases) {
3460             if (c.pats.nonEmpty()) {
3461                 VarSymbol label = (VarSymbol)TreeInfo.symbol(c.pats.head);
3462                 JCLiteral pat = map.forConstant(label);
3463                 newCases.append(make.Case(JCCase.STATEMENT, List.of(pat), c.stats, null));
3464             } else {
3465                 newCases.append(c);
3466             }
3467         }
3468         JCTree enumSwitch;
3469         if (tree.hasTag(SWITCH)) {
3470             enumSwitch = make.Switch(newSelector, newCases.toList());
3471         } else if (tree.hasTag(SWITCH_EXPRESSION)) {
3472             enumSwitch = make.SwitchExpression(newSelector, newCases.toList());
3473             enumSwitch.setType(tree.type);
3474         } else {
3475             Assert.error();
3476             throw new AssertionError();
3477         }
3478         patchTargets(enumSwitch, tree, enumSwitch);
3479         return enumSwitch;
3480     }
3481 
3482     public JCTree visitStringSwitch(JCTree tree, JCExpression selector, List<JCCase> caseList) {

3483         int alternatives = caseList.size();
3484 
3485         if (alternatives == 0) { // Strange but legal possibility (only legal for switch statement)
3486             return make.at(tree.pos()).Exec(attr.makeNullCheck(selector));
3487         } else {
3488             /*
3489              * The general approach used is to translate a single
3490              * string switch statement into a series of two chained
3491              * switch statements: the first a synthesized statement
3492              * switching on the argument string's hash value and
3493              * computing a string's position in the list of original
3494              * case labels, if any, followed by a second switch on the
3495              * computed integer value.  The second switch has the same
3496              * code structure as the original string switch statement
3497              * except that the string case labels are replaced with
3498              * positional integer constants starting at 0.
3499              *
3500              * The first switch statement can be thought of as an
3501              * inlined map from strings to their position in the case
3502              * label list.  An alternate implementation would use an
3503              * actual Map for this purpose, as done for enum switches.
3504              *
3505              * With some additional effort, it would be possible to
3506              * use a single switch statement on the hash code of the


3567 
3568             /*
3569              * s$ = top of stack;
3570              * tmp$ = -1;
3571              * switch($s.hashCode()) {
3572              *     case caseLabel.hashCode:
3573              *         if (s$.equals("caseLabel_1")
3574              *           tmp$ = caseLabelToPosition("caseLabel_1");
3575              *         else if (s$.equals("caseLabel_2"))
3576              *           tmp$ = caseLabelToPosition("caseLabel_2");
3577              *         ...
3578              *         break;
3579              * ...
3580              * }
3581              */
3582 
3583             VarSymbol dollar_s = new VarSymbol(FINAL|SYNTHETIC,
3584                                                names.fromString("s" + tree.pos + target.syntheticNameChar()),
3585                                                syms.stringType,
3586                                                currentMethodSym);
3587             stmtList.append(make.at(tree.pos()).VarDef(dollar_s, selector).setType(dollar_s.type));
3588 
3589             VarSymbol dollar_tmp = new VarSymbol(SYNTHETIC,
3590                                                  names.fromString("tmp" + tree.pos + target.syntheticNameChar()),
3591                                                  syms.intType,
3592                                                  currentMethodSym);
3593             JCVariableDecl dollar_tmp_def =
3594                 (JCVariableDecl)make.VarDef(dollar_tmp, make.Literal(INT, -1)).setType(dollar_tmp.type);
3595             dollar_tmp_def.init.type = dollar_tmp.type = syms.intType;
3596             stmtList.append(dollar_tmp_def);
3597             ListBuffer<JCCase> caseBuffer = new ListBuffer<>();
3598             // hashCode will trigger nullcheck on original switch expression
3599             JCMethodInvocation hashCodeCall = makeCall(make.Ident(dollar_s),
3600                                                        names.hashCode,
3601                                                        List.nil()).setType(syms.intType);
3602             JCSwitch switch1 = make.Switch(hashCodeCall,
3603                                         caseBuffer.toList());
3604             for(Map.Entry<Integer, Set<String>> entry : hashToString.entrySet()) {
3605                 int hashCode = entry.getKey();
3606                 Set<String> stringsWithHashCode = entry.getValue();
3607                 Assert.check(stringsWithHashCode.size() >= 1);


3617                                                  setType(dollar_tmp.type)),
3618                                        elsepart);
3619                 }
3620 
3621                 ListBuffer<JCStatement> lb = new ListBuffer<>();
3622                 JCBreak breakStmt = make.Break(null);
3623                 breakStmt.target = switch1;
3624                 lb.append(elsepart).append(breakStmt);
3625 
3626                 caseBuffer.append(make.Case(JCCase.STATEMENT, List.of(make.Literal(hashCode)), lb.toList(), null));
3627             }
3628 
3629             switch1.cases = caseBuffer.toList();
3630             stmtList.append(switch1);
3631 
3632             // Make isomorphic switch tree replacing string labels
3633             // with corresponding integer ones from the label to
3634             // position map.
3635 
3636             ListBuffer<JCCase> lb = new ListBuffer<>();

3637             for(JCCase oneCase : caseList ) {




3638                 boolean isDefault = (oneCase.pats.isEmpty());
3639                 JCExpression caseExpr;
3640                 if (isDefault)
3641                     caseExpr = null;
3642                 else {
3643                     caseExpr = make.Literal(caseLabelToPosition.get((String)TreeInfo.skipParens(oneCase.pats.head).
3644                                                                     type.constValue()));
3645                 }
3646 
3647                 lb.append(make.Case(JCCase.STATEMENT, caseExpr == null ? List.nil() : List.of(caseExpr),
3648                                     oneCase.stats, null));
3649             }
3650 
3651             if (tree.hasTag(SWITCH)) {
3652                 JCSwitch switch2 = make.Switch(make.Ident(dollar_tmp), lb.toList());
3653                 // Rewire up old unlabeled break statements to the
3654                 // replacement switch being created.
3655                 patchTargets(switch2, tree, switch2);
3656 
3657                 stmtList.append(switch2);
3658 
3659                 return make.Block(0L, stmtList.toList());
3660             } else {
3661                 JCSwitchExpression switch2 = make.SwitchExpression(make.Ident(dollar_tmp), lb.toList());
3662 
3663                 // Rewire up old unlabeled break statements to the
3664                 // replacement switch being created.
3665                 patchTargets(switch2, tree, switch2);















3666 
3667                 switch2.setType(tree.type);
3668 
3669                 LetExpr res = make.LetExpr(stmtList.toList(), switch2);











3670 
3671                 res.needsCond = true;
3672                 res.setType(tree.type);
3673 
3674                 return res;

3675             }
3676         }
3677     }
3678 









3679     @Override
3680     public void visitBreak(JCBreak tree) {
3681         if (tree.isValueBreak()) {
3682             tree.value = translate(tree.value, tree.target.type);










3683         }
3684         result = tree;

3685     }
3686 
3687     public void visitNewArray(JCNewArray tree) {
3688         tree.elemtype = translate(tree.elemtype);
3689         for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
3690             if (t.head != null) t.head = translate(t.head, syms.intType);
3691         tree.elems = translate(tree.elems, types.elemtype(tree.type));
3692         result = tree;
3693     }
3694 
3695     public void visitSelect(JCFieldAccess tree) {
3696         // need to special case-access of the form C.super.x
3697         // these will always need an access method, unless C
3698         // is a default interface subclassed by the current class.
3699         boolean qualifiedSuperAccess =
3700             tree.selected.hasTag(SELECT) &&
3701             TreeInfo.name(tree.selected) == names._super &&
3702             !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
3703         tree.selected = translate(tree.selected);
3704         if (tree.name == names._class) {


< prev index next >