diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 8a5e6ec80e4..ad8b5c605ed 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1742,20 +1742,35 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj) #define CLASP(name) (&name##Class) #define TYPED_ARRAY_CLASP(type) (&TypedArray::classes[TypedArray::type]) -#define EAGER_ATOM(name) ATOM_OFFSET(name) -#define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name) +#define EAGER_ATOM(name) NAME_OFFSET(name), NULL +#define EAGER_CLASS_ATOM(name) CLASS_NAME_OFFSET(name), NULL #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name) +#define LAZY_ATOM(name) NAME_OFFSET(lazy.name), js_##name##_str typedef struct JSStdName { JSObjectOp init; size_t atomOffset; /* offset of atom pointer in JSAtomState */ + const char *name; /* null if atom is pre-pinned, else name */ Class *clasp; } JSStdName; static PropertyName * StdNameToPropertyName(JSContext *cx, JSStdName *stdn) { - return OFFSET_TO_ATOM(cx->runtime, stdn->atomOffset); + size_t offset; + PropertyName *atom; + const char *name; + + offset = stdn->atomOffset; + atom = OFFSET_TO_NAME(cx->runtime, offset); + if (!atom) { + name = stdn->name; + if (name) { + atom = js_Atomize(cx, name, strlen(name), InternAtom)->asPropertyName(); + OFFSET_TO_NAME(cx->runtime, offset) = atom; + } + } + return atom; } /* @@ -1786,7 +1801,7 @@ static JSStdName standard_class_atoms[] = { {js_InitWeakMapClass, EAGER_CLASS_ATOM(WeakMap), &js::WeakMapClass}, {js_InitMapClass, EAGER_CLASS_ATOM(Map), &js::MapObject::class_}, {js_InitSetClass, EAGER_CLASS_ATOM(Set), &js::SetObject::class_}, - {NULL, 0, NULL} + {NULL, 0, NULL, NULL} }; /* @@ -1800,20 +1815,20 @@ static JSStdName standard_class_names[] = { /* Global properties and functions defined by the Number class. */ {js_InitNumberClass, EAGER_ATOM(NaN), CLASP(Number)}, {js_InitNumberClass, EAGER_ATOM(Infinity), CLASP(Number)}, - {js_InitNumberClass, EAGER_ATOM(isNaN), CLASP(Number)}, - {js_InitNumberClass, EAGER_ATOM(isFinite), CLASP(Number)}, - {js_InitNumberClass, EAGER_ATOM(parseFloat), CLASP(Number)}, - {js_InitNumberClass, EAGER_ATOM(parseInt), CLASP(Number)}, + {js_InitNumberClass, LAZY_ATOM(isNaN), CLASP(Number)}, + {js_InitNumberClass, LAZY_ATOM(isFinite), CLASP(Number)}, + {js_InitNumberClass, LAZY_ATOM(parseFloat), CLASP(Number)}, + {js_InitNumberClass, LAZY_ATOM(parseInt), CLASP(Number)}, /* String global functions. */ - {js_InitStringClass, EAGER_ATOM(escape), CLASP(String)}, - {js_InitStringClass, EAGER_ATOM(unescape), CLASP(String)}, - {js_InitStringClass, EAGER_ATOM(decodeURI), CLASP(String)}, - {js_InitStringClass, EAGER_ATOM(encodeURI), CLASP(String)}, - {js_InitStringClass, EAGER_ATOM(decodeURIComponent), CLASP(String)}, - {js_InitStringClass, EAGER_ATOM(encodeURIComponent), CLASP(String)}, + {js_InitStringClass, LAZY_ATOM(escape), CLASP(String)}, + {js_InitStringClass, LAZY_ATOM(unescape), CLASP(String)}, + {js_InitStringClass, LAZY_ATOM(decodeURI), CLASP(String)}, + {js_InitStringClass, LAZY_ATOM(encodeURI), CLASP(String)}, + {js_InitStringClass, LAZY_ATOM(decodeURIComponent), CLASP(String)}, + {js_InitStringClass, LAZY_ATOM(encodeURIComponent), CLASP(String)}, #if JS_HAS_UNEVAL - {js_InitStringClass, EAGER_ATOM(uneval), CLASP(String)}, + {js_InitStringClass, LAZY_ATOM(uneval), CLASP(String)}, #endif /* Exception constructors. */ @@ -1827,8 +1842,8 @@ static JSStdName standard_class_names[] = { {js_InitExceptionClasses, EAGER_CLASS_ATOM(URIError), CLASP(Error)}, #if JS_HAS_XML_SUPPORT - {js_InitXMLClass, EAGER_ATOM(XMLList), CLASP(XML)}, - {js_InitXMLClass, EAGER_ATOM(isXMLName), CLASP(XML)}, + {js_InitXMLClass, LAZY_ATOM(XMLList), CLASP(XML)}, + {js_InitXMLClass, LAZY_ATOM(isXMLName), CLASP(XML)}, #endif #if JS_HAS_GENERATORS @@ -1852,7 +1867,7 @@ static JSStdName standard_class_names[] = { {js_InitWeakMapClass, EAGER_ATOM_AND_CLASP(WeakMap)}, {js_InitProxyClass, EAGER_ATOM_AND_CLASP(Proxy)}, - {NULL, 0, NULL} + {NULL, 0, NULL, NULL} }; static JSStdName object_prototype_names[] = { @@ -1865,20 +1880,20 @@ static JSStdName object_prototype_names[] = { {js_InitObjectClass, EAGER_ATOM(toLocaleString), CLASP(Object)}, {js_InitObjectClass, EAGER_ATOM(valueOf), CLASP(Object)}, #if JS_HAS_OBJ_WATCHPOINT - {js_InitObjectClass, EAGER_ATOM(watch), CLASP(Object)}, - {js_InitObjectClass, EAGER_ATOM(unwatch), CLASP(Object)}, + {js_InitObjectClass, LAZY_ATOM(watch), CLASP(Object)}, + {js_InitObjectClass, LAZY_ATOM(unwatch), CLASP(Object)}, #endif - {js_InitObjectClass, EAGER_ATOM(hasOwnProperty), CLASP(Object)}, - {js_InitObjectClass, EAGER_ATOM(isPrototypeOf), CLASP(Object)}, - {js_InitObjectClass, EAGER_ATOM(propertyIsEnumerable), CLASP(Object)}, + {js_InitObjectClass, LAZY_ATOM(hasOwnProperty), CLASP(Object)}, + {js_InitObjectClass, LAZY_ATOM(isPrototypeOf), CLASP(Object)}, + {js_InitObjectClass, LAZY_ATOM(propertyIsEnumerable), CLASP(Object)}, #if OLD_GETTER_SETTER_METHODS - {js_InitObjectClass, EAGER_ATOM(defineGetter), CLASP(Object)}, - {js_InitObjectClass, EAGER_ATOM(defineSetter), CLASP(Object)}, - {js_InitObjectClass, EAGER_ATOM(lookupGetter), CLASP(Object)}, - {js_InitObjectClass, EAGER_ATOM(lookupSetter), CLASP(Object)}, + {js_InitObjectClass, LAZY_ATOM(defineGetter), CLASP(Object)}, + {js_InitObjectClass, LAZY_ATOM(defineSetter), CLASP(Object)}, + {js_InitObjectClass, LAZY_ATOM(lookupGetter), CLASP(Object)}, + {js_InitObjectClass, LAZY_ATOM(lookupSetter), CLASP(Object)}, #endif - {NULL, 0, NULL} + {NULL, 0, NULL, NULL} }; JS_PUBLIC_API(JSBool) @@ -2134,6 +2149,7 @@ JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj, JSIdArray *ida #undef EAGER_ATOM #undef EAGER_CLASS_ATOM #undef EAGER_ATOM_CLASP +#undef LAZY_ATOM JS_PUBLIC_API(JSBool) JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp) diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 8fb523b62ef..dcdda50b0b6 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -75,6 +75,7 @@ using namespace js; using namespace js::gc; const size_t JSAtomState::commonAtomsOffset = offsetof(JSAtomState, emptyAtom); +const size_t JSAtomState::lazyAtomsOffset = offsetof(JSAtomState, lazy); /* * ATOM_HASH assumes that JSHashNumber is 32-bit even on 64-bit systems. @@ -150,6 +151,9 @@ JSAtomState::checkStaticInvariants() offsetof(JSAtomState, booleanAtoms) - commonAtomsOffset); JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) == offsetof(JSAtomState, typeAtoms) - commonAtomsOffset); + + JS_STATIC_ASSERT(JS_ARRAY_LENGTH(js_common_atom_names) * sizeof(JSAtom *) == + lazyAtomsOffset - commonAtomsOffset); } /* @@ -232,6 +236,7 @@ js::InitCommonAtoms(JSContext *cx) *atoms = atom->asPropertyName(); } + state->clearLazyAtoms(); cx->runtime->emptyString = state->emptyAtom; return true; } diff --git a/js/src/jsatom.h b/js/src/jsatom.h index 014e7909c71..618a68a14b1 100644 --- a/js/src/jsatom.h +++ b/js/src/jsatom.h @@ -308,7 +308,38 @@ struct JSAtomState #undef DEFINE_PROTOTYPE_ATOM #undef DEFINE_KEYWORD_ATOM + /* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */ + struct { + js::PropertyName *XMLListAtom; + js::PropertyName *decodeURIAtom; + js::PropertyName *decodeURIComponentAtom; + js::PropertyName *defineGetterAtom; + js::PropertyName *defineSetterAtom; + js::PropertyName *encodeURIAtom; + js::PropertyName *encodeURIComponentAtom; + js::PropertyName *escapeAtom; + js::PropertyName *hasOwnPropertyAtom; + js::PropertyName *isFiniteAtom; + js::PropertyName *isNaNAtom; + js::PropertyName *isPrototypeOfAtom; + js::PropertyName *isXMLNameAtom; + js::PropertyName *lookupGetterAtom; + js::PropertyName *lookupSetterAtom; + js::PropertyName *parseFloatAtom; + js::PropertyName *parseIntAtom; + js::PropertyName *propertyIsEnumerableAtom; + js::PropertyName *unescapeAtom; + js::PropertyName *unevalAtom; + js::PropertyName *unwatchAtom; + js::PropertyName *watchAtom; + } lazy; + static const size_t commonAtomsOffset; + static const size_t lazyAtomsOffset; + + void clearLazyAtoms() { + memset(&lazy, 0, sizeof(lazy)); + } void junkAtoms() { #ifdef DEBUG diff --git a/js/src/jsatom.tbl b/js/src/jsatom.tbl index 47643f8340d..e2c6f3ba739 100644 --- a/js/src/jsatom.tbl +++ b/js/src/jsatom.tbl @@ -123,26 +123,3 @@ DEFINE_KEYWORD_ATOM(return) DEFINE_KEYWORD_ATOM(throw) DEFINE_ATOM(url, "url") DEFINE_ATOM(innermost, "innermost") - -DEFINE_ATOM(XMLList, "XMLList") -DEFINE_ATOM(decodeURI, "decodeURI") -DEFINE_ATOM(decodeURIComponent, "decodeURIComponent") -DEFINE_ATOM(defineGetter, "__defineGetter__") -DEFINE_ATOM(defineSetter, "__defineSetter__") -DEFINE_ATOM(encodeURI, "encodeURI") -DEFINE_ATOM(encodeURIComponent, "encodeURIComponent") -DEFINE_ATOM(escape, "escape") -DEFINE_ATOM(hasOwnProperty, "hasOwnProperty") -DEFINE_ATOM(isFinite, "isFinite") -DEFINE_ATOM(isNaN, "isNaN") -DEFINE_ATOM(isPrototypeOf, "isPrototypeOf") -DEFINE_ATOM(isXMLName, "isXMLName") -DEFINE_ATOM(lookupGetter, "__lookupGetter__") -DEFINE_ATOM(lookupSetter, "__lookupSetter__") -DEFINE_ATOM(parseFloat, "parseFloat") -DEFINE_ATOM(parseInt, "parseInt") -DEFINE_ATOM(propertyIsEnumerable, "propertyIsEnumerable") -DEFINE_ATOM(unescape, "unescape") -DEFINE_ATOM(uneval, "uneval") -DEFINE_ATOM(unwatch, "unwatch") -DEFINE_ATOM(watch, "watch") diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 484f6827ff0..0a083a36f7a 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -455,6 +455,11 @@ js::num_parseInt(JSContext *cx, unsigned argc, Value *vp) return true; } +const char js_isNaN_str[] = "isNaN"; +const char js_isFinite_str[] = "isFinite"; +const char js_parseFloat_str[] = "parseFloat"; +const char js_parseInt_str[] = "parseInt"; + static JSFunctionSpec number_functions[] = { JS_FN(js_isNaN_str, num_isNaN, 1,0), JS_FN(js_isFinite_str, num_isFinite, 1,0), diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 510e5863a65..39fa815cd08 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1392,6 +1392,11 @@ js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, Value *vp) #if OLD_GETTER_SETTER_METHODS +const char js_defineGetter_str[] = "__defineGetter__"; +const char js_defineSetter_str[] = "__defineSetter__"; +const char js_lookupGetter_str[] = "__lookupGetter__"; +const char js_lookupSetter_str[] = "__lookupSetter__"; + enum DefineType { Getter, Setter }; template @@ -2669,6 +2674,14 @@ obj_isSealed(JSContext *cx, unsigned argc, Value *vp) return true; } +#if JS_HAS_OBJ_WATCHPOINT +const char js_watch_str[] = "watch"; +const char js_unwatch_str[] = "unwatch"; +#endif +const char js_hasOwnProperty_str[] = "hasOwnProperty"; +const char js_isPrototypeOf_str[] = "isPrototypeOf"; +const char js_propertyIsEnumerable_str[] = "propertyIsEnumerable"; + JSFunctionSpec object_methods[] = { #if JS_HAS_TOSOURCE JS_FN(js_toSource_str, obj_toSource, 0,0), diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 32d5d8ff4d9..8742778a126 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -372,6 +372,16 @@ str_uneval(JSContext *cx, unsigned argc, Value *vp) } #endif +const char js_escape_str[] = "escape"; +const char js_unescape_str[] = "unescape"; +#if JS_HAS_UNEVAL +const char js_uneval_str[] = "uneval"; +#endif +const char js_decodeURI_str[] = "decodeURI"; +const char js_encodeURI_str[] = "encodeURI"; +const char js_decodeURIComponent_str[] = "decodeURIComponent"; +const char js_encodeURIComponent_str[] = "encodeURIComponent"; + static JSFunctionSpec string_functions[] = { JS_FN(js_escape_str, str_escape, 1,0), JS_FN(js_unescape_str, str_unescape, 1,0), diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 242ffbc9d44..59683e802e3 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -139,6 +139,8 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, void *rval) * Random utilities and global functions. */ const char js_AttributeName_str[] = "AttributeName"; +const char js_isXMLName_str[] = "isXMLName"; +const char js_XMLList_str[] = "XMLList"; const char js_localName_str[] = "localName"; const char js_xml_parent_str[] = "parent"; const char js_prefix_str[] = "prefix";