Chromium Code Reviews| 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); |
|
ahe
2012/11/23 06:51:23
Remove this method? I believe it was only there t
ngeoffray
2012/11/23 12:01:17
Done.
| |
| 1322 | |
| 1323 bool get isInterceptorCall { | |
| 1324 // We know it's a selector call if it follows the interceptor | |
| 1325 // calling convention, which adds the actual receiver as a | |
| 1326 // parameter to the call. | |
| 1327 return inputs.length - 2 == selector.argumentCount; | |
| 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) |
| 1336 : super(selector, null, inputs); | 1339 : super(selector, null, inputs); |
| 1337 toString() => 'invoke dynamic method: $selector'; | 1340 toString() => 'invoke dynamic method: $selector'; |
| 1338 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 1341 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); |
| 1339 } | 1342 } |
| 1340 | 1343 |
| 1341 abstract class HInvokeDynamicField extends HInvokeDynamic { | 1344 abstract class HInvokeDynamicField extends HInvokeDynamic { |
| 1342 final bool isSideEffectFree; | 1345 final bool isSideEffectFree; |
| 1343 HInvokeDynamicField( | 1346 HInvokeDynamicField( |
| 1344 Selector selector, Element element, List<HInstruction> inputs, | 1347 Selector selector, Element element, List<HInstruction> inputs, |
| 1345 this.isSideEffectFree) | 1348 this.isSideEffectFree) |
| 1346 : super(selector, element, inputs); | 1349 : super(selector, element, inputs); |
| 1347 toString() => 'invoke dynamic field: $selector'; | 1350 toString() => 'invoke dynamic field: $selector'; |
| 1348 | 1351 |
| 1349 // TODO(floitsch): make class abstract instead of adding an abstract method. | |
| 1350 accept(HVisitor visitor); | 1352 accept(HVisitor visitor); |
|
ahe
2012/11/23 06:51:23
Remove this method?
ngeoffray
2012/11/23 12:01:17
Done.
| |
| 1351 } | 1353 } |
| 1352 | 1354 |
| 1353 class HInvokeDynamicGetter extends HInvokeDynamicField { | 1355 class HInvokeDynamicGetter extends HInvokeDynamicField { |
| 1354 HInvokeDynamicGetter( | 1356 HInvokeDynamicGetter( |
| 1355 selector, element, receiver, isSideEffectFree) | 1357 selector, element, receiver, isSideEffectFree) |
| 1356 : super(selector, element, [receiver], isSideEffectFree); | 1358 : super(selector, element, [receiver], isSideEffectFree); |
| 1357 toString() => 'invoke dynamic getter: $selector'; | 1359 toString() => 'invoke dynamic getter: $selector'; |
| 1358 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); | 1360 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); |
| 1359 | 1361 |
| 1360 void prepareGvn(HTypeMap types) { | 1362 void prepareGvn(HTypeMap types) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1382 clearAllSideEffects(); | 1384 clearAllSideEffects(); |
| 1383 if (isSideEffectFree) { | 1385 if (isSideEffectFree) { |
| 1384 setChangesInstanceProperty(); | 1386 setChangesInstanceProperty(); |
| 1385 } else { | 1387 } else { |
| 1386 setAllSideEffects(); | 1388 setAllSideEffects(); |
| 1387 } | 1389 } |
| 1388 } | 1390 } |
| 1389 } | 1391 } |
| 1390 | 1392 |
| 1391 class HInvokeStatic extends HInvoke { | 1393 class HInvokeStatic extends HInvoke { |
| 1394 bool isSideEffectFree = false; | |
| 1392 /** The first input must be the target. */ | 1395 /** The first input must be the target. */ |
| 1393 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) { | 1396 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) { |
| 1394 guaranteedType = knownType; | 1397 guaranteedType = knownType; |
| 1395 } | 1398 } |
| 1396 | 1399 |
| 1397 toString() => 'invoke static: ${element.name}'; | 1400 toString() => 'invoke static: ${element.name}'; |
| 1398 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); | 1401 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); |
| 1399 int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE; | 1402 int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE; |
| 1400 Element get element => target.element; | 1403 Element get element => target.element; |
| 1401 HStatic get target => inputs[0]; | 1404 HStatic get target => inputs[0]; |
| 1402 | 1405 |
| 1403 HType computeDesiredTypeForInput(HInstruction input, | 1406 HType computeDesiredTypeForInput(HInstruction input, |
| 1404 HTypeMap types, | 1407 HTypeMap types, |
| 1405 Compiler compiler) { | 1408 Compiler compiler) { |
| 1406 // TODO(floitsch): we want the target to be a function. | 1409 // TODO(floitsch): we want the target to be a function. |
| 1407 if (input == target) return HType.UNKNOWN; | 1410 if (input == target) return HType.UNKNOWN; |
| 1408 return computeDesiredTypeForNonTargetInput(input, types, compiler); | 1411 return computeDesiredTypeForNonTargetInput(input, types, compiler); |
| 1409 } | 1412 } |
| 1410 | 1413 |
| 1411 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1414 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1412 HTypeMap types, | 1415 HTypeMap types, |
| 1413 Compiler compiler) { | 1416 Compiler compiler) { |
| 1414 return HType.UNKNOWN; | 1417 return HType.UNKNOWN; |
| 1415 } | 1418 } |
| 1419 | |
| 1420 void prepareGvn(HTypeMap types) { | |
| 1421 clearAllSideEffects(); | |
| 1422 if (!isSideEffectFree) { | |
| 1423 setAllSideEffects(); | |
| 1424 } | |
| 1425 } | |
| 1416 } | 1426 } |
| 1417 | 1427 |
| 1418 class HInvokeSuper extends HInvokeStatic { | 1428 class HInvokeSuper extends HInvokeStatic { |
| 1419 final bool isSetter; | 1429 final bool isSetter; |
| 1420 HInvokeSuper(inputs, {this.isSetter: false}) : super(inputs); | 1430 HInvokeSuper(inputs, {this.isSetter: false}) : super(inputs); |
| 1421 toString() => 'invoke super: ${element.name}'; | 1431 toString() => 'invoke super: ${element.name}'; |
| 1422 accept(HVisitor visitor) => visitor.visitInvokeSuper(this); | 1432 accept(HVisitor visitor) => visitor.visitInvokeSuper(this); |
| 1423 | 1433 |
| 1424 HInstruction get value { | 1434 HInstruction get value { |
| 1425 assert(isSetter); | 1435 assert(isSetter); |
| 1426 // Index 0: the element, index 1: 'this'. | 1436 // Index 0: the element, index 1: 'this'. |
| 1427 return inputs[2]; | 1437 return inputs[2]; |
| 1428 } | 1438 } |
| 1429 } | 1439 } |
| 1430 | 1440 |
| 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 { | 1441 abstract class HFieldAccess extends HInstruction { |
| 1509 final Element element; | 1442 final Element element; |
| 1510 | 1443 |
| 1511 HFieldAccess(Element element, List<HInstruction> inputs) | 1444 HFieldAccess(Element element, List<HInstruction> inputs) |
| 1512 : this.element = element, | 1445 : this.element = element, |
| 1513 super(inputs); | 1446 super(inputs); |
| 1514 } | 1447 } |
| 1515 | 1448 |
| 1516 class HFieldGet extends HFieldAccess { | 1449 class HFieldGet extends HFieldAccess { |
| 1517 final bool isAssignable; | 1450 final bool isAssignable; |
| (...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3016 HBasicBlock get start => expression.start; | 2949 HBasicBlock get start => expression.start; |
| 3017 HBasicBlock get end { | 2950 HBasicBlock get end { |
| 3018 // We don't create a switch block if there are no cases. | 2951 // We don't create a switch block if there are no cases. |
| 3019 assert(!statements.isEmpty); | 2952 assert(!statements.isEmpty); |
| 3020 return statements.last.end; | 2953 return statements.last.end; |
| 3021 } | 2954 } |
| 3022 | 2955 |
| 3023 bool accept(HStatementInformationVisitor visitor) => | 2956 bool accept(HStatementInformationVisitor visitor) => |
| 3024 visitor.visitSwitchInfo(this); | 2957 visitor.visitSwitchInfo(this); |
| 3025 } | 2958 } |
| OLD | NEW |