Bug 1178581 - Interning does not and should not imply infinite lifetime; r=sfink

--HG--
extra : rebase_source : f6fb6b881bffe5af0dfde6a45e9e0c29932c8885
This commit is contained in:
Terrence Cole 2015-06-30 07:58:31 -07:00
parent 8cdf1bf8c6
commit 620b712967
24 changed files with 115 additions and 122 deletions

View File

@ -350,7 +350,7 @@ nsresult
nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
{
#define SET_JSID_TO_STRING(_id, _cx, _str) \
if (JSString *str = ::JS_InternString(_cx, _str)) \
if (JSString *str = ::JS_AtomizeAndPinString(_cx, _str)) \
_id = INTERNED_STRING_TO_JSID(_cx, str); \
else \
return NS_ERROR_OUT_OF_MEMORY;

View File

@ -558,7 +558,7 @@ CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global,
// Might as well intern, since we're going to need an atomized
// version of name anyway when we stick our constructor on the
// global.
JS::Rooted<JSString*> nameStr(cx, JS_InternString(cx, name));
JS::Rooted<JSString*> nameStr(cx, JS_AtomizeAndPinString(cx, name));
if (!nameStr) {
return nullptr;
}

View File

@ -1731,9 +1731,9 @@ GetCallbackFromCallbackObject(T& aObj)
}
static inline bool
InternJSString(JSContext* cx, jsid& id, const char* chars)
AtomizeAndPinJSString(JSContext* cx, jsid& id, const char* chars)
{
if (JSString *str = ::JS_InternString(cx, chars)) {
if (JSString *str = ::JS_AtomizeAndPinString(cx, chars)) {
id = INTERNED_STRING_TO_JSID(cx, str);
return true;
}
@ -2379,7 +2379,7 @@ inline bool
AddStringToIDVector(JSContext* cx, JS::AutoIdVector& vector, const char* name)
{
return vector.growBy(1) &&
InternJSString(cx, *(vector[vector.length() - 1]).address(), name);
AtomizeAndPinJSString(cx, *(vector[vector.length() - 1]).address(), name);
}
// Implementation of the bits that XrayWrapper needs
@ -3058,18 +3058,18 @@ CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache,
}
/*
* Holds a jsid that is initialized to an interned string, with conversion to
* Handle<jsid>.
* Holds a jsid that is initialized to a pinned string, with automatic
* conversion to Handle<jsid>, as it is held live forever by pinning.
*/
class InternedStringId
class PinnedStringId
{
jsid id;
public:
InternedStringId() : id(JSID_VOID) {}
PinnedStringId() : id(JSID_VOID) {}
bool init(JSContext *cx, const char *string) {
JSString* str = JS_InternString(cx, string);
JSString* str = JS_AtomizeAndPinString(cx, string);
if (!str)
return false;
id = INTERNED_STRING_TO_JSID(cx, str);
@ -3081,7 +3081,7 @@ class InternedStringId
}
operator JS::Handle<jsid> () {
/* This is safe because we have interned the string. */
/* This is safe because we have pinned the string. */
return JS::Handle<jsid>::fromMarkedLocation(&id);
}
};

View File

@ -12300,7 +12300,7 @@ class CGResolveSystemBinding(CGAbstractMethod):
jsidInits = CGList(
(CGIfWrapper(
CGGeneric("return false;\n"),
'!InternJSString(aCx, %s, "%s")' %
'!AtomizeAndPinJSString(aCx, %s, "%s")' %
(descNameToId(desc.name), desc.interface.identifier.name))
for desc in descriptors),
"\n")
@ -15156,7 +15156,7 @@ class GlobalGenRoots():
def memberToAtomCacheMember(binaryNameFor, m):
binaryMemberName = binaryNameFor(m.identifier.name)
return ClassMember(CGDictionary.makeIdName(binaryMemberName),
"InternedStringId", visibility="public")
"PinnedStringId", visibility="public")
def buildAtomCacheStructure(idlobj, binaryNameFor, members):
classMembers = [memberToAtomCacheMember(binaryNameFor, m)
for m in members]
@ -15202,7 +15202,7 @@ class GlobalGenRoots():
CGWrapper(structs, pre='\n'))
curr = CGWrapper(curr, post='\n')
# Add include statement for InternedStringId.
# Add include statement for PinnedStringId.
declareIncludes = ['mozilla/dom/BindingUtils.h']
curr = CGHeaders([], [], [], [], declareIncludes, [], 'GeneratedAtomList',
curr)
@ -15379,7 +15379,7 @@ class GlobalGenRoots():
skipGen=False)]
defineIncludes.append("nsThreadUtils.h") # For NS_IsMainThread
defineIncludes.append("js/Id.h") # For jsid
defineIncludes.append("mozilla/dom/BindingUtils.h") # InternJSString
defineIncludes.append("mozilla/dom/BindingUtils.h") # AtomizeAndPinJSString
curr = CGHeaders([], [], [], [], [], defineIncludes,
'ResolveSystemBinding', curr)

View File

@ -25,7 +25,7 @@ jsid s_length_id = JSID_VOID;
bool
DefineStaticJSVals(JSContext* cx)
{
return InternJSString(cx, s_length_id, "length");
return AtomizeAndPinJSString(cx, s_length_id, "length");
}
const char DOMProxyHandler::family = 0;

View File

@ -1053,7 +1053,7 @@ nsJSObjWrapper::NP_Enumerate(NPObject *npobj, NPIdentifier **idarray,
NPIdentifier id;
if (v.isString()) {
JS::Rooted<JSString*> str(cx, v.toString());
str = JS_InternJSString(cx, str);
str = JS_AtomizeAndPinJSString(cx, str);
if (!str) {
PR_Free(*idarray);
return false;
@ -1553,7 +1553,7 @@ CallNPMethodInternal(JSContext *cx, JS::Handle<JSObject*> obj, unsigned argc,
if (npobj->_class->invoke) {
JSFunction *fun = ::JS_GetObjectFunction(funobj);
JS::Rooted<JSString*> funId(cx, ::JS_GetFunctionId(fun));
JSString *name = ::JS_InternJSString(cx, funId);
JSString *name = ::JS_AtomizeAndPinJSString(cx, funId);
NPIdentifier id = StringToNPIdentifier(cx, name);
ok = npobj->_class->invoke(npobj, id, npargs, argc, &v);

View File

@ -681,7 +681,7 @@ doGetIdentifier(JSContext *cx, const NPUTF8* name)
{
NS_ConvertUTF8toUTF16 utf16name(name);
JSString *str = ::JS_InternUCStringN(cx, utf16name.get(), utf16name.Length());
JSString *str = ::JS_AtomizeAndPinUCStringN(cx, utf16name.get(), utf16name.Length());
if (!str)
return nullptr;

View File

@ -129,7 +129,7 @@ inline bool
NPStringIdentifierIsPermanent(NPIdentifier id)
{
AutoSafeJSContext cx;
return JS_StringHasBeenInterned(cx, NPIdentifierToString(id));
return JS_StringHasBeenPinned(cx, NPIdentifierToString(id));
}
#define NPIdentifier_VOID (JSIdToNPIdentifier(JSID_VOID))

View File

@ -21,7 +21,7 @@ using namespace mozilla::plugins::parent;
/**
* NPIdentifiers in the chrome process are stored as jsids. The difficulty is in
* ensuring that string identifiers are rooted without interning them all. We
* ensuring that string identifiers are rooted without pinning them all. We
* assume that all NPIdentifiers passed into nsJSNPRuntime will not be used
* outside the scope of the NPAPI call (i.e., they won't be stored in the
* heap). Rooting is done using the StackIdentifier class, which roots the
@ -31,7 +31,7 @@ using namespace mozilla::plugins::parent;
* generational or compacting GC. When Firefox implements a moving GC for
* strings, we will need to ensure that no movement happens while NPAPI code is
* on the stack: although StackIdentifier roots all identifiers used, the GC has
* no way to no that a jsid cast to an NPIdentifier needs to be fixed up if it
* no way to know that a jsid cast to an NPIdentifier needs to be fixed up if it
* is moved.
*/
@ -39,7 +39,7 @@ class MOZ_STACK_CLASS StackIdentifier
{
public:
explicit StackIdentifier(const PluginIdentifier& aIdentifier,
bool aIntern = false);
bool aAtomizeAndPin = false);
bool Failed() const { return mFailed; }
NPIdentifier ToNPIdentifier() const { return mIdentifier; }
@ -51,7 +51,7 @@ private:
JS::RootedId mId;
};
StackIdentifier::StackIdentifier(const PluginIdentifier& aIdentifier, bool aIntern)
StackIdentifier::StackIdentifier(const PluginIdentifier& aIdentifier, bool aAtomizeAndPin)
: mFailed(false),
mId(mCx)
{
@ -64,8 +64,8 @@ StackIdentifier::StackIdentifier(const PluginIdentifier& aIdentifier, bool aInte
mFailed = true;
return;
}
if (aIntern) {
str = JS_InternJSString(mCx, str);
if (aAtomizeAndPin) {
str = JS_AtomizeAndPinJSString(mCx, str);
if (!str) {
NS_ERROR("Id can't be allocated");
mFailed = true;
@ -509,9 +509,9 @@ PluginScriptableObjectParent::ScriptableEnumerate(NPObject* aObject,
}
for (uint32_t index = 0; index < *aCount; index++) {
// We intern the ID to avoid a GC hazard here. This could probably be fixed
// We pin the ID to avoid a GC hazard here. This could probably be fixed
// if the interface with nsJSNPRuntime were smarter.
StackIdentifier stackID(identifiers[index], true /* aIntern */);
StackIdentifier stackID(identifiers[index], true /* aAtomizeAndPin */);
if (stackID.Failed()) {
return false;
}

View File

@ -784,7 +784,7 @@ HashableValue::setValue(JSContext* cx, HandleValue v)
{
if (v.isString()) {
// Atomize so that hash() and operator==() are fast and infallible.
JSString* str = AtomizeString(cx, v.toString(), DoNotInternAtom);
JSString* str = AtomizeString(cx, v.toString(), DoNotPinAtom);
if (!str)
return false;
value = StringValue(str);

View File

@ -3,7 +3,7 @@
FRAGMENT(jsid, simple) {
JS::Rooted<JSString*> string(cx, JS_NewStringCopyZ(cx, "moon"));
JS::Rooted<JSString*> interned(cx, JS_InternJSString(cx, string));
JS::Rooted<JSString*> interned(cx, JS_AtomizeAndPinJSString(cx, string));
JS::Rooted<jsid> string_id(cx, INTERNED_STRING_TO_JSID(cx, interned));
jsid int_id = INT_TO_JSID(1729);
JS::Rooted<jsid> unique_symbol_id(
@ -38,7 +38,7 @@ jsid_handles(JS::Handle<jsid> jsid_handle,
FRAGMENT(jsid, handles) {
JS::Rooted<JSString*> string(cx, JS_NewStringCopyZ(cx, "shovel"));
JS::Rooted<JSString*> interned(cx, JS_InternJSString(cx, string));
JS::Rooted<JSString*> interned(cx, JS_AtomizeAndPinJSString(cx, string));
JS::Rooted<jsid> string_id(cx, INTERNED_STRING_TO_JSID(cx, interned));
jsid_handles(string_id, &string_id);
}

View File

@ -13,28 +13,28 @@ BEGIN_TEST(testIntString_bug515273)
EVAL("'1';", &v);
JSString* str = v.toString();
CHECK(JS_StringHasBeenInterned(cx, str));
CHECK(JS_StringHasBeenPinned(cx, str));
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "1"));
EVAL("'42';", &v);
str = v.toString();
CHECK(JS_StringHasBeenInterned(cx, str));
CHECK(JS_StringHasBeenPinned(cx, str));
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "42"));
EVAL("'111';", &v);
str = v.toString();
CHECK(JS_StringHasBeenInterned(cx, str));
CHECK(JS_StringHasBeenPinned(cx, str));
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "111"));
/* Test other types of static strings. */
EVAL("'a';", &v);
str = v.toString();
CHECK(JS_StringHasBeenInterned(cx, str));
CHECK(JS_StringHasBeenPinned(cx, str));
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "a"));
EVAL("'bc';", &v);
str = v.toString();
CHECK(JS_StringHasBeenInterned(cx, str));
CHECK(JS_StringHasBeenPinned(cx, str));
CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "bc"));
return true;

View File

@ -10,17 +10,17 @@
using mozilla::ArrayLength;
BEGIN_TEST(testAtomizedIsNotInterned)
BEGIN_TEST(testAtomizedIsNotPinned)
{
/* Try to pick a string that won't be interned by other tests in this runtime. */
static const char someChars[] = "blah blah blah? blah blah blah";
JS::Rooted<JSAtom*> atom(cx, js::Atomize(cx, someChars, ArrayLength(someChars)));
CHECK(!JS_StringHasBeenInterned(cx, atom));
CHECK(JS_InternJSString(cx, atom));
CHECK(JS_StringHasBeenInterned(cx, atom));
CHECK(!JS_StringHasBeenPinned(cx, atom));
CHECK(JS_AtomizeAndPinJSString(cx, atom));
CHECK(JS_StringHasBeenPinned(cx, atom));
return true;
}
END_TEST(testAtomizedIsNotInterned)
END_TEST(testAtomizedIsNotPinned)
struct StringWrapperStruct
{
@ -28,9 +28,9 @@ struct StringWrapperStruct
bool strOk;
} sw;
BEGIN_TEST(testInternAcrossGC)
BEGIN_TEST(testPinAcrossGC)
{
sw.str = JS_InternString(cx, "wrapped chars that another test shouldn't be using");
sw.str = JS_AtomizeAndPinString(cx, "wrapped chars that another test shouldn't be using");
sw.strOk = false;
CHECK(sw.str);
JS_AddFinalizeCallback(rt, FinalizeCallback, nullptr);
@ -45,4 +45,4 @@ FinalizeCallback(JSFreeOp* fop, JSFinalizeStatus status, bool isCompartmentGC, v
if (status == JSFINALIZE_GROUP_START)
sw.strOk = js::gc::IsMarkedUnbarriered(&sw.str);
}
END_TEST(testInternAcrossGC)
END_TEST(testPinAcrossGC)

View File

@ -996,7 +996,7 @@ JS_GetCompartmentPrivate(JSCompartment* compartment)
JS_PUBLIC_API(JSAddonId*)
JS::NewAddonId(JSContext* cx, HandleString str)
{
return static_cast<JSAddonId*>(JS_InternJSString(cx, str));
return static_cast<JSAddonId*>(JS_AtomizeAndPinJSString(cx, str));
}
JS_PUBLIC_API(JSString*)
@ -2745,13 +2745,13 @@ PropertySpecNameToSymbolCode(const char* name)
static bool
PropertySpecNameToId(JSContext* cx, const char* name, MutableHandleId id,
js::InternBehavior ib = js::DoNotInternAtom)
js::PinningBehavior pin = js::DoNotPinAtom)
{
if (JS::PropertySpecNameIsSymbol(name)) {
JS::SymbolCode which = PropertySpecNameToSymbolCode(name);
id.set(SYMBOL_TO_JSID(cx->wellKnownSymbols().get(which)));
} else {
JSAtom* atom = Atomize(cx, name, strlen(name), ib);
JSAtom* atom = Atomize(cx, name, strlen(name), pin);
if (!atom)
return false;
id.set(AtomToId(atom));
@ -2767,7 +2767,7 @@ JS::PropertySpecNameToPermanentId(JSContext* cx, const char* name, jsid* idp)
// of this API is to populate *idp with a jsid that does not need to be
// marked.
return PropertySpecNameToId(cx, name, MutableHandleId::fromMarkedLocation(idp),
js::InternAtom);
js::PinAtom);
}
JS_PUBLIC_API(bool)
@ -4770,7 +4770,7 @@ JS_NewStringCopyZ(JSContext* cx, const char* s)
}
JS_PUBLIC_API(bool)
JS_StringHasBeenInterned(JSContext* cx, JSString* str)
JS_StringHasBeenPinned(JSContext* cx, JSString* str)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
@ -4778,7 +4778,7 @@ JS_StringHasBeenInterned(JSContext* cx, JSString* str)
if (!str->isAtom())
return false;
return AtomIsInterned(cx, &str->asAtom());
return AtomIsPinned(cx, &str->asAtom());
}
JS_PUBLIC_API(jsid)
@ -4786,33 +4786,33 @@ INTERNED_STRING_TO_JSID(JSContext* cx, JSString* str)
{
MOZ_ASSERT(str);
MOZ_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0);
MOZ_ASSERT_IF(cx, JS_StringHasBeenInterned(cx, str));
MOZ_ASSERT_IF(cx, JS_StringHasBeenPinned(cx, str));
return AtomToId(&str->asAtom());
}
JS_PUBLIC_API(JSString*)
JS_InternJSString(JSContext* cx, HandleString str)
JS_AtomizeAndPinJSString(JSContext* cx, HandleString str)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
JSAtom* atom = AtomizeString(cx, str, InternAtom);
MOZ_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
JSAtom* atom = AtomizeString(cx, str, PinAtom);
MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom));
return atom;
}
JS_PUBLIC_API(JSString*)
JS_InternString(JSContext* cx, const char* s)
JS_AtomizeAndPinString(JSContext* cx, const char* s)
{
return JS_InternStringN(cx, s, strlen(s));
return JS_AtomizeAndPinStringN(cx, s, strlen(s));
}
JS_PUBLIC_API(JSString*)
JS_InternStringN(JSContext* cx, const char* s, size_t length)
JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
JSAtom* atom = Atomize(cx, s, length, InternAtom);
MOZ_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
JSAtom* atom = Atomize(cx, s, length, PinAtom);
MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom));
return atom;
}
@ -4845,19 +4845,19 @@ JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s)
}
JS_PUBLIC_API(JSString*)
JS_InternUCStringN(JSContext* cx, const char16_t* s, size_t length)
JS_AtomizeAndPinUCStringN(JSContext* cx, const char16_t* s, size_t length)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
JSAtom* atom = AtomizeChars(cx, s, length, InternAtom);
MOZ_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
JSAtom* atom = AtomizeChars(cx, s, length, PinAtom);
MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom));
return atom;
}
JS_PUBLIC_API(JSString*)
JS_InternUCString(JSContext* cx, const char16_t* s)
JS_AtomizeAndPinUCString(JSContext* cx, const char16_t* s)
{
return JS_InternUCStringN(cx, s, js_strlen(s));
return JS_AtomizeAndPinUCStringN(cx, s, js_strlen(s));
}
JS_PUBLIC_API(size_t)

View File

@ -747,7 +747,7 @@ JS_NumberValue(double d)
/************************************************************************/
JS_PUBLIC_API(bool)
JS_StringHasBeenInterned(JSContext* cx, JSString* str);
JS_StringHasBeenPinned(JSContext* cx, JSString* str);
namespace JS {
@ -4071,13 +4071,13 @@ extern JS_PUBLIC_API(JSString*)
JS_NewStringCopyZ(JSContext* cx, const char* s);
extern JS_PUBLIC_API(JSString*)
JS_InternJSString(JSContext* cx, JS::HandleString str);
JS_AtomizeAndPinJSString(JSContext* cx, JS::HandleString str);
extern JS_PUBLIC_API(JSString*)
JS_InternStringN(JSContext* cx, const char* s, size_t length);
JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length);
extern JS_PUBLIC_API(JSString*)
JS_InternString(JSContext* cx, const char* s);
JS_AtomizeAndPinString(JSContext* cx, const char* s);
extern JS_PUBLIC_API(JSString*)
JS_NewUCString(JSContext* cx, char16_t* chars, size_t length);
@ -4089,10 +4089,10 @@ extern JS_PUBLIC_API(JSString*)
JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s);
extern JS_PUBLIC_API(JSString*)
JS_InternUCStringN(JSContext* cx, const char16_t* s, size_t length);
JS_AtomizeAndPinUCStringN(JSContext* cx, const char16_t* s, size_t length);
extern JS_PUBLIC_API(JSString*)
JS_InternUCString(JSContext* cx, const char16_t* s);
JS_AtomizeAndPinUCString(JSContext* cx, const char16_t* s);
extern JS_PUBLIC_API(bool)
JS_CompareStrings(JSContext* cx, JSString* str1, JSString* str2, int32_t* result);
@ -4113,9 +4113,8 @@ JS_FileEscapedString(FILE* fp, JSString* str, char quote);
* fail. As indicated by the lack of a JSContext parameter, there are two
* special cases where getting the chars is infallible:
*
* The first case is interned strings, i.e., strings from JS_InternString or
* JSID_TO_STRING(id), using JS_GetLatin1InternedStringChars or
* JS_GetTwoByteInternedStringChars.
* The first case is for strings that have been atomized, e.g. directly by
* JS_AtomizeAndPinString or implicitly because it is stored in a jsid.
*
* The second case is "flat" strings that have been explicitly prepared in a
* fallible context by JS_FlattenString. To catch errors, a separate opaque
@ -4176,12 +4175,6 @@ JS_GetTwoByteExternalStringChars(JSString* str);
extern JS_PUBLIC_API(bool)
JS_CopyStringChars(JSContext* cx, mozilla::Range<char16_t> dest, JSString* str);
extern JS_PUBLIC_API(const JS::Latin1Char*)
JS_GetLatin1InternedStringChars(const JS::AutoCheckCannotGC& nogc, JSString* str);
extern JS_PUBLIC_API(const char16_t*)
JS_GetTwoByteInternedStringChars(const JS::AutoCheckCannotGC& nogc, JSString* str);
extern JS_PUBLIC_API(JSFlatString*)
JS_FlattenString(JSContext* cx, JSString* str);

View File

@ -143,7 +143,7 @@ JSRuntime::initializeAtoms(JSContext* cx)
ImmutablePropertyNamePtr* names = reinterpret_cast<ImmutablePropertyNamePtr*>(commonNames);
for (size_t i = 0; i < ArrayLength(cachedNames); i++, names++) {
JSAtom* atom = Atomize(cx, cachedNames[i].str, cachedNames[i].length, InternAtom);
JSAtom* atom = Atomize(cx, cachedNames[i].str, cachedNames[i].length, PinAtom);
if (!atom)
return false;
names->init(atom->asPropertyName());
@ -197,11 +197,11 @@ js::MarkAtoms(JSTracer* trc)
JSRuntime* rt = trc->runtime();
for (AtomSet::Enum e(rt->atoms()); !e.empty(); e.popFront()) {
const AtomStateEntry& entry = e.front();
if (!entry.isTagged())
if (!entry.isPinned())
continue;
JSAtom* atom = entry.asPtr();
bool tagged = entry.isTagged();
bool tagged = entry.isPinned();
TraceRoot(trc, &atom, "interned_atom");
if (entry.asPtr() != atom)
e.rekeyFront(AtomHasher::Lookup(atom), AtomStateEntry(atom, tagged));
@ -257,7 +257,7 @@ JSRuntime::sweepAtoms()
bool isDying = IsAboutToBeFinalizedUnbarriered(&atom);
/* Pinned or interned key cannot be finalized. */
MOZ_ASSERT_IF(hasContexts() && entry.isTagged(), !isDying);
MOZ_ASSERT_IF(hasContexts() && entry.isPinned(), !isDying);
if (isDying)
e.removeFront();
@ -289,7 +289,7 @@ JSRuntime::transformToPermanentAtoms(JSContext* cx)
}
bool
AtomIsInterned(JSContext* cx, JSAtom* atom)
AtomIsPinned(JSContext* cx, JSAtom* atom)
{
/* We treat static strings as interned because they're never collected. */
if (StaticStrings::isStatic(atom))
@ -309,14 +309,14 @@ AtomIsInterned(JSContext* cx, JSAtom* atom)
if (!p)
return false;
return p->isTagged();
return p->isPinned();
}
/* |tbchars| must not point into an inline or short string. */
template <typename CharT>
MOZ_ALWAYS_INLINE
static JSAtom*
AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, InternBehavior ib)
AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, PinningBehavior pin)
{
if (JSAtom* s = cx->staticStrings().lookup(tbchars, length))
return s;
@ -340,7 +340,7 @@ AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, I
AtomSet::AddPtr p = atoms.lookupForAdd(lookup);
if (p) {
JSAtom* atom = p->asPtr();
p->setTagged(bool(ib));
p->setPinned(bool(pin));
return atom;
}
@ -360,7 +360,7 @@ AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, I
// We have held the lock since looking up p, and the operations we've done
// since then can't GC; therefore the atoms table has not been modified and
// p is still valid.
if (!atoms.add(p, AtomStateEntry(atom, bool(ib)))) {
if (!atoms.add(p, AtomStateEntry(atom, bool(pin)))) {
ReportOutOfMemory(cx); /* SystemAllocPolicy does not report OOM. */
return nullptr;
}
@ -369,19 +369,19 @@ AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, I
}
template JSAtom*
AtomizeAndCopyChars(ExclusiveContext* cx, const char16_t* tbchars, size_t length, InternBehavior ib);
AtomizeAndCopyChars(ExclusiveContext* cx, const char16_t* tbchars, size_t length, PinningBehavior pin);
template JSAtom*
AtomizeAndCopyChars(ExclusiveContext* cx, const Latin1Char* tbchars, size_t length, InternBehavior ib);
AtomizeAndCopyChars(ExclusiveContext* cx, const Latin1Char* tbchars, size_t length, PinningBehavior pin);
JSAtom*
js::AtomizeString(ExclusiveContext* cx, JSString* str,
js::InternBehavior ib /* = js::DoNotInternAtom */)
js::PinningBehavior pin /* = js::DoNotPinAtom */)
{
if (str->isAtom()) {
JSAtom& atom = str->asAtom();
/* N.B. static atoms are effectively always interned. */
if (ib != InternAtom || js::StaticStrings::isStatic(&atom))
if (pin != PinAtom || js::StaticStrings::isStatic(&atom))
return &atom;
AtomHasher::Lookup lookup(&atom);
@ -397,8 +397,8 @@ js::AtomizeString(ExclusiveContext* cx, JSString* str,
p = cx->atoms().lookup(lookup);
MOZ_ASSERT(p); /* Non-static atom must exist in atom state set. */
MOZ_ASSERT(p->asPtr() == &atom);
MOZ_ASSERT(ib == InternAtom);
p->setTagged(bool(ib));
MOZ_ASSERT(pin == PinAtom);
p->setPinned(bool(pin));
return &atom;
}
@ -408,12 +408,12 @@ js::AtomizeString(ExclusiveContext* cx, JSString* str,
JS::AutoCheckCannotGC nogc;
return linear->hasLatin1Chars()
? AtomizeAndCopyChars(cx, linear->latin1Chars(nogc), linear->length(), ib)
: AtomizeAndCopyChars(cx, linear->twoByteChars(nogc), linear->length(), ib);
? AtomizeAndCopyChars(cx, linear->latin1Chars(nogc), linear->length(), pin)
: AtomizeAndCopyChars(cx, linear->twoByteChars(nogc), linear->length(), pin);
}
JSAtom*
js::Atomize(ExclusiveContext* cx, const char* bytes, size_t length, InternBehavior ib)
js::Atomize(ExclusiveContext* cx, const char* bytes, size_t length, PinningBehavior pin)
{
CHECK_REQUEST(cx);
@ -421,26 +421,26 @@ js::Atomize(ExclusiveContext* cx, const char* bytes, size_t length, InternBehavi
return nullptr;
const Latin1Char* chars = reinterpret_cast<const Latin1Char*>(bytes);
return AtomizeAndCopyChars(cx, chars, length, ib);
return AtomizeAndCopyChars(cx, chars, length, pin);
}
template <typename CharT>
JSAtom*
js::AtomizeChars(ExclusiveContext* cx, const CharT* chars, size_t length, InternBehavior ib)
js::AtomizeChars(ExclusiveContext* cx, const CharT* chars, size_t length, PinningBehavior pin)
{
CHECK_REQUEST(cx);
if (!JSString::validateLength(cx, length))
return nullptr;
return AtomizeAndCopyChars(cx, chars, length, ib);
return AtomizeAndCopyChars(cx, chars, length, pin);
}
template JSAtom*
js::AtomizeChars(ExclusiveContext* cx, const Latin1Char* chars, size_t length, InternBehavior ib);
js::AtomizeChars(ExclusiveContext* cx, const Latin1Char* chars, size_t length, PinningBehavior pin);
template JSAtom*
js::AtomizeChars(ExclusiveContext* cx, const char16_t* chars, size_t length, InternBehavior ib);
js::AtomizeChars(ExclusiveContext* cx, const char16_t* chars, size_t length, PinningBehavior pin);
bool
js::IndexToIdSlow(ExclusiveContext* cx, uint32_t index, MutableHandleId idp)

View File

@ -72,7 +72,7 @@ class AtomStateEntry
MOZ_ASSERT((uintptr_t(ptr) & 0x1) == 0);
}
bool isTagged() const {
bool isPinned() const {
return bits & 0x1;
}
@ -80,8 +80,8 @@ class AtomStateEntry
* Non-branching code sequence. Note that the const_cast is safe because
* the hash function doesn't consider the tag to be a portion of the key.
*/
void setTagged(bool enabled) const {
const_cast<AtomStateEntry*>(this)->bits |= uintptr_t(enabled);
void setPinned(bool pinned) const {
const_cast<AtomStateEntry*>(this)->bits |= uintptr_t(pinned);
}
JSAtom* asPtr() const;
@ -151,7 +151,7 @@ class PropertyName;
} /* namespace js */
extern bool
AtomIsInterned(JSContext* cx, JSAtom* atom);
AtomIsPinned(JSContext* cx, JSAtom* atom);
/* Well-known predefined C strings. */
#define DECLARE_PROTO_STR(name,code,init,clasp) extern const char js_##name##_str[];
@ -218,23 +218,23 @@ void
MarkWellKnownSymbols(JSTracer* trc);
/* N.B. must correspond to boolean tagging behavior. */
enum InternBehavior
enum PinningBehavior
{
DoNotInternAtom = false,
InternAtom = true
DoNotPinAtom = false,
PinAtom = true
};
extern JSAtom*
Atomize(ExclusiveContext* cx, const char* bytes, size_t length,
js::InternBehavior ib = js::DoNotInternAtom);
js::PinningBehavior pin = js::DoNotPinAtom);
template <typename CharT>
extern JSAtom*
AtomizeChars(ExclusiveContext* cx, const CharT* chars, size_t length,
js::InternBehavior ib = js::DoNotInternAtom);
js::PinningBehavior pin = js::DoNotPinAtom);
extern JSAtom*
AtomizeString(ExclusiveContext* cx, JSString* str, js::InternBehavior ib = js::DoNotInternAtom);
AtomizeString(ExclusiveContext* cx, JSString* str, js::PinningBehavior pin = js::DoNotPinAtom);
template <AllowGC allowGC>
extern JSAtom*

View File

@ -2945,7 +2945,7 @@ JS::OrdinaryToPrimitive(JSContext* cx, HandleObject obj, JSType hint, MutableHan
/* Avoid recursive death when decompiling in ReportValueError. */
RootedString str(cx);
if (hint == JSTYPE_STRING) {
str = JS_InternString(cx, clasp->name);
str = JS_AtomizeAndPinString(cx, clasp->name);
if (!str)
return false;
} else {

View File

@ -2400,7 +2400,7 @@ Intern(JSContext* cx, unsigned argc, jsval* vp)
mozilla::Range<const char16_t> chars = strChars.twoByteRange();
if (!JS_InternUCStringN(cx, chars.start().get(), chars.length()))
if (!JS_AtomizeAndPinUCStringN(cx, chars.start().get(), chars.length()))
return false;
args.rval().setUndefined();

View File

@ -7566,7 +7566,7 @@ DebuggerEnv_getType(JSContext* cx, unsigned argc, Value* vp)
else
s = "object";
JSAtom* str = Atomize(cx, s, strlen(s), InternAtom);
JSAtom* str = Atomize(cx, s, strlen(s), PinAtom);
if (!str)
return false;
args.rval().setString(str);

View File

@ -436,7 +436,7 @@ ExportFunction(JSContext* cx, HandleValue vfunction, HandleValue vscope, HandleV
JSFunction* fun = JS_GetObjectFunction(funObj);
RootedString funName(cx, JS_GetFunctionId(fun));
if (!funName)
funName = JS_InternString(cx, "");
funName = JS_AtomizeAndPinString(cx, "");
if (!JS_StringToId(cx, funName, &id))
return false;

View File

@ -3526,7 +3526,7 @@ XPCJSRuntime::OnJSContextNew(JSContext* cx)
if (JSID_IS_VOID(mStrIDs[0])) {
RootedString str(cx);
for (unsigned i = 0; i < IDX_TOTAL_COUNT; i++) {
str = JS_InternString(cx, mStrings[i]);
str = JS_AtomizeAndPinString(cx, mStrings[i]);
if (!str) {
mStrIDs[0] = JSID_VOID;
return false;
@ -3560,7 +3560,7 @@ XPCJSRuntime::DescribeCustomObjects(JSObject* obj, const js::Class* clasp,
XPCWrappedNativeProto* p =
static_cast<XPCWrappedNativeProto*>(xpc_GetJSPrivate(obj));
si = p->GetScriptableInfo();
if (!si) {
return false;
}

View File

@ -293,7 +293,7 @@ XPCNativeInterface::NewInstance(nsIInterfaceInfo* aInfo)
if (!XPCConvert::IsMethodReflectable(*info))
continue;
str = JS_InternString(cx, info->GetName());
str = JS_AtomizeAndPinString(cx, info->GetName());
if (!str) {
NS_ERROR("bad method name");
failed = true;
@ -338,7 +338,7 @@ XPCNativeInterface::NewInstance(nsIInterfaceInfo* aInfo)
break;
}
str = JS_InternString(cx, namestr);
str = JS_AtomizeAndPinString(cx, namestr);
if (!str) {
NS_ERROR("bad constant name");
failed = true;
@ -364,7 +364,7 @@ XPCNativeInterface::NewInstance(nsIInterfaceInfo* aInfo)
if (!failed) {
const char* bytes;
if (NS_FAILED(aInfo->GetNameShared(&bytes)) || !bytes ||
nullptr == (str = JS_InternString(cx, bytes))) {
nullptr == (str = JS_AtomizeAndPinString(cx, bytes))) {
failed = true;
}
interfaceName = INTERNED_STRING_TO_JSID(cx, str);

View File

@ -804,7 +804,7 @@ XPCWrappedNativeScope::UpdateInterpositionWhitelist(JSContext* cx,
}
RootedString str(cx, idval.toString());
str = JS_InternJSString(cx, str);
str = JS_AtomizeAndPinJSString(cx, str);
if (!str) {
JS_ReportError(cx, "String internization failed.");
return false;