Changeset 171660 in webkit for trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
- Timestamp:
- Jul 27, 2014, 4:14:40 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r171648 r171660 1389 1389 1390 1390 case GetById: 1391 case GetByIdFlush: 1391 case GetByIdFlush: { 1392 1392 if (!node->prediction()) { 1393 1393 m_state.setIsValid(false); 1394 1394 break; 1395 1395 } 1396 if (isCellSpeculation(node->child1()->prediction())) {1397 // This use of onlyStructure() should be replaced by giving GetByIdStatus the ability1398 // to compute things based on a StructureSet, and then to factor ByteCodeParser's1399 // ability to generate code based on a GetByIdStatus out of ByteCodeParser so that1400 // ConstantFoldingPhase can use it.1401 // https://bugs.webkit.org/show_bug.cgi?id=1332291402 if (Structure* structure = forNode(node->child1()).m_structure.onlyStructure()) {1403 GetByIdStatus status = GetByIdStatus::computeFor(1404 m_graph.m_vm, structure,1405 m_graph.identifiers()[node->identifierNumber()]);1406 if (status.isSimple() && status.numVariants() == 1) {1407 // Assert things that we can't handle and that the computeFor() method1408 // above won't be able to return.1409 ASSERT(status[0].structureSet().size() == 1);1410 ASSERT(status[0].constantChecks().isEmpty());1411 ASSERT(!status[0].alternateBase());1396 1397 AbstractValue& value = forNode(node->child1()); 1398 if (!value.m_structure.isTop() && !value.m_structure.isClobbered() 1399 && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) { 1400 GetByIdStatus status = GetByIdStatus::computeFor( 1401 m_graph.m_vm, value.m_structure.set(), 1402 m_graph.identifiers()[node->identifierNumber()]); 1403 if (status.isSimple()) { 1404 // Figure out what the result is going to be - is it TOP, a constant, or maybe 1405 // something more subtle? 1406 AbstractValue result; 1407 for (unsigned i = status.numVariants(); i--;) { 1408 if (!status[i].specificValue()) { 1409 result.makeHeapTop(); 1410 break; 1411 } 1412 1412 1413 if (status[0].specificValue()) { 1414 if (status[0].specificValue().isCell()) { 1415 Structure* structure = status[0].specificValue().asCell()->structure(); 1416 m_graph.watchpoints().consider(structure); 1417 } 1418 setConstant(node, *m_graph.freeze(status[0].specificValue())); 1419 } else 1420 forNode(node).makeHeapTop(); 1421 filter(node->child1(), status[0].structureSet()); 1422 1413 AbstractValue thisResult; 1414 thisResult.set( 1415 m_graph, *m_graph.freeze(status[i].specificValue()), 1416 m_state.structureClobberState()); 1417 result.merge(thisResult); 1418 } 1419 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode)) 1423 1420 m_state.setFoundConstants(true); 1424 break; 1425 } 1426 } 1427 } 1421 forNode(node) = result; 1422 break; 1423 } 1424 } 1425 1428 1426 clobberWorld(node->origin.semantic, clobberLimit); 1429 1427 forNode(node).makeHeapTop(); 1430 1428 break; 1429 } 1431 1430 1432 1431 case GetArrayLength: … … 1463 1462 1464 1463 case PutStructure: 1465 case PhantomPutStructure:1466 1464 if (!forNode(node->child1()).m_structure.isClear()) { 1467 observeTransition( 1468 clobberLimit, node->transition()->previous, node->transition()->next); 1469 forNode(node->child1()).set(m_graph, node->transition()->next); 1465 if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next) 1466 m_state.setFoundConstants(true); 1467 else { 1468 observeTransition( 1469 clobberLimit, node->transition()->previous, node->transition()->next); 1470 forNode(node->child1()).changeStructure(m_graph, node->transition()->next); 1471 } 1470 1472 } 1471 1473 break; … … 1596 1598 1597 1599 case MultiGetByOffset: { 1598 AbstractValue& value = forNode(node->child1()); 1599 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this. 1600 1601 // This should just filter down the cases in MultiGetByOffset. If that results in all 1602 // cases having the same offset then we should strength reduce it to a CheckStructure + 1603 // GetByOffset. 1604 // https://bugs.webkit.org/show_bug.cgi?id=133229 1605 if (Structure* structure = value.m_structure.onlyStructure()) { 1606 bool done = false; 1607 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) { 1608 const GetByIdVariant& variant = node->multiGetByOffsetData().variants[i]; 1609 if (!variant.structureSet().contains(structure)) 1610 continue; 1611 1612 if (variant.alternateBase()) 1613 break; 1614 1615 filter(value, structure); 1616 forNode(node).makeHeapTop(); 1617 m_state.setFoundConstants(true); 1618 done = true; 1619 break; 1620 } 1621 if (done) 1622 break; 1623 } 1624 1625 StructureSet set; 1626 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) 1627 set.merge(node->multiGetByOffsetData().variants[i].structureSet()); 1628 1629 filter(node->child1(), set); 1630 forNode(node).makeHeapTop(); 1600 // This code will filter the base value in a manner that is possibly different (either more 1601 // or less precise) than the way it would be filtered if this was strength-reduced to a 1602 // CheckStructure. This is fine. It's legal for different passes over the code to prove 1603 // different things about the code, so long as all of them are sound. That even includes 1604 // one guy proving that code should never execute (due to a contradiction) and another guy 1605 // not finding that contradiction. If someone ever proved that there would be a 1606 // contradiction then there must always be a contradiction even if subsequent passes don't 1607 // realize it. This is the case here. 1608 1609 // Ordinarily you have to be careful with calling setFoundConstants() 1610 // because of the effect on compile times, but this node is FTL-only. 1611 m_state.setFoundConstants(true); 1612 1613 AbstractValue base = forNode(node->child1()); 1614 StructureSet baseSet; 1615 AbstractValue result; 1616 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) { 1617 GetByIdVariant& variant = node->multiGetByOffsetData().variants[i]; 1618 StructureSet set = variant.structureSet(); 1619 set.filter(base); 1620 if (set.isEmpty()) 1621 continue; 1622 baseSet.merge(set); 1623 if (!variant.specificValue()) { 1624 result.makeHeapTop(); 1625 continue; 1626 } 1627 AbstractValue thisResult; 1628 thisResult.set( 1629 m_graph, 1630 *m_graph.freeze(variant.specificValue()), 1631 m_state.structureClobberState()); 1632 result.merge(thisResult); 1633 } 1634 1635 if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction) 1636 m_state.setIsValid(false); 1637 1638 forNode(node) = result; 1631 1639 break; 1632 1640 } … … 1637 1645 1638 1646 case MultiPutByOffset: { 1639 AbstractValue& value = forNode(node->child1());1640 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.1641 1642 // This should just filter down the cases in MultiPutByOffset. If that results in either1643 // one case, or nothing but replace cases and they have the same offset, then we should1644 // just strength reduce it to the appropriate combination of CheckStructure,1645 // [Re]AllocatePropertyStorage, PutStructure, and PutByOffset.1646 // https://bugs.webkit.org/show_bug.cgi?id=1332291647 if (Structure* structure = value.m_structure.onlyStructure()) {1648 bool done = false;1649 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {1650 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];1651 if (variant.oldStructure() != structure)1652 continue;1653 1654 if (variant.kind() == PutByIdVariant::Replace) {1655 filter(node->child1(), structure);1656 m_state.setFoundConstants(true);1657 done = true;1658 break;1659 }1660 1661 ASSERT(variant.kind() == PutByIdVariant::Transition);1662 clobberStructures(clobberLimit);1663 forNode(node->child1()).set(m_graph, variant.newStructure());1664 m_state.setFoundConstants(true);1665 done = true;1666 break;1667 }1668 if (done)1669 break;1670 }1671 1672 StructureSet oldSet;1673 1647 StructureSet newSet; 1674 1648 TransitionVector transitions; 1649 1650 // Ordinarily you have to be careful with calling setFoundConstants() 1651 // because of the effect on compile times, but this node is FTL-only. 1652 m_state.setFoundConstants(true); 1653 1654 AbstractValue base = forNode(node->child1()); 1655 1675 1656 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) { 1676 1657 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i]; 1677 oldSet.add(variant.oldStructure()); 1658 StructureSet thisSet = variant.oldStructure(); 1659 thisSet.filter(base); 1660 if (thisSet.isEmpty()) 1661 continue; 1678 1662 if (variant.kind() == PutByIdVariant::Transition) { 1679 transitions.append(Transition(variant.oldStructure(), variant.newStructure())); 1663 if (thisSet.onlyStructure() != variant.newStructure()) { 1664 transitions.append( 1665 Transition(variant.oldStructureForTransition(), variant.newStructure())); 1666 } // else this is really a replace. 1680 1667 newSet.add(variant.newStructure()); 1681 1668 } else { 1682 1669 ASSERT(variant.kind() == PutByIdVariant::Replace); 1683 newSet.add(variant.oldStructure()); 1684 } 1685 } 1686 1687 filter(node->child1(), oldSet); 1670 newSet.merge(thisSet); 1671 } 1672 } 1673 1688 1674 observeTransitions(clobberLimit, transitions); 1689 forNode(node->child1()).set(m_graph, newSet); 1675 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction) 1676 m_state.setIsValid(false); 1690 1677 break; 1691 1678 } … … 1716 1703 case PutById: 1717 1704 case PutByIdFlush: 1718 case PutByIdDirect: 1719 // This use of onlyStructure() should be replaced by giving PutByIdStatus the ability 1720 // to compute things based on a StructureSet, and then to factor ByteCodeParser's 1721 // ability to generate code based on a PutByIdStatus out of ByteCodeParser so that 1722 // ConstantFoldingPhase can use it. 1723 // https://bugs.webkit.org/show_bug.cgi?id=133229 1724 if (Structure* structure = forNode(node->child1()).m_structure.onlyStructure()) { 1705 case PutByIdDirect: { 1706 AbstractValue& value = forNode(node->child1()); 1707 if (!value.m_structure.isTop() && !value.m_structure.isClobbered()) { 1725 1708 PutByIdStatus status = PutByIdStatus::computeFor( 1726 1709 m_graph.m_vm, 1727 1710 m_graph.globalObjectFor(node->origin.semantic), 1728 structure,1711 value.m_structure.set(), 1729 1712 m_graph.identifiers()[node->identifierNumber()], 1730 1713 node->op() == PutByIdDirect); 1731 if (status.isSimple() && status.numVariants() == 1) { 1732 if (status[0].kind() == PutByIdVariant::Replace) { 1733 filter(node->child1(), structure); 1714 1715 if (status.isSimple()) { 1716 StructureSet newSet; 1717 TransitionVector transitions; 1718 1719 for (unsigned i = status.numVariants(); i--;) { 1720 const PutByIdVariant& variant = status[i]; 1721 if (variant.kind() == PutByIdVariant::Transition) { 1722 transitions.append( 1723 Transition( 1724 variant.oldStructureForTransition(), variant.newStructure())); 1725 m_graph.watchpoints().consider(variant.newStructure()); 1726 newSet.add(variant.newStructure()); 1727 } else { 1728 ASSERT(variant.kind() == PutByIdVariant::Replace); 1729 newSet.merge(variant.oldStructure()); 1730 } 1731 } 1732 1733 if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode)) 1734 1734 m_state.setFoundConstants(true); 1735 break; 1736 } 1737 if (status[0].kind() == PutByIdVariant::Transition 1738 && structure->transitionWatchpointSetHasBeenInvalidated()) { 1739 m_graph.watchpoints().consider(status[0].newStructure()); 1740 clobberStructures(clobberLimit); 1741 forNode(node->child1()).set(m_graph, status[0].newStructure()); 1742 m_state.setFoundConstants(true); 1743 break; 1744 } 1745 } 1746 } 1735 1736 observeTransitions(clobberLimit, transitions); 1737 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction) 1738 m_state.setIsValid(false); 1739 break; 1740 } 1741 } 1742 1747 1743 clobberWorld(node->origin.semantic, clobberLimit); 1748 1744 break; 1745 } 1749 1746 1750 1747 case In: … … 1949 1946 AbstractValue::TransitionObserver transitionObserver(from, to); 1950 1947 forAllValues(clobberLimit, transitionObserver); 1951 setDidClobber(); 1948 1949 ASSERT(!from->dfgShouldWatch()); // We don't need to claim to be in a clobbered state because 'from' was never watchable (during the time we were compiling), hence no constants ever introduced into the DFG IR that ever had a watchable structure would ever have the same structure as from. 1952 1950 } 1953 1951 … … 1958 1956 AbstractValue::TransitionsObserver transitionsObserver(vector); 1959 1957 forAllValues(clobberLimit, transitionsObserver); 1960 setDidClobber(); 1958 1959 if (!ASSERT_DISABLED) { 1960 // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable. 1961 for (unsigned i = vector.size(); i--;) 1962 ASSERT(!vector[i].previous->dfgShouldWatch()); 1963 } 1961 1964 } 1962 1965
Note:
See TracChangeset
for help on using the changeset viewer.