Bug 1338828 part 3 - Add CacheIR SetProp/SetElem stubs for unshadowed setter calls on DOM proxies. r=h4writer

This commit is contained in:
Jan de Mooij 2017-02-21 13:49:29 +01:00
Родитель 26b0ba2897
Коммит cb50efb0c8
2 изменённых файлов: 85 добавлений и 28 удалений

Просмотреть файл

@ -2165,9 +2165,36 @@ SetPropIRGenerator::trackNotAttached()
#endif
}
static bool
CanAttachSetter(JSContext* cx, jsbytecode* pc, HandleObject obj, HandleId id,
MutableHandleObject holder, MutableHandleShape propShape,
bool* isTemporarilyUnoptimizable)
{
// Don't attach a setter stub for ops like JSOP_INITELEM.
if (IsPropertyInitOp(JSOp(*pc)))
return false;
MOZ_ASSERT(IsPropertySetOp(JSOp(*pc)));
PropertyResult prop;
if (!LookupPropertyPure(cx, obj, id, holder.address(), &prop))
return false;
if (prop.isNonNativeProperty())
return false;
propShape.set(prop.maybeShape());
if (!IsCacheableSetPropCallScripted(obj, holder, propShape, isTemporarilyUnoptimizable) &&
!IsCacheableSetPropCallNative(obj, holder, propShape))
{
return false;
}
return true;
}
static void
EmitCallSetterResultNoGuards(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
Shape* shape, ObjOperandId objId, ValOperandId rhsId)
EmitCallSetterNoGuards(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
Shape* shape, ObjOperandId objId, ValOperandId rhsId)
{
if (IsCacheableSetPropCallNative(obj, holder, shape)) {
JSFunction* target = &shape->setterValue().toObject().as<JSFunction>();
@ -2189,30 +2216,15 @@ bool
SetPropIRGenerator::tryAttachSetter(HandleObject obj, ObjOperandId objId, HandleId id,
ValOperandId rhsId)
{
// Don't attach a setter stub for ops like JSOP_INITELEM.
if (IsPropertyInitOp(JSOp(*pc_)))
RootedObject holder(cx_);
RootedShape propShape(cx_);
if (!CanAttachSetter(cx_, pc_, obj, id, &holder, &propShape, isTemporarilyUnoptimizable_))
return false;
MOZ_ASSERT(IsPropertySetOp(JSOp(*pc_)));
PropertyResult prop;
JSObject* holder;
if (!LookupPropertyPure(cx_, obj, id, &holder, &prop))
return false;
if (prop.isNonNativeProperty())
return false;
Shape* shape = prop.maybeShape();
if (!IsCacheableSetPropCallScripted(obj, holder, shape, isTemporarilyUnoptimizable_) &&
!IsCacheableSetPropCallNative(obj, holder, shape))
{
return false;
}
maybeEmitIdGuard(id);
Maybe<ObjOperandId> expandoId;
TestMatchingReceiver(writer, obj, shape, objId, &expandoId);
TestMatchingReceiver(writer, obj, propShape, objId, &expandoId);
if (obj != holder) {
GeneratePrototypeGuards(writer, obj, holder, objId);
@ -2222,7 +2234,7 @@ SetPropIRGenerator::tryAttachSetter(HandleObject obj, ObjOperandId objId, Handle
writer.guardShape(holderId, holder->as<NativeObject>().lastProperty());
}
EmitCallSetterResultNoGuards(writer, obj, holder, shape, objId, rhsId);
EmitCallSetterNoGuards(writer, obj, holder, propShape, objId, rhsId);
trackAttached("Setter");
return true;
@ -2512,15 +2524,19 @@ SetPropIRGenerator::tryAttachSetUnboxedArrayElementHole(HandleObject obj, ObjOpe
bool
SetPropIRGenerator::tryAttachGenericProxy(HandleObject obj, ObjOperandId objId, HandleId id,
ValOperandId rhsId)
ValOperandId rhsId, bool handleDOMProxies)
{
MOZ_ASSERT(obj->is<ProxyObject>());
writer.guardIsProxy(objId);
// Ensure that the incoming object is not a DOM proxy, so that we can get to
// the specialized stubs
writer.guardNotDOMProxy(objId);
if (!handleDOMProxies) {
// Ensure that the incoming object is not a DOM proxy, so that we can
// get to the specialized stubs. If handleDOMProxies is true, we were
// unable to attach a specialized DOM stub, so we just handle all
// proxies here.
writer.guardNotDOMProxy(objId);
}
if (cacheKind_ == CacheKind::SetProp) {
writer.callProxySet(objId, id, rhsId, IsStrictSetPC(pc_));
@ -2557,6 +2573,42 @@ SetPropIRGenerator::tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId obj
return true;
}
bool
SetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId, HandleId id,
ValOperandId rhsId)
{
MOZ_ASSERT(IsCacheableDOMProxy(obj));
RootedObject proto(cx_, obj->staticPrototype());
if (!proto)
return false;
RootedObject holder(cx_);
RootedShape propShape(cx_);
if (!CanAttachSetter(cx_, pc_, proto, id, &holder, &propShape, isTemporarilyUnoptimizable_))
return false;
maybeEmitIdGuard(id);
writer.guardShape(objId, obj->maybeShape());
// Guard that our expando object hasn't started shadowing this property.
CheckDOMProxyExpandoDoesNotShadow(writer, obj, id, objId);
GeneratePrototypeGuards(writer, obj, holder, objId);
// Guard on the holder of the property.
ObjOperandId holderId = writer.loadObject(holder);
writer.guardShape(holderId, holder->as<NativeObject>().lastProperty());
// EmitCallSetterNoGuards expects |obj| to be the object the property is
// on to do some checks. Since we actually looked at proto, and no extra
// guards will be generated, we can just pass that instead.
EmitCallSetterNoGuards(writer, proto, holder, propShape, objId, rhsId);
trackAttached("DOMProxyUnshadowed");
return true;
}
bool
SetPropIRGenerator::tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id,
ValOperandId rhsId)
@ -2568,8 +2620,11 @@ SetPropIRGenerator::tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleI
case ProxyStubType::DOMShadowed:
return tryAttachDOMProxyShadowed(obj, objId, id, rhsId);
case ProxyStubType::DOMUnshadowed:
if (tryAttachDOMProxyUnshadowed(obj, objId, id, rhsId))
return true;
return tryAttachGenericProxy(obj, objId, id, rhsId, /* handleDOMProxies = */ true);
case ProxyStubType::Generic:
return tryAttachGenericProxy(obj, objId, id, rhsId);
return tryAttachGenericProxy(obj, objId, id, rhsId, /* handleDOMProxies = */ false);
}
MOZ_CRASH("Unexpected ProxyStubType");

Просмотреть файл

@ -1092,9 +1092,11 @@ class MOZ_RAII SetPropIRGenerator : public IRGenerator
Int32OperandId indexId, ValOperandId rhsId);
bool tryAttachGenericProxy(HandleObject obj, ObjOperandId objId, HandleId id,
ValOperandId rhsId);
ValOperandId rhsId, bool handleDOMProxies);
bool tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId, HandleId id,
ValOperandId rhsId);
bool tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId, HandleId id,
ValOperandId rhsId);
bool tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id, ValOperandId rhsId);
bool tryAttachProxyElement(HandleObject obj, ObjOperandId objId, ValOperandId rhsId);