зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1018311 part 2 - Support creating dependent latin1 strings. r=luke
This commit is contained in:
Родитель
9f2d98a7d2
Коммит
50c08461e0
|
@ -4082,11 +4082,16 @@ js_NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t len
|
||||||
if (start == 0 && length == base->length())
|
if (start == 0 && length == base->length())
|
||||||
return base;
|
return base;
|
||||||
|
|
||||||
{
|
if (base->hasTwoByteChars()) {
|
||||||
AutoCheckCannotGC nogc;
|
AutoCheckCannotGC nogc;
|
||||||
const jschar *chars = base->twoByteChars(nogc) + start;
|
const jschar *chars = base->twoByteChars(nogc) + start;
|
||||||
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
|
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
|
||||||
return staticStr;
|
return staticStr;
|
||||||
|
} else {
|
||||||
|
AutoCheckCannotGC nogc;
|
||||||
|
const Latin1Char *chars = base->latin1Chars(nogc) + start;
|
||||||
|
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
|
||||||
|
return staticStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSDependentString::new_(cx, base, start, length);
|
return JSDependentString::new_(cx, base, start, length);
|
||||||
|
|
|
@ -19,24 +19,24 @@
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
template <AllowGC allowGC, typename CharT>
|
||||||
static MOZ_ALWAYS_INLINE JSInlineString *
|
static MOZ_ALWAYS_INLINE JSInlineString *
|
||||||
AllocateFatInlineString(ThreadSafeContext *cx, size_t len, jschar **chars)
|
AllocateFatInlineString(ThreadSafeContext *cx, size_t len, CharT **chars)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(JSFatInlineString::twoByteLengthFits(len));
|
MOZ_ASSERT(JSFatInlineString::lengthFits<CharT>(len));
|
||||||
|
|
||||||
if (JSInlineString::twoByteLengthFits(len)) {
|
if (JSInlineString::lengthFits<CharT>(len)) {
|
||||||
JSInlineString *str = JSInlineString::new_<allowGC>(cx);
|
JSInlineString *str = JSInlineString::new_<allowGC>(cx);
|
||||||
if (!str)
|
if (!str)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
*chars = str->initTwoByte(len);
|
*chars = str->init<CharT>(len);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSFatInlineString *str = JSFatInlineString::new_<allowGC>(cx);
|
JSFatInlineString *str = JSFatInlineString::new_<allowGC>(cx);
|
||||||
if (!str)
|
if (!str)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
*chars = str->initTwoByte(len);
|
*chars = str->init<CharT>(len);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +77,23 @@ NewFatInlineString(ExclusiveContext *cx, JS::TwoByteChars chars)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename CharT>
|
||||||
|
static MOZ_ALWAYS_INLINE JSInlineString *
|
||||||
|
NewFatInlineString(ExclusiveContext *cx, Handle<JSLinearString*> base, size_t start, size_t length)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(JSFatInlineString::lengthFits<CharT>(length));
|
||||||
|
|
||||||
|
CharT *chars;
|
||||||
|
JSInlineString *s = AllocateFatInlineString<CanGC>(cx, length, &chars);
|
||||||
|
if (!s)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
AutoCheckCannotGC nogc;
|
||||||
|
mozilla::PodCopy(chars, base->chars<CharT>(nogc) + start, length);
|
||||||
|
chars[length] = 0;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
StringWriteBarrierPost(js::ThreadSafeContext *maybecx, JSString **strp)
|
StringWriteBarrierPost(js::ThreadSafeContext *maybecx, JSString **strp)
|
||||||
{
|
{
|
||||||
|
@ -143,9 +160,14 @@ JSDependentString::init(js::ThreadSafeContext *cx, JSLinearString *base, size_t
|
||||||
MOZ_ASSERT(!js::IsPoisonedPtr(base));
|
MOZ_ASSERT(!js::IsPoisonedPtr(base));
|
||||||
MOZ_ASSERT(start + length <= base->length());
|
MOZ_ASSERT(start + length <= base->length());
|
||||||
d.u1.length = length;
|
d.u1.length = length;
|
||||||
d.u1.flags = DEPENDENT_FLAGS;
|
|
||||||
JS::AutoCheckCannotGC nogc;
|
JS::AutoCheckCannotGC nogc;
|
||||||
|
if (base->hasLatin1Chars()) {
|
||||||
|
d.u1.flags = DEPENDENT_FLAGS | LATIN1_CHARS_BIT;
|
||||||
|
d.s.u2.nonInlineCharsLatin1 = base->latin1Chars(nogc) + start;
|
||||||
|
} else {
|
||||||
|
d.u1.flags = DEPENDENT_FLAGS;
|
||||||
d.s.u2.nonInlineCharsTwoByte = base->twoByteChars(nogc) + start;
|
d.s.u2.nonInlineCharsTwoByte = base->twoByteChars(nogc) + start;
|
||||||
|
}
|
||||||
d.s.u3.base = base;
|
d.s.u3.base = base;
|
||||||
js::StringWriteBarrierPost(cx, reinterpret_cast<JSString **>(&d.s.u3.base));
|
js::StringWriteBarrierPost(cx, reinterpret_cast<JSString **>(&d.s.u3.base));
|
||||||
}
|
}
|
||||||
|
@ -168,17 +190,14 @@ JSDependentString::new_(js::ExclusiveContext *cx, JSLinearString *baseArg, size_
|
||||||
* both to avoid the awkward moving-GC hazard this introduces and because it
|
* both to avoid the awkward moving-GC hazard this introduces and because it
|
||||||
* is more efficient to immediately undepend here.
|
* is more efficient to immediately undepend here.
|
||||||
*/
|
*/
|
||||||
if (JSFatInlineString::twoByteLengthFits(length)) {
|
bool useFatInline = baseArg->hasTwoByteChars()
|
||||||
|
? JSFatInlineString::twoByteLengthFits(length)
|
||||||
|
: JSFatInlineString::latin1LengthFits(length);
|
||||||
|
if (useFatInline) {
|
||||||
JS::Rooted<JSLinearString*> base(cx, baseArg);
|
JS::Rooted<JSLinearString*> base(cx, baseArg);
|
||||||
jschar *chars;
|
if (baseArg->hasLatin1Chars())
|
||||||
JSInlineString *s = js::AllocateFatInlineString<js::CanGC>(cx, length, &chars);
|
return js::NewFatInlineString<JS::Latin1Char>(cx, base, start, length);
|
||||||
if (!s)
|
return js::NewFatInlineString<jschar>(cx, base, start, length);
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
JS::AutoCheckCannotGC nogc;
|
|
||||||
mozilla::PodCopy(chars, base->twoByteChars(nogc) + start, length);
|
|
||||||
chars[length] = 0;
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSDependentString *str = (JSDependentString *)js_NewGCString<js::NoGC>(cx);
|
JSDependentString *str = (JSDependentString *)js_NewGCString<js::NoGC>(cx);
|
||||||
|
@ -284,6 +303,34 @@ JSFatInlineString::initLatin1(size_t length)
|
||||||
return d.inlineStorageLatin1;
|
return d.inlineStorageLatin1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
MOZ_ALWAYS_INLINE JS::Latin1Char *
|
||||||
|
JSInlineString::init<JS::Latin1Char>(size_t length)
|
||||||
|
{
|
||||||
|
return initLatin1(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
MOZ_ALWAYS_INLINE jschar *
|
||||||
|
JSInlineString::init<jschar>(size_t length)
|
||||||
|
{
|
||||||
|
return initTwoByte(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
MOZ_ALWAYS_INLINE JS::Latin1Char *
|
||||||
|
JSFatInlineString::init<JS::Latin1Char>(size_t length)
|
||||||
|
{
|
||||||
|
return initLatin1(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
MOZ_ALWAYS_INLINE jschar *
|
||||||
|
JSFatInlineString::init<jschar>(size_t length)
|
||||||
|
{
|
||||||
|
return initTwoByte(length);
|
||||||
|
}
|
||||||
|
|
||||||
template <js::AllowGC allowGC>
|
template <js::AllowGC allowGC>
|
||||||
MOZ_ALWAYS_INLINE JSFatInlineString *
|
MOZ_ALWAYS_INLINE JSFatInlineString *
|
||||||
JSFatInlineString::new_(js::ThreadSafeContext *cx)
|
JSFatInlineString::new_(js::ThreadSafeContext *cx)
|
||||||
|
|
|
@ -627,6 +627,10 @@ class JSLinearString : public JSString
|
||||||
MOZ_ALWAYS_INLINE
|
MOZ_ALWAYS_INLINE
|
||||||
const jschar *chars() const;
|
const jschar *chars() const;
|
||||||
|
|
||||||
|
template<typename CharT>
|
||||||
|
MOZ_ALWAYS_INLINE
|
||||||
|
const CharT *chars(const JS::AutoCheckCannotGC &nogc) const;
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE
|
MOZ_ALWAYS_INLINE
|
||||||
const JS::Latin1Char *latin1Chars(const JS::AutoCheckCannotGC &nogc) const;
|
const JS::Latin1Char *latin1Chars(const JS::AutoCheckCannotGC &nogc) const;
|
||||||
|
|
||||||
|
@ -673,7 +677,11 @@ class JSDependentString : public JSLinearString
|
||||||
size_t baseOffset() const {
|
size_t baseOffset() const {
|
||||||
MOZ_ASSERT(JSString::isDependent());
|
MOZ_ASSERT(JSString::isDependent());
|
||||||
JS::AutoCheckCannotGC nogc;
|
JS::AutoCheckCannotGC nogc;
|
||||||
size_t offset = twoByteChars(nogc) - base()->twoByteChars(nogc);
|
size_t offset;
|
||||||
|
if (hasTwoByteChars())
|
||||||
|
offset = twoByteChars(nogc) - base()->twoByteChars(nogc);
|
||||||
|
else
|
||||||
|
offset = latin1Chars(nogc) - base()->latin1Chars(nogc);
|
||||||
MOZ_ASSERT(offset < base()->length());
|
MOZ_ASSERT(offset < base()->length());
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
@ -779,6 +787,9 @@ class JSInlineString : public JSFlatString
|
||||||
inline jschar *initTwoByte(size_t length);
|
inline jschar *initTwoByte(size_t length);
|
||||||
inline JS::Latin1Char *initLatin1(size_t length);
|
inline JS::Latin1Char *initLatin1(size_t length);
|
||||||
|
|
||||||
|
template <typename CharT>
|
||||||
|
inline CharT *init(size_t length);
|
||||||
|
|
||||||
inline void resetLength(size_t length);
|
inline void resetLength(size_t length);
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE
|
MOZ_ALWAYS_INLINE
|
||||||
|
@ -809,6 +820,9 @@ class JSInlineString : public JSFlatString
|
||||||
return length <= MAX_LENGTH_TWO_BYTE;
|
return length <= MAX_LENGTH_TWO_BYTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CharT>
|
||||||
|
static bool lengthFits(size_t length);
|
||||||
|
|
||||||
static size_t offsetOfInlineStorage() {
|
static size_t offsetOfInlineStorage() {
|
||||||
return offsetof(JSInlineString, d.inlineStorageTwoByte);
|
return offsetof(JSInlineString, d.inlineStorageTwoByte);
|
||||||
}
|
}
|
||||||
|
@ -868,6 +882,9 @@ class JSFatInlineString : public JSInlineString
|
||||||
inline jschar *initTwoByte(size_t length);
|
inline jschar *initTwoByte(size_t length);
|
||||||
inline JS::Latin1Char *initLatin1(size_t length);
|
inline JS::Latin1Char *initLatin1(size_t length);
|
||||||
|
|
||||||
|
template <typename CharT>
|
||||||
|
inline CharT *init(size_t length);
|
||||||
|
|
||||||
static bool latin1LengthFits(size_t length) {
|
static bool latin1LengthFits(size_t length) {
|
||||||
return length <= MAX_LENGTH_LATIN1;
|
return length <= MAX_LENGTH_LATIN1;
|
||||||
}
|
}
|
||||||
|
@ -875,6 +892,9 @@ class JSFatInlineString : public JSInlineString
|
||||||
return length <= MAX_LENGTH_TWO_BYTE;
|
return length <= MAX_LENGTH_TWO_BYTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CharT>
|
||||||
|
static bool lengthFits(size_t length);
|
||||||
|
|
||||||
/* Only called by the GC for strings with the FINALIZE_FAT_INLINE_STRING kind. */
|
/* Only called by the GC for strings with the FINALIZE_FAT_INLINE_STRING kind. */
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE void finalize(js::FreeOp *fop);
|
MOZ_ALWAYS_INLINE void finalize(js::FreeOp *fop);
|
||||||
|
@ -1054,7 +1074,8 @@ class StaticStrings
|
||||||
static bool isStatic(JSAtom *atom);
|
static bool isStatic(JSAtom *atom);
|
||||||
|
|
||||||
/* Return null if no static atom exists for the given (chars, length). */
|
/* Return null if no static atom exists for the given (chars, length). */
|
||||||
JSAtom *lookup(const jschar *chars, size_t length) {
|
template <typename CharT>
|
||||||
|
JSAtom *lookup(const CharT *chars, size_t length) {
|
||||||
switch (length) {
|
switch (length) {
|
||||||
case 1:
|
case 1:
|
||||||
if (chars[0] < UNIT_STATIC_LIMIT)
|
if (chars[0] < UNIT_STATIC_LIMIT)
|
||||||
|
@ -1273,6 +1294,48 @@ JSLinearString::nonInlineChars(const JS::AutoCheckCannotGC &nogc) const
|
||||||
return nonInlineLatin1Chars(nogc);
|
return nonInlineLatin1Chars(nogc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
MOZ_ALWAYS_INLINE const jschar *
|
||||||
|
JSLinearString::chars(const JS::AutoCheckCannotGC &nogc) const
|
||||||
|
{
|
||||||
|
return twoByteChars(nogc);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
MOZ_ALWAYS_INLINE const JS::Latin1Char *
|
||||||
|
JSLinearString::chars(const JS::AutoCheckCannotGC &nogc) const
|
||||||
|
{
|
||||||
|
return latin1Chars(nogc);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
MOZ_ALWAYS_INLINE bool
|
||||||
|
JSInlineString::lengthFits<JS::Latin1Char>(size_t length)
|
||||||
|
{
|
||||||
|
return latin1LengthFits(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
MOZ_ALWAYS_INLINE bool
|
||||||
|
JSInlineString::lengthFits<jschar>(size_t length)
|
||||||
|
{
|
||||||
|
return twoByteLengthFits(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
MOZ_ALWAYS_INLINE bool
|
||||||
|
JSFatInlineString::lengthFits<JS::Latin1Char>(size_t length)
|
||||||
|
{
|
||||||
|
return latin1LengthFits(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
MOZ_ALWAYS_INLINE bool
|
||||||
|
JSFatInlineString::lengthFits<jschar>(size_t length)
|
||||||
|
{
|
||||||
|
return twoByteLengthFits(length);
|
||||||
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
MOZ_ALWAYS_INLINE void
|
MOZ_ALWAYS_INLINE void
|
||||||
JSString::setNonInlineChars(const jschar *chars)
|
JSString::setNonInlineChars(const jschar *chars)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче