Consider IC for add/sub on Date
Categories
(Core :: JavaScript Engine: JIT, enhancement, P3)
Tracking
()
Tracking | Status | |
---|---|---|
firefox133 | --- | fixed |
People
(Reporter: evilpie, Assigned: debadree333)
References
(Blocks 1 open bug)
Details
Attachments
(3 files)
Updated•6 years ago
|
Comment 1•6 years ago
|
||
Updated•2 years ago
|
Assignee | ||
Comment 2•2 months ago
|
||
In case this bug is still relevant would adding a specialisation of Object <op> Object specialisation over here: https://searchfox.org/mozilla-central/source/js/src/jit/CacheIRGenerator.h#895 with specialisation say tryAttachObjectObjectArith which would in turn call these methods via callVM: https://searchfox.org/mozilla-central/source/js/src/vm/Interpreter-inl.h#624,693,725,741,765 be the way to approach this issue?
Assignee | ||
Updated•2 months ago
|
Comment 3•2 months ago
|
||
(In reply to Debadree Chatterjee from comment #2)
In case this bug is still relevant would adding a specialisation of Object <op> Object specialisation over here: https://searchfox.org/mozilla-central/source/js/src/jit/CacheIRGenerator.h#895 with specialisation say tryAttachObjectObjectArith which would in turn call these methods via callVM: https://searchfox.org/mozilla-central/source/js/src/vm/Interpreter-inl.h#624,693,725,741,765 be the way to approach this issue?
Exactly. We could call js::AddValues
, js::SubValues
etc directly from JIT code if the operands are both objects.
I'm not sure how much of a performance improvement it would be over the IC fallback code (IonBinaryArithIC::update
and the Baseline version, DoBinaryArithFallback
) because that does roughly the same thing although it also does some other things.
As a first step, I'd suggest adding some logging to IonBinaryArithIC::update
and DoBinaryArithFallback
to determine for the different JSOp
s handled there how common it is to have two object values as operands (could be just a printf
). You could then run the Speedometer 3 and JetStream 2 benchmarks in the browser and analyze the results.
If you do this we should also look at the type of objects (from obj->getClass()->name
). If 99% of the objects are Date
objects, maybe it makes sense to do something more efficient for just Date
objects.
Assignee | ||
Comment 4•2 months ago
|
||
Indeed it seems like Date is somewhat frequently used in speedometer! the only case seems to be Date - Date or Date - number (which makes sense i guess the use case is calculating time diff?) anyway running speedometer on the browser and sampling what hits IonBinaryArithIC::update
and DoBinaryArithFallback
i get the following https://pastebin.mozilla.org/TzxmEdt2 ! I am now investigating whether adding a specialisation improves it how much!
Assignee | ||
Comment 5•2 months ago
|
||
Updated•2 months ago
|
Assignee | ||
Comment 6•2 months ago
|
||
Depends on D223007
Comment 7•2 months ago
|
||
Assuming the "Op is Add|Sub" output comes after the lhs and rhs, that comes to:
Count | lhs | Op | rhs |
---|---|---|---|
1 | string | Add | BoundFunctionObject |
8 | Date | Sub | Date |
10 | string | Add | Object |
20 | Object | Add | string |
22 | number | Sub | Date |
350 | Function | Sub | number |
5092 | Date | Sub | number |
Why is it doing so many Function - number calls? Did I get the format wrong?
Comment 8•2 months ago
|
||
Assignee | ||
Comment 9•2 months ago
•
|
||
Thank you so much for summarising this is so nice!!
Yeah that seemed weird Function - number i thought about investigating it maybe its possible to print out the code that does this using the JSScript* structure? but i got to excited to write code instead hehe
Assignee | ||
Comment 10•2 months ago
|
||
Some more analysis using the amazing perl script provided by :sfink!
(note that we only log if either of lhs or rhs is an object)
On nightly startup and loading the homepage
Count | lhs | Op | rhs |
---|---|---|---|
1 | string | Add | BoundFunctionObject |
6 | Date | Sub | number |
379 | Date | Sub | Date |
On Jetstream2
Count | lhs | Op | rhs |
---|---|---|---|
1 | string | Add | BoundFunctionObject |
1 | string | Add | Date |
1 | Date | Add | string |
2 | string | Add | RegExp |
3 | Date | Sub | Date |
10 | Object | Add | string |
11 | number | Sub | Date |
45 | Function | Add | string |
84 | string | Add | Object |
101 | string | Add | Array |
1763 | string | Add | String |
On Octane2
Count | lhs | Op | rhs |
---|---|---|---|
19301 | Date | Sub | Date |
Regarding the weird Function <op> number operations:
I found this function seems to be the culprit https://github.com/WebKit/Speedometer/blob/ea14d27e03603bf796447598cf23b83788fca3f7/resources/perf.webkit.org/public/v3/components/time-series-chart.js#L414
but exact line number unable to figure out :-(
I used the following code the figure out the code i couldnt find a way to directly dump the code tho:
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -2276,6 +2276,36 @@ bool DoBinaryArithFallback(JSContext* cx
// generating stubs.
RootedValue lhsCopy(cx, lhs);
RootedValue rhsCopy(cx, rhs);
+ if (lhsCopy.isObject() || rhsCopy.isObject()) {
+ printf("===========DoBinaryArithFallback===========\n");
+ printf("lhs is of type %s and class %s\n", InformalValueTypeName(lhsCopy),
+ lhsCopy.isObject() ? lhsCopy.toObject().getClass()->name : "N/A");
+ printf("rhs is of type %s and class %s\n", InformalValueTypeName(rhsCopy),
+ rhsCopy.isObject() ? rhsCopy.toObject().getClass()->name : "N/A");
+ if (lhsCopy.isObject() && strcmp(lhsCopy.toObject().getClass()->name, "Function") == 0) {
+ frame->script()->dump(cx);
+ printf("the line num: %d", PCToLineNumber(frame->script(), pc));
+ }
+ if (rhsCopy.isObject() && strcmp(rhsCopy.toObject().getClass()->name, "Function") == 0) {
+ frame->script()->dump(cx);
+ printf("the line num: %d", PCToLineNumber(frame->script(), pc));
+ }
+ printf("===========================================\n");
+ switch (op) {
+ case JSOp::Add:
+ printf("Op is Add\n");
+ break;
+ case JSOp::Sub:
+ printf("Op is Sub\n");
+ break;
+ case JSOp::Mul:
+ printf("Op is Mul\n");
+ break;
+ case JSOp::Div:
+ printf("Op is Div\n");
+ break;
+ }
+ }
// Perform the arith operation.
switch (op) {
diff --git a/js/src/jit/IonIC.cpp b/js/src/jit/IonIC.cpp
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -589,6 +589,36 @@ bool IonBinaryArithIC::update(JSContext*
// generating stubs.
RootedValue lhsCopy(cx, lhs);
RootedValue rhsCopy(cx, rhs);
+ if (lhsCopy.isObject() || rhsCopy.isObject()) {
+ printf("===========IonBinaryArithIC===========\n");
+ printf("lhs is of type %s and class %s\n", InformalValueTypeName(lhsCopy),
+ lhsCopy.isObject() ? lhsCopy.toObject().getClass()->name : "N/A");
+ printf("rhs is of type %s and class %s\n", InformalValueTypeName(rhsCopy),
+ rhsCopy.isObject() ? rhsCopy.toObject().getClass()->name : "N/A");
+ printf("======================================\n");
+ if (lhsCopy.isObject() && strcmp(lhsCopy.toObject().getClass()->name, "Function") == 0) {
+ ic->script()->dump(cx);
+ printf("the line num: %d", PCToLineNumber(ic->script(), pc));
+ }
+ if (rhsCopy.isObject() && strcmp(rhsCopy.toObject().getClass()->name, "Function") == 0) {
+ ic->script()->dump(cx);
+ printf("the line num: %d", PCToLineNumber(ic->script(), pc));
+ }
+ switch (op) {
+ case JSOp::Add:
+ printf("Op is Add\n");
+ break;
+ case JSOp::Sub:
+ printf("Op is Sub\n");
+ break;
+ case JSOp::Mul:
+ printf("Op is Mul\n");
+ break;
+ case JSOp::Div:
+ printf("Op is Div\n");
+ break;
+ }
+ }
// Perform the compare operation.
switch (op) {
Are there any other benchmarks i could investigate in?
Also thank you once again :sfink for this amazing perl script i am inclined to try learning perl now!
Thank you!
Comment 11•1 month ago
|
||
Comment 12•1 month ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/94b2517be614
https://hg.mozilla.org/mozilla-central/rev/4a150e5d32d1
Description
•