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

Side by Side Diff: lib/compiler/implementation/constant_system_dart.dart

Issue 10968060: Add a value range analysis phase to remove bounds checks. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 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) 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 const DART_CONSTANT_SYSTEM = const DartConstantSystem(); 5 const DART_CONSTANT_SYSTEM = const DartConstantSystem();
6 6
7 class BitNotOperation implements UnaryOperation { 7 class BitNotOperation implements UnaryOperation {
8 final SourceString name = const SourceString('~'); 8 final SourceString name = const SourceString('~');
9 bool isUserDefinable() => true; 9 bool isUserDefinable() => true;
10 const BitNotOperation(); 10 const BitNotOperation();
11 Constant fold(Constant constant) { 11 Constant fold(Constant constant) {
12 if (constant.isInt()) { 12 if (constant.isInt()) {
13 IntConstant intConstant = constant; 13 IntConstant intConstant = constant;
14 return DART_CONSTANT_SYSTEM.createInt(~intConstant.value); 14 return DART_CONSTANT_SYSTEM.createInt(~intConstant.value);
15 } 15 }
16 return null; 16 return null;
17 } 17 }
18 apply(value) => ~value;
18 } 19 }
19 20
20 class NegateOperation implements UnaryOperation { 21 class NegateOperation implements UnaryOperation {
21 final SourceString name = const SourceString('negate'); 22 final SourceString name = const SourceString('negate');
22 bool isUserDefinable() => true; 23 bool isUserDefinable() => true;
23 const NegateOperation(); 24 const NegateOperation();
24 Constant fold(Constant constant) { 25 Constant fold(Constant constant) {
25 if (constant.isInt()) { 26 if (constant.isInt()) {
26 IntConstant intConstant = constant; 27 IntConstant intConstant = constant;
27 return DART_CONSTANT_SYSTEM.createInt(-intConstant.value); 28 return DART_CONSTANT_SYSTEM.createInt(-intConstant.value);
28 } 29 }
29 if (constant.isDouble()) { 30 if (constant.isDouble()) {
30 DoubleConstant doubleConstant = constant; 31 DoubleConstant doubleConstant = constant;
31 return DART_CONSTANT_SYSTEM.createDouble(-doubleConstant.value); 32 return DART_CONSTANT_SYSTEM.createDouble(-doubleConstant.value);
32 } 33 }
33 return null; 34 return null;
34 } 35 }
36 apply(value) => -value;
35 } 37 }
36 38
37 class NotOperation implements UnaryOperation { 39 class NotOperation implements UnaryOperation {
38 final SourceString name = const SourceString('!'); 40 final SourceString name = const SourceString('!');
39 bool isUserDefinable() => true; 41 bool isUserDefinable() => true;
40 const NotOperation(); 42 const NotOperation();
41 Constant fold(Constant constant) { 43 Constant fold(Constant constant) {
42 if (constant.isBool()) { 44 if (constant.isBool()) {
43 BoolConstant boolConstant = constant; 45 BoolConstant boolConstant = constant;
44 return DART_CONSTANT_SYSTEM.createBool(!boolConstant.value); 46 return DART_CONSTANT_SYSTEM.createBool(!boolConstant.value);
45 } 47 }
46 return null; 48 return null;
47 } 49 }
50 apply(value) => !value;
48 } 51 }
49 52
50 /** 53 /**
51 * Operations that only work if both arguments are integers. 54 * Operations that only work if both arguments are integers.
52 */ 55 */
53 class BinaryBitOperation implements BinaryOperation { 56 class BinaryBitOperation implements BinaryOperation {
54 bool isUserDefinable() => true; 57 bool isUserDefinable() => true;
55 const BinaryBitOperation(); 58 const BinaryBitOperation();
56 Constant fold(Constant left, Constant right) { 59 Constant fold(Constant left, Constant right) {
57 if (left.isInt() && right.isInt()) { 60 if (left.isInt() && right.isInt()) {
58 IntConstant leftInt = left; 61 IntConstant leftInt = left;
59 IntConstant rightInt = right; 62 IntConstant rightInt = right;
60 int resultValue = foldInts(leftInt.value, rightInt.value); 63 int resultValue = foldInts(leftInt.value, rightInt.value);
61 if (resultValue === null) return null; 64 if (resultValue === null) return null;
62 return DART_CONSTANT_SYSTEM.createInt(resultValue); 65 return DART_CONSTANT_SYSTEM.createInt(resultValue);
63 } 66 }
64 return null; 67 return null;
65 } 68 }
66 69
67 abstract int foldInts(int left, int right); 70 abstract int foldInts(int left, int right);
68 } 71 }
69 72
70 class BitOrOperation extends BinaryBitOperation { 73 class BitOrOperation extends BinaryBitOperation {
71 final SourceString name = const SourceString('|'); 74 final SourceString name = const SourceString('|');
72 const BitOrOperation(); 75 const BitOrOperation();
73 int foldInts(int left, int right) => left | right; 76 int foldInts(int left, int right) => left | right;
77 apply(left, right) => left | right;
74 } 78 }
75 79
76 class BitAndOperation extends BinaryBitOperation { 80 class BitAndOperation extends BinaryBitOperation {
77 final SourceString name = const SourceString('&'); 81 final SourceString name = const SourceString('&');
78 const BitAndOperation(); 82 const BitAndOperation();
79 int foldInts(int left, int right) => left & right; 83 int foldInts(int left, int right) => left & right;
84 apply(left, right) => left & right;
80 } 85 }
81 86
82 class BitXorOperation extends BinaryBitOperation { 87 class BitXorOperation extends BinaryBitOperation {
83 final SourceString name = const SourceString('^'); 88 final SourceString name = const SourceString('^');
84 const BitXorOperation(); 89 const BitXorOperation();
85 int foldInts(int left, int right) => left ^ right; 90 int foldInts(int left, int right) => left ^ right;
91 apply(left, right) => left ^ right;
86 } 92 }
87 93
88 class ShiftLeftOperation extends BinaryBitOperation { 94 class ShiftLeftOperation extends BinaryBitOperation {
89 final SourceString name = const SourceString('<<'); 95 final SourceString name = const SourceString('<<');
90 const ShiftLeftOperation(); 96 const ShiftLeftOperation();
91 int foldInts(int left, int right) { 97 int foldInts(int left, int right) {
92 // TODO(floitsch): find a better way to guard against excessive shifts to 98 // TODO(floitsch): find a better way to guard against excessive shifts to
93 // the left. 99 // the left.
94 if (right > 100 || right < 0) return null; 100 if (right > 100 || right < 0) return null;
95 return left << right; 101 return left << right;
96 } 102 }
103 apply(left, right) => left << right;
97 } 104 }
98 105
99 class ShiftRightOperation extends BinaryBitOperation { 106 class ShiftRightOperation extends BinaryBitOperation {
100 final SourceString name = const SourceString('>>'); 107 final SourceString name = const SourceString('>>');
101 const ShiftRightOperation(); 108 const ShiftRightOperation();
102 int foldInts(int left, int right) { 109 int foldInts(int left, int right) {
103 if (right < 0) return null; 110 if (right < 0) return null;
104 return left >> right; 111 return left >> right;
105 } 112 }
113 apply(left, right) => left >> right;
106 } 114 }
107 115
108 class BinaryBoolOperation implements BinaryOperation { 116 class BinaryBoolOperation implements BinaryOperation {
109 bool isUserDefinable() => false; 117 bool isUserDefinable() => false;
110 const BinaryBoolOperation(); 118 const BinaryBoolOperation();
111 Constant fold(Constant left, Constant right) { 119 Constant fold(Constant left, Constant right) {
112 if (left.isBool() && right.isBool()) { 120 if (left.isBool() && right.isBool()) {
113 BoolConstant leftBool = left; 121 BoolConstant leftBool = left;
114 BoolConstant rightBool = right; 122 BoolConstant rightBool = right;
115 bool resultValue = foldBools(leftBool.value, rightBool.value); 123 bool resultValue = foldBools(leftBool.value, rightBool.value);
116 return DART_CONSTANT_SYSTEM.createBool(resultValue); 124 return DART_CONSTANT_SYSTEM.createBool(resultValue);
117 } 125 }
118 return null; 126 return null;
119 } 127 }
120 128
121 abstract bool foldBools(bool left, bool right); 129 abstract bool foldBools(bool left, bool right);
122 } 130 }
123 131
124 class BooleanAndOperation extends BinaryBoolOperation { 132 class BooleanAndOperation extends BinaryBoolOperation {
125 final SourceString name = const SourceString('&&'); 133 final SourceString name = const SourceString('&&');
126 const BooleanAndOperation(); 134 const BooleanAndOperation();
127 bool foldBools(bool left, bool right) => left && right; 135 bool foldBools(bool left, bool right) => left && right;
136 apply(left, right) => left && right;
128 } 137 }
129 138
130 class BooleanOrOperation extends BinaryBoolOperation { 139 class BooleanOrOperation extends BinaryBoolOperation {
131 final SourceString name = const SourceString('||'); 140 final SourceString name = const SourceString('||');
132 const BooleanOrOperation(); 141 const BooleanOrOperation();
133 bool foldBools(bool left, bool right) => left || right; 142 bool foldBools(bool left, bool right) => left || right;
143 apply(left, right) => left || right;
134 } 144 }
135 145
136 class ArithmeticNumOperation implements BinaryOperation { 146 class ArithmeticNumOperation implements BinaryOperation {
137 bool isUserDefinable() => true; 147 bool isUserDefinable() => true;
138 const ArithmeticNumOperation(); 148 const ArithmeticNumOperation();
139 Constant fold(Constant left, Constant right) { 149 Constant fold(Constant left, Constant right) {
140 if (left.isNum() && right.isNum()) { 150 if (left.isNum() && right.isNum()) {
141 NumConstant leftNum = left; 151 NumConstant leftNum = left;
142 NumConstant rightNum = right; 152 NumConstant rightNum = right;
143 num foldedValue; 153 num foldedValue;
(...skipping 16 matching lines...) Expand all
160 170
161 bool isDivide() => false; 171 bool isDivide() => false;
162 num foldInts(int left, int right) => foldNums(left, right); 172 num foldInts(int left, int right) => foldNums(left, right);
163 abstract num foldNums(num left, num right); 173 abstract num foldNums(num left, num right);
164 } 174 }
165 175
166 class SubtractOperation extends ArithmeticNumOperation { 176 class SubtractOperation extends ArithmeticNumOperation {
167 final SourceString name = const SourceString('-'); 177 final SourceString name = const SourceString('-');
168 const SubtractOperation(); 178 const SubtractOperation();
169 num foldNums(num left, num right) => left - right; 179 num foldNums(num left, num right) => left - right;
180 apply(left, right) => left - right;
170 } 181 }
171 182
172 class MultiplyOperation extends ArithmeticNumOperation { 183 class MultiplyOperation extends ArithmeticNumOperation {
173 final SourceString name = const SourceString('*'); 184 final SourceString name = const SourceString('*');
174 const MultiplyOperation(); 185 const MultiplyOperation();
175 num foldNums(num left, num right) => left * right; 186 num foldNums(num left, num right) => left * right;
187 apply(left, right) => left * right;
176 } 188 }
177 189
178 class ModuloOperation extends ArithmeticNumOperation { 190 class ModuloOperation extends ArithmeticNumOperation {
179 final SourceString name = const SourceString('%'); 191 final SourceString name = const SourceString('%');
180 const ModuloOperation(); 192 const ModuloOperation();
181 int foldInts(int left, int right) { 193 int foldInts(int left, int right) {
182 if (right == 0) return null; 194 if (right == 0) return null;
183 return left % right; 195 return left % right;
184 } 196 }
185 num foldNums(num left, num right) => left % right; 197 num foldNums(num left, num right) => left % right;
198 apply(left, right) => left % right;
186 } 199 }
187 200
188 class TruncatingDivideOperation extends ArithmeticNumOperation { 201 class TruncatingDivideOperation extends ArithmeticNumOperation {
189 final SourceString name = const SourceString('~/'); 202 final SourceString name = const SourceString('~/');
190 const TruncatingDivideOperation(); 203 const TruncatingDivideOperation();
191 int foldInts(int left, int right) { 204 int foldInts(int left, int right) {
192 if (right == 0) return null; 205 if (right == 0) return null;
193 return left ~/ right; 206 return left ~/ right;
194 } 207 }
195 num foldNums(num left, num right) => left ~/ right; 208 num foldNums(num left, num right) => left ~/ right;
209 apply(left, right) => left ~/ right;
196 } 210 }
197 211
198 class DivideOperation extends ArithmeticNumOperation { 212 class DivideOperation extends ArithmeticNumOperation {
199 final SourceString name = const SourceString('/'); 213 final SourceString name = const SourceString('/');
200 const DivideOperation(); 214 const DivideOperation();
201 num foldNums(num left, num right) => left / right; 215 num foldNums(num left, num right) => left / right;
202 bool isDivide() => true; 216 bool isDivide() => true;
217 apply(left, right) => left / right;
203 } 218 }
204 219
205 class AddOperation implements BinaryOperation { 220 class AddOperation implements BinaryOperation {
206 final SourceString name = const SourceString('+'); 221 final SourceString name = const SourceString('+');
207 bool isUserDefinable() => true; 222 bool isUserDefinable() => true;
208 const AddOperation(); 223 const AddOperation();
209 Constant fold(Constant left, Constant right) { 224 Constant fold(Constant left, Constant right) {
210 if (left.isInt() && right.isInt()) { 225 if (left.isInt() && right.isInt()) {
211 IntConstant leftInt = left; 226 IntConstant leftInt = left;
212 IntConstant rightInt = right; 227 IntConstant rightInt = right;
213 int result = leftInt.value + rightInt.value; 228 int result = leftInt.value + rightInt.value;
214 return DART_CONSTANT_SYSTEM.createInt(result); 229 return DART_CONSTANT_SYSTEM.createInt(result);
215 } else if (left.isNum() && right.isNum()) { 230 } else if (left.isNum() && right.isNum()) {
216 NumConstant leftNum = left; 231 NumConstant leftNum = left;
217 NumConstant rightNum = right; 232 NumConstant rightNum = right;
218 double result = leftNum.value + rightNum.value; 233 double result = leftNum.value + rightNum.value;
219 return DART_CONSTANT_SYSTEM.createDouble(result); 234 return DART_CONSTANT_SYSTEM.createDouble(result);
220 } else { 235 } else {
221 return null; 236 return null;
222 } 237 }
223 } 238 }
239 apply(left, right) => left + right;
224 } 240 }
225 241
226 class RelationalNumOperation implements BinaryOperation { 242 class RelationalNumOperation implements BinaryOperation {
227 bool isUserDefinable() => true; 243 bool isUserDefinable() => true;
228 const RelationalNumOperation(); 244 const RelationalNumOperation();
229 Constant fold(Constant left, Constant right) { 245 Constant fold(Constant left, Constant right) {
230 if (left.isNum() && right.isNum()) { 246 if (left.isNum() && right.isNum()) {
231 NumConstant leftNum = left; 247 NumConstant leftNum = left;
232 NumConstant rightNum = right; 248 NumConstant rightNum = right;
233 bool foldedValue = foldNums(leftNum.value, rightNum.value); 249 bool foldedValue = foldNums(leftNum.value, rightNum.value);
234 assert(foldedValue != null); 250 assert(foldedValue != null);
235 return DART_CONSTANT_SYSTEM.createBool(foldedValue); 251 return DART_CONSTANT_SYSTEM.createBool(foldedValue);
236 } 252 }
237 } 253 }
238 254
239 abstract bool foldNums(num left, num right); 255 abstract bool foldNums(num left, num right);
240 } 256 }
241 257
242 class LessOperation extends RelationalNumOperation { 258 class LessOperation extends RelationalNumOperation {
243 final SourceString name = const SourceString('<'); 259 final SourceString name = const SourceString('<');
244 const LessOperation(); 260 const LessOperation();
245 bool foldNums(num left, num right) => left < right; 261 bool foldNums(num left, num right) => left < right;
262 apply(left, right) => left < right;
246 } 263 }
247 264
248 class LessEqualOperation extends RelationalNumOperation { 265 class LessEqualOperation extends RelationalNumOperation {
249 final SourceString name = const SourceString('<='); 266 final SourceString name = const SourceString('<=');
250 const LessEqualOperation(); 267 const LessEqualOperation();
251 bool foldNums(num left, num right) => left <= right; 268 bool foldNums(num left, num right) => left <= right;
269 apply(left, right) => left <= right;
252 } 270 }
253 271
254 class GreaterOperation extends RelationalNumOperation { 272 class GreaterOperation extends RelationalNumOperation {
255 final SourceString name = const SourceString('>'); 273 final SourceString name = const SourceString('>');
256 const GreaterOperation(); 274 const GreaterOperation();
257 bool foldNums(num left, num right) => left > right; 275 bool foldNums(num left, num right) => left > right;
276 apply(left, right) => left > right;
258 } 277 }
259 278
260 class GreaterEqualOperation extends RelationalNumOperation { 279 class GreaterEqualOperation extends RelationalNumOperation {
261 final SourceString name = const SourceString('>='); 280 final SourceString name = const SourceString('>=');
262 const GreaterEqualOperation(); 281 const GreaterEqualOperation();
263 bool foldNums(num left, num right) => left >= right; 282 bool foldNums(num left, num right) => left >= right;
283 apply(left, right) => left <= right;
264 } 284 }
265 285
266 class EqualsOperation implements BinaryOperation { 286 class EqualsOperation implements BinaryOperation {
267 final SourceString name = const SourceString('=='); 287 final SourceString name = const SourceString('==');
268 bool isUserDefinable() => true; 288 bool isUserDefinable() => true;
269 const EqualsOperation(); 289 const EqualsOperation();
270 Constant fold(Constant left, Constant right) { 290 Constant fold(Constant left, Constant right) {
271 if (left.isNum() && right.isNum()) { 291 if (left.isNum() && right.isNum()) {
272 // Numbers need to be treated specially because: NaN != NaN, -0.0 == 0.0, 292 // Numbers need to be treated specially because: NaN != NaN, -0.0 == 0.0,
273 // and 1 == 1.0. 293 // and 1 == 1.0.
274 NumConstant leftNum = left; 294 NumConstant leftNum = left;
275 NumConstant rightNum = right; 295 NumConstant rightNum = right;
276 bool result = leftNum.value == rightNum.value; 296 bool result = leftNum.value == rightNum.value;
277 return DART_CONSTANT_SYSTEM.createBool(result); 297 return DART_CONSTANT_SYSTEM.createBool(result);
278 } 298 }
279 if (left.isConstructedObject()) { 299 if (left.isConstructedObject()) {
280 // Unless we know that the user-defined object does not implement the 300 // Unless we know that the user-defined object does not implement the
281 // equality operator we cannot fold here. 301 // equality operator we cannot fold here.
282 return null; 302 return null;
283 } 303 }
284 return DART_CONSTANT_SYSTEM.createBool(left == right); 304 return DART_CONSTANT_SYSTEM.createBool(left == right);
285 } 305 }
306 apply(left, right) => left == right;
286 } 307 }
287 308
288 class IdentityOperation implements BinaryOperation { 309 class IdentityOperation implements BinaryOperation {
289 final SourceString name = const SourceString('==='); 310 final SourceString name = const SourceString('===');
290 bool isUserDefinable() => false; 311 bool isUserDefinable() => false;
291 const IdentityOperation(); 312 const IdentityOperation();
292 BoolConstant fold(Constant left, Constant right) { 313 BoolConstant fold(Constant left, Constant right) {
293 // In order to preserve runtime semantics which says that NaN !== NaN don't 314 // In order to preserve runtime semantics which says that NaN !== NaN don't
294 // constant fold NaN === NaN. Otherwise the output depends on inlined 315 // constant fold NaN === NaN. Otherwise the output depends on inlined
295 // variables and other optimizations. 316 // variables and other optimizations.
296 if (left.isNaN() && right.isNaN()) return null; 317 if (left.isNaN() && right.isNaN()) return null;
297 return DART_CONSTANT_SYSTEM.createBool(left == right); 318 return DART_CONSTANT_SYSTEM.createBool(left == right);
298 } 319 }
320 apply(left, right) => left === right;
299 } 321 }
300 322
301 /** 323 /**
302 * A constant system implementing the Dart semantics. This system relies on 324 * A constant system implementing the Dart semantics. This system relies on
303 * the underlying runtime-system. That is, if dart2js is run in an environment 325 * the underlying runtime-system. That is, if dart2js is run in an environment
304 * that doesn't correctly implement Dart's semantics this constant system will 326 * that doesn't correctly implement Dart's semantics this constant system will
305 * not return the correct values. 327 * not return the correct values.
306 */ 328 */
307 class DartConstantSystem implements ConstantSystem { 329 class DartConstantSystem implements ConstantSystem {
308 const add = const AddOperation(); 330 const add = const AddOperation();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 bool isInt(Constant constant) => constant.isInt(); 362 bool isInt(Constant constant) => constant.isInt();
341 bool isDouble(Constant constant) => constant.isDouble(); 363 bool isDouble(Constant constant) => constant.isDouble();
342 bool isString(Constant constant) => constant.isString(); 364 bool isString(Constant constant) => constant.isString();
343 bool isBool(Constant constant) => constant.isBool(); 365 bool isBool(Constant constant) => constant.isBool();
344 bool isNull(Constant constant) => constant.isNull(); 366 bool isNull(Constant constant) => constant.isNull();
345 367
346 bool isSubtype(Compiler compiler, DartType s, DartType t) { 368 bool isSubtype(Compiler compiler, DartType s, DartType t) {
347 return compiler.types.isSubtype(s, t); 369 return compiler.types.isSubtype(s, t);
348 } 370 }
349 } 371 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698