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

Side by Side Diff: pkg/compiler/lib/src/ssa/jump_handler.dart

Issue 2581143003: implement LabeledStatement and Break in kernel (Closed)
Patch Set: fix some tests Created 4 years 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
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 import '../common.dart'; 5 import '../common.dart';
6 import '../elements/elements.dart'; 6 import '../elements/elements.dart';
7 import '../tree/tree.dart' as ast; 7 import '../tree/tree.dart' as ast;
8 8
9 import 'builder.dart'; 9 import 'builder.dart';
10 import 'graph_builder.dart'; 10 import 'graph_builder.dart';
11 import 'locals_handler.dart'; 11 import 'locals_handler.dart';
12 import 'nodes.dart'; 12 import 'nodes.dart';
13 13
14 /// A single break/continue instruction. 14 /// A single break/continue instruction.
15 class JumpHandlerEntry { 15 class _JumpHandlerEntry {
16 final HJump jumpInstruction; 16 final HJump jumpInstruction;
17 final LocalsHandler locals; 17 final LocalsHandler locals;
18 bool isBreak() => jumpInstruction is HBreak; 18 bool isBreak() => jumpInstruction is HBreak;
19 bool isContinue() => jumpInstruction is HContinue; 19 bool isContinue() => jumpInstruction is HContinue;
20 JumpHandlerEntry(this.jumpInstruction, this.locals); 20 _JumpHandlerEntry(this.jumpInstruction, this.locals);
21 } 21 }
22 22
23 abstract class JumpHandler { 23 abstract class JumpHandler {
24 factory JumpHandler(GraphBuilder builder, JumpTarget target) { 24 factory JumpHandler(GraphBuilder builder, JumpTarget target) {
25 return new TargetJumpHandler(builder, target); 25 return new TargetJumpHandler(builder, target);
26 } 26 }
27 void generateBreak([LabelDefinition label]); 27 void generateBreak([LabelDefinition label]);
28 void generateContinue([LabelDefinition label]); 28 void generateContinue([LabelDefinition label]);
29 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); 29 void forEachBreak(void action(HBreak instruction, LocalsHandler locals));
30 void forEachContinue( 30 void forEachContinue(
31 void action(HContinue instruction, LocalsHandler locals)); 31 void action(HContinue instruction, LocalsHandler locals));
32 bool hasAnyContinue(); 32 bool hasAnyContinue();
33 bool hasAnyBreak(); 33 bool hasAnyBreak();
34 void close(); 34 void close();
35 final JumpTarget target; 35 final JumpTarget target;
36 List<LabelDefinition> labels(); 36 List<LabelDefinition> get labels;
37 } 37 }
38 38
39 /// Jump handler used to avoid null checks when a target isn't used as the 39 /// Jump handler used to avoid null checks when a target isn't used as the
40 /// target of a break, and therefore doesn't need a break handler associated 40 /// target of a break, and therefore doesn't need a break handler associated
41 /// with it. 41 /// with it.
42 class NullJumpHandler implements JumpHandler { 42 class NullJumpHandler implements JumpHandler {
43 final DiagnosticReporter reporter; 43 final DiagnosticReporter reporter;
44 44
45 NullJumpHandler(this.reporter); 45 NullJumpHandler(this.reporter);
46 46
47 void generateBreak([LabelDefinition label]) { 47 void generateBreak([LabelDefinition label]) {
48 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, 48 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
49 'NullJumpHandler.generateBreak should not be called.'); 49 'NullJumpHandler.generateBreak should not be called.');
50 } 50 }
51 51
52 void generateContinue([LabelDefinition label]) { 52 void generateContinue([LabelDefinition label]) {
53 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, 53 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
54 'NullJumpHandler.generateContinue should not be called.'); 54 'NullJumpHandler.generateContinue should not be called.');
55 } 55 }
56 56
57 void forEachBreak(Function ignored) {} 57 void forEachBreak(Function ignored) {}
58 void forEachContinue(Function ignored) {} 58 void forEachContinue(Function ignored) {}
59 void close() {} 59 void close() {}
60 bool hasAnyContinue() => false; 60 bool hasAnyContinue() => false;
61 bool hasAnyBreak() => false; 61 bool hasAnyBreak() => false;
62 62
63 List<LabelDefinition> labels() => const <LabelDefinition>[]; 63 List<LabelDefinition> get labels => const <LabelDefinition>[];
64 JumpTarget get target => null; 64 JumpTarget get target => null;
65 } 65 }
66 66
67 /// Jump handler that records breaks until a target block is available. 67 /// Jump handler that records breaks until a target block is available.
68 /// 68 ///
69 /// Breaks are always forward jumps. Continues in loops are implemented as 69 /// Breaks are always forward jumps. Continues in loops are implemented as
70 /// breaks of the body. Continues in switches is currently not handled. 70 /// breaks of the body. Continues in switches is currently not handled.
71 class TargetJumpHandler implements JumpHandler { 71 class TargetJumpHandler implements JumpHandler {
72 final GraphBuilder builder; 72 final GraphBuilder builder;
73 final JumpTarget target; 73 final JumpTarget target;
74 final List<JumpHandlerEntry> jumps; 74 final List<_JumpHandlerEntry> jumps;
75 75
76 TargetJumpHandler(GraphBuilder builder, this.target) 76 TargetJumpHandler(GraphBuilder builder, this.target)
77 : this.builder = builder, 77 : this.builder = builder,
78 jumps = <JumpHandlerEntry>[] { 78 jumps = <_JumpHandlerEntry>[] {
79 assert(builder.jumpTargets[target] == null); 79 assert(builder.jumpTargets[target] == null);
80 builder.jumpTargets[target] = this; 80 builder.jumpTargets[target] = this;
81 } 81 }
82 82
83 void generateBreak([LabelDefinition label]) { 83 void generateBreak([LabelDefinition label]) {
84 HInstruction breakInstruction; 84 HInstruction breakInstruction;
85 if (label == null) { 85 if (label == null) {
86 breakInstruction = new HBreak(target); 86 breakInstruction = new HBreak(target);
87 } else { 87 } else {
88 breakInstruction = new HBreak.toLabel(label); 88 breakInstruction = new HBreak.toLabel(label);
89 } 89 }
90 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler); 90 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
91 builder.close(breakInstruction); 91 builder.close(breakInstruction);
92 jumps.add(new JumpHandlerEntry(breakInstruction, locals)); 92 jumps.add(new _JumpHandlerEntry(breakInstruction, locals));
93 } 93 }
94 94
95 void generateContinue([LabelDefinition label]) { 95 void generateContinue([LabelDefinition label]) {
96 HInstruction continueInstruction; 96 HInstruction continueInstruction;
97 if (label == null) { 97 if (label == null) {
98 continueInstruction = new HContinue(target); 98 continueInstruction = new HContinue(target);
99 } else { 99 } else {
100 continueInstruction = new HContinue.toLabel(label); 100 continueInstruction = new HContinue.toLabel(label);
101 // Switch case continue statements must be handled by the 101 // Switch case continue statements must be handled by the
102 // [SwitchCaseJumpHandler]. 102 // [SwitchCaseJumpHandler].
103 assert(label.target.statement is! ast.SwitchCase); 103 assert(label.target.statement is! ast.SwitchCase);
104 } 104 }
105 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler); 105 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
106 builder.close(continueInstruction); 106 builder.close(continueInstruction);
107 jumps.add(new JumpHandlerEntry(continueInstruction, locals)); 107 jumps.add(new _JumpHandlerEntry(continueInstruction, locals));
108 } 108 }
109 109
110 void forEachBreak(Function action) { 110 void forEachBreak(Function action) {
111 for (JumpHandlerEntry entry in jumps) { 111 for (_JumpHandlerEntry entry in jumps) {
112 if (entry.isBreak()) action(entry.jumpInstruction, entry.locals); 112 if (entry.isBreak()) action(entry.jumpInstruction, entry.locals);
113 } 113 }
114 } 114 }
115 115
116 void forEachContinue(Function action) { 116 void forEachContinue(Function action) {
117 for (JumpHandlerEntry entry in jumps) { 117 for (_JumpHandlerEntry entry in jumps) {
118 if (entry.isContinue()) action(entry.jumpInstruction, entry.locals); 118 if (entry.isContinue()) action(entry.jumpInstruction, entry.locals);
119 } 119 }
120 } 120 }
121 121
122 bool hasAnyContinue() { 122 bool hasAnyContinue() {
123 for (JumpHandlerEntry entry in jumps) { 123 for (_JumpHandlerEntry entry in jumps) {
124 if (entry.isContinue()) return true; 124 if (entry.isContinue()) return true;
125 } 125 }
126 return false; 126 return false;
127 } 127 }
128 128
129 bool hasAnyBreak() { 129 bool hasAnyBreak() {
130 for (JumpHandlerEntry entry in jumps) { 130 for (_JumpHandlerEntry entry in jumps) {
131 if (entry.isBreak()) return true; 131 if (entry.isBreak()) return true;
132 } 132 }
133 return false; 133 return false;
134 } 134 }
135 135
136 void close() { 136 void close() {
137 // The mapping from TargetElement to JumpHandler is no longer needed. 137 // The mapping from TargetElement to JumpHandler is no longer needed.
138 builder.jumpTargets.remove(target); 138 builder.jumpTargets.remove(target);
139 } 139 }
140 140
141 List<LabelDefinition> labels() { 141 List<LabelDefinition> get labels {
142 List<LabelDefinition> result = null; 142 List<LabelDefinition> result = null;
143 for (LabelDefinition element in target.labels) { 143 for (LabelDefinition element in target.labels) {
144 if (result == null) result = <LabelDefinition>[]; 144 result ??= <LabelDefinition>[];
145 result.add(element); 145 result.add(element);
146 } 146 }
147 return (result == null) ? const <LabelDefinition>[] : result; 147 return result ?? const <LabelDefinition>[];
148 } 148 }
149 } 149 }
150 150
151 /// Special [JumpHandler] implementation used to handle continue statements 151 /// Special [JumpHandler] implementation used to handle continue statements
152 /// targeting switch cases. 152 /// targeting switch cases.
153 class SwitchCaseJumpHandler extends TargetJumpHandler { 153 class SwitchCaseJumpHandler extends TargetJumpHandler {
154 /// Map from switch case targets to indices used to encode the flow of the 154 /// Map from switch case targets to indices used to encode the flow of the
155 /// switch case loop. 155 /// switch case loop.
156 final Map<JumpTarget, int> targetIndexMap = new Map<JumpTarget, int>(); 156 final Map<JumpTarget, int> targetIndexMap = new Map<JumpTarget, int>();
157 157
(...skipping 26 matching lines...) Expand all
184 void generateBreak([LabelDefinition label]) { 184 void generateBreak([LabelDefinition label]) {
185 if (label == null) { 185 if (label == null) {
186 // Creates a special break instruction for the synthetic loop generated 186 // Creates a special break instruction for the synthetic loop generated
187 // for a switch statement with continue statements. See 187 // for a switch statement with continue statements. See
188 // [SsaFromAstMixin.buildComplexSwitchStatement] for detail. 188 // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
189 189
190 HInstruction breakInstruction = 190 HInstruction breakInstruction =
191 new HBreak(target, breakSwitchContinueLoop: true); 191 new HBreak(target, breakSwitchContinueLoop: true);
192 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler); 192 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
193 builder.close(breakInstruction); 193 builder.close(breakInstruction);
194 jumps.add(new JumpHandlerEntry(breakInstruction, locals)); 194 jumps.add(new _JumpHandlerEntry(breakInstruction, locals));
195 } else { 195 } else {
196 super.generateBreak(label); 196 super.generateBreak(label);
197 } 197 }
198 } 198 }
199 199
200 bool isContinueToSwitchCase(LabelDefinition label) { 200 bool isContinueToSwitchCase(LabelDefinition label) {
201 return label != null && targetIndexMap.containsKey(label.target); 201 return label != null && targetIndexMap.containsKey(label.target);
202 } 202 }
203 203
204 void generateContinue([LabelDefinition label]) { 204 void generateContinue([LabelDefinition label]) {
205 if (isContinueToSwitchCase(label)) { 205 if (isContinueToSwitchCase(label)) {
206 // Creates the special instructions 'label = i; continue l;' used in 206 // Creates the special instructions 'label = i; continue l;' used in
207 // switch statements with continue statements. See 207 // switch statements with continue statements. See
208 // [SsaFromAstMixin.buildComplexSwitchStatement] for detail. 208 // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
209 209
210 assert(label != null); 210 assert(label != null);
211 // TODO(het): change the graph 'addConstantXXX' to take a ConstantSystem 211 // TODO(het): change the graph 'addConstantXXX' to take a ConstantSystem
212 // instead of a Compiler. 212 // instead of a Compiler.
213 HInstruction value = builder.graph 213 HInstruction value = builder.graph
214 .addConstantInt(targetIndexMap[label.target], builder.compiler); 214 .addConstantInt(targetIndexMap[label.target], builder.compiler);
215 builder.localsHandler.updateLocal(target, value); 215 builder.localsHandler.updateLocal(target, value);
216 216
217 assert(label.target.labels.contains(label)); 217 assert(label.target.labels.contains(label));
218 HInstruction continueInstruction = new HContinue(target); 218 HInstruction continueInstruction = new HContinue(target);
219 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler); 219 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
220 builder.close(continueInstruction); 220 builder.close(continueInstruction);
221 jumps.add(new JumpHandlerEntry(continueInstruction, locals)); 221 jumps.add(new _JumpHandlerEntry(continueInstruction, locals));
222 } else { 222 } else {
223 super.generateContinue(label); 223 super.generateContinue(label);
224 } 224 }
225 } 225 }
226 226
227 void close() { 227 void close() {
228 // The mapping from TargetElement to JumpHandler is no longer needed. 228 // The mapping from TargetElement to JumpHandler is no longer needed.
229 for (JumpTarget target in targetIndexMap.keys) { 229 for (JumpTarget target in targetIndexMap.keys) {
230 builder.jumpTargets.remove(target); 230 builder.jumpTargets.remove(target);
231 } 231 }
232 super.close(); 232 super.close();
233 } 233 }
234 } 234 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698