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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart

Issue 1668913002: dart2js cps: More aggressive operator specialization. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update test expectations Created 4 years, 10 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
OLDNEW
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 library dart2js.ir_nodes; 4 library dart2js.ir_nodes;
5 5
6 import 'dart:collection'; 6 import 'dart:collection';
7 import 'cps_fragment.dart' show CpsFragment; 7 import 'cps_fragment.dart' show CpsFragment;
8 import 'cps_ir_nodes_sexpr.dart'; 8 import 'cps_ir_nodes_sexpr.dart';
9 import '../constants/values.dart' as values; 9 import '../constants/values.dart' as values;
10 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; 10 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 bool get isSafeForElimination; 253 bool get isSafeForElimination;
254 254
255 /// True if time-of-evaluation is irrelevant for the given primitive, 255 /// True if time-of-evaluation is irrelevant for the given primitive,
256 /// assuming its inputs are the same values. 256 /// assuming its inputs are the same values.
257 bool get isSafeForReordering; 257 bool get isSafeForReordering;
258 258
259 /// The source information associated with this primitive. 259 /// The source information associated with this primitive.
260 // TODO(johnniwinther): Require source information for all primitives. 260 // TODO(johnniwinther): Require source information for all primitives.
261 SourceInformation get sourceInformation => null; 261 SourceInformation get sourceInformation => null;
262 262
263 /// If this is a [Refinement], [BoundsCheck] or [NullCheck] node, returns the 263 /// If this is a [Refinement], [BoundsCheck] or [ReceiverCheck] node, returns the
264 /// value being refined, the indexable object being checked, or the value 264 /// value being refined, the indexable object being checked, or the value
265 /// that was checked to be non-null, respectively. 265 /// that was checked to be non-null, respectively.
266 /// 266 ///
267 /// Those instructions all return the corresponding operand directly, and 267 /// Those instructions all return the corresponding operand directly, and
268 /// this getter can be used to get (closer to) where the value came from. 268 /// this getter can be used to get (closer to) where the value came from.
269 // 269 //
270 // TODO(asgerf): Also do this for [TypeCast]? 270 // TODO(asgerf): Also do this for [TypeCast]?
271 Primitive get effectiveDefinition => this; 271 Primitive get effectiveDefinition => this;
272 272
273 /// Like [effectiveDefinition] but only unfolds [Refinement] nodes. 273 /// Like [effectiveDefinition] but only unfolds [Refinement] nodes.
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 /// and the [length] reference may be null if there is no upper bound or 798 /// and the [length] reference may be null if there is no upper bound or
799 /// emptiness check. 799 /// emptiness check.
800 /// 800 ///
801 /// If a separate code motion guard for the index is required, e.g. because it 801 /// If a separate code motion guard for the index is required, e.g. because it
802 /// must be known to be non-negative in an operator that does not involve 802 /// must be known to be non-negative in an operator that does not involve
803 /// [object], a [Refinement] can be created for it with the non-negative integer 803 /// [object], a [Refinement] can be created for it with the non-negative integer
804 /// type. 804 /// type.
805 class BoundsCheck extends Primitive { 805 class BoundsCheck extends Primitive {
806 final Reference<Primitive> object; 806 final Reference<Primitive> object;
807 Reference<Primitive> index; 807 Reference<Primitive> index;
808 Reference<Primitive> length; // FIXME write docs for length 808 Reference<Primitive> length;
809 int checks; 809 int checks;
810 final SourceInformation sourceInformation; 810 final SourceInformation sourceInformation;
811 811
812 /// If true, check that `index >= 0`. 812 /// If true, check that `index >= 0`.
813 bool get hasLowerBoundCheck => checks & LOWER_BOUND != 0; 813 bool get hasLowerBoundCheck => checks & LOWER_BOUND != 0;
814 814
815 /// If true, check that `index < object.length`. 815 /// If true, check that `index < object.length`.
816 bool get hasUpperBoundCheck => checks & UPPER_BOUND != 0; 816 bool get hasUpperBoundCheck => checks & UPPER_BOUND != 0;
817 817
818 /// If true, check that `object.length !== 0`. 818 /// If true, check that `object.length !== 0`.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 } 872 }
873 } 873 }
874 874
875 bool get isSafeForElimination => checks == NONE; 875 bool get isSafeForElimination => checks == NONE;
876 bool get isSafeForReordering => false; 876 bool get isSafeForReordering => false;
877 bool get hasValue => true; // Can be referenced to restrict code motion. 877 bool get hasValue => true; // Can be referenced to restrict code motion.
878 878
879 Primitive get effectiveDefinition => object.definition.effectiveDefinition; 879 Primitive get effectiveDefinition => object.definition.effectiveDefinition;
880 } 880 }
881 881
882 /// Throw an exception if [value] is `null`. 882 /// Throw a [NoSuchMethodError] if [value] cannot respond to [selector].
883 /// 883 ///
884 /// Returns [value] so this can be used to restrict code motion. 884 /// Returns [value] so this can be used to restrict code motion.
885 /// 885 ///
886 /// In the simplest form this compiles to `value.toString;`. 886 /// The check can take one of three forms:
887 /// 887 ///
888 /// [selector] holds the selector that is the cause of the null check. This is 888 /// value.toString;
889 /// usually a method that was inlined where [value] the receiver. 889 /// value.selectorName;
890 /// value.selectorName(); (should only be used if check always fails)
890 /// 891 ///
891 /// If [selector] is set and [useSelector] is true, `toString` is replaced with 892 /// The first two forms are used when it is known that only null fails the
892 /// the (possibly minified) invocation name of the selector. This can be 893 /// check. Additionally, the check may be guarded by a [condition], allowing
893 /// shorter and generate a more meaningful error message, but is expensive if 894 /// for three more forms:
894 /// [value] is non-null and does not have that property at runtime.
895 /// 895 ///
896 /// If [condition] is set, it is assumed that [condition] is true if and only 896 /// if (condition) value.toString; (this form is valid but unused)
897 /// if [value] is null. The check then compiles to: 897 /// if (condition) value.selectorName;
898 /// if (condition) value.selectorName();
898 /// 899 ///
899 /// if (condition) value.toString; (or .selector if non-null) 900 /// The condition must be true if and only if the check should fail. It should
901 /// ideally be of a form understood by JS engines, e.g. a `typeof` test.
900 /// 902 ///
901 /// The latter form is useful when [condition] is a form understood by the JS 903 /// If [useSelector] is false, the first form instead becomes `value.toString;`.
902 /// runtime, such as a `typeof` test. 904 /// This form is faster when the value is non-null and the accessed property has
903 class NullCheck extends Primitive { 905 /// been removed by tree shaking.
906 ///
907 /// [selector] may not be one of the selectors implemented by the null object.
908 class ReceiverCheck extends Primitive {
904 final Reference<Primitive> value; 909 final Reference<Primitive> value;
905 final Selector selector; 910 final Selector selector;
906 final bool useSelector; 911 final SourceInformation sourceInformation;
907 final Reference<Primitive> condition; 912 final Reference<Primitive> condition;
908 final SourceInformation sourceInformation; 913 final int _flags;
909 914
910 NullCheck(Primitive value, this.sourceInformation, 915 static const int _USE_SELECTOR = 1 << 0;
911 {Primitive condition, 916 static const int _NULL_CHECK = 1 << 1;
912 this.selector,
913 this.useSelector: false})
914 : this.value = new Reference<Primitive>(value),
915 this.condition =
916 condition == null ? null : new Reference<Primitive>(condition);
917 917
918 NullCheck.guarded(Primitive condition, Primitive value, this.selector, 918 /// True if the selector name should be used in the check; otherwise
919 this.sourceInformation) 919 /// `toString` will be used.
920 : this.condition = new Reference<Primitive>(condition), 920 bool get useSelector => _flags & _USE_SELECTOR != 0;
921 this.value = new Reference<Primitive>(value), 921
922 this.useSelector = true; 922 /// True if null is the only possible input that cannot respond to [selector].
923 bool get isNullCheck => _flags & _NULL_CHECK != 0;
924
925
926 /// Constructor for creating checks in arbitrary configurations.
927 ///
928 /// Consider using one of the named constructors instead.
929 ///
930 /// [useSelector] and [isNullCheck] are mandatory named arguments.
931 ReceiverCheck(Primitive value, this.selector, this.sourceInformation,
932 {Primitive condition, bool useSelector, bool isNullCheck})
933 : value = new Reference<Primitive>(value),
934 condition = _optionalReference(condition),
935 _flags = (useSelector ? _USE_SELECTOR : 0) |
936 (isNullCheck ? _NULL_CHECK : 0);
937
938 /// Simplified constructor for building null checks.
939 ///
940 /// Null must be the only possible input value that does not respond to
941 /// [selector].
942 ReceiverCheck.nullCheck(
943 Primitive value,
944 Selector selector,
945 SourceInformation sourceInformation,
946 {Primitive condition})
947 : this(value,
948 selector,
949 sourceInformation,
950 condition: condition,
951 useSelector: condition != null,
952 isNullCheck: true);
953
954 /// Simplified constructor for building the general check of form:
955 ///
956 /// if (condition) value.selectorName();
957 ///
958 ReceiverCheck.generalCheck(
959 Primitive value,
960 Selector selector,
961 SourceInformation sourceInformation,
962 Primitive condition)
963 : this(value,
964 selector,
965 sourceInformation,
966 condition: condition,
967 useSelector: true,
968 isNullCheck: false);
923 969
924 bool get isSafeForElimination => false; 970 bool get isSafeForElimination => false;
925 bool get isSafeForReordering => false; 971 bool get isSafeForReordering => false;
926 bool get hasValue => true; 972 bool get hasValue => true;
927 973
928 accept(Visitor visitor) => visitor.visitNullCheck(this); 974 accept(Visitor visitor) => visitor.visitReceiverCheck(this);
929 975
930 void setParentPointers() { 976 void setParentPointers() {
931 value.parent = this; 977 value.parent = this;
932 if (condition != null) { 978 if (condition != null) {
933 condition.parent = this; 979 condition.parent = this;
934 } 980 }
935 } 981 }
936 982
937 Primitive get effectiveDefinition => value.definition.effectiveDefinition; 983 Primitive get effectiveDefinition => value.definition.effectiveDefinition;
984
985 String get nullCheckString => isNullCheck ? 'null-check' : 'general-check';
986 String get useSelectorString => useSelector ? 'use-selector' : 'no-selector';
987 String get flagString => '$nullCheckString $useSelectorString';
938 } 988 }
939 989
940 /// An "is" type test. 990 /// An "is" type test.
941 /// 991 ///
942 /// Returns `true` if [value] is an instance of [dartType]. 992 /// Returns `true` if [value] is an instance of [dartType].
943 /// 993 ///
944 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might 994 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might
945 /// be a type variable containing one of these types). This design is chosen 995 /// be a type variable containing one of these types). This design is chosen
946 /// to simplify code generation for type tests. 996 /// to simplify code generation for type tests.
947 class TypeTest extends Primitive { 997 class TypeTest extends Primitive {
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after
1923 return visitor.visitYield(this); 1973 return visitor.visitYield(this);
1924 } 1974 }
1925 1975
1926 bool get hasValue => true; 1976 bool get hasValue => true;
1927 1977
1928 void setParentPointers() { 1978 void setParentPointers() {
1929 input.parent = this; 1979 input.parent = this;
1930 } 1980 }
1931 } 1981 }
1932 1982
1983 Reference<Primitive> _reference(Primitive definition) {
1984 return new Reference<Primitive>(definition);
1985 }
1986
1987 Reference<Primitive> _optionalReference(Primitive definition) {
1988 return definition == null
1989 ? null
1990 : new Reference<Primitive>(definition);
1991 }
1992
1933 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { 1993 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) {
1934 return definitions.map((e) => new Reference<Primitive>(e)).toList(); 1994 return definitions.map((e) => new Reference<Primitive>(e)).toList();
1935 } 1995 }
1936 1996
1937 void _setParentsOnNodes(List<Node> nodes, Node parent) { 1997 void _setParentsOnNodes(List<Node> nodes, Node parent) {
1938 for (Node node in nodes) { 1998 for (Node node in nodes) {
1939 node.parent = parent; 1999 node.parent = parent;
1940 } 2000 }
1941 } 2001 }
1942 2002
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2070 T visitCreateInvocationMirror(CreateInvocationMirror node); 2130 T visitCreateInvocationMirror(CreateInvocationMirror node);
2071 T visitTypeTest(TypeTest node); 2131 T visitTypeTest(TypeTest node);
2072 T visitTypeTestViaFlag(TypeTestViaFlag node); 2132 T visitTypeTestViaFlag(TypeTestViaFlag node);
2073 T visitApplyBuiltinOperator(ApplyBuiltinOperator node); 2133 T visitApplyBuiltinOperator(ApplyBuiltinOperator node);
2074 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); 2134 T visitApplyBuiltinMethod(ApplyBuiltinMethod node);
2075 T visitGetLength(GetLength node); 2135 T visitGetLength(GetLength node);
2076 T visitGetIndex(GetIndex node); 2136 T visitGetIndex(GetIndex node);
2077 T visitSetIndex(SetIndex node); 2137 T visitSetIndex(SetIndex node);
2078 T visitRefinement(Refinement node); 2138 T visitRefinement(Refinement node);
2079 T visitBoundsCheck(BoundsCheck node); 2139 T visitBoundsCheck(BoundsCheck node);
2080 T visitNullCheck(NullCheck node); 2140 T visitReceiverCheck(ReceiverCheck node);
2081 T visitForeignCode(ForeignCode node); 2141 T visitForeignCode(ForeignCode node);
2082 } 2142 }
2083 2143
2084 /// Recursively visits all children of a CPS term. 2144 /// Recursively visits all children of a CPS term.
2085 /// 2145 ///
2086 /// The user of the class is responsible for avoiding stack overflows from 2146 /// The user of the class is responsible for avoiding stack overflows from
2087 /// deep recursion, e.g. by overriding methods to cut off recursion at certain 2147 /// deep recursion, e.g. by overriding methods to cut off recursion at certain
2088 /// points. 2148 /// points.
2089 /// 2149 ///
2090 /// All recursive invocations occur through the [visit] method, which the 2150 /// All recursive invocations occur through the [visit] method, which the
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
2393 processBoundsCheck(node); 2453 processBoundsCheck(node);
2394 processReference(node.object); 2454 processReference(node.object);
2395 if (node.index != null) { 2455 if (node.index != null) {
2396 processReference(node.index); 2456 processReference(node.index);
2397 } 2457 }
2398 if (node.length != null) { 2458 if (node.length != null) {
2399 processReference(node.length); 2459 processReference(node.length);
2400 } 2460 }
2401 } 2461 }
2402 2462
2403 processNullCheck(NullCheck node) {} 2463 processNullCheck(ReceiverCheck node) {}
2404 visitNullCheck(NullCheck node) { 2464 visitReceiverCheck(ReceiverCheck node) {
2405 processNullCheck(node); 2465 processNullCheck(node);
2406 processReference(node.value); 2466 processReference(node.value);
2407 if (node.condition != null) { 2467 if (node.condition != null) {
2408 processReference(node.condition); 2468 processReference(node.condition);
2409 } 2469 }
2410 } 2470 }
2411 } 2471 }
2412 2472
2413 typedef void StackAction(); 2473 typedef void StackAction();
2414 2474
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
2754 return new BoundsCheck.noCheck(getCopy(node.object), 2814 return new BoundsCheck.noCheck(getCopy(node.object),
2755 node.sourceInformation); 2815 node.sourceInformation);
2756 } else { 2816 } else {
2757 return new BoundsCheck(getCopy(node.object), getCopy(node.index), 2817 return new BoundsCheck(getCopy(node.object), getCopy(node.index),
2758 node.length == null ? null : getCopy(node.length), 2818 node.length == null ? null : getCopy(node.length),
2759 node.checks, 2819 node.checks,
2760 node.sourceInformation); 2820 node.sourceInformation);
2761 } 2821 }
2762 } 2822 }
2763 2823
2764 Definition visitNullCheck(NullCheck node) { 2824 Definition visitReceiverCheck(ReceiverCheck node) {
2765 return new NullCheck(getCopy(node.value), node.sourceInformation, 2825 return new ReceiverCheck(getCopy(node.value),
2826 node.selector,
2827 node.sourceInformation,
2766 condition: node.condition == null ? null : getCopy(node.condition), 2828 condition: node.condition == null ? null : getCopy(node.condition),
2767 selector: node.selector, 2829 useSelector: node.useSelector,
2768 useSelector: node.useSelector); 2830 isNullCheck: node.isNullCheck);
2769 } 2831 }
2770 2832
2771 Definition visitForeignCode(ForeignCode node) { 2833 Definition visitForeignCode(ForeignCode node) {
2772 return new ForeignCode(node.codeTemplate, node.storedType, 2834 return new ForeignCode(node.codeTemplate, node.storedType,
2773 getList(node.arguments), 2835 getList(node.arguments),
2774 node.nativeBehavior, 2836 node.nativeBehavior,
2775 dependency: node.dependency); 2837 dependency: node.dependency);
2776 } 2838 }
2777 } 2839 }
2778 2840
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
2909 plug(new Branch.loose(_definitions.getCopy(node.condition), 2971 plug(new Branch.loose(_definitions.getCopy(node.condition),
2910 _copies[node.trueContinuation.definition], 2972 _copies[node.trueContinuation.definition],
2911 _copies[node.falseContinuation.definition]) 2973 _copies[node.falseContinuation.definition])
2912 ..isStrictCheck = node.isStrictCheck); 2974 ..isStrictCheck = node.isStrictCheck);
2913 } 2975 }
2914 2976
2915 visitUnreachable(Unreachable node) { 2977 visitUnreachable(Unreachable node) {
2916 plug(new Unreachable()); 2978 plug(new Unreachable());
2917 } 2979 }
2918 } 2980 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698