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

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

Issue 2954663002: Handle break as continue (Closed)
Patch Set: Add comments Created 3 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
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 JumpTarget target = _jumpTargetMap[node];
349 assert(target != null, failedAt(currentMember, 'No target for $node.')); 356 //assert(target != null, failedAt(currentMember, 'No target for $node.'));
Siggi Cherem (dart-lang) 2017/06/23 21:03:59 delete altogether then?
Johnni Winther 2017/06/26 11:27:56 Done.
350 return target; 357 return target;
351 } 358 }
352 359
353 @override 360 @override
354 JumpTarget getJumpTargetForSwitch(ir.SwitchStatement node) { 361 JumpTarget getJumpTargetForSwitch(ir.SwitchStatement node) {
355 _ensureJumpMap(node); 362 _ensureJumpMap(node);
356 throw new UnimplementedError( 363 throw new UnimplementedError(
357 'KernelToLocalsMapImpl.getJumpTargetForSwitch'); 364 'KernelToLocalsMapImpl.getJumpTargetForSwitch');
358 } 365 }
359 366
360 @override 367 @override
361 JumpTarget getJumpTargetForFor(ir.ForStatement node) { 368 JumpTarget getJumpTargetForFor(ir.ForStatement node) {
362 _ensureJumpMap(node); 369 _ensureJumpMap(node);
363 return _jumpTargetMap[node.parent]; 370 return _jumpTargetMap[node];
Siggi Cherem (dart-lang) 2017/06/23 21:03:59 remove .parent also in Do, ForIn, While?
Johnni Winther 2017/06/26 11:27:56 Will do when JumpVisitor recognizes these as break
364 } 371 }
365 372
366 @override 373 @override
367 JumpTarget getJumpTargetForForIn(ir.ForInStatement node) { 374 JumpTarget getJumpTargetForForIn(ir.ForInStatement node) {
368 _ensureJumpMap(node); 375 _ensureJumpMap(node);
369 return _jumpTargetMap[node.parent]; 376 return _jumpTargetMap[node.parent];
370 } 377 }
371 378
372 @override 379 @override
373 JumpTarget getJumpTargetForWhile(ir.WhileStatement node) { 380 JumpTarget getJumpTargetForWhile(ir.WhileStatement node) {
374 _ensureJumpMap(node); 381 _ensureJumpMap(node);
375 return _jumpTargetMap[node.parent]; 382 return _jumpTargetMap[node.parent];
376 } 383 }
377 384
378 @override 385 @override
379 Local getLocal(ir.VariableDeclaration node) { 386 Local getLocal(ir.VariableDeclaration node) {
380 return _map.putIfAbsent(node, () { 387 return _map.putIfAbsent(node, () {
381 return new KLocal(node.name, currentMember); 388 return new KLocal(node.name, currentMember);
382 }); 389 });
383 } 390 }
384 391
385 @override 392 @override
386 LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop( 393 LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop(
387 ClosureDataLookup closureLookup, ir.TreeNode node) { 394 ClosureDataLookup closureLookup, ir.TreeNode node) {
388 return closureLookup.getClosureRepresentationInfoForLoop(node); 395 return closureLookup.getClosureRepresentationInfoForLoop(node);
389 } 396 }
390 } 397 }
391 398
392 class JumpVisitor extends ir.Visitor { 399 class JumpVisitor extends ir.Visitor {
400 int index = 0;
393 final MemberEntity member; 401 final MemberEntity member;
394 final Map<ir.LabeledStatement, KJumpTarget> jumpTargetMap = 402 final Map<ir.TreeNode, KJumpTarget> jumpTargetMap =
395 <ir.LabeledStatement, KJumpTarget>{}; 403 <ir.TreeNode, KJumpTarget>{};
404 final Set<ir.BreakStatement> breaksAsContinue = new Set<ir.BreakStatement>();
396 405
397 JumpVisitor(this.member); 406 JumpVisitor(this.member);
398 407
399 KJumpTarget _getJumpTarget(ir.LabeledStatement node) { 408 KJumpTarget _getJumpTarget(ir.TreeNode node) {
400 return jumpTargetMap.putIfAbsent(node, () { 409 return jumpTargetMap.putIfAbsent(node, () {
401 return new KJumpTarget(member, jumpTargetMap.length); 410 return new KJumpTarget(member, index++);
402 }); 411 });
403 } 412 }
404 413
405 @override 414 @override
406 defaultNode(ir.Node node) => node.visitChildren(this); 415 defaultNode(ir.Node node) => node.visitChildren(this);
407 416
417 bool _canBeBreakTarget(ir.TreeNode node) {
418 // TODO(johnniwinther): Add more.
419 return node is ir.ForStatement;
420 }
421
422 bool _canBeContinueTarget(ir.TreeNode node) {
423 // TODO(johnniwinther): Add more.
424 return node is ir.ForStatement;
425 }
426
408 @override 427 @override
409 visitBreakStatement(ir.BreakStatement node) { 428 visitBreakStatement(ir.BreakStatement node) {
410 KJumpTarget target = _getJumpTarget(node.target); 429 // TODO(johnniwinther): Add labels if the enclosing loop is not the implicit
411 target.isBreakTarget = true; 430 // break target.
431 KJumpTarget target;
432 ir.TreeNode body = node.target.body;
433 ir.TreeNode parent = node.target.parent;
434 if (_canBeBreakTarget(body)) {
435 // We have code like
436 //
437 // l1: for (int i = 0; i < 10; i++) {
438 // break l1:
439 // }
440 //
441 // and can therefore use the for loop as the break target.
442 target = _getJumpTarget(body);
443 target.isBreakTarget = true;
444 } else if (_canBeContinueTarget(parent)) {
445 // We have code like
446 //
447 // for (int i = 0; i < 10; i++) l1: {
448 // break l1:
449 // }
450 //
451 // and can therefore use the for loop as a continue target.
452 target = _getJumpTarget(parent);
453 target.isContinueTarget = true;
454 breaksAsContinue.add(node);
455 } else {
456 target = _getJumpTarget(node.target);
457 target.isBreakTarget = true;
458 }
459 jumpTargetMap[node] = target;
412 super.visitBreakStatement(node); 460 super.visitBreakStatement(node);
413 } 461 }
414 } 462 }
415 463
416 class KJumpTarget extends JumpTarget<ir.Node> { 464 class KJumpTarget extends JumpTarget<ir.Node> {
417 final MemberEntity memberContext; 465 final MemberEntity memberContext;
418 final int nestingLevel; 466 final int nestingLevel;
419 467
420 KJumpTarget(this.memberContext, this.nestingLevel); 468 KJumpTarget(this.memberContext, this.nestingLevel);
421 469
(...skipping 12 matching lines...) Expand all
434 482
435 @override 483 @override
436 List<LabelDefinition<ir.Node>> get labels { 484 List<LabelDefinition<ir.Node>> get labels {
437 return const <LabelDefinition<ir.Node>>[]; 485 return const <LabelDefinition<ir.Node>>[];
438 } 486 }
439 487
440 @override 488 @override
441 ir.Node get statement { 489 ir.Node get statement {
442 throw new UnimplementedError('KJumpTarget.statement'); 490 throw new UnimplementedError('KJumpTarget.statement');
443 } 491 }
492
493 String toString() {
494 StringBuffer sb = new StringBuffer();
495 sb.write('KJumpTarget[');
496 sb.write('memberContext=');
497 sb.write(memberContext);
498 sb.write(',nestingLevel=');
499 sb.write(nestingLevel);
500 sb.write(',isBreakTarget=');
501 sb.write(isBreakTarget);
502 sb.write(',isContinueTarget=');
503 sb.write(isContinueTarget);
504 sb.write(']');
505 return sb.toString();
506 }
444 } 507 }
445 508
446 class KLocal implements Local { 509 class KLocal implements Local {
447 final String name; 510 final String name;
448 final MemberEntity memberContext; 511 final MemberEntity memberContext;
449 512
450 KLocal(this.name, this.memberContext); 513 KLocal(this.name, this.memberContext);
451 514
452 @override 515 @override
453 Entity get executableContext => memberContext; 516 Entity get executableContext => memberContext;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 Iterable<ClassEntity> sortClasses(Iterable<ClassEntity> classes) { 570 Iterable<ClassEntity> sortClasses(Iterable<ClassEntity> classes) {
508 return classes.toList() 571 return classes.toList()
509 ..sort((ClassEntity a, ClassEntity b) { 572 ..sort((ClassEntity a, ClassEntity b) {
510 int r = _compareLibraries(a.library, b.library); 573 int r = _compareLibraries(a.library, b.library);
511 if (r != 0) return r; 574 if (r != 0) return r;
512 return _compareNodes( 575 return _compareNodes(
513 a, elementMap.getClassNode(a), b, elementMap.getClassNode(b)); 576 a, elementMap.getClassNode(a), b, elementMap.getClassNode(b));
514 }); 577 });
515 } 578 }
516 } 579 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698