void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByIdVariant& variant, unsigned identifierNumber) { NodeOrigin origin = node->origin; Edge childEdge = node->child1(); addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure()); childEdge.setUseKind(KnownCellUse); Transition* transition = 0; if (variant.kind() == PutByIdVariant::Transition) { transition = m_graph.m_transitions.add( variant.oldStructureForTransition(), variant.newStructure()); } Edge propertyStorage; if (isInlineOffset(variant.offset())) propertyStorage = childEdge; else if (!variant.reallocatesStorage()) { propertyStorage = Edge(m_insertionSet.insertNode( indexInBlock, SpecNone, GetButterfly, origin, childEdge)); } else if (!variant.oldStructureForTransition()->outOfLineCapacity()) { ASSERT(variant.newStructure()->outOfLineCapacity()); ASSERT(!isInlineOffset(variant.offset())); Node* allocatePropertyStorage = m_insertionSet.insertNode( indexInBlock, SpecNone, AllocatePropertyStorage, origin, OpInfo(transition), childEdge); m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse)); propertyStorage = Edge(allocatePropertyStorage); } else { ASSERT(variant.oldStructureForTransition()->outOfLineCapacity()); ASSERT(variant.newStructure()->outOfLineCapacity() > variant.oldStructureForTransition()->outOfLineCapacity()); ASSERT(!isInlineOffset(variant.offset())); Node* reallocatePropertyStorage = m_insertionSet.insertNode( indexInBlock, SpecNone, ReallocatePropertyStorage, origin, OpInfo(transition), childEdge, Edge(m_insertionSet.insertNode( indexInBlock, SpecNone, GetButterfly, origin, childEdge))); m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse)); propertyStorage = Edge(reallocatePropertyStorage); } if (variant.kind() == PutByIdVariant::Transition) { Node* putStructure = m_graph.addNode(SpecNone, PutStructure, origin, OpInfo(transition), childEdge); m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse)); m_insertionSet.insert(indexInBlock, putStructure); } node->convertToPutByOffset(m_graph.m_storageAccessData.size(), propertyStorage); m_insertionSet.insertNode( indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child2().node(), KnownCellUse)); StorageAccessData storageAccessData; storageAccessData.offset = variant.offset(); storageAccessData.identifierNumber = identifierNumber; m_graph.m_storageAccessData.append(storageAccessData); }
void emitPutByOffset(unsigned indexInBlock, Node* node, Structure* structure, const PutByIdVariant& variant, unsigned identifierNumber) { NodeOrigin origin = node->origin; Edge childEdge = node->child1(); Node* child = childEdge.node(); ASSERT(variant.oldStructure() == structure); bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton(); bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell; // Now before we do anything else, push the CFA forward over the PutById // and make sure we signal to the loop that it should continue and not // do any eliminations. m_interpreter.execute(indexInBlock); if (needsWatchpoint) { m_insertionSet.insertNode( indexInBlock, SpecNone, StructureTransitionWatchpoint, origin, OpInfo(structure), childEdge); } else if (needsCellCheck) { m_insertionSet.insertNode( indexInBlock, SpecNone, Phantom, origin, childEdge); } childEdge.setUseKind(KnownCellUse); StructureTransitionData* transitionData = 0; if (variant.kind() == PutByIdVariant::Transition) { transitionData = m_graph.addStructureTransitionData( StructureTransitionData(structure, variant.newStructure())); if (node->op() == PutById) { if (!structure->storedPrototype().isNull()) { addStructureTransitionCheck( origin, indexInBlock, structure->storedPrototype().asCell()); } m_graph.chains().addLazily(variant.structureChain()); for (unsigned i = 0; i < variant.structureChain()->size(); ++i) { JSValue prototype = variant.structureChain()->at(i)->storedPrototype(); if (prototype.isNull()) continue; ASSERT(prototype.isCell()); addStructureTransitionCheck( origin, indexInBlock, prototype.asCell()); } } } Edge propertyStorage; if (isInlineOffset(variant.offset())) propertyStorage = childEdge; else if ( variant.kind() == PutByIdVariant::Replace || structure->outOfLineCapacity() == variant.newStructure()->outOfLineCapacity()) { propertyStorage = Edge(m_insertionSet.insertNode( indexInBlock, SpecNone, GetButterfly, origin, childEdge)); } else if (!structure->outOfLineCapacity()) { ASSERT(variant.newStructure()->outOfLineCapacity()); ASSERT(!isInlineOffset(variant.offset())); Node* allocatePropertyStorage = m_insertionSet.insertNode( indexInBlock, SpecNone, AllocatePropertyStorage, origin, OpInfo(transitionData), childEdge); m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse)); propertyStorage = Edge(allocatePropertyStorage); } else { ASSERT(structure->outOfLineCapacity()); ASSERT(variant.newStructure()->outOfLineCapacity() > structure->outOfLineCapacity()); ASSERT(!isInlineOffset(variant.offset())); Node* reallocatePropertyStorage = m_insertionSet.insertNode( indexInBlock, SpecNone, ReallocatePropertyStorage, origin, OpInfo(transitionData), childEdge, Edge(m_insertionSet.insertNode( indexInBlock, SpecNone, GetButterfly, origin, childEdge))); m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse)); propertyStorage = Edge(reallocatePropertyStorage); } if (variant.kind() == PutByIdVariant::Transition) { Node* putStructure = m_graph.addNode(SpecNone, PutStructure, origin, OpInfo(transitionData), childEdge); m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse)); m_insertionSet.insert(indexInBlock, putStructure); } node->convertToPutByOffset(m_graph.m_storageAccessData.size(), propertyStorage); m_insertionSet.insertNode( indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child2().node(), KnownCellUse)); StorageAccessData storageAccessData; storageAccessData.offset = variant.offset(); storageAccessData.identifierNumber = identifierNumber; m_graph.m_storageAccessData.append(storageAccessData); }