OLD | NEW |
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 import 'dart:collection'; | 5 import 'dart:collection'; |
6 | 6 |
7 import 'package:js_runtime/shared/embedded_names.dart'; | 7 import 'package:js_runtime/shared/embedded_names.dart'; |
8 | 8 |
9 import '../closure.dart'; | 9 import '../closure.dart'; |
10 import '../common.dart'; | 10 import '../common.dart'; |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 value, sourceInformationBuilder.buildReturn(functionElement.node))); | 670 value, sourceInformationBuilder.buildReturn(functionElement.node))); |
671 return closeFunction(); | 671 return closeFunction(); |
672 } | 672 } |
673 assert(invariant(functionElement, !function.modifiers.isExternal)); | 673 assert(invariant(functionElement, !function.modifiers.isExternal)); |
674 | 674 |
675 // If [functionElement] is `operator==` we explicitly add a null check at | 675 // If [functionElement] is `operator==` we explicitly add a null check at |
676 // the beginning of the method. This is to avoid having call sites do the | 676 // the beginning of the method. This is to avoid having call sites do the |
677 // null check. | 677 // null check. |
678 if (name == '==') { | 678 if (name == '==') { |
679 if (!backend.operatorEqHandlesNullArgument(functionElement)) { | 679 if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
680 handleIf(function, visitCondition: () { | 680 handleIf( |
681 HParameterValue parameter = parameters.values.first; | 681 node: function, |
682 push(new HIdentity(parameter, graph.addConstantNull(compiler), null, | 682 visitCondition: () { |
683 backend.boolType)); | 683 HParameterValue parameter = parameters.values.first; |
684 }, visitThen: () { | 684 push(new HIdentity(parameter, graph.addConstantNull(compiler), |
685 closeAndGotoExit(new HReturn(graph.addConstantBool(false, compiler), | 685 null, backend.boolType)); |
686 sourceInformationBuilder.buildImplicitReturn(functionElement))); | 686 }, |
687 }, | 687 visitThen: () { |
| 688 closeAndGotoExit(new HReturn( |
| 689 graph.addConstantBool(false, compiler), |
| 690 sourceInformationBuilder |
| 691 .buildImplicitReturn(functionElement))); |
| 692 }, |
688 visitElse: null, | 693 visitElse: null, |
689 sourceInformation: sourceInformationBuilder.buildIf(function.body)); | 694 sourceInformation: sourceInformationBuilder.buildIf(function.body)); |
690 } | 695 } |
691 } | 696 } |
692 if (const bool.fromEnvironment('unreachable-throw')) { | 697 if (const bool.fromEnvironment('unreachable-throw')) { |
693 var emptyParameters = | 698 var emptyParameters = |
694 parameters.values.where((p) => p.instructionType.isEmpty); | 699 parameters.values.where((p) => p.instructionType.isEmpty); |
695 if (emptyParameters.length > 0) { | 700 if (emptyParameters.length > 0) { |
696 addComment('${emptyParameters} inferred as [empty]'); | 701 addComment('${emptyParameters} inferred as [empty]'); |
697 pushInvokeStatic(function.body, helpers.assertUnreachableMethod, []); | 702 pushInvokeStatic(function.body, helpers.assertUnreachableMethod, []); |
(...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1652 visit(node.condition); | 1657 visit(node.condition); |
1653 pushInvokeStatic(node, helpers.assertTest, [pop()]); | 1658 pushInvokeStatic(node, helpers.assertTest, [pop()]); |
1654 } | 1659 } |
1655 | 1660 |
1656 void fail() { | 1661 void fail() { |
1657 visit(node.message); | 1662 visit(node.message); |
1658 pushInvokeStatic(node, helpers.assertThrow, [pop()]); | 1663 pushInvokeStatic(node, helpers.assertThrow, [pop()]); |
1659 pop(); | 1664 pop(); |
1660 } | 1665 } |
1661 | 1666 |
1662 handleIf(node, visitCondition: buildCondition, visitThen: fail); | 1667 handleIf(node: node, visitCondition: buildCondition, visitThen: fail); |
1663 } | 1668 } |
1664 | 1669 |
1665 visitBlock(ast.Block node) { | 1670 visitBlock(ast.Block node) { |
1666 assert(!isAborted()); | 1671 assert(!isAborted()); |
1667 if (!isReachable) return; // This can only happen when inlining. | 1672 if (!isReachable) return; // This can only happen when inlining. |
1668 for (Link<ast.Node> link = node.statements.nodes; | 1673 for (Link<ast.Node> link = node.statements.nodes; |
1669 !link.isEmpty; | 1674 !link.isEmpty; |
1670 link = link.tail) { | 1675 link = link.tail) { |
1671 visit(link.head); | 1676 visit(link.head); |
1672 if (!isReachable) { | 1677 if (!isReachable) { |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1947 if (node.isThis()) { | 1952 if (node.isThis()) { |
1948 visitThisGet(node); | 1953 visitThisGet(node); |
1949 } else { | 1954 } else { |
1950 reporter.internalError( | 1955 reporter.internalError( |
1951 node, "SsaFromAstMixin.visitIdentifier on non-this."); | 1956 node, "SsaFromAstMixin.visitIdentifier on non-this."); |
1952 } | 1957 } |
1953 } | 1958 } |
1954 | 1959 |
1955 visitIf(ast.If node) { | 1960 visitIf(ast.If node) { |
1956 assert(isReachable); | 1961 assert(isReachable); |
1957 handleIf(node, | 1962 handleIf( |
| 1963 node: node, |
1958 visitCondition: () => visit(node.condition), | 1964 visitCondition: () => visit(node.condition), |
1959 visitThen: () => visit(node.thenPart), | 1965 visitThen: () => visit(node.thenPart), |
1960 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null, | 1966 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null, |
1961 sourceInformation: sourceInformationBuilder.buildIf(node)); | 1967 sourceInformation: sourceInformationBuilder.buildIf(node)); |
1962 } | 1968 } |
1963 | 1969 |
1964 void handleIf(ast.Node diagnosticNode, | |
1965 {void visitCondition(), | |
1966 void visitThen(), | |
1967 void visitElse(), | |
1968 SourceInformation sourceInformation}) { | |
1969 SsaBranchBuilder branchBuilder = | |
1970 new SsaBranchBuilder(this, compiler, diagnosticNode); | |
1971 branchBuilder.handleIf(visitCondition, visitThen, visitElse, | |
1972 sourceInformation: sourceInformation); | |
1973 } | |
1974 | |
1975 @override | 1970 @override |
1976 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { | 1971 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { |
1977 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 1972 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); |
1978 brancher.handleIfNull(() => visit(left), () => visit(right)); | 1973 brancher.handleIfNull(() => visit(left), () => visit(right)); |
1979 } | 1974 } |
1980 | 1975 |
1981 /// Optimizes logical binary where the left is also a logical binary. | 1976 /// Optimizes logical binary where the left is also a logical binary. |
1982 /// | 1977 /// |
1983 /// This method transforms the operator by optimizing the case where [left] is | 1978 /// This method transforms the operator by optimizing the case where [left] is |
1984 /// a logical "and" or logical "or". Then it uses [branchBuilder] to build the | 1979 /// a logical "and" or logical "or". Then it uses [branchBuilder] to build the |
(...skipping 4168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6153 } else { | 6148 } else { |
6154 // If the switch statement has no default case, surround the loop with | 6149 // If the switch statement has no default case, surround the loop with |
6155 // a test of the target. | 6150 // a test of the target. |
6156 void buildCondition() { | 6151 void buildCondition() { |
6157 js.Template code = js.js.parseForeignJS('#'); | 6152 js.Template code = js.js.parseForeignJS('#'); |
6158 push(new HForeignCode( | 6153 push(new HForeignCode( |
6159 code, backend.boolType, [localsHandler.readLocal(switchTarget)], | 6154 code, backend.boolType, [localsHandler.readLocal(switchTarget)], |
6160 nativeBehavior: native.NativeBehavior.PURE)); | 6155 nativeBehavior: native.NativeBehavior.PURE)); |
6161 } | 6156 } |
6162 | 6157 |
6163 handleIf(node, | 6158 handleIf( |
| 6159 node: node, |
6164 visitCondition: buildCondition, | 6160 visitCondition: buildCondition, |
6165 visitThen: buildLoop, | 6161 visitThen: buildLoop, |
6166 visitElse: () => {}); | 6162 visitElse: () => {}); |
6167 } | 6163 } |
6168 } | 6164 } |
6169 | 6165 |
6170 /** | 6166 /** |
6171 * Creates a switch statement. | 6167 * Creates a switch statement. |
6172 * | 6168 * |
6173 * [jumpHandler] is the [JumpHandler] for the created switch statement. | 6169 * [jumpHandler] is the [JumpHandler] for the created switch statement. |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6495 } | 6491 } |
6496 visit(catchBlock); | 6492 visit(catchBlock); |
6497 } | 6493 } |
6498 | 6494 |
6499 void visitElse() { | 6495 void visitElse() { |
6500 if (link.isEmpty) { | 6496 if (link.isEmpty) { |
6501 closeAndGotoExit(new HThrow(exception, exception.sourceInformation, | 6497 closeAndGotoExit(new HThrow(exception, exception.sourceInformation, |
6502 isRethrow: true)); | 6498 isRethrow: true)); |
6503 } else { | 6499 } else { |
6504 ast.CatchBlock newBlock = link.head; | 6500 ast.CatchBlock newBlock = link.head; |
6505 handleIf(node, visitCondition: () { | 6501 handleIf( |
6506 pushCondition(newBlock); | 6502 node: node, |
6507 }, visitThen: visitThen, visitElse: visitElse); | 6503 visitCondition: () { |
| 6504 pushCondition(newBlock); |
| 6505 }, |
| 6506 visitThen: visitThen, |
| 6507 visitElse: visitElse); |
6508 } | 6508 } |
6509 } | 6509 } |
6510 | 6510 |
6511 ast.CatchBlock firstBlock = link.head; | 6511 ast.CatchBlock firstBlock = link.head; |
6512 handleIf(node, visitCondition: () { | 6512 handleIf( |
6513 pushCondition(firstBlock); | 6513 node: node, |
6514 }, visitThen: visitThen, visitElse: visitElse); | 6514 visitCondition: () { |
| 6515 pushCondition(firstBlock); |
| 6516 }, |
| 6517 visitThen: visitThen, |
| 6518 visitElse: visitElse); |
6515 if (!isAborted()) endCatchBlock = close(new HGoto()); | 6519 if (!isAborted()) endCatchBlock = close(new HGoto()); |
6516 | 6520 |
6517 rethrowableException = oldRethrowableException; | 6521 rethrowableException = oldRethrowableException; |
6518 tryInstruction.catchBlock = startCatchBlock; | 6522 tryInstruction.catchBlock = startCatchBlock; |
6519 catchGraph = new SubGraph(startCatchBlock, lastOpenedBlock); | 6523 catchGraph = new SubGraph(startCatchBlock, lastOpenedBlock); |
6520 } | 6524 } |
6521 | 6525 |
6522 SubGraph finallyGraph = null; | 6526 SubGraph finallyGraph = null; |
6523 if (node.finallyBlock != null) { | 6527 if (node.finallyBlock != null) { |
6524 localsHandler = new LocalsHandler.from(savedLocals); | 6528 localsHandler = new LocalsHandler.from(savedLocals); |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7040 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 7044 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
7041 unaliased.accept(this, builder); | 7045 unaliased.accept(this, builder); |
7042 } | 7046 } |
7043 | 7047 |
7044 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 7048 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
7045 JavaScriptBackend backend = builder.compiler.backend; | 7049 JavaScriptBackend backend = builder.compiler.backend; |
7046 ClassElement cls = backend.helpers.DynamicRuntimeType; | 7050 ClassElement cls = backend.helpers.DynamicRuntimeType; |
7047 builder.push(new HDynamicType(type, new TypeMask.exact(cls, closedWorld))); | 7051 builder.push(new HDynamicType(type, new TypeMask.exact(cls, closedWorld))); |
7048 } | 7052 } |
7049 } | 7053 } |
OLD | NEW |