mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1178581 - Interning does not and should not imply infinite lifetime; r=sfink
--HG-- extra : rebase_source : f6fb6b881bffe5af0dfde6a45e9e0c29932c8885
This commit is contained in:
parent
8cdf1bf8c6
commit
620b712967
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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*
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user