OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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.ir_builder; | 5 library dart2js.ir_builder; |
6 | 6 |
7 import '../compile_time_constants.dart' show BackendConstantEnvironment; | 7 import '../compile_time_constants.dart' show BackendConstantEnvironment; |
8 import '../constants/constant_system.dart'; | 8 import '../constants/constant_system.dart'; |
9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
10 import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue; | 10 import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue; |
(...skipping 1627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1638 SwitchCaseInfo defaultCase, | 1638 SwitchCaseInfo defaultCase, |
1639 Element error, | 1639 Element error, |
1640 SourceInformation sourceInformation) { | 1640 SourceInformation sourceInformation) { |
1641 assert(isOpen); | 1641 assert(isOpen); |
1642 JumpCollector join = new ForwardJumpCollector(environment, target: target); | 1642 JumpCollector join = new ForwardJumpCollector(environment, target: target); |
1643 | 1643 |
1644 IrBuilder casesBuilder = makeDelimitedBuilder(); | 1644 IrBuilder casesBuilder = makeDelimitedBuilder(); |
1645 casesBuilder.state.breakCollectors.add(join); | 1645 casesBuilder.state.breakCollectors.add(join); |
1646 for (SwitchCaseInfo caseInfo in cases) { | 1646 for (SwitchCaseInfo caseInfo in cases) { |
1647 buildConditionsFrom(int index) => (IrBuilder builder) { | 1647 buildConditionsFrom(int index) => (IrBuilder builder) { |
1648 ir.Primitive comparison = builder.addPrimitive( | 1648 ir.Primitive comparison = builder.buildIdentical( |
1649 new ir.Identical(value, caseInfo.constants[index])); | 1649 value, caseInfo.constants[index]); |
1650 return (index == caseInfo.constants.length - 1) | 1650 return (index == caseInfo.constants.length - 1) |
1651 ? comparison | 1651 ? comparison |
1652 : builder.buildLogicalOperator( | 1652 : builder.buildLogicalOperator( |
1653 comparison, buildConditionsFrom(index + 1), isLazyOr: true); | 1653 comparison, buildConditionsFrom(index + 1), isLazyOr: true); |
1654 }; | 1654 }; |
1655 | 1655 |
1656 ir.Primitive condition = buildConditionsFrom(0)(casesBuilder); | 1656 ir.Primitive condition = buildConditionsFrom(0)(casesBuilder); |
1657 IrBuilder thenBuilder = makeDelimitedBuilder(); | 1657 IrBuilder thenBuilder = makeDelimitedBuilder(); |
1658 caseInfo.buildBody(thenBuilder); | 1658 caseInfo.buildBody(thenBuilder); |
1659 if (thenBuilder.isOpen) { | 1659 if (thenBuilder.isOpen) { |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2084 leftFalseContinuation], | 2084 leftFalseContinuation], |
2085 new ir.Branch(new ir.IsTrue(leftValue), | 2085 new ir.Branch(new ir.IsTrue(leftValue), |
2086 leftTrueContinuation, | 2086 leftTrueContinuation, |
2087 leftFalseContinuation)))); | 2087 leftFalseContinuation)))); |
2088 environment = join.environment; | 2088 environment = join.environment; |
2089 environment.discard(1); | 2089 environment.discard(1); |
2090 // There is always a join parameter for the result value, because it | 2090 // There is always a join parameter for the result value, because it |
2091 // is different on at least two paths. | 2091 // is different on at least two paths. |
2092 return join.continuation.parameters.last; | 2092 return join.continuation.parameters.last; |
2093 } | 2093 } |
| 2094 |
| 2095 ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y) { |
| 2096 return addPrimitive(new ir.ApplyBuiltinOperator( |
| 2097 ir.BuiltinOperator.Identical, <ir.Primitive>[x, y])); |
| 2098 } |
2094 } | 2099 } |
2095 | 2100 |
2096 /// State shared between JsIrBuilders within the same function. | 2101 /// State shared between JsIrBuilders within the same function. |
2097 /// | 2102 /// |
2098 /// Note that this is not shared between builders of nested functions. | 2103 /// Note that this is not shared between builders of nested functions. |
2099 class JsIrBuilderSharedState { | 2104 class JsIrBuilderSharedState { |
2100 /// Maps boxed locals to their location. These locals are not part of | 2105 /// Maps boxed locals to their location. These locals are not part of |
2101 /// the environment. | 2106 /// the environment. |
2102 final Map<Local, ClosureLocation> boxedVariables = {}; | 2107 final Map<Local, ClosureLocation> boxedVariables = {}; |
2103 | 2108 |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2502 // For type tests, we must treat specially the rare cases where `null` | 2507 // For type tests, we must treat specially the rare cases where `null` |
2503 // satisfies the test (which otherwise never satisfies a type test). | 2508 // satisfies the test (which otherwise never satisfies a type test). |
2504 // This is not an optimization: the TypeOperator assumes that `null` | 2509 // This is not an optimization: the TypeOperator assumes that `null` |
2505 // cannot satisfy the type test unless the type is a type variable. | 2510 // cannot satisfy the type test unless the type is a type variable. |
2506 if (type.isObject || type.isDynamic) { | 2511 if (type.isObject || type.isDynamic) { |
2507 // `x is Object` and `x is dynamic` are always true, even if x is null. | 2512 // `x is Object` and `x is dynamic` are always true, even if x is null. |
2508 return buildBooleanConstant(true); | 2513 return buildBooleanConstant(true); |
2509 } | 2514 } |
2510 if (type is InterfaceType && type.element == program.nullClass) { | 2515 if (type is InterfaceType && type.element == program.nullClass) { |
2511 // `x is Null` is true if and only if x is null. | 2516 // `x is Null` is true if and only if x is null. |
2512 return addPrimitive(new ir.Identical(value, buildNullConstant())); | 2517 return _buildCheckNull(value); |
2513 } | 2518 } |
2514 return addPrimitive(new ir.TypeTest(value, type, typeArguments)); | 2519 return addPrimitive(new ir.TypeTest(value, type, typeArguments)); |
2515 } else { | 2520 } else { |
2516 return _continueWithExpression( | 2521 return _continueWithExpression( |
2517 (k) => new ir.TypeCast(value, type, typeArguments, k)); | 2522 (k) => new ir.TypeCast(value, type, typeArguments, k)); |
2518 } | 2523 } |
2519 } | 2524 } |
2520 | 2525 |
2521 @override | 2526 @override |
2522 ir.Primitive buildIfNull(ir.Primitive value, | 2527 ir.Primitive buildIfNull(ir.Primitive value, |
2523 ir.Primitive buildRight(IrBuilder builder)) { | 2528 ir.Primitive buildRight(IrBuilder builder)) { |
2524 ir.Primitive condition = _buildCheckNull(value); | 2529 ir.Primitive condition = _buildCheckNull(value); |
2525 return buildConditional(condition, buildRight, (_) => value); | 2530 return buildConditional(condition, buildRight, (_) => value); |
2526 } | 2531 } |
2527 | 2532 |
2528 @override | 2533 @override |
2529 ir.Primitive buildIfNotNullSend(ir.Primitive receiver, | 2534 ir.Primitive buildIfNotNullSend(ir.Primitive receiver, |
2530 ir.Primitive buildSend(IrBuilder builder)) { | 2535 ir.Primitive buildSend(IrBuilder builder)) { |
2531 ir.Primitive condition = _buildCheckNull(receiver); | 2536 ir.Primitive condition = _buildCheckNull(receiver); |
2532 return buildConditional(condition, (_) => receiver, buildSend); | 2537 return buildConditional(condition, (_) => receiver, buildSend); |
2533 } | 2538 } |
2534 | 2539 |
2535 /// Creates a type test checking whether [value] is null. | 2540 /// Creates a type test checking whether [value] is null. |
2536 ir.Primitive _buildCheckNull(ir.Primitive value) { | 2541 ir.Primitive _buildCheckNull(ir.Primitive value) { |
2537 assert(isOpen); | 2542 assert(isOpen); |
2538 ir.Primitive right = buildNullConstant(); | 2543 return buildIdentical(value, buildNullConstant()); |
2539 return addPrimitive(new ir.Identical(value, right)); | |
2540 } | 2544 } |
2541 | 2545 |
2542 /// Convert the given value to a string. | 2546 /// Convert the given value to a string. |
2543 ir.Primitive buildStringify(ir.Primitive value) { | 2547 ir.Primitive buildStringify(ir.Primitive value) { |
2544 return buildStaticFunctionInvocation( | 2548 return buildStaticFunctionInvocation( |
2545 program.stringifyFunction, | 2549 program.stringifyFunction, |
2546 new CallStructure.unnamed(1), | 2550 new CallStructure.unnamed(1), |
2547 <ir.Primitive>[value]); | 2551 <ir.Primitive>[value]); |
2548 } | 2552 } |
2549 } | 2553 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2620 } | 2624 } |
2621 | 2625 |
2622 class SwitchCaseInfo { | 2626 class SwitchCaseInfo { |
2623 final List<ir.Primitive> constants = <ir.Primitive>[]; | 2627 final List<ir.Primitive> constants = <ir.Primitive>[]; |
2624 final SubbuildFunction buildBody; | 2628 final SubbuildFunction buildBody; |
2625 | 2629 |
2626 SwitchCaseInfo(this.buildBody); | 2630 SwitchCaseInfo(this.buildBody); |
2627 | 2631 |
2628 void addConstant(ir.Primitive constant) => constants.add(constant); | 2632 void addConstant(ir.Primitive constant) => constants.add(constant); |
2629 } | 2633 } |
OLD | NEW |