Bug 921448 - Remove FunctionProxyObjects. r=ejpbruel

\o/
This commit is contained in:
Bobby Holley 2013-10-04 13:29:34 +02:00
parent b1da1dbabe
commit ce560e7d97
13 changed files with 103 additions and 270 deletions

View File

@ -34,7 +34,7 @@ inline const void* ProxyFamily() { return &HandlerFamily; }
inline bool IsDOMProxy(JSObject *obj, const js::Class* clasp)
{
MOZ_ASSERT(js::GetObjectClass(obj) == clasp);
return (js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) &&
return js::IsProxyClass(clasp) &&
js::GetProxyHandler(obj)->family() == ProxyFamily();
}

View File

@ -1539,9 +1539,9 @@ GenerateProxyClassGuards(MacroAssembler &masm, Register object, Register scratch
// that it is one of an ObjectProxy, FunctionProxy, or OuterWindowProxy.
// This is equivalent to obj->is<ProxyObject>().
masm.branchTestObjClass(Assembler::Equal, object, scratchReg,
ObjectProxyClassPtr, success);
CallableProxyClassPtr, success);
masm.branchTestObjClass(Assembler::Equal, object, scratchReg,
FunctionProxyClassPtr, success);
UncallableProxyClassPtr, success);
masm.branchTestObjClass(Assembler::NotEqual, object, scratchReg,
OuterWindowProxyClassPtr, failures);
}

View File

@ -912,9 +912,9 @@ class MacroAssembler : public MacroAssemblerSpecific
// of the JSObject::isWrapper test performed in EmulatesUndefined. If none
// of the branches are taken, we can check class flags directly.
loadObjClass(objReg, scratch);
branchPtr(Assembler::Equal, scratch, ImmPtr(&ObjectProxyObject::class_), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmPtr(&ProxyObject::callableClass_), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmPtr(&ProxyObject::uncallableClass_), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmPtr(&OuterWindowProxyObject::class_), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmPtr(&FunctionProxyObject::class_), slowCheck);
test32(Address(scratch, Class::offsetOfFlags()), Imm32(JSCLASS_EMULATES_UNDEFINED));
return truthy ? Assembler::Zero : Assembler::NonZero;

View File

@ -1371,7 +1371,7 @@ static const JSStdName standard_class_atoms[] = {
#ifdef ENABLE_PARALLEL_JS
{js_InitParallelArrayClass, EAGER_ATOM_AND_OCLASP(ParallelArray)},
#endif
{js_InitProxyClass, EAGER_CLASS_ATOM(Proxy), OCLASP(ObjectProxy)},
{js_InitProxyClass, EAGER_CLASS_ATOM(Proxy), &ProxyObject::uncallableClass_},
#if EXPOSE_INTL_API
{js_InitIntlClass, EAGER_ATOM_AND_CLASP(Intl)},
#endif

View File

@ -271,7 +271,7 @@ CallJSNativeConstructor(JSContext *cx, Native native, const CallArgs &args)
*
* - (new Object(Object)) returns the callee.
*/
JS_ASSERT_IF(native != FunctionProxyObject::class_.construct &&
JS_ASSERT_IF(native != ProxyObject::callableClass_.construct &&
native != js::CallOrConstructBoundFunction &&
native != js::IteratorConstructor &&
(!callee->is<JSFunction>() || callee->as<JSFunction>().native() != obj_construct),

View File

@ -339,7 +339,7 @@ JSCompartment::wrap(JSContext *cx, MutableHandleObject obj, HandleObject existin
/* Is it possible to reuse |existing|? */
if (!existing->getTaggedProto().isLazy() ||
// Note: don't use is<ObjectProxyObject>() here -- it also matches subclasses!
existing->getClass() != &ObjectProxyObject::class_ ||
existing->getClass() != &ProxyObject::uncallableClass_ ||
existing->getParent() != global ||
obj->isCallable())
{

View File

@ -530,13 +530,8 @@ js::SetFunctionNativeReserved(JSObject *fun, size_t which, const Value &val)
JS_FRIEND_API(bool)
js::GetObjectProto(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JSObject*> proto)
{
const js::Class *clasp = GetObjectClass(obj);
if (clasp == js::ObjectProxyClassPtr ||
clasp == js::OuterWindowProxyClassPtr ||
clasp == js::FunctionProxyClassPtr)
{
if (IsProxy(obj))
return JS_GetPrototype(cx, obj, proto);
}
proto.set(reinterpret_cast<const shadow::Object*>(obj.get())->type->proto);
return true;

View File

@ -302,7 +302,7 @@ BaseProxyHandler::construct(JSContext *cx, HandleObject proxy, const CallArgs &a
const char *
BaseProxyHandler::className(JSContext *cx, HandleObject proxy)
{
return proxy->is<FunctionProxyObject>() ? "Function" : "Object";
return proxy->isCallable() ? "Function" : "Object";
}
JSString *
@ -726,21 +726,6 @@ ArrayToIdVector(JSContext *cx, const Value &array, AutoIdVector &props)
return true;
}
inline HeapSlot &
FunctionProxyObject::construct()
{
JS_ASSERT(slotSpan() > CONSTRUCT_SLOT);
return getSlotRef(CONSTRUCT_SLOT);
}
inline Value
FunctionProxyObject::constructOrUndefined() const
{
if (slotSpan() <= CONSTRUCT_SLOT)
return UndefinedValue();
return getSlot(CONSTRUCT_SLOT);
}
namespace {
/* Derived class for all scripted indirect proxy handlers. */
@ -2991,17 +2976,6 @@ ProxyObject::trace(JSTracer *trc, JSObject *obj)
MarkSlot(trc, proxy->slotOfExtra(1), "extra1");
}
static void
proxy_TraceFunction(JSTracer *trc, JSObject *obj)
{
// NB: If you add new slots here, make sure to change
// nuke() to cope.
FunctionProxyObject *proxy = &obj->as<FunctionProxyObject>();
MarkCrossCompartmentSlot(trc, proxy, &proxy->call(), "call");
MarkSlot(trc, &proxy->construct(), "construct");
ProxyObject::trace(trc, proxy);
}
static JSObject *
proxy_WeakmapKeyDelegate(JSObject *obj)
{
@ -3033,6 +3007,24 @@ proxy_HasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool
return true;
}
static bool
proxy_Call(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject proxy(cx, &args.callee());
JS_ASSERT(proxy->is<ProxyObject>());
return Proxy::call(cx, proxy, args);
}
static bool
proxy_Construct(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject proxy(cx, &args.callee());
JS_ASSERT(proxy->is<ProxyObject>());
return Proxy::construct(cx, proxy, args);
}
#define PROXY_CLASS_EXT \
{ \
NULL, /* outerObject */ \
@ -3042,53 +3034,59 @@ proxy_HasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool
proxy_WeakmapKeyDelegate \
}
const Class js::ObjectProxyObject::class_ = {
"Proxy",
Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(4) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
proxy_Convert,
proxy_Finalize, /* finalize */
NULL, /* checkAccess */
NULL, /* call */
proxy_HasInstance, /* hasInstance */
NULL, /* construct */
ProxyObject::trace, /* trace */
PROXY_CLASS_EXT,
{
proxy_LookupGeneric,
proxy_LookupProperty,
proxy_LookupElement,
proxy_LookupSpecial,
proxy_DefineGeneric,
proxy_DefineProperty,
proxy_DefineElement,
proxy_DefineSpecial,
proxy_GetGeneric,
proxy_GetProperty,
proxy_GetElement,
proxy_GetElementIfPresent,
proxy_GetSpecial,
proxy_SetGeneric,
proxy_SetProperty,
proxy_SetElement,
proxy_SetSpecial,
proxy_GetGenericAttributes,
proxy_SetGenericAttributes,
proxy_DeleteProperty,
proxy_DeleteElement,
proxy_DeleteSpecial,
NULL, /* enumerate */
NULL, /* thisObject */
}
};
#define PROXY_CLASS(callOp, constructOp) { \
"Proxy", \
Class::NON_NATIVE | \
JSCLASS_IMPLEMENTS_BARRIERS | \
JSCLASS_HAS_RESERVED_SLOTS(4) | \
JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy), \
JS_PropertyStub, /* addProperty */ \
JS_DeletePropertyStub, /* delProperty */ \
JS_PropertyStub, /* getProperty */ \
JS_StrictPropertyStub, /* setProperty */ \
JS_EnumerateStub, \
JS_ResolveStub, \
proxy_Convert, \
proxy_Finalize, /* finalize */ \
NULL, /* checkAccess */ \
callOp, /* call */ \
proxy_HasInstance, /* hasInstance */ \
constructOp, /* construct */ \
ProxyObject::trace, /* trace */ \
PROXY_CLASS_EXT, \
{ \
proxy_LookupGeneric, \
proxy_LookupProperty, \
proxy_LookupElement, \
proxy_LookupSpecial, \
proxy_DefineGeneric, \
proxy_DefineProperty, \
proxy_DefineElement, \
proxy_DefineSpecial, \
proxy_GetGeneric, \
proxy_GetProperty, \
proxy_GetElement, \
proxy_GetElementIfPresent, \
proxy_GetSpecial, \
proxy_SetGeneric, \
proxy_SetProperty, \
proxy_SetElement, \
proxy_SetSpecial, \
proxy_GetGenericAttributes, \
proxy_SetGenericAttributes, \
proxy_DeleteProperty, \
proxy_DeleteElement, \
proxy_DeleteSpecial, \
NULL, /* enumerate */ \
NULL, /* thisObject */ \
} \
}
const Class* const js::ObjectProxyClassPtr = &ObjectProxyObject::class_;
const Class js::ProxyObject::uncallableClass_ = PROXY_CLASS(NULL, NULL);
const Class js::ProxyObject::callableClass_ = PROXY_CLASS(proxy_Call, proxy_Construct);
const Class* const js::CallableProxyClassPtr = &ProxyObject::callableClass_;
const Class* const js::UncallableProxyClassPtr = &ProxyObject::uncallableClass_;
const Class js::OuterWindowProxyObject::class_ = {
"Proxy",
@ -3143,71 +3141,6 @@ const Class js::OuterWindowProxyObject::class_ = {
const Class* const js::OuterWindowProxyClassPtr = &OuterWindowProxyObject::class_;
static bool
proxy_Call(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject proxy(cx, &args.callee());
JS_ASSERT(proxy->is<ProxyObject>());
return Proxy::call(cx, proxy, args);
}
static bool
proxy_Construct(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject proxy(cx, &args.callee());
JS_ASSERT(proxy->is<ProxyObject>());
return Proxy::construct(cx, proxy, args);
}
const Class js::FunctionProxyObject::class_ = {
"Proxy",
Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(6),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
proxy_Finalize, /* finalize */
NULL, /* checkAccess */
proxy_Call,
proxy_HasInstance,
proxy_Construct,
proxy_TraceFunction, /* trace */
PROXY_CLASS_EXT,
{
proxy_LookupGeneric,
proxy_LookupProperty,
proxy_LookupElement,
proxy_LookupSpecial,
proxy_DefineGeneric,
proxy_DefineProperty,
proxy_DefineElement,
proxy_DefineSpecial,
proxy_GetGeneric,
proxy_GetProperty,
proxy_GetElement,
proxy_GetElementIfPresent,
proxy_GetSpecial,
proxy_SetGeneric,
proxy_SetProperty,
proxy_SetElement,
proxy_SetSpecial,
proxy_GetGenericAttributes,
proxy_SetGenericAttributes,
proxy_DeleteProperty,
proxy_DeleteElement,
proxy_DeleteSpecial,
NULL, /* enumerate */
NULL, /* thisObject */
}
};
const Class* const js::FunctionProxyClassPtr = &FunctionProxyObject::class_;
/* static */ ProxyObject *
ProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, TaggedProto proto_,
JSObject *parent_, ProxyCallable callable, bool singleton)
@ -3218,11 +3151,11 @@ ProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, Tag
JS_ASSERT_IF(proto.isObject(), cx->compartment() == proto.toObject()->compartment());
JS_ASSERT_IF(parent, cx->compartment() == parent->compartment());
const Class *clasp;
if (callable)
clasp = &FunctionProxyObject::class_;
if (handler->isOuterWindow())
clasp = &OuterWindowProxyObject::class_;
else
clasp = handler->isOuterWindow() ? &OuterWindowProxyObject::class_
: &ObjectProxyObject::class_;
clasp = callable ? &ProxyObject::callableClass_
: &ProxyObject::uncallableClass_;
/*
* Eagerly mark properties unknown for proxies, so we don't try to track
@ -3263,38 +3196,12 @@ js::NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, J
callable, singleton);
}
/* static */ FunctionProxyObject *
FunctionProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv,
JSObject *proto, JSObject *parent, JSObject *callArg,
JSObject *constructArg)
{
RootedObject call(cx, callArg);
RootedObject construct(cx, constructArg);
JS_ASSERT(call || construct);
JS_ASSERT_IF(construct, cx->compartment() == construct->compartment());
JS_ASSERT_IF(call && cx->compartment() != call->compartment(), priv == ObjectValue(*call));
ProxyObject *obj = ProxyObject::New(cx, handler, priv, TaggedProto(proto), parent,
ProxyIsCallable);
if (!obj)
return NULL;
FunctionProxyObject *proxy = &obj->as<FunctionProxyObject>();
if (call)
proxy->initCrossCompartmentSlot(CALL_SLOT, ObjectValue(*call));
if (construct)
proxy->initCrossCompartmentSlot(CONSTRUCT_SLOT, ObjectValue(*construct));
return proxy;
}
void
ProxyObject::renew(JSContext *cx, BaseProxyHandler *handler, Value priv)
{
JS_ASSERT_IF(IsCrossCompartmentWrapper(this), IsDeadProxyObject(this));
JS_ASSERT(getParent() == cx->global());
JS_ASSERT(getClass() == &ObjectProxyObject::class_);
JS_ASSERT(getClass() == &uncallableClass_);
JS_ASSERT(getTaggedProto().isLazy());
#ifdef DEBUG
AutoSuppressGC suppressGC(cx);
@ -3442,6 +3349,6 @@ js_InitProxyClass(JSContext *cx, HandleObject obj)
return NULL;
}
MarkStandardClassInitializedNoProto(obj, &ObjectProxyObject::class_);
MarkStandardClassInitializedNoProto(obj, &ProxyObject::uncallableClass_);
return ctor;
}

View File

@ -278,35 +278,16 @@ class Proxy
static JSObject * const LazyProto;
};
// These are equal to |&{Function,Object,OuterWindow}ProxyObject::class_|. Use
// them in places where you don't want to #include vm/ProxyObject.h.
extern JS_FRIEND_DATA(const js::Class* const) FunctionProxyClassPtr;
extern JS_FRIEND_DATA(const js::Class* const) ObjectProxyClassPtr;
// Use these in places where you don't want to #include vm/ProxyObject.h.
extern JS_FRIEND_DATA(const js::Class* const) CallableProxyClassPtr;
extern JS_FRIEND_DATA(const js::Class* const) UncallableProxyClassPtr;
extern JS_FRIEND_DATA(const js::Class* const) OuterWindowProxyClassPtr;
inline bool IsObjectProxyClass(const Class *clasp)
{
return clasp == ObjectProxyClassPtr || clasp == OuterWindowProxyClassPtr;
}
inline bool IsFunctionProxyClass(const Class *clasp)
{
return clasp == FunctionProxyClassPtr;
}
inline bool IsProxyClass(const Class *clasp)
{
return IsObjectProxyClass(clasp) || IsFunctionProxyClass(clasp);
}
inline bool IsObjectProxy(JSObject *obj)
{
return IsObjectProxyClass(GetObjectClass(obj));
}
inline bool IsFunctionProxy(JSObject *obj)
{
return IsFunctionProxyClass(GetObjectClass(obj));
return clasp == CallableProxyClassPtr ||
clasp == UncallableProxyClassPtr ||
clasp == OuterWindowProxyClassPtr;
}
inline bool IsProxy(JSObject *obj)

View File

@ -44,14 +44,4 @@ ProxyObject::nuke(BaseProxyHandler *handler)
NukeSlot(this, EXTRA_SLOT + 0);
NukeSlot(this, EXTRA_SLOT + 1);
if (is<FunctionProxyObject>())
as<FunctionProxyObject>().nukeExtra();
}
void
FunctionProxyObject::nukeExtra()
{
NukeSlot(this, CALL_SLOT);
NukeSlot(this, CONSTRUCT_SLOT);
}

View File

@ -78,35 +78,12 @@ class ProxyObject : public JSObject
static void trace(JSTracer *trc, JSObject *obj);
void nuke(BaseProxyHandler *handler);
static const Class callableClass_;
static const Class uncallableClass_;
};
class FunctionProxyObject : public ProxyObject
{
static const uint32_t CALL_SLOT = 4;
static const uint32_t CONSTRUCT_SLOT = 5;
public:
static const Class class_;
static FunctionProxyObject *New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv,
JSObject *proto, JSObject *parent, JSObject *call,
JSObject *construct);
HeapSlot &call() { return getSlotRef(CALL_SLOT); }
inline HeapSlot &construct();
inline Value constructOrUndefined() const;
void nukeExtra();
};
class ObjectProxyObject : public ProxyObject
{
public:
static const Class class_;
};
class OuterWindowProxyObject : public ObjectProxyObject
class OuterWindowProxyObject : public ProxyObject
{
public:
static const Class class_;
@ -127,21 +104,4 @@ JSObject::is<js::ProxyObject>() const
return js::IsProxy(const_cast<JSObject*>(this));
}
template<>
inline bool
JSObject::is<js::FunctionProxyObject>() const
{
return js::IsFunctionProxy(const_cast<JSObject*>(this));
}
// WARNING: This function succeeds for ObjectProxyObject *and*
// OuterWindowProxyObject (which is a sub-class). If you want a test that only
// succeeds for ObjectProxyObject, use |hasClass(&ObjectProxyObject::class_)|.
template<>
inline bool
JSObject::is<js::ObjectProxyObject>() const
{
return js::IsObjectProxy(const_cast<JSObject*>(this));
}
#endif /* vm_ProxyObject_h */

View File

@ -1555,9 +1555,9 @@ DebugScopeObject::isForDeclarative() const
}
bool
js_IsDebugScopeSlow(ObjectProxyObject *proxy)
js_IsDebugScopeSlow(ProxyObject *proxy)
{
JS_ASSERT(proxy->hasClass(&ObjectProxyObject::class_));
JS_ASSERT(proxy->hasClass(&ProxyObject::uncallableClass_));
return proxy->handler() == &DebugScopeProxy::singleton;
}

View File

@ -620,7 +620,7 @@ extern JSObject *
GetDebugScopeForFrame(JSContext *cx, AbstractFramePtr frame);
/* Provides debugger access to a scope. */
class DebugScopeObject : public ObjectProxyObject
class DebugScopeObject : public ProxyObject
{
/*
* The enclosing scope on the dynamic scope chain. This slot is analogous
@ -732,11 +732,11 @@ template<>
inline bool
JSObject::is<js::DebugScopeObject>() const
{
extern bool js_IsDebugScopeSlow(js::ObjectProxyObject *proxy);
extern bool js_IsDebugScopeSlow(js::ProxyObject *proxy);
// Note: don't use is<ObjectProxyObject>() here -- it also matches subclasses!
return hasClass(&js::ObjectProxyObject::class_) &&
js_IsDebugScopeSlow(&const_cast<JSObject*>(this)->as<js::ObjectProxyObject>());
// Note: don't use is<ProxyObject>() here -- it also matches subclasses!
return hasClass(&js::ProxyObject::uncallableClass_) &&
js_IsDebugScopeSlow(&const_cast<JSObject*>(this)->as<js::ProxyObject>());
}
template<>