Bug 1023778 part 3 - Make AtomizeChars and js_NewStringCopyN accept Latin1 chars. r=luke

This commit is contained in:
Jan de Mooij 2014-06-13 20:51:05 +02:00
parent f138aa5022
commit e261152579
8 changed files with 156 additions and 64 deletions

View File

@ -352,9 +352,10 @@ AtomizeAndtake(ExclusiveContext *cx, jschar *tbchars, size_t length, InternBehav
}
/* |tbchars| must not point into an inline or short string. */
template <typename CharT>
MOZ_ALWAYS_INLINE
static JSAtom *
AtomizeAndCopyChars(ExclusiveContext *cx, const jschar *tbchars, size_t length, InternBehavior ib)
AtomizeAndCopyChars(ExclusiveContext *cx, const CharT *tbchars, size_t length, InternBehavior ib)
{
if (JSAtom *s = cx->staticStrings().lookup(tbchars, length))
return s;
@ -396,6 +397,12 @@ AtomizeAndCopyChars(ExclusiveContext *cx, const jschar *tbchars, size_t length,
return atom;
}
template JSAtom *
AtomizeAndCopyChars(ExclusiveContext *cx, const jschar *tbchars, size_t length, InternBehavior ib);
template JSAtom *
AtomizeAndCopyChars(ExclusiveContext *cx, const Latin1Char *tbchars, size_t length, InternBehavior ib);
JSAtom *
js::AtomizeString(ExclusiveContext *cx, JSString *str,
js::InternBehavior ib /* = js::DoNotInternAtom */)
@ -458,8 +465,9 @@ js::Atomize(ExclusiveContext *cx, const char *bytes, size_t length, InternBehavi
return AtomizeAndtake(cx, tbcharsZ, length, ib);
}
template <typename CharT>
JSAtom *
js::AtomizeChars(ExclusiveContext *cx, const jschar *chars, size_t length, InternBehavior ib)
js::AtomizeChars(ExclusiveContext *cx, const CharT *chars, size_t length, InternBehavior ib)
{
CHECK_REQUEST(cx);
@ -469,6 +477,12 @@ js::AtomizeChars(ExclusiveContext *cx, const jschar *chars, size_t length, Inter
return AtomizeAndCopyChars(cx, chars, length, ib);
}
template JSAtom *
js::AtomizeChars(ExclusiveContext *cx, const Latin1Char *chars, size_t length, InternBehavior ib);
template JSAtom *
js::AtomizeChars(ExclusiveContext *cx, const jschar *chars, size_t length, InternBehavior ib);
bool
js::IndexToIdSlow(ExclusiveContext *cx, uint32_t index, MutableHandleId idp)
{

View File

@ -13,6 +13,7 @@
#include "gc/Barrier.h"
#include "gc/Rooting.h"
#include "js/GCAPI.h"
#include "vm/CommonPropertyNames.h"
class JSAtom;
@ -85,14 +86,24 @@ struct AtomHasher
{
struct Lookup
{
const jschar *chars;
size_t length;
const JSAtom *atom; /* Optional. */
union {
const JS::Latin1Char *latin1Chars;
const jschar *twoByteChars;
};
bool isLatin1;
size_t length;
const JSAtom *atom; /* Optional. */
JS::AutoCheckCannotGC nogc;
HashNumber hash;
Lookup(const jschar *chars, size_t length)
: chars(chars), length(length), atom(nullptr)
: twoByteChars(chars), isLatin1(false), length(length), atom(nullptr)
{
hash = mozilla::HashString(chars, length);
}
Lookup(const JS::Latin1Char *chars, size_t length)
: latin1Chars(chars), isLatin1(true), length(length), atom(nullptr)
{
hash = mozilla::HashString(chars, length);
}
@ -187,8 +198,9 @@ extern JSAtom *
Atomize(ExclusiveContext *cx, const char *bytes, size_t length,
js::InternBehavior ib = js::DoNotInternAtom);
template <typename CharT>
extern JSAtom *
AtomizeChars(ExclusiveContext *cx, const jschar *chars, size_t length,
AtomizeChars(ExclusiveContext *cx, const CharT *chars, size_t length,
js::InternBehavior ib = js::DoNotInternAtom);
extern JSAtom *

View File

@ -137,9 +137,15 @@ IdToString(JSContext *cx, jsid id)
inline
AtomHasher::Lookup::Lookup(const JSAtom *atom)
: chars(atom->chars()), length(atom->length()), atom(atom)
: isLatin1(atom->hasLatin1Chars()), length(atom->length()), atom(atom)
{
hash = mozilla::HashString(chars, length);
if (isLatin1) {
latin1Chars = atom->latin1Chars(nogc);
hash = mozilla::HashString(latin1Chars, length);
} else {
twoByteChars = atom->twoByteChars(nogc);
hash = mozilla::HashString(twoByteChars, length);
}
}
inline bool
@ -150,7 +156,18 @@ AtomHasher::match(const AtomStateEntry &entry, const Lookup &lookup)
return lookup.atom == key;
if (key->length() != lookup.length)
return false;
return mozilla::PodEqual(key->chars(), lookup.chars, lookup.length);
if (key->hasLatin1Chars()) {
const Latin1Char *keyChars = key->latin1Chars(lookup.nogc);
if (lookup.isLatin1)
return mozilla::PodEqual(keyChars, lookup.latin1Chars, lookup.length);
return EqualCharsLatin1TwoByte(keyChars, lookup.twoByteChars, lookup.length);
}
const jschar *keyChars = key->twoByteChars(lookup.nogc);
if (lookup.isLatin1)
return EqualCharsLatin1TwoByte(lookup.latin1Chars, keyChars, lookup.length);
return mozilla::PodEqual(keyChars, lookup.twoByteChars, lookup.length);
}
inline Handle<PropertyName*>

View File

@ -22,6 +22,7 @@
#include "mozilla/CheckedInt.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/PodOperations.h"
#include "mozilla/Range.h"
#include "mozilla/TypeTraits.h"
#include <ctype.h>
@ -71,6 +72,7 @@ using mozilla::IsNegativeZero;
using mozilla::IsSame;
using mozilla::PodCopy;
using mozilla::PodEqual;
using mozilla::Range;
using mozilla::SafeCast;
using JS::AutoCheckCannotGC;
@ -1702,16 +1704,6 @@ str_lastIndexOf(JSContext *cx, unsigned argc, Value *vp)
return true;
}
static bool
EqualCharsLatin1TwoByte(const Latin1Char *s1, const jschar *s2, size_t len)
{
for (const Latin1Char *s1end = s1 + len; s1 < s1end; s1++, s2++) {
if (jschar(*s1) != *s2)
return false;
}
return true;
}
static bool
HasSubstringAt(JSLinearString *text, JSLinearString *pat, size_t start)
{
@ -4279,51 +4271,90 @@ js_NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t len
return JSDependentString::new_(cx, base, start, length);
}
template <AllowGC allowGC>
JSFlatString *
js_NewStringCopyN(ExclusiveContext *cx, const jschar *s, size_t n)
{
if (JSFatInlineString::twoByteLengthFits(n))
return NewFatInlineString<allowGC>(cx, TwoByteChars(s, n));
template <typename CharT>
static void
CopyCharsMaybeInflate(jschar *dest, const CharT *src, size_t len);
jschar *news = cx->pod_malloc<jschar>(n + 1);
template <>
void
CopyCharsMaybeInflate(jschar *dest, const jschar *src, size_t len)
{
PodCopy(dest, src, len);
}
template <>
void
CopyCharsMaybeInflate(jschar *dest, const Latin1Char *src, size_t len)
{
CopyAndInflateChars(dest, src, len);
}
template <AllowGC allowGC, typename CharT>
JSFlatString *
js_NewStringCopyN(ThreadSafeContext *cx, const CharT *s, size_t n)
{
if (EnableLatin1Strings) {
if (JSFatInlineString::lengthFits<CharT>(n))
return NewFatInlineString<allowGC>(cx, Range<const CharT>(s, n));
ScopedJSFreePtr<CharT> news(cx->pod_malloc<CharT>(n + 1));
if (!news)
return nullptr;
PodCopy(news.get(), s, n);
news[n] = 0;
JSFlatString *str = js_NewString<allowGC>(cx, news.get(), n);
if (!str)
return nullptr;
news.forget();
return str;
}
if (JSFatInlineString::twoByteLengthFits(n))
return NewFatInlineString<allowGC>(cx, Range<const CharT>(s, n));
ScopedJSFreePtr<jschar> news(cx->pod_malloc<jschar>(n + 1));
if (!news)
return nullptr;
js_strncpy(news, s, n);
CopyCharsMaybeInflate(news.get(), s, n);
news[n] = 0;
JSFlatString *str = js_NewString<allowGC>(cx, news, n);
JSFlatString *str = js_NewString<allowGC>(cx, news.get(), n);
if (!str)
js_free(news);
return str;
}
template JSFlatString *
js_NewStringCopyN<CanGC>(ExclusiveContext *cx, const jschar *s, size_t n);
template JSFlatString *
js_NewStringCopyN<NoGC>(ExclusiveContext *cx, const jschar *s, size_t n);
template <AllowGC allowGC>
JSFlatString *
js_NewStringCopyN(ThreadSafeContext *cx, const char *s, size_t n)
{
if (JSFatInlineString::twoByteLengthFits(n))
return NewFatInlineString<allowGC>(cx, JS::Latin1Chars(s, n));
jschar *chars = InflateString(cx, s, &n);
if (!chars)
return nullptr;
JSFlatString *str = js_NewString<allowGC>(cx, chars, n);
if (!str)
js_free(chars);
news.forget();
return str;
}
template JSFlatString *
js_NewStringCopyN<CanGC>(ThreadSafeContext *cx, const char *s, size_t n);
js_NewStringCopyN<CanGC>(ThreadSafeContext *cx, const jschar *s, size_t n);
template JSFlatString *
js_NewStringCopyN<NoGC>(ThreadSafeContext *cx, const char *s, size_t n);
js_NewStringCopyN<NoGC>(ThreadSafeContext *cx, const jschar *s, size_t n);
template JSFlatString *
js_NewStringCopyN<CanGC>(ThreadSafeContext *cx, const Latin1Char *s, size_t n);
template JSFlatString *
js_NewStringCopyN<NoGC>(ThreadSafeContext *cx, const Latin1Char *s, size_t n);
template <>
JSFlatString *
js_NewStringCopyN<CanGC>(ThreadSafeContext *cx, const char *s, size_t n)
{
return js_NewStringCopyN<CanGC>(cx, reinterpret_cast<const Latin1Char *>(s), n);
}
template <>
JSFlatString *
js_NewStringCopyN<NoGC>(ThreadSafeContext *cx, const char *s, size_t n)
{
return js_NewStringCopyN<NoGC>(cx, reinterpret_cast<const Latin1Char *>(s), n);
}
template <AllowGC allowGC>
JSFlatString *
@ -4331,7 +4362,7 @@ js_NewStringCopyZ(ExclusiveContext *cx, const jschar *s)
{
size_t n = js_strlen(s);
if (JSFatInlineString::twoByteLengthFits(n))
return NewFatInlineString<allowGC>(cx, TwoByteChars(s, n));
return NewFatInlineString<allowGC>(cx, Range<const jschar>(s, n));
size_t m = (n + 1) * sizeof(jschar);
jschar *news = (jschar *) cx->malloc_(m);

View File

@ -101,13 +101,9 @@ extern JSLinearString *
js_NewDependentString(JSContext *cx, JSString *base, size_t start, size_t length);
/* Copy a counted string and GC-allocate a descriptor for it. */
template <js::AllowGC allowGC>
template <js::AllowGC allowGC, typename CharT>
extern JSFlatString *
js_NewStringCopyN(js::ExclusiveContext *cx, const jschar *s, size_t n);
template <js::AllowGC allowGC>
extern JSFlatString *
js_NewStringCopyN(js::ThreadSafeContext *cx, const char *s, size_t n);
js_NewStringCopyN(js::ThreadSafeContext *cx, const CharT *s, size_t n);
/* Copy a C string and GC-allocate a descriptor for it. */
template <js::AllowGC allowGC>
@ -237,6 +233,16 @@ js_strdup(js::ThreadSafeContext *cx, const jschar *s);
namespace js {
inline bool
EqualCharsLatin1TwoByte(const Latin1Char *s1, const jschar *s2, size_t len)
{
for (const Latin1Char *s1end = s1 + len; s1 < s1end; s1++, s2++) {
if (jschar(*s1) != *s2)
return false;
}
return true;
}
/*
* Inflate bytes in ASCII encoding to jschars. Return null on error, otherwise
* return the jschar that was malloc'ed. length is updated to the length of the

View File

@ -10,6 +10,7 @@
#include "vm/String.h"
#include "mozilla/PodOperations.h"
#include "mozilla/Range.h"
#include "jscntxt.h"
@ -42,7 +43,7 @@ AllocateFatInlineString(ThreadSafeContext *cx, size_t len, CharT **chars)
template <AllowGC allowGC>
static MOZ_ALWAYS_INLINE JSInlineString *
NewFatInlineString(ThreadSafeContext *cx, JS::Latin1Chars chars)
NewFatInlineString(ThreadSafeContext *cx, mozilla::Range<const Latin1Char> chars)
{
size_t len = chars.length();
@ -70,7 +71,7 @@ NewFatInlineString(ThreadSafeContext *cx, JS::Latin1Chars chars)
template <AllowGC allowGC>
static MOZ_ALWAYS_INLINE JSInlineString *
NewFatInlineString(ExclusiveContext *cx, JS::TwoByteChars chars)
NewFatInlineString(ThreadSafeContext *cx, mozilla::Range<const jschar> chars)
{
/*
* Don't bother trying to find a static atom; measurement shows that not

View File

@ -6,12 +6,16 @@
#include "vm/StringBuffer.h"
#include "mozilla/Range.h"
#include "jsobjinlines.h"
#include "vm/String-inl.h"
using namespace js;
using mozilla::Range;
template <typename CharT, class Buffer>
static CharT *
ExtractWellSized(ExclusiveContext *cx, Buffer &cb)
@ -96,10 +100,10 @@ StringBuffer::finishString()
if (isLatin1()) {
if (JSFatInlineString::latin1LengthFits(len))
return NewFatInlineString<CanGC>(cx, Latin1Chars(latin1Chars().begin(), len));
return NewFatInlineString<CanGC>(cx, Range<const Latin1Char>(latin1Chars().begin(), len));
} else {
if (JSFatInlineString::twoByteLengthFits(len))
return NewFatInlineString<CanGC>(cx, TwoByteChars(twoByteChars().begin(), len));
return NewFatInlineString<CanGC>(cx, Range<const jschar>(twoByteChars().begin(), len));
}
return isLatin1()

View File

@ -313,6 +313,13 @@ HashString(const char* str, size_t length)
return detail::HashKnownLength(str, length);
}
MOZ_WARN_UNUSED_RESULT
inline uint32_t
HashString(const unsigned char* str, size_t length)
{
return detail::HashKnownLength(str, length);
}
MOZ_WARN_UNUSED_RESULT
inline uint32_t
HashString(const uint16_t* str)