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

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

Issue 1699033003: dart2js cps: Combine integer type check with bounds check. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update status 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 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 774
775 Primitive get unrefined => value.definition.unrefined; 775 Primitive get unrefined => value.definition.unrefined;
776 776
777 void setParentPointers() { 777 void setParentPointers() {
778 value.parent = this; 778 value.parent = this;
779 } 779 }
780 } 780 }
781 781
782 /// Checks that [index] is a valid index on a given indexable [object]. 782 /// Checks that [index] is a valid index on a given indexable [object].
783 /// 783 ///
784 /// Compiles to the following, with a subset of the conditions in the `if`: 784 /// In the simplest form, compiles to the following:
785 /// 785 ///
786 /// if (index < 0 || index >= object.length || object.length === 0) 786 /// if (index < 0 || index >= object.length)
787 /// ThrowIndexOutOfRangeException(object, index); 787 /// ThrowIndexOutOfRangeException(object, index);
788 /// 788 ///
789 /// [index] must be an integer, and [object] must refer to null or an indexable 789 /// In the general form, any of the following conditions can be checked:
790 /// object, and [length] must be the length of [object] at the time of the 790 ///
791 /// check. 791 /// Lower bound: `index >= 0`
792 /// Upper bound: `index < object.length`
793 /// Emptiness: `object.length !== 0`
794 /// Integerness: `index >>> 0 === index`
795 ///
796 /// [index] must be an integer unless integerness is checked, and [object] must
797 /// refer to null or an indexable object, and [length] must be the length of
798 /// [object] at the time of the check.
792 /// 799 ///
793 /// Returns [object] so the bounds check can be used to restrict code motion. 800 /// Returns [object] so the bounds check can be used to restrict code motion.
794 /// It is possible to have a bounds check node that performs no checks but 801 /// It is possible to have a bounds check node that performs no checks but
795 /// is retained to restrict code motion. 802 /// is retained to restrict code motion.
796 /// 803 ///
797 /// The [index] reference may be null if there are no checks to perform, 804 /// The [index] reference may be null if there are no checks to perform,
798 /// and the [length] reference may be null if there is no upper bound or 805 /// and the [length] reference may be null if there is no upper bound or
799 /// emptiness check. 806 /// emptiness check.
800 /// 807 ///
801 /// If a separate code motion guard for the index is required, e.g. because it 808 /// If a separate code motion guard for the index is required, e.g. because it
(...skipping 16 matching lines...) Expand all
818 /// If true, check that `object.length !== 0`. 825 /// If true, check that `object.length !== 0`.
819 /// 826 ///
820 /// Equivalent to a lower bound check with `object.length - 1` as the index, 827 /// Equivalent to a lower bound check with `object.length - 1` as the index,
821 /// but this check is faster. 828 /// but this check is faster.
822 /// 829 ///
823 /// Although [index] is not used in the condition, it is used to generate 830 /// Although [index] is not used in the condition, it is used to generate
824 /// the thrown error. Currently it is always `-1` for emptiness checks, 831 /// the thrown error. Currently it is always `-1` for emptiness checks,
825 /// because that corresponds to `object.length - 1` in the error case. 832 /// because that corresponds to `object.length - 1` in the error case.
826 bool get hasEmptinessCheck => checks & EMPTINESS != 0; 833 bool get hasEmptinessCheck => checks & EMPTINESS != 0;
827 834
835 /// If true, check that `index` is an integer.
836 bool get hasIntegerCheck => checks & INTEGER != 0;
837
828 /// True if the [length] is needed to perform the check. 838 /// True if the [length] is needed to perform the check.
829 bool get lengthUsedInCheck => checks & (UPPER_BOUND | EMPTINESS) != 0; 839 bool get lengthUsedInCheck => checks & (UPPER_BOUND | EMPTINESS) != 0;
830 840
831 bool get hasNoChecks => checks == NONE; 841 bool get hasNoChecks => checks == NONE;
832 842
833 static const int UPPER_BOUND = 1 << 0; 843 static const int UPPER_BOUND = 1 << 0;
834 static const int LOWER_BOUND = 1 << 1; 844 static const int LOWER_BOUND = 1 << 1;
835 static const int EMPTINESS = 1 << 2; // See [hasEmptinessCheck]. 845 static const int EMPTINESS = 1 << 2; // See [hasEmptinessCheck].
846 static const int INTEGER = 1 << 3; // Check if index is an int.
836 static const int BOTH_BOUNDS = UPPER_BOUND | LOWER_BOUND; 847 static const int BOTH_BOUNDS = UPPER_BOUND | LOWER_BOUND;
837 static const int NONE = 0; 848 static const int NONE = 0;
838 849
839 BoundsCheck(Primitive object, Primitive index, Primitive length, 850 BoundsCheck(Primitive object, Primitive index, Primitive length,
840 [this.checks = BOTH_BOUNDS, this.sourceInformation]) 851 [this.checks = BOTH_BOUNDS, this.sourceInformation])
841 : this.object = new Reference<Primitive>(object), 852 : this.object = new Reference<Primitive>(object),
842 this.index = new Reference<Primitive>(index), 853 this.index = new Reference<Primitive>(index),
843 this.length = length == null ? null : new Reference<Primitive>(length); 854 this.length = length == null ? null : new Reference<Primitive>(length);
844 855
845 BoundsCheck.noCheck(Primitive object, [this.sourceInformation]) 856 BoundsCheck.noCheck(Primitive object, [this.sourceInformation])
846 : this.object = new Reference<Primitive>(object), 857 : this.object = new Reference<Primitive>(object),
847 this.checks = NONE; 858 this.checks = NONE;
848 859
849 accept(Visitor visitor) => visitor.visitBoundsCheck(this); 860 accept(Visitor visitor) => visitor.visitBoundsCheck(this);
850 861
851 void setParentPointers() { 862 void setParentPointers() {
852 object.parent = this; 863 object.parent = this;
853 if (index != null) { 864 if (index != null) {
854 index.parent = this; 865 index.parent = this;
855 } 866 }
856 if (length != null) { 867 if (length != null) {
857 length.parent = this; 868 length.parent = this;
858 } 869 }
859 } 870 }
860 871
861 String get checkString { 872 String get checkString {
862 if (hasUpperBoundCheck && hasLowerBoundCheck) { 873 if (hasNoChecks) return 'no-check';
863 return 'upper-lower-checks'; 874 return [hasUpperBoundCheck ? 'upper' : null,
864 } else if (hasUpperBoundCheck) { 875 hasLowerBoundCheck ? 'lower' : null,
865 return 'upper-check'; 876 hasEmptinessCheck ? 'emptiness' : null,
866 } else if (hasLowerBoundCheck) { 877 hasIntegerCheck ? 'integer' : null,
867 return 'lower-check'; 878 'check']
868 } else if (hasEmptinessCheck) { 879 .where((x) => x != null).join('-');
869 return 'emptiness-check';
870 } else {
871 return 'no-check';
872 }
873 } 880 }
874 881
875 bool get isSafeForElimination => checks == NONE; 882 bool get isSafeForElimination => checks == NONE;
876 bool get isSafeForReordering => false; 883 bool get isSafeForReordering => false;
877 bool get hasValue => true; // Can be referenced to restrict code motion. 884 bool get hasValue => true; // Can be referenced to restrict code motion.
878 885
879 Primitive get effectiveDefinition => object.definition.effectiveDefinition; 886 Primitive get effectiveDefinition => object.definition.effectiveDefinition;
880 } 887 }
881 888
882 /// Throw a [NoSuchMethodError] if [value] cannot respond to [selector]. 889 /// Throw a [NoSuchMethodError] if [value] cannot respond to [selector].
(...skipping 2090 matching lines...) Expand 10 before | Expand all | Expand 10 after
2973 plug(new Branch.loose(_definitions.getCopy(node.condition), 2980 plug(new Branch.loose(_definitions.getCopy(node.condition),
2974 _copies[node.trueContinuation.definition], 2981 _copies[node.trueContinuation.definition],
2975 _copies[node.falseContinuation.definition]) 2982 _copies[node.falseContinuation.definition])
2976 ..isStrictCheck = node.isStrictCheck); 2983 ..isStrictCheck = node.isStrictCheck);
2977 } 2984 }
2978 2985
2979 visitUnreachable(Unreachable node) { 2986 visitUnreachable(Unreachable node) {
2980 plug(new Unreachable()); 2987 plug(new Unreachable());
2981 } 2988 }
2982 } 2989 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698