Bug 126610 - Memory leak from windowScriptObjectAvailable
Summary: Memory leak from windowScriptObjectAvailable
Status: RESOLVED WORKSFORME
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit API (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-01-07 17:54 PST by Alex Christensen
Modified: 2014-01-30 19:58 PST (History)
3 users (show)

See Also:


Attachments
Patch (1.14 KB, patch)
2014-01-10 10:55 PST, Alex Christensen
no flags Details | Formatted Diff | Diff
Patch (1.27 KB, patch)
2014-01-14 11:15 PST, Alex Christensen
alex.christensen: review-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alex Christensen 2014-01-07 17:54:50 PST
I'm working on finding a memory leak in Source/WebKit/win.  We are getting a JSContextRef from the call to windowScriptObjectAvailable in WebFrameLoaderClient::dispatchDidClearWindowObjectInWorld.  The JSContextRef has an extra reference to it that is not being dereferenced when we call WebView::close, and it's causing our JSObjectFinalizeCallback not to be called.  I'm not sure where exactly to look, but it feels like a release of some sort should be added to WebView::close.
Comment 1 Alex Christensen 2014-01-09 15:20:54 PST
Inspired by https://bugs.webkit.org/attachment.cgi?id=93818&action=prettypatch I added vm.heap.collectAllGarbage() to JSGlobalContextRelease and it fixed my problem without appearing to break anything.  That's not optimal performance, and that's certainly not a good fix, but I think it's close.  Is there a reason we aren't garbage collecting at all in JSGlobalContextRelease at all anymore?
Comment 2 Alex Christensen 2014-01-10 10:55:54 PST
Created attachment 220862 [details]
Patch
Comment 3 Alex Christensen 2014-01-10 10:58:55 PST
This patch feels super hacky, and I'm sure there's a better way, and I'm sure there are reasons to not garbage collect when closing a WebView.  I'm expecting an r-, but hopefully some insight about how to do this better.

It would be really nice if there were a way to initiate garbage collection from a JSContextRef, so an API user can tell JavaScriptCore that now is a good time to garbage collect based on the state of my application that JavaScript doesn't know about.
Comment 4 Geoffrey Garen 2014-01-10 11:57:35 PST
Comment on attachment 220862 [details]
Patch

A better way to do this is to call GCController::garbageCollectSoon(). Can you try that?

GCController::garbageCollectSoon() does a better job of batching collection requests.
Comment 5 Alex Christensen 2014-01-14 11:06:07 PST
Adding a call to GCController::garbageCollectNow to WebView::close solves my problem, but GCController::garbageCollectSoon does not.  I'm not sure if every user of WebKit on Windows would want the lag of garbage collecting when closing a WebView.
Comment 6 Alex Christensen 2014-01-14 11:15:23 PST
Created attachment 221181 [details]
Patch
Comment 7 Alex Christensen 2014-01-14 12:41:06 PST
I found a solution using the JavaScript API that works for me and doesn't force other WebKit users to garbage collect when they don't want to.  I call JSReportExtraMemoryCost(ctx,1000000000); then JSGarbageCollect(ctx); and it garbage collects when I open the next WebKit widget.  This is also hacky, but I can refine it on my end without changing WebKit.
Comment 8 Mark Hahnenberg 2014-01-14 12:51:34 PST
Where is the extra reference to the JSContextRef coming from? Maybe the ref count is zero, but you're not sweeping anything so finalization never happens? Does the IncrementalSweeper work on Windows?

collectAllGarbage also forces eager sweeping, which is why it would cause finalization to happen.
Comment 9 Alex Christensen 2014-01-14 13:31:42 PST
(In reply to comment #7)
> I call JSReportExtraMemoryCost(ctx,1000000000); then JSGarbageCollect(ctx);
For the record, this is a terrible solution, and the garbage collector keeps the memory usage to a few megabytes when JSReportExtraMemoryCost is used correctly, which is reasonable.

(In reply to comment #8)
> Where is the extra reference to the JSContextRef coming from? Maybe the ref count is zero, but you're not sweeping anything so finalization never happens? Does the IncrementalSweeper work on Windows?
I'm not sure, but the ref count of the JSContextRef is always between 2 and 4.  Doing extra releases causes crashes, so there's probably something global that I wasn't expecting to be global.  
> 
> collectAllGarbage also forces eager sweeping, which is why it would cause finalization to happen.
Comment 10 Mark Hahnenberg 2014-01-14 14:48:29 PST
I would do some further investigation into whether or not sweeping is being triggered in a timely manner. Try adding a printf or breakpoint inside MarkedBlock::sweep and see if things are being swept after the WebView is closed. Sweeping is when finalizers are run, so if a finalizer isn't running that should be the first thing to check.
Comment 11 Alex Christensen 2014-01-30 19:58:51 PST
Comment on attachment 221181 [details]
Patch

I'm cleaning up old bugs.  This does not need to go in.