WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED WONTFIX
146278
[Streams API] Remove use of JSC::Strong as much as possible
https://bugs.webkit.org/show_bug.cgi?id=146278
Summary
[Streams API] Remove use of JSC::Strong as much as possible
youenn fablet
Reported
2015-06-24 08:23:14 PDT
Following on
bug 142635
, it might be good to remove usage of JSC::Strong for errorFunction, source and sizeFunction, as we could end up in ref cycles.
Attachments
Patch
(27.65 KB, patch)
2015-07-31 08:52 PDT
,
youenn fablet
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews104 for mac-mavericks-wk2
(635.11 KB, application/zip)
2015-07-31 09:33 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews101 for mac-mavericks
(597.81 KB, application/zip)
2015-07-31 09:47 PDT
,
Build Bot
no flags
Details
Fixing crash
(24.81 KB, patch)
2015-08-03 03:18 PDT
,
youenn fablet
no flags
Details
Formatted Diff
Diff
Simplifying patch
(19.72 KB, patch)
2015-08-03 04:44 PDT
,
youenn fablet
no flags
Details
Formatted Diff
Diff
Show Obsolete
(4)
View All
Add attachment
proposed patch, testcase, etc.
youenn fablet
Comment 1
2015-06-24 08:23:43 PDT
II was meaning
bug 146235
youenn fablet
Comment 2
2015-06-24 08:25:19 PDT
It is suggested to use GC marking. I am not yet very familiar with it. As in the spec, we could put errorFunction, source and sizeFunction in JSReadableStream internalSlots. This could be extended to pull fullfil/reject JS callbacks whenever created. Or we may reuse what is behind CachedAttribute. Any other possibility?
youenn fablet
Comment 3
2015-06-24 08:26:15 PDT
Darin is suggesting to use GC marking. I am not yet very familiar with it. As written in the streams spec, we could put errorFunction, source and sizeFunction in JSReadableStream internalSlots. This could be extended to pull fullfil/reject JS callbacks whenever created. We might also reuse what is behind CachedAttribute IDL. Any other possibility?
Darin Adler
Comment 4
2015-06-24 11:28:02 PDT
(In reply to
comment #2
)
> It is suggested to use GC marking. > I am not yet very familiar with it.
First of all, I think the main thing to do is to actually make test cases that reproduce these reference cycles to ensure the objects aren’t leaked. I’m not sure exactly what the best way to make such tests is, but it seems even more important to do that than to fix the bugs, so we don’t introduce the bugs in the future. Marking is relatively straightforward. The class needs to have the JSCustomMarkFunction attribute in the IDL. Then custom wrapper code needs to implement a visitAdditionalChildren function. The function then needs to call addOpaqueRoot on each object we need to keep alive. Some examples to look at are JSXMLHttpRequest::visitAdditionalChildren and JSTreeWalker::visitAdditionalChildren.
youenn fablet
Comment 5
2015-07-30 09:41:04 PDT
This is not as straightforward as I thought. I would think using JSCustomMark and passing from JSC::Strong to JSC::WriteBarrier would work, just as done for Cached attributes. It seems I can make it work for the enqueued chunks but not always for the stored error where I get some crashes related to GC. I will upload some code probably tomorrow about that.
youenn fablet
Comment 6
2015-07-30 09:43:24 PDT
(In reply to
comment #4
)
> (In reply to
comment #2
) > > It is suggested to use GC marking. > > I am not yet very familiar with it. > > First of all, I think the main thing to do is to actually make test cases > that reproduce these reference cycles to ensure the objects aren’t leaked. > I’m not sure exactly what the best way to make such tests is, but it seems > even more important to do that than to fix the bugs, so we don’t introduce > the bugs in the future.
I do not think we can easily create tests that show reference cycles. The GC is expected to not be monitorable from web apps. We might be able (?) to improve test runner to actually dump a list of JS objects that are not collected at the end of a test. This might then allow us to generate tests checking reference cycles.
youenn fablet
Comment 7
2015-07-31 08:52:02 PDT
Created
attachment 257922
[details]
Patch
youenn fablet
Comment 8
2015-07-31 09:03:15 PDT
(In reply to
comment #7
)
> Created
attachment 257922
[details]
> Patch
youenn fablet
Comment 9
2015-07-31 09:08:24 PDT
This patch tries to remove all JSC::Strong usage from ReadableStream. The separation between JSReadableStream and ReadableStream makes things more complex than it would be if implemented in JSC. This patch could probably be simplified by using RefCount instead of adding yet another counter for ensuring JS ReadableStream wrapper is not collected.
Build Bot
Comment 10
2015-07-31 09:33:09 PDT
Comment on
attachment 257922
[details]
Patch
Attachment 257922
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.webkit.org/results/3116
New failing tests: streams/reference-implementation/bad-underlying-sources.html streams/reference-implementation/readable-stream.html
Build Bot
Comment 11
2015-07-31 09:33:13 PDT
Created
attachment 257925
[details]
Archive of layout-test-results from ews104 for mac-mavericks-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews104 Port: mac-mavericks-wk2 Platform: Mac OS X 10.9.5
Build Bot
Comment 12
2015-07-31 09:47:21 PDT
Comment on
attachment 257922
[details]
Patch
Attachment 257922
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.webkit.org/results/3141
New failing tests: streams/reference-implementation/bad-underlying-sources.html streams/reference-implementation/readable-stream.html
Build Bot
Comment 13
2015-07-31 09:47:25 PDT
Created
attachment 257926
[details]
Archive of layout-test-results from ews101 for mac-mavericks The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: ews101 Port: mac-mavericks Platform: Mac OS X 10.9.5
Geoffrey Garen
Comment 14
2015-07-31 13:27:16 PDT
Comment on
attachment 257922
[details]
Patch EWS is failing.
youenn fablet
Comment 15
2015-08-03 03:18:42 PDT
Created
attachment 258052
[details]
Fixing crash
youenn fablet
Comment 16
2015-08-03 04:44:25 PDT
Created
attachment 258054
[details]
Simplifying patch
Xabier Rodríguez Calvar
Comment 17
2015-08-04 10:32:29 PDT
(In reply to
comment #6
)
> We might be able (?) to improve test runner to actually dump a list of JS > objects that are not collected at the end of a test. > This might then allow us to generate tests checking reference cycles.
I might be wrong, but I don't know if this is even possible, because I don't think GC is completely deterministic, so even if we add the still living objects in the expections, it would create tons of flakiness. Am I right? Maybe a special flag that you can activate for special tests testing it...
Xabier Rodríguez Calvar
Comment 18
2015-08-04 11:09:08 PDT
Comment on
attachment 258054
[details]
Simplifying patch View in context:
https://bugs.webkit.org/attachment.cgi?id=258054&action=review
Nice patch, nice tests. I asked about some concerts that are probably nothing and some nits about the tests.
> Source/WebCore/bindings/js/ReadableJSStream.cpp:137 > + RefPtr<ReadableJSStream> protectedStream(this);
I guess the case of this line is ensuring that the method is reentrant, right? I ask because you don't use it anywhere else in rest of the function.
> Source/WebCore/bindings/js/ReadableJSStream.cpp:165 > + RefPtr<ReadableJSStream> protectedStream(this);
Ditto.
> Source/WebCore/bindings/js/ReadableJSStream.cpp:205 > + RefPtr<ReadableJSStream> protectedStream(this);
Ditto.
> LayoutTests/streams/readable-stream-gc.html:73 > + controller.enqueue({ one: "test"}); > + controller.enqueue({ two: "test"}); > + controller.enqueue([ 10, { three: 'test' }]);
Nit: It could make sense to store these values in an array inside the test and then checking them below against the value for the index with assert_object_equals. It would make the test just a bit more maintainable, though you would't be able (probably) of though a so thorough type check like the one you do for the object of the [1] element of the third array...
> LayoutTests/streams/readable-stream-gc.html:88 > + reader.read().then(test4.step_func(function(iterator) { > + assert_equals(iterator.value.one, "test"); > + })); > + reader.read().then(test4.step_func(function(iterator) { > + assert_equals(iterator.value.two, "test"); > + })); > + reader.read().then(test4.step_func(function(iterator) { > + assert_equals(iterator.value[1].three, "test"); > + test4.done();
<paranoid mode>I would add a counter for read calls to test just before the done and test it for 3. That way you can ensure that the promise was resolve the 3 times and that nothing funny happened inbetween.</paranoid mode>
> LayoutTests/streams/readable-stream-gc.html:93 > +var test4b = async_test('Readable stream enqueued values when pulling should not be collectable');
I would renumber the test here. It is a PITA, but otherwise they could get out of hand with test4b1IPromiseNotToPutAnythingElseInBetween.
> LayoutTests/streams/readable-stream-gc.html:100 > + controller.enqueue({ one: "test"}); > + controller.enqueue({ two: "test"});
Same nit as for test4.
> LayoutTests/streams/readable-stream-gc.html:105 > + controller.enqueue([ 10, { three: 'test' }]); > + controller.enqueue([ 10, { four: 'test' }]);
Ditto.
> LayoutTests/streams/readable-stream-gc.html:108 > + garbageCollectAndDo(function() { });
What do you get with this? Would it make sense to create a function to force GC instead of calling a phony one?
> LayoutTests/streams/readable-stream-gc.html:122 > + reader.read().then(test4b.step_func(function(iterator) { > + assert_equals(iterator.value.one, "test"); > + })); > + reader.read().then(test4b.step_func(function(iterator) { > + assert_equals(iterator.value.two, "test"); > + })); > + reader.read().then(test4b.step_func(function(iterator) { > + assert_equals(iterator.value[1].three, "test"); > + test4b.done();
Read counter?
> LayoutTests/streams/readable-stream-gc.html:131 > + controller.error({ one: "test"});
I would keep the error outsize and create an actual Error that I could check against later.
> LayoutTests/streams/readable-stream-gc.html:143 > +var test5b = async_test('Readable stream error when pulling should not be collectable');
Renumbering?
> LayoutTests/streams/readable-stream-gc.html:147 > + controller.error({ one: "test"});
Keep error outside and check later against it.
> LayoutTests/streams/readable-stream-gc.html:166 > + controller.enqueue({ one: "test"}); > + controller.enqueue({ two: "test"}); > + controller.enqueue([ 10, { three: 'test' }]);
Again elements in array?
> LayoutTests/streams/readable-stream-gc.html:183 > + reader.read().then(test6.step_func(function(iterator) { > + assert_equals(iterator.value.one, "test"); > + })); > + reader.read().then(test6.step_func(function(iterator) { > + assert_equals(iterator.value.two, "test"); > + })); > + reader.read().then(test6.step_func(function(iterator) { > + assert_equals(iterator.value[1].three, "test"); > + assert_equals(sizeCalledCounter, 3);
Read count? Against sizeCalledCounter?
youenn fablet
Comment 19
2015-08-04 11:37:13 PDT
Thanks for the feedback.
> > Source/WebCore/bindings/js/ReadableJSStream.cpp:137 > > + RefPtr<ReadableJSStream> protectedStream(this); > > I guess the case of this line is ensuring that the method is reentrant, > right? I ask because you don't use it anywhere else in rest of the function.
It is not related to reentrancy but to GC actually. It is quite similar to using setPendingActivity/unsetPendingActivity so that the JSReadableStream wrapper is not collected throughout start/pull/cancel. I decided not to use setPendingActivity/unsetPendingActivity as it does not work well when used inside JS promise callbacks. If promise is never resolved nor rejected, we would have made a setPendingActivity call but we would not get a corresponding unsetPendingActivity call. With RefPtr protection, we do not have this issue. As of the test comments, I agree with most of them. Renumbering them and improving the value read checks as done in the other reference tests are good points. If needed, I can provide a patch with updated tests. But I think the tests can be updated at cq time/at follow-up patch time.
Xabier Rodríguez Calvar
Comment 20
2015-08-04 15:07:33 PDT
(In reply to
comment #19
)
> But I think the tests can be updated at cq time/at follow-up patch time.
Sounds good.
youenn fablet
Comment 21
2015-09-30 06:52:27 PDT
ReadableStream will move to JS Builtins
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug