Example #1
0
bool InferredType::set(const ConcurrentJSLocker& locker, VM& vm, Descriptor newDescriptor)
{
    // We will trigger write barriers while holding our lock. Currently, write barriers don't GC, but that
    // could change. If it does, we don't want to deadlock. Note that we could have used
    // GCSafeConcurrentJSLocker in the caller, but the caller is on a fast path so maybe that wouldn't be
    // a good idea.
    DeferGCForAWhile deferGC(vm.heap);
    
    // Be defensive: if we're not really changing the type, then we don't have to do anything.
    if (descriptor(locker) == newDescriptor)
        return false;

    bool shouldFireWatchpointSet = false;
    
    // The new descriptor must be more general than the previous one.
    ASSERT(newDescriptor.subsumes(descriptor(locker)));

    // If the new descriptors have different structures, then it can only be because one is null.
    if (descriptor(locker).structure() != newDescriptor.structure())
        ASSERT(!descriptor(locker).structure() || !newDescriptor.structure());

    // We are changing the type, so make sure that if anyone was watching, they find out about it now. If
    // anyone is watching, we make sure to go to Top so that we don't do this sort of thing again.
    if (m_watchpointSet.state() != ClearWatchpoint) {
        // We cannot have been invalidated, since if we were, then we'd already be at Top.
        ASSERT(m_watchpointSet.state() != IsInvalidated);

        // We're about to do expensive things because some compiler thread decided to watch this type and
        // then the type changed. Assume that this property is crazy, and don't ever do any more things for
        // it.
        newDescriptor = Top;

        shouldFireWatchpointSet = true;
    }

    // Remove the old InferredStructure object if we no longer need it.
    if (!newDescriptor.structure())
        m_structure = nullptr;

    // Add a new InferredStructure object if we need one now.
    if (newDescriptor.structure()) {
        if (m_structure) {
            // We should agree on the structures if we get here.
            ASSERT(newDescriptor.structure() == m_structure->structure());
        } else {
            m_structure = adoptRef(new InferredStructure(vm, this, newDescriptor.structure()));
            newDescriptor.structure()->addTransitionWatchpoint(&m_structure->m_watchpoint);
        }
    }

    // Finally, set the descriptor kind.
    m_kind = newDescriptor.kind();

    // Assert that we did things.
    ASSERT(descriptor(locker) == newDescriptor);

    return shouldFireWatchpointSet;
}
Example #2
0
void InferredType::Descriptor::merge(const Descriptor& other)
{
    // Filter out common things to simplify the switch statement below.
    if (*this == other)
        return;
    if (other.m_kind == Bottom)
        return;

    switch (m_kind) {
    case Bottom:
        *this = other;
        return;
    case Boolean:
    case String:
    case Symbol:
        *this = Top;
        return;
    case Other:
        switch (other.m_kind) {
        case ObjectWithStructure:
        case ObjectWithStructureOrOther:
            *this = Descriptor(ObjectWithStructureOrOther, other.structure());
            return;
        case Object:
        case ObjectOrOther:
            *this = ObjectOrOther;
            return;
        default:
            *this = Top;
            return;
        }
    case Int32:
        switch (other.m_kind) {
        case Number:
            *this = Number;
            return;
        default:
            *this = Top;
            return;
        }
    case Number:
        switch (other.m_kind) {
        case Int32:
            return;
        default:
            *this = Top;
            return;
        }
    case ObjectWithStructure:
        switch (other.m_kind) {
        case ObjectWithStructure: // If we see this here, then we know that the structures didn't match.
        case Object:
            *this = Object;
            return;
        case ObjectWithStructureOrOther:
            if (m_structure == other.m_structure) {
                *this = other;
                return;
            }
            *this = ObjectOrOther;
            return;
        case ObjectOrOther:
            *this = ObjectOrOther;
            return;
        case Other:
            m_kind = ObjectWithStructureOrOther;
            return;
        default:
            *this = Top;
            return;
        }
    case ObjectWithStructureOrOther:
        switch (other.m_kind) {
        case ObjectWithStructure:
            if (m_structure == other.m_structure)
                return;
            *this = ObjectOrOther;
            return;
        case Object:
        case ObjectWithStructureOrOther: // If we see this here, then we know that the structures didn't match.
        case ObjectOrOther:
            *this = ObjectOrOther;
            return;
        case Other:
            return;
        default:
            *this = Top;
            return;
        }
    case Object:
        switch (other.m_kind) {
        case ObjectWithStructure:
            return;
        case ObjectWithStructureOrOther:
        case ObjectOrOther:
        case Other:
            *this = ObjectOrOther;
            return;
        default:
            *this = Top;
            return;
        }
    case ObjectOrOther:
        switch (other.m_kind) {
        case ObjectWithStructure:
        case ObjectWithStructureOrOther:
        case Object:
        case Other:
            return;
        default:
            *this = Top;
            return;
        }
    case Top:
        return;
    }

    RELEASE_ASSERT_NOT_REACHED();
}