Bug 1008421 - Remove JSString::parent. r=luke

--HG--
extra : rebase_source : d624662d22bdb11c2cc992138daff081729805c5
This commit is contained in:
Jan de Mooij 2014-05-14 13:32:22 +02:00
parent 98c9f31d64
commit 6974cfa696
3 changed files with 49 additions and 43 deletions

View File

@ -87,7 +87,7 @@ JSString::validateLength(js::ThreadSafeContext *maybecx, size_t length)
MOZ_ALWAYS_INLINE void
JSRope::init(js::ThreadSafeContext *cx, JSString *left, JSString *right, size_t length)
{
d.lengthAndFlags = buildLengthAndFlags(length, ROPE_FLAGS);
d.u0.lengthAndFlags = buildLengthAndFlags(length, ROPE_FLAGS);
d.u1.left = left;
d.s.u2.right = right;
js::StringWriteBarrierPost(cx, &d.u1.left);
@ -122,7 +122,7 @@ JSDependentString::init(js::ThreadSafeContext *cx, JSLinearString *base, const j
size_t length)
{
JS_ASSERT(!js::IsPoisonedPtr(base));
d.lengthAndFlags = buildLengthAndFlags(length, DEPENDENT_FLAGS);
d.u0.lengthAndFlags = buildLengthAndFlags(length, DEPENDENT_FLAGS);
d.u1.chars = chars;
d.s.u2.base = base;
js::StringWriteBarrierPost(cx, reinterpret_cast<JSString **>(&d.s.u2.base));
@ -185,7 +185,7 @@ JSString::markBase(JSTracer *trc)
MOZ_ALWAYS_INLINE void
JSFlatString::init(const jschar *chars, size_t length)
{
d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
d.u0.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
d.u1.chars = chars;
}
@ -229,7 +229,7 @@ JSInlineString::new_(js::ThreadSafeContext *cx)
MOZ_ALWAYS_INLINE jschar *
JSInlineString::init(size_t length)
{
d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
d.u0.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
d.u1.chars = d.inlineStorage;
JS_ASSERT(lengthFits(length) || (isFatInline() && JSFatInlineString::lengthFits(length)));
return d.inlineStorage;
@ -238,7 +238,7 @@ JSInlineString::init(size_t length)
MOZ_ALWAYS_INLINE void
JSInlineString::resetLength(size_t length)
{
d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
d.u0.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
JS_ASSERT(lengthFits(length) || (isFatInline() && JSFatInlineString::lengthFits(length)));
}
@ -254,7 +254,7 @@ JSExternalString::init(const jschar *chars, size_t length, const JSStringFinaliz
{
JS_ASSERT(fin);
JS_ASSERT(fin->finalize);
d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
d.u0.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
d.u1.chars = chars;
d.s.u2.externalFinalizer = fin;
}

View File

@ -231,8 +231,7 @@ JSRope::flattenInternal(ExclusiveContext *maybecx)
* To avoid maintaining a stack, tree nodes are mutated to indicate how many
* times they have been visited. Since ropes can be dags, a node may be
* encountered multiple times during traversal. However, step 3 above leaves
* a valid dependent string, so everything works out. This algorithm is
* homomorphic to marking code.
* a valid dependent string, so everything works out.
*
* While ropes avoid all sorts of quadratic cases with string
* concatenation, they can't help when ropes are immediately flattened.
@ -260,6 +259,14 @@ JSRope::flattenInternal(ExclusiveContext *maybecx)
JSString *str = this;
jschar *pos;
/*
* JSString::flattenData is a tagged pointer to the parent node.
* The tag indicates what to do when we return to the parent.
*/
static const uintptr_t Tag_Mask = 0x3;
static const uintptr_t Tag_FinishNode = 0x0;
static const uintptr_t Tag_VisitRightChild = 0x1;
/* Find the left most string, containing the first string. */
JSRope *leftMostRope = this;
while (leftMostRope->leftChild()->isRope())
@ -273,16 +280,16 @@ JSRope::flattenInternal(ExclusiveContext *maybecx)
* Simulate a left-most traversal from the root to leftMost->leftChild()
* via first_visit_node
*/
JS_ASSERT(str->isRope());
while (str != leftMostRope) {
JS_ASSERT(str->isRope());
if (b == WithIncrementalBarrier) {
JSString::writeBarrierPre(str->d.u1.left);
JSString::writeBarrierPre(str->d.s.u2.right);
}
JSString *child = str->d.u1.left;
JS_ASSERT(child->isRope());
str->d.u1.chars = left.chars();
child->d.s.u3.parent = str;
child->d.lengthAndFlags = 0x200;
child->d.u0.flattenData = uintptr_t(str) | Tag_VisitRightChild;
str = child;
}
if (b == WithIncrementalBarrier) {
@ -292,10 +299,10 @@ JSRope::flattenInternal(ExclusiveContext *maybecx)
str->d.u1.chars = left.chars();
wholeCapacity = capacity;
wholeChars = const_cast<jschar *>(left.chars());
size_t bits = left.d.lengthAndFlags;
size_t bits = left.d.u0.lengthAndFlags;
pos = wholeChars + (bits >> LENGTH_SHIFT);
JS_STATIC_ASSERT(!(EXTENSIBLE_FLAGS & DEPENDENT_FLAGS));
left.d.lengthAndFlags = bits ^ (EXTENSIBLE_FLAGS | DEPENDENT_FLAGS);
left.d.u0.lengthAndFlags = bits ^ (EXTENSIBLE_FLAGS | DEPENDENT_FLAGS);
left.d.s.u2.base = (JSLinearString *)this; /* will be true on exit */
StringWriteBarrierPostRemove(maybecx, &left.d.u1.left);
StringWriteBarrierPost(maybecx, (JSString **)&left.d.s.u2.base);
@ -317,8 +324,8 @@ JSRope::flattenInternal(ExclusiveContext *maybecx)
str->d.u1.chars = pos;
StringWriteBarrierPostRemove(maybecx, &str->d.u1.left);
if (left.isRope()) {
left.d.s.u3.parent = str; /* Return to this when 'left' done, */
left.d.lengthAndFlags = 0x200; /* but goto visit_right_child. */
/* Return to this node when 'left' done, then goto visit_right_child. */
left.d.u0.flattenData = uintptr_t(str) | Tag_VisitRightChild;
str = &left;
goto first_visit_node;
}
@ -329,8 +336,8 @@ JSRope::flattenInternal(ExclusiveContext *maybecx)
visit_right_child: {
JSString &right = *str->d.s.u2.right;
if (right.isRope()) {
right.d.s.u3.parent = str; /* Return to this node when 'right' done, */
right.d.lengthAndFlags = 0x300; /* but goto finish_node. */
/* Return to this node when 'right' done, then goto finish_node. */
right.d.u0.flattenData = uintptr_t(str) | Tag_FinishNode;
str = &right;
goto first_visit_node;
}
@ -342,21 +349,21 @@ JSRope::flattenInternal(ExclusiveContext *maybecx)
if (str == this) {
JS_ASSERT(pos == wholeChars + wholeLength);
*pos = '\0';
str->d.lengthAndFlags = buildLengthAndFlags(wholeLength, EXTENSIBLE_FLAGS);
str->d.u0.lengthAndFlags = buildLengthAndFlags(wholeLength, EXTENSIBLE_FLAGS);
str->d.u1.chars = wholeChars;
str->d.s.u2.capacity = wholeCapacity;
StringWriteBarrierPostRemove(maybecx, &str->d.u1.left);
StringWriteBarrierPostRemove(maybecx, &str->d.s.u2.right);
return &this->asFlat();
}
size_t progress = str->d.lengthAndFlags;
str->d.lengthAndFlags = buildLengthAndFlags(pos - str->d.u1.chars, DEPENDENT_FLAGS);
uintptr_t flattenData = str->d.u0.flattenData;
str->d.u0.lengthAndFlags = buildLengthAndFlags(pos - str->d.u1.chars, DEPENDENT_FLAGS);
str->d.s.u2.base = (JSLinearString *)this; /* will be true on exit */
StringWriteBarrierPost(maybecx, (JSString **)&str->d.s.u2.base);
str = str->d.s.u3.parent;
if (progress == 0x200)
str = (JSString *)(flattenData & ~Tag_Mask);
if ((flattenData & Tag_Mask) == Tag_VisitRightChild)
goto visit_right_child;
JS_ASSERT(progress == 0x300);
JS_ASSERT((flattenData & Tag_Mask) == Tag_FinishNode);
goto finish_node;
}
}
@ -465,7 +472,7 @@ JSDependentString::undepend(ExclusiveContext *cx)
* Transform *this into an undepended string so 'base' will remain rooted
* for the benefit of any other dependent string that depends on *this.
*/
d.lengthAndFlags = buildLengthAndFlags(n, UNDEPENDED_FLAGS);
d.u0.lengthAndFlags = buildLengthAndFlags(n, UNDEPENDED_FLAGS);
return &this->asFlat();
}

View File

@ -136,7 +136,10 @@ class JSString : public js::gc::BarrieredCell<JSString>
/* Fields only apply to string types commented on the right. */
struct Data
{
size_t lengthAndFlags; /* JSString */
union {
size_t lengthAndFlags; /* JSString */
uintptr_t flattenData; /* JSRope (temporary while flattening) */
} u0;
union {
const jschar *chars; /* JSLinearString */
JSString *left; /* JSRope */
@ -150,10 +153,6 @@ class JSString : public js::gc::BarrieredCell<JSString>
size_t capacity; /* JSFlatString (extensible) */
const JSStringFinalizer *externalFinalizer;/* JSExternalString */
} u2;
union {
JSString *parent; /* JSRope (temporary) */
size_t reserved; /* may use for bug 615290 */
} u3;
} s;
};
} d;
@ -252,12 +251,12 @@ class JSString : public js::gc::BarrieredCell<JSString>
MOZ_ALWAYS_INLINE
size_t length() const {
return d.lengthAndFlags >> LENGTH_SHIFT;
return d.u0.lengthAndFlags >> LENGTH_SHIFT;
}
MOZ_ALWAYS_INLINE
bool empty() const {
return d.lengthAndFlags <= FLAGS_MASK;
return d.u0.lengthAndFlags <= FLAGS_MASK;
}
/*
@ -299,7 +298,7 @@ class JSString : public js::gc::BarrieredCell<JSString>
MOZ_ALWAYS_INLINE
bool isRope() const {
return (d.lengthAndFlags & FLAGS_MASK) == ROPE_FLAGS;
return (d.u0.lengthAndFlags & FLAGS_MASK) == ROPE_FLAGS;
}
MOZ_ALWAYS_INLINE
@ -321,7 +320,7 @@ class JSString : public js::gc::BarrieredCell<JSString>
MOZ_ALWAYS_INLINE
bool isDependent() const {
return (d.lengthAndFlags & FLAGS_MASK) == DEPENDENT_FLAGS;
return (d.u0.lengthAndFlags & FLAGS_MASK) == DEPENDENT_FLAGS;
}
MOZ_ALWAYS_INLINE
@ -343,7 +342,7 @@ class JSString : public js::gc::BarrieredCell<JSString>
MOZ_ALWAYS_INLINE
bool isExtensible() const {
return (d.lengthAndFlags & FLAGS_MASK) == EXTENSIBLE_FLAGS;
return (d.u0.lengthAndFlags & FLAGS_MASK) == EXTENSIBLE_FLAGS;
}
MOZ_ALWAYS_INLINE
@ -376,17 +375,17 @@ class JSString : public js::gc::BarrieredCell<JSString>
MOZ_ALWAYS_INLINE
bool isUndepended() const {
return (d.lengthAndFlags & FLAGS_MASK) == UNDEPENDED_FLAGS;
return (d.u0.lengthAndFlags & FLAGS_MASK) == UNDEPENDED_FLAGS;
}
MOZ_ALWAYS_INLINE
bool isAtom() const {
return d.lengthAndFlags & ATOM_BIT;
return d.u0.lengthAndFlags & ATOM_BIT;
}
MOZ_ALWAYS_INLINE
bool isPermanentAtom() const {
return (d.lengthAndFlags & FLAGS_MASK) == PERMANENT_ATOM_FLAGS;
return (d.u0.lengthAndFlags & FLAGS_MASK) == PERMANENT_ATOM_FLAGS;
}
MOZ_ALWAYS_INLINE
@ -399,7 +398,7 @@ class JSString : public js::gc::BarrieredCell<JSString>
inline bool hasBase() const {
JS_STATIC_ASSERT((DEPENDENT_FLAGS | JS_BIT(1)) == UNDEPENDED_FLAGS);
return d.lengthAndFlags & HAS_BASE_BIT;
return d.u0.lengthAndFlags & HAS_BASE_BIT;
}
inline JSLinearString *base() const;
@ -417,7 +416,7 @@ class JSString : public js::gc::BarrieredCell<JSString>
/* Offsets for direct field from jit code. */
static size_t offsetOfLengthAndFlags() {
return offsetof(JSString, d.lengthAndFlags);
return offsetof(JSString, d.u0.lengthAndFlags);
}
static size_t offsetOfChars() {
@ -594,11 +593,11 @@ class JSFlatString : public JSLinearString
* operation changes the string to the JSAtom type, in place.
*/
MOZ_ALWAYS_INLINE JSAtom *morphAtomizedStringIntoAtom() {
d.lengthAndFlags = buildLengthAndFlags(length(), ATOM_BIT);
d.u0.lengthAndFlags = buildLengthAndFlags(length(), ATOM_BIT);
return &asAtom();
}
MOZ_ALWAYS_INLINE JSAtom *morphAtomizedStringIntoPermanentAtom() {
d.lengthAndFlags = buildLengthAndFlags(length(), PERMANENT_ATOM_FLAGS);
d.u0.lengthAndFlags = buildLengthAndFlags(length(), PERMANENT_ATOM_FLAGS);
return &asAtom();
}
@ -740,13 +739,13 @@ class JSAtom : public JSFlatString
MOZ_ALWAYS_INLINE
bool isPermanent() const {
return d.lengthAndFlags & PERMANENT_BIT;
return d.u0.lengthAndFlags & PERMANENT_BIT;
}
// Transform this atom into a permanent atom. This is only done during
// initialization of the runtime.
MOZ_ALWAYS_INLINE void morphIntoPermanentAtom() {
d.lengthAndFlags = buildLengthAndFlags(length(), PERMANENT_ATOM_FLAGS);
d.u0.lengthAndFlags = buildLengthAndFlags(length(), PERMANENT_ATOM_FLAGS);
}
#ifdef DEBUG