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 18 matching lines...) Expand all Loading... | |
29 R visitGreaterEqual(HGreaterEqual node); | 29 R visitGreaterEqual(HGreaterEqual node); |
30 R visitIdentity(HIdentity node); | 30 R visitIdentity(HIdentity node); |
31 R visitIf(HIf node); | 31 R visitIf(HIf node); |
32 R visitIndex(HIndex node); | 32 R visitIndex(HIndex node); |
33 R visitIndexAssign(HIndexAssign node); | 33 R visitIndexAssign(HIndexAssign node); |
34 R visitIntegerCheck(HIntegerCheck node); | 34 R visitIntegerCheck(HIntegerCheck node); |
35 R visitInvokeClosure(HInvokeClosure node); | 35 R visitInvokeClosure(HInvokeClosure node); |
36 R visitInvokeDynamicGetter(HInvokeDynamicGetter node); | 36 R visitInvokeDynamicGetter(HInvokeDynamicGetter node); |
37 R visitInvokeDynamicMethod(HInvokeDynamicMethod node); | 37 R visitInvokeDynamicMethod(HInvokeDynamicMethod node); |
38 R visitInvokeDynamicSetter(HInvokeDynamicSetter node); | 38 R visitInvokeDynamicSetter(HInvokeDynamicSetter node); |
39 R visitInvokeInterceptor(HInvokeInterceptor node); | |
40 R visitInvokeStatic(HInvokeStatic node); | 39 R visitInvokeStatic(HInvokeStatic node); |
41 R visitInvokeSuper(HInvokeSuper node); | 40 R visitInvokeSuper(HInvokeSuper node); |
42 R visitIs(HIs node); | 41 R visitIs(HIs node); |
43 R visitLazyStatic(HLazyStatic node); | 42 R visitLazyStatic(HLazyStatic node); |
44 R visitLess(HLess node); | 43 R visitLess(HLess node); |
45 R visitLessEqual(HLessEqual node); | 44 R visitLessEqual(HLessEqual node); |
46 R visitLiteralList(HLiteralList node); | 45 R visitLiteralList(HLiteralList node); |
47 R visitLocalGet(HLocalGet node); | 46 R visitLocalGet(HLocalGet node); |
48 R visitLocalSet(HLocalSet node); | 47 R visitLocalSet(HLocalSet node); |
49 R visitLocalValue(HLocalValue node); | 48 R visitLocalValue(HLocalValue node); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
293 visitIndexAssign(HIndexAssign node) => visitInvokeStatic(node); | 292 visitIndexAssign(HIndexAssign node) => visitInvokeStatic(node); |
294 visitIntegerCheck(HIntegerCheck node) => visitCheck(node); | 293 visitIntegerCheck(HIntegerCheck node) => visitCheck(node); |
295 visitInvokeClosure(HInvokeClosure node) | 294 visitInvokeClosure(HInvokeClosure node) |
296 => visitInvokeDynamic(node); | 295 => visitInvokeDynamic(node); |
297 visitInvokeDynamicMethod(HInvokeDynamicMethod node) | 296 visitInvokeDynamicMethod(HInvokeDynamicMethod node) |
298 => visitInvokeDynamic(node); | 297 => visitInvokeDynamic(node); |
299 visitInvokeDynamicGetter(HInvokeDynamicGetter node) | 298 visitInvokeDynamicGetter(HInvokeDynamicGetter node) |
300 => visitInvokeDynamicField(node); | 299 => visitInvokeDynamicField(node); |
301 visitInvokeDynamicSetter(HInvokeDynamicSetter node) | 300 visitInvokeDynamicSetter(HInvokeDynamicSetter node) |
302 => visitInvokeDynamicField(node); | 301 => visitInvokeDynamicField(node); |
303 visitInvokeInterceptor(HInvokeInterceptor node) | |
304 => visitInvokeStatic(node); | |
305 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); | 302 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); |
306 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node); | 303 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node); |
307 visitJump(HJump node) => visitControlFlow(node); | 304 visitJump(HJump node) => visitControlFlow(node); |
308 visitLazyStatic(HLazyStatic node) => visitStatic(node); | 305 visitLazyStatic(HLazyStatic node) => visitStatic(node); |
309 visitLess(HLess node) => visitRelational(node); | 306 visitLess(HLess node) => visitRelational(node); |
310 visitLessEqual(HLessEqual node) => visitRelational(node); | 307 visitLessEqual(HLessEqual node) => visitRelational(node); |
311 visitLiteralList(HLiteralList node) => visitInstruction(node); | 308 visitLiteralList(HLiteralList node) => visitInstruction(node); |
312 visitLocalGet(HLocalGet node) => visitFieldGet(node); | 309 visitLocalGet(HLocalGet node) => visitFieldGet(node); |
313 visitLocalSet(HLocalSet node) => visitFieldSet(node); | 310 visitLocalSet(HLocalSet node) => visitFieldSet(node); |
314 visitLocalValue(HLocalValue node) => visitInstruction(node); | 311 visitLocalValue(HLocalValue node) => visitInstruction(node); |
(...skipping 999 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1314 | 1311 |
1315 abstract class HInvokeDynamic extends HInvoke { | 1312 abstract class HInvokeDynamic extends HInvoke { |
1316 final Selector selector; | 1313 final Selector selector; |
1317 Element element; | 1314 Element element; |
1318 | 1315 |
1319 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) | 1316 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) |
1320 : super(inputs); | 1317 : super(inputs); |
1321 toString() => 'invoke dynamic: $selector'; | 1318 toString() => 'invoke dynamic: $selector'; |
1322 HInstruction get receiver => inputs[0]; | 1319 HInstruction get receiver => inputs[0]; |
1323 | 1320 |
1324 // TODO(floitsch): make class abstract instead of adding an abstract method. | |
1325 accept(HVisitor visitor); | 1321 accept(HVisitor visitor); |
1322 | |
1323 bool get isInterceptorCall { | |
1324 // We know it's a selector call if it follows the interceptor | |
karlklose
2012/11/20 16:40:35
How about
// We know it is an interceptor call, i
karlklose
2012/11/21 08:34:55
I meant inputs - 2
ngeoffray
2012/11/21 09:43:42
Done.
| |
1325 // calling convention, which adds the actual receiver as a | |
1326 // parameter to the call. | |
1327 return inputs.length - 1 != selector.argumentCount; | |
karlklose
2012/11/20 16:40:35
Trailing whitespace.
ngeoffray
2012/11/21 09:43:42
Done.
| |
1328 } | |
1326 } | 1329 } |
1327 | 1330 |
1328 class HInvokeClosure extends HInvokeDynamic { | 1331 class HInvokeClosure extends HInvokeDynamic { |
1329 HInvokeClosure(Selector selector, List<HInstruction> inputs) | 1332 HInvokeClosure(Selector selector, List<HInstruction> inputs) |
1330 : super(selector, null, inputs); | 1333 : super(selector, null, inputs); |
1331 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); | 1334 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); |
1332 } | 1335 } |
1333 | 1336 |
1334 class HInvokeDynamicMethod extends HInvokeDynamic { | 1337 class HInvokeDynamicMethod extends HInvokeDynamic { |
1335 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) | 1338 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1421 toString() => 'invoke super: ${element.name}'; | 1424 toString() => 'invoke super: ${element.name}'; |
1422 accept(HVisitor visitor) => visitor.visitInvokeSuper(this); | 1425 accept(HVisitor visitor) => visitor.visitInvokeSuper(this); |
1423 | 1426 |
1424 HInstruction get value { | 1427 HInstruction get value { |
1425 assert(isSetter); | 1428 assert(isSetter); |
1426 // Index 0: the element, index 1: 'this'. | 1429 // Index 0: the element, index 1: 'this'. |
1427 return inputs[2]; | 1430 return inputs[2]; |
1428 } | 1431 } |
1429 } | 1432 } |
1430 | 1433 |
1431 class HInvokeInterceptor extends HInvokeStatic { | |
1432 final Selector selector; | |
1433 final bool isSideEffectFree; | |
1434 | |
1435 HInvokeInterceptor(this.selector, | |
1436 List<HInstruction> inputs, | |
1437 [bool this.isSideEffectFree = false]) | |
1438 : super(inputs); | |
1439 | |
1440 toString() => 'invoke interceptor: ${element.name}'; | |
1441 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this); | |
1442 | |
1443 bool isLengthGetter() { | |
1444 return selector.isGetter() && | |
1445 selector.name == const SourceString('length'); | |
1446 } | |
1447 | |
1448 bool isPopCall(HTypeMap types) { | |
1449 return selector.isCall() | |
1450 && inputs[1].isExtendableArray(types) | |
1451 && selector.name == const SourceString('removeLast') | |
1452 && selector.argumentCount == 0; | |
1453 } | |
1454 | |
1455 bool isLengthGetterOnStringOrArray(HTypeMap types) { | |
1456 return isLengthGetter() && inputs[1].isIndexablePrimitive(types); | |
1457 } | |
1458 | |
1459 HType computeLikelyType(HTypeMap types, Compiler compiler) { | |
1460 // In general a length getter or method returns an int. | |
1461 if (isLengthGetter()) return HType.INTEGER; | |
1462 return HType.UNKNOWN; | |
1463 } | |
1464 | |
1465 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { | |
1466 if (isLengthGetterOnStringOrArray(types)) return HType.INTEGER; | |
1467 return HType.UNKNOWN; | |
1468 } | |
1469 | |
1470 HType computeDesiredTypeForNonTargetInput(HInstruction input, | |
1471 HTypeMap types, | |
1472 Compiler compiler) { | |
1473 // If the first argument is a string or an array and we invoke methods | |
1474 // on it that mutate it, then we want to restrict the incoming type to be | |
1475 // a mutable array. | |
1476 if (input == inputs[1] && input.isIndexablePrimitive(types)) { | |
1477 // TODO(kasperl): Should we check that the selector is a call selector? | |
1478 if (selector.name == const SourceString('add') | |
1479 || selector.name == const SourceString('removeLast')) { | |
1480 return HType.MUTABLE_ARRAY; | |
1481 } | |
1482 } | |
1483 return HType.UNKNOWN; | |
1484 } | |
1485 | |
1486 void prepareGvn(HTypeMap types) { | |
1487 clearAllSideEffects(); | |
1488 if (isLengthGetterOnStringOrArray(types)) { | |
1489 setUseGvn(); | |
1490 // If the input is a string or a fixed length array, we know | |
1491 // the length cannot change. | |
1492 if (!inputs[1].isString(types) && !inputs[1].isFixedArray(types)) { | |
1493 setDependsOnInstancePropertyStore(); | |
1494 } | |
1495 } else if (isSideEffectFree) { | |
1496 setUseGvn(); | |
1497 setDependsOnSomething(); | |
1498 } else { | |
1499 setAllSideEffects(); | |
1500 } | |
1501 } | |
1502 | |
1503 int typeCode() => HInstruction.INVOKE_INTERCEPTOR_TYPECODE; | |
1504 bool typeEquals(other) => other is HInvokeInterceptor; | |
1505 bool dataEquals(HInvokeInterceptor other) => selector == other.selector; | |
1506 } | |
1507 | |
1508 abstract class HFieldAccess extends HInstruction { | 1434 abstract class HFieldAccess extends HInstruction { |
1509 final Element element; | 1435 final Element element; |
1510 | 1436 |
1511 HFieldAccess(Element element, List<HInstruction> inputs) | 1437 HFieldAccess(Element element, List<HInstruction> inputs) |
1512 : this.element = element, | 1438 : this.element = element, |
1513 super(inputs); | 1439 super(inputs); |
1514 } | 1440 } |
1515 | 1441 |
1516 class HFieldGet extends HFieldAccess { | 1442 class HFieldGet extends HFieldAccess { |
1517 final bool isAssignable; | 1443 final bool isAssignable; |
(...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3016 HBasicBlock get start => expression.start; | 2942 HBasicBlock get start => expression.start; |
3017 HBasicBlock get end { | 2943 HBasicBlock get end { |
3018 // We don't create a switch block if there are no cases. | 2944 // We don't create a switch block if there are no cases. |
3019 assert(!statements.isEmpty); | 2945 assert(!statements.isEmpty); |
3020 return statements.last.end; | 2946 return statements.last.end; |
3021 } | 2947 } |
3022 | 2948 |
3023 bool accept(HStatementInformationVisitor visitor) => | 2949 bool accept(HStatementInformationVisitor visitor) => |
3024 visitor.visitSwitchInfo(this); | 2950 visitor.visitSwitchInfo(this); |
3025 } | 2951 } |
OLD | NEW |