Bug 1322093 followup - Make idempotent ICs handle unshadowed DOM proxies to fix Dromaeo regressions. r=evilpie on IRC

--HG--
extra : rebase_source : 593e4f4e25fcf63cfa391a93ac088c1bce1f3c2f
extra : source : 981fd29c57012c7e8a28168ca0941e00be560462
This commit is contained in:
Jan de Mooij 2016-12-23 15:17:32 +01:00
Родитель 55da96bdab
Коммит 2555852e40
2 изменённых файлов: 65 добавлений и 32 удалений

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

@ -45,12 +45,40 @@ EmitLoadSlotResult(CacheIRWriter& writer, ObjOperandId holderOp, NativeObject* h
}
}
enum class ProxyStubType {
None,
DOMShadowed,
DOMUnshadowed,
Generic
};
static ProxyStubType
GetProxyStubType(JSContext* cx, HandleObject obj, HandleId id)
{
if (!obj->is<ProxyObject>())
return ProxyStubType::None;
if (!IsCacheableDOMProxy(obj))
return ProxyStubType::Generic;
DOMProxyShadowsResult shadows = GetDOMProxyShadowsCheck()(cx, obj, id);
if (shadows == ShadowCheckFailed) {
cx->clearPendingException();
return ProxyStubType::None;
}
if (DOMProxyIsShadowing(shadows))
return ProxyStubType::DOMShadowed;
MOZ_ASSERT(shadows == DoesntShadow || shadows == DoesntShadowUnique);
return ProxyStubType::DOMUnshadowed;
}
bool
GetPropIRGenerator::tryAttachStub()
{
// pc_ should only be null for idempotent ICs, and idempotent ICs should
// call tryAttachIdempotentStub instead.
MOZ_ASSERT(pc_);
// Idempotent ICs should call tryAttachIdempotentStub instead.
MOZ_ASSERT(!idempotent());
AutoAssertNoPendingException aanpe(cx_);
@ -140,16 +168,21 @@ GetPropIRGenerator::tryAttachIdempotentStub()
// of (2), we don't support for instance missing properties or array
// lengths, as TI does not account for these cases.
// No pc if idempotent, as there can be multiple bytecode locations
// due to GVN.
MOZ_ASSERT(!pc_);
MOZ_ASSERT(idempotent());
RootedObject obj(cx_, &val_.toObject());
RootedId id(cx_, NameToId(idVal_.toString()->asAtom().asPropertyName()));
ValOperandId valId(writer.setInputOperandId(0));
ObjOperandId objId = writer.guardIsObject(valId);
return tryAttachNative(obj, objId, id);
if (tryAttachNative(obj, objId, id))
return true;
// Also support native data properties on DOMProxy prototypes.
if (GetProxyStubType(cx_, obj, id) == ProxyStubType::DOMUnshadowed)
return tryAttachDOMProxyUnshadowed(obj, objId, id);
return false;
}
static bool
@ -202,11 +235,16 @@ CanAttachNativeGetProp(JSContext* cx, HandleObject obj, HandleId id,
holder.set(&baseHolder->as<NativeObject>());
}
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, shape) ||
IsCacheableNoProperty(cx, obj, holder, shape, id, pc))
{
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, shape))
return CanAttachReadSlot;
// Idempotent ICs only support plain data properties, see
// tryAttachIdempotentStub.
if (!pc)
return CanAttachNone;
if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc))
return CanAttachReadSlot;
}
if (IsCacheableGetPropCallScripted(obj, holder, shape, isTemporarilyUnoptimizable)) {
// See bug 1226816.
@ -381,13 +419,8 @@ GetPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId, Handle
NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, obj, id, &holder, &shape, pc_,
engine_, isTemporarilyUnoptimizable_);
if (!pc_) {
// Idempotent ICs only support plain data properties.
if (type != CanAttachReadSlot)
return false;
MOZ_ASSERT(holder);
}
MOZ_ASSERT_IF(idempotent(),
type == CanAttachNone || (type == CanAttachReadSlot && holder));
switch (type) {
case CanAttachNone:
return false;
@ -546,6 +579,8 @@ GetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId o
NativeGetPropCacheability canCache = CanAttachNativeGetProp(cx_, checkObj, id, &holder, &shape,
pc_, engine_,
isTemporarilyUnoptimizable_);
MOZ_ASSERT_IF(idempotent(),
canCache == CanAttachNone || (canCache == CanAttachReadSlot && holder));
if (canCache == CanAttachNone)
return false;
@ -588,24 +623,18 @@ GetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId o
bool
GetPropIRGenerator::tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id)
{
if (!obj->is<ProxyObject>())
switch (GetProxyStubType(cx_, obj, id)) {
case ProxyStubType::None:
return false;
// Skim off DOM proxies.
if (IsCacheableDOMProxy(obj)) {
DOMProxyShadowsResult shadows = GetDOMProxyShadowsCheck()(cx_, obj, id);
if (shadows == ShadowCheckFailed) {
cx_->clearPendingException();
return false;
}
if (DOMProxyIsShadowing(shadows))
case ProxyStubType::DOMShadowed:
return tryAttachDOMProxyShadowed(obj, objId, id);
MOZ_ASSERT(shadows == DoesntShadow || shadows == DoesntShadowUnique);
case ProxyStubType::DOMUnshadowed:
return tryAttachDOMProxyUnshadowed(obj, objId, id);
case ProxyStubType::Generic:
return tryAttachGenericProxy(obj, objId, id);
}
return tryAttachGenericProxy(obj, objId, id);
MOZ_CRASH("Unexpected ProxyStubType");
}
bool

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

@ -717,6 +717,10 @@ class MOZ_RAII GetPropIRGenerator
return ValOperandId(1);
}
// No pc if idempotent, as there can be multiple bytecode locations
// due to GVN.
bool idempotent() const { return pc_ == nullptr; }
// If this is a GetElem cache, emit instructions to guard the incoming Value
// matches |id|.
void maybeEmitIdGuard(jsid id);