зеркало из https://github.com/mozilla/pjs.git
Bug 725888 - Remove some js_GetClassPrototype calls, using faster methods on GlobalObject instead. Also introduce JS_GetObjectPrototype to retrieve Object.prototype so that a friend API can be made un-friendly. r=dmandelin
--HG-- extra : rebase_source : d68d7f1fdcc1bc9a1a027c08ea62bebd8e9d0178
This commit is contained in:
Родитель
940b5d6043
Коммит
40a728cbad
|
@ -2172,6 +2172,14 @@ JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp)
|
|||
return js_GetClassObject(cx, obj, key, objp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetObjectPrototype(JSContext *cx, JSObject *forObj)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, forObj);
|
||||
return forObj->global().getOrCreateObjectPrototype(cx);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
|
|
|
@ -2728,6 +2728,13 @@ extern JS_PUBLIC_API(JSBool)
|
|||
JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
|
||||
JSObject **objp);
|
||||
|
||||
/*
|
||||
* Returns the original value of |Object.prototype| from the global object in
|
||||
* which |forObj| was created.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetObjectPrototype(JSContext *cx, JSObject *forObj);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetGlobalForObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
|
|
|
@ -971,14 +971,6 @@ JS_STATIC_ASSERT(JSProto_Error + JSEXN_SYNTAXERR == JSProto_SyntaxError);
|
|||
JS_STATIC_ASSERT(JSProto_Error + JSEXN_TYPEERR == JSProto_TypeError);
|
||||
JS_STATIC_ASSERT(JSProto_Error + JSEXN_URIERR == JSProto_URIError);
|
||||
|
||||
static JS_INLINE JSProtoKey
|
||||
GetExceptionProtoKey(intN exn)
|
||||
{
|
||||
JS_ASSERT(JSEXN_ERR <= exn);
|
||||
JS_ASSERT(exn < JSEXN_LIMIT);
|
||||
return JSProtoKey(JSProto_Error + exn);
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
InitErrorClass(JSContext *cx, GlobalObject *global, intN type, JSObject &proto)
|
||||
{
|
||||
|
@ -1031,8 +1023,8 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
|
|||
|
||||
GlobalObject *global = &obj->asGlobal();
|
||||
|
||||
JSObject *objectProto;
|
||||
if (!js_GetClassPrototype(cx, global, JSProto_Object, &objectProto))
|
||||
JSObject *objectProto = global->getOrCreateObjectPrototype(cx);
|
||||
if (!objectProto)
|
||||
return NULL;
|
||||
|
||||
/* Initialize the base Error class first. */
|
||||
|
@ -1331,8 +1323,8 @@ js_CopyErrorObject(JSContext *cx, JSObject *errobj, JSObject *scope)
|
|||
copy->exnType = priv->exnType;
|
||||
|
||||
// Create the Error object.
|
||||
JSObject *proto;
|
||||
if (!js_GetClassPrototype(cx, &scope->global(), GetExceptionProtoKey(copy->exnType), &proto))
|
||||
JSObject *proto = scope->global().getOrCreateCustomErrorPrototype(cx, copy->exnType);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
JSObject *copyobj = NewObjectWithGivenProto(cx, &ErrorClass, proto, NULL);
|
||||
SetExnPrivate(cx, copyobj, copy);
|
||||
|
|
|
@ -101,4 +101,12 @@ js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale,
|
|||
extern JSObject *
|
||||
js_CopyErrorObject(JSContext *cx, JSObject *errobj, JSObject *scope);
|
||||
|
||||
static JS_INLINE JSProtoKey
|
||||
GetExceptionProtoKey(intN exn)
|
||||
{
|
||||
JS_ASSERT(JSEXN_ERR <= exn);
|
||||
JS_ASSERT(exn < JSEXN_LIMIT);
|
||||
return JSProtoKey(JSProto_Error + exn);
|
||||
}
|
||||
|
||||
#endif /* jsexn_h___ */
|
||||
|
|
|
@ -755,14 +755,6 @@ class ObjectPtr
|
|||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
|
||||
* JSProto_Null, clasp must non-null.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey,
|
||||
JSObject **protop, js::Class *clasp = NULL);
|
||||
|
||||
#endif
|
||||
|
||||
/* Implemented in jsdate.cpp. */
|
||||
|
|
|
@ -1244,8 +1244,8 @@ ResolveInterpretedFunctionPrototype(JSContext *cx, JSObject *obj)
|
|||
* Make the prototype object an instance of Object with the same parent
|
||||
* as the function object itself.
|
||||
*/
|
||||
JSObject *objProto;
|
||||
if (!js_GetClassPrototype(cx, obj->getParent(), JSProto_Object, &objProto))
|
||||
JSObject *objProto = obj->global().getOrCreateObjectPrototype(cx);
|
||||
if (!objProto)
|
||||
return NULL;
|
||||
JSObject *proto = NewObjectWithGivenProto(cx, &ObjectClass, objProto, NULL);
|
||||
if (!proto || !proto->setSingletonType(cx))
|
||||
|
|
|
@ -2094,11 +2094,11 @@ types::ArrayPrototypeHasIndexedProperty(JSContext *cx, JSScript *script)
|
|||
if (!cx->typeInferenceEnabled() || !script->hasGlobal())
|
||||
return true;
|
||||
|
||||
JSObject *proto;
|
||||
if (!js_GetClassPrototype(cx, NULL, JSProto_Array, &proto, NULL))
|
||||
JSObject *proto = script->global()->getOrCreateArrayPrototype(cx);
|
||||
if (!proto)
|
||||
return true;
|
||||
|
||||
while (proto) {
|
||||
do {
|
||||
TypeObject *type = proto->getType(cx);
|
||||
if (type->unknownProperties())
|
||||
return true;
|
||||
|
@ -2106,7 +2106,7 @@ types::ArrayPrototypeHasIndexedProperty(JSContext *cx, JSScript *script)
|
|||
if (!indexTypes || indexTypes->isOwnProperty(cx, type, true) || indexTypes->knownNonEmpty(cx))
|
||||
return true;
|
||||
proto = proto->getProto();
|
||||
}
|
||||
} while (proto);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -2612,7 +2612,7 @@ BEGIN_CASE(JSOP_CALLELEM)
|
|||
{
|
||||
/* Find the object on which to look for |this|'s properties. */
|
||||
Value thisv = regs.sp[-2];
|
||||
JSObject *thisObj = ValuePropertyBearer(cx, thisv, -2);
|
||||
JSObject *thisObj = ValuePropertyBearer(cx, regs.fp(), thisv, -2);
|
||||
if (!thisObj)
|
||||
goto error;
|
||||
|
||||
|
|
|
@ -153,28 +153,23 @@ ComputeThis(JSContext *cx, StackFrame *fp)
|
|||
* problem to the value at |spindex| on the stack.
|
||||
*/
|
||||
JS_ALWAYS_INLINE JSObject *
|
||||
ValuePropertyBearer(JSContext *cx, const Value &v, int spindex)
|
||||
ValuePropertyBearer(JSContext *cx, StackFrame *fp, const Value &v, int spindex)
|
||||
{
|
||||
if (v.isObject())
|
||||
return &v.toObject();
|
||||
|
||||
JSProtoKey protoKey;
|
||||
if (v.isString()) {
|
||||
protoKey = JSProto_String;
|
||||
} else if (v.isNumber()) {
|
||||
protoKey = JSProto_Number;
|
||||
} else if (v.isBoolean()) {
|
||||
protoKey = JSProto_Boolean;
|
||||
} else {
|
||||
JS_ASSERT(v.isNull() || v.isUndefined());
|
||||
js_ReportIsNullOrUndefined(cx, spindex, v, NULL);
|
||||
return NULL;
|
||||
}
|
||||
GlobalObject &global = fp->scopeChain().global();
|
||||
|
||||
JSObject *pobj;
|
||||
if (!js_GetClassPrototype(cx, NULL, protoKey, &pobj))
|
||||
return NULL;
|
||||
return pobj;
|
||||
if (v.isString())
|
||||
return global.getOrCreateStringPrototype(cx);
|
||||
if (v.isNumber())
|
||||
return global.getOrCreateNumberPrototype(cx);
|
||||
if (v.isBoolean())
|
||||
return global.getOrCreateBooleanPrototype(cx);
|
||||
|
||||
JS_ASSERT(v.isNull() || v.isUndefined());
|
||||
js_ReportIsNullOrUndefined(cx, spindex, v, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
|
|
@ -2000,6 +2000,17 @@ js_InferFlags(JSContext *cx, uintN defaultFlags);
|
|||
JSBool
|
||||
js_Object(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
/*
|
||||
* If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
|
||||
* JSProto_Null, clasp must non-null.
|
||||
*
|
||||
* If protoKey is constant and scope is non-null, use GlobalObject's prototype
|
||||
* methods instead.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey,
|
||||
JSObject **protop, js::Class *clasp = NULL);
|
||||
|
||||
namespace js {
|
||||
|
||||
extern bool
|
||||
|
|
|
@ -4507,8 +4507,8 @@ mjit::Compiler::callArrayBuiltin(uint32_t argc, bool callingNew)
|
|||
if (!js_GetClassObject(cx, globalObj, JSProto_Array, &arrayObj))
|
||||
return Compile_Error;
|
||||
|
||||
JSObject *arrayProto;
|
||||
if (!js_GetClassPrototype(cx, globalObj, JSProto_Array, &arrayProto))
|
||||
JSObject *arrayProto = globalObj->global().getOrCreateArrayPrototype(cx);
|
||||
if (!arrayProto)
|
||||
return Compile_Error;
|
||||
|
||||
if (argc > 1)
|
||||
|
|
|
@ -1518,8 +1518,8 @@ GetDenseArrayShape(JSContext *cx, JSObject *globalObj)
|
|||
{
|
||||
JS_ASSERT(globalObj);
|
||||
|
||||
JSObject *proto;
|
||||
if (!js_GetClassPrototype(cx, globalObj, JSProto_Array, &proto, NULL))
|
||||
JSObject *proto = globalObj->global().getOrCreateArrayPrototype(cx);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
||||
return EmptyShape::getInitialShape(cx, &ArrayClass, proto,
|
||||
|
|
|
@ -2633,8 +2633,8 @@ DebuggerFrame_getArguments(JSContext *cx, uintN argc, Value *vp)
|
|||
/* Create an arguments object. */
|
||||
RootedVar<GlobalObject*> global(cx);
|
||||
global = &args.callee().global();
|
||||
JSObject *proto;
|
||||
if (!js_GetClassPrototype(cx, global, JSProto_Array, &proto))
|
||||
JSObject *proto = global->getOrCreateArrayPrototype(cx);
|
||||
if (!proto)
|
||||
return false;
|
||||
argsobj = NewObjectWithGivenProto(cx, &DebuggerArguments_class, proto, global);
|
||||
if (!argsobj)
|
||||
|
@ -3791,7 +3791,8 @@ JS_DefineDebuggerObject(JSContext *cx, JSObject *obj)
|
|||
scriptProto(cx),
|
||||
objectProto(cx);
|
||||
|
||||
if (!js_GetClassPrototype(cx, obj, JSProto_Object, objProto.address()))
|
||||
objProto = obj->asGlobal().getOrCreateObjectPrototype(cx);
|
||||
if (!objProto)
|
||||
return false;
|
||||
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
#include "jsarray.h"
|
||||
#include "jsbool.h"
|
||||
#include "jsexn.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsiter.h"
|
||||
#include "jsnum.h"
|
||||
|
@ -186,6 +187,9 @@ class GlobalObject : public JSObject {
|
|||
bool arrayBufferClassInitialized() const {
|
||||
return classIsInitialized(JSProto_ArrayBuffer);
|
||||
}
|
||||
bool errorClassesInitialized() const {
|
||||
return classIsInitialized(JSProto_Error);
|
||||
}
|
||||
|
||||
public:
|
||||
static GlobalObject *create(JSContext *cx, Class *clasp);
|
||||
|
@ -294,6 +298,17 @@ class GlobalObject : public JSObject {
|
|||
return &self->getPrototype(JSProto_ArrayBuffer).toObject();
|
||||
}
|
||||
|
||||
JSObject *getOrCreateCustomErrorPrototype(JSContext *cx, intN exnType) {
|
||||
GlobalObject *self = this;
|
||||
JSProtoKey key = GetExceptionProtoKey(exnType);
|
||||
if (!errorClassesInitialized()) {
|
||||
Root<GlobalObject*> root(cx, &self);
|
||||
if (!js_InitExceptionClasses(cx, this))
|
||||
return NULL;
|
||||
}
|
||||
return &self->getPrototype(key).toObject();
|
||||
}
|
||||
|
||||
JSObject *getOrCreateGeneratorPrototype(JSContext *cx) {
|
||||
GlobalObject *self = this;
|
||||
Value v = getSlotRef(GENERATOR_PROTO);
|
||||
|
|
|
@ -1312,10 +1312,7 @@ NoBase::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope)
|
|||
// We need to pass the object prototype to JS_NewObject. If we pass NULL then the JS engine
|
||||
// will look up a prototype on the global by using the class' name and we'll recurse into
|
||||
// getPrototype.
|
||||
JSObject* proto;
|
||||
if (!js_GetClassPrototype(cx, scope->GetGlobalJSObject(), JSProto_Object, &proto))
|
||||
return NULL;
|
||||
return proto;
|
||||
return JS_GetObjectPrototype(cx, scope->GetGlobalJSObject());
|
||||
}
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче