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

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

Issue 10544024: Implement constant switch as JS switch. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments. Added to Tracer. Created 8 years, 6 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
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2903 matching lines...) Expand 10 before | Expand all | Expand 10 after
2914 visitLiteralMapEntry(LiteralMapEntry node) { 2914 visitLiteralMapEntry(LiteralMapEntry node) {
2915 visit(node.value); 2915 visit(node.value);
2916 visit(node.key); 2916 visit(node.key);
2917 } 2917 }
2918 2918
2919 visitNamedArgument(NamedArgument node) { 2919 visitNamedArgument(NamedArgument node) {
2920 visit(node.expression); 2920 visit(node.expression);
2921 } 2921 }
2922 2922
2923 visitSwitchStatement(SwitchStatement node) { 2923 visitSwitchStatement(SwitchStatement node) {
2924 if (tryBuildConstantSwitch(node)) return;
2925
2924 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 2926 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2925 HBasicBlock startBlock = openNewBlock(); 2927 HBasicBlock startBlock = openNewBlock();
2926 visit(node.expression); 2928 visit(node.expression);
2927 HInstruction expression = pop(); 2929 HInstruction expression = pop();
2928 if (node.cases.isEmpty()) { 2930 if (node.cases.isEmpty()) {
2929 return; 2931 return;
2930 } 2932 }
2933
2931 Link<Node> cases = node.cases.nodes; 2934 Link<Node> cases = node.cases.nodes;
2932
2933 JumpHandler jumpHandler = createJumpHandler(node); 2935 JumpHandler jumpHandler = createJumpHandler(node);
2934 2936
2935 buildSwitchCases(cases, expression); 2937 buildSwitchCases(cases, expression);
2936 2938
2937 HBasicBlock lastBlock = lastOpenedBlock; 2939 HBasicBlock lastBlock = lastOpenedBlock;
2938 2940
2939 // Create merge block for break targets. 2941 // Create merge block for break targets.
2940 HBasicBlock joinBlock = new HBasicBlock(); 2942 HBasicBlock joinBlock = new HBasicBlock();
2941 List<LocalsHandler> caseLocals = <LocalsHandler>[]; 2943 List<LocalsHandler> caseLocals = <LocalsHandler>[];
2942 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { 2944 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) {
(...skipping 20 matching lines...) Expand all
2963 joinBlock = null; 2965 joinBlock = null;
2964 } 2966 }
2965 startBlock.setBlockFlow( 2967 startBlock.setBlockFlow(
2966 new HLabeledBlockInformation.implicit( 2968 new HLabeledBlockInformation.implicit(
2967 new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)), 2969 new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)),
2968 elements[node]), 2970 elements[node]),
2969 joinBlock); 2971 joinBlock);
2970 jumpHandler.close(); 2972 jumpHandler.close();
2971 } 2973 }
2972 2974
2975 bool tryBuildConstantSwitch(SwitchStatement node) {
2976 Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>();
2977 // First check whether all case expressions are compile-time constants.
2978 for (SwitchCase switchCase in node.cases) {
2979 for (Node labelOrCase in switchCase.labelsAndCases) {
2980 if (labelOrCase is CaseMatch) {
2981 CaseMatch match = labelOrCase;
2982 Constant constant =
2983 compiler.constantHandler.tryCompileNodeWithDefinitions(
2984 match.expression, elements);
2985 if (constant === null) return false;
2986 constants[labelOrCase] = constant;
2987 } else {
2988 // We don't handle labels yet.
2989 return false;
2990 }
2991 }
2992 }
2993 // TODO(ngeoffray): Handle switch-instruction in bailout code.
2994 work.allowSpeculativeOptimization = false;
2995 // Then build a switch structure.
2996 HBasicBlock expressionStart = openNewBlock();
2997 visit(node.expression);
2998 HInstruction expression = pop();
2999 if (node.cases.isEmpty()) {
3000 return true;
3001 }
3002 HBasicBlock expressionEnd = current;
3003
3004 HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]);
3005 HBasicBlock expressionBlock = close(switchInstruction);
3006 JumpHandler jumpHandler = createJumpHandler(node);
3007 LocalsHandler savedLocals = localsHandler;
3008
3009 List<List<Constant>> matchExpressions = <List<Constant>>[];
3010 List<HStatementInformation> statements = <HStatementInformation>[];
3011 bool hasDefault = false;
3012 Element getFallThroughErrorElement =
3013 compiler.findHelper(const SourceString("getFallThroughError"));
3014 Iterator<Node> caseIterator = node.cases.iterator();
3015 while (caseIterator.hasNext()) {
3016 SwitchCase switchCase = caseIterator.next();
3017 List<Constant> caseConstants = <Constant>[];
3018 HBasicBlock block = graph.addNewBlock();
3019 for (Node labelOrCase in switchCase.labelsAndCases) {
3020 if (labelOrCase is CaseMatch) {
3021 Constant constant = constants[labelOrCase];
3022 caseConstants.add(constant);
3023 HConstant hConstant = graph.addConstant(constant);
3024 switchInstruction.inputs.add(hConstant);
3025 hConstant.usedBy.add(switchInstruction);
3026 expressionBlock.addSuccessor(block);
3027 }
3028 }
3029 matchExpressions.add(caseConstants);
3030
3031 if (switchCase.isDefaultCase) {
3032 // An HSwitch has n inputs and n+1 successors, the last being the
3033 // default case.
3034 expressionBlock.addSuccessor(block);
3035 hasDefault = true;
3036 }
3037 open(block);
3038 localsHandler = new LocalsHandler.from(savedLocals);
3039 visit(switchCase.statements);
3040 if (!isAborted() && caseIterator.hasNext()) {
3041 push(new HStatic(getFallThroughErrorElement));
3042 HInstruction error = new HInvokeStatic(
3043 Selector.INVOCATION_0, <HInstruction>[pop()]);
3044 add(error);
3045 close(new HThrow(error));
3046 }
3047 statements.add(
3048 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock)));
3049 }
3050
3051 // Add a join-block if necessary.
3052 // We create [joinBlock] early, and then go through the cases that might
3053 // want to jump to it. In each case, if we add [joinBlock] as a successor
3054 // of another block, we also add an element to [caseLocals] that is used
3055 // to create the phis in [joinBlock].
3056 // If we never jump to the join block, [caseLocals] will stay empty, and
3057 // the join block is never added to the graph.
3058 HBasicBlock joinBlock = new HBasicBlock();
3059 List<LocalsHandler> caseLocals = <LocalsHandler>[];
3060 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) {
3061 instruction.block.addSuccessor(joinBlock);
3062 caseLocals.add(locals);
3063 });
3064 if (!isAborted()) {
3065 current.close(new HGoto());
3066 lastOpenedBlock.addSuccessor(joinBlock);
3067 caseLocals.add(localsHandler);
3068 }
3069 if (!hasDefault) {
3070 // The current flow is only aborted if the switch has a default that
3071 // aborts (all previous cases must abort, and if there is no default,
3072 // it's possible to miss all the cases).
3073 expressionEnd.addSuccessor(joinBlock);
3074 caseLocals.add(savedLocals);
3075 }
3076 assert(caseLocals.length == joinBlock.predecessors.length);
3077 if (caseLocals.length != 0) {
3078 graph.addBlock(joinBlock);
3079 open(joinBlock);
3080 if (caseLocals.length == 1) {
3081 localsHandler = caseLocals[0];
3082 } else {
3083 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock);
3084 }
3085 } else {
3086 // The joinblock is not used.
3087 joinBlock = null;
3088 }
3089
3090 HSubExpressionBlockInformation expressionInfo =
3091 new HSubExpressionBlockInformation(new SubExpression(expressionStart,
3092 expressionEnd));
3093 expressionStart.setBlockFlow(
3094 new HSwitchBlockInformation(expressionInfo,
3095 matchExpressions,
3096 statements,
3097 hasDefault,
3098 jumpHandler.target,
3099 jumpHandler.labels()),
3100 joinBlock);
3101
3102 jumpHandler.close();
3103 return true;
3104 }
3105
2973 3106
2974 // Recursively build an if/else structure to match the cases. 3107 // Recursively build an if/else structure to match the cases.
2975 buildSwitchCases(Link<Node> cases, HInstruction expression, 3108 void buildSwitchCases(Link<Node> cases, HInstruction expression,
2976 [int encounteredCaseTypes = 0]) { 3109 [int encounteredCaseTypes = 0]) {
2977 final int NO_TYPE = 0; 3110 final int NO_TYPE = 0;
2978 final int INT_TYPE = 1; 3111 final int INT_TYPE = 1;
2979 final int STRING_TYPE = 2; 3112 final int STRING_TYPE = 2;
2980 final int CONFLICT_TYPE = 3; 3113 final int CONFLICT_TYPE = 3;
2981 int combine(int type1, int type2) => type1 | type2; 3114 int combine(int type1, int type2) => type1 | type2;
2982 3115
2983 SwitchCase node = cases.head; 3116 SwitchCase node = cases.head;
2984 // Called for the statements on all but the last case block. 3117 // Called for the statements on all but the last case block.
2985 // Ensures that a user expecting a fallthrough gets an error. 3118 // Ensures that a user expecting a fallthrough gets an error.
2986 void visitStatementsAndAbort() { 3119 void visitStatementsAndAbort() {
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
3393 <HInstruction>[target, input], 3526 <HInstruction>[target, input],
3394 HType.STRING)); 3527 HType.STRING));
3395 return builder.pop(); 3528 return builder.pop();
3396 } 3529 }
3397 3530
3398 HInstruction result(Node node) { 3531 HInstruction result(Node node) {
3399 flushLiterals(node); 3532 flushLiterals(node);
3400 return prefix; 3533 return prefix;
3401 } 3534 }
3402 } 3535 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698