Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(418)

Side by Side Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10387080: Accept more labels per switch case. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix bug when there are more than one label on a statement. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 class Interceptors { 5 class Interceptors {
6 Compiler compiler; 6 Compiler compiler;
7 Interceptors(Compiler this.compiler); 7 Interceptors(Compiler this.compiler);
8 8
9 SourceString mapOperatorToMethodName(Operator op) { 9 SourceString mapOperatorToMethodName(Operator op) {
10 String name = op.source.stringValue; 10 String name = op.source.stringValue;
(...skipping 2932 matching lines...) Expand 10 before | Expand all | Expand 10 after
2943 new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)), 2943 new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)),
2944 elements[node]), 2944 elements[node]),
2945 joinBlock); 2945 joinBlock);
2946 jumpHandler.close(); 2946 jumpHandler.close();
2947 } 2947 }
2948 2948
2949 2949
2950 // Recursively build an if/else structure to match the cases. 2950 // Recursively build an if/else structure to match the cases.
2951 buildSwitchCases(Link<Node> cases, HInstruction expression) { 2951 buildSwitchCases(Link<Node> cases, HInstruction expression) {
2952 SwitchCase node = cases.head; 2952 SwitchCase node = cases.head;
2953
2954 // Called for the statements on all but the last case block. 2953 // Called for the statements on all but the last case block.
2955 // Ensures that a user expecting a fallthrough gets an error. 2954 // Ensures that a user expecting a fallthrough gets an error.
2956 void visitStatementsAndAbort() { 2955 void visitStatementsAndAbort() {
2957 visit(node.statements); 2956 visit(node.statements);
2958 if (!isAborted()) { 2957 if (!isAborted()) {
2959 compiler.reportWarning(node, 'Missing break at end of switch case'); 2958 compiler.reportWarning(node, 'Missing break at end of switch case');
2960 Element element = 2959 Element element =
2961 compiler.findHelper(const SourceString("getFallThroughError")); 2960 compiler.findHelper(const SourceString("getFallThroughError"));
2962 push(new HStatic(element)); 2961 push(new HStatic(element));
2963 HInstruction error = new HInvokeStatic( 2962 HInstruction error = new HInvokeStatic(
2964 Selector.INVOCATION_0, <HInstruction>[pop()]); 2963 Selector.INVOCATION_0, <HInstruction>[pop()]);
2965 add(error); 2964 add(error);
2966 close(new HThrow(error)); 2965 close(new HThrow(error));
2967 } 2966 }
2968 } 2967 }
2969 2968
2970 Link<Node> expressions = node.expressions.nodes; 2969 Link<Node> skipLabels(Link<Node> labelsAndCases) {
2971 if (expressions.isEmpty()) { 2970 while (!labelsAndCases.isEmpty() && labelsAndCases.head is Label) {
2971 labelsAndCases = labelsAndCases.tail;
2972 }
2973 return labelsAndCases;
2974 }
2975
2976 Link<Node> labelsAndCases = skipLabels(node.labelsAndCases.nodes);
2977 if (labelsAndCases.isEmpty()) {
2972 // Default case with no expressions. 2978 // Default case with no expressions.
2973 if (!node.isDefaultCase) { 2979 if (!node.isDefaultCase) {
2974 compiler.internalError("Case with no expression and not default", 2980 compiler.internalError("Case with no expression and not default",
2975 node: node); 2981 node: node);
2976 } 2982 }
2977 visit(node.statements); 2983 visit(node.statements);
2978 // This must be the final case (otherwise "default" would be invalid), 2984 // This must be the final case (otherwise "default" would be invalid),
2979 // so we don't need to check for fallthrough. 2985 // so we don't need to check for fallthrough.
2980 return; 2986 return;
2981 } 2987 }
2982 2988
2983 // Recursively build the test conditions. Leaves the result on the 2989 // Recursively build the test conditions. Leaves the result on the
2984 // expression stack. 2990 // expression stack.
2985 void buildTests(Link<Node> remainingExpressions) { 2991 void buildTests(Link<Node> remainingCases) {
2986 // Build comparison for one case expression. 2992 // Build comparison for one case expression.
2987 void left() { 2993 void left() {
2988 Element equalsHelper = interceptors.getEqualsInterceptor(); 2994 Element equalsHelper = interceptors.getEqualsInterceptor();
2989 HInstruction target = new HStatic(equalsHelper); 2995 HInstruction target = new HStatic(equalsHelper);
2990 add(target); 2996 add(target);
2991 visit(remainingExpressions.head); 2997 CaseMatch match = remainingCases.head;
2998 visit(match.expression);
2992 push(new HEquals(target, pop(), expression)); 2999 push(new HEquals(target, pop(), expression));
2993 } 3000 }
2994 3001
2995 // If this is the last expression, just return it. 3002 // If this is the last expression, just return it.
2996 if (remainingExpressions.tail.isEmpty()) { 3003 Link<Node> tail = skipLabels(remainingCases.tail);
3004 if (tail.isEmpty()) {
2997 left(); 3005 left();
2998 return; 3006 return;
2999 } 3007 }
3000 3008
3001 void right() { 3009 void right() {
3002 buildTests(remainingExpressions.tail); 3010 buildTests(tail);
3003 } 3011 }
3004 handleLogicalAndOr(left, right, isAnd: false); 3012 handleLogicalAndOr(left, right, isAnd: false);
3005 } 3013 }
3006 3014
3007 if (node.isDefaultCase) { 3015 if (node.isDefaultCase) {
3008 buildTests(expressions); 3016 // Default case must be last.
3009 // Throw away the test result. We always execute the default case. 3017 assert(cases.tail.isEmpty());
3010 pop(); 3018 // Perform the tests until one of them match, but then always execute the
3019 // statements.
3020 // TODO(lrn): Stop performing tests when all expressions are compile-time
3021 // constant strings or integers.
3022 handleIf(() { buildTests(labelsAndCases); }, (){}, null);
3011 visit(node.statements); 3023 visit(node.statements);
3012 } else { 3024 } else {
3013 if (cases.tail.isEmpty()) { 3025 if (cases.tail.isEmpty()) {
3014 handleIf(() { buildTests(expressions); }, 3026 handleIf(() { buildTests(labelsAndCases); },
3015 () { visit(node.statements); }, 3027 () { visit(node.statements); },
3016 null); 3028 null);
3017 } else { 3029 } else {
3018 handleIf(() { buildTests(expressions); }, 3030 handleIf(() { buildTests(labelsAndCases); },
3019 () { visitStatementsAndAbort(); }, 3031 () { visitStatementsAndAbort(); },
3020 () { buildSwitchCases(cases.tail, expression); }); 3032 () { buildSwitchCases(cases.tail, expression); });
3021 } 3033 }
3022 } 3034 }
3023 } 3035 }
3024 3036
3025 visitSwitchCase(SwitchCase node) { 3037 visitSwitchCase(SwitchCase node) {
3026 unreachable(); 3038 unreachable();
3027 } 3039 }
3028 3040
3041 visitCaseMatch(CaseMatch node) {
3042 unreachable();
3043 }
3044
3029 visitTryStatement(TryStatement node) { 3045 visitTryStatement(TryStatement node) {
3030 work.allowSpeculativeOptimization = false; 3046 work.allowSpeculativeOptimization = false;
3031 HBasicBlock enterBlock = openNewBlock(); 3047 HBasicBlock enterBlock = openNewBlock();
3032 HTry tryInstruction = new HTry(); 3048 HTry tryInstruction = new HTry();
3033 List<HBasicBlock> blocks = <HBasicBlock>[]; 3049 List<HBasicBlock> blocks = <HBasicBlock>[];
3034 blocks.add(close(tryInstruction)); 3050 blocks.add(close(tryInstruction));
3035 3051
3036 HBasicBlock tryBody = graph.addNewBlock(); 3052 HBasicBlock tryBody = graph.addNewBlock();
3037 enterBlock.addSuccessor(tryBody); 3053 enterBlock.addSuccessor(tryBody);
3038 open(tryBody); 3054 open(tryBody);
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
3315 <HInstruction>[target, input], 3331 <HInstruction>[target, input],
3316 HType.STRING)); 3332 HType.STRING));
3317 return builder.pop(); 3333 return builder.pop();
3318 } 3334 }
3319 3335
3320 HInstruction result() { 3336 HInstruction result() {
3321 flushLiterals(); 3337 flushLiterals();
3322 return prefix; 3338 return prefix;
3323 } 3339 }
3324 } 3340 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698