Example #1
0
void Structure::materializePropertyMap(VM& vm)
{
    ASSERT(structure()->classInfo() == info());
    ASSERT(!propertyTable());

    Vector<Structure*, 8> structures;
    Structure* structure;
    PropertyTable* table;

    findStructuresAndMapForMaterialization(structures, structure, table);

    if (table) {
        table = table->copy(vm, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
        structure->m_lock.unlock();
    }

    // Must hold the lock on this structure, since we will be modifying this structure's
    // property map. We don't want getConcurrently() to see the property map in a half-baked
    // state.
    GCSafeConcurrentJITLocker locker(m_lock, vm.heap);
    if (!table)
        createPropertyMap(locker, vm, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
    else
        propertyTable().set(vm, this, table);

    InferredTypeTable* typeTable = m_inferredTypeTable.get();

    for (size_t i = structures.size(); i--;) {
        structure = structures[i];
        if (!structure->m_nameInPrevious)
            continue;
        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious());
        if (typeTable && typeTable->get(structure->m_nameInPrevious.get()))
            entry.hasInferredType = true;
        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
    }

    checkOffsetConsistency();
}
Example #2
0
Structure* Structure::nonPropertyTransition(VM& vm, Structure* structure, NonPropertyTransition transitionKind)
{
    unsigned attributes = toAttributes(transitionKind);
    IndexingType indexingType = newIndexingType(structure->indexingTypeIncludingHistory(), transitionKind);
    
    if (changesIndexingType(transitionKind)) {
        if (JSGlobalObject* globalObject = structure->m_globalObject.get()) {
            if (globalObject->isOriginalArrayStructure(structure)) {
                Structure* result = globalObject->originalArrayStructureForIndexingType(indexingType);
                if (result->indexingTypeIncludingHistory() == indexingType) {
                    structure->didTransitionFromThisStructure();
                    return result;
                }
            }
        }
    }
    
    Structure* existingTransition;
    if (!structure->isDictionary() && (existingTransition = structure->m_transitionTable.get(0, attributes))) {
        ASSERT(existingTransition->attributesInPrevious() == attributes);
        ASSERT(existingTransition->indexingTypeIncludingHistory() == indexingType);
        return existingTransition;
    }
    
    DeferGC deferGC(vm.heap);
    
    Structure* transition = create(vm, structure);
    transition->setAttributesInPrevious(attributes);
    transition->m_blob.setIndexingType(indexingType);
    
    if (preventsExtensions(transitionKind))
        transition->setDidPreventExtensions(true);
    
    unsigned additionalPropertyAttributes = 0;
    if (setsDontDeleteOnAllProperties(transitionKind))
        additionalPropertyAttributes |= DontDelete;
    if (setsReadOnlyOnAllProperties(transitionKind))
        additionalPropertyAttributes |= ReadOnly;
    if (additionalPropertyAttributes) {
        // We pin the property table on transitions that do wholesale editing of the property
        // table, since our logic for walking the property transition chain to rematerialize the
        // table doesn't know how to take into account such wholesale edits.
        
        structure->materializePropertyMapIfNecessary(vm, deferGC);
        transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm));
        transition->m_offset = structure->m_offset;
        transition->pinForCaching();
        
        if (transition->propertyTable()) {
            for (auto& entry : *transition->propertyTable().get())
                entry.attributes |= additionalPropertyAttributes;
        }
    } else {
        transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
        transition->m_offset = structure->m_offset;
        checkOffset(transition->m_offset, transition->inlineCapacity());
    }
    
    if (setsReadOnlyOnAllProperties(transitionKind)
        && transition->propertyTable()
        && !transition->propertyTable()->isEmpty())
        transition->setHasReadOnlyOrGetterSetterPropertiesExcludingProto(true);
    
    if (structure->isDictionary())
        transition->pin();
    else {
        ConcurrentJITLocker locker(structure->m_lock);
        structure->m_transitionTable.add(vm, transition);
    }

    transition->checkOffsetConsistency();
    return transition;
}