RESOLVED FIXED Bug 201633
[JSC] Remove CheckAdd in JetStream2/async-fs's Math.random function
https://bugs.webkit.org/show_bug.cgi?id=201633
Summary [JSC] Remove CheckAdd in JetStream2/async-fs's Math.random function
Yusuke Suzuki
Reported 2019-09-09 23:18:37 PDT
Math.random function implementation in async-fs repeatedly emits CheckAdd. And this makes PutGlobalVariable un-sunkable, and bloats many code that is not inherently necessary. 35 return function() { 36 // Robert Jenkins' 32 bit integer hash function. 37 seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; 38 seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; 39 seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; 40 seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; 41 seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; 42 seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; 43 return (seed & 0xfffffff) / 0x10000000; 44 }; But seems that `& 0xffffffff` is saying that we only care lower 32bit. I would like to check how to remove the above check-add and make this efficient.
Attachments
Patch (10.32 KB, patch)
2019-09-20 22:09 PDT, Yusuke Suzuki
no flags
Patch (10.32 KB, patch)
2019-09-20 22:17 PDT, Yusuke Suzuki
mark.lam: review+
Yusuke Suzuki
Comment 1 2019-09-19 01:35:57 PDT
(In reply to Yusuke Suzuki from comment #0) > Math.random function implementation in async-fs repeatedly emits CheckAdd. > And this makes PutGlobalVariable un-sunkable, and bloats many code that is > not inherently necessary. > > 35 return function() { > 36 // Robert Jenkins' 32 bit integer hash function. > 37 seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; > 38 seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; > 39 seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; > 40 seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; > 41 seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; > 42 seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; > 43 return (seed & 0xfffffff) / 0x10000000; > 44 }; > > But seems that `& 0xffffffff` is saying that we only care lower 32bit. I > would like to check how to remove the above check-add and make this > efficient. Maybe, we should do integer-range-optimization in B3 to convert CheckAdd to Add. Then, CSE should work.
Yusuke Suzuki
Comment 2 2019-09-19 01:42:11 PDT
Or, extend existing DFG IntegerRangeOptimization Phase.
Yusuke Suzuki
Comment 3 2019-09-19 02:02:29 PDT
After looking through the code, I think, 1. We can improve things in B3 by analyzing integer-range. 2. But in this case, we can easily improve it in DFG since DFG knows Int52Rep(Int32) semantics while it is encoded into shift in B3 And the most common case in general JS code with Int52 is `ArithAdd(Int52Rep(Int32), Int52Constant)`, which will be shown when we decide upgrading Int32 to Int52. After considering about it, I'm guessing this is soooooooooo common than I expected (maybe, the most common pattern for Int52 calculation?). If we can remove CheckOverflow from this, we could improve many programs (even in non-FTL) very easily. While (1) is attractive, just adding (2) adhocly also looks nice to me. (1) looks nice to me too, it could potentially improve bound-checked Wasm code...? I'm not sure.
Yusuke Suzuki
Comment 4 2019-09-20 18:30:01 PDT
Or, we can do this easily in B3, checking.
Yusuke Suzuki
Comment 5 2019-09-20 19:09:32 PDT
Do it in B3 first. I found that this is super easy.
Yusuke Suzuki
Comment 6 2019-09-20 22:09:28 PDT
Yusuke Suzuki
Comment 7 2019-09-20 22:17:47 PDT
Radar WebKit Bug Importer
Comment 8 2019-09-20 22:55:55 PDT
Mark Lam
Comment 9 2019-09-21 20:56:48 PDT
Comment on attachment 379306 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=379306&action=review Nice. r=me > Source/JavaScriptCore/ChangeLog:25 > + This converts many CheckAdd in JetStream2/async-fs's hot function simple Add, removes bunch of unnecessary instructions which exist because of this OSR exit. /function simple Add, removes bunch/function to simple Add, and removes a bunch/. > Source/JavaScriptCore/b3/testb3_5.cpp:950 > + CHECK(invoke<int64_t>(*code, value) == 2ll * static_cast<int32_t>(value)); Why is this static_cast necessary?
Yusuke Suzuki
Comment 10 2019-09-22 00:18:53 PDT
Comment on attachment 379306 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=379306&action=review >> Source/JavaScriptCore/b3/testb3_5.cpp:950 >> + CHECK(invoke<int64_t>(*code, value) == 2ll * static_cast<int32_t>(value)); > > Why is this static_cast necessary? This code is precisely simulating the B3's code, like, first performing SExt8, just for readability.
Yusuke Suzuki
Comment 11 2019-09-22 00:19:47 PDT
Mark Lam
Comment 12 2019-09-22 00:38:03 PDT
Comment on attachment 379306 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=379306&action=review >>> Source/JavaScriptCore/b3/testb3_5.cpp:950 >>> + CHECK(invoke<int64_t>(*code, value) == 2ll * static_cast<int32_t>(value)); >> >> Why is this static_cast necessary? > > This code is precisely simulating the B3's code, like, first performing SExt8, just for readability. Yeah, but you don't do this for the SExt16 case below. I noticed the inconsistency and wondered why. It's not a big deal as the code behaves the same either way.
Yusuke Suzuki
Comment 13 2019-09-22 02:02:58 PDT
Comment on attachment 379306 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=379306&action=review >>>> Source/JavaScriptCore/b3/testb3_5.cpp:950 >>>> + CHECK(invoke<int64_t>(*code, value) == 2ll * static_cast<int32_t>(value)); >>> >>> Why is this static_cast necessary? >> >> This code is precisely simulating the B3's code, like, first performing SExt8, just for readability. > > Yeah, but you don't do this for the SExt16 case below. I noticed the inconsistency and wondered why. It's not a big deal as the code behaves the same either way. I see, I'll add the static_cast to SExt16 case too!
Yusuke Suzuki
Comment 14 2019-09-22 02:08:32 PDT
Note You need to log in before you can comment on or make changes to this bug.