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

Side by Side Diff: pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart

Issue 2954663002: Handle break as continue (Closed)
Patch Set: Add break/continue to run_from_dill_test Created 3 years, 5 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.kernel.backend_strategy; 5 library dart2js.kernel.backend_strategy;
6 6
7 import 'package:kernel/ast.dart' as ir; 7 import 'package:kernel/ast.dart' as ir;
8 8
9 import '../backend_strategy.dart'; 9 import '../backend_strategy.dart';
10 import '../closure.dart'; 10 import '../closure.dart';
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 273
274 KernelToLocalsMap getLocalsMap(MemberEntity member) { 274 KernelToLocalsMap getLocalsMap(MemberEntity member) {
275 return _localsMaps.putIfAbsent( 275 return _localsMaps.putIfAbsent(
276 member, () => new KernelToLocalsMapImpl(member)); 276 member, () => new KernelToLocalsMapImpl(member));
277 } 277 }
278 } 278 }
279 279
280 class KernelToLocalsMapImpl implements KernelToLocalsMap { 280 class KernelToLocalsMapImpl implements KernelToLocalsMap {
281 final List<MemberEntity> _members = <MemberEntity>[]; 281 final List<MemberEntity> _members = <MemberEntity>[];
282 Map<ir.VariableDeclaration, KLocal> _map = <ir.VariableDeclaration, KLocal>{}; 282 Map<ir.VariableDeclaration, KLocal> _map = <ir.VariableDeclaration, KLocal>{};
283 Map<ir.LabeledStatement, KJumpTarget> _jumpTargetMap; 283 Map<ir.TreeNode, KJumpTarget> _jumpTargetMap;
284 Set<ir.BreakStatement> _breaksAsContinue;
284 285
285 MemberEntity get currentMember => _members.last; 286 MemberEntity get currentMember => _members.last;
286 287
287 // TODO(johnniwinther): Compute this eagerly from the root of the member. 288 // TODO(johnniwinther): Compute this eagerly from the root of the member.
288 void _ensureJumpMap(ir.TreeNode node) { 289 void _ensureJumpMap(ir.TreeNode node) {
289 if (_jumpTargetMap == null) { 290 if (_jumpTargetMap == null) {
290 JumpVisitor visitor = new JumpVisitor(currentMember); 291 JumpVisitor visitor = new JumpVisitor(currentMember);
291 292
292 // Find the root node for the current member. 293 // Find the root node for the current member.
293 while (node is! ir.Member) { 294 while (node is! ir.Member) {
294 node = node.parent; 295 node = node.parent;
295 } 296 }
296 297
297 node.accept(visitor); 298 node.accept(visitor);
298 _jumpTargetMap = visitor.jumpTargetMap; 299 _jumpTargetMap = visitor.jumpTargetMap;
300 _breaksAsContinue = visitor.breaksAsContinue;
299 } 301 }
300 } 302 }
301 303
302 KernelToLocalsMapImpl(MemberEntity member) { 304 KernelToLocalsMapImpl(MemberEntity member) {
303 _members.add(member); 305 _members.add(member);
304 } 306 }
305 307
306 @override 308 @override
307 void enterInlinedMember(MemberEntity member) { 309 void enterInlinedMember(MemberEntity member) {
308 _members.add(member); 310 _members.add(member);
309 } 311 }
310 312
311 @override 313 @override
312 void leaveInlinedMember(MemberEntity member) { 314 void leaveInlinedMember(MemberEntity member) {
313 assert(member == currentMember); 315 assert(member == currentMember);
314 _members.removeLast(); 316 _members.removeLast();
315 } 317 }
316 318
317 @override 319 @override
318 JumpTarget getJumpTargetForBreak(ir.BreakStatement node) { 320 JumpTarget getJumpTargetForBreak(ir.BreakStatement node) {
319 _ensureJumpMap(node.target); 321 _ensureJumpMap(node.target);
320 JumpTarget target = _jumpTargetMap[node.target]; 322 JumpTarget target = _jumpTargetMap[node];
321 assert(target != null, failedAt(currentMember, 'No target for $node.')); 323 assert(target != null, failedAt(currentMember, 'No target for $node.'));
322 return target; 324 return target;
323 } 325 }
324 326
325 @override 327 @override
328 bool generateContinueForBreak(ir.BreakStatement node) {
329 return _breaksAsContinue.contains(node);
330 }
331
332 @override
326 JumpTarget getJumpTargetForContinueSwitch(ir.ContinueSwitchStatement node) { 333 JumpTarget getJumpTargetForContinueSwitch(ir.ContinueSwitchStatement node) {
327 _ensureJumpMap(node.target); 334 _ensureJumpMap(node.target);
328 throw new UnimplementedError( 335 throw new UnimplementedError(
329 'KernelToLocalsMapImpl.getJumpTargetForContinueSwitch'); 336 'KernelToLocalsMapImpl.getJumpTargetForContinueSwitch');
330 } 337 }
331 338
332 @override 339 @override
333 JumpTarget getJumpTargetForSwitchCase(ir.SwitchCase node) { 340 JumpTarget getJumpTargetForSwitchCase(ir.SwitchCase node) {
334 _ensureJumpMap(node); 341 _ensureJumpMap(node);
335 throw new UnimplementedError( 342 throw new UnimplementedError(
336 'KernelToLocalsMapImpl.getJumpTargetForSwitchCase'); 343 'KernelToLocalsMapImpl.getJumpTargetForSwitchCase');
337 } 344 }
338 345
339 @override 346 @override
340 JumpTarget getJumpTargetForDo(ir.DoStatement node) { 347 JumpTarget getJumpTargetForDo(ir.DoStatement node) {
341 _ensureJumpMap(node); 348 _ensureJumpMap(node);
342 return _jumpTargetMap[node.parent]; 349 return _jumpTargetMap[node.parent];
343 } 350 }
344 351
345 @override 352 @override
346 JumpTarget getJumpTargetForLabel(ir.LabeledStatement node) { 353 JumpTarget getJumpTargetForLabel(ir.LabeledStatement node) {
347 _ensureJumpMap(node); 354 _ensureJumpMap(node);
348 JumpTarget target = _jumpTargetMap[node]; 355 return _jumpTargetMap[node];
349 assert(target != null, failedAt(currentMember, 'No target for $node.'));
350 return target;
351 } 356 }
352 357
353 @override 358 @override
354 JumpTarget getJumpTargetForSwitch(ir.SwitchStatement node) { 359 JumpTarget getJumpTargetForSwitch(ir.SwitchStatement node) {
355 _ensureJumpMap(node); 360 _ensureJumpMap(node);
356 throw new UnimplementedError( 361 throw new UnimplementedError(
357 'KernelToLocalsMapImpl.getJumpTargetForSwitch'); 362 'KernelToLocalsMapImpl.getJumpTargetForSwitch');
358 } 363 }
359 364
360 @override 365 @override
361 JumpTarget getJumpTargetForFor(ir.ForStatement node) { 366 JumpTarget getJumpTargetForFor(ir.ForStatement node) {
362 _ensureJumpMap(node); 367 _ensureJumpMap(node);
363 return _jumpTargetMap[node.parent]; 368 return _jumpTargetMap[node];
364 } 369 }
365 370
366 @override 371 @override
367 JumpTarget getJumpTargetForForIn(ir.ForInStatement node) { 372 JumpTarget getJumpTargetForForIn(ir.ForInStatement node) {
368 _ensureJumpMap(node); 373 _ensureJumpMap(node);
369 return _jumpTargetMap[node.parent]; 374 return _jumpTargetMap[node.parent];
370 } 375 }
371 376
372 @override 377 @override
373 JumpTarget getJumpTargetForWhile(ir.WhileStatement node) { 378 JumpTarget getJumpTargetForWhile(ir.WhileStatement node) {
374 _ensureJumpMap(node); 379 _ensureJumpMap(node);
375 return _jumpTargetMap[node.parent]; 380 return _jumpTargetMap[node.parent];
376 } 381 }
377 382
378 @override 383 @override
379 Local getLocal(ir.VariableDeclaration node) { 384 Local getLocal(ir.VariableDeclaration node) {
380 return _map.putIfAbsent(node, () { 385 return _map.putIfAbsent(node, () {
381 return new KLocal(node.name, currentMember); 386 return new KLocal(node.name, currentMember);
382 }); 387 });
383 } 388 }
384 389
385 @override 390 @override
386 LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop( 391 LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop(
387 ClosureDataLookup closureLookup, ir.TreeNode node) { 392 ClosureDataLookup closureLookup, ir.TreeNode node) {
388 return closureLookup.getClosureRepresentationInfoForLoop(node); 393 return closureLookup.getClosureRepresentationInfoForLoop(node);
389 } 394 }
390 } 395 }
391 396
392 class JumpVisitor extends ir.Visitor { 397 class JumpVisitor extends ir.Visitor {
398 int index = 0;
393 final MemberEntity member; 399 final MemberEntity member;
394 final Map<ir.LabeledStatement, KJumpTarget> jumpTargetMap = 400 final Map<ir.TreeNode, KJumpTarget> jumpTargetMap =
395 <ir.LabeledStatement, KJumpTarget>{}; 401 <ir.TreeNode, KJumpTarget>{};
402 final Set<ir.BreakStatement> breaksAsContinue = new Set<ir.BreakStatement>();
396 403
397 JumpVisitor(this.member); 404 JumpVisitor(this.member);
398 405
399 KJumpTarget _getJumpTarget(ir.LabeledStatement node) { 406 KJumpTarget _getJumpTarget(ir.TreeNode node) {
400 return jumpTargetMap.putIfAbsent(node, () { 407 return jumpTargetMap.putIfAbsent(node, () {
401 return new KJumpTarget(member, jumpTargetMap.length); 408 return new KJumpTarget(member, index++);
402 }); 409 });
403 } 410 }
404 411
405 @override 412 @override
406 defaultNode(ir.Node node) => node.visitChildren(this); 413 defaultNode(ir.Node node) => node.visitChildren(this);
407 414
415 bool _canBeBreakTarget(ir.TreeNode node) {
416 // TODO(johnniwinther): Add more.
417 return node is ir.ForStatement;
418 }
419
420 bool _canBeContinueTarget(ir.TreeNode node) {
421 // TODO(johnniwinther): Add more.
422 return node is ir.ForStatement;
423 }
424
408 @override 425 @override
409 visitBreakStatement(ir.BreakStatement node) { 426 visitBreakStatement(ir.BreakStatement node) {
410 KJumpTarget target = _getJumpTarget(node.target); 427 // TODO(johnniwinther): Add labels if the enclosing loop is not the implicit
411 target.isBreakTarget = true; 428 // break target.
429 KJumpTarget target;
430 ir.TreeNode body = node.target.body;
431 ir.TreeNode parent = node.target.parent;
432 if (_canBeBreakTarget(body)) {
433 // We have code like
434 //
435 // l1: for (int i = 0; i < 10; i++) {
436 // break l1:
437 // }
438 //
439 // and can therefore use the for loop as the break target.
440 target = _getJumpTarget(body);
441 target.isBreakTarget = true;
442 } else if (_canBeContinueTarget(parent)) {
443 // We have code like
444 //
445 // for (int i = 0; i < 10; i++) l1: {
446 // break l1:
447 // }
448 //
449 // and can therefore use the for loop as a continue target.
450 target = _getJumpTarget(parent);
451 target.isContinueTarget = true;
452 breaksAsContinue.add(node);
453 } else {
454 target = _getJumpTarget(node.target);
455 target.isBreakTarget = true;
456 }
457 jumpTargetMap[node] = target;
412 super.visitBreakStatement(node); 458 super.visitBreakStatement(node);
413 } 459 }
414 } 460 }
415 461
416 class KJumpTarget extends JumpTarget<ir.Node> { 462 class KJumpTarget extends JumpTarget<ir.Node> {
417 final MemberEntity memberContext; 463 final MemberEntity memberContext;
418 final int nestingLevel; 464 final int nestingLevel;
419 465
420 KJumpTarget(this.memberContext, this.nestingLevel); 466 KJumpTarget(this.memberContext, this.nestingLevel);
421 467
(...skipping 12 matching lines...) Expand all
434 480
435 @override 481 @override
436 List<LabelDefinition<ir.Node>> get labels { 482 List<LabelDefinition<ir.Node>> get labels {
437 return const <LabelDefinition<ir.Node>>[]; 483 return const <LabelDefinition<ir.Node>>[];
438 } 484 }
439 485
440 @override 486 @override
441 ir.Node get statement { 487 ir.Node get statement {
442 throw new UnimplementedError('KJumpTarget.statement'); 488 throw new UnimplementedError('KJumpTarget.statement');
443 } 489 }
490
491 String toString() {
492 StringBuffer sb = new StringBuffer();
493 sb.write('KJumpTarget[');
494 sb.write('memberContext=');
495 sb.write(memberContext);
496 sb.write(',nestingLevel=');
497 sb.write(nestingLevel);
498 sb.write(',isBreakTarget=');
499 sb.write(isBreakTarget);
500 sb.write(',isContinueTarget=');
501 sb.write(isContinueTarget);
502 sb.write(']');
503 return sb.toString();
504 }
444 } 505 }
445 506
446 class KLocal implements Local { 507 class KLocal implements Local {
447 final String name; 508 final String name;
448 final MemberEntity memberContext; 509 final MemberEntity memberContext;
449 510
450 KLocal(this.name, this.memberContext); 511 KLocal(this.name, this.memberContext);
451 512
452 @override 513 @override
453 Entity get executableContext => memberContext; 514 Entity get executableContext => memberContext;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 Iterable<ClassEntity> sortClasses(Iterable<ClassEntity> classes) { 568 Iterable<ClassEntity> sortClasses(Iterable<ClassEntity> classes) {
508 return classes.toList() 569 return classes.toList()
509 ..sort((ClassEntity a, ClassEntity b) { 570 ..sort((ClassEntity a, ClassEntity b) {
510 int r = _compareLibraries(a.library, b.library); 571 int r = _compareLibraries(a.library, b.library);
511 if (r != 0) return r; 572 if (r != 0) return r;
512 return _compareNodes( 573 return _compareNodes(
513 a, elementMap.getClassNode(a), b, elementMap.getClassNode(b)); 574 a, elementMap.getClassNode(a), b, elementMap.getClassNode(b));
514 }); 575 });
515 } 576 }
516 } 577 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/kernel/element_map.dart ('k') | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698