| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |