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

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 739 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 750
751 final List<HInstruction> inputs; 751 final List<HInstruction> inputs;
752 final List<HInstruction> usedBy; 752 final List<HInstruction> usedBy;
753 753
754 HBasicBlock block; 754 HBasicBlock block;
755 HInstruction previous = null; 755 HInstruction previous = null;
756 HInstruction next = null; 756 HInstruction next = null;
757 int flags = 0; 757 int flags = 0;
758 758
759 // Changes flags. 759 // Changes flags.
760 static const int FLAG_CHANGES_SOMETHING = 0; 760 static const int FLAG_CHANGES_INDEX = 0;
761 static const int FLAG_CHANGES_COUNT = FLAG_CHANGES_SOMETHING + 1; 761 static const int FLAG_CHANGES_PROPERTY = FLAG_CHANGES_INDEX + 1;
762 static const int FLAG_CHANGES_STATIC = FLAG_CHANGES_PROPERTY + 1;
Søren Gjesse 2012/10/01 07:22:20 How about FLAG_CHANGES_STATIC_PROPERTY (and then m
ngeoffray 2012/10/04 10:41:42 Done.
763 static const int FLAG_CHANGES_SOMETHING = FLAG_CHANGES_STATIC + 1;
764 static const int FLAG_CHANGES_COUNT = FLAG_CHANGES_SOMETHING + 1;
762 765
763 // Depends flags (one for each changes flag). 766 // Depends flags (one for each changes flag).
764 static const int FLAG_DEPENDS_ON_SOMETHING = FLAG_CHANGES_COUNT; 767 static const int FLAG_DEPENDS_ON_INDEX_STORE = FLAG_CHANGES_COUNT;
768 static const int FLAG_DEPENDS_ON_PROPERTY_STORE =
769 FLAG_DEPENDS_ON_INDEX_STORE + 1;
770 static const int FLAG_DEPENDS_ON_STATIC = FLAG_DEPENDS_ON_PROPERTY_STORE + 1;
771 static const int FLAG_DEPENDS_ON_SOMETHING = FLAG_DEPENDS_ON_STATIC + 1;
765 772
766 // Other flags. 773 // Other flags.
767 static const int FLAG_USE_GVN = FLAG_DEPENDS_ON_SOMETHING + 1; 774 static const int FLAG_USE_GVN = FLAG_DEPENDS_ON_SOMETHING + 1;
768 775
769 // Type codes. 776 // Type codes.
770 static const int UNDEFINED_TYPECODE = -1; 777 static const int UNDEFINED_TYPECODE = -1;
771 static const int BOOLIFY_TYPECODE = 0; 778 static const int BOOLIFY_TYPECODE = 0;
772 static const int TYPE_GUARD_TYPECODE = 1; 779 static const int TYPE_GUARD_TYPECODE = 1;
773 static const int BOUNDS_CHECK_TYPECODE = 2; 780 static const int BOUNDS_CHECK_TYPECODE = 2;
774 static const int INTEGER_CHECK_TYPECODE = 3; 781 static const int INTEGER_CHECK_TYPECODE = 3;
(...skipping 18 matching lines...) Expand all
793 static const int GREATER_EQUAL_TYPECODE = 22; 800 static const int GREATER_EQUAL_TYPECODE = 22;
794 static const int LESS_TYPECODE = 23; 801 static const int LESS_TYPECODE = 23;
795 static const int LESS_EQUAL_TYPECODE = 24; 802 static const int LESS_EQUAL_TYPECODE = 24;
796 static const int STATIC_TYPECODE = 25; 803 static const int STATIC_TYPECODE = 25;
797 static const int STATIC_STORE_TYPECODE = 26; 804 static const int STATIC_STORE_TYPECODE = 26;
798 static const int FIELD_GET_TYPECODE = 27; 805 static const int FIELD_GET_TYPECODE = 27;
799 static const int TYPE_CONVERSION_TYPECODE = 28; 806 static const int TYPE_CONVERSION_TYPECODE = 28;
800 static const int BAILOUT_TARGET_TYPECODE = 29; 807 static const int BAILOUT_TARGET_TYPECODE = 29;
801 static const int INVOKE_STATIC_TYPECODE = 30; 808 static const int INVOKE_STATIC_TYPECODE = 30;
802 static const int INVOKE_DYNAMIC_GETTER_TYPECODE = 31; 809 static const int INVOKE_DYNAMIC_GETTER_TYPECODE = 31;
810 static const int INDEX_TYPECODE = 32;
803 811
804 HInstruction(this.inputs) 812 HInstruction(this.inputs)
805 : id = idCounter++, 813 : id = idCounter++,
806 usedBy = <HInstruction>[]; 814 usedBy = <HInstruction>[];
807 815
808 int hashCode() => id; 816 int hashCode() => id;
809 817
810 bool getFlag(int position) => (flags & (1 << position)) != 0; 818 bool getFlag(int position) => (flags & (1 << position)) != 0;
811 void setFlag(int position) { flags |= (1 << position); } 819 void setFlag(int position) { flags |= (1 << position); }
812 void clearFlag(int position) { flags &= ~(1 << position); } 820 void clearFlag(int position) { flags &= ~(1 << position); }
813 821
814 static int computeDependsOnFlags(int flags) => flags << FLAG_CHANGES_COUNT; 822 static int computeDependsOnFlags(int flags) => flags << FLAG_CHANGES_COUNT;
815 823
816 int getChangesFlags() => flags & ((1 << FLAG_CHANGES_COUNT) - 1); 824 int getChangesFlags() => flags & ((1 << FLAG_CHANGES_COUNT) - 1);
817 bool hasSideEffects(HTypeMap types) => getChangesFlags() != 0; 825 bool hasSideEffects(HTypeMap types) => getChangesFlags() != 0;
818 void prepareGvn(HTypeMap types) { setAllSideEffects(); } 826 void prepareGvn(HTypeMap types) { setAllSideEffects(); }
819 827
820 void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); } 828 void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); }
821 void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); } 829 void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); }
822 830
823 bool dependsOnSomething() => getFlag(FLAG_DEPENDS_ON_SOMETHING); 831 bool dependsOnSomething() => getFlag(FLAG_DEPENDS_ON_SOMETHING);
824 void setDependsOnSomething() { setFlag(FLAG_DEPENDS_ON_SOMETHING); } 832 void setDependsOnSomething() { setFlag(FLAG_DEPENDS_ON_SOMETHING); }
825 833
834 bool dependsOnStatic() => getFlag(FLAG_DEPENDS_ON_STATIC);
Søren Gjesse 2012/10/01 07:22:20 dependsOnStaticPropertyStore?
ngeoffray 2012/10/04 10:41:42 Done.
835 void setDependsOnStatic() { setFlag(FLAG_DEPENDS_ON_STATIC); }
836 void setChangesStatic() { setFlag(FLAG_CHANGES_STATIC); }
837
838 bool dependsOnIndexStore() => getFlag(FLAG_DEPENDS_ON_INDEX_STORE);
839 void setDependsOnIndexStore() { setFlag(FLAG_DEPENDS_ON_INDEX_STORE); }
840 void setChangesIndex() { setFlag(FLAG_CHANGES_INDEX); }
841
842 bool dependsOnPropertyStore() => getFlag(FLAG_DEPENDS_ON_PROPERTY_STORE);
843 void setDependsOnPropertyStore() { setFlag(FLAG_DEPENDS_ON_PROPERTY_STORE); }
844 void setChangesProperty() { setFlag(FLAG_CHANGES_PROPERTY); }
845
826 bool useGvn() => getFlag(FLAG_USE_GVN); 846 bool useGvn() => getFlag(FLAG_USE_GVN);
827 void setUseGvn() { setFlag(FLAG_USE_GVN); } 847 void setUseGvn() { setFlag(FLAG_USE_GVN); }
828 // Does this node potentially affect control flow. 848 // Does this node potentially affect control flow.
829 bool isControlFlow() => false; 849 bool isControlFlow() => false;
830 850
831 // All isFunctions work on the propagated types. 851 // All isFunctions work on the propagated types.
832 bool isArray(HTypeMap types) => types[this].isArray(); 852 bool isArray(HTypeMap types) => types[this].isArray();
833 bool isReadableArray(HTypeMap types) => types[this].isReadableArray(); 853 bool isReadableArray(HTypeMap types) => types[this].isReadableArray();
834 bool isMutableArray(HTypeMap types) => types[this].isMutableArray(); 854 bool isMutableArray(HTypeMap types) => types[this].isMutableArray();
835 bool isExtendableArray(HTypeMap types) => types[this].isExtendableArray(); 855 bool isExtendableArray(HTypeMap types) => types[this].isExtendableArray();
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
1291 } 1311 }
1292 1312
1293 class HInvokeDynamicMethod extends HInvokeDynamic { 1313 class HInvokeDynamicMethod extends HInvokeDynamic {
1294 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) 1314 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs)
1295 : super(selector, null, inputs); 1315 : super(selector, null, inputs);
1296 toString() => 'invoke dynamic method: $selector'; 1316 toString() => 'invoke dynamic method: $selector';
1297 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); 1317 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
1298 } 1318 }
1299 1319
1300 class HInvokeDynamicField extends HInvokeDynamic { 1320 class HInvokeDynamicField extends HInvokeDynamic {
1301 HInvokeDynamicField(Selector selector, Element element, 1321 final bool isSideEffectFree;
1302 List<HInstruction> inputs) 1322 HInvokeDynamicField(
1323 Selector selector, Element element, List<HInstruction> inputs,
1324 this.isSideEffectFree)
1303 : super(selector, element, inputs); 1325 : super(selector, element, inputs);
1304 toString() => 'invoke dynamic field: $selector'; 1326 toString() => 'invoke dynamic field: $selector';
1305 1327
1306 // TODO(floitsch): make class abstract instead of adding an abstract method. 1328 // TODO(floitsch): make class abstract instead of adding an abstract method.
1307 abstract accept(HVisitor visitor); 1329 abstract accept(HVisitor visitor);
1308 } 1330 }
1309 1331
1310 class HInvokeDynamicGetter extends HInvokeDynamicField { 1332 class HInvokeDynamicGetter extends HInvokeDynamicField {
1311 final bool isSideEffectFree;
1312 HInvokeDynamicGetter( 1333 HInvokeDynamicGetter(
1313 selector, element, receiver, this.isSideEffectFree) 1334 selector, element, receiver, isSideEffectFree)
1314 : super(selector, element,[receiver]); 1335 : super(selector, element, [receiver], isSideEffectFree);
1315 toString() => 'invoke dynamic getter: $selector'; 1336 toString() => 'invoke dynamic getter: $selector';
1316 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); 1337 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);
1317 1338
1318 void prepareGvn(HTypeMap types) { 1339 void prepareGvn(HTypeMap types) {
1319 if (isSideEffectFree) { 1340 if (isSideEffectFree) {
1320 setUseGvn(); 1341 setUseGvn();
1321 clearAllSideEffects(); 1342 clearAllSideEffects();
1322 setDependsOnSomething(); 1343 setDependsOnPropertyStore();
1323 } else { 1344 } else {
1324 setAllSideEffects(); 1345 setAllSideEffects();
1325 } 1346 }
1326 } 1347 }
1327 1348
1328 int typeCode() => HInstruction.INVOKE_DYNAMIC_GETTER_TYPECODE; 1349 int typeCode() => HInstruction.INVOKE_DYNAMIC_GETTER_TYPECODE;
1329 bool typeEquals(other) => other is HInvokeDynamicGetter; 1350 bool typeEquals(other) => other is HInvokeDynamicGetter;
1330 bool dataEquals(HInvokeDynamicGetter other) => selector == other.selector; 1351 bool dataEquals(HInvokeDynamicGetter other) => selector == other.selector;
1331 } 1352 }
1332 1353
1333 class HInvokeDynamicSetter extends HInvokeDynamicField { 1354 class HInvokeDynamicSetter extends HInvokeDynamicField {
1334 HInvokeDynamicSetter(selector, element, receiver, value) 1355 HInvokeDynamicSetter(selector, element, receiver, value, isSideEffectFree)
1335 : super(selector, element, [receiver, value]); 1356 : super(selector, element, [receiver, value], isSideEffectFree);
1336 toString() => 'invoke dynamic setter: $selector'; 1357 toString() => 'invoke dynamic setter: $selector';
1337 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this); 1358 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);
1359
1360 void prepareGvn(HTypeMap types) {
1361 if (isSideEffectFree) {
1362 setChangesProperty();
1363 } else {
1364 setAllSideEffects();
1365 }
1366 }
1338 } 1367 }
1339 1368
1340 class HInvokeStatic extends HInvoke { 1369 class HInvokeStatic extends HInvoke {
1341 /** The first input must be the target. */ 1370 /** The first input must be the target. */
1342 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) { 1371 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) {
1343 guaranteedType = knownType; 1372 guaranteedType = knownType;
1344 } 1373 }
1345 1374
1346 toString() => 'invoke static: ${element.name}'; 1375 toString() => 'invoke static: ${element.name}';
1347 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); 1376 accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1429 } 1458 }
1430 1459
1431 void prepareGvn(HTypeMap types) { 1460 void prepareGvn(HTypeMap types) {
1432 if (isLengthGetterOnStringOrArray(types)) { 1461 if (isLengthGetterOnStringOrArray(types)) {
1433 setUseGvn(); 1462 setUseGvn();
1434 clearAllSideEffects(); 1463 clearAllSideEffects();
1435 // If the input is a string, we know the length cannot change. 1464 // If the input is a string, we know the length cannot change.
1436 // We cannot do the same thing for non-extendable array because 1465 // We cannot do the same thing for non-extendable array because
1437 // we don't express that type yet: a mutable array might be 1466 // we don't express that type yet: a mutable array might be
1438 // extendable. 1467 // extendable.
1439 if (!inputs[1].isString(types)) setDependsOnSomething(); 1468 if (!inputs[1].isString(types)) setDependsOnPropertyStore();
1440 } else if (isSideEffectFree) { 1469 } else if (isSideEffectFree) {
1441 setUseGvn(); 1470 setUseGvn();
1442 clearAllSideEffects(); 1471 clearAllSideEffects();
1443 setDependsOnSomething(); 1472 setDependsOnSomething();
1473 } else if (selector.isGetter()) {
1474 // Getter interceptors do not have side effects.
floitsch 2012/10/01 08:40:30 I don't think this is true. o.length is an HInvoke
ngeoffray 2012/10/01 21:56:10 Right, I was only thinking about getters on primit
1475 setUseGvn();
1476 clearAllSideEffects();
1477 setDependsOnPropertyStore();
1444 } else { 1478 } else {
1445 setAllSideEffects(); 1479 setAllSideEffects();
1446 } 1480 }
1447 } 1481 }
1448 1482
1449 int typeCode() => HInstruction.INVOKE_INTERCEPTOR_TYPECODE; 1483 int typeCode() => HInstruction.INVOKE_INTERCEPTOR_TYPECODE;
1450 bool typeEquals(other) => other is HInvokeInterceptor; 1484 bool typeEquals(other) => other is HInvokeInterceptor;
1451 bool dataEquals(HInvokeInterceptor other) => selector == other.selector; 1485 bool dataEquals(HInvokeInterceptor other) => selector == other.selector;
1452 } 1486 }
1453 1487
(...skipping 14 matching lines...) Expand all
1468 : element.isAssignable(), 1502 : element.isAssignable(),
1469 super(element, <HInstruction>[receiver]); 1503 super(element, <HInstruction>[receiver]);
1470 1504
1471 HInstruction get receiver => inputs[0]; 1505 HInstruction get receiver => inputs[0];
1472 1506
1473 accept(HVisitor visitor) => visitor.visitFieldGet(this); 1507 accept(HVisitor visitor) => visitor.visitFieldGet(this);
1474 1508
1475 void prepareGvn(HTypeMap types) { 1509 void prepareGvn(HTypeMap types) {
1476 setUseGvn(); 1510 setUseGvn();
1477 clearAllSideEffects(); 1511 clearAllSideEffects();
1478 if (isAssignable) setDependsOnSomething(); 1512 if (isAssignable) {
1513 setDependsOnPropertyStore();
1514 }
1479 } 1515 }
1480 1516
1481 int typeCode() => HInstruction.FIELD_GET_TYPECODE; 1517 int typeCode() => HInstruction.FIELD_GET_TYPECODE;
1482 bool typeEquals(other) => other is HFieldGet; 1518 bool typeEquals(other) => other is HFieldGet;
1483 bool dataEquals(HFieldGet other) => element == other.element; 1519 bool dataEquals(HFieldGet other) => element == other.element;
1484 String toString() => "FieldGet $element"; 1520 String toString() => "FieldGet $element";
1485 } 1521 }
1486 1522
1487 class HFieldSet extends HFieldAccess { 1523 class HFieldSet extends HFieldAccess {
1488 HFieldSet(Element element, 1524 HFieldSet(Element element,
1489 HInstruction receiver, 1525 HInstruction receiver,
1490 HInstruction value) 1526 HInstruction value)
1491 : super(element, <HInstruction>[receiver, value]); 1527 : super(element, <HInstruction>[receiver, value]);
1492 1528
1493 HInstruction get receiver => inputs[0]; 1529 HInstruction get receiver => inputs[0];
1494 HInstruction get value => inputs[1]; 1530 HInstruction get value => inputs[1];
1495 accept(HVisitor visitor) => visitor.visitFieldSet(this); 1531 accept(HVisitor visitor) => visitor.visitFieldSet(this);
1496 1532
1497 void prepareGvn(HTypeMap types) { 1533 void prepareGvn(HTypeMap types) {
1498 // TODO(ngeoffray): implement more fine grained side effects. 1534 setChangesProperty();
1499 setAllSideEffects();
1500 } 1535 }
1501 1536
1502 bool isJsStatement(HTypeMap types) => true; 1537 bool isJsStatement(HTypeMap types) => true;
1503 String toString() => "FieldSet $element"; 1538 String toString() => "FieldSet $element";
1504 } 1539 }
1505 1540
1506 class HLocalGet extends HFieldGet { 1541 class HLocalGet extends HFieldGet {
1507 HLocalGet(Element element, HLocalValue local) : super(element, local); 1542 HLocalGet(Element element, HLocalValue local) : super(element, local);
1508 1543
1509 accept(HVisitor visitor) => visitor.visitLocalGet(this); 1544 accept(HVisitor visitor) => visitor.visitLocalGet(this);
1510 1545
1511 HLocalValue get local => inputs[0]; 1546 HLocalValue get local => inputs[0];
1512
1513 void prepareGvn(HTypeMap types) {
1514 setUseGvn();
1515 // TODO(floitsch): if the variable is not captured then it only depends
1516 // on assignments to the same variable. Otherwise we need to see if the
1517 // variable is mutated inside closures.
1518 setDependsOnSomething();
1519 }
1520 } 1547 }
1521 1548
1522 class HLocalSet extends HFieldSet { 1549 class HLocalSet extends HFieldSet {
1523 HLocalSet(Element element, HLocalValue local, HInstruction value) 1550 HLocalSet(Element element, HLocalValue local, HInstruction value)
1524 : super(element, local, value); 1551 : super(element, local, value);
1525 1552
1526 accept(HVisitor visitor) => visitor.visitLocalSet(this); 1553 accept(HVisitor visitor) => visitor.visitLocalSet(this);
1527 1554
1528 HLocalValue get local => inputs[0]; 1555 HLocalValue get local => inputs[0];
1529
1530 void prepareGvn(HTypeMap types) {
1531 // TODO(floitsch): implement more fine grained side effects.
1532 setAllSideEffects();
1533 }
1534 } 1556 }
1535 1557
1536 class HForeign extends HInstruction { 1558 class HForeign extends HInstruction {
1537 final DartString code; 1559 final DartString code;
1538 final HType foreignType; 1560 final HType foreignType;
1539 final bool _isStatement; 1561 final bool _isStatement;
1540 1562
1541 HForeign(this.code, DartString declaredType, List<HInstruction> inputs) 1563 HForeign(this.code, DartString declaredType, List<HInstruction> inputs)
1542 : foreignType = computeTypeFromDeclaredType(declaredType), 1564 : foreignType = computeTypeFromDeclaredType(declaredType),
1543 _isStatement = false, 1565 _isStatement = false,
(...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after
2371 class HStatic extends HInstruction { 2393 class HStatic extends HInstruction {
2372 final Element element; 2394 final Element element;
2373 HStatic(this.element) : super(<HInstruction>[]) { 2395 HStatic(this.element) : super(<HInstruction>[]) {
2374 assert(element !== null); 2396 assert(element !== null);
2375 assert(invariant(this, element.isDeclaration)); 2397 assert(invariant(this, element.isDeclaration));
2376 } 2398 }
2377 2399
2378 void prepareGvn(HTypeMap types) { 2400 void prepareGvn(HTypeMap types) {
2379 if (!element.isAssignable()) { 2401 if (!element.isAssignable()) {
2380 clearAllSideEffects(); 2402 clearAllSideEffects();
2381 setUseGvn(); 2403 } else {
2404 setDependsOnStatic();
2382 } 2405 }
2406 setUseGvn();
2383 } 2407 }
2384 toString() => 'static ${element.name}'; 2408 toString() => 'static ${element.name}';
2385 accept(HVisitor visitor) => visitor.visitStatic(this); 2409 accept(HVisitor visitor) => visitor.visitStatic(this);
2386 2410
2387 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode(); 2411 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode();
2388 int typeCode() => HInstruction.STATIC_TYPECODE; 2412 int typeCode() => HInstruction.STATIC_TYPECODE;
2389 bool typeEquals(other) => other is HStatic; 2413 bool typeEquals(other) => other is HStatic;
2390 bool dataEquals(HStatic other) => element == other.element; 2414 bool dataEquals(HStatic other) => element == other.element;
2391 bool isCodeMotionInvariant() => !element.isAssignable(); 2415 bool isCodeMotionInvariant() => !element.isAssignable();
2392 } 2416 }
(...skipping 19 matching lines...) Expand all
2412 class HStaticStore extends HInstruction { 2436 class HStaticStore extends HInstruction {
2413 Element element; 2437 Element element;
2414 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]); 2438 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]);
2415 toString() => 'static store ${element.name}'; 2439 toString() => 'static store ${element.name}';
2416 accept(HVisitor visitor) => visitor.visitStaticStore(this); 2440 accept(HVisitor visitor) => visitor.visitStaticStore(this);
2417 2441
2418 int typeCode() => HInstruction.STATIC_STORE_TYPECODE; 2442 int typeCode() => HInstruction.STATIC_STORE_TYPECODE;
2419 bool typeEquals(other) => other is HStaticStore; 2443 bool typeEquals(other) => other is HStaticStore;
2420 bool dataEquals(HStaticStore other) => element == other.element; 2444 bool dataEquals(HStaticStore other) => element == other.element;
2421 bool isJsStatement(HTypeMap types) => true; 2445 bool isJsStatement(HTypeMap types) => true;
2446
2447 void prepareGvn(HTypeMap types) {
2448 setChangesStatic();
2449 }
2422 } 2450 }
2423 2451
2424 class HLiteralList extends HInstruction { 2452 class HLiteralList extends HInstruction {
2425 HLiteralList(inputs) : super(inputs); 2453 HLiteralList(inputs) : super(inputs);
2426 toString() => 'literal list'; 2454 toString() => 'literal list';
2427 accept(HVisitor visitor) => visitor.visitLiteralList(this); 2455 accept(HVisitor visitor) => visitor.visitLiteralList(this);
2428 2456
2429 HType get guaranteedType => HType.EXTENDABLE_ARRAY; 2457 HType get guaranteedType => HType.EXTENDABLE_ARRAY;
2430 2458
2431 void prepareGvn(HTypeMap types) { 2459 void prepareGvn(HTypeMap types) {
2432 assert(!hasSideEffects(types)); 2460 assert(!hasSideEffects(types));
2433 } 2461 }
2434 } 2462 }
2435 2463
2436 class HIndex extends HInvokeStatic { 2464 class HIndex extends HInvokeStatic {
2437 HIndex(HStatic target, HInstruction receiver, HInstruction index) 2465 HIndex(HStatic target, HInstruction receiver, HInstruction index)
2438 : super(<HInstruction>[target, receiver, index]); 2466 : super(<HInstruction>[target, receiver, index]);
2439 toString() => 'index operator'; 2467 toString() => 'index operator';
2440 accept(HVisitor visitor) => visitor.visitIndex(this); 2468 accept(HVisitor visitor) => visitor.visitIndex(this);
2441 2469
2442 void prepareGvn(HTypeMap types) { 2470 void prepareGvn(HTypeMap types) {
2443 if (isBuiltin(types)) { 2471 if (isBuiltin(types)) {
2444 clearAllSideEffects(); 2472 clearAllSideEffects();
2473 setDependsOnIndexStore();
2474 setUseGvn();
2445 } else { 2475 } else {
2446 setAllSideEffects(); 2476 setAllSideEffects();
2447 } 2477 }
2448 } 2478 }
2449 2479
2450 HInstruction get receiver => inputs[1]; 2480 HInstruction get receiver => inputs[1];
2451 HInstruction get index => inputs[2]; 2481 HInstruction get index => inputs[2];
2452 2482
2453 HType computeDesiredTypeForNonTargetInput(HInstruction input, 2483 HType computeDesiredTypeForNonTargetInput(HInstruction input,
2454 HTypeMap types) { 2484 HTypeMap types) {
2455 if (input == receiver && 2485 if (input == receiver &&
2456 (index.isTypeUnknown(types) || index.isNumber(types))) { 2486 (index.isTypeUnknown(types) || index.isNumber(types))) {
2457 return HType.INDEXABLE_PRIMITIVE; 2487 return HType.INDEXABLE_PRIMITIVE;
2458 } 2488 }
2459 // The index should be an int when the receiver is a string or array. 2489 // 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 2490 // However it turns out that inserting an integer check in the optimized
2461 // version is cheaper than having another bailout case. This is true, 2491 // version is cheaper than having another bailout case. This is true,
2462 // because the integer check will simply throw if it fails. 2492 // because the integer check will simply throw if it fails.
2463 return HType.UNKNOWN; 2493 return HType.UNKNOWN;
2464 } 2494 }
2465 2495
2466 bool isBuiltin(HTypeMap types) 2496 bool isBuiltin(HTypeMap types)
2467 => receiver.isIndexablePrimitive(types) && index.isInteger(types); 2497 => receiver.isIndexablePrimitive(types) && index.isInteger(types);
2498
2499 int typeCode() => HInstruction.INDEX_TYPECODE;
2500 bool typeEquals(HInstruction other) => other is HIndex;
2501 bool dataEquals(HIndex other) => true;
2468 } 2502 }
2469 2503
2470 class HIndexAssign extends HInvokeStatic { 2504 class HIndexAssign extends HInvokeStatic {
2471 HIndexAssign(HStatic target, 2505 HIndexAssign(HStatic target,
2472 HInstruction receiver, 2506 HInstruction receiver,
2473 HInstruction index, 2507 HInstruction index,
2474 HInstruction value) 2508 HInstruction value)
2475 : super(<HInstruction>[target, receiver, index, value]); 2509 : super(<HInstruction>[target, receiver, index, value]);
2476 toString() => 'index assign operator'; 2510 toString() => 'index assign operator';
2477 accept(HVisitor visitor) => visitor.visitIndexAssign(this); 2511 accept(HVisitor visitor) => visitor.visitIndexAssign(this);
2478 2512
2479 HInstruction get receiver => inputs[1]; 2513 HInstruction get receiver => inputs[1];
2480 HInstruction get index => inputs[2]; 2514 HInstruction get index => inputs[2];
2481 HInstruction get value => inputs[3]; 2515 HInstruction get value => inputs[3];
2482 2516
2517 void prepareGvn(HTypeMap types) {
2518 if (isBuiltin(types)) {
2519 setChangesIndex();
2520 } else {
2521 setAllSideEffects();
2522 }
2523 }
2524
2483 // Note, that we don't have a computeTypeFromInputTypes, since [HIndexAssign] 2525 // Note, that we don't have a computeTypeFromInputTypes, since [HIndexAssign]
2484 // is never used as input. 2526 // is never used as input.
2485 2527
2486 HType computeDesiredTypeForNonTargetInput(HInstruction input, 2528 HType computeDesiredTypeForNonTargetInput(HInstruction input,
2487 HTypeMap types) { 2529 HTypeMap types) {
2488 if (input == receiver && 2530 if (input == receiver &&
2489 (index.isTypeUnknown(types) || index.isNumber(types))) { 2531 (index.isTypeUnknown(types) || index.isNumber(types))) {
2490 return HType.MUTABLE_ARRAY; 2532 return HType.MUTABLE_ARRAY;
2491 } 2533 }
2492 // The index should be an int when the receiver is a string or array. 2534 // 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; 2959 HBasicBlock get start => expression.start;
2918 HBasicBlock get end { 2960 HBasicBlock get end {
2919 // We don't create a switch block if there are no cases. 2961 // We don't create a switch block if there are no cases.
2920 assert(!statements.isEmpty()); 2962 assert(!statements.isEmpty());
2921 return statements.last().end; 2963 return statements.last().end;
2922 } 2964 }
2923 2965
2924 bool accept(HStatementInformationVisitor visitor) => 2966 bool accept(HStatementInformationVisitor visitor) =>
2925 visitor.visitSwitchInfo(this); 2967 visitor.visitSwitchInfo(this);
2926 } 2968 }
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