예제 #1
0
파일: Deque.cpp 프로젝트: cheekiatng/webkit
TEST(WTF_Deque, Remove)
{
    Deque<int> deque;
    deque.append(11);
    deque.prepend(10);
    deque.append(12);
    deque.append(13);

    EXPECT_EQ(10, deque.first());
    EXPECT_EQ(13, deque.last());

    deque.removeLast();
    EXPECT_EQ(10, deque.first());
    EXPECT_EQ(12, deque.last());

    deque.removeFirst();
    EXPECT_EQ(11, deque.first());
    EXPECT_EQ(12, deque.last());

    deque.removeFirst();
    EXPECT_EQ(12, deque.first());
    EXPECT_EQ(12, deque.last());

    deque.removeLast();
    EXPECT_TRUE(deque.isEmpty());
}
예제 #2
0
bool AccessibilityTree::isTreeValid() const
{
    // A valid tree can only have treeitem or group of treeitems as a child
    // http://www.w3.org/TR/wai-aria/roles#tree

    Node* node = this->node();
    if (!node)
        return false;
    
    Deque<Node*> queue;
    for (auto child = node->firstChild(); child; child = child->nextSibling())
        queue.append(child);

    while (!queue.isEmpty()) {
        auto child = queue.takeFirst();

        if (!is<Element>(*child))
            continue;
        if (nodeHasRole(child, "treeitem"))
            continue;
        if (!nodeHasRole(child, "group"))
            return false;

        for (auto groupChild = child->firstChild(); groupChild; groupChild = groupChild->nextSibling())
            queue.append(groupChild);
    }
    return true;
}
void HistoryController::goToItem(HistoryItem* targetItem, ResourceRequestCachePolicy cachePolicy)
{
    if (m_defersLoading) {
        m_deferredItem = targetItem;
        m_deferredCachePolicy = cachePolicy;
        return;
    }

    OwnPtr<HistoryEntry> newEntry = HistoryEntry::create(targetItem);
    Deque<HistoryNode*> historyNodes;
    historyNodes.append(newEntry->rootHistoryNode());
    while (!historyNodes.isEmpty()) {
        // For each item, read the children (if any) off the HistoryItem,
        // create a new HistoryNode for each child and attach it,
        // then clear the children on the HistoryItem.
        HistoryNode* historyNode = historyNodes.takeFirst();
        const HistoryItemVector& children = historyNode->value()->children();
        for (size_t i = 0; i < children.size(); i++) {
            HistoryNode* childHistoryNode = historyNode->addChild(children[i].get());
            historyNodes.append(childHistoryNode);
        }
        historyNode->value()->clearChildren();
    }
    goToEntry(newEntry.release(), cachePolicy);
}
예제 #4
0
void DOMPatchSupport::markNodeAsUsed(Digest* digest)
{
    Deque<Digest*> queue;
    queue.append(digest);
    while (!queue.isEmpty()) {
        Digest* first = queue.takeFirst();
        m_unusedNodesMap.remove(first->m_sha1);
        for (size_t i = 0; i < first->m_children.size(); ++i)
            queue.append(first->m_children[i].get());
    }
}
예제 #5
0
void EventSender::mouseUp(const CppArgumentList& arguments, CppVariant* result)
{
    if (result) // Could be 0 if invoked asynchronously.
        result->setNull();

    webview()->layout();

    int buttonNumber = getButtonNumberFromSingleArg(arguments);
    ASSERT(buttonNumber != -1);

    WebMouseEvent::Button buttonType = getButtonTypeFromButtonNumber(buttonNumber);

    if (isDragMode() && !replayingSavedEvents) {
        SavedEvent savedEvent;
        savedEvent.type = SavedEvent::MouseUp;
        savedEvent.buttonType = buttonType;
        mouseEventQueue.append(savedEvent);
        replaySavedEvents();
    } else {
        WebMouseEvent event;
        initMouseEvent(WebInputEvent::MouseUp, buttonType, lastMousePos, &event);
        if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isString()))
            applyKeyModifiers(&(arguments[1]), &event);
        doMouseUp(event);
    }
}
예제 #6
0
static void uriChangedCallback(WebKitWebPage* webPage, GParamSpec* pspec, WebKitWebExtension* extension)
{
    gpointer data = g_object_get_data(G_OBJECT(extension), "dbus-connection");
    if (data)
        emitURIChanged(G_DBUS_CONNECTION(data), webkit_web_page_get_uri(webPage));
    else
        delayedSignalsQueue.append(adoptPtr(new DelayedSignal(URIChangedSignal, webkit_web_page_get_uri(webPage))));
}
예제 #7
0
static void documentLoadedCallback(WebKitWebPage*, WebKitWebExtension* extension)
{
    gpointer data = g_object_get_data(G_OBJECT(extension), "dbus-connection");
    if (data)
        emitDocumentLoaded(G_DBUS_CONNECTION(data));
    else
        delayedSignalsQueue.append(adoptPtr(new DelayedSignal(DocumentLoadedSignal)));
}
예제 #8
0
RefPtr<UniqueIDBDatabaseTransaction> UniqueIDBDatabase::takeNextRunnableTransaction(bool& hadDeferredTransactions)
{
    Deque<RefPtr<UniqueIDBDatabaseTransaction>> deferredTransactions;
    RefPtr<UniqueIDBDatabaseTransaction> currentTransaction;

    while (!m_pendingTransactions.isEmpty()) {
        currentTransaction = m_pendingTransactions.takeFirst();

        switch (currentTransaction->info().mode()) {
        case IndexedDB::TransactionMode::ReadOnly:
            // If there are any deferred transactions, the first one is a read-write transaction we need to unblock.
            // Therefore, skip this read-only transaction if its scope overlaps with that read-write transaction.
            if (!deferredTransactions.isEmpty()) {
                ASSERT(deferredTransactions.first()->info().mode() == IndexedDB::TransactionMode::ReadWrite);
                if (scopesOverlap(deferredTransactions.first()->objectStoreIdentifiers(), currentTransaction->objectStoreIdentifiers()))
                    deferredTransactions.append(WTF::move(currentTransaction));
            }

            break;
        case IndexedDB::TransactionMode::ReadWrite:
            // If this read-write transaction's scope overlaps with running transactions, it must be deferred.
            if (scopesOverlap(m_objectStoreTransactionCounts, currentTransaction->objectStoreIdentifiers()))
                deferredTransactions.append(WTF::move(currentTransaction));

            break;
        case IndexedDB::TransactionMode::VersionChange:
            // Version change transactions should never be scheduled in the traditional manner.
            RELEASE_ASSERT_NOT_REACHED();
        }

        // If we didn't defer the currentTransaction above, it can be run now.
        if (currentTransaction)
            break;
    }

    hadDeferredTransactions = !deferredTransactions.isEmpty();
    if (!hadDeferredTransactions)
        return WTF::move(currentTransaction);

    // Prepend the deferred transactions back on the beginning of the deque for future scheduling passes.
    while (!deferredTransactions.isEmpty())
        m_pendingTransactions.prepend(deferredTransactions.takeLast());

    return WTF::move(currentTransaction);
}
예제 #9
0
void CSSStyleSheet::addSubresourceStyleURLs(ListHashSet<KURL>& urls)
{
    Deque<CSSStyleSheet*> styleSheetQueue;
    styleSheetQueue.append(this);

    while (!styleSheetQueue.isEmpty()) {
        CSSStyleSheet* styleSheet = styleSheetQueue.takeFirst();

        for (unsigned i = 0; i < styleSheet->length(); ++i) {
            CSSRule* rule = styleSheet->item(i);
            if (rule->isImportRule()) {
                if (CSSStyleSheet* ruleStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet())
                    styleSheetQueue.append(ruleStyleSheet);
            }
            rule->addSubresourceStyleURLs(urls);
        }
    }
}
예제 #10
0
void FullscreenElementStack::fullScreenChangeDelayTimerFired(Timer<FullscreenElementStack>*)
{
    // Since we dispatch events in this function, it's possible that the
    // document will be detached and GC'd. We protect it here to make sure we
    // can finish the function successfully.
    RefPtr<Document> protectDocument(document());
    Deque<RefPtr<Node> > changeQueue;
    m_fullScreenChangeEventTargetQueue.swap(changeQueue);
    Deque<RefPtr<Node> > errorQueue;
    m_fullScreenErrorEventTargetQueue.swap(errorQueue);

    while (!changeQueue.isEmpty()) {
        RefPtr<Node> node = changeQueue.takeFirst();
        if (!node)
            node = document()->documentElement();
        // The dispatchEvent below may have blown away our documentElement.
        if (!node)
            continue;

        // If the element was removed from our tree, also message the documentElement. Since we may
        // have a document hierarchy, check that node isn't in another document.
        if (!document()->contains(node.get()) && !node->inDocument())
            changeQueue.append(document()->documentElement());

        node->dispatchEvent(Event::createBubble(eventNames().webkitfullscreenchangeEvent));
    }

    while (!errorQueue.isEmpty()) {
        RefPtr<Node> node = errorQueue.takeFirst();
        if (!node)
            node = document()->documentElement();
        // The dispatchEvent below may have blown away our documentElement.
        if (!node)
            continue;

        // If the element was removed from our tree, also message the documentElement. Since we may
        // have a document hierarchy, check that node isn't in another document.
        if (!document()->contains(node.get()) && !node->inDocument())
            errorQueue.append(document()->documentElement());

        node->dispatchEvent(Event::createBubble(eventNames().webkitfullscreenerrorEvent));
    }
}
예제 #11
0
void SavedFormState::appendControlState(const AtomicString& name, const AtomicString& type, const FormControlState& state)
{
    FormElementKey key(name.impl(), type.impl());
    FormElementStateMap::iterator it = m_stateForNewFormElements.find(key);
    if (it != m_stateForNewFormElements.end()) {
        it->value.append(state);
    } else {
        Deque<FormControlState> stateList;
        stateList.append(state);
        m_stateForNewFormElements.set(key, stateList);
    }
    m_controlStateCount++;
}
예제 #12
0
파일: Deque.cpp 프로젝트: cheekiatng/webkit
TEST(WTF, DequeReverseIterator)
{
    Deque<int> deque;
    deque.append(11);
    deque.prepend(10);
    deque.append(12);
    deque.append(13);

    Deque<int>::reverse_iterator it = deque.rbegin();
    Deque<int>::reverse_iterator end = deque.rend();
    EXPECT_TRUE(end != it);

    EXPECT_EQ(13, *it);
    ++it;
    EXPECT_EQ(12, *it);
    ++it;
    EXPECT_EQ(11, *it);
    ++it;
    EXPECT_EQ(10, *it);
    ++it;

    EXPECT_TRUE(end == it);
}
예제 #13
0
파일: Deque.cpp 프로젝트: cheekiatng/webkit
TEST(WTF_Deque, Iterator)
{
    Deque<int> deque;
    deque.append(11);
    deque.prepend(10);
    deque.append(12);
    deque.append(13);

    Deque<int>::iterator it = deque.begin();
    Deque<int>::iterator end = deque.end();
    EXPECT_TRUE(end != it);

    EXPECT_EQ(10, *it);
    ++it;
    EXPECT_EQ(11, *it);
    ++it;
    EXPECT_EQ(12, *it);
    ++it;
    EXPECT_EQ(13, *it);
    ++it;

    EXPECT_TRUE(end == it);
}
예제 #14
0
void HistoryController::goToItem(HistoryItem* targetItem, ResourceRequestCachePolicy cachePolicy)
{
    // We don't have enough information to set a correct frame id here. This might be a restore from
    // disk, and the frame ids might not match up if the state was saved from a different process.
    // Ensure the HistoryEntry's main frame id matches the actual main frame id. Its subframe ids
    // are invalid to ensure they don't accidentally match a potentially random frame.
    OwnPtr<HistoryEntry> newEntry = HistoryEntry::create(targetItem, m_page->mainFrame()->frameID());
    Deque<HistoryNode*> historyNodes;
    historyNodes.append(newEntry->rootHistoryNode());
    while (!historyNodes.isEmpty()) {
        // For each item, read the children (if any) off the HistoryItem,
        // create a new HistoryNode for each child and attach it,
        // then clear the children on the HistoryItem.
        HistoryNode* historyNode = historyNodes.takeFirst();
        const HistoryItemVector& children = historyNode->value()->deprecatedChildren();
        for (size_t i = 0; i < children.size(); i++) {
            HistoryNode* childHistoryNode = historyNode->addChild(children[i].get(), -1);
            historyNodes.append(childHistoryNode);
        }
        historyNode->value()->deprecatedClearChildren();
    }
    goToEntry(newEntry.release(), cachePolicy);
}
예제 #15
0
void AccessibilityTable::addChildrenFromSection(RenderTableSection* tableSection, unsigned& maxColumnCount)
{
    ASSERT(tableSection);
    if (!tableSection)
        return;
    
    AXObjectCache* axCache = m_renderer->document().axObjectCache();
    HashSet<AccessibilityObject*> appendedRows;
    unsigned numRows = tableSection->numRows();
    for (unsigned rowIndex = 0; rowIndex < numRows; ++rowIndex) {
        
        RenderTableRow* renderRow = tableSection->rowRendererAt(rowIndex);
        if (!renderRow)
            continue;
        
        AccessibilityObject& rowObject = *axCache->getOrCreate(renderRow);
        
        // If the row is anonymous, we should dive deeper into the descendants to try to find a valid row.
        if (renderRow->isAnonymous()) {
            Deque<AccessibilityObject*> queue;
            queue.append(&rowObject);
            
            while (!queue.isEmpty()) {
                AccessibilityObject* obj = queue.takeFirst();
                if (obj->node() && is<AccessibilityTableRow>(*obj)) {
                    addTableCellChild(obj, appendedRows, maxColumnCount);
                    continue;
                }
                for (auto child = obj->firstChild(); child; child = child->nextSibling())
                    queue.append(child);
            }
        } else
            addTableCellChild(&rowObject, appendedRows, maxColumnCount);
    }
    
    maxColumnCount = std::max(tableSection->numColumns(), maxColumnCount);
}
예제 #16
0
void CSSStyleSheet::addSubresourceStyleURLs(ListHashSet<KURL>& urls)
{
    Deque<CSSStyleSheet*> styleSheetQueue;
    styleSheetQueue.append(this);

    while (!styleSheetQueue.isEmpty()) {
        CSSStyleSheet* styleSheet = styleSheetQueue.takeFirst();
        
        for (unsigned i = 0; i < styleSheet->m_importRules.size(); ++i) {
            StyleRuleImport* importRule = styleSheet->m_importRules[i].get();
            if (importRule->styleSheet()) {
                styleSheetQueue.append(importRule->styleSheet());
                addSubresourceURL(urls, importRule->styleSheet()->baseURL());
            }
        }
        for (unsigned i = 0; i < styleSheet->m_childRules.size(); ++i) {
            StyleRuleBase* rule = styleSheet->m_childRules[i].get();
            if (rule->isStyleRule())
                static_cast<StyleRule*>(rule)->properties()->addSubresourceStyleURLs(urls, this);
            else if (rule->isFontFaceRule())
                static_cast<StyleRuleFontFace*>(rule)->properties()->addSubresourceStyleURLs(urls, this);
        }
    }
}
예제 #17
0
void EventSender::leapForward(const CppArgumentList& arguments, CppVariant* result)
{
    result->setNull();

    if (arguments.size() < 1 || !arguments[0].isNumber())
        return;

    int milliseconds = arguments[0].toInt32();
    if (isDragMode() && pressedButton == WebMouseEvent::ButtonLeft && !replayingSavedEvents) {
        SavedEvent savedEvent;
        savedEvent.type = SavedEvent::LeapForward;
        savedEvent.milliseconds = milliseconds;
        mouseEventQueue.append(savedEvent);
    } else
        doLeapForward(milliseconds);
}
예제 #18
0
파일: Deque.cpp 프로젝트: cheekiatng/webkit
TEST(WTF_Deque, MoveOnly)
{
    Deque<MoveOnly> deque;

    deque.append(MoveOnly(1));
    deque.prepend(MoveOnly(0));

    EXPECT_EQ(0U, deque.first().value());
    EXPECT_EQ(1U, deque.last().value());

    auto first = deque.takeFirst();
    EXPECT_EQ(0U, first.value());

    auto last = deque.takeLast();
    EXPECT_EQ(1U, last.value());
}
예제 #19
0
void Worklist::removeDeadPlans(VM& vm)
{
    {
        LockHolder locker(m_lock);
        HashSet<CompilationKey> deadPlanKeys;
        for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) {
            Plan* plan = iter->value.get();
            if (&plan->vm != &vm)
                continue;
            if (plan->isKnownToBeLiveDuringGC())
                continue;
            RELEASE_ASSERT(plan->stage != Plan::Cancelled); // Should not be cancelled, yet.
            ASSERT(!deadPlanKeys.contains(plan->key()));
            deadPlanKeys.add(plan->key());
        }
        if (!deadPlanKeys.isEmpty()) {
            for (HashSet<CompilationKey>::iterator iter = deadPlanKeys.begin(); iter != deadPlanKeys.end(); ++iter)
                m_plans.take(*iter)->cancel();
            Deque<RefPtr<Plan>> newQueue;
            while (!m_queue.isEmpty()) {
                RefPtr<Plan> plan = m_queue.takeFirst();
                if (plan->stage != Plan::Cancelled)
                    newQueue.append(plan);
            }
            m_queue.swap(newQueue);
            for (unsigned i = 0; i < m_readyPlans.size(); ++i) {
                if (m_readyPlans[i]->stage != Plan::Cancelled)
                    continue;
                m_readyPlans[i] = m_readyPlans.last();
                m_readyPlans.removeLast();
            }
        }
    }
    
    // No locking needed for this part, see comment in visitWeakReferences().
    for (unsigned i = m_threads.size(); i--;) {
        ThreadData* data = m_threads[i].get();
        Safepoint* safepoint = data->m_safepoint;
        if (!safepoint)
            continue;
        if (&safepoint->vm() != &vm)
            continue;
        if (safepoint->isKnownToBeLiveDuringGC())
            continue;
        safepoint->cancel();
    }
}
예제 #20
0
void DatabaseThread::unscheduleDatabaseTasks(Database* database)
{
    // Note that the thread loop is running, so some tasks for the database
    // may still be executed. This is unavoidable.

    Deque<RefPtr<DatabaseTask> > filteredReverseQueue;
    RefPtr<DatabaseTask> task;
    while (m_queue.tryGetMessage(task)) {
        if (task->database() != database)
            filteredReverseQueue.append(task);
    }

    while (!filteredReverseQueue.isEmpty()) {
        m_queue.append(filteredReverseQueue.first());
        filteredReverseQueue.removeFirst();
    }
}
예제 #21
0
파일: Deque.cpp 프로젝트: cheekiatng/webkit
TEST(WTF_Deque, MoveConstructor)
{
    Deque<MoveOnly, 4> deque;

    for (unsigned i = 0; i < 10; ++i)
        deque.append(MoveOnly(i));

    EXPECT_EQ(10u, deque.size());

    Deque<MoveOnly, 4> deque2 = WTF::move(deque);

    EXPECT_EQ(10u, deque2.size());

    unsigned i = 0;
    for (auto& element : deque2) {
        EXPECT_EQ(i, element.value());
        ++i;
    }
}
예제 #22
0
static void documentLoadedCallback(WebKitWebPage* webPage, WebKitWebExtension* extension)
{
    // FIXME: Too much code just to send a message, we need convenient custom API for this.
    WebKitDOMDocument* document = webkit_web_page_get_dom_document(webPage);
    GRefPtr<WebKitDOMDOMWindow> window = adoptGRef(webkit_dom_document_get_default_view(document));
    if (WebKitDOMWebKitNamespace* webkit = webkit_dom_dom_window_get_webkit_namespace(window.get())) {
        WebKitDOMUserMessageHandlersNamespace* messageHandlers = webkit_dom_webkit_namespace_get_message_handlers(webkit);
        if (WebKitDOMUserMessageHandler* handler = webkit_dom_user_message_handlers_namespace_get_handler(messageHandlers, "dom"))
            webkit_dom_user_message_handler_post_message(handler, "DocumentLoaded", nullptr);
    }

    webkit_dom_dom_window_webkit_message_handlers_post_message(window.get(), "dom-convenience", "DocumentLoaded");

    gpointer data = g_object_get_data(G_OBJECT(extension), "dbus-connection");
    if (data)
        emitDocumentLoaded(G_DBUS_CONNECTION(data));
    else
        delayedSignalsQueue.append(DelayedSignal(DocumentLoadedSignal));
}
예제 #23
0
void EventSender::mouseMoveTo(const CppArgumentList& arguments, CppVariant* result)
{
    result->setNull();

    if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
        return;
    webview()->layout();

    WebPoint mousePos(arguments[0].toInt32(), arguments[1].toInt32());

    if (isDragMode() && pressedButton == WebMouseEvent::ButtonLeft && !replayingSavedEvents) {
        SavedEvent savedEvent;
        savedEvent.type = SavedEvent::MouseMove;
        savedEvent.pos = mousePos;
        mouseEventQueue.append(savedEvent);
    } else {
        WebMouseEvent event;
        initMouseEvent(WebInputEvent::MouseMove, pressedButton, mousePos, &event);
        doMouseMove(event);
    }
}
예제 #24
0
파일: WebSocket.cpp 프로젝트: kublaj/blink
void WebSocket::EventQueue::dispatchQueuedEvents()
{
    if (m_state != Active)
        return;

    RefPtr<EventQueue> protect(this);

    Deque<RefPtr<Event> > events;
    events.swap(m_events);
    while (!events.isEmpty()) {
        if (m_state == Stopped || m_state == Suspended)
            break;
        ASSERT(m_state == Active);
        ASSERT(m_target->executionContext());
        m_target->dispatchEvent(events.takeFirst());
        // |this| can be stopped here.
    }
    if (m_state == Suspended) {
        while (!m_events.isEmpty())
            events.append(m_events.takeFirst());
        events.swap(m_events);
    }
}
예제 #25
0
inline bool RunLoop::populateTasks(RunMode runMode, Status& statusOfThisLoop, Deque<RefPtr<TimerBase::ScheduledTask>>& firedTimers)
{
    LockHolder locker(m_loopLock);

    if (runMode == RunMode::Drain) {
        MonotonicTime sleepUntil = MonotonicTime::infinity();
        if (!m_schedules.isEmpty())
            sleepUntil = m_schedules.first()->scheduledTimePoint();

        m_readyToRun.waitUntil(m_loopLock, sleepUntil, [&] {
            return m_shutdown || m_pendingTasks || statusOfThisLoop == Status::Stopping;
        });
    }

    if (statusOfThisLoop == Status::Stopping || m_shutdown) {
        m_mainLoops.removeLast();
        if (m_mainLoops.isEmpty())
            m_stopCondition.notifyOne();
        return false;
    }
    m_pendingTasks = false;
    if (runMode == RunMode::Iterate)
        statusOfThisLoop = Status::Stopping;

    // Check expired timers.
    MonotonicTime now = MonotonicTime::now();
    while (!m_schedules.isEmpty()) {
        RefPtr<TimerBase::ScheduledTask> earliest = m_schedules.first();
        if (earliest->scheduledTimePoint() > now)
            break;
        std::pop_heap(m_schedules.begin(), m_schedules.end(), TimerBase::ScheduledTask::EarliestSchedule());
        m_schedules.removeLast();
        firedTimers.append(WTFMove(earliest));
    }

    return true;
}
예제 #26
0
// Sorts the given list of layers such that they can be painted in a back-to-front
// order. Sorting produces correct results for non-intersecting layers that don't have
// cyclical order dependencies. Cycles and intersections are broken (somewhat) aribtrarily.
// Sorting of layers is done via a topological sort of a directed graph whose nodes are
// the layers themselves. An edge from node A to node B signifies that layer A needs to
// be drawn before layer B. If A and B have no dependency between each other, then we
// preserve the ordering of those layers as they were in the original list.
//
// The draw order between two layers is determined by projecting the two triangles making
// up each layer quad to the Z = 0 plane, finding points of intersection between the triangles
// and backprojecting those points to the plane of the layer to determine the corresponding Z
// coordinate. The layer with the lower Z coordinate (farther from the eye) needs to be rendered
// first.
//
// If the layer projections don't intersect, then no edges (dependencies) are created
// between them in the graph. HOWEVER, in this case we still need to preserve the ordering
// of the original list of layers, since that list should already have proper z-index
// ordering of layers.
//
void CCLayerSorter::sort(LayerList::iterator first, LayerList::iterator last)
{
#if !defined( NDEBUG )
    LOG(CCLayerSorter, "Sorting start ----\n");
#endif
    createGraphNodes(first, last);

    createGraphEdges();

    Vector<GraphNode*> sortedList;
    Deque<GraphNode*> noIncomingEdgeNodeList;

    // Find all the nodes that don't have incoming edges.
    for (NodeList::iterator la = m_nodes.begin(); la < m_nodes.end(); la++) {
        if (!la->incoming.size())
            noIncomingEdgeNodeList.append(la);
    }

#if !defined( NDEBUG )
    LOG(CCLayerSorter, "Sorted list: ");
#endif
    while (m_activeEdges.size() || noIncomingEdgeNodeList.size()) {
        while (noIncomingEdgeNodeList.size()) {

            // It is necessary to preserve the existing ordering of layers, when there are
            // no explicit dependencies (because this existing ordering has correct
            // z-index/layout ordering). To preserve this ordering, we process Nodes in
            // the same order that they were added to the list.
            GraphNode* fromNode = noIncomingEdgeNodeList.takeFirst();

            // Add it to the final list.
            sortedList.append(fromNode);

#if !defined( NDEBUG )
            LOG(CCLayerSorter, "%d, ", fromNode->layer->debugID());
#endif

            // Remove all its outgoing edges from the graph.
            for (unsigned i = 0; i < fromNode->outgoing.size(); i++) {
                GraphEdge* outgoingEdge = fromNode->outgoing[i];

                m_activeEdges.remove(outgoingEdge);
                removeEdgeFromList(outgoingEdge, outgoingEdge->to->incoming);
                outgoingEdge->to->incomingEdgeWeight -= outgoingEdge->weight;

                if (!outgoingEdge->to->incoming.size())
                    noIncomingEdgeNodeList.append(outgoingEdge->to);
            }
            fromNode->outgoing.clear();
        }

        if (!m_activeEdges.size())
            break;

        // If there are still active edges but the list of nodes without incoming edges
        // is empty then we have run into a cycle. Break the cycle by finding the node
        // with the smallest overall incoming edge weight and use it. This will favor
        // nodes that have zero-weight incoming edges i.e. layers that are being
        // occluded by a layer that intersects them.
        float minIncomingEdgeWeight = FLT_MAX;
        GraphNode* nextNode = 0;
        for (unsigned i = 0; i < m_nodes.size(); i++) {
            if (m_nodes[i].incoming.size() && m_nodes[i].incomingEdgeWeight < minIncomingEdgeWeight) {
                minIncomingEdgeWeight = m_nodes[i].incomingEdgeWeight;
                nextNode = &m_nodes[i];
            }
        }
        ASSERT(nextNode);
        // Remove all its incoming edges.
        for (unsigned e = 0; e < nextNode->incoming.size(); e++) {
            GraphEdge* incomingEdge = nextNode->incoming[e];

            m_activeEdges.remove(incomingEdge);
            removeEdgeFromList(incomingEdge, incomingEdge->from->outgoing);
        }
        nextNode->incoming.clear();
        nextNode->incomingEdgeWeight = 0;
        noIncomingEdgeNodeList.append(nextNode);
#if !defined( NDEBUG )
        LOG(CCLayerSorter, "Breaking cycle by cleaning up incoming edges from %d (weight = %f)\n", nextNode->layer->debugID(), minIncomingEdgeWeight);
#endif
    }

    // Note: The original elements of the list are in no danger of having their ref count go to zero
    // here as they are all nodes of the layer hierarchy and are kept alive by their parent nodes.
    int count = 0;
    for (LayerList::iterator it = first; it < last; it++)
        *it = sortedList[count++]->layer;

#if !defined( NDEBUG )
    LOG(CCLayerSorter, "Sorting end ----\n");
#endif

    m_nodes.clear();
    m_edges.clear();
    m_activeEdges.clear();
}
예제 #27
0
static PassOwnPtr<ArgumentDecoder> createArgumentDecoder(mach_msg_header_t* header)
{
    if (!(header->msgh_bits & MACH_MSGH_BITS_COMPLEX)) {
        // We have a simple message.
        size_t bodySize = header->msgh_size - sizeof(mach_msg_header_t);
        uint8_t* body = reinterpret_cast<uint8_t*>(header + 1);
        
        return adoptPtr(new ArgumentDecoder(body, bodySize));
    }

    bool messageBodyIsOOL = header->msgh_id & MessageBodyIsOOL;

    mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1);
    mach_msg_size_t numDescriptors = body->msgh_descriptor_count;
    ASSERT(numDescriptors);

    // Build attachment list
    Deque<Attachment> attachments;
    uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1);

    // If the message body was sent out-of-line, don't treat the last descriptor
    // as an attachment, since it is really the message body.
    if (messageBodyIsOOL)
        --numDescriptors;

    for (mach_msg_size_t i = 0; i < numDescriptors; ++i) {
        mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);

        switch (descriptor->type.type) {
        case MACH_MSG_PORT_DESCRIPTOR:
            attachments.append(Attachment(descriptor->port.name, descriptor->port.disposition));
            descriptorData += sizeof(mach_msg_port_descriptor_t);
            break;
        case MACH_MSG_OOL_DESCRIPTOR:
            attachments.append(Attachment(descriptor->out_of_line.address, descriptor->out_of_line.size,
                                          descriptor->out_of_line.copy, descriptor->out_of_line.deallocate));
            descriptorData += sizeof(mach_msg_ool_descriptor_t);
            break;
        default:
            ASSERT(false && "Unhandled descriptor type");
        }
    }

    if (messageBodyIsOOL) {
        mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
        ASSERT(descriptor->type.type == MACH_MSG_OOL_DESCRIPTOR);
        Attachment messageBodyAttachment(descriptor->out_of_line.address, descriptor->out_of_line.size,
                                         descriptor->out_of_line.copy, descriptor->out_of_line.deallocate);

        uint8_t* messageBody = static_cast<uint8_t*>(messageBodyAttachment.address());
        size_t messageBodySize = messageBodyAttachment.size();

        ArgumentDecoder* argumentDecoder;

        if (attachments.isEmpty())
            argumentDecoder = new ArgumentDecoder(messageBody, messageBodySize);
        else
            argumentDecoder = new ArgumentDecoder(messageBody, messageBodySize, attachments);

        vm_deallocate(mach_task_self(), reinterpret_cast<vm_address_t>(messageBodyAttachment.address()), messageBodyAttachment.size());

        return adoptPtr(argumentDecoder);
    }

    uint8_t* messageBody = descriptorData;
    size_t messageBodySize = header->msgh_size - (descriptorData - reinterpret_cast<uint8_t*>(header));

    return adoptPtr(new ArgumentDecoder(messageBody, messageBodySize, attachments));
}