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

Side by Side Diff: lib/compiler/implementation/operations.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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 interface Operation {
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
15 class BitNotOperation implements UnaryOperation {
16 final SourceString name = const SourceString('~');
17 bool isUserDefinable() => true;
18 const BitNotOperation();
19 Constant fold(Constant constant) {
20 if (constant.isInt()) {
21 IntConstant intConstant = constant;
22 return new IntConstant(~intConstant.value);
23 }
24 return null;
25 }
26 }
27
28 class NegateOperation implements UnaryOperation {
29 final SourceString name = const SourceString('negate');
30 bool isUserDefinable() => true;
31 const NegateOperation();
32 Constant fold(Constant constant) {
33 if (constant.isInt()) {
34 IntConstant intConstant = constant;
35 return new IntConstant(-intConstant.value);
36 }
37 if (constant.isDouble()) {
38 DoubleConstant doubleConstant = constant;
39 return new DoubleConstant(-doubleConstant.value);
40 }
41 return null;
42 }
43 }
44
45 class NotOperation implements UnaryOperation {
46 final SourceString name = const SourceString('!');
47 bool isUserDefinable() => true;
48 const NotOperation();
49 Constant fold(Constant constant) {
50 if (constant.isBool()) {
51 BoolConstant boolConstant = constant;
52 return boolConstant.negate();
53 }
54 return null;
55 }
56 }
57
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 /**
64 * Operations that only work if both arguments are integers.
65 */
66 class BinaryIntOperation implements BinaryOperation {
67 bool isUserDefinable() => true;
68 const BinaryIntOperation();
69 Constant fold(Constant left, Constant right) {
70 if (left.isInt() && right.isInt()) {
71 IntConstant leftInt = left;
72 IntConstant rightInt = right;
73 int resultValue = foldInts(leftInt.value, rightInt.value);
74 if (resultValue === null) return null;
75 return new IntConstant(resultValue);
76 }
77 return null;
78 }
79
80 abstract int foldInts(int left, int right);
81 }
82
83 class BitOrOperation extends BinaryIntOperation {
84 final SourceString name = const SourceString('|');
85 const BitOrOperation();
86 int foldInts(int left, int right) => left | right;
87 }
88
89 class BitAndOperation extends BinaryIntOperation {
90 final SourceString name = const SourceString('&');
91 const BitAndOperation();
92 int foldInts(int left, int right) => left & right;
93 }
94
95 class BitXorOperation extends BinaryIntOperation {
96 final SourceString name = const SourceString('^');
97 const BitXorOperation();
98 int foldInts(int left, int right) => left ^ right;
99 }
100
101 class ShiftLeftOperation extends BinaryIntOperation {
102 final SourceString name = const SourceString('<<');
103 const ShiftLeftOperation();
104 int foldInts(int left, int right) {
105 // TODO(floitsch): find a better way to guard against excessive shifts to
106 // the left.
107 if (right > 100 || right < 0) return null;
108 return left << right;
109 }
110 }
111
112 class ShiftRightOperation extends BinaryIntOperation {
113 final SourceString name = const SourceString('>>');
114 const ShiftRightOperation();
115 int foldInts(int left, int right) {
116 if (right < 0) return null;
117 return left >> right;
118 }
119 }
120
121 class BinaryBoolOperation implements BinaryOperation {
122 bool isUserDefinable() => false;
123 const BinaryBoolOperation();
124 Constant fold(Constant left, Constant right) {
125 if (left.isBool() && right.isBool()) {
126 BoolConstant leftBool = left;
127 BoolConstant rightBool = right;
128 bool resultValue = foldBools(leftBool.value, rightBool.value);
129 return new BoolConstant(resultValue);
130 }
131 return null;
132 }
133
134 abstract bool foldBools(bool left, bool right);
135 }
136
137 class BooleanAnd extends BinaryBoolOperation {
138 final SourceString name = const SourceString('&&');
139 const BooleanAnd();
140 bool foldBools(bool left, bool right) => left && right;
141 }
142
143 class BooleanOr extends BinaryBoolOperation {
144 final SourceString name = const SourceString('||');
145 const BooleanOr();
146 bool foldBools(bool left, bool right) => left || right;
147 }
148
149 class ArithmeticNumOperation implements BinaryOperation {
150 bool isUserDefinable() => true;
151 const ArithmeticNumOperation();
152 Constant fold(Constant left, Constant right) {
153 if (left.isNum() && right.isNum()) {
154 NumConstant leftNum = left;
155 NumConstant rightNum = right;
156 num foldedValue;
157 if (left.isInt() && right.isInt()) {
158 foldedValue = foldInts(leftNum.value, rightNum.value);
159 } else {
160 foldedValue = foldNums(leftNum.value, rightNum.value);
161 }
162 // A division by 0 means that we might not have a folded value.
163 if (foldedValue === null) return null;
164 if (left.isInt() && right.isInt() && !isDivide()) {
165 assert(foldedValue is int);
166 return new IntConstant(foldedValue);
167 } else {
168 return new DoubleConstant(foldedValue);
169 }
170 }
171 return null;
172 }
173
174 bool isDivide() => false;
175 num foldInts(int left, int right) => foldNums(left, right);
176 abstract num foldNums(num left, num right);
177 }
178
179 class SubtractOperation extends ArithmeticNumOperation {
180 final SourceString name = const SourceString('-');
181 const SubtractOperation();
182 num foldNums(num left, num right) => left - right;
183 }
184
185 class MultiplyOperation extends ArithmeticNumOperation {
186 final SourceString name = const SourceString('*');
187 const MultiplyOperation();
188 num foldNums(num left, num right) => left * right;
189 }
190
191 class ModuloOperation extends ArithmeticNumOperation {
192 final SourceString name = const SourceString('%');
193 const ModuloOperation();
194 int foldInts(int left, int right) {
195 if (right == 0) return null;
196 return left % right;
197 }
198 num foldNums(num left, num right) => left % right;
199 }
200
201 class TruncatingDivideOperation extends ArithmeticNumOperation {
202 final SourceString name = const SourceString('~/');
203 const TruncatingDivideOperation();
204 int foldInts(int left, int right) {
205 if (right == 0) return null;
206 return left ~/ right;
207 }
208 num foldNums(num left, num right) => left ~/ right;
209 }
210
211 class DivideOperation extends ArithmeticNumOperation {
212 final SourceString name = const SourceString('/');
213 const DivideOperation();
214 num foldNums(num left, num right) => left / right;
215 bool isDivide() => true;
216 }
217
218 class AddOperation implements BinaryOperation {
219 final SourceString name = const SourceString('+');
220 bool isUserDefinable() => true;
221 const AddOperation();
222 Constant fold(Constant left, Constant right) {
223 if (left.isInt() && right.isInt()) {
224 IntConstant leftInt = left;
225 IntConstant rightInt = right;
226 return new IntConstant(leftInt.value + rightInt.value);
227 } else if (left.isNum() && right.isNum()) {
228 NumConstant leftNum = left;
229 NumConstant rightNum = right;
230 return new DoubleConstant(leftNum.value + rightNum.value);
231 } else {
232 return null;
233 }
234 }
235 }
236
237 class RelationalNumOperation implements BinaryOperation {
238 bool isUserDefinable() => true;
239 const RelationalNumOperation();
240 Constant fold(Constant left, Constant right) {
241 if (left.isNum() && right.isNum()) {
242 NumConstant leftNum = left;
243 NumConstant rightNum = right;
244 bool foldedValue = foldNums(leftNum.value, rightNum.value);
245 assert(foldedValue != null);
246 return new BoolConstant(foldedValue);
247 }
248 }
249
250 abstract bool foldNums(num left, num right);
251 }
252
253 class LessOperation extends RelationalNumOperation {
254 final SourceString name = const SourceString('<');
255 const LessOperation();
256 bool foldNums(num left, num right) => left < right;
257 }
258
259 class LessEqualOperation extends RelationalNumOperation {
260 final SourceString name = const SourceString('<=');
261 const LessEqualOperation();
262 bool foldNums(num left, num right) => left <= right;
263 }
264
265 class GreaterOperation extends RelationalNumOperation {
266 final SourceString name = const SourceString('>');
267 const GreaterOperation();
268 bool foldNums(num left, num right) => left > right;
269 }
270
271 class GreaterEqualOperation extends RelationalNumOperation {
272 final SourceString name = const SourceString('>=');
273 const GreaterEqualOperation();
274 bool foldNums(num left, num right) => left >= right;
275 }
276
277 class EqualsOperation implements BinaryOperation {
278 final SourceString name = const SourceString('==');
279 bool isUserDefinable() => true;
280 const EqualsOperation();
281 Constant fold(Constant left, Constant right) {
282 if (left.isNum() && right.isNum()) {
283 // Numbers need to be treated specially because: NaN != NaN, -0.0 == 0.0,
284 // and 1 == 1.0.
285 NumConstant leftNum = left;
286 NumConstant rightNum = right;
287 return new BoolConstant(leftNum.value == rightNum.value);
288 }
289 if (left.isConstructedObject()) {
290 // Unless we know that the user-defined object does not implement the
291 // equality operator we cannot fold here.
292 return null;
293 }
294 return new BoolConstant(left == right);
295 }
296 }
297
298 class IdentityOperation implements BinaryOperation {
299 final SourceString name = const SourceString('===');
300 bool isUserDefinable() => false;
301 const IdentityOperation();
302 Constant fold(Constant left, Constant right) {
303 // In order to preserve runtime semantics which says that NaN !== NaN don't
304 // constant fold NaN === NaN. Otherwise the output depends on inlined
305 // variables and other optimizations.
306 if (left.isNaN() && right.isNaN()) return null;
307 return new BoolConstant(left == right);
308 }
309 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/native_handler.dart ('k') | lib/compiler/implementation/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698