Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |