diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index e7ac4469e3..4f7b22a09d 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -1576,10 +1576,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()), temp2); + masm.and32(Imm32(JSString::TYPE_FLAGS_MASK), temp2); + masm.branch32(Assembler::NotEqual, temp2, Imm32(JSString::DEPENDENT_FLAGS), &noBase); masm.loadPtr(Address(base, JSDependentString::offsetOfBase()), temp2); masm.storePtr(temp1, Address(string, JSDependentString::offsetOfBase())); masm.bind(&noBase); @@ -7719,7 +7718,7 @@ JitCompartment::generateStringConcatStub(JSContext* cx) // lhs and rhs flags, so we just have to clear the other flags and set // NON_ATOM_BIT to get our rope flags (Latin1 if both lhs and rhs are // Latin1). - static_assert(JSString::ROPE_FLAGS == JSString::NON_ATOM_BIT, + static_assert(JSString::INIT_ROPE_FLAGS == JSString::NON_ATOM_BIT, "Rope type flags must be NON_ATOM_BIT only"); masm.and32(Imm32(JSString::LATIN1_CHARS_BIT), temp1); masm.or32(Imm32(JSString::NON_ATOM_BIT), temp1); diff --git a/js/src/jit/MacroAssembler-inl.h b/js/src/jit/MacroAssembler-inl.h index bdf5305fa4..d84d37fd50 100644 --- a/js/src/jit/MacroAssembler-inl.h +++ b/js/src/jit/MacroAssembler-inl.h @@ -392,8 +392,7 @@ void MacroAssembler::branchIfRope(Register str, Label* label) { Address flags(str, JSString::offsetOfFlags()); - static_assert(JSString::ROPE_FLAGS == JSString::NON_ATOM_BIT, "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 @@ -403,9 +402,7 @@ MacroAssembler::branchIfRopeOrExternal(Register str, Register temp, Label* label move32(Imm32(JSString::TYPE_FLAGS_MASK), temp); and32(flags, temp); - static_assert(JSString::ROPE_FLAGS == JSString::NON_ATOM_BIT, "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); } @@ -413,8 +410,7 @@ void MacroAssembler::branchIfNotRope(Register str, Label* label) { Address flags(str, JSString::offsetOfFlags()); - static_assert(JSString::ROPE_FLAGS == JSString::NON_ATOM_BIT, "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 diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 5db137e50e..8269a0413c 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -586,9 +586,10 @@ struct Function { struct String { static const uint32_t NON_ATOM_BIT = JS_BIT(0); + static const uint32_t LINEAR_BIT = JS_BIT(1); static const uint32_t INLINE_CHARS_BIT = JS_BIT(3); static const uint32_t LATIN1_CHARS_BIT = JS_BIT(6); - static const uint32_t ROPE_FLAGS = NON_ATOM_BIT; + static const uint32_t EXTERNAL_FLAGS = LINEAR_BIT | NON_ATOM_BIT | JS_BIT(5); static const uint32_t TYPE_FLAGS_MASK = JS_BIT(6) - 1; uint32_t flags; uint32_t length; @@ -868,7 +869,7 @@ StringToLinearString(JSContext* cx, JSString* str) { using shadow::String; String* s = reinterpret_cast(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(str); } diff --git a/js/src/vm/String-inl.h b/js/src/vm/String-inl.h index 32009cccf4..ef567f21e5 100644 --- a/js/src/vm/String-inl.h +++ b/js/src/vm/String-inl.h @@ -103,7 +103,7 @@ MOZ_ALWAYS_INLINE void JSRope::init(js::ExclusiveContext* 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; diff --git a/js/src/vm/String.cpp b/js/src/vm/String.cpp index 37fc4a893c..2c24ba0161 100644 --- a/js/src/vm/String.cpp +++ b/js/src/vm/String.cpp @@ -194,7 +194,7 @@ JSString::dumpRepresentationHeader(FILE* fp, int indent, const char* subclass) c // Print the string's address as an actual C++ expression, to facilitate // copy-and-paste into a debugger. fprintf(fp, "((%s*) %p) length: %" PRIuSIZE " flags: 0x%x", subclass, this, length(), flags); - if (flags & FLAT_BIT) fputs(" FLAT", fp); + if (flags & LINEAR_BIT) fputs(" LINEAR", fp); if (flags & HAS_BASE_BIT) fputs(" HAS_BASE", fp); if (flags & INLINE_CHARS_BIT) fputs(" INLINE_CHARS", fp); if (flags & NON_ATOM_BIT) fputs(" NON_ATOM", fp); @@ -488,7 +488,10 @@ JSRope::flattenInternal(ExclusiveContext* maybecx) } str->setNonInlineChars(wholeChars); pos = wholeChars + left.d.u1.length; - left.d.u1.flags ^= (EXTENSIBLE_FLAGS | DEPENDENT_FLAGS); + if (IsSame::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 */ BarrierMethods::postBarrier((JSString**)&left.d.s.u3.base, nullptr, this); Nursery& nursery = zone()->group()->nursery(); diff --git a/js/src/vm/String.h b/js/src/vm/String.h index 531ad1f64c..c022c42004 100644 --- a/js/src/vm/String.h +++ b/js/src/vm/String.h @@ -256,24 +256,24 @@ class JSString : public js::gc::Cell */ static const uint32_t NON_ATOM_BIT = JS_BIT(0); - static const uint32_t FLAT_BIT = JS_BIT(1); + static const uint32_t LINEAR_BIT = JS_BIT(1); static const uint32_t HAS_BASE_BIT = JS_BIT(2); static const uint32_t INLINE_CHARS_BIT = JS_BIT(3); - static const uint32_t ROPE_FLAGS = NON_ATOM_BIT; - static const uint32_t DEPENDENT_FLAGS = NON_ATOM_BIT | HAS_BASE_BIT; - static const uint32_t UNDEPENDED_FLAGS = NON_ATOM_BIT | FLAT_BIT | HAS_BASE_BIT; - static const uint32_t EXTENSIBLE_FLAGS = NON_ATOM_BIT | FLAT_BIT | JS_BIT(4); - static const uint32_t EXTERNAL_FLAGS = NON_ATOM_BIT | JS_BIT(5); + static const uint32_t DEPENDENT_FLAGS = NON_ATOM_BIT | LINEAR_BIT | HAS_BASE_BIT; + static const uint32_t UNDEPENDED_FLAGS = NON_ATOM_BIT | LINEAR_BIT | HAS_BASE_BIT | JS_BIT(4); + static const uint32_t EXTENSIBLE_FLAGS = NON_ATOM_BIT | LINEAR_BIT | JS_BIT(4); + static const uint32_t EXTERNAL_FLAGS = NON_ATOM_BIT | 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 = NON_ATOM_BIT | JS_BIT(5); static const uint32_t PERMANENT_ATOM_FLAGS = JS_BIT(5); /* Initial flags for thin inline and fat inline strings. */ - static const uint32_t INIT_THIN_INLINE_FLAGS = NON_ATOM_BIT | FLAT_BIT | INLINE_CHARS_BIT; - static const uint32_t INIT_FAT_INLINE_FLAGS = NON_ATOM_BIT | FLAT_BIT | FAT_INLINE_MASK; - static const uint32_t INIT_FLAT_FLAGS = NON_ATOM_BIT | FLAT_BIT; + static const uint32_t INIT_THIN_INLINE_FLAGS = NON_ATOM_BIT | LINEAR_BIT | INLINE_CHARS_BIT; + static const uint32_t INIT_FAT_INLINE_FLAGS = NON_ATOM_BIT | LINEAR_BIT | FAT_INLINE_MASK; + static const uint32_t INIT_ROPE_FLAGS = NON_ATOM_BIT; + static const uint32_t INIT_FLAT_FLAGS = NON_ATOM_BIT | LINEAR_BIT; static const uint32_t TYPE_FLAGS_MASK = JS_BIT(6) - 1; @@ -317,14 +317,14 @@ class JSString : public js::gc::Cell "shadow::String inlineStorage offset must match JSString"); static_assert(NON_ATOM_BIT == String::NON_ATOM_BIT, "shadow::String::NON_ATOM_BIT must match JSString::NON_ATOM_BIT"); + 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"); } /* Avoid lame compile errors in JSRope::flatten */ @@ -373,7 +373,7 @@ class JSString : public js::gc::Cell MOZ_ALWAYS_INLINE bool isRope() const { - return (d.u1.flags & TYPE_FLAGS_MASK) == ROPE_FLAGS; + return !(d.u1.flags & LINEAR_BIT); } MOZ_ALWAYS_INLINE @@ -384,7 +384,7 @@ class JSString : public js::gc::Cell MOZ_ALWAYS_INLINE bool isLinear() const { - return !isRope(); + return d.u1.flags & LINEAR_BIT; } MOZ_ALWAYS_INLINE @@ -406,7 +406,7 @@ class JSString : public js::gc::Cell MOZ_ALWAYS_INLINE bool isFlat() const { - return d.u1.flags & FLAT_BIT; + return isLinear() && !isDependent() && !isExternal(); } MOZ_ALWAYS_INLINE