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

Side by Side Diff: frog/leg/ssa/nodes.dart

Issue 9595017: Refactor constant part. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 9 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 visitBailoutTarget(HBailoutTarget node); 7 R visitBailoutTarget(HBailoutTarget node);
8 R visitBitAnd(HBitAnd node); 8 R visitBitAnd(HBitAnd node);
9 R visitBitNot(HBitNot node); 9 R visitBitNot(HBitNot node);
10 R visitBitOr(HBitOr node); 10 R visitBitOr(HBitOr node);
11 R visitBitXor(HBitXor node); 11 R visitBitXor(HBitXor node);
12 R visitBoolify(HBoolify node); 12 R visitBoolify(HBoolify node);
13 R visitBoundsCheck(HBoundsCheck node); 13 R visitBoundsCheck(HBoundsCheck node);
14 R visitBreak(HBreak node); 14 R visitBreak(HBreak node);
15 R visitConstant(HConstant node);
15 R visitDivide(HDivide node); 16 R visitDivide(HDivide node);
16 R visitEquals(HEquals node); 17 R visitEquals(HEquals node);
17 R visitExit(HExit node); 18 R visitExit(HExit node);
18 R visitFieldGet(HFieldGet node); 19 R visitFieldGet(HFieldGet node);
19 R visitFieldSet(HFieldSet node); 20 R visitFieldSet(HFieldSet node);
20 R visitForeign(HForeign node); 21 R visitForeign(HForeign node);
21 R visitForeignNew(HForeignNew); 22 R visitForeignNew(HForeignNew);
22 R visitGoto(HGoto node); 23 R visitGoto(HGoto node);
23 R visitGreater(HGreater node); 24 R visitGreater(HGreater node);
24 R visitGreaterEqual(HGreaterEqual node); 25 R visitGreaterEqual(HGreaterEqual node);
25 R visitIdentity(HIdentity node); 26 R visitIdentity(HIdentity node);
26 R visitIf(HIf node); 27 R visitIf(HIf node);
27 R visitIndex(HIndex node); 28 R visitIndex(HIndex node);
28 R visitIndexAssign(HIndexAssign node); 29 R visitIndexAssign(HIndexAssign node);
29 R visitIntegerCheck(HIntegerCheck node); 30 R visitIntegerCheck(HIntegerCheck node);
30 R visitInvokeClosure(HInvokeClosure node); 31 R visitInvokeClosure(HInvokeClosure node);
31 R visitInvokeDynamicGetter(HInvokeDynamicGetter node); 32 R visitInvokeDynamicGetter(HInvokeDynamicGetter node);
32 R visitInvokeDynamicMethod(HInvokeDynamicMethod node); 33 R visitInvokeDynamicMethod(HInvokeDynamicMethod node);
33 R visitInvokeDynamicSetter(HInvokeDynamicSetter node); 34 R visitInvokeDynamicSetter(HInvokeDynamicSetter node);
34 R visitInvokeInterceptor(HInvokeInterceptor node); 35 R visitInvokeInterceptor(HInvokeInterceptor node);
35 R visitInvokeStatic(HInvokeStatic node); 36 R visitInvokeStatic(HInvokeStatic node);
36 R visitInvokeSuper(HInvokeSuper node); 37 R visitInvokeSuper(HInvokeSuper node);
37 R visitIs(HIs node); 38 R visitIs(HIs node);
38 R visitLess(HLess node); 39 R visitLess(HLess node);
39 R visitLessEqual(HLessEqual node); 40 R visitLessEqual(HLessEqual node);
40 R visitLiteral(HLiteral node);
41 R visitLiteralList(HLiteralList node); 41 R visitLiteralList(HLiteralList node);
42 R visitLoad(HLoad node); 42 R visitLoad(HLoad node);
43 R visitLocal(HLocal node); 43 R visitLocal(HLocal node);
44 R visitLogicalOperator(HLogicalOperator node); 44 R visitLogicalOperator(HLogicalOperator node);
45 R visitLoopBranch(HLoopBranch node); 45 R visitLoopBranch(HLoopBranch node);
46 R visitModulo(HModulo node); 46 R visitModulo(HModulo node);
47 R visitMultiply(HMultiply node); 47 R visitMultiply(HMultiply node);
48 R visitNegate(HNegate node); 48 R visitNegate(HNegate node);
49 R visitNot(HNot node); 49 R visitNot(HNot node);
50 R visitParameterValue(HParameterValue node); 50 R visitParameterValue(HParameterValue node);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 currentBlock = node; 109 currentBlock = node;
110 visitInstructionList(node); 110 visitInstructionList(node);
111 } 111 }
112 } 112 }
113 113
114 class HGraph { 114 class HGraph {
115 HBasicBlock entry; 115 HBasicBlock entry;
116 HBasicBlock exit; 116 HBasicBlock exit;
117 final List<HBasicBlock> blocks; 117 final List<HBasicBlock> blocks;
118 118
119 // We canonicalize all literals used within a graph so we do not 119 // We canonicalize all constants used within a graph so we do not
120 // have to worry about them for global value numbering. 120 // have to worry about them for global value numbering.
121 HLiteral nullLiteral; 121 Map<Constant, HConstant> constants;
122 HLiteral trueLiteral;
123 HLiteral falseLiteral;
124 HLiteral nanLiteral;
125 HLiteral negativeZeroLiteral;
126 Map<int, HLiteral> intLiterals;
127 Map<double, HLiteral> doubleLiterals;
128 Map<num, HLiteral> numLiterals;
129 Map<String, HLiteral> stringLiterals;
130 122
131 HGraph() : blocks = new List<HBasicBlock>() { 123 HGraph()
124 : blocks = new List<HBasicBlock>(),
125 constants = new Map<Constant, HConstant>() {
132 entry = addNewBlock(); 126 entry = addNewBlock();
133 // The exit block will be added later, so it has an id that is 127 // The exit block will be added later, so it has an id that is
134 // after all others in the system. 128 // after all others in the system.
135 exit = new HBasicBlock(); 129 exit = new HBasicBlock();
136 } 130 }
137 131
138 void addBlock(HBasicBlock block) { 132 void addBlock(HBasicBlock block) {
139 int id = blocks.length; 133 int id = blocks.length;
140 block.id = id; 134 block.id = id;
141 blocks.add(block); 135 blocks.add(block);
142 assert(blocks[id] === block); 136 assert(blocks[id] === block);
143 } 137 }
144 138
145 HBasicBlock addNewBlock() { 139 HBasicBlock addNewBlock() {
146 HBasicBlock result = new HBasicBlock(); 140 HBasicBlock result = new HBasicBlock();
147 addBlock(result); 141 addBlock(result);
148 return result; 142 return result;
149 } 143 }
150 144
151 HBasicBlock addNewLoopHeaderBlock(List<SourceString> labels) { 145 HBasicBlock addNewLoopHeaderBlock(List<SourceString> labels) {
152 HBasicBlock result = addNewBlock(); 146 HBasicBlock result = addNewBlock();
153 result.loopInformation = new HLoopInformation(result, labels); 147 result.loopInformation = new HLoopInformation(result, labels);
154 return result; 148 return result;
155 } 149 }
156 150
157 HLiteral addNewLiteralInt(int value) { 151 HType mapConstantTypeToSsaType(Constant constant) {
kasperl 2012/03/05 13:53:16 static?
floitsch 2012/03/05 15:43:24 Done.
158 if (intLiterals === null) intLiterals = new Map<int, HLiteral>(); 152 if (constant.isNull()) return HType.UNKNOWN;
159 HLiteral result = intLiterals[value]; 153 if (constant.isBool()) return HType.BOOLEAN;
154 if (constant.isInt()) return HType.INTEGER;
155 if (constant.isDouble()) return HType.DOUBLE;
156 if (constant.isString()) return HType.STRING;
157 if (constant.isList()) return HType.ARRAY;
158 return HType.UNKNOWN;
159 }
160
161 HConstant addNewConstant(Constant constant) {
162 HConstant result = constants[constant];
160 if (result === null) { 163 if (result === null) {
161 result = new HLiteral.internal(value, HType.INTEGER); 164 HType type = mapConstantTypeToSsaType(constant);
165 result = new HConstant.internal(constant, type);
162 entry.addAtExit(result); 166 entry.addAtExit(result);
163 intLiterals[value] = result; 167 constants[constant] = result;
164 } 168 }
165 return result; 169 return result;
166 } 170 }
167 171
168 HLiteral addNewLiteralNaN() {
169 if (nanLiteral === null) {
170 nanLiteral = new HLiteral.internal(double.NAN, HType.DOUBLE);
171 entry.addAtExit(nanLiteral);
172 }
173 return nanLiteral;
174 }
175
176 HLiteral addNewNegativeZeroLiteral() {
177 if (negativeZeroLiteral === null) {
178 negativeZeroLiteral = new HLiteral.internal(-0.0, HType.DOUBLE);
179 entry.addAtExit(negativeZeroLiteral);
180 }
181 return negativeZeroLiteral;
182 }
183
184 HLiteral addNewLiteralDouble(double value) {
185 if (value.isNaN()) return addNewLiteralNaN(); // Avoid hashing NaN.
186 if (value == 0 && value.isNegative()) {
187 // Avoid hashing -0.0 as it compares equal to 0.0.
188 return addNewNegativeZeroLiteral();
189 }
190 if (doubleLiterals === null) doubleLiterals = new Map<double, HLiteral>();
191 HLiteral result = doubleLiterals[value];
192 if (result === null) {
193 result = new HLiteral.internal(value, HType.DOUBLE);
194 entry.addAtExit(result);
195 doubleLiterals[value] = result;
196 }
197 return result;
198 }
199
200 HLiteral addNewLiteralNum(num value, HType type) {
201 // If we've propagated type information then the type must be a
202 // number or in conflict, but when we turn off speculative
203 // optimization the type may be unknown. In any case, we make it a
204 // number from this point forward.
205 assert(type.isUnknown() || type.isConflicting() || type.isNumber());
206 if (type.isInteger()) return addNewLiteralInt(value);
207 if (type.isDouble() || value.isNaN()) return addNewLiteralDouble(value);
208 // Probe our literals map and add a new number literal if necessary.
209 if (numLiterals === null) numLiterals = new Map<num, HLiteral>();
210 HLiteral result = numLiterals[value];
211 if (result === null) {
212 result = new HLiteral.internal(value, HType.NUMBER);
213 entry.addAtExit(result);
214 numLiterals[value] = result;
215 }
216 return result;
217 }
218
219 HLiteral addNewLiteralTrue() {
220 if (trueLiteral === null) {
221 trueLiteral = new HLiteral.internal(true, HType.BOOLEAN);
222 entry.addAtExit(trueLiteral);
223 }
224 return trueLiteral;
225 }
226
227 HLiteral addNewLiteralFalse() {
228 if (falseLiteral === null) {
229 falseLiteral = new HLiteral.internal(false, HType.BOOLEAN);
230 entry.addAtExit(falseLiteral);
231 }
232 return falseLiteral;
233 }
234
235 HLiteral addNewLiteralBool(bool value) {
236 return value ? addNewLiteralTrue() : addNewLiteralFalse();
237 }
238
239 HLiteral addNewLiteralString(DartString value) {
240 if (stringLiterals === null) stringLiterals = new Map<String, HLiteral>();
241 String key = value.toString(); // We need something hashable.
242 HLiteral result = stringLiterals[key];
243 if (result === null) {
244 result = new HLiteral.internal(value, HType.STRING);
245 entry.addAtExit(result);
246 stringLiterals[key] = result;
247 }
248 return result;
249 }
250
251 HLiteral addNewLiteralNull() {
252 if (nullLiteral === null) {
253 nullLiteral = new HLiteral.internal(null, HType.UNKNOWN);
254 entry.addAtExit(nullLiteral);
255 }
256 return nullLiteral;
257 }
258
259 void finalize() { 172 void finalize() {
260 addBlock(exit); 173 addBlock(exit);
261 exit.open(); 174 exit.open();
262 exit.close(new HExit()); 175 exit.close(new HExit());
263 assignDominators(); 176 assignDominators();
264 } 177 }
265 178
266 void assignDominators() { 179 void assignDominators() {
267 // Run through the blocks in order of increasing ids so we are 180 // Run through the blocks in order of increasing ids so we are
268 // guaranteed that we have computed dominators for all blocks 181 // guaranteed that we have computed dominators for all blocks
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 visitAdd(HAdd node) => visitBinaryArithmetic(node); 230 visitAdd(HAdd node) => visitBinaryArithmetic(node);
318 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); 231 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
319 visitBitNot(HBitNot node) => visitInvokeUnary(node); 232 visitBitNot(HBitNot node) => visitInvokeUnary(node);
320 visitBitOr(HBitOr node) => visitBinaryBitOp(node); 233 visitBitOr(HBitOr node) => visitBinaryBitOp(node);
321 visitBitXor(HBitXor node) => visitBinaryBitOp(node); 234 visitBitXor(HBitXor node) => visitBinaryBitOp(node);
322 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); 235 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node);
323 visitBoolify(HBoolify node) => visitInstruction(node); 236 visitBoolify(HBoolify node) => visitInstruction(node);
324 visitBoundsCheck(HBoundsCheck node) => visitCheck(node); 237 visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
325 visitBreak(HBreak node) => visitGoto(node); 238 visitBreak(HBreak node) => visitGoto(node);
326 visitCheck(HCheck node) => visitInstruction(node); 239 visitCheck(HCheck node) => visitInstruction(node);
240 visitConstant(HConstant node) => visitInstruction(node);
327 visitDivide(HDivide node) => visitBinaryArithmetic(node); 241 visitDivide(HDivide node) => visitBinaryArithmetic(node);
328 visitEquals(HEquals node) => visitRelational(node); 242 visitEquals(HEquals node) => visitRelational(node);
329 visitExit(HExit node) => visitControlFlow(node); 243 visitExit(HExit node) => visitControlFlow(node);
330 visitFieldGet(HFieldGet node) => visitInstruction(node); 244 visitFieldGet(HFieldGet node) => visitInstruction(node);
331 visitFieldSet(HFieldSet node) => visitInstruction(node); 245 visitFieldSet(HFieldSet node) => visitInstruction(node);
332 visitForeign(HForeign node) => visitInstruction(node); 246 visitForeign(HForeign node) => visitInstruction(node);
333 visitForeignNew(HForeignNew node) => visitForeign(node); 247 visitForeignNew(HForeignNew node) => visitForeign(node);
334 visitGoto(HGoto node) => visitControlFlow(node); 248 visitGoto(HGoto node) => visitControlFlow(node);
335 visitGreater(HGreater node) => visitRelational(node); 249 visitGreater(HGreater node) => visitRelational(node);
336 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); 250 visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
(...skipping 12 matching lines...) Expand all
349 => visitInvokeDynamicField(node); 263 => visitInvokeDynamicField(node);
350 visitInvokeInterceptor(HInvokeInterceptor node) 264 visitInvokeInterceptor(HInvokeInterceptor node)
351 => visitInvokeStatic(node); 265 => visitInvokeStatic(node);
352 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); 266 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
353 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node); 267 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node);
354 visitLess(HLess node) => visitRelational(node); 268 visitLess(HLess node) => visitRelational(node);
355 visitLessEqual(HLessEqual node) => visitRelational(node); 269 visitLessEqual(HLessEqual node) => visitRelational(node);
356 visitLoad(HLoad node) => visitInstruction(node); 270 visitLoad(HLoad node) => visitInstruction(node);
357 visitLocal(HLocal node) => visitInstruction(node); 271 visitLocal(HLocal node) => visitInstruction(node);
358 visitLogicalOperator(HLogicalOperator node) => visitInstruction(node); 272 visitLogicalOperator(HLogicalOperator node) => visitInstruction(node);
359 visitLiteral(HLiteral node) => visitInstruction(node);
360 visitLiteralList(HLiteralList node) => visitInstruction(node); 273 visitLiteralList(HLiteralList node) => visitInstruction(node);
361 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); 274 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
362 visitModulo(HModulo node) => visitBinaryArithmetic(node); 275 visitModulo(HModulo node) => visitBinaryArithmetic(node);
363 visitNegate(HNegate node) => visitInvokeUnary(node); 276 visitNegate(HNegate node) => visitInvokeUnary(node);
364 visitNot(HNot node) => visitInstruction(node); 277 visitNot(HNot node) => visitInstruction(node);
365 visitPhi(HPhi node) => visitInstruction(node); 278 visitPhi(HPhi node) => visitInstruction(node);
366 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); 279 visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
367 visitParameterValue(HParameterValue node) => visitInstruction(node); 280 visitParameterValue(HParameterValue node) => visitInstruction(node);
368 visitReturn(HReturn node) => visitControlFlow(node); 281 visitReturn(HReturn node) => visitControlFlow(node);
369 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node); 282 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 inputUsedBy[j] = inputUsedBy[inputUsedBy.length - 1]; 911 inputUsedBy[j] = inputUsedBy[inputUsedBy.length - 1];
999 inputUsedBy.removeLast(); 912 inputUsedBy.removeLast();
1000 break; 913 break;
1001 } 914 }
1002 } 915 }
1003 } 916 }
1004 this.block = null; 917 this.block = null;
1005 assert(isValid()); 918 assert(isValid());
1006 } 919 }
1007 920
1008 bool isLiteralNull() => false; 921 bool isNullConstant() => false;
kasperl 2012/03/05 13:53:16 I know it doesn't read as well, but I think I'd pr
floitsch 2012/03/05 15:43:24 Done.
1009 bool isLiteralNumber() => false; 922 bool isNumberConstant() => false;
1010 bool isLiteralString() => false; 923 bool isStringConstant() => false;
1011 924
1012 bool isValid() { 925 bool isValid() {
1013 HValidator validator = new HValidator(); 926 HValidator validator = new HValidator();
1014 validator.currentBlock = block; 927 validator.currentBlock = block;
1015 validator.visitInstruction(this); 928 validator.visitInstruction(this);
1016 return validator.isValid; 929 return validator.isValid;
1017 } 930 }
1018 } 931 }
1019 932
1020 class HBoolify extends HInstruction { 933 class HBoolify extends HInstruction {
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1262 || name == const SourceString('removeLast')) { 1175 || name == const SourceString('removeLast')) {
1263 return HType.ARRAY; 1176 return HType.ARRAY;
1264 } 1177 }
1265 } 1178 }
1266 return HType.UNKNOWN; 1179 return HType.UNKNOWN;
1267 } 1180 }
1268 1181
1269 bool hasExpectedType() => builtinJsName != null; 1182 bool hasExpectedType() => builtinJsName != null;
1270 1183
1271 HInstruction fold(HGraph graph) { 1184 HInstruction fold(HGraph graph) {
1272 if (name == const SourceString('length') && inputs[1].isLiteralString()) { 1185 if (name == const SourceString('length') && inputs[1].isStringConstant()) {
1273 HLiteral input = inputs[1]; 1186 HConstant input = inputs[1];
1274 DartString string = input.value; 1187 DartString string = input.constant.value;
1275 return graph.addNewLiteralInt(string.length); 1188 return graph.addNewConstant(new IntConstant(string.length));
kasperl 2012/03/05 13:53:16 Maybe keeping a few helpers around (graph.addNewCo
floitsch 2012/03/05 15:43:24 Done.
1276 } 1189 }
1277 return this; 1190 return this;
1278 } 1191 }
1279 1192
1280 void prepareGvn() { 1193 void prepareGvn() {
1281 if (builtinJsName == 'length') { 1194 if (builtinJsName == 'length') {
1282 assert(!hasSideEffects()); 1195 assert(!hasSideEffects());
1283 } else { 1196 } else {
1284 setAllSideEffects(); 1197 setAllSideEffects();
1285 } 1198 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 1273
1361 HType computeInputsType() { 1274 HType computeInputsType() {
1362 HType leftType = left.type; 1275 HType leftType = left.type;
1363 HType rightType = right.type; 1276 HType rightType = right.type;
1364 if (leftType.isUnknown() || rightType.isUnknown()) { 1277 if (leftType.isUnknown() || rightType.isUnknown()) {
1365 return HType.UNKNOWN; 1278 return HType.UNKNOWN;
1366 } 1279 }
1367 return leftType.combine(rightType); 1280 return leftType.combine(rightType);
1368 } 1281 }
1369 1282
1370 abstract HInstruction fold(HGraph graph); 1283 HInstruction fold(HGraph graph) {
1371 abstract evaluate(num a, num b); 1284 if (left is HConstant && right is HConstant) {
1285 HConstant op1 = left;
1286 HConstant op2 = right;
1287 Constant folded =
1288 op1.constant.binaryFold(operationAsString(), op2.constant);
1289 if (folded !== null) return graph.addNewConstant(folded);
1290 }
1291 return this;
1292 }
1293 abstract String operationAsString();
1372 } 1294 }
1373 1295
1374 class HBinaryArithmetic extends HInvokeBinary { 1296 class HBinaryArithmetic extends HInvokeBinary {
1375 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) 1297 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right)
1376 : super(target, left, right); 1298 : super(target, left, right);
1377 1299
1378 void prepareGvn() { 1300 void prepareGvn() {
1379 // An arithmetic expression can take part in global value 1301 // An arithmetic expression can take part in global value
1380 // numbering and do not have any side-effects if we know that all 1302 // numbering and do not have any side-effects if we know that all
1381 // inputs are numbers. 1303 // inputs are numbers.
1382 if (builtin) { 1304 if (builtin) {
1383 assert(!hasSideEffects()); 1305 assert(!hasSideEffects());
1384 setUseGvn(); 1306 setUseGvn();
1385 } else { 1307 } else {
1386 setAllSideEffects(); 1308 setAllSideEffects();
1387 } 1309 }
1388 } 1310 }
1389 1311
1390 HInstruction fold(HGraph graph) {
1391 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1392 HLiteral op1 = left;
1393 HLiteral op2 = right;
1394 return graph.addNewLiteralNum(evaluate(op1.value, op2.value), type);
1395 }
1396 return this;
1397 }
1398
1399 HType computeType() { 1312 HType computeType() {
1400 HType type = computeInputsType(); 1313 HType type = computeInputsType();
1401 builtin = type.isNumber(); 1314 builtin = type.isNumber();
1402 if (!type.isUnknown()) return type; 1315 if (!type.isUnknown()) return type;
1403 if (left.isNumber()) return HType.NUMBER; 1316 if (left.isNumber()) return HType.NUMBER;
1404 return HType.UNKNOWN; 1317 return HType.UNKNOWN;
1405 } 1318 }
1406 1319
1407 HType computeDesiredInputType(HInstruction input) { 1320 HType computeDesiredInputType(HInstruction input) {
1408 // TODO(floitsch): we want the target to be a function. 1321 // TODO(floitsch): we want the target to be a function.
1409 if (input == target) return HType.UNKNOWN; 1322 if (input == target) return HType.UNKNOWN;
1410 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; 1323 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER;
1411 if (type.isUnknown()) return HType.NUMBER; 1324 if (type.isUnknown()) return HType.NUMBER;
1412 return HType.UNKNOWN; 1325 return HType.UNKNOWN;
1413 } 1326 }
1414 1327
1415 bool hasExpectedType() => builtin || type.isUnknown(); 1328 bool hasExpectedType() => builtin || type.isUnknown();
1416
1417 abstract num evaluate(num a, num b);
1418 } 1329 }
1419 1330
1420 class HAdd extends HBinaryArithmetic { 1331 class HAdd extends HBinaryArithmetic {
1421 HAdd(HStatic target, HInstruction left, HInstruction right) 1332 HAdd(HStatic target, HInstruction left, HInstruction right)
1422 : super(target, left, right); 1333 : super(target, left, right);
1423 accept(HVisitor visitor) => visitor.visitAdd(this); 1334 accept(HVisitor visitor) => visitor.visitAdd(this);
1424 num evaluate(num a, num b) => a + b;
1425 int typeCode() => 5;
1426 bool typeEquals(other) => other is HAdd;
1427 bool dataEquals(HInstruction other) => true;
1428 1335
1429 HType computeType() { 1336 HType computeType() {
1430 HType type = computeInputsType(); 1337 HType type = computeInputsType();
1431 builtin = (type.isNumber() || type.isString()); 1338 builtin = (type.isNumber() || type.isString());
1432 if (type.isConflicting() && left.isString()) { 1339 if (type.isConflicting() && left.isString()) {
1433 builtin = right is HLiteral; 1340 builtin = right is HConstant;
1434 return HType.STRING; 1341 return HType.STRING;
1435 } 1342 }
1436 if (!type.isUnknown()) return type; 1343 if (!type.isUnknown()) return type;
1437 if (left.isNumber()) return HType.NUMBER; 1344 if (left.isNumber()) return HType.NUMBER;
1438 return HType.UNKNOWN; 1345 return HType.UNKNOWN;
1439 } 1346 }
1440 1347
1441 bool hasExpectedType() => builtin || type.isUnknown() || left.isString(); 1348 bool hasExpectedType() => builtin || type.isUnknown() || left.isString();
1442 1349
1443 HType computeDesiredInputType(HInstruction input) { 1350 HType computeDesiredInputType(HInstruction input) {
1444 // TODO(floitsch): we want the target to be a function. 1351 // TODO(floitsch): we want the target to be a function.
1445 if (input == target) return HType.UNKNOWN; 1352 if (input == target) return HType.UNKNOWN;
1446 if (isString() || left.isString()) { 1353 if (isString() || left.isString()) {
1447 return (input == left) ? HType.STRING : HType.UNKNOWN; 1354 return (input == left) ? HType.STRING : HType.UNKNOWN;
1448 } 1355 }
1449 if (right.isString()) return HType.STRING; 1356 if (right.isString()) return HType.STRING;
1450 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; 1357 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER;
1451 return HType.UNKNOWN; 1358 return HType.UNKNOWN;
1452 } 1359 }
1453 1360
1454 HInstruction fold(HGraph graph) { 1361 HInstruction fold(HGraph graph) {
1455 if (left.isLiteralString() && right is HLiteral) { 1362 // TODO(floitsch): move this code to the compile-time-constant handler.
1456 HLiteral op1 = left; 1363 if (left.isStringConstant() && right is HConstant) {
1457 HLiteral op2 = right; 1364 HConstant op1 = left;
1458 DartString leftString = op1.value; 1365 HConstant op2 = right;
1366 DartString leftString = op1.constant.value;
1459 DartString otherString = null; 1367 DartString otherString = null;
1460 if (right.isLiteralString()) { 1368 if (right.isStringConstant()) {
1461 otherString = op2.value; 1369 otherString = op2.constant.value;
1462 } else { 1370 } else {
1463 assert(op2.isLiteralNumber() || 1371 assert(op2.isNumberConstant() ||
1464 op2.isLiteralBoolean() || 1372 op2.isBooleanConstant() ||
1465 op2.isLiteralNull()); 1373 op2.isNullConstant());
1466 otherString = new DartString.literal(op2.value.toString()); 1374 otherString = new DartString.literal(op2.constant.value.toString());
1467 } 1375 }
1468 DartString cons = new ConsDartString(leftString, otherString); 1376 DartString cons = new ConsDartString(leftString, otherString);
1469 return graph.addNewLiteralString(cons); 1377 return graph.addNewConstant(new StringConstant(cons));
1470 } 1378 }
1471 return super.fold(graph); 1379 return super.fold(graph);
1472 } 1380 }
1381
1382 String operationAsString() => "+";
kasperl 2012/03/05 13:53:16 These operationAsString seem a bit broken. I wonde
floitsch 2012/03/05 15:43:24 will think about it in another CL.
1383 int typeCode() => 5;
1384 bool typeEquals(other) => other is HAdd;
1385 bool dataEquals(HInstruction other) => true;
1473 } 1386 }
1474 1387
1475 class HDivide extends HBinaryArithmetic { 1388 class HDivide extends HBinaryArithmetic {
1476 HDivide(HStatic target, HInstruction left, HInstruction right) 1389 HDivide(HStatic target, HInstruction left, HInstruction right)
1477 : super(target, left, right); 1390 : super(target, left, right);
1478 accept(HVisitor visitor) => visitor.visitDivide(this); 1391 accept(HVisitor visitor) => visitor.visitDivide(this);
1479 1392
1480 HType computeType() { 1393 HType computeType() {
1481 HType type = computeInputsType(); 1394 HType type = computeInputsType();
1482 builtin = type.isNumber(); 1395 builtin = type.isNumber();
1483 if (left.isNumber()) return HType.DOUBLE; 1396 if (left.isNumber()) return HType.DOUBLE;
1484 return HType.UNKNOWN; 1397 return HType.UNKNOWN;
1485 } 1398 }
1486 1399
1487 num evaluate(num a, num b) => a / b; 1400 String operationAsString() => "/";
1488 int typeCode() => 6; 1401 int typeCode() => 6;
1489 bool typeEquals(other) => other is HDivide; 1402 bool typeEquals(other) => other is HDivide;
1490 bool dataEquals(HInstruction other) => true; 1403 bool dataEquals(HInstruction other) => true;
1491 } 1404 }
1492 1405
1493 class HModulo extends HBinaryArithmetic { 1406 class HModulo extends HBinaryArithmetic {
1494 HModulo(HStatic target, HInstruction left, HInstruction right) 1407 HModulo(HStatic target, HInstruction left, HInstruction right)
1495 : super(target, left, right); 1408 : super(target, left, right);
1496 accept(HVisitor visitor) => visitor.visitModulo(this); 1409 accept(HVisitor visitor) => visitor.visitModulo(this);
1497 num evaluate(num a, num b) => a % b; 1410
1411 String operationAsString() => "%";
1498 int typeCode() => 7; 1412 int typeCode() => 7;
1499 bool typeEquals(other) => other is HModulo; 1413 bool typeEquals(other) => other is HModulo;
1500 bool dataEquals(HInstruction other) => true; 1414 bool dataEquals(HInstruction other) => true;
1501 } 1415 }
1502 1416
1503 class HMultiply extends HBinaryArithmetic { 1417 class HMultiply extends HBinaryArithmetic {
1504 HMultiply(HStatic target, HInstruction left, HInstruction right) 1418 HMultiply(HStatic target, HInstruction left, HInstruction right)
1505 : super(target, left, right); 1419 : super(target, left, right);
1506 accept(HVisitor visitor) => visitor.visitMultiply(this); 1420 accept(HVisitor visitor) => visitor.visitMultiply(this);
1507 num evaluate(num a, num b) => a * b; 1421
1422 String operationAsString() => "*";
1508 int typeCode() => 8; 1423 int typeCode() => 8;
1509 bool typeEquals(other) => other is HMultiply; 1424 bool typeEquals(other) => other is HMultiply;
1510 bool dataEquals(HInstruction other) => true; 1425 bool dataEquals(HInstruction other) => true;
1511 } 1426 }
1512 1427
1513 class HSubtract extends HBinaryArithmetic { 1428 class HSubtract extends HBinaryArithmetic {
1514 HSubtract(HStatic target, HInstruction left, HInstruction right) 1429 HSubtract(HStatic target, HInstruction left, HInstruction right)
1515 : super(target, left, right); 1430 : super(target, left, right);
1516 accept(HVisitor visitor) => visitor.visitSubtract(this); 1431 accept(HVisitor visitor) => visitor.visitSubtract(this);
1517 num evaluate(num a, num b) => a - b; 1432
1433 String operationAsString() => "-";
1518 int typeCode() => 9; 1434 int typeCode() => 9;
1519 bool typeEquals(other) => other is HSubtract; 1435 bool typeEquals(other) => other is HSubtract;
1520 bool dataEquals(HInstruction other) => true; 1436 bool dataEquals(HInstruction other) => true;
1521 } 1437 }
1522 1438
1523 class HTruncatingDivide extends HBinaryArithmetic { 1439 class HTruncatingDivide extends HBinaryArithmetic {
1524 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right) 1440 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right)
1525 : super(target, left, right); 1441 : super(target, left, right);
1526 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this); 1442 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);
1527 1443
1528 HInstruction fold(HGraph graph) { 1444 String operationAsString() => "~/";
1529 // Avoid a DivisionByZeroException.
1530 if (right.isLiteralNumber() && right.dynamic.value == 0) {
1531 return this;
1532 }
1533 return super.fold(graph);
1534 }
1535
1536 num evaluate(num a, num b) => a ~/ b;
1537 int typeCode() => 10; 1445 int typeCode() => 10;
1538 bool typeEquals(other) => other is HTruncatingDivide; 1446 bool typeEquals(other) => other is HTruncatingDivide;
1539 bool dataEquals(HInstruction other) => true; 1447 bool dataEquals(HInstruction other) => true;
1540 } 1448 }
1541 1449
1542 1450
1543 // TODO(floitsch): Should HBinaryArithmetic really be the super class of 1451 // TODO(floitsch): Should HBinaryArithmetic really be the super class of
1544 // HBinaryBitOp? 1452 // HBinaryBitOp?
1545 class HBinaryBitOp extends HBinaryArithmetic { 1453 class HBinaryBitOp extends HBinaryArithmetic {
1546 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right) 1454 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right)
1547 : super(target, left, right); 1455 : super(target, left, right);
1548 1456
1549 HType computeType() { 1457 HType computeType() {
1550 HType type = computeInputsType(); 1458 HType type = computeInputsType();
1551 builtin = type.isInteger(); 1459 builtin = type.isInteger();
1552 if (!type.isUnknown()) return type; 1460 if (!type.isUnknown()) return type;
1553 if (left.isInteger()) return HType.INTEGER; 1461 if (left.isInteger()) return HType.INTEGER;
1554 return HType.UNKNOWN; 1462 return HType.UNKNOWN;
1555 } 1463 }
1556 1464
1557 HType computeDesiredInputType(HInstruction input) { 1465 HType computeDesiredInputType(HInstruction input) {
1558 // TODO(floitsch): we want the target to be a function. 1466 // TODO(floitsch): we want the target to be a function.
1559 if (input == target) return HType.UNKNOWN; 1467 if (input == target) return HType.UNKNOWN;
1560 return HType.INTEGER; 1468 return HType.INTEGER;
1561 } 1469 }
1562 1470
1563 HInstruction fold(HGraph graph) {
1564 // Bit-operations are only defined on integers.
1565 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1566 HLiteral op1 = left;
1567 HLiteral op2 = right;
1568 // Avoid exceptions.
1569 if (op1.isInteger() && op2.isInteger()) {
1570 return graph.addNewLiteralInt(evaluate(op1.value, op2.value));
1571 }
1572 }
1573 return this;
1574 }
1575
1576 // TODO(floitsch): make class abstract instead of adding an abstract method. 1471 // TODO(floitsch): make class abstract instead of adding an abstract method.
1577 abstract accept(HVisitor visitor); 1472 abstract accept(HVisitor visitor);
1578 } 1473 }
1579 1474
1580 class HShiftLeft extends HBinaryBitOp { 1475 class HShiftLeft extends HBinaryBitOp {
1581 HShiftLeft(HStatic target, HInstruction left, HInstruction right) 1476 HShiftLeft(HStatic target, HInstruction left, HInstruction right)
1582 : super(target, left, right); 1477 : super(target, left, right);
1583 accept(HVisitor visitor) => visitor.visitShiftLeft(this); 1478 accept(HVisitor visitor) => visitor.visitShiftLeft(this);
1584 1479
1585 HInstruction fold(HGraph graph) { 1480 String operationAsString() => "<<";
1586 if (right.isLiteralNumber()) {
1587 // TODO(floitsch): find good max left-shift amount.
1588 final int MAX_SHIFT_LEFT_AMOUNT = 50;
1589 HLiteral op2 = right;
1590 // Only positive shifting is allowed. Also guard against out-of-memory
1591 // shifts.
1592 if (op2.value < 0 || op2.value > MAX_SHIFT_LEFT_AMOUNT) return this;
1593 }
1594 return super.fold(graph);
1595 }
1596
1597 int evaluate(int a, int b) => a << b;
1598 int typeCode() => 11; 1481 int typeCode() => 11;
1599 bool typeEquals(other) => other is HShiftLeft; 1482 bool typeEquals(other) => other is HShiftLeft;
1600 bool dataEquals(HInstruction other) => true; 1483 bool dataEquals(HInstruction other) => true;
1601 } 1484 }
1602 1485
1603 class HShiftRight extends HBinaryBitOp { 1486 class HShiftRight extends HBinaryBitOp {
1604 HShiftRight(HStatic target, HInstruction left, HInstruction right) 1487 HShiftRight(HStatic target, HInstruction left, HInstruction right)
1605 : super(target, left, right); 1488 : super(target, left, right);
1606 accept(HVisitor visitor) => visitor.visitShiftRight(this); 1489 accept(HVisitor visitor) => visitor.visitShiftRight(this);
1607 1490
1608 HInstruction fold(HGraph graph) { 1491 String operationAsString() => ">>";
1609 if (right.isLiteralNumber()) {
1610 HLiteral op2 = right;
1611 // Only positive shifting is allowed.
1612 if (op2.value < 0) return this;
1613 }
1614 return super.fold(graph);
1615 }
1616
1617 int evaluate(int a, int b) => a >> b;
1618 int typeCode() => 12; 1492 int typeCode() => 12;
1619 bool typeEquals(other) => other is HShiftRight; 1493 bool typeEquals(other) => other is HShiftRight;
1620 bool dataEquals(HInstruction other) => true; 1494 bool dataEquals(HInstruction other) => true;
1621 } 1495 }
1622 1496
1623 class HBitOr extends HBinaryBitOp { 1497 class HBitOr extends HBinaryBitOp {
1624 HBitOr(HStatic target, HInstruction left, HInstruction right) 1498 HBitOr(HStatic target, HInstruction left, HInstruction right)
1625 : super(target, left, right); 1499 : super(target, left, right);
1626 accept(HVisitor visitor) => visitor.visitBitOr(this); 1500 accept(HVisitor visitor) => visitor.visitBitOr(this);
1627 1501
1628 int evaluate(int a, int b) => a | b; 1502 String operationAsString() => "|";
1629 int typeCode() => 13; 1503 int typeCode() => 13;
1630 bool typeEquals(other) => other is HBitOr; 1504 bool typeEquals(other) => other is HBitOr;
1631 bool dataEquals(HInstruction other) => true; 1505 bool dataEquals(HInstruction other) => true;
1632 } 1506 }
1633 1507
1634 class HBitAnd extends HBinaryBitOp { 1508 class HBitAnd extends HBinaryBitOp {
1635 HBitAnd(HStatic target, HInstruction left, HInstruction right) 1509 HBitAnd(HStatic target, HInstruction left, HInstruction right)
1636 : super(target, left, right); 1510 : super(target, left, right);
1637 accept(HVisitor visitor) => visitor.visitBitAnd(this); 1511 accept(HVisitor visitor) => visitor.visitBitAnd(this);
1638 1512
1639 int evaluate(int a, int b) => a & b; 1513 String operationAsString() => "&";
1640 int typeCode() => 14; 1514 int typeCode() => 14;
1641 bool typeEquals(other) => other is HBitAnd; 1515 bool typeEquals(other) => other is HBitAnd;
1642 bool dataEquals(HInstruction other) => true; 1516 bool dataEquals(HInstruction other) => true;
1643 } 1517 }
1644 1518
1645 class HBitXor extends HBinaryBitOp { 1519 class HBitXor extends HBinaryBitOp {
1646 HBitXor(HStatic target, HInstruction left, HInstruction right) 1520 HBitXor(HStatic target, HInstruction left, HInstruction right)
1647 : super(target, left, right); 1521 : super(target, left, right);
1648 accept(HVisitor visitor) => visitor.visitBitXor(this); 1522 accept(HVisitor visitor) => visitor.visitBitXor(this);
1649 1523
1650 int evaluate(int a, int b) => a ^ b; 1524 String operationAsString() => "^";
1651 int typeCode() => 15; 1525 int typeCode() => 15;
1652 bool typeEquals(other) => other is HBitXor; 1526 bool typeEquals(other) => other is HBitXor;
1653 bool dataEquals(HInstruction other) => true; 1527 bool dataEquals(HInstruction other) => true;
1654 } 1528 }
1655 1529
1656 class HInvokeUnary extends HInvokeStatic { 1530 class HInvokeUnary extends HInvokeStatic {
1657 HInvokeUnary(HStatic target, HInstruction input) 1531 HInvokeUnary(HStatic target, HInstruction input)
1658 : super(Selector.UNARY_OPERATOR, <HInstruction>[target, input]); 1532 : super(Selector.UNARY_OPERATOR, <HInstruction>[target, input]);
1659 1533
1660 HInstruction get operand() => inputs[1]; 1534 HInstruction get operand() => inputs[1];
(...skipping 19 matching lines...) Expand all
1680 1554
1681 HType computeDesiredInputType(HInstruction input) { 1555 HType computeDesiredInputType(HInstruction input) {
1682 // TODO(floitsch): we want the target to be a function. 1556 // TODO(floitsch): we want the target to be a function.
1683 if (input == target) return HType.UNKNOWN; 1557 if (input == target) return HType.UNKNOWN;
1684 if (type.isUnknown() || type.isNumber()) return HType.NUMBER; 1558 if (type.isUnknown() || type.isNumber()) return HType.NUMBER;
1685 return HType.UNKNOWN; 1559 return HType.UNKNOWN;
1686 } 1560 }
1687 1561
1688 bool hasExpectedType() => builtin || (type.isUnknown()); 1562 bool hasExpectedType() => builtin || (type.isUnknown());
1689 1563
1690 abstract HInstruction fold(HGraph graph); 1564 HInstruction fold(HGraph graph) {
1565 if (operand is HConstant) {
1566 HConstant op = operand;
1567 Constant folded = op.constant.unaryFold(operationAsString());
1568 if (folded !== null) return graph.addNewConstant(folded);
1569 }
1570 return this;
1571 }
1691 1572
1692 abstract num evaluate(num a); 1573 abstract String operationAsString();
1693 } 1574 }
1694 1575
1695 class HNegate extends HInvokeUnary { 1576 class HNegate extends HInvokeUnary {
1696 HNegate(HStatic target, HInstruction input) : super(target, input); 1577 HNegate(HStatic target, HInstruction input) : super(target, input);
1697 accept(HVisitor visitor) => visitor.visitNegate(this); 1578 accept(HVisitor visitor) => visitor.visitNegate(this);
1698 1579
1699 HInstruction fold(HGraph graph) { 1580 String operationAsString() => "-";
1700 if (operand.isLiteralNumber()) {
1701 HLiteral input = operand;
1702 return graph.addNewLiteralNum(evaluate(input.value), type);
1703 }
1704 return this;
1705 }
1706
1707 num evaluate(num a) => -a;
1708 int typeCode() => 16; 1581 int typeCode() => 16;
1709 bool typeEquals(other) => other is HNegate; 1582 bool typeEquals(other) => other is HNegate;
1710 bool dataEquals(HInstruction other) => true; 1583 bool dataEquals(HInstruction other) => true;
1711 } 1584 }
1712 1585
1713 class HBitNot extends HInvokeUnary { 1586 class HBitNot extends HInvokeUnary {
1714 HBitNot(HStatic target, HInstruction input) : super(target, input); 1587 HBitNot(HStatic target, HInstruction input) : super(target, input);
1715 accept(HVisitor visitor) => visitor.visitBitNot(this); 1588 accept(HVisitor visitor) => visitor.visitBitNot(this);
1716 1589
1717 HType computeType() { 1590 HType computeType() {
1718 HType type = operand.type; 1591 HType type = operand.type;
1719 builtin = type.isInteger(); 1592 builtin = type.isInteger();
1720 if (!type.isUnknown()) return type; 1593 if (!type.isUnknown()) return type;
1721 return HType.UNKNOWN; 1594 return HType.UNKNOWN;
1722 } 1595 }
1723 1596
1724 HType computeDesiredInputType(HInstruction input) { 1597 HType computeDesiredInputType(HInstruction input) {
1725 // TODO(floitsch): we want the target to be a function. 1598 // TODO(floitsch): we want the target to be a function.
1726 if (input == target) return HType.UNKNOWN; 1599 if (input == target) return HType.UNKNOWN;
1727 return HType.INTEGER; 1600 return HType.INTEGER;
1728 } 1601 }
1729 1602
1730 HInstruction fold(HGraph graph) { 1603 String operationAsString() => "~";
1731 if (operand.isLiteralNumber()) {
1732 HLiteral input = operand;
1733 if (input.isInteger()) {
1734 return graph.addNewLiteralInt(evaluate(input.value));
1735 }
1736 }
1737 return this;
1738 }
1739
1740 int evaluate(int a) => ~a;
1741 int typeCode() => 17; 1604 int typeCode() => 17;
1742 bool typeEquals(other) => other is HBitNot; 1605 bool typeEquals(other) => other is HBitNot;
1743 bool dataEquals(HInstruction other) => true; 1606 bool dataEquals(HInstruction other) => true;
1744 } 1607 }
1745 1608
1746 class HExit extends HControlFlow { 1609 class HExit extends HControlFlow {
1747 HExit() : super(const <HInstruction>[]); 1610 HExit() : super(const <HInstruction>[]);
1748 toString() => 'exit'; 1611 toString() => 'exit';
1749 accept(HVisitor visitor) => visitor.visitExit(this); 1612 accept(HVisitor visitor) => visitor.visitExit(this);
1750 } 1613 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1810 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP]) 1673 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP])
1811 : super(<HInstruction>[condition]); 1674 : super(<HInstruction>[condition]);
1812 toString() => 'loop-branch'; 1675 toString() => 'loop-branch';
1813 accept(HVisitor visitor) => visitor.visitLoopBranch(this); 1676 accept(HVisitor visitor) => visitor.visitLoopBranch(this);
1814 1677
1815 bool isDoWhile() { 1678 bool isDoWhile() {
1816 return kind === DO_WHILE_LOOP; 1679 return kind === DO_WHILE_LOOP;
1817 } 1680 }
1818 } 1681 }
1819 1682
1820 class HLiteral extends HInstruction { 1683 class HConstant extends HInstruction {
1821 final value; 1684 final Constant constant;
1822 HLiteral.internal(this.value, HType type) : super(<HInstruction>[]) { 1685 HConstant.internal(this.constant, HType type) : super(<HInstruction>[]) {
1823 this.type = type; 1686 this.type = type;
1824 tryGenerateAtUseSite(); // Maybe avoid this if the literal is big? 1687 tryGenerateAtUseSite(); // Maybe avoid this if the literal is big?
1825 } 1688 }
1826 1689
1827 void prepareGvn() { 1690 void prepareGvn() {
1828 assert(!hasSideEffects()); 1691 assert(!hasSideEffects());
1829 } 1692 }
1830 1693
1831 toString() => 'literal: $value'; 1694 toString() => 'literal: $constant';
1832 accept(HVisitor visitor) => visitor.visitLiteral(this); 1695 accept(HVisitor visitor) => visitor.visitConstant(this);
1833 HType computeType() => type; 1696 HType computeType() => type;
1834 1697
1835 // Literals have the type they have. It can't be changed. 1698 // Literals have the type they have. It can't be changed.
1836 bool updateType() => false; 1699 bool updateType() => false;
1837 1700
1838 bool hasExpectedType() => true; 1701 bool hasExpectedType() => true;
1839 1702
1840 bool isLiteralBoolean() => value is bool; 1703 bool isBooleanConstant() => constant.isBool();
1841 bool isLiteralNull() => value === null; 1704 bool isNullConstant() => constant.isNull();
1842 bool isLiteralNumber() => value is num; 1705 bool isNumberConstant() => constant.isNum();
1843 bool isLiteralString() => value is DartString; 1706 bool isStringConstant() => constant.isString();
1844 } 1707 }
1845 1708
1846 class HNot extends HInstruction { 1709 class HNot extends HInstruction {
1847 HNot(HInstruction value) : super(<HInstruction>[value]); 1710 HNot(HInstruction value) : super(<HInstruction>[value]);
1848 void prepareGvn() { 1711 void prepareGvn() {
1849 assert(!hasSideEffects()); 1712 assert(!hasSideEffects());
1850 setUseGvn(); 1713 setUseGvn();
1851 } 1714 }
1852 1715
1853 HType computeType() => HType.BOOLEAN; 1716 HType computeType() => HType.BOOLEAN;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1972 // and do not have any side-effects if we know all the inputs are 1835 // and do not have any side-effects if we know all the inputs are
1973 // numbers. This can be improved for at least equality. 1836 // numbers. This can be improved for at least equality.
1974 if (builtin) { 1837 if (builtin) {
1975 assert(!hasSideEffects()); 1838 assert(!hasSideEffects());
1976 setUseGvn(); 1839 setUseGvn();
1977 } else { 1840 } else {
1978 setAllSideEffects(); 1841 setAllSideEffects();
1979 } 1842 }
1980 } 1843 }
1981 1844
1982 HInstruction fold(HGraph graph) {
1983 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1984 HLiteral op1 = left;
1985 HLiteral op2 = right;
1986 return graph.addNewLiteralBool(evaluate(op1.value, op2.value));
1987 }
1988 return this;
1989 }
1990
1991 HType computeType() { 1845 HType computeType() {
1992 builtin = computeInputsType().isNumber(); 1846 builtin = computeInputsType().isNumber();
1993 return HType.BOOLEAN; 1847 return HType.BOOLEAN;
1994 } 1848 }
1995 1849
1996 HType computeDesiredInputType(HInstruction input) { 1850 HType computeDesiredInputType(HInstruction input) {
1997 // TODO(floitsch): we want the target to be a function. 1851 // TODO(floitsch): we want the target to be a function.
1998 if (input == target) return HType.UNKNOWN; 1852 if (input == target) return HType.UNKNOWN;
1999 // For all relational operations exept HEquals, we expect to only 1853 // For all relational operations exept HEquals, we expect to only
2000 // get numbers. 1854 // get numbers.
2001 return HType.NUMBER; 1855 return HType.NUMBER;
2002 } 1856 }
2003 1857
2004 // A HRelational goes through the builtin operator or the top level 1858 // A HRelational goes through the builtin operator or the top level
2005 // element. Therefore, it always has the expected type. 1859 // element. Therefore, it always has the expected type.
2006 bool hasExpectedType() => true; 1860 bool hasExpectedType() => true;
2007
2008 abstract bool evaluate(num a, num b);
2009 } 1861 }
2010 1862
2011 class HEquals extends HRelational { 1863 class HEquals extends HRelational {
2012 HEquals(HStatic target, HInstruction left, HInstruction right) 1864 HEquals(HStatic target, HInstruction left, HInstruction right)
2013 : super(target, left, right); 1865 : super(target, left, right);
2014 bool evaluate(num a, num b) => a == b;
2015 accept(HVisitor visitor) => visitor.visitEquals(this); 1866 accept(HVisitor visitor) => visitor.visitEquals(this);
2016 int typeCode() => 19;
2017 bool typeEquals(other) => other is HEquals;
2018 bool dataEquals(HInstruction other) => true;
2019 1867
2020 HType computeType() { 1868 HType computeType() {
2021 builtin = computeInputsType().isNumber() || (left is HLiteral); 1869 builtin = computeInputsType().isNumber() || (left is HConstant);
2022 return HType.BOOLEAN; 1870 return HType.BOOLEAN;
2023 } 1871 }
2024 1872
2025 HType computeDesiredInputType(HInstruction input) { 1873 HType computeDesiredInputType(HInstruction input) {
2026 // TODO(floitsch): we want the target to be a function. 1874 // TODO(floitsch): we want the target to be a function.
2027 if (input == target) return HType.UNKNOWN; 1875 if (input == target) return HType.UNKNOWN;
2028 if (left.isNumber() || right.isNumber()) return HType.NUMBER; 1876 if (left.isNumber() || right.isNumber()) return HType.NUMBER;
2029 return HType.UNKNOWN; 1877 return HType.UNKNOWN;
2030 } 1878 }
1879
1880 String operationAsString() => "==";
1881 int typeCode() => 19;
1882 bool typeEquals(other) => other is HEquals;
1883 bool dataEquals(HInstruction other) => true;
2031 } 1884 }
2032 1885
2033 class HIdentity extends HRelational { 1886 class HIdentity extends HRelational {
2034 HIdentity(HStatic target, HInstruction left, HInstruction right) 1887 HIdentity(HStatic target, HInstruction left, HInstruction right)
2035 : super(target, left, right); 1888 : super(target, left, right);
2036 bool evaluate(num a, num b) => a === b;
2037 accept(HVisitor visitor) => visitor.visitIdentity(this); 1889 accept(HVisitor visitor) => visitor.visitIdentity(this);
2038 int typeCode() => 20;
2039 bool typeEquals(other) => other is HIdentity;
2040 bool dataEquals(HInstruction other) => true;
2041 1890
2042 HType computeType() { 1891 HType computeType() {
2043 builtin = true; 1892 builtin = true;
2044 return HType.BOOLEAN; 1893 return HType.BOOLEAN;
2045 } 1894 }
2046 1895
2047 bool hasExpectedType() => true; 1896 bool hasExpectedType() => true;
2048 1897
2049 HType computeDesiredInputType(HInstruction input) => HType.UNKNOWN; 1898 HType computeDesiredInputType(HInstruction input) => HType.UNKNOWN;
1899
1900 String operationAsString() => "===";
1901 int typeCode() => 20;
1902 bool typeEquals(other) => other is HIdentity;
1903 bool dataEquals(HInstruction other) => true;
2050 } 1904 }
2051 1905
2052 class HGreater extends HRelational { 1906 class HGreater extends HRelational {
2053 HGreater(HStatic target, HInstruction left, HInstruction right) 1907 HGreater(HStatic target, HInstruction left, HInstruction right)
2054 : super(target, left, right); 1908 : super(target, left, right);
2055 bool evaluate(num a, num b) => a > b;
2056 accept(HVisitor visitor) => visitor.visitGreater(this); 1909 accept(HVisitor visitor) => visitor.visitGreater(this);
1910
1911 String operationAsString() => ">";
2057 int typeCode() => 21; 1912 int typeCode() => 21;
2058 bool typeEquals(other) => other is HGreater; 1913 bool typeEquals(other) => other is HGreater;
2059 bool dataEquals(HInstruction other) => true; 1914 bool dataEquals(HInstruction other) => true;
2060 } 1915 }
2061 1916
2062 class HGreaterEqual extends HRelational { 1917 class HGreaterEqual extends HRelational {
2063 HGreaterEqual(HStatic target, HInstruction left, HInstruction right) 1918 HGreaterEqual(HStatic target, HInstruction left, HInstruction right)
2064 : super(target, left, right); 1919 : super(target, left, right);
2065 bool evaluate(num a, num b) => a >= b;
2066 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); 1920 accept(HVisitor visitor) => visitor.visitGreaterEqual(this);
1921
1922 String operationAsString() => ">=";
2067 int typeCode() => 22; 1923 int typeCode() => 22;
2068 bool typeEquals(other) => other is HGreaterEqual; 1924 bool typeEquals(other) => other is HGreaterEqual;
2069 bool dataEquals(HInstruction other) => true; 1925 bool dataEquals(HInstruction other) => true;
2070 } 1926 }
2071 1927
2072 class HLess extends HRelational { 1928 class HLess extends HRelational {
2073 HLess(HStatic target, HInstruction left, HInstruction right) 1929 HLess(HStatic target, HInstruction left, HInstruction right)
2074 : super(target, left, right); 1930 : super(target, left, right);
2075 bool evaluate(num a, num b) => a < b;
2076 accept(HVisitor visitor) => visitor.visitLess(this); 1931 accept(HVisitor visitor) => visitor.visitLess(this);
1932
1933 String operationAsString() => "<";
1934 int typeCode() => 23;
2077 bool typeEquals(other) => other is HLess; 1935 bool typeEquals(other) => other is HLess;
2078 bool dataEquals(HInstruction other) => true; 1936 bool dataEquals(HInstruction other) => true;
2079 } 1937 }
2080 1938
2081 class HLessEqual extends HRelational { 1939 class HLessEqual extends HRelational {
2082 HLessEqual(HStatic target, HInstruction left, HInstruction right) 1940 HLessEqual(HStatic target, HInstruction left, HInstruction right)
2083 : super(target, left, right); 1941 : super(target, left, right);
2084 bool evaluate(num a, num b) => a <= b;
2085 accept(HVisitor visitor) => visitor.visitLessEqual(this); 1942 accept(HVisitor visitor) => visitor.visitLessEqual(this);
2086 int typeCode() => 23; 1943
1944 String operationAsString() => "<=";
1945 int typeCode() => 24;
2087 bool typeEquals(other) => other is HLessEqual; 1946 bool typeEquals(other) => other is HLessEqual;
2088 bool dataEquals(HInstruction other) => true; 1947 bool dataEquals(HInstruction other) => true;
2089 } 1948 }
2090 1949
2091 class HReturn extends HControlFlow { 1950 class HReturn extends HControlFlow {
2092 HReturn(value) : super(<HInstruction>[value]); 1951 HReturn(value) : super(<HInstruction>[value]);
2093 toString() => 'return'; 1952 toString() => 'return';
2094 accept(HVisitor visitor) => visitor.visitReturn(this); 1953 accept(HVisitor visitor) => visitor.visitReturn(this);
2095 } 1954 }
2096 1955
(...skipping 12 matching lines...) Expand all
2109 void prepareGvn() { 1968 void prepareGvn() {
2110 assert(!hasSideEffects()); 1969 assert(!hasSideEffects());
2111 if (!element.isAssignable()) { 1970 if (!element.isAssignable()) {
2112 setUseGvn(); 1971 setUseGvn();
2113 } 1972 }
2114 } 1973 }
2115 toString() => 'static ${element.name}'; 1974 toString() => 'static ${element.name}';
2116 accept(HVisitor visitor) => visitor.visitStatic(this); 1975 accept(HVisitor visitor) => visitor.visitStatic(this);
2117 1976
2118 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode(); 1977 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode();
2119 int typeCode() => 24; 1978 int typeCode() => 25;
2120 bool typeEquals(other) => other is HStatic; 1979 bool typeEquals(other) => other is HStatic;
2121 bool dataEquals(HStatic other) => element == other.element; 1980 bool dataEquals(HStatic other) => element == other.element;
2122 } 1981 }
2123 1982
2124 class HStaticStore extends HInstruction { 1983 class HStaticStore extends HInstruction {
2125 Element element; 1984 Element element;
2126 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]); 1985 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]);
2127 toString() => 'static store ${element.name}'; 1986 toString() => 'static store ${element.name}';
2128 accept(HVisitor visitor) => visitor.visitStaticStore(this); 1987 accept(HVisitor visitor) => visitor.visitStaticStore(this);
2129 1988
2130 int typeCode() => 25; 1989 int typeCode() => 26;
2131 bool typeEquals(other) => other is HStaticStore; 1990 bool typeEquals(other) => other is HStaticStore;
2132 bool dataEquals(HStaticStore other) => element == other.element; 1991 bool dataEquals(HStaticStore other) => element == other.element;
2133 } 1992 }
2134 1993
2135 class HLiteralList extends HInstruction { 1994 class HLiteralList extends HInstruction {
2136 HLiteralList(inputs, this.isConst) : super(inputs); 1995 HLiteralList(inputs, this.isConst) : super(inputs);
2137 toString() => 'literal list'; 1996 toString() => 'literal list';
2138 accept(HVisitor visitor) => visitor.visitLiteralList(this); 1997 accept(HVisitor visitor) => visitor.visitLiteralList(this);
2139 HType computeType() => HType.ARRAY; 1998 HType computeType() => HType.ARRAY;
2140 bool hasExpectedType() => true; 1999 bool hasExpectedType() => true;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
2266 2125
2267 HInstruction get expression() => inputs[0]; 2126 HInstruction get expression() => inputs[0];
2268 2127
2269 HType computeType() => HType.BOOLEAN; 2128 HType computeType() => HType.BOOLEAN;
2270 bool hasExpectedType() => true; 2129 bool hasExpectedType() => true;
2271 2130
2272 accept(HVisitor visitor) => visitor.visitIs(this); 2131 accept(HVisitor visitor) => visitor.visitIs(this);
2273 2132
2274 toString() => "$expression is $typeExpression"; 2133 toString() => "$expression is $typeExpression";
2275 } 2134 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698