Bug 1125567 - Simplify FindClassPrototype/FindClassObject machinery. r=Waldo

This commit is contained in:
Tom Schuster
2015-01-29 19:52:01 +01:00
parent 1ad1d054af
commit be38797c7a
3 changed files with 84 additions and 105 deletions

View File

@@ -1404,6 +1404,90 @@ ClassProtoKeyOrAnonymousOrNull(const js::Class *clasp)
return JSProto_Null;
}
static inline bool
NativeGetPureInline(NativeObject *pobj, Shape *shape, MutableHandleValue vp)
{
if (shape->hasSlot()) {
vp.set(pobj->getSlot(shape->slot()));
MOZ_ASSERT(!vp.isMagic());
} else {
vp.setUndefined();
}
/* Fail if we have a custom getter. */
return shape->hasDefaultGetter();
}
static bool
FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
{
protop.set(nullptr);
JSAtom *atom = Atomize(cx, clasp->name, strlen(clasp->name));
if (!atom)
return false;
RootedId id(cx, AtomToId(atom));
RootedObject pobj(cx);
RootedShape shape(cx);
if (!NativeLookupProperty<CanGC>(cx, cx->global(), id, &pobj, &shape))
return false;
RootedObject ctor(cx);
if (shape && pobj->isNative()) {
if (shape->hasSlot()) {
RootedValue v(cx, pobj->as<NativeObject>().getSlot(shape->slot()));
if (v.isObject())
ctor.set(&v.toObject());
}
}
if (ctor && ctor->is<JSFunction>()) {
JSFunction *nctor = &ctor->as<JSFunction>();
RootedValue v(cx);
if (cx->isJSContext()) {
if (!GetProperty(cx->asJSContext(), ctor, ctor, cx->names().prototype, &v))
return false;
} else {
Shape *shape = nctor->lookup(cx, cx->names().prototype);
if (!shape || !NativeGetPureInline(nctor, shape, &v))
return false;
}
if (v.isObject())
protop.set(&v.toObject());
}
return true;
}
// Find the appropriate proto for a class. There are three different ways to achieve this:
// 1. Built-in classes have a cached proto and anonymous classes get Object.prototype.
// 2. Lookup global[clasp->name].prototype
// 3. Fallback to Object.prototype
//
// Step 2 is in some circumstances an observable operation, which is probably wrong
// as a matter of specifications. It's legacy garbage that we're working to remove eventually.
static bool
FindProto(ExclusiveContext *cx, const js::Class *clasp, MutableHandleObject proto)
{
JSProtoKey protoKey = ClassProtoKeyOrAnonymousOrNull(clasp);
if (protoKey != JSProto_Null)
return GetBuiltinPrototype(cx, protoKey, proto);
if (!FindClassPrototype(cx, proto, clasp))
return false;
if (!proto) {
// We're looking for the prototype of a class that is currently being
// resolved; the global object's resolve hook is on the
// stack. js::FindClassPrototype detects this goofy case and returns
// true with proto null. Fall back on Object.prototype.
MOZ_ASSERT(JSCLASS_CACHED_PROTO_KEY(clasp) == JSProto_Null);
return GetBuiltinPrototype(cx, JSProto_Object, proto);
}
return true;
}
JSObject *
js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg,
const js::Class *clasp, JSObject *protoArg, JSObject *parentArg,
@@ -2779,35 +2863,6 @@ JS::IdentifyStandardConstructor(JSObject *obj)
return JSProto_Null;
}
bool
js::FindClassObject(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
{
JSProtoKey protoKey = ClassProtoKeyOrAnonymousOrNull(clasp);
if (protoKey != JSProto_Null) {
MOZ_ASSERT(JSProto_Null < protoKey);
MOZ_ASSERT(protoKey < JSProto_LIMIT);
return GetBuiltinConstructor(cx, protoKey, protop);
}
JSAtom *atom = Atomize(cx, clasp->name, strlen(clasp->name));
if (!atom)
return false;
RootedId id(cx, AtomToId(atom));
RootedObject pobj(cx);
RootedShape shape(cx);
if (!NativeLookupProperty<CanGC>(cx, cx->global(), id, &pobj, &shape))
return false;
RootedValue v(cx);
if (shape && pobj->isNative()) {
if (shape->hasSlot())
v = pobj->as<NativeObject>().getSlot(shape->slot());
}
if (v.isObject())
protop.set(&v.toObject());
return true;
}
bool
JSObject::isCallable() const
{
@@ -3050,20 +3105,6 @@ LookupPropertyPureInline(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObj
return true;
}
static MOZ_ALWAYS_INLINE bool
NativeGetPureInline(NativeObject *pobj, Shape *shape, Value *vp)
{
if (shape->hasSlot()) {
*vp = pobj->getSlot(shape->slot());
MOZ_ASSERT(!vp->isMagic());
} else {
vp->setUndefined();
}
/* Fail if we have a custom getter. */
return shape->hasDefaultGetter();
}
bool
js::LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObject **objp,
Shape **propp)
@@ -3571,39 +3612,6 @@ js::GetBuiltinPrototypePure(GlobalObject *global, JSProtoKey protoKey)
return nullptr;
}
/*
* The first part of this function has been hand-expanded and optimized into
* NewBuiltinClassInstance in jsobjinlines.h.
*/
bool
js::FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
{
protop.set(nullptr);
JSProtoKey protoKey = ClassProtoKeyOrAnonymousOrNull(clasp);
if (protoKey != JSProto_Null)
return GetBuiltinPrototype(cx, protoKey, protop);
RootedObject ctor(cx);
if (!FindClassObject(cx, &ctor, clasp))
return false;
if (ctor && ctor->is<JSFunction>()) {
JSFunction *nctor = &ctor->as<JSFunction>();
RootedValue v(cx);
if (cx->isJSContext()) {
if (!GetProperty(cx->asJSContext(), ctor, ctor, cx->names().prototype, &v))
return false;
} else {
Shape *shape = nctor->lookup(cx, cx->names().prototype);
if (!shape || !NativeGetPureInline(nctor, shape, v.address()))
return false;
}
if (v.isObject())
protop.set(&v.toObject());
}
return true;
}
JSObject *
js::PrimitiveToObject(JSContext *cx, const Value &v)
{