Closed Bug 582974 Opened 14 years ago Closed 13 years ago

Slow property ops on "water" testcase

Categories

(Core :: JavaScript Engine, defect)

x86
macOS
defect
Not set
normal

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: bzbarsky, Unassigned)

References

()

Details

We're slower than Chrome on this testcase, and about 45% of the time is in jseng.  It's mostly on trace (42% under ExecuteTree), and breaks down like so (all percentages of total testcase time):

8% Running jitted code
18% SetPropertyByIndex calling js_SetProperty; about half of this is under
    JSScope::putProperty adding properties, and the other half is
    js_LookupPropertyWithFlags, js_NativeSet, time spent in js_SetPropertyHelper
    itself, etc.
8% GetPropertyByIndex (js_LookupPropertyWithFlags called from
   js_GetPropertyHelper here, as well as some other random stuff).

Are we missing the propcache?  Would PICs in JM help here?

The testcase is attached in bug 582973 as well as linked in the url field
This must mean setters -- cc'ing jorendorff.

bz: JSScope::putProperty if it doesn't tail-call JSScope::addPropertyHelper right away is not adding properties, it is changing existing (defined as bound by id in the object) properties.

/be
I don't think there are any setters here.  Just array indexing... using negative indices at times, so producing slow arrays.  At least that's what I see us hitting js::TraceRecorder::initOrSetPropertyByIndex and js::TraceRecorder::getPropertyByIndex for.  Example |obj| when coming through the latter:

(gdb) p obj->isDenseArray()
$20 = false
(gdb) call js_DumpObject(obj)
object 0x1b221a80
class 0x5de6a0 Array
properties:
    enumerate 271: slot 280
    enumerate 236: slot 279
    enumerate 235: slot 278
    enumerate 234: slot 277
    enumerate 233: slot 276
    enumerate 232: slot 275
    enumerate 231: slot 274
    enumerate 230: slot 273
....
    enumerate -1: slot 43
    enumerate -2: slot 42
    enumerate -3: slot 41
    enumerate -4: slot 40

etc.  This array even has holes (slots 2, 3, and 5-10 contain undefined).
Slow arrays would explain the perf issue, for sure.  I guess we need the hybrid-storage arrays or something similar.
Yikes, negative array indexing.

If the access sites are using o[i] and not o[-1], there's no likely PIC story in general (perhaps this benchmark uses only a small set of negative indexes).

Here is a dirty idea: optimize negative indexes as if they are dense, off the end of our dense length limit (if we still have one).

/be
That idea makes me a little nervous in my fast-path places.  Growing the array into the region of negative wraparound would require 

Having arrays use a side object for named properties would probably be not extremely difficult.  If we never wanted to make arrays slow due to sparse indexed property use, it would simplify things too.
> If the access sites are using o[i] and not o[-1]

We're talking stuff like this:

  levels[y - (dataHeightMap[index] * HEIGHT >> 10) ] = y;

in hot loops.  Also nonnegative access on sparse arrays like so:

  index = indices[y];
  data[index + 1] = pixel - 64 + (y >> 2);
  data[index + 2] = pixel - 32 + (y >> 2);

> (perhaps this benchmark uses only a small set of negative indexes)

I assume "40" is not small in this context?  The array I was looking at had about that many.

We use slow arrays on sparse use to avoid unnecessary huge buffers, right?  I'm not sure we have a good way to deal with that without slow-ifying....
We use slow arrays on non-index use basically because I thought it was rare and it avoided needing more complex property lookup code.   That array doesn't look sparse to me, so I think it's mostly a case of us wanting to be able to have named properties (including those named "-1" and such) without losing the fast path for indexed ones.

Do V8 or JSC have fast paths for negative indexes?
JSC takes a slow path if the index, as a 32-bit unsigned integer, compares >= to the array length.
So... what happens with us is that if the _first_ prop you set on an array is a negative one, then we will compile the slow path in TM with no guard as far as I can see.  And then we will take that path for all indexed prop sets on that array.  Then again, I see no guard on the index in the index >= 0 case either.  Am I just missing it?

For the gets, we just lose because the arrays aren't dense so we go through the resolve thing no matter what, even for nonnegative indices.
This is very smooth with JM+TI.
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.