Closed Bug 602366 Opened 14 years ago Closed 13 years ago

Add a JSOP_COPYELEM bytecode

Categories

(Core :: JavaScript Engine, defect)

x86
macOS
defect
Not set
normal

Tracking

()

RESOLVED WONTFIX

People

(Reporter: n.nethercote, Unassigned)

References

Details

This idea has come up several times, most recently in bug 598655.  Repeating bug 598655 comment 17:

A GETELEM/SETELEM pair on an initialized dense array,
eg. a[j] = a[i]; involves these steps in trace-generated code (I imagine JM
code must do similar things):

GETELEM
1. load pointer to 'a' from the stack
2. if 'a' is not a dense array, exit
3. if 'i' exceeds the capacity of 'a', exit
4. load the dslots pointer of 'a'
5. compute the address of the dslot for a[i]
6. load a[i]'s tag from the dslot
7. if the tag doesn't match the expected type, exit
8. load a[i]'s payload 
9. unbox the value
10. store the unboxed value on the stack

SETELEM
11. load pointer to 'a' from the stack
12. if 'a' is not a dense array, exit
13. if 'j' exceeds the capacity of 'a', call js_EnsureDenseArrayCapacity()
14. load the dslots pointer of 'a'
15. compute the address of the dslot for a[j]
16. load the a[j]'s existing tag from the dslot
17. if the existing tag is for a hole, call js_Array_dense_setelem_hole
18. box the new value
19. store the boxed value into a[j]'s dslot

Horrid, isn't it?  

Here's what COPYELEM would do:

COPYELEM
1. load pointer to 'a' from the stack
2. if 'a' is not a dense array, exit
3. if 'i' exceeds the capacity of 'a', exit
4. if 'j' exceeds the capacity of 'a', call js_EnsureDenseArrayCapacity()
5. load the dslots pointer of 'a'
6. compute the address of the dslot for a[i]
7. load a[i]'s tag and payload from the dslot
8. compute the address of the dslot for a[j]
9. load a[j]'s existing tag
10. if the existing tag is for a hole, call js_Array_dense_setelem_hole
11. store a[i]'s tag and payload into a[j]'s slot.

So this has the following benefits (for trace-generated code):
- No need to reload 'a' from the stack and test if it's a dense array.
  (The tracer can omit these steps thanks to CSE, but the methodjit
  presumably can't.)

- No need to reload the dslots pointer and recompute the dslots address.
  (The tracer can't CSE those in the GETELEM/SETELEM version because of the
  possibly intervening call to js_EnsureDenseArrayCapacity(), which can
  reallocate dslots.)

- No need to do anything with the gotten value -- type-test it, unbox it, or
  store it to the stack.

So that's quite a bit better, I would guess close to 2x faster.  This
assumes that COPYELEM does not put a copy of the element on the stack;
doing so would negate several of the potential benefits, and it doesn't make
much sense.

One issue would be whether the front-end fuses separate GETELEM/SETELEM
pairs, eg:

  var tmp = a[i];
  a[j] = tmp;

You'd hope so, but I'm not certain, I don't know much about the front-end.
Things can get more complicated if there is code between the GETELEM and the
SETELEM.
Blocks: 601988
New benchmark code and results in

https://bugzilla.mozilla.org/show_bug.cgi?id=601988#c14
https://bugzilla.mozilla.org/show_bug.cgi?id=601988#c15

appear to be good examples of code that would greatly benefit from a COPYELEM bytecode. In particular the combination of COPYELEM with typed arrays seems very promising for improving performance.
Nb: bug 486802 is a dup of this;  it was marked WONTFIX.  I'm not sure that's the right decision.
(In reply to comment #2)
> Nb: bug 486802 is a dup of this;  it was marked WONTFIX.  I'm not sure that's
> the right decision.

I was pretty sure at the time that it was premature, and I think you've proved the case.

/be
This might still be a good idea even once TM goes away, but I won't be working on it.
Assignee: nnethercote → general
Status: ASSIGNED → NEW
Summary: TM: add a JSOP_COPYELEM bytecode → Add a JSOP_COPYELEM bytecode
This won't be needed in IM, if we read an untyped value off the heap we don't need to unbox it.
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.