Memoize standard class.prototype bindings, per ECMA-262 (304376, r=mrbkap).

This commit is contained in:
brendan%mozilla.org 2006-04-19 00:22:43 +00:00
parent bd98558d71
commit 705725e02f
17 changed files with 479 additions and 226 deletions

View File

@ -1087,6 +1087,7 @@ JS_SetGlobalObject(JSContext *cx, JSObject *obj)
#if JS_HAS_XML_SUPPORT
cx->xmlSettingFlags = 0;
#endif
memset(cx->prototypes, 0, sizeof cx->prototypes);
}
static JSObject *
@ -1109,13 +1110,13 @@ InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
if (resolving) {
rt = cx->runtime;
key.obj = obj;
key.id = ATOM_TO_JSID(rt->atomState.FunctionAtom);
key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Function]);
entry = (JSResolvingEntry *)
JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
if (entry && entry->key.obj && (entry->flags & JSRESFLAG_LOOKUP)) {
/* Already resolving Function, record Object too. */
JS_ASSERT(entry->key.obj == obj);
key.id = ATOM_TO_JSID(rt->atomState.ObjectAtom);
key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
entry = (JSResolvingEntry *)
JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
}
@ -1199,7 +1200,8 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
js_InitDateClass(cx, obj);
}
#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom)
#define ATOM_OFFSET(name) offsetof(JSAtomState,name##Atom)
#define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState,classAtoms[JSProto_##name])
#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off)))
/*
@ -1210,33 +1212,33 @@ static struct {
JSObjectOp init;
size_t atomOffset;
} standard_class_atoms[] = {
{InitFunctionAndObjectClasses, ATOM_OFFSET(Function)},
{InitFunctionAndObjectClasses, ATOM_OFFSET(Object)},
{js_InitArrayClass, ATOM_OFFSET(Array)},
{js_InitBooleanClass, ATOM_OFFSET(Boolean)},
{js_InitDateClass, ATOM_OFFSET(Date)},
{js_InitMathClass, ATOM_OFFSET(Math)},
{js_InitNumberClass, ATOM_OFFSET(Number)},
{js_InitStringClass, ATOM_OFFSET(String)},
{InitFunctionAndObjectClasses, CLASS_ATOM_OFFSET(Function)},
{InitFunctionAndObjectClasses, CLASS_ATOM_OFFSET(Object)},
{js_InitArrayClass, CLASS_ATOM_OFFSET(Array)},
{js_InitBooleanClass, CLASS_ATOM_OFFSET(Boolean)},
{js_InitDateClass, CLASS_ATOM_OFFSET(Date)},
{js_InitMathClass, CLASS_ATOM_OFFSET(Math)},
{js_InitNumberClass, CLASS_ATOM_OFFSET(Number)},
{js_InitStringClass, CLASS_ATOM_OFFSET(String)},
#if JS_HAS_CALL_OBJECT
{js_InitCallClass, ATOM_OFFSET(Call)},
{js_InitCallClass, CLASS_ATOM_OFFSET(Call)},
#endif
#if JS_HAS_ERROR_EXCEPTIONS
{js_InitExceptionClasses, ATOM_OFFSET(Error)},
{js_InitExceptionClasses, CLASS_ATOM_OFFSET(Error)},
#endif
#if JS_HAS_REGEXPS
{js_InitRegExpClass, ATOM_OFFSET(RegExp)},
{js_InitRegExpClass, CLASS_ATOM_OFFSET(RegExp)},
#endif
#if JS_HAS_SCRIPT_OBJECT
{js_InitScriptClass, ATOM_OFFSET(Script)},
{js_InitScriptClass, CLASS_ATOM_OFFSET(Script)},
#endif
#if JS_HAS_XML_SUPPORT
{js_InitXMLClass, ATOM_OFFSET(XML)},
{js_InitNamespaceClass, ATOM_OFFSET(Namespace)},
{js_InitQNameClass, ATOM_OFFSET(QName)},
{js_InitXMLClass, CLASS_ATOM_OFFSET(XML)},
{js_InitNamespaceClass, CLASS_ATOM_OFFSET(Namespace)},
{js_InitQNameClass, CLASS_ATOM_OFFSET(QName)},
#endif
#if JS_HAS_FILE_OBJECT
{js_InitFileClass, ATOM_OFFSET(File)},
{js_InitFileClass, CLASS_ATOM_OFFSET(File)},
#endif
{NULL, 0}
};
@ -1271,8 +1273,9 @@ StdNameToAtom(JSContext *cx, JSStdName *stdn)
return atom;
}
#define EAGERLY_PINNED_ATOM(name) ATOM_OFFSET(name), NULL
#define LAZILY_PINNED_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
#define EAGERLY_PINNED_ATOM(name) ATOM_OFFSET(name), NULL
#define EAGERLY_PINNED_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
#define LAZILY_PINNED_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
static JSStdName standard_class_names[] = {
/* ECMA requires that eval be a direct property of the global object. */
@ -1299,19 +1302,19 @@ static JSStdName standard_class_names[] = {
/* Exception constructors. */
#if JS_HAS_ERROR_EXCEPTIONS
{js_InitExceptionClasses, EAGERLY_PINNED_ATOM(Error)},
{js_InitExceptionClasses, LAZILY_PINNED_ATOM(InternalError)},
{js_InitExceptionClasses, LAZILY_PINNED_ATOM(EvalError)},
{js_InitExceptionClasses, LAZILY_PINNED_ATOM(RangeError)},
{js_InitExceptionClasses, LAZILY_PINNED_ATOM(ReferenceError)},
{js_InitExceptionClasses, LAZILY_PINNED_ATOM(SyntaxError)},
{js_InitExceptionClasses, LAZILY_PINNED_ATOM(TypeError)},
{js_InitExceptionClasses, LAZILY_PINNED_ATOM(URIError)},
{js_InitExceptionClasses, EAGERLY_PINNED_CLASS_ATOM(Error)},
{js_InitExceptionClasses, EAGERLY_PINNED_CLASS_ATOM(InternalError)},
{js_InitExceptionClasses, EAGERLY_PINNED_CLASS_ATOM(EvalError)},
{js_InitExceptionClasses, EAGERLY_PINNED_CLASS_ATOM(RangeError)},
{js_InitExceptionClasses, EAGERLY_PINNED_CLASS_ATOM(ReferenceError)},
{js_InitExceptionClasses, EAGERLY_PINNED_CLASS_ATOM(SyntaxError)},
{js_InitExceptionClasses, EAGERLY_PINNED_CLASS_ATOM(TypeError)},
{js_InitExceptionClasses, EAGERLY_PINNED_CLASS_ATOM(URIError)},
#endif
#if JS_HAS_XML_SUPPORT
{js_InitAnyNameClass, LAZILY_PINNED_ATOM(AnyName)},
{js_InitAttributeNameClass, LAZILY_PINNED_ATOM(AttributeName)},
{js_InitAnyNameClass, EAGERLY_PINNED_CLASS_ATOM(AnyName)},
{js_InitAttributeNameClass, EAGERLY_PINNED_CLASS_ATOM(AttributeName)},
{js_InitXMLClass, LAZILY_PINNED_ATOM(XMLList)},
{js_InitXMLClass, LAZILY_PINNED_ATOM(isXMLName)},
#endif
@ -1558,6 +1561,14 @@ JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
return js_SetIdArrayLength(cx, ida, i);
}
JS_PUBLIC_API(JSBool)
JS_GetCachedPrototype(JSContext *cx, JSObject *obj, JSProtoKey key,
JSObject **protop)
{
CHECK_REQUEST(cx);
return js_GetCachedPrototype(cx, obj, key, protop);
}
#undef ATOM_OFFSET
#undef OFFSET_TO_ATOM
@ -1967,8 +1978,14 @@ JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
CHECK_REQUEST(cx);
if (JSVAL_IS_INT(v)) {
*idp = v;
*idp = INT_JSVAL_TO_JSID(v);
} else {
#if JS_HAS_XML_SUPPORT
if (JSVAL_IS_OBJECT(v)) {
*idp = OBJECT_JSVAL_TO_JSID(v);
return JS_TRUE;
}
#endif
atom = js_ValueToStringAtom(cx, v);
if (!atom)
return JS_FALSE;
@ -2031,6 +2048,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
jsval cval, rval;
JSBool named;
JSFunction *fun;
JSProtoKey key;
CHECK_REQUEST(cx);
atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
@ -2046,12 +2064,19 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(proto), &tvr);
if (!constructor) {
/* Lacking a constructor, name the prototype (e.g., Math). */
named = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
OBJECT_TO_JSVAL(proto),
NULL, NULL, 0, NULL);
if (!named)
goto bad;
/*
* Lacking a constructor, name the prototype (e.g., Math) unless this
* class is anonymous, i.e. for internal use only.
*/
if (clasp->flags & JSCLASS_IS_ANONYMOUS) {
named = JS_FALSE;
} else {
named = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
OBJECT_TO_JSVAL(proto),
NULL, NULL, 0, NULL);
if (!named)
goto bad;
}
ctor = proto;
} else {
/* Define the constructor function in obj's scope. */
@ -2106,6 +2131,11 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
goto bad;
}
/* If this is a standard class, cache its prototype. */
key = JSCLASS_CACHED_PROTO_KEY(clasp);
if (key != JSProto_Null)
js_SetCachedPrototype(cx, obj, key, proto);
out:
JS_POP_TEMP_ROOT(cx, &tvr);
return proto;
@ -2724,17 +2754,10 @@ JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
}
JS_PUBLIC_API(JSBool)
JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
jsval *vp)
JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
jsval *vp)
{
JSAtom *atom;
jsid id;
CHECK_REQUEST(cx);
atom = js_Atomize(cx, name, strlen(name), 0);
if (!atom)
return JS_FALSE;
id = ATOM_TO_JSID(atom);
#if JS_HAS_XML_SUPPORT
if (OBJECT_IS_XML(cx, obj)) {
@ -2755,6 +2778,18 @@ JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
return JS_TRUE;
}
JS_PUBLIC_API(JSBool)
JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
jsval *vp)
{
JSAtom *atom;
atom = js_Atomize(cx, name, strlen(name), 0);
if (!atom)
return JS_FALSE;
return JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), objp, vp);
}
JS_PUBLIC_API(JSBool)
JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
{
@ -3069,6 +3104,8 @@ JS_ClearScope(JSContext *cx, JSObject *obj)
if (obj->map->ops->clear)
obj->map->ops->clear(cx, obj);
if (cx->globalObject == obj)
memset(cx->prototypes, 0, sizeof cx->prototypes);
}
JS_PUBLIC_API(JSIdArray *)

View File

@ -567,6 +567,10 @@ extern JS_PUBLIC_API(JSIdArray *)
JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
JSIdArray *ida);
extern JS_PUBLIC_API(JSBool)
JS_GetCachedPrototype(JSContext *cx, JSObject *obj, JSProtoKey key,
JSObject **protop);
extern JS_PUBLIC_API(JSObject *)
JS_GetScopeChain(JSContext *cx);
@ -952,6 +956,16 @@ struct JSExtendedClass {
/* True if JSClass is really a JSExtendedClass. */
#define JSCLASS_IS_EXTENDED (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0))
#define JSCLASS_IS_ANONYMOUS (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1))
/* Fast access to the original value of each standard class's prototype. */
#define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 8)
#define JSCLASS_CACHED_PROTO_WIDTH 8
#define JSCLASS_CACHED_PROTO_MASK JS_BITMASK(JSCLASS_CACHED_PROTO_WIDTH)
#define JSCLASS_HAS_CACHED_PROTO(key) ((key) << JSCLASS_CACHED_PROTO_SHIFT)
#define JSCLASS_CACHED_PROTO_KEY(clasp) (((clasp)->flags \
>> JSCLASS_CACHED_PROTO_SHIFT) \
& JSCLASS_CACHED_PROTO_MASK)
/* Initializer for unused members of statically initialized JSClass structs. */
#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,0
@ -1224,6 +1238,10 @@ JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
extern JS_PUBLIC_API(JSBool)
JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
extern JS_PUBLIC_API(JSBool)
JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
jsval *vp);
extern JS_PUBLIC_API(JSBool)
JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
jsval *vp);

View File

@ -90,22 +90,16 @@ const char *js_boolean_strs[] = {
js_true_str
};
const char js_Arguments_str[] = "Arguments";
const char js_Array_str[] = "Array";
const char js_Boolean_str[] = "Boolean";
const char js_Call_str[] = "Call";
const char js_Date_str[] = "Date";
const char js_Function_str[] = "Function";
const char js_Math_str[] = "Math";
const char js_Namespace_str[] = "Namespace";
const char js_Number_str[] = "Number";
const char js_Object_str[] = "Object";
const char js_QName_str[] = "QName";
const char js_RegExp_str[] = "RegExp";
const char js_Script_str[] = "Script";
const char js_String_str[] = "String";
const char js_XML_str[] = "XML";
const char js_File_str[] = "File";
#define JS_PROTO(name,init) const char js_##name##_str[] = #name;
#include "jsproto.tbl"
#undef JS_PROTO
const char *js_proto_strs[JSProto_LIMIT] = {
#define JS_PROTO(name,init) js_##name##_str,
#include "jsproto.tbl"
#undef JS_PROTO
};
const char js_anonymous_str[] = "anonymous";
const char js_arguments_str[] = "arguments";
const char js_arity_str[] = "arity";
@ -116,8 +110,8 @@ const char js_constructor_str[] = "constructor";
const char js_count_str[] = "__count__";
const char js_each_str[] = "each";
const char js_eval_str[] = "eval";
const char js_getter_str[] = "getter";
const char js_get_str[] = "get";
const char js_getter_str[] = "getter";
const char js_index_str[] = "index";
const char js_input_str[] = "input";
const char js_length_str[] = "length";
@ -299,29 +293,13 @@ js_InitPinnedAtoms(JSContext *cx, JSAtomState *state)
for (i = 0; i < JSTYPE_LIMIT; i++)
FROB(typeAtoms[i], js_type_strs[i]);
for (i = 0; i < JSProto_LIMIT; i++)
FROB(classAtoms[i], js_proto_strs[i]);
FROB(booleanAtoms[0], js_false_str);
FROB(booleanAtoms[1], js_true_str);
FROB(nullAtom, js_null_str);
FROB(ArgumentsAtom, js_Arguments_str);
FROB(ArrayAtom, js_Array_str);
FROB(BooleanAtom, js_Boolean_str);
FROB(CallAtom, js_Call_str);
FROB(DateAtom, js_Date_str);
#if JS_HAS_ERROR_EXCEPTIONS
FROB(ErrorAtom, js_Error_str);
#endif
FROB(FunctionAtom, js_Function_str);
FROB(MathAtom, js_Math_str);
FROB(NamespaceAtom, js_Namespace_str);
FROB(NumberAtom, js_Number_str);
FROB(ObjectAtom, js_Object_str);
FROB(QNameAtom, js_QName_str);
FROB(RegExpAtom, js_RegExp_str);
FROB(ScriptAtom, js_Script_str);
FROB(StringAtom, js_String_str);
FROB(XMLAtom, js_XML_str);
FROB(FileAtom, js_File_str);
FROB(anonymousAtom, js_anonymous_str);
FROB(argumentsAtom, js_arguments_str);
FROB(arityAtom, js_arity_str);

View File

@ -160,24 +160,10 @@ struct JSAtomState {
JSAtom *booleanAtoms[2];
JSAtom *nullAtom;
/* Standard class constructor or prototype names. */
JSAtom *classAtoms[JSProto_LIMIT];
/* Various built-in or commonly-used atoms, pinned on first context. */
JSAtom *ArgumentsAtom;
JSAtom *ArrayAtom;
JSAtom *BooleanAtom;
JSAtom *CallAtom;
JSAtom *DateAtom;
JSAtom *ErrorAtom;
JSAtom *FunctionAtom;
JSAtom *MathAtom;
JSAtom *NamespaceAtom;
JSAtom *NumberAtom;
JSAtom *ObjectAtom;
JSAtom *QNameAtom;
JSAtom *RegExpAtom;
JSAtom *ScriptAtom;
JSAtom *StringAtom;
JSAtom *XMLAtom;
JSAtom *FileAtom;
JSAtom *anonymousAtom;
JSAtom *argumentsAtom;
JSAtom *arityAtom;
@ -216,17 +202,8 @@ struct JSAtomState {
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
struct {
JSAtom *AnyNameAtom;
JSAtom *AttributeNameAtom;
JSAtom *EvalErrorAtom;
JSAtom *InfinityAtom;
JSAtom *InternalErrorAtom;
JSAtom *NaNAtom;
JSAtom *RangeErrorAtom;
JSAtom *ReferenceErrorAtom;
JSAtom *SyntaxErrorAtom;
JSAtom *TypeErrorAtom;
JSAtom *URIErrorAtom;
JSAtom *XMLListAtom;
JSAtom *decodeURIAtom;
JSAtom *decodeURIComponentAtom;
@ -265,9 +242,17 @@ struct JSAtomState {
#endif
};
#define CLASS_ATOM(cx,name) \
((cx)->runtime->atomState.classAtoms[JSProto_##name])
/* Well-known predefined strings and their atoms. */
extern const char *js_type_strs[];
extern const char *js_boolean_strs[];
extern const char *js_proto_strs[];
#define JS_PROTO(name,init) extern const char js_##name##_str[];
#include "jsproto.tbl"
#undef JS_PROTO
extern const char js_Arguments_str[];
extern const char js_Array_str[];
@ -296,8 +281,8 @@ extern const char js_count_str[];
extern const char js_etago_str[];
extern const char js_each_str[];
extern const char js_eval_str[];
extern const char js_getter_str[];
extern const char js_get_str[];
extern const char js_getter_str[];
extern const char js_index_str[];
extern const char js_input_str[];
extern const char js_length_str[];

View File

@ -775,6 +775,116 @@ js_MarkLocalRoots(JSContext *cx, JSLocalRootStack *lrs)
JS_ASSERT(!lrc);
}
static JSObjectOp lazy_cached_prototype_init[JSProto_LIMIT] = {
#define JS_PROTO(name,init) init,
#include "jsproto.tbl"
#undef JS_PROTO
};
/*
* We optimize prototype caching by storing strong references to standard
* object prototypes in each cx whose globalObject is populated (eagerly or
* lazily) with the standard class constructors and global functions.
*
* But since in anything like a browser embedding, an object statically
* scoped by one global object may be accessed by script running on another
* global object's context, we must not dynamically scope cached prototypes.
* This may require searching all contexts for a given thread, in the event
* that a given execution context does not have a global object equal to the
* global of a given target object.
*/
static JSContext *
FindContextForObject(JSContext *cx, JSObject *obj)
{
JSCList *head, *link;
JSContext *ocx;
JS_ASSERT(cx->globalObject != obj);
#ifdef JS_THREADSAFE
head = &cx->thread->contextList;
#else
head = &cx->runtime->contextList;
#endif
for (link = head->next; link != head; link = link->next) {
#ifdef JS_THREADSAFE
ocx = CX_FROM_THREAD_LINKS(link);
JS_ASSERT(ocx->thread == cx->thread);
#else
ocx = (JSContext *) link;
#endif
if (ocx != cx && ocx->globalObject == obj)
return ocx;
}
return NULL;
}
JSBool
js_GetCachedPrototype(JSContext *cx, JSObject *obj, JSProtoKey key,
JSObject **protop)
{
JSBool ok;
JSResolvingKey rkey;
JSResolvingEntry *rentry;
uint32 generation;
JSObject *pobj;
JSContext *ocx;
JSObjectOp init;
rkey.obj = obj;
rkey.id = INT_TO_JSID(key);
ok = js_StartResolving(cx, &rkey, JSRESFLAG_PROTOCACHE, &rentry);
if (!ok)
return JS_FALSE;
if (!rentry) {
/* Already caching key in obj -- suppress recursion. */
*protop = NULL;
return JS_TRUE;
}
generation = cx->resolvingTable->generation;
while ((pobj = OBJ_GET_PARENT(cx, obj)) != NULL)
obj = pobj;
if (obj == cx->globalObject) {
ocx = cx;
} else {
ocx = FindContextForObject(cx, obj);
if (!ocx)
goto out;
}
pobj = ocx->prototypes[key];
if (!pobj) {
init = lazy_cached_prototype_init[key];
if (init) {
if (!init(cx, obj))
ok = JS_FALSE;
pobj = ocx->prototypes[key];
}
}
out:
*protop = pobj;
js_StopResolving(cx, &rkey, JSRESFLAG_PROTOCACHE, rentry, generation);
return ok;
}
void
js_SetCachedPrototype(JSContext *cx, JSObject *obj, JSProtoKey key,
JSObject *value)
{
JSContext *ocx;
JS_ASSERT(!OBJ_GET_PARENT(cx, obj));
if (obj == cx->globalObject) {
ocx = cx;
} else {
ocx = FindContextForObject(cx, obj);
if (!ocx)
return;
}
ocx->prototypes[key] = value;
}
static void
ReportError(JSContext *cx, const char *message, JSErrorReport *reportp)
{

View File

@ -393,6 +393,7 @@ typedef struct JSResolvingEntry {
#define JSRESFLAG_LOOKUP 0x1 /* resolving id from lookup */
#define JSRESFLAG_WATCH 0x2 /* resolving id from watch */
#define JSRESFLAG_PROTOCACHE 0x4 /* resolving prototype cache key */
typedef struct JSLocalRootChunk JSLocalRootChunk;
@ -603,6 +604,9 @@ struct JSContext {
/* Stack of thread-stack-allocated temporary GC roots. */
JSTempValueRooter *tempValueRooters;
/* Roots for the standard object prototypes (Object.prototype, etc.) */
JSObject *prototypes[JSProto_LIMIT];
#ifdef GC_MARK_DEBUG
/* Top of the GC mark stack. */
void *gcCurrentMarkNode;
@ -736,6 +740,17 @@ js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v);
extern void
js_MarkLocalRoots(JSContext *cx, JSLocalRootStack *lrs);
/*
* Fast access to immutable standard objects (constructors and prototypes).
*/
extern JSBool
js_GetCachedPrototype(JSContext *cx, JSObject *obj, JSProtoKey key,
JSObject **protop);
extern void
js_SetCachedPrototype(JSContext *cx, JSObject *obj, JSProtoKey key,
JSObject *value);
/*
* Report an exception, which is currently realized as a printf-style format
* string and its arguments.

View File

@ -3634,8 +3634,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
}
/* Construct the scope holder and push it on. */
ale = js_IndexAtom(cx, cx->runtime->atomState.ObjectAtom,
&cg->atomList);
ale = js_IndexAtom(cx, CLASS_ATOM(cx, Object), &cg->atomList);
if (!ale)
return JS_FALSE;
EMIT_ATOM_INDEX_OP(JSOP_NAME, ALE_INDEX(ale));
@ -4597,8 +4596,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* but use a stack slot for t and avoid dup'ing and popping it via
* the JSOP_NEWINIT and JSOP_INITELEM bytecodes.
*/
ale = js_IndexAtom(cx, cx->runtime->atomState.ArrayAtom,
&cg->atomList);
ale = js_IndexAtom(cx, CLASS_ATOM(cx, Array), &cg->atomList);
if (!ale)
return JS_FALSE;
EMIT_ATOM_INDEX_OP(JSOP_NAME, ALE_INDEX(ale));
@ -4650,8 +4648,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* but use a stack slot for t and avoid dup'ing and popping it via
* the JSOP_NEWINIT and JSOP_INITELEM bytecodes.
*/
ale = js_IndexAtom(cx, cx->runtime->atomState.ObjectAtom,
&cg->atomList);
ale = js_IndexAtom(cx, CLASS_ATOM(cx, Object), &cg->atomList);
if (!ale)
return JS_FALSE;
EMIT_ATOM_INDEX_OP(JSOP_NAME, ALE_INDEX(ale));

View File

@ -79,7 +79,7 @@ static void
exn_finalize(JSContext *cx, JSObject *obj);
static JSClass ExceptionClass = {
"Error",
js_Error_str,
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize,
@ -266,6 +266,7 @@ js_ErrorFromException(JSContext *cx, jsval exn)
struct JSExnSpec {
int protoIndex;
const char *name;
JSProtoKey key;
JSNative native;
};
@ -276,7 +277,6 @@ struct JSExnSpec {
* standard class sets. See jsfun.c:fun_hasInstance.
*/
#define MAKE_EXCEPTION_CTOR(name) \
const char js_##name##_str[] = #name; \
static JSBool \
name(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) \
{ \
@ -295,15 +295,15 @@ MAKE_EXCEPTION_CTOR(URIError)
#undef MAKE_EXCEPTION_CTOR
static struct JSExnSpec exceptions[] = {
{ JSEXN_NONE, js_Error_str, Error },
{ JSEXN_ERR, js_InternalError_str, InternalError },
{ JSEXN_ERR, js_EvalError_str, EvalError },
{ JSEXN_ERR, js_RangeError_str, RangeError },
{ JSEXN_ERR, js_ReferenceError_str, ReferenceError },
{ JSEXN_ERR, js_SyntaxError_str, SyntaxError },
{ JSEXN_ERR, js_TypeError_str, TypeError },
{ JSEXN_ERR, js_URIError_str, URIError },
{0,NULL,NULL}
{JSEXN_NONE, js_Error_str, JSProto_Error, Error},
{JSEXN_ERR, js_InternalError_str, JSProto_InternalError, InternalError},
{JSEXN_ERR, js_EvalError_str, JSProto_EvalError, EvalError},
{JSEXN_ERR, js_RangeError_str, JSProto_RangeError, RangeError},
{JSEXN_ERR, js_ReferenceError_str, JSProto_ReferenceError, ReferenceError},
{JSEXN_ERR, js_SyntaxError_str, JSProto_SyntaxError, SyntaxError},
{JSEXN_ERR, js_TypeError_str, JSProto_TypeError, TypeError},
{JSEXN_ERR, js_URIError_str, JSProto_URIError, URIError},
{0, NULL, JSProto_Null, NULL}
};
static JSBool
@ -936,7 +936,6 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
JSErrNum errorNumber;
JSExnType exn;
JSBool ok;
JSAtom *errAtom;
JSObject *errProto, *errObject;
JSString *messageStr, *filenameStr;
uintN lineno;
@ -987,23 +986,13 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
if (!ok)
goto out;
/*
* FIXME: Can runtime->atomState->lazy.nameErrorAtom be used here instead
* of atomizing name?
*/
errAtom = js_Atomize(cx, exceptions[exn].name,
strlen(exceptions[exn].name), 0);
if (!errAtom) {
ok = JS_FALSE;
goto out;
}
/*
* Try to get an appropriate prototype by looking up the corresponding
* exception constructor name in the scope chain of the current context's
* top stack frame, or in the global object if no frame is active.
*/
ok = js_GetClassPrototype(cx, NULL, errAtom, &errProto);
ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(exceptions[exn].key),
&errProto);
if (!ok)
goto out;

View File

@ -1103,7 +1103,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
* Beware of the wacky case of a user function named Object -- trying
* to find a prototype for that will recur back here _ad perniciem_.
*/
if (!parentProto && fun->atom == cx->runtime->atomState.ObjectAtom)
if (!parentProto && fun->atom == CLASS_ATOM(cx, Object))
return JS_TRUE;
/*
@ -1844,7 +1844,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
/* Belt-and-braces: check that the caller has access to parent. */
if (!js_CheckPrincipalsAccess(cx, parent, principals,
cx->runtime->atomState.FunctionAtom)) {
CLASS_ATOM(cx, Function))) {
return JS_FALSE;
}

View File

@ -1763,13 +1763,62 @@ js_ForceGC(JSContext *cx, uintN gcflags)
} \
JS_END_MACRO
void
js_MarkStackFrame(JSContext *cx, JSStackFrame *fp)
{
uintN depth, nslots;
if (fp->callobj)
GC_MARK(cx, fp->callobj, "call object");
if (fp->argsobj)
GC_MARK(cx, fp->argsobj, "arguments object");
if (fp->varobj)
GC_MARK(cx, fp->varobj, "variables object");
if (fp->script) {
js_MarkScript(cx, fp->script);
if (fp->spbase) {
/*
* Don't mark what has not been pushed yet, or what has been
* popped already.
*/
depth = fp->script->depth;
nslots = (JS_UPTRDIFF(fp->sp, fp->spbase)
< depth * sizeof(jsval))
? (uintN)(fp->sp - fp->spbase)
: depth;
GC_MARK_JSVALS(cx, nslots, fp->spbase, "operand");
}
}
GC_MARK(cx, fp->thisp, "this");
if (fp->argv) {
nslots = fp->argc;
if (fp->fun) {
if (fp->fun->nargs > nslots)
nslots = fp->fun->nargs;
if (!fp->fun->interpreted)
nslots += fp->fun->u.n.extra;
}
GC_MARK_JSVALS(cx, nslots, fp->argv, "arg");
}
if (JSVAL_IS_GCTHING(fp->rval))
GC_MARK(cx, JSVAL_TO_GCTHING(fp->rval), "rval");
if (fp->vars)
GC_MARK_JSVALS(cx, fp->nvars, fp->vars, "var");
GC_MARK(cx, fp->scopeChain, "scope chain");
if (fp->sharpArray)
GC_MARK(cx, fp->sharpArray, "sharp array");
if (fp->xmlNamespace)
GC_MARK(cx, fp->xmlNamespace, "xmlNamespace");
}
void
js_GC(JSContext *cx, uintN gcflags)
{
JSRuntime *rt;
JSContext *iter, *acx;
JSStackFrame *fp, *chain;
uintN i, depth, nslots, type;
uintN i, type;
JSStackHeader *sh;
JSTempValueRooter *tvr;
size_t nbytes, nflags, limit, offset;
@ -1971,48 +2020,7 @@ restart:
for (fp = chain; fp; fp = chain = chain->dormantNext) {
do {
if (fp->callobj)
GC_MARK(cx, fp->callobj, "call object");
if (fp->argsobj)
GC_MARK(cx, fp->argsobj, "arguments object");
if (fp->varobj)
GC_MARK(cx, fp->varobj, "variables object");
if (fp->script) {
js_MarkScript(cx, fp->script);
if (fp->spbase) {
/*
* Don't mark what has not been pushed yet, or what
* has been popped already.
*/
depth = fp->script->depth;
nslots = (JS_UPTRDIFF(fp->sp, fp->spbase)
< depth * sizeof(jsval))
? (uintN)(fp->sp - fp->spbase)
: depth;
GC_MARK_JSVALS(cx, nslots, fp->spbase, "operand");
}
}
GC_MARK(cx, fp->thisp, "this");
if (fp->argv) {
nslots = fp->argc;
if (fp->fun) {
if (fp->fun->nargs > nslots)
nslots = fp->fun->nargs;
if (!fp->fun->interpreted)
nslots += fp->fun->u.n.extra;
}
GC_MARK_JSVALS(cx, nslots, fp->argv, "arg");
}
if (JSVAL_IS_GCTHING(fp->rval))
GC_MARK(cx, JSVAL_TO_GCTHING(fp->rval), "rval");
if (fp->vars)
GC_MARK_JSVALS(cx, fp->nvars, fp->vars, "var");
GC_MARK(cx, fp->scopeChain, "scope chain");
if (fp->sharpArray)
GC_MARK(cx, fp->sharpArray, "sharp array");
if (fp->xmlNamespace)
GC_MARK(cx, fp->xmlNamespace, "xmlNamespace");
js_MarkStackFrame(cx, fp);
} while ((fp = fp->down) != NULL);
}
@ -2048,6 +2056,7 @@ restart:
if (acx->localRootStack)
js_MarkLocalRoots(cx, acx->localRootStack);
for (tvr = acx->tempValueRooters; tvr; tvr = tvr->down) {
if (tvr->count < 0) {
if (JSVAL_IS_GCTHING(tvr->u.value)) {
@ -2058,6 +2067,9 @@ restart:
GC_MARK_JSVALS(cx, tvr->count, tvr->u.array, "tvr->u.array");
}
}
for (i = 0; i < JSProto_LIMIT; i++)
GC_MARK(cx, acx->prototypes[i], "prototypes[i]");
}
#ifdef DUMP_CALL_TABLE

View File

@ -468,7 +468,7 @@ static JSBool
math_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
*rval = ATOM_KEY(cx->runtime->atomState.MathAtom);
*rval = ATOM_KEY(CLASS_ATOM(cx, Math));
return JS_TRUE;
}
#endif

View File

@ -1984,10 +1984,28 @@ FreeSlots(JSContext *cx, jsval *slots)
JS_free(cx, slots - 1);
}
extern JSBool
js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp)
{
JSProtoKey key;
JSAtom *atom;
key = JSCLASS_CACHED_PROTO_KEY(clasp);
if (key != JSProto_Null) {
*idp = INT_TO_JSID(key);
} else {
atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
if (!atom)
return JS_FALSE;
*idp = ATOM_TO_JSID(atom);
}
return JS_TRUE;
}
JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
{
JSAtom *classAtom;
jsid id;
JSObject *obj;
JSObjectOps *ops;
JSObjectMap *map;
@ -1998,14 +2016,12 @@ js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
/* Bootstrap the ur-object, and make it the default prototype object. */
if (!proto) {
classAtom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
if (!classAtom)
if (!js_GetClassId(cx, clasp, &id))
return NULL;
if (!js_GetClassPrototype(cx, parent, classAtom, &proto))
if (!js_GetClassPrototype(cx, parent, id, &proto))
return NULL;
if (!proto &&
!js_GetClassPrototype(cx, parent,
cx->runtime->atomState.ObjectAtom,
!js_GetClassPrototype(cx, parent, INT_TO_JSID(JSProto_Object),
&proto)) {
return NULL;
}
@ -2018,7 +2034,7 @@ js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
/*
* Allocate a zeroed object from the GC heap. Do this *after* any other
* GC-thing allocations under GetClassPrototype or clasp->getObjectOps,
* GC-thing allocations under js_GetClassPrototype or clasp->getObjectOps,
* to avoid displacing the newborn root for obj.
*/
obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
@ -2026,10 +2042,10 @@ js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
return NULL;
/*
* Root obj to prevent it from being killed.
* AllocSlots can trigger a finalizer from a last-ditch GC calling
* JS_ClearNewbornRoots. There's also the possibilty of things
* happening under the objectHook call-out below.
* Root obj to prevent it from being collected out from under this call.
* to js_NewObject. AllocSlots can trigger a finalizer from a last-ditch
* GC calling JS_ClearNewbornRoots. There's also the possibilty of things
* happening under the objectHook call-out further below.
*/
JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(obj), &tvr);
@ -2109,9 +2125,10 @@ bad:
}
JSBool
js_FindConstructor(JSContext *cx, JSObject *start, JSAtom *ctorName, jsval *vp)
js_FindClassObject(JSContext *cx, JSObject *start, jsid id, jsval *vp)
{
JSObject *obj, *pobj;
JSProtoKey key;
JSProperty *prop;
JSScopeProperty *sprop;
@ -2129,9 +2146,21 @@ js_FindConstructor(JSContext *cx, JSObject *start, JSAtom *ctorName, jsval *vp)
}
}
if (JSID_IS_INT(id)) {
key = JSID_TO_INT(id);
JS_ASSERT(key != JSProto_Null);
if (!js_GetCachedPrototype(cx, obj, key, &pobj))
return JS_FALSE;
if (pobj) {
*vp = OBJECT_TO_JSVAL(pobj);
return JS_TRUE;
}
id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[key]);
}
JS_ASSERT(OBJ_IS_NATIVE(obj));
if (!js_LookupPropertyWithFlags(cx, obj, ATOM_TO_JSID(ctorName),
JSRESOLVE_CLASSNAME, &pobj, &prop)) {
if (!js_LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_CLASSNAME,
&pobj, &prop)) {
return JS_FALSE;
}
if (!prop) {
@ -2151,20 +2180,19 @@ JSObject *
js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, uintN argc, jsval *argv)
{
JSAtom *ctorName;
jsid id;
jsval cval, rval;
JSTempValueRooter argtvr, tvr;
JSObject *obj, *ctor;
JS_PUSH_TEMP_ROOT(cx, argc, argv, &argtvr);
ctorName = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
if (!ctorName)
return NULL;
if (!js_FindConstructor(cx, parent, ctorName, &cval)) {
if (!js_GetClassId(cx, clasp, &id) ||
!js_FindClassObject(cx, parent, id, &cval)) {
JS_POP_TEMP_ROOT(cx, &argtvr);
return NULL;
}
if (JSVAL_IS_PRIMITIVE(cval)) {
js_ReportIsNotFunction(cx, &cval, JSV2F_CONSTRUCT | JSV2F_SEARCH_STACK);
JS_POP_TEMP_ROOT(cx, &argtvr);
@ -2742,7 +2770,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
return JS_FALSE;
}
if (!entry) {
/* Already resolving id in obj -- dampen recursion. */
/* Already resolving id in obj -- suppress recursion. */
JS_UNLOCK_OBJ(cx, obj);
goto out;
}
@ -3919,13 +3947,13 @@ js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
}
JSBool
js_GetClassPrototype(JSContext *cx, JSObject *scope, JSAtom *classAtom,
js_GetClassPrototype(JSContext *cx, JSObject *scope, jsid id,
JSObject **protop)
{
jsval v;
JSObject *ctor;
if (!js_FindConstructor(cx, scope, classAtom, &v))
if (!js_FindClassObject(cx, scope, id, &v))
return JS_FALSE;
if (JSVAL_IS_FUNCTION(cx, v)) {
ctor = JSVAL_TO_OBJECT(v);
@ -4138,33 +4166,39 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
{
JSContext *cx;
JSClass *clasp;
JSAtom *classAtom;
uint32 classId, classDef;
JSProtoKey protoKey;
jsid classKey;
JSAtom *atom;
JSObject *proto;
cx = xdr->cx;
if (xdr->mode == JSXDR_ENCODE) {
/*
* XXX: faster way to get already existing classAtom from objp?
*/
clasp = OBJ_GET_CLASS(cx, *objp);
classAtom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
if (!classAtom)
return JS_FALSE;
classId = JS_XDRFindClassIdByName(xdr, clasp->name);
classDef = !classId;
if (classDef && !JS_XDRRegisterClass(xdr, clasp, &classId))
return JS_FALSE;
protoKey = JSCLASS_CACHED_PROTO_KEY(clasp);
if (protoKey != JSProto_Null) {
classDef |= (protoKey << 1);
classKey = INT_TO_JSID(protoKey);
} else {
atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
if (!atom)
return JS_FALSE;
classKey = ATOM_TO_JSID(atom);
}
} else {
classDef = 0;
classAtom = NULL;
clasp = NULL; /* quell GCC overwarning */
classDef = 0;
classKey = 0;
}
/* XDR a flag word followed (if true) by the class name. */
if (!JS_XDRUint32(xdr, &classDef))
return JS_FALSE;
if (classDef && !js_XDRCStringAtom(xdr, &classAtom))
if (classDef && !js_XDRCStringAtom(xdr, &atom))
return JS_FALSE;
if (!JS_XDRUint32(xdr, &classId))
@ -4172,7 +4206,12 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
if (xdr->mode == JSXDR_DECODE) {
if (classDef) {
if (!js_GetClassPrototype(cx, NULL, classAtom, &proto))
/* NB: we know that JSProto_Null is 0 here, for backward compat. */
protoKey = classDef >> 1;
classKey = (protoKey != JSProto_Null)
? INT_TO_JSID(protoKey)
: ATOM_TO_JSID(atom);
if (!js_GetClassPrototype(cx, NULL, classKey, &proto))
return JS_FALSE;
clasp = OBJ_GET_CLASS(cx, proto);
if (!JS_XDRRegisterClass(xdr, clasp, &classId))

View File

@ -302,11 +302,14 @@ js_HoldObjectMap(JSContext *cx, JSObjectMap *map);
extern JSObjectMap *
js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj);
extern JSBool
js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp);
extern JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
extern JSBool
js_FindConstructor(JSContext *cx, JSObject *start, JSAtom *ctorName, jsval *vp);
js_FindClassObject(JSContext *cx, JSObject *start, jsid id, jsval *vp);
extern JSObject *
js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
@ -454,7 +457,7 @@ extern JSBool
js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
extern JSBool
js_GetClassPrototype(JSContext *cx, JSObject *scope, JSAtom *atom,
js_GetClassPrototype(JSContext *cx, JSObject *scope, jsid id,
JSObject **protop);
extern JSBool

64
js/src/jsproto.tbl Normal file
View File

@ -0,0 +1,64 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set sw=4 ts=8 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey 1.7 work in progress, released
* February 14, 2006.
*
* The Initial Developer of the Original Code is
* Brendan Eich <brendan@mozilla.org>
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
JS_PROTO(Null, NULL)
JS_PROTO(Object, NULL)
JS_PROTO(Function, NULL)
JS_PROTO(Array, NULL)
JS_PROTO(Boolean, NULL)
JS_PROTO(Call, NULL)
JS_PROTO(Date, NULL)
JS_PROTO(File, NULL)
JS_PROTO(Math, NULL)
JS_PROTO(Number, NULL)
JS_PROTO(String, NULL)
JS_PROTO(RegExp, NULL)
JS_PROTO(Script, NULL)
JS_PROTO(XML, NULL)
JS_PROTO(Namespace, NULL)
JS_PROTO(QName, NULL)
JS_PROTO(AnyName, NULL)
JS_PROTO(AttributeName, NULL)
JS_PROTO(Error, NULL)
JS_PROTO(InternalError, NULL)
JS_PROTO(EvalError, NULL)
JS_PROTO(RangeError, NULL)
JS_PROTO(ReferenceError, NULL)
JS_PROTO(SyntaxError, NULL)
JS_PROTO(TypeError, NULL)
JS_PROTO(URIError, NULL)

View File

@ -90,6 +90,14 @@ typedef enum JSType {
JSTYPE_LIMIT
} JSType;
/* Dense index into cached prototypes and class atoms for standard objects. */
typedef enum JSProtoKey {
#define JS_PROTO(name,init) JSProto_##name,
#include "jsproto.tbl"
#undef JS_PROTO
JSProto_LIMIT
} JSProtoKey;
/* JSObjectOps.checkAccess mode enumeration. */
typedef enum JSAccessMode {
JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */
@ -547,7 +555,7 @@ typedef void
JSErrorReport *report);
/*
* Possible exception types. These types are part of a JSErrorFormatString
* Possible exception types. These types are part of a JSErrorFormatString
* structure. They define which error to throw in case of a runtime error.
* JSEXN_NONE marks an unthrowable error.
*/

View File

@ -316,7 +316,7 @@ script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
/* Belt-and-braces: check that this script object has access to scopeobj. */
principals = script->principals;
if (!js_CheckPrincipalsAccess(cx, scopeobj, principals,
cx->runtime->atomState.ScriptAtom)) {
CLASS_ATOM(cx, Script))) {
return JS_FALSE;
}

View File

@ -116,8 +116,6 @@ static struct {
/*
* Random utilities and global functions.
*/
const char js_AnyName_str[] = "AnyName";
const char js_AttributeName_str[] = "AttributeName";
const char js_isXMLName_str[] = "isXMLName";
const char js_XMLList_str[] = "XMLList";
const char js_localName_str[] = "localName";
@ -1824,7 +1822,7 @@ GetXMLSetting(JSContext *cx, const char *name, jsval *vp)
{
jsval v;
if (!js_FindConstructor(cx, NULL, cx->runtime->atomState.XMLAtom, &v))
if (!js_FindClassObject(cx, NULL, INT_TO_JSID(JSProto_XML), &v))
return JS_FALSE;
if (!JSVAL_IS_FUNCTION(cx, v)) {
*vp = JSVAL_VOID;