Changeset 84741 in webkit
- Timestamp:
- Apr 23, 2011 12:11:38 AM (13 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r84740 r84741 1 2011-04-19 Vitaly Repeshko <vitalyr@chromium.org> 2 3 Reviewed by Adam Barth. 4 5 [V8] Use implicit references for V8 listeners on DOM nodes. 6 https://bugs.webkit.org/show_bug.cgi?id=58953 7 8 Instead of allocating an auxiliary V8 array referencing V8 9 listener objects associated with a DOM node and using an extra 10 pointer in every DOM node wrapper, we can register implicit 11 references between nodes and their listeners during GC. This also 12 makes V8 bindings more aligned with JSC bindings. 13 14 No new tests because this is a refactoring. 15 16 * bindings/scripts/CodeGeneratorV8.pm: Stopped generating the 17 listener cache internal field for DOM nodes. 18 * bindings/v8/V8AbstractEventListener.h: Exposed the lister handle 19 to the GC. 20 (WebCore::V8AbstractEventListener::existingListenerObjectPeristentHandle): 21 * bindings/v8/V8GCController.cpp: Started using implicit references. 22 (WebCore::GrouperVisitor::visitDOMWrapper): 23 * dom/EventTarget.h: Implemented an iterator over all listeners. 24 (WebCore::EventListenerIterator): 25 1 26 2011-04-22 Jon Lee <jonlee@apple.com> 2 27 -
trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm
r84665 r84741 442 442 my @customInternalFields = (); 443 443 444 # We can't ask whether a parent type has a given extendedAttribute, so special-case Node, AbstractWorker and WorkerContext to include all sub-types. 444 # We can't ask whether a parent type has a given extendedAttribute, so special-case AbstractWorker and WorkerContext to include all sub-types. 445 # Event listeners on DOM nodes are explicitly supported in the GC controller. 445 446 # FIXME: SVGElementInstance should probably have the EventTarget extended attribute, but doesn't. 446 if ($dataNode->extendedAttributes->{"EventTarget"} || IsNodeSubType($dataNode) || IsSubType($dataNode, "AbstractWorker") || IsSubType($dataNode, "WorkerContext") 447 || $name eq "SVGElementInstance") { 447 if (!IsNodeSubType($dataNode) && 448 ($dataNode->extendedAttributes->{"EventTarget"} || 449 IsSubType($dataNode, "AbstractWorker") || 450 IsSubType($dataNode, "WorkerContext") || 451 $name eq "SVGElementInstance")) { 448 452 push(@customInternalFields, "eventListenerCacheIndex"); 449 453 } … … 997 1001 my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName); 998 1002 $implIncludes{"V8AbstractEventListener.h"} = 1; 999 push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n"); 1003 if (!IsNodeSubType($dataNode)) { 1004 push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n"); 1005 } 1000 1006 if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") { 1001 1007 $implIncludes{"V8EventListenerList.h"} = 1; … … 1068 1074 { 1069 1075 my $implClassName = shift; 1076 my $requiresHiddenDependency = shift; 1070 1077 my $functionName = shift; 1071 1078 my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only"; … … 1080 1087 if (listener) { 1081 1088 V8${implClassName}::toNative(args.Holder())->${functionName}EventListener(v8ValueToAtomicWebCoreString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue()); 1089 END 1090 if ($requiresHiddenDependency) { 1091 push(@implContentDecls, <<END); 1082 1092 ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${implClassName}::eventListenerCacheIndex); 1093 END 1094 } 1095 push(@implContentDecls, <<END); 1083 1096 } 1084 1097 return v8::Undefined(); … … 1186 1199 # so we can generate them as a "special case". 1187 1200 if ($name eq "addEventListener") { 1188 GenerateEventListenerCallback($implClassName, "add");1201 GenerateEventListenerCallback($implClassName, !IsNodeSubType($dataNode), "add"); 1189 1202 return; 1190 1203 } elsif ($name eq "removeEventListener") { 1191 GenerateEventListenerCallback($implClassName, "remove");1204 GenerateEventListenerCallback($implClassName, !IsNodeSubType($dataNode), "remove"); 1192 1205 return; 1193 1206 } -
trunk/Source/WebCore/bindings/v8/V8AbstractEventListener.h
r62897 r84741 89 89 } 90 90 91 // Provides access to the underlying handle for GC. Returned 92 // value might be a weak handle and so not guaranteed to stay 93 // alive. 94 v8::Persistent<v8::Object> existingListenerObjectPersistentHandle() 95 { 96 return m_listener; 97 } 98 91 99 bool hasExistingListenerObject() 92 100 { -
trunk/Source/WebCore/bindings/v8/V8GCController.cpp
r84665 r84741 327 327 void visitDOMWrapper(DOMDataStore* store, Node* node, v8::Persistent<v8::Object> wrapper) 328 328 { 329 if (node->hasEventListeners()) { 330 Vector<v8::Persistent<v8::Value> > listeners; 331 EventListenerIterator iterator(node); 332 while (EventListener* listener = iterator.nextListener()) { 333 if (listener->type() != EventListener::JSEventListenerType) 334 continue; 335 V8AbstractEventListener* v8listener = static_cast<V8AbstractEventListener*>(listener); 336 if (!v8listener->hasExistingListenerObject()) 337 continue; 338 listeners.append(v8listener->existingListenerObjectPersistentHandle()); 339 } 340 if (!listeners.isEmpty()) 341 v8::V8::AddImplicitReferences(wrapper, listeners.data(), listeners.size()); 342 } 343 329 344 GroupId groupId = calculateGroupId(node); 330 345 if (!groupId) -
trunk/Source/WebCore/dom/EventTarget.cpp
r83261 r84741 36 36 #include "EventException.h" 37 37 #include <wtf/StdLibExtras.h> 38 #include <wtf/Vector.h> 38 39 39 40 using namespace WTF; … … 391 392 } 392 393 394 EventListenerIterator::EventListenerIterator() 395 : m_index(0) 396 { 397 } 398 399 EventListenerIterator::EventListenerIterator(EventTarget* target) 400 : m_index(0) 401 { 402 EventTargetData* data = target->eventTargetData(); 403 if (!data) 404 return; 405 m_mapIterator = data->eventListenerMap.begin(); 406 m_mapEnd = data->eventListenerMap.end(); 407 } 408 409 EventListener* EventListenerIterator::nextListener() 410 { 411 for (; m_mapIterator != m_mapEnd; ++m_mapIterator) { 412 EventListenerVector& listeners = *m_mapIterator->second; 413 if (m_index < listeners.size()) 414 return listeners[m_index++].listener.get(); 415 m_index = 0; 416 } 417 return 0; 418 } 419 393 420 } // namespace WebCore -
trunk/Source/WebCore/dom/EventTarget.h
r84556 r84741 186 186 187 187 void fireEventListeners(Event*, EventTargetData*, EventListenerVector&); 188 189 friend class EventListenerIterator; 190 }; 191 192 class EventListenerIterator { 193 public: 194 EventListenerIterator(); 195 196 // EventTarget must not be modified while an iterator is active. 197 EventListenerIterator(EventTarget*); 198 199 EventListener* nextListener(); 200 201 private: 202 EventListenerMap::iterator m_mapIterator; 203 EventListenerMap::iterator m_mapEnd; 204 unsigned m_index; 188 205 }; 189 206
Note: See TracChangeset
for help on using the changeset viewer.