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

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: 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 copied = mergeLocals(conditionBranch, thenBranch, needsCopy: false);
3431 mergeLocals(conditionBranch, elseBranch, needsCopy: !copied);
3427 3432
3428 conditionGraph = 3433 conditionBranch.graph =
3429 new SubExpression(conditionStartBlock, builder.lastOpenedBlock); 3434 new SubExpression(conditionBranch.block, conditionExitBlock);
3430 conditionLocals = builder.localsHandler;
3431 return conditionGraph;
3432 } 3435 }
3433 3436
3434 SubGraph buildThen(void visitThen(), LocalsHandler locals) { 3437 /** Returns true if the locals have been copied. */
Lasse Reichstein Nielsen 2012/07/11 12:10:53 What does it mean to "have been copied"? Can we us
floitsch 2012/07/11 12:24:19 Did not change the return type, but inverted the a
3435 builder.localsHandler = locals; 3438 bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch, [needsCopy]) {
Lasse Reichstein Nielsen 2012/07/11 12:10:53 Type 'bool' on needsCopy.
floitsch 2012/07/11 12:24:19 Done.
3436 HBasicBlock thenBlock = builder.addNewBlock(); 3439 LocalsHandler fromLocals = fromBranch.exitLocals;
3437 conditionGraph.end.addSuccessor(thenBlock); 3440 if (toBranch.startLocals == null) {
3438 builder.open(thenBlock); 3441 if (needsCopy) {
3439 visitThen(); 3442 toBranch.startLocals = new LocalsHandler.from(fromLocals);
3440 if (branchesHaveValues) { 3443 return true;
3441 checkNotAborted(); 3444 } else {
3442 thenValue = builder.pop(); 3445 toBranch.startLocals = fromLocals;
3446 return false;
3447 }
3448 } else {
3449 toBranch.startLocals.mergeWith(fromLocals, toBranch.block);
3450 return true;
3443 } 3451 }
3444 thenGraph = new SubGraph(thenBlock, builder.lastOpenedBlock);
3445 thenLocals = builder.localsHandler;
3446 return thenGraph;
3447 } 3452 }
3448 3453
3449 SubGraph buildElse(void visitElse(), LocalsHandler locals) { 3454 void startBranch(SsaBranch branch) {
3450 builder.localsHandler = locals; 3455 builder.graph.addBlock(branch.block);
3451 HBasicBlock elseBlock = builder.addNewBlock(); 3456 builder.localsHandler = branch.startLocals;
3452 conditionGraph.end.addSuccessor(elseBlock); 3457 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 } 3458 }
3463 3459
3464 HBasicBlock join() { 3460 HInstruction buildBranch(SsaBranch branch,
3465 HBasicBlock joinBlock = null; 3461 void visitBranch(),
3466 HBasicBlock thenBlock = thenGraph.end; 3462 SsaBranch joinBranch,
3467 HBasicBlock elseBlock = elseGraph.end; 3463 bool isExpression) {
3468 // If the last instruction is already a control-flow instruction then the 3464 startBranch(branch);
3469 // block has been aborted. 3465 visitBranch();
3470 if (thenBlock.last is HControlFlow) thenBlock = null; 3466 branch.graph = new SubGraph(branch.block, builder.lastOpenedBlock);
3471 if (elseBlock.last is HControlFlow) elseBlock = null; 3467 branch.exitLocals = builder.localsHandler;
3472 3468 if (!builder.isAborted()) {
3473 if (thenBlock !== null || elseBlock !== null) { 3469 builder.goto(builder.current, joinBranch.block);
3474 joinBlock = builder.addNewBlock(); 3470 mergeLocals(branch, joinBranch, needsCopy: false);
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 } 3471 }
3500 return builder.current; 3472 if (isExpression) {
3473 checkNotAborted();
3474 return builder.pop();
3475 }
3476 return null;
3501 } 3477 }
3502 3478
3503 handleIf(void visitCondition(), void visitThen(), void visitElse()) { 3479 handleIf(void visitCondition(), void visitThen(), void visitElse()) {
3480 if (visitElse == null) {
3481 // Make sure to have an else part to avoid a critical edge. A
3482 // critical edge is an edge that connects a block with multiple
3483 // successors to a block with multiple predecessors. We avoid
3484 // such edges because they prevent inserting copies during code
3485 // generation of phi instructions.
3486 visitElse = () {};
3487 }
3488
3504 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); 3489 _handleDiamondBranch(visitCondition, visitThen, visitElse, false);
3505 } 3490 }
3506 3491
3507 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { 3492 handleConditional(void visitCondition(), void visitThen(), void visitElse()) {
3493 assert(visitElse != null);
3508 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); 3494 _handleDiamondBranch(visitCondition, visitThen, visitElse, true);
3509 } 3495 }
3510 3496
3511 void _handleDiamondBranch(void visitCondition(), 3497 void _handleDiamondBranch(void visitCondition(),
3512 void visitThen(), 3498 void visitThen(),
3513 void visitElse(), 3499 void visitElse(),
3514 bool isExpression) { 3500 bool isExpression) {
3515 branchesHaveValues = isExpression; 3501 SsaBranch conditionBranch = new SsaBranch(this);
3516 if (visitElse == null) { 3502 SsaBranch thenBranch = new SsaBranch(this);
3517 if (isExpression) { 3503 SsaBranch elseBranch = new SsaBranch(this);
3518 compiler.internalError("Diamond branch with values but without else.", 3504 SsaBranch joinBranch = new SsaBranch(this);
3519 node: diagnosticNode); 3505
3520 } 3506 conditionBranch.startLocals = builder.localsHandler;
3521 // Make sure to have an else part to avoid a critical edge. A 3507 builder.goto(builder.current, conditionBranch.block);
3522 // critical edge is an edge that connects a block with multiple 3508
3523 // successors to a block with multiple predecessors. We avoid 3509 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch);
3524 // such edges because they prevent inserting copies during code 3510 HInstruction thenValue =
3525 // generation of phi instructions. 3511 buildBranch(thenBranch, visitThen, joinBranch, isExpression);
3526 visitElse = () {}; 3512 HInstruction elseValue =
3513 buildBranch(elseBranch, visitElse, joinBranch, isExpression);
3514
3515 if (isExpression) {
3516 assert(thenValue != null && elseValue != null);
3517 HPhi phi =
3518 new HPhi.manyInputs(null, <HInstruction>[thenValue, elseValue]);
3519 joinBranch.block.addPhi(phi);
3520 builder.stack.add(phi);
3527 } 3521 }
3528 3522
3529 buildCondition(visitCondition); 3523 HBasicBlock thenBlock = thenBranch.block;
3530 buildThen(visitThen, new LocalsHandler.from(conditionLocals)); 3524 HBasicBlock elseBlock = elseBranch.block;
3531 // Use the locals state after the condition. We are the last ones to use the 3525 HBasicBlock joinBlock;
3532 // conditionLocals. So we don't need to make a copy of it. 3526 // If at least one branch did not abort, open the joinBranch.
3533 buildElse(visitElse, conditionLocals); 3527 if (!joinBranch.block.predecessors.isEmpty()) {
3534 HBasicBlock joinBlock = join(); 3528 startBranch(joinBranch);
3529 joinBlock = joinBranch.block;
3530 }
3535 3531
3536 HIfBlockInformation info = 3532 HIfBlockInformation info =
3537 new HIfBlockInformation( 3533 new HIfBlockInformation(
3538 new HSubExpressionBlockInformation(conditionGraph), 3534 new HSubExpressionBlockInformation(conditionBranch.graph),
3539 new HSubGraphBlockInformation(thenGraph), 3535 new HSubGraphBlockInformation(thenBranch.graph),
3540 new HSubGraphBlockInformation(elseGraph)); 3536 new HSubGraphBlockInformation(elseBranch.graph));
3541 3537
3542 HBasicBlock conditionStartBlock = conditionGraph.start; 3538 HBasicBlock conditionStartBlock = conditionBranch.block;
3543 conditionGraph.start.setBlockFlow(info, joinBlock); 3539 conditionStartBlock.setBlockFlow(info, joinBlock);
3540 SubGraph conditionGraph = conditionBranch.graph;
3544 HIf branch = conditionGraph.end.last; 3541 HIf branch = conditionGraph.end.last;
3545 assert(branch is HIf); 3542 assert(branch is HIf);
3546 branch.blockInformation = conditionStartBlock.blockFlow; 3543 branch.blockInformation = conditionStartBlock.blockFlow;
3547 } 3544 }
3548 } 3545 }
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