Closed
Bug 614653
Opened 14 years ago
Closed 14 years ago
avoid O(n^2) rope node marking
Categories
(Core :: JavaScript Engine, defect)
Core
JavaScript Engine
Tracking
()
RESOLVED
FIXED
People
(Reporter: luke, Assigned: luke)
Details
(Whiteboard: fixed-in-tracemonkey)
Attachments
(1 file)
5.24 KB,
patch
|
gwagner
:
review+
|
Details | Diff | Splinter Review |
This pathological case takes 3s:
var arr = [];
var s = "abcdefghijklmnop";
for (var i = 0; i < 10000; ++i) {
s = "<" + s + ">";
arr.push(s);
}
gc();
Having TypedMarker return early when a rope node is already marked takes 2ms. I think rope marking could be further improved to skip the initial "walk to the left-most node" step by using str->asCell()->isMarked() as the "visited" bit in a traditional tree traversal.
Assignee | ||
Comment 1•14 years ago
|
||
Using "isMarked" as "visited" wasn't such a hot idea. This patch just avoids the O(n^2) behavior.
Attachment #493124 -
Flags: review?(igor)
Comment 2•14 years ago
|
||
Comment on attachment 493124 [details] [diff] [review]
fix
>diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h
> static JS_ALWAYS_INLINE void
>-TypedMarker(JSTracer *trc, JSString *thing)
>+TypedMarker(JSTracer *trc, JSString *str)
> {
>+ JSRopeNodeIterator iter;
>+ if (str->isRope()) {
>+ if (str->asCell()->isMarked())
>+ return;
That does not work as isMarked is only available for GCMarker. It does not work for a generic marker like CC one or various debug dumping.
Attachment #493124 -
Flags: review?(igor) → review-
Assignee | ||
Comment 3•14 years ago
|
||
Ok. So, is there an equivalent to isMarked() for generic markers?
Assignee | ||
Comment 4•14 years ago
|
||
Also, why is it valid for TypedMarker to call str->asCell()->markIfUnmarked (which uses str->asCell()->isMarked()) a few lines later?
Assignee | ||
Comment 5•14 years ago
|
||
Perhaps Gregor has an answer?
Comment 6•14 years ago
|
||
(In reply to comment #2)
> Comment on attachment 493124 [details] [diff] [review]
> fix
>
> >diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h
> > static JS_ALWAYS_INLINE void
> >-TypedMarker(JSTracer *trc, JSString *thing)
> >+TypedMarker(JSTracer *trc, JSString *str)
> > {
> >+ JSRopeNodeIterator iter;
> >+ if (str->isRope()) {
> >+ if (str->asCell()->isMarked())
> >+ return;
>
> That does not work as isMarked is only available for GCMarker. It does not work
> for a generic marker like CC one or various debug dumping.
We don't even call TypedMarker if IS_GC_MARKING_TRACER returns false.
Assignee | ||
Updated•14 years ago
|
Attachment #493124 -
Flags: review- → review?(anygregor)
Comment 7•14 years ago
|
||
Comment on attachment 493124 [details] [diff] [review]
fix
>diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h
>--- a/js/src/jsgcinlines.h
>+++ b/js/src/jsgcinlines.h
>@@ -346,28 +346,34 @@ TypedMarker(JSTracer *trc, JSFunction *t
>
> static JS_ALWAYS_INLINE void
> TypedMarker(JSTracer *trc, JSShortString *thing)
> {
> thing->asCell()->markIfUnmarked();
> }
>
> static JS_ALWAYS_INLINE void
>-TypedMarker(JSTracer *trc, JSString *thing)
>+TypedMarker(JSTracer *trc, JSString *str)
> {
> /*
>- * Iterate through all nodes and leaves in the rope if this is part of a
>- * rope; otherwise, we only iterate once: on the string itself.
>+ * When marking any node of a rope, mark the entire rope. This means if
>+ * a given rope node is already marked, we are done.
> */
>- JSRopeNodeIterator iter(thing);
>- JSString *str = iter.init();
>+ JSRopeNodeIterator iter;
>+ if (str->isRope()) {
>+ if (str->asCell()->isMarked())
>+ return;
>+ str = iter.init(str);
>+ goto not_static;
Uhhh a goto from Luke :) I hope the jump target doesn't slow down the loop.
If I change your motivating example and always append a string at the beginning I still have to go the slow path right?
Attachment #493124 -
Flags: review?(anygregor) → review+
Assignee | ||
Comment 8•14 years ago
|
||
(In reply to comment #7)
> Uhhh a goto from Luke :)
http://hg.mozilla.org/tracemonkey/annotate/67dd268276f3/js/src/jsstr.cpp#l136
Yeah, I've been using them a lot recently ;-)
> I hope the jump target doesn't slow down the loop.
>
> If I change your motivating example and always append a string at the beginning
> I still have to go the slow path right?
I'm not sure what you mean by "append a string at the beginning", do you mean, switch the order of the two statements in the loop? Also, which "slow path" are you referring to?
Assignee | ||
Comment 9•14 years ago
|
||
Whiteboard: fixed-in-tracemonkey
Comment 10•14 years ago
|
||
Status: ASSIGNED → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
You need to log in
before you can comment on or make changes to this bug.
Description
•