Bug 1018311 part 2 - Support creating dependent latin1 strings. r=luke

This commit is contained in:
Jan de Mooij 2014-06-03 13:13:56 +02:00
Родитель 9f2d98a7d2
Коммит 50c08461e0
3 изменённых файлов: 136 добавлений и 21 удалений

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

@ -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)