Changeset 142103 in webkit
- Timestamp:
- Feb 7, 2013 5:37:24 AM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r142099 r142103 1 2013-02-07 Kentaro Hara <haraken@chromium.org> 2 3 Unreviewed, rolling out r142077. 4 http://trac.webkit.org/changeset/142077 5 https://bugs.webkit.org/show_bug.cgi?id=108579 6 7 fast/filesystem/workers/file-writer-empty-blob.html is broken 8 9 * bindings/v8/DOMDataStore.h: 10 (WebCore::DOMDataStore::setWrapperInObject): 11 * bindings/v8/DOMWrapperWorld.h: 12 (DOMWrapperWorld): 13 (WebCore::DOMWrapperWorld::isolated): 14 * bindings/v8/V8Binding.h: 15 (WebCore): 16 (WebCore::worldForEnteredContextIfIsolated): 17 * bindings/v8/V8DOMWindowShell.cpp: 18 (WebCore::V8DOMWindowShell::initializeIfNeeded): 19 * bindings/v8/V8GCController.cpp: 20 (WebCore::WrapperVisitor::WrapperVisitor): 21 (WebCore): 22 (WebCore::gcTree): 23 (WebCore::V8GCController::didCreateWrapperForNode): 24 (WebCore::V8GCController::gcPrologue): 25 (WebCore::V8GCController::minorGCPrologue): 26 (WebCore::V8GCController::majorGCPrologue): 27 * bindings/v8/V8GCController.h: 28 (V8GCController): 29 1 30 2013-02-07 Tony Gentilcore <tonyg@chromium.org> 2 31 -
trunk/Source/WebCore/bindings/v8/DOMDataStore.h
r142077 r142103 165 165 wrapper.MakeWeak(isolate, object, weakCallback); 166 166 } 167 static void setWrapperInObject(Node* object, v8::Persistent<v8::Object> wrapper, v8::Isolate* isolate) 168 { 169 ASSERT(object->wrapper().IsEmpty()); 170 object->setWrapper(wrapper); 171 V8GCController::didCreateWrapperForNode(object); 172 wrapper.MakeWeak(isolate, static_cast<ScriptWrappable*>(object), weakCallback); 173 } 167 174 168 175 static void weakCallback(v8::Isolate*, v8::Persistent<v8::Value>, void* context); -
trunk/Source/WebCore/bindings/v8/DOMWrapperWorld.h
r142077 r142103 64 64 static void assertContextHasCorrectPrototype(v8::Handle<v8::Context>); 65 65 #endif 66 // FIXME: Rename this method to getWorld().67 66 static DOMWrapperWorld* isolated(v8::Handle<v8::Context> context) 68 67 { … … 70 69 assertContextHasCorrectPrototype(context); 71 70 #endif 72 return static_cast<DOMWrapperWorld*>(context->GetAlignedPointerFromEmbedderData(v8ContextIsolatedWorld));73 }74 static DOMWrapperWorld* getWorldWithoutContextCheck(v8::Handle<v8::Context> context)75 {76 71 return static_cast<DOMWrapperWorld*>(context->GetAlignedPointerFromEmbedderData(v8ContextIsolatedWorld)); 77 72 } -
trunk/Source/WebCore/bindings/v8/V8Binding.h
r142077 r142103 438 438 Frame* toFrameIfNotDetached(v8::Handle<v8::Context>); 439 439 440 // FIXME: Rename this method to worldForEnteredContext().441 440 inline DOMWrapperWorld* worldForEnteredContextIfIsolated() 442 441 { 443 v8::Handle<v8::Context> context = v8::Context::GetEntered(); 444 if (context.IsEmpty()) 442 if (!v8::Context::InContext()) 445 443 return 0; 446 return DOMWrapperWorld::isolated(context); 447 } 448 449 // This is a slightly different version of worldForEnteredContext(). 450 // The difference is just that worldForEnteredContextWithoutContextCheck() 451 // does not call assertContextHasCorrectPrototype() (which is enabled on 452 // Debug builds only). Because assertContextHasCorrectPrototype() crashes 453 // if it is called when a current context is not completely initialized, 454 // you have to use worldForEnteredContextWithoutContextCheck() if you need 455 // to get a DOMWrapperWorld while a current context is being initialized. 456 // See https://bugs.webkit.org/show_bug.cgi?id=108579#c15 for more details. 457 inline DOMWrapperWorld* worldForEnteredContextWithoutContextCheck() 458 { 459 v8::Handle<v8::Context> context = v8::Context::GetEntered(); 460 if (context.IsEmpty()) 461 return 0; 462 return DOMWrapperWorld::getWorldWithoutContextCheck(context); 444 return DOMWrapperWorld::isolated(v8::Context::GetEntered()); 463 445 } 464 446 -
trunk/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp
r142077 r142103 209 209 return false; 210 210 211 m_world->setIsolatedWorldField(m_context.get());212 213 211 bool isMainWorld = m_world->isMainWorld(); 214 212 215 213 v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_context.get()); 216 214 v8::Context::Scope contextScope(context); 215 216 m_world->setIsolatedWorldField(m_context.get()); 217 217 218 218 if (m_global.isEmpty()) { -
trunk/Source/WebCore/bindings/v8/V8GCController.cpp
r142077 r142103 179 179 } 180 180 181 static void gcTree(Node* startNode) 182 { 183 Vector<v8::Persistent<v8::Value>, initialNodeVectorSize> newSpaceWrappers; 184 185 // We traverse a DOM tree in the DFS order starting from startNode. 186 // The traversal order does not matter for correctness but does matter for performance. 187 Node* node = startNode; 188 // To make each minor GC time bounded, we might need to give up 189 // traversing at some point for a large DOM tree. That being said, 190 // I could not observe the need even in pathological test cases. 191 do { 192 ASSERT(node); 193 if (!node->wrapper().IsEmpty()) { 194 // FIXME: Remove the special handling for image elements. 195 // The same special handling is in V8GCController::opaqueRootForGC(). 196 // Maybe should image elements be active DOM nodes? 197 // See https://code.google.com/p/chromium/issues/detail?id=164882 198 if (!node->isV8CollectableDuringMinorGC() || (node->hasTagName(HTMLNames::imgTag) && static_cast<HTMLImageElement*>(node)->hasPendingActivity())) { 199 // This node is not in the new space of V8. This indicates that 200 // the minor GC cannot anyway judge reachability of this DOM tree. 201 // Thus we give up traversing the DOM tree. 202 return; 203 } 204 node->setV8CollectableDuringMinorGC(false); 205 newSpaceWrappers.append(node->wrapper()); 206 } 207 if (node->firstChild()) { 208 node = node->firstChild(); 209 continue; 210 } 211 while (!node->nextSibling()) { 212 if (!node->parentNode()) 213 break; 214 node = node->parentNode(); 215 } 216 if (node->parentNode()) 217 node = node->nextSibling(); 218 } while (node != startNode); 219 220 // We completed the DOM tree traversal. All wrappers in the DOM tree are 221 // stored in newSpaceWrappers and are expected to exist in the new space of V8. 222 // We report those wrappers to V8 as an object group. 223 for (size_t i = 0; i < newSpaceWrappers.size(); i++) 224 newSpaceWrappers[i].MarkPartiallyDependent(); 225 if (newSpaceWrappers.size() > 0) 226 v8::V8::AddObjectGroup(&newSpaceWrappers[0], newSpaceWrappers.size()); 227 } 228 229 // Regarding a minor GC algorithm for DOM nodes, see this document: 230 // https://docs.google.com/a/google.com/presentation/d/1uifwVYGNYTZDoGLyCb7sXa7g49mWNMW2gaWvMN5NLk8/edit#slide=id.p 231 class MinorGCWrapperVisitor : public v8::PersistentHandleVisitor { 181 class WrapperVisitor : public v8::PersistentHandleVisitor { 232 182 public: 233 explicit MinorGCWrapperVisitor(v8::Isolate* isolate) 234 : m_isolate(isolate) 235 { 236 UNUSED_PARAM(m_isolate); 237 } 238 239 virtual void VisitPersistentHandle(v8::Persistent<v8::Value> value, uint16_t classId) OVERRIDE 240 { 241 // A minor DOM GC can collect only Nodes. 242 if (classId != v8DOMNodeClassId) 243 return; 244 245 // To make minor GC cycle time bounded, we limit the number of wrappers handled 246 // by each minor GC cycle to 10000. This value was selected so that the minor 247 // GC cycle time is bounded to 20 ms in a case where the new space size 248 // is 16 MB and it is full of wrappers (which is almost the worst case). 249 // Practically speaking, as far as I crawled real web applications, 250 // the number of wrappers handled by each minor GC cycle is at most 3000. 251 // So this limit is mainly for pathological micro benchmarks. 252 const unsigned wrappersHandledByEachMinorGC = 10000; 253 if (m_nodesInNewSpace.size() >= wrappersHandledByEachMinorGC) 254 return; 255 256 ASSERT(value->IsObject()); 257 v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value); 258 ASSERT(V8DOMWrapper::maybeDOMWrapper(value)); 259 ASSERT(V8Node::HasInstance(wrapper, m_isolate)); 260 Node* node = V8Node::toNative(wrapper); 261 m_nodesInNewSpace.append(node); 262 node->setV8CollectableDuringMinorGC(true); 263 } 264 265 void notifyFinished() 266 { 267 for (size_t i = 0; i < m_nodesInNewSpace.size(); i++) { 268 ASSERT(!m_nodesInNewSpace[i]->wrapper().IsEmpty()); 269 if (m_nodesInNewSpace[i]->isV8CollectableDuringMinorGC()) // This branch is just for performance. 270 gcTree(m_nodesInNewSpace[i]); 271 } 272 } 273 274 private: 275 Vector<Node*> m_nodesInNewSpace; 276 v8::Isolate* m_isolate; 277 }; 278 279 class MajorGCWrapperVisitor : public v8::PersistentHandleVisitor { 280 public: 281 explicit MajorGCWrapperVisitor(v8::Isolate* isolate) 183 explicit WrapperVisitor(v8::Isolate* isolate) 282 184 : m_isolate(isolate) 283 185 { … … 347 249 }; 348 250 251 // Regarding a minor GC algorithm for DOM nodes, see this document: 252 // https://docs.google.com/a/google.com/presentation/d/1uifwVYGNYTZDoGLyCb7sXa7g49mWNMW2gaWvMN5NLk8/edit#slide=id.p 253 // 254 // m_edenNodes stores nodes that have wrappers that have been created since the last minor/major GC. 255 Vector<Node*>* V8GCController::m_edenNodes = 0; 256 257 static void gcTree(Node* startNode) 258 { 259 Vector<v8::Persistent<v8::Value>, initialNodeVectorSize> newSpaceWrappers; 260 261 // We traverse a DOM tree in the DFS order starting from startNode. 262 // The traversal order does not matter for correctness but does matter for performance. 263 Node* node = startNode; 264 // To make each minor GC time bounded, we might need to give up 265 // traversing at some point for a large DOM tree. That being said, 266 // I could not observe the need even in pathological test cases. 267 do { 268 ASSERT(node); 269 if (!node->wrapper().IsEmpty()) { 270 // FIXME: Remove the special handling for image elements. 271 // The same special handling is in V8GCController::opaqueRootForGC(). 272 // Maybe should image elements be active DOM nodes? 273 // See https://code.google.com/p/chromium/issues/detail?id=164882 274 if (!node->isV8CollectableDuringMinorGC() || (node->hasTagName(HTMLNames::imgTag) && static_cast<HTMLImageElement*>(node)->hasPendingActivity())) { 275 // The fact that we encounter a node that is not in the Eden space 276 // implies that its wrapper might be in the old space of V8. 277 // This indicates that the minor GC cannot anyway judge reachability 278 // of this DOM tree. Thus we give up traversing the DOM tree. 279 return; 280 } 281 // A once traversed node is removed from the Eden space. 282 node->setV8CollectableDuringMinorGC(false); 283 newSpaceWrappers.append(node->wrapper()); 284 } 285 if (node->firstChild()) { 286 node = node->firstChild(); 287 continue; 288 } 289 while (!node->nextSibling()) { 290 if (!node->parentNode()) 291 break; 292 node = node->parentNode(); 293 } 294 if (node->parentNode()) 295 node = node->nextSibling(); 296 } while (node != startNode); 297 298 // We completed the DOM tree traversal. All wrappers in the DOM tree are 299 // stored in newSpaceWrappers and are expected to exist in the new space of V8. 300 // We report those wrappers to V8 as an object group. 301 for (size_t i = 0; i < newSpaceWrappers.size(); i++) 302 newSpaceWrappers[i].MarkPartiallyDependent(); 303 if (newSpaceWrappers.size() > 0) 304 v8::V8::AddObjectGroup(&newSpaceWrappers[0], newSpaceWrappers.size()); 305 } 306 307 void V8GCController::didCreateWrapperForNode(Node* node) 308 { 309 // To make minor GC cycle time bounded, we limit the number of wrappers handled 310 // by each minor GC cycle to 10000. This value was selected so that the minor 311 // GC cycle time is bounded to 20 ms in a case where the new space size 312 // is 16 MB and it is full of wrappers (which is almost the worst case). 313 // Practically speaking, as far as I crawled real web applications, 314 // the number of wrappers handled by each minor GC cycle is at most 3000. 315 // So this limit is mainly for pathological micro benchmarks. 316 const unsigned wrappersHandledByEachMinorGC = 10000; 317 ASSERT(!node->wrapper().IsEmpty()); 318 if (!m_edenNodes) 319 m_edenNodes = adoptPtr(new Vector<Node*>).leakPtr(); 320 if (m_edenNodes->size() <= wrappersHandledByEachMinorGC) { 321 // A node of a newly created wrapper is put into the Eden space. 322 m_edenNodes->append(node); 323 node->setV8CollectableDuringMinorGC(true); 324 } 325 } 326 349 327 void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags) 350 328 { … … 353 331 else if (type == v8::kGCTypeMarkSweepCompact) 354 332 majorGCPrologue(); 333 334 if (isMainThreadOrGCThread() && m_edenNodes) { 335 // The Eden space is cleared at every minor/major GC. 336 m_edenNodes->clear(); 337 } 355 338 } 356 339 357 340 void V8GCController::minorGCPrologue() 341 { 342 TRACE_EVENT_BEGIN0("v8", "GC"); 343 344 if (isMainThreadOrGCThread() && m_edenNodes) { 345 for (size_t i = 0; i < m_edenNodes->size(); i++) { 346 ASSERT(!m_edenNodes->at(i)->wrapper().IsEmpty()); 347 if (m_edenNodes->at(i)->isV8CollectableDuringMinorGC()) // This branch is just for performance. 348 gcTree(m_edenNodes->at(i)); 349 } 350 } 351 } 352 353 // Create object groups for DOM tree nodes. 354 void V8GCController::majorGCPrologue() 358 355 { 359 356 TRACE_EVENT_BEGIN0("v8", "GC"); … … 362 359 v8::HandleScope scope; 363 360 364 // A minor GC can handle the main world only. 365 DOMWrapperWorld* world = worldForEnteredContextWithoutContextCheck(); 366 if (world && world->isMainWorld()) { 367 MinorGCWrapperVisitor visitor(isolate); 368 v8::V8::VisitHandlesForPartialDependence(isolate, &visitor); 369 visitor.notifyFinished(); 370 } 371 } 372 373 // Create object groups for DOM tree nodes. 374 void V8GCController::majorGCPrologue() 375 { 376 TRACE_EVENT_BEGIN0("v8", "GC"); 377 378 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 379 v8::HandleScope scope; 380 381 MajorGCWrapperVisitor visitor(isolate); 361 WrapperVisitor visitor(isolate); 382 362 v8::V8::VisitHandlesWithClassIds(&visitor); 383 363 visitor.notifyFinished(); -
trunk/Source/WebCore/bindings/v8/V8GCController.h
r142077 r142103 53 53 54 54 static Node* opaqueRootForGC(Node*, v8::Isolate*); 55 static void didCreateWrapperForNode(Node*); 55 56 56 57 private:
Note: See TracChangeset
for help on using the changeset viewer.