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

Side by Side Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10693143: Refactor SsaBranchBuilder. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 class Interceptors { 5 class Interceptors {
6 Compiler compiler; 6 Compiler compiler;
7 Interceptors(Compiler this.compiler); 7 Interceptors(Compiler this.compiler);
8 8
9 SourceString mapOperatorToMethodName(Operator op) { 9 SourceString mapOperatorToMethodName(Operator op) {
10 String name = op.source.stringValue; 10 String name = op.source.stringValue;
(...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 loopEntry.forEachPhi((HPhi phi) { 581 loopEntry.forEachPhi((HPhi phi) {
582 Element element = phi.sourceElement; 582 Element element = phi.sourceElement;
583 HInstruction postLoopDefinition = directLocals[element]; 583 HInstruction postLoopDefinition = directLocals[element];
584 phi.addInput(postLoopDefinition); 584 phi.addInput(postLoopDefinition);
585 }); 585 });
586 } 586 }
587 587
588 /** 588 /**
589 * Merge [otherLocals] into this locals handler, creating phi-nodes when 589 * Merge [otherLocals] into this locals handler, creating phi-nodes when
590 * there is a conflict. 590 * there is a conflict.
591 * If a phi node is necessary, it will use the otherLocals instruction as the 591 * If a phi node is necessary, it will use this handler's instruction as the
592 * first input, and this handler's instruction as the second. 592 * first input, and the otherLocals instruction as the second.
593 * NOTICE: This means that the predecessor corresponding to [otherLocals]
594 * should be the first predecessor of the current block, and the one
595 * corresponding to this locals handler should be the second.
596 */ 593 */
597 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) { 594 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) {
598 // If an element is in one map but not the other we can safely 595 // If an element is in one map but not the other we can safely
599 // ignore it. It means that a variable was declared in the 596 // ignore it. It means that a variable was declared in the
600 // block. Since variable declarations are scoped the declared 597 // block. Since variable declarations are scoped the declared
601 // variable cannot be alive outside the block. Note: this is only 598 // variable cannot be alive outside the block. Note: this is only
602 // true for nodes where we do joins. 599 // true for nodes where we do joins.
603 Map<Element, HInstruction> joinedLocals = new Map<Element, HInstruction>(); 600 Map<Element, HInstruction> joinedLocals = new Map<Element, HInstruction>();
604 otherLocals.directLocals.forEach((element, instruction) { 601 otherLocals.directLocals.forEach((element, instruction) {
605 // We know 'this' cannot be modified. 602 // We know 'this' cannot be modified.
606 if (element === closureData.thisElement) { 603 if (element === closureData.thisElement) {
607 assert(directLocals[element] == instruction); 604 assert(directLocals[element] == instruction);
608 joinedLocals[element] = instruction; 605 joinedLocals[element] = instruction;
609 } else { 606 } else {
610 HInstruction mine = directLocals[element]; 607 HInstruction mine = directLocals[element];
611 if (mine === null) return; 608 if (mine === null) return;
612 if (instruction === mine) { 609 if (instruction === mine) {
613 joinedLocals[element] = instruction; 610 joinedLocals[element] = instruction;
614 } else { 611 } else {
615 HInstruction phi = 612 HInstruction phi =
616 new HPhi.manyInputs(element, <HInstruction>[instruction, mine]); 613 new HPhi.manyInputs(element, <HInstruction>[mine, instruction]);
617 joinBlock.addPhi(phi); 614 joinBlock.addPhi(phi);
618 joinedLocals[element] = phi; 615 joinedLocals[element] = phi;
619 } 616 }
620 } 617 }
621 }); 618 });
622 directLocals = joinedLocals; 619 directLocals = joinedLocals;
623 } 620 }
624 621
625 /** 622 /**
626 * The current localsHandler is not used for its values, only for its 623 * The current localsHandler is not used for its values, only for its
(...skipping 2757 matching lines...) Expand 10 before | Expand all | Expand 10 after
3384 node.visitChildren(this); 3381 node.visitChildren(this);
3385 } 3382 }
3386 3383
3387 HInstruction concat(HInstruction left, HInstruction right) { 3384 HInstruction concat(HInstruction left, HInstruction right) {
3388 HInstruction instruction = new HStringConcat(left, right, diagnosticNode); 3385 HInstruction instruction = new HStringConcat(left, right, diagnosticNode);
3389 builder.add(instruction); 3386 builder.add(instruction);
3390 return instruction; 3387 return instruction;
3391 } 3388 }
3392 } 3389 }
3393 3390
3391 class SsaBranch {
3392 final SsaBranchBuilder branchBuilder;
3393 final HBasicBlock block;
3394 LocalsHandler startLocals;
3395 LocalsHandler exitLocals;
3396 SubGraph graph;
3397
3398 SsaBranch(this.branchBuilder) : block = new HBasicBlock();
3399 }
3400
3394 class SsaBranchBuilder { 3401 class SsaBranchBuilder {
3395 final SsaBuilder builder; 3402 final SsaBuilder builder;
3396 final Node diagnosticNode; 3403 final Node diagnosticNode;
3397 3404
3398 bool branchesHaveValues;
3399 HInstruction thenValue;
3400 HInstruction elseValue;
3401 // The locals-handler at the end of the condition block.
3402 LocalsHandler conditionLocals;
3403 LocalsHandler thenLocals;
3404 LocalsHandler elseLocals;
3405 SubGraph conditionGraph;
3406 SubGraph thenGraph;
3407 SubGraph elseGraph;
3408
3409 SsaBranchBuilder(this.builder, [this.diagnosticNode]); 3405 SsaBranchBuilder(this.builder, [this.diagnosticNode]);
3410 3406
3411 Compiler get compiler() => builder.compiler; 3407 Compiler get compiler() => builder.compiler;
3412 3408
3413 void checkNotAborted() { 3409 void checkNotAborted() {
3414 if (builder.isAborted()) { 3410 if (builder.isAborted()) {
3415 compiler.unimplemented("aborted control flow", node: diagnosticNode); 3411 compiler.unimplemented("aborted control flow", node: diagnosticNode);
3416 } 3412 }
3417 } 3413 }
3418 3414
3419 SubGraph buildCondition(void doCondition()) { 3415 void buildCondition(void visitCondition(),
3420 HBasicBlock conditionStartBlock = builder.openNewBlock(); 3416 SsaBranch conditionBranch,
3421 doCondition(); 3417 SsaBranch thenBranch,
3418 SsaBranch elseBranch) {
3419 startBranch(conditionBranch);
3420 visitCondition();
3422 checkNotAborted(); 3421 checkNotAborted();
3423 assert(builder.current === builder.lastOpenedBlock); 3422 assert(builder.current === builder.lastOpenedBlock);
3424 HInstruction condition = builder.popBoolified(); 3423 HInstruction conditionValue = builder.popBoolified();
3425 HIf branch = new HIf(condition); 3424 HIf branch = new HIf(conditionValue);
3425 HBasicBlock conditionExitBlock = builder.current;
3426 builder.close(branch); 3426 builder.close(branch);
3427 conditionBranch.exitLocals = builder.localsHandler;
3428 conditionExitBlock.addSuccessor(thenBranch.block);
3429 conditionExitBlock.addSuccessor(elseBranch.block);
3430 bool conditionBranchLocalsCanBeReused =
3431 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true);
3432 mergeLocals(conditionBranch, elseBranch,
3433 mayReuseFromLocals: conditionBranchLocalsCanBeReused);
3427 3434
3428 conditionGraph = 3435 conditionBranch.graph =
3429 new SubExpression(conditionStartBlock, builder.lastOpenedBlock); 3436 new SubExpression(conditionBranch.block, conditionExitBlock);
3430 conditionLocals = builder.localsHandler;
3431 return conditionGraph;
3432 } 3437 }
3433 3438
3434 SubGraph buildThen(void visitThen(), LocalsHandler locals) { 3439 /**
3435 builder.localsHandler = locals; 3440 * Returns true if the locals of the [fromBranch] may be reused. A [:true:]
3436 HBasicBlock thenBlock = builder.addNewBlock(); 3441 * return value implies that [mayReuseFromLocals] was set to [:true:].
3437 conditionGraph.end.addSuccessor(thenBlock); 3442 */
3438 builder.open(thenBlock); 3443 bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch,
3439 visitThen(); 3444 [bool mayReuseFromLocals]) {
3440 if (branchesHaveValues) { 3445 LocalsHandler fromLocals = fromBranch.exitLocals;
3441 checkNotAborted(); 3446 if (toBranch.startLocals == null) {
3442 thenValue = builder.pop(); 3447 if (mayReuseFromLocals) {
3448 toBranch.startLocals = fromLocals;
3449 return false;
3450 } else {
3451 toBranch.startLocals = new LocalsHandler.from(fromLocals);
3452 return true;
3453 }
3454 } else {
3455 toBranch.startLocals.mergeWith(fromLocals, toBranch.block);
3456 return true;
3443 } 3457 }
3444 thenGraph = new SubGraph(thenBlock, builder.lastOpenedBlock);
3445 thenLocals = builder.localsHandler;
3446 return thenGraph;
3447 } 3458 }
3448 3459
3449 SubGraph buildElse(void visitElse(), LocalsHandler locals) { 3460 void startBranch(SsaBranch branch) {
3450 builder.localsHandler = locals; 3461 builder.graph.addBlock(branch.block);
3451 HBasicBlock elseBlock = builder.addNewBlock(); 3462 builder.localsHandler = branch.startLocals;
3452 conditionGraph.end.addSuccessor(elseBlock); 3463 builder.open(branch.block);
3453 builder.open(elseBlock);
3454 visitElse();
3455 if (branchesHaveValues) {
3456 checkNotAborted();
3457 elseValue = builder.pop();
3458 }
3459 elseGraph = new SubGraph(elseBlock, builder.lastOpenedBlock);
3460 elseLocals = builder.localsHandler;
3461 return elseGraph;
3462 } 3464 }
3463 3465
3464 HBasicBlock join() { 3466 HInstruction buildBranch(SsaBranch branch,
3465 HBasicBlock joinBlock = null; 3467 void visitBranch(),
3466 HBasicBlock thenBlock = thenGraph.end; 3468 SsaBranch joinBranch,
3467 HBasicBlock elseBlock = elseGraph.end; 3469 bool isExpression) {
3468 // If the last instruction is already a control-flow instruction then the 3470 startBranch(branch);
3469 // block has been aborted. 3471 visitBranch();
3470 if (thenBlock.last is HControlFlow) thenBlock = null; 3472 branch.graph = new SubGraph(branch.block, builder.lastOpenedBlock);
3471 if (elseBlock.last is HControlFlow) elseBlock = null; 3473 branch.exitLocals = builder.localsHandler;
3472 3474 if (!builder.isAborted()) {
3473 if (thenBlock !== null || elseBlock !== null) { 3475 builder.goto(builder.current, joinBranch.block);
3474 joinBlock = builder.addNewBlock(); 3476 mergeLocals(branch, joinBranch, mayReuseFromLocals: true);
3475 if (thenBlock !== null) builder.goto(thenBlock, joinBlock);
3476 if (elseBlock !== null) builder.goto(elseBlock, joinBlock);
3477 // If the join block has two predecessors we have to merge the
3478 // locals. The current locals is what either the
3479 // condition or the else block left us with, so we merge that
3480 // with the set of locals we got after visiting the then
3481 // part of the if.
3482 builder.open(joinBlock);
3483 if (joinBlock.predecessors.length == 2) {
3484 builder.localsHandler.mergeWith(thenLocals, joinBlock);
3485 if (branchesHaveValues) {
3486 assert(thenValue !== null);
3487 assert(elseValue !== null);
3488 HPhi phi = new HPhi.manyInputs(null,
3489 <HInstruction>[thenValue, elseValue]);
3490 joinBlock.addPhi(phi);
3491 builder.stack.add(phi);
3492 }
3493 } else if (thenBlock !== null) {
3494 // The only predecessor is the then branch.
3495 builder.localsHandler = thenLocals;
3496 } else {
3497 assert(builder.localsHandler == elseLocals);
3498 }
3499 } 3477 }
3500 return builder.current; 3478 if (isExpression) {
3479 checkNotAborted();
3480 return builder.pop();
3481 }
3482 return null;
3501 } 3483 }
3502 3484
3503 handleIf(void visitCondition(), void visitThen(), void visitElse()) { 3485 handleIf(void visitCondition(), void visitThen(), void visitElse()) {
3486 if (visitElse == null) {
3487 // Make sure to have an else part to avoid a critical edge. A
3488 // critical edge is an edge that connects a block with multiple
3489 // successors to a block with multiple predecessors. We avoid
3490 // such edges because they prevent inserting copies during code
3491 // generation of phi instructions.
3492 visitElse = () {};
3493 }
3494
3504 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); 3495 _handleDiamondBranch(visitCondition, visitThen, visitElse, false);
3505 } 3496 }
3506 3497
3507 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { 3498 handleConditional(void visitCondition(), void visitThen(), void visitElse()) {
3499 assert(visitElse != null);
3508 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); 3500 _handleDiamondBranch(visitCondition, visitThen, visitElse, true);
3509 } 3501 }
3510 3502
3511 void _handleDiamondBranch(void visitCondition(), 3503 void _handleDiamondBranch(void visitCondition(),
3512 void visitThen(), 3504 void visitThen(),
3513 void visitElse(), 3505 void visitElse(),
3514 bool isExpression) { 3506 bool isExpression) {
3515 branchesHaveValues = isExpression; 3507 SsaBranch conditionBranch = new SsaBranch(this);
3516 if (visitElse == null) { 3508 SsaBranch thenBranch = new SsaBranch(this);
3517 if (isExpression) { 3509 SsaBranch elseBranch = new SsaBranch(this);
3518 compiler.internalError("Diamond branch with values but without else.", 3510 SsaBranch joinBranch = new SsaBranch(this);
3519 node: diagnosticNode); 3511
3520 } 3512 conditionBranch.startLocals = builder.localsHandler;
3521 // Make sure to have an else part to avoid a critical edge. A 3513 builder.goto(builder.current, conditionBranch.block);
3522 // critical edge is an edge that connects a block with multiple 3514
3523 // successors to a block with multiple predecessors. We avoid 3515 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch);
3524 // such edges because they prevent inserting copies during code 3516 HInstruction thenValue =
3525 // generation of phi instructions. 3517 buildBranch(thenBranch, visitThen, joinBranch, isExpression);
3526 visitElse = () {}; 3518 HInstruction elseValue =
3519 buildBranch(elseBranch, visitElse, joinBranch, isExpression);
3520
3521 if (isExpression) {
3522 assert(thenValue != null && elseValue != null);
3523 HPhi phi =
3524 new HPhi.manyInputs(null, <HInstruction>[thenValue, elseValue]);
3525 joinBranch.block.addPhi(phi);
3526 builder.stack.add(phi);
3527 } 3527 }
3528 3528
3529 buildCondition(visitCondition); 3529 HBasicBlock thenBlock = thenBranch.block;
3530 buildThen(visitThen, new LocalsHandler.from(conditionLocals)); 3530 HBasicBlock elseBlock = elseBranch.block;
3531 // Use the locals state after the condition. We are the last ones to use the 3531 HBasicBlock joinBlock;
3532 // conditionLocals. So we don't need to make a copy of it. 3532 // If at least one branch did not abort, open the joinBranch.
3533 buildElse(visitElse, conditionLocals); 3533 if (!joinBranch.block.predecessors.isEmpty()) {
3534 HBasicBlock joinBlock = join(); 3534 startBranch(joinBranch);
3535 joinBlock = joinBranch.block;
3536 }
3535 3537
3536 HIfBlockInformation info = 3538 HIfBlockInformation info =
3537 new HIfBlockInformation( 3539 new HIfBlockInformation(
3538 new HSubExpressionBlockInformation(conditionGraph), 3540 new HSubExpressionBlockInformation(conditionBranch.graph),
3539 new HSubGraphBlockInformation(thenGraph), 3541 new HSubGraphBlockInformation(thenBranch.graph),
3540 new HSubGraphBlockInformation(elseGraph)); 3542 new HSubGraphBlockInformation(elseBranch.graph));
3541 3543
3542 HBasicBlock conditionStartBlock = conditionGraph.start; 3544 HBasicBlock conditionStartBlock = conditionBranch.block;
3543 conditionGraph.start.setBlockFlow(info, joinBlock); 3545 conditionStartBlock.setBlockFlow(info, joinBlock);
3546 SubGraph conditionGraph = conditionBranch.graph;
3544 HIf branch = conditionGraph.end.last; 3547 HIf branch = conditionGraph.end.last;
3545 assert(branch is HIf); 3548 assert(branch is HIf);
3546 branch.blockInformation = conditionStartBlock.blockFlow; 3549 branch.blockInformation = conditionStartBlock.blockFlow;
3547 } 3550 }
3548 } 3551 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698