Changeset 171660 in webkit for trunk/Source/JavaScriptCore/dfg
- Timestamp:
- Jul 27, 2014, 4:14:40 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore/dfg
- Files:
-
- 22 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 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
r171648 r171660 192 192 } 193 193 194 FiltrationResult AbstractValue::changeStructure(Graph& graph, const StructureSet& other) 195 { 196 m_type &= other.speculationFromStructures(); 197 m_arrayModes = other.arrayModesFromStructures(); 198 m_structure = other; 199 200 filterValueByType(); 201 202 return normalizeClarity(graph); 203 } 204 194 205 FiltrationResult AbstractValue::filterArrayModes(ArrayModes arrayModes) 195 206 { … … 242 253 } 243 254 255 bool AbstractValue::contains(Structure* structure) const 256 { 257 return couldBeType(speculationFromStructure(structure)) 258 && (m_arrayModes & arrayModeFromStructure(structure)) 259 && m_structure.contains(structure); 260 } 261 244 262 FiltrationResult AbstractValue::filter(const AbstractValue& other) 245 263 { -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h
r171648 r171660 268 268 } 269 269 270 bool couldBeType(SpeculatedType desiredType) 270 bool couldBeType(SpeculatedType desiredType) const 271 271 { 272 272 return !!(m_type & desiredType); 273 273 } 274 274 275 bool isType(SpeculatedType desiredType) 275 bool isType(SpeculatedType desiredType) const 276 276 { 277 277 return !(m_type & ~desiredType); … … 283 283 FiltrationResult filterByValue(const FrozenValue& value); 284 284 FiltrationResult filter(const AbstractValue&); 285 286 FiltrationResult changeStructure(Graph&, const StructureSet&); 287 288 bool contains(Structure*) const; 285 289 286 290 bool validate(JSValue value) const -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r171648 r171660 1892 1892 emitChecks(variant.constantChecks()); 1893 1893 1894 ASSERT(variant.oldStructure ()->transitionWatchpointSetHasBeenInvalidated());1894 ASSERT(variant.oldStructureForTransition()->transitionWatchpointSetHasBeenInvalidated()); 1895 1895 1896 1896 Node* propertyStorage; 1897 1897 Transition* transition = m_graph.m_transitions.add( 1898 variant.oldStructure(), variant.newStructure()); 1899 1900 if (variant.oldStructure()->outOfLineCapacity() 1901 != variant.newStructure()->outOfLineCapacity()) { 1898 variant.oldStructureForTransition(), variant.newStructure()); 1899 1900 if (variant.reallocatesStorage()) { 1902 1901 1903 1902 // If we're growing the property storage then it must be because we're … … 1905 1904 ASSERT(!isInlineOffset(variant.offset())); 1906 1905 1907 if (!variant.oldStructure ()->outOfLineCapacity()) {1906 if (!variant.oldStructureForTransition()->outOfLineCapacity()) { 1908 1907 propertyStorage = addToGraph( 1909 1908 AllocatePropertyStorage, OpInfo(transition), base); … … 2037 2036 if (op1->op() != ToThis) { 2038 2037 Structure* cachedStructure = currentInstruction[2].u.structure.get(); 2039 if (!cachedStructure 2038 if (currentInstruction[2].u.toThisStatus != ToThisOK 2039 || !cachedStructure 2040 2040 || cachedStructure->classInfo()->methodTable.toThis != JSObject::info()->methodTable.toThis 2041 2041 || m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex) … … 2887 2887 SpeculatedType prediction = getPrediction(); 2888 2888 GetByIdStatus status = GetByIdStatus::computeFor(*m_vm, structure, uid); 2889 if (status.state() != GetByIdStatus::Simple || status.numVariants() != 1) { 2889 if (status.state() != GetByIdStatus::Simple 2890 || status.numVariants() != 1 2891 || status[0].structureSet().size() != 1) { 2890 2892 set(VirtualRegister(dst), addToGraph(GetByIdFlush, OpInfo(identifierNumber), OpInfo(prediction), get(VirtualRegister(scope)))); 2891 2893 break; … … 2972 2974 case GlobalPropertyWithVarInjectionChecks: { 2973 2975 PutByIdStatus status = PutByIdStatus::computeFor(*m_vm, globalObject, structure, uid, false); 2974 if (status.numVariants() != 1 || status[0].kind() != PutByIdVariant::Replace) { 2976 if (status.numVariants() != 1 2977 || status[0].kind() != PutByIdVariant::Replace 2978 || status[0].structure().size() != 1) { 2975 2979 addToGraph(PutById, OpInfo(identifierNumber), get(VirtualRegister(scope)), get(VirtualRegister(value))); 2976 2980 break; 2977 2981 } 2978 Node* base = cellConstantWithStructureCheck(globalObject, status[0].structure()); 2982 ASSERT(status[0].structure().onlyStructure() == structure); 2983 Node* base = cellConstantWithStructureCheck(globalObject, structure); 2979 2984 addToGraph(Phantom, get(VirtualRegister(scope))); 2980 2985 handlePutByOffset(base, identifierNumber, static_cast<PropertyOffset>(operand), get(VirtualRegister(value))); -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r171648 r171660 441 441 442 442 case PutStructure: 443 case PhantomPutStructure:444 443 write(JSCell_structureID); 445 444 write(JSCell_typeInfoType); -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r171648 r171660 133 133 } 134 134 135 case PutStructure: { 136 if (m_state.forNode(node->child1()).m_structure.onlyStructure() != node->transition()->next) 137 break; 138 139 node->convertToPhantom(); 140 eliminated = true; 141 break; 142 } 143 135 144 case CheckFunction: { 136 145 if (m_state.forNode(node->child1()).value() != node->function()->value()) … … 155 164 156 165 case MultiGetByOffset: { 157 Edge childEdge = node->child1();158 Node* child = childEdge.node();166 Edge baseEdge = node->child1(); 167 Node* base = baseEdge.node(); 159 168 MultiGetByOffsetData& data = node->multiGetByOffsetData(); 160 169 161 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 162 if (!structure) 163 break; 164 165 for (unsigned i = data.variants.size(); i--;) { 166 const GetByIdVariant& variant = data.variants[i]; 167 if (!variant.structureSet().contains(structure)) 170 // First prune the variants, then check if the MultiGetByOffset can be 171 // strength-reduced to a GetByOffset. 172 173 AbstractValue baseValue = m_state.forNode(base); 174 175 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before. 176 eliminated = true; // Don't allow the default constant folder to do things to this. 177 178 for (unsigned i = 0; i < data.variants.size(); ++i) { 179 GetByIdVariant& variant = data.variants[i]; 180 variant.structureSet().filter(baseValue); 181 if (variant.structureSet().isEmpty()) { 182 data.variants[i--] = data.variants.last(); 183 data.variants.removeLast(); 184 } 185 } 186 187 if (data.variants.size() != 1) 188 break; 189 190 emitGetByOffset( 191 indexInBlock, node, baseValue, data.variants[0], data.identifierNumber); 192 break; 193 } 194 195 case MultiPutByOffset: { 196 Edge baseEdge = node->child1(); 197 Node* base = baseEdge.node(); 198 MultiPutByOffsetData& data = node->multiPutByOffsetData(); 199 200 AbstractValue baseValue = m_state.forNode(base); 201 202 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before. 203 eliminated = true; // Don't allow the default constant folder to do things to this. 204 205 206 for (unsigned i = 0; i < data.variants.size(); ++i) { 207 PutByIdVariant& variant = data.variants[i]; 208 variant.oldStructure().filter(baseValue); 209 210 if (variant.oldStructure().isEmpty()) { 211 data.variants[i--] = data.variants.last(); 212 data.variants.removeLast(); 168 213 continue; 214 } 169 215 170 if (variant.alternateBase()) 171 break; 172 173 emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber); 174 eliminated = true; 175 break; 176 } 177 break; 178 } 179 180 case MultiPutByOffset: { 181 Edge childEdge = node->child1(); 182 Node* child = childEdge.node(); 183 MultiPutByOffsetData& data = node->multiPutByOffsetData(); 184 185 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 186 if (!structure) 187 break; 188 189 for (unsigned i = data.variants.size(); i--;) { 190 const PutByIdVariant& variant = data.variants[i]; 191 if (variant.oldStructure() != structure) 192 continue; 193 194 emitPutByOffset(indexInBlock, node, structure, variant, data.identifierNumber); 195 eliminated = true; 196 break; 197 } 216 if (variant.kind() == PutByIdVariant::Transition 217 && variant.oldStructure().onlyStructure() == variant.newStructure()) { 218 variant = PutByIdVariant::replace( 219 variant.oldStructure(), 220 variant.offset()); 221 } 222 } 223 224 if (data.variants.size() != 1) 225 break; 226 227 emitPutByOffset( 228 indexInBlock, node, baseValue, data.variants[0], data.identifierNumber); 198 229 break; 199 230 } … … 205 236 unsigned identifierNumber = node->identifierNumber(); 206 237 207 if (childEdge.useKind() != CellUse) 208 break; 209 210 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 211 if (!structure) 212 break; 213 238 AbstractValue baseValue = m_state.forNode(child); 239 240 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before. 241 eliminated = true; // Don't allow the default constant folder to do things to this. 242 243 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered() 244 || (node->child1().useKind() == UntypedUse || (baseValue.m_type & ~SpecCell))) 245 break; 246 214 247 GetByIdStatus status = GetByIdStatus::computeFor( 215 vm(), structure, m_graph.identifiers()[identifierNumber]); 216 217 if (!status.isSimple() || status.numVariants() != 1 || 218 !status[0].constantChecks().isEmpty() || status[0].alternateBase()) { 219 // FIXME: We could handle prototype cases. 220 // https://bugs.webkit.org/show_bug.cgi?id=110386 221 break; 222 } 223 224 emitGetByOffset(indexInBlock, node, structure, status[0], identifierNumber); 225 eliminated = true; 248 vm(), baseValue.m_structure.set(), m_graph.identifiers()[identifierNumber]); 249 if (!status.isSimple()) 250 break; 251 252 for (unsigned i = status.numVariants(); i--;) { 253 if (!status[i].constantChecks().isEmpty() 254 || status[i].alternateBase()) { 255 // FIXME: We could handle prototype cases. 256 // https://bugs.webkit.org/show_bug.cgi?id=110386 257 break; 258 } 259 } 260 261 if (status.numVariants() == 1) { 262 emitGetByOffset(indexInBlock, node, baseValue, status[0], identifierNumber); 263 break; 264 } 265 266 if (!isFTL(m_graph.m_plan.mode)) 267 break; 268 269 MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add(); 270 data->variants = status.variants(); 271 data->identifierNumber = identifierNumber; 272 node->convertToMultiGetByOffset(data); 226 273 break; 227 274 } 228 275 229 276 case PutById: 230 case PutByIdDirect: { 277 case PutByIdDirect: 278 case PutByIdFlush: { 231 279 NodeOrigin origin = node->origin; 232 280 Edge childEdge = node->child1(); … … 236 284 ASSERT(childEdge.useKind() == CellUse); 237 285 238 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 239 if (!structure) 286 AbstractValue baseValue = m_state.forNode(child); 287 288 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before. 289 eliminated = true; // Don't allow the default constant folder to do things to this. 290 291 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()) 240 292 break; 241 293 … … 243 295 vm(), 244 296 m_graph.globalObjectFor(origin.semantic), 245 structure,297 baseValue.m_structure.set(), 246 298 m_graph.identifiers()[identifierNumber], 247 299 node->op() == PutByIdDirect); … … 249 301 if (!status.isSimple()) 250 302 break; 251 if (status.numVariants() != 1) 252 break; 253 254 emitPutByOffset(indexInBlock, node, structure, status[0], identifierNumber); 255 eliminated = true; 303 304 for (unsigned i = status.numVariants(); i--;) 305 addChecks(origin, indexInBlock, status[i].constantChecks()); 306 307 if (status.numVariants() == 1) { 308 emitPutByOffset(indexInBlock, node, baseValue, status[0], identifierNumber); 309 break; 310 } 311 312 if (!isFTL(m_graph.m_plan.mode)) 313 break; 314 315 MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add(); 316 data->variants = status.variants(); 317 data->identifierNumber = identifierNumber; 318 node->convertToMultiPutByOffset(data); 256 319 break; 257 320 } … … 344 407 } 345 408 346 void emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant& variant, unsigned identifierNumber)409 void emitGetByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const GetByIdVariant& variant, unsigned identifierNumber) 347 410 { 348 411 NodeOrigin origin = node->origin; … … 350 413 Node* child = childEdge.node(); 351 414 352 bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell; 353 354 ASSERT(!variant.alternateBase()); 355 ASSERT_UNUSED(structure, variant.structureSet().contains(structure)); 356 357 // Now before we do anything else, push the CFA forward over the GetById 358 // and make sure we signal to the loop that it should continue and not 359 // do any eliminations. 360 m_interpreter.execute(indexInBlock); 361 362 if (needsCellCheck) { 363 m_insertionSet.insertNode( 364 indexInBlock, SpecNone, Phantom, origin, childEdge); 365 } 415 addBaseCheck(indexInBlock, node, baseValue, variant.structureSet()); 366 416 367 417 if (variant.specificValue()) { … … 370 420 } 371 421 372 childEdge.setUseKind(KnownCellUse); 422 if (variant.alternateBase()) { 423 child = m_insertionSet.insertConstant(indexInBlock, origin, variant.alternateBase()); 424 childEdge = Edge(child, KnownCellUse); 425 } else 426 childEdge.setUseKind(KnownCellUse); 373 427 374 428 Edge propertyStorage; … … 389 443 } 390 444 391 void emitPutByOffset(unsigned indexInBlock, Node* node, Structure* structure, const PutByIdVariant& variant, unsigned identifierNumber)445 void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByIdVariant& variant, unsigned identifierNumber) 392 446 { 393 447 NodeOrigin origin = node->origin; 394 448 Edge childEdge = node->child1(); 395 Node* child = childEdge.node(); 396 397 ASSERT(variant.oldStructure() == structure); 398 399 bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell; 400 401 // Now before we do anything else, push the CFA forward over the PutById 402 // and make sure we signal to the loop that it should continue and not 403 // do any eliminations. 404 m_interpreter.execute(indexInBlock); 405 406 if (needsCellCheck) { 407 m_insertionSet.insertNode( 408 indexInBlock, SpecNone, Phantom, origin, childEdge); 409 } 449 450 addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure()); 410 451 411 452 childEdge.setUseKind(KnownCellUse); … … 413 454 Transition* transition = 0; 414 455 if (variant.kind() == PutByIdVariant::Transition) { 415 transition = m_graph.m_transitions.add(structure, variant.newStructure()); 416 417 for (unsigned i = 0; i < variant.constantChecks().size(); ++i) { 418 addStructureTransitionCheck( 419 origin, indexInBlock, 420 variant.constantChecks()[i].constant(), 421 variant.constantChecks()[i].structure()); 422 } 456 transition = m_graph.m_transitions.add( 457 variant.oldStructureForTransition(), variant.newStructure()); 423 458 } 424 459 … … 427 462 if (isInlineOffset(variant.offset())) 428 463 propertyStorage = childEdge; 429 else if ( 430 variant.kind() == PutByIdVariant::Replace 431 || structure->outOfLineCapacity() == variant.newStructure()->outOfLineCapacity()) { 464 else if (!variant.reallocatesStorage()) { 432 465 propertyStorage = Edge(m_insertionSet.insertNode( 433 466 indexInBlock, SpecNone, GetButterfly, origin, childEdge)); 434 } else if (! structure->outOfLineCapacity()) {467 } else if (!variant.oldStructureForTransition()->outOfLineCapacity()) { 435 468 ASSERT(variant.newStructure()->outOfLineCapacity()); 436 469 ASSERT(!isInlineOffset(variant.offset())); … … 441 474 propertyStorage = Edge(allocatePropertyStorage); 442 475 } else { 443 ASSERT( structure->outOfLineCapacity());444 ASSERT(variant.newStructure()->outOfLineCapacity() > structure->outOfLineCapacity());476 ASSERT(variant.oldStructureForTransition()->outOfLineCapacity()); 477 ASSERT(variant.newStructure()->outOfLineCapacity() > variant.oldStructureForTransition()->outOfLineCapacity()); 445 478 ASSERT(!isInlineOffset(variant.offset())); 446 479 … … 470 503 m_graph.m_storageAccessData.append(storageAccessData); 471 504 } 505 506 void addBaseCheck( 507 unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const StructureSet& set) 508 { 509 if (!baseValue.m_structure.isSubsetOf(set)) { 510 // Arises when we prune MultiGetByOffset. We could have a 511 // MultiGetByOffset with a single variant that checks for structure S, 512 // and the input has structures S and T, for example. 513 m_insertionSet.insertNode( 514 indexInBlock, SpecNone, CheckStructure, node->origin, 515 OpInfo(m_graph.addStructureSet(set)), node->child1()); 516 return; 517 } 518 519 if (baseValue.m_type & ~SpecCell) { 520 m_insertionSet.insertNode( 521 indexInBlock, SpecNone, Phantom, node->origin, node->child1()); 522 } 523 } 524 525 void addChecks( 526 NodeOrigin origin, unsigned indexInBlock, const ConstantStructureCheckVector& checks) 527 { 528 for (unsigned i = 0; i < checks.size(); ++i) { 529 addStructureTransitionCheck( 530 origin, indexInBlock, checks[i].constant(), checks[i].structure()); 531 } 532 } 472 533 473 534 void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell, Structure* structure) -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r171648 r171660 187 187 case PutByValAlias: 188 188 case PutStructure: 189 case PhantomPutStructure:190 189 case GetByOffset: 191 190 case GetGetterSetterByOffset: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r171648 r171660 981 981 case Upsilon: 982 982 case GetArgument: 983 case PhantomPutStructure:984 983 case GetIndexedPropertyStorage: 985 984 case GetTypedArrayByteOffset: -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r171648 r171660 890 890 891 891 case PutStructure: 892 case PhantomPutStructure:893 892 case AllocatePropertyStorage: 894 893 case ReallocatePropertyStorage: … … 918 917 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) { 919 918 PutByIdVariant& variant = node->multiPutByOffsetData().variants[i]; 920 visitor.appendUnbarrieredReadOnlyPointer(variant.oldStructure()); 919 const StructureSet& set = variant.oldStructure(); 920 for (unsigned j = set.size(); j--;) 921 visitor.appendUnbarrieredReadOnlyPointer(set[j]); 921 922 if (variant.kind() == PutByIdVariant::Transition) 922 923 visitor.appendUnbarrieredReadOnlyPointer(variant.newStructure()); … … 952 953 FrozenValue* Graph::freezeStrong(JSValue value) 953 954 { 954 FrozenValue* result = freeze (value);955 FrozenValue* result = freezeFragile(value); 955 956 result->strengthenTo(StrongValue); 956 957 return result; -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r171648 r171660 148 148 149 149 FrozenValue* freezeFragile(JSValue value); 150 FrozenValue* freeze(JSValue value); // We use weak freezing by default. 151 FrozenValue* freezeStrong(JSValue value); // Shorthand for freeze (value)->markStrongly().150 FrozenValue* freeze(JSValue value); // We use weak freezing by default. Shorthand for freezeFragile(value)->strengthenTo(WeakValue); 151 FrozenValue* freezeStrong(JSValue value); // Shorthand for freezeFragile(value)->strengthenTo(StrongValue). 152 152 153 153 void convertToConstant(Node* node, FrozenValue* value); -
trunk/Source/JavaScriptCore/dfg/DFGNode.cpp
r171648 r171660 38 38 { 39 39 for (unsigned i = variants.size(); i--;) { 40 if (variants[i]. kind() == PutByIdVariant::Transition)40 if (variants[i].writesStructures()) 41 41 return true; 42 42 } … … 47 47 { 48 48 for (unsigned i = variants.size(); i--;) { 49 if (variants[i].kind() != PutByIdVariant::Transition) 50 continue; 51 52 if (variants[i].oldStructure()->outOfLineCapacity() == 53 variants[i].newStructure()->outOfLineCapacity()) 54 continue; 55 56 return true; 49 if (variants[i].reallocatesStorage()) 50 return true; 57 51 } 58 52 return false; -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r171648 r171660 459 459 } 460 460 461 void convertToMultiGetByOffset(MultiGetByOffsetData* data) 462 { 463 ASSERT(m_op == GetById || m_op == GetByIdFlush); 464 m_opInfo = bitwise_cast<intptr_t>(data); 465 child1().setUseKind(CellUse); 466 m_op = MultiGetByOffset; 467 m_flags &= ~NodeClobbersWorld; 468 } 469 461 470 void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage) 462 471 { 463 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == MultiPutByOffset);472 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op == MultiPutByOffset); 464 473 m_opInfo = storageAccessDataIndex; 465 474 children.setChild3(children.child2()); … … 467 476 children.setChild1(storage); 468 477 m_op = PutByOffset; 478 m_flags &= ~NodeClobbersWorld; 479 } 480 481 void convertToMultiPutByOffset(MultiPutByOffsetData* data) 482 { 483 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush); 484 m_opInfo = bitwise_cast<intptr_t>(data); 485 m_op = MultiPutByOffset; 469 486 m_flags &= ~NodeClobbersWorld; 470 487 } … … 1108 1125 switch (op()) { 1109 1126 case PutStructure: 1110 case PhantomPutStructure:1111 1127 case AllocatePropertyStorage: 1112 1128 case ReallocatePropertyStorage: -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r171648 r171660 156 156 macro(CheckExecutable, NodeMustGenerate) \ 157 157 macro(PutStructure, NodeMustGenerate) \ 158 macro(PhantomPutStructure, NodeMustGenerate) \159 158 macro(AllocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \ 160 159 macro(ReallocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \ -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r171648 r171660 541 541 case GetMyArgumentsLength: 542 542 case GetMyArgumentByVal: 543 case PhantomPutStructure:544 543 case PhantomArguments: 545 544 case CheckArray: -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r171648 r171660 284 284 285 285 case PutStructure: 286 case PhantomPutStructure:287 286 case AllocatePropertyStorage: 288 287 case ReallocatePropertyStorage: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r171648 r171660 344 344 ASSERT(info.gpr() == source); 345 345 if (node->hasConstant()) { 346 DFG_ASSERT(m_jit.graph(), m_currentNode, node->isCellConstant());347 346 node->asCell(); // To get the assertion. 348 347 fillAction = SetCellConstant; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r171648 r171660 868 868 VirtualRegister virtualRegister = edge->virtualRegister(); 869 869 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 870 871 if (edge->hasConstant() && !edge->isCellConstant()) {872 // Protect the silent spill/fill logic by failing early. If we "speculate" on873 // the constant then the silent filler may think that we have a cell and a874 // constant, so it will try to fill this as an cell constant. Bad things will875 // happen.876 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);877 return allocate();878 }879 870 880 871 switch (info.registerFormat()) { … … 888 879 JSValue jsValue = edge->asJSValue(); 889 880 GPRReg gpr = allocate(); 890 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 891 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr); 892 info.fillCell(*m_stream, gpr); 881 if (jsValue.isCell()) { 882 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 883 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr); 884 info.fillCell(*m_stream, gpr); 885 return gpr; 886 } 887 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 893 888 return gpr; 894 889 } … … 3740 3735 } 3741 3736 3742 case PhantomPutStructure: {3743 ASSERT(isKnownCell(node->child1().node()));3744 m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);3745 noResult(node);3746 break;3747 }3748 3749 3737 case PutStructure: { 3750 3738 Structure* oldStructure = node->transition()->previous; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r171648 r171660 98 98 default: 99 99 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 100 RELEASE_ASSERT(spillFormat & DataFormatJS);100 DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat & DataFormatJS); 101 101 break; 102 102 } … … 138 138 case DataFormatInt52: 139 139 // this type currently never occurs 140 RELEASE_ASSERT_NOT_REACHED();140 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format"); 141 141 142 142 default: 143 RELEASE_ASSERT_NOT_REACHED();143 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format"); 144 144 return InvalidGPRReg; 145 145 } … … 312 312 Node* branchNode = m_block->at(branchIndexInBlock); 313 313 314 RELEASE_ASSERT(node->adjustedRefCount() == 1);314 DFG_ASSERT(m_jit.graph(), node, node->adjustedRefCount() == 1); 315 315 316 316 nonSpeculativePeepholeBranchNull(operand, branchNode, invert); … … 629 629 bool isCall = node->op() == Call; 630 630 if (!isCall) 631 RELEASE_ASSERT(node->op() == Construct);632 631 DFG_ASSERT(m_jit.graph(), node, node->op() == Construct); 632 633 633 // For constructors, the this argument is not passed but we have to make space 634 634 // for it. … … 742 742 DataFormat spillFormat = info.spillFormat(); 743 743 744 RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);744 DFG_ASSERT(m_jit.graph(), m_currentNode, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32); 745 745 746 746 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); … … 772 772 773 773 case DataFormatJS: { 774 RELEASE_ASSERT(!(type & SpecInt52));774 DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52)); 775 775 // Check the value is an integer. 776 776 GPRReg gpr = info.gpr(); … … 835 835 case DataFormatInt52: 836 836 case DataFormatStrictInt52: 837 RELEASE_ASSERT_NOT_REACHED();837 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format"); 838 838 839 839 default: 840 RELEASE_ASSERT_NOT_REACHED();840 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format"); 841 841 return InvalidGPRReg; 842 842 } … … 855 855 DataFormat mustBeDataFormatInt32; 856 856 GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32); 857 RELEASE_ASSERT(mustBeDataFormatInt32 == DataFormatInt32);857 DFG_ASSERT(m_jit.graph(), m_currentNode, mustBeDataFormatInt32 == DataFormatInt32); 858 858 return result; 859 859 } … … 890 890 DataFormat spillFormat = info.spillFormat(); 891 891 892 RELEASE_ASSERT(spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);892 DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52); 893 893 894 894 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); … … 942 942 943 943 default: 944 RELEASE_ASSERT_NOT_REACHED();944 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format"); 945 945 return InvalidGPRReg; 946 946 } … … 973 973 974 974 DataFormat spillFormat = info.spillFormat(); 975 RELEASE_ASSERT(spillFormat == DataFormatDouble);975 DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble); 976 976 FPRReg fpr = fprAllocate(); 977 977 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr); … … 981 981 } 982 982 983 RELEASE_ASSERT(info.registerFormat() == DataFormatDouble);983 DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble); 984 984 FPRReg fpr = info.fpr(); 985 985 m_fprs.lock(fpr); … … 996 996 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 997 997 998 if (edge->hasConstant() && !edge->isCellConstant()) {999 // Better to fail early on constants.1000 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);1001 return allocate();1002 }1003 1004 998 switch (info.registerFormat()) { 1005 999 case DataFormatNone: { … … 1008 1002 if (edge->hasConstant()) { 1009 1003 JSValue jsValue = edge->asJSValue(); 1010 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 1011 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr); 1012 info.fillJSValue(*m_stream, gpr, DataFormatJSCell); 1004 if (jsValue.isCell()) { 1005 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 1006 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr); 1007 info.fillJSValue(*m_stream, gpr, DataFormatJSCell); 1008 return gpr; 1009 } 1010 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1013 1011 return gpr; 1014 1012 } … … 1063 1061 case DataFormatInt52: 1064 1062 case DataFormatStrictInt52: 1065 RELEASE_ASSERT_NOT_REACHED();1063 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format"); 1066 1064 1067 1065 default: 1068 RELEASE_ASSERT_NOT_REACHED();1066 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format"); 1069 1067 return InvalidGPRReg; 1070 1068 } … … 1099 1097 return gpr; 1100 1098 } 1101 RELEASE_ASSERT(info.spillFormat() & DataFormatJS);1099 DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS); 1102 1100 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 1103 1101 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); … … 1144 1142 case DataFormatInt52: 1145 1143 case DataFormatStrictInt52: 1146 RELEASE_ASSERT_NOT_REACHED();1144 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format"); 1147 1145 1148 1146 default: 1149 RELEASE_ASSERT_NOT_REACHED();1147 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format"); 1150 1148 return InvalidGPRReg; 1151 1149 } … … 1611 1609 1612 1610 default: 1613 RELEASE_ASSERT_NOT_REACHED();1611 DFG_CRASH(m_jit.graph(), node, "Bad use kind"); 1614 1612 break; 1615 1613 } … … 1766 1764 1767 1765 default: 1768 RELEASE_ASSERT_NOT_REACHED();1766 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind"); 1769 1767 } 1770 1768 } … … 1791 1789 case Identity: { 1792 1790 // CSE should always eliminate this. 1793 RELEASE_ASSERT_NOT_REACHED();1791 DFG_CRASH(m_jit.graph(), node, "Unexpected Identity node"); 1794 1792 break; 1795 1793 } … … 1872 1870 case ZombieHint: 1873 1871 case Check: { 1874 RELEASE_ASSERT_NOT_REACHED();1872 DFG_CRASH(m_jit.graph(), node, "Unexpected node"); 1875 1873 break; 1876 1874 } … … 1932 1930 1933 1931 default: 1934 RELEASE_ASSERT_NOT_REACHED();1932 DFG_CRASH(m_jit.graph(), node, "Bad flush format"); 1935 1933 break; 1936 1934 } … … 2070 2068 2071 2069 default: 2072 RELEASE_ASSERT_NOT_REACHED();2070 DFG_CRASH(m_jit.graph(), node, "Bad use kind"); 2073 2071 } 2074 2072 break; … … 2150 2148 2151 2149 default: 2152 RELEASE_ASSERT_NOT_REACHED();2150 DFG_CRASH(m_jit.graph(), node, "Bad use kind"); 2153 2151 break; 2154 2152 } … … 2217 2215 2218 2216 default: 2219 RELEASE_ASSERT_NOT_REACHED();2217 DFG_CRASH(m_jit.graph(), node, "Bad use kind"); 2220 2218 break; 2221 2219 } … … 2339 2337 case Array::SelectUsingPredictions: 2340 2338 case Array::ForceExit: 2341 RELEASE_ASSERT_NOT_REACHED(); 2342 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 2339 DFG_CRASH(m_jit.graph(), node, "Bad array mode type"); 2343 2340 break; 2344 2341 case Array::Generic: { … … 2541 2538 case Array::SelectUsingPredictions: 2542 2539 case Array::ForceExit: 2543 RELEASE_ASSERT_NOT_REACHED(); 2544 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 2545 alreadyHandled = true; 2540 DFG_CRASH(m_jit.graph(), node, "Bad array mode type"); 2546 2541 break; 2547 2542 case Array::Generic: { 2548 RELEASE_ASSERT(node->op() == PutByVal);2543 DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal); 2549 2544 2550 2545 JSValueOperand arg1(this, child1); … … 3119 3114 3120 3115 default: 3121 RELEASE_ASSERT_NOT_REACHED();3116 DFG_CRASH(m_jit.graph(), node, "Bad use kind"); 3122 3117 break; 3123 3118 } … … 3126 3121 3127 3122 case ToPrimitive: { 3128 RELEASE_ASSERT(node->child1().useKind() == UntypedUse);3123 DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse); 3129 3124 JSValueOperand op1(this, node->child1()); 3130 3125 GPRTemporary result(this, Reuse, op1); … … 3193 3188 if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) { 3194 3189 Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()); 3195 RELEASE_ASSERT(structure->indexingType() == node->indexingType());3190 DFG_ASSERT(m_jit.graph(), node, structure->indexingType() == node->indexingType()); 3196 3191 ASSERT( 3197 3192 hasUndecided(structure->indexingType()) … … 3444 3439 emitAllocateJSArray(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements); 3445 3440 3446 RELEASE_ASSERT(indexingType & IsArray);3441 DFG_ASSERT(m_jit.graph(), node, indexingType & IsArray); 3447 3442 JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant()); 3448 3443 if (indexingType == ArrayWithDouble) { … … 3498 3493 } 3499 3494 default: 3500 RELEASE_ASSERT_NOT_REACHED();3495 DFG_CRASH(m_jit.graph(), node, "Bad use kind"); 3501 3496 break; 3502 3497 } … … 3728 3723 3729 3724 default: 3730 RELEASE_ASSERT_NOT_REACHED();3725 DFG_CRASH(m_jit.graph(), node, "Bad use kind"); 3731 3726 break; 3732 3727 } … … 3778 3773 3779 3774 default: 3780 RELEASE_ASSERT_NOT_REACHED();3775 DFG_CRASH(m_jit.graph(), node, "Bad use kind"); 3781 3776 break; 3782 3777 } … … 3834 3829 } 3835 3830 3836 noResult(node);3837 break;3838 }3839 3840 case PhantomPutStructure: {3841 ASSERT(isKnownCell(node->child1().node()));3842 m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);3843 3831 noResult(node); 3844 3832 break; … … 4249 4237 4250 4238 case CreateActivation: { 4251 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);4239 DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame); 4252 4240 4253 4241 JSValueOperand value(this, node->child1()); … … 4322 4310 4323 4311 case TearOffActivation: { 4324 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);4312 DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame); 4325 4313 4326 4314 JSValueOperand activationValue(this, node->child1()); … … 4394 4382 } 4395 4383 4396 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);4384 DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame); 4397 4385 m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultGPR); 4398 4386 m_jit.sub32(TrustedImm32(1), resultGPR); … … 4470 4458 JITCompiler::JumpList slowArgumentOutOfBounds; 4471 4459 if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) { 4472 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);4460 DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame); 4473 4461 const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get(); 4474 4462 … … 4537 4525 JITCompiler::JumpList slowArgumentOutOfBounds; 4538 4526 if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) { 4539 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);4527 DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame); 4540 4528 const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get(); 4541 4529 … … 4672 4660 4673 4661 case Unreachable: 4674 RELEASE_ASSERT_NOT_REACHED();4662 DFG_CRASH(m_jit.graph(), node, "Unexpected Unreachable node"); 4675 4663 break; 4676 4664 … … 4740 4728 case CheckTierUpAtReturn: 4741 4729 case CheckTierUpAndOSREnter: 4742 RELEASE_ASSERT_NOT_REACHED();4730 DFG_CRASH(m_jit.graph(), node, "Unexpected tier-up node"); 4743 4731 break; 4744 4732 #endif // ENABLE(FTL_JIT) … … 4756 4744 case MultiPutByOffset: 4757 4745 case FiatInt52: 4758 RELEASE_ASSERT_NOT_REACHED();4746 DFG_CRASH(m_jit.graph(), node, "Unexpected FTL node"); 4759 4747 break; 4760 4748 } -
trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.cpp
r171648 r171660 84 84 { 85 85 SAMPLE("StructureAbstractValue observeTransition"); 86 87 ASSERT(!from->dfgShouldWatch()); 86 88 87 89 if (isTop()) … … 90 92 if (!m_set.contains(from)) 91 93 return; 92 93 if (from->dfgShouldWatch()) {94 setClobbered(true);95 return;96 }97 94 98 95 if (!m_set.add(to)) … … 112 109 StructureSet newStructures; 113 110 for (unsigned i = vector.size(); i--;) { 111 ASSERT(!vector[i].previous->dfgShouldWatch()); 112 114 113 if (!m_set.contains(vector[i].previous)) 115 114 continue; 116 115 117 if (vector[i].previous->dfgShouldWatch()) 118 setClobbered(true); 119 else 120 newStructures.add(vector[i].next); 116 newStructures.add(vector[i].next); 121 117 } 122 118 -
trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h
r171648 r171660 56 56 } 57 57 58 ALWAYS_INLINE StructureAbstractValue& operator=(Structure* structure) 59 { 60 m_set = structure; 61 setClobbered(false); 62 return *this; 63 } 64 ALWAYS_INLINE StructureAbstractValue& operator=(const StructureSet& other) 65 { 66 m_set = other; 67 setClobbered(false); 68 return *this; 69 } 58 70 ALWAYS_INLINE StructureAbstractValue& operator=(const StructureAbstractValue& other) 59 71 { … … 150 162 } 151 163 164 const StructureSet& set() const 165 { 166 ASSERT(!isTop()); 167 return m_set; 168 } 169 152 170 size_t size() const 153 171 { … … 164 182 Structure* operator[](size_t i) const { return at(i); } 165 183 166 // FIXME: Eliminate all uses of this method. There shouldn't be any167 // special-casing for the one-structure case.168 // https://bugs.webkit.org/show_bug.cgi?id=133229184 // In most cases, what you really want to do is verify whether the set is top or clobbered, and 185 // if not, enumerate the set of structures. Use this only in cases where the singleton case is 186 // meaningfully special, like for transitions. 169 187 Structure* onlyStructure() const 170 188 { 171 if (isTop() || size() != 1)189 if (isTop() || isClobbered()) 172 190 return nullptr; 173 return at(0);191 return m_set.onlyStructure(); 174 192 } 175 193 -
trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp
r171648 r171660 234 234 VALIDATE((node), !!node->child2()); 235 235 break; 236 case PutStructure: 237 VALIDATE((node), !node->transition()->previous->dfgShouldWatch()); 238 break; 239 case MultiPutByOffset: 240 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) { 241 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i]; 242 if (variant.kind() != PutByIdVariant::Transition) 243 continue; 244 VALIDATE((node), !variant.oldStructureForTransition()->dfgShouldWatch()); 245 } 246 break; 236 247 default: 237 248 break; -
trunk/Source/JavaScriptCore/dfg/DFGWatchableStructureWatchingPhase.cpp
r171648 r171660 78 78 79 79 case PutStructure: 80 case PhantomPutStructure:81 80 case AllocatePropertyStorage: 82 81 case ReallocatePropertyStorage:
Note:
See TracChangeset
for help on using the changeset viewer.