Changeset 48701 in webkit for trunk/JavaScriptCore/wtf/Vector.h


Ignore:
Timestamp:
Sep 23, 2009, 10:53:23 PM (16 years ago)
Author:
[email protected]
Message:

JavaScriptCore: Added the ability to swap vectors with inline capacities, so you can
store a vector with inline capacity in a hash table.

Patch by Geoffrey Garen <[email protected]> on 2009-09-23
Reviewed by Sam Weinig.

  • wtf/Vector.h:

(WTF::swap):
(WTF::VectorBuffer::swap):

WebCore: Bring a little sanity to this crazy EventTarget world of ours
https://bugs.webkit.org/show_bug.cgi?id=29701

Patch by Geoffrey Garen <[email protected]> on 2009-09-23
Reviewed by Sam Weinig.

Lots of EventTarget refactoring to achieve a single shared implementation
that fixes some of the performance and correctness bugs of the many individual
implementations, and makes reasoning about EventTargets and EventListeners
much easier.

The basic design is this:

  • EventTarget manages a set of EventListeners.
  • onXXX EventListener attributes forward to standard EventTarget APIs.
  • Since the onXXX code is repetitive, it is usually done with macros of the form DEFINE_ATTRIBUTE_EVENT_LISTENER(attributeName).
  • EventTarget provides a shared implementation of dispatchEvent, which subclasses with special event dispatch rules, like Node, override.
  • To support Node, which lazily instantiates its EventTarget data, EventTarget has no data members, and instead makes a virtual call to get its data from wherever its subclass chose to store it.


Code that used to call dispatchEvent, passing an ExceptionCode paratmeter,
even though no exception could be thrown, has been changed not to do so,
to improve clarity and performance.

Code that used to call a special dispatchXXXEvent function, which just
turned around and called dispatchEvent, has been changed to call
dispatchEvent, to improve clarity and performance.

  • WebCore.base.exp:
  • WebCore.xcodeproj/project.pbxproj: Another day in the life of a WebKit

engineer.

  • bindings/js/JSDOMBinding.cpp:

(WebCore::isObservableThroughDOM): Updated for Node API change. Added
"is not in the document but is firing event listeners" as a condition
that makes a Node observable in the DOM, so that event listeners firing
on removed nodes are not destroyed midstream. (This was a long-standing
bug that was somewhat hidden by the old implementation's habit of
copying the RegisteredEventListener vector before firing events, which
would keep almost all the relevant objects from being destroyed.)

  • bindings/js/JSEventListener.cpp:

(WebCore::JSEventListener::handleEvent): Removed the isWindowEvent flag
because it was one of the most elaborately planned no-ops in the history
of software crime, and one of the reasons clients thought they needed more
than one dispatchEvent function even though they didn't.

  • bindings/js/JSEventListener.h:
  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::JSDOMWindow::markChildren):
(WebCore::JSMessagePort::markChildren):

  • bindings/js/JSNodeCustom.cpp:

(WebCore::JSNode::markChildren):

  • bindings/js/JSAbstractWorkerCustom.cpp:
  • bindings/js/JSDOMApplicationCacheCustom.cpp:
  • bindings/js/JSDedicatedWorkerContextCustom.cpp:
  • bindings/js/JSEventSourceCustom.cpp:
  • bindings/js/JSMessagePortCustom.cpp:
  • bindings/js/JSSharedWorkerContextCustom.cpp: Removed.
  • bindings/js/JSWebSocketCustom.cpp:
  • bindings/js/JSWorkerContextCustom.cpp:

(WebCore::JSWorkerContext::markChildren):

  • bindings/js/JSWorkerCustom.cpp:
  • bindings/js/JSXMLHttpRequestCustom.cpp:

(WebCore::JSXMLHttpRequest::markChildren):

  • bindings/js/JSXMLHttpRequestUploadCustom.cpp:

(WebCore::JSXMLHttpRequestUpload::markChildren): EventListener marking is
now autogenerated. Classes that still have custom mark functions for other
reasons now call a shared EventTarget API to mark their EventListeners.

  • bindings/objc/ObjCEventListener.h:
  • bindings/objc/ObjCEventListener.mm:

(WebCore::ObjCEventListener::handleEvent): Bye bye isWindowEvent.

  • bindings/scripts/CodeGeneratorJS.pm: Autogeneration support for

marking and invalidating event listeners.

  • dom/CharacterData.cpp:

(WebCore::CharacterData::dispatchModifiedEvent):

  • dom/ContainerNode.cpp:

(WebCore::ContainerNode::insertBefore):
(WebCore::ContainerNode::replaceChild):
(WebCore::willRemoveChild):
(WebCore::ContainerNode::appendChild):
(WebCore::dispatchChildInsertionEvents):
(WebCore::dispatchChildRemovalEvents):

  • dom/Document.cpp:

(WebCore::Document::removeAllEventListeners):
(WebCore::Document::implicitClose):
(WebCore::Document::setFocusedNode):
(WebCore::Document::dispatchWindowEvent):
(WebCore::Document::dispatchWindowLoadEvent):
(WebCore::Document::finishedParsing):

  • dom/Document.h: Use dispatchEvent directly.
  • dom/Element.h: Moved a few event listener attributes down from Node,

since they don't apply to all Nodes, only Elements.

  • dom/EventListener.h: Removed isWindowEvent parameter.
  • dom/EventNames.h: Added the "display" event name, so it works correctly

with attribute macros, and for performance.

  • dom/EventTarget.cpp:

(WebCore::forbidEventDispatch):
(WebCore::allowEventDispatch):
(WebCore::eventDispatchForbidden): Made this code (embarrasingly) thread
safe, since it's now called on multiple threads. (Currently, we only forbid
event dispatch on the main thread. If we ever want to forbid event dispatch
on secondary threads, we can improve it then.)

(WebCore::EventTarget::addEventListener):
(WebCore::EventTarget::removeEventListener):
(WebCore::EventTarget::setAttributeEventListener):
(WebCore::EventTarget::getAttributeEventListener):
(WebCore::EventTarget::clearAttributeEventListener):
(WebCore::EventTarget::dispatchEvent):
(WebCore::EventTarget::fireEventListeners):
(WebCore::EventTarget::getEventListeners):
(WebCore::EventTarget::removeAllEventListeners):

  • dom/EventTarget.h:

(WebCore::FiringEventEndIterator::FiringEventEndIterator):
(WebCore::EventTarget::ref):
(WebCore::EventTarget::deref):
(WebCore::EventTarget::markEventListeners):
(WebCore::EventTarget::invalidateEventListeners):
(WebCore::EventTarget::isFiringEventListeners):
(WebCore::EventTarget::hasEventListeners): The ONE TRUE IMPLEMENTATION of
EventTarget APIs, crafted from an amalgam of all the different versions
we used to have. The most significant change here is that we no longer
make a copy of an EventListener vector before firing the events in the
vector -- instead, we use a reference to the original vector, along with
a notification mechanism for the unlikely case when an EventListener is
removed from the vector. This substantially reduces malloc, copying, and
refcount overhead, and complexity.

  • dom/InputElement.cpp:

(WebCore::InputElement::setValueFromRenderer):

  • dom/MessageEvent.h:

(WebCore::MessageEvent::create): Use dispatchEvent directly.

  • dom/MessagePort.cpp:

(WebCore::MessagePort::dispatchMessages):
(WebCore::MessagePort::eventTargetData):
(WebCore::MessagePort::ensureEventTargetData):

  • dom/MessagePort.h:

(WebCore::MessagePort::setOnmessage):
(WebCore::MessagePort::onmessage):

  • dom/MessagePort.idl: Removed custom EventTarget implementation.
  • dom/MutationEvent.h:

(WebCore::MutationEvent::create): Added some default values so callers
can construct MutationEvents more easily, without calling a custom dispatch
function.

  • dom/Node.cpp:

(WebCore::Node::addEventListener):
(WebCore::Node::removeEventListener):
(WebCore::Node::eventTargetData):
(WebCore::Node::ensureEventTargetData):
(WebCore::Node::handleLocalEvents):
(WebCore::Node::dispatchEvent):
(WebCore::Node::dispatchGenericEvent):
(WebCore::Node::dispatchSubtreeModifiedEvent):
(WebCore::Node::dispatchUIEvent):
(WebCore::Node::dispatchKeyEvent):
(WebCore::Node::dispatchMouseEvent):
(WebCore::Node::dispatchWheelEvent):
(WebCore::Node::dispatchFocusEvent):
(WebCore::Node::dispatchBlurEvent):

  • dom/Node.h:

(WebCore::Node::preDispatchEventHandler):
(WebCore::Node::postDispatchEventHandler):

  • dom/Node.idl:
  • dom/NodeRareData.h:

(WebCore::NodeRareData::eventTargetData):
(WebCore::NodeRareData::ensureEventTargetData): Use the shared EventTarget
interface, and call dispatchEvent directly instead of custom dispatchXXXEvent
functions that just forwarded to dispatchEvent.

  • dom/RegisteredEventListener.cpp:
  • dom/RegisteredEventListener.h:

(WebCore::RegisteredEventListener::RegisteredEventListener):
(WebCore::operator==): This is just a simple struct now, since we no longer
do a complicated copy / refCount / isRemoved dance just to honor the rule
that an EventListener can be removed during event dispatch.

  • history/CachedFrame.cpp:

(WebCore::CachedFrameBase::restore): Removed another custom dispatchEvent.

  • html/HTMLBodyElement.cpp:
  • html/HTMLBodyElement.h: Use the shared EventTarget API.
  • html/HTMLFormControlElement.cpp:

(WebCore::HTMLFormControlElement::dispatchFormControlChangeEvent):
(WebCore::HTMLFormControlElement::checkValidity):

  • html/HTMLFormElement.cpp:

(WebCore::HTMLFormElement::handleLocalEvents):
(WebCore::HTMLFormElement::prepareSubmit):
(WebCore::HTMLFormElement::reset):

  • html/HTMLFormElement.h: Use the standard dispatchEvent API.
  • html/HTMLFrameSetElement.cpp:
  • html/HTMLFrameSetElement.h: Use the shared EventTarget API.
  • html/HTMLImageLoader.cpp:

(WebCore::HTMLImageLoader::dispatchLoadEvent):

  • html/HTMLInputElement.cpp:

(WebCore::HTMLInputElement::onSearch):

  • html/HTMLMediaElement.cpp:

(WebCore::HTMLMediaElement::loadInternal):

  • html/HTMLScriptElement.cpp:

(WebCore::HTMLScriptElement::dispatchLoadEvent):
(WebCore::HTMLScriptElement::dispatchErrorEvent):

  • html/HTMLSourceElement.cpp:

(WebCore::HTMLSourceElement::errorEventTimerFired):

  • html/HTMLTokenizer.cpp:

(WebCore::HTMLTokenizer::notifyFinished): Use the standard dispatchEvent API.

  • inspector/InspectorDOMAgent.cpp:

(WebCore::InspectorDOMAgent::handleEvent):

  • inspector/InspectorDOMAgent.h:
  • inspector/InspectorDOMStorageResource.cpp:

(WebCore::InspectorDOMStorageResource::handleEvent):

  • inspector/InspectorDOMStorageResource.h:
  • loader/FrameLoader.cpp:

(WebCore::FrameLoader::stopLoading):
(WebCore::FrameLoader::canCachePageContainingThisFrame):
(WebCore::FrameLoader::logCanCacheFrameDecision):
(WebCore::HashChangeEventTask::performTask):
(WebCore::FrameLoader::pageHidden): No more isWindowEvent.

  • loader/ImageDocument.cpp:

(WebCore::ImageEventListener::handleEvent):

  • loader/appcache/ApplicationCacheGroup.cpp:

(WebCore::CallCacheListenerTask::performTask):

  • loader/appcache/ApplicationCacheHost.cpp:

(WebCore::ApplicationCacheHost::notifyDOMApplicationCache):

  • loader/appcache/ApplicationCacheHost.h:
  • loader/appcache/DOMApplicationCache.cpp:

(WebCore::DOMApplicationCache::eventTargetData):
(WebCore::DOMApplicationCache::ensureEventTargetData):

  • loader/appcache/DOMApplicationCache.h:
  • loader/appcache/DOMApplicationCache.idl: Switched to the standard

EventTarget API. As a part of this, I switched this class from using a
custom internal event name enumeration to using the standard EventNames.

  • notifications/Notification.cpp:

(WebCore::Notification::eventTargetData):
(WebCore::Notification::ensureEventTargetData):

  • notifications/Notification.h:

(WebCore::Notification::scriptExecutionContext):

  • notifications/Notification.idl: Switched to the standard EventTarget API.
  • page/DOMWindow.cpp:

(WebCore::PostMessageTimer::event):
(WebCore::windowsWithUnloadEventListeners):
(WebCore::windowsWithBeforeUnloadEventListeners):
(WebCore::allowsBeforeUnloadListeners):
(WebCore::DOMWindow::dispatchAllPendingBeforeUnloadEvents):
(WebCore::DOMWindow::pendingUnloadEventListeners):
(WebCore::DOMWindow::dispatchAllPendingUnloadEvents): Changed the "pending"
unload / beforeunload listener tracker just to track which windows had
such listeners, instead of actually keeping a copy of the listeners. Now,
this code can use the standard EventTarget API.

(WebCore::DOMWindow::~DOMWindow):
(WebCore::DOMWindow::postMessageTimerFired):
(WebCore::DOMWindow::addEventListener):
(WebCore::DOMWindow::removeEventListener):
(WebCore::DOMWindow::dispatchLoadEvent):
(WebCore::DOMWindow::dispatchEvent):
(WebCore::DOMWindow::removeAllEventListeners):
(WebCore::DOMWindow::captureEvents):
(WebCore::DOMWindow::releaseEvents):
(WebCore::DOMWindow::eventTargetData):
(WebCore::DOMWindow::ensureEventTargetData):

  • page/DOMWindow.h:
  • page/DOMWindow.idl: Use the standard EventTarget APIs.
  • page/EventHandler.cpp:

(WebCore::EventHandler::canMouseDownStartSelect):
(WebCore::EventHandler::canMouseDragExtendSelect):
(WebCore::EventHandler::sendResizeEvent):
(WebCore::EventHandler::sendScrollEvent): Use dispatchEvent directly.

  • page/EventSource.cpp:

(WebCore::EventSource::endRequest):
(WebCore::EventSource::didReceiveResponse):
(WebCore::EventSource::parseEventStreamLine):
(WebCore::EventSource::stop):
(WebCore::EventSource::createMessageEvent):
(WebCore::EventSource::eventTargetData):
(WebCore::EventSource::ensureEventTargetData):

  • page/EventSource.h:
  • page/EventSource.idl: Use the standard EventTarget APIs.
  • page/FocusController.cpp:

(WebCore::dispatchEventsOnWindowAndFocusedNode):
(WebCore::FocusController::setFocusedFrame):

  • page/Frame.cpp:

(WebCore::Frame::shouldClose):

  • page/Frame.h:
  • page/Page.cpp:

(WebCore::networkStateChanged):

  • page/animation/AnimationController.cpp:

(WebCore::AnimationControllerPrivate::updateStyleIfNeededDispatcherFired):

  • rendering/RenderListBox.cpp:

(WebCore::RenderListBox::valueChanged):

  • rendering/RenderTextControl.cpp:

(WebCore::RenderTextControl::selectionChanged):

  • rendering/RenderTextControlMultiLine.cpp:

(WebCore::RenderTextControlMultiLine::subtreeHasChanged): Use dispatchEvent.

  • svg/SVGElement.cpp:

(WebCore::hasLoadListener): Rewritten for new EventTarget API.

  • svg/SVGElementInstance.cpp:

(WebCore::dummyEventTargetData):
(WebCore::SVGElementInstance::addEventListener):
(WebCore::SVGElementInstance::removeEventListener):
(WebCore::SVGElementInstance::removeAllEventListeners):
(WebCore::SVGElementInstance::dispatchEvent):
(WebCore::SVGElementInstance::eventTargetData):
(WebCore::SVGElementInstance::ensureEventTargetData): Use the EventTarget API.

  • svg/SVGElementInstance.h:
  • svg/SVGImageLoader.cpp:

(WebCore::SVGImageLoader::dispatchLoadEvent):

  • svg/SVGScriptElement.cpp:

(WebCore::SVGScriptElement::dispatchErrorEvent): Use dispatchEvent directly.

  • svg/SVGUseElement.cpp:

(WebCore::SVGUseElement::transferEventListenersToShadowTree): Updated for
new EventTarget API.

  • svg/animation/SVGSMILElement.cpp:

(WebCore::ConditionEventListener::handleEvent): No more isWindowEvent.

  • websockets/WebSocket.cpp:

(WebCore::ProcessWebSocketEventTask::create):
(WebCore::ProcessWebSocketEventTask::performTask):
(WebCore::ProcessWebSocketEventTask::ProcessWebSocketEventTask):
(WebCore::WebSocket::didConnect):
(WebCore::WebSocket::didReceiveMessage):
(WebCore::WebSocket::didClose):
(WebCore::WebSocket::eventTargetData):
(WebCore::WebSocket::ensureEventTargetData):

  • websockets/WebSocket.h:
  • websockets/WebSocket.idl:
  • workers/AbstractWorker.cpp:

(WebCore::AbstractWorker::eventTargetData):
(WebCore::AbstractWorker::ensureEventTargetData):

  • workers/AbstractWorker.h:
  • workers/AbstractWorker.idl:
  • workers/DedicatedWorkerContext.cpp:
  • workers/DedicatedWorkerContext.h:
  • workers/DedicatedWorkerContext.idl:
  • workers/DefaultSharedWorkerRepository.cpp:

(WebCore::SharedWorkerConnectTask::performTask):
(WebCore::SharedWorkerScriptLoader::load):
(WebCore::SharedWorkerScriptLoader::notifyFinished):

  • workers/SharedWorker.idl:
  • workers/SharedWorkerContext.cpp:

(WebCore::createConnectEvent):

  • workers/SharedWorkerContext.h:
  • workers/SharedWorkerContext.idl:
  • workers/Worker.cpp:

(WebCore::Worker::notifyFinished):

  • workers/Worker.h:
  • workers/Worker.idl:
  • workers/WorkerContext.cpp:

(WebCore::WorkerContext::eventTargetData):
(WebCore::WorkerContext::ensureEventTargetData):

  • workers/WorkerContext.h:
  • workers/WorkerContext.idl:
  • workers/WorkerMessagingProxy.cpp:

(WebCore::MessageWorkerContextTask::performTask):
(WebCore::MessageWorkerTask::performTask):
(WebCore::WorkerExceptionTask::performTask):

  • xml/XMLHttpRequest.cpp:

(WebCore::XMLHttpRequest::callReadyStateChangeListener):
(WebCore::XMLHttpRequest::createRequest):
(WebCore::XMLHttpRequest::abort):
(WebCore::XMLHttpRequest::networkError):
(WebCore::XMLHttpRequest::abortError):
(WebCore::XMLHttpRequest::didSendData):
(WebCore::XMLHttpRequest::didReceiveData):
(WebCore::XMLHttpRequest::eventTargetData):
(WebCore::XMLHttpRequest::ensureEventTargetData):

  • xml/XMLHttpRequest.h:
  • xml/XMLHttpRequest.idl:
  • xml/XMLHttpRequestProgressEvent.h:

(WebCore::XMLHttpRequestProgressEvent::create):

  • xml/XMLHttpRequestUpload.cpp:

(WebCore::XMLHttpRequestUpload::eventTargetData):
(WebCore::XMLHttpRequestUpload::ensureEventTargetData):

  • xml/XMLHttpRequestUpload.h:
  • xml/XMLHttpRequestUpload.idl: Use new EventTarget API.

WebKit/mac: Updated for a WebCore rename.

Patch by Geoffrey Garen <[email protected]> on 2009-09-23
Reviewed by Sam Weinig.

  • WebView/WebFrame.mm:

(-[WebFrame _cacheabilityDictionary]):

LayoutTests: Layout tests for event target sanitization.

Patch by Geoffrey Garen <[email protected]> on 2009-09-23
Reviewed by Sam Weinig.

New tests for event dispatch:

  • fast/events/event-attributes-after-exception-expected.txt: Added.
  • fast/events/event-attributes-after-exception.html: Added.
  • fast/events/event-fire-order-expected.txt: Added.
  • fast/events/event-fire-order.html: Added.
  • fast/events/event-fired-after-removal-expected.txt: Added.
  • fast/events/event-fired-after-removal.html: Added.


Fixed these tests:

  • fast/xmlhttprequest/xmlhttprequest-get-expected.txt: eventPhase should

be AT_TARGET (2) when firing an event on an XHR, not INVALID (0).

  • http/tests/xmlhttprequest/infoOnProgressEvent-expected.txt: ditto
  • http/tests/xmlhttprequest/event-target-expected.txt:
  • http/tests/xmlhttprequest/event-target.html: Removing an event listener

during event dispatch should prevent it from firing. (This test was backwards.)

  • svg/custom/loadevents-capturing.svg: Enhanced this test to tell you

why it fails when it fails. Changed it to register runTest() (now named
reportResults()) using addEventListener() instead of the 'onload' attribute.
The test relies on reportResults() running after handler(), so it needs
to register reportResults() after handler().

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/wtf/Vector.h

    r46147 r48701  
    6464    template <size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); };
    6565
     66    template <size_t size, size_t alignment>
     67    void swap(AlignedBuffer<size, alignment>& a, AlignedBuffer<size, alignment>& b)
     68    {
     69        for (size_t i = 0; i < size; ++i)
     70            std::swap(a.buffer[i], b.buffer[i]);
     71    }
     72
    6673    template <bool needsDestruction, typename T>
    6774    class VectorDestructor;
     
    405412        }
    406413       
     414        void swap(VectorBuffer<T, inlineCapacity>& other)
     415        {
     416            if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) {
     417                WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
     418                std::swap(m_capacity, other.m_capacity);
     419            } else if (buffer() == inlineBuffer()) {
     420                m_buffer = other.m_buffer;
     421                other.m_buffer = other.inlineBuffer();
     422                WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
     423                std::swap(m_capacity, other.m_capacity);
     424            } else if (other.buffer() == other.inlineBuffer()) {
     425                other.m_buffer = m_buffer;
     426                m_buffer = inlineBuffer();
     427                WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
     428                std::swap(m_capacity, other.m_capacity);
     429            } else {
     430                std::swap(m_buffer, other.m_buffer);
     431                std::swap(m_capacity, other.m_capacity);
     432            }
     433        }
     434
    407435        void restoreInlineBufferIfNeeded()
    408436        {
Note: See TracChangeset for help on using the changeset viewer.