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()); }
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); }
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()); } }
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); } }
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)))); }
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))); }
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); }
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); } } }
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)); } }
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++; }
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); }
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); }
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); }
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); }
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); } } }
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); }
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()); }
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(); } }
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(); } }
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; } }
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)); }
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); } }
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); } }
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; }
// 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(); }
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)); }