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

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: 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
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 2923 matching lines...) Expand 10 before | Expand all | Expand 10 after
2934 visitLiteralMapEntry(LiteralMapEntry node) { 2934 visitLiteralMapEntry(LiteralMapEntry node) {
2935 visit(node.value); 2935 visit(node.value);
2936 visit(node.key); 2936 visit(node.key);
2937 } 2937 }
2938 2938
2939 visitNamedArgument(NamedArgument node) { 2939 visitNamedArgument(NamedArgument node) {
2940 visit(node.expression); 2940 visit(node.expression);
2941 } 2941 }
2942 2942
2943 visitSwitchStatement(SwitchStatement node) { 2943 visitSwitchStatement(SwitchStatement node) {
2944 if (tryBuildConstantSwitch(node)) return;
2945
2944 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 2946 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2945 HBasicBlock startBlock = openNewBlock(); 2947 HBasicBlock startBlock = openNewBlock();
2946 visit(node.expression); 2948 visit(node.expression);
2947 HInstruction expression = pop(); 2949 HInstruction expression = pop();
2948 if (node.cases.isEmpty()) { 2950 if (node.cases.isEmpty()) {
2949 return; 2951 return;
2950 } 2952 }
2953
2951 Link<Node> cases = node.cases.nodes; 2954 Link<Node> cases = node.cases.nodes;
2952
2953 JumpHandler jumpHandler = createJumpHandler(node); 2955 JumpHandler jumpHandler = createJumpHandler(node);
2954 2956
2955 buildSwitchCases(cases, expression); 2957 buildSwitchCases(cases, expression);
2956 2958
2957 HBasicBlock lastBlock = lastOpenedBlock; 2959 HBasicBlock lastBlock = lastOpenedBlock;
2958 2960
2959 // Create merge block for break targets. 2961 // Create merge block for break targets.
2960 HBasicBlock joinBlock = new HBasicBlock(); 2962 HBasicBlock joinBlock = new HBasicBlock();
2961 List<LocalsHandler> caseLocals = <LocalsHandler>[]; 2963 List<LocalsHandler> caseLocals = <LocalsHandler>[];
2962 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { 2964 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) {
(...skipping 20 matching lines...) Expand all
2983 joinBlock = null; 2985 joinBlock = null;
2984 } 2986 }
2985 startBlock.setBlockFlow( 2987 startBlock.setBlockFlow(
2986 new HLabeledBlockInformation.implicit( 2988 new HLabeledBlockInformation.implicit(
2987 new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)), 2989 new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)),
2988 elements[node]), 2990 elements[node]),
2989 joinBlock); 2991 joinBlock);
2990 jumpHandler.close(); 2992 jumpHandler.close();
2991 } 2993 }
2992 2994
2995 bool tryBuildConstantSwitch(SwitchStatement node) {
2996 Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>();
2997 // First check whether all case expressions are compile-time constants.
2998 for (SwitchCase switchCase in node.cases) {
2999 for (Node labelOrCase in switchCase.labelsAndCases) {
3000 if (labelOrCase is CaseMatch) {
3001 CaseMatch match = labelOrCase;
3002 Constant constant =
3003 compiler.constantHandler.tryCompileNodeWithDefinitions(
3004 match.expression, elements);
3005 if (constant === null) return false;
3006 constants[labelOrCase] = constant;
3007 } else {
3008 // We don't handle labels yet.
3009 return false;
3010 }
3011 }
3012 }
3013 // TODO(ngeoffray): Handle switch-instruction in bailout code.
Lasse Reichstein Nielsen 2012/06/06 09:29:31 I hope it's simple if you know how :)
3014 work.allowSpeculativeOptimization = false;
3015 // Then build a switch structure.
3016 HBasicBlock expressionStart = openNewBlock();
3017 visit(node.expression);
3018 HInstruction expression = pop();
3019 if (node.cases.isEmpty()) {
3020 return true;
3021 }
3022 HBasicBlock expressionEnd = current;
3023
3024 HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]);
3025 HBasicBlock expressionBlock = close(switchInstruction);
3026 JumpHandler jumpHandler = createJumpHandler(node);
3027 LocalsHandler savedLocals = localsHandler;
3028
3029 List<List<Constant>> matchExpressions = <List<Constant>>[];
3030 List<HStatementInformation> statements = <HStatementInformation>[];
3031 bool hasDefault = false;
3032 for (Iterator<Node> iterator = node.cases.iterator(); iterator.hasNext();) {
floitsch 2012/06/06 11:50:26 I would prefer a while loop.
Lasse Reichstein Nielsen 2012/06/06 13:01:21 Done.
3033 SwitchCase switchCase = iterator.next();
3034 List<Constant> caseConstants = <Constant>[];
3035 HBasicBlock block = graph.addNewBlock();
3036 for (Node labelOrCase in switchCase.labelsAndCases) {
3037 if (labelOrCase is CaseMatch) {
floitsch 2012/06/06 11:50:26 At the moment an assert would work too here, no?
Lasse Reichstein Nielsen 2012/06/06 13:01:21 No, we still parse the labels, we just don't do an
floitsch 2012/06/06 14:32:01 But isn't there a "return false" in line 3009 for
Lasse Reichstein Nielsen 2012/06/07 12:03:05 True, there is. Let's not make the assumption in m
3038 Constant constant = constants[labelOrCase];
3039 caseConstants.add(constant);
3040 HConstant hConstant = graph.addConstant(constant);
3041 switchInstruction.inputs.add(hConstant);
3042 hConstant.usedBy.add(switchInstruction);
3043 expressionBlock.addSuccessor(block);
3044 }
3045 }
3046 matchExpressions.add(caseConstants);
3047
3048 if (switchCase.isDefaultCase) {
3049 // An HSwitch has n inputs and n+1 successors, the last being the
3050 // default case.
3051 expressionBlock.addSuccessor(block);
3052 hasDefault = true;
3053 }
3054 open(block);
3055 localsHandler = new LocalsHandler.from(savedLocals);
3056 visit(switchCase.statements);
3057 if (!isAborted() && iterator.hasNext()) {
3058 compiler.reportWarning(node, 'Missing break at end of switch case');
ngeoffray 2012/06/06 12:03:46 I don't think the codegen should emit a warning.
Lasse Reichstein Nielsen 2012/06/06 13:01:21 True. Something earlier should do that. I'll remo
3059 Element element =
3060 compiler.findHelper(const SourceString("getFallThroughError"));
ngeoffray 2012/06/06 12:03:46 Maybe move that call out of the loop?
Lasse Reichstein Nielsen 2012/06/06 13:01:21 Reasonable. Done.
3061 push(new HStatic(element));
3062 HInstruction error = new HInvokeStatic(
3063 Selector.INVOCATION_0, <HInstruction>[pop()]);
3064 add(error);
3065 close(new HThrow(error));
3066 }
3067 statements.add(
3068 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock)));
3069 }
3070
3071 // Add a join-block if necessary.
3072 HBasicBlock joinBlock = new HBasicBlock();
3073 List<LocalsHandler> caseLocals = <LocalsHandler>[];
3074 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) {
3075 instruction.block.addSuccessor(joinBlock);
3076 caseLocals.add(locals);
3077 });
3078 if (!isAborted()) {
ngeoffray 2012/06/06 12:03:46 Should this check be in the one line 3090? You're
Lasse Reichstein Nielsen 2012/06/06 13:01:21 If this test succeedes, it adds an element to case
3079 current.close(new HGoto());
3080 lastOpenedBlock.addSuccessor(joinBlock);
3081 caseLocals.add(localsHandler);
3082 }
3083 if (!hasDefault) {
ngeoffray 2012/06/06 12:03:46 ditto
Lasse Reichstein Nielsen 2012/06/06 13:01:21 And ditto.
3084 // The current flow is only aborted if the switch has a default that
3085 // aborts (all previous cases must abort, and if there is no default,
3086 // it's possible to miss all the cases).
3087 expressionEnd.addSuccessor(joinBlock);
3088 caseLocals.add(savedLocals);
3089 }
3090 if (caseLocals.length != 0) {
3091 graph.addBlock(joinBlock);
3092 open(joinBlock);
3093 if (caseLocals.length == 1) {
3094 localsHandler = caseLocals[0];
3095 } else {
3096 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock);
3097 }
3098 } else {
3099 // The joinblock is not used.
3100 joinBlock = null;
3101 }
3102
3103 HSubExpressionBlockInformation expressionInfo =
3104 new HSubExpressionBlockInformation(new SubExpression(expressionStart,
3105 expressionEnd));
3106 expressionStart.setBlockFlow(
3107 new HSwitchBlockInformation(expressionInfo,
3108 matchExpressions,
3109 statements,
3110 hasDefault,
3111 jumpHandler.target,
3112 jumpHandler.labels()),
3113 joinBlock);
3114
3115 jumpHandler.close();
3116 return true;
3117 }
3118
2993 3119
2994 // Recursively build an if/else structure to match the cases. 3120 // Recursively build an if/else structure to match the cases.
2995 buildSwitchCases(Link<Node> cases, HInstruction expression, 3121 void buildSwitchCases(Link<Node> cases, HInstruction expression,
2996 [int encounteredCaseTypes = 0]) { 3122 [int encounteredCaseTypes = 0]) {
2997 final int NO_TYPE = 0; 3123 final int NO_TYPE = 0;
2998 final int INT_TYPE = 1; 3124 final int INT_TYPE = 1;
2999 final int STRING_TYPE = 2; 3125 final int STRING_TYPE = 2;
3000 final int CONFLICT_TYPE = 3; 3126 final int CONFLICT_TYPE = 3;
3001 int combine(int type1, int type2) => type1 | type2; 3127 int combine(int type1, int type2) => type1 | type2;
3002 3128
3003 SwitchCase node = cases.head; 3129 SwitchCase node = cases.head;
3004 // Called for the statements on all but the last case block. 3130 // Called for the statements on all but the last case block.
3005 // Ensures that a user expecting a fallthrough gets an error. 3131 // Ensures that a user expecting a fallthrough gets an error.
3006 void visitStatementsAndAbort() { 3132 void visitStatementsAndAbort() {
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
3413 <HInstruction>[target, input], 3539 <HInstruction>[target, input],
3414 HType.STRING)); 3540 HType.STRING));
3415 return builder.pop(); 3541 return builder.pop();
3416 } 3542 }
3417 3543
3418 HInstruction result(Node node) { 3544 HInstruction result(Node node) {
3419 flushLiterals(node); 3545 flushLiterals(node);
3420 return prefix; 3546 return prefix;
3421 } 3547 }
3422 } 3548 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen.dart » ('j') | lib/compiler/implementation/ssa/codegen.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698