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

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: Address comments. 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
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 Operation { 5 const DART_CONSTANT_SYSTEM = const DartConstantSystem();
6 final SourceString name;
7 bool isUserDefinable();
8 }
9
10 interface UnaryOperation extends Operation {
11 /** Returns [:null:] if it was unable to fold the operation. */
12 Constant fold(Constant constant);
13 }
14 6
15 class BitNotOperation implements UnaryOperation { 7 class BitNotOperation implements UnaryOperation {
16 final SourceString name = const SourceString('~'); 8 final SourceString name = const SourceString('~');
17 bool isUserDefinable() => true; 9 bool isUserDefinable() => true;
18 const BitNotOperation(); 10 const BitNotOperation();
19 Constant fold(Constant constant) { 11 Constant fold(Constant constant) {
20 if (constant.isInt()) { 12 if (constant.isInt()) {
21 IntConstant intConstant = constant; 13 IntConstant intConstant = constant;
22 return new IntConstant(~intConstant.value); 14 return DART_CONSTANT_SYSTEM.createInt(~intConstant.value);
23 } 15 }
24 return null; 16 return null;
25 } 17 }
26 } 18 }
27 19
28 class NegateOperation implements UnaryOperation { 20 class NegateOperation implements UnaryOperation {
29 final SourceString name = const SourceString('negate'); 21 final SourceString name = const SourceString('negate');
30 bool isUserDefinable() => true; 22 bool isUserDefinable() => true;
31 const NegateOperation(); 23 const NegateOperation();
32 Constant fold(Constant constant) { 24 Constant fold(Constant constant) {
33 if (constant.isInt()) { 25 if (constant.isInt()) {
34 IntConstant intConstant = constant; 26 IntConstant intConstant = constant;
35 return new IntConstant(-intConstant.value); 27 return DART_CONSTANT_SYSTEM.createInt(-intConstant.value);
36 } 28 }
37 if (constant.isDouble()) { 29 if (constant.isDouble()) {
38 DoubleConstant doubleConstant = constant; 30 DoubleConstant doubleConstant = constant;
39 return new DoubleConstant(-doubleConstant.value); 31 return DART_CONSTANT_SYSTEM.createDouble(-doubleConstant.value);
40 } 32 }
41 return null; 33 return null;
42 } 34 }
43 } 35 }
44 36
45 class NotOperation implements UnaryOperation { 37 class NotOperation implements UnaryOperation {
46 final SourceString name = const SourceString('!'); 38 final SourceString name = const SourceString('!');
47 bool isUserDefinable() => true; 39 bool isUserDefinable() => true;
48 const NotOperation(); 40 const NotOperation();
49 Constant fold(Constant constant) { 41 Constant fold(Constant constant) {
50 if (constant.isBool()) { 42 if (constant.isBool()) {
51 BoolConstant boolConstant = constant; 43 BoolConstant boolConstant = constant;
52 return boolConstant.negate(); 44 return DART_CONSTANT_SYSTEM.createBool(!boolConstant.value);
53 } 45 }
54 return null; 46 return null;
55 } 47 }
56 } 48 }
57 49
58 interface BinaryOperation extends Operation {
59 /** Returns [:null:] if it was unable to fold the operation. */
60 Constant fold(Constant left, Constant right);
61 }
62
63 /** 50 /**
64 * Operations that only work if both arguments are integers. 51 * Operations that only work if both arguments are integers.
65 */ 52 */
66 class BinaryIntOperation implements BinaryOperation { 53 class BinaryBitOperation implements BinaryOperation {
67 bool isUserDefinable() => true; 54 bool isUserDefinable() => true;
68 const BinaryIntOperation(); 55 const BinaryBitOperation();
69 Constant fold(Constant left, Constant right) { 56 Constant fold(Constant left, Constant right) {
70 if (left.isInt() && right.isInt()) { 57 if (left.isInt() && right.isInt()) {
71 IntConstant leftInt = left; 58 IntConstant leftInt = left;
72 IntConstant rightInt = right; 59 IntConstant rightInt = right;
73 int resultValue = foldInts(leftInt.value, rightInt.value); 60 int resultValue = foldInts(leftInt.value, rightInt.value);
74 if (resultValue === null) return null; 61 if (resultValue === null) return null;
75 return new IntConstant(resultValue); 62 return DART_CONSTANT_SYSTEM.createInt(resultValue);
76 } 63 }
77 return null; 64 return null;
78 } 65 }
79 66
80 abstract int foldInts(int left, int right); 67 abstract int foldInts(int left, int right);
81 } 68 }
82 69
83 class BitOrOperation extends BinaryIntOperation { 70 class BitOrOperation extends BinaryBitOperation {
84 final SourceString name = const SourceString('|'); 71 final SourceString name = const SourceString('|');
85 const BitOrOperation(); 72 const BitOrOperation();
86 int foldInts(int left, int right) => left | right; 73 int foldInts(int left, int right) => left | right;
87 } 74 }
88 75
89 class BitAndOperation extends BinaryIntOperation { 76 class BitAndOperation extends BinaryBitOperation {
90 final SourceString name = const SourceString('&'); 77 final SourceString name = const SourceString('&');
91 const BitAndOperation(); 78 const BitAndOperation();
92 int foldInts(int left, int right) => left & right; 79 int foldInts(int left, int right) => left & right;
93 } 80 }
94 81
95 class BitXorOperation extends BinaryIntOperation { 82 class BitXorOperation extends BinaryBitOperation {
96 final SourceString name = const SourceString('^'); 83 final SourceString name = const SourceString('^');
97 const BitXorOperation(); 84 const BitXorOperation();
98 int foldInts(int left, int right) => left ^ right; 85 int foldInts(int left, int right) => left ^ right;
99 } 86 }
100 87
101 class ShiftLeftOperation extends BinaryIntOperation { 88 class ShiftLeftOperation extends BinaryBitOperation {
102 final SourceString name = const SourceString('<<'); 89 final SourceString name = const SourceString('<<');
103 const ShiftLeftOperation(); 90 const ShiftLeftOperation();
104 int foldInts(int left, int right) { 91 int foldInts(int left, int right) {
105 // TODO(floitsch): find a better way to guard against excessive shifts to 92 // TODO(floitsch): find a better way to guard against excessive shifts to
106 // the left. 93 // the left.
107 if (right > 100 || right < 0) return null; 94 if (right > 100 || right < 0) return null;
108 return left << right; 95 return left << right;
109 } 96 }
110 } 97 }
111 98
112 class ShiftRightOperation extends BinaryIntOperation { 99 class ShiftRightOperation extends BinaryBitOperation {
113 final SourceString name = const SourceString('>>'); 100 final SourceString name = const SourceString('>>');
114 const ShiftRightOperation(); 101 const ShiftRightOperation();
115 int foldInts(int left, int right) { 102 int foldInts(int left, int right) {
116 if (right < 0) return null; 103 if (right < 0) return null;
117 return left >> right; 104 return left >> right;
118 } 105 }
119 } 106 }
120 107
121 class BinaryBoolOperation implements BinaryOperation { 108 class BinaryBoolOperation implements BinaryOperation {
122 bool isUserDefinable() => false; 109 bool isUserDefinable() => false;
123 const BinaryBoolOperation(); 110 const BinaryBoolOperation();
124 Constant fold(Constant left, Constant right) { 111 Constant fold(Constant left, Constant right) {
125 if (left.isBool() && right.isBool()) { 112 if (left.isBool() && right.isBool()) {
126 BoolConstant leftBool = left; 113 BoolConstant leftBool = left;
127 BoolConstant rightBool = right; 114 BoolConstant rightBool = right;
128 bool resultValue = foldBools(leftBool.value, rightBool.value); 115 bool resultValue = foldBools(leftBool.value, rightBool.value);
129 return new BoolConstant(resultValue); 116 return DART_CONSTANT_SYSTEM.createBool(resultValue);
130 } 117 }
131 return null; 118 return null;
132 } 119 }
133 120
134 abstract bool foldBools(bool left, bool right); 121 abstract bool foldBools(bool left, bool right);
135 } 122 }
136 123
137 class BooleanAnd extends BinaryBoolOperation { 124 class BooleanAndOperation extends BinaryBoolOperation {
138 final SourceString name = const SourceString('&&'); 125 final SourceString name = const SourceString('&&');
139 const BooleanAnd(); 126 const BooleanAndOperation();
140 bool foldBools(bool left, bool right) => left && right; 127 bool foldBools(bool left, bool right) => left && right;
141 } 128 }
142 129
143 class BooleanOr extends BinaryBoolOperation { 130 class BooleanOrOperation extends BinaryBoolOperation {
144 final SourceString name = const SourceString('||'); 131 final SourceString name = const SourceString('||');
145 const BooleanOr(); 132 const BooleanOrOperation();
146 bool foldBools(bool left, bool right) => left || right; 133 bool foldBools(bool left, bool right) => left || right;
147 } 134 }
148 135
149 class ArithmeticNumOperation implements BinaryOperation { 136 class ArithmeticNumOperation implements BinaryOperation {
150 bool isUserDefinable() => true; 137 bool isUserDefinable() => true;
151 const ArithmeticNumOperation(); 138 const ArithmeticNumOperation();
152 Constant fold(Constant left, Constant right) { 139 Constant fold(Constant left, Constant right) {
153 if (left.isNum() && right.isNum()) { 140 if (left.isNum() && right.isNum()) {
154 NumConstant leftNum = left; 141 NumConstant leftNum = left;
155 NumConstant rightNum = right; 142 NumConstant rightNum = right;
156 num foldedValue; 143 num foldedValue;
157 if (left.isInt() && right.isInt()) { 144 if (left.isInt() && right.isInt()) {
158 foldedValue = foldInts(leftNum.value, rightNum.value); 145 foldedValue = foldInts(leftNum.value, rightNum.value);
159 } else { 146 } else {
160 foldedValue = foldNums(leftNum.value, rightNum.value); 147 foldedValue = foldNums(leftNum.value, rightNum.value);
161 } 148 }
162 // A division by 0 means that we might not have a folded value. 149 // A division by 0 means that we might not have a folded value.
163 if (foldedValue === null) return null; 150 if (foldedValue === null) return null;
164 if (left.isInt() && right.isInt() && !isDivide()) { 151 if (left.isInt() && right.isInt() && !isDivide()) {
165 assert(foldedValue is int); 152 assert(foldedValue is int);
166 return new IntConstant(foldedValue); 153 return DART_CONSTANT_SYSTEM.createInt(foldedValue);
167 } else { 154 } else {
168 return new DoubleConstant(foldedValue); 155 return DART_CONSTANT_SYSTEM.createDouble(foldedValue);
169 } 156 }
170 } 157 }
171 return null; 158 return null;
172 } 159 }
173 160
174 bool isDivide() => false; 161 bool isDivide() => false;
175 num foldInts(int left, int right) => foldNums(left, right); 162 num foldInts(int left, int right) => foldNums(left, right);
176 abstract num foldNums(num left, num right); 163 abstract num foldNums(num left, num right);
177 } 164 }
178 165
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 } 203 }
217 204
218 class AddOperation implements BinaryOperation { 205 class AddOperation implements BinaryOperation {
219 final SourceString name = const SourceString('+'); 206 final SourceString name = const SourceString('+');
220 bool isUserDefinable() => true; 207 bool isUserDefinable() => true;
221 const AddOperation(); 208 const AddOperation();
222 Constant fold(Constant left, Constant right) { 209 Constant fold(Constant left, Constant right) {
223 if (left.isInt() && right.isInt()) { 210 if (left.isInt() && right.isInt()) {
224 IntConstant leftInt = left; 211 IntConstant leftInt = left;
225 IntConstant rightInt = right; 212 IntConstant rightInt = right;
226 return new IntConstant(leftInt.value + rightInt.value); 213 int result = leftInt.value + rightInt.value;
214 return DART_CONSTANT_SYSTEM.createInt(result);
227 } else if (left.isNum() && right.isNum()) { 215 } else if (left.isNum() && right.isNum()) {
228 NumConstant leftNum = left; 216 NumConstant leftNum = left;
229 NumConstant rightNum = right; 217 NumConstant rightNum = right;
230 return new DoubleConstant(leftNum.value + rightNum.value); 218 double result = leftNum.value + rightNum.value;
219 return DART_CONSTANT_SYSTEM.createDouble(result);
231 } else { 220 } else {
232 return null; 221 return null;
233 } 222 }
234 } 223 }
235 } 224 }
236 225
237 class RelationalNumOperation implements BinaryOperation { 226 class RelationalNumOperation implements BinaryOperation {
238 bool isUserDefinable() => true; 227 bool isUserDefinable() => true;
239 const RelationalNumOperation(); 228 const RelationalNumOperation();
240 Constant fold(Constant left, Constant right) { 229 Constant fold(Constant left, Constant right) {
241 if (left.isNum() && right.isNum()) { 230 if (left.isNum() && right.isNum()) {
242 NumConstant leftNum = left; 231 NumConstant leftNum = left;
243 NumConstant rightNum = right; 232 NumConstant rightNum = right;
244 bool foldedValue = foldNums(leftNum.value, rightNum.value); 233 bool foldedValue = foldNums(leftNum.value, rightNum.value);
245 assert(foldedValue != null); 234 assert(foldedValue != null);
246 return new BoolConstant(foldedValue); 235 return DART_CONSTANT_SYSTEM.createBool(foldedValue);
247 } 236 }
248 } 237 }
249 238
250 abstract bool foldNums(num left, num right); 239 abstract bool foldNums(num left, num right);
251 } 240 }
252 241
253 class LessOperation extends RelationalNumOperation { 242 class LessOperation extends RelationalNumOperation {
254 final SourceString name = const SourceString('<'); 243 final SourceString name = const SourceString('<');
255 const LessOperation(); 244 const LessOperation();
256 bool foldNums(num left, num right) => left < right; 245 bool foldNums(num left, num right) => left < right;
(...skipping 20 matching lines...) Expand all
277 class EqualsOperation implements BinaryOperation { 266 class EqualsOperation implements BinaryOperation {
278 final SourceString name = const SourceString('=='); 267 final SourceString name = const SourceString('==');
279 bool isUserDefinable() => true; 268 bool isUserDefinable() => true;
280 const EqualsOperation(); 269 const EqualsOperation();
281 Constant fold(Constant left, Constant right) { 270 Constant fold(Constant left, Constant right) {
282 if (left.isNum() && right.isNum()) { 271 if (left.isNum() && right.isNum()) {
283 // Numbers need to be treated specially because: NaN != NaN, -0.0 == 0.0, 272 // Numbers need to be treated specially because: NaN != NaN, -0.0 == 0.0,
284 // and 1 == 1.0. 273 // and 1 == 1.0.
285 NumConstant leftNum = left; 274 NumConstant leftNum = left;
286 NumConstant rightNum = right; 275 NumConstant rightNum = right;
287 return new BoolConstant(leftNum.value == rightNum.value); 276 bool result = leftNum.value == rightNum.value;
277 return DART_CONSTANT_SYSTEM.createBool(result);
288 } 278 }
289 if (left.isConstructedObject()) { 279 if (left.isConstructedObject()) {
290 // Unless we know that the user-defined object does not implement the 280 // Unless we know that the user-defined object does not implement the
291 // equality operator we cannot fold here. 281 // equality operator we cannot fold here.
292 return null; 282 return null;
293 } 283 }
294 return new BoolConstant(left == right); 284 return DART_CONSTANT_SYSTEM.createBool(left == right);
295 } 285 }
296 } 286 }
297 287
298 class IdentityOperation implements BinaryOperation { 288 class IdentityOperation implements BinaryOperation {
299 final SourceString name = const SourceString('==='); 289 final SourceString name = const SourceString('===');
300 bool isUserDefinable() => false; 290 bool isUserDefinable() => false;
301 const IdentityOperation(); 291 const IdentityOperation();
302 Constant fold(Constant left, Constant right) { 292 BoolConstant fold(Constant left, Constant right) {
303 // In order to preserve runtime semantics which says that NaN !== NaN don't 293 // In order to preserve runtime semantics which says that NaN !== NaN don't
304 // constant fold NaN === NaN. Otherwise the output depends on inlined 294 // constant fold NaN === NaN. Otherwise the output depends on inlined
305 // variables and other optimizations. 295 // variables and other optimizations.
306 if (left.isNaN() && right.isNaN()) return null; 296 if (left.isNaN() && right.isNaN()) return null;
307 return new BoolConstant(left == right); 297 return DART_CONSTANT_SYSTEM.createBool(left == right);
308 } 298 }
309 } 299 }
300
301 /**
302 * 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
304 * that doesn't correctly implement Dart's semantics this constant system will
305 * not return the correct values.
306 */
307 class DartConstantSystem implements ConstantSystem {
308 const add = const AddOperation();
309 const bitAnd = const BitAndOperation();
310 const bitNot = const BitNotOperation();
311 const bitOr = const BitOrOperation();
312 const bitXor = const BitXorOperation();
313 const booleanAnd = const BooleanAndOperation();
314 const booleanOr = const BooleanOrOperation();
315 const divide = const DivideOperation();
316 const equal = const EqualsOperation();
317 const greaterEqual = const GreaterEqualOperation();
318 const greater = const GreaterOperation();
319 const identity = const IdentityOperation();
320 const lessEqual = const LessEqualOperation();
321 const less = const LessOperation();
322 const modulo = const ModuloOperation();
323 const multiply = const MultiplyOperation();
324 const negate = const NegateOperation();
325 const not = const NotOperation();
326 const shiftLeft = const ShiftLeftOperation();
327 const shiftRight = const ShiftRightOperation();
328 const subtract = const SubtractOperation();
329 const truncatingDivide = const TruncatingDivideOperation();
330
331 const DartConstantSystem();
332
333 IntConstant createInt(int i) => new IntConstant(i);
334 DoubleConstant createDouble(double d) => new DoubleConstant(d);
335 StringConstant createString(DartString string, Node diagnosticNode)
336 => new StringConstant(string, diagnosticNode);
337 BoolConstant createBool(bool value) => new BoolConstant(value);
338 NullConstant createNull() => new NullConstant();
339
340 bool isInt(Constant constant) => constant.isInt();
341 bool isDouble(Constant constant) => constant.isDouble();
342 bool isString(Constant constant) => constant.isString();
343 bool isBool(Constant constant) => constant.isBool();
344 bool isNull(Constant constant) => constant.isNull();
345 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/constant_system.dart ('k') | lib/compiler/implementation/js_backend/backend.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698