OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of ssa; | 5 part of ssa; |
6 | 6 |
7 abstract class HVisitor<R> { | 7 abstract class HVisitor<R> { |
8 R visitAdd(HAdd node); | 8 R visitAdd(HAdd node); |
9 R visitBailoutTarget(HBailoutTarget node); | 9 R visitBailoutTarget(HBailoutTarget node); |
10 R visitBitAnd(HBitAnd node); | 10 R visitBitAnd(HBitAnd node); |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 assert(isNew()); | 496 assert(isNew()); |
497 status = STATUS_OPEN; | 497 status = STATUS_OPEN; |
498 } | 498 } |
499 | 499 |
500 void close(HControlFlow end) { | 500 void close(HControlFlow end) { |
501 assert(isOpen()); | 501 assert(isOpen()); |
502 addAfter(last, end); | 502 addAfter(last, end); |
503 status = STATUS_CLOSED; | 503 status = STATUS_CLOSED; |
504 } | 504 } |
505 | 505 |
506 // TODO(kasperl): I really don't want to pass the compiler into this | |
507 // method. Maybe we need a better logging framework. | |
508 void printToCompiler(Compiler compiler) { | |
509 HInstruction instruction = first; | |
510 while (instruction != null) { | |
511 int instructionId = instruction.id; | |
512 String inputsAsString = instruction.inputsToString(); | |
513 compiler.log('$instructionId: $instruction $inputsAsString'); | |
514 instruction = instruction.next; | |
515 } | |
516 } | |
517 | |
518 void addAtEntry(HInstruction instruction) { | 506 void addAtEntry(HInstruction instruction) { |
519 assert(instruction is !HPhi); | 507 assert(instruction is !HPhi); |
520 super.addBefore(first, instruction); | 508 super.addBefore(first, instruction); |
521 instruction.notifyAddedToBlock(this); | 509 instruction.notifyAddedToBlock(this); |
522 } | 510 } |
523 | 511 |
524 void addAtExit(HInstruction instruction) { | 512 void addAtExit(HInstruction instruction) { |
525 assert(isClosed()); | 513 assert(isClosed()); |
526 assert(last is HControlFlow); | 514 assert(last is HControlFlow); |
527 assert(instruction is !HPhi); | 515 assert(instruction is !HPhi); |
(...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1278 int typeCode() => HInstruction.INTEGER_CHECK_TYPECODE; | 1266 int typeCode() => HInstruction.INTEGER_CHECK_TYPECODE; |
1279 bool typeEquals(other) => other is HIntegerCheck; | 1267 bool typeEquals(other) => other is HIntegerCheck; |
1280 bool dataEquals(HInstruction other) => true; | 1268 bool dataEquals(HInstruction other) => true; |
1281 } | 1269 } |
1282 | 1270 |
1283 abstract class HConditionalBranch extends HControlFlow { | 1271 abstract class HConditionalBranch extends HControlFlow { |
1284 HConditionalBranch(inputs) : super(inputs); | 1272 HConditionalBranch(inputs) : super(inputs); |
1285 HInstruction get condition => inputs[0]; | 1273 HInstruction get condition => inputs[0]; |
1286 HBasicBlock get trueBranch => block.successors[0]; | 1274 HBasicBlock get trueBranch => block.successors[0]; |
1287 HBasicBlock get falseBranch => block.successors[1]; | 1275 HBasicBlock get falseBranch => block.successors[1]; |
1288 toString(); | |
1289 } | 1276 } |
1290 | 1277 |
1291 abstract class HControlFlow extends HInstruction { | 1278 abstract class HControlFlow extends HInstruction { |
1292 HControlFlow(inputs) : super(inputs); | 1279 HControlFlow(inputs) : super(inputs); |
1293 toString(); | |
1294 void prepareGvn(HTypeMap types) { | 1280 void prepareGvn(HTypeMap types) { |
1295 // Control flow does not have side-effects. | 1281 // Control flow does not have side-effects. |
1296 } | 1282 } |
1297 bool isControlFlow() => true; | 1283 bool isControlFlow() => true; |
1298 bool isJsStatement(HTypeMap types) => true; | 1284 bool isJsStatement(HTypeMap types) => true; |
1299 } | 1285 } |
1300 | 1286 |
1301 abstract class HInvoke extends HInstruction { | 1287 abstract class HInvoke extends HInstruction { |
1302 /** | 1288 /** |
1303 * The first argument must be the target: either an [HStatic] node, or | 1289 * The first argument must be the target: either an [HStatic] node, or |
1304 * the receiver of a method-call. The remaining inputs are the arguments | 1290 * the receiver of a method-call. The remaining inputs are the arguments |
1305 * to the invocation. | 1291 * to the invocation. |
1306 */ | 1292 */ |
1307 HInvoke(List<HInstruction> inputs) : super(inputs); | 1293 HInvoke(List<HInstruction> inputs) : super(inputs); |
1308 static const int ARGUMENTS_OFFSET = 1; | 1294 static const int ARGUMENTS_OFFSET = 1; |
1309 | |
1310 // TODO(floitsch): make class abstract instead of adding an abstract method. | |
1311 accept(HVisitor visitor); | |
1312 } | 1295 } |
1313 | 1296 |
1314 abstract class HInvokeDynamic extends HInvoke { | 1297 abstract class HInvokeDynamic extends HInvoke { |
1315 final Selector selector; | 1298 final Selector selector; |
1316 Element element; | 1299 Element element; |
1317 | 1300 |
1318 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) | 1301 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) |
1319 : super(inputs); | 1302 : super(inputs); |
1320 toString() => 'invoke dynamic: $selector'; | 1303 toString() => 'invoke dynamic: $selector'; |
1321 HInstruction get receiver => inputs[0]; | 1304 HInstruction get receiver => inputs[0]; |
1322 | 1305 |
1323 accept(HVisitor visitor); | |
1324 | |
1325 bool get isInterceptorCall { | 1306 bool get isInterceptorCall { |
1326 // We know it's a selector call if it follows the interceptor | 1307 // We know it's a selector call if it follows the interceptor |
1327 // calling convention, which adds the actual receiver as a | 1308 // calling convention, which adds the actual receiver as a |
1328 // parameter to the call. | 1309 // parameter to the call. |
1329 return inputs.length - 2 == selector.argumentCount; | 1310 return inputs.length - 2 == selector.argumentCount; |
1330 } | 1311 } |
1331 } | 1312 } |
1332 | 1313 |
1333 class HInvokeClosure extends HInvokeDynamic { | 1314 class HInvokeClosure extends HInvokeDynamic { |
1334 HInvokeClosure(Selector selector, List<HInstruction> inputs) | 1315 HInvokeClosure(Selector selector, List<HInstruction> inputs) |
1335 : super(selector, null, inputs); | 1316 : super(selector, null, inputs); |
1336 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); | 1317 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); |
1337 } | 1318 } |
1338 | 1319 |
1339 class HInvokeDynamicMethod extends HInvokeDynamic { | 1320 class HInvokeDynamicMethod extends HInvokeDynamic { |
1340 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) | 1321 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) |
1341 : super(selector, null, inputs); | 1322 : super(selector, null, inputs); |
1342 toString() => 'invoke dynamic method: $selector'; | 1323 toString() => 'invoke dynamic method: $selector'; |
1343 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 1324 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); |
1344 } | 1325 } |
1345 | 1326 |
1346 abstract class HInvokeDynamicField extends HInvokeDynamic { | 1327 abstract class HInvokeDynamicField extends HInvokeDynamic { |
1347 final bool isSideEffectFree; | 1328 final bool isSideEffectFree; |
1348 HInvokeDynamicField( | 1329 HInvokeDynamicField( |
1349 Selector selector, Element element, List<HInstruction> inputs, | 1330 Selector selector, Element element, List<HInstruction> inputs, |
1350 this.isSideEffectFree) | 1331 this.isSideEffectFree) |
1351 : super(selector, element, inputs); | 1332 : super(selector, element, inputs); |
1352 toString() => 'invoke dynamic field: $selector'; | 1333 toString() => 'invoke dynamic field: $selector'; |
1353 | |
1354 accept(HVisitor visitor); | |
1355 } | 1334 } |
1356 | 1335 |
1357 class HInvokeDynamicGetter extends HInvokeDynamicField { | 1336 class HInvokeDynamicGetter extends HInvokeDynamicField { |
1358 HInvokeDynamicGetter( | 1337 HInvokeDynamicGetter( |
1359 selector, element, receiver, isSideEffectFree) | 1338 selector, element, receiver, isSideEffectFree) |
1360 : super(selector, element, [receiver], isSideEffectFree); | 1339 : super(selector, element, [receiver], isSideEffectFree); |
1361 toString() => 'invoke dynamic getter: $selector'; | 1340 toString() => 'invoke dynamic getter: $selector'; |
1362 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); | 1341 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); |
1363 | 1342 |
1364 void prepareGvn(HTypeMap types) { | 1343 void prepareGvn(HTypeMap types) { |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1749 if (propagatedType.isUnknown() || propagatedType.isNumber()) { | 1728 if (propagatedType.isUnknown() || propagatedType.isNumber()) { |
1750 return HType.INTEGER; | 1729 return HType.INTEGER; |
1751 } | 1730 } |
1752 return HType.UNKNOWN; | 1731 return HType.UNKNOWN; |
1753 } | 1732 } |
1754 | 1733 |
1755 HType computeLikelyType(HTypeMap types, Compiler compiler) { | 1734 HType computeLikelyType(HTypeMap types, Compiler compiler) { |
1756 if (left.isTypeUnknown(types)) return HType.INTEGER; | 1735 if (left.isTypeUnknown(types)) return HType.INTEGER; |
1757 return HType.UNKNOWN; | 1736 return HType.UNKNOWN; |
1758 } | 1737 } |
1759 | |
1760 // TODO(floitsch): make class abstract instead of adding an abstract method. | |
1761 accept(HVisitor visitor); | |
1762 } | 1738 } |
1763 | 1739 |
1764 class HShiftLeft extends HBinaryBitOp { | 1740 class HShiftLeft extends HBinaryBitOp { |
1765 HShiftLeft(HStatic target, HInstruction left, HInstruction right) | 1741 HShiftLeft(HStatic target, HInstruction left, HInstruction right) |
1766 : super(target, left, right); | 1742 : super(target, left, right); |
1767 accept(HVisitor visitor) => visitor.visitShiftLeft(this); | 1743 accept(HVisitor visitor) => visitor.visitShiftLeft(this); |
1768 | 1744 |
1769 // Shift left cannot be mapped to the native operator unless the | 1745 // Shift left cannot be mapped to the native operator unless the |
1770 // shift count is guaranteed to be an integer in the [0,31] range. | 1746 // shift count is guaranteed to be an integer in the [0,31] range. |
1771 bool isBuiltin(HTypeMap types) { | 1747 bool isBuiltin(HTypeMap types) { |
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2223 return HType.NUMBER; | 2199 return HType.NUMBER; |
2224 } | 2200 } |
2225 } | 2201 } |
2226 return HType.UNKNOWN; | 2202 return HType.UNKNOWN; |
2227 } | 2203 } |
2228 | 2204 |
2229 HType computeLikelyType(HTypeMap types, Compiler compiler) => HType.BOOLEAN; | 2205 HType computeLikelyType(HTypeMap types, Compiler compiler) => HType.BOOLEAN; |
2230 | 2206 |
2231 bool isBuiltin(HTypeMap types) | 2207 bool isBuiltin(HTypeMap types) |
2232 => left.isNumber(types) && right.isNumber(types); | 2208 => left.isNumber(types) && right.isNumber(types); |
2233 // TODO(1603): the class should be marked as abstract. | |
2234 BinaryOperation operation(ConstantSystem constantSystem); | |
2235 } | 2209 } |
2236 | 2210 |
2237 class HEquals extends HRelational { | 2211 class HEquals extends HRelational { |
2238 HEquals(HStatic target, HInstruction left, HInstruction right) | 2212 HEquals(HStatic target, HInstruction left, HInstruction right) |
2239 : super(target, left, right); | 2213 : super(target, left, right); |
2240 accept(HVisitor visitor) => visitor.visitEquals(this); | 2214 accept(HVisitor visitor) => visitor.visitEquals(this); |
2241 | 2215 |
2242 bool isBuiltin(HTypeMap types) { | 2216 bool isBuiltin(HTypeMap types) { |
2243 // All primitive types have 'identical' semantics. | 2217 // All primitive types have 'identical' semantics. |
2244 // Note that this includes all constants except the user-constructed | 2218 // Note that this includes all constants except the user-constructed |
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2958 HBasicBlock get start => expression.start; | 2932 HBasicBlock get start => expression.start; |
2959 HBasicBlock get end { | 2933 HBasicBlock get end { |
2960 // We don't create a switch block if there are no cases. | 2934 // We don't create a switch block if there are no cases. |
2961 assert(!statements.isEmpty); | 2935 assert(!statements.isEmpty); |
2962 return statements.last.end; | 2936 return statements.last.end; |
2963 } | 2937 } |
2964 | 2938 |
2965 bool accept(HStatementInformationVisitor visitor) => | 2939 bool accept(HStatementInformationVisitor visitor) => |
2966 visitor.visitSwitchInfo(this); | 2940 visitor.visitSwitchInfo(this); |
2967 } | 2941 } |
OLD | NEW |