Changeset 171648 in webkit for trunk/Source/JavaScriptCore/dfg
- Timestamp:
- Jul 26, 2014, 12:06:44 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore/dfg
- Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r171641 r171648 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 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 maybe1405 // something more subtle?1406 AbstractValue result;1407 for (unsigned i = status.numVariants(); i--;) {1408 if (!status[i].specificValue()) {1409 result.makeHeapTop();1410 break;1411 }1396 if (isCellSpeculation(node->child1()->prediction())) { 1397 // This use of onlyStructure() should be replaced by giving GetByIdStatus the ability 1398 // to compute things based on a StructureSet, and then to factor ByteCodeParser's 1399 // ability to generate code based on a GetByIdStatus out of ByteCodeParser so that 1400 // ConstantFoldingPhase can use it. 1401 // https://bugs.webkit.org/show_bug.cgi?id=133229 1402 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() method 1408 // 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()); 1412 1412 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)) 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 1420 1423 m_state.setFoundConstants(true); 1421 forNode(node) = result; 1422 break; 1423 } 1424 } 1425 1424 break; 1425 } 1426 } 1427 } 1426 1428 clobberWorld(node->origin.semantic, clobberLimit); 1427 1429 forNode(node).makeHeapTop(); 1428 1430 break; 1429 }1430 1431 1431 1432 case GetArrayLength: … … 1462 1463 1463 1464 case PutStructure: 1465 case PhantomPutStructure: 1464 1466 if (!forNode(node->child1()).m_structure.isClear()) { 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 } 1467 observeTransition( 1468 clobberLimit, node->transition()->previous, node->transition()->next); 1469 forNode(node->child1()).set(m_graph, node->transition()->next); 1472 1470 } 1473 1471 break; … … 1598 1596 1599 1597 case MultiGetByOffset: { 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; 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(); 1639 1631 break; 1640 1632 } … … 1645 1637 1646 1638 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 either 1643 // one case, or nothing but replace cases and they have the same offset, then we should 1644 // 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=133229 1647 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; 1647 1673 StructureSet newSet; 1648 1674 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 1656 1675 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) { 1657 1676 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i]; 1658 StructureSet thisSet = variant.oldStructure(); 1659 thisSet.filter(base); 1660 if (thisSet.isEmpty()) 1661 continue; 1677 oldSet.add(variant.oldStructure()); 1662 1678 if (variant.kind() == PutByIdVariant::Transition) { 1663 if (thisSet.onlyStructure() != variant.newStructure()) { 1664 transitions.append( 1665 Transition(variant.oldStructureForTransition(), variant.newStructure())); 1666 } // else this is really a replace. 1679 transitions.append(Transition(variant.oldStructure(), variant.newStructure())); 1667 1680 newSet.add(variant.newStructure()); 1668 1681 } else { 1669 1682 ASSERT(variant.kind() == PutByIdVariant::Replace); 1670 newSet.merge(thisSet); 1671 } 1672 } 1673 1683 newSet.add(variant.oldStructure()); 1684 } 1685 } 1686 1687 filter(node->child1(), oldSet); 1674 1688 observeTransitions(clobberLimit, transitions); 1675 if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction) 1676 m_state.setIsValid(false); 1689 forNode(node->child1()).set(m_graph, newSet); 1677 1690 break; 1678 1691 } … … 1703 1716 case PutById: 1704 1717 case PutByIdFlush: 1705 case PutByIdDirect: { 1706 AbstractValue& value = forNode(node->child1()); 1707 if (!value.m_structure.isTop() && !value.m_structure.isClobbered()) { 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()) { 1708 1725 PutByIdStatus status = PutByIdStatus::computeFor( 1709 1726 m_graph.m_vm, 1710 1727 m_graph.globalObjectFor(node->origin.semantic), 1711 value.m_structure.set(),1728 structure, 1712 1729 m_graph.identifiers()[node->identifierNumber()], 1713 1730 node->op() == PutByIdDirect); 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)) 1731 if (status.isSimple() && status.numVariants() == 1) { 1732 if (status[0].kind() == PutByIdVariant::Replace) { 1733 filter(node->child1(), structure); 1734 1734 m_state.setFoundConstants(true); 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 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 } 1743 1747 clobberWorld(node->origin.semantic, clobberLimit); 1744 1748 break; 1745 }1746 1749 1747 1750 case In: … … 1946 1949 AbstractValue::TransitionObserver transitionObserver(from, to); 1947 1950 forAllValues(clobberLimit, transitionObserver); 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. 1951 setDidClobber(); 1950 1952 } 1951 1953 … … 1956 1958 AbstractValue::TransitionsObserver transitionsObserver(vector); 1957 1959 forAllValues(clobberLimit, transitionsObserver); 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 } 1960 setDidClobber(); 1964 1961 } 1965 1962 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
r171641 r171648 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 205 194 FiltrationResult AbstractValue::filterArrayModes(ArrayModes arrayModes) 206 195 { … … 253 242 } 254 243 255 bool AbstractValue::contains(Structure* structure) const256 {257 return couldBeType(speculationFromStructure(structure))258 && (m_arrayModes & arrayModeFromStructure(structure))259 && m_structure.contains(structure);260 }261 262 244 FiltrationResult AbstractValue::filter(const AbstractValue& other) 263 245 { -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h
r171641 r171648 268 268 } 269 269 270 bool couldBeType(SpeculatedType desiredType) const270 bool couldBeType(SpeculatedType desiredType) 271 271 { 272 272 return !!(m_type & desiredType); 273 273 } 274 274 275 bool isType(SpeculatedType desiredType) const275 bool isType(SpeculatedType desiredType) 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;289 285 290 286 bool validate(JSValue value) const -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r171641 r171648 1892 1892 emitChecks(variant.constantChecks()); 1893 1893 1894 ASSERT(variant.oldStructure ForTransition()->transitionWatchpointSetHasBeenInvalidated());1894 ASSERT(variant.oldStructure()->transitionWatchpointSetHasBeenInvalidated()); 1895 1895 1896 1896 Node* propertyStorage; 1897 1897 Transition* transition = m_graph.m_transitions.add( 1898 variant.oldStructureForTransition(), variant.newStructure()); 1899 1900 if (variant.reallocatesStorage()) { 1898 variant.oldStructure(), variant.newStructure()); 1899 1900 if (variant.oldStructure()->outOfLineCapacity() 1901 != variant.newStructure()->outOfLineCapacity()) { 1901 1902 1902 1903 // If we're growing the property storage then it must be because we're … … 1904 1905 ASSERT(!isInlineOffset(variant.offset())); 1905 1906 1906 if (!variant.oldStructure ForTransition()->outOfLineCapacity()) {1907 if (!variant.oldStructure()->outOfLineCapacity()) { 1907 1908 propertyStorage = addToGraph( 1908 1909 AllocatePropertyStorage, OpInfo(transition), base); … … 2036 2037 if (op1->op() != ToThis) { 2037 2038 Structure* cachedStructure = currentInstruction[2].u.structure.get(); 2038 if (currentInstruction[2].u.toThisStatus != ToThisOK 2039 || !cachedStructure 2039 if (!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 2890 || status.numVariants() != 1 2891 || status[0].structureSet().size() != 1) { 2889 if (status.state() != GetByIdStatus::Simple || status.numVariants() != 1) { 2892 2890 set(VirtualRegister(dst), addToGraph(GetByIdFlush, OpInfo(identifierNumber), OpInfo(prediction), get(VirtualRegister(scope)))); 2893 2891 break; … … 2974 2972 case GlobalPropertyWithVarInjectionChecks: { 2975 2973 PutByIdStatus status = PutByIdStatus::computeFor(*m_vm, globalObject, structure, uid, false); 2976 if (status.numVariants() != 1 2977 || status[0].kind() != PutByIdVariant::Replace 2978 || status[0].structure().size() != 1) { 2974 if (status.numVariants() != 1 || status[0].kind() != PutByIdVariant::Replace) { 2979 2975 addToGraph(PutById, OpInfo(identifierNumber), get(VirtualRegister(scope)), get(VirtualRegister(value))); 2980 2976 break; 2981 2977 } 2982 ASSERT(status[0].structure().onlyStructure() == structure); 2983 Node* base = cellConstantWithStructureCheck(globalObject, structure); 2978 Node* base = cellConstantWithStructureCheck(globalObject, status[0].structure()); 2984 2979 addToGraph(Phantom, get(VirtualRegister(scope))); 2985 2980 handlePutByOffset(base, identifierNumber, static_cast<PropertyOffset>(operand), get(VirtualRegister(value))); -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r171641 r171648 441 441 442 442 case PutStructure: 443 case PhantomPutStructure: 443 444 write(JSCell_structureID); 444 445 write(JSCell_typeInfoType); -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r171641 r171648 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 144 135 case CheckFunction: { 145 136 if (m_state.forNode(node->child1()).value() != node->function()->value()) … … 164 155 165 156 case MultiGetByOffset: { 166 Edge baseEdge = node->child1();167 Node* base = baseEdge.node();157 Edge childEdge = node->child1(); 158 Node* child = childEdge.node(); 168 159 MultiGetByOffsetData& data = node->multiGetByOffsetData(); 169 160 170 // First prune the variants, then check if the MultiGetByOffset can be171 // 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 }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)) 168 continue; 169 170 if (variant.alternateBase()) 171 break; 172 173 emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber); 174 eliminated = true; 175 break; 185 176 } 186 187 if (data.variants.size() != 1)188 break;189 190 emitGetByOffset(191 indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);192 177 break; 193 178 } 194 179 195 180 case MultiPutByOffset: { 196 Edge baseEdge = node->child1();197 Node* base = baseEdge.node();181 Edge childEdge = node->child1(); 182 Node* child = childEdge.node(); 198 183 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); 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; 209 193 210 if (variant.oldStructure().isEmpty()) { 211 data.variants[i--] = data.variants.last(); 212 data.variants.removeLast(); 213 continue; 214 } 215 216 if (variant.kind() == PutByIdVariant::Transition 217 && variant.oldStructure().onlyStructure() == variant.newStructure()) { 218 variant = PutByIdVariant::replace( 219 variant.oldStructure(), 220 variant.offset()); 221 } 194 emitPutByOffset(indexInBlock, node, structure, variant, data.identifierNumber); 195 eliminated = true; 196 break; 222 197 } 223 224 if (data.variants.size() != 1)225 break;226 227 emitPutByOffset(228 indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);229 198 break; 230 199 } … … 236 205 unsigned identifierNumber = node->identifierNumber(); 237 206 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 207 if (childEdge.useKind() != CellUse) 208 break; 209 210 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 211 if (!structure) 212 break; 213 247 214 GetByIdStatus status = GetByIdStatus::computeFor( 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 } 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; 259 222 } 260 223 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); 224 emitGetByOffset(indexInBlock, node, structure, status[0], identifierNumber); 225 eliminated = true; 273 226 break; 274 227 } 275 228 276 229 case PutById: 277 case PutByIdDirect: 278 case PutByIdFlush: { 230 case PutByIdDirect: { 279 231 NodeOrigin origin = node->origin; 280 232 Edge childEdge = node->child1(); … … 284 236 ASSERT(childEdge.useKind() == CellUse); 285 237 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()) 238 Structure* structure = m_state.forNode(child).m_structure.onlyStructure(); 239 if (!structure) 292 240 break; 293 241 … … 295 243 vm(), 296 244 m_graph.globalObjectFor(origin.semantic), 297 baseValue.m_structure.set(),245 structure, 298 246 m_graph.identifiers()[identifierNumber], 299 247 node->op() == PutByIdDirect); … … 301 249 if (!status.isSimple()) 302 250 break; 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); 251 if (status.numVariants() != 1) 252 break; 253 254 emitPutByOffset(indexInBlock, node, structure, status[0], identifierNumber); 255 eliminated = true; 319 256 break; 320 257 } … … 407 344 } 408 345 409 void emitGetByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const GetByIdVariant& variant, unsigned identifierNumber)346 void emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant& variant, unsigned identifierNumber) 410 347 { 411 348 NodeOrigin origin = node->origin; … … 413 350 Node* child = childEdge.node(); 414 351 415 addBaseCheck(indexInBlock, node, baseValue, variant.structureSet()); 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 } 416 366 417 367 if (variant.specificValue()) { … … 420 370 } 421 371 422 if (variant.alternateBase()) { 423 child = m_insertionSet.insertConstant(indexInBlock, origin, variant.alternateBase()); 424 childEdge = Edge(child, KnownCellUse); 425 } else 426 childEdge.setUseKind(KnownCellUse); 372 childEdge.setUseKind(KnownCellUse); 427 373 428 374 Edge propertyStorage; … … 443 389 } 444 390 445 void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByIdVariant& variant, unsigned identifierNumber)391 void emitPutByOffset(unsigned indexInBlock, Node* node, Structure* structure, const PutByIdVariant& variant, unsigned identifierNumber) 446 392 { 447 393 NodeOrigin origin = node->origin; 448 394 Edge childEdge = node->child1(); 449 450 addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure()); 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 } 451 410 452 411 childEdge.setUseKind(KnownCellUse); … … 454 413 Transition* transition = 0; 455 414 if (variant.kind() == PutByIdVariant::Transition) { 456 transition = m_graph.m_transitions.add( 457 variant.oldStructureForTransition(), variant.newStructure()); 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 } 458 423 } 459 424 … … 462 427 if (isInlineOffset(variant.offset())) 463 428 propertyStorage = childEdge; 464 else if (!variant.reallocatesStorage()) { 429 else if ( 430 variant.kind() == PutByIdVariant::Replace 431 || structure->outOfLineCapacity() == variant.newStructure()->outOfLineCapacity()) { 465 432 propertyStorage = Edge(m_insertionSet.insertNode( 466 433 indexInBlock, SpecNone, GetButterfly, origin, childEdge)); 467 } else if (! variant.oldStructureForTransition()->outOfLineCapacity()) {434 } else if (!structure->outOfLineCapacity()) { 468 435 ASSERT(variant.newStructure()->outOfLineCapacity()); 469 436 ASSERT(!isInlineOffset(variant.offset())); … … 474 441 propertyStorage = Edge(allocatePropertyStorage); 475 442 } else { 476 ASSERT( variant.oldStructureForTransition()->outOfLineCapacity());477 ASSERT(variant.newStructure()->outOfLineCapacity() > variant.oldStructureForTransition()->outOfLineCapacity());443 ASSERT(structure->outOfLineCapacity()); 444 ASSERT(variant.newStructure()->outOfLineCapacity() > structure->outOfLineCapacity()); 478 445 ASSERT(!isInlineOffset(variant.offset())); 479 446 … … 503 470 m_graph.m_storageAccessData.append(storageAccessData); 504 471 } 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 a511 // 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 }533 472 534 473 void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell, Structure* structure) -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r171641 r171648 187 187 case PutByValAlias: 188 188 case PutStructure: 189 case PhantomPutStructure: 189 190 case GetByOffset: 190 191 case GetGetterSetterByOffset: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r171641 r171648 981 981 case Upsilon: 982 982 case GetArgument: 983 case PhantomPutStructure: 983 984 case GetIndexedPropertyStorage: 984 985 case GetTypedArrayByteOffset: -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r171641 r171648 890 890 891 891 case PutStructure: 892 case PhantomPutStructure: 892 893 case AllocatePropertyStorage: 893 894 case ReallocatePropertyStorage: … … 917 918 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) { 918 919 PutByIdVariant& variant = node->multiPutByOffsetData().variants[i]; 919 const StructureSet& set = variant.oldStructure(); 920 for (unsigned j = set.size(); j--;) 921 visitor.appendUnbarrieredReadOnlyPointer(set[j]); 920 visitor.appendUnbarrieredReadOnlyPointer(variant.oldStructure()); 922 921 if (variant.kind() == PutByIdVariant::Transition) 923 922 visitor.appendUnbarrieredReadOnlyPointer(variant.newStructure()); … … 953 952 FrozenValue* Graph::freezeStrong(JSValue value) 954 953 { 955 FrozenValue* result = freeze Fragile(value);954 FrozenValue* result = freeze(value); 956 955 result->strengthenTo(StrongValue); 957 956 return result; -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r171641 r171648 148 148 149 149 FrozenValue* freezeFragile(JSValue value); 150 FrozenValue* freeze(JSValue value); // We use weak freezing by default. Shorthand for freezeFragile(value)->strengthenTo(WeakValue);151 FrozenValue* freezeStrong(JSValue value); // Shorthand for freeze Fragile(value)->strengthenTo(StrongValue).150 FrozenValue* freeze(JSValue value); // We use weak freezing by default. 151 FrozenValue* freezeStrong(JSValue value); // Shorthand for freeze(value)->markStrongly(). 152 152 153 153 void convertToConstant(Node* node, FrozenValue* value); -
trunk/Source/JavaScriptCore/dfg/DFGNode.cpp
r171641 r171648 38 38 { 39 39 for (unsigned i = variants.size(); i--;) { 40 if (variants[i]. writesStructures())40 if (variants[i].kind() == PutByIdVariant::Transition) 41 41 return true; 42 42 } … … 47 47 { 48 48 for (unsigned i = variants.size(); i--;) { 49 if (variants[i].reallocatesStorage()) 50 return true; 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; 51 57 } 52 58 return false; -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r171641 r171648 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 470 461 void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage) 471 462 { 472 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op ==MultiPutByOffset);463 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == MultiPutByOffset); 473 464 m_opInfo = storageAccessDataIndex; 474 465 children.setChild3(children.child2()); … … 476 467 children.setChild1(storage); 477 468 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;486 469 m_flags &= ~NodeClobbersWorld; 487 470 } … … 1125 1108 switch (op()) { 1126 1109 case PutStructure: 1110 case PhantomPutStructure: 1127 1111 case AllocatePropertyStorage: 1128 1112 case ReallocatePropertyStorage: -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r171641 r171648 156 156 macro(CheckExecutable, NodeMustGenerate) \ 157 157 macro(PutStructure, NodeMustGenerate) \ 158 macro(PhantomPutStructure, NodeMustGenerate) \ 158 159 macro(AllocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \ 159 160 macro(ReallocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \ -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r171641 r171648 541 541 case GetMyArgumentsLength: 542 542 case GetMyArgumentByVal: 543 case PhantomPutStructure: 543 544 case PhantomArguments: 544 545 case CheckArray: -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r171641 r171648 284 284 285 285 case PutStructure: 286 case PhantomPutStructure: 286 287 case AllocatePropertyStorage: 287 288 case ReallocatePropertyStorage: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r171613 r171648 344 344 ASSERT(info.gpr() == source); 345 345 if (node->hasConstant()) { 346 DFG_ASSERT(m_jit.graph(), m_currentNode, node->isCellConstant()); 346 347 node->asCell(); // To get the assertion. 347 348 fillAction = SetCellConstant; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r171641 r171648 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" on 873 // the constant then the silent filler may think that we have a cell and a 874 // constant, so it will try to fill this as an cell constant. Bad things will 875 // happen. 876 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 877 return allocate(); 878 } 870 879 871 880 switch (info.registerFormat()) { … … 879 888 JSValue jsValue = edge->asJSValue(); 880 889 GPRReg gpr = allocate(); 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); 890 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 891 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr); 892 info.fillCell(*m_stream, gpr); 888 893 return gpr; 889 894 } … … 3735 3740 } 3736 3741 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 3737 3749 case PutStructure: { 3738 3750 Structure* oldStructure = node->transition()->previous; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r171641 r171648 98 98 default: 99 99 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 100 DFG_ASSERT(m_jit.graph(), m_currentNode,spillFormat & DataFormatJS);100 RELEASE_ASSERT(spillFormat & DataFormatJS); 101 101 break; 102 102 } … … 138 138 case DataFormatInt52: 139 139 // this type currently never occurs 140 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");140 RELEASE_ASSERT_NOT_REACHED(); 141 141 142 142 default: 143 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");143 RELEASE_ASSERT_NOT_REACHED(); 144 144 return InvalidGPRReg; 145 145 } … … 312 312 Node* branchNode = m_block->at(branchIndexInBlock); 313 313 314 DFG_ASSERT(m_jit.graph(), node,node->adjustedRefCount() == 1);314 RELEASE_ASSERT(node->adjustedRefCount() == 1); 315 315 316 316 nonSpeculativePeepholeBranchNull(operand, branchNode, invert); … … 629 629 bool isCall = node->op() == Call; 630 630 if (!isCall) 631 DFG_ASSERT(m_jit.graph(), node,node->op() == Construct);632 631 RELEASE_ASSERT(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 DFG_ASSERT(m_jit.graph(), m_currentNode,(spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);744 RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32); 745 745 746 746 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); … … 772 772 773 773 case DataFormatJS: { 774 DFG_ASSERT(m_jit.graph(), m_currentNode,!(type & SpecInt52));774 RELEASE_ASSERT(!(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 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");837 RELEASE_ASSERT_NOT_REACHED(); 838 838 839 839 default: 840 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");840 RELEASE_ASSERT_NOT_REACHED(); 841 841 return InvalidGPRReg; 842 842 } … … 855 855 DataFormat mustBeDataFormatInt32; 856 856 GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32); 857 DFG_ASSERT(m_jit.graph(), m_currentNode,mustBeDataFormatInt32 == DataFormatInt32);857 RELEASE_ASSERT(mustBeDataFormatInt32 == DataFormatInt32); 858 858 return result; 859 859 } … … 890 890 DataFormat spillFormat = info.spillFormat(); 891 891 892 DFG_ASSERT(m_jit.graph(), m_currentNode,spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);892 RELEASE_ASSERT(spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52); 893 893 894 894 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); … … 942 942 943 943 default: 944 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");944 RELEASE_ASSERT_NOT_REACHED(); 945 945 return InvalidGPRReg; 946 946 } … … 973 973 974 974 DataFormat spillFormat = info.spillFormat(); 975 DFG_ASSERT(m_jit.graph(), m_currentNode,spillFormat == DataFormatDouble);975 RELEASE_ASSERT(spillFormat == DataFormatDouble); 976 976 FPRReg fpr = fprAllocate(); 977 977 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr); … … 981 981 } 982 982 983 DFG_ASSERT(m_jit.graph(), m_currentNode,info.registerFormat() == DataFormatDouble);983 RELEASE_ASSERT(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 998 1004 switch (info.registerFormat()) { 999 1005 case DataFormatNone: { … … 1002 1008 if (edge->hasConstant()) { 1003 1009 JSValue jsValue = edge->asJSValue(); 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); 1010 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 1011 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr); 1012 info.fillJSValue(*m_stream, gpr, DataFormatJSCell); 1011 1013 return gpr; 1012 1014 } … … 1061 1063 case DataFormatInt52: 1062 1064 case DataFormatStrictInt52: 1063 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");1065 RELEASE_ASSERT_NOT_REACHED(); 1064 1066 1065 1067 default: 1066 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");1068 RELEASE_ASSERT_NOT_REACHED(); 1067 1069 return InvalidGPRReg; 1068 1070 } … … 1097 1099 return gpr; 1098 1100 } 1099 DFG_ASSERT(m_jit.graph(), m_currentNode,info.spillFormat() & DataFormatJS);1101 RELEASE_ASSERT(info.spillFormat() & DataFormatJS); 1100 1102 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 1101 1103 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); … … 1142 1144 case DataFormatInt52: 1143 1145 case DataFormatStrictInt52: 1144 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");1146 RELEASE_ASSERT_NOT_REACHED(); 1145 1147 1146 1148 default: 1147 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");1149 RELEASE_ASSERT_NOT_REACHED(); 1148 1150 return InvalidGPRReg; 1149 1151 } … … 1609 1611 1610 1612 default: 1611 DFG_CRASH(m_jit.graph(), node, "Bad use kind");1613 RELEASE_ASSERT_NOT_REACHED(); 1612 1614 break; 1613 1615 } … … 1764 1766 1765 1767 default: 1766 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");1768 RELEASE_ASSERT_NOT_REACHED(); 1767 1769 } 1768 1770 } … … 1789 1791 case Identity: { 1790 1792 // CSE should always eliminate this. 1791 DFG_CRASH(m_jit.graph(), node, "Unexpected Identity node");1793 RELEASE_ASSERT_NOT_REACHED(); 1792 1794 break; 1793 1795 } … … 1870 1872 case ZombieHint: 1871 1873 case Check: { 1872 DFG_CRASH(m_jit.graph(), node, "Unexpected node");1874 RELEASE_ASSERT_NOT_REACHED(); 1873 1875 break; 1874 1876 } … … 1930 1932 1931 1933 default: 1932 DFG_CRASH(m_jit.graph(), node, "Bad flush format");1934 RELEASE_ASSERT_NOT_REACHED(); 1933 1935 break; 1934 1936 } … … 2068 2070 2069 2071 default: 2070 DFG_CRASH(m_jit.graph(), node, "Bad use kind");2072 RELEASE_ASSERT_NOT_REACHED(); 2071 2073 } 2072 2074 break; … … 2148 2150 2149 2151 default: 2150 DFG_CRASH(m_jit.graph(), node, "Bad use kind");2152 RELEASE_ASSERT_NOT_REACHED(); 2151 2153 break; 2152 2154 } … … 2215 2217 2216 2218 default: 2217 DFG_CRASH(m_jit.graph(), node, "Bad use kind");2219 RELEASE_ASSERT_NOT_REACHED(); 2218 2220 break; 2219 2221 } … … 2337 2339 case Array::SelectUsingPredictions: 2338 2340 case Array::ForceExit: 2339 DFG_CRASH(m_jit.graph(), node, "Bad array mode type"); 2341 RELEASE_ASSERT_NOT_REACHED(); 2342 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 2340 2343 break; 2341 2344 case Array::Generic: { … … 2538 2541 case Array::SelectUsingPredictions: 2539 2542 case Array::ForceExit: 2540 DFG_CRASH(m_jit.graph(), node, "Bad array mode type"); 2543 RELEASE_ASSERT_NOT_REACHED(); 2544 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 2545 alreadyHandled = true; 2541 2546 break; 2542 2547 case Array::Generic: { 2543 DFG_ASSERT(m_jit.graph(), node,node->op() == PutByVal);2548 RELEASE_ASSERT(node->op() == PutByVal); 2544 2549 2545 2550 JSValueOperand arg1(this, child1); … … 3114 3119 3115 3120 default: 3116 DFG_CRASH(m_jit.graph(), node, "Bad use kind");3121 RELEASE_ASSERT_NOT_REACHED(); 3117 3122 break; 3118 3123 } … … 3121 3126 3122 3127 case ToPrimitive: { 3123 DFG_ASSERT(m_jit.graph(), node,node->child1().useKind() == UntypedUse);3128 RELEASE_ASSERT(node->child1().useKind() == UntypedUse); 3124 3129 JSValueOperand op1(this, node->child1()); 3125 3130 GPRTemporary result(this, Reuse, op1); … … 3188 3193 if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) { 3189 3194 Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()); 3190 DFG_ASSERT(m_jit.graph(), node,structure->indexingType() == node->indexingType());3195 RELEASE_ASSERT(structure->indexingType() == node->indexingType()); 3191 3196 ASSERT( 3192 3197 hasUndecided(structure->indexingType()) … … 3439 3444 emitAllocateJSArray(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements); 3440 3445 3441 DFG_ASSERT(m_jit.graph(), node,indexingType & IsArray);3446 RELEASE_ASSERT(indexingType & IsArray); 3442 3447 JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant()); 3443 3448 if (indexingType == ArrayWithDouble) { … … 3493 3498 } 3494 3499 default: 3495 DFG_CRASH(m_jit.graph(), node, "Bad use kind");3500 RELEASE_ASSERT_NOT_REACHED(); 3496 3501 break; 3497 3502 } … … 3723 3728 3724 3729 default: 3725 DFG_CRASH(m_jit.graph(), node, "Bad use kind");3730 RELEASE_ASSERT_NOT_REACHED(); 3726 3731 break; 3727 3732 } … … 3773 3778 3774 3779 default: 3775 DFG_CRASH(m_jit.graph(), node, "Bad use kind");3780 RELEASE_ASSERT_NOT_REACHED(); 3776 3781 break; 3777 3782 } … … 3829 3834 } 3830 3835 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); 3831 3843 noResult(node); 3832 3844 break; … … 4237 4249 4238 4250 case CreateActivation: { 4239 DFG_ASSERT(m_jit.graph(), node,!node->origin.semantic.inlineCallFrame);4251 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame); 4240 4252 4241 4253 JSValueOperand value(this, node->child1()); … … 4310 4322 4311 4323 case TearOffActivation: { 4312 DFG_ASSERT(m_jit.graph(), node,!node->origin.semantic.inlineCallFrame);4324 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame); 4313 4325 4314 4326 JSValueOperand activationValue(this, node->child1()); … … 4382 4394 } 4383 4395 4384 DFG_ASSERT(m_jit.graph(), node,!node->origin.semantic.inlineCallFrame);4396 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame); 4385 4397 m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultGPR); 4386 4398 m_jit.sub32(TrustedImm32(1), resultGPR); … … 4458 4470 JITCompiler::JumpList slowArgumentOutOfBounds; 4459 4471 if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) { 4460 DFG_ASSERT(m_jit.graph(), node,!node->origin.semantic.inlineCallFrame);4472 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame); 4461 4473 const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get(); 4462 4474 … … 4525 4537 JITCompiler::JumpList slowArgumentOutOfBounds; 4526 4538 if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) { 4527 DFG_ASSERT(m_jit.graph(), node,!node->origin.semantic.inlineCallFrame);4539 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame); 4528 4540 const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get(); 4529 4541 … … 4660 4672 4661 4673 case Unreachable: 4662 DFG_CRASH(m_jit.graph(), node, "Unexpected Unreachable node");4674 RELEASE_ASSERT_NOT_REACHED(); 4663 4675 break; 4664 4676 … … 4728 4740 case CheckTierUpAtReturn: 4729 4741 case CheckTierUpAndOSREnter: 4730 DFG_CRASH(m_jit.graph(), node, "Unexpected tier-up node");4742 RELEASE_ASSERT_NOT_REACHED(); 4731 4743 break; 4732 4744 #endif // ENABLE(FTL_JIT) … … 4744 4756 case MultiPutByOffset: 4745 4757 case FiatInt52: 4746 DFG_CRASH(m_jit.graph(), node, "Unexpected FTL node");4758 RELEASE_ASSERT_NOT_REACHED(); 4747 4759 break; 4748 4760 } -
trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.cpp
r171641 r171648 84 84 { 85 85 SAMPLE("StructureAbstractValue observeTransition"); 86 87 ASSERT(!from->dfgShouldWatch());88 86 89 87 if (isTop()) … … 92 90 if (!m_set.contains(from)) 93 91 return; 92 93 if (from->dfgShouldWatch()) { 94 setClobbered(true); 95 return; 96 } 94 97 95 98 if (!m_set.add(to)) … … 109 112 StructureSet newStructures; 110 113 for (unsigned i = vector.size(); i--;) { 111 ASSERT(!vector[i].previous->dfgShouldWatch());112 113 114 if (!m_set.contains(vector[i].previous)) 114 115 continue; 115 116 116 newStructures.add(vector[i].next); 117 if (vector[i].previous->dfgShouldWatch()) 118 setClobbered(true); 119 else 120 newStructures.add(vector[i].next); 117 121 } 118 122 -
trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h
r171641 r171648 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 }70 58 ALWAYS_INLINE StructureAbstractValue& operator=(const StructureAbstractValue& other) 71 59 { … … 162 150 } 163 151 164 const StructureSet& set() const165 {166 ASSERT(!isTop());167 return m_set;168 }169 170 152 size_t size() const 171 153 { … … 182 164 Structure* operator[](size_t i) const { return at(i); } 183 165 184 // In most cases, what you really want to do is verify whether the set is top or clobbered, and185 // if not, enumerate the set of structures. Use this only in cases where the singleton case is186 // meaningfully special, like for transitions.166 // FIXME: Eliminate all uses of this method. There shouldn't be any 167 // special-casing for the one-structure case. 168 // https://bugs.webkit.org/show_bug.cgi?id=133229 187 169 Structure* onlyStructure() const 188 170 { 189 if (isTop() || isClobbered())171 if (isTop() || size() != 1) 190 172 return nullptr; 191 return m_set.onlyStructure();173 return at(0); 192 174 } 193 175 -
trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp
r171641 r171648 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;247 236 default: 248 237 break; -
trunk/Source/JavaScriptCore/dfg/DFGWatchableStructureWatchingPhase.cpp
r171641 r171648 78 78 79 79 case PutStructure: 80 case PhantomPutStructure: 80 81 case AllocatePropertyStorage: 81 82 case ReallocatePropertyStorage:
Note:
See TracChangeset
for help on using the changeset viewer.