| 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 |