зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 3 changesets (bug 1698791) for causing valgrind failures.
Backed out changeset 1bd16d8959e5 (bug 1698791) Backed out changeset 467a7afcdd3d (bug 1698791) Backed out changeset 48b921d8aeee (bug 1698791)
This commit is contained in:
Родитель
0583e7e496
Коммит
f29929310e
|
@ -223,20 +223,57 @@ static MOZ_ALWAYS_INLINE bool GetLengthProperty(JSContext* cx, HandleObject obj,
|
|||
* "08" or "4.0" as array indices, which they are not.
|
||||
*
|
||||
*/
|
||||
template <typename CharT>
|
||||
static bool StringIsArrayIndexHelper(const CharT* s, uint32_t length,
|
||||
uint32_t* indexp) {
|
||||
const CharT* end = s + length;
|
||||
|
||||
if (length == 0 || length > (sizeof("4294967294") - 1) || !IsAsciiDigit(*s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t c = 0, previous = 0;
|
||||
uint32_t index = AsciiDigitToNumber(*s++);
|
||||
|
||||
/* Don't allow leading zeros. */
|
||||
if (index == 0 && s != end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (; s < end; s++) {
|
||||
if (!IsAsciiDigit(*s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
previous = index;
|
||||
c = AsciiDigitToNumber(*s);
|
||||
index = 10 * index + c;
|
||||
}
|
||||
|
||||
/* Make sure we didn't overflow. */
|
||||
if (previous < (MAX_ARRAY_INDEX / 10) ||
|
||||
(previous == (MAX_ARRAY_INDEX / 10) && c <= (MAX_ARRAY_INDEX % 10))) {
|
||||
MOZ_ASSERT(index <= MAX_ARRAY_INDEX);
|
||||
*indexp = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_FRIEND_API bool js::StringIsArrayIndex(JSLinearString* str,
|
||||
uint32_t* indexp) {
|
||||
return str->isIndex(indexp) && *indexp <= MAX_ARRAY_INDEX;
|
||||
AutoCheckCannotGC nogc;
|
||||
return str->hasLatin1Chars()
|
||||
? StringIsArrayIndexHelper(str->latin1Chars(nogc), str->length(),
|
||||
indexp)
|
||||
: StringIsArrayIndexHelper(str->twoByteChars(nogc), str->length(),
|
||||
indexp);
|
||||
}
|
||||
|
||||
JS_FRIEND_API bool js::StringIsArrayIndex(const char16_t* str, uint32_t length,
|
||||
uint32_t* indexp) {
|
||||
if (length == 0 || length > UINT32_CHAR_BUFFER_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
if (!mozilla::IsAsciiDigit(str[0])) {
|
||||
return false;
|
||||
}
|
||||
return CheckStringIsIndex(str, length, indexp) && *indexp <= MAX_ARRAY_INDEX;
|
||||
return StringIsArrayIndexHelper(str, length, indexp);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -37,7 +37,12 @@ MOZ_ALWAYS_INLINE bool IdIsIndex(jsid id, uint32_t* indexp) {
|
|||
}
|
||||
|
||||
JSAtom* atom = JSID_TO_ATOM(id);
|
||||
return atom->isIndex(indexp) && *indexp <= MAX_ARRAY_INDEX;
|
||||
if (atom->length() == 0 ||
|
||||
!mozilla::IsAsciiDigit(atom->latin1OrTwoByteChar(0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return js::StringIsArrayIndex(atom, indexp);
|
||||
}
|
||||
|
||||
// The methods below only create dense boxed arrays.
|
||||
|
|
|
@ -336,7 +336,8 @@ static bool ValueToNameOrSymbolId(JSContext* cx, HandleValue idVal,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (id.isAtom() && id.toAtom()->isIndex()) {
|
||||
uint32_t dummy;
|
||||
if (id.isAtom() && id.toAtom()->isIndex(&dummy)) {
|
||||
id.set(JSID_VOID);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -12111,7 +12111,8 @@ void CodeGenerator::addGetPropertyCache(LInstruction* ins,
|
|||
CacheKind kind = CacheKind::GetElem;
|
||||
if (id.constant() && id.value().isString()) {
|
||||
JSString* idString = id.value().toString();
|
||||
if (idString->isAtom() && !idString->asAtom().isIndex()) {
|
||||
uint32_t dummy;
|
||||
if (idString->isAtom() && !idString->asAtom().isIndex(&dummy)) {
|
||||
kind = CacheKind::GetProp;
|
||||
}
|
||||
}
|
||||
|
@ -12128,7 +12129,8 @@ void CodeGenerator::addSetPropertyCache(LInstruction* ins,
|
|||
CacheKind kind = CacheKind::SetElem;
|
||||
if (id.constant() && id.value().isString()) {
|
||||
JSString* idString = id.value().toString();
|
||||
if (idString->isAtom() && !idString->asAtom().isIndex()) {
|
||||
uint32_t dummy;
|
||||
if (idString->isAtom() && !idString->asAtom().isIndex(&dummy)) {
|
||||
kind = CacheKind::SetProp;
|
||||
}
|
||||
}
|
||||
|
@ -12176,7 +12178,8 @@ void CodeGenerator::visitGetPropSuperCache(LGetPropSuperCache* ins) {
|
|||
CacheKind kind = CacheKind::GetElemSuper;
|
||||
if (id.constant() && id.value().isString()) {
|
||||
JSString* idString = id.value().toString();
|
||||
if (idString->isAtom() && !idString->asAtom().isIndex()) {
|
||||
uint32_t dummy;
|
||||
if (idString->isAtom() && !idString->asAtom().isIndex(&dummy)) {
|
||||
kind = CacheKind::GetPropSuper;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1165,7 +1165,7 @@ int32_t GetIndexFromString(JSString* str) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
uint32_t index;
|
||||
uint32_t index = UINT32_MAX;
|
||||
if (!str->asLinear().isIndex(&index) || index > INT32_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -5431,7 +5431,9 @@ JS_PUBLIC_API bool JS_CharsToId(JSContext* cx, JS::TwoByteChars chars,
|
|||
return false;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!atom->isIndex(), "API misuse: |chars| must not encode an index");
|
||||
uint32_t dummy;
|
||||
MOZ_ASSERT(!atom->isIndex(&dummy),
|
||||
"API misuse: |chars| must not encode an index");
|
||||
#endif
|
||||
idp.set(AtomToId(atom));
|
||||
return true;
|
||||
|
|
|
@ -818,7 +818,7 @@ JSLinearString* js::Int32ToString(JSContext* cx, int32_t si) {
|
|||
return nullptr;
|
||||
}
|
||||
if (si >= 0) {
|
||||
str->maybeInitializeIndexValue(si);
|
||||
str->maybeInitializeIndex(si);
|
||||
}
|
||||
|
||||
CacheNumber(cx, si, str);
|
||||
|
@ -1660,7 +1660,7 @@ static JSString* NumberToStringWithBase(JSContext* cx, double d, int base) {
|
|||
}
|
||||
|
||||
if (isBase10Int && i >= 0) {
|
||||
s->maybeInitializeIndexValue(i);
|
||||
s->maybeInitializeIndex(i);
|
||||
}
|
||||
|
||||
realm->dtoaCache.cache(base, d, s);
|
||||
|
|
|
@ -518,7 +518,11 @@ bool ArgumentsObject::obj_mayResolve(const JSAtomState& names, jsid id,
|
|||
// Arguments might resolve indexes, Symbol.iterator, or length/callee.
|
||||
if (JSID_IS_ATOM(id)) {
|
||||
JSAtom* atom = JSID_TO_ATOM(id);
|
||||
return atom->isIndex() || atom == names.length || atom == names.callee;
|
||||
uint32_t index;
|
||||
if (atom->isIndex(&index)) {
|
||||
return true;
|
||||
}
|
||||
return atom == names.length || atom == names.callee;
|
||||
}
|
||||
|
||||
return id.isInt() || id.isWellKnownSymbol(JS::SymbolCode::iterator);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
MOZ_ALWAYS_INLINE jsid AtomToId(JSAtom* atom) {
|
||||
inline jsid AtomToId(JSAtom* atom) {
|
||||
static_assert(JSID_INT_MIN == 0);
|
||||
|
||||
uint32_t index;
|
||||
|
|
|
@ -954,14 +954,7 @@ static MOZ_ALWAYS_INLINE JSAtom* AllocateNewAtom(
|
|||
MOZ_ASSERT(atom->hash() == lookup.hash);
|
||||
|
||||
if (indexValue) {
|
||||
atom->setIsIndex(*indexValue);
|
||||
} else {
|
||||
// We need to call isIndexSlow directly to avoid the flag check in isIndex,
|
||||
// because we still have to initialize that flag.
|
||||
uint32_t index;
|
||||
if (atom->isIndexSlow(&index)) {
|
||||
atom->setIsIndex(index);
|
||||
}
|
||||
atom->maybeInitializeIndex(*indexValue, true);
|
||||
}
|
||||
|
||||
return atom;
|
||||
|
|
|
@ -1230,40 +1230,17 @@ template bool js::CheckStringIsIndex(const char16_t* s, size_t length,
|
|||
uint32_t* indexp);
|
||||
|
||||
template <typename CharT>
|
||||
static uint32_t AtomCharsToIndex(const CharT* s, size_t length) {
|
||||
// Chars are known to be a valid index value (as determined by
|
||||
// CheckStringIsIndex) that didn't fit in the "index value" bits in the
|
||||
// header.
|
||||
|
||||
MOZ_ASSERT(length > 0);
|
||||
MOZ_ASSERT(length <= UINT32_CHAR_BUFFER_LENGTH);
|
||||
|
||||
RangedPtr<const CharT> cp(s, length);
|
||||
const RangedPtr<const CharT> end(s + length, s, length);
|
||||
|
||||
MOZ_ASSERT(IsAsciiDigit(*cp));
|
||||
uint32_t index = AsciiDigitToNumber(*cp++);
|
||||
MOZ_ASSERT(index != 0);
|
||||
|
||||
while (cp < end) {
|
||||
MOZ_ASSERT(IsAsciiDigit(*cp));
|
||||
index = 10 * index + AsciiDigitToNumber(*cp);
|
||||
cp++;
|
||||
/* static */
|
||||
bool JSLinearString::isIndexSlow(const CharT* s, size_t length,
|
||||
uint32_t* indexp) {
|
||||
return js::CheckStringIsIndex(s, length, indexp);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
template bool JSLinearString::isIndexSlow(const Latin1Char* s, size_t length,
|
||||
uint32_t* indexp);
|
||||
|
||||
uint32_t JSAtom::getIndexSlow() const {
|
||||
MOZ_ASSERT(isIndex());
|
||||
MOZ_ASSERT(!hasIndexValue());
|
||||
|
||||
size_t len = length();
|
||||
|
||||
AutoCheckCannotGC nogc;
|
||||
return hasLatin1Chars() ? AtomCharsToIndex(latin1Chars(nogc), len)
|
||||
: AtomCharsToIndex(twoByteChars(nogc), len);
|
||||
}
|
||||
template bool JSLinearString::isIndexSlow(const char16_t* s, size_t length,
|
||||
uint32_t* indexp);
|
||||
|
||||
constexpr StaticStrings::SmallCharTable StaticStrings::createSmallCharTable() {
|
||||
SmallCharTable array{};
|
||||
|
@ -1328,7 +1305,7 @@ bool StaticStrings::init(JSContext* cx) {
|
|||
|
||||
// Static string initialization can not race, so allow even without the
|
||||
// lock.
|
||||
intStaticTable[i]->setIsIndex(i);
|
||||
intStaticTable[i]->maybeInitializeIndex(i, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -61,12 +61,6 @@ class PropertyName;
|
|||
/* The buffer length required to contain any unsigned 32-bit integer. */
|
||||
static const size_t UINT32_CHAR_BUFFER_LENGTH = sizeof("4294967295") - 1;
|
||||
|
||||
// Returns true if the characters of `s` store an unsigned 32-bit integer value,
|
||||
// initializing `*indexp` to that value if so.
|
||||
// Leading '0' isn't allowed except 0 itself.
|
||||
template <typename CharT>
|
||||
bool CheckStringIsIndex(const CharT* s, size_t length, uint32_t* indexp);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
// clang-format off
|
||||
|
@ -311,20 +305,16 @@ class JSString : public js::gc::CellWithLengthAndFlags {
|
|||
|
||||
static const uint32_t LATIN1_CHARS_BIT = js::Bit(9);
|
||||
|
||||
// Whether this atom's characters store an uint32 index value. Not used for
|
||||
// non-atomized strings. See JSLinearString::isIndex.
|
||||
static const uint32_t ATOM_IS_INDEX = js::Bit(10);
|
||||
|
||||
static const uint32_t INDEX_VALUE_BIT = js::Bit(11);
|
||||
static const uint32_t INDEX_VALUE_BIT = js::Bit(10);
|
||||
static const uint32_t INDEX_VALUE_SHIFT = 16;
|
||||
|
||||
// NON_DEDUP_BIT is used in string deduplication during tenuring.
|
||||
static const uint32_t NON_DEDUP_BIT = js::Bit(12);
|
||||
static const uint32_t NON_DEDUP_BIT = js::Bit(11);
|
||||
|
||||
// If IN_STRING_TO_ATOM_CACHE is set, this string had an entry in the
|
||||
// StringToAtomCache at some point. Note that GC can purge the cache without
|
||||
// clearing this bit.
|
||||
static const uint32_t IN_STRING_TO_ATOM_CACHE = js::Bit(13);
|
||||
static const uint32_t IN_STRING_TO_ATOM_CACHE = js::Bit(12);
|
||||
|
||||
static const uint32_t MAX_LENGTH = JS::MaxStringLength;
|
||||
|
||||
|
@ -785,6 +775,9 @@ class JSLinearString : public JSString {
|
|||
bool isLinear() const = delete;
|
||||
JSLinearString& asLinear() const = delete;
|
||||
|
||||
template <typename CharT>
|
||||
static bool isIndexSlow(const CharT* s, size_t length, uint32_t* indexp);
|
||||
|
||||
protected:
|
||||
/* Returns void pointer to latin1/twoByte chars, for finalizers. */
|
||||
MOZ_ALWAYS_INLINE
|
||||
|
@ -871,11 +864,10 @@ class JSLinearString : public JSString {
|
|||
JS::AutoCheckCannotGC nogc;
|
||||
if (hasLatin1Chars()) {
|
||||
const JS::Latin1Char* s = latin1Chars(nogc);
|
||||
return mozilla::IsAsciiDigit(*s) &&
|
||||
js::CheckStringIsIndex(s, len, indexp);
|
||||
return mozilla::IsAsciiDigit(*s) && isIndexSlow(s, len, indexp);
|
||||
}
|
||||
const char16_t* s = twoByteChars(nogc);
|
||||
return mozilla::IsAsciiDigit(*s) && js::CheckStringIsIndex(s, len, indexp);
|
||||
return mozilla::IsAsciiDigit(*s) && isIndexSlow(s, len, indexp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -885,9 +877,18 @@ class JSLinearString : public JSString {
|
|||
* (Thus if calling isIndex returns true, js::IndexToString(cx, *indexp) will
|
||||
* be a string equal to this string.)
|
||||
*/
|
||||
inline bool isIndex(uint32_t* indexp) const;
|
||||
bool isIndex(uint32_t* indexp) const {
|
||||
MOZ_ASSERT(JSString::isLinear());
|
||||
|
||||
void maybeInitializeIndexValue(uint32_t index, bool allowAtom = false) {
|
||||
if (JSString::hasIndexValue()) {
|
||||
*indexp = getIndexValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
return isIndexSlow(indexp);
|
||||
}
|
||||
|
||||
void maybeInitializeIndex(uint32_t index, bool allowAtom = false) {
|
||||
MOZ_ASSERT(JSString::isLinear());
|
||||
MOZ_ASSERT_IF(hasIndexValue(), getIndexValue() == index);
|
||||
MOZ_ASSERT_IF(!allowAtom, !isAtom());
|
||||
|
@ -1163,29 +1164,6 @@ class JSAtom : public JSLinearString {
|
|||
setFlagBit(PERMANENT_ATOM_MASK);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool isIndex() const {
|
||||
MOZ_ASSERT(JSString::isAtom());
|
||||
mozilla::DebugOnly<uint32_t> index;
|
||||
MOZ_ASSERT(!!(flags() & ATOM_IS_INDEX) == isIndexSlow(&index));
|
||||
return flags() & ATOM_IS_INDEX;
|
||||
}
|
||||
MOZ_ALWAYS_INLINE bool isIndex(uint32_t* index) const {
|
||||
MOZ_ASSERT(JSString::isAtom());
|
||||
if (!isIndex()) {
|
||||
return false;
|
||||
}
|
||||
*index = hasIndexValue() ? getIndexValue() : getIndexSlow();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t getIndexSlow() const;
|
||||
|
||||
void setIsIndex(uint32_t index) {
|
||||
MOZ_ASSERT(JSString::isAtom());
|
||||
setFlagBit(ATOM_IS_INDEX);
|
||||
maybeInitializeIndexValue(index, /* allowAtom = */ true);
|
||||
}
|
||||
|
||||
inline js::HashNumber hash() const;
|
||||
inline void initHash(js::HashNumber hash);
|
||||
|
||||
|
@ -1266,6 +1244,12 @@ MOZ_ALWAYS_INLINE JSAtom* JSLinearString::morphAtomizedStringIntoPermanentAtom(
|
|||
|
||||
namespace js {
|
||||
|
||||
// Returns true if the characters of `s` store an unsigned 32-bit integer value,
|
||||
// initializing `*indexp` to that value if so.
|
||||
// Leading '0' isn't allowed except 0 itself.
|
||||
template <typename CharT>
|
||||
bool CheckStringIsIndex(const CharT* s, size_t length, uint32_t* indexp);
|
||||
|
||||
/**
|
||||
* An indexable characters class exposing unaligned, little-endian encoded
|
||||
* char16_t data.
|
||||
|
@ -1989,25 +1973,13 @@ MOZ_ALWAYS_INLINE const char16_t* JSLinearString::rawTwoByteChars() const {
|
|||
}
|
||||
|
||||
inline js::PropertyName* JSAtom::asPropertyName() {
|
||||
MOZ_ASSERT(!isIndex());
|
||||
#ifdef DEBUG
|
||||
uint32_t dummy;
|
||||
MOZ_ASSERT(!isIndex(&dummy));
|
||||
#endif
|
||||
return static_cast<js::PropertyName*>(this);
|
||||
}
|
||||
|
||||
inline bool JSLinearString::isIndex(uint32_t* indexp) const {
|
||||
MOZ_ASSERT(JSString::isLinear());
|
||||
|
||||
if (isAtom()) {
|
||||
return asAtom().isIndex(indexp);
|
||||
}
|
||||
|
||||
if (JSString::hasIndexValue()) {
|
||||
*indexp = getIndexValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
return isIndexSlow(indexp);
|
||||
}
|
||||
|
||||
inline size_t JSLinearString::allocSize() const {
|
||||
MOZ_ASSERT(ownsMallocedChars());
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче