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

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

Issue 9592009: Reapply "Refactor constant part." (r4958) with fixes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update tests and fix code after renaming. 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 static HType mapConstantTypeToSsaType(Constant constant) {
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 addConstant(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() { 172 HConstant addConstantInt(int i) {
169 if (nanLiteral === null) { 173 return addConstant(new IntConstant(i));
170 nanLiteral = new HLiteral.internal(double.NAN, HType.DOUBLE);
171 entry.addAtExit(nanLiteral);
172 }
173 return nanLiteral;
174 } 174 }
175 175
176 HLiteral addNewNegativeZeroLiteral() { 176 HConstant addConstantDouble(int d) {
177 if (negativeZeroLiteral === null) { 177 return addConstant(new DoubleConstant(d));
178 negativeZeroLiteral = new HLiteral.internal(-0.0, HType.DOUBLE);
179 entry.addAtExit(negativeZeroLiteral);
180 }
181 return negativeZeroLiteral;
182 } 178 }
183 179
184 HLiteral addNewLiteralDouble(double value) { 180 HConstant addConstantString(DartString str) {
185 if (value.isNaN()) return addNewLiteralNaN(); // Avoid hashing NaN. 181 return addConstant(new StringConstant(str));
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 } 182 }
199 183
200 HLiteral addNewLiteralNum(num value, HType type) { 184 HConstant addConstantBool(bool value) {
201 // If we've propagated type information then the type must be a 185 return addConstant(new BoolConstant(value));
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 } 186 }
218 187
219 HLiteral addNewLiteralTrue() { 188 HConstant addConstantNull() {
220 if (trueLiteral === null) { 189 return addConstant(const NullConstant());
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 } 190 }
258 191
259 void finalize() { 192 void finalize() {
260 addBlock(exit); 193 addBlock(exit);
261 exit.open(); 194 exit.open();
262 exit.close(new HExit()); 195 exit.close(new HExit());
263 assignDominators(); 196 assignDominators();
264 } 197 }
265 198
266 void assignDominators() { 199 void assignDominators() {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 visitAdd(HAdd node) => visitBinaryArithmetic(node); 250 visitAdd(HAdd node) => visitBinaryArithmetic(node);
318 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); 251 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
319 visitBitNot(HBitNot node) => visitInvokeUnary(node); 252 visitBitNot(HBitNot node) => visitInvokeUnary(node);
320 visitBitOr(HBitOr node) => visitBinaryBitOp(node); 253 visitBitOr(HBitOr node) => visitBinaryBitOp(node);
321 visitBitXor(HBitXor node) => visitBinaryBitOp(node); 254 visitBitXor(HBitXor node) => visitBinaryBitOp(node);
322 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); 255 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node);
323 visitBoolify(HBoolify node) => visitInstruction(node); 256 visitBoolify(HBoolify node) => visitInstruction(node);
324 visitBoundsCheck(HBoundsCheck node) => visitCheck(node); 257 visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
325 visitBreak(HBreak node) => visitGoto(node); 258 visitBreak(HBreak node) => visitGoto(node);
326 visitCheck(HCheck node) => visitInstruction(node); 259 visitCheck(HCheck node) => visitInstruction(node);
260 visitConstant(HConstant node) => visitInstruction(node);
327 visitDivide(HDivide node) => visitBinaryArithmetic(node); 261 visitDivide(HDivide node) => visitBinaryArithmetic(node);
328 visitEquals(HEquals node) => visitRelational(node); 262 visitEquals(HEquals node) => visitRelational(node);
329 visitExit(HExit node) => visitControlFlow(node); 263 visitExit(HExit node) => visitControlFlow(node);
330 visitFieldGet(HFieldGet node) => visitInstruction(node); 264 visitFieldGet(HFieldGet node) => visitInstruction(node);
331 visitFieldSet(HFieldSet node) => visitInstruction(node); 265 visitFieldSet(HFieldSet node) => visitInstruction(node);
332 visitForeign(HForeign node) => visitInstruction(node); 266 visitForeign(HForeign node) => visitInstruction(node);
333 visitForeignNew(HForeignNew node) => visitForeign(node); 267 visitForeignNew(HForeignNew node) => visitForeign(node);
334 visitGoto(HGoto node) => visitControlFlow(node); 268 visitGoto(HGoto node) => visitControlFlow(node);
335 visitGreater(HGreater node) => visitRelational(node); 269 visitGreater(HGreater node) => visitRelational(node);
336 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); 270 visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
(...skipping 12 matching lines...) Expand all
349 => visitInvokeDynamicField(node); 283 => visitInvokeDynamicField(node);
350 visitInvokeInterceptor(HInvokeInterceptor node) 284 visitInvokeInterceptor(HInvokeInterceptor node)
351 => visitInvokeStatic(node); 285 => visitInvokeStatic(node);
352 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); 286 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
353 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node); 287 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node);
354 visitLess(HLess node) => visitRelational(node); 288 visitLess(HLess node) => visitRelational(node);
355 visitLessEqual(HLessEqual node) => visitRelational(node); 289 visitLessEqual(HLessEqual node) => visitRelational(node);
356 visitLoad(HLoad node) => visitInstruction(node); 290 visitLoad(HLoad node) => visitInstruction(node);
357 visitLocal(HLocal node) => visitInstruction(node); 291 visitLocal(HLocal node) => visitInstruction(node);
358 visitLogicalOperator(HLogicalOperator node) => visitInstruction(node); 292 visitLogicalOperator(HLogicalOperator node) => visitInstruction(node);
359 visitLiteral(HLiteral node) => visitInstruction(node);
360 visitLiteralList(HLiteralList node) => visitInstruction(node); 293 visitLiteralList(HLiteralList node) => visitInstruction(node);
361 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); 294 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
362 visitModulo(HModulo node) => visitBinaryArithmetic(node); 295 visitModulo(HModulo node) => visitBinaryArithmetic(node);
363 visitNegate(HNegate node) => visitInvokeUnary(node); 296 visitNegate(HNegate node) => visitInvokeUnary(node);
364 visitNot(HNot node) => visitInstruction(node); 297 visitNot(HNot node) => visitInstruction(node);
365 visitPhi(HPhi node) => visitInstruction(node); 298 visitPhi(HPhi node) => visitInstruction(node);
366 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); 299 visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
367 visitParameterValue(HParameterValue node) => visitInstruction(node); 300 visitParameterValue(HParameterValue node) => visitInstruction(node);
368 visitReturn(HReturn node) => visitControlFlow(node); 301 visitReturn(HReturn node) => visitControlFlow(node);
369 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node); 302 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
1010 inputUsedBy[j] = inputUsedBy[inputUsedBy.length - 1]; 943 inputUsedBy[j] = inputUsedBy[inputUsedBy.length - 1];
1011 inputUsedBy.removeLast(); 944 inputUsedBy.removeLast();
1012 break; 945 break;
1013 } 946 }
1014 } 947 }
1015 } 948 }
1016 this.block = null; 949 this.block = null;
1017 assert(isValid()); 950 assert(isValid());
1018 } 951 }
1019 952
1020 bool isLiteralNull() => false; 953 bool isConstant() => false;
1021 bool isLiteralNumber() => false; 954 bool isConstantNull() => false;
1022 bool isLiteralString() => false; 955 bool isConstantNumber() => false;
956 bool isConstantString() => false;
1023 957
1024 bool isValid() { 958 bool isValid() {
1025 HValidator validator = new HValidator(); 959 HValidator validator = new HValidator();
1026 validator.currentBlock = block; 960 validator.currentBlock = block;
1027 validator.visitInstruction(this); 961 validator.visitInstruction(this);
1028 return validator.isValid; 962 return validator.isValid;
1029 } 963 }
1030 } 964 }
1031 965
1032 class HBoolify extends HInstruction { 966 class HBoolify extends HInstruction {
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 || name == const SourceString('removeLast')) { 1208 || name == const SourceString('removeLast')) {
1275 return HType.ARRAY; 1209 return HType.ARRAY;
1276 } 1210 }
1277 } 1211 }
1278 return HType.UNKNOWN; 1212 return HType.UNKNOWN;
1279 } 1213 }
1280 1214
1281 bool hasExpectedType() => builtinJsName != null; 1215 bool hasExpectedType() => builtinJsName != null;
1282 1216
1283 HInstruction fold(HGraph graph) { 1217 HInstruction fold(HGraph graph) {
1284 if (name == const SourceString('length') && inputs[1].isLiteralString()) { 1218 if (name == const SourceString('length') && inputs[1].isConstantString()) {
1285 HLiteral input = inputs[1]; 1219 HConstant input = inputs[1];
1286 DartString string = input.value; 1220 DartString string = input.constant.value;
1287 return graph.addNewLiteralInt(string.length); 1221 return graph.addConstantInt(string.length);
1288 } 1222 }
1289 return this; 1223 return this;
1290 } 1224 }
1291 1225
1292 void prepareGvn() { 1226 void prepareGvn() {
1293 if (builtinJsName == 'length') { 1227 if (builtinJsName == 'length') {
1294 assert(!hasSideEffects()); 1228 assert(!hasSideEffects());
1295 } else { 1229 } else {
1296 setAllSideEffects(); 1230 setAllSideEffects();
1297 } 1231 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1372 1306
1373 HType computeInputsType() { 1307 HType computeInputsType() {
1374 HType leftType = left.type; 1308 HType leftType = left.type;
1375 HType rightType = right.type; 1309 HType rightType = right.type;
1376 if (leftType.isUnknown() || rightType.isUnknown()) { 1310 if (leftType.isUnknown() || rightType.isUnknown()) {
1377 return HType.UNKNOWN; 1311 return HType.UNKNOWN;
1378 } 1312 }
1379 return leftType.combine(rightType); 1313 return leftType.combine(rightType);
1380 } 1314 }
1381 1315
1382 abstract HInstruction fold(HGraph graph); 1316 HInstruction fold(HGraph graph) {
1383 abstract evaluate(num a, num b); 1317 if (left is HConstant && right is HConstant) {
1318 HConstant op1 = left;
1319 HConstant op2 = right;
1320 Constant folded =
1321 op1.constant.binaryFold(operationAsString(), op2.constant);
1322 if (folded !== null) return graph.addConstant(folded);
1323 }
1324 return this;
1325 }
1326 abstract String operationAsString();
1384 } 1327 }
1385 1328
1386 class HBinaryArithmetic extends HInvokeBinary { 1329 class HBinaryArithmetic extends HInvokeBinary {
1387 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) 1330 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right)
1388 : super(target, left, right); 1331 : super(target, left, right);
1389 1332
1390 void prepareGvn() { 1333 void prepareGvn() {
1391 // An arithmetic expression can take part in global value 1334 // An arithmetic expression can take part in global value
1392 // numbering and do not have any side-effects if we know that all 1335 // numbering and do not have any side-effects if we know that all
1393 // inputs are numbers. 1336 // inputs are numbers.
1394 if (builtin) { 1337 if (builtin) {
1395 assert(!hasSideEffects()); 1338 assert(!hasSideEffects());
1396 setUseGvn(); 1339 setUseGvn();
1397 } else { 1340 } else {
1398 setAllSideEffects(); 1341 setAllSideEffects();
1399 } 1342 }
1400 } 1343 }
1401 1344
1402 HInstruction fold(HGraph graph) {
1403 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1404 HLiteral op1 = left;
1405 HLiteral op2 = right;
1406 return graph.addNewLiteralNum(evaluate(op1.value, op2.value), type);
1407 }
1408 return this;
1409 }
1410
1411 HType computeType() { 1345 HType computeType() {
1412 HType type = computeInputsType(); 1346 HType type = computeInputsType();
1413 builtin = type.isNumber(); 1347 builtin = type.isNumber();
1414 if (!type.isUnknown()) return type; 1348 if (!type.isUnknown()) return type;
1415 if (left.isNumber()) return HType.NUMBER; 1349 if (left.isNumber()) return HType.NUMBER;
1416 return HType.UNKNOWN; 1350 return HType.UNKNOWN;
1417 } 1351 }
1418 1352
1419 HType computeDesiredInputType(HInstruction input) { 1353 HType computeDesiredInputType(HInstruction input) {
1420 // TODO(floitsch): we want the target to be a function. 1354 // TODO(floitsch): we want the target to be a function.
1421 if (input == target) return HType.UNKNOWN; 1355 if (input == target) return HType.UNKNOWN;
1422 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; 1356 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER;
1423 if (type.isUnknown()) return HType.NUMBER; 1357 if (type.isUnknown()) return HType.NUMBER;
1424 return HType.UNKNOWN; 1358 return HType.UNKNOWN;
1425 } 1359 }
1426 1360
1427 bool hasExpectedType() => builtin || type.isUnknown(); 1361 bool hasExpectedType() => builtin || type.isUnknown();
1428
1429 abstract num evaluate(num a, num b);
1430 } 1362 }
1431 1363
1432 class HAdd extends HBinaryArithmetic { 1364 class HAdd extends HBinaryArithmetic {
1433 HAdd(HStatic target, HInstruction left, HInstruction right) 1365 HAdd(HStatic target, HInstruction left, HInstruction right)
1434 : super(target, left, right); 1366 : super(target, left, right);
1435 accept(HVisitor visitor) => visitor.visitAdd(this); 1367 accept(HVisitor visitor) => visitor.visitAdd(this);
1436 num evaluate(num a, num b) => a + b;
1437 int typeCode() => 5;
1438 bool typeEquals(other) => other is HAdd;
1439 bool dataEquals(HInstruction other) => true;
1440 1368
1441 HType computeType() { 1369 HType computeType() {
1442 HType type = computeInputsType(); 1370 HType type = computeInputsType();
1443 builtin = (type.isNumber() || type.isString()); 1371 builtin = (type.isNumber() || type.isString());
1444 if (type.isConflicting() && left.isString()) { 1372 if (type.isConflicting() && left.isString()) {
1445 builtin = right is HLiteral; 1373 builtin = right is HConstant;
1446 return HType.STRING; 1374 return HType.STRING;
1447 } 1375 }
1448 if (!type.isUnknown()) return type; 1376 if (!type.isUnknown()) return type;
1449 if (left.isNumber()) return HType.NUMBER; 1377 if (left.isNumber()) return HType.NUMBER;
1450 return HType.UNKNOWN; 1378 return HType.UNKNOWN;
1451 } 1379 }
1452 1380
1453 bool hasExpectedType() => builtin || type.isUnknown() || left.isString(); 1381 bool hasExpectedType() => builtin || type.isUnknown() || left.isString();
1454 1382
1455 HType computeDesiredInputType(HInstruction input) { 1383 HType computeDesiredInputType(HInstruction input) {
1456 // TODO(floitsch): we want the target to be a function. 1384 // TODO(floitsch): we want the target to be a function.
1457 if (input == target) return HType.UNKNOWN; 1385 if (input == target) return HType.UNKNOWN;
1458 if (isString() || left.isString()) { 1386 if (isString() || left.isString()) {
1459 return (input == left) ? HType.STRING : HType.UNKNOWN; 1387 return (input == left) ? HType.STRING : HType.UNKNOWN;
1460 } 1388 }
1461 if (right.isString()) return HType.STRING; 1389 if (right.isString()) return HType.STRING;
1462 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER; 1390 if (isNumber() || left.isNumber() || right.isNumber()) return HType.NUMBER;
1463 return HType.UNKNOWN; 1391 return HType.UNKNOWN;
1464 } 1392 }
1465 1393
1466 HInstruction fold(HGraph graph) { 1394 HInstruction fold(HGraph graph) {
1467 if (left.isLiteralString() && right is HLiteral) { 1395 // TODO(floitsch): move this code to the compile-time-constant handler.
1468 HLiteral op1 = left; 1396 if (left.isConstantString() && right is HConstant) {
1469 HLiteral op2 = right; 1397 HConstant op1 = left;
1470 DartString leftString = op1.value; 1398 HConstant op2 = right;
1399 DartString leftString = op1.constant.value;
1471 DartString otherString = null; 1400 DartString otherString = null;
1472 if (right.isLiteralString()) { 1401 if (right.isConstantString()) {
1473 otherString = op2.value; 1402 otherString = op2.constant.value;
1474 } else { 1403 } else {
1475 assert(op2.isLiteralNumber() || 1404 assert(op2.isConstantNumber() ||
1476 op2.isLiteralBoolean() || 1405 op2.isConstantBoolean() ||
1477 op2.isLiteralNull()); 1406 op2.isConstantNull());
1478 otherString = new DartString.literal(op2.value.toString()); 1407 otherString = new DartString.literal(op2.constant.value.toString());
1479 } 1408 }
1480 DartString cons = new ConsDartString(leftString, otherString); 1409 DartString cons = new ConsDartString(leftString, otherString);
1481 return graph.addNewLiteralString(cons); 1410 return graph.addConstantString(cons);
1482 } 1411 }
1483 return super.fold(graph); 1412 return super.fold(graph);
1484 } 1413 }
1414
1415 String operationAsString() => "+";
1416 int typeCode() => 5;
1417 bool typeEquals(other) => other is HAdd;
1418 bool dataEquals(HInstruction other) => true;
1485 } 1419 }
1486 1420
1487 class HDivide extends HBinaryArithmetic { 1421 class HDivide extends HBinaryArithmetic {
1488 HDivide(HStatic target, HInstruction left, HInstruction right) 1422 HDivide(HStatic target, HInstruction left, HInstruction right)
1489 : super(target, left, right); 1423 : super(target, left, right);
1490 accept(HVisitor visitor) => visitor.visitDivide(this); 1424 accept(HVisitor visitor) => visitor.visitDivide(this);
1491 1425
1492 HType computeType() { 1426 HType computeType() {
1493 HType type = computeInputsType(); 1427 HType type = computeInputsType();
1494 builtin = type.isNumber(); 1428 builtin = type.isNumber();
1495 if (left.isNumber()) return HType.DOUBLE; 1429 if (left.isNumber()) return HType.DOUBLE;
1496 return HType.UNKNOWN; 1430 return HType.UNKNOWN;
1497 } 1431 }
1498 1432
1499 num evaluate(num a, num b) => a / b; 1433 String operationAsString() => "/";
1500 int typeCode() => 6; 1434 int typeCode() => 6;
1501 bool typeEquals(other) => other is HDivide; 1435 bool typeEquals(other) => other is HDivide;
1502 bool dataEquals(HInstruction other) => true; 1436 bool dataEquals(HInstruction other) => true;
1503 } 1437 }
1504 1438
1505 class HModulo extends HBinaryArithmetic { 1439 class HModulo extends HBinaryArithmetic {
1506 HModulo(HStatic target, HInstruction left, HInstruction right) 1440 HModulo(HStatic target, HInstruction left, HInstruction right)
1507 : super(target, left, right); 1441 : super(target, left, right);
1508 accept(HVisitor visitor) => visitor.visitModulo(this); 1442 accept(HVisitor visitor) => visitor.visitModulo(this);
1509 num evaluate(num a, num b) => a % b; 1443
1444 String operationAsString() => "%";
1510 int typeCode() => 7; 1445 int typeCode() => 7;
1511 bool typeEquals(other) => other is HModulo; 1446 bool typeEquals(other) => other is HModulo;
1512 bool dataEquals(HInstruction other) => true; 1447 bool dataEquals(HInstruction other) => true;
1513 } 1448 }
1514 1449
1515 class HMultiply extends HBinaryArithmetic { 1450 class HMultiply extends HBinaryArithmetic {
1516 HMultiply(HStatic target, HInstruction left, HInstruction right) 1451 HMultiply(HStatic target, HInstruction left, HInstruction right)
1517 : super(target, left, right); 1452 : super(target, left, right);
1518 accept(HVisitor visitor) => visitor.visitMultiply(this); 1453 accept(HVisitor visitor) => visitor.visitMultiply(this);
1519 num evaluate(num a, num b) => a * b; 1454
1455 String operationAsString() => "*";
1520 int typeCode() => 8; 1456 int typeCode() => 8;
1521 bool typeEquals(other) => other is HMultiply; 1457 bool typeEquals(other) => other is HMultiply;
1522 bool dataEquals(HInstruction other) => true; 1458 bool dataEquals(HInstruction other) => true;
1523 } 1459 }
1524 1460
1525 class HSubtract extends HBinaryArithmetic { 1461 class HSubtract extends HBinaryArithmetic {
1526 HSubtract(HStatic target, HInstruction left, HInstruction right) 1462 HSubtract(HStatic target, HInstruction left, HInstruction right)
1527 : super(target, left, right); 1463 : super(target, left, right);
1528 accept(HVisitor visitor) => visitor.visitSubtract(this); 1464 accept(HVisitor visitor) => visitor.visitSubtract(this);
1529 num evaluate(num a, num b) => a - b; 1465
1466 String operationAsString() => "-";
1530 int typeCode() => 9; 1467 int typeCode() => 9;
1531 bool typeEquals(other) => other is HSubtract; 1468 bool typeEquals(other) => other is HSubtract;
1532 bool dataEquals(HInstruction other) => true; 1469 bool dataEquals(HInstruction other) => true;
1533 } 1470 }
1534 1471
1535 class HTruncatingDivide extends HBinaryArithmetic { 1472 class HTruncatingDivide extends HBinaryArithmetic {
1536 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right) 1473 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right)
1537 : super(target, left, right); 1474 : super(target, left, right);
1538 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this); 1475 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);
1539 1476
1540 HInstruction fold(HGraph graph) { 1477 String operationAsString() => "~/";
1541 // Avoid a DivisionByZeroException.
1542 if (right.isLiteralNumber() && right.dynamic.value == 0) {
1543 return this;
1544 }
1545 return super.fold(graph);
1546 }
1547
1548 num evaluate(num a, num b) => a ~/ b;
1549 int typeCode() => 10; 1478 int typeCode() => 10;
1550 bool typeEquals(other) => other is HTruncatingDivide; 1479 bool typeEquals(other) => other is HTruncatingDivide;
1551 bool dataEquals(HInstruction other) => true; 1480 bool dataEquals(HInstruction other) => true;
1552 } 1481 }
1553 1482
1554 1483
1555 // TODO(floitsch): Should HBinaryArithmetic really be the super class of 1484 // TODO(floitsch): Should HBinaryArithmetic really be the super class of
1556 // HBinaryBitOp? 1485 // HBinaryBitOp?
1557 class HBinaryBitOp extends HBinaryArithmetic { 1486 class HBinaryBitOp extends HBinaryArithmetic {
1558 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right) 1487 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right)
1559 : super(target, left, right); 1488 : super(target, left, right);
1560 1489
1561 HType computeType() { 1490 HType computeType() {
1562 HType type = computeInputsType(); 1491 HType type = computeInputsType();
1563 builtin = type.isInteger(); 1492 builtin = type.isInteger();
1564 if (!type.isUnknown()) return type; 1493 if (!type.isUnknown()) return type;
1565 if (left.isInteger()) return HType.INTEGER; 1494 if (left.isInteger()) return HType.INTEGER;
1566 return HType.UNKNOWN; 1495 return HType.UNKNOWN;
1567 } 1496 }
1568 1497
1569 HType computeDesiredInputType(HInstruction input) { 1498 HType computeDesiredInputType(HInstruction input) {
1570 // TODO(floitsch): we want the target to be a function. 1499 // TODO(floitsch): we want the target to be a function.
1571 if (input == target) return HType.UNKNOWN; 1500 if (input == target) return HType.UNKNOWN;
1572 return HType.INTEGER; 1501 return HType.INTEGER;
1573 } 1502 }
1574 1503
1575 HInstruction fold(HGraph graph) {
1576 // Bit-operations are only defined on integers.
1577 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1578 HLiteral op1 = left;
1579 HLiteral op2 = right;
1580 // Avoid exceptions.
1581 if (op1.isInteger() && op2.isInteger()) {
1582 return graph.addNewLiteralInt(evaluate(op1.value, op2.value));
1583 }
1584 }
1585 return this;
1586 }
1587
1588 // TODO(floitsch): make class abstract instead of adding an abstract method. 1504 // TODO(floitsch): make class abstract instead of adding an abstract method.
1589 abstract accept(HVisitor visitor); 1505 abstract accept(HVisitor visitor);
1590 } 1506 }
1591 1507
1592 class HShiftLeft extends HBinaryBitOp { 1508 class HShiftLeft extends HBinaryBitOp {
1593 HShiftLeft(HStatic target, HInstruction left, HInstruction right) 1509 HShiftLeft(HStatic target, HInstruction left, HInstruction right)
1594 : super(target, left, right); 1510 : super(target, left, right);
1595 accept(HVisitor visitor) => visitor.visitShiftLeft(this); 1511 accept(HVisitor visitor) => visitor.visitShiftLeft(this);
1596 1512
1597 HInstruction fold(HGraph graph) { 1513 String operationAsString() => "<<";
1598 if (right.isLiteralNumber()) {
1599 // TODO(floitsch): find good max left-shift amount.
1600 final int MAX_SHIFT_LEFT_AMOUNT = 50;
1601 HLiteral op2 = right;
1602 // Only positive shifting is allowed. Also guard against out-of-memory
1603 // shifts.
1604 if (op2.value < 0 || op2.value > MAX_SHIFT_LEFT_AMOUNT) return this;
1605 }
1606 return super.fold(graph);
1607 }
1608
1609 int evaluate(int a, int b) => a << b;
1610 int typeCode() => 11; 1514 int typeCode() => 11;
1611 bool typeEquals(other) => other is HShiftLeft; 1515 bool typeEquals(other) => other is HShiftLeft;
1612 bool dataEquals(HInstruction other) => true; 1516 bool dataEquals(HInstruction other) => true;
1613 } 1517 }
1614 1518
1615 class HShiftRight extends HBinaryBitOp { 1519 class HShiftRight extends HBinaryBitOp {
1616 HShiftRight(HStatic target, HInstruction left, HInstruction right) 1520 HShiftRight(HStatic target, HInstruction left, HInstruction right)
1617 : super(target, left, right); 1521 : super(target, left, right);
1618 accept(HVisitor visitor) => visitor.visitShiftRight(this); 1522 accept(HVisitor visitor) => visitor.visitShiftRight(this);
1619 1523
1620 HInstruction fold(HGraph graph) { 1524 String operationAsString() => ">>";
1621 if (right.isLiteralNumber()) {
1622 HLiteral op2 = right;
1623 // Only positive shifting is allowed.
1624 if (op2.value < 0) return this;
1625 }
1626 return super.fold(graph);
1627 }
1628
1629 int evaluate(int a, int b) => a >> b;
1630 int typeCode() => 12; 1525 int typeCode() => 12;
1631 bool typeEquals(other) => other is HShiftRight; 1526 bool typeEquals(other) => other is HShiftRight;
1632 bool dataEquals(HInstruction other) => true; 1527 bool dataEquals(HInstruction other) => true;
1633 } 1528 }
1634 1529
1635 class HBitOr extends HBinaryBitOp { 1530 class HBitOr extends HBinaryBitOp {
1636 HBitOr(HStatic target, HInstruction left, HInstruction right) 1531 HBitOr(HStatic target, HInstruction left, HInstruction right)
1637 : super(target, left, right); 1532 : super(target, left, right);
1638 accept(HVisitor visitor) => visitor.visitBitOr(this); 1533 accept(HVisitor visitor) => visitor.visitBitOr(this);
1639 1534
1640 int evaluate(int a, int b) => a | b; 1535 String operationAsString() => "|";
1641 int typeCode() => 13; 1536 int typeCode() => 13;
1642 bool typeEquals(other) => other is HBitOr; 1537 bool typeEquals(other) => other is HBitOr;
1643 bool dataEquals(HInstruction other) => true; 1538 bool dataEquals(HInstruction other) => true;
1644 } 1539 }
1645 1540
1646 class HBitAnd extends HBinaryBitOp { 1541 class HBitAnd extends HBinaryBitOp {
1647 HBitAnd(HStatic target, HInstruction left, HInstruction right) 1542 HBitAnd(HStatic target, HInstruction left, HInstruction right)
1648 : super(target, left, right); 1543 : super(target, left, right);
1649 accept(HVisitor visitor) => visitor.visitBitAnd(this); 1544 accept(HVisitor visitor) => visitor.visitBitAnd(this);
1650 1545
1651 int evaluate(int a, int b) => a & b; 1546 String operationAsString() => "&";
1652 int typeCode() => 14; 1547 int typeCode() => 14;
1653 bool typeEquals(other) => other is HBitAnd; 1548 bool typeEquals(other) => other is HBitAnd;
1654 bool dataEquals(HInstruction other) => true; 1549 bool dataEquals(HInstruction other) => true;
1655 } 1550 }
1656 1551
1657 class HBitXor extends HBinaryBitOp { 1552 class HBitXor extends HBinaryBitOp {
1658 HBitXor(HStatic target, HInstruction left, HInstruction right) 1553 HBitXor(HStatic target, HInstruction left, HInstruction right)
1659 : super(target, left, right); 1554 : super(target, left, right);
1660 accept(HVisitor visitor) => visitor.visitBitXor(this); 1555 accept(HVisitor visitor) => visitor.visitBitXor(this);
1661 1556
1662 int evaluate(int a, int b) => a ^ b; 1557 String operationAsString() => "^";
1663 int typeCode() => 15; 1558 int typeCode() => 15;
1664 bool typeEquals(other) => other is HBitXor; 1559 bool typeEquals(other) => other is HBitXor;
1665 bool dataEquals(HInstruction other) => true; 1560 bool dataEquals(HInstruction other) => true;
1666 } 1561 }
1667 1562
1668 class HInvokeUnary extends HInvokeStatic { 1563 class HInvokeUnary extends HInvokeStatic {
1669 HInvokeUnary(HStatic target, HInstruction input) 1564 HInvokeUnary(HStatic target, HInstruction input)
1670 : super(Selector.UNARY_OPERATOR, <HInstruction>[target, input]); 1565 : super(Selector.UNARY_OPERATOR, <HInstruction>[target, input]);
1671 1566
1672 HInstruction get operand() => inputs[1]; 1567 HInstruction get operand() => inputs[1];
(...skipping 19 matching lines...) Expand all
1692 1587
1693 HType computeDesiredInputType(HInstruction input) { 1588 HType computeDesiredInputType(HInstruction input) {
1694 // TODO(floitsch): we want the target to be a function. 1589 // TODO(floitsch): we want the target to be a function.
1695 if (input == target) return HType.UNKNOWN; 1590 if (input == target) return HType.UNKNOWN;
1696 if (type.isUnknown() || type.isNumber()) return HType.NUMBER; 1591 if (type.isUnknown() || type.isNumber()) return HType.NUMBER;
1697 return HType.UNKNOWN; 1592 return HType.UNKNOWN;
1698 } 1593 }
1699 1594
1700 bool hasExpectedType() => builtin || (type.isUnknown()); 1595 bool hasExpectedType() => builtin || (type.isUnknown());
1701 1596
1702 abstract HInstruction fold(HGraph graph); 1597 HInstruction fold(HGraph graph) {
1598 if (operand is HConstant) {
1599 HConstant op = operand;
1600 Constant folded = op.constant.unaryFold(operationAsString());
1601 if (folded !== null) return graph.addConstant(folded);
1602 }
1603 return this;
1604 }
1703 1605
1704 abstract num evaluate(num a); 1606 abstract String operationAsString();
1705 } 1607 }
1706 1608
1707 class HNegate extends HInvokeUnary { 1609 class HNegate extends HInvokeUnary {
1708 HNegate(HStatic target, HInstruction input) : super(target, input); 1610 HNegate(HStatic target, HInstruction input) : super(target, input);
1709 accept(HVisitor visitor) => visitor.visitNegate(this); 1611 accept(HVisitor visitor) => visitor.visitNegate(this);
1710 1612
1711 HInstruction fold(HGraph graph) { 1613 String operationAsString() => "-";
1712 if (operand.isLiteralNumber()) {
1713 HLiteral input = operand;
1714 return graph.addNewLiteralNum(evaluate(input.value), type);
1715 }
1716 return this;
1717 }
1718
1719 num evaluate(num a) => -a;
1720 int typeCode() => 16; 1614 int typeCode() => 16;
1721 bool typeEquals(other) => other is HNegate; 1615 bool typeEquals(other) => other is HNegate;
1722 bool dataEquals(HInstruction other) => true; 1616 bool dataEquals(HInstruction other) => true;
1723 } 1617 }
1724 1618
1725 class HBitNot extends HInvokeUnary { 1619 class HBitNot extends HInvokeUnary {
1726 HBitNot(HStatic target, HInstruction input) : super(target, input); 1620 HBitNot(HStatic target, HInstruction input) : super(target, input);
1727 accept(HVisitor visitor) => visitor.visitBitNot(this); 1621 accept(HVisitor visitor) => visitor.visitBitNot(this);
1728 1622
1729 HType computeType() { 1623 HType computeType() {
1730 HType type = operand.type; 1624 HType type = operand.type;
1731 builtin = type.isInteger(); 1625 builtin = type.isInteger();
1732 if (!type.isUnknown()) return type; 1626 if (!type.isUnknown()) return type;
1733 return HType.UNKNOWN; 1627 return HType.UNKNOWN;
1734 } 1628 }
1735 1629
1736 HType computeDesiredInputType(HInstruction input) { 1630 HType computeDesiredInputType(HInstruction input) {
1737 // TODO(floitsch): we want the target to be a function. 1631 // TODO(floitsch): we want the target to be a function.
1738 if (input == target) return HType.UNKNOWN; 1632 if (input == target) return HType.UNKNOWN;
1739 return HType.INTEGER; 1633 return HType.INTEGER;
1740 } 1634 }
1741 1635
1742 HInstruction fold(HGraph graph) { 1636 String operationAsString() => "~";
1743 if (operand.isLiteralNumber()) {
1744 HLiteral input = operand;
1745 if (input.isInteger()) {
1746 return graph.addNewLiteralInt(evaluate(input.value));
1747 }
1748 }
1749 return this;
1750 }
1751
1752 int evaluate(int a) => ~a;
1753 int typeCode() => 17; 1637 int typeCode() => 17;
1754 bool typeEquals(other) => other is HBitNot; 1638 bool typeEquals(other) => other is HBitNot;
1755 bool dataEquals(HInstruction other) => true; 1639 bool dataEquals(HInstruction other) => true;
1756 } 1640 }
1757 1641
1758 class HExit extends HControlFlow { 1642 class HExit extends HControlFlow {
1759 HExit() : super(const <HInstruction>[]); 1643 HExit() : super(const <HInstruction>[]);
1760 toString() => 'exit'; 1644 toString() => 'exit';
1761 accept(HVisitor visitor) => visitor.visitExit(this); 1645 accept(HVisitor visitor) => visitor.visitExit(this);
1762 } 1646 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1815 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP]) 1699 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP])
1816 : super(<HInstruction>[condition]); 1700 : super(<HInstruction>[condition]);
1817 toString() => 'loop-branch'; 1701 toString() => 'loop-branch';
1818 accept(HVisitor visitor) => visitor.visitLoopBranch(this); 1702 accept(HVisitor visitor) => visitor.visitLoopBranch(this);
1819 1703
1820 bool isDoWhile() { 1704 bool isDoWhile() {
1821 return kind === DO_WHILE_LOOP; 1705 return kind === DO_WHILE_LOOP;
1822 } 1706 }
1823 } 1707 }
1824 1708
1825 class HLiteral extends HInstruction { 1709 class HConstant extends HInstruction {
1826 final value; 1710 final Constant constant;
1827 HLiteral.internal(this.value, HType type) : super(<HInstruction>[]) { 1711 HConstant.internal(this.constant, HType type) : super(<HInstruction>[]) {
1828 this.type = type; 1712 this.type = type;
1829 tryGenerateAtUseSite(); // Maybe avoid this if the literal is big? 1713 tryGenerateAtUseSite(); // Maybe avoid this if the literal is big?
1830 } 1714 }
1831 1715
1832 void prepareGvn() { 1716 void prepareGvn() {
1833 assert(!hasSideEffects()); 1717 assert(!hasSideEffects());
1834 } 1718 }
1835 1719
1836 toString() => 'literal: $value'; 1720 toString() => 'literal: $constant';
1837 accept(HVisitor visitor) => visitor.visitLiteral(this); 1721 accept(HVisitor visitor) => visitor.visitConstant(this);
1838 HType computeType() => type; 1722 HType computeType() => type;
1839 1723
1840 // Literals have the type they have. It can't be changed. 1724 // Literals have the type they have. It can't be changed.
1841 bool updateType() => false; 1725 bool updateType() => false;
1842 1726
1843 bool hasExpectedType() => true; 1727 bool hasExpectedType() => true;
1844 1728
1845 bool isLiteralBoolean() => value is bool; 1729 bool isConstant() => true;
1846 bool isLiteralNull() => value === null; 1730 bool isConstantBoolean() => constant.isBool();
1847 bool isLiteralNumber() => value is num; 1731 bool isConstantNull() => constant.isNull();
1848 bool isLiteralString() => value is DartString; 1732 bool isConstantNumber() => constant.isNum();
1733 bool isConstantString() => constant.isString();
1849 } 1734 }
1850 1735
1851 class HNot extends HInstruction { 1736 class HNot extends HInstruction {
1852 HNot(HInstruction value) : super(<HInstruction>[value]); 1737 HNot(HInstruction value) : super(<HInstruction>[value]);
1853 void prepareGvn() { 1738 void prepareGvn() {
1854 assert(!hasSideEffects()); 1739 assert(!hasSideEffects());
1855 setUseGvn(); 1740 setUseGvn();
1856 } 1741 }
1857 1742
1858 HType computeType() => HType.BOOLEAN; 1743 HType computeType() => HType.BOOLEAN;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1977 // and do not have any side-effects if we know all the inputs are 1862 // and do not have any side-effects if we know all the inputs are
1978 // numbers. This can be improved for at least equality. 1863 // numbers. This can be improved for at least equality.
1979 if (builtin) { 1864 if (builtin) {
1980 assert(!hasSideEffects()); 1865 assert(!hasSideEffects());
1981 setUseGvn(); 1866 setUseGvn();
1982 } else { 1867 } else {
1983 setAllSideEffects(); 1868 setAllSideEffects();
1984 } 1869 }
1985 } 1870 }
1986 1871
1987 HInstruction fold(HGraph graph) {
1988 if (left.isLiteralNumber() && right.isLiteralNumber()) {
1989 HLiteral op1 = left;
1990 HLiteral op2 = right;
1991 return graph.addNewLiteralBool(evaluate(op1.value, op2.value));
1992 }
1993 return this;
1994 }
1995
1996 HType computeType() { 1872 HType computeType() {
1997 builtin = computeInputsType().isNumber(); 1873 builtin = computeInputsType().isNumber();
1998 return HType.BOOLEAN; 1874 return HType.BOOLEAN;
1999 } 1875 }
2000 1876
2001 HType computeDesiredInputType(HInstruction input) { 1877 HType computeDesiredInputType(HInstruction input) {
2002 // TODO(floitsch): we want the target to be a function. 1878 // TODO(floitsch): we want the target to be a function.
2003 if (input == target) return HType.UNKNOWN; 1879 if (input == target) return HType.UNKNOWN;
2004 // For all relational operations exept HEquals, we expect to only 1880 // For all relational operations exept HEquals, we expect to only
2005 // get numbers. 1881 // get numbers.
2006 return HType.NUMBER; 1882 return HType.NUMBER;
2007 } 1883 }
2008 1884
2009 // A HRelational goes through the builtin operator or the top level 1885 // A HRelational goes through the builtin operator or the top level
2010 // element. Therefore, it always has the expected type. 1886 // element. Therefore, it always has the expected type.
2011 bool hasExpectedType() => true; 1887 bool hasExpectedType() => true;
2012
2013 abstract bool evaluate(num a, num b);
2014 } 1888 }
2015 1889
2016 class HEquals extends HRelational { 1890 class HEquals extends HRelational {
2017 HEquals(HStatic target, HInstruction left, HInstruction right) 1891 HEquals(HStatic target, HInstruction left, HInstruction right)
2018 : super(target, left, right); 1892 : super(target, left, right);
2019 bool evaluate(num a, num b) => a == b;
2020 accept(HVisitor visitor) => visitor.visitEquals(this); 1893 accept(HVisitor visitor) => visitor.visitEquals(this);
2021 int typeCode() => 19;
2022 bool typeEquals(other) => other is HEquals;
2023 bool dataEquals(HInstruction other) => true;
2024 1894
2025 HType computeType() { 1895 HType computeType() {
2026 builtin = computeInputsType().isNumber() || (left is HLiteral); 1896 builtin = computeInputsType().isNumber() || (left is HConstant);
2027 return HType.BOOLEAN; 1897 return HType.BOOLEAN;
2028 } 1898 }
2029 1899
2030 HType computeDesiredInputType(HInstruction input) { 1900 HType computeDesiredInputType(HInstruction input) {
2031 // TODO(floitsch): we want the target to be a function. 1901 // TODO(floitsch): we want the target to be a function.
2032 if (input == target) return HType.UNKNOWN; 1902 if (input == target) return HType.UNKNOWN;
2033 if (left.isNumber() || right.isNumber()) return HType.NUMBER; 1903 if (left.isNumber() || right.isNumber()) return HType.NUMBER;
2034 return HType.UNKNOWN; 1904 return HType.UNKNOWN;
2035 } 1905 }
1906
1907 String operationAsString() => "==";
1908 int typeCode() => 19;
1909 bool typeEquals(other) => other is HEquals;
1910 bool dataEquals(HInstruction other) => true;
2036 } 1911 }
2037 1912
2038 class HIdentity extends HRelational { 1913 class HIdentity extends HRelational {
2039 HIdentity(HStatic target, HInstruction left, HInstruction right) 1914 HIdentity(HStatic target, HInstruction left, HInstruction right)
2040 : super(target, left, right); 1915 : super(target, left, right);
2041 bool evaluate(num a, num b) => a === b;
2042 accept(HVisitor visitor) => visitor.visitIdentity(this); 1916 accept(HVisitor visitor) => visitor.visitIdentity(this);
2043 int typeCode() => 20;
2044 bool typeEquals(other) => other is HIdentity;
2045 bool dataEquals(HInstruction other) => true;
2046 1917
2047 HType computeType() { 1918 HType computeType() {
2048 builtin = true; 1919 builtin = true;
2049 return HType.BOOLEAN; 1920 return HType.BOOLEAN;
2050 } 1921 }
2051 1922
2052 bool hasExpectedType() => true; 1923 bool hasExpectedType() => true;
2053 1924
2054 HType computeDesiredInputType(HInstruction input) => HType.UNKNOWN; 1925 HType computeDesiredInputType(HInstruction input) => HType.UNKNOWN;
1926
1927 String operationAsString() => "===";
1928 int typeCode() => 20;
1929 bool typeEquals(other) => other is HIdentity;
1930 bool dataEquals(HInstruction other) => true;
2055 } 1931 }
2056 1932
2057 class HGreater extends HRelational { 1933 class HGreater extends HRelational {
2058 HGreater(HStatic target, HInstruction left, HInstruction right) 1934 HGreater(HStatic target, HInstruction left, HInstruction right)
2059 : super(target, left, right); 1935 : super(target, left, right);
2060 bool evaluate(num a, num b) => a > b;
2061 accept(HVisitor visitor) => visitor.visitGreater(this); 1936 accept(HVisitor visitor) => visitor.visitGreater(this);
1937
1938 String operationAsString() => ">";
2062 int typeCode() => 21; 1939 int typeCode() => 21;
2063 bool typeEquals(other) => other is HGreater; 1940 bool typeEquals(other) => other is HGreater;
2064 bool dataEquals(HInstruction other) => true; 1941 bool dataEquals(HInstruction other) => true;
2065 } 1942 }
2066 1943
2067 class HGreaterEqual extends HRelational { 1944 class HGreaterEqual extends HRelational {
2068 HGreaterEqual(HStatic target, HInstruction left, HInstruction right) 1945 HGreaterEqual(HStatic target, HInstruction left, HInstruction right)
2069 : super(target, left, right); 1946 : super(target, left, right);
2070 bool evaluate(num a, num b) => a >= b;
2071 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); 1947 accept(HVisitor visitor) => visitor.visitGreaterEqual(this);
1948
1949 String operationAsString() => ">=";
2072 int typeCode() => 22; 1950 int typeCode() => 22;
2073 bool typeEquals(other) => other is HGreaterEqual; 1951 bool typeEquals(other) => other is HGreaterEqual;
2074 bool dataEquals(HInstruction other) => true; 1952 bool dataEquals(HInstruction other) => true;
2075 } 1953 }
2076 1954
2077 class HLess extends HRelational { 1955 class HLess extends HRelational {
2078 HLess(HStatic target, HInstruction left, HInstruction right) 1956 HLess(HStatic target, HInstruction left, HInstruction right)
2079 : super(target, left, right); 1957 : super(target, left, right);
2080 bool evaluate(num a, num b) => a < b;
2081 accept(HVisitor visitor) => visitor.visitLess(this); 1958 accept(HVisitor visitor) => visitor.visitLess(this);
1959
1960 String operationAsString() => "<";
1961 int typeCode() => 23;
2082 bool typeEquals(other) => other is HLess; 1962 bool typeEquals(other) => other is HLess;
2083 bool dataEquals(HInstruction other) => true; 1963 bool dataEquals(HInstruction other) => true;
2084 } 1964 }
2085 1965
2086 class HLessEqual extends HRelational { 1966 class HLessEqual extends HRelational {
2087 HLessEqual(HStatic target, HInstruction left, HInstruction right) 1967 HLessEqual(HStatic target, HInstruction left, HInstruction right)
2088 : super(target, left, right); 1968 : super(target, left, right);
2089 bool evaluate(num a, num b) => a <= b;
2090 accept(HVisitor visitor) => visitor.visitLessEqual(this); 1969 accept(HVisitor visitor) => visitor.visitLessEqual(this);
2091 int typeCode() => 23; 1970
1971 String operationAsString() => "<=";
1972 int typeCode() => 24;
2092 bool typeEquals(other) => other is HLessEqual; 1973 bool typeEquals(other) => other is HLessEqual;
2093 bool dataEquals(HInstruction other) => true; 1974 bool dataEquals(HInstruction other) => true;
2094 } 1975 }
2095 1976
2096 class HReturn extends HControlFlow { 1977 class HReturn extends HControlFlow {
2097 HReturn(value) : super(<HInstruction>[value]); 1978 HReturn(value) : super(<HInstruction>[value]);
2098 toString() => 'return'; 1979 toString() => 'return';
2099 accept(HVisitor visitor) => visitor.visitReturn(this); 1980 accept(HVisitor visitor) => visitor.visitReturn(this);
2100 } 1981 }
2101 1982
(...skipping 12 matching lines...) Expand all
2114 void prepareGvn() { 1995 void prepareGvn() {
2115 assert(!hasSideEffects()); 1996 assert(!hasSideEffects());
2116 if (!element.isAssignable()) { 1997 if (!element.isAssignable()) {
2117 setUseGvn(); 1998 setUseGvn();
2118 } 1999 }
2119 } 2000 }
2120 toString() => 'static ${element.name}'; 2001 toString() => 'static ${element.name}';
2121 accept(HVisitor visitor) => visitor.visitStatic(this); 2002 accept(HVisitor visitor) => visitor.visitStatic(this);
2122 2003
2123 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode(); 2004 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode();
2124 int typeCode() => 24; 2005 int typeCode() => 25;
2125 bool typeEquals(other) => other is HStatic; 2006 bool typeEquals(other) => other is HStatic;
2126 bool dataEquals(HStatic other) => element == other.element; 2007 bool dataEquals(HStatic other) => element == other.element;
2127 } 2008 }
2128 2009
2129 class HStaticStore extends HInstruction { 2010 class HStaticStore extends HInstruction {
2130 Element element; 2011 Element element;
2131 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]); 2012 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]);
2132 toString() => 'static store ${element.name}'; 2013 toString() => 'static store ${element.name}';
2133 accept(HVisitor visitor) => visitor.visitStaticStore(this); 2014 accept(HVisitor visitor) => visitor.visitStaticStore(this);
2134 2015
2135 int typeCode() => 25; 2016 int typeCode() => 26;
2136 bool typeEquals(other) => other is HStaticStore; 2017 bool typeEquals(other) => other is HStaticStore;
2137 bool dataEquals(HStaticStore other) => element == other.element; 2018 bool dataEquals(HStaticStore other) => element == other.element;
2138 } 2019 }
2139 2020
2140 class HLiteralList extends HInstruction { 2021 class HLiteralList extends HInstruction {
2141 HLiteralList(inputs, this.isConst) : super(inputs); 2022 HLiteralList(inputs, this.isConst) : super(inputs);
2142 toString() => 'literal list'; 2023 toString() => 'literal list';
2143 accept(HVisitor visitor) => visitor.visitLiteralList(this); 2024 accept(HVisitor visitor) => visitor.visitLiteralList(this);
2144 HType computeType() => HType.ARRAY; 2025 HType computeType() => HType.ARRAY;
2145 bool hasExpectedType() => true; 2026 bool hasExpectedType() => true;
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2283 class HIfBlockInformation { 2164 class HIfBlockInformation {
2284 final HIf branch; 2165 final HIf branch;
2285 final SubGraph thenGraph; 2166 final SubGraph thenGraph;
2286 final SubGraph elseGraph; 2167 final SubGraph elseGraph;
2287 final HBasicBlock joinBlock; 2168 final HBasicBlock joinBlock;
2288 HIfBlockInformation(this.branch, 2169 HIfBlockInformation(this.branch,
2289 this.thenGraph, 2170 this.thenGraph,
2290 this.elseGraph, 2171 this.elseGraph,
2291 this.joinBlock); 2172 this.joinBlock);
2292 } 2173 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698