Bug 150945 - Regression(r191815): 5.3% regression on Dromaeo JS Library Benchmark
Summary: Regression(r191815): 5.3% regression on Dromaeo JS Library Benchmark
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Keith Miller
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-11-05 14:14 PST by Keith Miller
Modified: 2015-11-12 12:28 PST (History)
7 users (show)

See Also:


Attachments
Patch (53.75 KB, patch)
2015-11-06 15:08 PST, Keith Miller
no flags Details | Formatted Diff | Diff
Patch (52.24 KB, patch)
2015-11-06 15:23 PST, Keith Miller
no flags Details | Formatted Diff | Diff
Benchmark results (63.03 KB, text/plain)
2015-11-06 15:30 PST, Keith Miller
no flags Details
Archive of layout-test-results from ews101 for mac-mavericks (889.18 KB, application/zip)
2015-11-06 16:27 PST, Build Bot
no flags Details
Archive of layout-test-results from ews104 for mac-mavericks-wk2 (801.09 KB, application/zip)
2015-11-06 16:29 PST, Build Bot
no flags Details
Archive of layout-test-results from ews112 for mac-yosemite (1.09 MB, application/zip)
2015-11-06 16:33 PST, Build Bot
no flags Details
Patch (45.57 KB, patch)
2015-11-10 10:29 PST, Keith Miller
no flags Details | Formatted Diff | Diff
Patch (47.59 KB, patch)
2015-11-10 13:02 PST, Keith Miller
fpizlo: review+
Details | Formatted Diff | Diff
Patch (51.20 KB, patch)
2015-11-10 16:57 PST, Keith Miller
commit-queue: commit-queue-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Keith Miller 2015-11-05 14:14:19 PST
Regression(r191815): 5.3% regression on Dromaeo JS Library Benchmark
Comment 1 Keith Miller 2015-11-06 15:08:35 PST
Created attachment 264960 [details]
Patch
Comment 2 Keith Miller 2015-11-06 15:23:18 PST
Created attachment 264962 [details]
Patch
Comment 3 Keith Miller 2015-11-06 15:30:24 PST
Created attachment 264963 [details]
Benchmark results
Comment 4 Keith Miller 2015-11-06 15:33:12 PST
                                  WithoutTag                MyChanges

json-stringify-tinderbox        23.494+-3.259             23.436+-0.662

<arithmetic>                    23.494+-3.259             23.436+-0.662           might be 1.0025x faster
Comment 5 Keith Miller 2015-11-06 15:35:01 PST
Regression in benchmarks appear to be noise.

                                  WithoutTag                MyChanges

json-stringify-tinderbox        23.494+-3.259             23.436+-0.662

<arithmetic>                    23.494+-3.259             23.436+-0.662           might be 1.0025x faster
Comment 6 Geoffrey Garen 2015-11-06 15:35:35 PST
Can you add a regress performance test?
Comment 7 Keith Miller 2015-11-06 16:21:45 PST
Whoops, I forgot to upload the results of my test against tip of tree:

                               TOT                        MC

symbol-tostringtag       29.1231+-2.2000     ^      2.9094+-0.1330        ^ definitely 10.0101x faster

<geometric>              29.1231+-2.2000     ^      2.9094+-0.1330        ^ definitely 10.0101x faster
Comment 8 Build Bot 2015-11-06 16:26:41 PST
Comment on attachment 264962 [details]
Patch

Attachment 264962 [details] did not pass mac-ews (mac):
Output: http://webkit-queues.webkit.org/results/393535

New failing tests:
http/tests/security/cross-frame-access-history-get.html
http/tests/security/cross-frame-access-object-setPrototypeOf.html
http/tests/security/cross-frame-access-custom.html
http/tests/history/cross-origin-replace-history-object-child.html
Comment 9 Build Bot 2015-11-06 16:27:14 PST
Created attachment 264975 [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
Comment 10 Build Bot 2015-11-06 16:29:06 PST
Comment on attachment 264962 [details]
Patch

Attachment 264962 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.webkit.org/results/393536

New failing tests:
http/tests/security/cross-frame-access-object-setPrototypeOf.html
http/tests/security/cross-frame-access-custom.html
http/tests/history/cross-origin-replace-history-object-child.html
Comment 11 Build Bot 2015-11-06 16:29:38 PST
Created attachment 264976 [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
Comment 12 Build Bot 2015-11-06 16:32:55 PST
Comment on attachment 264962 [details]
Patch

Attachment 264962 [details] did not pass mac-debug-ews (mac):
Output: http://webkit-queues.webkit.org/results/393513

New failing tests:
http/tests/security/cross-frame-access-history-get.html
http/tests/security/cross-frame-access-object-setPrototypeOf.html
http/tests/security/cross-frame-access-custom.html
http/tests/history/cross-origin-replace-history-object-child.html
Comment 13 Build Bot 2015-11-06 16:33:28 PST
Created attachment 264977 [details]
Archive of layout-test-results from ews112 for mac-yosemite

The attached test failures were seen while running run-webkit-tests on the mac-debug-ews.
Bot: ews112  Port: mac-yosemite  Platform: Mac OS X 10.10.5
Comment 14 Filip Pizlo 2015-11-07 08:40:07 PST
Comment on attachment 264962 [details]
Patch

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

> Source/JavaScriptCore/ChangeLog:13
> +        This patch fixes a performance regression introduced by r191815. Before adding Symbol.toStringTag
> +        we would cache the value of Object.prototype.toString() in the rareData of the structure.
> +        In order to cache the result of Object.prototype.toString() we now need to ensure that the
> +        value stored in Symbol.toStringTag is a known constant. Thus, in order to ensure the stored Symbol.toStringTag
> +        value remains constant adaptive watchpoints have been refactored to be generalizable and new versions of
> +        them that clear out the toString value cache when fired have been added.

Why did you generalize adaptive watchpoints?

I think that this patch takes something that is very simple - the adaptive watchpoint code in the DFG - and makes it a lot more complicated just so that it can reuse a tiny part of that functionality for something that is only peripherally related.

Did you consider if maybe the code change would be smaller, and the result easier to understand, if you just wrote a specialized watchpoint for the toStringTag case?  I believe that you aren't actually saving any code by doing this kind of generalization.  Instead, you're making the code more complicated because now I have to search through multiple files to figure out what the firing of one of those watchpoints does.

> Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBase.h:36
> +template<typename T>

What is T?

> Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBaseInlines.h:68
> +    T::handleFire(static_cast<T*>(this), detail);

This is really weird.  Why isn't this a virtual method?

> Source/JavaScriptCore/dfg/DFGAdaptiveInferredPropertyValueWatchpoint.h:35
> +class DFGAdaptiveInferredPropertyValueWatchpoint : public AdaptiveInferredPropertyValueWatchpointBase<DFGAdaptiveInferredPropertyValueWatchpoint> {

This is an odd choice of name.  "DFG" is the name of a namespace.  It's strange to have something with a leading "DFG" in the "DFG" namespace.
Comment 15 Keith Miller 2015-11-09 11:21:48 PST
Comment on attachment 264962 [details]
Patch

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

>> Source/JavaScriptCore/ChangeLog:13
>> +        them that clear out the toString value cache when fired have been added.
> 
> Why did you generalize adaptive watchpoints?
> 
> I think that this patch takes something that is very simple - the adaptive watchpoint code in the DFG - and makes it a lot more complicated just so that it can reuse a tiny part of that functionality for something that is only peripherally related.
> 
> Did you consider if maybe the code change would be smaller, and the result easier to understand, if you just wrote a specialized watchpoint for the toStringTag case?  I believe that you aren't actually saving any code by doing this kind of generalization.  Instead, you're making the code more complicated because now I have to search through multiple files to figure out what the firing of one of those watchpoints does.

I generalized adaptive watchpoints because in order to make the toStringTag optimization we need to know that the value stored in the Symbol.toStringTag slot is a constant. If I were to implement a specialized watchpoint the code would be essentially identical to the adaptive watchpoint code. While, I agree that the code might be smaller and slightly less complex if wrote a specialized watchpoint the code maintenance overhead from having two roughly identical implementations is probably not worthwhile.

>> Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBaseInlines.h:68
>> +    T::handleFire(static_cast<T*>(this), detail);
> 
> This is really weird.  Why isn't this a virtual method?

In hindsight, this should definitely be a virtual method. Fixed.

>> Source/JavaScriptCore/dfg/DFGAdaptiveInferredPropertyValueWatchpoint.h:35
>> +class DFGAdaptiveInferredPropertyValueWatchpoint : public AdaptiveInferredPropertyValueWatchpointBase<DFGAdaptiveInferredPropertyValueWatchpoint> {
> 
> This is an odd choice of name.  "DFG" is the name of a namespace.  It's strange to have something with a leading "DFG" in the "DFG" namespace.

I started the name with DFG because that was the name of the file. Perhaps I should start it with CodeJettisoning instead.
Comment 16 Filip Pizlo 2015-11-09 11:27:44 PST
(In reply to comment #15)
> Comment on attachment 264962 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=264962&action=review
> 
> >> Source/JavaScriptCore/ChangeLog:13
> >> +        them that clear out the toString value cache when fired have been added.
> > 
> > Why did you generalize adaptive watchpoints?
> > 
> > I think that this patch takes something that is very simple - the adaptive watchpoint code in the DFG - and makes it a lot more complicated just so that it can reuse a tiny part of that functionality for something that is only peripherally related.
> > 
> > Did you consider if maybe the code change would be smaller, and the result easier to understand, if you just wrote a specialized watchpoint for the toStringTag case?  I believe that you aren't actually saving any code by doing this kind of generalization.  Instead, you're making the code more complicated because now I have to search through multiple files to figure out what the firing of one of those watchpoints does.
> 
> I generalized adaptive watchpoints because in order to make the toStringTag
> optimization we need to know that the value stored in the Symbol.toStringTag
> slot is a constant. If I were to implement a specialized watchpoint the code
> would be essentially identical to the adaptive watchpoint code. While, I
> agree that the code might be smaller and slightly less complex if wrote a
> specialized watchpoint the code maintenance overhead from having two roughly
> identical implementations is probably not worthwhile.

There is a non-trivial cost to any code that uses templates in this manner.  We have to weigh that cost against the cost of slight code duplication.

Note that we already have multiple watchpoints that essentially duplicate this pattern.  It's a simple pattern to work with, so I don't think it's bad to duplicate it.

> 
> >> Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBaseInlines.h:68
> >> +    T::handleFire(static_cast<T*>(this), detail);
> > 
> > This is really weird.  Why isn't this a virtual method?
> 
> In hindsight, this should definitely be a virtual method. Fixed.

Does that allow you to get rid of the template stuff?

> 
> >> Source/JavaScriptCore/dfg/DFGAdaptiveInferredPropertyValueWatchpoint.h:35
> >> +class DFGAdaptiveInferredPropertyValueWatchpoint : public AdaptiveInferredPropertyValueWatchpointBase<DFGAdaptiveInferredPropertyValueWatchpoint> {
> > 
> > This is an odd choice of name.  "DFG" is the name of a namespace.  It's strange to have something with a leading "DFG" in the "DFG" namespace.
> 
> I started the name with DFG because that was the name of the file. Perhaps I
> should start it with CodeJettisoning instead.
Comment 17 Keith Miller 2015-11-09 11:48:08 PST
(In reply to comment #16)
> (In reply to comment #15)
> > Comment on attachment 264962 [details]
> > Patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=264962&action=review
> > 
> > >> Source/JavaScriptCore/ChangeLog:13
> > >> +        them that clear out the toString value cache when fired have been added.
> > > 
> > > Why did you generalize adaptive watchpoints?
> > > 
> > > I think that this patch takes something that is very simple - the adaptive watchpoint code in the DFG - and makes it a lot more complicated just so that it can reuse a tiny part of that functionality for something that is only peripherally related.
> > > 
> > > Did you consider if maybe the code change would be smaller, and the result easier to understand, if you just wrote a specialized watchpoint for the toStringTag case?  I believe that you aren't actually saving any code by doing this kind of generalization.  Instead, you're making the code more complicated because now I have to search through multiple files to figure out what the firing of one of those watchpoints does.
> > 
> > I generalized adaptive watchpoints because in order to make the toStringTag
> > optimization we need to know that the value stored in the Symbol.toStringTag
> > slot is a constant. If I were to implement a specialized watchpoint the code
> > would be essentially identical to the adaptive watchpoint code. While, I
> > agree that the code might be smaller and slightly less complex if wrote a
> > specialized watchpoint the code maintenance overhead from having two roughly
> > identical implementations is probably not worthwhile.
> 
> There is a non-trivial cost to any code that uses templates in this manner. 
> We have to weigh that cost against the cost of slight code duplication.
> 
> Note that we already have multiple watchpoints that essentially duplicate
> this pattern.  It's a simple pattern to work with, so I don't think it's bad
> to duplicate it.
> 

Is "this pattern" referring to the general watchpoint pattern or the adaptive watchpoint pattern? The inferred property value watchpoint in particular seems sufficiently complex for it to be profitable to have a generalized version.

> > 
> > >> Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBaseInlines.h:68
> > >> +    T::handleFire(static_cast<T*>(this), detail);
> > > 
> > > This is really weird.  Why isn't this a virtual method?
> > 
> > In hindsight, this should definitely be a virtual method. Fixed.
> 
> Does that allow you to get rid of the template stuff?
> 

Yes. It's gone now.
Comment 18 Filip Pizlo 2015-11-09 11:59:03 PST
(In reply to comment #17)
> (In reply to comment #16)
> > (In reply to comment #15)
> > > Comment on attachment 264962 [details]
> > > Patch
> > > 
> > > View in context:
> > > https://bugs.webkit.org/attachment.cgi?id=264962&action=review
> > > 
> > > >> Source/JavaScriptCore/ChangeLog:13
> > > >> +        them that clear out the toString value cache when fired have been added.
> > > > 
> > > > Why did you generalize adaptive watchpoints?
> > > > 
> > > > I think that this patch takes something that is very simple - the adaptive watchpoint code in the DFG - and makes it a lot more complicated just so that it can reuse a tiny part of that functionality for something that is only peripherally related.
> > > > 
> > > > Did you consider if maybe the code change would be smaller, and the result easier to understand, if you just wrote a specialized watchpoint for the toStringTag case?  I believe that you aren't actually saving any code by doing this kind of generalization.  Instead, you're making the code more complicated because now I have to search through multiple files to figure out what the firing of one of those watchpoints does.
> > > 
> > > I generalized adaptive watchpoints because in order to make the toStringTag
> > > optimization we need to know that the value stored in the Symbol.toStringTag
> > > slot is a constant. If I were to implement a specialized watchpoint the code
> > > would be essentially identical to the adaptive watchpoint code. While, I
> > > agree that the code might be smaller and slightly less complex if wrote a
> > > specialized watchpoint the code maintenance overhead from having two roughly
> > > identical implementations is probably not worthwhile.
> > 
> > There is a non-trivial cost to any code that uses templates in this manner. 
> > We have to weigh that cost against the cost of slight code duplication.
> > 
> > Note that we already have multiple watchpoints that essentially duplicate
> > this pattern.  It's a simple pattern to work with, so I don't think it's bad
> > to duplicate it.
> > 
> 
> Is "this pattern" referring to the general watchpoint pattern or the
> adaptive watchpoint pattern? The inferred property value watchpoint in
> particular seems sufficiently complex for it to be profitable to have a
> generalized version.

I just mean having a fire() method that does this:

    if (!m_key.isWatchable(PropertyCondition::EnsureWatchability)) {
        // jettison code, clear a stub, whatever.
        return;
    }
    
    m_key.object()->structure()->addTransitionWatchpoint(this);

But I get now that you're referring to the more complex logic involved in inferred values.  I can see wanting that to be abstract.

> 
> > > 
> > > >> Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBaseInlines.h:68
> > > >> +    T::handleFire(static_cast<T*>(this), detail);
> > > > 
> > > > This is really weird.  Why isn't this a virtual method?
> > > 
> > > In hindsight, this should definitely be a virtual method. Fixed.
> > 
> > Does that allow you to get rid of the template stuff?
> > 
> 
> Yes. It's gone now.

OK - put the patch up when you're ready.
Comment 19 Keith Miller 2015-11-10 10:29:03 PST
Created attachment 265195 [details]
Patch
Comment 20 Keith Miller 2015-11-10 13:02:17 PST
Created attachment 265221 [details]
Patch
Comment 21 Keith Miller 2015-11-10 13:04:10 PST
Re-uploaded the patch since I forgot an expect and needed to rebase. Other than that it is the same however.
Comment 22 Keith Miller 2015-11-10 16:57:47 PST
Created attachment 265248 [details]
Patch
Comment 23 Keith Miller 2015-11-10 17:00:50 PST
Added a new patch to check CMake build... :|
Comment 24 Chris Dumez 2015-11-11 13:22:05 PST
(In reply to comment #23)
> Added a new patch to check CMake build... :|

Ready to commit?
Comment 25 WebKit Commit Bot 2015-11-11 13:25:02 PST
Comment on attachment 265248 [details]
Patch

Rejecting attachment 265248 [details] from commit-queue.

Failed to run "['/Volumes/Data/EWS/WebKit/Tools/Scripts/webkit-patch', '--status-host=webkit-queues.webkit.org', '--bot-id=webkit-cq-01', 'apply-attachment', '--no-update', '--non-interactive', 265248, '--port=mac']" exit_code: 2 cwd: /Volumes/Data/EWS/WebKit

Last 500 characters of output:

patching file LayoutTests/ChangeLog
Hunk #1 succeeded at 1 with fuzz 3.
patching file LayoutTests/http/tests/history/cross-origin-replace-history-object-child-expected.txt
patching file LayoutTests/js/regress/script-tests/symbol-tostringtag.js
patching file LayoutTests/js/regress/symbol-tostringtag-expected.txt
patching file LayoutTests/js/regress/symbol-tostringtag.html

Failed to run "[u'/Volumes/Data/EWS/WebKit/Tools/Scripts/svn-apply', '--force']" exit_code: 1 cwd: /Volumes/Data/EWS/WebKit

Full output: http://webkit-queues.webkit.org/results/416073
Comment 26 Keith Miller 2015-11-11 13:25:50 PST
Guess I need to do it by hand.
Comment 27 Keith Miller 2015-11-11 13:34:55 PST
Committed r192321: <http://trac.webkit.org/changeset/192321>