From 8575db2cf132e245bea8fb53e9c95082d1f90c91 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Jun 2013 22:39:22 -0700 Subject: [PATCH] Bug 887558 (part 2) - Move various functions into ProxyObject and FunctionProxyObject. r=jorendorff. --HG-- extra : rebase_source : 14402b9ab7eda3389eb1b812ee961e46067b5b1d --- dom/bindings/BindingUtils.h | 4 +- dom/bindings/DOMJSProxyHandler.cpp | 2 +- dom/bindings/DOMJSProxyHandler.h | 2 +- js/src/ion/BaselineIC.cpp | 33 +-- js/src/ion/BaselineIC.h | 12 +- js/src/ion/IonCaches.cpp | 7 +- js/src/jsapi-tests/testBug604087.cpp | 6 +- js/src/jscompartment.cpp | 6 +- js/src/jsfriendapi.cpp | 3 +- js/src/jsgc.cpp | 22 +- js/src/jsproxy.cpp | 321 ++++++++++++++------------- js/src/jsproxy.h | 24 +- js/src/jsweakmap.cpp | 3 +- js/src/jswrapper.cpp | 36 +-- js/src/moz.build | 1 + js/src/vm/Debugger.cpp | 3 +- js/src/vm/ProxyObject.cpp | 60 +++++ js/src/vm/ProxyObject.h | 76 +++++++ js/src/vm/ScopeObject.cpp | 18 +- 19 files changed, 382 insertions(+), 257 deletions(-) create mode 100644 js/src/vm/ProxyObject.cpp diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index ddb5543ebd3..e0a21134072 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -128,8 +128,8 @@ IsDOMIfaceAndProtoClass(const js::Class* clasp) return IsDOMIfaceAndProtoClass(Jsvalify(clasp)); } -MOZ_STATIC_ASSERT(DOM_OBJECT_SLOT == js::JSSLOT_PROXY_PRIVATE, - "JSSLOT_PROXY_PRIVATE doesn't match DOM_OBJECT_SLOT. " +MOZ_STATIC_ASSERT(DOM_OBJECT_SLOT == js::PROXY_PRIVATE_SLOT, + "js::PROXY_PRIVATE_SLOT doesn't match DOM_OBJECT_SLOT. " "Expect bad things"); template inline T* diff --git a/dom/bindings/DOMJSProxyHandler.cpp b/dom/bindings/DOMJSProxyHandler.cpp index 9988398c9ed..5c356f338b7 100644 --- a/dom/bindings/DOMJSProxyHandler.cpp +++ b/dom/bindings/DOMJSProxyHandler.cpp @@ -63,7 +63,7 @@ struct SetDOMProxyInformation { SetDOMProxyInformation() { js::SetDOMProxyInformation((void*) &HandlerFamily, - js::JSSLOT_PROXY_EXTRA + JSPROXYSLOT_EXPANDO, DOMProxyShadows); + js::PROXY_EXTRA_SLOT + JSPROXYSLOT_EXPANDO, DOMProxyShadows); } }; diff --git a/dom/bindings/DOMJSProxyHandler.h b/dom/bindings/DOMJSProxyHandler.h index 8d52ee468d8..c329a1cb090 100644 --- a/dom/bindings/DOMJSProxyHandler.h +++ b/dom/bindings/DOMJSProxyHandler.h @@ -15,7 +15,7 @@ #include "xpcpublic.h" #include "nsStringGlue.h" -#define DOM_PROXY_OBJECT_SLOT js::JSSLOT_PROXY_PRIVATE +#define DOM_PROXY_OBJECT_SLOT js::PROXY_PRIVATE_SLOT namespace mozilla { namespace dom { diff --git a/js/src/ion/BaselineIC.cpp b/js/src/ion/BaselineIC.cpp index 3878c586c52..25c8280461c 100644 --- a/js/src/ion/BaselineIC.cpp +++ b/js/src/ion/BaselineIC.cpp @@ -3069,7 +3069,7 @@ IsCacheableDOMProxy(JSObject *obj) if (!obj->is()) return false; - BaseProxyHandler *handler = GetProxyHandler(obj); + BaseProxyHandler *handler = obj->as().handler(); if (handler->family() != GetDOMProxyHandlerFamily()) return false; @@ -3101,7 +3101,7 @@ GenerateDOMProxyChecks(JSContext *cx, MacroAssembler &masm, Register object, // 1. The object is a DOMProxy. // 2. The object does not have expando properties, or has an expando // which is known to not have the desired property. - Address handlerAddr(object, JSObject::getFixedSlotOffset(JSSLOT_PROXY_HANDLER)); + Address handlerAddr(object, ProxyObject::offsetOfHandler()); Address expandoAddr(object, JSObject::getFixedSlotOffset(GetDOMProxyExpandoSlot())); // Check that object is a DOMProxy. @@ -5330,8 +5330,9 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, } else { kind = ICStub::GetProp_CallDOMProxyNative; } - ICGetPropCallDOMProxyNativeCompiler compiler(cx, kind, monitorStub, obj, holder, callee, - pc - script->code); + Rooted proxy(cx, &obj->as()); + ICGetPropCallDOMProxyNativeCompiler + compiler(cx, kind, monitorStub, proxy, holder, callee, pc - script->code); newStub = compiler.getStub(compiler.getStubSpace(script)); } else { ICGetProp_CallNative::Compiler compiler(cx, monitorStub, obj, holder, callee, @@ -5350,7 +5351,8 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, JS_ASSERT(obj == holder); IonSpew(IonSpew_BaselineIC, " Generating GetProp(DOMProxyProxy) stub"); - ICGetProp_DOMProxyShadowed::Compiler compiler(cx, monitorStub, obj, name, + Rooted proxy(cx, &obj->as()); + ICGetProp_DOMProxyShadowed::Compiler compiler(cx, monitorStub, proxy, name, pc - script->code); ICStub *newStub = compiler.getStub(compiler.getStubSpace(script)); if (!newStub) @@ -5956,10 +5958,10 @@ ICGetPropCallDOMProxyNativeCompiler::generateStubCode(MacroAssembler &masm) ICStub * ICGetPropCallDOMProxyNativeCompiler::getStub(ICStubSpace *space) { - RootedShape shape(cx, obj_->lastProperty()); + RootedShape shape(cx, proxy_->lastProperty()); RootedShape holderShape(cx, holder_->lastProperty()); - Value expandoSlot = obj_->getFixedSlot(GetDOMProxyExpandoSlot()); + Value expandoSlot = proxy_->getFixedSlot(GetDOMProxyExpandoSlot()); RootedShape expandoShape(cx, NULL); ExpandoAndGeneration *expandoAndGeneration; int32_t generation; @@ -5979,12 +5981,12 @@ ICGetPropCallDOMProxyNativeCompiler::getStub(ICStubSpace *space) if (kind == ICStub::GetProp_CallDOMProxyNative) { return ICGetProp_CallDOMProxyNative::New( - space, getStubCode(), firstMonitorStub_, shape, GetProxyHandler(obj_), + space, getStubCode(), firstMonitorStub_, shape, proxy_->handler(), expandoShape, holder_, holderShape, getter_, pcOffset_); } return ICGetProp_CallDOMProxyWithGenerationNative::New( - space, getStubCode(), firstMonitorStub_, shape, GetProxyHandler(obj_), + space, getStubCode(), firstMonitorStub_, shape, proxy_->handler(), expandoAndGeneration, generation, expandoShape, holder_, holderShape, getter_, pcOffset_); } @@ -5992,9 +5994,9 @@ ICGetPropCallDOMProxyNativeCompiler::getStub(ICStubSpace *space) ICStub * ICGetProp_DOMProxyShadowed::Compiler::getStub(ICStubSpace *space) { - RootedShape shape(cx, obj_->lastProperty()); - return ICGetProp_DOMProxyShadowed::New(space, getStubCode(), firstMonitorStub_, - shape, GetProxyHandler(obj_), name_, pcOffset_); + RootedShape shape(cx, proxy_->lastProperty()); + return ICGetProp_DOMProxyShadowed::New(space, getStubCode(), firstMonitorStub_, shape, + proxy_->handler(), name_, pcOffset_); } static bool @@ -8557,21 +8559,20 @@ ICGetPropCallDOMProxyNativeStub::ICGetPropCallDOMProxyNativeStub(Kind kind, IonC ICGetPropCallDOMProxyNativeCompiler::ICGetPropCallDOMProxyNativeCompiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub, - HandleObject obj, + Handle proxy, HandleObject holder, HandleFunction getter, uint32_t pcOffset) : ICStubCompiler(cx, kind), firstMonitorStub_(firstMonitorStub), - obj_(cx, obj), + proxy_(cx, proxy), holder_(cx, holder), getter_(cx, getter), pcOffset_(pcOffset) { JS_ASSERT(kind == ICStub::GetProp_CallDOMProxyNative || kind == ICStub::GetProp_CallDOMProxyWithGenerationNative); - JS_ASSERT(obj_->is()); - JS_ASSERT(GetProxyHandler(obj_)->family() == GetDOMProxyHandlerFamily()); + JS_ASSERT(proxy_->handler()->family() == GetDOMProxyHandlerFamily()); } ICGetProp_DOMProxyShadowed::ICGetProp_DOMProxyShadowed(IonCode *stubCode, diff --git a/js/src/ion/BaselineIC.h b/js/src/ion/BaselineIC.h index a7ad3c6f1eb..9e9613108a5 100644 --- a/js/src/ion/BaselineIC.h +++ b/js/src/ion/BaselineIC.h @@ -4379,7 +4379,7 @@ class ICGetProp_CallDOMProxyWithGenerationNative : public ICGetPropCallDOMProxyN class ICGetPropCallDOMProxyNativeCompiler : public ICStubCompiler { ICStub *firstMonitorStub_; - RootedObject obj_; + Rooted proxy_; RootedObject holder_; RootedFunction getter_; uint32_t pcOffset_; @@ -4390,7 +4390,7 @@ class ICGetPropCallDOMProxyNativeCompiler : public ICStubCompiler { public: ICGetPropCallDOMProxyNativeCompiler(JSContext *cx, ICStub::Kind kind, - ICStub *firstMonitorStub, HandleObject obj, + ICStub *firstMonitorStub, Handle proxy, HandleObject holder, HandleFunction getter, uint32_t pcOffset); @@ -4444,18 +4444,18 @@ class ICGetProp_DOMProxyShadowed : public ICMonitoredStub class Compiler : public ICStubCompiler { ICStub *firstMonitorStub_; - RootedObject obj_; + Rooted proxy_; RootedPropertyName name_; uint32_t pcOffset_; bool generateStubCode(MacroAssembler &masm); public: - Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj, HandlePropertyName name, - uint32_t pcOffset) + Compiler(JSContext *cx, ICStub *firstMonitorStub, Handle proxy, + HandlePropertyName name, uint32_t pcOffset) : ICStubCompiler(cx, ICStub::GetProp_CallNative), firstMonitorStub_(firstMonitorStub), - obj_(cx, obj), + proxy_(cx, proxy), name_(cx, name), pcOffset_(pcOffset) {} diff --git a/js/src/ion/IonCaches.cpp b/js/src/ion/IonCaches.cpp index 59f79e29cdb..c1397f7fe7a 100644 --- a/js/src/ion/IonCaches.cpp +++ b/js/src/ion/IonCaches.cpp @@ -427,7 +427,7 @@ IsCacheableDOMProxy(JSObject *obj) if (!obj->is()) return false; - BaseProxyHandler *handler = GetProxyHandler(obj); + BaseProxyHandler *handler = obj->as().handler(); if (handler->family() != GetDOMProxyHandlerFamily()) return false; @@ -637,11 +637,12 @@ GenerateDOMProxyChecks(JSContext *cx, MacroAssembler &masm, JSObject *obj, // 1. The object is a DOMProxy. // 2. The object does not have expando properties, or has an expando // which is known to not have the desired property. - Address handlerAddr(object, JSObject::getFixedSlotOffset(JSSLOT_PROXY_HANDLER)); + Address handlerAddr(object, ProxyObject::offsetOfHandler()); Address expandoSlotAddr(object, JSObject::getFixedSlotOffset(GetDOMProxyExpandoSlot())); // Check that object is a DOMProxy. - masm.branchPrivatePtr(Assembler::NotEqual, handlerAddr, ImmWord(GetProxyHandler(obj)), stubFailure); + masm.branchPrivatePtr(Assembler::NotEqual, handlerAddr, + ImmWord(obj->as().handler()), stubFailure); if (skipExpandoCheck) return; diff --git a/js/src/jsapi-tests/testBug604087.cpp b/js/src/jsapi-tests/testBug604087.cpp index 7d99a7c185e..5f72b9aa99b 100644 --- a/js/src/jsapi-tests/testBug604087.cpp +++ b/js/src/jsapi-tests/testBug604087.cpp @@ -72,15 +72,15 @@ BEGIN_TEST(testBug604087) JS::RootedObject c2wrapper(cx, wrap(cx, outerObj, compartment2)); CHECK(c2wrapper); - js::SetProxyExtra(c2wrapper, 0, js::Int32Value(2)); + c2wrapper->as().setExtra(0, js::Int32Value(2)); JS::RootedObject c3wrapper(cx, wrap(cx, outerObj, compartment3)); CHECK(c3wrapper); - js::SetProxyExtra(c3wrapper, 0, js::Int32Value(3)); + c3wrapper->as().setExtra(0, js::Int32Value(3)); JS::RootedObject c4wrapper(cx, wrap(cx, outerObj, compartment4)); CHECK(c4wrapper); - js::SetProxyExtra(c4wrapper, 0, js::Int32Value(4)); + c4wrapper->as().setExtra(0, js::Int32Value(4)); compartment4 = c4wrapper = NULL; JS::RootedObject next(cx); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index cdc27445929..70a633930a4 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -456,15 +456,15 @@ JSCompartment::markCrossCompartmentWrappers(JSTracer *trc) for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { Value v = e.front().value; if (e.front().key.kind == CrossCompartmentKey::ObjectWrapper) { - JSObject *wrapper = &v.toObject(); + ProxyObject *wrapper = &v.toObject().as(); /* * We have a cross-compartment wrapper. Its private pointer may * point into the compartment being collected, so we should mark it. */ - Value referent = GetProxyPrivate(wrapper); + Value referent = wrapper->private_(); MarkValueRoot(trc, &referent, "cross-compartment wrapper"); - JS_ASSERT(referent == GetProxyPrivate(wrapper)); + JS_ASSERT(referent == wrapper->private_()); } } } diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 6d5ffc6d479..1e61d60efcf 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -578,8 +578,7 @@ JS_IsDeadWrapper(JSObject *obj) return false; } - BaseProxyHandler *handler = GetProxyHandler(obj); - return handler->family() == &DeadObjectProxy::sDeadObjectFamily; + return obj->as().handler()->family() == &DeadObjectProxy::sDeadObjectFamily; } void diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 8204dda62c4..c4aa98a6bb0 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -65,6 +65,7 @@ using mozilla::Swap; #include "gc/Marking.h" #include "gc/Memory.h" #include "vm/Debugger.h" +#include "vm/ProxyObject.h" #include "vm/Shape.h" #include "vm/String.h" #include "vm/ForkJoin.h" @@ -3365,20 +3366,19 @@ IsGrayListObject(JSObject *obj) return IsCrossCompartmentWrapper(obj) && !IsDeadProxyObject(obj); } -const unsigned JSSLOT_GC_GRAY_LINK = JSSLOT_PROXY_EXTRA + 1; - -static unsigned -GrayLinkSlot(JSObject *obj) +/* static */ unsigned +ProxyObject::grayLinkSlot(JSObject *obj) { JS_ASSERT(IsGrayListObject(obj)); - return JSSLOT_GC_GRAY_LINK; + return ProxyObject::EXTRA_SLOT + 1; } #ifdef DEBUG static void AssertNotOnGrayList(JSObject *obj) { - JS_ASSERT_IF(IsGrayListObject(obj), obj->getReservedSlot(GrayLinkSlot(obj)).isUndefined()); + JS_ASSERT_IF(IsGrayListObject(obj), + obj->getReservedSlot(ProxyObject::grayLinkSlot(obj)).isUndefined()); } #endif @@ -3386,13 +3386,13 @@ static JSObject * CrossCompartmentPointerReferent(JSObject *obj) { JS_ASSERT(IsGrayListObject(obj)); - return &GetProxyPrivate(obj).toObject(); + return &obj->as().private_().toObject(); } static JSObject * NextIncomingCrossCompartmentPointer(JSObject *prev, bool unlink) { - unsigned slot = GrayLinkSlot(prev); + unsigned slot = ProxyObject::grayLinkSlot(prev); JSObject *next = prev->getReservedSlot(slot).toObjectOrNull(); JS_ASSERT_IF(next, IsGrayListObject(next)); @@ -3408,7 +3408,7 @@ js::DelayCrossCompartmentGrayMarking(JSObject *src) JS_ASSERT(IsGrayListObject(src)); /* Called from MarkCrossCompartmentXXX functions. */ - unsigned slot = GrayLinkSlot(src); + unsigned slot = ProxyObject::grayLinkSlot(src); JSObject *dest = CrossCompartmentPointerReferent(src); JSCompartment *comp = dest->compartment(); @@ -3486,7 +3486,7 @@ RemoveFromGrayList(JSObject *wrapper) if (!IsGrayListObject(wrapper)) return false; - unsigned slot = GrayLinkSlot(wrapper); + unsigned slot = ProxyObject::grayLinkSlot(wrapper); if (wrapper->getReservedSlot(slot).isUndefined()) return false; /* Not on our list. */ @@ -3501,7 +3501,7 @@ RemoveFromGrayList(JSObject *wrapper) } while (obj) { - unsigned slot = GrayLinkSlot(obj); + unsigned slot = ProxyObject::grayLinkSlot(obj); JSObject *next = obj->getReservedSlot(slot).toObjectOrNull(); if (next == wrapper) { obj->setCrossCompartmentSlot(slot, ObjectOrNullValue(tail)); diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index d58838ab57c..691b1eb6f69 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -26,29 +26,6 @@ using namespace js; using namespace js::gc; using mozilla::ArrayLength; -static inline HeapSlot & -GetCall(JSObject *proxy) -{ - JS_ASSERT(proxy->is()); - return proxy->getSlotRef(JSSLOT_PROXY_CALL); -} - -static inline Value -GetConstruct(JSObject *proxy) -{ - if (proxy->slotSpan() <= JSSLOT_PROXY_CONSTRUCT) - return UndefinedValue(); - return proxy->getSlot(JSSLOT_PROXY_CONSTRUCT); -} - -static inline HeapSlot & -GetFunctionProxyConstruct(JSObject *proxy) -{ - JS_ASSERT(proxy->is()); - JS_ASSERT(proxy->slotSpan() > JSSLOT_PROXY_CONSTRUCT); - return proxy->getSlotRef(JSSLOT_PROXY_CONSTRUCT); -} - void js::AutoEnterPolicy::reportError(JSContext *cx, jsid id) { @@ -211,7 +188,7 @@ BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver, } else if ((desc.attrs & JSPROP_SETTER) || desc.setter != JS_StrictPropertyStub) { if (!CallSetter(cx, receiver, id, desc.setter, desc.attrs, desc.shortid, strict, vp)) return false; - if (!proxy->is() || GetProxyHandler(proxy) != this) + if (!proxy->is() || proxy->as().handler() != this) return true; if (desc.attrs & JSPROP_SHARED) return true; @@ -238,7 +215,7 @@ BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver, } else if ((desc.attrs & JSPROP_SETTER) || desc.setter != JS_StrictPropertyStub) { if (!CallSetter(cx, receiver, id, desc.setter, desc.attrs, desc.shortid, strict, vp)) return false; - if (!proxy->is() || GetProxyHandler(proxy) != this) + if (!proxy->is() || proxy->as().handler() != this) return true; if (desc.attrs & JSPROP_SHARED) return true; @@ -392,7 +369,7 @@ DirectProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, Han { assertEnteredPolicy(cx, proxy, id); JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype. - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return JS_GetPropertyDescriptorById(cx, target, id, 0, desc); } @@ -417,7 +394,7 @@ DirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, PropertyDescriptor *desc, unsigned flags) { assertEnteredPolicy(cx, proxy, id); - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return GetOwnPropertyDescriptor(cx, target, id, 0, desc); } @@ -426,7 +403,7 @@ DirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId i PropertyDescriptor *desc) { assertEnteredPolicy(cx, proxy, id); - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); RootedValue v(cx, desc->value); return CheckDefineProperty(cx, target, id, v, desc->getter, desc->setter, desc->attrs) && JS_DefinePropertyById(cx, target, id, v, desc->getter, desc->setter, desc->attrs); @@ -437,7 +414,7 @@ DirectProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props) { assertEnteredPolicy(cx, proxy, JSID_VOID); - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return GetPropertyNames(cx, target, JSITER_OWNONLY | JSITER_HIDDEN, &props); } @@ -445,7 +422,7 @@ bool DirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) { assertEnteredPolicy(cx, proxy, id); - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); RootedValue v(cx); if (!JS_DeletePropertyById2(cx, target, id, v.address())) return false; @@ -462,7 +439,7 @@ DirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy, { assertEnteredPolicy(cx, proxy, JSID_VOID); JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype. - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return GetPropertyNames(cx, target, 0, &props); } @@ -470,7 +447,7 @@ bool DirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args) { assertEnteredPolicy(cx, proxy, JSID_VOID); - RootedValue target(cx, GetProxyPrivate(proxy)); + RootedValue target(cx, proxy->as().private_()); return Invoke(cx, args.thisv(), target, args.length(), args.array(), args.rval()); } @@ -478,7 +455,7 @@ bool DirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const CallArgs &args) { assertEnteredPolicy(cx, proxy, JSID_VOID); - RootedValue target(cx, GetProxyPrivate(proxy)); + RootedValue target(cx, proxy->as().private_()); return InvokeConstructor(cx, target, args.length(), args.array(), args.rval().address()); } @@ -486,7 +463,7 @@ bool DirectProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args) { - args.setThis(ObjectValue(*GetProxyTargetObject(&args.thisv().toObject()))); + args.setThis(ObjectValue(*args.thisv().toObject().as().target())); if (!test(args.thisv())) { ReportIncompatible(cx, args); return false; @@ -501,7 +478,7 @@ DirectProxyHandler::hasInstance(JSContext *cx, HandleObject proxy, MutableHandle { assertEnteredPolicy(cx, proxy, JSID_VOID); JSBool b; - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); if (!JS_HasInstance(cx, target, v, &b)) return false; *bp = !!b; @@ -513,15 +490,15 @@ bool DirectProxyHandler::objectClassIs(HandleObject proxy, ESClassValue classValue, JSContext *cx) { - RootedObject obj(cx, GetProxyTargetObject(proxy)); - return ObjectClassIs(obj, classValue, cx); + RootedObject target(cx, proxy->as().target()); + return ObjectClassIs(target, classValue, cx); } const char * DirectProxyHandler::className(JSContext *cx, HandleObject proxy) { assertEnteredPolicy(cx, proxy, JSID_VOID); - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return JSObject::className(cx, target); } @@ -530,7 +507,7 @@ DirectProxyHandler::fun_toString(JSContext *cx, HandleObject proxy, unsigned indent) { assertEnteredPolicy(cx, proxy, JSID_VOID); - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return fun_toStringHelper(cx, target, indent); } @@ -538,7 +515,7 @@ bool DirectProxyHandler::regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) { - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return RegExpToShared(cx, target, g); } @@ -546,7 +523,7 @@ bool DirectProxyHandler::defaultValue(JSContext *cx, HandleObject proxy, JSType hint, MutableHandleValue vp) { - vp.set(ObjectValue(*GetProxyTargetObject(proxy))); + vp.set(ObjectValue(*proxy->as().target())); if (hint == JSTYPE_VOID) return ToPrimitive(cx, vp); return ToPrimitive(cx, hint, vp); @@ -569,7 +546,7 @@ DirectProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp assertEnteredPolicy(cx, proxy, id); JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype. JSBool found; - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); if (!JS_HasPropertyById(cx, target, id, &found)) return false; *bp = !!found; @@ -580,7 +557,7 @@ bool DirectProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) { assertEnteredPolicy(cx, proxy, id); - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); AutoPropertyDescriptorRooter desc(cx); if (!JS_GetPropertyDescriptorById(cx, target, id, 0, &desc)) return false; @@ -593,7 +570,7 @@ DirectProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver HandleId id, MutableHandleValue vp) { assertEnteredPolicy(cx, proxy, id); - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return JSObject::getGeneric(cx, target, receiver, id, vp); } @@ -602,7 +579,7 @@ DirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver HandleId id, bool strict, MutableHandleValue vp) { assertEnteredPolicy(cx, proxy, id); - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return JSObject::setGeneric(cx, target, receiver, id, vp, strict); } @@ -610,7 +587,7 @@ bool DirectProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) { assertEnteredPolicy(cx, proxy, JSID_VOID); - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return GetPropertyNames(cx, target, JSITER_OWNONLY, &props); } @@ -620,21 +597,21 @@ DirectProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags, { assertEnteredPolicy(cx, proxy, JSID_VOID); JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype. - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return GetIterator(cx, target, flags, vp); } bool DirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) { - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return JSObject::isExtensible(cx, target, extensible); } bool DirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy) { - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); return JSObject::preventExtensions(cx, target); } @@ -757,6 +734,21 @@ 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); +} + /* Derived class for all scripted indirect proxy handlers. */ class ScriptedIndirectProxyHandler : public BaseProxyHandler { @@ -845,7 +837,7 @@ ReturnedValueMustNotBePrimitive(JSContext *cx, HandleObject proxy, JSAtom *atom, static JSObject * GetIndirectProxyHandlerObject(JSObject *proxy) { - return GetProxyPrivate(proxy).toObjectOrNull(); + return proxy->as().private_().toObjectOrNull(); } bool @@ -1013,7 +1005,7 @@ bool ScriptedIndirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args) { assertEnteredPolicy(cx, proxy, JSID_VOID); - RootedValue call(cx, GetCall(proxy)); + RootedValue call(cx, proxy->as().call()); return Invoke(cx, args.thisv(), call, args.length(), args.array(), args.rval()); } @@ -1021,9 +1013,9 @@ bool ScriptedIndirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const CallArgs &args) { assertEnteredPolicy(cx, proxy, JSID_VOID); - RootedValue fval(cx, GetConstruct(proxy)); + RootedValue fval(cx, proxy->as().constructOrUndefined()); if (fval.isUndefined()) - fval = GetCall(proxy); + fval = proxy->as().call(); return InvokeConstructor(cx, fval, args.length(), args.array(), args.rval().address()); } @@ -1038,9 +1030,8 @@ JSString * ScriptedIndirectProxyHandler::fun_toString(JSContext *cx, HandleObject proxy, unsigned indent) { assertEnteredPolicy(cx, proxy, JSID_VOID); - Value fval = GetCall(proxy); - if (proxy->is() && - (fval.isPrimitive() || !fval.toObject().is())) { + Value fval = proxy->as().call(); + if (fval.isPrimitive() || !fval.toObject().is()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, js_Function_str, js_toString_str, @@ -1067,7 +1058,7 @@ ScriptedIndirectProxyHandler ScriptedIndirectProxyHandler::singleton; static JSObject * GetDirectProxyHandlerObject(JSObject *proxy) { - return GetProxyExtra(proxy, 0).toObjectOrNull(); + return proxy->as().extra(0).toObjectOrNull(); } /* Derived class for all scripted direct proxy handlers. */ @@ -1355,7 +1346,7 @@ TrapGetOwnProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHandle RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 2 - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step 3 RootedValue trap(cx); @@ -1463,7 +1454,7 @@ TrapDefineOwnProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHan RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 2 - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step 3 RootedValue trap(cx); @@ -1668,7 +1659,7 @@ ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy) RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step b - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step c RootedValue trap(cx); @@ -1770,7 +1761,7 @@ ScriptedDirectProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject prox RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step b - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step c RootedValue trap(cx); @@ -1808,7 +1799,7 @@ ScriptedDirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 2 - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step 3 RootedValue trap(cx); @@ -1860,7 +1851,7 @@ ScriptedDirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdV RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step b - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step c RootedValue trap(cx); @@ -1903,7 +1894,7 @@ ScriptedDirectProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 2 - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step 3 RootedValue trap(cx); @@ -1966,7 +1957,7 @@ ScriptedDirectProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId i RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 2 - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step 3 RootedValue trap(cx); @@ -2043,7 +2034,7 @@ ScriptedDirectProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 2 - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step 3 RootedValue trap(cx); @@ -2112,7 +2103,7 @@ ScriptedDirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 2 - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step 3 RootedValue trap(cx); @@ -2180,7 +2171,7 @@ ScriptedDirectProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step b - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); // step c RootedValue trap(cx); @@ -2229,7 +2220,7 @@ ScriptedDirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallAr RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 2 - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); /* * NB: Remember to throw a TypeError here if we change NewProxyObject so that this trap can get @@ -2267,7 +2258,7 @@ ScriptedDirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const C RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); // step 2 - RootedObject target(cx, GetProxyTargetObject(proxy)); + RootedObject target(cx, proxy->as().target()); /* * NB: Remember to throw a TypeError here if we change NewProxyObject so that this trap can get @@ -2315,7 +2306,7 @@ Proxy::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, PropertyDescriptor *desc, unsigned flags) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); desc->obj = NULL; // default result if we refuse to perform this action AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true); if (!policy.allowed()) @@ -2348,7 +2339,7 @@ Proxy::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); desc->obj = NULL; // default result if we refuse to perform this action AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true); if (!policy.allowed()) @@ -2372,11 +2363,11 @@ bool Proxy::defineProperty(JSContext *cx, HandleObject proxy, HandleId id, PropertyDescriptor *desc) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true); if (!policy.allowed()) return policy.returnValue(); - return GetProxyHandler(proxy)->defineProperty(cx, proxy, id, desc); + return proxy->as().handler()->defineProperty(cx, proxy, id, desc); } bool @@ -2392,23 +2383,23 @@ bool Proxy::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, BaseProxyHandler::GET, true); if (!policy.allowed()) return policy.returnValue(); - return GetProxyHandler(proxy)->getOwnPropertyNames(cx, proxy, props); + return proxy->as().handler()->getOwnPropertyNames(cx, proxy, props); } bool Proxy::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); *bp = true; // default result if we refuse to perform this action AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true); if (!policy.allowed()) return policy.returnValue(); - return GetProxyHandler(proxy)->delete_(cx, proxy, id, bp); + return proxy->as().handler()->delete_(cx, proxy, id, bp); } JS_FRIEND_API(bool) @@ -2435,12 +2426,12 @@ bool Proxy::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, BaseProxyHandler::GET, true); if (!policy.allowed()) return policy.returnValue(); if (!handler->hasPrototype()) - return GetProxyHandler(proxy)->enumerate(cx, proxy, props); + return proxy->as().handler()->enumerate(cx, proxy, props); if (!handler->keys(cx, proxy, props)) return false; AutoIdVector protoProps(cx); @@ -2453,7 +2444,7 @@ bool Proxy::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); *bp = false; // default result if we refuse to perform this action AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true); if (!policy.allowed()) @@ -2474,7 +2465,7 @@ bool Proxy::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); *bp = false; // default result if we refuse to perform this action AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true); if (!policy.allowed()) @@ -2487,7 +2478,7 @@ Proxy::get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id MutableHandleValue vp) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); vp.setUndefined(); // default result if we refuse to perform this action AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true); if (!policy.allowed()) @@ -2514,7 +2505,7 @@ Proxy::getElementIfPresent(JSContext *cx, HandleObject proxy, HandleObject recei if (!IndexToId(cx, index, &id)) return false; - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true); if (!policy.allowed()) return policy.returnValue(); @@ -2530,7 +2521,7 @@ Proxy::getElementIfPresent(JSContext *cx, HandleObject proxy, HandleObject recei if (hasOwn) { *present = true; - return GetProxyHandler(proxy)->get(cx, proxy, receiver, id, vp); + return proxy->as().handler()->get(cx, proxy, receiver, id, vp); } *present = false; @@ -2543,7 +2534,7 @@ Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id MutableHandleValue vp) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true); if (!policy.allowed()) return policy.returnValue(); @@ -2573,7 +2564,7 @@ bool Proxy::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, BaseProxyHandler::GET, true); if (!policy.allowed()) return policy.returnValue(); @@ -2584,7 +2575,7 @@ bool Proxy::iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); vp.setUndefined(); // default result if we refuse to perform this action if (!handler->hasPrototype()) { AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, @@ -2612,14 +2603,14 @@ bool Proxy::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) { JS_CHECK_RECURSION(cx, return false); - return GetProxyHandler(proxy)->isExtensible(cx, proxy, extensible); + return proxy->as().handler()->isExtensible(cx, proxy, extensible); } bool Proxy::preventExtensions(JSContext *cx, HandleObject proxy) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); return handler->preventExtensions(cx, proxy); } @@ -2627,7 +2618,7 @@ bool Proxy::call(JSContext *cx, HandleObject proxy, const CallArgs &args) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); // Because vp[0] is JS_CALLEE on the way in and JS_RVAL on the way out, we // can only set our default value once we're sure that we're not calling the @@ -2646,7 +2637,7 @@ bool Proxy::construct(JSContext *cx, HandleObject proxy, const CallArgs &args) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); // Because vp[0] is JS_CALLEE on the way in and JS_RVAL on the way out, we // can only set our default value once we're sure that we're not calling the @@ -2669,33 +2660,33 @@ Proxy::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArg // Note - we don't enter a policy here because our security architecture // guards against nativeCall by overriding the trap itself in the right // circumstances. - return GetProxyHandler(proxy)->nativeCall(cx, test, impl, args); + return proxy->as().handler()->nativeCall(cx, test, impl, args); } bool Proxy::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp) { JS_CHECK_RECURSION(cx, return false); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); *bp = false; // default result if we refuse to perform this action AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, BaseProxyHandler::GET, true); if (!policy.allowed()) return policy.returnValue(); - return GetProxyHandler(proxy)->hasInstance(cx, proxy, v, bp); + return proxy->as().handler()->hasInstance(cx, proxy, v, bp); } bool Proxy::objectClassIs(HandleObject proxy, ESClassValue classValue, JSContext *cx) { JS_CHECK_RECURSION(cx, return false); - return GetProxyHandler(proxy)->objectClassIs(proxy, classValue, cx); + return proxy->as().handler()->objectClassIs(proxy, classValue, cx); } const char * Proxy::className(JSContext *cx, HandleObject proxy) { JS_CHECK_RECURSION(cx, return NULL); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, BaseProxyHandler::GET, /* mayThrow = */ false); // Do the safe thing if the policy rejects. @@ -2709,7 +2700,7 @@ JSString * Proxy::fun_toString(JSContext *cx, HandleObject proxy, unsigned indent) { JS_CHECK_RECURSION(cx, return NULL); - BaseProxyHandler *handler = GetProxyHandler(proxy); + BaseProxyHandler *handler = proxy->as().handler(); AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, BaseProxyHandler::GET, /* mayThrow = */ false); // Do the safe thing if the policy rejects. @@ -2726,21 +2717,21 @@ bool Proxy::regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) { JS_CHECK_RECURSION(cx, return false); - return GetProxyHandler(proxy)->regexp_toShared(cx, proxy, g); + return proxy->as().handler()->regexp_toShared(cx, proxy, g); } bool Proxy::defaultValue(JSContext *cx, HandleObject proxy, JSType hint, MutableHandleValue vp) { JS_CHECK_RECURSION(cx, return false); - return GetProxyHandler(proxy)->defaultValue(cx, proxy, hint, vp); + return proxy->as().handler()->defaultValue(cx, proxy, hint, vp); } bool Proxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject proto) { JS_CHECK_RECURSION(cx, return false); - return GetProxyHandler(proxy)->getPrototypeOf(cx, proxy, proto); + return proxy->as().handler()->getPrototypeOf(cx, proxy, proto); } JSObject * const Proxy::LazyProto = reinterpret_cast(0x1); @@ -2748,7 +2739,7 @@ JSObject * const Proxy::LazyProto = reinterpret_cast(0x1); static JSObject * proxy_innerObject(JSContext *cx, HandleObject obj) { - return GetProxyPrivate(obj).toObjectOrNull(); + return obj->as().private_().toObjectOrNull(); } static JSBool @@ -3008,52 +2999,55 @@ proxy_DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, JSBool return proxy_DeleteGeneric(cx, obj, id, succeeded); } -static void -proxy_TraceObject(JSTracer *trc, JSObject *obj) +/* static */ void +ProxyObject::trace(JSTracer *trc, JSObject *obj) { + ProxyObject *proxy = &obj->as(); + #ifdef DEBUG - if (!trc->runtime->gcDisableStrictProxyCheckingCount && obj->isWrapper()) { - JSObject *referent = &GetProxyPrivate(obj).toObject(); - if (referent->compartment() != obj->compartment()) { + if (!trc->runtime->gcDisableStrictProxyCheckingCount && proxy->isWrapper()) { + JSObject *referent = &proxy->private_().toObject(); + if (referent->compartment() != proxy->compartment()) { /* * Assert that this proxy is tracked in the wrapper map. We maintain * the invariant that the wrapped object is the key in the wrapper map. */ Value key = ObjectValue(*referent); - WrapperMap::Ptr p = obj->compartment()->lookupWrapper(key); - JS_ASSERT(*p->value.unsafeGet() == ObjectValue(*obj)); + WrapperMap::Ptr p = proxy->compartment()->lookupWrapper(key); + JS_ASSERT(*p->value.unsafeGet() == ObjectValue(*proxy)); } } #endif - // NB: If you add new slots here, make sure to change - // js::NukeChromeCrossCompartmentWrappers to cope. - MarkCrossCompartmentSlot(trc, obj, &obj->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "private"); - MarkSlot(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 0), "extra0"); + // Note: If you add new slots here, make sure to change + // nuke() to cope. + MarkCrossCompartmentSlot(trc, obj, proxy->slotOfPrivate(), "private"); + MarkSlot(trc, proxy->slotOfExtra(0), "extra0"); /* * The GC can use the second reserved slot to link the cross compartment * wrappers into a linked list, in which case we don't want to trace it. */ - if (!IsCrossCompartmentWrapper(obj)) - MarkSlot(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 1), "extra1"); + if (!IsCrossCompartmentWrapper(proxy)) + 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 - // js::NukeChromeCrossCompartmentWrappers to cope. - MarkCrossCompartmentSlot(trc, obj, &GetCall(obj), "call"); - MarkSlot(trc, &GetFunctionProxyConstruct(obj), "construct"); - proxy_TraceObject(trc, obj); + // nuke() to cope. + FunctionProxyObject *proxy = &obj->as(); + MarkCrossCompartmentSlot(trc, proxy, &proxy->call(), "call"); + MarkSlot(trc, &proxy->construct(), "construct"); + ProxyObject::trace(trc, proxy); } static JSObject * proxy_WeakmapKeyDelegate(JSObject *obj) { JS_ASSERT(obj->is()); - return GetProxyHandler(obj)->weakmapKeyDelegate(obj); + return obj->as().handler()->weakmapKeyDelegate(obj); } static JSBool @@ -3067,7 +3061,7 @@ static void proxy_Finalize(FreeOp *fop, JSObject *obj) { JS_ASSERT(obj->is()); - GetProxyHandler(obj)->finalize(fop, obj); + obj->as().handler()->finalize(fop, obj); } static JSBool @@ -3105,7 +3099,7 @@ Class js::ObjectProxyObject::class_ = { NULL, /* call */ proxy_HasInstance, /* hasInstance */ NULL, /* construct */ - proxy_TraceObject, /* trace */ + ProxyObject::trace, /* trace */ PROXY_CLASS_EXT, { proxy_LookupGeneric, @@ -3158,7 +3152,7 @@ Class js::OuterWindowProxyObject::class_ = { NULL, /* call */ NULL, /* hasInstance */ NULL, /* construct */ - proxy_TraceObject, /* trace */ + ProxyObject::trace, /* trace */ { NULL, /* outerObject */ proxy_innerObject, @@ -3273,9 +3267,9 @@ Class js::FunctionProxyObject::class_ = { JS_FRIEND_DATA(Class*) js::FunctionProxyClassPtr = &FunctionProxyObject::class_; -static JSObject * -NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, TaggedProto proto_, - JSObject *parent_, ProxyCallable callable) +/* static */ ProxyObject * +ProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, TaggedProto proto_, + JSObject *parent_, ProxyCallable callable) { Rooted proto(cx, proto_); RootedObject parent(cx, parent_); @@ -3308,65 +3302,77 @@ NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, Tagge RootedObject obj(cx, NewObjectWithGivenProto(cx, clasp, proto, parent, allocKind, newKind)); if (!obj) return NULL; - obj->initSlot(JSSLOT_PROXY_HANDLER, PrivateValue(handler)); - obj->initCrossCompartmentSlot(JSSLOT_PROXY_PRIVATE, priv); + + Rooted proxy(cx, &obj->as()); + proxy->initHandler(handler); + proxy->initCrossCompartmentPrivate(priv); /* Don't track types of properties of proxies. */ if (newKind != SingletonObject) - MarkTypeObjectUnknownProperties(cx, obj->type()); + MarkTypeObjectUnknownProperties(cx, proxy->type()); - return obj; + return proxy; } JS_FRIEND_API(JSObject *) js::NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, JSObject *proto_, JSObject *parent_, ProxyCallable callable) { - return NewProxyObject(cx, handler, priv, TaggedProto(proto_), parent_, callable); + return ProxyObject::New(cx, handler, priv, TaggedProto(proto_), parent_, callable); } -static JSObject * -NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, JSObject *proto_, - JSObject *parent_, JSObject *call_, JSObject *construct_) +static ProxyObject * +NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, JSObject *proto, + JSObject *parent, JSObject *call, JSObject *construct) { - RootedObject call(cx, call_); - RootedObject construct(cx, construct_); + if (!call && !construct) + return ProxyObject::New(cx, handler, priv, TaggedProto(proto), parent, ProxyNotCallable); + return FunctionProxyObject::New(cx, handler, priv, proto, parent, call, construct); +} + +/* 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)); - JSObject *proxy = NewProxyObject(cx, handler, priv, TaggedProto(proto_), parent_, - call || construct ? ProxyIsCallable : ProxyNotCallable); - if (!proxy) + ProxyObject *obj = ProxyObject::New(cx, handler, priv, TaggedProto(proto), parent, + ProxyIsCallable); + if (!obj) return NULL; + FunctionProxyObject *proxy = &obj->as(); if (call) - proxy->initCrossCompartmentSlot(JSSLOT_PROXY_CALL, ObjectValue(*call)); + proxy->initCrossCompartmentSlot(CALL_SLOT, ObjectValue(*call)); if (construct) - proxy->initCrossCompartmentSlot(JSSLOT_PROXY_CONSTRUCT, ObjectValue(*construct)); + proxy->initCrossCompartmentSlot(CONSTRUCT_SLOT, ObjectValue(*construct)); return proxy; } -JSObject * -js::RenewProxyObject(JSContext *cx, JSObject *obj, - BaseProxyHandler *handler, Value priv) +void +ProxyObject::renew(JSContext *cx, BaseProxyHandler *handler, Value priv) { - JS_ASSERT_IF(IsCrossCompartmentWrapper(obj), IsDeadProxyObject(obj)); - JS_ASSERT(obj->getParent() == cx->global()); - JS_ASSERT(obj->getClass() == &ObjectProxyObject::class_); - JS_ASSERT(obj->getTaggedProto().isLazy()); + JS_ASSERT_IF(IsCrossCompartmentWrapper(this), IsDeadProxyObject(this)); + JS_ASSERT(getParent() == cx->global()); + JS_ASSERT(getClass() == &ObjectProxyObject::class_); + JS_ASSERT(getTaggedProto().isLazy()); #ifdef DEBUG AutoSuppressGC suppressGC(cx); JS_ASSERT(!handler->isOuterWindow()); #endif - obj->setSlot(JSSLOT_PROXY_HANDLER, PrivateValue(handler)); - obj->setCrossCompartmentSlot(JSSLOT_PROXY_PRIVATE, priv); - obj->setSlot(JSSLOT_PROXY_EXTRA + 0, UndefinedValue()); - obj->setSlot(JSSLOT_PROXY_EXTRA + 1, UndefinedValue()); - - return obj; + setSlot(HANDLER_SLOT, PrivateValue(handler)); + setCrossCompartmentSlot(PRIVATE_SLOT, priv); + setSlot(EXTRA_SLOT + 0, UndefinedValue()); + setSlot(EXTRA_SLOT + 1, UndefinedValue()); } static JSBool @@ -3389,12 +3395,11 @@ proxy(JSContext *cx, unsigned argc, jsval *vp) return false; RootedObject fun(cx, target->isCallable() ? target.get() : (JSObject *) NULL); RootedValue priv(cx, ObjectValue(*target)); - JSObject *proxy = NewProxyObject(cx, &ScriptedDirectProxyHandler::singleton, - priv, proto, cx->global(), - fun, fun); + ProxyObject *proxy = NewProxyObject(cx, &ScriptedDirectProxyHandler::singleton, + priv, proto, cx->global(), fun, fun); if (!proxy) return false; - SetProxyExtra(proxy, 0, ObjectOrNullValue(handler)); + proxy->setExtra(0, ObjectOrNullValue(handler)); vp->setObject(*proxy); return true; } diff --git a/js/src/jsproxy.h b/js/src/jsproxy.h index 9fea610772d..56868a05c3c 100644 --- a/js/src/jsproxy.h +++ b/js/src/jsproxy.h @@ -287,32 +287,30 @@ inline bool IsProxy(JSObject *obj) return IsProxyClass(GetObjectClass(obj)); } -/* Shared between object and function proxies. */ /* - * NOTE: JSSLOT_PROXY_PRIVATE is 0, because that way slot 0 is usable by API + * These are part of the API. + * + * NOTE: PROXY_PRIVATE_SLOT is 0 because that way slot 0 is usable by API * clients for both proxy and non-proxy objects. So an API client that only * needs to store one slot's worth of data doesn't need to branch on what sort * of object it has. */ -const uint32_t JSSLOT_PROXY_PRIVATE = 0; -const uint32_t JSSLOT_PROXY_HANDLER = 1; -const uint32_t JSSLOT_PROXY_EXTRA = 2; -/* Function proxies only. */ -const uint32_t JSSLOT_PROXY_CALL = 4; -const uint32_t JSSLOT_PROXY_CONSTRUCT = 5; +const uint32_t PROXY_PRIVATE_SLOT = 0; +const uint32_t PROXY_HANDLER_SLOT = 1; +const uint32_t PROXY_EXTRA_SLOT = 2; inline BaseProxyHandler * GetProxyHandler(JSObject *obj) { JS_ASSERT(IsProxy(obj)); - return (BaseProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate(); + return (BaseProxyHandler *) GetReservedSlot(obj, PROXY_HANDLER_SLOT).toPrivate(); } inline const Value & GetProxyPrivate(JSObject *obj) { JS_ASSERT(IsProxy(obj)); - return GetReservedSlot(obj, JSSLOT_PROXY_PRIVATE); + return GetReservedSlot(obj, PROXY_PRIVATE_SLOT); } inline JSObject * @@ -326,14 +324,14 @@ inline const Value & GetProxyExtra(JSObject *obj, size_t n) { JS_ASSERT(IsProxy(obj)); - return GetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n); + return GetReservedSlot(obj, PROXY_EXTRA_SLOT + n); } inline void SetProxyHandler(JSObject *obj, BaseProxyHandler *handler) { JS_ASSERT(IsProxy(obj)); - SetReservedSlot(obj, JSSLOT_PROXY_HANDLER, PrivateValue(handler)); + SetReservedSlot(obj, PROXY_HANDLER_SLOT, PrivateValue(handler)); } inline void @@ -341,7 +339,7 @@ SetProxyExtra(JSObject *obj, size_t n, const Value &extra) { JS_ASSERT(IsProxy(obj)); JS_ASSERT(n <= 1); - SetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n, extra); + SetReservedSlot(obj, PROXY_EXTRA_SLOT + n, extra); } enum ProxyCallable { diff --git a/js/src/jsweakmap.cpp b/js/src/jsweakmap.cpp index 879a7f30c2f..c292cfcbef4 100644 --- a/js/src/jsweakmap.cpp +++ b/js/src/jsweakmap.cpp @@ -258,7 +258,8 @@ TryPreserveReflector(JSContext *cx, HandleObject obj) { if (obj->getClass()->ext.isWrappedNative || (obj->getClass()->flags & JSCLASS_IS_DOMJSCLASS) || - (obj->is() && GetProxyHandler(obj)->family() == GetDOMProxyHandlerFamily())) + (obj->is() && + obj->as().handler()->family() == GetDOMProxyHandlerFamily())) { JS_ASSERT(cx->runtime()->preserveWrapperCallback); if (!cx->runtime()->preserveWrapperCallback(cx, obj)) { diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index b374e940c0f..957bef4b481 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -47,21 +47,22 @@ JSObject * Wrapper::Renew(JSContext *cx, JSObject *existing, JSObject *obj, Wrapper *handler) { JS_ASSERT(!obj->isCallable()); - return RenewProxyObject(cx, existing, handler, ObjectValue(*obj)); + existing->as().renew(cx, handler, ObjectValue(*obj)); + return existing; } Wrapper * Wrapper::wrapperHandler(JSObject *wrapper) { JS_ASSERT(wrapper->isWrapper()); - return static_cast(GetProxyHandler(wrapper)); + return static_cast(wrapper->as().handler()); } JSObject * Wrapper::wrappedObject(JSObject *wrapper) { JS_ASSERT(wrapper->isWrapper()); - return GetProxyTargetObject(wrapper); + return wrapper->as().target(); } JS_FRIEND_API(JSObject *) @@ -71,7 +72,7 @@ js::UncheckedUnwrap(JSObject *wrapped, bool stopAtOuter, unsigned *flagsp) while (wrapped->isWrapper() && !JS_UNLIKELY(stopAtOuter && wrapped->getClass()->ext.innerObject)) { flags |= Wrapper::wrapperHandler(wrapped)->flags(); - wrapped = GetProxyPrivate(wrapped).toObjectOrNull(); + wrapped = wrapped->as().private_().toObjectOrNull(); } if (flagsp) *flagsp = flags; @@ -836,20 +837,8 @@ js::NewDeadProxyObject(JSContext *cx, JSObject *parent) bool js::IsDeadProxyObject(JSObject *obj) { - return obj->is() && GetProxyHandler(obj) == &DeadObjectProxy::singleton; -} - -static void -NukeSlot(JSObject *wrapper, uint32_t slot, Value v) -{ - Value old = wrapper->getSlot(slot); - if (old.isMarkable()) { - Zone *zone = ZoneOfValue(old); - AutoMarkInDeadZone amd(zone); - wrapper->setReservedSlot(slot, v); - } else { - wrapper->setReservedSlot(slot, v); - } + return obj->is() && + obj->as().handler() == &DeadObjectProxy::singleton; } void @@ -859,16 +848,7 @@ js::NukeCrossCompartmentWrapper(JSContext *cx, JSObject *wrapper) NotifyGCNukeWrapper(wrapper); - NukeSlot(wrapper, JSSLOT_PROXY_PRIVATE, NullValue()); - SetProxyHandler(wrapper, &DeadObjectProxy::singleton); - - if (wrapper->is()) { - NukeSlot(wrapper, JSSLOT_PROXY_CALL, NullValue()); - NukeSlot(wrapper, JSSLOT_PROXY_CONSTRUCT, NullValue()); - } - - NukeSlot(wrapper, JSSLOT_PROXY_EXTRA + 0, NullValue()); - NukeSlot(wrapper, JSSLOT_PROXY_EXTRA + 1, NullValue()); + wrapper->as().nuke(&DeadObjectProxy::singleton); JS_ASSERT(IsDeadProxyObject(wrapper)); } diff --git a/js/src/moz.build b/js/src/moz.build index 94e584b20d2..f412f875b79 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -112,6 +112,7 @@ CPP_SOURCES += [ 'Probes.cpp', 'Profilers.cpp', 'PropertyKey.cpp', + 'ProxyObject.cpp', 'RegExp.cpp', 'RegExpObject.cpp', 'RegExpStatics.cpp', diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 7f63f050f99..1fbf2bcac63 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -2099,7 +2099,8 @@ Debugger::construct(JSContext *cx, unsigned argc, Value *vp) /* Add the initial debuggees, if any. */ for (unsigned i = 0; i < argc; i++) { - Rooted debuggee(cx, &GetProxyPrivate(&args[i].toObject()).toObject().global()); + Rooted + debuggee(cx, &args[i].toObject().as().private_().toObject().global()); if (!dbg->addDebuggeeGlobal(cx, debuggee)) return false; } diff --git a/js/src/vm/ProxyObject.cpp b/js/src/vm/ProxyObject.cpp new file mode 100644 index 00000000000..8ed37f860d1 --- /dev/null +++ b/js/src/vm/ProxyObject.cpp @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "vm/ProxyObject.h" + +#include "jsgcinlines.h" +#include "jsobjinlines.h" + +#include "gc/Barrier-inl.h" +#include "vm/ObjectImpl-inl.h" + +using namespace js; + +void +ProxyObject::initCrossCompartmentPrivate(HandleValue priv) +{ + initCrossCompartmentSlot(PRIVATE_SLOT, priv); +} + +void +ProxyObject::initHandler(BaseProxyHandler *handler) +{ + initSlot(HANDLER_SLOT, PrivateValue(handler)); +} + +static void +NukeSlot(ProxyObject *proxy, uint32_t slot) +{ + Value old = proxy->getSlot(slot); + if (old.isMarkable()) { + Zone *zone = ZoneOfValue(old); + AutoMarkInDeadZone amd(zone); + proxy->setReservedSlot(slot, NullValue()); + } else { + proxy->setReservedSlot(slot, NullValue()); + } +} + +void +ProxyObject::nuke(BaseProxyHandler *handler) +{ + NukeSlot(this, PRIVATE_SLOT); + setHandler(handler); + + NukeSlot(this, EXTRA_SLOT + 0); + NukeSlot(this, EXTRA_SLOT + 1); + + if (is()) + as().nukeExtra(); +} + +void +FunctionProxyObject::nukeExtra() +{ + NukeSlot(this, CALL_SLOT); + NukeSlot(this, CONSTRUCT_SLOT); +} diff --git a/js/src/vm/ProxyObject.h b/js/src/vm/ProxyObject.h index aab81bb35a9..c939d4ace32 100644 --- a/js/src/vm/ProxyObject.h +++ b/js/src/vm/ProxyObject.h @@ -16,12 +16,88 @@ namespace js { // instantiated. class ProxyObject : public JSObject { + // These are just local renamings of the slot constants that are part of + // the API in jsproxy.h. + static const uint32_t PRIVATE_SLOT = PROXY_PRIVATE_SLOT; + static const uint32_t HANDLER_SLOT = PROXY_HANDLER_SLOT; + static const uint32_t EXTRA_SLOT = PROXY_EXTRA_SLOT; + + public: + static ProxyObject *New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, + TaggedProto proto_, JSObject *parent_, ProxyCallable callable); + + const Value &private_() { + return GetReservedSlot(this, PRIVATE_SLOT); + } + + void initCrossCompartmentPrivate(HandleValue priv); + + HeapSlot *slotOfPrivate() { + return &getReservedSlotRef(PRIVATE_SLOT); + } + + JSObject *target() const { + return const_cast(this)->private_().toObjectOrNull(); + } + + BaseProxyHandler *handler() { + return static_cast(GetReservedSlot(this, HANDLER_SLOT).toPrivate()); + } + + void initHandler(BaseProxyHandler *handler); + + void setHandler(BaseProxyHandler *handler) { + SetReservedSlot(this, HANDLER_SLOT, PrivateValue(handler)); + } + + static size_t offsetOfHandler() { + return getFixedSlotOffset(HANDLER_SLOT); + } + + const Value &extra(size_t n) const { + JS_ASSERT(n == 0 || n == 1); + return GetReservedSlot(const_cast(this), EXTRA_SLOT + n); + } + + void setExtra(size_t n, const Value &extra) { + JS_ASSERT(n == 0 || n == 1); + SetReservedSlot(this, EXTRA_SLOT + n, extra); + } + + private: + HeapSlot *slotOfExtra(size_t n) { + JS_ASSERT(n == 0 || n == 1); + return &getReservedSlotRef(EXTRA_SLOT + n); + } + + public: + static unsigned grayLinkSlot(JSObject *obj); + + void renew(JSContext *cx, BaseProxyHandler *handler, Value priv); + + static void trace(JSTracer *trc, JSObject *obj); + + void nuke(BaseProxyHandler *handler); }; class FunctionProxyObject : public ProxyObject { + static const uint32_t CALL_SLOT = 4; + static const uint32_t CONSTRUCT_SLOT = 5; + public: static 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 diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 02b893fa19c..a292fd38e29 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -1549,36 +1549,38 @@ DebugScopeObject::create(JSContext *cx, ScopeObject &scope, HandleObject enclosi return NULL; JS_ASSERT(!enclosing->is()); - SetProxyExtra(obj, ENCLOSING_EXTRA, ObjectValue(*enclosing)); - SetProxyExtra(obj, SNAPSHOT_EXTRA, NullValue()); - return &obj->as(); + DebugScopeObject *debugScope = &obj->as(); + debugScope->setExtra(ENCLOSING_EXTRA, ObjectValue(*enclosing)); + debugScope->setExtra(SNAPSHOT_EXTRA, NullValue()); + + return debugScope; } ScopeObject & DebugScopeObject::scope() const { - return GetProxyTargetObject(const_cast(this))->as(); + return target()->as(); } JSObject & DebugScopeObject::enclosingScope() const { - return GetProxyExtra(const_cast(this), ENCLOSING_EXTRA).toObject(); + return extra(ENCLOSING_EXTRA).toObject(); } JSObject * DebugScopeObject::maybeSnapshot() const { JS_ASSERT(!scope().as().isForEval()); - return GetProxyExtra(const_cast(this), SNAPSHOT_EXTRA).toObjectOrNull(); + return extra(SNAPSHOT_EXTRA).toObjectOrNull(); } void DebugScopeObject::initSnapshot(JSObject &o) { JS_ASSERT(maybeSnapshot() == NULL); - SetProxyExtra(this, SNAPSHOT_EXTRA, ObjectValue(o)); + setExtra(SNAPSHOT_EXTRA, ObjectValue(o)); } bool @@ -1592,7 +1594,7 @@ bool js_IsDebugScopeSlow(ObjectProxyObject *proxy) { JS_ASSERT(proxy->hasClass(&ObjectProxyObject::class_)); - return GetProxyHandler(proxy) == &DebugScopeProxy::singleton; + return proxy->handler() == &DebugScopeProxy::singleton; } /*****************************************************************************/