Bug 1434263 - Refactor JSString to have an IsLinear flag instead of IsFlat. r=luke

This commit is contained in:
Jan de Mooij 2018-02-01 15:29:29 +01:00
Родитель ff91a17fb3
Коммит aac278c57c
6 изменённых файлов: 39 добавлений и 41 удалений

Просмотреть файл

@ -1626,10 +1626,9 @@ CreateDependentString::generate(MacroAssembler& masm, const JSAtomState& names,
// Watch for undepended strings, which have a base pointer but don't
// actually share their characters with it.
Label noBase;
masm.branchTest32(Assembler::Zero, Address(base, JSString::offsetOfFlags()),
Imm32(JSString::HAS_BASE_BIT), &noBase);
masm.branchTest32(Assembler::NonZero, Address(base, JSString::offsetOfFlags()),
Imm32(JSString::FLAT_BIT), &noBase);
masm.load32(Address(base, JSString::offsetOfFlags()), temp1);
masm.and32(Imm32(JSString::TYPE_FLAGS_MASK), temp1);
masm.branch32(Assembler::NotEqual, temp1, Imm32(JSString::DEPENDENT_FLAGS), &noBase);
masm.loadPtr(Address(base, JSDependentString::offsetOfBase()), temp1);
masm.storePtr(temp1, Address(string, JSDependentString::offsetOfBase()));
masm.bind(&noBase);
@ -8032,7 +8031,7 @@ JitCompartment::generateStringConcatStub(JSContext* cx)
// Store rope length and flags. temp1 still holds the result of AND'ing the
// lhs and rhs flags, so we just have to clear the other flags to get our
// rope flags (Latin1 if both lhs and rhs are Latin1).
static_assert(JSString::ROPE_FLAGS == 0, "Rope flags must be 0");
static_assert(JSString::INIT_ROPE_FLAGS == 0, "Rope type flags must be 0");
masm.and32(Imm32(JSString::LATIN1_CHARS_BIT), temp1);
masm.store32(temp1, Address(output, JSString::offsetOfFlags()));
masm.store32(temp2, Address(output, JSString::offsetOfLength()));

Просмотреть файл

@ -397,8 +397,7 @@ void
MacroAssembler::branchIfRope(Register str, Label* label)
{
Address flags(str, JSString::offsetOfFlags());
static_assert(JSString::ROPE_FLAGS == 0, "Rope type flags must be 0");
branchTest32(Assembler::Zero, flags, Imm32(JSString::TYPE_FLAGS_MASK), label);
branchTest32(Assembler::Zero, flags, Imm32(JSString::LINEAR_BIT), label);
}
void
@ -408,8 +407,7 @@ MacroAssembler::branchIfRopeOrExternal(Register str, Register temp, Label* label
move32(Imm32(JSString::TYPE_FLAGS_MASK), temp);
and32(flags, temp);
static_assert(JSString::ROPE_FLAGS == 0, "Rope type flags must be 0");
branchTest32(Assembler::Zero, temp, temp, label);
branchTest32(Assembler::Zero, temp, Imm32(JSString::LINEAR_BIT), label);
branch32(Assembler::Equal, temp, Imm32(JSString::EXTERNAL_FLAGS), label);
}
@ -418,8 +416,7 @@ void
MacroAssembler::branchIfNotRope(Register str, Label* label)
{
Address flags(str, JSString::offsetOfFlags());
static_assert(JSString::ROPE_FLAGS == 0, "Rope type flags must be 0");
branchTest32(Assembler::NonZero, flags, Imm32(JSString::TYPE_FLAGS_MASK), label);
branchTest32(Assembler::NonZero, flags, Imm32(JSString::LINEAR_BIT), label);
}
void

Просмотреть файл

@ -612,10 +612,10 @@ struct Function {
struct String
{
static const uint32_t LINEAR_BIT = JS_BIT(0);
static const uint32_t INLINE_CHARS_BIT = JS_BIT(2);
static const uint32_t LATIN1_CHARS_BIT = JS_BIT(6);
static const uint32_t ROPE_FLAGS = 0;
static const uint32_t EXTERNAL_FLAGS = JS_BIT(5);
static const uint32_t EXTERNAL_FLAGS = JS_BIT(0) | JS_BIT(5);
static const uint32_t TYPE_FLAGS_MASK = JS_BIT(6) - 1;
uint32_t flags;
uint32_t length;
@ -904,7 +904,7 @@ StringToLinearString(JSContext* cx, JSString* str)
{
using shadow::String;
String* s = reinterpret_cast<String*>(str);
if (MOZ_UNLIKELY((s->flags & String::TYPE_FLAGS_MASK) == String::ROPE_FLAGS))
if (MOZ_UNLIKELY(!(s->flags & String::LINEAR_BIT)))
return StringToLinearStringSlow(cx, str);
return reinterpret_cast<JSLinearString*>(str);
}

Просмотреть файл

@ -109,7 +109,7 @@ MOZ_ALWAYS_INLINE void
JSRope::init(JSContext* cx, JSString* left, JSString* right, size_t length)
{
d.u1.length = length;
d.u1.flags = ROPE_FLAGS;
d.u1.flags = INIT_ROPE_FLAGS;
if (left->hasLatin1Chars() && right->hasLatin1Chars())
d.u1.flags |= LATIN1_CHARS_BIT;
d.s.u2.left = left;
@ -206,7 +206,7 @@ MOZ_ALWAYS_INLINE void
JSFlatString::init(const char16_t* chars, size_t length)
{
d.u1.length = length;
d.u1.flags = FLAT_BIT;
d.u1.flags = LINEAR_BIT;
d.s.u2.nonInlineCharsTwoByte = chars;
}
@ -214,7 +214,7 @@ MOZ_ALWAYS_INLINE void
JSFlatString::init(const JS::Latin1Char* chars, size_t length)
{
d.u1.length = length;
d.u1.flags = FLAT_BIT | LATIN1_CHARS_BIT;
d.u1.flags = LINEAR_BIT | LATIN1_CHARS_BIT;
d.s.u2.nonInlineCharsLatin1 = chars;
}

Просмотреть файл

@ -205,7 +205,7 @@ JSString::dumpRepresentationHeader(js::GenericPrinter& out, int indent, const ch
// Print the string's address as an actual C++ expression, to facilitate
// copy-and-paste into a debugger.
out.printf("((%s*) %p) length: %zu flags: 0x%x", subclass, this, length(), flags);
if (flags & FLAT_BIT) out.put(" FLAT");
if (flags & LINEAR_BIT) out.put(" LINEAR");
if (flags & HAS_BASE_BIT) out.put(" HAS_BASE");
if (flags & INLINE_CHARS_BIT) out.put(" INLINE_CHARS");
if (flags & ATOM_BIT) out.put(" ATOM");
@ -497,8 +497,10 @@ JSRope::flattenInternal(JSContext* maybecx)
wholeCapacity = capacity;
wholeChars = const_cast<CharT*>(left.nonInlineChars<CharT>(nogc));
pos = wholeChars + left.d.u1.length;
JS_STATIC_ASSERT(!(EXTENSIBLE_FLAGS & DEPENDENT_FLAGS));
left.d.u1.flags ^= (EXTENSIBLE_FLAGS | DEPENDENT_FLAGS);
if (IsSame<CharT, char16_t>::value)
left.d.u1.flags = DEPENDENT_FLAGS;
else
left.d.u1.flags = DEPENDENT_FLAGS | LATIN1_CHARS_BIT;
left.d.s.u3.base = (JSLinearString*)this; /* will be true on exit */
StringWriteBarrierPostRemove(maybecx, &left.d.s.u2.left);
StringWriteBarrierPost(maybecx, (JSString**)&left.d.s.u3.base);
@ -1102,7 +1104,7 @@ JSExternalString::ensureFlat(JSContext* cx)
// Transform the string into a non-external, flat string.
setNonInlineChars<char16_t>(s);
d.u1.flags = FLAT_BIT;
d.u1.flags = LINEAR_BIT;
return &this->asFlat();
}

Просмотреть файл

@ -220,13 +220,13 @@ class JSString : public js::gc::TenuredCell
* String Instance Subtype
* type encoding predicate
* ------------------------------------
* Rope 000000 000000
* Linear - !000000
* Rope 000000 xxxxx0
* Linear - xxxxx1
* HasBase - xxxx1x
* Dependent 000010 000010
* External 100000 100000
* Flat - xxxxx1
* Undepended 000011 000011
* Dependent 000011 000011
* External 100001 100001
* Flat - Linear && !Dependent && !External
* Undepended 010011 010011
* Extensible 010001 010001
* Inline 000101 xxx1xx
* FatInline 010101 x1x1xx
@ -238,7 +238,7 @@ class JSString : public js::gc::TenuredCell
* Note that the first 4 flag bits (from right to left in the previous table)
* have the following meaning and can be used for some hot queries:
*
* Bit 0: IsFlat
* Bit 0: IsLinear
* Bit 1: HasBase (Dependent, Undepended)
* Bit 2: IsInline (Inline, FatInline)
* Bit 3: IsAtom (Atom, PermanentAtom)
@ -253,23 +253,23 @@ class JSString : public js::gc::TenuredCell
* index.
*/
static const uint32_t FLAT_BIT = JS_BIT(0);
static const uint32_t LINEAR_BIT = JS_BIT(0);
static const uint32_t HAS_BASE_BIT = JS_BIT(1);
static const uint32_t INLINE_CHARS_BIT = JS_BIT(2);
static const uint32_t ATOM_BIT = JS_BIT(3);
static const uint32_t ROPE_FLAGS = 0;
static const uint32_t DEPENDENT_FLAGS = HAS_BASE_BIT;
static const uint32_t UNDEPENDED_FLAGS = FLAT_BIT | HAS_BASE_BIT;
static const uint32_t EXTENSIBLE_FLAGS = FLAT_BIT | JS_BIT(4);
static const uint32_t EXTERNAL_FLAGS = JS_BIT(5);
static const uint32_t DEPENDENT_FLAGS = LINEAR_BIT | HAS_BASE_BIT;
static const uint32_t UNDEPENDED_FLAGS = LINEAR_BIT | HAS_BASE_BIT | JS_BIT(4);
static const uint32_t EXTENSIBLE_FLAGS = LINEAR_BIT | JS_BIT(4);
static const uint32_t EXTERNAL_FLAGS = LINEAR_BIT | JS_BIT(5);
static const uint32_t FAT_INLINE_MASK = INLINE_CHARS_BIT | JS_BIT(4);
static const uint32_t PERMANENT_ATOM_MASK = ATOM_BIT | JS_BIT(5);
/* Initial flags for thin inline and fat inline strings. */
static const uint32_t INIT_THIN_INLINE_FLAGS = FLAT_BIT | INLINE_CHARS_BIT;
static const uint32_t INIT_FAT_INLINE_FLAGS = FLAT_BIT | FAT_INLINE_MASK;
static const uint32_t INIT_THIN_INLINE_FLAGS = LINEAR_BIT | INLINE_CHARS_BIT;
static const uint32_t INIT_FAT_INLINE_FLAGS = LINEAR_BIT | FAT_INLINE_MASK;
static const uint32_t INIT_ROPE_FLAGS = 0;
static const uint32_t TYPE_FLAGS_MASK = JS_BIT(6) - 1;
@ -316,14 +316,14 @@ class JSString : public js::gc::TenuredCell
"shadow::String inlineStorage offset must match JSString");
static_assert(offsetof(JSString, d.inlineStorageTwoByte) == offsetof(String, inlineStorageTwoByte),
"shadow::String inlineStorage offset must match JSString");
static_assert(LINEAR_BIT == String::LINEAR_BIT,
"shadow::String::LINEAR_BIT must match JSString::LINEAR_BIT");
static_assert(INLINE_CHARS_BIT == String::INLINE_CHARS_BIT,
"shadow::String::INLINE_CHARS_BIT must match JSString::INLINE_CHARS_BIT");
static_assert(LATIN1_CHARS_BIT == String::LATIN1_CHARS_BIT,
"shadow::String::LATIN1_CHARS_BIT must match JSString::LATIN1_CHARS_BIT");
static_assert(TYPE_FLAGS_MASK == String::TYPE_FLAGS_MASK,
"shadow::String::TYPE_FLAGS_MASK must match JSString::TYPE_FLAGS_MASK");
static_assert(ROPE_FLAGS == String::ROPE_FLAGS,
"shadow::String::ROPE_FLAGS must match JSString::ROPE_FLAGS");
static_assert(EXTERNAL_FLAGS == String::EXTERNAL_FLAGS,
"shadow::String::EXTERNAL_FLAGS must match JSString::EXTERNAL_FLAGS");
}
@ -384,7 +384,7 @@ class JSString : public js::gc::TenuredCell
MOZ_ALWAYS_INLINE
bool isRope() const {
return (d.u1.flags & TYPE_FLAGS_MASK) == ROPE_FLAGS;
return !(d.u1.flags & LINEAR_BIT);
}
MOZ_ALWAYS_INLINE
@ -395,7 +395,7 @@ class JSString : public js::gc::TenuredCell
MOZ_ALWAYS_INLINE
bool isLinear() const {
return !isRope();
return d.u1.flags & LINEAR_BIT;
}
MOZ_ALWAYS_INLINE
@ -417,7 +417,7 @@ class JSString : public js::gc::TenuredCell
MOZ_ALWAYS_INLINE
bool isFlat() const {
return d.u1.flags & FLAT_BIT;
return isLinear() && !isDependent() && !isExternal();
}
MOZ_ALWAYS_INLINE