Bug 613457 - clean up string interfaces (r=njn)

This commit is contained in:
Luke Wagner
2011-03-14 13:59:53 -07:00
parent e61b795ad1
commit bd750d98e0
60 changed files with 1546 additions and 1428 deletions

View File

@@ -91,7 +91,7 @@ JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) ==
const char *
js_AtomToPrintableString(JSContext *cx, JSAtom *atom, JSAutoByteString *bytes)
{
return js_ValueToPrintable(cx, StringValue(ATOM_TO_STRING(atom)), bytes);
return js_ValueToPrintable(cx, StringValue(atom), bytes);
}
#define JS_PROTO(name,code,init) const char js_##name##_str[] = #name;
@@ -390,7 +390,7 @@ js_InitCommonAtoms(JSContext *cx)
JS_ASSERT((uint8 *)atoms - (uint8 *)state == LAZY_ATOM_OFFSET_START);
memset(atoms, 0, ATOM_OFFSET_LIMIT - LAZY_ATOM_OFFSET_START);
cx->runtime->emptyString = ATOM_TO_STRING(state->emptyAtom);
cx->runtime->emptyString = state->emptyAtom;
return JS_TRUE;
}
@@ -456,79 +456,84 @@ js_SweepAtomState(JSContext *cx)
}
}
JSAtom *
js_AtomizeString(JSContext *cx, JSString *strArg, uintN flags)
/*
* This call takes ownership of 'chars' if ATOM_NOCOPY is set.
*/
static JSAtom *
Atomize(JSContext *cx, const jschar *chars, size_t length, uintN flags)
{
JS_ASSERT(!(flags & ~(ATOM_PINNED|ATOM_INTERNED|ATOM_TMPSTR|ATOM_NOCOPY)));
JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR);
JS_ASSERT(!(flags & ~(ATOM_PINNED|ATOM_INTERNED|ATOM_NOCOPY)));
if (strArg->isAtom())
return STRING_TO_ATOM(strArg);
JSLinearString *str = strArg->ensureLinear(cx);
if (!str)
return NULL;
const jschar *chars = str->chars();
size_t length = str->length();
JSString *staticStr = JSString::lookupStaticString(chars, length);
if (staticStr)
return STRING_TO_ATOM(staticStr);
if (JSAtom *s = JSAtom::lookupStatic(chars, length))
return s;
AutoLockAtomsCompartment lock(cx);
AtomSet &atoms = cx->runtime->atomState.atoms;
AtomSet::AddPtr p = atoms.lookupForAdd(str);
AtomSet::AddPtr p = atoms.lookupForAdd(AtomHasher::Lookup(chars, length));
/* Hashing the string should have flattened it if it was a rope. */
JS_ASSERT(str->isFlat() || str->isDependent());
JSLinearString *key;
JSAtom *atom;
if (p) {
key = AtomEntryToKey(*p);
atom = AtomEntryToKey(*p);
} else {
/*
* We have to relookup the key as the last ditch GC invoked from the
* string allocation or OOM handling may unlock the atomsCompartment.
*/
SwitchToCompartment sc(cx, cx->runtime->atomsCompartment);
if (flags & ATOM_NOCOPY) {
key = js_NewString(cx, const_cast<jschar *>(str->flatChars()), length);
if (!key)
return NULL;
/* Finish handing off chars to the GC'ed key string. */
JS_ASSERT(flags & ATOM_TMPSTR);
str->u.chars = NULL;
JSFixedString *key;
if (flags & ATOM_NOCOPY) {
key = js_NewString(cx, const_cast<jschar *>(chars), length);
if (!key) {
cx->free(const_cast<jschar *>(chars));
return NULL;
}
} else {
key = js_NewStringCopyN(cx, chars, length);
if (!key)
return NULL;
}
if (!atoms.relookupOrAdd(p, key, StringToInitialAtomEntry(key))) {
/*
* We have to relookup the key as the last ditch GC invoked from the
* string allocation or OOM handling may unlock the atomsCompartment.
*/
AtomHasher::Lookup lookup(chars, length);
if (!atoms.relookupOrAdd(p, lookup, StringToInitialAtomEntry(key))) {
JS_ReportOutOfMemory(cx); /* SystemAllocPolicy does not report */
return NULL;
}
key->flatSetAtomized();
atom = key->morphInternedStringIntoAtom();
}
AddAtomEntryFlags(*p, flags & (ATOM_PINNED | ATOM_INTERNED));
JSAtom *atom = STRING_TO_ATOM(key);
return atom;
}
JSAtom *
js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
{
JS_ASSERT(!(flags & ATOM_NOCOPY));
if (str->isAtom())
return &str->asAtom();
size_t length = str->length();
const jschar *chars = str->getChars(cx);
if (!chars)
return NULL;
JS_ASSERT(length <= JSString::MAX_LENGTH);
return Atomize(cx, chars, length, flags);
}
JSAtom *
js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags, bool useCESU8)
{
jschar *chars;
JSString str;
JSAtom *atom;
JS_ASSERT(!(flags & ATOM_NOCOPY));
CHECK_REQUEST(cx);
if (!CheckStringLength(cx, length))
return NULL;
/*
* Avoiding the malloc in js_InflateString on shorter strings saves us
* over 20,000 malloc calls on mozilla browser startup. This compares to
@@ -536,10 +541,11 @@ js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags, bool us
* The vast majority of atomized strings are already in the hashtable. So
* js_AtomizeString rarely has to copy the temp string we make.
*/
#define ATOMIZE_BUF_MAX 32
static const unsigned ATOMIZE_BUF_MAX = 32;
jschar inflated[ATOMIZE_BUF_MAX];
size_t inflatedLength = ATOMIZE_BUF_MAX - 1;
const jschar *chars;
if (length < ATOMIZE_BUF_MAX) {
if (useCESU8)
js_InflateUTF8StringToBuffer(cx, bytes, length, inflated, &inflatedLength, true);
@@ -555,48 +561,29 @@ js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags, bool us
flags |= ATOM_NOCOPY;
}
str.initFlat(chars, inflatedLength);
atom = js_AtomizeString(cx, &str, ATOM_TMPSTR | flags);
if (chars != inflated && str.flatChars())
cx->free(chars);
return atom;
return Atomize(cx, chars, inflatedLength, flags);
}
JSAtom *
js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags)
{
JSString str;
JS_ASSERT(!(flags & ATOM_NOCOPY));
CHECK_REQUEST(cx);
if (!CheckStringLength(cx, length))
return NULL;
str.initFlatNotTerminated((jschar *)chars, length);
return js_AtomizeString(cx, &str, ATOM_TMPSTR | flags);
return Atomize(cx, chars, length, flags);
}
JSAtom *
js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
{
JSString str, *str2;
JSAtomState *state;
if (length == 1) {
jschar c = *chars;
if (c < UNIT_STRING_LIMIT)
return STRING_TO_ATOM(JSString::unitString(c));
}
str.initFlatNotTerminated((jschar *)chars, length);
state = &cx->runtime->atomState;
JS_LOCK(cx, &state->lock);
AtomSet::Ptr p = state->atoms.lookup(str.assertIsFlat());
str2 = p ? AtomEntryToKey(*p) : NULL;
JS_UNLOCK(cx, &state->lock);
return str2 ? STRING_TO_ATOM(str2) : NULL;
if (JSAtom *atom = JSAtom::lookupStatic(chars, length))
return atom;
AutoLockAtomsCompartment lock(cx);
AtomSet::Ptr p = cx->runtime->atomState.atoms.lookup(AtomHasher::Lookup(chars, length));
return p ? AtomEntryToKey(*p) : NULL;
}
#ifdef DEBUG