зеркало из 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())
|
||||
return base;
|
||||
|
||||
{
|
||||
if (base->hasTwoByteChars()) {
|
||||
AutoCheckCannotGC nogc;
|
||||
const jschar *chars = base->twoByteChars(nogc) + start;
|
||||
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
|
||||
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);
|
||||
|
|
|
@ -19,24 +19,24 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
template <AllowGC allowGC>
|
||||
template <AllowGC allowGC, typename CharT>
|
||||
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);
|
||||
if (!str)
|
||||
return nullptr;
|
||||
*chars = str->initTwoByte(len);
|
||||
*chars = str->init<CharT>(len);
|
||||
return str;
|
||||
}
|
||||
|
||||
JSFatInlineString *str = JSFatInlineString::new_<allowGC>(cx);
|
||||
if (!str)
|
||||
return nullptr;
|
||||
*chars = str->initTwoByte(len);
|
||||
*chars = str->init<CharT>(len);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,23 @@ NewFatInlineString(ExclusiveContext *cx, JS::TwoByteChars chars)
|
|||
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
|
||||
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(start + length <= base->length());
|
||||
d.u1.length = length;
|
||||
d.u1.flags = DEPENDENT_FLAGS;
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
d.s.u2.nonInlineCharsTwoByte = base->twoByteChars(nogc) + start;
|
||||
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.u3.base = 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
|
||||
* 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);
|
||||
jschar *chars;
|
||||
JSInlineString *s = js::AllocateFatInlineString<js::CanGC>(cx, length, &chars);
|
||||
if (!s)
|
||||
return nullptr;
|
||||
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
mozilla::PodCopy(chars, base->twoByteChars(nogc) + start, length);
|
||||
chars[length] = 0;
|
||||
return s;
|
||||
if (baseArg->hasLatin1Chars())
|
||||
return js::NewFatInlineString<JS::Latin1Char>(cx, base, start, length);
|
||||
return js::NewFatInlineString<jschar>(cx, base, start, length);
|
||||
}
|
||||
|
||||
JSDependentString *str = (JSDependentString *)js_NewGCString<js::NoGC>(cx);
|
||||
|
@ -284,6 +303,34 @@ JSFatInlineString::initLatin1(size_t length)
|
|||
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>
|
||||
MOZ_ALWAYS_INLINE JSFatInlineString *
|
||||
JSFatInlineString::new_(js::ThreadSafeContext *cx)
|
||||
|
|
|
@ -627,6 +627,10 @@ class JSLinearString : public JSString
|
|||
MOZ_ALWAYS_INLINE
|
||||
const jschar *chars() const;
|
||||
|
||||
template<typename CharT>
|
||||
MOZ_ALWAYS_INLINE
|
||||
const CharT *chars(const JS::AutoCheckCannotGC &nogc) const;
|
||||
|
||||
MOZ_ALWAYS_INLINE
|
||||
const JS::Latin1Char *latin1Chars(const JS::AutoCheckCannotGC &nogc) const;
|
||||
|
||||
|
@ -673,7 +677,11 @@ class JSDependentString : public JSLinearString
|
|||
size_t baseOffset() const {
|
||||
MOZ_ASSERT(JSString::isDependent());
|
||||
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());
|
||||
return offset;
|
||||
}
|
||||
|
@ -779,6 +787,9 @@ class JSInlineString : public JSFlatString
|
|||
inline jschar *initTwoByte(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);
|
||||
|
||||
MOZ_ALWAYS_INLINE
|
||||
|
@ -809,6 +820,9 @@ class JSInlineString : public JSFlatString
|
|||
return length <= MAX_LENGTH_TWO_BYTE;
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
static bool lengthFits(size_t length);
|
||||
|
||||
static size_t offsetOfInlineStorage() {
|
||||
return offsetof(JSInlineString, d.inlineStorageTwoByte);
|
||||
}
|
||||
|
@ -868,6 +882,9 @@ class JSFatInlineString : public JSInlineString
|
|||
inline jschar *initTwoByte(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) {
|
||||
return length <= MAX_LENGTH_LATIN1;
|
||||
}
|
||||
|
@ -875,6 +892,9 @@ class JSFatInlineString : public JSInlineString
|
|||
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. */
|
||||
|
||||
MOZ_ALWAYS_INLINE void finalize(js::FreeOp *fop);
|
||||
|
@ -1054,7 +1074,8 @@ class StaticStrings
|
|||
static bool isStatic(JSAtom *atom);
|
||||
|
||||
/* 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) {
|
||||
case 1:
|
||||
if (chars[0] < UNIT_STATIC_LIMIT)
|
||||
|
@ -1273,6 +1294,48 @@ JSLinearString::nonInlineChars(const JS::AutoCheckCannotGC &nogc) const
|
|||
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<>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
JSString::setNonInlineChars(const jschar *chars)
|
||||
|
|
Загрузка…
Ссылка в новой задаче