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

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

Issue 10825386: Use JavaScript runtime semantics when constant folding. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update status file. Created 8 years, 3 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
ngeoffray 2012/09/05 11:20:36 Move this file to the backend?
floitsch 2012/09/05 16:12:01 Left this file here. The Dart constant system is i
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();
6
5 interface Operation { 7 interface Operation {
6 final SourceString name; 8 final SourceString name;
7 bool isUserDefinable(); 9 bool isUserDefinable();
8 } 10 }
9 11
10 interface UnaryOperation extends Operation { 12 interface UnaryOperation extends Operation {
11 /** Returns [:null:] if it was unable to fold the operation. */ 13 /** Returns [:null:] if it was unable to fold the operation. */
12 Constant fold(Constant constant); 14 Constant fold(Constant constant);
13 } 15 }
14 16
15 class BitNotOperation implements UnaryOperation { 17 class BitNotOperation implements UnaryOperation {
16 final SourceString name = const SourceString('~'); 18 final SourceString name = const SourceString('~');
17 bool isUserDefinable() => true; 19 bool isUserDefinable() => true;
18 const BitNotOperation(); 20 const BitNotOperation();
19 Constant fold(Constant constant) { 21 Constant fold(Constant constant) {
20 if (constant.isInt()) { 22 if (constant.isInt()) {
21 IntConstant intConstant = constant; 23 IntConstant intConstant = constant;
22 return new IntConstant(~intConstant.value); 24 return DART_CONSTANT_SYSTEM.createInt(~intConstant.value);
23 } 25 }
24 return null; 26 return null;
25 } 27 }
26 } 28 }
27 29
28 class NegateOperation implements UnaryOperation { 30 class NegateOperation implements UnaryOperation {
29 final SourceString name = const SourceString('negate'); 31 final SourceString name = const SourceString('negate');
30 bool isUserDefinable() => true; 32 bool isUserDefinable() => true;
31 const NegateOperation(); 33 const NegateOperation();
32 Constant fold(Constant constant) { 34 Constant fold(Constant constant) {
33 if (constant.isInt()) { 35 if (constant.isInt()) {
34 IntConstant intConstant = constant; 36 IntConstant intConstant = constant;
35 return new IntConstant(-intConstant.value); 37 return DART_CONSTANT_SYSTEM.createInt(-intConstant.value);
36 } 38 }
37 if (constant.isDouble()) { 39 if (constant.isDouble()) {
38 DoubleConstant doubleConstant = constant; 40 DoubleConstant doubleConstant = constant;
39 return new DoubleConstant(-doubleConstant.value); 41 return DART_CONSTANT_SYSTEM.createDouble(-doubleConstant.value);
40 } 42 }
41 return null; 43 return null;
42 } 44 }
43 } 45 }
44 46
45 class NotOperation implements UnaryOperation { 47 class NotOperation implements UnaryOperation {
46 final SourceString name = const SourceString('!'); 48 final SourceString name = const SourceString('!');
47 bool isUserDefinable() => true; 49 bool isUserDefinable() => true;
48 const NotOperation(); 50 const NotOperation();
49 Constant fold(Constant constant) { 51 Constant fold(Constant constant) {
50 if (constant.isBool()) { 52 if (constant.isBool()) {
51 BoolConstant boolConstant = constant; 53 BoolConstant boolConstant = constant;
52 return boolConstant.negate(); 54 return DART_CONSTANT_SYSTEM.createBool(!boolConstant.value);
53 } 55 }
54 return null; 56 return null;
55 } 57 }
56 } 58 }
57 59
58 interface BinaryOperation extends Operation { 60 interface BinaryOperation extends Operation {
59 /** Returns [:null:] if it was unable to fold the operation. */ 61 /** Returns [:null:] if it was unable to fold the operation. */
60 Constant fold(Constant left, Constant right); 62 Constant fold(Constant left, Constant right);
61 } 63 }
62 64
63 /** 65 /**
64 * Operations that only work if both arguments are integers. 66 * Operations that only work if both arguments are integers.
65 */ 67 */
66 class BinaryIntOperation implements BinaryOperation { 68 class BinaryBitOperation implements BinaryOperation {
67 bool isUserDefinable() => true; 69 bool isUserDefinable() => true;
68 const BinaryIntOperation(); 70 const BinaryBitOperation();
69 Constant fold(Constant left, Constant right) { 71 Constant fold(Constant left, Constant right) {
70 if (left.isInt() && right.isInt()) { 72 if (left.isInt() && right.isInt()) {
71 IntConstant leftInt = left; 73 IntConstant leftInt = left;
72 IntConstant rightInt = right; 74 IntConstant rightInt = right;
73 int resultValue = foldInts(leftInt.value, rightInt.value); 75 int resultValue = foldInts(leftInt.value, rightInt.value);
74 if (resultValue === null) return null; 76 if (resultValue === null) return null;
75 return new IntConstant(resultValue); 77 return DART_CONSTANT_SYSTEM.createInt(resultValue);
76 } 78 }
77 return null; 79 return null;
78 } 80 }
79 81
80 abstract int foldInts(int left, int right); 82 abstract int foldInts(int left, int right);
81 } 83 }
82 84
83 class BitOrOperation extends BinaryIntOperation { 85 class BitOrOperation extends BinaryBitOperation {
84 final SourceString name = const SourceString('|'); 86 final SourceString name = const SourceString('|');
85 const BitOrOperation(); 87 const BitOrOperation();
86 int foldInts(int left, int right) => left | right; 88 int foldInts(int left, int right) => left | right;
87 } 89 }
88 90
89 class BitAndOperation extends BinaryIntOperation { 91 class BitAndOperation extends BinaryBitOperation {
90 final SourceString name = const SourceString('&'); 92 final SourceString name = const SourceString('&');
91 const BitAndOperation(); 93 const BitAndOperation();
92 int foldInts(int left, int right) => left & right; 94 int foldInts(int left, int right) => left & right;
93 } 95 }
94 96
95 class BitXorOperation extends BinaryIntOperation { 97 class BitXorOperation extends BinaryBitOperation {
96 final SourceString name = const SourceString('^'); 98 final SourceString name = const SourceString('^');
97 const BitXorOperation(); 99 const BitXorOperation();
98 int foldInts(int left, int right) => left ^ right; 100 int foldInts(int left, int right) => left ^ right;
99 } 101 }
100 102
101 class ShiftLeftOperation extends BinaryIntOperation { 103 class ShiftLeftOperation extends BinaryBitOperation {
102 final SourceString name = const SourceString('<<'); 104 final SourceString name = const SourceString('<<');
103 const ShiftLeftOperation(); 105 const ShiftLeftOperation();
104 int foldInts(int left, int right) { 106 int foldInts(int left, int right) {
105 // TODO(floitsch): find a better way to guard against excessive shifts to 107 // TODO(floitsch): find a better way to guard against excessive shifts to
106 // the left. 108 // the left.
107 if (right > 100 || right < 0) return null; 109 if (right > 100 || right < 0) return null;
108 return left << right; 110 return left << right;
109 } 111 }
110 } 112 }
111 113
112 class ShiftRightOperation extends BinaryIntOperation { 114 class ShiftRightOperation extends BinaryBitOperation {
113 final SourceString name = const SourceString('>>'); 115 final SourceString name = const SourceString('>>');
114 const ShiftRightOperation(); 116 const ShiftRightOperation();
115 int foldInts(int left, int right) { 117 int foldInts(int left, int right) {
116 if (right < 0) return null; 118 if (right < 0) return null;
117 return left >> right; 119 return left >> right;
118 } 120 }
119 } 121 }
120 122
121 class BinaryBoolOperation implements BinaryOperation { 123 class BinaryBoolOperation implements BinaryOperation {
122 bool isUserDefinable() => false; 124 bool isUserDefinable() => false;
123 const BinaryBoolOperation(); 125 const BinaryBoolOperation();
124 Constant fold(Constant left, Constant right) { 126 Constant fold(Constant left, Constant right) {
125 if (left.isBool() && right.isBool()) { 127 if (left.isBool() && right.isBool()) {
126 BoolConstant leftBool = left; 128 BoolConstant leftBool = left;
127 BoolConstant rightBool = right; 129 BoolConstant rightBool = right;
128 bool resultValue = foldBools(leftBool.value, rightBool.value); 130 bool resultValue = foldBools(leftBool.value, rightBool.value);
129 return new BoolConstant(resultValue); 131 return DART_CONSTANT_SYSTEM.createBool(resultValue);
130 } 132 }
131 return null; 133 return null;
132 } 134 }
133 135
134 abstract bool foldBools(bool left, bool right); 136 abstract bool foldBools(bool left, bool right);
135 } 137 }
136 138
137 class BooleanAnd extends BinaryBoolOperation { 139 class BooleanAndOperation extends BinaryBoolOperation {
138 final SourceString name = const SourceString('&&'); 140 final SourceString name = const SourceString('&&');
139 const BooleanAnd(); 141 const BooleanAndOperation();
140 bool foldBools(bool left, bool right) => left && right; 142 bool foldBools(bool left, bool right) => left && right;
141 } 143 }
142 144
143 class BooleanOr extends BinaryBoolOperation { 145 class BooleanOrOperation extends BinaryBoolOperation {
144 final SourceString name = const SourceString('||'); 146 final SourceString name = const SourceString('||');
145 const BooleanOr(); 147 const BooleanOrOperation();
146 bool foldBools(bool left, bool right) => left || right; 148 bool foldBools(bool left, bool right) => left || right;
147 } 149 }
148 150
149 class ArithmeticNumOperation implements BinaryOperation { 151 class ArithmeticNumOperation implements BinaryOperation {
150 bool isUserDefinable() => true; 152 bool isUserDefinable() => true;
151 const ArithmeticNumOperation(); 153 const ArithmeticNumOperation();
152 Constant fold(Constant left, Constant right) { 154 Constant fold(Constant left, Constant right) {
153 if (left.isNum() && right.isNum()) { 155 if (left.isNum() && right.isNum()) {
154 NumConstant leftNum = left; 156 NumConstant leftNum = left;
155 NumConstant rightNum = right; 157 NumConstant rightNum = right;
156 num foldedValue; 158 num foldedValue;
157 if (left.isInt() && right.isInt()) { 159 if (left.isInt() && right.isInt()) {
158 foldedValue = foldInts(leftNum.value, rightNum.value); 160 foldedValue = foldInts(leftNum.value, rightNum.value);
159 } else { 161 } else {
160 foldedValue = foldNums(leftNum.value, rightNum.value); 162 foldedValue = foldNums(leftNum.value, rightNum.value);
161 } 163 }
162 // A division by 0 means that we might not have a folded value. 164 // A division by 0 means that we might not have a folded value.
163 if (foldedValue === null) return null; 165 if (foldedValue === null) return null;
164 if (left.isInt() && right.isInt() && !isDivide()) { 166 if (left.isInt() && right.isInt() && !isDivide()) {
165 assert(foldedValue is int); 167 assert(foldedValue is int);
166 return new IntConstant(foldedValue); 168 return DART_CONSTANT_SYSTEM.createInt(foldedValue);
167 } else { 169 } else {
168 return new DoubleConstant(foldedValue); 170 return DART_CONSTANT_SYSTEM.createDouble(foldedValue);
169 } 171 }
170 } 172 }
171 return null; 173 return null;
172 } 174 }
173 175
174 bool isDivide() => false; 176 bool isDivide() => false;
175 num foldInts(int left, int right) => foldNums(left, right); 177 num foldInts(int left, int right) => foldNums(left, right);
176 abstract num foldNums(num left, num right); 178 abstract num foldNums(num left, num right);
177 } 179 }
178 180
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 } 218 }
217 219
218 class AddOperation implements BinaryOperation { 220 class AddOperation implements BinaryOperation {
219 final SourceString name = const SourceString('+'); 221 final SourceString name = const SourceString('+');
220 bool isUserDefinable() => true; 222 bool isUserDefinable() => true;
221 const AddOperation(); 223 const AddOperation();
222 Constant fold(Constant left, Constant right) { 224 Constant fold(Constant left, Constant right) {
223 if (left.isInt() && right.isInt()) { 225 if (left.isInt() && right.isInt()) {
224 IntConstant leftInt = left; 226 IntConstant leftInt = left;
225 IntConstant rightInt = right; 227 IntConstant rightInt = right;
226 return new IntConstant(leftInt.value + rightInt.value); 228 int result = leftInt.value + rightInt.value;
229 return DART_CONSTANT_SYSTEM.createInt(result);
227 } else if (left.isNum() && right.isNum()) { 230 } else if (left.isNum() && right.isNum()) {
228 NumConstant leftNum = left; 231 NumConstant leftNum = left;
229 NumConstant rightNum = right; 232 NumConstant rightNum = right;
230 return new DoubleConstant(leftNum.value + rightNum.value); 233 double result = leftNum.value + rightNum.value;
234 return DART_CONSTANT_SYSTEM.createDouble(result);
231 } else { 235 } else {
232 return null; 236 return null;
233 } 237 }
234 } 238 }
235 } 239 }
236 240
237 class RelationalNumOperation implements BinaryOperation { 241 class RelationalNumOperation implements BinaryOperation {
238 bool isUserDefinable() => true; 242 bool isUserDefinable() => true;
239 const RelationalNumOperation(); 243 const RelationalNumOperation();
240 Constant fold(Constant left, Constant right) { 244 Constant fold(Constant left, Constant right) {
241 if (left.isNum() && right.isNum()) { 245 if (left.isNum() && right.isNum()) {
242 NumConstant leftNum = left; 246 NumConstant leftNum = left;
243 NumConstant rightNum = right; 247 NumConstant rightNum = right;
244 bool foldedValue = foldNums(leftNum.value, rightNum.value); 248 bool foldedValue = foldNums(leftNum.value, rightNum.value);
245 assert(foldedValue != null); 249 assert(foldedValue != null);
246 return new BoolConstant(foldedValue); 250 return DART_CONSTANT_SYSTEM.createBool(foldedValue);
247 } 251 }
248 } 252 }
249 253
250 abstract bool foldNums(num left, num right); 254 abstract bool foldNums(num left, num right);
251 } 255 }
252 256
253 class LessOperation extends RelationalNumOperation { 257 class LessOperation extends RelationalNumOperation {
254 final SourceString name = const SourceString('<'); 258 final SourceString name = const SourceString('<');
255 const LessOperation(); 259 const LessOperation();
256 bool foldNums(num left, num right) => left < right; 260 bool foldNums(num left, num right) => left < right;
(...skipping 20 matching lines...) Expand all
277 class EqualsOperation implements BinaryOperation { 281 class EqualsOperation implements BinaryOperation {
278 final SourceString name = const SourceString('=='); 282 final SourceString name = const SourceString('==');
279 bool isUserDefinable() => true; 283 bool isUserDefinable() => true;
280 const EqualsOperation(); 284 const EqualsOperation();
281 Constant fold(Constant left, Constant right) { 285 Constant fold(Constant left, Constant right) {
282 if (left.isNum() && right.isNum()) { 286 if (left.isNum() && right.isNum()) {
283 // Numbers need to be treated specially because: NaN != NaN, -0.0 == 0.0, 287 // Numbers need to be treated specially because: NaN != NaN, -0.0 == 0.0,
284 // and 1 == 1.0. 288 // and 1 == 1.0.
285 NumConstant leftNum = left; 289 NumConstant leftNum = left;
286 NumConstant rightNum = right; 290 NumConstant rightNum = right;
287 return new BoolConstant(leftNum.value == rightNum.value); 291 bool result = leftNum.value == rightNum.value;
292 return DART_CONSTANT_SYSTEM.createBool(result);
288 } 293 }
289 if (left.isConstructedObject()) { 294 if (left.isConstructedObject()) {
290 // Unless we know that the user-defined object does not implement the 295 // Unless we know that the user-defined object does not implement the
291 // equality operator we cannot fold here. 296 // equality operator we cannot fold here.
292 return null; 297 return null;
293 } 298 }
294 return new BoolConstant(left == right); 299 return DART_CONSTANT_SYSTEM.createBool(left == right);
295 } 300 }
296 } 301 }
297 302
298 class IdentityOperation implements BinaryOperation { 303 class IdentityOperation implements BinaryOperation {
299 final SourceString name = const SourceString('==='); 304 final SourceString name = const SourceString('===');
300 bool isUserDefinable() => false; 305 bool isUserDefinable() => false;
301 const IdentityOperation(); 306 const IdentityOperation();
302 Constant fold(Constant left, Constant right) { 307 BoolConstant fold(Constant left, Constant right) {
303 // In order to preserve runtime semantics which says that NaN !== NaN don't 308 // In order to preserve runtime semantics which says that NaN !== NaN don't
304 // constant fold NaN === NaN. Otherwise the output depends on inlined 309 // constant fold NaN === NaN. Otherwise the output depends on inlined
305 // variables and other optimizations. 310 // variables and other optimizations.
306 if (left.isNaN() && right.isNaN()) return null; 311 if (left.isNaN() && right.isNaN()) return null;
307 return new BoolConstant(left == right); 312 return DART_CONSTANT_SYSTEM.createBool(left == right);
308 } 313 }
309 } 314 }
315
316 /**
317 * A [ConstantSystem] is responsible for creating constants and folding them.
318 */
319 interface ConstantSystem {
320 BinaryOperation get add();
321 BinaryOperation get bitAnd();
322 UnaryOperation get bitNot();
323 BinaryOperation get bitOr();
324 BinaryOperation get bitXor();
325 BinaryOperation get booleanAnd();
326 BinaryOperation get booleanOr();
327 BinaryOperation get divide();
328 BinaryOperation get equal();
329 BinaryOperation get greaterEqual();
330 BinaryOperation get greater();
331 BinaryOperation get identity();
332 BinaryOperation get lessEqual();
333 BinaryOperation get less();
334 BinaryOperation get modulo();
335 BinaryOperation get multiply();
336 UnaryOperation get negate();
337 UnaryOperation get not();
338 BinaryOperation get shiftLeft();
339 BinaryOperation get shiftRight();
340 BinaryOperation get subtract();
341 BinaryOperation get truncatingDivide();
342
343 Constant createInt(int i);
344 Constant createDouble(double d);
345 // We need a diagnostic node to report errors in case the string is malformed.
346 Constant createString(DartString string, Node diagnosticNode);
347 Constant createBool(bool value);
348 Constant createNull();
349
350 /** Returns true if the [constant] is an integer at runtime. */
351 bool isInt(Constant constant);
352 /** Returns true if the [constant] is a double at runtime. */
353 bool isDouble(Constant constant);
354 /** Returns true if the [constant] is a string at runtime. */
355 bool isString(Constant constant);
356 /** Returns true if the [constant] is a boolean at runtime. */
357 bool isBool(Constant constant);
358 /** Returns true if the [constant] is null at runtime. */
359 bool isNull(Constant constant);
360 }
361
362 /**
363 * A constant system implementing the Dart semantics. This system relies on
364 * the underlying runtime-system. That is, if dart2js is run in an environment
365 * that doesn't correctly implement Dart's semantics this constant system will
366 * not return the correct values.
367 */
368 class DartConstantSystem implements ConstantSystem {
369 const add = const AddOperation();
370 const bitAnd = const BitAndOperation();
371 const bitNot = const BitNotOperation();
372 const bitOr = const BitOrOperation();
373 const bitXor = const BitXorOperation();
374 const booleanAnd = const BooleanAndOperation();
375 const booleanOr = const BooleanOrOperation();
376 const divide = const DivideOperation();
377 const equal = const EqualsOperation();
378 const greaterEqual = const GreaterEqualOperation();
379 const greater = const GreaterOperation();
380 const identity = const IdentityOperation();
381 const lessEqual = const LessEqualOperation();
382 const less = const LessOperation();
383 const modulo = const ModuloOperation();
384 const multiply = const MultiplyOperation();
385 const negate = const NegateOperation();
386 const not = const NotOperation();
387 const shiftLeft = const ShiftLeftOperation();
388 const shiftRight = const ShiftRightOperation();
389 const subtract = const SubtractOperation();
390 const truncatingDivide = const TruncatingDivideOperation();
391
392 const DartConstantSystem();
393
394 IntConstant createInt(int i) => new IntConstant(i);
395 DoubleConstant createDouble(double d) => new DoubleConstant(d);
396 StringConstant createString(DartString string, Node diagnosticNode)
397 => new StringConstant(string, diagnosticNode);
398 BoolConstant createBool(bool value) => new BoolConstant(value);
399 NullConstant createNull() => new NullConstant();
400
401 bool isInt(Constant constant) => constant.isInt();
402 bool isDouble(Constant constant) => constant.isDouble();
403 bool isString(Constant constant) => constant.isString();
404 bool isBool(Constant constant) => constant.isBool();
405 bool isNull(Constant constant) => constant.isNull();
406 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698