mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-29 18:40:41 +00:00
reverting rmottola/Arctic-Fox changes in order to bisect memory leak and greasemonkey issue:
- Bug 1136925 part 1. Stop passing a parent to JS_CloneObject (02806f3cb) - Bug 1136925 part 2. Stop passing a parent to Wrapper::New. (1d51cbd34) - Bug 1136925 part 3. Stop passing parents to js::NewProxyObject. (dc13db8da) - Bug 1136925 part 4. Stop passing parents to ProxyObject::New. (e2d30e340) - Bug 1130679: IonMonkey: Make it possible to guard on type changes/bailouts (ecec18313) - Bug 1136980 part 1. Get rid of JS_SetParent uses in DOM/XPConnect. (5cad9c256) - Bug 1136980 part 2. Remove JS_SetParent, even though we have a CLOSED TREE (96cf58c85) - Bug 1066229 - Part 5: Emitter support for basic ES6 ClassStatements. (e2a3cc979) - Bug 1135423 - Use unboxed objects for object literals where possible, clean up object literal creation and property initialization code (1d9e381c2) - Bug 1137523 part 2 - Unprefix a few js_* functions I forgot in part 1 (e6beaf0d8) - Bug 1135816 - Handle unboxed object receivers when compiling getter/setter calls in baseline/Ion (82233087e) - Bug 1138265 - TraceLogger: Throw error when trying to enable in AsmJS (64c799042) - Bug 1113369, part 1 - Introduce JS::ObjectOpResult and use it in js::StandardDefineProperty. (15663c476) - Bug 1113369, part 1½ - Avoid regressing error messages by adding obj to the ObjectOpResult methods that could throw a TypeError. (e063faf08) - Bug 1113369, part 2 - js::SetArrayLength ObjectOpResult support. (cf8326017) - Bug 1113369, part 3 - [[DefineOwnProperty]] ObjectOpResult support. (e16605a90) - Bug 1113369, part 4 - [[Set]] ObjectOpResult support. (6f94604d4) - Bug 1077002 - Give a better error message when showModalDialog is used (18d8ecc12) - Bug 1135792. Stop assuming that every binding for a global with a non-worker descriptor is a binding for Window. (dd0260c12) - Bug 1135810. Add more explicit checks for whether a descriptor wants Xrays or not instead of assuming that Xrays are desired if and only if descriptor.workers is false. (17ef71544) - Bug 1050456 - Part 1: Prevent prerendered pages from showing the slow script dialog (173044922) - Bug 1050456 - Part 2: Add a nsGlobalWindow::GetIsPrerendered helper (ac680a5f7) hopefully we can re-apply them later.
This commit is contained in:
@@ -159,8 +159,7 @@ bool
|
||||
WindowNamedPropertiesHandler::defineProperty(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aProxy,
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JSPropertyDescriptor> aDesc,
|
||||
JS::ObjectOpResult &result) const
|
||||
JS::MutableHandle<JSPropertyDescriptor> aDesc) const
|
||||
{
|
||||
ErrorResult rv;
|
||||
rv.ThrowTypeError(MSG_DEFINEPROPERTY_ON_GSP);
|
||||
@@ -281,6 +280,7 @@ WindowNamedPropertiesHandler::Create(JSContext* aCx,
|
||||
options.setClass(&WindowNamedPropertiesClass.mBase);
|
||||
return js::NewProxyObject(aCx, WindowNamedPropertiesHandler::getInstance(),
|
||||
JS::NullHandleValue, aProto,
|
||||
js::GetGlobalForObjectCrossCompartment(aProto),
|
||||
options);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@ public:
|
||||
virtual bool
|
||||
defineProperty(JSContext* aCx, JS::Handle<JSObject*> aProxy,
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JSPropertyDescriptor> aDesc,
|
||||
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
JS::MutableHandle<JSPropertyDescriptor> aDesc) const override;
|
||||
virtual bool
|
||||
ownPropNames(JSContext* aCx, JS::Handle<JSObject*> aProxy, unsigned flags,
|
||||
JS::AutoIdVector& aProps) const override;
|
||||
|
||||
@@ -1170,7 +1170,13 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!contentDefinedProperty && desc.object() && !desc.value().isUndefined() &&
|
||||
!JS_DefineUCProperty(cx, global, mData->mNameUTF16,
|
||||
NS_strlen(mData->mNameUTF16), desc)) {
|
||||
NS_strlen(mData->mNameUTF16),
|
||||
desc.value(),
|
||||
// Descriptors never store JSNatives for accessors:
|
||||
// they have either JSFunctions or JSPropertyOps.
|
||||
desc.attributes() | JSPROP_PROPOP_ACCESSORS,
|
||||
JS_PROPERTYOP_GETTER(desc.getter()),
|
||||
JS_PROPERTYOP_SETTER(desc.setter()))) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
+33
-29
@@ -622,8 +622,8 @@ public:
|
||||
virtual bool defineProperty(JSContext* cx,
|
||||
JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc)
|
||||
const override;
|
||||
virtual bool ownPropertyKeys(JSContext *cx,
|
||||
JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const override;
|
||||
@@ -646,8 +646,8 @@ public:
|
||||
virtual bool set(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<JSObject*> receiver,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JS::Value> vp,
|
||||
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
bool strict,
|
||||
JS::MutableHandle<JS::Value> vp) const override;
|
||||
|
||||
// SpiderMonkey extensions
|
||||
virtual bool getPropertyDescriptor(JSContext* cx,
|
||||
@@ -783,8 +783,8 @@ bool
|
||||
nsOuterWindowProxy::defineProperty(JSContext* cx,
|
||||
JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
JS::ObjectOpResult &result) const
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc)
|
||||
const
|
||||
{
|
||||
int32_t index = GetArrayIndexFromId(cx, id);
|
||||
if (IsArrayIndex(index)) {
|
||||
@@ -792,7 +792,7 @@ nsOuterWindowProxy::defineProperty(JSContext* cx,
|
||||
// since we have no indexed setter or indexed creator. That means
|
||||
// throwing in strict mode (FIXME: Bug 828137), doing nothing in
|
||||
// non-strict mode.
|
||||
return result.succeed();
|
||||
return true;
|
||||
}
|
||||
|
||||
// For now, allow chrome code to define non-configurable properties
|
||||
@@ -803,7 +803,7 @@ nsOuterWindowProxy::defineProperty(JSContext* cx,
|
||||
return ThrowErrorMessage(cx, MSG_DEFINE_NON_CONFIGURABLE_PROP_ON_WINDOW);
|
||||
}
|
||||
|
||||
return js::Wrapper::defineProperty(cx, proxy, id, desc, result);
|
||||
return js::Wrapper::defineProperty(cx, proxy, id, desc);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -917,17 +917,19 @@ bool
|
||||
nsOuterWindowProxy::set(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<JSObject*> receiver,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JS::Value> vp,
|
||||
JS::ObjectOpResult &result) const
|
||||
bool strict,
|
||||
JS::MutableHandle<JS::Value> vp) const
|
||||
{
|
||||
int32_t index = GetArrayIndexFromId(cx, id);
|
||||
if (IsArrayIndex(index)) {
|
||||
// Reject (which means throw if and only if strict) the set.
|
||||
// XXX See bug 828137.
|
||||
return result.succeed();
|
||||
if (strict) {
|
||||
// XXXbz This needs to throw, but see bug 828137.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return js::Wrapper::set(cx, proxy, receiver, id, vp, result);
|
||||
return js::Wrapper::set(cx, proxy, receiver, id, strict, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1057,15 +1059,13 @@ const nsChromeOuterWindowProxy
|
||||
nsChromeOuterWindowProxy::singleton;
|
||||
|
||||
static JSObject*
|
||||
NewOuterWindowProxy(JSContext *cx, JS::Handle<JSObject*> global, bool isChrome)
|
||||
NewOuterWindowProxy(JSContext *cx, JS::Handle<JSObject*> parent, bool isChrome)
|
||||
{
|
||||
JSAutoCompartment ac(cx, global);
|
||||
MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(global) == global);
|
||||
|
||||
JSAutoCompartment ac(cx, parent);
|
||||
js::WrapperOptions options;
|
||||
options.setClass(&OuterWindowProxyClass);
|
||||
options.setSingleton(true);
|
||||
JSObject *obj = js::Wrapper::New(cx, global,
|
||||
JSObject *obj = js::Wrapper::New(cx, parent, parent,
|
||||
isChrome ? &nsChromeOuterWindowProxy::singleton
|
||||
: &nsOuterWindowProxy::singleton,
|
||||
options);
|
||||
@@ -2608,10 +2608,21 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
|
||||
SetWrapper(outerObject);
|
||||
|
||||
MOZ_ASSERT(js::GetObjectParent(outerObject) == newInnerGlobal);
|
||||
{
|
||||
JSAutoCompartment ac(cx, outerObject);
|
||||
|
||||
// Inform the nsJSContext, which is the canonical holder of the outer.
|
||||
mContext->SetWindowProxy(outerObject);
|
||||
JS_SetParent(cx, outerObject, newInnerGlobal);
|
||||
|
||||
// Inform the nsJSContext, which is the canonical holder of the outer.
|
||||
mContext->SetWindowProxy(outerObject);
|
||||
|
||||
NS_ASSERTION(!JS_IsExceptionPending(cx),
|
||||
"We might overwrite a pending exception!");
|
||||
XPCWrappedNativeScope* scope = xpc::ObjectScope(outerObject);
|
||||
if (scope->mWaiverWrapperMap) {
|
||||
scope->mWaiverWrapperMap->Reparent(cx, newInnerGlobal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Enter the new global's compartment.
|
||||
@@ -9324,7 +9335,7 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
|
||||
(aUrl, aArgument, aOptions, aError), aError,
|
||||
nullptr);
|
||||
|
||||
if (!IsShowModalDialogEnabled() || XRE_GetProcessType() == GoannaProcessType_Content) {
|
||||
if (!IsShowModalDialogEnabled()) {
|
||||
aError.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -14257,13 +14268,6 @@ nsGlobalWindow::CreateNamedPropertiesObject(JSContext *aCx,
|
||||
return WindowNamedPropertiesHandler::Create(aCx, aProto);
|
||||
}
|
||||
|
||||
bool
|
||||
nsGlobalWindow::GetIsPrerendered()
|
||||
{
|
||||
nsIDocShell* docShell = GetDocShell();
|
||||
return docShell && docShell->GetIsPrerendered();
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
void
|
||||
nsGlobalWindow::EnableNetworkEvent(uint32_t aType)
|
||||
|
||||
@@ -1282,8 +1282,6 @@ public:
|
||||
const nsAString &aPopupWindowFeatures);
|
||||
void FireOfflineStatusEventIfChanged();
|
||||
|
||||
bool GetIsPrerendered();
|
||||
|
||||
// Inner windows only.
|
||||
nsresult ScheduleNextIdleObserverCallback();
|
||||
uint32_t GetFuzzTimeMS();
|
||||
|
||||
@@ -1469,14 +1469,13 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
bool
|
||||
XrayDefineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
JS::ObjectOpResult &result, bool *defined)
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined)
|
||||
{
|
||||
if (!js::IsProxy(obj))
|
||||
return true;
|
||||
return true;
|
||||
|
||||
const DOMProxyHandler* handler = GetDOMProxyHandler(obj);
|
||||
return handler->defineProperty(cx, wrapper, id, desc, result, defined);
|
||||
return handler->defineProperty(cx, wrapper, id, desc, defined);
|
||||
}
|
||||
|
||||
template<typename SpecType>
|
||||
@@ -1634,7 +1633,7 @@ XrayOwnPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
obj, flags, props);
|
||||
}
|
||||
|
||||
NativePropertyHooks sEmptyNativePropertyHooks = {
|
||||
NativePropertyHooks sWorkerNativePropertyHooks = {
|
||||
nullptr,
|
||||
nullptr,
|
||||
{
|
||||
@@ -1832,7 +1831,7 @@ ReparentWrapper(JSContext* aCx, JS::Handle<JSObject*> aObjArg)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> newobj(aCx, JS_CloneObject(aCx, aObj, proto));
|
||||
JS::Rooted<JSObject*> newobj(aCx, JS_CloneObject(aCx, aObj, proto, newParent));
|
||||
if (!newobj) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@@ -2436,7 +2435,13 @@ EnforceNotInPrerendering(JSContext* aCx, JSObject* aObj)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (window->GetIsPrerendered()) {
|
||||
nsIDocShell* docShell = window->GetDocShell();
|
||||
if (!docShell) {
|
||||
// Without a docshell, we cannot check the safety.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (docShell->GetIsPrerendered()) {
|
||||
HandlePrerenderingViolation(window);
|
||||
// When the bindings layer sees a false return value, it returns false form
|
||||
// the JSNative in order to trigger an uncatchable exception.
|
||||
|
||||
@@ -2450,17 +2450,12 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
* wrapper is the Xray JS object.
|
||||
* obj is the target object of the Xray, a binding's instance object or a
|
||||
* interface or interface prototype object.
|
||||
* id and desc are the parameters for the property to be defined.
|
||||
* result is the out-parameter indicating success (read it only if
|
||||
* this returns true and also sets *defined to true).
|
||||
* defined will be set to true if a property was set as a result of this call.
|
||||
*/
|
||||
bool
|
||||
XrayDefineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
JS::ObjectOpResult &result,
|
||||
bool *defined);
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined);
|
||||
|
||||
/**
|
||||
* Add to props the property keys of all indexed or named properties of obj and
|
||||
@@ -2516,7 +2511,7 @@ XrayGetNativeProto(JSContext* cx, JS::Handle<JSObject*> obj,
|
||||
return JS_WrapObject(cx, protop);
|
||||
}
|
||||
|
||||
extern NativePropertyHooks sEmptyNativePropertyHooks;
|
||||
extern NativePropertyHooks sWorkerNativePropertyHooks;
|
||||
|
||||
inline bool
|
||||
UseDOMXray(JSObject* obj)
|
||||
@@ -2800,7 +2795,7 @@ public:
|
||||
options.setClass(aClass);
|
||||
JS::Rooted<JS::Value> proxyPrivateVal(aCx, JS::PrivateValue(aNative));
|
||||
aReflector.set(js::NewProxyObject(aCx, aHandler, proxyPrivateVal, aProto,
|
||||
options));
|
||||
/* parent= */nullptr, options));
|
||||
if (aReflector) {
|
||||
mNative = aNative;
|
||||
mReflector = aReflector;
|
||||
|
||||
@@ -45,13 +45,9 @@
|
||||
# interfaces. Defaults to true for non-worker non-callback
|
||||
# descriptors.
|
||||
#
|
||||
# A non-worker descriptor can have 'wantsXrays': False specified if it
|
||||
# should not have Xray hooks generated. Make sure to have someone
|
||||
# familiar with Xrays review any use of this!
|
||||
#
|
||||
# The following fields are either a string, an array (defaults to an empty
|
||||
# array) or a dictionary with three possible keys (all, getterOnly and
|
||||
# setterOnly) each having such an array as the value
|
||||
# The following fields are either a string, an array (defaults to an empty
|
||||
# array) or a dictionary with three possible keys (all, getterOnly and
|
||||
# setterOnly) each having such an array as the value
|
||||
#
|
||||
# * implicitJSContext - attributes and methods specified in the .webidl file
|
||||
# that require a JSContext as the first argument
|
||||
|
||||
+31
-29
@@ -255,7 +255,7 @@ class CGNativePropertyHooks(CGThing):
|
||||
self.properties = properties
|
||||
|
||||
def declare(self):
|
||||
if not self.descriptor.wantsXrays:
|
||||
if self.descriptor.workers:
|
||||
return ""
|
||||
return dedent("""
|
||||
// We declare this as an array so that retrieving a pointer to this
|
||||
@@ -269,7 +269,7 @@ class CGNativePropertyHooks(CGThing):
|
||||
""")
|
||||
|
||||
def define(self):
|
||||
if not self.descriptor.wantsXrays:
|
||||
if self.descriptor.workers:
|
||||
return ""
|
||||
if self.descriptor.concrete and self.descriptor.proxy:
|
||||
resolveOwnProperty = "ResolveOwnProperty"
|
||||
@@ -323,7 +323,7 @@ class CGNativePropertyHooks(CGThing):
|
||||
|
||||
|
||||
def NativePropertyHooks(descriptor):
|
||||
return "&sEmptyNativePropertyHooks" if not descriptor.wantsXrays else "sNativePropertyHooks"
|
||||
return "&sWorkerNativePropertyHooks" if descriptor.workers else "sNativePropertyHooks"
|
||||
|
||||
|
||||
def DOMClass(descriptor):
|
||||
@@ -381,7 +381,7 @@ class CGDOMJSClass(CGThing):
|
||||
classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS) | JSCLASS_IMPLEMENTS_BARRIERS"
|
||||
traceHook = "JS_GlobalObjectTraceHook"
|
||||
reservedSlots = "JSCLASS_GLOBAL_APPLICATION_SLOTS"
|
||||
if self.descriptor.interface.identifier.name == "Window":
|
||||
if not self.descriptor.workers:
|
||||
classExtensionAndObjectOps = fill(
|
||||
"""
|
||||
{
|
||||
@@ -1958,7 +1958,8 @@ class PropertyDefiner:
|
||||
return "nullptr"
|
||||
|
||||
def usedForXrays(self):
|
||||
return self.descriptor.wantsXrays
|
||||
# No Xrays in workers.
|
||||
return not self.descriptor.workers
|
||||
|
||||
def __str__(self):
|
||||
# We only need to generate id arrays for things that will end
|
||||
@@ -2618,8 +2619,9 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||
assert needInterfaceObject or needInterfacePrototypeObject
|
||||
|
||||
idsToInit = []
|
||||
# There is no need to init any IDs in bindings that don't want Xrays.
|
||||
if self.descriptor.wantsXrays:
|
||||
# There is no need to init any IDs in workers, because worker bindings
|
||||
# don't have Xrays.
|
||||
if not self.descriptor.workers:
|
||||
for var in self.properties.arrayNames():
|
||||
props = getattr(self.properties, var)
|
||||
# We only have non-chrome ids to init if we have no chrome ids.
|
||||
@@ -7621,7 +7623,10 @@ class CGResolveHook(CGAbstractBindingMethod):
|
||||
// has already defined it on the object. Don't try to also
|
||||
// define it.
|
||||
if (!desc.value().isUndefined() &&
|
||||
!JS_DefinePropertyById(cx, obj, id, desc)) {
|
||||
!JS_DefinePropertyById(cx, obj, id, desc.value(),
|
||||
desc.attributes() | JSPROP_PROPOP_ACCESSORS,
|
||||
JS_PROPERTYOP_GETTER(desc.getter()),
|
||||
JS_PROPERTYOP_SETTER(desc.setter()))) {
|
||||
return false;
|
||||
}
|
||||
*resolvedp = true;
|
||||
@@ -9616,7 +9621,10 @@ class CGResolveOwnPropertyViaResolve(CGAbstractBindingMethod):
|
||||
// try to also define it.
|
||||
if (objDesc.object() &&
|
||||
!objDesc.value().isUndefined() &&
|
||||
!JS_DefinePropertyById(cx, obj, id, objDesc)) {
|
||||
!JS_DefinePropertyById(cx, obj, id, objDesc.value(),
|
||||
objDesc.attributes() | JSPROP_PROPOP_ACCESSORS,
|
||||
JS_PROPERTYOP_GETTER(objDesc.getter()),
|
||||
JS_PROPERTYOP_SETTER(objDesc.setter()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -10179,13 +10187,10 @@ class CGDOMJSProxyHandler_getOwnPropDescriptor(ClassMethod):
|
||||
|
||||
class CGDOMJSProxyHandler_defineProperty(ClassMethod):
|
||||
def __init__(self, descriptor):
|
||||
# The usual convention is to name the ObjectOpResult out-parameter
|
||||
# `result`, but that name is a bit overloaded around here.
|
||||
args = [Argument('JSContext*', 'cx'),
|
||||
Argument('JS::Handle<JSObject*>', 'proxy'),
|
||||
Argument('JS::Handle<jsid>', 'id'),
|
||||
Argument('JS::MutableHandle<JSPropertyDescriptor>', 'desc'),
|
||||
Argument('JS::ObjectOpResult&', 'opresult'),
|
||||
Argument('bool*', 'defined')]
|
||||
ClassMethod.__init__(self, "defineProperty", "bool", args, virtual=True, override=True, const=True)
|
||||
self.descriptor = descriptor
|
||||
@@ -10203,7 +10208,7 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
|
||||
if (IsArrayIndex(index)) {
|
||||
*defined = true;
|
||||
$*{callSetter}
|
||||
return opresult.succeed();
|
||||
return true;
|
||||
}
|
||||
""",
|
||||
callSetter=CGProxyIndexedSetter(self.descriptor).define())
|
||||
@@ -10216,9 +10221,7 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
|
||||
set += fill(
|
||||
"""
|
||||
if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
|
||||
return js::IsInNonStrictPropertySet(cx)
|
||||
? opresult.succeed()
|
||||
: ThrowErrorMessage(cx, MSG_NO_INDEXED_SETTER, "${name}");
|
||||
return js::IsInNonStrictPropertySet(cx) || ThrowErrorMessage(cx, MSG_NO_INDEXED_SETTER, "${name}");
|
||||
}
|
||||
""",
|
||||
name=self.descriptor.name)
|
||||
@@ -10233,7 +10236,8 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
|
||||
"}\n"
|
||||
"if (hasUnforgeable) {\n"
|
||||
" *defined = true;\n"
|
||||
" return js::DefineOwnProperty(cx, ${holder}, id, desc, opresult);\n"
|
||||
" bool unused;\n"
|
||||
" return js::DefineOwnProperty(cx, ${holder}, id, desc, &unused);\n"
|
||||
"}\n")
|
||||
set += CallOnUnforgeableHolder(self.descriptor,
|
||||
defineOnUnforgeable,
|
||||
@@ -10250,7 +10254,7 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
|
||||
*defined = true;
|
||||
$*{callSetter}
|
||||
|
||||
return opresult.succeed();
|
||||
return true;
|
||||
""",
|
||||
callSetter=CGProxyNamedSetter(self.descriptor).define())
|
||||
else:
|
||||
@@ -10266,9 +10270,7 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
|
||||
$*{presenceChecker}
|
||||
|
||||
if (found) {
|
||||
return js::IsInNonStrictPropertySet(cx)
|
||||
? opresult.succeed()
|
||||
: ThrowErrorMessage(cx, MSG_NO_NAMED_SETTER, "${name}");
|
||||
return js::IsInNonStrictPropertySet(cx) || ThrowErrorMessage(cx, MSG_NO_NAMED_SETTER, "${name}");
|
||||
}
|
||||
""",
|
||||
presenceChecker=CGProxyNamedPresenceChecker(self.descriptor, foundVar="found").define(),
|
||||
@@ -11173,14 +11175,14 @@ class CGDescriptor(CGThing):
|
||||
cgThings.append(CGGeneric(define=str(properties)))
|
||||
cgThings.append(CGNativeProperties(descriptor, properties))
|
||||
|
||||
# Set up our Xray callbacks as needed.
|
||||
if descriptor.wantsXrays:
|
||||
if descriptor.concrete and descriptor.proxy:
|
||||
cgThings.append(CGResolveOwnProperty(descriptor))
|
||||
cgThings.append(CGEnumerateOwnProperties(descriptor))
|
||||
elif descriptor.needsXrayResolveHooks():
|
||||
cgThings.append(CGResolveOwnPropertyViaResolve(descriptor))
|
||||
cgThings.append(CGEnumerateOwnPropertiesViaGetOwnPropertyNames(descriptor))
|
||||
# Set up our Xray callbacks as needed. Note that we don't need to do
|
||||
# it in workers.
|
||||
if not descriptor.workers and descriptor.concrete and descriptor.proxy:
|
||||
cgThings.append(CGResolveOwnProperty(descriptor))
|
||||
cgThings.append(CGEnumerateOwnProperties(descriptor))
|
||||
elif descriptor.needsXrayResolveHooks():
|
||||
cgThings.append(CGResolveOwnPropertyViaResolve(descriptor))
|
||||
cgThings.append(CGEnumerateOwnPropertiesViaGetOwnPropertyNames(descriptor))
|
||||
|
||||
# Now that we have our ResolveOwnProperty/EnumerateOwnProperties stuff
|
||||
# done, set up our NativePropertyHooks.
|
||||
|
||||
@@ -302,12 +302,6 @@ class Descriptor(DescriptorProvider):
|
||||
DescriptorProvider.__init__(self, config, desc.get('workers', False))
|
||||
self.interface = interface
|
||||
|
||||
if self.workers:
|
||||
assert 'wantsXrays' not in desc
|
||||
self.wantsXrays = False
|
||||
else:
|
||||
self.wantsXrays = desc.get('wantsXrays', True)
|
||||
|
||||
# Read the desc, and fill in the relevant defaults.
|
||||
ifaceName = self.interface.identifier.name
|
||||
if self.interface.isExternal():
|
||||
|
||||
@@ -195,15 +195,18 @@ BaseDOMProxyHandler::getOwnPropertyDescriptor(JSContext* cx,
|
||||
|
||||
bool
|
||||
DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||
MutableHandle<JSPropertyDescriptor> desc,
|
||||
JS::ObjectOpResult &result, bool *defined) const
|
||||
MutableHandle<JSPropertyDescriptor> desc, bool* defined) const
|
||||
{
|
||||
if (desc.hasGetterObject() && desc.setter() == JS_StrictPropertyStub) {
|
||||
return result.failGetterOnly();
|
||||
return JS_ReportErrorFlagsAndNumber(cx,
|
||||
JSREPORT_WARNING | JSREPORT_STRICT |
|
||||
JSREPORT_STRICT_MODE_ERROR,
|
||||
js::GetErrorMessage, nullptr,
|
||||
JSMSG_GETTER_ONLY);
|
||||
}
|
||||
|
||||
if (xpc::WrapperFactory::IsXrayWrapper(proxy)) {
|
||||
return result.succeed();
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject* expando = EnsureExpandoObject(cx, proxy);
|
||||
@@ -211,16 +214,13 @@ DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!js::DefineOwnProperty(cx, expando, id, desc, result)) {
|
||||
return false;
|
||||
}
|
||||
*defined = true;
|
||||
return true;
|
||||
bool dummy;
|
||||
return js::DefineOwnProperty(cx, expando, id, desc, &dummy);
|
||||
}
|
||||
|
||||
bool
|
||||
DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<JSObject*> receiver,
|
||||
Handle<jsid> id, MutableHandle<JS::Value> vp, ObjectOpResult &result) const
|
||||
Handle<jsid> id, bool strict, MutableHandle<JS::Value> vp) const
|
||||
{
|
||||
MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
|
||||
"Should not have a XrayWrapper here");
|
||||
@@ -229,7 +229,7 @@ DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<JSObject*> r
|
||||
return false;
|
||||
}
|
||||
if (done) {
|
||||
return result.succeed();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make sure to ignore our named properties when checking for own
|
||||
@@ -254,7 +254,7 @@ DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<JSObject*> r
|
||||
}
|
||||
|
||||
return js::SetPropertyIgnoringNamedGetter(cx, this, proxy, receiver, id,
|
||||
&desc, descIsOwn, vp, result);
|
||||
&desc, descIsOwn, strict, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -105,26 +105,25 @@ public:
|
||||
{}
|
||||
|
||||
bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
JS::ObjectOpResult &result) const MOZ_OVERRIDE
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc) const override
|
||||
{
|
||||
bool unused;
|
||||
return defineProperty(cx, proxy, id, desc, result, &unused);
|
||||
return defineProperty(cx, proxy, id, desc, &unused);
|
||||
}
|
||||
virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
JS::ObjectOpResult &result, bool *defined) const;
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined)
|
||||
const;
|
||||
bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id, bool* bp) const MOZ_OVERRIDE;
|
||||
JS::Handle<jsid> id, bool* bp) const override;
|
||||
bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
bool *succeeded) const MOZ_OVERRIDE;
|
||||
bool *succeeded) const override;
|
||||
bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
|
||||
const override;
|
||||
bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||
bool* bp) const MOZ_OVERRIDE;
|
||||
bool* bp) const override;
|
||||
bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
|
||||
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp, JS::ObjectOpResult &result)
|
||||
const MOZ_OVERRIDE;
|
||||
JS::Handle<jsid> id, bool strict, JS::MutableHandle<JS::Value> vp)
|
||||
const override;
|
||||
|
||||
/*
|
||||
* If assigning to proxy[id] hits a named setter with OverrideBuiltins or
|
||||
|
||||
@@ -11,5 +11,3 @@ support-files =
|
||||
file_focuser.html
|
||||
file_fullScreenPropertyAccessor.html
|
||||
skip-if = e10s # prerendering doesn't work in e10s yet
|
||||
[test_kill_longrunning_prerendered_content.xul]
|
||||
skip-if = e10s # prerendering doesn't work in e10s yet
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
onload="runTest();">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function Listener(aBrowser, aPrerendered, aCallback) {
|
||||
this.init(aBrowser, aPrerendered, aCallback);
|
||||
}
|
||||
|
||||
Listener.prototype = {
|
||||
init: function(aBrowser, aCallback) {
|
||||
this.mBrowser = aBrowser;
|
||||
this.mCallback = aCallback;
|
||||
},
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
|
||||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
|
||||
aIID.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
},
|
||||
onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if ((aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) &&
|
||||
(aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT)) {
|
||||
setTimeout(this.mCallback, 0);
|
||||
}
|
||||
},
|
||||
onProgressChange : function(aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {},
|
||||
onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) {},
|
||||
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {},
|
||||
onSecurityChange : function(aWebProgress, aRequest, aState) {},
|
||||
mBrowser: null,
|
||||
mPrerendered: false,
|
||||
mCallback: null
|
||||
};
|
||||
|
||||
var progress, progressListener;
|
||||
|
||||
function runTest() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.max_script_run_time", 1]
|
||||
]
|
||||
}, function() {
|
||||
test(function() {
|
||||
ok("The page is successfully interrupted.");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test(aCallback) {
|
||||
var browser = document.getElementById("prerendered");;
|
||||
progressListener = new Listener(browser, aCallback);
|
||||
var docShell = browser.docShell;
|
||||
progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebProgress);
|
||||
progress.addProgressListener(progressListener,
|
||||
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
|
||||
browser.loadURI("data:text/html,<script>;for(;;);</script" + ">");
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body id="html_body" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1050456">Mozilla Bug 1050456</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
<browser prerendered="true" id="prerendered"/>
|
||||
</window>
|
||||
@@ -169,8 +169,8 @@ static bool
|
||||
NPObjWrapper_DelProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool *succeeded);
|
||||
|
||||
static bool
|
||||
NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JS::Value> vp, JS::ObjectOpResult &result);
|
||||
NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool strict,
|
||||
JS::MutableHandle<JS::Value> vp);
|
||||
|
||||
static bool
|
||||
NPObjWrapper_GetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp);
|
||||
@@ -1326,8 +1326,8 @@ NPObjWrapper_DelProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<js
|
||||
}
|
||||
|
||||
static bool
|
||||
NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JS::Value> vp, JS::ObjectOpResult &result)
|
||||
NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool strict,
|
||||
JS::MutableHandle<JS::Value> vp)
|
||||
{
|
||||
NPObject *npobj = GetNPObject(cx, obj);
|
||||
|
||||
@@ -1382,7 +1382,7 @@ NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<js
|
||||
return false;
|
||||
}
|
||||
|
||||
return result.succeed();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
||||
@@ -52,7 +52,8 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
|
||||
return Answer::RecvGetOwnPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
|
||||
}
|
||||
bool RecvDefineProperty(const uint64_t& objId, const JSIDVariant& id,
|
||||
const PPropertyDescriptor &flags, ReturnStatus *rs) {
|
||||
const PPropertyDescriptor& flags,
|
||||
ReturnStatus* rs) {
|
||||
return Answer::RecvDefineProperty(ObjectId::deserialize(objId), id, flags, rs);
|
||||
}
|
||||
bool RecvDelete(const uint64_t& objId, const JSIDVariant& id,
|
||||
@@ -74,9 +75,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
|
||||
return Answer::RecvGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
|
||||
}
|
||||
bool RecvSet(const uint64_t& objId, const ObjectVariant& receiverVar,
|
||||
const JSIDVariant &id, const JSVariant &value, ReturnStatus *rs,
|
||||
JSVariant *result) {
|
||||
return Answer::RecvSet(ObjectId::deserialize(objId), receiverVar, id, value, rs, result);
|
||||
const JSIDVariant& id, const bool& strict,
|
||||
const JSVariant& value, ReturnStatus* rs, JSVariant* result) {
|
||||
return Answer::RecvSet(ObjectId::deserialize(objId), receiverVar, id, strict, value, rs, result);
|
||||
}
|
||||
|
||||
bool RecvIsExtensible(const uint64_t& objId, ReturnStatus* rs,
|
||||
@@ -144,7 +145,7 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
|
||||
}
|
||||
bool SendDefineProperty(const ObjectId& objId, const JSIDVariant& id,
|
||||
const PPropertyDescriptor& flags,
|
||||
ReturnStatus *rs) {
|
||||
ReturnStatus* rs) {
|
||||
return Base::SendDefineProperty(objId.serialize(), id, flags, rs);
|
||||
}
|
||||
bool SendDelete(const ObjectId& objId, const JSIDVariant& id,
|
||||
@@ -166,9 +167,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
|
||||
return Base::SendGet(objId.serialize(), receiverVar, id, rs, result);
|
||||
}
|
||||
bool SendSet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
const JSIDVariant &id, const JSVariant &value, ReturnStatus *rs,
|
||||
JSVariant *result) {
|
||||
return Base::SendSet(objId.serialize(), receiverVar, id, value, rs, result);
|
||||
const JSIDVariant& id, const bool& strict,
|
||||
const JSVariant& value, ReturnStatus* rs, JSVariant* result) {
|
||||
return Base::SendSet(objId.serialize(), receiverVar, id, strict, value, rs, result);
|
||||
}
|
||||
|
||||
bool SendIsExtensible(const ObjectId& objId, ReturnStatus* rs,
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace jsipc {
|
||||
#define LOG_STACK() \
|
||||
PR_BEGIN_MACRO \
|
||||
if (StackLoggingEnabled()) { \
|
||||
js::DumpBacktrace(cx); \
|
||||
js_DumpBacktrace(cx); \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
|
||||
@@ -605,8 +605,7 @@ UnknownPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleV
|
||||
}
|
||||
|
||||
bool
|
||||
UnknownStrictPropertyStub(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp,
|
||||
ObjectOpResult &result)
|
||||
UnknownStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
|
||||
{
|
||||
JS_ReportError(cx, "setter could not be wrapped via CPOWs");
|
||||
return false;
|
||||
|
||||
@@ -103,17 +103,11 @@ struct ReturnException
|
||||
JSVariant exn;
|
||||
};
|
||||
|
||||
struct ReturnObjectOpResult
|
||||
{
|
||||
uint32_t code;
|
||||
};
|
||||
|
||||
union ReturnStatus
|
||||
{
|
||||
ReturnSuccess;
|
||||
ReturnStopIteration;
|
||||
ReturnException;
|
||||
ReturnObjectOpResult;
|
||||
};
|
||||
|
||||
union JSParam
|
||||
|
||||
@@ -33,7 +33,7 @@ both:
|
||||
prio(high) sync Has(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
|
||||
prio(high) sync HasOwn(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
|
||||
prio(high) sync Get(uint64_t objId, ObjectVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
|
||||
prio(high) sync Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, JSVariant value) returns (ReturnStatus rs, JSVariant result);
|
||||
prio(high) sync Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
|
||||
|
||||
prio(high) sync IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
|
||||
prio(high) sync CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
|
||||
|
||||
+12
-20
@@ -64,15 +64,6 @@ WrapperAnswer::ok(ReturnStatus* rs)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperAnswer::ok(ReturnStatus *rs, const JS::ObjectOpResult &result)
|
||||
{
|
||||
*rs = result
|
||||
? ReturnStatus(ReturnSuccess())
|
||||
: ReturnStatus(ReturnObjectOpResult(result.failureCode()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperAnswer::RecvPreventExtensions(const ObjectId& objId, ReturnStatus* rs,
|
||||
bool* succeeded)
|
||||
@@ -188,10 +179,11 @@ WrapperAnswer::RecvDefineProperty(const ObjectId& objId, const JSIDVariant& idVa
|
||||
if (!toDescriptor(cx, descriptor, &desc))
|
||||
return fail(cx, rs);
|
||||
|
||||
ObjectOpResult success;
|
||||
if (!js::DefineOwnProperty(cx, obj, id, desc, success))
|
||||
bool ignored;
|
||||
if (!js::DefineOwnProperty(cx, obj, id, desc, &ignored))
|
||||
return fail(cx, rs);
|
||||
return ok(rs, success);
|
||||
|
||||
return ok(rs);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -313,8 +305,8 @@ WrapperAnswer::RecvGet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
|
||||
bool
|
||||
WrapperAnswer::RecvSet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
const JSIDVariant &idVar, const JSVariant &value, ReturnStatus *rs,
|
||||
JSVariant *resultValue)
|
||||
const JSIDVariant& idVar, const bool& strict, const JSVariant& value,
|
||||
ReturnStatus* rs, JSVariant* result)
|
||||
{
|
||||
// We may run scripted setters.
|
||||
AutoEntryScript aes(xpc::NativeGlobal(scopeForTargetObjects()));
|
||||
@@ -322,7 +314,7 @@ WrapperAnswer::RecvSet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
|
||||
// The outparam will be written to the buffer, so it must be set even if
|
||||
// the parent won't read it.
|
||||
*resultValue = UndefinedVariant();
|
||||
*result = UndefinedVariant();
|
||||
|
||||
RootedObject obj(cx, findObjectById(cx, objId));
|
||||
if (!obj)
|
||||
@@ -338,19 +330,19 @@ WrapperAnswer::RecvSet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
if (!fromJSIDVariant(cx, idVar, &id))
|
||||
return fail(cx, rs);
|
||||
|
||||
MOZ_ASSERT(obj == receiver);
|
||||
|
||||
RootedValue val(cx);
|
||||
if (!fromVariant(cx, value, &val))
|
||||
return fail(cx, rs);
|
||||
|
||||
ObjectOpResult result;
|
||||
RootedValue receiverVal(cx, ObjectValue(*receiver));
|
||||
if (!JS_ForwardSetPropertyTo(cx, obj, id, val, receiverVal, result))
|
||||
if (!JS_SetPropertyById(cx, obj, id, val))
|
||||
return fail(cx, rs);
|
||||
|
||||
if (!toVariant(cx, val, resultValue))
|
||||
if (!toVariant(cx, val, result))
|
||||
return fail(cx, rs);
|
||||
|
||||
return ok(rs, result);
|
||||
return ok(rs);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -28,7 +28,8 @@ class WrapperAnswer : public virtual JavaScriptShared
|
||||
ReturnStatus* rs,
|
||||
PPropertyDescriptor* out);
|
||||
bool RecvDefineProperty(const ObjectId& objId, const JSIDVariant& id,
|
||||
const PPropertyDescriptor &flags, ReturnStatus *rs);
|
||||
const PPropertyDescriptor& flags,
|
||||
ReturnStatus* rs);
|
||||
bool RecvDelete(const ObjectId& objId, const JSIDVariant& id,
|
||||
ReturnStatus* rs, bool* success);
|
||||
|
||||
@@ -40,8 +41,8 @@ class WrapperAnswer : public virtual JavaScriptShared
|
||||
const JSIDVariant& id,
|
||||
ReturnStatus* rs, JSVariant* result);
|
||||
bool RecvSet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
const JSIDVariant &id, const JSVariant &value, ReturnStatus *rs,
|
||||
JSVariant *result);
|
||||
const JSIDVariant& id, const bool& strict,
|
||||
const JSVariant& value, ReturnStatus* rs, JSVariant* result);
|
||||
|
||||
bool RecvIsExtensible(const ObjectId& objId, ReturnStatus* rs,
|
||||
bool* result);
|
||||
@@ -66,8 +67,7 @@ class WrapperAnswer : public virtual JavaScriptShared
|
||||
|
||||
private:
|
||||
bool fail(JSContext* cx, ReturnStatus* rs);
|
||||
bool ok(ReturnStatus *rs);
|
||||
bool ok(ReturnStatus *rs, const JS::ObjectOpResult &result);
|
||||
bool ok(ReturnStatus* rs);
|
||||
};
|
||||
|
||||
} // mozilla
|
||||
|
||||
+14
-27
@@ -90,8 +90,7 @@ class CPOWProxyHandler : public BaseProxyHandler
|
||||
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc) const override;
|
||||
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc,
|
||||
ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
MutableHandle<JSPropertyDescriptor> desc) const override;
|
||||
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
|
||||
AutoIdVector& props) const override;
|
||||
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
|
||||
@@ -102,8 +101,7 @@ class CPOWProxyHandler : public BaseProxyHandler
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp) const override;
|
||||
virtual bool set(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||
JS::HandleId id, JS::MutableHandleValue vp,
|
||||
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp) const override;
|
||||
virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
|
||||
virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
|
||||
|
||||
@@ -204,16 +202,14 @@ WrapperOwner::getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, Handle
|
||||
|
||||
bool
|
||||
CPOWProxyHandler::defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc,
|
||||
ObjectOpResult &result) const
|
||||
MutableHandle<JSPropertyDescriptor> desc) const
|
||||
{
|
||||
FORWARD(defineProperty, (cx, proxy, id, desc, result));
|
||||
FORWARD(defineProperty, (cx, proxy, id, desc));
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperOwner::defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc,
|
||||
ObjectOpResult &result)
|
||||
MutableHandle<JSPropertyDescriptor> desc)
|
||||
{
|
||||
ObjectId objId = idOf(proxy);
|
||||
|
||||
@@ -231,7 +227,7 @@ WrapperOwner::defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
|
||||
LOG_STACK();
|
||||
|
||||
return ok(cx, status, result);
|
||||
return ok(cx, status);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -435,14 +431,14 @@ WrapperOwner::get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
|
||||
bool
|
||||
CPOWProxyHandler::set(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result) const
|
||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp) const
|
||||
{
|
||||
FORWARD(set, (cx, proxy, receiver, id, vp, result));
|
||||
FORWARD(set, (cx, proxy, receiver, id, strict, vp));
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperOwner::set(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result)
|
||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp)
|
||||
{
|
||||
ObjectId objId = idOf(proxy);
|
||||
|
||||
@@ -459,16 +455,16 @@ WrapperOwner::set(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiv
|
||||
return false;
|
||||
|
||||
ReturnStatus status;
|
||||
JSVariant resultValue;
|
||||
if (!SendSet(objId, receiverVar, idVar, val, &status, &resultValue))
|
||||
JSVariant result;
|
||||
if (!SendSet(objId, receiverVar, idVar, strict, val, &status, &result))
|
||||
return ipcfail(cx);
|
||||
|
||||
LOG_STACK();
|
||||
|
||||
if (!ok(cx, status, result))
|
||||
if (!ok(cx, status))
|
||||
return false;
|
||||
|
||||
return fromVariant(cx, resultValue, vp);
|
||||
return fromVariant(cx, result, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -938,16 +934,6 @@ WrapperOwner::ok(JSContext* cx, const ReturnStatus& status)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperOwner::ok(JSContext *cx, const ReturnStatus &status, ObjectOpResult &result)
|
||||
{
|
||||
if (status.type() == ReturnStatus::TReturnObjectOpResult)
|
||||
return result.fail(status.get_ReturnObjectOpResult().code());
|
||||
if (!ok(cx, status))
|
||||
return false;
|
||||
return result.succeed();
|
||||
}
|
||||
|
||||
static RemoteObject
|
||||
MakeRemoteObject(JSContext* cx, ObjectId id, HandleObject obj)
|
||||
{
|
||||
@@ -1034,6 +1020,7 @@ WrapperOwner::fromRemoteObjectVariant(JSContext* cx, RemoteObject objVar)
|
||||
&CPOWProxyHandler::singleton,
|
||||
v,
|
||||
nullptr,
|
||||
junkScope,
|
||||
options);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
@@ -32,8 +32,7 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||
bool getOwnPropertyDescriptor(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||
bool defineProperty(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
JS::ObjectOpResult &result);
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||
bool ownPropertyKeys(JSContext* cx, JS::HandleObject proxy, JS::AutoIdVector& props);
|
||||
bool delete_(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, bool* bp);
|
||||
bool preventExtensions(JSContext* cx, JS::HandleObject proxy, bool* succeeded);
|
||||
@@ -42,7 +41,7 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||
bool get(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||
JS::HandleId id, JS::MutableHandleValue vp);
|
||||
bool set(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result);
|
||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp);
|
||||
bool callOrConstruct(JSContext* cx, JS::HandleObject proxy, const JS::CallArgs& args,
|
||||
bool construct);
|
||||
|
||||
@@ -94,10 +93,6 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||
bool ipcfail(JSContext* cx);
|
||||
|
||||
// Check whether a return status is okay, and if not, propagate its error.
|
||||
//
|
||||
// If 'status' might be a ReturnObjectOpResult, which is only possible for
|
||||
// a subset of the operations below, 'result' must be passed.
|
||||
bool ok(JSContext *cx, const ReturnStatus &status, JS::ObjectOpResult &result);
|
||||
bool ok(JSContext* cx, const ReturnStatus& status);
|
||||
|
||||
bool inactive_;
|
||||
@@ -128,8 +123,8 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||
const JSIDVariant& id,
|
||||
ReturnStatus* rs, JSVariant* result) = 0;
|
||||
virtual bool SendSet(const ObjectId& objId, const ObjectVariant& receiverVar,
|
||||
const JSIDVariant &id, const JSVariant &value,
|
||||
ReturnStatus *rs, JSVariant *result) = 0;
|
||||
const JSIDVariant& id, const bool& strict,
|
||||
const JSVariant& value, ReturnStatus* rs, JSVariant* result) = 0;
|
||||
|
||||
virtual bool SendIsExtensible(const ObjectId& objId, ReturnStatus* rs,
|
||||
bool* result) = 0;
|
||||
|
||||
+3
-125
@@ -44,127 +44,6 @@ namespace JS {
|
||||
|
||||
class AutoIdVector;
|
||||
|
||||
/*
|
||||
* Per ES6, the [[DefineOwnProperty]] internal method has three different
|
||||
* possible outcomes:
|
||||
*
|
||||
* - It can throw an exception (which we indicate by returning false).
|
||||
*
|
||||
* - It can return true, indicating unvarnished success.
|
||||
*
|
||||
* - It can return false, indicating "strict failure". The property could
|
||||
* not be defined. It's an error, but no exception was thrown.
|
||||
*
|
||||
* It's not just [[DefineOwnProperty]]: all the mutating internal methods have
|
||||
* the same three outcomes. (The other affected internal methods are [[Set]],
|
||||
* [[Delete]], [[SetPrototypeOf]], and [[PreventExtensions]].)
|
||||
*
|
||||
* If you think this design is awful, you're not alone. But as it's the
|
||||
* standard, we must represent these boolean "success" values somehow.
|
||||
* ObjectOpSuccess is the class for this. It's like a bool, but when it's false
|
||||
* it also stores an error code.
|
||||
*
|
||||
* Typical usage:
|
||||
*
|
||||
* ObjectOpResult result;
|
||||
* if (!DefineProperty(cx, obj, id, ..., result))
|
||||
* return false;
|
||||
* if (!result)
|
||||
* return result.reportError(cx, obj, id);
|
||||
*
|
||||
* Users don't have to call `result.report()`; another possible ending is:
|
||||
*
|
||||
* argv.rval().setBoolean(bool(result));
|
||||
* return true;
|
||||
*/
|
||||
class ObjectOpResult
|
||||
{
|
||||
private:
|
||||
uint32_t code_;
|
||||
|
||||
public:
|
||||
enum { OkCode = 0, Uninitialized = 0xffffffff };
|
||||
|
||||
ObjectOpResult() : code_(Uninitialized) {}
|
||||
|
||||
/* Return true if fail() was not called. */
|
||||
bool ok() const {
|
||||
MOZ_ASSERT(code_ != Uninitialized);
|
||||
return code_ == OkCode;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return ok(); }
|
||||
|
||||
/* Set this ObjectOpResult to true and return true. */
|
||||
bool succeed() {
|
||||
code_ = OkCode;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set this ObjectOpResult to false with an error code.
|
||||
*
|
||||
* Always returns true, as a convenience. Typical usage will be:
|
||||
*
|
||||
* if (funny condition)
|
||||
* return result.fail(JSMSG_CANT_DO_THE_THINGS);
|
||||
*
|
||||
* The true return value indicates that no exception is pending, and it
|
||||
* would be OK to ignore the failure and continue.
|
||||
*/
|
||||
bool fail(uint32_t msg) {
|
||||
MOZ_ASSERT(msg != OkCode);
|
||||
code_ = msg;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool) failCantRedefineProp();
|
||||
JS_PUBLIC_API(bool) failReadOnly();
|
||||
JS_PUBLIC_API(bool) failGetterOnly();
|
||||
JS_PUBLIC_API(bool) failCantSetInterposed();
|
||||
|
||||
uint32_t failureCode() const {
|
||||
MOZ_ASSERT(!ok());
|
||||
return code_;
|
||||
}
|
||||
|
||||
/*
|
||||
* Report an error or warning if necessary; return true to proceed and
|
||||
* false if an error was reported. Call this when failure should cause
|
||||
* a warning if extraWarnings are enabled.
|
||||
*
|
||||
* The precise rules are like this:
|
||||
*
|
||||
* - If ok(), then we succeeded. Do nothing and return true.
|
||||
* - Otherwise, if |strict| is true, or if cx has both extraWarnings and
|
||||
* werrorOption enabled, throw a TypeError and return false.
|
||||
* - Otherwise, if cx has extraWarnings enabled, emit a warning and
|
||||
* return true.
|
||||
* - Otherwise, do nothing and return true.
|
||||
*/
|
||||
bool checkStrictErrorOrWarning(JSContext *cx, HandleObject obj, HandleId id, bool strict) {
|
||||
if (ok())
|
||||
return true;
|
||||
return reportStrictErrorOrWarning(cx, obj, id, strict);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience method. Return true if ok() or if strict is false; otherwise
|
||||
* throw a TypeError and return false.
|
||||
*/
|
||||
bool checkStrict(JSContext *cx, HandleObject obj, HandleId id) {
|
||||
return checkStrictErrorOrWarning(cx, obj, id, true);
|
||||
}
|
||||
|
||||
/* Throw a TypeError. Call this only if !ok(). */
|
||||
bool reportError(JSContext *cx, HandleObject obj, HandleId id) {
|
||||
return reportStrictErrorOrWarning(cx, obj, id, true);
|
||||
}
|
||||
|
||||
/* Helper function for checkStrictErrorOrWarning's slow path. */
|
||||
JS_PUBLIC_API(bool) reportStrictErrorOrWarning(JSContext *cx, HandleObject obj, HandleId id, bool strict);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// JSClass operation signatures.
|
||||
@@ -183,7 +62,7 @@ typedef bool
|
||||
// set.
|
||||
typedef bool
|
||||
(* JSStrictPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::MutableHandleValue vp, JS::ObjectOpResult &result);
|
||||
bool strict, JS::MutableHandleValue vp);
|
||||
|
||||
// Delete a property named by id in obj.
|
||||
//
|
||||
@@ -287,8 +166,7 @@ typedef bool
|
||||
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
|
||||
typedef bool
|
||||
(* DefinePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs,
|
||||
JS::ObjectOpResult &result);
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
|
||||
typedef bool
|
||||
(* HasPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
|
||||
typedef bool
|
||||
@@ -296,7 +174,7 @@ typedef bool
|
||||
JS::MutableHandleValue vp);
|
||||
typedef bool
|
||||
(* SetPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
|
||||
JS::MutableHandleValue vp, JS::ObjectOpResult &result);
|
||||
JS::MutableHandleValue vp, bool strict);
|
||||
typedef bool
|
||||
(* GetOwnPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||
|
||||
+5
-9
@@ -26,7 +26,6 @@ using JS::MutableHandle;
|
||||
using JS::MutableHandleObject;
|
||||
using JS::MutableHandleValue;
|
||||
using JS::NativeImpl;
|
||||
using JS::ObjectOpResult;
|
||||
using JS::PrivateValue;
|
||||
using JS::Value;
|
||||
|
||||
@@ -252,8 +251,7 @@ class JS_FRIEND_API(BaseProxyHandler)
|
||||
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc) const = 0;
|
||||
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc,
|
||||
ObjectOpResult &result) const = 0;
|
||||
MutableHandle<JSPropertyDescriptor> desc) const = 0;
|
||||
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
|
||||
AutoIdVector& props) const = 0;
|
||||
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const = 0;
|
||||
@@ -291,7 +289,7 @@ class JS_FRIEND_API(BaseProxyHandler)
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp) const;
|
||||
virtual bool set(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const;
|
||||
HandleId id, bool strict, MutableHandleValue vp) const;
|
||||
|
||||
/*
|
||||
* [[Call]] and [[Construct]] are standard internal methods but according
|
||||
@@ -370,8 +368,7 @@ class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler
|
||||
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc) const override;
|
||||
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc,
|
||||
ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
MutableHandle<JSPropertyDescriptor> desc) const override;
|
||||
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
|
||||
AutoIdVector& props) const override;
|
||||
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
@@ -391,8 +388,7 @@ class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler
|
||||
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp) const override;
|
||||
virtual bool set(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp,
|
||||
ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
HandleId id, bool strict, MutableHandleValue vp) const override;
|
||||
virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
|
||||
virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
|
||||
|
||||
@@ -586,7 +582,7 @@ class MOZ_STACK_CLASS ProxyOptions {
|
||||
|
||||
JS_FRIEND_API(JSObject*)
|
||||
NewProxyObject(JSContext* cx, const BaseProxyHandler* handler, HandleValue priv,
|
||||
JSObject* proto, const ProxyOptions& options = ProxyOptions());
|
||||
JSObject* proto, JSObject* parent, const ProxyOptions& options = ProxyOptions());
|
||||
|
||||
JSObject*
|
||||
RenewProxyObject(JSContext* cx, JSObject* obj, BaseProxyHandler* handler, Value priv);
|
||||
|
||||
@@ -45,7 +45,6 @@ class MOZ_STACK_CLASS SourceBufferHolder;
|
||||
|
||||
class HandleValueArray;
|
||||
|
||||
class ObjectOpResult;
|
||||
}
|
||||
|
||||
// Do the importing.
|
||||
@@ -144,8 +143,6 @@ using JS::FalseHandleValue;
|
||||
|
||||
using JS::HandleValueArray;
|
||||
|
||||
using JS::ObjectOpResult;
|
||||
|
||||
using JS::Zone;
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
@@ -833,7 +833,8 @@ js::obj_defineProperty(JSContext* cx, unsigned argc, Value* vp)
|
||||
if (!desc.initialize(cx, args.get(2)))
|
||||
return false;
|
||||
|
||||
if (!StandardDefineProperty(cx, obj, id, desc))
|
||||
bool ignored;
|
||||
if (!StandardDefineProperty(cx, obj, id, desc, true, &ignored))
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
|
||||
@@ -1858,10 +1858,8 @@ EnableTraceLogger(JSContext* cx, unsigned argc, jsval* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
|
||||
if (!TraceLoggerEnable(logger, cx))
|
||||
return false;
|
||||
args.rval().setBoolean(TraceLoggerEnable(logger, cx));
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1884,7 +1882,7 @@ DumpObject(JSContext* cx, unsigned argc, jsval* vp)
|
||||
if (!JS_ConvertArguments(cx, args, "o", obj.address()))
|
||||
return false;
|
||||
|
||||
DumpObject(obj);
|
||||
js_DumpObject(obj);
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
@@ -1929,7 +1927,7 @@ static bool
|
||||
DumpBacktrace(JSContext* cx, unsigned argc, jsval* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
DumpBacktrace(cx);
|
||||
js_DumpBacktrace(cx);
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1755,8 +1755,7 @@ ReportPropertyError(JSContext* cx,
|
||||
|
||||
bool
|
||||
TypedObject::obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
|
||||
ObjectOpResult &result)
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
|
||||
{
|
||||
Rooted<TypedObject*> typedObj(cx, &obj->as<TypedObject>());
|
||||
return ReportTypedObjTypeError(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, typedObj);
|
||||
@@ -1908,7 +1907,7 @@ TypedObject::obj_getArrayElement(JSContext* cx,
|
||||
|
||||
bool
|
||||
TypedObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp, ObjectOpResult &result)
|
||||
MutableHandleValue vp, bool strict)
|
||||
{
|
||||
Rooted<TypedObject*> typedObj(cx, &obj->as<TypedObject>());
|
||||
|
||||
@@ -1927,13 +1926,13 @@ TypedObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleObject recei
|
||||
nullptr, JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
|
||||
return false;
|
||||
}
|
||||
return result.failReadOnly();
|
||||
return SetNonWritableProperty(cx, id, strict);
|
||||
}
|
||||
|
||||
uint32_t index;
|
||||
if (IdIsIndex(id, &index)) {
|
||||
if (obj != receiver)
|
||||
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
|
||||
return SetPropertyByDefining(cx, obj, receiver, id, vp, strict, false);
|
||||
|
||||
if (index >= uint32_t(typedObj->length())) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage,
|
||||
@@ -1944,9 +1943,7 @@ TypedObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleObject recei
|
||||
Rooted<TypeDescr*> elementType(cx);
|
||||
elementType = &typedObj->typeDescr().as<ArrayTypeDescr>().elementType();
|
||||
size_t offset = elementType->size() * index;
|
||||
if (!ConvertAndCopyTo(cx, elementType, typedObj, offset, NullPtr(), vp))
|
||||
return false;
|
||||
return result.succeed();
|
||||
return ConvertAndCopyTo(cx, elementType, typedObj, offset, NullPtr(), vp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1959,18 +1956,16 @@ TypedObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleObject recei
|
||||
break;
|
||||
|
||||
if (obj != receiver)
|
||||
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
|
||||
return SetPropertyByDefining(cx, obj, receiver, id, vp, strict, false);
|
||||
|
||||
size_t offset = descr->fieldOffset(fieldIndex);
|
||||
Rooted<TypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
|
||||
RootedAtom fieldName(cx, &descr->fieldName(fieldIndex));
|
||||
if (!ConvertAndCopyTo(cx, fieldType, typedObj, offset, fieldName, vp))
|
||||
return false;
|
||||
return result.succeed();
|
||||
return ConvertAndCopyTo(cx, fieldType, typedObj, offset, fieldName, vp);
|
||||
}
|
||||
}
|
||||
|
||||
return SetPropertyOnProto(cx, obj, receiver, id, vp, result);
|
||||
return SetPropertyOnProto(cx, obj, receiver, id, vp, strict);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -528,8 +528,7 @@ class TypedObject : public JSObject
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
|
||||
static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
|
||||
ObjectOpResult &result);
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||
|
||||
static bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
|
||||
|
||||
@@ -540,7 +539,7 @@ class TypedObject : public JSObject
|
||||
uint32_t index, MutableHandleValue vp);
|
||||
|
||||
static bool obj_setProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp, ObjectOpResult &result);
|
||||
HandleId id, MutableHandleValue vp, bool strict);
|
||||
|
||||
static bool obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc);
|
||||
|
||||
+10
-17
@@ -287,8 +287,7 @@ namespace ArrayType {
|
||||
bool LengthGetter(JSContext* cx, const JS::CallArgs& args);
|
||||
|
||||
static bool Getter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp);
|
||||
static bool Setter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp,
|
||||
ObjectOpResult &result);
|
||||
static bool Setter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, MutableHandleValue vp);
|
||||
static bool AddressOfElement(JSContext* cx, unsigned argc, jsval* vp);
|
||||
}
|
||||
|
||||
@@ -301,9 +300,9 @@ namespace StructType {
|
||||
bool FieldsArrayGetter(JSContext* cx, const JS::CallArgs& args);
|
||||
|
||||
static bool FieldGetter(JSContext* cx, HandleObject obj, HandleId idval,
|
||||
MutableHandleValue vp);
|
||||
static bool FieldSetter(JSContext* cx, HandleObject obj, HandleId idval,
|
||||
MutableHandleValue vp, ObjectOpResult &result);
|
||||
MutableHandleValue vp);
|
||||
static bool FieldSetter(JSContext* cx, HandleObject obj, HandleId idval, bool strict,
|
||||
MutableHandleValue vp);
|
||||
static bool AddressOfField(JSContext* cx, unsigned argc, jsval* vp);
|
||||
static bool Define(JSContext* cx, unsigned argc, jsval* vp);
|
||||
}
|
||||
@@ -4629,8 +4628,7 @@ ArrayType::Getter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandle
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp,
|
||||
ObjectOpResult &result)
|
||||
ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, MutableHandleValue vp)
|
||||
{
|
||||
// This should never happen, but we'll check to be safe.
|
||||
if (!CData::IsCData(obj)) {
|
||||
@@ -4642,7 +4640,7 @@ ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandle
|
||||
// CData, regardless of CType.)
|
||||
JSObject* typeObj = CData::GetCType(obj);
|
||||
if (CType::GetTypeCode(typeObj) != TYPE_array)
|
||||
return result.succeed();
|
||||
return true;
|
||||
|
||||
// Convert the index to a size_t and bounds-check it.
|
||||
size_t index;
|
||||
@@ -4652,7 +4650,7 @@ ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandle
|
||||
if (!ok && JSID_IS_STRING(idval) && !StringToInteger(cx, JSID_TO_STRING(idval), &dummy)) {
|
||||
// String either isn't a number, or doesn't fit in size_t.
|
||||
// Chances are it's a regular property lookup, so return.
|
||||
return result.succeed();
|
||||
return true;
|
||||
}
|
||||
if (!ok || index >= length) {
|
||||
JS_ReportError(cx, "invalid index");
|
||||
@@ -4662,9 +4660,7 @@ ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandle
|
||||
JSObject* baseType = GetBaseType(typeObj);
|
||||
size_t elementSize = CType::GetSize(baseType);
|
||||
char* data = static_cast<char*>(CData::GetData(obj)) + elementSize * index;
|
||||
if (!ImplicitConvert(cx, vp, baseType, data, false, nullptr))
|
||||
return false;
|
||||
return result.succeed();
|
||||
return ImplicitConvert(cx, vp, baseType, data, false, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -5297,8 +5293,7 @@ StructType::FieldGetter(JSContext* cx, HandleObject obj, HandleId idval, Mutable
|
||||
}
|
||||
|
||||
bool
|
||||
StructType::FieldSetter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp,
|
||||
ObjectOpResult &result)
|
||||
StructType::FieldSetter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, MutableHandleValue vp)
|
||||
{
|
||||
if (!CData::IsCData(obj)) {
|
||||
JS_ReportError(cx, "not a CData");
|
||||
@@ -5316,9 +5311,7 @@ StructType::FieldSetter(JSContext* cx, HandleObject obj, HandleId idval, Mutable
|
||||
return false;
|
||||
|
||||
char* data = static_cast<char*>(CData::GetData(obj)) + field->mOffset;
|
||||
if (!ImplicitConvert(cx, vp, field->mType, data, false, nullptr))
|
||||
return false;
|
||||
return result.succeed();
|
||||
return ImplicitConvert(cx, vp, field->mType, data, false, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -6571,6 +6571,8 @@ static bool
|
||||
EmitPropertyList(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
MutableHandlePlainObject objp, PropListType type)
|
||||
{
|
||||
MOZ_ASSERT(type == ObjectLiteral);
|
||||
|
||||
for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
|
||||
if (!UpdateSourceCoordNotes(cx, bce, propdef->pn_pos.begin))
|
||||
return false;
|
||||
@@ -6578,7 +6580,6 @@ EmitPropertyList(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
// Handle __proto__: v specially because *only* this form, and no other
|
||||
// involving "__proto__", performs [[Prototype]] mutation.
|
||||
if (propdef->isKind(PNK_MUTATEPROTO)) {
|
||||
MOZ_ASSERT(type == ObjectLiteral);
|
||||
if (!EmitTree(cx, bce, propdef->pn_kid))
|
||||
return false;
|
||||
objp.set(nullptr);
|
||||
@@ -6595,10 +6596,6 @@ EmitPropertyList(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
return false;
|
||||
isIndex = true;
|
||||
} else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
|
||||
// EmitClass took care of constructor already.
|
||||
if (type == ClassBody && key->pn_atom == cx->names().constructor)
|
||||
continue;
|
||||
|
||||
// The parser already checked for atoms representing indexes and
|
||||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
// as indexes for simpliciation of downstream analysis.
|
||||
@@ -6927,80 +6924,6 @@ EmitLexicalInitialization(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode
|
||||
return true;
|
||||
}
|
||||
|
||||
// This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15
|
||||
// (BindingClassDeclarationEvaluation).
|
||||
static bool
|
||||
EmitClass(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
{
|
||||
ClassNode &classNode = pn->as<ClassNode>();
|
||||
|
||||
ClassNames *names = classNode.names();
|
||||
|
||||
MOZ_ASSERT(!classNode.heritage(), "For now, no heritage expressions");
|
||||
LexicalScopeNode *innerBlock = classNode.scope();
|
||||
|
||||
ParseNode *classMethods = innerBlock->pn_expr;
|
||||
MOZ_ASSERT(classMethods->isKind(PNK_CLASSMETHODLIST));
|
||||
|
||||
ParseNode *constructor = nullptr;
|
||||
for (ParseNode *mn = classMethods->pn_head; mn; mn = mn->pn_next) {
|
||||
ClassMethod &method = mn->as<ClassMethod>();
|
||||
ParseNode &methodName = method.name();
|
||||
if (methodName.isKind(PNK_OBJECT_PROPERTY_NAME) &&
|
||||
methodName.pn_atom == cx->names().constructor)
|
||||
{
|
||||
constructor = &method.method();
|
||||
break;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(constructor, "For now, no default constructors");
|
||||
|
||||
bool savedStrictness = bce->sc->setLocalStrictMode(true);
|
||||
|
||||
StmtInfoBCE stmtInfo(cx);
|
||||
if (!EnterBlockScope(cx, bce, &stmtInfo, innerBlock->pn_objbox, JSOP_UNINITIALIZED))
|
||||
return false;
|
||||
|
||||
if (!EmitFunc(cx, bce, constructor))
|
||||
return false;
|
||||
|
||||
if (!EmitNewInit(cx, bce, JSProto_Object))
|
||||
return false;
|
||||
|
||||
if (Emit1(cx, bce, JSOP_DUP2) < 0)
|
||||
return false;
|
||||
if (!EmitAtomOp(cx, cx->names().prototype, JSOP_INITLOCKEDPROP, bce))
|
||||
return false;
|
||||
if (!EmitAtomOp(cx, cx->names().constructor, JSOP_INITHIDDENPROP, bce))
|
||||
return false;
|
||||
|
||||
RootedPlainObject obj(cx);
|
||||
if (!EmitPropertyList(cx, bce, classMethods, &obj, ClassBody))
|
||||
return false;
|
||||
|
||||
if (Emit1(cx, bce, JSOP_POP) < 0)
|
||||
return false;
|
||||
|
||||
// That DEFCONST is never gonna be used, but use it here for logical consistency.
|
||||
ParseNode *innerName = names->innerBinding();
|
||||
if (!EmitLexicalInitialization(cx, bce, innerName, JSOP_DEFCONST))
|
||||
return false;
|
||||
|
||||
if (!LeaveNestedScope(cx, bce, &stmtInfo))
|
||||
return false;
|
||||
|
||||
ParseNode *outerName = names->outerBinding();
|
||||
if (!EmitLexicalInitialization(cx, bce, outerName, JSOP_DEFVAR))
|
||||
return false;
|
||||
|
||||
if (Emit1(cx, bce, JSOP_POP) < 0)
|
||||
return false;
|
||||
|
||||
MOZ_ALWAYS_TRUE(bce->sc->setLocalStrictMode(savedStrictness));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::EmitTree(ExclusiveContext* cx, BytecodeEmitter* bce, ParseNode* pn)
|
||||
{
|
||||
@@ -7460,8 +7383,9 @@ frontend::EmitTree(ExclusiveContext* cx, BytecodeEmitter* bce, ParseNode* pn)
|
||||
break;
|
||||
|
||||
case PNK_CLASS:
|
||||
ok = EmitClass(cx, bce, pn);
|
||||
break;
|
||||
// TODO: Implement emitter support for classes
|
||||
bce->reportError(nullptr, JSMSG_CLASS_NOT_IMPLEMENTED);
|
||||
return false;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(0);
|
||||
@@ -7901,7 +7825,7 @@ SrcNoteArity(jssrcnote* sn)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(unsigned)
|
||||
js::SrcNoteLength(jssrcnote *sn)
|
||||
js_SrcNoteLength(jssrcnote* sn)
|
||||
{
|
||||
unsigned arity;
|
||||
jssrcnote* base;
|
||||
@@ -7915,7 +7839,7 @@ js::SrcNoteLength(jssrcnote *sn)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(ptrdiff_t)
|
||||
js::GetSrcNoteOffset(jssrcnote *sn, unsigned which)
|
||||
js_GetSrcNoteOffset(jssrcnote* sn, unsigned which)
|
||||
{
|
||||
/* Find the offset numbered which (i.e., skip exactly which offsets). */
|
||||
MOZ_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
|
||||
|
||||
@@ -73,7 +73,7 @@ AtomDecls<ParseHandler>::dump()
|
||||
{
|
||||
for (AtomDefnListRange r = map->all(); !r.empty(); r.popFront()) {
|
||||
fprintf(stderr, "atom: ");
|
||||
DumpAtom(r.front().key());
|
||||
js_DumpAtom(r.front().key());
|
||||
const DefinitionList& dlist = r.front().value();
|
||||
for (DefinitionList::Range dr = dlist.all(); !dr.empty(); dr.popFront()) {
|
||||
fprintf(stderr, " defn: %p\n", (void*) dr.front<ParseHandler>());
|
||||
@@ -91,7 +91,7 @@ DumpAtomDefnMap(const AtomDefnMapPtr& map)
|
||||
|
||||
for (AtomDefnRange r = map->all(); !r.empty(); r.popFront()) {
|
||||
fprintf(stderr, "atom: ");
|
||||
DumpAtom(r.front().key());
|
||||
js_DumpAtom(r.front().key());
|
||||
fprintf(stderr, "defn: %p\n", (void*) r.front().value().get<FullParseHandler>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ SN_COLSPAN_TO_OFFSET(ptrdiff_t colspan) {
|
||||
}
|
||||
|
||||
#define SN_LENGTH(sn) ((js_SrcNoteSpec[SN_TYPE(sn)].arity == 0) ? 1 \
|
||||
: js::SrcNoteLength(sn))
|
||||
: js_SrcNoteLength(sn))
|
||||
#define SN_NEXT(sn) ((sn) + SN_LENGTH(sn))
|
||||
|
||||
struct JSSrcNoteSpec {
|
||||
@@ -193,18 +193,12 @@ struct JSSrcNoteSpec {
|
||||
};
|
||||
|
||||
extern JS_FRIEND_DATA(const JSSrcNoteSpec) js_SrcNoteSpec[];
|
||||
|
||||
namespace js {
|
||||
|
||||
extern JS_FRIEND_API(unsigned)
|
||||
SrcNoteLength(jssrcnote *sn);
|
||||
extern JS_FRIEND_API(unsigned) js_SrcNoteLength(jssrcnote* sn);
|
||||
|
||||
/*
|
||||
* Get and set the offset operand identified by which (0 for the first, etc.).
|
||||
*/
|
||||
extern JS_FRIEND_API(ptrdiff_t)
|
||||
GetSrcNoteOffset(jssrcnote* sn, unsigned which);
|
||||
|
||||
}
|
||||
js_GetSrcNoteOffset(jssrcnote* sn, unsigned which);
|
||||
|
||||
#endif /* frontend_SourceNotes_h */
|
||||
|
||||
@@ -1447,9 +1447,6 @@ ScanObjectGroup(GCMarker* gcmarker, ObjectGroup* group)
|
||||
if (group->newScript())
|
||||
group->newScript()->trace(gcmarker);
|
||||
|
||||
if (group->maybePreliminaryObjects())
|
||||
group->maybePreliminaryObjects()->trace(gcmarker);
|
||||
|
||||
if (group->maybeUnboxedLayout())
|
||||
group->unboxedLayout().trace(gcmarker);
|
||||
|
||||
@@ -1481,9 +1478,6 @@ gc::MarkChildren(JSTracer* trc, ObjectGroup* group)
|
||||
if (group->newScript())
|
||||
group->newScript()->trace(trc);
|
||||
|
||||
if (group->maybePreliminaryObjects())
|
||||
group->maybePreliminaryObjects()->trace(trc);
|
||||
|
||||
if (group->maybeUnboxedLayout())
|
||||
group->unboxedLayout().trace(trc);
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ check("o[- (o)]");
|
||||
|
||||
// A few one off tests
|
||||
check_one("6", (function () { 6() }), " is not a function");
|
||||
check_one("0", (function () { Array.prototype.reverse.call('123'); }), " is read-only");
|
||||
check_one("Array.prototype.reverse.call(...)", (function () { Array.prototype.reverse.call('123'); }), " is read-only");
|
||||
check_one(`(intermediate value)[Symbol.iterator](...).next(...).value`,
|
||||
function () { var [{ x }] = [null, {}]; }, " is null");
|
||||
check_one(`(intermediate value)[Symbol.iterator](...).next(...).value`,
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
|
||||
function f(x) {
|
||||
return x >>> 0 !== Math.imul(1, x >>> 0);
|
||||
}
|
||||
f(0)
|
||||
assertEq(f(-1),true)
|
||||
|
||||
function g(x) {
|
||||
return 2147483647+x !== Math.imul(1, 2147483647+x);
|
||||
}
|
||||
g(0)
|
||||
assertEq(g(1),true)
|
||||
|
||||
function h(x) {
|
||||
if (2147483647+x !== Math.imul(1, 2147483647+x))
|
||||
return true;
|
||||
return (2147483647+x)|0
|
||||
}
|
||||
h(0)
|
||||
assertEq(h(1), true)
|
||||
|
||||
function i2(x) {
|
||||
return x === x
|
||||
}
|
||||
function i(x) {
|
||||
return i2(0 / Math.sign(x > 0))
|
||||
}
|
||||
i(1)
|
||||
assertEq(i(-1), false)
|
||||
@@ -1,13 +0,0 @@
|
||||
// |jit-test| error:Error
|
||||
(function(b, foreign, p) {
|
||||
"use asm"
|
||||
var ff = foreign.ff
|
||||
function f() {
|
||||
ff() | 0
|
||||
}
|
||||
return f
|
||||
})(this, {
|
||||
ff: startTraceLogger
|
||||
}, ArrayBuffer)()
|
||||
|
||||
|
||||
@@ -1813,10 +1813,47 @@ BaselineCompiler::emit_JSOP_NEWOBJECT()
|
||||
{
|
||||
frame.syncStack(0);
|
||||
|
||||
ICNewObject_Fallback::Compiler stubCompiler(cx);
|
||||
RootedObjectGroup group(cx);
|
||||
if (!ObjectGroup::useSingletonForAllocationSite(script, pc, JSProto_Object)) {
|
||||
group = ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Object);
|
||||
if (!group)
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedPlainObject baseObject(cx, &script->getObject(pc)->as<PlainObject>());
|
||||
RootedPlainObject templateObject(cx, CopyInitializerObject(cx, baseObject, TenuredObject));
|
||||
if (!templateObject)
|
||||
return false;
|
||||
|
||||
if (group) {
|
||||
templateObject->setGroup(group);
|
||||
} else {
|
||||
if (!JSObject::setSingleton(cx, templateObject))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to do the allocation inline.
|
||||
Label done;
|
||||
if (group && !group->shouldPreTenure() && !templateObject->hasDynamicSlots()) {
|
||||
Label slowPath;
|
||||
Register objReg = R0.scratchReg();
|
||||
Register tempReg = R1.scratchReg();
|
||||
masm.movePtr(ImmGCPtr(group), tempReg);
|
||||
masm.branchTest32(Assembler::NonZero, Address(tempReg, ObjectGroup::offsetOfFlags()),
|
||||
Imm32(OBJECT_FLAG_PRE_TENURE), &slowPath);
|
||||
masm.branchPtr(Assembler::NotEqual, AbsoluteAddress(cx->compartment()->addressOfMetadataCallback()),
|
||||
ImmWord(0), &slowPath);
|
||||
masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap, &slowPath);
|
||||
masm.tagValue(JSVAL_TYPE_OBJECT, objReg, R0);
|
||||
masm.jump(&done);
|
||||
masm.bind(&slowPath);
|
||||
}
|
||||
|
||||
ICNewObject_Fallback::Compiler stubCompiler(cx, templateObject);
|
||||
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
|
||||
return false;
|
||||
|
||||
masm.bind(&done);
|
||||
frame.push(R0);
|
||||
return true;
|
||||
}
|
||||
@@ -1850,7 +1887,19 @@ BaselineCompiler::emit_JSOP_NEWINIT()
|
||||
} else {
|
||||
MOZ_ASSERT(key == JSProto_Object);
|
||||
|
||||
ICNewObject_Fallback::Compiler stubCompiler(cx);
|
||||
RootedPlainObject templateObject(cx,
|
||||
NewBuiltinClassInstance<PlainObject>(cx, TenuredObject));
|
||||
if (!templateObject)
|
||||
return false;
|
||||
|
||||
if (group) {
|
||||
templateObject->setGroup(group);
|
||||
} else {
|
||||
if (!JSObject::setSingleton(cx, templateObject))
|
||||
return false;
|
||||
}
|
||||
|
||||
ICNewObject_Fallback::Compiler stubCompiler(cx, templateObject);
|
||||
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
|
||||
return false;
|
||||
}
|
||||
|
||||
+145
-194
@@ -165,16 +165,6 @@ ICStub::updateCode(JitCode* code)
|
||||
stubCode_ = code->raw();
|
||||
}
|
||||
|
||||
void
|
||||
ReceiverGuard::trace(JSTracer *trc)
|
||||
{
|
||||
MOZ_ASSERT(!!shape_ != !!group_);
|
||||
if (shape_)
|
||||
MarkShape(trc, &shape_, "receiver_guard_shape");
|
||||
else
|
||||
MarkObjectGroup(trc, &group_, "receiver_guard_group");
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ICStub::trace(JSTracer* trc)
|
||||
{
|
||||
@@ -352,14 +342,20 @@ ICStub::trace(JSTracer* trc)
|
||||
}
|
||||
case ICStub::GetProp_NativePrototype: {
|
||||
ICGetProp_NativePrototype* propStub = toGetProp_NativePrototype();
|
||||
propStub->guard().trace(trc);
|
||||
MarkShape(trc, &propStub->shape(), "baseline-getpropnativeproto-stub-shape");
|
||||
MarkObject(trc, &propStub->holder(), "baseline-getpropnativeproto-stub-holder");
|
||||
MarkShape(trc, &propStub->holderShape(), "baseline-getpropnativeproto-stub-holdershape");
|
||||
break;
|
||||
}
|
||||
case ICStub::GetProp_UnboxedPrototype: {
|
||||
ICGetProp_UnboxedPrototype* propStub = toGetProp_UnboxedPrototype();
|
||||
MarkObjectGroup(trc, &propStub->group(), "baseline-getpropnativeproto-stub-group");
|
||||
MarkObject(trc, &propStub->holder(), "baseline-getpropnativeproto-stub-holder");
|
||||
MarkShape(trc, &propStub->holderShape(), "baseline-getpropnativeproto-stub-holdershape");
|
||||
break;
|
||||
}
|
||||
case ICStub::GetProp_NativeDoesNotExist: {
|
||||
ICGetProp_NativeDoesNotExist* propStub = toGetProp_NativeDoesNotExist();
|
||||
propStub->guard().trace(trc);
|
||||
JS_STATIC_ASSERT(ICGetProp_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH == 8);
|
||||
switch (propStub->protoChainDepth()) {
|
||||
case 0: propStub->toImpl<0>()->traceShapes(trc); break;
|
||||
@@ -410,7 +406,7 @@ ICStub::trace(JSTracer* trc)
|
||||
}
|
||||
case ICStub::GetProp_CallScripted: {
|
||||
ICGetProp_CallScripted* callStub = toGetProp_CallScripted();
|
||||
callStub->receiverGuard().trace(trc);
|
||||
MarkShape(trc, &callStub->receiverShape(), "baseline-getpropcallscripted-stub-receivershape");
|
||||
MarkObject(trc, &callStub->holder(), "baseline-getpropcallscripted-stub-holder");
|
||||
MarkShape(trc, &callStub->holderShape(), "baseline-getpropcallscripted-stub-holdershape");
|
||||
MarkObject(trc, &callStub->getter(), "baseline-getpropcallscripted-stub-getter");
|
||||
@@ -425,7 +421,7 @@ ICStub::trace(JSTracer* trc)
|
||||
}
|
||||
case ICStub::GetProp_CallNativePrototype: {
|
||||
ICGetProp_CallNativePrototype* callStub = toGetProp_CallNativePrototype();
|
||||
callStub->receiverGuard().trace(trc);
|
||||
MarkShape(trc, &callStub->receiverShape(), "baseline-getpropcallnativeproto-stub-receivershape");
|
||||
MarkObject(trc, &callStub->holder(), "baseline-getpropcallnativeproto-stub-holder");
|
||||
MarkShape(trc, &callStub->holderShape(), "baseline-getpropcallnativeproto-stub-holdershape");
|
||||
MarkObject(trc, &callStub->getter(), "baseline-getpropcallnativeproto-stub-getter");
|
||||
@@ -467,7 +463,7 @@ ICStub::trace(JSTracer* trc)
|
||||
}
|
||||
case ICStub::SetProp_CallScripted: {
|
||||
ICSetProp_CallScripted* callStub = toSetProp_CallScripted();
|
||||
callStub->guard().trace(trc);
|
||||
MarkShape(trc, &callStub->shape(), "baseline-setpropcallscripted-stub-shape");
|
||||
MarkObject(trc, &callStub->holder(), "baseline-setpropcallscripted-stub-holder");
|
||||
MarkShape(trc, &callStub->holderShape(), "baseline-setpropcallscripted-stub-holdershape");
|
||||
MarkObject(trc, &callStub->setter(), "baseline-setpropcallscripted-stub-setter");
|
||||
@@ -475,7 +471,7 @@ ICStub::trace(JSTracer* trc)
|
||||
}
|
||||
case ICStub::SetProp_CallNative: {
|
||||
ICSetProp_CallNative* callStub = toSetProp_CallNative();
|
||||
callStub->guard().trace(trc);
|
||||
MarkShape(trc, &callStub->shape(), "baseline-setpropcallnative-stub-shape");
|
||||
MarkObject(trc, &callStub->holder(), "baseline-setpropcallnative-stub-holder");
|
||||
MarkShape(trc, &callStub->holderShape(), "baseline-setpropcallnative-stub-holdershape");
|
||||
MarkObject(trc, &callStub->setter(), "baseline-setpropcallnative-stub-setter");
|
||||
@@ -494,8 +490,7 @@ ICStub::trace(JSTracer* trc)
|
||||
}
|
||||
case ICStub::NewObject_Fallback: {
|
||||
ICNewObject_Fallback* stub = toNewObject_Fallback();
|
||||
if (stub->templateObject())
|
||||
MarkObject(trc, &stub->templateObject(), "baseline-newobject-template");
|
||||
MarkObject(trc, &stub->templateObject(), "baseline-newobject-template");
|
||||
break;
|
||||
}
|
||||
case ICStub::Rest_Fallback: {
|
||||
@@ -1670,80 +1665,13 @@ ICNewArray_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
// NewObject_Fallback
|
||||
//
|
||||
|
||||
|
||||
// Unlike typical baseline IC stubs, the code for NewObject_WithTemplate is
|
||||
// specialized for the template object being allocated.
|
||||
static JitCode *
|
||||
GenerateNewObjectWithTemplateCode(JSContext *cx, JSObject *templateObject)
|
||||
{
|
||||
JitContext jctx(cx, nullptr);
|
||||
MacroAssembler masm;
|
||||
#ifdef JS_CODEGEN_ARM
|
||||
masm.setSecondScratchReg(BaselineSecondScratchReg);
|
||||
#endif
|
||||
|
||||
Label failure;
|
||||
Register objReg = R0.scratchReg();
|
||||
Register tempReg = R1.scratchReg();
|
||||
masm.movePtr(ImmGCPtr(templateObject->group()), tempReg);
|
||||
masm.branchTest32(Assembler::NonZero, Address(tempReg, ObjectGroup::offsetOfFlags()),
|
||||
Imm32(OBJECT_FLAG_PRE_TENURE), &failure);
|
||||
masm.branchPtr(Assembler::NotEqual, AbsoluteAddress(cx->compartment()->addressOfMetadataCallback()),
|
||||
ImmWord(0), &failure);
|
||||
masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap, &failure);
|
||||
masm.tagValue(JSVAL_TYPE_OBJECT, objReg, R0);
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
|
||||
Linker linker(masm);
|
||||
AutoFlushICache afc("GenerateNewObjectWithTemplateCode");
|
||||
return linker.newCode<CanGC>(cx, BASELINE_CODE);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
DoNewObject(JSContext *cx, BaselineFrame *frame, ICNewObject_Fallback *stub, MutableHandleValue res)
|
||||
DoNewObject(JSContext* cx, ICNewObject_Fallback* stub, MutableHandleValue res)
|
||||
{
|
||||
FallbackICSpew(cx, stub, "NewObject");
|
||||
|
||||
RootedObject obj(cx);
|
||||
|
||||
RootedObject templateObject(cx, stub->templateObject());
|
||||
if (templateObject) {
|
||||
MOZ_ASSERT(!templateObject->group()->maybePreliminaryObjects());
|
||||
obj = NewObjectOperationWithTemplate(cx, templateObject);
|
||||
} else {
|
||||
RootedScript script(cx, frame->script());
|
||||
jsbytecode *pc = stub->icEntry()->pc(script);
|
||||
obj = NewObjectOperation(cx, script, pc);
|
||||
|
||||
if (obj && !obj->isSingleton() && !obj->group()->maybePreliminaryObjects()) {
|
||||
JSObject *templateObject = NewObjectOperation(cx, script, pc, TenuredObject);
|
||||
if (!templateObject)
|
||||
return false;
|
||||
|
||||
if (templateObject->is<UnboxedPlainObject>() ||
|
||||
!templateObject->as<PlainObject>().hasDynamicSlots())
|
||||
{
|
||||
JitCode *code = GenerateNewObjectWithTemplateCode(cx, templateObject);
|
||||
if (!code)
|
||||
return false;
|
||||
|
||||
ICStubSpace *space =
|
||||
ICStubCompiler::StubSpaceForKind(ICStub::NewObject_WithTemplate, script);
|
||||
ICStub *templateStub = ICStub::New<ICNewObject_WithTemplate>(space, code);
|
||||
if (!templateStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(templateStub);
|
||||
}
|
||||
|
||||
stub->setTemplateObject(templateObject);
|
||||
}
|
||||
}
|
||||
|
||||
RootedPlainObject templateObject(cx, stub->templateObject());
|
||||
JSObject* obj = NewInitObject(cx, templateObject);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
@@ -1751,7 +1679,7 @@ DoNewObject(JSContext *cx, BaselineFrame *frame, ICNewObject_Fallback *stub, Mut
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool(*DoNewObjectFn)(JSContext *, BaselineFrame *, ICNewObject_Fallback *, MutableHandleValue);
|
||||
typedef bool(*DoNewObjectFn)(JSContext*, ICNewObject_Fallback*, MutableHandleValue);
|
||||
static const VMFunction DoNewObjectInfo = FunctionInfo<DoNewObjectFn>(DoNewObject, TailCall);
|
||||
|
||||
bool
|
||||
@@ -1760,7 +1688,6 @@ ICNewObject_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
masm.push(BaselineStubReg); // stub.
|
||||
masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
|
||||
|
||||
return tailCallVM(DoNewObjectInfo, masm);
|
||||
}
|
||||
@@ -3304,15 +3231,18 @@ EffectlesslyLookupProperty(JSContext* cx, HandleObject obj, HandlePropertyName n
|
||||
checkObj = GetDOMProxyProto(obj);
|
||||
if (!checkObj)
|
||||
return true;
|
||||
} else if (!obj->isNative() && !obj->is<UnboxedPlainObject>()) {
|
||||
} else if (!obj->isNative()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (LookupPropertyPure(cx, checkObj, NameToId(name), holder.address(), shape.address()))
|
||||
return true;
|
||||
|
||||
holder.set(nullptr);
|
||||
shape.set(nullptr);
|
||||
if (checkObj->hasIdempotentProtoChain()) {
|
||||
if (!LookupProperty(cx, checkObj, name, holder, shape))
|
||||
return false;
|
||||
} else if (checkObj->isNative()) {
|
||||
shape.set(checkObj->as<NativeObject>().lookup(cx, NameToId(name)));
|
||||
if (shape)
|
||||
holder.set(checkObj);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3325,21 +3255,16 @@ CheckHasNoSuchProperty(JSContext* cx, HandleObject obj, HandlePropertyName name,
|
||||
size_t depth = 0;
|
||||
RootedObject curObj(cx, obj);
|
||||
while (curObj) {
|
||||
if (curObj->isNative()) {
|
||||
// Don't handle proto chains with resolve hooks.
|
||||
if (curObj->getClass()->resolve)
|
||||
return false;
|
||||
if (!curObj->isNative())
|
||||
return false;
|
||||
|
||||
if (curObj->as<NativeObject>().contains(cx, NameToId(name)))
|
||||
return false;
|
||||
} else {
|
||||
// Handle unboxed plain objects as the original receiver.
|
||||
if (!curObj->is<UnboxedPlainObject>() || curObj != obj)
|
||||
return false;
|
||||
// Don't handle proto chains with resolve hooks.
|
||||
if (curObj->getClass()->resolve)
|
||||
return false;
|
||||
|
||||
if (curObj->as<UnboxedPlainObject>().layout().lookup(name))
|
||||
return false;
|
||||
}
|
||||
Shape* shape = curObj->as<NativeObject>().lookup(cx, NameToId(name));
|
||||
if (shape)
|
||||
return false;
|
||||
|
||||
JSObject* proto = curObj->getTaggedProto().toObjectOrNull();
|
||||
if (!proto)
|
||||
@@ -5390,6 +5315,7 @@ ICSetElem_Dense::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
static bool
|
||||
GetProtoShapes(JSObject* obj, size_t protoChainDepth, AutoShapeVector* shapes)
|
||||
{
|
||||
MOZ_ASSERT(shapes->length() == 1);
|
||||
JSObject* curProto = obj->getProto();
|
||||
for (size_t i = 0; i < protoChainDepth; i++) {
|
||||
if (!shapes->append(curProto->lastProperty()))
|
||||
@@ -5791,20 +5717,20 @@ UpdateExistingGetPropCallStubs(ICFallbackStub* fallbackStub,
|
||||
MOZ_ASSERT(fallbackStub->isGetName_Fallback() ||
|
||||
fallbackStub->isGetProp_Fallback());
|
||||
bool foundMatchingStub = false;
|
||||
ReceiverGuard::Token receiverGuard = receiver ? ReceiverGuard::objectToken(receiver) : 0;
|
||||
Shape* receiverShape = receiver ? receiver->lastProperty() : nullptr;
|
||||
for (ICStubConstIterator iter = fallbackStub->beginChainConst(); !iter.atEnd(); iter++) {
|
||||
if (iter->kind() == kind) {
|
||||
ICGetPropCallGetter* getPropStub = static_cast<ICGetPropCallGetter*>(*iter);
|
||||
if (getPropStub->holder() == holder) {
|
||||
// We want to update the holder shape to match the new one no
|
||||
// matter what, even if the receiver shape is different.
|
||||
ReceiverGuard::Token cachedReceiverGuard;
|
||||
Shape* cachedReceiverShape;
|
||||
if (kind == ICStub::GetProp_CallNative) {
|
||||
cachedReceiverGuard = 0;
|
||||
cachedReceiverShape = nullptr;
|
||||
} else {
|
||||
ICGetPropCallPrototypeGetter* stubWithReceiver =
|
||||
static_cast<ICGetPropCallPrototypeGetter*>(getPropStub);
|
||||
cachedReceiverGuard = stubWithReceiver->receiverGuard().token();
|
||||
cachedReceiverShape = stubWithReceiver->receiverShape();
|
||||
}
|
||||
// We would like to assert that either
|
||||
// getPropStub->holderShape() != holder->lastProperty() or
|
||||
@@ -5820,7 +5746,7 @@ UpdateExistingGetPropCallStubs(ICFallbackStub* fallbackStub,
|
||||
// Make sure to update the getter, since a shape change might
|
||||
// have changed which getter we want to use.
|
||||
getPropStub->getter() = getter;
|
||||
if (receiverGuard == cachedReceiverGuard)
|
||||
if (receiverShape == cachedReceiverShape)
|
||||
foundMatchingStub = true;
|
||||
}
|
||||
}
|
||||
@@ -5833,10 +5759,10 @@ UpdateExistingGetPropCallStubs(ICFallbackStub* fallbackStub,
|
||||
// place with a new shape and setter.
|
||||
static bool
|
||||
UpdateExistingSetPropCallStubs(ICSetProp_Fallback* fallbackStub,
|
||||
ICStub::Kind kind,
|
||||
JSObject *holder,
|
||||
ReceiverGuard::Token receiverGuard,
|
||||
JSFunction *setter)
|
||||
ICStub::Kind kind,
|
||||
HandleObject holder,
|
||||
HandleShape receiverShape,
|
||||
HandleFunction setter)
|
||||
{
|
||||
MOZ_ASSERT(kind == ICStub::SetProp_CallScripted ||
|
||||
kind == ICStub::SetProp_CallNative);
|
||||
@@ -5848,13 +5774,13 @@ UpdateExistingSetPropCallStubs(ICSetProp_Fallback* fallbackStub,
|
||||
// We want to update the holder shape to match the new one no
|
||||
// matter what, even if the receiver shape is different.
|
||||
MOZ_ASSERT(setPropStub->holderShape() != holder->lastProperty() ||
|
||||
setPropStub->guard().token() != receiverGuard,
|
||||
setPropStub->shape() != receiverShape,
|
||||
"Why didn't we end up using this stub?");
|
||||
setPropStub->holderShape() = holder->lastProperty();
|
||||
// Make sure to update the setter, since a shape change might
|
||||
// have changed which setter we want to use.
|
||||
setPropStub->setter() = setter;
|
||||
if (receiverGuard == setPropStub->guard().token())
|
||||
if (receiverShape == setPropStub->shape())
|
||||
foundMatchingStub = true;
|
||||
}
|
||||
}
|
||||
@@ -6539,8 +6465,15 @@ TryAttachNativeGetPropStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
if (IsIonEnabled(cx))
|
||||
EnsureTrackPropertyTypes(cx, holder, NameToId(name));
|
||||
|
||||
ICStub::Kind kind =
|
||||
(obj == holder) ? ICStub::GetProp_Native : ICStub::GetProp_NativePrototype;
|
||||
ICStub::Kind kind;
|
||||
if (obj == holder)
|
||||
kind = ICStub::GetProp_Native;
|
||||
else if (obj->isNative())
|
||||
kind = ICStub::GetProp_NativePrototype;
|
||||
else if (obj->is<UnboxedPlainObject>())
|
||||
kind = ICStub::GetProp_UnboxedPrototype;
|
||||
else
|
||||
MOZ_CRASH("Bad kind");
|
||||
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetProp(%s %s) stub",
|
||||
isDOMProxy ? "DOMProxy" : "Native",
|
||||
@@ -6562,8 +6495,8 @@ TryAttachNativeGetPropStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
}
|
||||
|
||||
bool isScripted = false;
|
||||
bool cacheableCall = IsCacheableGetPropCall(cx, obj, holder, shape, &isScripted,
|
||||
isTemporarilyUnoptimizable);
|
||||
bool cacheableCall = obj->isNative() && IsCacheableGetPropCall(cx, obj, holder, shape, &isScripted,
|
||||
isTemporarilyUnoptimizable);
|
||||
|
||||
// Try handling scripted getters.
|
||||
if (cacheableCall && isScripted && !isDOMProxy) {
|
||||
@@ -6624,7 +6557,7 @@ TryAttachNativeGetPropStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
}
|
||||
|
||||
const Class* outerClass = nullptr;
|
||||
if (!isDOMProxy && !obj->isNative() && !obj->is<UnboxedPlainObject>()) {
|
||||
if (!isDOMProxy && !obj->isNative()) {
|
||||
outerClass = obj->getClass();
|
||||
DebugOnly<JSObject*> outer = obj.get();
|
||||
obj = GetInnerObject(obj);
|
||||
@@ -6872,6 +6805,8 @@ TryAttachNativeDoesNotExistStub(JSContext* cx, HandleScript script, jsbytecode*
|
||||
return true;
|
||||
|
||||
ICStub* monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
|
||||
RootedShape objShape(cx, obj->lastProperty());
|
||||
RootedShape lastShape(cx, lastProto->lastProperty());
|
||||
|
||||
// Confirmed no-such-property. Add stub.
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetProp_NativeDoesNotExist stub");
|
||||
@@ -7192,36 +7127,25 @@ ICGetPropNativeCompiler::getStub(ICStubSpace* space)
|
||||
|
||||
case ICStub::GetProp_NativePrototype: {
|
||||
MOZ_ASSERT(obj_ != holder_);
|
||||
ReceiverGuard::Token guard = ReceiverGuard::objectToken(obj_);
|
||||
Shape *holderShape = holder_->lastProperty();
|
||||
return ICStub::New<ICGetProp_NativePrototype>(space, getStubCode(), firstMonitorStub_, guard,
|
||||
RootedShape shape(cx, obj_->lastProperty());
|
||||
RootedShape holderShape(cx, holder_->lastProperty());
|
||||
return ICStub::New<ICGetProp_NativePrototype>(space, getStubCode(), firstMonitorStub_, shape,
|
||||
offset_, holder_, holderShape);
|
||||
}
|
||||
|
||||
case ICStub::GetProp_UnboxedPrototype: {
|
||||
MOZ_ASSERT(obj_ != holder_);
|
||||
RootedObjectGroup group(cx, obj_->group());
|
||||
RootedShape holderShape(cx, holder_->lastProperty());
|
||||
return ICStub::New<ICGetProp_UnboxedPrototype>(space, getStubCode(), firstMonitorStub_, group,
|
||||
offset_, holder_, holderShape);
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad stub kind");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
GuardNativeOrUnboxedReceiver(MacroAssembler &masm, JSObject *obj,
|
||||
Register object, Register scratch,
|
||||
size_t receiverGuardOffset, Label *failure)
|
||||
{
|
||||
if (obj->isNative()) {
|
||||
masm.loadPtr(Address(BaselineStubReg,
|
||||
receiverGuardOffset + ReceiverGuard::offsetOfShape()),
|
||||
scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, object, scratch, failure);
|
||||
} else {
|
||||
MOZ_ASSERT(obj->is<UnboxedPlainObject>());
|
||||
masm.loadPtr(Address(BaselineStubReg,
|
||||
receiverGuardOffset + ReceiverGuard::offsetOfGroup()),
|
||||
scratch);
|
||||
masm.branchTestObjGroup(Assembler::NotEqual, object, scratch, failure);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ICGetPropNativeCompiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
@@ -7242,16 +7166,26 @@ ICGetPropNativeCompiler::generateStubCode(MacroAssembler& masm)
|
||||
Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
|
||||
|
||||
// Shape/group guard.
|
||||
MOZ_ASSERT(ICGetProp_Native::offsetOfShape() ==
|
||||
ICGetProp_NativePrototype::offsetOfGuard() + ReceiverGuard::offsetOfShape());
|
||||
GuardNativeOrUnboxedReceiver(masm, obj_, objReg, scratch,
|
||||
ICGetProp_NativePrototype::offsetOfGuard(), &failure);
|
||||
if (kind == ICStub::GetProp_UnboxedPrototype) {
|
||||
masm.loadPtr(Address(BaselineStubReg, ICGetProp_UnboxedPrototype::offsetOfGroup()), scratch);
|
||||
masm.branchPtr(Assembler::NotEqual, Address(objReg, JSObject::offsetOfGroup()), scratch,
|
||||
&failure);
|
||||
} else {
|
||||
MOZ_ASSERT(ICGetProp_Native::offsetOfShape() ==
|
||||
ICGetProp_NativePrototype::offsetOfShape());
|
||||
masm.loadPtr(Address(BaselineStubReg, ICGetProp_Native::offsetOfShape()), scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
|
||||
}
|
||||
|
||||
Register holderReg;
|
||||
if (obj_ == holder_) {
|
||||
holderReg = objReg;
|
||||
} else {
|
||||
// Shape guard holder.
|
||||
MOZ_ASSERT(ICGetProp_NativePrototype::offsetOfHolder() ==
|
||||
ICGetProp_UnboxedPrototype::offsetOfHolder());
|
||||
MOZ_ASSERT(ICGetProp_NativePrototype::offsetOfHolderShape() ==
|
||||
ICGetProp_UnboxedPrototype::offsetOfHolderShape());
|
||||
holderReg = regs.takeAny();
|
||||
masm.loadPtr(Address(BaselineStubReg, ICGetProp_NativePrototype::offsetOfHolder()),
|
||||
holderReg);
|
||||
@@ -7338,6 +7272,8 @@ ICStub*
|
||||
ICGetPropNativeDoesNotExistCompiler::getStub(ICStubSpace* space)
|
||||
{
|
||||
AutoShapeVector shapes(cx);
|
||||
if (!shapes.append(obj_->lastProperty()))
|
||||
return nullptr;
|
||||
|
||||
if (!GetProtoShapes(obj_, protoChainDepth_, &shapes))
|
||||
return nullptr;
|
||||
@@ -7384,17 +7320,18 @@ ICGetPropNativeDoesNotExistCompiler::generateStubCode(MacroAssembler& masm)
|
||||
// Guard input is an object.
|
||||
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
// Unbox and guard against old shape/group.
|
||||
// Unbox and guard against old shape.
|
||||
Register objReg = masm.extractObject(R0, ExtractTemp0);
|
||||
GuardNativeOrUnboxedReceiver(masm, obj_, objReg, scratch,
|
||||
ICGetProp_NativeDoesNotExist::offsetOfGuard(), &failure);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICGetProp_NativeDoesNotExist::offsetOfShape(0)),
|
||||
scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
|
||||
|
||||
Register protoReg = regs.takeAny();
|
||||
// Check the proto chain.
|
||||
for (size_t i = 0; i < protoChainDepth_; i++) {
|
||||
masm.loadObjProto(i == 0 ? objReg : protoReg, protoReg);
|
||||
masm.branchTestPtr(Assembler::Zero, protoReg, protoReg, &failure);
|
||||
size_t shapeOffset = ICGetProp_NativeDoesNotExistImpl<0>::offsetOfShape(i);
|
||||
size_t shapeOffset = ICGetProp_NativeDoesNotExistImpl<0>::offsetOfShape(i + 1);
|
||||
masm.loadPtr(Address(BaselineStubReg, shapeOffset), scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, protoReg, scratch, &failure);
|
||||
}
|
||||
@@ -7425,8 +7362,8 @@ ICGetProp_CallScripted::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
|
||||
// Unbox and shape guard.
|
||||
Register objReg = masm.extractObject(R0, ExtractTemp0);
|
||||
GuardNativeOrUnboxedReceiver(masm, receiver_, objReg, scratch,
|
||||
ICGetProp_CallScripted::offsetOfReceiverGuard(), &failure);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallScripted::offsetOfReceiverShape()), scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
|
||||
|
||||
Register holderReg = regs.takeAny();
|
||||
masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallScripted::offsetOfHolder()), holderReg);
|
||||
@@ -7587,8 +7524,8 @@ ICGetProp_CallNativePrototype::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
|
||||
|
||||
// Shape guard.
|
||||
GuardNativeOrUnboxedReceiver(masm, receiver_, objReg, scratch,
|
||||
ICGetProp_CallNativePrototype::offsetOfReceiverGuard(), &failure);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallNativePrototype::offsetOfReceiverShape()), scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
|
||||
|
||||
Register holderReg = regs.takeAny();
|
||||
masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallNativePrototype::offsetOfHolder()), holderReg);
|
||||
@@ -8160,14 +8097,14 @@ TryAttachSetValuePropStub(JSContext* cx, HandleScript script, jsbytecode* pc, IC
|
||||
// an accessor property.
|
||||
static bool
|
||||
TryAttachSetAccessorPropStub(JSContext* cx, HandleScript script, jsbytecode* pc, ICSetProp_Fallback* stub,
|
||||
HandleObject obj, ReceiverGuard::Token receiverGuard, HandlePropertyName name,
|
||||
HandleObject obj, HandleShape receiverShape, HandlePropertyName name,
|
||||
HandleId id, HandleValue rhs, bool* attached,
|
||||
bool* isTemporarilyUnoptimizable)
|
||||
{
|
||||
MOZ_ASSERT(!*attached);
|
||||
MOZ_ASSERT(!*isTemporarilyUnoptimizable);
|
||||
|
||||
if (obj->watched())
|
||||
if (!obj->isNative() || obj->watched())
|
||||
return true;
|
||||
|
||||
RootedShape shape(cx);
|
||||
@@ -8186,7 +8123,7 @@ TryAttachSetAccessorPropStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
MOZ_ASSERT(callee->hasScript());
|
||||
|
||||
if (UpdateExistingSetPropCallStubs(stub, ICStub::SetProp_CallScripted,
|
||||
holder, receiverGuard, callee)) {
|
||||
holder, receiverShape, callee)) {
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@@ -8211,7 +8148,7 @@ TryAttachSetAccessorPropStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
MOZ_ASSERT(callee->isNative());
|
||||
|
||||
if (UpdateExistingSetPropCallStubs(stub, ICStub::SetProp_CallNative,
|
||||
holder, receiverGuard, callee)) {
|
||||
holder, receiverShape, callee)) {
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@@ -8342,7 +8279,6 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
|
||||
RootedObject obj(cx, ToObjectFromStack(cx, lhs));
|
||||
if (!obj)
|
||||
return false;
|
||||
ReceiverGuard::Token oldGuard = ReceiverGuard::objectToken(obj);
|
||||
RootedShape oldShape(cx, obj->lastProperty());
|
||||
RootedObjectGroup oldGroup(cx, obj->getGroup(cx));
|
||||
if (!oldGroup)
|
||||
@@ -8357,7 +8293,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
|
||||
bool isTemporarilyUnoptimizable = false;
|
||||
if (stub->numOptimizedStubs() < ICSetProp_Fallback::MAX_OPTIMIZED_STUBS &&
|
||||
lhs.isObject() &&
|
||||
!TryAttachSetAccessorPropStub(cx, script, pc, stub, obj, oldGuard, name, id,
|
||||
!TryAttachSetAccessorPropStub(cx, script, pc, stub, obj, oldShape, name, id,
|
||||
rhs, &attached, &isTemporarilyUnoptimizable))
|
||||
{
|
||||
return false;
|
||||
@@ -8367,8 +8303,13 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
|
||||
op == JSOP_INITLOCKEDPROP ||
|
||||
op == JSOP_INITHIDDENPROP)
|
||||
{
|
||||
if (!InitPropertyOperation(cx, op, obj, id, rhs))
|
||||
MOZ_ASSERT(obj->is<PlainObject>());
|
||||
unsigned propAttrs = GetInitDataPropAttrs(op);
|
||||
if (!NativeDefineProperty(cx, obj.as<PlainObject>(), id, rhs,
|
||||
nullptr, nullptr, propAttrs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else if (op == JSOP_SETNAME ||
|
||||
op == JSOP_STRICTSETNAME ||
|
||||
op == JSOP_SETGNAME ||
|
||||
@@ -8382,7 +8323,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
|
||||
MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
|
||||
|
||||
RootedValue v(cx, rhs);
|
||||
if (!PutProperty(cx, obj, id, &v, op == JSOP_STRICTSETPROP))
|
||||
if (!SetProperty(cx, obj, obj, id, &v, op == JSOP_STRICTSETPROP))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -8910,8 +8851,8 @@ ICSetProp_CallScripted::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
|
||||
// Unbox and shape guard.
|
||||
Register objReg = masm.extractObject(R0, ExtractTemp0);
|
||||
GuardNativeOrUnboxedReceiver(masm, obj_, objReg, scratch,
|
||||
ICSetProp_CallScripted::offsetOfGuard(), &failureUnstow);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallScripted::offsetOfShape()), scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failureUnstow);
|
||||
|
||||
Register holderReg = regs.takeAny();
|
||||
masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallScripted::offsetOfHolder()), holderReg);
|
||||
@@ -9029,8 +8970,8 @@ ICSetProp_CallNative::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
|
||||
// Unbox and shape guard.
|
||||
Register objReg = masm.extractObject(R0, ExtractTemp0);
|
||||
GuardNativeOrUnboxedReceiver(masm, obj_, objReg, scratch,
|
||||
ICSetProp_CallNative::offsetOfGuard(), &failureUnstow);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallNative::offsetOfShape()), scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failureUnstow);
|
||||
|
||||
Register holderReg = regs.takeAny();
|
||||
masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallNative::offsetOfHolder()), holderReg);
|
||||
@@ -11895,10 +11836,10 @@ ICGetProp_Native::Clone(ICStubSpace* space, ICStub* firstMonitorStub,
|
||||
}
|
||||
|
||||
ICGetProp_NativePrototype::ICGetProp_NativePrototype(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard::Token guard, uint32_t offset,
|
||||
Shape* shape, uint32_t offset,
|
||||
JSObject* holder, Shape* holderShape)
|
||||
: ICGetPropNativeStub(GetProp_NativePrototype, stubCode, firstMonitorStub, offset),
|
||||
guard_(guard),
|
||||
shape_(shape),
|
||||
holder_(holder),
|
||||
holderShape_(holderShape)
|
||||
{ }
|
||||
@@ -11907,15 +11848,30 @@ ICGetProp_NativePrototype::ICGetProp_NativePrototype(JitCode* stubCode, ICStub*
|
||||
ICGetProp_NativePrototype::Clone(ICStubSpace* space, ICStub* firstMonitorStub,
|
||||
ICGetProp_NativePrototype& other)
|
||||
{
|
||||
return New<ICGetProp_NativePrototype>(space, other.jitCode(), firstMonitorStub,
|
||||
other.guard().token(),
|
||||
return New<ICGetProp_NativePrototype>(space, other.jitCode(), firstMonitorStub, other.shape(),
|
||||
other.offset(), other.holder_, other.holderShape_);
|
||||
}
|
||||
|
||||
ICGetProp_UnboxedPrototype::ICGetProp_UnboxedPrototype(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ObjectGroup* group, uint32_t offset,
|
||||
JSObject* holder, Shape* holderShape)
|
||||
: ICGetPropNativeStub(GetProp_UnboxedPrototype, stubCode, firstMonitorStub, offset),
|
||||
group_(group),
|
||||
holder_(holder),
|
||||
holderShape_(holderShape)
|
||||
{ }
|
||||
|
||||
/* static */ ICGetProp_UnboxedPrototype*
|
||||
ICGetProp_UnboxedPrototype::Clone(ICStubSpace* space, ICStub* firstMonitorStub,
|
||||
ICGetProp_UnboxedPrototype& other)
|
||||
{
|
||||
return New<ICGetProp_UnboxedPrototype>(space, other.jitCode(), firstMonitorStub, other.group(),
|
||||
other.offset(), other.holder_, other.holderShape_);
|
||||
}
|
||||
|
||||
ICGetProp_NativeDoesNotExist::ICGetProp_NativeDoesNotExist(
|
||||
JitCode *stubCode, ICStub *firstMonitorStub, ReceiverGuard::Token guard, size_t protoChainDepth)
|
||||
: ICMonitoredStub(GetProp_NativeDoesNotExist, stubCode, firstMonitorStub),
|
||||
guard_(guard)
|
||||
JitCode* stubCode, ICStub* firstMonitorStub, size_t protoChainDepth)
|
||||
: ICMonitoredStub(GetProp_NativeDoesNotExist, stubCode, firstMonitorStub)
|
||||
{
|
||||
MOZ_ASSERT(protoChainDepth <= MAX_PROTO_CHAIN_DEPTH);
|
||||
extra_ = protoChainDepth;
|
||||
@@ -11932,14 +11888,11 @@ ICGetProp_NativeDoesNotExist::offsetOfShape(size_t idx)
|
||||
|
||||
template <size_t ProtoChainDepth>
|
||||
ICGetProp_NativeDoesNotExistImpl<ProtoChainDepth>::ICGetProp_NativeDoesNotExistImpl(
|
||||
JitCode *stubCode, ICStub *firstMonitorStub, ReceiverGuard::Token guard,
|
||||
const AutoShapeVector *shapes)
|
||||
: ICGetProp_NativeDoesNotExist(stubCode, firstMonitorStub, guard, ProtoChainDepth)
|
||||
JitCode* stubCode, ICStub* firstMonitorStub, const AutoShapeVector* shapes)
|
||||
: ICGetProp_NativeDoesNotExist(stubCode, firstMonitorStub, ProtoChainDepth)
|
||||
{
|
||||
MOZ_ASSERT(shapes->length() == NumShapes);
|
||||
|
||||
// Note: using int32_t here to avoid gcc warning.
|
||||
for (int32_t i = 0; i < int32_t(NumShapes); i++)
|
||||
for (size_t i = 0; i < NumShapes; i++)
|
||||
shapes_[i].init((*shapes)[i]);
|
||||
}
|
||||
|
||||
@@ -11971,12 +11924,11 @@ ICGetPropCallGetter::ICGetPropCallGetter(Kind kind, JitCode* stubCode, ICStub* f
|
||||
|
||||
ICGetPropCallPrototypeGetter::ICGetPropCallPrototypeGetter(Kind kind, JitCode* stubCode,
|
||||
ICStub* firstMonitorStub,
|
||||
ReceiverGuard::Token receiverGuard,
|
||||
JSObject *holder,
|
||||
Shape* receiverShape, JSObject* holder,
|
||||
Shape* holderShape,
|
||||
JSFunction* getter, uint32_t pcOffset)
|
||||
: ICGetPropCallGetter(kind, stubCode, firstMonitorStub, holder, holderShape, getter, pcOffset),
|
||||
receiverGuard_(receiverGuard)
|
||||
receiverShape_(receiverShape)
|
||||
{
|
||||
MOZ_ASSERT(kind == ICStub::GetProp_CallScripted || kind == ICStub::GetProp_CallNativePrototype);
|
||||
}
|
||||
@@ -11994,8 +11946,7 @@ ICGetProp_CallScripted::Clone(ICStubSpace* space, ICStub* firstMonitorStub,
|
||||
ICGetProp_CallScripted& other)
|
||||
{
|
||||
return New<ICGetProp_CallScripted>(space, other.jitCode(), firstMonitorStub,
|
||||
other.receiverGuard().token(),
|
||||
other.holder_, other.holderShape_,
|
||||
other.receiverShape_, other.holder_, other.holderShape_,
|
||||
other.getter_, other.pcOffset_);
|
||||
}
|
||||
|
||||
@@ -12012,7 +11963,7 @@ ICGetProp_CallNativePrototype::Clone(ICStubSpace* space, ICStub* firstMonitorStu
|
||||
ICGetProp_CallNativePrototype& other)
|
||||
{
|
||||
return New<ICGetProp_CallNativePrototype>(space, other.jitCode(), firstMonitorStub,
|
||||
other.receiverGuard().token(), other.holder_,
|
||||
other.receiverShape_, other.holder_,
|
||||
other.holderShape_, other.getter_, other.pcOffset_);
|
||||
}
|
||||
|
||||
@@ -12084,11 +12035,11 @@ ICSetPropNativeAddCompiler::ICSetPropNativeAddCompiler(JSContext* cx, HandleObje
|
||||
MOZ_ASSERT(protoChainDepth_ <= ICSetProp_NativeAdd::MAX_PROTO_CHAIN_DEPTH);
|
||||
}
|
||||
|
||||
ICSetPropCallSetter::ICSetPropCallSetter(Kind kind, JitCode *stubCode, ReceiverGuard::Token guard,
|
||||
ICSetPropCallSetter::ICSetPropCallSetter(Kind kind, JitCode* stubCode, Shape* shape,
|
||||
JSObject* holder, Shape* holderShape,
|
||||
JSFunction* setter, uint32_t pcOffset)
|
||||
: ICStub(kind, stubCode),
|
||||
guard_(guard),
|
||||
shape_(shape),
|
||||
holder_(holder),
|
||||
holderShape_(holderShape),
|
||||
setter_(setter),
|
||||
@@ -12100,14 +12051,14 @@ ICSetPropCallSetter::ICSetPropCallSetter(Kind kind, JitCode *stubCode, ReceiverG
|
||||
/* static */ ICSetProp_CallScripted*
|
||||
ICSetProp_CallScripted::Clone(ICStubSpace* space, ICStub*, ICSetProp_CallScripted& other)
|
||||
{
|
||||
return New<ICSetProp_CallScripted>(space, other.jitCode(), other.guard().token(), other.holder_,
|
||||
return New<ICSetProp_CallScripted>(space, other.jitCode(), other.shape_, other.holder_,
|
||||
other.holderShape_, other.setter_, other.pcOffset_);
|
||||
}
|
||||
|
||||
/* static */ ICSetProp_CallNative*
|
||||
ICSetProp_CallNative::Clone(ICStubSpace* space, ICStub*, ICSetProp_CallNative& other)
|
||||
{
|
||||
return New<ICSetProp_CallNative>(space, other.jitCode(), other.guard().token(), other.holder_,
|
||||
return New<ICSetProp_CallNative>(space, other.jitCode(), other.shape_, other.holder_,
|
||||
other.holderShape_, other.setter_, other.pcOffset_);
|
||||
}
|
||||
|
||||
|
||||
+123
-177
@@ -19,7 +19,6 @@
|
||||
#include "jit/BaselineRegisters.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
#include "vm/TypedArrayCommon.h"
|
||||
#include "vm/UnboxedObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
@@ -349,7 +348,6 @@ class ICEntry
|
||||
\
|
||||
_(NewArray_Fallback) \
|
||||
_(NewObject_Fallback) \
|
||||
_(NewObject_WithTemplate) \
|
||||
\
|
||||
_(Compare_Fallback) \
|
||||
_(Compare_Int32) \
|
||||
@@ -432,6 +430,7 @@ class ICEntry
|
||||
_(GetProp_Native) \
|
||||
_(GetProp_NativeDoesNotExist) \
|
||||
_(GetProp_NativePrototype) \
|
||||
_(GetProp_UnboxedPrototype) \
|
||||
_(GetProp_Unboxed) \
|
||||
_(GetProp_TypedObject) \
|
||||
_(GetProp_CallScripted) \
|
||||
@@ -844,6 +843,7 @@ class ICStub
|
||||
case GetElem_Dense:
|
||||
case GetElem_Arguments:
|
||||
case GetProp_NativePrototype:
|
||||
case GetProp_UnboxedPrototype:
|
||||
case GetProp_Native:
|
||||
#endif
|
||||
return true;
|
||||
@@ -1769,42 +1769,31 @@ class ICNewObject_Fallback : public ICFallbackStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
HeapPtrObject templateObject_;
|
||||
HeapPtrPlainObject templateObject_;
|
||||
|
||||
explicit ICNewObject_Fallback(JitCode* stubCode)
|
||||
: ICFallbackStub(ICStub::NewObject_Fallback, stubCode), templateObject_(nullptr)
|
||||
ICNewObject_Fallback(JitCode* stubCode, PlainObject* templateObject)
|
||||
: ICFallbackStub(ICStub::NewObject_Fallback, stubCode), templateObject_(templateObject)
|
||||
{}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
RootedPlainObject templateObject;
|
||||
bool generateStubCode(MacroAssembler& masm);
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext *cx)
|
||||
: ICStubCompiler(cx, ICStub::NewObject_Fallback)
|
||||
Compiler(JSContext* cx, PlainObject* templateObject)
|
||||
: ICStubCompiler(cx, ICStub::NewObject_Fallback),
|
||||
templateObject(cx, templateObject)
|
||||
{}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) {
|
||||
return ICStub::New<ICNewObject_Fallback>(space, getStubCode());
|
||||
return ICStub::New<ICNewObject_Fallback>(space, getStubCode(), templateObject);
|
||||
}
|
||||
};
|
||||
|
||||
HeapPtrObject& templateObject() {
|
||||
HeapPtrPlainObject& templateObject() {
|
||||
return templateObject_;
|
||||
}
|
||||
|
||||
void setTemplateObject(JSObject *obj) {
|
||||
templateObject_ = obj;
|
||||
}
|
||||
};
|
||||
|
||||
class ICNewObject_WithTemplate : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICNewObject_WithTemplate(JitCode *stubCode)
|
||||
: ICStub(ICStub::NewObject_WithTemplate, stubCode)
|
||||
{}
|
||||
};
|
||||
|
||||
// Compare
|
||||
@@ -3894,101 +3883,32 @@ class ICGetProp_Native : public ICGetPropNativeStub
|
||||
ICGetProp_Native& other);
|
||||
};
|
||||
|
||||
// Structure encapsulating the guarding that needs to be done on an object
|
||||
// which might be either native or unboxed. In the former case, only the
|
||||
// object's shape needs to be guarded. In the latter case, only the object's
|
||||
// group needs to be guarded.
|
||||
class ReceiverGuard
|
||||
{
|
||||
HeapPtrShape shape_;
|
||||
HeapPtrObjectGroup group_;
|
||||
|
||||
public:
|
||||
typedef uintptr_t Token;
|
||||
|
||||
static Token shapeToken(Shape *shape) {
|
||||
return reinterpret_cast<Token>(shape) | 1;
|
||||
}
|
||||
|
||||
static Token groupToken(ObjectGroup *group) {
|
||||
return reinterpret_cast<Token>(group);
|
||||
}
|
||||
|
||||
|
||||
static Shape *tokenShape(Token token) {
|
||||
if (token & 1)
|
||||
return reinterpret_cast<Shape *>(token & ~1);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static ObjectGroup *tokenGroup(Token token) {
|
||||
if (!(token & 1))
|
||||
return reinterpret_cast<ObjectGroup *>(token);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Token objectToken(JSObject *obj) {
|
||||
if (obj->is<UnboxedPlainObject>())
|
||||
return groupToken(obj->group());
|
||||
return shapeToken(obj->lastProperty());
|
||||
}
|
||||
|
||||
explicit ReceiverGuard(Token token)
|
||||
: shape_(tokenShape(token)), group_(tokenGroup(token))
|
||||
{
|
||||
MOZ_ASSERT(shape_ || group_);
|
||||
}
|
||||
|
||||
void trace(JSTracer *trc);
|
||||
|
||||
Token token() {
|
||||
MOZ_ASSERT(!!shape_ != !!group_);
|
||||
if (shape_)
|
||||
return shapeToken(shape_);
|
||||
return groupToken(group_);
|
||||
}
|
||||
Shape *shape() const {
|
||||
return shape_;
|
||||
}
|
||||
ObjectGroup *group() const {
|
||||
return group_;
|
||||
}
|
||||
|
||||
static size_t offsetOfShape() {
|
||||
return offsetof(ReceiverGuard, shape_);
|
||||
}
|
||||
static size_t offsetOfGroup() {
|
||||
return offsetof(ReceiverGuard, group_);
|
||||
}
|
||||
};
|
||||
|
||||
// Stub for accessing a property on the native prototype of a native or unboxed
|
||||
// object. Note that due to the shape teleporting optimization, we only have to
|
||||
// guard on the object's shape/group and the holder's shape.
|
||||
// Stub for accessing a property on a native object's prototype. Note that due to
|
||||
// the shape teleporting optimization, we only have to guard on the object's shape
|
||||
// and the holder's shape.
|
||||
class ICGetProp_NativePrototype : public ICGetPropNativeStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
protected:
|
||||
// Object shape/group.
|
||||
ReceiverGuard guard_;
|
||||
// Object shape (lastProperty).
|
||||
HeapPtrShape shape_;
|
||||
|
||||
// Holder and its shape.
|
||||
HeapPtrObject holder_;
|
||||
HeapPtrShape holderShape_;
|
||||
|
||||
ICGetProp_NativePrototype(JitCode *stubCode, ICStub *firstMonitorStub,
|
||||
ReceiverGuard::Token guard,
|
||||
uint32_t offset, JSObject *holder, Shape *holderShape);
|
||||
ICGetProp_NativePrototype(JitCode* stubCode, ICStub* firstMonitorStub, Shape* shape,
|
||||
uint32_t offset, JSObject* holder, Shape* holderShape);
|
||||
|
||||
public:
|
||||
static ICGetProp_NativePrototype *Clone(ICStubSpace *space,
|
||||
ICStub *firstMonitorStub,
|
||||
ICGetProp_NativePrototype &other);
|
||||
static ICGetProp_NativePrototype* Clone(ICStubSpace* space,
|
||||
ICStub* firstMonitorStub,
|
||||
ICGetProp_NativePrototype& other);
|
||||
|
||||
public:
|
||||
ReceiverGuard &guard() {
|
||||
return guard_;
|
||||
HeapPtrShape& shape() {
|
||||
return shape_;
|
||||
}
|
||||
HeapPtrObject& holder() {
|
||||
return holder_;
|
||||
@@ -3996,8 +3916,8 @@ class ICGetProp_NativePrototype : public ICGetPropNativeStub
|
||||
HeapPtrShape& holderShape() {
|
||||
return holderShape_;
|
||||
}
|
||||
static size_t offsetOfGuard() {
|
||||
return offsetof(ICGetProp_NativePrototype, guard_);
|
||||
static size_t offsetOfShape() {
|
||||
return offsetof(ICGetProp_NativePrototype, shape_);
|
||||
}
|
||||
static size_t offsetOfHolder() {
|
||||
return offsetof(ICGetProp_NativePrototype, holder_);
|
||||
@@ -4007,6 +3927,51 @@ class ICGetProp_NativePrototype : public ICGetPropNativeStub
|
||||
}
|
||||
};
|
||||
|
||||
// Stub for accessing a property on an unboxed object's native prototype. Note
|
||||
// that due to the shape teleporting optimization, we only have to guard on the
|
||||
// object's type and the holder's shape.
|
||||
class ICGetProp_UnboxedPrototype : public ICGetPropNativeStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
protected:
|
||||
// Object group.
|
||||
HeapPtrObjectGroup group_;
|
||||
|
||||
// Holder and its shape.
|
||||
HeapPtrObject holder_;
|
||||
HeapPtrShape holderShape_;
|
||||
|
||||
ICGetProp_UnboxedPrototype(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ObjectGroup* group,
|
||||
uint32_t offset, JSObject* holder, Shape* holderShape);
|
||||
|
||||
public:
|
||||
static ICGetProp_UnboxedPrototype* Clone(ICStubSpace* space,
|
||||
ICStub* firstMonitorStub,
|
||||
ICGetProp_UnboxedPrototype& other);
|
||||
|
||||
public:
|
||||
HeapPtrObjectGroup& group() {
|
||||
return group_;
|
||||
}
|
||||
HeapPtrObject& holder() {
|
||||
return holder_;
|
||||
}
|
||||
HeapPtrShape& holderShape() {
|
||||
return holderShape_;
|
||||
}
|
||||
static size_t offsetOfGroup() {
|
||||
return offsetof(ICGetProp_UnboxedPrototype, group_);
|
||||
}
|
||||
static size_t offsetOfHolder() {
|
||||
return offsetof(ICGetProp_UnboxedPrototype, holder_);
|
||||
}
|
||||
static size_t offsetOfHolderShape() {
|
||||
return offsetof(ICGetProp_UnboxedPrototype, holderShape_);
|
||||
}
|
||||
};
|
||||
|
||||
// Compiler for native GetProp stubs.
|
||||
class ICGetPropNativeCompiler : public ICStubCompiler
|
||||
{
|
||||
@@ -4023,11 +3988,16 @@ class ICGetPropNativeCompiler : public ICStubCompiler
|
||||
|
||||
protected:
|
||||
virtual int32_t getKey() const {
|
||||
#if JS_HAS_NO_SUCH_METHOD
|
||||
return static_cast<int32_t>(kind) |
|
||||
(static_cast<int32_t>(isCallProp_) << 16) |
|
||||
(static_cast<int32_t>(isFixedSlot_) << 17) |
|
||||
(static_cast<int32_t>(inputDefinitelyObject_) << 18) |
|
||||
(static_cast<int32_t>(obj_->isNative()) << 19);
|
||||
(static_cast<int32_t>(inputDefinitelyObject_) << 18);
|
||||
#else
|
||||
return static_cast<int32_t>(kind) |
|
||||
(static_cast<int32_t>(isFixedSlot_) << 16) |
|
||||
(static_cast<int32_t>(inputDefinitelyObject_) << 17);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -4055,13 +4025,10 @@ class ICGetProp_NativeDoesNotExist : public ICMonitoredStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
public:
|
||||
ReceiverGuard guard_;
|
||||
|
||||
static const size_t MAX_PROTO_CHAIN_DEPTH = 8;
|
||||
|
||||
protected:
|
||||
ICGetProp_NativeDoesNotExist(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard::Token guard,
|
||||
size_t protoChainDepth);
|
||||
|
||||
public:
|
||||
@@ -4076,14 +4043,6 @@ class ICGetProp_NativeDoesNotExist : public ICMonitoredStub
|
||||
return static_cast<ICGetProp_NativeDoesNotExistImpl<ProtoChainDepth>*>(this);
|
||||
}
|
||||
|
||||
ReceiverGuard &guard() {
|
||||
return guard_;
|
||||
}
|
||||
|
||||
static size_t offsetOfGuard() {
|
||||
return offsetof(ICGetProp_NativeDoesNotExist, guard_);
|
||||
}
|
||||
|
||||
static size_t offsetOfShape(size_t idx);
|
||||
};
|
||||
|
||||
@@ -4093,19 +4052,17 @@ class ICGetProp_NativeDoesNotExistImpl : public ICGetProp_NativeDoesNotExist
|
||||
friend class ICStubSpace;
|
||||
public:
|
||||
static const size_t MAX_PROTO_CHAIN_DEPTH = 8;
|
||||
static const size_t NumShapes = ProtoChainDepth;
|
||||
static const size_t NumShapes = ProtoChainDepth + 1;
|
||||
|
||||
private:
|
||||
mozilla::Array<HeapPtrShape, NumShapes> shapes_;
|
||||
|
||||
ICGetProp_NativeDoesNotExistImpl(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard::Token guard,
|
||||
const AutoShapeVector* shapes);
|
||||
|
||||
public:
|
||||
void traceShapes(JSTracer* trc) {
|
||||
// Note: using int32_t here to avoid gcc warning.
|
||||
for (int32_t i = 0; i < int32_t(NumShapes); i++)
|
||||
for (size_t i = 0; i < NumShapes; i++)
|
||||
MarkShape(trc, &shapes_[i], "baseline-getpropnativedoesnotexist-stub-shape");
|
||||
}
|
||||
|
||||
@@ -4122,9 +4079,7 @@ class ICGetPropNativeDoesNotExistCompiler : public ICStubCompiler
|
||||
|
||||
protected:
|
||||
virtual int32_t getKey() const {
|
||||
return static_cast<int32_t>(kind) |
|
||||
(static_cast<int32_t>(obj_->isNative()) << 16) |
|
||||
(static_cast<int32_t>(protoChainDepth_) << 17);
|
||||
return static_cast<int32_t>(kind) | (static_cast<int32_t>(protoChainDepth_) << 16);
|
||||
}
|
||||
|
||||
bool generateStubCode(MacroAssembler& masm);
|
||||
@@ -4135,8 +4090,8 @@ class ICGetPropNativeDoesNotExistCompiler : public ICStubCompiler
|
||||
|
||||
template <size_t ProtoChainDepth>
|
||||
ICStub* getStubSpecific(ICStubSpace* space, const AutoShapeVector* shapes) {
|
||||
return ICStub::New<ICGetProp_NativeDoesNotExistImpl<ProtoChainDepth> >
|
||||
(space, getStubCode(), firstMonitorStub_, ReceiverGuard::objectToken(obj_), shapes);
|
||||
return ICStub::New<ICGetProp_NativeDoesNotExistImpl<ProtoChainDepth>>(space, getStubCode(),
|
||||
firstMonitorStub_, shapes);
|
||||
}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space);
|
||||
@@ -4319,25 +4274,22 @@ class ICGetPropCallGetter : public ICMonitoredStub
|
||||
RootedFunction getter_;
|
||||
uint32_t pcOffset_;
|
||||
const Class* outerClass_;
|
||||
bool receiverNative_;
|
||||
|
||||
virtual int32_t getKey() const {
|
||||
return static_cast<int32_t>(kind) |
|
||||
(static_cast<int32_t>(receiverNative_) << 16) |
|
||||
(static_cast<int32_t>(!!outerClass_) << 17);
|
||||
}
|
||||
(static_cast<int32_t>(!!outerClass_) << 16);
|
||||
}
|
||||
|
||||
public:
|
||||
Compiler(JSContext* cx, ICStub::Kind kind, ICStub* firstMonitorStub,
|
||||
HandleObject holder, HandleFunction getter, uint32_t pcOffset,
|
||||
const Class* outerClass, bool receiverNative)
|
||||
const Class* outerClass)
|
||||
: ICStubCompiler(cx, kind),
|
||||
firstMonitorStub_(firstMonitorStub),
|
||||
holder_(cx, holder),
|
||||
getter_(cx, getter),
|
||||
pcOffset_(pcOffset),
|
||||
outerClass_(outerClass),
|
||||
receiverNative_(receiverNative)
|
||||
outerClass_(outerClass)
|
||||
{
|
||||
MOZ_ASSERT(kind == ICStub::GetProp_CallScripted ||
|
||||
kind == ICStub::GetProp_CallNative ||
|
||||
@@ -4353,21 +4305,21 @@ class ICGetPropCallPrototypeGetter : public ICGetPropCallGetter
|
||||
friend class ICStubSpace;
|
||||
|
||||
protected:
|
||||
// Shape/group of receiver object.
|
||||
ReceiverGuard receiverGuard_;
|
||||
// shape of receiver object.
|
||||
HeapPtrShape receiverShape_;
|
||||
|
||||
ICGetPropCallPrototypeGetter(Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard::Token receiverGuard,
|
||||
Shape* receiverShape,
|
||||
JSObject* holder, Shape* holderShape,
|
||||
JSFunction* getter, uint32_t pcOffset);
|
||||
|
||||
public:
|
||||
ReceiverGuard &receiverGuard() {
|
||||
return receiverGuard_;
|
||||
HeapPtrShape& receiverShape() {
|
||||
return receiverShape_;
|
||||
}
|
||||
|
||||
static size_t offsetOfReceiverGuard() {
|
||||
return offsetof(ICGetPropCallPrototypeGetter, receiverGuard_);
|
||||
static size_t offsetOfReceiverShape() {
|
||||
return offsetof(ICGetPropCallPrototypeGetter, receiverShape_);
|
||||
}
|
||||
|
||||
class Compiler : public ICGetPropCallGetter::Compiler {
|
||||
@@ -4379,7 +4331,7 @@ class ICGetPropCallPrototypeGetter : public ICGetPropCallGetter
|
||||
HandleObject obj, HandleObject holder, HandleFunction getter, uint32_t pcOffset,
|
||||
const Class* outerClass)
|
||||
: ICGetPropCallGetter::Compiler(cx, kind, firstMonitorStub, holder, getter, pcOffset,
|
||||
outerClass, obj->isNative()),
|
||||
outerClass),
|
||||
receiver_(cx, obj)
|
||||
{
|
||||
MOZ_ASSERT(kind == ICStub::GetProp_CallScripted ||
|
||||
@@ -4396,11 +4348,10 @@ class ICGetProp_CallScripted : public ICGetPropCallPrototypeGetter
|
||||
|
||||
protected:
|
||||
ICGetProp_CallScripted(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard::Token receiverGuard,
|
||||
JSObject *holder, Shape *holderShape,
|
||||
Shape* receiverShape, JSObject* holder, Shape* holderShape,
|
||||
JSFunction* getter, uint32_t pcOffset)
|
||||
: ICGetPropCallPrototypeGetter(GetProp_CallScripted, stubCode, firstMonitorStub,
|
||||
receiverGuard, holder, holderShape, getter, pcOffset)
|
||||
receiverShape, holder, holderShape, getter, pcOffset)
|
||||
{}
|
||||
|
||||
public:
|
||||
@@ -4420,10 +4371,10 @@ class ICGetProp_CallScripted : public ICGetPropCallPrototypeGetter
|
||||
{}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) {
|
||||
ReceiverGuard::Token guard = ReceiverGuard::objectToken(receiver_);
|
||||
Shape *holderShape = holder_->lastProperty();
|
||||
RootedShape receiverShape(cx, receiver_->lastProperty());
|
||||
RootedShape holderShape(cx, holder_->lastProperty());
|
||||
return ICStub::New<ICGetProp_CallScripted>(space, getStubCode(), firstMonitorStub_,
|
||||
guard, holder_, holderShape, getter_,
|
||||
receiverShape, holder_, holderShape, getter_,
|
||||
pcOffset_);
|
||||
}
|
||||
};
|
||||
@@ -4462,7 +4413,7 @@ class ICGetProp_CallNative : public ICGetPropCallGetter
|
||||
HandleFunction getter, uint32_t pcOffset, const Class* outerClass,
|
||||
bool inputDefinitelyObject = false)
|
||||
: ICGetPropCallGetter::Compiler(cx, ICStub::GetProp_CallNative, firstMonitorStub,
|
||||
obj, getter, pcOffset, outerClass, true),
|
||||
obj, getter, pcOffset, outerClass),
|
||||
inputDefinitelyObject_(inputDefinitelyObject)
|
||||
{}
|
||||
|
||||
@@ -4481,10 +4432,10 @@ class ICGetProp_CallNativePrototype : public ICGetPropCallPrototypeGetter
|
||||
|
||||
protected:
|
||||
ICGetProp_CallNativePrototype(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard::Token receiverGuard, JSObject* holder, Shape* holderShape,
|
||||
Shape* receiverShape, JSObject* holder, Shape* holderShape,
|
||||
JSFunction* getter, uint32_t pcOffset)
|
||||
: ICGetPropCallPrototypeGetter(GetProp_CallNativePrototype, stubCode, firstMonitorStub,
|
||||
receiverGuard, holder, holderShape, getter, pcOffset)
|
||||
receiverShape, holder, holderShape, getter, pcOffset)
|
||||
{}
|
||||
|
||||
public:
|
||||
@@ -4513,10 +4464,10 @@ class ICGetProp_CallNativePrototype : public ICGetPropCallPrototypeGetter
|
||||
{}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) {
|
||||
ReceiverGuard::Token guard = ReceiverGuard::objectToken(receiver_);
|
||||
Shape *holderShape = holder_->lastProperty();
|
||||
RootedShape receiverShape(cx, receiver_->lastProperty());
|
||||
RootedShape holderShape(cx, holder_->lastProperty());
|
||||
return ICStub::New<ICGetProp_CallNativePrototype>(space, getStubCode(), firstMonitorStub_,
|
||||
guard, holder_, holderShape,
|
||||
receiverShape, holder_, holderShape,
|
||||
getter_, pcOffset_);
|
||||
}
|
||||
};
|
||||
@@ -5123,14 +5074,14 @@ class ICSetProp_TypedObject : public ICUpdatedStub
|
||||
};
|
||||
};
|
||||
|
||||
// Base stub for calling a setters on a native or unboxed object.
|
||||
// Base stub for calling a setters on a native object.
|
||||
class ICSetPropCallSetter : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
protected:
|
||||
// Object shape/group.
|
||||
ReceiverGuard guard_;
|
||||
// Object shape (lastProperty).
|
||||
HeapPtrShape shape_;
|
||||
|
||||
// Holder and shape.
|
||||
HeapPtrObject holder_;
|
||||
@@ -5142,12 +5093,12 @@ class ICSetPropCallSetter : public ICStub
|
||||
// PC of call, for profiler
|
||||
uint32_t pcOffset_;
|
||||
|
||||
ICSetPropCallSetter(Kind kind, JitCode* stubCode, ReceiverGuard::Token guard, JSObject* holder,
|
||||
ICSetPropCallSetter(Kind kind, JitCode* stubCode, Shape* shape, JSObject* holder,
|
||||
Shape* holderShape, JSFunction* setter, uint32_t pcOffset);
|
||||
|
||||
public:
|
||||
ReceiverGuard &guard() {
|
||||
return guard_;
|
||||
HeapPtrShape& shape() {
|
||||
return shape_;
|
||||
}
|
||||
HeapPtrObject& holder() {
|
||||
return holder_;
|
||||
@@ -5159,8 +5110,8 @@ class ICSetPropCallSetter : public ICStub
|
||||
return setter_;
|
||||
}
|
||||
|
||||
static size_t offsetOfGuard() {
|
||||
return offsetof(ICSetPropCallSetter, guard_);
|
||||
static size_t offsetOfShape() {
|
||||
return offsetof(ICSetPropCallSetter, shape_);
|
||||
}
|
||||
static size_t offsetOfHolder() {
|
||||
return offsetof(ICSetPropCallSetter, holder_);
|
||||
@@ -5182,11 +5133,6 @@ class ICSetPropCallSetter : public ICStub
|
||||
RootedFunction setter_;
|
||||
uint32_t pcOffset_;
|
||||
|
||||
virtual int32_t getKey() const {
|
||||
return static_cast<int32_t>(kind) |
|
||||
(static_cast<int32_t>(obj_->isNative()) << 16);
|
||||
}
|
||||
|
||||
public:
|
||||
Compiler(JSContext* cx, ICStub::Kind kind, HandleObject obj, HandleObject holder,
|
||||
HandleFunction setter, uint32_t pcOffset)
|
||||
@@ -5207,9 +5153,9 @@ class ICSetProp_CallScripted : public ICSetPropCallSetter
|
||||
friend class ICStubSpace;
|
||||
|
||||
protected:
|
||||
ICSetProp_CallScripted(JitCode* stubCode, ReceiverGuard::Token guard, JSObject* holder,
|
||||
ICSetProp_CallScripted(JitCode* stubCode, Shape* shape, JSObject* holder,
|
||||
Shape* holderShape, JSFunction* setter, uint32_t pcOffset)
|
||||
: ICSetPropCallSetter(SetProp_CallScripted, stubCode, guard, holder, holderShape,
|
||||
: ICSetPropCallSetter(SetProp_CallScripted, stubCode, shape, holder, holderShape,
|
||||
setter, pcOffset)
|
||||
{}
|
||||
|
||||
@@ -5229,9 +5175,9 @@ class ICSetProp_CallScripted : public ICSetPropCallSetter
|
||||
{}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) {
|
||||
ReceiverGuard::Token guard = ReceiverGuard::objectToken(obj_);
|
||||
Shape *holderShape = holder_->lastProperty();
|
||||
return ICStub::New<ICSetProp_CallScripted>(space, getStubCode(), guard, holder_,
|
||||
RootedShape shape(cx, obj_->lastProperty());
|
||||
RootedShape holderShape(cx, holder_->lastProperty());
|
||||
return ICStub::New<ICSetProp_CallScripted>(space, getStubCode(), shape, holder_,
|
||||
holderShape, setter_, pcOffset_);
|
||||
}
|
||||
};
|
||||
@@ -5243,9 +5189,9 @@ class ICSetProp_CallNative : public ICSetPropCallSetter
|
||||
friend class ICStubSpace;
|
||||
|
||||
protected:
|
||||
ICSetProp_CallNative(JitCode* stubCode, ReceiverGuard::Token guard, JSObject* holder,
|
||||
ICSetProp_CallNative(JitCode* stubCode, Shape* shape, JSObject* holder,
|
||||
Shape* holderShape, JSFunction* setter, uint32_t pcOffset)
|
||||
: ICSetPropCallSetter(SetProp_CallNative, stubCode, guard, holder, holderShape,
|
||||
: ICSetPropCallSetter(SetProp_CallNative, stubCode, shape, holder, holderShape,
|
||||
setter, pcOffset)
|
||||
{}
|
||||
|
||||
@@ -5265,9 +5211,9 @@ class ICSetProp_CallNative : public ICSetPropCallSetter
|
||||
{}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) {
|
||||
ReceiverGuard::Token guard = ReceiverGuard::objectToken(obj_);
|
||||
Shape *holderShape = holder_->lastProperty();
|
||||
return ICStub::New<ICSetProp_CallNative>(space, getStubCode(), guard, holder_,
|
||||
RootedShape shape(cx, obj_->lastProperty());
|
||||
RootedShape holderShape(cx, holder_->lastProperty());
|
||||
return ICStub::New<ICSetProp_CallNative>(space, getStubCode(), shape, holder_,
|
||||
holderShape, setter_, pcOffset_);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -574,55 +574,49 @@ static Shape* GlobalShapeForGetPropFunction(ICStub* stub)
|
||||
if (stub->isGetProp_CallNativePrototype()) {
|
||||
ICGetProp_CallNativePrototype* nstub =
|
||||
stub->toGetProp_CallNativePrototype();
|
||||
const ReceiverGuard &guard = nstub->receiverGuard();
|
||||
if (Shape *shape = guard.shape()) {
|
||||
if (shape->getObjectClass()->flags & JSCLASS_IS_GLOBAL)
|
||||
return shape;
|
||||
}
|
||||
if (nstub->receiverShape()->getObjectClass()->flags & JSCLASS_IS_GLOBAL)
|
||||
return nstub->receiverShape();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool
|
||||
AddReceiver(BaselineInspector::ShapeVector &nativeShapes,
|
||||
BaselineInspector::ObjectGroupVector &unboxedGroups,
|
||||
ReceiverGuard::Token receiver)
|
||||
AddReceiverShape(BaselineInspector::ShapeVector& shapes, Shape* shape)
|
||||
{
|
||||
if (Shape *shape = ReceiverGuard::tokenShape(receiver))
|
||||
return VectorAppendNoDuplicate(nativeShapes, shape);
|
||||
ObjectGroup *group = ReceiverGuard::tokenGroup(receiver);
|
||||
return VectorAppendNoDuplicate(unboxedGroups, group);
|
||||
MOZ_ASSERT(shape);
|
||||
|
||||
for (size_t i = 0; i < shapes.length(); i++) {
|
||||
if (shapes[i] == shape)
|
||||
return true;
|
||||
}
|
||||
|
||||
return shapes.append(shape);
|
||||
}
|
||||
|
||||
static bool
|
||||
AddReceiverForGetPropFunction(BaselineInspector::ShapeVector &nativeShapes,
|
||||
BaselineInspector::ObjectGroupVector &unboxedGroups,
|
||||
ICStub *stub)
|
||||
AddReceiverShapeForGetPropFunction(BaselineInspector::ShapeVector& shapes, ICStub* stub)
|
||||
{
|
||||
if (stub->isGetProp_CallNative())
|
||||
return true;
|
||||
|
||||
ReceiverGuard::Token token;
|
||||
Shape* shape = nullptr;
|
||||
if (stub->isGetProp_CallScripted())
|
||||
token = stub->toGetProp_CallScripted()->receiverGuard().token();
|
||||
shape = stub->toGetProp_CallScripted()->receiverShape();
|
||||
else
|
||||
token = stub->toGetProp_CallNativePrototype()->receiverGuard().token();
|
||||
shape = stub->toGetProp_CallNativePrototype()->receiverShape();
|
||||
|
||||
return AddReceiver(nativeShapes, unboxedGroups, token);
|
||||
return AddReceiverShape(shapes, shape);
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineInspector::commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
|
||||
JSFunction** commonGetter, Shape** globalShape,
|
||||
bool *isOwnProperty,
|
||||
ShapeVector &nativeShapes,
|
||||
ObjectGroupVector &unboxedGroups)
|
||||
bool* isOwnProperty, ShapeVector& receiverShapes)
|
||||
{
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(nativeShapes.empty());
|
||||
MOZ_ASSERT(unboxedGroups.empty());
|
||||
MOZ_ASSERT(receiverShapes.empty());
|
||||
|
||||
*holder = nullptr;
|
||||
const ICEntry& entry = icEntryFromPC(pc);
|
||||
@@ -634,7 +628,7 @@ BaselineInspector::commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shap
|
||||
{
|
||||
ICGetPropCallGetter* nstub = static_cast<ICGetPropCallGetter*>(stub);
|
||||
bool isOwn = stub->isGetProp_CallNative();
|
||||
if (!AddReceiverForGetPropFunction(nativeShapes, unboxedGroups, nstub))
|
||||
if (!AddReceiverShapeForGetPropFunction(receiverShapes, nstub))
|
||||
return false;
|
||||
|
||||
if (!*holder) {
|
||||
@@ -666,21 +660,19 @@ BaselineInspector::commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shap
|
||||
if (!*holder)
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(*isOwnProperty == (nativeShapes.empty() && unboxedGroups.empty()));
|
||||
MOZ_ASSERT(*isOwnProperty == receiverShapes.empty());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
|
||||
JSFunction** commonSetter, bool* isOwnProperty,
|
||||
ShapeVector &nativeShapes,
|
||||
ObjectGroupVector &unboxedGroups)
|
||||
ShapeVector& receiverShapes)
|
||||
{
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(nativeShapes.empty());
|
||||
MOZ_ASSERT(unboxedGroups.empty());
|
||||
MOZ_ASSERT(receiverShapes.empty());
|
||||
|
||||
*holder = nullptr;
|
||||
const ICEntry& entry = icEntryFromPC(pc);
|
||||
@@ -688,7 +680,7 @@ BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shap
|
||||
for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
|
||||
if (stub->isSetProp_CallScripted() || stub->isSetProp_CallNative()) {
|
||||
ICSetPropCallSetter* nstub = static_cast<ICSetPropCallSetter*>(stub);
|
||||
if (!AddReceiver(nativeShapes, unboxedGroups, nstub->guard().token()))
|
||||
if (!AddReceiverShape(receiverShapes, nstub->shape()))
|
||||
return false;
|
||||
|
||||
if (!*holder) {
|
||||
|
||||
@@ -126,10 +126,10 @@ class BaselineInspector
|
||||
|
||||
bool commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
|
||||
JSFunction** commonGetter, Shape** globalShape, bool* isOwnProperty,
|
||||
ShapeVector &nativeShapes, ObjectGroupVector &unboxedGroups);
|
||||
ShapeVector& receiverShapes);
|
||||
bool commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
|
||||
JSFunction** commonSetter, bool* isOwnProperty,
|
||||
ShapeVector &nativeShapes, ObjectGroupVector &unboxedGroups);
|
||||
ShapeVector& receiverShapes);
|
||||
|
||||
bool instanceOfData(jsbytecode* pc, Shape** shape, uint32_t* slot, JSObject** prototypeObject);
|
||||
};
|
||||
|
||||
@@ -130,7 +130,7 @@ BytecodeAnalysis::init(TempAllocator& alloc, GSNCache& gsn)
|
||||
jssrcnote* sn = GetSrcNote(gsn, script_, pc);
|
||||
MOZ_ASSERT(SN_TYPE(sn) == SRC_TRY);
|
||||
|
||||
jsbytecode* endOfTry = pc + GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* endOfTry = pc + js_GetSrcNoteOffset(sn, 0);
|
||||
MOZ_ASSERT(JSOp(*endOfTry) == JSOP_GOTO);
|
||||
|
||||
jsbytecode* afterTry = endOfTry + GET_JUMP_OFFSET(endOfTry);
|
||||
|
||||
@@ -2533,38 +2533,23 @@ CodeGenerator::visitGuardObjectIdentity(LGuardObjectIdentity* guard)
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitGuardReceiverPolymorphic(LGuardReceiverPolymorphic *lir)
|
||||
CodeGenerator::visitGuardShapePolymorphic(LGuardShapePolymorphic* lir)
|
||||
{
|
||||
const MGuardReceiverPolymorphic *mir = lir->mir();
|
||||
const MGuardShapePolymorphic* mir = lir->mir();
|
||||
Register obj = ToRegister(lir->object());
|
||||
Register temp = ToRegister(lir->temp());
|
||||
|
||||
MOZ_ASSERT(mir->numShapes() + mir->numUnboxedGroups() > 1);
|
||||
MOZ_ASSERT(mir->numShapes() > 1);
|
||||
|
||||
Label done;
|
||||
masm.loadObjShape(obj, temp);
|
||||
|
||||
if (mir->numShapes()) {
|
||||
masm.loadObjShape(obj, temp);
|
||||
|
||||
for (size_t i = 0; i < mir->numShapes(); i++) {
|
||||
Shape *shape = mir->getShape(i);
|
||||
if (i == mir->numShapes() - 1 && !mir->numUnboxedGroups())
|
||||
bailoutCmpPtr(Assembler::NotEqual, temp, ImmGCPtr(shape), lir->snapshot());
|
||||
else
|
||||
masm.branchPtr(Assembler::Equal, temp, ImmGCPtr(shape), &done);
|
||||
}
|
||||
}
|
||||
|
||||
if (mir->numUnboxedGroups()) {
|
||||
masm.loadObjGroup(obj, temp);
|
||||
|
||||
for (size_t i = 0; i < mir->numUnboxedGroups(); i++) {
|
||||
ObjectGroup *group = mir->getUnboxedGroup(i);
|
||||
if (i == mir->numUnboxedGroups() - 1)
|
||||
bailoutCmpPtr(Assembler::NotEqual, temp, ImmGCPtr(group), lir->snapshot());
|
||||
else
|
||||
masm.branchPtr(Assembler::Equal, temp, ImmGCPtr(group), &done);
|
||||
}
|
||||
for (size_t i = 0; i < mir->numShapes(); i++) {
|
||||
Shape* shape = mir->getShape(i);
|
||||
if (i == mir->numShapes() - 1)
|
||||
bailoutCmpPtr(Assembler::NotEqual, temp, ImmGCPtr(shape), lir->snapshot());
|
||||
else
|
||||
masm.branchPtr(Assembler::Equal, temp, ImmGCPtr(shape), &done);
|
||||
}
|
||||
|
||||
masm.bind(&done);
|
||||
@@ -4197,12 +4182,8 @@ class OutOfLineNewObject : public OutOfLineCodeBase<CodeGenerator>
|
||||
}
|
||||
};
|
||||
|
||||
typedef JSObject *(*NewInitObjectWithTemplateFn)(JSContext *, HandleObject);
|
||||
static const VMFunction NewInitObjectWithTemplateInfo =
|
||||
FunctionInfo<NewInitObjectWithTemplateFn>(NewObjectOperationWithTemplate);
|
||||
|
||||
typedef JSObject *(*NewInitObjectFn)(JSContext *, HandleScript, jsbytecode *pc, NewObjectKind);
|
||||
static const VMFunction NewInitObjectInfo = FunctionInfo<NewInitObjectFn>(NewObjectOperation);
|
||||
typedef JSObject* (*NewInitObjectFn)(JSContext*, HandlePlainObject);
|
||||
static const VMFunction NewInitObjectInfo = FunctionInfo<NewInitObjectFn>(NewInitObject);
|
||||
|
||||
typedef PlainObject* (*ObjectCreateWithTemplateFn)(JSContext*, HandlePlainObject);
|
||||
static const VMFunction ObjectCreateWithTemplateInfo =
|
||||
@@ -4216,25 +4197,16 @@ CodeGenerator::visitNewObjectVMCall(LNewObject* lir)
|
||||
MOZ_ASSERT(!lir->isCall());
|
||||
saveLive(lir);
|
||||
|
||||
JSObject *templateObject = lir->mir()->templateObject();
|
||||
pushArg(ImmGCPtr(lir->mir()->templateObject()));
|
||||
|
||||
// If we're making a new object with a class prototype (that is, an object
|
||||
// that derives its class from its prototype instead of being
|
||||
// PlainObject::class_'d) from self-hosted code, we need a different init
|
||||
// JSObject::class_'d) from self-hosted code, we need a different init
|
||||
// function.
|
||||
if (lir->mir()->mode() == MNewObject::ObjectLiteral) {
|
||||
if (templateObject) {
|
||||
pushArg(ImmGCPtr(templateObject));
|
||||
callVM(NewInitObjectWithTemplateInfo, lir);
|
||||
} else {
|
||||
pushArg(Imm32(GenericObject));
|
||||
pushArg(ImmPtr(lir->mir()->resumePoint()->pc()));
|
||||
pushArg(ImmGCPtr(lir->mir()->block()->info().script()));
|
||||
callVM(NewInitObjectInfo, lir);
|
||||
}
|
||||
callVM(NewInitObjectInfo, lir);
|
||||
} else {
|
||||
MOZ_ASSERT(lir->mir()->mode() == MNewObject::ObjectCreate);
|
||||
pushArg(ImmGCPtr(templateObject));
|
||||
callVM(ObjectCreateWithTemplateInfo, lir);
|
||||
}
|
||||
|
||||
@@ -4245,12 +4217,8 @@ CodeGenerator::visitNewObjectVMCall(LNewObject* lir)
|
||||
}
|
||||
|
||||
static bool
|
||||
ShouldInitFixedSlots(LInstruction *lir, JSObject *obj)
|
||||
ShouldInitFixedSlots(LInstruction* lir, NativeObject* templateObj)
|
||||
{
|
||||
if (!obj->isNative())
|
||||
return true;
|
||||
NativeObject *templateObj = &obj->as<NativeObject>();
|
||||
|
||||
// Look for StoreFixedSlot instructions following an object allocation
|
||||
// that write to this object before a GC is triggered or this object is
|
||||
// passed to a VM call. If all fixed slots will be initialized, the
|
||||
@@ -4337,7 +4305,7 @@ CodeGenerator::visitNewObject(LNewObject* lir)
|
||||
{
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
JSObject* templateObject = lir->mir()->templateObject();
|
||||
PlainObject* templateObject = lir->mir()->templateObject();
|
||||
|
||||
if (lir->mir()->shouldUseVM()) {
|
||||
visitNewObjectVMCall(lir);
|
||||
@@ -4635,7 +4603,8 @@ CodeGenerator::visitMutateProto(LMutateProto* lir)
|
||||
callVM(MutatePrototypeInfo, lir);
|
||||
}
|
||||
|
||||
typedef bool(*InitPropFn)(JSContext *, HandleObject, HandlePropertyName, HandleValue, jsbytecode *pc);
|
||||
typedef bool(*InitPropFn)(JSContext *cx, HandleNativeObject obj,
|
||||
HandlePropertyName name, HandleValue value, jsbytecode *pc);
|
||||
static const VMFunction InitPropInfo = FunctionInfo<InitPropFn>(InitProp);
|
||||
|
||||
void
|
||||
|
||||
@@ -123,7 +123,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
void visitMaybeToDoubleElement(LMaybeToDoubleElement* lir);
|
||||
void visitMaybeCopyElementsForWrite(LMaybeCopyElementsForWrite* lir);
|
||||
void visitGuardObjectIdentity(LGuardObjectIdentity* guard);
|
||||
void visitGuardReceiverPolymorphic(LGuardReceiverPolymorphic *lir);
|
||||
void visitGuardShapePolymorphic(LGuardShapePolymorphic* lir);
|
||||
void visitTypeBarrierV(LTypeBarrierV* lir);
|
||||
void visitTypeBarrierO(LTypeBarrierO* lir);
|
||||
void visitMonitorTypes(LMonitorTypes* lir);
|
||||
|
||||
+7
-13
@@ -1903,20 +1903,14 @@ IonCompile(JSContext* cx, JSScript* script,
|
||||
|
||||
if (!succeeded) {
|
||||
AbortReason reason = builder->abortReason();
|
||||
if (reason == AbortReason_PreliminaryObjects) {
|
||||
// Some group was accessed which has associated preliminary objects
|
||||
// to analyze. Do this now and we will try to build again shortly.
|
||||
const MIRGenerator::ObjectGroupVector &groups = builder->abortedPreliminaryGroups();
|
||||
if (reason == AbortReason_NewScriptProperties) {
|
||||
// Some type was accessed which needs the new script properties
|
||||
// analysis to be performed. Do this now and we will try to build
|
||||
// again shortly.
|
||||
const MIRGenerator::ObjectGroupVector& groups = builder->abortedNewScriptPropertiesGroups();
|
||||
for (size_t i = 0; i < groups.length(); i++) {
|
||||
ObjectGroup *group = groups[i];
|
||||
if (group->newScript()) {
|
||||
if (!group->newScript()->maybeAnalyze(cx, group, nullptr, /* force = */ true))
|
||||
return AbortReason_Alloc;
|
||||
} else if (group->maybePreliminaryObjects()) {
|
||||
group->maybePreliminaryObjects()->maybeAnalyze(cx, group, /* force = */ true);
|
||||
} else {
|
||||
MOZ_CRASH("Unexpected aborted preliminary group");
|
||||
}
|
||||
if (!groups[i]->newScript()->maybeAnalyze(cx, groups[i], nullptr, /* force = */ true))
|
||||
return AbortReason_Alloc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ enum MethodStatus
|
||||
enum AbortReason {
|
||||
AbortReason_Alloc,
|
||||
AbortReason_Inlining,
|
||||
AbortReason_PreliminaryObjects,
|
||||
AbortReason_NewScriptProperties,
|
||||
AbortReason_Disable,
|
||||
AbortReason_Error,
|
||||
AbortReason_NoAbort
|
||||
|
||||
@@ -538,8 +538,7 @@ jit::EliminateDeadResumePointOperands(MIRGenerator* mir, MIRGraph& graph)
|
||||
bool
|
||||
js::jit::DeadIfUnused(const MDefinition* def)
|
||||
{
|
||||
return !def->isEffectful() && !def->isGuard() && !def->isGuardRangeBailouts() &&
|
||||
!def->isControlInstruction() &&
|
||||
return !def->isEffectful() && !def->isGuard() && !def->isControlInstruction() &&
|
||||
(!def->isInstruction() || !def->toInstruction()->resumePoint());
|
||||
}
|
||||
|
||||
|
||||
+114
-125
@@ -887,9 +887,9 @@ IonBuilder::build()
|
||||
if (!processIterators())
|
||||
return false;
|
||||
|
||||
if (!abortedPreliminaryGroups().empty()) {
|
||||
if (!abortedNewScriptPropertiesGroups().empty()) {
|
||||
MOZ_ASSERT(!info().isAnalysis());
|
||||
abortReason_ = AbortReason_PreliminaryObjects;
|
||||
abortReason_ = AbortReason_NewScriptProperties;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1042,9 +1042,9 @@ IonBuilder::buildInline(IonBuilder* callerBuilder, MResumePoint* callerResumePoi
|
||||
// Discard unreferenced & pre-allocated resume points.
|
||||
replaceMaybeFallbackFunctionGetter(nullptr);
|
||||
|
||||
if (!abortedPreliminaryGroups().empty()) {
|
||||
if (!abortedNewScriptPropertiesGroups().empty()) {
|
||||
MOZ_ASSERT(!info().isAnalysis());
|
||||
abortReason_ = AbortReason_PreliminaryObjects;
|
||||
abortReason_ = AbortReason_NewScriptProperties;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2954,7 +2954,7 @@ IonBuilder::assertValidLoopHeadOp(jsbytecode* pc)
|
||||
// do-while loops have a source note.
|
||||
jssrcnote* sn = info().getNote(gsn, pc);
|
||||
if (sn) {
|
||||
jsbytecode* ifne = pc + GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* ifne = pc + js_GetSrcNoteOffset(sn, 0);
|
||||
|
||||
jsbytecode* expected_ifne;
|
||||
switch (state.state) {
|
||||
@@ -2987,11 +2987,11 @@ IonBuilder::doWhileLoop(JSOp op, jssrcnote* sn)
|
||||
// COND ; start of condition
|
||||
// ...
|
||||
// IFNE -> ; goes to LOOPHEAD
|
||||
int condition_offset = GetSrcNoteOffset(sn, 0);
|
||||
int condition_offset = js_GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* conditionpc = pc + condition_offset;
|
||||
|
||||
jssrcnote* sn2 = info().getNote(gsn, pc+1);
|
||||
int offset = GetSrcNoteOffset(sn2, 0);
|
||||
int offset = js_GetSrcNoteOffset(sn2, 0);
|
||||
jsbytecode* ifne = pc + offset + 1;
|
||||
MOZ_ASSERT(ifne > pc);
|
||||
|
||||
@@ -3057,7 +3057,7 @@ IonBuilder::whileOrForInLoop(jssrcnote* sn)
|
||||
// IFNE ; goes to LOOPHEAD
|
||||
// for (x in y) { } loops are similar; the cond will be a MOREITER.
|
||||
MOZ_ASSERT(SN_TYPE(sn) == SRC_FOR_OF || SN_TYPE(sn) == SRC_FOR_IN || SN_TYPE(sn) == SRC_WHILE);
|
||||
int ifneOffset = GetSrcNoteOffset(sn, 0);
|
||||
int ifneOffset = js_GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* ifne = pc + ifneOffset;
|
||||
MOZ_ASSERT(ifne > pc);
|
||||
|
||||
@@ -3121,9 +3121,9 @@ IonBuilder::forLoop(JSOp op, jssrcnote* sn)
|
||||
MOZ_ASSERT(op == JSOP_POP || op == JSOP_NOP);
|
||||
pc = GetNextPc(pc);
|
||||
|
||||
jsbytecode* condpc = pc + GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* updatepc = pc + GetSrcNoteOffset(sn, 1);
|
||||
jsbytecode* ifne = pc + GetSrcNoteOffset(sn, 2);
|
||||
jsbytecode* condpc = pc + js_GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* updatepc = pc + js_GetSrcNoteOffset(sn, 1);
|
||||
jsbytecode* ifne = pc + js_GetSrcNoteOffset(sn, 2);
|
||||
jsbytecode* exitpc = GetNextPc(ifne);
|
||||
|
||||
// for loops have the following structures:
|
||||
@@ -3253,7 +3253,7 @@ IonBuilder::tableSwitch(JSOp op, jssrcnote* sn)
|
||||
MDefinition* ins = current->pop();
|
||||
|
||||
// Get the default and exit pc
|
||||
jsbytecode* exitpc = pc + GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* exitpc = pc + js_GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* defaultpc = pc + GET_JUMP_OFFSET(pc);
|
||||
|
||||
MOZ_ASSERT(defaultpc > pc && defaultpc <= exitpc);
|
||||
@@ -3832,8 +3832,8 @@ IonBuilder::jsop_condswitch()
|
||||
MOZ_ASSERT(SN_TYPE(sn) == SRC_CONDSWITCH);
|
||||
|
||||
// Get the exit pc
|
||||
jsbytecode* exitpc = pc + GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* firstCase = pc + GetSrcNoteOffset(sn, 1);
|
||||
jsbytecode* exitpc = pc + js_GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* firstCase = pc + js_GetSrcNoteOffset(sn, 1);
|
||||
|
||||
// Iterate all cases in the conditional switch.
|
||||
// - Stop at the default case. (always emitted after the last case)
|
||||
@@ -3848,7 +3848,7 @@ IonBuilder::jsop_condswitch()
|
||||
// Fetch the next case.
|
||||
jssrcnote* caseSn = info().getNote(gsn, curCase);
|
||||
MOZ_ASSERT(caseSn && SN_TYPE(caseSn) == SRC_NEXTCASE);
|
||||
ptrdiff_t off = GetSrcNoteOffset(caseSn, 0);
|
||||
ptrdiff_t off = js_GetSrcNoteOffset(caseSn, 0);
|
||||
curCase = off ? curCase + off : GetNextPc(curCase);
|
||||
MOZ_ASSERT(pc < curCase && curCase <= exitpc);
|
||||
|
||||
@@ -3928,7 +3928,7 @@ IonBuilder::processCondSwitchCase(CFGState& state)
|
||||
|
||||
// Fetch the following case in which we will continue.
|
||||
jssrcnote* sn = info().getNote(gsn, pc);
|
||||
ptrdiff_t off = GetSrcNoteOffset(sn, 0);
|
||||
ptrdiff_t off = js_GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* casePc = off ? pc + off : GetNextPc(pc);
|
||||
bool caseIsDefault = JSOp(*casePc) == JSOP_DEFAULT;
|
||||
MOZ_ASSERT(JSOp(*casePc) == JSOP_CASE || caseIsDefault);
|
||||
@@ -4209,7 +4209,7 @@ IonBuilder::jsop_ifeq(JSOp op)
|
||||
{
|
||||
// Infer the join point from the JSOP_GOTO[X] sitting here, then
|
||||
// assert as we much we can that this is the right GOTO.
|
||||
jsbytecode* trueEnd = pc + GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* trueEnd = pc + js_GetSrcNoteOffset(sn, 0);
|
||||
MOZ_ASSERT(trueEnd > pc);
|
||||
MOZ_ASSERT(trueEnd < falseStart);
|
||||
MOZ_ASSERT(JSOp(*trueEnd) == JSOP_GOTO);
|
||||
@@ -4264,7 +4264,7 @@ IonBuilder::jsop_try()
|
||||
|
||||
// Get the pc of the last instruction in the try block. It's a JSOP_GOTO to
|
||||
// jump over the catch block.
|
||||
jsbytecode* endpc = pc + GetSrcNoteOffset(sn, 0);
|
||||
jsbytecode* endpc = pc + js_GetSrcNoteOffset(sn, 0);
|
||||
MOZ_ASSERT(JSOp(*endpc) == JSOP_GOTO);
|
||||
MOZ_ASSERT(GetJumpOffset(endpc) > 0);
|
||||
|
||||
@@ -4679,12 +4679,14 @@ IonBuilder::inlineScriptedCall(CallInfo& callInfo, JSFunction* target)
|
||||
if (inlineBuilder.abortReason_ == AbortReason_Disable) {
|
||||
calleeScript->setUninlineable();
|
||||
abortReason_ = AbortReason_Inlining;
|
||||
} else if (inlineBuilder.abortReason_ == AbortReason_PreliminaryObjects) {
|
||||
const ObjectGroupVector &groups = inlineBuilder.abortedPreliminaryGroups();
|
||||
} else if (inlineBuilder.abortReason_ == AbortReason_Inlining) {
|
||||
abortReason_ = AbortReason_Inlining;
|
||||
} else if (inlineBuilder.abortReason_ == AbortReason_NewScriptProperties) {
|
||||
const ObjectGroupVector& groups = inlineBuilder.abortedNewScriptPropertiesGroups();
|
||||
MOZ_ASSERT(!groups.empty());
|
||||
for (size_t i = 0; i < groups.length(); i++)
|
||||
addAbortedPreliminaryGroup(groups[i]);
|
||||
abortReason_ = AbortReason_PreliminaryObjects;
|
||||
addAbortedNewScriptPropertiesGroup(groups[i]);
|
||||
abortReason_ = AbortReason_NewScriptProperties;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -6436,19 +6438,23 @@ bool
|
||||
IonBuilder::jsop_newobject()
|
||||
{
|
||||
JSObject* templateObject = inspector->getTemplateObject(pc);
|
||||
gc::InitialHeap heap;
|
||||
MConstant *templateConst;
|
||||
|
||||
if (templateObject) {
|
||||
heap = templateObject->group()->initialHeap(constraints());
|
||||
templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
|
||||
} else {
|
||||
heap = gc::DefaultHeap;
|
||||
templateConst = MConstant::New(alloc(), NullValue());
|
||||
if (!templateObject) {
|
||||
if (info().analysisMode() == Analysis_ArgumentsUsage) {
|
||||
MUnknownValue* unknown = MUnknownValue::New(alloc());
|
||||
current->add(unknown);
|
||||
current->push(unknown);
|
||||
return true;
|
||||
}
|
||||
return abort("No template object for NEWOBJECT");
|
||||
}
|
||||
|
||||
MOZ_ASSERT(templateObject->is<PlainObject>());
|
||||
MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
|
||||
current->add(templateConst);
|
||||
MNewObject *ins = MNewObject::New(alloc(), constraints(), templateConst, heap,
|
||||
MNewObject* ins = MNewObject::New(alloc(), constraints(), templateConst,
|
||||
templateObject->isSingleton()
|
||||
? gc::TenuredHeap
|
||||
: templateObject->group()->initialHeap(constraints()),
|
||||
MNewObject::ObjectLiteral);
|
||||
|
||||
current->add(ins);
|
||||
@@ -6550,53 +6556,66 @@ IonBuilder::jsop_mutateproto()
|
||||
bool
|
||||
IonBuilder::jsop_initprop(PropertyName* name)
|
||||
{
|
||||
MDefinition* value = current->pop();
|
||||
MDefinition* obj = current->peek(-1);
|
||||
|
||||
NativeObject* templateObject = nullptr;
|
||||
Shape* shape = nullptr;
|
||||
|
||||
bool useSlowPath = false;
|
||||
|
||||
MDefinition *value = current->peek(-1);
|
||||
MDefinition *obj = current->peek(-2);
|
||||
if (obj->isLambda()) {
|
||||
if (obj->isUnknownValue()) {
|
||||
useSlowPath = true;
|
||||
} else if (JSObject *templateObject = obj->toNewObject()->templateObject()) {
|
||||
if (templateObject->is<PlainObject>()) {
|
||||
if (!templateObject->as<PlainObject>().containsPure(name))
|
||||
useSlowPath = true;
|
||||
} else {
|
||||
MOZ_ASSERT(templateObject->as<UnboxedPlainObject>().layout().lookup(name));
|
||||
}
|
||||
} else {
|
||||
templateObject = obj->toNewObject()->templateObject();
|
||||
shape = templateObject->lastProperty()->searchLinear(NameToId(name));
|
||||
|
||||
if (!shape)
|
||||
useSlowPath = true;
|
||||
}
|
||||
|
||||
if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
|
||||
&obj, name, &value, /* canModify = */ true))
|
||||
{
|
||||
useSlowPath = true;
|
||||
}
|
||||
|
||||
if (useSlowPath) {
|
||||
current->pop();
|
||||
// JSOP_NEWINIT becomes an MNewObject without preconfigured properties.
|
||||
MInitProp *init = MInitProp::New(alloc(), obj, name, value);
|
||||
current->add(init);
|
||||
return resumeAfter(init);
|
||||
}
|
||||
|
||||
MInstruction *last = *current->rbegin();
|
||||
if (NeedsPostBarrier(info(), value))
|
||||
current->add(MPostWriteBarrier::New(alloc(), obj, value));
|
||||
|
||||
// This is definitely initializing an 'own' property of the object, treat
|
||||
// it as an assignment.
|
||||
if (!jsop_setprop(name))
|
||||
return false;
|
||||
|
||||
// SETPROP pushed the value, instead of the object. Fix this on the stack,
|
||||
// and check the most recent resume point to see if it needs updating too.
|
||||
current->pop();
|
||||
current->push(obj);
|
||||
for (MInstructionReverseIterator riter = current->rbegin(); *riter != last; riter++) {
|
||||
if (MResumePoint *resumePoint = riter->resumePoint()) {
|
||||
MOZ_ASSERT(resumePoint->pc() == pc);
|
||||
if (resumePoint->mode() == MResumePoint::ResumeAfter) {
|
||||
size_t index = resumePoint->numOperands() - 1;
|
||||
resumePoint->replaceOperand(index, obj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
bool needsBarrier = true;
|
||||
if (obj->resultTypeSet() &&
|
||||
!obj->resultTypeSet()->propertyNeedsBarrier(constraints(), NameToId(name)))
|
||||
{
|
||||
needsBarrier = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (templateObject->isFixedSlot(shape->slot())) {
|
||||
MStoreFixedSlot* store = MStoreFixedSlot::New(alloc(), obj, shape->slot(), value);
|
||||
if (needsBarrier)
|
||||
store->setNeedsBarrier();
|
||||
|
||||
current->add(store);
|
||||
return resumeAfter(store);
|
||||
}
|
||||
|
||||
MSlots *slots = MSlots::New(alloc(), obj);
|
||||
current->add(slots);
|
||||
|
||||
uint32_t slot = templateObject->dynamicSlotIndex(shape->slot());
|
||||
MStoreSlot* store = MStoreSlot::New(alloc(), slots, slot, value);
|
||||
if (needsBarrier)
|
||||
store->setNeedsBarrier();
|
||||
|
||||
current->add(store);
|
||||
return resumeAfter(store);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -9353,9 +9372,8 @@ IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
// Watch for groups which still have preliminary object information and
|
||||
// have not had the new script properties other analyses performed on their
|
||||
// preliminary objects. Normally this is done after a small number of the
|
||||
// Watch for types which the new script properties analysis has not been
|
||||
// performed on yet. Normally this is done after a small number of the
|
||||
// objects have been created, but if only a few have been created we can
|
||||
// still perform the analysis with a smaller object population. The
|
||||
// analysis can have side effects so abort the builder and retry later.
|
||||
@@ -9372,12 +9390,7 @@ IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_
|
||||
|
||||
if (ObjectGroup* group = key->maybeGroup()) {
|
||||
if (group->newScript() && !group->newScript()->analyzed()) {
|
||||
addAbortedPreliminaryGroup(group);
|
||||
trackOptimizationOutcome(TrackedOutcome::NoAnalysisInfo);
|
||||
return UINT32_MAX;
|
||||
}
|
||||
if (group->maybePreliminaryObjects()) {
|
||||
addAbortedPreliminaryGroup(group);
|
||||
addAbortedNewScriptPropertiesGroup(group);
|
||||
trackOptimizationOutcome(TrackedOutcome::NoAnalysisInfo);
|
||||
return UINT32_MAX;
|
||||
}
|
||||
@@ -10497,9 +10510,8 @@ IonBuilder::getPropTryUnboxed(bool* emitted, MDefinition* obj, PropertyName* nam
|
||||
|
||||
MDefinition*
|
||||
IonBuilder::addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Shape* holderShape,
|
||||
const BaselineInspector::ShapeVector &receiverShapes,
|
||||
const BaselineInspector::ObjectGroupVector &receiverUnboxedGroups,
|
||||
bool isOwnProperty)
|
||||
const BaselineInspector::ShapeVector& receiverShapes,
|
||||
bool isOwnProperty)
|
||||
{
|
||||
MOZ_ASSERT(holder);
|
||||
MOZ_ASSERT(holderShape);
|
||||
@@ -10512,7 +10524,7 @@ IonBuilder::addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Sh
|
||||
MDefinition* holderDef = constantMaybeNursery(holder);
|
||||
addShapeGuard(holderDef, holderShape, Bailout_ShapeGuard);
|
||||
|
||||
return addShapeGuardPolymorphic(obj, receiverShapes, receiverUnboxedGroups);
|
||||
return addShapeGuardPolymorphic(obj, receiverShapes);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -10527,10 +10539,8 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
|
||||
JSObject* foundProto = nullptr;
|
||||
bool isOwnProperty = false;
|
||||
BaselineInspector::ShapeVector receiverShapes(alloc());
|
||||
BaselineInspector::ObjectGroupVector receiverUnboxedGroups(alloc());
|
||||
if (!inspector->commonGetPropFunction(pc, &foundProto, &lastProperty, &commonGetter,
|
||||
&globalShape, &isOwnProperty,
|
||||
receiverShapes, receiverUnboxedGroups))
|
||||
&globalShape, &isOwnProperty, receiverShapes))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -10545,8 +10555,7 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
|
||||
if (!canUseTIForGetter) {
|
||||
// If type information is bad, we can still optimize the getter if we
|
||||
// shape guard.
|
||||
obj = addShapeGuardsForGetterSetter(obj, foundProto, lastProperty,
|
||||
receiverShapes, receiverUnboxedGroups,
|
||||
obj = addShapeGuardsForGetterSetter(obj, foundProto, lastProperty, receiverShapes,
|
||||
isOwnProperty);
|
||||
if (!obj)
|
||||
return false;
|
||||
@@ -10757,7 +10766,13 @@ IonBuilder::getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName
|
||||
|
||||
ObjectGroup* group = unboxedGroups[0];
|
||||
|
||||
obj = addGroupGuard(obj, group, Bailout_ShapeGuard);
|
||||
// Failures in this group guard should be treated the same as a shape guard failure.
|
||||
obj = MGuardObjectGroup::New(alloc(), obj, group, /* bailOnEquality = */ false,
|
||||
Bailout_ShapeGuard);
|
||||
current->add(obj->toInstruction());
|
||||
|
||||
if (failedShapeGuard_)
|
||||
obj->toGuardObjectGroup()->setNotMovable();
|
||||
|
||||
const UnboxedLayout::Property* property = group->unboxedLayout().lookup(name);
|
||||
MInstruction* load = loadUnboxedProperty(obj, property->offset, property->type, barrier, types);
|
||||
@@ -10779,7 +10794,7 @@ IonBuilder::getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName
|
||||
return false;
|
||||
|
||||
if (sameSlot && unboxedGroups.empty()) {
|
||||
obj = addShapeGuardPolymorphic(obj, nativeShapes, unboxedGroups);
|
||||
obj = addShapeGuardPolymorphic(obj, nativeShapes);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
@@ -11045,10 +11060,8 @@ IonBuilder::setPropTryCommonSetter(bool* emitted, MDefinition* obj,
|
||||
JSObject* foundProto = nullptr;
|
||||
bool isOwnProperty;
|
||||
BaselineInspector::ShapeVector receiverShapes(alloc());
|
||||
BaselineInspector::ObjectGroupVector receiverUnboxedGroups(alloc());
|
||||
if (!inspector->commonSetPropFunction(pc, &foundProto, &lastProperty, &commonSetter,
|
||||
&isOwnProperty,
|
||||
receiverShapes, receiverUnboxedGroups))
|
||||
if (!inspector->commonSetPropFunction(pc, &foundProto, &lastProperty, &commonSetter, &isOwnProperty,
|
||||
receiverShapes))
|
||||
{
|
||||
trackOptimizationOutcome(TrackedOutcome::NoProtoFound);
|
||||
return true;
|
||||
@@ -11062,8 +11075,7 @@ IonBuilder::setPropTryCommonSetter(bool* emitted, MDefinition* obj,
|
||||
if (!canUseTIForSetter) {
|
||||
// If type information is bad, we can still optimize the setter if we
|
||||
// shape guard.
|
||||
obj = addShapeGuardsForGetterSetter(obj, foundProto, lastProperty,
|
||||
receiverShapes, receiverUnboxedGroups,
|
||||
obj = addShapeGuardsForGetterSetter(obj, foundProto, lastProperty, receiverShapes,
|
||||
isOwnProperty);
|
||||
if (!obj)
|
||||
return false;
|
||||
@@ -11449,7 +11461,13 @@ IonBuilder::setPropTryInlineAccess(bool* emitted, MDefinition* obj,
|
||||
|
||||
ObjectGroup* group = unboxedGroups[0];
|
||||
|
||||
obj = addGroupGuard(obj, group, Bailout_ShapeGuard);
|
||||
// Failures in this group guard should be treated the same as a shape guard failure.
|
||||
obj = MGuardObjectGroup::New(alloc(), obj, group, /* bailOnEquality = */ false,
|
||||
Bailout_ShapeGuard);
|
||||
current->add(obj->toInstruction());
|
||||
|
||||
if (failedShapeGuard_)
|
||||
obj->toGuardObjectGroup()->setNotMovable();
|
||||
|
||||
const UnboxedLayout::Property* property = group->unboxedLayout().lookup(name);
|
||||
storeUnboxedProperty(obj, property->offset, property->type, value);
|
||||
@@ -11469,7 +11487,7 @@ IonBuilder::setPropTryInlineAccess(bool* emitted, MDefinition* obj,
|
||||
return false;
|
||||
|
||||
if (sameSlot && unboxedGroups.empty()) {
|
||||
obj = addShapeGuardPolymorphic(obj, nativeShapes, unboxedGroups);
|
||||
obj = addShapeGuardPolymorphic(obj, nativeShapes);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
@@ -12404,53 +12422,24 @@ IonBuilder::addShapeGuard(MDefinition* obj, Shape* const shape, BailoutKind bail
|
||||
}
|
||||
|
||||
MInstruction*
|
||||
IonBuilder::addGroupGuard(MDefinition *obj, ObjectGroup *group, BailoutKind bailoutKind)
|
||||
IonBuilder::addShapeGuardPolymorphic(MDefinition* obj, const BaselineInspector::ShapeVector& shapes)
|
||||
{
|
||||
MGuardObjectGroup *guard = MGuardObjectGroup::New(alloc(), obj, group,
|
||||
/* bailOnEquality = */ false,
|
||||
bailoutKind);
|
||||
current->add(guard);
|
||||
|
||||
// If a shape guard failed in the past, don't optimize group guards.
|
||||
if (failedShapeGuard_)
|
||||
guard->setNotMovable();
|
||||
|
||||
LifoAlloc *lifoAlloc = alloc().lifoAlloc();
|
||||
guard->setResultTypeSet(lifoAlloc->new_<TemporaryTypeSet>(lifoAlloc,
|
||||
TypeSet::ObjectType(group)));
|
||||
|
||||
return guard;
|
||||
}
|
||||
|
||||
MInstruction *
|
||||
IonBuilder::addShapeGuardPolymorphic(MDefinition *obj,
|
||||
const BaselineInspector::ShapeVector &shapes,
|
||||
const BaselineInspector::ObjectGroupVector &unboxedGroups)
|
||||
{
|
||||
if (shapes.length() == 1 && unboxedGroups.empty())
|
||||
if (shapes.length() == 1)
|
||||
return addShapeGuard(obj, shapes[0], Bailout_ShapeGuard);
|
||||
|
||||
if (shapes.empty() && unboxedGroups.length() == 1)
|
||||
return addGroupGuard(obj, unboxedGroups[0], Bailout_ShapeGuard);
|
||||
MOZ_ASSERT(shapes.length() > 1);
|
||||
|
||||
MOZ_ASSERT(shapes.length() + unboxedGroups.length() > 1);
|
||||
|
||||
MGuardReceiverPolymorphic *guard = MGuardReceiverPolymorphic::New(alloc(), obj);
|
||||
MGuardShapePolymorphic* guard = MGuardShapePolymorphic::New(alloc(), obj);
|
||||
current->add(guard);
|
||||
|
||||
if (failedShapeGuard_)
|
||||
guard->setNotMovable();
|
||||
|
||||
for (size_t i = 0; i < shapes.length(); i++) {
|
||||
for (size_t i = 0, len = shapes.length(); i < len; i++) {
|
||||
if (!guard->addShape(shapes[i]))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < unboxedGroups.length(); i++) {
|
||||
if (!guard->addUnboxedGroup(unboxedGroups[i]))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return guard;
|
||||
}
|
||||
|
||||
|
||||
+5
-11
@@ -398,12 +398,8 @@ class IonBuilder
|
||||
MDefinition* addMaybeCopyElementsForWrite(MDefinition* object);
|
||||
MInstruction* addBoundsCheck(MDefinition* index, MDefinition* length);
|
||||
MInstruction* addShapeGuard(MDefinition* obj, Shape* const shape, BailoutKind bailoutKind);
|
||||
MInstruction *addGroupGuard(MDefinition *obj, ObjectGroup *group, BailoutKind bailoutKind);
|
||||
|
||||
MInstruction *
|
||||
addShapeGuardPolymorphic(MDefinition *obj,
|
||||
const BaselineInspector::ShapeVector &shapes,
|
||||
const BaselineInspector::ObjectGroupVector &unboxedGroups);
|
||||
MInstruction* addShapeGuardPolymorphic(MDefinition* obj,
|
||||
const BaselineInspector::ShapeVector& shapes);
|
||||
|
||||
MDefinition* convertShiftToMaskForStaticTypedArray(MDefinition* id,
|
||||
Scalar::Type viewType);
|
||||
@@ -904,11 +900,9 @@ class IonBuilder
|
||||
bool testShouldDOMCall(TypeSet* inTypes,
|
||||
JSFunction* func, JSJitInfo::OpType opType);
|
||||
|
||||
MDefinition *
|
||||
addShapeGuardsForGetterSetter(MDefinition *obj, JSObject *holder, Shape *holderShape,
|
||||
const BaselineInspector::ShapeVector &receiverShapes,
|
||||
const BaselineInspector::ObjectGroupVector &receiverGroups,
|
||||
bool isOwnProperty);
|
||||
MDefinition* addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Shape* holderShape,
|
||||
const BaselineInspector::ShapeVector& receiverShapes,
|
||||
bool isOwnProperty);
|
||||
|
||||
bool annotateGetPropertyCache(MDefinition* obj, MGetPropertyCache* getPropCache,
|
||||
TemporaryTypeSet* objTypes,
|
||||
|
||||
+38
-116
@@ -1104,19 +1104,16 @@ GenerateCallGetter(JSContext* cx, IonScript* ion, MacroAssembler& masm,
|
||||
JSObject* holder, HandleShape shape, RegisterSet& liveRegs, Register object,
|
||||
TypedOrValueRegister output, void* returnAddr, Label* failures = nullptr)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
MOZ_ASSERT(output.hasValue());
|
||||
|
||||
// Use the passed in label if there was one. Otherwise, we'll have to make our own.
|
||||
Label stubFailure;
|
||||
failures = failures ? failures : &stubFailure;
|
||||
|
||||
// Initial shape/group check.
|
||||
if (obj->isNative())
|
||||
masm.branchTestObjShape(Assembler::NotEqual, object, obj->lastProperty(), failures);
|
||||
else if (obj->is<UnboxedPlainObject>())
|
||||
masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), failures);
|
||||
else
|
||||
MOZ_CRASH("Unexpected object");
|
||||
// Initial shape check.
|
||||
masm.branchPtr(Assembler::NotEqual, Address(object, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(obj->lastProperty()), failures);
|
||||
|
||||
Register scratchReg = output.valueReg().scratchReg();
|
||||
bool spillObjReg = scratchReg == object;
|
||||
@@ -1460,13 +1457,6 @@ GetPropertyIC::tryAttachTypedArrayLength(JSContext* cx, HandleScript outerScript
|
||||
return linkAndAttachStub(cx, masm, attacher, ion, "typed array length");
|
||||
}
|
||||
|
||||
static void
|
||||
PushObjectOpResult(MacroAssembler &masm, uint32_t value = ObjectOpResult::Uninitialized)
|
||||
{
|
||||
static_assert(sizeof(ObjectOpResult) == sizeof(int32_t),
|
||||
"ObjectOpResult size must match size reserved by masm.Push() here");
|
||||
masm.Push(Imm32(value));
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
|
||||
@@ -1511,9 +1501,6 @@ EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
|
||||
masm.Push(object);
|
||||
masm.movePtr(StackPointer, argProxyReg);
|
||||
|
||||
// Unused space, to keep the same stack layout as Proxy::set frames.
|
||||
PushObjectOpResult(masm, 0);
|
||||
|
||||
masm.loadJSContext(argJSContextReg);
|
||||
|
||||
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
|
||||
@@ -2067,6 +2054,8 @@ SetPropertyIC::attachSetSlot(JSContext* cx, HandleScript outerScript, IonScript*
|
||||
static bool
|
||||
IsCacheableSetPropCallNative(HandleObject obj, HandleObject holder, HandleShape shape)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
|
||||
if (!shape || !IsCacheableProtoChainForIon(obj, holder))
|
||||
return false;
|
||||
|
||||
@@ -2089,6 +2078,8 @@ IsCacheableSetPropCallNative(HandleObject obj, HandleObject holder, HandleShape
|
||||
static bool
|
||||
IsCacheableSetPropCallScripted(HandleObject obj, HandleObject holder, HandleShape shape)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
|
||||
if (!shape || !IsCacheableProtoChainForIon(obj, holder))
|
||||
return false;
|
||||
|
||||
@@ -2103,6 +2094,8 @@ IsCacheableSetPropCallScripted(HandleObject obj, HandleObject holder, HandleShap
|
||||
static bool
|
||||
IsCacheableSetPropCallPropertyOp(HandleObject obj, HandleObject holder, HandleShape shape)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
|
||||
if (!shape)
|
||||
return false;
|
||||
|
||||
@@ -2128,54 +2121,6 @@ IsCacheableSetPropCallPropertyOp(HandleObject obj, HandleObject holder, HandleSh
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ReportStrictErrorOrWarning(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool strict,
|
||||
JS::ObjectOpResult &result)
|
||||
{
|
||||
return result.reportStrictErrorOrWarning(cx, obj, id, strict);
|
||||
}
|
||||
|
||||
template <class FrameLayout>
|
||||
void
|
||||
EmitObjectOpResultCheck(MacroAssembler &masm, Label *failure, bool strict,
|
||||
Register scratchReg,
|
||||
Register argJSContextReg,
|
||||
Register argObjReg,
|
||||
Register argIdReg,
|
||||
Register argStrictReg,
|
||||
Register argResultReg)
|
||||
{
|
||||
// if (!result) {
|
||||
Label noStrictError;
|
||||
masm.branch32(Assembler::Equal,
|
||||
Address(StackPointer,
|
||||
FrameLayout::offsetOfObjectOpResult()),
|
||||
Imm32(ObjectOpResult::OkCode),
|
||||
&noStrictError);
|
||||
|
||||
// if (!ReportStrictErrorOrWarning(cx, obj, id, strict, &result))
|
||||
// goto failure;
|
||||
masm.loadJSContext(argJSContextReg);
|
||||
masm.computeEffectiveAddress(
|
||||
Address(StackPointer, FrameLayout::offsetOfId()),
|
||||
argIdReg);
|
||||
masm.move32(Imm32(strict), argStrictReg);
|
||||
masm.computeEffectiveAddress(
|
||||
Address(StackPointer, FrameLayout::offsetOfObjectOpResult()),
|
||||
argResultReg);
|
||||
masm.setupUnalignedABICall(5, scratchReg);
|
||||
masm.passABIArg(argJSContextReg);
|
||||
masm.passABIArg(argObjReg);
|
||||
masm.passABIArg(argIdReg);
|
||||
masm.passABIArg(argStrictReg);
|
||||
masm.passABIArg(argResultReg);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ReportStrictErrorOrWarning));
|
||||
masm.branchIfFalseBool(ReturnReg, failure);
|
||||
|
||||
// }
|
||||
masm.bind(&noStrictError);
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
|
||||
HandleId propId, RegisterSet liveRegs, Register object,
|
||||
@@ -2183,23 +2128,18 @@ EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
|
||||
{
|
||||
MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
|
||||
|
||||
// Remaining registers should be free, but we still need to use |object| so
|
||||
// leave it alone.
|
||||
//
|
||||
// WARNING: We do not take() the register used by |value|, if any, so
|
||||
// regSet is going to re-allocate it. Hence the emitted code must not touch
|
||||
// any of the registers allocated from regSet until after the last use of
|
||||
// |value|. (We can't afford to take it, either, because x86.)
|
||||
// Remaining registers should be free, but we need to use |object| still
|
||||
// so leave it alone.
|
||||
RegisterSet regSet(RegisterSet::All());
|
||||
regSet.take(AnyRegister(object));
|
||||
|
||||
// Proxy::set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
// MutableHandleValue vp, ObjectOpResult &result)
|
||||
// bool strict, MutableHandleValue vp)
|
||||
Register argJSContextReg = regSet.takeGeneral();
|
||||
Register argProxyReg = regSet.takeGeneral();
|
||||
Register argIdReg = regSet.takeGeneral();
|
||||
Register argVpReg = regSet.takeGeneral();
|
||||
Register argResultReg = regSet.takeGeneral();
|
||||
Register argStrictReg = regSet.takeGeneral();
|
||||
|
||||
Register scratch = regSet.takeGeneral();
|
||||
|
||||
@@ -2219,11 +2159,8 @@ EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
|
||||
masm.Push(object);
|
||||
masm.movePtr(StackPointer, argProxyReg);
|
||||
|
||||
// Allocate result out-param.
|
||||
PushObjectOpResult(masm);
|
||||
masm.movePtr(StackPointer, argResultReg);
|
||||
|
||||
masm.loadJSContext(argJSContextReg);
|
||||
masm.move32(Imm32(strict? 1 : 0), argStrictReg);
|
||||
|
||||
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
|
||||
return false;
|
||||
@@ -2235,19 +2172,13 @@ EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
|
||||
masm.passABIArg(argProxyReg);
|
||||
masm.passABIArg(argProxyReg);
|
||||
masm.passABIArg(argIdReg);
|
||||
masm.passABIArg(argStrictReg);
|
||||
masm.passABIArg(argVpReg);
|
||||
masm.passABIArg(argResultReg);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, Proxy::set));
|
||||
|
||||
// Test for error.
|
||||
// Test for failure.
|
||||
masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
|
||||
|
||||
// Test for strict failure. We emit the check even in non-strict mode in
|
||||
// order to pick up the warning if extraWarnings is enabled.
|
||||
EmitObjectOpResultCheck<IonOOLProxyExitFrameLayout>(masm, masm.exceptionLabel(), strict,
|
||||
scratch, argJSContextReg, argProxyReg,
|
||||
argIdReg, argVpReg, argResultReg);
|
||||
|
||||
// masm.leaveExitFrame & pop locals
|
||||
masm.adjustStack(IonOOLProxyExitFrameLayout::Size());
|
||||
|
||||
@@ -2458,28 +2389,24 @@ GenerateCallSetter(JSContext* cx, IonScript* ion, MacroAssembler& masm,
|
||||
Register argVpReg = regSet.takeGeneral();
|
||||
Register argObjReg = regSet.takeGeneral();
|
||||
Register argIdReg = regSet.takeGeneral();
|
||||
Register argResultReg = regSet.takeGeneral();
|
||||
Register argStrictReg = regSet.takeGeneral();
|
||||
|
||||
attacher.pushStubCodePointer(masm);
|
||||
|
||||
StrictPropertyOp target = shape->setterOp();
|
||||
MOZ_ASSERT(target);
|
||||
// JSStrictPropertyOp: bool fn(JSContext* cx, HandleObject obj,
|
||||
// HandleId id, MutableHandleValue vp, ObjectOpResult &result);
|
||||
// HandleId id, bool strict, MutableHandleValue vp);
|
||||
|
||||
// First, allocate an ObjectOpResult on the stack. We push this before
|
||||
// the stubCode pointer in order to match the layout of
|
||||
// IonOOLSetterOpExitFrameLayout.
|
||||
PushObjectOpResult(masm);
|
||||
masm.movePtr(StackPointer, argResultReg);
|
||||
|
||||
attacher.pushStubCodePointer(masm);
|
||||
|
||||
// Push args on stack so we can take pointers to make handles.
|
||||
// Push args on stack first so we can take pointers to make handles.
|
||||
if (value.constant())
|
||||
masm.Push(value.value());
|
||||
else
|
||||
masm.Push(value.reg());
|
||||
masm.movePtr(StackPointer, argVpReg);
|
||||
|
||||
masm.move32(Imm32(strict ? 1 : 0), argStrictReg);
|
||||
|
||||
// push canonical jsid from shape instead of propertyname.
|
||||
masm.Push(shape->propid(), argIdReg);
|
||||
masm.movePtr(StackPointer, argIdReg);
|
||||
@@ -2491,27 +2418,22 @@ GenerateCallSetter(JSContext* cx, IonScript* ion, MacroAssembler& masm,
|
||||
|
||||
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
|
||||
return false;
|
||||
masm.enterFakeExitFrame(IonOOLSetterOpExitFrameLayout::Token());
|
||||
masm.enterFakeExitFrame(IonOOLPropertyOpExitFrameLayout::Token());
|
||||
|
||||
// Make the call.
|
||||
masm.setupUnalignedABICall(5, scratchReg);
|
||||
masm.passABIArg(argJSContextReg);
|
||||
masm.passABIArg(argObjReg);
|
||||
masm.passABIArg(argIdReg);
|
||||
masm.passABIArg(argStrictReg);
|
||||
masm.passABIArg(argVpReg);
|
||||
masm.passABIArg(argResultReg);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, target));
|
||||
|
||||
// Test for error.
|
||||
// Test for failure.
|
||||
masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
|
||||
|
||||
// Test for failure.
|
||||
EmitObjectOpResultCheck<IonOOLSetterOpExitFrameLayout>(masm, failure, strict, scratchReg,
|
||||
argJSContextReg, argObjReg,
|
||||
argIdReg, argVpReg, argResultReg);
|
||||
|
||||
// masm.leaveExitFrame & pop locals.
|
||||
masm.adjustStack(IonOOLSetterOpExitFrameLayout::Size());
|
||||
masm.adjustStack(IonOOLPropertyOpExitFrameLayout::Size());
|
||||
} else {
|
||||
MOZ_ASSERT(IsCacheableSetPropCallScripted(obj, holder, shape));
|
||||
|
||||
@@ -2654,16 +2576,16 @@ SetPropertyIC::attachCallSetter(JSContext* cx, HandleScript outerScript, IonScri
|
||||
HandleObject obj, HandleObject holder, HandleShape shape,
|
||||
void* returnAddr)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
||||
Label failure;
|
||||
if (obj->isNative())
|
||||
masm.branchTestObjShape(Assembler::NotEqual, object(), obj->lastProperty(), &failure);
|
||||
else if (obj->is<UnboxedPlainObject>())
|
||||
masm.branchTestObjGroup(Assembler::NotEqual, object(), obj->group(), &failure);
|
||||
else
|
||||
MOZ_CRASH("Unexpected object");
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(object(), JSObject::offsetOfShape()),
|
||||
ImmGCPtr(obj->lastProperty()),
|
||||
&failure);
|
||||
|
||||
if (!GenerateCallSetter(cx, ion, masm, attacher, obj, holder, shape, strict(),
|
||||
object(), value(), &failure, liveRegs_, returnAddr))
|
||||
@@ -2930,12 +2852,12 @@ CanAttachNativeSetProp(JSContext* cx, HandleObject obj, HandleId id, ConstantOrR
|
||||
bool needsTypeBarrier, MutableHandleObject holder,
|
||||
MutableHandleShape shape, bool* checkTypeset)
|
||||
{
|
||||
if (!obj->isNative())
|
||||
return SetPropertyIC::CanAttachNone;
|
||||
|
||||
// See if the property exists on the object.
|
||||
if (obj->isNative() && IsPropertySetInlineable(&obj->as<NativeObject>(), id, shape, val,
|
||||
needsTypeBarrier, checkTypeset))
|
||||
{
|
||||
if (IsPropertySetInlineable(&obj->as<NativeObject>(), id, shape, val, needsTypeBarrier, checkTypeset))
|
||||
return SetPropertyIC::CanAttachSetSlot;
|
||||
}
|
||||
|
||||
// If we couldn't find the property on the object itself, do a full, but
|
||||
// still pure lookup for setters.
|
||||
|
||||
@@ -1316,7 +1316,7 @@ MarkJitExitFrame(JSTracer* trc, const JitFrameIterator& frame)
|
||||
}
|
||||
|
||||
if (frame.isExitFrameLayout<IonOOLNativeExitFrameLayout>()) {
|
||||
IonOOLNativeExitFrameLayout *oolnative =
|
||||
IonOOLNativeExitFrameLayout* oolnative =
|
||||
frame.exitFrame()->as<IonOOLNativeExitFrameLayout>();
|
||||
gc::MarkJitCodeRoot(trc, oolnative->stubCode(), "ion-ool-native-code");
|
||||
gc::MarkValueRoot(trc, oolnative->vp(), "iol-ool-native-vp");
|
||||
@@ -1325,16 +1325,9 @@ MarkJitExitFrame(JSTracer* trc, const JitFrameIterator& frame)
|
||||
return;
|
||||
}
|
||||
|
||||
if (frame.isExitFrameLayout<IonOOLPropertyOpExitFrameLayout>() ||
|
||||
frame.isExitFrameLayout<IonOOLSetterOpExitFrameLayout>())
|
||||
{
|
||||
// A SetterOp frame is a different size, but that's the only relevant
|
||||
// difference between the two. The fields that need marking are all in
|
||||
// the common base class.
|
||||
IonOOLPropertyOpExitFrameLayout *oolgetter =
|
||||
frame.isExitFrameLayout<IonOOLPropertyOpExitFrameLayout>()
|
||||
? frame.exitFrame()->as<IonOOLPropertyOpExitFrameLayout>()
|
||||
: frame.exitFrame()->as<IonOOLSetterOpExitFrameLayout>();
|
||||
if (frame.isExitFrameLayout<IonOOLPropertyOpExitFrameLayout>()) {
|
||||
IonOOLPropertyOpExitFrameLayout* oolgetter =
|
||||
frame.exitFrame()->as<IonOOLPropertyOpExitFrameLayout>();
|
||||
gc::MarkJitCodeRoot(trc, oolgetter->stubCode(), "ion-ool-property-op-code");
|
||||
gc::MarkValueRoot(trc, oolgetter->vp(), "ion-ool-property-op-vp");
|
||||
gc::MarkIdRoot(trc, oolgetter->id(), "ion-ool-property-op-id");
|
||||
@@ -1342,7 +1335,6 @@ MarkJitExitFrame(JSTracer* trc, const JitFrameIterator& frame)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (frame.isExitFrameLayout<IonOOLProxyExitFrameLayout>()) {
|
||||
IonOOLProxyExitFrameLayout* oolproxy = frame.exitFrame()->as<IonOOLProxyExitFrameLayout>();
|
||||
gc::MarkJitCodeRoot(trc, oolproxy->stubCode(), "ion-ool-proxy-code");
|
||||
@@ -2584,7 +2576,7 @@ struct DumpOp {
|
||||
void operator()(const Value& v) {
|
||||
fprintf(stderr, " actual (arg %d): ", i_);
|
||||
#ifdef DEBUG
|
||||
DumpValue(v);
|
||||
js_DumpValue(v);
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
@@ -2601,7 +2593,7 @@ JitFrameIterator::dumpBaseline() const
|
||||
if (isFunctionFrame()) {
|
||||
fprintf(stderr, " callee fun: ");
|
||||
#ifdef DEBUG
|
||||
DumpObject(callee());
|
||||
js_DumpObject(callee());
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
@@ -2628,7 +2620,7 @@ JitFrameIterator::dumpBaseline() const
|
||||
fprintf(stderr, " slot %u: ", i);
|
||||
#ifdef DEBUG
|
||||
Value* v = frame->valueSlot(i);
|
||||
DumpValue(*v);
|
||||
js_DumpValue(*v);
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
@@ -2650,7 +2642,7 @@ InlineFrameIterator::dump() const
|
||||
isFunction = true;
|
||||
fprintf(stderr, " callee fun: ");
|
||||
#ifdef DEBUG
|
||||
DumpObject(callee(fallback));
|
||||
js_DumpObject(callee(fallback));
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
@@ -2689,7 +2681,7 @@ InlineFrameIterator::dump() const
|
||||
} else
|
||||
fprintf(stderr, " slot %u: ", i);
|
||||
#ifdef DEBUG
|
||||
DumpValue(si.maybeRead(fallback));
|
||||
js_DumpValue(si.maybeRead(fallback));
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
|
||||
+3
-36
@@ -494,8 +494,7 @@ enum ExitFrameTokenValues
|
||||
IonDOMMethodExitFrameLayoutToken = 0x3,
|
||||
IonOOLNativeExitFrameLayoutToken = 0x4,
|
||||
IonOOLPropertyOpExitFrameLayoutToken = 0x5,
|
||||
IonOOLSetterOpExitFrameLayoutToken = 0x6,
|
||||
IonOOLProxyExitFrameLayoutToken = 0x7,
|
||||
IonOOLProxyExitFrameLayoutToken = 0x6,
|
||||
LazyLinkExitFrameLayoutToken = 0xFE,
|
||||
ExitFrameLayoutBareToken = 0xFF
|
||||
};
|
||||
@@ -629,7 +628,7 @@ class IonOOLNativeExitFrameLayout
|
||||
|
||||
class IonOOLPropertyOpExitFrameLayout
|
||||
{
|
||||
protected:
|
||||
protected: // only to silence a clang warning about unused private fields
|
||||
ExitFooterFrame footer_;
|
||||
ExitFrameLayout exit_;
|
||||
|
||||
@@ -654,10 +653,6 @@ class IonOOLPropertyOpExitFrameLayout
|
||||
return sizeof(IonOOLPropertyOpExitFrameLayout);
|
||||
}
|
||||
|
||||
static size_t offsetOfId() {
|
||||
return offsetof(IonOOLPropertyOpExitFrameLayout, id_);
|
||||
}
|
||||
|
||||
static size_t offsetOfResult() {
|
||||
return offsetof(IonOOLPropertyOpExitFrameLayout, vp0_);
|
||||
}
|
||||
@@ -676,36 +671,16 @@ class IonOOLPropertyOpExitFrameLayout
|
||||
}
|
||||
};
|
||||
|
||||
class IonOOLSetterOpExitFrameLayout : public IonOOLPropertyOpExitFrameLayout
|
||||
{
|
||||
protected: // only to silence a clang warning about unused private fields
|
||||
JS::ObjectOpResult result_;
|
||||
|
||||
public:
|
||||
static JitCode *Token() { return (JitCode *)IonOOLSetterOpExitFrameLayoutToken; }
|
||||
|
||||
static size_t offsetOfObjectOpResult() {
|
||||
return offsetof(IonOOLSetterOpExitFrameLayout, result_);
|
||||
}
|
||||
|
||||
static size_t Size() {
|
||||
return sizeof(IonOOLSetterOpExitFrameLayout);
|
||||
}
|
||||
};
|
||||
|
||||
// Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
// MutableHandleValue vp)
|
||||
// Proxy::set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
// MutableHandleValue vp, ObjectOpResult &result)
|
||||
// bool strict, MutableHandleValue vp)
|
||||
class IonOOLProxyExitFrameLayout
|
||||
{
|
||||
protected: // only to silence a clang warning about unused private fields
|
||||
ExitFooterFrame footer_;
|
||||
ExitFrameLayout exit_;
|
||||
|
||||
// result out-parameter (unused for Proxy::get)
|
||||
JS::ObjectOpResult result_;
|
||||
|
||||
// The proxy object.
|
||||
JSObject* proxy_;
|
||||
|
||||
@@ -734,14 +709,6 @@ class IonOOLProxyExitFrameLayout
|
||||
return offsetof(IonOOLProxyExitFrameLayout, vp0_);
|
||||
}
|
||||
|
||||
static size_t offsetOfId() {
|
||||
return offsetof(IonOOLProxyExitFrameLayout, id_);
|
||||
}
|
||||
|
||||
static size_t offsetOfObjectOpResult() {
|
||||
return offsetof(IonOOLProxyExitFrameLayout, result_);
|
||||
}
|
||||
|
||||
inline JitCode** stubCode() {
|
||||
return &stubCode_;
|
||||
}
|
||||
|
||||
@@ -5978,12 +5978,12 @@ class LRest : public LCallInstructionHelper<1, 1, 3>
|
||||
}
|
||||
};
|
||||
|
||||
class LGuardReceiverPolymorphic : public LInstructionHelper<0, 1, 1>
|
||||
class LGuardShapePolymorphic : public LInstructionHelper<0, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(GuardReceiverPolymorphic)
|
||||
LIR_HEADER(GuardShapePolymorphic)
|
||||
|
||||
LGuardReceiverPolymorphic(const LAllocation &in, const LDefinition &temp) {
|
||||
LGuardShapePolymorphic(const LAllocation& in, const LDefinition& temp) {
|
||||
setOperand(0, in);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
@@ -5993,8 +5993,8 @@ class LGuardReceiverPolymorphic : public LInstructionHelper<0, 1, 1>
|
||||
const LDefinition* temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
const MGuardReceiverPolymorphic *mir() const {
|
||||
return mir_->toGuardReceiverPolymorphic();
|
||||
const MGuardShapePolymorphic* mir() const {
|
||||
return mir_->toGuardShapePolymorphic();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
_(StoreSlotV) \
|
||||
_(StoreSlotT) \
|
||||
_(GuardShape) \
|
||||
_(GuardReceiverPolymorphic) \
|
||||
_(GuardShapePolymorphic) \
|
||||
_(GuardObjectGroup) \
|
||||
_(GuardObjectIdentity) \
|
||||
_(GuardClass) \
|
||||
|
||||
@@ -3216,13 +3216,13 @@ LIRGenerator::visitPolyInlineGuard(MPolyInlineGuard* ins)
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitGuardReceiverPolymorphic(MGuardReceiverPolymorphic *ins)
|
||||
LIRGenerator::visitGuardShapePolymorphic(MGuardShapePolymorphic* ins)
|
||||
{
|
||||
MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
|
||||
MOZ_ASSERT(ins->type() == MIRType_Object);
|
||||
|
||||
LGuardReceiverPolymorphic *guard =
|
||||
new(alloc()) LGuardReceiverPolymorphic(useRegister(ins->obj()), temp());
|
||||
LGuardShapePolymorphic* guard =
|
||||
new(alloc()) LGuardShapePolymorphic(useRegister(ins->obj()), temp());
|
||||
assignSnapshot(guard, Bailout_ShapeGuard);
|
||||
add(guard, ins);
|
||||
redefine(ins, ins->obj());
|
||||
|
||||
@@ -220,7 +220,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
void visitGuardClass(MGuardClass* ins);
|
||||
void visitGuardObject(MGuardObject* ins);
|
||||
void visitGuardString(MGuardString* ins);
|
||||
void visitGuardReceiverPolymorphic(MGuardReceiverPolymorphic *ins);
|
||||
void visitGuardShapePolymorphic(MGuardShapePolymorphic* ins);
|
||||
void visitPolyInlineGuard(MPolyInlineGuard* ins);
|
||||
void visitAssertRange(MAssertRange* ins);
|
||||
void visitCallGetProperty(MCallGetProperty* ins);
|
||||
|
||||
+7
-18
@@ -3318,9 +3318,6 @@ MCompare::tryFoldEqualOperands(bool* result)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DeadIfUnused(lhs()))
|
||||
lhs()->setGuardRangeBailouts();
|
||||
|
||||
*result = (jsop() == JSOP_STRICTEQ);
|
||||
return true;
|
||||
}
|
||||
@@ -3788,9 +3785,8 @@ MBeta::printOpcode(FILE* fp) const
|
||||
bool
|
||||
MNewObject::shouldUseVM() const
|
||||
{
|
||||
if (JSObject *obj = templateObject())
|
||||
return obj->is<PlainObject>() && obj->as<PlainObject>().hasDynamicSlots();
|
||||
return true;
|
||||
PlainObject* obj = templateObject();
|
||||
return obj->isSingleton() || obj->hasDynamicSlots();
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -3809,7 +3805,7 @@ MObjectState::MObjectState(MDefinition* obj)
|
||||
setRecoveredOnBailout();
|
||||
NativeObject* templateObject = nullptr;
|
||||
if (obj->isNewObject())
|
||||
templateObject = &obj->toNewObject()->templateObject()->as<PlainObject>();
|
||||
templateObject = obj->toNewObject()->templateObject();
|
||||
else if (obj->isCreateThisWithTemplate())
|
||||
templateObject = &obj->toCreateThisWithTemplate()->templateObject()->as<PlainObject>();
|
||||
else
|
||||
@@ -4106,27 +4102,20 @@ MLoadElement::foldsTo(TempAllocator& alloc)
|
||||
}
|
||||
|
||||
bool
|
||||
MGuardReceiverPolymorphic::congruentTo(const MDefinition *ins) const
|
||||
MGuardShapePolymorphic::congruentTo(const MDefinition* ins) const
|
||||
{
|
||||
if (!ins->isGuardReceiverPolymorphic())
|
||||
if (!ins->isGuardShapePolymorphic())
|
||||
return false;
|
||||
|
||||
const MGuardReceiverPolymorphic *other = ins->toGuardReceiverPolymorphic();
|
||||
|
||||
const MGuardShapePolymorphic* other = ins->toGuardShapePolymorphic();
|
||||
if (numShapes() != other->numShapes())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < numShapes(); i++) {
|
||||
if (getShape(i) != other->getShape(i))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numUnboxedGroups() != other->numUnboxedGroups())
|
||||
return false;
|
||||
for (size_t i = 0; i < numUnboxedGroups(); i++) {
|
||||
if (getUnboxedGroup(i) != other->getUnboxedGroup(i))
|
||||
return false;
|
||||
}
|
||||
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
|
||||
+12
-40
@@ -73,20 +73,6 @@ MIRType MIRTypeFromValue(const js::Value& vp)
|
||||
_(Lowered) /* (Debug only) has a virtual register */ \
|
||||
_(Guard) /* Not removable if uses == 0 */ \
|
||||
\
|
||||
/* Flag an instruction to be considered as a Guard if the instructions
|
||||
* bails out on some inputs.
|
||||
*
|
||||
* Some optimizations can replace an instruction, and leave its operands
|
||||
* unused. When the type information of the operand got used as a
|
||||
* predicate of the transformation, then we have to flag the operands as
|
||||
* GuardRangeBailouts.
|
||||
*
|
||||
* This flag prevents further optimization of instructions, which
|
||||
* might remove the run-time checks (bailout conditions) used as a
|
||||
* predicate of the previous transformation.
|
||||
*/ \
|
||||
_(GuardRangeBailouts) \
|
||||
\
|
||||
/* Keep the flagged instruction in resume points and do not substitute this
|
||||
* instruction by an UndefinedValue. This might be used by call inlining
|
||||
* when a function argument is not used by the inlined instructions.
|
||||
@@ -2957,10 +2943,10 @@ class MNewObject
|
||||
initialHeap_(initialHeap),
|
||||
mode_(mode)
|
||||
{
|
||||
PlainObject* obj = templateObject();
|
||||
MOZ_ASSERT_IF(mode != ObjectLiteral, !shouldUseVM());
|
||||
setResultType(MIRType_Object);
|
||||
|
||||
if (JSObject *obj = templateObject())
|
||||
if (!obj->isSingleton())
|
||||
setResultTypeSet(MakeSingletonTypeSet(constraints, obj));
|
||||
|
||||
// The constant is kept separated in a MConstant, this way we can safely
|
||||
@@ -2968,8 +2954,7 @@ class MNewObject
|
||||
// making it emittedAtUses, we do not produce register allocations for
|
||||
// it and inline its content inside the code produced by the
|
||||
// CodeGenerator.
|
||||
if (templateConst->toConstant()->value().isObject())
|
||||
templateConst->setEmittedAtUses();
|
||||
templateConst->setEmittedAtUses();
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -2990,8 +2975,8 @@ class MNewObject
|
||||
return mode_;
|
||||
}
|
||||
|
||||
JSObject *templateObject() const {
|
||||
return getOperand(0)->toConstant()->value().toObjectOrNull();
|
||||
PlainObject* templateObject() const {
|
||||
return &getOperand(0)->toConstant()->value().toObject().as<PlainObject>();
|
||||
}
|
||||
|
||||
gc::InitialHeap initialHeap() const {
|
||||
@@ -9975,18 +9960,16 @@ class MGuardShape
|
||||
}
|
||||
};
|
||||
|
||||
// Bail if the object's shape or unboxed group is not in the input list.
|
||||
class MGuardReceiverPolymorphic
|
||||
// Bail if the object's shape is not one of the shapes in shapes_.
|
||||
class MGuardShapePolymorphic
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy::Data
|
||||
{
|
||||
Vector<Shape*, 4, JitAllocPolicy> shapes_;
|
||||
Vector<ObjectGroup *, 4, JitAllocPolicy> unboxedGroups_;
|
||||
|
||||
MGuardReceiverPolymorphic(TempAllocator &alloc, MDefinition *obj)
|
||||
MGuardShapePolymorphic(TempAllocator& alloc, MDefinition* obj)
|
||||
: MUnaryInstruction(obj),
|
||||
shapes_(alloc),
|
||||
unboxedGroups_(alloc)
|
||||
shapes_(alloc)
|
||||
{
|
||||
setGuard();
|
||||
setMovable();
|
||||
@@ -9994,16 +9977,15 @@ class MGuardReceiverPolymorphic
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(GuardReceiverPolymorphic)
|
||||
INSTRUCTION_HEADER(GuardShapePolymorphic)
|
||||
|
||||
static MGuardReceiverPolymorphic *New(TempAllocator &alloc, MDefinition *obj) {
|
||||
return new(alloc) MGuardReceiverPolymorphic(alloc, obj);
|
||||
static MGuardShapePolymorphic* New(TempAllocator& alloc, MDefinition* obj) {
|
||||
return new(alloc) MGuardShapePolymorphic(alloc, obj);
|
||||
}
|
||||
|
||||
MDefinition* obj() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
bool addShape(Shape* shape) {
|
||||
return shapes_.append(shape);
|
||||
}
|
||||
@@ -10014,16 +9996,6 @@ class MGuardReceiverPolymorphic
|
||||
return shapes_[i];
|
||||
}
|
||||
|
||||
bool addUnboxedGroup(ObjectGroup *group) {
|
||||
return unboxedGroups_.append(group);
|
||||
}
|
||||
size_t numUnboxedGroups() const {
|
||||
return unboxedGroups_.length();
|
||||
}
|
||||
ObjectGroup *getUnboxedGroup(size_t i) const {
|
||||
return unboxedGroups_[i];
|
||||
}
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override;
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
|
||||
@@ -157,10 +157,10 @@ class MIRGenerator
|
||||
|
||||
typedef Vector<ObjectGroup*, 0, JitAllocPolicy> ObjectGroupVector;
|
||||
|
||||
// When abortReason() == AbortReason_PreliminaryObjects, all groups with
|
||||
// preliminary objects which haven't been analyzed yet.
|
||||
const ObjectGroupVector &abortedPreliminaryGroups() const {
|
||||
return abortedPreliminaryGroups_;
|
||||
// When abortReason() == AbortReason_NewScriptProperties, all types which
|
||||
// the new script properties analysis hasn't been performed on yet.
|
||||
const ObjectGroupVector& abortedNewScriptPropertiesGroups() const {
|
||||
return abortedNewScriptPropertiesGroups_;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -175,7 +175,7 @@ class MIRGenerator
|
||||
MIRGraph* graph_;
|
||||
AbortReason abortReason_;
|
||||
bool shouldForceAbort_; // Force AbortReason_Disable
|
||||
ObjectGroupVector abortedPreliminaryGroups_;
|
||||
ObjectGroupVector abortedNewScriptPropertiesGroups_;
|
||||
bool error_;
|
||||
mozilla::Atomic<bool, mozilla::Relaxed>* pauseBuild_;
|
||||
mozilla::Atomic<bool, mozilla::Relaxed> cancelBuild_;
|
||||
@@ -200,8 +200,7 @@ class MIRGenerator
|
||||
// CodeGenerator::link).
|
||||
ObjectVector nurseryObjects_;
|
||||
|
||||
void addAbortedPreliminaryGroup(ObjectGroup *group);
|
||||
|
||||
void addAbortedNewScriptPropertiesGroup(ObjectGroup* type);
|
||||
void setForceAbort() {
|
||||
shouldForceAbort_ = true;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ MIRGenerator::MIRGenerator(CompileCompartment* compartment, const JitCompileOpti
|
||||
graph_(graph),
|
||||
abortReason_(AbortReason_NoAbort),
|
||||
shouldForceAbort_(false),
|
||||
abortedPreliminaryGroups_(*alloc_),
|
||||
abortedNewScriptPropertiesGroups_(*alloc_),
|
||||
error_(false),
|
||||
pauseBuild_(nullptr),
|
||||
cancelBuild_(false),
|
||||
@@ -93,14 +93,14 @@ MIRGenerator::abort(const char* message, ...)
|
||||
}
|
||||
|
||||
void
|
||||
MIRGenerator::addAbortedPreliminaryGroup(ObjectGroup *group)
|
||||
MIRGenerator::addAbortedNewScriptPropertiesGroup(ObjectGroup* group)
|
||||
{
|
||||
for (size_t i = 0; i < abortedPreliminaryGroups_.length(); i++) {
|
||||
if (group == abortedPreliminaryGroups_[i])
|
||||
for (size_t i = 0; i < abortedNewScriptPropertiesGroups_.length(); i++) {
|
||||
if (group == abortedNewScriptPropertiesGroups_[i])
|
||||
return;
|
||||
}
|
||||
if (!abortedPreliminaryGroups_.append(group))
|
||||
CrashAtUnhandlableOOM("addAbortedPreliminaryGroup");
|
||||
if (!abortedNewScriptPropertiesGroups_.append(group))
|
||||
CrashAtUnhandlableOOM("addAbortedNewScriptPropertiesGroup");
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -159,7 +159,7 @@ namespace jit {
|
||||
_(SetElementCache) \
|
||||
_(BindNameCache) \
|
||||
_(GuardShape) \
|
||||
_(GuardReceiverPolymorphic) \
|
||||
_(GuardShapePolymorphic) \
|
||||
_(GuardObjectGroup) \
|
||||
_(GuardObjectIdentity) \
|
||||
_(GuardClass) \
|
||||
|
||||
@@ -283,20 +283,18 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
void loadObjShape(Register objReg, Register dest) {
|
||||
loadPtr(Address(objReg, JSObject::offsetOfShape()), dest);
|
||||
}
|
||||
void loadObjGroup(Register objReg, Register dest) {
|
||||
loadPtr(Address(objReg, JSObject::offsetOfGroup()), dest);
|
||||
}
|
||||
void loadBaseShape(Register objReg, Register dest) {
|
||||
loadObjShape(objReg, dest);
|
||||
loadPtr(Address(objReg, JSObject::offsetOfShape()), dest);
|
||||
|
||||
loadPtr(Address(dest, Shape::offsetOfBase()), dest);
|
||||
}
|
||||
void loadObjClass(Register objReg, Register dest) {
|
||||
loadObjGroup(objReg, dest);
|
||||
loadPtr(Address(objReg, JSObject::offsetOfGroup()), dest);
|
||||
loadPtr(Address(dest, ObjectGroup::offsetOfClasp()), dest);
|
||||
}
|
||||
void branchTestObjClass(Condition cond, Register obj, Register scratch, const js::Class* clasp,
|
||||
Label* label) {
|
||||
loadObjGroup(obj, scratch);
|
||||
loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
|
||||
branchPtr(cond, Address(scratch, ObjectGroup::offsetOfClasp()), ImmPtr(clasp), label);
|
||||
}
|
||||
void branchTestObjShape(Condition cond, Register obj, const Shape* shape, Label* label) {
|
||||
@@ -305,12 +303,6 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
void branchTestObjShape(Condition cond, Register obj, Register shape, Label* label) {
|
||||
branchPtr(cond, Address(obj, JSObject::offsetOfShape()), shape, label);
|
||||
}
|
||||
void branchTestObjGroup(Condition cond, Register obj, ObjectGroup *group, Label *label) {
|
||||
branchPtr(cond, Address(obj, JSObject::offsetOfGroup()), ImmGCPtr(group), label);
|
||||
}
|
||||
void branchTestObjGroup(Condition cond, Register obj, Register group, Label *label) {
|
||||
branchPtr(cond, Address(obj, JSObject::offsetOfGroup()), group, label);
|
||||
}
|
||||
void branchTestProxyHandlerFamily(Condition cond, Register proxy, Register scratch,
|
||||
const void* handlerp, Label* label) {
|
||||
Address handlerAddr(proxy, ProxyObject::offsetOfHandler());
|
||||
|
||||
@@ -2798,10 +2798,6 @@ ComputeRequestedTruncateKind(MDefinition* candidate, bool* shouldClone)
|
||||
break;
|
||||
}
|
||||
|
||||
// We cannot do full trunction on guarded instructions.
|
||||
if (candidate->isGuard() || candidate->isGuardRangeBailouts())
|
||||
kind = Min(kind, MDefinition::TruncateAfterBailouts);
|
||||
|
||||
// If the value naturally produces an int32 value (before bailout checks)
|
||||
// that needs no conversion, we don't have to worry about resume points
|
||||
// seeing truncated values.
|
||||
@@ -3223,6 +3219,8 @@ RangeAnalysis::prepareForUCE(bool* shouldRemoveDeadCode)
|
||||
{
|
||||
*shouldRemoveDeadCode = false;
|
||||
|
||||
MDefinitionVector deadConditions(alloc());
|
||||
|
||||
for (ReversePostorderIterator iter(graph_.rpoBegin()); iter != graph_.rpoEnd(); iter++) {
|
||||
MBasicBlock* block = *iter;
|
||||
|
||||
@@ -3246,8 +3244,11 @@ RangeAnalysis::prepareForUCE(bool* shouldRemoveDeadCode)
|
||||
constant = MConstant::New(alloc(), BooleanValue(true));
|
||||
}
|
||||
|
||||
if (DeadIfUnused(condition))
|
||||
condition->setGuardRangeBailoutsUnchecked();
|
||||
if (DeadIfUnused(condition) && !condition->isInWorklist()) {
|
||||
condition->setInWorklist();
|
||||
if (!deadConditions.append(condition))
|
||||
return false;
|
||||
}
|
||||
|
||||
test->block()->insertBefore(test, constant);
|
||||
|
||||
@@ -3258,73 +3259,55 @@ RangeAnalysis::prepareForUCE(bool* shouldRemoveDeadCode)
|
||||
*shouldRemoveDeadCode = true;
|
||||
}
|
||||
|
||||
return tryRemovingGuards();
|
||||
}
|
||||
|
||||
bool RangeAnalysis::tryRemovingGuards() {
|
||||
|
||||
MDefinitionVector guards(alloc());
|
||||
|
||||
for (ReversePostorderIterator block = graph_.rpoBegin(); block != graph_.rpoEnd(); block++) {
|
||||
for (MInstructionReverseIterator iter = block->rbegin(); iter != block->rend(); iter++) {
|
||||
if (!iter->isGuardRangeBailouts())
|
||||
continue;
|
||||
|
||||
if (!guards.append(*iter))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Flag all fallible instructions which were indirectly used in the
|
||||
// computation of the condition, such that we do not ignore
|
||||
// bailout-paths which are used to shrink the input range of the
|
||||
// operands of the condition.
|
||||
for (size_t i = 0; i < guards.length(); i++) {
|
||||
MDefinition *guard = guards[i];
|
||||
for (size_t i = 0; i < deadConditions.length(); i++) {
|
||||
MDefinition* cond = deadConditions[i];
|
||||
|
||||
#ifdef DEBUG
|
||||
// There is no need to mark an instructions if there is
|
||||
// already a more restrictive flag on it.
|
||||
guard->setNotGuardRangeBailouts();
|
||||
MOZ_ASSERT(DeadIfUnused(guard));
|
||||
guard->setGuardRangeBailouts();
|
||||
#endif
|
||||
|
||||
if (!guard->range())
|
||||
// If this instruction is a guard, then there is not need to continue on
|
||||
// this instruction.
|
||||
if (cond->isGuard())
|
||||
continue;
|
||||
|
||||
// Filter the range of the instruction based on its MIRType.
|
||||
Range typeFilteredRange(guard);
|
||||
if (cond->range()) {
|
||||
// Filter the range of the instruction based on its MIRType.
|
||||
Range typeFilteredRange(cond);
|
||||
|
||||
// If the output range is updated by adding the inner range,
|
||||
// then the MIRType act as an effectful filter. As we do not know if
|
||||
// this filtered Range might change or not the result of the
|
||||
// previous comparison, we have to keep this instruction as a guard
|
||||
// because it has to bailout in order to restrict the Range to its
|
||||
// MIRType.
|
||||
if (typeFilteredRange.update(guard->range()))
|
||||
continue;
|
||||
// If the filtered range is updated by adding the original range,
|
||||
// then the MIRType act as an effectful filter. As we do not know if
|
||||
// this filtered Range might change or not the result of the
|
||||
// previous comparison, we have to keep this instruction as a guard
|
||||
// because it has to bailout in order to restrict the Range to its
|
||||
// MIRType.
|
||||
if (typeFilteredRange.update(cond->range())) {
|
||||
cond->setGuard();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
guard->setNotGuardRangeBailouts();
|
||||
|
||||
// Propagate the guard to its operands.
|
||||
for (size_t op = 0, e = guard->numOperands(); op < e; op++) {
|
||||
MDefinition *operand = guard->getOperand(op);
|
||||
|
||||
// Already marked.
|
||||
if (operand->isGuardRangeBailouts())
|
||||
for (size_t op = 0, e = cond->numOperands(); op < e; op++) {
|
||||
MDefinition* operand = cond->getOperand(op);
|
||||
if (!DeadIfUnused(operand) || operand->isInWorklist())
|
||||
continue;
|
||||
|
||||
// No need to mark as a guard, since it is has already an even more
|
||||
// restrictive flag set.
|
||||
if (!DeadIfUnused(operand))
|
||||
// If the operand has no range, then its range is always infered
|
||||
// from its MIRType, so it cannot be used change the result deduced
|
||||
// by Range Analysis.
|
||||
if (!operand->range())
|
||||
continue;
|
||||
|
||||
operand->setGuardRangeBailouts();
|
||||
if (!guards.append(operand))
|
||||
operand->setInWorklist();
|
||||
if (!deadConditions.append(operand))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
while (!deadConditions.empty()) {
|
||||
MDefinition* cond = deadConditions.popCopy();
|
||||
cond->setNotInWorklist();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,6 @@ class RangeAnalysis
|
||||
bool addRangeAssertions();
|
||||
bool removeBetaNodes();
|
||||
bool prepareForUCE(bool* shouldRemoveDeadCode);
|
||||
bool tryRemovingGuards();
|
||||
bool truncate();
|
||||
|
||||
// Any iteration bounds discovered for loops in the graph.
|
||||
|
||||
@@ -1176,7 +1176,7 @@ RNewObject::recover(JSContext* cx, SnapshotIterator& iter) const
|
||||
|
||||
// See CodeGenerator::visitNewObjectVMCall
|
||||
if (mode_ == MNewObject::ObjectLiteral) {
|
||||
resultObject = NewObjectOperationWithTemplate(cx, templateObject);
|
||||
resultObject = NewInitObject(cx, templateObject);
|
||||
} else {
|
||||
MOZ_ASSERT(mode_ == MNewObject::ObjectCreate);
|
||||
resultObject = ObjectCreateWithTemplate(cx, templateObject);
|
||||
|
||||
@@ -162,7 +162,7 @@ RematerializedFrame::dump()
|
||||
if (isFunctionFrame()) {
|
||||
fprintf(stderr, " callee fun: ");
|
||||
#ifdef DEBUG
|
||||
DumpValue(ObjectValue(*callee()));
|
||||
js_DumpValue(ObjectValue(*callee()));
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
@@ -179,7 +179,7 @@ RematerializedFrame::dump()
|
||||
if (isFunctionFrame()) {
|
||||
fprintf(stderr, " scope chain: ");
|
||||
#ifdef DEBUG
|
||||
DumpValue(ObjectValue(*scopeChain()));
|
||||
js_DumpValue(ObjectValue(*scopeChain()));
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
@@ -187,7 +187,7 @@ RematerializedFrame::dump()
|
||||
if (hasArgsObj()) {
|
||||
fprintf(stderr, " args obj: ");
|
||||
#ifdef DEBUG
|
||||
DumpValue(ObjectValue(argsObj()));
|
||||
js_DumpValue(ObjectValue(argsObj()));
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
@@ -195,7 +195,7 @@ RematerializedFrame::dump()
|
||||
|
||||
fprintf(stderr, " this: ");
|
||||
#ifdef DEBUG
|
||||
DumpValue(thisValue());
|
||||
js_DumpValue(thisValue());
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
@@ -206,7 +206,7 @@ RematerializedFrame::dump()
|
||||
else
|
||||
fprintf(stderr, " overflown (arg %d): ", i);
|
||||
#ifdef DEBUG
|
||||
DumpValue(argv()[i]);
|
||||
js_DumpValue(argv()[i]);
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
@@ -215,7 +215,7 @@ RematerializedFrame::dump()
|
||||
for (unsigned i = 0; i < script()->nfixed(); i++) {
|
||||
fprintf(stderr, " local %d: ", i);
|
||||
#ifdef DEBUG
|
||||
DumpValue(locals()[i]);
|
||||
js_DumpValue(locals()[i]);
|
||||
#else
|
||||
fprintf(stderr, "?\n");
|
||||
#endif
|
||||
|
||||
@@ -113,9 +113,6 @@ IsObjectEscaped(MInstruction* ins, JSObject* objDefault = nullptr)
|
||||
else
|
||||
obj = objDefault;
|
||||
|
||||
if (!obj)
|
||||
return true;
|
||||
|
||||
// Don't optimize unboxed objects, which aren't handled by MObjectState.
|
||||
if (obj->is<UnboxedPlainObject>())
|
||||
return true;
|
||||
|
||||
+1
-4
@@ -57,11 +57,8 @@ Sink(MIRGenerator* mir, MIRGraph& graph)
|
||||
|
||||
// Only instructions which can be recovered on bailout can be moved
|
||||
// into the bailout paths.
|
||||
if (ins->isGuard() || ins->isGuardRangeBailouts() ||
|
||||
ins->isRecoveredOnBailout() || !ins->canRecoverOnBailout())
|
||||
{
|
||||
if (ins->isGuard() || ins->isRecoveredOnBailout() || !ins->canRecoverOnBailout())
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute a common dominator for all uses of the current
|
||||
// instruction.
|
||||
|
||||
+30
-18
@@ -192,11 +192,12 @@ MutatePrototype(JSContext* cx, HandlePlainObject obj, HandleValue value)
|
||||
}
|
||||
|
||||
bool
|
||||
InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
|
||||
InitProp(JSContext *cx, HandleNativeObject obj, HandlePropertyName name, HandleValue value,
|
||||
jsbytecode *pc)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return InitPropertyOperation(cx, JSOp(*pc), obj, id, value);
|
||||
unsigned propAttrs = GetInitDataPropAttrs(JSOp(*pc));
|
||||
return NativeDefineProperty(cx, obj, id, value, nullptr, nullptr, propAttrs);
|
||||
}
|
||||
|
||||
template<bool Equal>
|
||||
@@ -265,6 +266,23 @@ StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs, bool* res)
|
||||
template bool StringsEqual<true>(JSContext* cx, HandleString lhs, HandleString rhs, bool* res);
|
||||
template bool StringsEqual<false>(JSContext* cx, HandleString lhs, HandleString rhs, bool* res);
|
||||
|
||||
JSObject*
|
||||
NewInitObject(JSContext* cx, HandlePlainObject templateObject)
|
||||
{
|
||||
NewObjectKind newKind = templateObject->isSingleton() ? SingletonObject : GenericObject;
|
||||
if (!templateObject->hasLazyGroup() && templateObject->group()->shouldPreTenure())
|
||||
newKind = TenuredObject;
|
||||
RootedObject obj(cx, CopyInitializerObject(cx, templateObject, newKind));
|
||||
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
if (!templateObject->isSingleton())
|
||||
obj->setGroup(templateObject->group());
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
ArraySpliceDense(JSContext* cx, HandleObject obj, uint32_t start, uint32_t deleteCount)
|
||||
{
|
||||
@@ -448,24 +466,18 @@ SetProperty(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValu
|
||||
return true;
|
||||
}
|
||||
|
||||
ObjectOpResult result;
|
||||
if (MOZ_LIKELY(!obj->getOps()->setProperty)) {
|
||||
if (!NativeSetProperty(
|
||||
cx, obj.as<NativeObject>(), obj.as<NativeObject>(), id,
|
||||
(op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
|
||||
op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)
|
||||
? Unqualified
|
||||
: Qualified,
|
||||
&v,
|
||||
result))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!SetProperty(cx, obj, obj, id, &v, result))
|
||||
return false;
|
||||
return NativeSetProperty(
|
||||
cx, obj.as<NativeObject>(), obj.as<NativeObject>(), id,
|
||||
(op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
|
||||
op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)
|
||||
? Unqualified
|
||||
: Qualified,
|
||||
&v,
|
||||
strict);
|
||||
}
|
||||
return result.checkStrictErrorOrWarning(cx, obj, id, strict);
|
||||
|
||||
return SetProperty(cx, obj, obj, id, &v, strict);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -647,7 +647,8 @@ bool CheckOverRecursedWithExtra(JSContext* cx, BaselineFrame* frame,
|
||||
bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
|
||||
bool SetConst(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, HandleValue rval);
|
||||
bool MutatePrototype(JSContext *cx, HandlePlainObject obj, HandleValue value);
|
||||
bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
|
||||
|
||||
bool InitProp(JSContext *cx, HandleNativeObject obj, HandlePropertyName name, HandleValue value,
|
||||
jsbytecode *pc);
|
||||
|
||||
template<bool Equal>
|
||||
@@ -664,6 +665,8 @@ bool GreaterThanOrEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValu
|
||||
template<bool Equal>
|
||||
bool StringsEqual(JSContext* cx, HandleString left, HandleString right, bool* res);
|
||||
|
||||
JSObject* NewInitObject(JSContext* cx, HandlePlainObject templateObject);
|
||||
|
||||
bool ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval);
|
||||
bool ArrayPushDense(JSContext* cx, HandleArrayObject obj, HandleValue v, uint32_t* length);
|
||||
bool ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval);
|
||||
|
||||
+2
-8
@@ -50,7 +50,6 @@ MSG_DEF(JSMSG_BAD_SORT_ARG, 0, JSEXN_TYPEERR, "invalid Array.prototyp
|
||||
MSG_DEF(JSMSG_CANT_WATCH, 1, JSEXN_TYPEERR, "can't watch non-native objects of class {0}")
|
||||
MSG_DEF(JSMSG_READ_ONLY, 1, JSEXN_TYPEERR, "{0} is read-only")
|
||||
MSG_DEF(JSMSG_CANT_DELETE, 1, JSEXN_TYPEERR, "property {0} is non-configurable and can't be deleted")
|
||||
MSG_DEF(JSMSG_CANT_TRUNCATE_ARRAY, 0, JSEXN_TYPEERR, "can't delete non-configurable array element")
|
||||
MSG_DEF(JSMSG_NOT_FUNCTION, 1, JSEXN_TYPEERR, "{0} is not a function")
|
||||
MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 1, JSEXN_TYPEERR, "{0} is not a constructor")
|
||||
MSG_DEF(JSMSG_CANT_CONVERT, 1, JSEXN_ERR, "can't convert {0} to an integer")
|
||||
@@ -84,7 +83,7 @@ MSG_DEF(JSMSG_MISSING_FUN_ARG, 2, JSEXN_TYPEERR, "missing argument {0} w
|
||||
MSG_DEF(JSMSG_NOT_NONNULL_OBJECT, 1, JSEXN_TYPEERR, "{0} is not a non-null object")
|
||||
MSG_DEF(JSMSG_INVALID_DESCRIPTOR, 0, JSEXN_TYPEERR, "property descriptors must not specify a value or be writable when a getter or setter has been specified")
|
||||
MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE, 1, JSEXN_TYPEERR, "{0} is not extensible")
|
||||
MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 1, JSEXN_TYPEERR, "can't redefine non-configurable property {0}")
|
||||
MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 1, JSEXN_TYPEERR, "can't redefine non-configurable property '{0}'")
|
||||
MSG_DEF(JSMSG_CANT_APPEND_TO_ARRAY, 0, JSEXN_TYPEERR, "can't add elements past the end of an array if its length property is unwritable")
|
||||
MSG_DEF(JSMSG_CANT_REDEFINE_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't redefine array length")
|
||||
MSG_DEF(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't define array index property past the end of an array with non-writable length")
|
||||
@@ -206,6 +205,7 @@ MSG_DEF(JSMSG_CATCH_AFTER_GENERAL, 0, JSEXN_SYNTAXERR, "catch after uncondit
|
||||
MSG_DEF(JSMSG_CATCH_IDENTIFIER, 0, JSEXN_SYNTAXERR, "missing identifier in catch")
|
||||
MSG_DEF(JSMSG_CATCH_OR_FINALLY, 0, JSEXN_SYNTAXERR, "missing catch or finally after try")
|
||||
MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 0, JSEXN_SYNTAXERR, "catch without try")
|
||||
MSG_DEF(JSMSG_CLASS_NOT_IMPLEMENTED, 0, JSEXN_SYNTAXERR, "classes are not implemented yet")
|
||||
MSG_DEF(JSMSG_COLON_AFTER_CASE, 0, JSEXN_SYNTAXERR, "missing : after case label")
|
||||
MSG_DEF(JSMSG_COLON_AFTER_ID, 0, JSEXN_SYNTAXERR, "missing : after property id")
|
||||
MSG_DEF(JSMSG_COLON_IN_COND, 0, JSEXN_SYNTAXERR, "missing : in conditional expression")
|
||||
@@ -393,9 +393,6 @@ MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 0, JSEXN_TYPEERR, "findScripts query objec
|
||||
MSG_DEF(JSMSG_DEBUG_CANT_SET_OPT_ENV, 1, JSEXN_REFERENCEERR, "can't set `{0}' in an optimized-out environment")
|
||||
MSG_DEF(JSMSG_DEBUG_INVISIBLE_COMPARTMENT, 0, JSEXN_TYPEERR, "object in compartment marked as invisible to Debugger")
|
||||
|
||||
// Tracelogger
|
||||
MSG_DEF(JSMSG_TRACELOGGER_ENABLE_FAIL, 1, JSEXN_ERR, "enabling tracelogger failed: {0}")
|
||||
|
||||
// Intl
|
||||
MSG_DEF(JSMSG_DATE_NOT_FINITE, 0, JSEXN_RANGEERR, "date value is not finite in DateTimeFormat.format()")
|
||||
MSG_DEF(JSMSG_INTERNAL_INTL_ERROR, 0, JSEXN_ERR, "internal error while computing Intl data")
|
||||
@@ -465,6 +462,3 @@ MSG_DEF(JSMSG_SYMBOL_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert symbol t
|
||||
MSG_DEF(JSMSG_ATOMICS_BAD_ARRAY, 0, JSEXN_TYPEERR, "invalid array type for the operation")
|
||||
MSG_DEF(JSMSG_ATOMICS_TOO_LONG, 0, JSEXN_RANGEERR, "timeout value too large")
|
||||
MSG_DEF(JSMSG_ATOMICS_WAIT_NOT_ALLOWED, 0, JSEXN_ERR, "waiting is not allowed on this thread")
|
||||
|
||||
// XPConnect wrappers
|
||||
MSG_DEF(JSMSG_CANT_SET_INTERPOSED, 1, JSEXN_TYPEERR, "unable to set interposed data property '{0}'")
|
||||
|
||||
@@ -44,9 +44,10 @@ PreWrap(JSContext* cx, JS::HandleObject scope, JS::HandleObject obj,
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
Wrap(JSContext* cx, JS::HandleObject existing, JS::HandleObject obj)
|
||||
Wrap(JSContext* cx, JS::HandleObject existing, JS::HandleObject obj,
|
||||
JS::HandleObject parent)
|
||||
{
|
||||
return js::Wrapper::New(cx, obj, &js::CrossCompartmentWrapper::singleton);
|
||||
return js::Wrapper::New(cx, obj, parent, &js::CrossCompartmentWrapper::singleton);
|
||||
}
|
||||
|
||||
static const JSWrapObjectCallbacks WrapObjectCallbacks = {
|
||||
@@ -59,7 +60,7 @@ BEGIN_TEST(testBug604087)
|
||||
js::WrapperOptions options;
|
||||
options.setClass(&OuterWrapperClass);
|
||||
options.setSingleton(true);
|
||||
JS::RootedObject outerObj(cx, js::Wrapper::New(cx, global, &js::Wrapper::singleton, options));
|
||||
JS::RootedObject outerObj(cx, js::Wrapper::New(cx, global, global, &js::Wrapper::singleton, options));
|
||||
JS::RootedObject compartment2(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr, JS::FireOnNewGlobalHook));
|
||||
JS::RootedObject compartment3(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr, JS::FireOnNewGlobalHook));
|
||||
JS::RootedObject compartment4(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr, JS::FireOnNewGlobalHook));
|
||||
@@ -80,7 +81,7 @@ BEGIN_TEST(testBug604087)
|
||||
JS::RootedObject next(cx);
|
||||
{
|
||||
JSAutoCompartment ac(cx, compartment2);
|
||||
next = js::Wrapper::New(cx, compartment2, &js::Wrapper::singleton, options);
|
||||
next = js::Wrapper::New(cx, compartment2, compartment2, &js::Wrapper::singleton, options);
|
||||
CHECK(next);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,14 +45,11 @@ BEGIN_TEST(testForwardSetProperty)
|
||||
|
||||
// Non-strict setter
|
||||
|
||||
ObjectOpResult result;
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, v3, result));
|
||||
CHECK(result);
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, v3, true, setval));
|
||||
|
||||
EXEC("assertEq(foundValue, obj3, 'wrong receiver passed to setter');");
|
||||
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, setval, result));
|
||||
CHECK(result);
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, true, setval));
|
||||
|
||||
EXEC("assertEq(typeof foundValue === 'object', true, \n"
|
||||
" 'passing 42 as receiver to non-strict setter ' + \n"
|
||||
@@ -72,13 +69,12 @@ BEGIN_TEST(testForwardSetProperty)
|
||||
"obj1;",
|
||||
&v1);
|
||||
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, v3, result));
|
||||
CHECK(result);
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, v3, true, setval));
|
||||
|
||||
EXEC("assertEq(foundValue, obj3, 'wrong receiver passed to strict setter');");
|
||||
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, setval, result));
|
||||
CHECK(result);
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, true, setval));
|
||||
|
||||
|
||||
JS::RootedValue strictSetSupported(cx);
|
||||
EVAL("var strictSetSupported = false; \n"
|
||||
|
||||
@@ -28,13 +28,13 @@ class CustomProxyHandler : public DirectProxyHandler {
|
||||
}
|
||||
|
||||
bool set(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const MOZ_OVERRIDE
|
||||
HandleId id, bool strict, MutableHandleValue vp) const override
|
||||
{
|
||||
Rooted<JSPropertyDescriptor> desc(cx);
|
||||
if (!DirectProxyHandler::getPropertyDescriptor(cx, proxy, id, &desc))
|
||||
return false;
|
||||
return SetPropertyIgnoringNamedGetter(cx, this, proxy, receiver, id, &desc,
|
||||
desc.object() == proxy, vp, result);
|
||||
desc.object() == proxy, strict, vp);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -72,7 +72,7 @@ BEGIN_TEST(testSetPropertyIgnoringNamedGetter_direct)
|
||||
EVAL("({})", &targetv);
|
||||
|
||||
RootedObject proxyObj(cx, NewProxyObject(cx, &customProxyHandler, targetv,
|
||||
&protov.toObject(), ProxyOptions()));
|
||||
&protov.toObject(), global, ProxyOptions()));
|
||||
CHECK(proxyObj);
|
||||
|
||||
CHECK(JS_DefineProperty(cx, global, "target", targetv, 0));
|
||||
|
||||
+25
-131
@@ -129,70 +129,6 @@ JS::CallArgs::requireAtLeast(JSContext* cx, const char* fnname, unsigned require
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ErrorTakesIdArgument(unsigned msg)
|
||||
{
|
||||
MOZ_ASSERT(msg < JSErr_Limit);
|
||||
unsigned argCount = js_ErrorFormatString[msg].argCount;
|
||||
MOZ_ASSERT(argCount <= 1);
|
||||
return argCount == 1;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::ObjectOpResult::reportStrictErrorOrWarning(JSContext *cx, HandleObject obj, HandleId id,
|
||||
bool strict)
|
||||
{
|
||||
static_assert(unsigned(OkCode) == unsigned(JSMSG_NOT_AN_ERROR),
|
||||
"unsigned value of OkCode must not be an error code");
|
||||
MOZ_ASSERT(code_ != Uninitialized);
|
||||
MOZ_ASSERT(!ok());
|
||||
|
||||
unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_WARNING | JSREPORT_STRICT);
|
||||
if (code_ == JSMSG_OBJECT_NOT_EXTENSIBLE) {
|
||||
RootedValue val(cx, ObjectValue(*obj));
|
||||
return ReportValueErrorFlags(cx, flags, code_, JSDVG_IGNORE_STACK, val,
|
||||
NullPtr(), nullptr, nullptr);
|
||||
}
|
||||
if (ErrorTakesIdArgument(code_)) {
|
||||
RootedValue idv(cx, IdToValue(id));
|
||||
RootedString str(cx, ValueToSource(cx, idv));
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
JSAutoByteString propName(cx, str);
|
||||
if (!propName)
|
||||
return false;
|
||||
|
||||
return JS_ReportErrorFlagsAndNumber(cx, flags, GetErrorMessage, nullptr, code_,
|
||||
propName.ptr());
|
||||
}
|
||||
return JS_ReportErrorFlagsAndNumber(cx, flags, GetErrorMessage, nullptr, code_);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::ObjectOpResult::failCantRedefineProp()
|
||||
{
|
||||
return fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::ObjectOpResult::failReadOnly()
|
||||
{
|
||||
return fail(JSMSG_READ_ONLY);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::ObjectOpResult::failGetterOnly()
|
||||
{
|
||||
return fail(JSMSG_GETTER_ONLY);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::ObjectOpResult::failCantSetInterposed()
|
||||
{
|
||||
return fail(JSMSG_CANT_SET_INTERPOSED);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(int64_t)
|
||||
JS_Now()
|
||||
{
|
||||
@@ -1851,10 +1787,9 @@ JS_PropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_StrictPropertyStub(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp,
|
||||
ObjectOpResult &result)
|
||||
JS_StrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
|
||||
{
|
||||
return result.succeed();
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
@@ -1976,6 +1911,18 @@ JS_GetParent(JSObject* obj)
|
||||
return obj->getParent();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_SetParent(JSContext* cx, HandleObject obj, HandleObject parent)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
MOZ_ASSERT(!obj->is<ScopeObject>());
|
||||
MOZ_ASSERT(parent || !obj->getParent());
|
||||
assertSameCompartment(cx, obj, parent);
|
||||
|
||||
return JSObject::setParent(cx, obj, parent);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
JS_GetConstructor(JSContext* cx, HandleObject proto)
|
||||
{
|
||||
@@ -2451,33 +2398,6 @@ JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, double value
|
||||
NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefinePropertyByDescriptor(JSContext *cx, HandleObject obj, HandleId id,
|
||||
Handle<JSPropertyDescriptor> desc, ObjectOpResult &result)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, id, desc);
|
||||
return DefineProperty(cx, obj, id, desc.value(), desc.getter(), desc.setter(),
|
||||
desc.attributes(), result);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id,
|
||||
Handle<JSPropertyDescriptor> desc, ObjectOpResult &result)
|
||||
{
|
||||
return DefinePropertyByDescriptor(cx, obj, id, desc, result);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id,
|
||||
Handle<JSPropertyDescriptor> desc)
|
||||
{
|
||||
ObjectOpResult result;
|
||||
return DefinePropertyByDescriptor(cx, obj, id, desc, result) &&
|
||||
result.checkStrict(cx, obj, id);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
|
||||
unsigned attrs, Native getter, Native setter)
|
||||
@@ -2734,31 +2654,6 @@ JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_
|
||||
getter, setter, attrs, 0);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefineUCProperty(JSContext *cx, HandleObject obj, const char16_t *name, size_t namelen,
|
||||
Handle<JSPropertyDescriptor> desc,
|
||||
ObjectOpResult &result)
|
||||
{
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
if (!atom)
|
||||
return false;
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
return DefinePropertyByDescriptor(cx, obj, id, desc, result);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefineUCProperty(JSContext *cx, HandleObject obj, const char16_t *name, size_t namelen,
|
||||
Handle<JSPropertyDescriptor> desc)
|
||||
{
|
||||
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
if (!atom)
|
||||
return false;
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
ObjectOpResult result;
|
||||
return DefinePropertyByDescriptor(cx, obj, id, desc, result) &&
|
||||
result.checkStrict(cx, obj, id);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
JS_DefineObject(JSContext* cx, HandleObject obj, const char* name, const JSClass* jsclasp,
|
||||
unsigned attrs)
|
||||
@@ -3001,25 +2896,25 @@ JS_SetPropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, id);
|
||||
|
||||
ObjectOpResult ignored;
|
||||
return SetProperty(cx, obj, obj, id, &value, ignored);
|
||||
return SetProperty(cx, obj, obj, id, &value, false);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ForwardSetPropertyTo(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
HandleValue receiver, ObjectOpResult &result)
|
||||
JS_ForwardSetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue onBehalfOf,
|
||||
bool strict, JS::HandleValue v)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, id, receiver);
|
||||
assertSameCompartment(cx, obj, id);
|
||||
assertSameCompartment(cx, onBehalfOf);
|
||||
|
||||
// XXX Bug 603201 will eliminate this ToObject.
|
||||
RootedObject receiverObj(cx, ToObject(cx, receiver));
|
||||
if (!receiverObj)
|
||||
RootedObject receiver(cx, ToObject(cx, onBehalfOf));
|
||||
if (!receiver)
|
||||
return false;
|
||||
|
||||
RootedValue value(cx, v);
|
||||
return SetProperty(cx, obj, receiverObj, id, &value, result);
|
||||
return SetProperty(cx, obj, receiver, id, &value, strict);
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -3029,8 +2924,7 @@ SetElement(JSContext* cx, HandleObject obj, uint32_t index, MutableHandleValue v
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, vp);
|
||||
|
||||
ObjectOpResult ignored;
|
||||
return SetElement(cx, obj, obj, index, vp, ignored);
|
||||
return SetElement(cx, obj, obj, index, vp, false);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
@@ -3548,7 +3442,7 @@ JS_BindCallable(JSContext* cx, HandleObject target, HandleObject newThis)
|
||||
}
|
||||
|
||||
static bool
|
||||
GenericNativeMethodDispatcher(JSContext *cx, unsigned argc, Value *vp)
|
||||
js_generic_native_method_dispatcher(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
@@ -3617,7 +3511,7 @@ JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs,
|
||||
|
||||
flags &= ~JSFUN_GENERIC_NATIVE;
|
||||
JSFunction* fun = DefineFunction(cx, ctor, id,
|
||||
GenericNativeMethodDispatcher,
|
||||
js_generic_native_method_dispatcher,
|
||||
fs->nargs + 1, flags,
|
||||
JSFunction::ExtendedFinalizeKind);
|
||||
if (!fun)
|
||||
|
||||
+96
-118
@@ -730,7 +730,8 @@ typedef bool
|
||||
* guaranteed not to wrap a function.
|
||||
*/
|
||||
typedef JSObject*
|
||||
(* JSWrapObjectCallback)(JSContext* cx, JS::HandleObject existing, JS::HandleObject obj);
|
||||
(* JSWrapObjectCallback)(JSContext* cx, JS::HandleObject existing, JS::HandleObject obj,
|
||||
JS::HandleObject parent);
|
||||
|
||||
/*
|
||||
* Callback used by the wrap hook to ask the embedding to prepare an object
|
||||
@@ -2036,8 +2037,8 @@ JS_PropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::MutableHandleValue vp);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_StrictPropertyStub(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::MutableHandleValue vp, JS::ObjectOpResult &result);
|
||||
JS_StrictPropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool strict,
|
||||
JS::MutableHandleValue vp);
|
||||
|
||||
template<typename T>
|
||||
struct JSConstScalarSpec {
|
||||
@@ -2289,6 +2290,9 @@ JS_SetPrototype(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto);
|
||||
extern JS_PUBLIC_API(JSObject*)
|
||||
JS_GetParent(JSObject* obj);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_SetParent(JSContext* cx, JS::HandleObject obj, JS::HandleObject parent);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject*)
|
||||
JS_GetConstructor(JSContext* cx, JS::Handle<JSObject*> proto);
|
||||
|
||||
@@ -2555,7 +2559,92 @@ JS_PreventExtensions(JSContext* cx, JS::HandleObject obj, bool* succeeded);
|
||||
extern JS_PUBLIC_API(JSObject*)
|
||||
JS_New(JSContext* cx, JS::HandleObject ctor, const JS::HandleValueArray& args);
|
||||
|
||||
/*** Property descriptors ************************************************************************/
|
||||
extern JS_PUBLIC_API(JSObject*)
|
||||
JS_DefineObject(JSContext* cx, JS::HandleObject obj, const char* name,
|
||||
const JSClass* clasp = nullptr, unsigned attrs = 0);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineConstDoubles(JSContext* cx, JS::HandleObject obj, const JSConstDoubleSpec* cds);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineConstIntegers(JSContext* cx, JS::HandleObject obj, const JSConstIntegerSpec* cis);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperties(JSContext* cx, JS::HandleObject obj, const JSPropertySpec* ps);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleObject value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleString value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, int32_t value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, uint32_t value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, double value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleString value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, int32_t value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, uint32_t value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, double value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_AlreadyHasOwnProperty(JSContext* cx, JS::HandleObject obj, const char* name,
|
||||
bool* foundp);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_AlreadyHasOwnPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||
bool* foundp);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_HasProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_HasPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
|
||||
|
||||
struct JSPropertyDescriptor {
|
||||
JSObject* obj;
|
||||
@@ -2744,108 +2833,6 @@ ParsePropertyDescriptorObject(JSContext* cx,
|
||||
|
||||
} // namespace JS
|
||||
|
||||
/*** [[DefineOwnProperty]] and variations ********************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleValue value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleObject value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleString value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, int32_t value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, uint32_t value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, double value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleString value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, int32_t value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, uint32_t value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, double value,
|
||||
unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::Handle<JSPropertyDescriptor> desc,
|
||||
JS::ObjectOpResult &result);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::Handle<JSPropertyDescriptor> desc);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_DefineObject(JSContext *cx, JS::HandleObject obj, const char *name,
|
||||
const JSClass *clasp = nullptr, unsigned attrs = 0);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineConstDoubles(JSContext *cx, JS::HandleObject obj, const JSConstDoubleSpec *cds);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineConstIntegers(JSContext *cx, JS::HandleObject obj, const JSConstIntegerSpec *cis);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperties(JSContext *cx, JS::HandleObject obj, const JSPropertySpec *ps);
|
||||
|
||||
|
||||
/* * */
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_AlreadyHasOwnProperty(JSContext *cx, JS::HandleObject obj, const char *name,
|
||||
bool *foundp);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_AlreadyHasOwnPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
|
||||
bool *foundp);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_HasProperty(JSContext *cx, JS::HandleObject obj, const char *name, bool *foundp);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_HasPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *foundp);
|
||||
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_GetOwnPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||
@@ -2884,8 +2871,8 @@ extern JS_PUBLIC_API(bool)
|
||||
JS_SetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_ForwardSetPropertyTo(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
|
||||
JS::HandleValue receiver, JS::ObjectOpResult &result);
|
||||
JS_ForwardSetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue onBehalfOf,
|
||||
bool strict, JS::HandleValue vp);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name);
|
||||
@@ -2929,15 +2916,6 @@ JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, s
|
||||
double value, unsigned attrs,
|
||||
JSNative getter = nullptr, JSNative setter = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineUCProperty(JSContext *cx, JS::HandleObject obj, const char16_t *name, size_t namelen,
|
||||
JS::Handle<JSPropertyDescriptor> desc,
|
||||
JS::ObjectOpResult &result);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineUCProperty(JSContext *cx, JS::HandleObject obj, const char16_t *name, size_t namelen,
|
||||
JS::Handle<JSPropertyDescriptor> desc);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_AlreadyHasOwnUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name,
|
||||
size_t namelen, bool* foundp);
|
||||
@@ -3707,7 +3685,7 @@ JS_DecompileFunctionBody(JSContext* cx, JS::Handle<JSFunction*> fun, unsigned in
|
||||
* names) of the execution context for script.
|
||||
*
|
||||
* Using obj as the variables object is problematic if obj's parent (which is
|
||||
* the scope chain link) is not null, which in practice is always true: in
|
||||
* the scope chain link; see JS_SetParent and JS_NewObject) is not null: in
|
||||
* this case, variables created by 'var x = 0', e.g., go in obj, but variables
|
||||
* created by assignment to an unbound id, 'x = 0', go in the last object on
|
||||
* the scope chain linked by parent.
|
||||
|
||||
+62
-22
@@ -363,7 +363,7 @@ SetArrayElement(JSContext* cx, HandleObject obj, double index, HandleValue v)
|
||||
return false;
|
||||
|
||||
RootedValue tmp(cx, v);
|
||||
return SetProperty(cx, obj, obj, id, &tmp);
|
||||
return SetProperty(cx, obj, obj, id, &tmp, true);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -433,7 +433,7 @@ bool
|
||||
js::SetLengthProperty(JSContext* cx, HandleObject obj, double length)
|
||||
{
|
||||
RootedValue v(cx, NumberValue(length));
|
||||
return SetProperty(cx, obj, obj, cx->names().length, &v);
|
||||
return SetProperty(cx, obj, obj, cx->names().length, &v, true);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -459,8 +459,7 @@ array_length_getter(JSContext* cx, HandleObject obj_, HandleId id, MutableHandle
|
||||
}
|
||||
|
||||
static bool
|
||||
array_length_setter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp,
|
||||
ObjectOpResult &result)
|
||||
array_length_setter(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
|
||||
{
|
||||
if (!obj->is<ArrayObject>()) {
|
||||
// This array .length property was found on the prototype
|
||||
@@ -468,14 +467,13 @@ array_length_setter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleV
|
||||
// we're here, do an impression of SetPropertyByDefining.
|
||||
const Class* clasp = obj->getClass();
|
||||
return DefineProperty(cx, obj, cx->names().length, vp,
|
||||
clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE, result);
|
||||
clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
|
||||
MOZ_ASSERT(arr->lengthIsWritable(),
|
||||
"setter shouldn't be called if property is non-writable");
|
||||
|
||||
return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, vp, result);
|
||||
return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, vp, strict);
|
||||
}
|
||||
|
||||
struct ReverseIndexComparator
|
||||
@@ -508,7 +506,7 @@ js::CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* newLen)
|
||||
/* ES6 20130308 draft 8.4.2.4 ArraySetLength */
|
||||
bool
|
||||
js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
|
||||
unsigned attrs, HandleValue value, ObjectOpResult &result)
|
||||
unsigned attrs, HandleValue value, bool setterIsStrict)
|
||||
{
|
||||
MOZ_ASSERT(id == NameToId(cx->names().length));
|
||||
|
||||
@@ -531,8 +529,11 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
|
||||
// OrdinaryDefineOwnProperty in ES6, the default [[DefineOwnProperty]] in
|
||||
// ES5 -- but we reimplement all the conflict-detection bits ourselves here
|
||||
// so that we can use a customized length representation.)
|
||||
if (!(attrs & JSPROP_PERMANENT) || (attrs & JSPROP_ENUMERATE))
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
if (!(attrs & JSPROP_PERMANENT) || (attrs & JSPROP_ENUMERATE)) {
|
||||
if (!setterIsStrict)
|
||||
return true;
|
||||
return Throw(cx, id, JSMSG_CANT_REDEFINE_PROP);
|
||||
}
|
||||
|
||||
/* Steps 6-7. */
|
||||
bool lengthIsWritable = arr->lengthIsWritable();
|
||||
@@ -549,9 +550,14 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
|
||||
/* Steps 8-9 for arrays with non-writable length. */
|
||||
if (!lengthIsWritable) {
|
||||
if (newLen == oldLen)
|
||||
return result.succeed();
|
||||
return true;
|
||||
|
||||
return result.fail(JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
|
||||
if (setterIsStrict) {
|
||||
return JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, GetErrorMessage, nullptr,
|
||||
JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
|
||||
}
|
||||
|
||||
return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
|
||||
}
|
||||
|
||||
/* Step 8. */
|
||||
@@ -732,20 +738,53 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
|
||||
}
|
||||
}
|
||||
|
||||
if (!succeeded)
|
||||
return result.fail(JSMSG_CANT_TRUNCATE_ARRAY);
|
||||
if (setterIsStrict && !succeeded) {
|
||||
RootedId elementId(cx);
|
||||
if (!IndexToId(cx, newLen - 1, &elementId))
|
||||
return false;
|
||||
return arr->reportNotConfigurable(cx, elementId);
|
||||
}
|
||||
|
||||
return result.succeed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index)
|
||||
js::WouldDefinePastNonwritableLength(ExclusiveContext* cx,
|
||||
HandleObject obj, uint32_t index, bool strict,
|
||||
bool* definesPast)
|
||||
{
|
||||
if (!obj->is<ArrayObject>())
|
||||
return false;
|
||||
if (!obj->is<ArrayObject>()) {
|
||||
*definesPast = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
ArrayObject *arr = &obj->as<ArrayObject>();
|
||||
return !arr->lengthIsWritable() && index >= arr->length();
|
||||
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
|
||||
uint32_t length = arr->length();
|
||||
if (index < length) {
|
||||
*definesPast = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arr->lengthIsWritable()) {
|
||||
*definesPast = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
*definesPast = true;
|
||||
|
||||
// Error in strict mode code or warn with strict option.
|
||||
unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_STRICT | JSREPORT_WARNING);
|
||||
if (!cx->isJSContext())
|
||||
return true;
|
||||
|
||||
JSContext* ncx = cx->asJSContext();
|
||||
|
||||
if (!strict && !ncx->compartment()->options().extraWarnings(ncx))
|
||||
return true;
|
||||
|
||||
// XXX include the index and maybe array length in the error message
|
||||
return JS_ReportErrorFlagsAndNumber(ncx, flags, GetErrorMessage, nullptr,
|
||||
JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -1269,7 +1308,7 @@ InitArrayElements(JSContext* cx, HandleObject obj, uint32_t start, uint32_t coun
|
||||
value = *vector++;
|
||||
indexv = DoubleValue(index);
|
||||
if (!ValueToId<CanGC>(cx, indexv, &id) ||
|
||||
!SetProperty(cx, obj, obj, id, &value))
|
||||
!SetProperty(cx, obj, obj, id, &value, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -3073,7 +3112,8 @@ array_of(JSContext* cx, unsigned argc, Value* vp)
|
||||
}
|
||||
|
||||
// Steps 9-10.
|
||||
if (!SetLengthProperty(cx, obj, args.length()))
|
||||
RootedValue v(cx, NumberValue(args.length()));
|
||||
if (!SetProperty(cx, obj, obj, cx->names().length, &v, true))
|
||||
return false;
|
||||
|
||||
// Step 11.
|
||||
|
||||
+3
-1
@@ -101,7 +101,9 @@ NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::In
|
||||
* increase the length of the array.
|
||||
*/
|
||||
extern bool
|
||||
WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index);
|
||||
WouldDefinePastNonwritableLength(ExclusiveContext* cx,
|
||||
HandleObject obj, uint32_t index, bool strict,
|
||||
bool* definesPast);
|
||||
|
||||
/*
|
||||
* Canonicalize |vp| to a uint32_t value potentially suitable for use as an
|
||||
|
||||
+7
-18
@@ -132,15 +132,6 @@ class CompartmentChecker
|
||||
void check(InterpreterFrame* fp);
|
||||
void check(AbstractFramePtr frame);
|
||||
void check(SavedStacks* stacks);
|
||||
|
||||
void check(Handle<JSPropertyDescriptor> desc) {
|
||||
check(desc.object());
|
||||
if (desc.hasGetterObject())
|
||||
check(desc.getterObject());
|
||||
if (desc.hasSetterObject())
|
||||
check(desc.setterObject());
|
||||
check(desc.value());
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -316,12 +307,12 @@ CallJSPropertyOp(JSContext* cx, PropertyOp op, HandleObject receiver, HandleId i
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
CallJSPropertyOpSetter(JSContext* cx, StrictPropertyOp op, HandleObject obj, HandleId id,
|
||||
MutableHandleValue vp, ObjectOpResult &result)
|
||||
bool strict, MutableHandleValue vp)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
|
||||
assertSameCompartment(cx, obj, id, vp);
|
||||
return op(cx, obj, id, vp, result);
|
||||
return op(cx, obj, id, strict, vp);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@@ -339,22 +330,20 @@ CallJSDeletePropertyOp(JSContext* cx, JSDeletePropertyOp op, HandleObject receiv
|
||||
|
||||
inline bool
|
||||
CallSetter(JSContext* cx, HandleObject obj, HandleId id, StrictPropertyOp op, unsigned attrs,
|
||||
MutableHandleValue vp, ObjectOpResult &result)
|
||||
bool strict, MutableHandleValue vp)
|
||||
{
|
||||
if (attrs & JSPROP_SETTER) {
|
||||
RootedValue opv(cx, CastAsObjectJsval(op));
|
||||
if (!InvokeGetterOrSetter(cx, obj, opv, 1, vp.address(), vp))
|
||||
return false;
|
||||
return result.succeed();
|
||||
return InvokeGetterOrSetter(cx, obj, opv, 1, vp.address(), vp);
|
||||
}
|
||||
|
||||
if (attrs & JSPROP_GETTER)
|
||||
return result.fail(JSMSG_GETTER_ONLY);
|
||||
return ReportGetterOnlyAssignment(cx, strict);
|
||||
|
||||
if (!op)
|
||||
return result.succeed();
|
||||
return true;
|
||||
|
||||
return CallJSPropertyOpSetter(cx, op, obj, id, vp, result);
|
||||
return CallJSPropertyOpSetter(cx, op, obj, id, strict, vp);
|
||||
}
|
||||
|
||||
inline uintptr_t
|
||||
|
||||
@@ -425,7 +425,7 @@ JSCompartment::wrap(JSContext* cx, MutableHandleObject obj, HandleObject existin
|
||||
}
|
||||
}
|
||||
|
||||
obj.set(cb->wrap(cx, existing, obj));
|
||||
obj.set(cb->wrap(cx, existing, obj, global));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -606,27 +606,27 @@ js::StringToLinearStringSlow(JSContext* cx, JSString* str)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject*)
|
||||
JS_CloneObject(JSContext* cx, HandleObject obj, HandleObject protoArg)
|
||||
JS_CloneObject(JSContext* cx, HandleObject obj, HandleObject protoArg, HandleObject parent)
|
||||
{
|
||||
Rooted<TaggedProto> proto(cx, TaggedProto(protoArg.get()));
|
||||
return CloneObject(cx, obj, proto);
|
||||
return CloneObject(cx, obj, proto, parent);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JS_FRIEND_API(void)
|
||||
js::DumpString(JSString *str)
|
||||
js_DumpString(JSString* str)
|
||||
{
|
||||
str->dump();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::DumpAtom(JSAtom *atom)
|
||||
js_DumpAtom(JSAtom* atom)
|
||||
{
|
||||
atom->dump();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::DumpChars(const char16_t *s, size_t n)
|
||||
js_DumpChars(const char16_t* s, size_t n)
|
||||
{
|
||||
fprintf(stderr, "char16_t * (%p) = ", (void*) s);
|
||||
JSString::dumpChars(s, n);
|
||||
@@ -634,7 +634,7 @@ js::DumpChars(const char16_t *s, size_t n)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::DumpObject(JSObject *obj)
|
||||
js_DumpObject(JSObject* obj)
|
||||
{
|
||||
if (!obj) {
|
||||
fprintf(stderr, "NULL\n");
|
||||
@@ -1169,7 +1169,7 @@ js::GetObjectMetadata(JSObject* obj)
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js::DefineOwnProperty(JSContext* cx, JSObject* objArg, jsid idArg,
|
||||
JS::Handle<js::PropertyDescriptor> descriptor, ObjectOpResult &result)
|
||||
JS::Handle<js::PropertyDescriptor> descriptor, bool* bp)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
RootedId id(cx, idArg);
|
||||
@@ -1181,7 +1181,7 @@ js::DefineOwnProperty(JSContext* cx, JSObject* objArg, jsid idArg,
|
||||
if (descriptor.hasSetterObject())
|
||||
assertSameCompartment(cx, descriptor.setterObject());
|
||||
|
||||
return StandardDefineProperty(cx, obj, id, descriptor, result);
|
||||
return StandardDefineProperty(cx, obj, id, descriptor, bp);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
|
||||
+17
-25
@@ -115,7 +115,8 @@ extern JS_FRIEND_API(JSObject*)
|
||||
JS_ObjectToOuterObject(JSContext* cx, JS::HandleObject obj);
|
||||
|
||||
extern JS_FRIEND_API(JSObject*)
|
||||
JS_CloneObject(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto);
|
||||
JS_CloneObject(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto,
|
||||
JS::HandleObject parent);
|
||||
|
||||
extern JS_FRIEND_API(JSString*)
|
||||
JS_BasicObjectToString(JSContext* cx, JS::HandleObject obj);
|
||||
@@ -137,48 +138,41 @@ AddRawValueRoot(JSContext* cx, JS::Value* vp, const char* name);
|
||||
JS_FRIEND_API(void)
|
||||
RemoveRawValueRoot(JSContext* cx, JS::Value* vp);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
|
||||
/*
|
||||
* Routines to print out values during debugging. These are FRIEND_API to help
|
||||
* the debugger find them and to support temporarily hacking js::Dump* calls
|
||||
* the debugger find them and to support temporarily hacking js_Dump* calls
|
||||
* into other code.
|
||||
*/
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
DumpString(JSString *str);
|
||||
js_DumpString(JSString* str);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
DumpAtom(JSAtom *atom);
|
||||
js_DumpAtom(JSAtom* atom);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
DumpObject(JSObject *obj);
|
||||
js_DumpObject(JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
DumpChars(const char16_t *s, size_t n);
|
||||
js_DumpChars(const char16_t* s, size_t n);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
DumpValue(const JS::Value &val);
|
||||
js_DumpValue(const JS::Value& val);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
DumpId(jsid id);
|
||||
js_DumpId(jsid id);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
DumpInterpreterFrame(JSContext *cx, InterpreterFrame *start = nullptr);
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
DumpPC(JSContext *cx);
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
DumpScript(JSContext *cx, JSScript *scriptArg);
|
||||
js_DumpInterpreterFrame(JSContext* cx, js::InterpreterFrame* start = nullptr);
|
||||
|
||||
#endif
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
DumpBacktrace(JSContext *cx);
|
||||
|
||||
|
||||
} // namespace js
|
||||
js_DumpBacktrace(JSContext* cx);
|
||||
|
||||
namespace JS {
|
||||
|
||||
@@ -311,8 +305,7 @@ proxy_LookupProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::M
|
||||
JS::MutableHandle<Shape*> propp);
|
||||
extern JS_FRIEND_API(bool)
|
||||
proxy_DefineProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs,
|
||||
JS::ObjectOpResult &result);
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
|
||||
extern JS_FRIEND_API(bool)
|
||||
proxy_HasProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
|
||||
extern JS_FRIEND_API(bool)
|
||||
@@ -320,7 +313,7 @@ proxy_GetProperty(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver
|
||||
JS::MutableHandleValue vp);
|
||||
extern JS_FRIEND_API(bool)
|
||||
proxy_SetProperty(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
|
||||
JS::MutableHandleValue bp, JS::ObjectOpResult &result);
|
||||
JS::MutableHandleValue bp, bool strict);
|
||||
extern JS_FRIEND_API(bool)
|
||||
proxy_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||
@@ -2551,8 +2544,7 @@ JS_FRIEND_API(bool)
|
||||
SetPropertyIgnoringNamedGetter(JSContext* cx, const BaseProxyHandler* handler,
|
||||
JS::HandleObject proxy, JS::HandleObject receiver,
|
||||
JS::HandleId id, JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
bool descIsOwn, JS::MutableHandleValue vp,
|
||||
JS::ObjectOpResult &result);
|
||||
bool descIsOwn, bool strict, JS::MutableHandleValue vp);
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
ReportErrorWithId(JSContext* cx, const char* msg, JS::HandleId id);
|
||||
@@ -2623,7 +2615,7 @@ ReportIsNotFunction(JSContext* cx, JS::HandleValue v);
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
DefineOwnProperty(JSContext* cx, JSObject* objArg, jsid idArg,
|
||||
JS::Handle<JSPropertyDescriptor> descriptor, JS::ObjectOpResult &result);
|
||||
JS::Handle<JSPropertyDescriptor> descriptor, bool* bp);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
|
||||
+131
-141
@@ -445,12 +445,41 @@ js::Throw(JSContext* cx, JSObject* obj, unsigned errorNumber)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
Reject(JSContext* cx, unsigned errorNumber, bool throwError, jsid id, bool* rval)
|
||||
{
|
||||
if (throwError)
|
||||
return Throw(cx, id, errorNumber);
|
||||
|
||||
*rval = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
Reject(JSContext* cx, JSObject* obj, unsigned errorNumber, bool throwError, bool* rval)
|
||||
{
|
||||
if (throwError)
|
||||
return Throw(cx, obj, errorNumber);
|
||||
|
||||
*rval = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
Reject(JSContext* cx, HandleId id, unsigned errorNumber, bool throwError, bool* rval)
|
||||
{
|
||||
if (throwError)
|
||||
return Throw(cx, id, errorNumber);
|
||||
|
||||
*rval = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*** Standard-compliant property definition (used by Object.defineProperty) **********************/
|
||||
|
||||
static bool
|
||||
DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const PropDesc& desc,
|
||||
ObjectOpResult &result)
|
||||
bool throwError, bool* rval)
|
||||
{
|
||||
/* 8.12.9 step 1. */
|
||||
RootedShape shape(cx);
|
||||
@@ -466,19 +495,20 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
|
||||
if (!IsExtensible(cx, obj, &extensible))
|
||||
return false;
|
||||
if (!extensible)
|
||||
return result.fail(JSMSG_OBJECT_NOT_EXTENSIBLE);
|
||||
return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
|
||||
|
||||
*rval = true;
|
||||
|
||||
if (desc.isGenericDescriptor() || desc.isDataDescriptor()) {
|
||||
MOZ_ASSERT(!obj->getOps()->defineProperty);
|
||||
RootedValue v(cx, desc.hasValue() ? desc.value() : UndefinedValue());
|
||||
return NativeDefineProperty(cx, obj, id, v, nullptr, nullptr, desc.attributes(),
|
||||
result);
|
||||
return NativeDefineProperty(cx, obj, id, v, nullptr, nullptr, desc.attributes());
|
||||
}
|
||||
|
||||
MOZ_ASSERT(desc.isAccessorDescriptor());
|
||||
|
||||
return NativeDefineProperty(cx, obj, id, UndefinedHandleValue,
|
||||
desc.getter(), desc.setter(), desc.attributes(), result);
|
||||
desc.getter(), desc.setter(), desc.attributes());
|
||||
}
|
||||
|
||||
/* 8.12.9 steps 5-6 (note 5 is merely a special case of 6). */
|
||||
@@ -555,7 +585,7 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
|
||||
desc.isDataDescriptor() &&
|
||||
(desc.hasWritable() ? desc.writable() : shape->writable()))
|
||||
{
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
|
||||
}
|
||||
|
||||
if (!NativeGetExistingProperty(cx, obj, obj, shape, &v))
|
||||
@@ -581,16 +611,16 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
|
||||
* flag we veto from true to false for non-configurable
|
||||
* PropertyOp-based data properties and test before the
|
||||
* SameValue check later on in order to re-use that "if
|
||||
* (!SameValue) return false" logic.
|
||||
* (!SameValue) Reject" logic.
|
||||
*
|
||||
* This function is large and complex enough that it
|
||||
* seems best to repeat a small bit of code and return
|
||||
* result.fail() ASAP, instead of being clever.
|
||||
* Reject(...) ASAP, instead of being clever.
|
||||
*/
|
||||
if (!shapeConfigurable &&
|
||||
(!shape->hasDefaultGetter() || !shape->hasDefaultSetter()))
|
||||
{
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -609,14 +639,15 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
|
||||
break;
|
||||
|
||||
/* The conditions imposed by step 5 or step 6 apply. */
|
||||
return result.succeed();
|
||||
*rval = true;
|
||||
return true;
|
||||
} while (0);
|
||||
|
||||
/* 8.12.9 step 7. */
|
||||
if (!shapeConfigurable) {
|
||||
if ((desc.hasConfigurable() && desc.configurable()) ||
|
||||
(desc.hasEnumerable() && desc.enumerable() != shape->enumerable())) {
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,19 +658,19 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
|
||||
} else if (desc.isDataDescriptor() != shapeDataDescriptor) {
|
||||
/* 8.12.9 step 9. */
|
||||
if (!shapeConfigurable)
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
|
||||
} else if (desc.isDataDescriptor()) {
|
||||
/* 8.12.9 step 10. */
|
||||
MOZ_ASSERT(shapeDataDescriptor);
|
||||
if (!shapeConfigurable && !shape->writable()) {
|
||||
if (desc.hasWritable() && desc.writable())
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
|
||||
if (desc.hasValue()) {
|
||||
bool same;
|
||||
if (!SameValue(cx, desc.value(), v, &same))
|
||||
return false;
|
||||
if (!same)
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,7 +685,7 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
|
||||
if (!SameValue(cx, desc.setterValue(), setter, &same))
|
||||
return false;
|
||||
if (!same)
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
|
||||
}
|
||||
|
||||
if (desc.hasGet()) {
|
||||
@@ -663,7 +694,7 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
|
||||
if (!SameValue(cx, desc.getterValue(), getter, &same))
|
||||
return false;
|
||||
if (!same)
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -728,6 +759,8 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
|
||||
}
|
||||
}
|
||||
|
||||
*rval = true;
|
||||
|
||||
/*
|
||||
* Since "data" properties implemented using native C functions may rely on
|
||||
* side effects during setting, we must make them aware that they have been
|
||||
@@ -738,18 +771,18 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
|
||||
* redefining it or we had invoked its setter to change its value).
|
||||
*/
|
||||
if (callDelProperty) {
|
||||
bool ignored;
|
||||
if (!CallJSDeletePropertyOp(cx, obj->getClass()->delProperty, obj, id, &ignored))
|
||||
bool succeeded;
|
||||
if (!CallJSDeletePropertyOp(cx, obj->getClass()->delProperty, obj, id, &succeeded))
|
||||
return false;
|
||||
}
|
||||
|
||||
return NativeDefineProperty(cx, obj, id, v, getter, setter, attrs, result);
|
||||
return NativeDefineProperty(cx, obj, id, v, getter, setter, attrs);
|
||||
}
|
||||
|
||||
/* ES6 20130308 draft 8.4.2.1 [[DefineOwnProperty]] */
|
||||
static bool
|
||||
DefinePropertyOnArray(JSContext* cx, Handle<ArrayObject*> arr, HandleId id, const PropDesc& desc,
|
||||
ObjectOpResult &result)
|
||||
bool throwError, bool* rval)
|
||||
{
|
||||
/* Step 2. */
|
||||
if (id == NameToId(cx->names().length)) {
|
||||
@@ -771,23 +804,23 @@ DefinePropertyOnArray(JSContext* cx, Handle<ArrayObject*> arr, HandleId id, cons
|
||||
}
|
||||
|
||||
if (desc.hasConfigurable() && desc.configurable())
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
|
||||
if (desc.hasEnumerable() && desc.enumerable())
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
|
||||
|
||||
if (desc.isAccessorDescriptor())
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
|
||||
|
||||
unsigned attrs = arr->lookup(cx, id)->attributes();
|
||||
if (!arr->lengthIsWritable()) {
|
||||
if (desc.hasWritable() && desc.writable())
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
|
||||
} else {
|
||||
if (desc.hasWritable() && !desc.writable())
|
||||
attrs = attrs | JSPROP_READONLY;
|
||||
}
|
||||
|
||||
return ArraySetLength(cx, arr, id, attrs, v, result);
|
||||
return ArraySetLength(cx, arr, id, attrs, v, throwError);
|
||||
}
|
||||
|
||||
/* Step 3. */
|
||||
@@ -798,21 +831,22 @@ DefinePropertyOnArray(JSContext* cx, Handle<ArrayObject*> arr, HandleId id, cons
|
||||
|
||||
/* Steps 3a, 3e. */
|
||||
if (index >= oldLen && !arr->lengthIsWritable())
|
||||
return result.fail(JSMSG_CANT_APPEND_TO_ARRAY);
|
||||
return Reject(cx, arr, JSMSG_CANT_APPEND_TO_ARRAY, throwError, rval);
|
||||
|
||||
/* Steps 3f-j. */
|
||||
return DefinePropertyOnObject(cx, arr, id, desc, result);
|
||||
return DefinePropertyOnObject(cx, arr, id, desc, throwError, rval);
|
||||
}
|
||||
|
||||
/* Step 4. */
|
||||
return DefinePropertyOnObject(cx, arr, id, desc, result);
|
||||
return DefinePropertyOnObject(cx, arr, id, desc, throwError, rval);
|
||||
}
|
||||
|
||||
// ES6 draft rev31 9.4.5.3 [[DefineOwnProperty]]
|
||||
static bool
|
||||
DefinePropertyOnTypedArray(JSContext* cx, HandleObject obj, HandleId id, const PropDesc& desc,
|
||||
ObjectOpResult &result)
|
||||
bool throwError, bool* rval)
|
||||
{
|
||||
|
||||
MOZ_ASSERT(IsAnyTypedArray(obj));
|
||||
// Steps 3.a-c.
|
||||
uint64_t index;
|
||||
@@ -820,24 +854,26 @@ DefinePropertyOnTypedArray(JSContext* cx, HandleObject obj, HandleId id, const P
|
||||
// These are all substeps of 3.c.
|
||||
// Steps i-vi.
|
||||
// We (wrongly) ignore out of range defines with a value.
|
||||
if (index >= AnyTypedArrayLength(obj))
|
||||
return result.succeed();
|
||||
if (index >= AnyTypedArrayLength(obj)) {
|
||||
*rval = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step vii.
|
||||
if (desc.isAccessorDescriptor())
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
|
||||
|
||||
// Step viii.
|
||||
if (desc.hasConfigurable() && desc.configurable())
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
|
||||
|
||||
// Step ix.
|
||||
if (desc.hasEnumerable() && !desc.enumerable())
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
|
||||
|
||||
// Step x.
|
||||
if (desc.hasWritable() && !desc.writable())
|
||||
return result.fail(JSMSG_CANT_REDEFINE_PROP);
|
||||
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
|
||||
|
||||
// Step xi.
|
||||
if (desc.hasValue()) {
|
||||
@@ -852,24 +888,25 @@ DefinePropertyOnTypedArray(JSContext* cx, HandleObject obj, HandleId id, const P
|
||||
}
|
||||
|
||||
// Step xii.
|
||||
return result.succeed();
|
||||
*rval = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, result);
|
||||
return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, throwError, rval);
|
||||
}
|
||||
|
||||
bool
|
||||
js::StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id, const PropDesc& desc,
|
||||
ObjectOpResult &result)
|
||||
bool throwError, bool* rval)
|
||||
{
|
||||
if (obj->is<ArrayObject>()) {
|
||||
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
|
||||
return DefinePropertyOnArray(cx, arr, id, desc, result);
|
||||
return DefinePropertyOnArray(cx, arr, id, desc, throwError, rval);
|
||||
}
|
||||
|
||||
if (IsAnyTypedArray(obj))
|
||||
return DefinePropertyOnTypedArray(cx, obj, id, desc, result);
|
||||
return DefinePropertyOnTypedArray(cx, obj, id, desc, throwError, rval);
|
||||
|
||||
if (obj->is<UnboxedPlainObject>() && !UnboxedPlainObject::convertToNative(cx, obj))
|
||||
return false;
|
||||
@@ -879,38 +916,21 @@ js::StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id, const P
|
||||
Rooted<PropertyDescriptor> pd(cx);
|
||||
desc.populatePropertyDescriptor(obj, &pd);
|
||||
pd.object().set(obj);
|
||||
return Proxy::defineProperty(cx, obj, id, &pd, result);
|
||||
return Proxy::defineProperty(cx, obj, id, &pd);
|
||||
}
|
||||
return result.fail(JSMSG_OBJECT_NOT_EXTENSIBLE);
|
||||
return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
|
||||
}
|
||||
|
||||
return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, result);
|
||||
return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, throwError, rval);
|
||||
}
|
||||
|
||||
bool
|
||||
js::StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
Handle<PropertyDescriptor> descriptor, ObjectOpResult &result)
|
||||
Handle<PropertyDescriptor> descriptor, bool* bp)
|
||||
{
|
||||
Rooted<PropDesc> desc(cx);
|
||||
desc.initFromPropertyDescriptor(descriptor);
|
||||
return StandardDefineProperty(cx, obj, id, desc, result);
|
||||
}
|
||||
|
||||
bool
|
||||
js::StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc)
|
||||
{
|
||||
ObjectOpResult success;
|
||||
return StandardDefineProperty(cx, obj, id, desc, success) &&
|
||||
success.checkStrict(cx, obj, id);
|
||||
}
|
||||
|
||||
bool
|
||||
js::StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id,
|
||||
Handle<PropertyDescriptor> desc)
|
||||
{
|
||||
ObjectOpResult success;
|
||||
return StandardDefineProperty(cx, obj, id, desc, success) &&
|
||||
success.checkStrict(cx, obj, id);
|
||||
return StandardDefineProperty(cx, obj, id, desc, true, bp);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -943,8 +963,9 @@ js::DefineProperties(JSContext* cx, HandleObject obj, HandleObject props)
|
||||
if (!ReadPropertyDescriptors(cx, props, true, &ids, &descs))
|
||||
return false;
|
||||
|
||||
bool dummy;
|
||||
for (size_t i = 0, len = ids.length(); i < len; i++) {
|
||||
if (!StandardDefineProperty(cx, obj, ids[i], descs[i]))
|
||||
if (!StandardDefineProperty(cx, obj, ids[i], descs[i], true, &dummy))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1062,7 +1083,8 @@ js::SetIntegrityLevel(JSContext* cx, HandleObject obj, IntegrityLevel level)
|
||||
desc.object().set(obj);
|
||||
|
||||
// 8.a.i-ii. / 9.a.iii.3-4
|
||||
if (!StandardDefineProperty(cx, obj, id, desc))
|
||||
bool result;
|
||||
if (!StandardDefineProperty(cx, obj, id, desc, &result))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1654,24 +1676,24 @@ js::CreateThisForFunction(JSContext* cx, HandleObject callee, NewObjectKind newK
|
||||
|
||||
/* static */ bool
|
||||
JSObject::nonNativeSetProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp, ObjectOpResult &result)
|
||||
HandleId id, MutableHandleValue vp, bool strict)
|
||||
{
|
||||
if (MOZ_UNLIKELY(obj->watched())) {
|
||||
WatchpointMap* wpmap = cx->compartment()->watchpointMap;
|
||||
if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
|
||||
return false;
|
||||
}
|
||||
return obj->getOps()->setProperty(cx, obj, receiver, id, vp, result);
|
||||
return obj->getOps()->setProperty(cx, obj, receiver, id, vp, strict);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
JSObject::nonNativeSetElement(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp, ObjectOpResult &result)
|
||||
uint32_t index, MutableHandleValue vp, bool strict)
|
||||
{
|
||||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return nonNativeSetProperty(cx, obj, receiver, id, vp, result);
|
||||
return nonNativeSetProperty(cx, obj, receiver, id, vp, strict);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
@@ -1702,7 +1724,8 @@ JS_CopyPropertyFrom(JSContext* cx, HandleId id, HandleObject target,
|
||||
if (!cx->compartment()->wrap(cx, &desc))
|
||||
return false;
|
||||
|
||||
return StandardDefineProperty(cx, target, wrappedId, desc);
|
||||
bool ignored;
|
||||
return StandardDefineProperty(cx, target, wrappedId, desc, &ignored);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
@@ -1751,7 +1774,7 @@ CopyProxyObject(JSContext* cx, Handle<ProxyObject*> from, Handle<ProxyObject*> t
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto)
|
||||
js::CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto, HandleObject parent)
|
||||
{
|
||||
if (!obj->isNative() && !obj->is<ProxyObject>()) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
|
||||
@@ -1761,7 +1784,7 @@ js::CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto)
|
||||
|
||||
RootedObject clone(cx);
|
||||
if (obj->isNative()) {
|
||||
clone = NewObjectWithGivenTaggedProto(cx, obj->getClass(), proto, NullPtr());
|
||||
clone = NewObjectWithGivenTaggedProto(cx, obj->getClass(), proto, parent);
|
||||
if (!clone)
|
||||
return nullptr;
|
||||
|
||||
@@ -1777,7 +1800,7 @@ js::CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto)
|
||||
ProxyOptions options;
|
||||
options.setClass(obj->getClass());
|
||||
|
||||
clone = ProxyObject::New(cx, GetProxyHandler(obj), JS::NullHandleValue, proto, options);
|
||||
clone = ProxyObject::New(cx, GetProxyHandler(obj), JS::NullHandleValue, proto, parent, options);
|
||||
if (!clone)
|
||||
return nullptr;
|
||||
|
||||
@@ -2965,7 +2988,7 @@ js::LookupPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSObject**
|
||||
do {
|
||||
const Class* clasp = obj->getClass();
|
||||
if (!clasp->resolve)
|
||||
break;
|
||||
break;
|
||||
if (clasp->resolve == fun_resolve && !FunctionHasResolveHook(cx->names(), id))
|
||||
break;
|
||||
if (clasp->resolve == str_resolve && !JSID_IS_INT(id))
|
||||
@@ -3183,8 +3206,7 @@ js::GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
|
||||
|
||||
bool
|
||||
js::DefineProperty(ExclusiveContext* cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs,
|
||||
ObjectOpResult &result)
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
|
||||
{
|
||||
MOZ_ASSERT(getter != JS_PropertyStub);
|
||||
MOZ_ASSERT(setter != JS_StrictPropertyStub);
|
||||
@@ -3194,54 +3216,15 @@ js::DefineProperty(ExclusiveContext* cx, HandleObject obj, HandleId id, HandleVa
|
||||
if (op) {
|
||||
if (!cx->shouldBeJSContext())
|
||||
return false;
|
||||
return op(cx->asJSContext(), obj, id, value, getter, setter, attrs, result);
|
||||
return op(cx->asJSContext(), obj, id, value, getter, setter, attrs);
|
||||
}
|
||||
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, value, getter, setter, attrs,
|
||||
result);
|
||||
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, value, getter, setter, attrs);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs,
|
||||
ObjectOpResult &result)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return DefineProperty(cx, obj, id, value, getter, setter, attrs, result);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineElement(ExclusiveContext *cx, HandleObject obj, uint32_t index, HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs,
|
||||
ObjectOpResult &result)
|
||||
{
|
||||
MOZ_ASSERT(getter != JS_PropertyStub);
|
||||
MOZ_ASSERT(setter != JS_StrictPropertyStub);
|
||||
|
||||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return DefineProperty(cx, obj, id, value, getter, setter, attrs, result);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
|
||||
{
|
||||
ObjectOpResult result;
|
||||
if (!DefineProperty(cx, obj, id, value, getter, setter, attrs, result))
|
||||
return false;
|
||||
if (!result) {
|
||||
if (!cx->shouldBeJSContext())
|
||||
return false;
|
||||
result.reportError(cx->asJSContext(), obj, id);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
|
||||
js::DefineProperty(ExclusiveContext* cx, HandleObject obj,
|
||||
PropertyName* name, HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return DefineProperty(cx, obj, id, value, getter, setter, attrs);
|
||||
@@ -3249,7 +3232,7 @@ js::DefineProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, H
|
||||
|
||||
bool
|
||||
js::DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
|
||||
{
|
||||
MOZ_ASSERT(getter != JS_PropertyStub);
|
||||
MOZ_ASSERT(setter != JS_StrictPropertyStub);
|
||||
@@ -3260,22 +3243,6 @@ js::DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, Handle
|
||||
return DefineProperty(cx, obj, id, value, getter, setter, attrs);
|
||||
}
|
||||
|
||||
bool
|
||||
js::SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return SetProperty(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::PutProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue value,
|
||||
bool strict)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return PutProperty(cx, obj, id, value, strict);
|
||||
}
|
||||
|
||||
|
||||
/*** SpiderMonkey nonstandard internal methods ***************************************************/
|
||||
|
||||
@@ -3707,7 +3674,7 @@ js::ReportGetterOnlyAssignment(JSContext* cx, bool strict)
|
||||
|
||||
/*
|
||||
* Routines to print out values during debugging. These are FRIEND_API to help
|
||||
* the debugger find them and to support temporarily hacking js::Dump* calls
|
||||
* the debugger find them and to support temporarily hacking js_Dump* calls
|
||||
* into other code.
|
||||
*/
|
||||
|
||||
@@ -3770,14 +3737,14 @@ dumpValue(const Value& v)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::DumpValue(const Value &val)
|
||||
js_DumpValue(const Value& val)
|
||||
{
|
||||
dumpValue(val);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::DumpId(jsid id)
|
||||
js_DumpId(jsid id)
|
||||
{
|
||||
fprintf(stderr, "jsid %p = ", (void*) JSID_BITS(id));
|
||||
dumpValue(IdToValue(id));
|
||||
@@ -3941,7 +3908,7 @@ MaybeDumpValue(const char* name, const Value& v)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::DumpInterpreterFrame(JSContext *cx, InterpreterFrame *start)
|
||||
js_DumpInterpreterFrame(JSContext* cx, InterpreterFrame* start)
|
||||
{
|
||||
/* This should only called during live debugging. */
|
||||
ScriptFrameIter i(cx, ScriptFrameIter::GO_THROUGH_SAVED);
|
||||
@@ -4011,7 +3978,7 @@ js::DumpInterpreterFrame(JSContext *cx, InterpreterFrame *start)
|
||||
#endif /* DEBUG */
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::DumpBacktrace(JSContext *cx)
|
||||
js_DumpBacktrace(JSContext* cx)
|
||||
{
|
||||
Sprinter sprinter(cx);
|
||||
sprinter.init();
|
||||
@@ -4087,6 +4054,29 @@ JSObject::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ClassIn
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
JSObject::hasIdempotentProtoChain() const
|
||||
{
|
||||
// Return false if obj (or an object on its proto chain) is non-native or
|
||||
// has a resolve or lookup hook.
|
||||
JSObject* obj = const_cast<JSObject*>(this);
|
||||
while (true) {
|
||||
if (!obj->isNative())
|
||||
return false;
|
||||
|
||||
JSResolveOp resolve = obj->getClass()->resolve;
|
||||
if (resolve && resolve != js::fun_resolve && resolve != js::str_resolve)
|
||||
return false;
|
||||
|
||||
if (obj->getOps()->lookupProperty)
|
||||
return false;
|
||||
|
||||
obj = obj->getProto();
|
||||
if (!obj)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSObject::markChildren(JSTracer* trc)
|
||||
{
|
||||
|
||||
+12
-67
@@ -313,6 +313,8 @@ class JSObject : public js::gc::Cell
|
||||
|
||||
void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ClassInfo* info);
|
||||
|
||||
bool hasIdempotentProtoChain() const;
|
||||
|
||||
/*
|
||||
* Marks this object as having a singleton type, and leave the group lazy.
|
||||
* Constructs a new, unique shape for the object.
|
||||
@@ -519,10 +521,10 @@ class JSObject : public js::gc::Cell
|
||||
|
||||
static bool nonNativeSetProperty(JSContext* cx, js::HandleObject obj,
|
||||
js::HandleObject receiver, js::HandleId id,
|
||||
js::MutableHandleValue vp, JS::ObjectOpResult &result);
|
||||
js::MutableHandleValue vp, bool strict);
|
||||
static bool nonNativeSetElement(JSContext* cx, js::HandleObject obj,
|
||||
js::HandleObject receiver, uint32_t index,
|
||||
js::MutableHandleValue vp, JS::ObjectOpResult &result);
|
||||
js::MutableHandleValue vp, bool strict);
|
||||
|
||||
static bool swap(JSContext* cx, JS::HandleObject a, JS::HandleObject b);
|
||||
|
||||
@@ -787,40 +789,13 @@ GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
|
||||
* the DefineProperty functions do not enforce some invariants mandated by ES6.
|
||||
*/
|
||||
extern bool
|
||||
StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc,
|
||||
ObjectOpResult &result);
|
||||
StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
const PropDesc& desc, bool throwError, bool* rval);
|
||||
|
||||
extern bool
|
||||
StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
Handle<PropertyDescriptor> descriptor, ObjectOpResult &result);
|
||||
Handle<PropertyDescriptor> descriptor, bool* bp);
|
||||
|
||||
/*
|
||||
* For convenience, signatures identical to the above except without the
|
||||
* ObjectOpResult out-parameter. They throw a TypeError on failure.
|
||||
*/
|
||||
extern bool
|
||||
StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc);
|
||||
|
||||
extern bool
|
||||
StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
Handle<PropertyDescriptor> desc);
|
||||
|
||||
extern bool
|
||||
DefineProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp, unsigned attrs, ObjectOpResult &result);
|
||||
|
||||
extern bool
|
||||
DefineProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp, unsigned attrs, ObjectOpResult &result);
|
||||
|
||||
extern bool
|
||||
DefineElement(ExclusiveContext *cx, HandleObject obj, uint32_t index, HandleValue value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp, unsigned attrs, ObjectOpResult &result);
|
||||
|
||||
/*
|
||||
* When the 'result' out-param is omitted, the behavior is the same as above, except
|
||||
* that any failure results in a TypeError.
|
||||
*/
|
||||
extern bool
|
||||
DefineProperty(ExclusiveContext* cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
JSPropertyOp getter = nullptr,
|
||||
@@ -903,49 +878,19 @@ GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t index,
|
||||
*/
|
||||
inline bool
|
||||
SetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp, ObjectOpResult &result);
|
||||
MutableHandleValue vp, bool strict);
|
||||
|
||||
inline bool
|
||||
SetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, PropertyName* name,
|
||||
MutableHandleValue vp, ObjectOpResult &result)
|
||||
MutableHandleValue vp, bool strict)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return SetProperty(cx, obj, receiver, id, vp, result);
|
||||
return SetProperty(cx, obj, receiver, id, vp, strict);
|
||||
}
|
||||
|
||||
inline bool
|
||||
SetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index,
|
||||
MutableHandleValue vp, ObjectOpResult &result);
|
||||
|
||||
inline bool
|
||||
SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
ObjectOpResult result;
|
||||
return SetProperty(cx, obj, receiver, id, vp, result) &&
|
||||
result.checkStrict(cx, receiver, id);
|
||||
}
|
||||
|
||||
extern bool
|
||||
SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name,
|
||||
MutableHandleValue vp);
|
||||
|
||||
/*
|
||||
* ES6 draft rev 31 (15 Jan 2015) 7.3.3 Put (O, P, V, Throw), except that on
|
||||
* success, the spec says this is supposed to return a boolean value, which we
|
||||
* don't bother doing.
|
||||
*/
|
||||
inline bool
|
||||
PutProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue value, bool strict)
|
||||
{
|
||||
ObjectOpResult result;
|
||||
return SetProperty(cx, obj, obj, id, value, result) &&
|
||||
result.checkStrictErrorOrWarning(cx, obj, id, strict);
|
||||
}
|
||||
|
||||
extern bool
|
||||
PutProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue value,
|
||||
bool strict);
|
||||
MutableHandleValue vp, bool strict);
|
||||
|
||||
/*
|
||||
* ES6 [[Delete]]. Equivalent to the JS code `delete obj[id]`.
|
||||
@@ -1195,7 +1140,7 @@ extern JSObject*
|
||||
CreateThis(JSContext* cx, const js::Class* clasp, js::HandleObject callee);
|
||||
|
||||
extern JSObject*
|
||||
CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto);
|
||||
CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto, HandleObject parent);
|
||||
|
||||
extern NativeObject*
|
||||
DeepCloneObjectLiteral(JSContext* cx, HandleNativeObject obj, NewObjectKind newKind = GenericObject);
|
||||
|
||||
+23
-54
@@ -797,37 +797,6 @@ js::Disassemble(JSContext* cx, HandleScript script, bool lines, Sprinter* sp)
|
||||
return DisassembleAtPC(cx, script, lines, nullptr, false, sp);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js::DumpPC(JSContext *cx)
|
||||
{
|
||||
gc::AutoSuppressGC suppressGC(cx);
|
||||
Sprinter sprinter(cx);
|
||||
if (!sprinter.init())
|
||||
return false;
|
||||
ScriptFrameIter iter(cx);
|
||||
if (iter.done()) {
|
||||
fprintf(stdout, "Empty stack.\n");
|
||||
return true;
|
||||
}
|
||||
RootedScript script(cx, iter.script());
|
||||
bool ok = DisassembleAtPC(cx, script, true, iter.pc(), false, &sprinter);
|
||||
fprintf(stdout, "%s", sprinter.string());
|
||||
return ok;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js::DumpScript(JSContext *cx, JSScript *scriptArg)
|
||||
{
|
||||
gc::AutoSuppressGC suppressGC(cx);
|
||||
Sprinter sprinter(cx);
|
||||
if (!sprinter.init())
|
||||
return false;
|
||||
RootedScript script(cx, scriptArg);
|
||||
bool ok = Disassemble(cx, script, true, &sprinter);
|
||||
fprintf(stdout, "%s", sprinter.string());
|
||||
return ok;
|
||||
}
|
||||
|
||||
static char*
|
||||
QuoteString(Sprinter* sp, JSString* str, char16_t quote);
|
||||
|
||||
@@ -1594,31 +1563,31 @@ ExpressionDecompiler::decompilePC(jsbytecode* pc)
|
||||
write("(...)");
|
||||
case JSOP_NEWARRAY:
|
||||
return write("[]");
|
||||
case JSOP_REGEXP: {
|
||||
RootedObject obj(cx, script->getRegExp(GET_UINT32_INDEX(pc)));
|
||||
JSString* str = obj->as<RegExpObject>().toString(cx);
|
||||
if (!str)
|
||||
return false;
|
||||
return write(str);
|
||||
case JSOP_REGEXP: {
|
||||
RootedObject obj(cx, script->getRegExp(GET_UINT32_INDEX(pc)));
|
||||
JSString* str = obj->as<RegExpObject>().toString(cx);
|
||||
if (!str)
|
||||
return false;
|
||||
return write(str);
|
||||
}
|
||||
case JSOP_NEWARRAY_COPYONWRITE: {
|
||||
RootedObject obj(cx, script->getObject(GET_UINT32_INDEX(pc)));
|
||||
Handle<ArrayObject*> aobj = obj.as<ArrayObject>();
|
||||
if (!write("["))
|
||||
return false;
|
||||
for (size_t i = 0; i < aobj->getDenseInitializedLength(); i++) {
|
||||
if (i > 0 && !write(", "))
|
||||
return false;
|
||||
|
||||
RootedValue v(cx, aobj->getDenseElement(i));
|
||||
MOZ_RELEASE_ASSERT(v.isPrimitive() && !v.isMagic());
|
||||
|
||||
JSString* str = ValueToSource(cx, v);
|
||||
if (!str || !write(str))
|
||||
return false;
|
||||
}
|
||||
return write("]");
|
||||
}
|
||||
RootedObject obj(cx, script->getObject(GET_UINT32_INDEX(pc)));
|
||||
Handle<ArrayObject*> aobj = obj.as<ArrayObject>();
|
||||
if (!write("["))
|
||||
return false;
|
||||
for (size_t i = 0; i < aobj->getDenseInitializedLength(); i++) {
|
||||
if (i > 0 && !write(", "))
|
||||
return false;
|
||||
|
||||
RootedValue v(cx, aobj->getDenseElement(i));
|
||||
MOZ_RELEASE_ASSERT(v.isPrimitive() && !v.isMagic());
|
||||
|
||||
JSString* str = ValueToSource(cx, v);
|
||||
if (!str || !write(str))
|
||||
return false;
|
||||
}
|
||||
return write("]");
|
||||
}
|
||||
case JSOP_OBJECT: {
|
||||
JSObject* obj = script->getObject(GET_UINT32_INDEX(pc));
|
||||
RootedValue objv(cx, ObjectValue(*obj));
|
||||
|
||||
+2
-2
@@ -452,7 +452,7 @@ class SrcNoteLineScanner
|
||||
*/
|
||||
bool lineHeader;
|
||||
|
||||
public:
|
||||
public:
|
||||
SrcNoteLineScanner(jssrcnote* sn, uint32_t lineno)
|
||||
: offset(0), sn(sn), lineno(lineno)
|
||||
{
|
||||
@@ -491,7 +491,7 @@ class SrcNoteLineScanner
|
||||
SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
|
||||
if (type == SRC_SETLINE || type == SRC_NEWLINE) {
|
||||
if (type == SRC_SETLINE)
|
||||
lineno = GetSrcNoteOffset(sn, 0);
|
||||
lineno = js_GetSrcNoteOffset(sn, 0);
|
||||
else
|
||||
lineno++;
|
||||
|
||||
|
||||
@@ -742,7 +742,7 @@ NodeBuilder::newArray(NodeVector& elts, MutableHandleValue dst)
|
||||
if (val.isMagic(JS_SERIALIZE_NO_NODE))
|
||||
continue;
|
||||
|
||||
if (!DefineElement(cx, array, i, val))
|
||||
if (!SetElement(cx, array, array, i, &val, false))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -2806,7 +2806,7 @@ js::PCToLineNumber(unsigned startLine, jssrcnote* notes, jsbytecode* code, jsbyt
|
||||
SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
|
||||
if (type == SRC_SETLINE) {
|
||||
if (offset <= target)
|
||||
lineno = unsigned(GetSrcNoteOffset(sn, 0));
|
||||
lineno = (unsigned) js_GetSrcNoteOffset(sn, 0);
|
||||
column = 0;
|
||||
} else if (type == SRC_NEWLINE) {
|
||||
if (offset <= target)
|
||||
@@ -2818,7 +2818,7 @@ js::PCToLineNumber(unsigned startLine, jssrcnote* notes, jsbytecode* code, jsbyt
|
||||
break;
|
||||
|
||||
if (type == SRC_COLSPAN) {
|
||||
ptrdiff_t colspan = SN_OFFSET_TO_COLSPAN(GetSrcNoteOffset(sn, 0));
|
||||
ptrdiff_t colspan = SN_OFFSET_TO_COLSPAN(js_GetSrcNoteOffset(sn, 0));
|
||||
MOZ_ASSERT(ptrdiff_t(column) + colspan >= 0);
|
||||
column += colspan;
|
||||
}
|
||||
@@ -2864,7 +2864,7 @@ js::LineNumberToPC(JSScript* script, unsigned target)
|
||||
offset += SN_DELTA(sn);
|
||||
SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
|
||||
if (type == SRC_SETLINE) {
|
||||
lineno = unsigned(GetSrcNoteOffset(sn, 0));
|
||||
lineno = (unsigned) js_GetSrcNoteOffset(sn, 0);
|
||||
} else if (type == SRC_NEWLINE) {
|
||||
lineno++;
|
||||
}
|
||||
@@ -2883,7 +2883,7 @@ js::GetScriptLineExtent(JSScript* script)
|
||||
for (jssrcnote* sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
|
||||
SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
|
||||
if (type == SRC_SETLINE)
|
||||
lineno = unsigned(GetSrcNoteOffset(sn, 0));
|
||||
lineno = (unsigned) js_GetSrcNoteOffset(sn, 0);
|
||||
else if (type == SRC_NEWLINE)
|
||||
lineno++;
|
||||
|
||||
|
||||
+1
-1
@@ -2175,7 +2175,7 @@ class MOZ_STACK_CLASS StringRegExpGuard
|
||||
|
||||
// Handle everything else generically (including throwing if .lastIndex is non-writable).
|
||||
RootedValue zero(cx, Int32Value(0));
|
||||
return SetProperty(cx, obj_, obj_, cx->names().lastIndex, &zero);
|
||||
return SetProperty(cx, obj_, obj_, cx->names().lastIndex, &zero, true);
|
||||
}
|
||||
|
||||
RegExpShared& regExp() { return *re_; }
|
||||
|
||||
+7
-8
@@ -69,7 +69,7 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
|
||||
virtual bool defaultValue(JSContext* cx, HandleObject obj, JSType hint,
|
||||
MutableHandleValue vp) const override;
|
||||
|
||||
static JSObject* New(JSContext* cx, JSObject* obj, const Wrapper* handler,
|
||||
static JSObject* New(JSContext* cx, JSObject* obj, JSObject* parent, const Wrapper* handler,
|
||||
const WrapperOptions& options = WrapperOptions());
|
||||
|
||||
static JSObject* Renew(JSContext* cx, JSObject* existing, JSObject* obj, const Wrapper* handler);
|
||||
@@ -117,8 +117,7 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
|
||||
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc) const override;
|
||||
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc,
|
||||
ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
MutableHandle<JSPropertyDescriptor> desc) const override;
|
||||
virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
|
||||
AutoIdVector& props) const override;
|
||||
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
|
||||
@@ -135,8 +134,8 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
|
||||
virtual bool has(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
|
||||
virtual bool get(JSContext* cx, HandleObject wrapper, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp) const override;
|
||||
virtual bool set(JSContext *cx, HandleObject wrapper, HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp, ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
virtual bool set(JSContext* cx, HandleObject wrapper, HandleObject receiver,
|
||||
HandleId id, bool strict, MutableHandleValue vp) const override;
|
||||
virtual bool call(JSContext* cx, HandleObject wrapper, const CallArgs& args) const override;
|
||||
virtual bool construct(JSContext* cx, HandleObject wrapper, const CallArgs& args) const override;
|
||||
|
||||
@@ -183,8 +182,7 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
|
||||
bool* bp) const override;
|
||||
|
||||
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc,
|
||||
ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
MutableHandle<JSPropertyDescriptor> desc) const override;
|
||||
virtual bool isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const override;
|
||||
virtual bool preventExtensions(JSContext* cx, HandleObject wrapper, bool* succeeded) const override;
|
||||
virtual bool setPrototypeOf(JSContext* cx, HandleObject proxy, HandleObject proto,
|
||||
@@ -219,7 +217,8 @@ typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
|
||||
typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
|
||||
|
||||
extern JSObject*
|
||||
TransparentObjectWrapper(JSContext* cx, HandleObject existing, HandleObject obj);
|
||||
TransparentObjectWrapper(JSContext* cx, HandleObject existing, HandleObject obj,
|
||||
HandleObject parent);
|
||||
|
||||
inline bool
|
||||
IsWrapper(JSObject* obj)
|
||||
|
||||
@@ -73,7 +73,7 @@ BaseProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
|
||||
bool
|
||||
BaseProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
|
||||
HandleId id, bool strict, MutableHandleValue vp) const
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id, SET);
|
||||
|
||||
@@ -94,7 +94,7 @@ BaseProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
if (!GetPrototype(cx, proxy, &proto))
|
||||
return false;
|
||||
if (proto)
|
||||
return SetProperty(cx, proto, receiver, id, vp, result);
|
||||
return SetProperty(cx, proto, receiver, id, vp, strict);
|
||||
|
||||
// Change ownDesc to be a complete descriptor for a configurable,
|
||||
// writable, enumerable data property. Then fall through to step 5.
|
||||
@@ -106,14 +106,19 @@ BaseProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
if (ownDesc.isDataDescriptor()) {
|
||||
// Steps 5.a-b, adapted to our nonstandard implementation of ES6
|
||||
// [[Set]] return values.
|
||||
if (!ownDesc.isWritable())
|
||||
return result.fail(JSMSG_READ_ONLY);
|
||||
if (!ownDesc.isWritable()) {
|
||||
if (strict)
|
||||
return JSObject::reportReadOnly(cx, id, JSREPORT_ERROR);
|
||||
if (cx->compartment()->options().extraWarnings(cx))
|
||||
return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nonstandard SpiderMonkey special case: setter ops.
|
||||
StrictPropertyOp setter = ownDesc.setter();
|
||||
MOZ_ASSERT(setter != JS_StrictPropertyStub);
|
||||
if (setter && setter != JS_StrictPropertyStub)
|
||||
return CallSetter(cx, receiver, id, setter, ownDesc.attributes(), vp, result);
|
||||
return CallSetter(cx, receiver, id, setter, ownDesc.attributes(), strict, vp);
|
||||
|
||||
// Steps 5.c-d. Adapt for SpiderMonkey by using HasOwnProperty instead
|
||||
// of the standard [[GetOwnProperty]].
|
||||
@@ -132,8 +137,8 @@ BaseProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
const Class* clasp = receiver->getClass();
|
||||
MOZ_ASSERT(clasp->getProperty != JS_PropertyStub);
|
||||
MOZ_ASSERT(clasp->setProperty != JS_StrictPropertyStub);
|
||||
return DefineProperty(cx, receiver, id, vp, clasp->getProperty, clasp->setProperty,
|
||||
attrs, result);
|
||||
return DefineProperty(cx, receiver, id, vp,
|
||||
clasp->getProperty, clasp->setProperty, attrs);
|
||||
}
|
||||
|
||||
// Step 6.
|
||||
@@ -142,18 +147,16 @@ BaseProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
if (ownDesc.hasSetterObject())
|
||||
setter = ownDesc.setterObject();
|
||||
if (!setter)
|
||||
return result.fail(JSMSG_GETTER_ONLY);
|
||||
return ReportGetterOnlyAssignment(cx, strict);
|
||||
RootedValue setterValue(cx, ObjectValue(*setter));
|
||||
if (!InvokeGetterOrSetter(cx, receiver, setterValue, 1, vp.address(), vp))
|
||||
return false;
|
||||
return result.succeed();
|
||||
return InvokeGetterOrSetter(cx, receiver, setterValue, 1, vp.address(), vp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::SetPropertyIgnoringNamedGetter(JSContext* cx, const BaseProxyHandler* handler,
|
||||
HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandle<PropertyDescriptor> desc,
|
||||
bool descIsOwn, MutableHandleValue vp, ObjectOpResult &result)
|
||||
bool descIsOwn, bool strict, MutableHandleValue vp)
|
||||
{
|
||||
/* The control-flow here differs from ::get() because of the fall-through case below. */
|
||||
MOZ_ASSERT_IF(descIsOwn, desc.object());
|
||||
@@ -162,37 +165,35 @@ js::SetPropertyIgnoringNamedGetter(JSContext* cx, const BaseProxyHandler* handle
|
||||
MOZ_ASSERT(desc.setter() != JS_StrictPropertyStub);
|
||||
|
||||
// Check for read-only properties.
|
||||
if (desc.isReadonly())
|
||||
return result.fail(descIsOwn ? JSMSG_READ_ONLY : JSMSG_CANT_REDEFINE_PROP);
|
||||
if (desc.isReadonly()) {
|
||||
if (strict)
|
||||
return Throw(cx, id, descIsOwn ? JSMSG_READ_ONLY : JSMSG_CANT_REDEFINE_PROP);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (desc.hasSetterObject() || desc.setter()) {
|
||||
if (!CallSetter(cx, receiver, id, desc.setter(), desc.attributes(), vp, result))
|
||||
if (!CallSetter(cx, receiver, id, desc.setter(), desc.attributes(), strict, vp))
|
||||
return false;
|
||||
if (!result)
|
||||
if (!proxy->is<ProxyObject>() || proxy->as<ProxyObject>().handler() != handler)
|
||||
return true;
|
||||
if (desc.isShared())
|
||||
return true;
|
||||
if (!proxy->is<ProxyObject>() ||
|
||||
proxy->as<ProxyObject>().handler() != handler ||
|
||||
desc.isShared())
|
||||
{
|
||||
return result.succeed();
|
||||
}
|
||||
}
|
||||
desc.value().set(vp.get());
|
||||
|
||||
if (descIsOwn) {
|
||||
MOZ_ASSERT(desc.object() == proxy);
|
||||
return handler->defineProperty(cx, proxy, id, desc, result);
|
||||
return handler->defineProperty(cx, proxy, id, desc);
|
||||
}
|
||||
return DefineProperty(cx, receiver, id, desc.value(), desc.getter(), desc.setter(),
|
||||
desc.attributes(), result);
|
||||
return DefineProperty(cx, receiver, id, desc.value(),
|
||||
desc.getter(), desc.setter(), desc.attributes());
|
||||
}
|
||||
desc.object().set(receiver);
|
||||
desc.value().set(vp.get());
|
||||
desc.setAttributes(JSPROP_ENUMERATE);
|
||||
desc.setGetter(nullptr);
|
||||
desc.setSetter(nullptr); // Pick up the class getter/setter.
|
||||
return DefineProperty(cx, receiver, id, desc.value(), nullptr, nullptr, JSPROP_ENUMERATE,
|
||||
result);
|
||||
return DefineProperty(cx, receiver, id, desc.value(), nullptr, nullptr, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -49,13 +49,12 @@ CrossCompartmentWrapper::getOwnPropertyDescriptor(JSContext* cx, HandleObject wr
|
||||
|
||||
bool
|
||||
CrossCompartmentWrapper::defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc,
|
||||
ObjectOpResult &result) const
|
||||
MutableHandle<PropertyDescriptor> desc) const
|
||||
{
|
||||
Rooted<PropertyDescriptor> desc2(cx, desc);
|
||||
PIERCE(cx, wrapper,
|
||||
cx->compartment()->wrap(cx, &desc2),
|
||||
Wrapper::defineProperty(cx, wrapper, id, &desc2, result),
|
||||
Wrapper::defineProperty(cx, wrapper, id, &desc2),
|
||||
NOTHING);
|
||||
}
|
||||
|
||||
@@ -169,13 +168,13 @@ CrossCompartmentWrapper::get(JSContext* cx, HandleObject wrapper, HandleObject r
|
||||
|
||||
bool
|
||||
CrossCompartmentWrapper::set(JSContext* cx, HandleObject wrapper, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
|
||||
HandleId id, bool strict, MutableHandleValue vp) const
|
||||
{
|
||||
RootedObject receiverCopy(cx, receiver);
|
||||
PIERCE(cx, wrapper,
|
||||
cx->compartment()->wrap(cx, &receiverCopy) &&
|
||||
cx->compartment()->wrap(cx, vp),
|
||||
Wrapper::set(cx, wrapper, receiverCopy, id, vp, result),
|
||||
Wrapper::set(cx, wrapper, receiverCopy, id, strict, vp),
|
||||
NOTHING);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,7 @@ DeadObjectProxy::getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, H
|
||||
|
||||
bool
|
||||
DeadObjectProxy::defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc,
|
||||
ObjectOpResult &result) const
|
||||
MutableHandle<PropertyDescriptor> desc) const
|
||||
{
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
|
||||
@@ -22,8 +22,7 @@ class DeadObjectProxy : public BaseProxyHandler
|
||||
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc) const override;
|
||||
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc,
|
||||
ObjectOpResult &result) const MOZ_OVERRIDE;
|
||||
MutableHandle<JSPropertyDescriptor> desc) const override;
|
||||
virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
|
||||
AutoIdVector& props) const override;
|
||||
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
|
||||
|
||||
@@ -34,12 +34,12 @@ DirectProxyHandler::getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy,
|
||||
|
||||
bool
|
||||
DirectProxyHandler::defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc,
|
||||
ObjectOpResult &result) const
|
||||
MutableHandle<PropertyDescriptor> desc) const
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id, SET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return StandardDefineProperty(cx, target, id, desc, result);
|
||||
bool ignored;
|
||||
return StandardDefineProperty(cx, target, id, desc, &ignored);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -223,11 +223,11 @@ DirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject receiver
|
||||
|
||||
bool
|
||||
DirectProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
|
||||
HandleId id, bool strict, MutableHandleValue vp) const
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id, SET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return SetProperty(cx, target, receiver, id, vp, result);
|
||||
return SetProperty(cx, target, receiver, id, vp, strict);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
+17
-23
@@ -134,17 +134,14 @@ Proxy::getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
|
||||
bool
|
||||
Proxy::defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc, ObjectOpResult &result)
|
||||
MutableHandle<PropertyDescriptor> desc)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
const BaseProxyHandler* handler = proxy->as<ProxyObject>().handler();
|
||||
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true);
|
||||
if (!policy.allowed()) {
|
||||
if (!policy.returnValue())
|
||||
return false;
|
||||
return result.succeed();
|
||||
}
|
||||
return proxy->as<ProxyObject>().handler()->defineProperty(cx, proxy, id, desc, result);
|
||||
if (!policy.allowed())
|
||||
return policy.returnValue();
|
||||
return proxy->as<ProxyObject>().handler()->defineProperty(cx, proxy, id, desc);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -304,23 +301,20 @@ Proxy::callProp(JSContext* cx, HandleObject proxy, HandleObject receiver, Handle
|
||||
}
|
||||
|
||||
bool
|
||||
Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp, ObjectOpResult &result)
|
||||
Proxy::set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id, bool strict,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
const BaseProxyHandler* handler = proxy->as<ProxyObject>().handler();
|
||||
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true);
|
||||
if (!policy.allowed()) {
|
||||
if (!policy.returnValue())
|
||||
return false;
|
||||
return result.succeed();
|
||||
}
|
||||
if (!policy.allowed())
|
||||
return policy.returnValue();
|
||||
|
||||
// Special case. See the comment on BaseProxyHandler::mHasPrototype.
|
||||
if (handler->hasPrototype())
|
||||
return handler->BaseProxyHandler::set(cx, proxy, receiver, id, vp, result);
|
||||
return handler->BaseProxyHandler::set(cx, proxy, receiver, id, strict, vp);
|
||||
|
||||
return handler->set(cx, proxy, receiver, id, vp, result);
|
||||
return handler->set(cx, proxy, receiver, id, strict, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -557,8 +551,7 @@ js::proxy_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
|
||||
bool
|
||||
js::proxy_DefineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
|
||||
ObjectOpResult &result)
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
|
||||
{
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
desc.object().set(obj);
|
||||
@@ -566,7 +559,7 @@ js::proxy_DefineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleVal
|
||||
desc.setAttributes(attrs);
|
||||
desc.setGetter(getter);
|
||||
desc.setSetter(setter);
|
||||
return Proxy::defineProperty(cx, obj, id, &desc, result);
|
||||
return Proxy::defineProperty(cx, obj, id, &desc);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -584,9 +577,9 @@ js::proxy_GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, Ha
|
||||
|
||||
bool
|
||||
js::proxy_SetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp, ObjectOpResult &result)
|
||||
MutableHandleValue vp, bool strict)
|
||||
{
|
||||
return Proxy::set(cx, obj, receiver, id, vp, result);
|
||||
return Proxy::set(cx, obj, receiver, id, strict, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -735,14 +728,15 @@ const Class* const js::ProxyClassPtr = &js::ProxyObject::class_;
|
||||
|
||||
JS_FRIEND_API(JSObject*)
|
||||
js::NewProxyObject(JSContext* cx, const BaseProxyHandler* handler, HandleValue priv, JSObject* proto_,
|
||||
const ProxyOptions& options)
|
||||
JSObject* parent_, const ProxyOptions& options)
|
||||
{
|
||||
if (options.lazyProto()) {
|
||||
MOZ_ASSERT(!proto_);
|
||||
proto_ = TaggedProto::LazyProto;
|
||||
}
|
||||
|
||||
return ProxyObject::New(cx, handler, priv, TaggedProto(proto_), options);
|
||||
return ProxyObject::New(cx, handler, priv, TaggedProto(proto_), parent_,
|
||||
options);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -29,7 +29,7 @@ class Proxy
|
||||
static bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc);
|
||||
static bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc, ObjectOpResult &result);
|
||||
MutableHandle<JSPropertyDescriptor> desc);
|
||||
static bool ownPropertyKeys(JSContext* cx, HandleObject proxy, AutoIdVector& props);
|
||||
static bool delete_(JSContext* cx, HandleObject proxy, HandleId id, bool* bp);
|
||||
static bool enumerate(JSContext* cx, HandleObject proxy, MutableHandleObject objp);
|
||||
@@ -42,7 +42,7 @@ class Proxy
|
||||
static bool get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp);
|
||||
static bool set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp, ObjectOpResult &result);
|
||||
bool strict, MutableHandleValue vp);
|
||||
static bool call(JSContext* cx, HandleObject proxy, const CallArgs& args);
|
||||
static bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user