Bug 227677 - [JSC] Optimize Object.assign and putDirectInternal
Summary: [JSC] Optimize Object.assign and putDirectInternal
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: Yusuke Suzuki
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2021-07-04 23:14 PDT by Yusuke Suzuki
Modified: 2021-07-06 13:20 PDT (History)
12 users (show)

See Also:


Attachments
Patch (61.71 KB, patch)
2021-07-04 23:21 PDT, Yusuke Suzuki
no flags Details | Formatted Diff | Diff
Patch (61.64 KB, patch)
2021-07-04 23:23 PDT, Yusuke Suzuki
no flags Details | Formatted Diff | Diff
Patch (58.99 KB, patch)
2021-07-05 00:15 PDT, Yusuke Suzuki
fpizlo: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Yusuke Suzuki 2021-07-04 23:14:45 PDT
[JSC] Optimize Object.assign and putDirectInternal
Comment 1 Yusuke Suzuki 2021-07-04 23:21:05 PDT
Created attachment 432871 [details]
Patch
Comment 2 Yusuke Suzuki 2021-07-04 23:23:24 PDT
Created attachment 432872 [details]
Patch
Comment 3 Yusuke Suzuki 2021-07-05 00:15:48 PDT
Created attachment 432873 [details]
Patch
Comment 4 Filip Pizlo 2021-07-05 09:59:05 PDT
Comment on attachment 432873 [details]
Patch

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

> Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:2941
> +            // ToObject is idempotent if it succeeds. Plus, it is non-observable except for the case that an exception is thrown. And when the exception is thrown,
> +            // we exit from DFG / FTL. Plus, we keep ordering of these two ToObject because clobberizing rule says clobberTop. So,
> +            // we can say exitOK for each ToObject.

If it's only observable when an exception is thrown, then why do you need to put in ExitOK?
Comment 5 Yusuke Suzuki 2021-07-06 12:22:05 PDT
Comment on attachment 432873 [details]
Patch

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

>> Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:2941
>> +            // we can say exitOK for each ToObject.
> 
> If it's only observable when an exception is thrown, then why do you need to put in ExitOK?

The reason is that, even for exception-exit, we make it ExitInvalid. In fix-up phase, we convert them to `Identify(Check:Object)` in many cases, and then we failed to insert these checks since the state is ExitInvalid.
We need to ensure that state is ExitOK after these ToObject.
Comment 6 Yusuke Suzuki 2021-07-06 12:25:13 PDT
Committed r279604 (239428@main): <https://commits.webkit.org/239428@main>
Comment 7 Radar WebKit Bug Importer 2021-07-06 12:26:18 PDT
<rdar://problem/80225148>
Comment 8 Darin Adler 2021-07-06 12:30:12 PDT
Comment on attachment 432873 [details]
Patch

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

> Source/JavaScriptCore/ChangeLog:17
> +            2.2. Before r277620, we are checking m_replacementWatchpointSets's nullptr and that was fast. But after that, we are always
> +                 calling HashMap::get, and it is not inlined. This means that if we have StructureRareData, we are always calling HashMap::get
> +                 even though there is no m_replacementWatchpointSets set. This patch adds HashMap::isNullStorage to avoid this call by inlinely
> +                 check this via `LIKELY(m_replacementWatchpointSets.isNullStorage())`.

It seems like this is not a unique case. Should we instead change HashMap::get so that the empty case is always inlined and marked LIKELY? Or add an overload of HashMap::get? Not wanting to block landing this; seems like a more-refined way to handle this that can help many other call sites.
Comment 9 Yusuke Suzuki 2021-07-06 12:33:38 PDT
Comment on attachment 432873 [details]
Patch

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

>> Source/JavaScriptCore/ChangeLog:17
>> +                 check this via `LIKELY(m_replacementWatchpointSets.isNullStorage())`.
> 
> It seems like this is not a unique case. Should we instead change HashMap::get so that the empty case is always inlined and marked LIKELY? Or add an overload of HashMap::get? Not wanting to block landing this; seems like a more-refined way to handle this that can help many other call sites.

I think whether nullptr is LIKELY or not highly depends on the places. I think many HashMaps will have at least one entry and in that case, this LIKELY will rather hurt the performance.
But in this place, nullptr is highly expected, and that's why I inserted this branch for this place.
I think it is OK to inline `if (m_table)` check in HashMap::get globally, but I don't think putting `LIKELY` there is good.
Comment 10 Darin Adler 2021-07-06 13:20:15 PDT
Comment on attachment 432873 [details]
Patch

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

>>> Source/JavaScriptCore/ChangeLog:17
>>> +                 check this via `LIKELY(m_replacementWatchpointSets.isNullStorage())`.
>> 
>> It seems like this is not a unique case. Should we instead change HashMap::get so that the empty case is always inlined and marked LIKELY? Or add an overload of HashMap::get? Not wanting to block landing this; seems like a more-refined way to handle this that can help many other call sites.
> 
> I think whether nullptr is LIKELY or not highly depends on the places. I think many HashMaps will have at least one entry and in that case, this LIKELY will rather hurt the performance.
> But in this place, nullptr is highly expected, and that's why I inserted this branch for this place.
> I think it is OK to inline `if (m_table)` check in HashMap::get globally, but I don't think putting `LIKELY` there is good.

Sounds fine.

I am pretty sure that there are a lot of "almost always empty" maps. I agree that there are also many "likely to have at least one thing" maps. In the end we just have to measure like we always do. Could have multiple versions of get and find if this really has to be carefully optimized.