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

Side by Side Diff: pkg/compiler/lib/src/js_model/locals.dart

Issue 3001233002: Handle labelled breaks (Closed)
Patch Set: Cleanup Created 3 years, 4 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
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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 library dart2js.js_model.locals; 5 library dart2js.js_model.locals;
6 6
7 import 'package:kernel/ast.dart' as ir; 7 import 'package:kernel/ast.dart' as ir;
8 8
9 import 'closure.dart' show JClosureClass; 9 import 'closure.dart' show JClosureClass;
10 import '../closure.dart'; 10 import '../closure.dart';
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 } 164 }
165 165
166 @override 166 @override
167 CapturedLoopScope getCapturedLoopScope( 167 CapturedLoopScope getCapturedLoopScope(
168 ClosureDataLookup closureLookup, ir.TreeNode node) { 168 ClosureDataLookup closureLookup, ir.TreeNode node) {
169 return closureLookup.getCapturedLoopScope(node); 169 return closureLookup.getCapturedLoopScope(node);
170 } 170 }
171 } 171 }
172 172
173 class JumpVisitor extends ir.Visitor { 173 class JumpVisitor extends ir.Visitor {
174 int index = 0; 174 int jumpIndex = 0;
175 int labelIndex = 0;
175 final MemberEntity member; 176 final MemberEntity member;
176 final Map<ir.TreeNode, JJumpTarget> jumpTargetMap = 177 final Map<ir.TreeNode, JJumpTarget> jumpTargetMap =
177 <ir.TreeNode, JJumpTarget>{}; 178 <ir.TreeNode, JJumpTarget>{};
178 final Set<ir.BreakStatement> breaksAsContinue = new Set<ir.BreakStatement>(); 179 final Set<ir.BreakStatement> breaksAsContinue = new Set<ir.BreakStatement>();
179 180
180 JumpVisitor(this.member); 181 JumpVisitor(this.member);
181 182
182 JJumpTarget _getJumpTarget(ir.TreeNode node) { 183 JJumpTarget _getJumpTarget(ir.TreeNode node) {
183 return jumpTargetMap.putIfAbsent(node, () { 184 return jumpTargetMap.putIfAbsent(node, () {
184 return new JJumpTarget(member, index++); 185 return new JJumpTarget(member, jumpIndex++);
185 }); 186 });
186 } 187 }
187 188
188 @override 189 @override
189 defaultNode(ir.Node node) => node.visitChildren(this); 190 defaultNode(ir.Node node) => node.visitChildren(this);
190 191
191 bool _canBeBreakTarget(ir.TreeNode node) { 192 bool _canBeBreakTarget(ir.TreeNode node) {
192 return node is ir.ForStatement || 193 return node is ir.ForStatement ||
193 node is ir.ForInStatement || 194 node is ir.ForInStatement ||
194 node is ir.WhileStatement || 195 node is ir.WhileStatement ||
(...skipping 19 matching lines...) Expand all
214 if (_canBeBreakTarget(body)) { 215 if (_canBeBreakTarget(body)) {
215 // We have code like 216 // We have code like
216 // 217 //
217 // l1: for (int i = 0; i < 10; i++) { 218 // l1: for (int i = 0; i < 10; i++) {
218 // break l1: 219 // break l1:
219 // } 220 // }
220 // 221 //
221 // and can therefore use the for loop as the break target. 222 // and can therefore use the for loop as the break target.
222 target = _getJumpTarget(body); 223 target = _getJumpTarget(body);
223 target.isBreakTarget = true; 224 target.isBreakTarget = true;
225 ir.TreeNode search = node;
226 bool needsLabel = false;
227 while (search != node.target) {
228 if (_canBeBreakTarget(search)) {
229 needsLabel = search != body;
230 break;
231 }
232 search = search.parent;
233 }
234 if (needsLabel) {
235 target.addLabel(node.target, 'label${labelIndex++}',
236 isBreakTarget: true);
237 }
224 } else if (_canBeContinueTarget(parent)) { 238 } else if (_canBeContinueTarget(parent)) {
225 // We have code like 239 // We have code like
226 // 240 //
227 // for (int i = 0; i < 10; i++) l1: { 241 // for (int i = 0; i < 10; i++) l1: {
228 // break l1: 242 // break l1:
229 // } 243 // }
230 // 244 //
231 // and can therefore use the for loop as a continue target. 245 // and can therefore use the for loop as a continue target.
232 target = _getJumpTarget(parent); 246 target = _getJumpTarget(parent);
233 target.isContinueTarget = true; 247 target.isContinueTarget = true;
234 breaksAsContinue.add(node); 248 breaksAsContinue.add(node);
235 } else { 249 } else {
236 target = _getJumpTarget(node.target); 250 target = _getJumpTarget(node.target);
237 target.isBreakTarget = true; 251 target.isBreakTarget = true;
238 } 252 }
239 jumpTargetMap[node] = target; 253 jumpTargetMap[node] = target;
240 super.visitBreakStatement(node); 254 super.visitBreakStatement(node);
241 } 255 }
242 } 256 }
243 257
244 class JJumpTarget extends JumpTarget<ir.Node> { 258 class JJumpTarget extends JumpTarget<ir.Node> {
245 final MemberEntity memberContext; 259 final MemberEntity memberContext;
246 final int nestingLevel; 260 final int nestingLevel;
261 List<LabelDefinition<ir.Node>> _labels;
247 262
248 JJumpTarget(this.memberContext, this.nestingLevel); 263 JJumpTarget(this.memberContext, this.nestingLevel);
249 264
250 bool isBreakTarget = false; 265 bool isBreakTarget = false;
251 bool isContinueTarget = false; 266 bool isContinueTarget = false;
252 bool isSwitch = false; 267 bool isSwitch = false;
253 268
254 @override 269 @override
255 Entity get executableContext => memberContext; 270 Entity get executableContext => memberContext;
256 271
257 @override 272 @override
258 LabelDefinition<ir.Node> addLabel(ir.Node label, String labelName, 273 LabelDefinition<ir.Node> addLabel(ir.Node label, String labelName,
259 {bool isBreakTarget: false}) { 274 {bool isBreakTarget: false}) {
260 throw new UnimplementedError('KJumpTarget.addLabel'); 275 _labels ??= <LabelDefinition<ir.Node>>[];
276 LabelDefinition<ir.Node> labelDefinition = new JLabelDefinition(
277 this, label, labelName,
278 isBreakTarget: isBreakTarget);
279 _labels.add(labelDefinition);
280 return labelDefinition;
261 } 281 }
262 282
263 @override 283 @override
264 List<LabelDefinition<ir.Node>> get labels { 284 List<LabelDefinition<ir.Node>> get labels {
265 return const <LabelDefinition<ir.Node>>[]; 285 return _labels ?? const <LabelDefinition<ir.Node>>[];
266 } 286 }
267 287
268 @override 288 @override
269 ir.Node get statement { 289 ir.Node get statement {
270 throw new UnimplementedError('KJumpTarget.statement'); 290 throw new UnimplementedError('JJumpTarget.statement');
271 } 291 }
272 292
273 String toString() { 293 String toString() {
274 StringBuffer sb = new StringBuffer(); 294 StringBuffer sb = new StringBuffer();
275 sb.write('KJumpTarget['); 295 sb.write('JJumpTarget(');
276 sb.write('memberContext='); 296 sb.write('memberContext=');
277 sb.write(memberContext); 297 sb.write(memberContext);
278 sb.write(',nestingLevel='); 298 sb.write(',nestingLevel=');
279 sb.write(nestingLevel); 299 sb.write(nestingLevel);
280 sb.write(',isBreakTarget='); 300 sb.write(',isBreakTarget=');
281 sb.write(isBreakTarget); 301 sb.write(isBreakTarget);
282 sb.write(',isContinueTarget='); 302 sb.write(',isContinueTarget=');
283 sb.write(isContinueTarget); 303 sb.write(isContinueTarget);
284 sb.write(']'); 304 if (_labels != null) {
305 sb.write(',labels=');
306 sb.write(_labels);
307 }
308 sb.write(')');
285 return sb.toString(); 309 return sb.toString();
286 } 310 }
287 } 311 }
312
313 class JLabelDefinition extends LabelDefinition<ir.Node> {
314 final JumpTarget<ir.Node> target;
315 final ir.Node label;
316 final String labelName;
317 final bool isBreakTarget;
318 final bool isContinueTarget;
319
320 JLabelDefinition(this.target, this.label, this.labelName,
321 {this.isBreakTarget: false, this.isContinueTarget: false});
322
323 @override
324 String get name => labelName;
325 String toString() {
326 StringBuffer sb = new StringBuffer();
327 sb.write('JLabelDefinition(');
328 sb.write('label=');
329 sb.write(label);
330 sb.write(',labelName=');
331 sb.write(labelName);
332 sb.write(',isBreakTarget=');
333 sb.write(isBreakTarget);
334 sb.write(',isContinueTarget=');
335 sb.write(isContinueTarget);
336 sb.write(')');
337 return sb.toString();
338 }
339 }
288 340
289 class JLocal implements Local { 341 class JLocal implements Local {
290 final String name; 342 final String name;
291 final MemberEntity memberContext; 343 final MemberEntity memberContext;
292 344
293 /// True if this local represents a local parameter. 345 /// True if this local represents a local parameter.
294 final bool isRegularParameter; 346 final bool isRegularParameter;
295 347
296 JLocal(this.name, this.memberContext, [isParameter = false]) 348 JLocal(this.name, this.memberContext, [isParameter = false])
297 : isRegularParameter = isParameter; 349 : isRegularParameter = isParameter;
298 350
299 @override 351 @override
300 Entity get executableContext => memberContext; 352 Entity get executableContext => memberContext;
301 353
302 String toString() { 354 String toString() {
303 StringBuffer sb = new StringBuffer(); 355 StringBuffer sb = new StringBuffer();
304 sb.write('local('); 356 sb.write('local(');
305 if (memberContext.enclosingClass != null) { 357 if (memberContext.enclosingClass != null) {
306 sb.write(memberContext.enclosingClass.name); 358 sb.write(memberContext.enclosingClass.name);
307 sb.write('.'); 359 sb.write('.');
308 } 360 }
309 sb.write(memberContext.name); 361 sb.write(memberContext.name);
310 sb.write('#'); 362 sb.write('#');
311 sb.write(name); 363 sb.write(name);
312 sb.write(')'); 364 sb.write(')');
313 return sb.toString(); 365 return sb.toString();
314 } 366 }
315 } 367 }
OLDNEW
« no previous file with comments | « no previous file | tests/compiler/dart2js/kernel/compile_from_dill_test_helper.dart » ('j') | tests/corelib_2/corelib_2.status » ('J')

Powered by Google App Engine
This is Rietveld 408576698