Bug 108579

Summary: [V8] Remove V8GCController::m_edenNodes and make minor DOM GC more precise
Product: WebKit Reporter: Kentaro Hara <haraken>
Component: WebCore JavaScriptAssignee: Kentaro Hara <haraken>
Status: RESOLVED FIXED    
Severity: Normal CC: abarth, dglazkov, gavinp, japhet, peter+ews, webkit.review.bot
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 109055    
Bug Blocks:    
Attachments:
Description Flags
performance benchmark
none
Patch
none
Patch
none
patch for landing
none
Patch
none
Patch
none
patch for landing
none
patch for landing none

Description Kentaro Hara 2013-01-31 21:50:02 PST
Currently V8GCController::m_edenNodes stores a list of nodes whose wrappers have been created since the latest GC. The reason why we needed m_edenNodes is that there was no way to know a list of wrappers in the new space of V8. By using m_edenNodes, we had been approximating 'wrappers in the new space' by 'wrappers that have been created since the latest GC'.

Now V8 provides VisitHandlesForPartialDependence(), with which WebKit can know a list of wrappers in the new space (yeah, the API name could be VisitHandlesInNewSpace() but the V8 team didn't want to expose the concept of generational GC to APIs:-). By using the API, we can remove V8GCController::m_edenNodes. The benefit is that (1) we no longer need to keep m_edenNodes and that (2) it enables more precise minor DOM GC (Remember that m_edenNodes was just an approximation).
Comment 1 Kentaro Hara 2013-01-31 21:52:04 PST
Created attachment 185940 [details]
performance benchmark
Comment 2 Kentaro Hara 2013-01-31 21:57:41 PST
Created attachment 185942 [details]
Patch
Comment 3 Peter Beverloo (cr-android ews) 2013-01-31 22:19:05 PST
Comment on attachment 185942 [details]
Patch

Attachment 185942 [details] did not pass cr-android-ews (chromium-android):
Output: http://queues.webkit.org/results/16296336
Comment 4 WebKit Review Bot 2013-01-31 22:23:42 PST
Comment on attachment 185942 [details]
Patch

Attachment 185942 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/16298362
Comment 5 Kentaro Hara 2013-01-31 22:36:26 PST
Created attachment 185947 [details]
Patch
Comment 6 Adam Barth 2013-01-31 23:02:08 PST
Comment on attachment 185947 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=185947&action=review

> Source/WebCore/bindings/v8/DOMDataStore.h:172
>      {
>          ASSERT(object->wrapper().IsEmpty());
>          object->setWrapper(wrapper);
> -        V8GCController::didCreateWrapperForNode(object);
>          wrapper.MakeWeak(static_cast<ScriptWrappable*>(object), weakCallback);
>      }

We can now delete this whole function and use the ScriptWrappable version of setWrapperInObject instead.

> Source/WebCore/bindings/v8/V8GCController.cpp:199
> +                // The fact that we encounter a node that is not in the Eden space

Should this comment still refer to Eden now that we've removed that concept?
Comment 7 Kentaro Hara 2013-01-31 23:13:31 PST
Created attachment 185952 [details]
patch for landing
Comment 8 Kentaro Hara 2013-01-31 23:14:21 PST
(In reply to comment #6)
> 
> We can now delete this whole function and use the ScriptWrappable version of setWrapperInObject instead.
> 
> > Source/WebCore/bindings/v8/V8GCController.cpp:199
> > +                // The fact that we encounter a node that is not in the Eden space
> 
> Should this comment still refer to Eden now that we've removed that concept?

Fixed. Thanks!
Comment 9 WebKit Review Bot 2013-02-01 00:28:43 PST
Comment on attachment 185952 [details]
patch for landing

Clearing flags on attachment: 185952

Committed r141548: <http://trac.webkit.org/changeset/141548>
Comment 10 WebKit Review Bot 2013-02-01 00:28:47 PST
All reviewed patches have been landed.  Closing bug.
Comment 11 Kentaro Hara 2013-02-01 03:51:11 PST
Reverted r141548 for reason:

userscript-plugin-document.html is flaky

Committed r141577: <http://trac.webkit.org/changeset/141577>
Comment 12 Kentaro Hara 2013-02-01 04:10:22 PST
Comment on attachment 185952 [details]
patch for landing

View in context: https://bugs.webkit.org/attachment.cgi?id=185952&action=review

> Source/WebCore/bindings/v8/V8GCController.cpp:262
> +            ASSERT(!m_nodesInNewSpace[i]->wrapper().IsEmpty());

The following tests hit this ASSERT(), which looks strange. This ASSERT() should not be hit.

  userscripts/mixed-case-stylesheet.html [ Crash ]
  userscripts/script-run-at-start.html [ Crash ]
  userscripts/user-script-all-frames.html [ Crash ]
  userscripts/user-style-all-frames.html [ Crash ]
Comment 13 Kentaro Hara 2013-02-01 04:12:00 PST
Comment on attachment 185952 [details]
patch for landing

View in context: https://bugs.webkit.org/attachment.cgi?id=185952&action=review

> Source/WebCore/bindings/v8/V8GCController.cpp:254
> +        Node* node = V8Node::toNative(wrapper);

More specifically, if we insert ASSERT(!node->wrapper().IsEmpty()), the userscripts/* tests hit the ASSERT(). Let me take a detailed look on Monday.
Comment 14 Kentaro Hara 2013-02-04 05:00:26 PST
Created attachment 186356 [details]
Patch
Comment 15 Kentaro Hara 2013-02-04 05:11:37 PST
Comment on attachment 186356 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=186356&action=review

> Source/WebCore/bindings/v8/V8GCController.cpp:364
> +    // A minor GC can handle the main world only.
> +    DOMWrapperWorld* world = worldForEnteredContextWithoutContextCheck();
> +    if (world && world->isMainWorld()) {

abarth: Since the latest review, I just added this check. Review again please?

I'm pretty sure that we need the isMainWorld() check here because a minor GC can handle the main world only. On the other hand, the reason why we cannot simply use worldForEnteredContext() to get the current world is complicated:

(1) A minor GC can be triggered while the current context is being initialized. Specifically, V8DOMWindowShell::installDOMWindow() calls V8ObjectConstructor::newInstance(), which can trigger a minor GC. At this point, native information is not yet set on context->Global()->GetPrototype().
(2) The minor GC calls back V8GCController::minorGCPrologue(). Here imagine that minorGCPrologue() calls worldForEnteredContext().
(3) worldForEnteredContext() calls assertContextHasCorrectPrototype(context), which calls isWrapperOfType(toInnerGlobalObject(context), ...), which tries to retrieve native information from context->Global()->GetPrototype(). Because the native information has not yet set, the code crashes.

To avoid the situation, I added another version of worldForEnteredContext() that does not call assertContextHasCorrectPrototype(context).
Comment 16 WebKit Review Bot 2013-02-04 08:35:49 PST
Comment on attachment 186356 [details]
Patch

Attachment 186356 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/16371270

New failing tests:
accessibility/anchor-linked-anonymous-block-crash.html
http/tests/appcache/main-resource-hash.html
animations/3d/matrix-transform-type-animation.html
accessibility/aria-readonly.html
animations/3d/state-at-end-event-transform.html
animations/animation-add-events-in-handler.html
accessibility/aria-labelledby-on-input.html
canvas/philip/tests/2d.clearRect.globalalpha.html
accessibility/aria-disabled.html
animations/animation-direction-alternate-reverse.html
accessibility/aria-labelledby-overrides-label.html
http/tests/appcache/access-via-redirect.php
accessibility/aria-option-role.html
accessibility/aria-controls-with-tabs.html
http/tests/appcache/destroyed-frame.html
http/tests/appcache/deferred-events-delete-while-raising-timer.html
http/tests/appcache/insert-html-element-with-manifest.html
accessibility/aria-link-supports-press.html
animations/3d/transform-perspective.html
accessibility/aria-hidden-updates-alldescendants.html
accessibility/aria-scrollbar-role.html
http/tests/appcache/local-content.html
http/tests/appcache/manifest-parsing.html
canvas/philip/tests/2d.canvas.reference.html
animations/animation-controller-drt-api.html
canvas/philip/tests/2d.clearRect.basic.html
accessibility/aria-hidden.html
http/tests/appcache/foreign-fallback.html
accessibility/aria-help.html
canvas/philip/tests/2d.clearRect+fillRect.alpha0.html
Comment 17 Adam Barth 2013-02-04 10:15:19 PST
Looks like you've got some test failures to work through.  What you've written in Comment #15 makes sense.
Comment 18 Kentaro Hara 2013-02-04 17:27:32 PST
Created attachment 186506 [details]
Patch
Comment 19 Kentaro Hara 2013-02-04 17:29:48 PST
Comment on attachment 186506 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=186506&action=review

> Source/WebCore/bindings/v8/V8Binding.h:467
>      inline DOMWrapperWorld* worldForEnteredContextIfIsolated()
>      {
> -        if (!v8::Context::InContext())
> +        v8::Handle<v8::Context> context = v8::Context::GetEntered();
> +        if (context.IsEmpty())
>              return 0;
> -        return DOMWrapperWorld::isolated(v8::Context::GetEntered());
> +        return DOMWrapperWorld::isolated(context);
> +    }
> +
> +    inline DOMWrapperWorld* worldForEnteredContextWithoutContextCheck()
> +    {
> +        v8::Handle<v8::Context> context = v8::Context::GetEntered();
> +        if (context.IsEmpty())
> +            return 0;
> +        return DOMWrapperWorld::getWorldWithoutContextCheck(context);
>      }

abarth: I just changed these lines, which I think fixed the test failures. Given that we are using an entered context, we have to do an empty check for the entered context instead of InContext().
Comment 20 Kentaro Hara 2013-02-05 20:10:22 PST
abarth: review?
Comment 21 Adam Barth 2013-02-06 00:27:57 PST
Comment on attachment 186506 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=186506&action=review

> Source/WebCore/bindings/v8/DOMWrapperWorld.h:74
> +    static DOMWrapperWorld* getWorldWithoutContextCheck(v8::Handle<v8::Context> context)

Can you add a comment about when you'd wan to call getWorldWithoutContextCheck instead of getWorld()/isolated() ?

> Source/WebCore/bindings/v8/V8Binding.h:455
> +        v8::Handle<v8::Context> context = v8::Context::GetEntered();

Is this safe to call if !InContext()?  I guess so if we pass all the tests.

>> Source/WebCore/bindings/v8/V8Binding.h:467
>>      }
> 
> abarth: I just changed these lines, which I think fixed the test failures. Given that we are using an entered context, we have to do an empty check for the entered context instead of InContext().

In what situations does InContext return true but GetEntered returns an empty context?  That seems very odd.
Comment 22 Adam Barth 2013-02-06 00:29:03 PST
I see your explanation in Comment #15.  It would be good to add a comment about that to the code because that's a very subtle issue.
Comment 23 Kentaro Hara 2013-02-06 00:30:19 PST
(In reply to comment #22)
> I see your explanation in Comment #15.  It would be good to add a comment about that to the code because that's a very subtle issue.

Will add a comment. The weird situation happens only during an initialization step.
Comment 24 Kentaro Hara 2013-02-06 03:42:38 PST
Committed r141983: <http://trac.webkit.org/changeset/141983>
Comment 26 WebKit Review Bot 2013-02-06 07:46:41 PST
Re-opened since this is blocked by bug 109055
Comment 27 Kentaro Hara 2013-02-06 23:25:45 PST
Created attachment 186997 [details]
patch for landing
Comment 28 Kentaro Hara 2013-02-06 23:26:24 PST
Comment on attachment 186997 [details]
patch for landing

Corrected a place where a handle scope is created.
Comment 29 Kentaro Hara 2013-02-07 00:43:53 PST
Committed r142077: <http://trac.webkit.org/changeset/142077>
Comment 30 Kentaro Hara 2013-02-07 05:39:02 PST
Reverted r142077 for reason:

fast/filesystem/workers/file-writer-empty-blob.html is broken

Committed r142103: <http://trac.webkit.org/changeset/142103>
Comment 31 Kentaro Hara 2013-02-08 04:07:44 PST
Created attachment 187286 [details]
patch for landing
Comment 32 Kentaro Hara 2013-02-10 17:18:00 PST
Committed r142419: <http://trac.webkit.org/changeset/142419>