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

Side by Side Diff: lib/compiler/implementation/ssa/nodes.dart

Issue 9965047: Make constant lists immutable. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 interface HVisitor<R> { 5 interface HVisitor<R> {
6 R visitAdd(HAdd node); 6 R visitAdd(HAdd node);
7 R visitBitAnd(HBitAnd node); 7 R visitBitAnd(HBitAnd node);
8 R visitBitNot(HBitNot node); 8 R visitBitNot(HBitNot node);
9 R visitBitOr(HBitOr node); 9 R visitBitOr(HBitOr node);
10 R visitBitXor(HBitXor node); 10 R visitBitXor(HBitXor node);
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 result.loopInformation = new HLoopInformation(type, result, target, labels); 145 result.loopInformation = new HLoopInformation(type, result, target, labels);
146 return result; 146 return result;
147 } 147 }
148 148
149 static HType mapConstantTypeToSsaType(Constant constant) { 149 static HType mapConstantTypeToSsaType(Constant constant) {
150 if (constant.isNull()) return HType.UNKNOWN; 150 if (constant.isNull()) return HType.UNKNOWN;
151 if (constant.isBool()) return HType.BOOLEAN; 151 if (constant.isBool()) return HType.BOOLEAN;
152 if (constant.isInt()) return HType.INTEGER; 152 if (constant.isInt()) return HType.INTEGER;
153 if (constant.isDouble()) return HType.DOUBLE; 153 if (constant.isDouble()) return HType.DOUBLE;
154 if (constant.isString()) return HType.STRING; 154 if (constant.isString()) return HType.STRING;
155 if (constant.isList()) return HType.ARRAY; 155 if (constant.isList()) return HType.READABLE_ARRAY;
156 return HType.UNKNOWN; 156 return HType.UNKNOWN;
157 } 157 }
158 158
159 HConstant addConstant(Constant constant) { 159 HConstant addConstant(Constant constant) {
160 HConstant result = constants[constant]; 160 HConstant result = constants[constant];
161 if (result === null) { 161 if (result === null) {
162 HType type = mapConstantTypeToSsaType(constant); 162 HType type = mapConstantTypeToSsaType(constant);
163 result = new HConstant.internal(constant, type); 163 result = new HConstant.internal(constant, type);
164 entry.addAtExit(result); 164 entry.addAtExit(result);
165 constants[constant] = result; 165 constants[constant] = result;
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 750
751 class HType { 751 class HType {
752 final int flag; 752 final int flag;
753 const HType(int this.flag); 753 const HType(int this.flag);
754 754
755 static final int FLAG_CONFLICTING = 0; 755 static final int FLAG_CONFLICTING = 0;
756 static final int FLAG_UNKNOWN = 1; 756 static final int FLAG_UNKNOWN = 1;
757 static final int FLAG_BOOLEAN = FLAG_UNKNOWN << 1; 757 static final int FLAG_BOOLEAN = FLAG_UNKNOWN << 1;
758 static final int FLAG_INTEGER = FLAG_BOOLEAN << 1; 758 static final int FLAG_INTEGER = FLAG_BOOLEAN << 1;
759 static final int FLAG_STRING = FLAG_INTEGER << 1; 759 static final int FLAG_STRING = FLAG_INTEGER << 1;
760 static final int FLAG_ARRAY = FLAG_STRING << 1; 760 static final int FLAG_READABLE_ARRAY = FLAG_STRING << 1;
761 static final int FLAG_DOUBLE = FLAG_ARRAY << 1; 761 // FLAG_WRITABLE_ARRAY implies FLAG_READABLE_ARRAY.
762 static final int FLAG_WRITEABLE_ARRAY = FLAG_READABLE_ARRAY << 1;
763 static final int FLAG_DOUBLE = FLAG_WRITEABLE_ARRAY << 1;
762 764
763 static final HType CONFLICTING = const HType(FLAG_CONFLICTING); 765 static final HType CONFLICTING = const HType(FLAG_CONFLICTING);
764 static final HType UNKNOWN = const HType(FLAG_UNKNOWN); 766 static final HType UNKNOWN = const HType(FLAG_UNKNOWN);
765 static final HType BOOLEAN = const HType(FLAG_BOOLEAN); 767 static final HType BOOLEAN = const HType(FLAG_BOOLEAN);
766 static final HType STRING = const HType(FLAG_STRING); 768 static final HType STRING = const HType(FLAG_STRING);
767 static final HType ARRAY = const HType(FLAG_ARRAY); 769 static final HType READABLE_ARRAY = const HType(FLAG_READABLE_ARRAY);
770 static final HType MUTABLE_ARRAY =
771 const HType(FLAG_READABLE_ARRAY | FLAG_WRITEABLE_ARRAY);
768 static final HType INTEGER = const HType(FLAG_INTEGER); 772 static final HType INTEGER = const HType(FLAG_INTEGER);
769 static final HType DOUBLE = const HType(FLAG_DOUBLE); 773 static final HType DOUBLE = const HType(FLAG_DOUBLE);
770 static final HType STRING_OR_ARRAY = const HType(FLAG_STRING | FLAG_ARRAY); 774 static final HType STRING_OR_ARRAY =
775 const HType(FLAG_STRING | FLAG_READABLE_ARRAY | FLAG_WRITEABLE_ARRAY);
771 static final HType NUMBER = const HType(FLAG_DOUBLE | FLAG_INTEGER); 776 static final HType NUMBER = const HType(FLAG_DOUBLE | FLAG_INTEGER);
772 777
773 bool isConflicting() => this === CONFLICTING; 778 bool isConflicting() => this === CONFLICTING;
774 bool isUnknown() => this === UNKNOWN; 779 bool isUnknown() => this === UNKNOWN;
775 bool isBoolean() => this === BOOLEAN; 780 bool isBoolean() => this === BOOLEAN;
776 bool isInteger() => this === INTEGER; 781 bool isInteger() => this === INTEGER;
777 bool isDouble() => this === DOUBLE; 782 bool isDouble() => this === DOUBLE;
778 bool isString() => this === STRING; 783 bool isString() => this === STRING;
779 bool isArray() => this === ARRAY; 784 bool isArray() => (this.flag & FLAG_READABLE_ARRAY) != 0;
785 bool isMutableArray() => this === MUTABLE_ARRAY;
780 bool isNumber() => (this.flag & (FLAG_INTEGER | FLAG_DOUBLE)) != 0; 786 bool isNumber() => (this.flag & (FLAG_INTEGER | FLAG_DOUBLE)) != 0;
781 bool isStringOrArray() => (this.flag & (FLAG_STRING | FLAG_ARRAY)) != 0; 787 bool isStringOrArray() =>
788 (this.flag & (FLAG_STRING | FLAG_READABLE_ARRAY)) != 0;
782 bool isKnown() => this !== UNKNOWN && this !== CONFLICTING; 789 bool isKnown() => this !== UNKNOWN && this !== CONFLICTING;
783 790
784 static HType getTypeFromFlag(int flag) { 791 static HType getTypeFromFlag(int flag) {
785 if (flag === CONFLICTING.flag) return CONFLICTING; 792 if (flag === CONFLICTING.flag) return CONFLICTING;
786 if (flag === UNKNOWN.flag) return UNKNOWN; 793 if (flag === UNKNOWN.flag) return UNKNOWN;
787 if (flag === BOOLEAN.flag) return BOOLEAN; 794 if (flag === BOOLEAN.flag) return BOOLEAN;
788 if (flag === INTEGER.flag) return INTEGER; 795 if (flag === INTEGER.flag) return INTEGER;
789 if (flag === DOUBLE.flag) return DOUBLE; 796 if (flag === DOUBLE.flag) return DOUBLE;
790 if (flag === STRING.flag) return STRING; 797 if (flag === STRING.flag) return STRING;
791 if (flag === ARRAY.flag) return ARRAY; 798 if (flag === READABLE_ARRAY.flag) return READABLE_ARRAY;
799 if (flag === MUTABLE_ARRAY.flag) return MUTABLE_ARRAY;
792 if (flag === NUMBER.flag) return NUMBER; 800 if (flag === NUMBER.flag) return NUMBER;
793 if (flag === STRING_OR_ARRAY.flag) return STRING_OR_ARRAY; 801 if (flag === STRING_OR_ARRAY.flag) return STRING_OR_ARRAY;
794 assert(false); 802 assert(false);
795 } 803 }
796 804
797 String toString() { 805 String toString() {
798 if (isConflicting()) return 'conflicting'; 806 if (isConflicting()) return 'conflicting';
799 if (isUnknown()) return 'unknown'; 807 if (isUnknown()) return 'unknown';
800 if (isBoolean()) return 'boolean'; 808 if (isBoolean()) return 'boolean';
801 if (isInteger()) return 'integer'; 809 if (isInteger()) return 'integer';
802 if (isDouble()) return 'double'; 810 if (isDouble()) return 'double';
803 if (isString()) return 'string'; 811 if (isString()) return 'string';
812 if (isMutableArray()) return 'mutable array';
804 if (isArray()) return 'array'; 813 if (isArray()) return 'array';
805 if (isNumber()) return 'number'; 814 if (isNumber()) return 'number';
806 if (isStringOrArray()) return 'string or array'; 815 if (isStringOrArray()) return 'string or array';
807 unreachable(); 816 unreachable();
808 } 817 }
809 818
810 HType combine(HType other) { 819 HType combine(HType other) {
811 if (isUnknown()) return other; 820 if (isUnknown()) return other;
812 if (other.isUnknown()) return this; 821 if (other.isUnknown()) return this;
813 return getTypeFromFlag(this.flag & other.flag); 822 return getTypeFromFlag(this.flag & other.flag);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 862
854 void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); } 863 void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); }
855 void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); } 864 void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); }
856 865
857 bool useGvn() => getFlag(FLAG_USE_GVN); 866 bool useGvn() => getFlag(FLAG_USE_GVN);
858 void setUseGvn() { setFlag(FLAG_USE_GVN); } 867 void setUseGvn() { setFlag(FLAG_USE_GVN); }
859 // Does this node potentially affect control flow. 868 // Does this node potentially affect control flow.
860 bool isControlFlow() => false; 869 bool isControlFlow() => false;
861 870
862 bool isArray() => type.isArray(); 871 bool isArray() => type.isArray();
872 bool isMutableArray() => type.isMutableArray();
863 bool isBoolean() => type.isBoolean(); 873 bool isBoolean() => type.isBoolean();
864 bool isInteger() => type.isInteger(); 874 bool isInteger() => type.isInteger();
865 bool isNumber() => type.isNumber(); 875 bool isNumber() => type.isNumber();
866 bool isString() => type.isString(); 876 bool isString() => type.isString();
867 bool isTypeUnknown() => type.isUnknown(); 877 bool isTypeUnknown() => type.isUnknown();
868 bool isStringOrArray() => type.isStringOrArray(); 878 bool isStringOrArray() => type.isStringOrArray();
869 879
870 // Compute the type of the instruction. 880 // Compute the type of the instruction.
871 HType computeType() => HType.UNKNOWN; 881 HType computeType() => HType.UNKNOWN;
872 882
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 1173
1164 bool isArrayConstructor() { 1174 bool isArrayConstructor() {
1165 // TODO(ngeoffray): This is not the right way to do the check, 1175 // TODO(ngeoffray): This is not the right way to do the check,
1166 // nor the right place. We need to move it to a phase. 1176 // nor the right place. We need to move it to a phase.
1167 return (element.isFactoryConstructor() 1177 return (element.isFactoryConstructor()
1168 && element.enclosingElement.name.slowToString() == 'List'); 1178 && element.enclosingElement.name.slowToString() == 'List');
1169 } 1179 }
1170 1180
1171 HType computeType() { 1181 HType computeType() {
1172 if (isArrayConstructor()) { 1182 if (isArrayConstructor()) {
1173 return HType.ARRAY; 1183 return HType.MUTABLE_ARRAY;
1174 } 1184 }
1175 return HType.UNKNOWN; 1185 return HType.UNKNOWN;
1176 } 1186 }
1177 1187
1178 bool get builtin() => isArrayConstructor(); 1188 bool get builtin() => isArrayConstructor();
1179 bool hasExpectedType() => isArrayConstructor(); 1189 bool hasExpectedType() => isArrayConstructor();
1180 } 1190 }
1181 1191
1182 class HInvokeSuper extends HInvokeStatic { 1192 class HInvokeSuper extends HInvokeStatic {
1183 HInvokeSuper(selector, inputs) : super(selector, inputs); 1193 HInvokeSuper(selector, inputs) : super(selector, inputs);
(...skipping 11 matching lines...) Expand all
1195 List<HInstruction> inputs) 1205 List<HInstruction> inputs)
1196 : super(selector, inputs); 1206 : super(selector, inputs);
1197 toString() => 'invoke interceptor: ${element.name}'; 1207 toString() => 'invoke interceptor: ${element.name}';
1198 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this); 1208 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this);
1199 1209
1200 String get builtinJsName() { 1210 String get builtinJsName() {
1201 if (getter 1211 if (getter
1202 && name == const SourceString('length') 1212 && name == const SourceString('length')
1203 && inputs[1].isStringOrArray()) { 1213 && inputs[1].isStringOrArray()) {
1204 return 'length'; 1214 return 'length';
1205 } else if (name == const SourceString('add') && inputs[1].isArray()) { 1215 } else if (name == const SourceString('add') &&
1216 inputs[1].isMutableArray()) {
1206 return 'push'; 1217 return 'push';
1207 } else if (name == const SourceString('removeLast') 1218 } else if (name == const SourceString('removeLast')
1208 && inputs[1].isArray()) { 1219 && inputs[1].isMutableArray()) {
karlklose 2012/04/10 14:18:57 Move && to previous line (for consistency).
floitsch 2012/04/10 15:06:42 Done.
1209 return 'pop'; 1220 return 'pop';
1210 } 1221 }
1211 return null; 1222 return null;
1212 } 1223 }
1213 1224
1214 HType computeType() { 1225 HType computeType() {
1215 if (getter 1226 if (getter
1216 && name == const SourceString('length') 1227 && name == const SourceString('length')
1217 && inputs[1].isStringOrArray()) { 1228 && inputs[1].isStringOrArray()) {
1218 return HType.INTEGER; 1229 return HType.INTEGER;
1219 } 1230 }
1220 return HType.UNKNOWN; 1231 return HType.UNKNOWN;
1221 } 1232 }
1222 1233
1223 HType computeDesiredInputType(HInstruction input) { 1234 HType computeDesiredInputType(HInstruction input) {
1224 if (input == inputs[0]) return HType.UNKNOWN; 1235 if (input == inputs[0]) return HType.UNKNOWN;
1225 if (input == inputs[1] && input.isStringOrArray()) { 1236 if (input == inputs[1] && input.isStringOrArray()) {
1226 if (name == const SourceString('add') 1237 if (name == const SourceString('add')
1227 || name == const SourceString('removeLast')) { 1238 || name == const SourceString('removeLast')) {
1228 return HType.ARRAY; 1239 return HType.MUTABLE_ARRAY;
1229 } 1240 }
1230 } 1241 }
1231 return HType.UNKNOWN; 1242 return HType.UNKNOWN;
1232 } 1243 }
1233 1244
1234 bool hasExpectedType() => builtinJsName != null; 1245 bool hasExpectedType() => builtinJsName != null;
1235 1246
1236 void prepareGvn() { 1247 void prepareGvn() {
1237 if (builtinJsName == 'length') { 1248 if (builtinJsName == 'length') {
1238 clearAllSideEffects(); 1249 clearAllSideEffects();
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after
1995 2006
1996 int typeCode() => 26; 2007 int typeCode() => 26;
1997 bool typeEquals(other) => other is HStaticStore; 2008 bool typeEquals(other) => other is HStaticStore;
1998 bool dataEquals(HStaticStore other) => element == other.element; 2009 bool dataEquals(HStaticStore other) => element == other.element;
1999 } 2010 }
2000 2011
2001 class HLiteralList extends HInstruction { 2012 class HLiteralList extends HInstruction {
2002 HLiteralList(inputs, this.isConst) : super(inputs); 2013 HLiteralList(inputs, this.isConst) : super(inputs);
2003 toString() => 'literal list'; 2014 toString() => 'literal list';
2004 accept(HVisitor visitor) => visitor.visitLiteralList(this); 2015 accept(HVisitor visitor) => visitor.visitLiteralList(this);
2005 HType computeType() => HType.ARRAY; 2016 HType computeType() => HType.MUTABLE_ARRAY;
2006 bool hasExpectedType() => true; 2017 bool hasExpectedType() => true;
2007 final bool isConst; // TODO(floitsch): Remove when CTC handles arrays. 2018 final bool isConst; // TODO(floitsch): Remove when CTC handles arrays.
2008 2019
2009 void prepareGvn() { 2020 void prepareGvn() {
2010 assert(!hasSideEffects()); 2021 assert(!hasSideEffects());
2011 } 2022 }
2012 } 2023 }
2013 2024
2014 class HIndex extends HInvokeStatic { 2025 class HIndex extends HInvokeStatic {
2015 HIndex(HStatic target, HInstruction receiver, HInstruction index) 2026 HIndex(HStatic target, HInstruction receiver, HInstruction index)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2050 toString() => 'index assign operator'; 2061 toString() => 'index assign operator';
2051 accept(HVisitor visitor) => visitor.visitIndexAssign(this); 2062 accept(HVisitor visitor) => visitor.visitIndexAssign(this);
2052 2063
2053 HInstruction get receiver() => inputs[1]; 2064 HInstruction get receiver() => inputs[1];
2054 HInstruction get index() => inputs[2]; 2065 HInstruction get index() => inputs[2];
2055 HInstruction get value() => inputs[3]; 2066 HInstruction get value() => inputs[3];
2056 2067
2057 HType computeDesiredInputType(HInstruction input) { 2068 HType computeDesiredInputType(HInstruction input) {
2058 // TODO(floitsch): we want the target to be a function. 2069 // TODO(floitsch): we want the target to be a function.
2059 if (input == target) return HType.UNKNOWN; 2070 if (input == target) return HType.UNKNOWN;
2060 if (input == receiver) return HType.ARRAY; 2071 if (input == receiver) return HType.MUTABLE_ARRAY;
2061 return HType.UNKNOWN; 2072 return HType.UNKNOWN;
2062 } 2073 }
2063 2074
2064 bool get builtin() => receiver.isArray(); 2075 bool get builtin() => receiver.isMutableArray();
2065 HType computeType() => value.type; 2076 HType computeType() => value.type;
2066 // This instruction does not yield a new value, so it always 2077 // This instruction does not yield a new value, so it always
2067 // has the expected type (void). 2078 // has the expected type (void).
2068 bool hasExpectedType() => true; 2079 bool hasExpectedType() => true;
2069 } 2080 }
2070 2081
2071 class HIs extends HInstruction { 2082 class HIs extends HInstruction {
2072 // TODO(ahe): This should be a Type, not Element. 2083 // TODO(ahe): This should be a Type, not Element.
2073 final Element typeExpression; 2084 final Element typeExpression;
2074 final bool nullOk; 2085 final bool nullOk;
(...skipping 14 matching lines...) Expand all
2089 class HIfBlockInformation { 2100 class HIfBlockInformation {
2090 final HIf branch; 2101 final HIf branch;
2091 final SubGraph thenGraph; 2102 final SubGraph thenGraph;
2092 final SubGraph elseGraph; 2103 final SubGraph elseGraph;
2093 final HBasicBlock joinBlock; 2104 final HBasicBlock joinBlock;
2094 HIfBlockInformation(this.branch, 2105 HIfBlockInformation(this.branch,
2095 this.thenGraph, 2106 this.thenGraph,
2096 this.elseGraph, 2107 this.elseGraph,
2097 this.joinBlock); 2108 this.joinBlock);
2098 } 2109 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/codegen.dart ('k') | lib/compiler/implementation/ssa/tracer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698