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

Side by Side Diff: lib/compiler/implementation/ssa/nodes.dart

Issue 11017006: Create and use new change/depends flags for the GVN analysis. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 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
« no previous file with comments | « lib/compiler/implementation/ssa/builder.dart ('k') | lib/compiler/implementation/world.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 abstract class HVisitor<R> { 5 abstract class 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);
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 582
583 void addSuccessor(HBasicBlock block) { 583 void addSuccessor(HBasicBlock block) {
584 if (successors.isEmpty()) { 584 if (successors.isEmpty()) {
585 successors = [block]; 585 successors = [block];
586 } else { 586 } else {
587 successors.add(block); 587 successors.add(block);
588 } 588 }
589 block.predecessors.add(this); 589 block.predecessors.add(this);
590 } 590 }
591 591
592 void removeSuccessor(HBasicBlock successor) {
593 successors.removeAt(successors.indexOf(successor));
594 successor.predecessors.removeAt(successors.predecessors.indexOf(this));
595 }
596
592 void postProcessLoopHeader() { 597 void postProcessLoopHeader() {
593 assert(isLoopHeader()); 598 assert(isLoopHeader());
594 // Only the first entry into the loop is from outside the 599 // Only the first entry into the loop is from outside the
595 // loop. All other entries must be back edges. 600 // loop. All other entries must be back edges.
596 for (int i = 1, length = predecessors.length; i < length; i++) { 601 for (int i = 1, length = predecessors.length; i < length; i++) {
597 loopInformation.addBackEdge(predecessors[i]); 602 loopInformation.addBackEdge(predecessors[i]);
598 } 603 }
599 } 604 }
600 605
601 /** 606 /**
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 755
751 final List<HInstruction> inputs; 756 final List<HInstruction> inputs;
752 final List<HInstruction> usedBy; 757 final List<HInstruction> usedBy;
753 758
754 HBasicBlock block; 759 HBasicBlock block;
755 HInstruction previous = null; 760 HInstruction previous = null;
756 HInstruction next = null; 761 HInstruction next = null;
757 int flags = 0; 762 int flags = 0;
758 763
759 // Changes flags. 764 // Changes flags.
760 static const int FLAG_CHANGES_SOMETHING = 0; 765 static const int FLAG_CHANGES_INDEX = 0;
761 static const int FLAG_CHANGES_COUNT = FLAG_CHANGES_SOMETHING + 1; 766 static const int FLAG_CHANGES_INSTANCE_PROPERTY = FLAG_CHANGES_INDEX + 1;
767 static const int FLAG_CHANGES_STATIC_PROPERTY
768 = FLAG_CHANGES_INSTANCE_PROPERTY + 1;
769 static const int FLAG_CHANGES_SOMETHING = FLAG_CHANGES_STATIC_PROPERTY + 1;
770 static const int FLAG_CHANGES_COUNT = FLAG_CHANGES_SOMETHING + 1;
762 771
763 // Depends flags (one for each changes flag). 772 // Depends flags (one for each changes flag).
764 static const int FLAG_DEPENDS_ON_SOMETHING = FLAG_CHANGES_COUNT; 773 static const int FLAG_DEPENDS_ON_INDEX_STORE = FLAG_CHANGES_COUNT;
774 static const int FLAG_DEPENDS_ON_INSTANCE_PROPERTY_STORE =
775 FLAG_DEPENDS_ON_INDEX_STORE + 1;
776 static const int FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE =
777 FLAG_DEPENDS_ON_INSTANCE_PROPERTY_STORE + 1;
778 static const int FLAG_DEPENDS_ON_SOMETHING =
779 FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE + 1;
765 780
766 // Other flags. 781 // Other flags.
767 static const int FLAG_USE_GVN = FLAG_DEPENDS_ON_SOMETHING + 1; 782 static const int FLAG_USE_GVN = FLAG_DEPENDS_ON_SOMETHING + 1;
768 783
769 // Type codes. 784 // Type codes.
770 static const int UNDEFINED_TYPECODE = -1; 785 static const int UNDEFINED_TYPECODE = -1;
771 static const int BOOLIFY_TYPECODE = 0; 786 static const int BOOLIFY_TYPECODE = 0;
772 static const int TYPE_GUARD_TYPECODE = 1; 787 static const int TYPE_GUARD_TYPECODE = 1;
773 static const int BOUNDS_CHECK_TYPECODE = 2; 788 static const int BOUNDS_CHECK_TYPECODE = 2;
774 static const int INTEGER_CHECK_TYPECODE = 3; 789 static const int INTEGER_CHECK_TYPECODE = 3;
775 static const int INVOKE_INTERCEPTOR_TYPECODE = 4; 790 static const int INVOKE_INTERCEPTOR_TYPECODE = 4;
776 static const int ADD_TYPECODE = 5; 791 static const int ADD_TYPECODE = 5;
777 static const int DIVIDE_TYPECODE = 6; 792 static const int DIVIDE_TYPECODE = 6;
(...skipping 15 matching lines...) Expand all
793 static const int GREATER_EQUAL_TYPECODE = 22; 808 static const int GREATER_EQUAL_TYPECODE = 22;
794 static const int LESS_TYPECODE = 23; 809 static const int LESS_TYPECODE = 23;
795 static const int LESS_EQUAL_TYPECODE = 24; 810 static const int LESS_EQUAL_TYPECODE = 24;
796 static const int STATIC_TYPECODE = 25; 811 static const int STATIC_TYPECODE = 25;
797 static const int STATIC_STORE_TYPECODE = 26; 812 static const int STATIC_STORE_TYPECODE = 26;
798 static const int FIELD_GET_TYPECODE = 27; 813 static const int FIELD_GET_TYPECODE = 27;
799 static const int TYPE_CONVERSION_TYPECODE = 28; 814 static const int TYPE_CONVERSION_TYPECODE = 28;
800 static const int BAILOUT_TARGET_TYPECODE = 29; 815 static const int BAILOUT_TARGET_TYPECODE = 29;
801 static const int INVOKE_STATIC_TYPECODE = 30; 816 static const int INVOKE_STATIC_TYPECODE = 30;
802 static const int INVOKE_DYNAMIC_GETTER_TYPECODE = 31; 817 static const int INVOKE_DYNAMIC_GETTER_TYPECODE = 31;
818 static const int INDEX_TYPECODE = 32;
803 819
804 HInstruction(this.inputs) 820 HInstruction(this.inputs)
805 : id = idCounter++, 821 : id = idCounter++,
806 usedBy = <HInstruction>[]; 822 usedBy = <HInstruction>[];
807 823
808 int hashCode() => id; 824 int hashCode() => id;
809 825
810 bool getFlag(int position) => (flags & (1 << position)) != 0; 826 bool getFlag(int position) => (flags & (1 << position)) != 0;
811 void setFlag(int position) { flags |= (1 << position); } 827 void setFlag(int position) { flags |= (1 << position); }
812 void clearFlag(int position) { flags &= ~(1 << position); } 828 void clearFlag(int position) { flags &= ~(1 << position); }
813 829
814 static int computeDependsOnFlags(int flags) => flags << FLAG_CHANGES_COUNT; 830 static int computeDependsOnFlags(int flags) => flags << FLAG_CHANGES_COUNT;
815 831
816 int getChangesFlags() => flags & ((1 << FLAG_CHANGES_COUNT) - 1); 832 int getChangesFlags() => flags & ((1 << FLAG_CHANGES_COUNT) - 1);
817 bool hasSideEffects(HTypeMap types) => getChangesFlags() != 0; 833 bool hasSideEffects(HTypeMap types) => getChangesFlags() != 0;
818 void prepareGvn(HTypeMap types) { setAllSideEffects(); } 834 void prepareGvn(HTypeMap types) { setAllSideEffects(); }
819 835
820 void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); } 836 void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); }
821 void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); } 837 void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); }
822 838
823 bool dependsOnSomething() => getFlag(FLAG_DEPENDS_ON_SOMETHING); 839 bool dependsOnSomething() => getFlag(FLAG_DEPENDS_ON_SOMETHING);
824 void setDependsOnSomething() { setFlag(FLAG_DEPENDS_ON_SOMETHING); } 840 void setDependsOnSomething() { setFlag(FLAG_DEPENDS_ON_SOMETHING); }
825 841
842 bool dependsOnStaticPropertyStore() {
843 return getFlag(FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE);
844 }
845 void setDependsOnStaticPropertyStore() {
846 setFlag(FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE);
847 }
848 void setChangesStaticProperty() { setFlag(FLAG_CHANGES_STATIC_PROPERTY); }
849
850 bool dependsOnIndexStore() => getFlag(FLAG_DEPENDS_ON_INDEX_STORE);
851 void setDependsOnIndexStore() { setFlag(FLAG_DEPENDS_ON_INDEX_STORE); }
852 void setChangesIndex() { setFlag(FLAG_CHANGES_INDEX); }
853
854 bool dependsOnInstancePropertyStore() {
855 return getFlag(FLAG_DEPENDS_ON_INSTANCE_PROPERTY_STORE);
856 }
857 void setDependsOnInstancePropertyStore() {
858 setFlag(FLAG_DEPENDS_ON_INSTANCE_PROPERTY_STORE);
859 }
860 void setChangesInstanceProperty() { setFlag(FLAG_CHANGES_INSTANCE_PROPERTY); }
861
826 bool useGvn() => getFlag(FLAG_USE_GVN); 862 bool useGvn() => getFlag(FLAG_USE_GVN);
827 void setUseGvn() { setFlag(FLAG_USE_GVN); } 863 void setUseGvn() { setFlag(FLAG_USE_GVN); }
828 // Does this node potentially affect control flow. 864 // Does this node potentially affect control flow.
829 bool isControlFlow() => false; 865 bool isControlFlow() => false;
830 866
831 // All isFunctions work on the propagated types. 867 // All isFunctions work on the propagated types.
832 bool isArray(HTypeMap types) => types[this].isArray(); 868 bool isArray(HTypeMap types) => types[this].isArray();
833 bool isReadableArray(HTypeMap types) => types[this].isReadableArray(); 869 bool isReadableArray(HTypeMap types) => types[this].isReadableArray();
834 bool isMutableArray(HTypeMap types) => types[this].isMutableArray(); 870 bool isMutableArray(HTypeMap types) => types[this].isMutableArray();
835 bool isExtendableArray(HTypeMap types) => types[this].isExtendableArray(); 871 bool isExtendableArray(HTypeMap types) => types[this].isExtendableArray();
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 } 1328 }
1293 1329
1294 class HInvokeDynamicMethod extends HInvokeDynamic { 1330 class HInvokeDynamicMethod extends HInvokeDynamic {
1295 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) 1331 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs)
1296 : super(selector, null, inputs); 1332 : super(selector, null, inputs);
1297 toString() => 'invoke dynamic method: $selector'; 1333 toString() => 'invoke dynamic method: $selector';
1298 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); 1334 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
1299 } 1335 }
1300 1336
1301 abstract class HInvokeDynamicField extends HInvokeDynamic { 1337 abstract class HInvokeDynamicField extends HInvokeDynamic {
1302 HInvokeDynamicField(Selector selector, Element element, 1338 final bool isSideEffectFree;
1303 List<HInstruction> inputs) 1339 HInvokeDynamicField(
1340 Selector selector, Element element, List<HInstruction> inputs,
1341 this.isSideEffectFree)
1304 : super(selector, element, inputs); 1342 : super(selector, element, inputs);
1305 toString() => 'invoke dynamic field: $selector'; 1343 toString() => 'invoke dynamic field: $selector';
1306 1344
1307 // TODO(floitsch): make class abstract instead of adding an abstract method. 1345 // TODO(floitsch): make class abstract instead of adding an abstract method.
1308 abstract accept(HVisitor visitor); 1346 abstract accept(HVisitor visitor);
1309 } 1347 }
1310 1348
1311 class HInvokeDynamicGetter extends HInvokeDynamicField { 1349 class HInvokeDynamicGetter extends HInvokeDynamicField {
1312 final bool isSideEffectFree;
1313 HInvokeDynamicGetter( 1350 HInvokeDynamicGetter(
1314 selector, element, receiver, this.isSideEffectFree) 1351 selector, element, receiver, isSideEffectFree)
1315 : super(selector, element,[receiver]); 1352 : super(selector, element, [receiver], isSideEffectFree);
1316 toString() => 'invoke dynamic getter: $selector'; 1353 toString() => 'invoke dynamic getter: $selector';
1317 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); 1354 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);
1318 1355
1319 void prepareGvn(HTypeMap types) { 1356 void prepareGvn(HTypeMap types) {
1357 clearAllSideEffects();
1320 if (isSideEffectFree) { 1358 if (isSideEffectFree) {
1321 setUseGvn(); 1359 setUseGvn();
1322 clearAllSideEffects(); 1360 setDependsOnInstancePropertyStore();
1323 setDependsOnSomething();
1324 } else { 1361 } else {
1325 setAllSideEffects(); 1362 setAllSideEffects();
1326 } 1363 }
1327 } 1364 }
1328 1365
1329 int typeCode() => HInstruction.INVOKE_DYNAMIC_GETTER_TYPECODE; 1366 int typeCode() => HInstruction.INVOKE_DYNAMIC_GETTER_TYPECODE;
1330 bool typeEquals(other) => other is HInvokeDynamicGetter; 1367 bool typeEquals(other) => other is HInvokeDynamicGetter;
1331 bool dataEquals(HInvokeDynamicGetter other) => selector == other.selector; 1368 bool dataEquals(HInvokeDynamicGetter other) => selector == other.selector;
1332 } 1369 }
1333 1370
1334 class HInvokeDynamicSetter extends HInvokeDynamicField { 1371 class HInvokeDynamicSetter extends HInvokeDynamicField {
1335 HInvokeDynamicSetter(selector, element, receiver, value) 1372 HInvokeDynamicSetter(selector, element, receiver, value, isSideEffectFree)
1336 : super(selector, element, [receiver, value]); 1373 : super(selector, element, [receiver, value], isSideEffectFree);
1337 toString() => 'invoke dynamic setter: $selector'; 1374 toString() => 'invoke dynamic setter: $selector';
1338 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this); 1375 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);
1376
1377 void prepareGvn(HTypeMap types) {
1378 clearAllSideEffects();
1379 if (isSideEffectFree) {
1380 setChangesInstanceProperty();
1381 } else {
1382 setAllSideEffects();
1383 }
1384 }
1339 } 1385 }
1340 1386
1341 class HInvokeStatic extends HInvoke { 1387 class HInvokeStatic extends HInvoke {
1342 /** The first input must be the target. */ 1388 /** The first input must be the target. */
1343 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) { 1389 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) {
1344 guaranteedType = knownType; 1390 guaranteedType = knownType;
1345 } 1391 }
1346 1392
1347 toString() => 'invoke static: ${element.name}'; 1393 toString() => 'invoke static: ${element.name}';
1348 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); 1394 accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 // TODO(kasperl): Should we check that the selector is a call selector? 1469 // TODO(kasperl): Should we check that the selector is a call selector?
1424 if (selector.name == const SourceString('add') 1470 if (selector.name == const SourceString('add')
1425 || selector.name == const SourceString('removeLast')) { 1471 || selector.name == const SourceString('removeLast')) {
1426 return HType.MUTABLE_ARRAY; 1472 return HType.MUTABLE_ARRAY;
1427 } 1473 }
1428 } 1474 }
1429 return HType.UNKNOWN; 1475 return HType.UNKNOWN;
1430 } 1476 }
1431 1477
1432 void prepareGvn(HTypeMap types) { 1478 void prepareGvn(HTypeMap types) {
1479 clearAllSideEffects();
1433 if (isLengthGetterOnStringOrArray(types)) { 1480 if (isLengthGetterOnStringOrArray(types)) {
1434 setUseGvn(); 1481 setUseGvn();
1435 clearAllSideEffects();
1436 // If the input is a string, we know the length cannot change. 1482 // If the input is a string, we know the length cannot change.
1437 // We cannot do the same thing for non-extendable array because 1483 // We cannot do the same thing for non-extendable array because
1438 // we don't express that type yet: a mutable array might be 1484 // we don't express that type yet: a mutable array might be
1439 // extendable. 1485 // extendable.
1440 if (!inputs[1].isString(types)) setDependsOnSomething(); 1486 if (!inputs[1].isString(types)) setDependsOnInstancePropertyStore();
1441 } else if (isSideEffectFree) { 1487 } else if (isSideEffectFree) {
1442 setUseGvn(); 1488 setUseGvn();
1443 clearAllSideEffects();
1444 setDependsOnSomething(); 1489 setDependsOnSomething();
1445 } else { 1490 } else {
1446 setAllSideEffects(); 1491 setAllSideEffects();
1447 } 1492 }
1448 } 1493 }
1449 1494
1450 int typeCode() => HInstruction.INVOKE_INTERCEPTOR_TYPECODE; 1495 int typeCode() => HInstruction.INVOKE_INTERCEPTOR_TYPECODE;
1451 bool typeEquals(other) => other is HInvokeInterceptor; 1496 bool typeEquals(other) => other is HInvokeInterceptor;
1452 bool dataEquals(HInvokeInterceptor other) => selector == other.selector; 1497 bool dataEquals(HInvokeInterceptor other) => selector == other.selector;
1453 } 1498 }
(...skipping 13 matching lines...) Expand all
1467 : this.isAssignable = (isAssignable !== null) 1512 : this.isAssignable = (isAssignable !== null)
1468 ? isAssignable 1513 ? isAssignable
1469 : element.isAssignable(), 1514 : element.isAssignable(),
1470 super(element, <HInstruction>[receiver]); 1515 super(element, <HInstruction>[receiver]);
1471 1516
1472 HInstruction get receiver => inputs[0]; 1517 HInstruction get receiver => inputs[0];
1473 1518
1474 accept(HVisitor visitor) => visitor.visitFieldGet(this); 1519 accept(HVisitor visitor) => visitor.visitFieldGet(this);
1475 1520
1476 void prepareGvn(HTypeMap types) { 1521 void prepareGvn(HTypeMap types) {
1522 clearAllSideEffects();
1477 setUseGvn(); 1523 setUseGvn();
1478 clearAllSideEffects(); 1524 if (isAssignable) {
1479 if (isAssignable) setDependsOnSomething(); 1525 setDependsOnInstancePropertyStore();
1526 }
1480 } 1527 }
1481 1528
1482 int typeCode() => HInstruction.FIELD_GET_TYPECODE; 1529 int typeCode() => HInstruction.FIELD_GET_TYPECODE;
1483 bool typeEquals(other) => other is HFieldGet; 1530 bool typeEquals(other) => other is HFieldGet;
1484 bool dataEquals(HFieldGet other) => element == other.element; 1531 bool dataEquals(HFieldGet other) => element == other.element;
1485 String toString() => "FieldGet $element"; 1532 String toString() => "FieldGet $element";
1486 } 1533 }
1487 1534
1488 class HFieldSet extends HFieldAccess { 1535 class HFieldSet extends HFieldAccess {
1489 HFieldSet(Element element, 1536 HFieldSet(Element element,
1490 HInstruction receiver, 1537 HInstruction receiver,
1491 HInstruction value) 1538 HInstruction value)
1492 : super(element, <HInstruction>[receiver, value]); 1539 : super(element, <HInstruction>[receiver, value]);
1493 1540
1494 HInstruction get receiver => inputs[0]; 1541 HInstruction get receiver => inputs[0];
1495 HInstruction get value => inputs[1]; 1542 HInstruction get value => inputs[1];
1496 accept(HVisitor visitor) => visitor.visitFieldSet(this); 1543 accept(HVisitor visitor) => visitor.visitFieldSet(this);
1497 1544
1498 void prepareGvn(HTypeMap types) { 1545 void prepareGvn(HTypeMap types) {
1499 // TODO(ngeoffray): implement more fine grained side effects. 1546 clearAllSideEffects();
1500 setAllSideEffects(); 1547 setChangesInstanceProperty();
1501 } 1548 }
1502 1549
1503 bool isJsStatement(HTypeMap types) => true; 1550 bool isJsStatement(HTypeMap types) => true;
1504 String toString() => "FieldSet $element"; 1551 String toString() => "FieldSet $element";
1505 } 1552 }
1506 1553
1507 class HLocalGet extends HFieldGet { 1554 class HLocalGet extends HFieldGet {
1508 HLocalGet(Element element, HLocalValue local) : super(element, local); 1555 HLocalGet(Element element, HLocalValue local) : super(element, local);
1509 1556
1510 accept(HVisitor visitor) => visitor.visitLocalGet(this); 1557 accept(HVisitor visitor) => visitor.visitLocalGet(this);
1511 1558
1512 HLocalValue get local => inputs[0]; 1559 HLocalValue get local => inputs[0];
1513
1514 void prepareGvn(HTypeMap types) {
1515 setUseGvn();
1516 // TODO(floitsch): if the variable is not captured then it only depends
1517 // on assignments to the same variable. Otherwise we need to see if the
1518 // variable is mutated inside closures.
1519 setDependsOnSomething();
1520 }
1521 } 1560 }
1522 1561
1523 class HLocalSet extends HFieldSet { 1562 class HLocalSet extends HFieldSet {
1524 HLocalSet(Element element, HLocalValue local, HInstruction value) 1563 HLocalSet(Element element, HLocalValue local, HInstruction value)
1525 : super(element, local, value); 1564 : super(element, local, value);
1526 1565
1527 accept(HVisitor visitor) => visitor.visitLocalSet(this); 1566 accept(HVisitor visitor) => visitor.visitLocalSet(this);
1528 1567
1529 HLocalValue get local => inputs[0]; 1568 HLocalValue get local => inputs[0];
1530
1531 void prepareGvn(HTypeMap types) {
1532 // TODO(floitsch): implement more fine grained side effects.
1533 setAllSideEffects();
1534 }
1535 } 1569 }
1536 1570
1537 class HForeign extends HInstruction { 1571 class HForeign extends HInstruction {
1538 final DartString code; 1572 final DartString code;
1539 final HType foreignType; 1573 final HType foreignType;
1540 final bool _isStatement; 1574 final bool _isStatement;
1541 1575
1542 HForeign(this.code, DartString declaredType, List<HInstruction> inputs) 1576 HForeign(this.code, DartString declaredType, List<HInstruction> inputs)
1543 : foreignType = computeTypeFromDeclaredType(declaredType), 1577 : foreignType = computeTypeFromDeclaredType(declaredType),
1544 _isStatement = false, 1578 _isStatement = false,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1580 1614
1581 abstract BinaryOperation operation(ConstantSystem constantSystem); 1615 abstract BinaryOperation operation(ConstantSystem constantSystem);
1582 abstract isBuiltin(HTypeMap types); 1616 abstract isBuiltin(HTypeMap types);
1583 } 1617 }
1584 1618
1585 abstract class HBinaryArithmetic extends HInvokeBinary { 1619 abstract class HBinaryArithmetic extends HInvokeBinary {
1586 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) 1620 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right)
1587 : super(target, left, right); 1621 : super(target, left, right);
1588 1622
1589 void prepareGvn(HTypeMap types) { 1623 void prepareGvn(HTypeMap types) {
1624 clearAllSideEffects();
1590 // An arithmetic expression can take part in global value 1625 // An arithmetic expression can take part in global value
1591 // numbering and do not have any side-effects if we know that all 1626 // numbering and do not have any side-effects if we know that all
1592 // inputs are numbers. 1627 // inputs are numbers.
1593 if (isBuiltin(types)) { 1628 if (isBuiltin(types)) {
1594 clearAllSideEffects();
1595 setUseGvn(); 1629 setUseGvn();
1596 } else { 1630 } else {
1597 setAllSideEffects(); 1631 setAllSideEffects();
1598 } 1632 }
1599 } 1633 }
1600 1634
1601 bool isBuiltin(HTypeMap types) 1635 bool isBuiltin(HTypeMap types)
1602 => left.isNumber(types) && right.isNumber(types); 1636 => left.isNumber(types) && right.isNumber(types);
1603 1637
1604 HType computeTypeFromInputTypes(HTypeMap types) { 1638 HType computeTypeFromInputTypes(HTypeMap types) {
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
1856 bool dataEquals(HInstruction other) => true; 1890 bool dataEquals(HInstruction other) => true;
1857 } 1891 }
1858 1892
1859 abstract class HInvokeUnary extends HInvokeStatic { 1893 abstract class HInvokeUnary extends HInvokeStatic {
1860 HInvokeUnary(HStatic target, HInstruction input) 1894 HInvokeUnary(HStatic target, HInstruction input)
1861 : super(<HInstruction>[target, input]); 1895 : super(<HInstruction>[target, input]);
1862 1896
1863 HInstruction get operand => inputs[1]; 1897 HInstruction get operand => inputs[1];
1864 1898
1865 void prepareGvn(HTypeMap types) { 1899 void prepareGvn(HTypeMap types) {
1900 clearAllSideEffects();
1866 // A unary arithmetic expression can take part in global value 1901 // A unary arithmetic expression can take part in global value
1867 // numbering and does not have any side-effects if its input is a 1902 // numbering and does not have any side-effects if its input is a
1868 // number. 1903 // number.
1869 if (isBuiltin(types)) { 1904 if (isBuiltin(types)) {
1870 clearAllSideEffects();
1871 setUseGvn(); 1905 setUseGvn();
1872 } else { 1906 } else {
1873 setAllSideEffects(); 1907 setAllSideEffects();
1874 } 1908 }
1875 } 1909 }
1876 1910
1877 bool isBuiltin(HTypeMap types) => operand.isNumber(types); 1911 bool isBuiltin(HTypeMap types) => operand.isNumber(types);
1878 1912
1879 HType computeTypeFromInputTypes(HTypeMap types) { 1913 HType computeTypeFromInputTypes(HTypeMap types) {
1880 HType operandType = types[operand]; 1914 HType operandType = types[operand];
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
2185 toString() => 'phi'; 2219 toString() => 'phi';
2186 accept(HVisitor visitor) => visitor.visitPhi(this); 2220 accept(HVisitor visitor) => visitor.visitPhi(this);
2187 } 2221 }
2188 2222
2189 abstract class HRelational extends HInvokeBinary { 2223 abstract class HRelational extends HInvokeBinary {
2190 bool usesBoolifiedInterceptor = false; 2224 bool usesBoolifiedInterceptor = false;
2191 HRelational(HStatic target, HInstruction left, HInstruction right) 2225 HRelational(HStatic target, HInstruction left, HInstruction right)
2192 : super(target, left, right); 2226 : super(target, left, right);
2193 2227
2194 void prepareGvn(HTypeMap types) { 2228 void prepareGvn(HTypeMap types) {
2229 clearAllSideEffects();
2195 // Relational expressions can take part in global value numbering 2230 // Relational expressions can take part in global value numbering
2196 // and do not have any side-effects if we know all the inputs are 2231 // and do not have any side-effects if we know all the inputs are
2197 // numbers. This can be improved for at least equality. 2232 // numbers. This can be improved for at least equality.
2198 if (isBuiltin(types)) { 2233 if (isBuiltin(types)) {
2199 clearAllSideEffects();
2200 setUseGvn(); 2234 setUseGvn();
2201 } else { 2235 } else {
2202 setAllSideEffects(); 2236 setAllSideEffects();
2203 } 2237 }
2204 } 2238 }
2205 2239
2206 HType computeTypeFromInputTypes(HTypeMap types) { 2240 HType computeTypeFromInputTypes(HTypeMap types) {
2207 if (left.isNumber(types) || usesBoolifiedInterceptor) return HType.BOOLEAN; 2241 if (left.isNumber(types) || usesBoolifiedInterceptor) return HType.BOOLEAN;
2208 return HType.UNKNOWN; 2242 return HType.UNKNOWN;
2209 } 2243 }
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
2369 } 2403 }
2370 2404
2371 class HStatic extends HInstruction { 2405 class HStatic extends HInstruction {
2372 final Element element; 2406 final Element element;
2373 HStatic(this.element) : super(<HInstruction>[]) { 2407 HStatic(this.element) : super(<HInstruction>[]) {
2374 assert(element !== null); 2408 assert(element !== null);
2375 assert(invariant(this, element.isDeclaration)); 2409 assert(invariant(this, element.isDeclaration));
2376 } 2410 }
2377 2411
2378 void prepareGvn(HTypeMap types) { 2412 void prepareGvn(HTypeMap types) {
2379 if (!element.isAssignable()) { 2413 clearAllSideEffects();
2380 clearAllSideEffects(); 2414 if (element.isAssignable()) {
2381 setUseGvn(); 2415 setDependsOnStaticPropertyStore();
2382 } 2416 }
2417 setUseGvn();
2383 } 2418 }
2384 toString() => 'static ${element.name}'; 2419 toString() => 'static ${element.name}';
2385 accept(HVisitor visitor) => visitor.visitStatic(this); 2420 accept(HVisitor visitor) => visitor.visitStatic(this);
2386 2421
2387 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode(); 2422 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode();
2388 int typeCode() => HInstruction.STATIC_TYPECODE; 2423 int typeCode() => HInstruction.STATIC_TYPECODE;
2389 bool typeEquals(other) => other is HStatic; 2424 bool typeEquals(other) => other is HStatic;
2390 bool dataEquals(HStatic other) => element == other.element; 2425 bool dataEquals(HStatic other) => element == other.element;
2391 bool isCodeMotionInvariant() => !element.isAssignable(); 2426 bool isCodeMotionInvariant() => !element.isAssignable();
2392 } 2427 }
(...skipping 19 matching lines...) Expand all
2412 class HStaticStore extends HInstruction { 2447 class HStaticStore extends HInstruction {
2413 Element element; 2448 Element element;
2414 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]); 2449 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]);
2415 toString() => 'static store ${element.name}'; 2450 toString() => 'static store ${element.name}';
2416 accept(HVisitor visitor) => visitor.visitStaticStore(this); 2451 accept(HVisitor visitor) => visitor.visitStaticStore(this);
2417 2452
2418 int typeCode() => HInstruction.STATIC_STORE_TYPECODE; 2453 int typeCode() => HInstruction.STATIC_STORE_TYPECODE;
2419 bool typeEquals(other) => other is HStaticStore; 2454 bool typeEquals(other) => other is HStaticStore;
2420 bool dataEquals(HStaticStore other) => element == other.element; 2455 bool dataEquals(HStaticStore other) => element == other.element;
2421 bool isJsStatement(HTypeMap types) => true; 2456 bool isJsStatement(HTypeMap types) => true;
2457
2458 void prepareGvn(HTypeMap types) {
2459 clearAllSideEffects();
2460 setChangesStaticProperty();
2461 }
2422 } 2462 }
2423 2463
2424 class HLiteralList extends HInstruction { 2464 class HLiteralList extends HInstruction {
2425 HLiteralList(inputs) : super(inputs); 2465 HLiteralList(inputs) : super(inputs);
2426 toString() => 'literal list'; 2466 toString() => 'literal list';
2427 accept(HVisitor visitor) => visitor.visitLiteralList(this); 2467 accept(HVisitor visitor) => visitor.visitLiteralList(this);
2428 2468
2429 HType get guaranteedType => HType.EXTENDABLE_ARRAY; 2469 HType get guaranteedType => HType.EXTENDABLE_ARRAY;
2430 2470
2431 void prepareGvn(HTypeMap types) { 2471 void prepareGvn(HTypeMap types) {
2432 assert(!hasSideEffects(types)); 2472 assert(!hasSideEffects(types));
2433 } 2473 }
2434 } 2474 }
2435 2475
2436 class HIndex extends HInvokeStatic { 2476 class HIndex extends HInvokeStatic {
2437 HIndex(HStatic target, HInstruction receiver, HInstruction index) 2477 HIndex(HStatic target, HInstruction receiver, HInstruction index)
2438 : super(<HInstruction>[target, receiver, index]); 2478 : super(<HInstruction>[target, receiver, index]);
2439 toString() => 'index operator'; 2479 toString() => 'index operator';
2440 accept(HVisitor visitor) => visitor.visitIndex(this); 2480 accept(HVisitor visitor) => visitor.visitIndex(this);
2441 2481
2442 void prepareGvn(HTypeMap types) { 2482 void prepareGvn(HTypeMap types) {
2483 clearAllSideEffects();
2443 if (isBuiltin(types)) { 2484 if (isBuiltin(types)) {
2444 clearAllSideEffects(); 2485 setDependsOnIndexStore();
2486 setUseGvn();
2445 } else { 2487 } else {
2446 setAllSideEffects(); 2488 setAllSideEffects();
2447 } 2489 }
2448 } 2490 }
2449 2491
2450 HInstruction get receiver => inputs[1]; 2492 HInstruction get receiver => inputs[1];
2451 HInstruction get index => inputs[2]; 2493 HInstruction get index => inputs[2];
2452 2494
2453 HType computeDesiredTypeForNonTargetInput(HInstruction input, 2495 HType computeDesiredTypeForNonTargetInput(HInstruction input,
2454 HTypeMap types) { 2496 HTypeMap types) {
2455 if (input == receiver && 2497 if (input == receiver &&
2456 (index.isTypeUnknown(types) || index.isNumber(types))) { 2498 (index.isTypeUnknown(types) || index.isNumber(types))) {
2457 return HType.INDEXABLE_PRIMITIVE; 2499 return HType.INDEXABLE_PRIMITIVE;
2458 } 2500 }
2459 // The index should be an int when the receiver is a string or array. 2501 // The index should be an int when the receiver is a string or array.
2460 // However it turns out that inserting an integer check in the optimized 2502 // However it turns out that inserting an integer check in the optimized
2461 // version is cheaper than having another bailout case. This is true, 2503 // version is cheaper than having another bailout case. This is true,
2462 // because the integer check will simply throw if it fails. 2504 // because the integer check will simply throw if it fails.
2463 return HType.UNKNOWN; 2505 return HType.UNKNOWN;
2464 } 2506 }
2465 2507
2466 bool isBuiltin(HTypeMap types) 2508 bool isBuiltin(HTypeMap types)
2467 => receiver.isIndexablePrimitive(types) && index.isInteger(types); 2509 => receiver.isIndexablePrimitive(types) && index.isInteger(types);
2510
2511 int typeCode() => HInstruction.INDEX_TYPECODE;
2512 bool typeEquals(HInstruction other) => other is HIndex;
2513 bool dataEquals(HIndex other) => true;
2468 } 2514 }
2469 2515
2470 class HIndexAssign extends HInvokeStatic { 2516 class HIndexAssign extends HInvokeStatic {
2471 HIndexAssign(HStatic target, 2517 HIndexAssign(HStatic target,
2472 HInstruction receiver, 2518 HInstruction receiver,
2473 HInstruction index, 2519 HInstruction index,
2474 HInstruction value) 2520 HInstruction value)
2475 : super(<HInstruction>[target, receiver, index, value]); 2521 : super(<HInstruction>[target, receiver, index, value]);
2476 toString() => 'index assign operator'; 2522 toString() => 'index assign operator';
2477 accept(HVisitor visitor) => visitor.visitIndexAssign(this); 2523 accept(HVisitor visitor) => visitor.visitIndexAssign(this);
2478 2524
2479 HInstruction get receiver => inputs[1]; 2525 HInstruction get receiver => inputs[1];
2480 HInstruction get index => inputs[2]; 2526 HInstruction get index => inputs[2];
2481 HInstruction get value => inputs[3]; 2527 HInstruction get value => inputs[3];
2482 2528
2529 void prepareGvn(HTypeMap types) {
2530 clearAllSideEffects();
2531 if (isBuiltin(types)) {
2532 setChangesIndex();
2533 } else {
2534 setAllSideEffects();
2535 }
2536 }
2537
2483 // Note, that we don't have a computeTypeFromInputTypes, since [HIndexAssign] 2538 // Note, that we don't have a computeTypeFromInputTypes, since [HIndexAssign]
2484 // is never used as input. 2539 // is never used as input.
2485 2540
2486 HType computeDesiredTypeForNonTargetInput(HInstruction input, 2541 HType computeDesiredTypeForNonTargetInput(HInstruction input,
2487 HTypeMap types) { 2542 HTypeMap types) {
2488 if (input == receiver && 2543 if (input == receiver &&
2489 (index.isTypeUnknown(types) || index.isNumber(types))) { 2544 (index.isTypeUnknown(types) || index.isNumber(types))) {
2490 return HType.MUTABLE_ARRAY; 2545 return HType.MUTABLE_ARRAY;
2491 } 2546 }
2492 // The index should be an int when the receiver is a string or array. 2547 // The index should be an int when the receiver is a string or array.
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after
2917 HBasicBlock get start => expression.start; 2972 HBasicBlock get start => expression.start;
2918 HBasicBlock get end { 2973 HBasicBlock get end {
2919 // We don't create a switch block if there are no cases. 2974 // We don't create a switch block if there are no cases.
2920 assert(!statements.isEmpty()); 2975 assert(!statements.isEmpty());
2921 return statements.last().end; 2976 return statements.last().end;
2922 } 2977 }
2923 2978
2924 bool accept(HStatementInformationVisitor visitor) => 2979 bool accept(HStatementInformationVisitor visitor) =>
2925 visitor.visitSwitchInfo(this); 2980 visitor.visitSwitchInfo(this);
2926 } 2981 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/builder.dart ('k') | lib/compiler/implementation/world.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698