Exemple #1
0
    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 emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant& variant, unsigned identifierNumber)
    {
        NodeOrigin origin = node->origin;
        Edge childEdge = node->child1();
        Node* child = childEdge.node();

        bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton();
        bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
        
        ASSERT(!variant.chain());
        ASSERT(variant.structureSet().contains(structure));
        
        // Now before we do anything else, push the CFA forward over the GetById
        // 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);
        }
        
        if (variant.specificValue()) {
            m_graph.convertToConstant(node, variant.specificValue());
            return;
        }
        
        childEdge.setUseKind(KnownCellUse);
        
        Edge propertyStorage;
        
        if (isInlineOffset(variant.offset()))
            propertyStorage = childEdge;
        else {
            propertyStorage = Edge(m_insertionSet.insertNode(
                indexInBlock, SpecNone, GetButterfly, origin, childEdge));
        }
        
        node->convertToGetByOffset(m_graph.m_storageAccessData.size(), propertyStorage);
        
        StorageAccessData storageAccessData;
        storageAccessData.offset = variant.offset();
        storageAccessData.identifierNumber = identifierNumber;
        m_graph.m_storageAccessData.append(storageAccessData);
    }
Exemple #3
0
    void emitGetByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const GetByIdVariant& variant, unsigned identifierNumber)
    {
        NodeOrigin origin = node->origin;
        Edge childEdge = node->child1();
        Node* child = childEdge.node();

        addBaseCheck(indexInBlock, node, baseValue, variant.structureSet());
        
        JSValue baseForLoad;
        if (variant.alternateBase())
            baseForLoad = variant.alternateBase();
        else
            baseForLoad = baseValue.m_value;
        if (JSValue value = m_graph.tryGetConstantProperty(baseForLoad, variant.baseStructure(), variant.offset())) {
            m_graph.convertToConstant(node, m_graph.freeze(value));
            return;
        }
        
        if (variant.alternateBase()) {
            child = m_insertionSet.insertConstant(indexInBlock, origin, variant.alternateBase());
            childEdge = Edge(child, KnownCellUse);
        } else
            childEdge.setUseKind(KnownCellUse);
        
        Edge propertyStorage;
        
        if (isInlineOffset(variant.offset()))
            propertyStorage = childEdge;
        else {
            propertyStorage = Edge(m_insertionSet.insertNode(
                indexInBlock, SpecNone, GetButterfly, origin, childEdge));
        }
        
        node->convertToGetByOffset(m_graph.m_storageAccessData.size(), propertyStorage);
        
        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);
    }