| 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 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1314 } | 1314 } |
| 1315 } | 1315 } |
| 1316 | 1316 |
| 1317 class HInvokeClosure extends HInvokeDynamic { | 1317 class HInvokeClosure extends HInvokeDynamic { |
| 1318 HInvokeClosure(Selector selector, List<HInstruction> inputs) | 1318 HInvokeClosure(Selector selector, List<HInstruction> inputs) |
| 1319 : super(selector, null, inputs); | 1319 : super(selector, null, inputs); |
| 1320 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); | 1320 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); |
| 1321 } | 1321 } |
| 1322 | 1322 |
| 1323 class HInvokeDynamicMethod extends HInvokeDynamic { | 1323 class HInvokeDynamicMethod extends HInvokeDynamic { |
| 1324 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) | 1324 final InvokeDynamicSpecializer specializer; |
| 1325 : super(selector, null, inputs); | 1325 HInvokeDynamicMethod(Selector selector, |
| 1326 List<HInstruction> inputs, |
| 1327 [bool isIntercepted = false]) |
| 1328 : super(selector, null, inputs), |
| 1329 specializer = isIntercepted |
| 1330 ? InvokeDynamicSpecializer.lookupSpecializer(selector) |
| 1331 : const InvokeDynamicSpecializer(); |
| 1326 String toString() => 'invoke dynamic method: $selector'; | 1332 String toString() => 'invoke dynamic method: $selector'; |
| 1327 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 1333 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); |
| 1328 | 1334 |
| 1329 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) { | 1335 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) { |
| 1330 return isInterceptorCall | 1336 return isInterceptorCall |
| 1331 && selector.kind == SelectorKind.INDEX | 1337 && selector.kind == SelectorKind.INDEX |
| 1332 && selector.name == const SourceString('[]') | 1338 && selector.name == const SourceString('[]') |
| 1333 && inputs[1].isIndexablePrimitive(types); | 1339 && inputs[1].isIndexablePrimitive(types); |
| 1334 } | 1340 } |
| 1335 | 1341 |
| 1336 HType computeDesiredTypeForInput(HInstruction input, | 1342 HType computeDesiredTypeForInput(HInstruction input, |
| 1337 HTypeMap types, | 1343 HTypeMap types, |
| 1338 Compiler compiler) { | 1344 Compiler compiler) { |
| 1339 // TODO(ngeoffray): Move this logic into a different class that | 1345 return specializer.computeDesiredTypeForInput(this, input, types, compiler); |
| 1340 // will know what type it wants for a given selector. | |
| 1341 if (!isInterceptorCall) return HType.UNKNOWN; | |
| 1342 | |
| 1343 if (selector.kind == SelectorKind.INDEX) { | |
| 1344 HInstruction index = inputs[2]; | |
| 1345 if (input == inputs[1] && | |
| 1346 (index.isTypeUnknown(types) || index.isNumber(types))) { | |
| 1347 return selector.name == const SourceString('[]') | |
| 1348 ? HType.INDEXABLE_PRIMITIVE | |
| 1349 : HType.MUTABLE_ARRAY; | |
| 1350 } | |
| 1351 // The index should be an int when the receiver is a string or array. | |
| 1352 // However it turns out that inserting an integer check in the optimized | |
| 1353 // version is cheaper than having another bailout case. This is true, | |
| 1354 // because the integer check will simply throw if it fails. | |
| 1355 return HType.UNKNOWN; | |
| 1356 } else if (selector.kind == SelectorKind.OPERATOR) { | |
| 1357 HType propagatedType = types[this]; | |
| 1358 if (selector.name == const SourceString('unary-') && input == inputs[1]) { | |
| 1359 // If the outgoing type should be a number (integer, double or both) we | |
| 1360 // want the outgoing type to be the input too. | |
| 1361 // If we don't know the outgoing type we try to make it a number. | |
| 1362 if (propagatedType.isNumber()) return propagatedType; | |
| 1363 if (propagatedType.isUnknown()) return HType.NUMBER; | |
| 1364 } else if (selector.name == const SourceString('~') | |
| 1365 && input == inputs[1]) { | |
| 1366 if (propagatedType.isUnknown() || propagatedType.isNumber()) { | |
| 1367 return HType.INTEGER; | |
| 1368 } | |
| 1369 } | |
| 1370 return HType.UNKNOWN; | |
| 1371 } | |
| 1372 return HType.UNKNOWN; | |
| 1373 } | 1346 } |
| 1374 | 1347 |
| 1375 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { | 1348 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 1376 // TODO(ngeoffray): Move this logic into a different class that | 1349 return specializer.computeTypeFromInputTypes(this, types, compiler); |
| 1377 // will know what type it has for a given selector. | |
| 1378 if (!isInterceptorCall) return HType.UNKNOWN; | |
| 1379 | |
| 1380 if (selector.kind == SelectorKind.OPERATOR) { | |
| 1381 if (selector.name == const SourceString('unary-')) { | |
| 1382 HType operandType = types[inputs[1]]; | |
| 1383 if (operandType.isNumber()) return operandType; | |
| 1384 } else if (selector.name == const SourceString('~')) { | |
| 1385 // All bitwise operations on primitive types either produce an | |
| 1386 // integer or throw an error. | |
| 1387 if (inputs[1].isPrimitive(types)) return HType.INTEGER; | |
| 1388 } | |
| 1389 } | |
| 1390 return HType.UNKNOWN; | |
| 1391 } | 1350 } |
| 1392 } | 1351 } |
| 1393 | 1352 |
| 1394 abstract class HInvokeDynamicField extends HInvokeDynamic { | 1353 abstract class HInvokeDynamicField extends HInvokeDynamic { |
| 1395 final bool isSideEffectFree; | 1354 final bool isSideEffectFree; |
| 1396 HInvokeDynamicField( | 1355 HInvokeDynamicField( |
| 1397 Selector selector, Element element, List<HInstruction> inputs, | 1356 Selector selector, Element element, List<HInstruction> inputs, |
| 1398 this.isSideEffectFree) | 1357 this.isSideEffectFree) |
| 1399 : super(selector, element, inputs); | 1358 : super(selector, element, inputs); |
| 1400 toString() => 'invoke dynamic field: $selector'; | 1359 toString() => 'invoke dynamic field: $selector'; |
| (...skipping 1532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2933 HBasicBlock get start => expression.start; | 2892 HBasicBlock get start => expression.start; |
| 2934 HBasicBlock get end { | 2893 HBasicBlock get end { |
| 2935 // We don't create a switch block if there are no cases. | 2894 // We don't create a switch block if there are no cases. |
| 2936 assert(!statements.isEmpty); | 2895 assert(!statements.isEmpty); |
| 2937 return statements.last.end; | 2896 return statements.last.end; |
| 2938 } | 2897 } |
| 2939 | 2898 |
| 2940 bool accept(HStatementInformationVisitor visitor) => | 2899 bool accept(HStatementInformationVisitor visitor) => |
| 2941 visitor.visitSwitchInfo(this); | 2900 visitor.visitSwitchInfo(this); |
| 2942 } | 2901 } |
| OLD | NEW |