зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1383777 - Support idempotent ICs that access missing properties and object lengths, r=jandem.
--HG-- extra : rebase_source : 405e682faa19e1e710f4d9f1c3692baf0a1b8299
This commit is contained in:
Родитель
142609c919
Коммит
d00e270300
|
@ -0,0 +1,34 @@
|
|||
// Test that we don't attach ICs to idempotent caches that are incompatible
|
||||
// with the cache result type.
|
||||
|
||||
var missingObjs = [{a:1},Object.create({a:2}),{}];
|
||||
function testMissing(limit)
|
||||
{
|
||||
var res = 0;
|
||||
for (var i = 0; i < 1000; i++) {
|
||||
for (var j = 0; j < missingObjs.length; j++) {
|
||||
var obj = missingObjs[j];
|
||||
if (j < limit)
|
||||
res += obj.a;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
assertEq(testMissing(2), 3000);
|
||||
assertEq(testMissing(3), NaN);
|
||||
|
||||
var lengthObjs = [{length:{a:1}},Object.create({length:{a:2}}),[0,1]];
|
||||
function testArrayLength(limit)
|
||||
{
|
||||
var res = 0;
|
||||
for (var i = 0; i < 1000; i++) {
|
||||
for (var j = 0; j < lengthObjs.length; j++) {
|
||||
var obj = lengthObjs[j];
|
||||
if (j < limit)
|
||||
res += obj.length.a;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
assertEq(testArrayLength(2), 3000);
|
||||
assertEq(testArrayLength(3), NaN);
|
|
@ -810,8 +810,10 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
|
|||
|
||||
if (stub->state().canAttachStub()) {
|
||||
ICStubEngine engine = ICStubEngine::Baseline;
|
||||
GetPropIRGenerator gen(cx, script, pc, CacheKind::GetElem, stub->state().mode(),
|
||||
&isTemporarilyUnoptimizable, lhs, rhs, lhs, CanAttachGetter::Yes);
|
||||
GetPropIRGenerator gen(cx, script, pc,
|
||||
CacheKind::GetElem, stub->state().mode(),
|
||||
&isTemporarilyUnoptimizable, lhs, rhs, lhs,
|
||||
GetPropertyResultFlags::All);
|
||||
if (gen.tryAttachStub()) {
|
||||
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
|
||||
BaselineCacheIRStubKind::Monitored,
|
||||
|
@ -884,7 +886,7 @@ DoGetElemSuperFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback*
|
|||
ICStubEngine engine = ICStubEngine::Baseline;
|
||||
GetPropIRGenerator gen(cx, script, pc, CacheKind::GetElemSuper, stub->state().mode(),
|
||||
&isTemporarilyUnoptimizable, lhs, rhs, receiver,
|
||||
CanAttachGetter::Yes);
|
||||
GetPropertyResultFlags::All);
|
||||
if (gen.tryAttachStub()) {
|
||||
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
|
||||
BaselineCacheIRStubKind::Monitored,
|
||||
|
|
|
@ -48,13 +48,13 @@ GetPropIRGenerator::GetPropIRGenerator(JSContext* cx, HandleScript script, jsbyt
|
|||
CacheKind cacheKind, ICState::Mode mode,
|
||||
bool* isTemporarilyUnoptimizable, HandleValue val,
|
||||
HandleValue idVal, HandleValue receiver,
|
||||
CanAttachGetter canAttachGetter)
|
||||
GetPropertyResultFlags resultFlags)
|
||||
: IRGenerator(cx, script, pc, cacheKind, mode),
|
||||
val_(val),
|
||||
idVal_(idVal),
|
||||
receiver_(receiver),
|
||||
isTemporarilyUnoptimizable_(isTemporarilyUnoptimizable),
|
||||
canAttachGetter_(canAttachGetter),
|
||||
resultFlags_(resultFlags),
|
||||
preliminaryObjectAction_(PreliminaryObjectAction::None)
|
||||
{}
|
||||
|
||||
|
@ -247,11 +247,9 @@ GetPropIRGenerator::tryAttachStub()
|
|||
bool
|
||||
GetPropIRGenerator::tryAttachIdempotentStub()
|
||||
{
|
||||
// For idempotent ICs, only attach stubs for plain data properties.
|
||||
// This ensures (1) the lookup has no side-effects and (2) Ion has complete
|
||||
// static type information and we don't have to monitor the result. Because
|
||||
// of (2), we don't support for instance missing properties or array
|
||||
// lengths, as TI does not account for these cases.
|
||||
// For idempotent ICs, only attach stubs which we can be sure have no side
|
||||
// effects and produce a result which the MIR in the calling code is able
|
||||
// to handle, since we do not have a pc to explicitly monitor the result.
|
||||
|
||||
MOZ_ASSERT(idempotent());
|
||||
|
||||
|
@ -263,6 +261,10 @@ GetPropIRGenerator::tryAttachIdempotentStub()
|
|||
if (tryAttachNative(obj, objId, id))
|
||||
return true;
|
||||
|
||||
// Object lengths are supported only if int32 results are allowed.
|
||||
if ((resultFlags_ & GetPropertyResultFlags::AllowInt32) && tryAttachObjectLength(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);
|
||||
|
@ -272,22 +274,23 @@ GetPropIRGenerator::tryAttachIdempotentStub()
|
|||
|
||||
static bool
|
||||
IsCacheableNoProperty(JSContext* cx, JSObject* obj, JSObject* holder, Shape* shape, jsid id,
|
||||
jsbytecode* pc)
|
||||
jsbytecode* pc, GetPropertyResultFlags resultFlags)
|
||||
{
|
||||
if (shape)
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(!holder);
|
||||
|
||||
if (!pc) {
|
||||
// This is an idempotent IC, don't attach a missing-property stub.
|
||||
// See tryAttachStub.
|
||||
// Idempotent ICs may only attach missing-property stubs if undefined
|
||||
// results are explicitly allowed, since no monitoring is done of the
|
||||
// cache result.
|
||||
if (!pc && !(resultFlags & GetPropertyResultFlags::AllowUndefined))
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we're doing a name lookup, we have to throw a ReferenceError. If
|
||||
// extra warnings are enabled, we may have to report a warning.
|
||||
if (*pc == JSOP_GETBOUNDNAME || cx->compartment()->behaviors().extraWarnings(cx))
|
||||
// Note that Ion does not generate idempotent caches for JSOP_GETBOUNDNAME.
|
||||
if ((pc && *pc == JSOP_GETBOUNDNAME) || cx->compartment()->behaviors().extraWarnings(cx))
|
||||
return false;
|
||||
|
||||
return CheckHasNoSuchProperty(cx, obj, id);
|
||||
|
@ -302,7 +305,7 @@ enum NativeGetPropCacheability {
|
|||
static NativeGetPropCacheability
|
||||
CanAttachNativeGetProp(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleNativeObject holder, MutableHandleShape shape,
|
||||
jsbytecode* pc, CanAttachGetter canAttachGetter,
|
||||
jsbytecode* pc, GetPropertyResultFlags resultFlags,
|
||||
bool* isTemporarilyUnoptimizable)
|
||||
{
|
||||
MOZ_ASSERT(JSID_IS_STRING(id) || JSID_IS_SYMBOL(id));
|
||||
|
@ -327,22 +330,17 @@ CanAttachNativeGetProp(JSContext* cx, HandleObject obj, HandleId id,
|
|||
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, prop))
|
||||
return CanAttachReadSlot;
|
||||
|
||||
// Idempotent ICs only support plain data properties, see
|
||||
// tryAttachIdempotentStub.
|
||||
if (!pc)
|
||||
return CanAttachNone;
|
||||
|
||||
if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc))
|
||||
if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc, resultFlags))
|
||||
return CanAttachReadSlot;
|
||||
|
||||
if (canAttachGetter == CanAttachGetter::No)
|
||||
return CanAttachNone;
|
||||
// Idempotent ICs cannot call getters, see tryAttachIdempotentStub.
|
||||
if (pc && (resultFlags & GetPropertyResultFlags::Monitored)) {
|
||||
if (IsCacheableGetPropCallScripted(obj, holder, shape, isTemporarilyUnoptimizable))
|
||||
return CanAttachCallGetter;
|
||||
|
||||
if (IsCacheableGetPropCallScripted(obj, holder, shape, isTemporarilyUnoptimizable))
|
||||
return CanAttachCallGetter;
|
||||
|
||||
if (IsCacheableGetPropCallNative(obj, holder, shape))
|
||||
return CanAttachCallGetter;
|
||||
if (IsCacheableGetPropCallNative(obj, holder, shape))
|
||||
return CanAttachCallGetter;
|
||||
}
|
||||
|
||||
return CanAttachNone;
|
||||
}
|
||||
|
@ -582,10 +580,8 @@ GetPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId, Handle
|
|||
RootedNativeObject holder(cx_);
|
||||
|
||||
NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, obj, id, &holder, &shape, pc_,
|
||||
canAttachGetter_,
|
||||
resultFlags_,
|
||||
isTemporarilyUnoptimizable_);
|
||||
MOZ_ASSERT_IF(idempotent(),
|
||||
type == CanAttachNone || (type == CanAttachReadSlot && holder));
|
||||
switch (type) {
|
||||
case CanAttachNone:
|
||||
return false;
|
||||
|
@ -613,6 +609,7 @@ GetPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId, Handle
|
|||
return true;
|
||||
case CanAttachCallGetter: {
|
||||
// |super.prop| accesses use a |this| value that differs from lookup object
|
||||
MOZ_ASSERT(!idempotent());
|
||||
ObjOperandId receiverId = isSuper() ? writer.guardIsObject(getSuperReceiverValueId())
|
||||
: objId;
|
||||
maybeEmitIdGuard(id);
|
||||
|
@ -651,7 +648,7 @@ GetPropIRGenerator::tryAttachWindowProxy(HandleObject obj, ObjOperandId objId, H
|
|||
RootedShape shape(cx_);
|
||||
RootedNativeObject holder(cx_);
|
||||
NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, windowObj, id, &holder, &shape, pc_,
|
||||
canAttachGetter_,
|
||||
resultFlags_,
|
||||
isTemporarilyUnoptimizable_);
|
||||
switch (type) {
|
||||
case CanAttachNone:
|
||||
|
@ -738,8 +735,8 @@ GetPropIRGenerator::tryAttachCrossCompartmentWrapper(HandleObject obj, ObjOperan
|
|||
RootedShape shape(cx_);
|
||||
RootedNativeObject holder(cx_);
|
||||
NativeGetPropCacheability canCache =
|
||||
CanAttachNativeGetProp(cx_, unwrapped, id, &holder, &shape, pc_, canAttachGetter_,
|
||||
isTemporarilyUnoptimizable_);
|
||||
CanAttachNativeGetProp(cx_, unwrapped, id, &holder, &shape, pc_,
|
||||
resultFlags_, isTemporarilyUnoptimizable_);
|
||||
if (canCache != CanAttachReadSlot)
|
||||
return false;
|
||||
|
||||
|
@ -963,7 +960,7 @@ GetPropIRGenerator::tryAttachDOMProxyExpando(HandleObject obj, ObjOperandId objI
|
|||
RootedShape propShape(cx_);
|
||||
NativeGetPropCacheability canCache =
|
||||
CanAttachNativeGetProp(cx_, expandoObj, id, &holder, &propShape, pc_,
|
||||
canAttachGetter_, isTemporarilyUnoptimizable_);
|
||||
resultFlags_, isTemporarilyUnoptimizable_);
|
||||
if (canCache != CanAttachReadSlot && canCache != CanAttachCallGetter)
|
||||
return false;
|
||||
if (!holder)
|
||||
|
@ -1054,10 +1051,8 @@ GetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId o
|
|||
RootedNativeObject holder(cx_);
|
||||
RootedShape shape(cx_);
|
||||
NativeGetPropCacheability canCache = CanAttachNativeGetProp(cx_, checkObj, id, &holder, &shape,
|
||||
pc_, canAttachGetter_,
|
||||
pc_, resultFlags_,
|
||||
isTemporarilyUnoptimizable_);
|
||||
MOZ_ASSERT_IF(idempotent(),
|
||||
canCache == CanAttachNone || (canCache == CanAttachReadSlot && holder));
|
||||
if (canCache == CanAttachNone)
|
||||
return false;
|
||||
|
||||
|
@ -1394,7 +1389,7 @@ GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId, HandleId id)
|
|||
RootedShape shape(cx_);
|
||||
RootedNativeObject holder(cx_);
|
||||
NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, proto, id, &holder, &shape, pc_,
|
||||
canAttachGetter_,
|
||||
resultFlags_,
|
||||
isTemporarilyUnoptimizable_);
|
||||
if (type != CanAttachReadSlot)
|
||||
return false;
|
||||
|
|
|
@ -1147,7 +1147,38 @@ class MOZ_RAII IRGenerator
|
|||
CacheKind cacheKind() const { return cacheKind_; }
|
||||
};
|
||||
|
||||
enum class CanAttachGetter { Yes, No };
|
||||
// Flags used to describe what values a GetProperty cache may produce.
|
||||
enum class GetPropertyResultFlags {
|
||||
None = 0,
|
||||
|
||||
// Values produced by this cache will go through a type barrier,
|
||||
// so the cache may produce any type of value that is compatible with its
|
||||
// result operand.
|
||||
Monitored = 1 << 0,
|
||||
|
||||
// Whether particular primitives may be produced by this cache.
|
||||
AllowUndefined = 1 << 1,
|
||||
AllowInt32 = 1 << 2,
|
||||
AllowDouble = 1 << 3,
|
||||
|
||||
All = Monitored | AllowUndefined | AllowInt32 | AllowDouble
|
||||
};
|
||||
|
||||
static inline bool operator&(GetPropertyResultFlags a, GetPropertyResultFlags b)
|
||||
{
|
||||
return static_cast<int>(a) & static_cast<int>(b);
|
||||
}
|
||||
|
||||
static inline GetPropertyResultFlags operator|(GetPropertyResultFlags a, GetPropertyResultFlags b)
|
||||
{
|
||||
return static_cast<GetPropertyResultFlags>(static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
|
||||
static inline GetPropertyResultFlags& operator|=(GetPropertyResultFlags& lhs, GetPropertyResultFlags b)
|
||||
{
|
||||
lhs = lhs | b;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// GetPropIRGenerator generates CacheIR for a GetProp IC.
|
||||
class MOZ_RAII GetPropIRGenerator : public IRGenerator
|
||||
|
@ -1156,7 +1187,7 @@ class MOZ_RAII GetPropIRGenerator : public IRGenerator
|
|||
HandleValue idVal_;
|
||||
HandleValue receiver_;
|
||||
bool* isTemporarilyUnoptimizable_;
|
||||
CanAttachGetter canAttachGetter_;
|
||||
GetPropertyResultFlags resultFlags_;
|
||||
|
||||
enum class PreliminaryObjectAction { None, Unlink, NotePreliminary };
|
||||
PreliminaryObjectAction preliminaryObjectAction_;
|
||||
|
@ -1233,7 +1264,8 @@ class MOZ_RAII GetPropIRGenerator : public IRGenerator
|
|||
public:
|
||||
GetPropIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, CacheKind cacheKind,
|
||||
ICState::Mode mode, bool* isTemporarilyUnoptimizable, HandleValue val,
|
||||
HandleValue idVal, HandleValue receiver, CanAttachGetter canAttachGetter);
|
||||
HandleValue idVal, HandleValue receiver,
|
||||
GetPropertyResultFlags resultFlags);
|
||||
|
||||
bool tryAttachStub();
|
||||
bool tryAttachIdempotentStub();
|
||||
|
|
|
@ -10285,7 +10285,7 @@ void
|
|||
CodeGenerator::addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs,
|
||||
TypedOrValueRegister value, const ConstantOrRegister& id,
|
||||
TypedOrValueRegister output, Register maybeTemp,
|
||||
bool monitoredResult, bool allowDoubleResult,
|
||||
GetPropertyResultFlags resultFlags,
|
||||
jsbytecode* profilerLeavePc)
|
||||
{
|
||||
CacheKind kind = CacheKind::GetElem;
|
||||
|
@ -10295,8 +10295,7 @@ CodeGenerator::addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs,
|
|||
if (idString->isAtom() && !idString->asAtom().isIndex(&dummy))
|
||||
kind = CacheKind::GetProp;
|
||||
}
|
||||
IonGetPropertyIC cache(kind, liveRegs, value, id, output, maybeTemp, monitoredResult,
|
||||
allowDoubleResult);
|
||||
IonGetPropertyIC cache(kind, liveRegs, value, id, output, maybeTemp, resultFlags);
|
||||
addIC(ins, allocateIC(cache));
|
||||
}
|
||||
|
||||
|
@ -10333,6 +10332,35 @@ CodeGenerator::toConstantOrRegister(LInstruction* lir, size_t n, MIRType type)
|
|||
return TypedOrValueRegister(type, ToAnyRegister(value));
|
||||
}
|
||||
|
||||
static GetPropertyResultFlags
|
||||
IonGetPropertyICFlags(const MGetPropertyCache* mir)
|
||||
{
|
||||
GetPropertyResultFlags flags = GetPropertyResultFlags::None;
|
||||
if (mir->monitoredResult())
|
||||
flags |= GetPropertyResultFlags::Monitored;
|
||||
|
||||
if (mir->type() == MIRType::Value) {
|
||||
if (TemporaryTypeSet* types = mir->resultTypeSet()) {
|
||||
if (types->hasType(TypeSet::UndefinedType()))
|
||||
flags |= GetPropertyResultFlags::AllowUndefined;
|
||||
if (types->hasType(TypeSet::Int32Type()))
|
||||
flags |= GetPropertyResultFlags::AllowInt32;
|
||||
if (types->hasType(TypeSet::DoubleType()))
|
||||
flags |= GetPropertyResultFlags::AllowDouble;
|
||||
} else {
|
||||
flags |= GetPropertyResultFlags::AllowUndefined
|
||||
| GetPropertyResultFlags::AllowInt32
|
||||
| GetPropertyResultFlags::AllowDouble;
|
||||
}
|
||||
} else if (mir->type() == MIRType::Int32) {
|
||||
flags |= GetPropertyResultFlags::AllowInt32;
|
||||
} else if (mir->type() == MIRType::Double) {
|
||||
flags |= GetPropertyResultFlags::AllowInt32 | GetPropertyResultFlags::AllowDouble;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitGetPropertyCacheV(LGetPropertyCacheV* ins)
|
||||
{
|
||||
|
@ -10340,12 +10368,11 @@ CodeGenerator::visitGetPropertyCacheV(LGetPropertyCacheV* ins)
|
|||
TypedOrValueRegister value =
|
||||
toConstantOrRegister(ins, LGetPropertyCacheV::Value, ins->mir()->value()->type()).reg();
|
||||
ConstantOrRegister id = toConstantOrRegister(ins, LGetPropertyCacheV::Id, ins->mir()->idval()->type());
|
||||
bool monitoredResult = ins->mir()->monitoredResult();
|
||||
TypedOrValueRegister output = TypedOrValueRegister(GetValueOutput(ins));
|
||||
Register maybeTemp = ins->temp()->isBogusTemp() ? InvalidReg : ToRegister(ins->temp());
|
||||
|
||||
addGetPropertyCache(ins, liveRegs, value, id, output, maybeTemp, monitoredResult,
|
||||
ins->mir()->allowDoubleResult(), ins->mir()->profilerLeavePc());
|
||||
addGetPropertyCache(ins, liveRegs, value, id, output, maybeTemp,
|
||||
IonGetPropertyICFlags(ins->mir()), ins->mir()->profilerLeavePc());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -10355,12 +10382,11 @@ CodeGenerator::visitGetPropertyCacheT(LGetPropertyCacheT* ins)
|
|||
TypedOrValueRegister value =
|
||||
toConstantOrRegister(ins, LGetPropertyCacheV::Value, ins->mir()->value()->type()).reg();
|
||||
ConstantOrRegister id = toConstantOrRegister(ins, LGetPropertyCacheT::Id, ins->mir()->idval()->type());
|
||||
bool monitoredResult = ins->mir()->monitoredResult();
|
||||
TypedOrValueRegister output(ins->mir()->type(), ToAnyRegister(ins->getDef(0)));
|
||||
Register maybeTemp = ins->temp()->isBogusTemp() ? InvalidReg : ToRegister(ins->temp());
|
||||
|
||||
addGetPropertyCache(ins, liveRegs, value, id, output, maybeTemp, monitoredResult,
|
||||
ins->mir()->allowDoubleResult(), ins->mir()->profilerLeavePc());
|
||||
addGetPropertyCache(ins, liveRegs, value, id, output, maybeTemp,
|
||||
IonGetPropertyICFlags(ins->mir()), ins->mir()->profilerLeavePc());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef jit_CodeGenerator_h
|
||||
#define jit_CodeGenerator_h
|
||||
|
||||
#include "jit/CacheIR.h"
|
||||
#include "jit/IonCaches.h"
|
||||
#if defined(JS_ION_PERF)
|
||||
# include "jit/PerfSpewer.h"
|
||||
|
@ -468,8 +469,8 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
|||
private:
|
||||
void addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs,
|
||||
TypedOrValueRegister value, const ConstantOrRegister& id,
|
||||
TypedOrValueRegister output, Register maybeTemp, bool monitoredResult,
|
||||
bool allowDoubleResult, jsbytecode* profilerLeavePc);
|
||||
TypedOrValueRegister output, Register maybeTemp,
|
||||
GetPropertyResultFlags flags, jsbytecode* profilerLeavePc);
|
||||
void addSetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg,
|
||||
Register temp, FloatRegister tempDouble,
|
||||
FloatRegister tempF32, const ConstantOrRegister& id,
|
||||
|
|
|
@ -135,12 +135,11 @@ IonGetPropertyIC::update(JSContext* cx, HandleScript outerScript, IonGetProperty
|
|||
// needs a type barrier. Unfortunately, PropertyReadNeedsTypeBarrier
|
||||
// does not account for getters, so we should only attach a getter
|
||||
// stub if we inserted a type barrier.
|
||||
CanAttachGetter canAttachGetter =
|
||||
ic->monitoredResult() ? CanAttachGetter::Yes : CanAttachGetter::No;
|
||||
jsbytecode* pc = ic->idempotent() ? nullptr : ic->pc();
|
||||
bool isTemporarilyUnoptimizable = false;
|
||||
GetPropIRGenerator gen(cx, outerScript, pc, ic->kind(), ic->state().mode(),
|
||||
&isTemporarilyUnoptimizable, val, idVal, val, canAttachGetter);
|
||||
&isTemporarilyUnoptimizable, val, idVal, val,
|
||||
ic->resultFlags());
|
||||
if (ic->idempotent() ? gen.tryAttachIdempotentStub() : gen.tryAttachStub())
|
||||
ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
|
||||
|
||||
|
|
|
@ -178,6 +178,7 @@ class IonIC
|
|||
|
||||
class IonGetPropertyIC : public IonIC
|
||||
{
|
||||
private:
|
||||
LiveRegisterSet liveRegs_;
|
||||
|
||||
TypedOrValueRegister value_;
|
||||
|
@ -185,30 +186,29 @@ class IonGetPropertyIC : public IonIC
|
|||
TypedOrValueRegister output_;
|
||||
Register maybeTemp_; // Might be InvalidReg.
|
||||
|
||||
bool monitoredResult_ : 1;
|
||||
bool allowDoubleResult_ : 1;
|
||||
GetPropertyResultFlags resultFlags_;
|
||||
|
||||
public:
|
||||
IonGetPropertyIC(CacheKind kind, LiveRegisterSet liveRegs, TypedOrValueRegister value,
|
||||
const ConstantOrRegister& id, TypedOrValueRegister output, Register maybeTemp,
|
||||
bool monitoredResult, bool allowDoubleResult)
|
||||
GetPropertyResultFlags resultFlags)
|
||||
: IonIC(kind),
|
||||
liveRegs_(liveRegs),
|
||||
value_(value),
|
||||
id_(id),
|
||||
output_(output),
|
||||
maybeTemp_(maybeTemp),
|
||||
monitoredResult_(monitoredResult),
|
||||
allowDoubleResult_(allowDoubleResult)
|
||||
resultFlags_(resultFlags)
|
||||
{ }
|
||||
|
||||
bool monitoredResult() const { return monitoredResult_; }
|
||||
TypedOrValueRegister value() const { return value_; }
|
||||
ConstantOrRegister id() const { return id_; }
|
||||
TypedOrValueRegister output() const { return output_; }
|
||||
Register maybeTemp() const { return maybeTemp_; }
|
||||
LiveRegisterSet liveRegs() const { return liveRegs_; }
|
||||
bool allowDoubleResult() const { return allowDoubleResult_; }
|
||||
GetPropertyResultFlags resultFlags() const { return resultFlags_; }
|
||||
bool monitoredResult() const { return resultFlags_ & GetPropertyResultFlags::Monitored; }
|
||||
bool allowDoubleResult() const { return resultFlags_ & GetPropertyResultFlags::AllowDouble; }
|
||||
|
||||
static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonGetPropertyIC* ic,
|
||||
HandleValue val, HandleValue idVal, MutableHandleValue res);
|
||||
|
|
|
@ -2069,7 +2069,8 @@ DoGetPropFallback(JSContext* cx, BaselineFrame* frame, ICGetProp_Fallback* stub_
|
|||
if (stub->state().canAttachStub()) {
|
||||
RootedValue idVal(cx, StringValue(name));
|
||||
GetPropIRGenerator gen(cx, script, pc, CacheKind::GetProp, stub->state().mode(),
|
||||
&isTemporarilyUnoptimizable, val, idVal, val, CanAttachGetter::Yes);
|
||||
&isTemporarilyUnoptimizable, val, idVal, val,
|
||||
GetPropertyResultFlags::All);
|
||||
if (gen.tryAttachStub()) {
|
||||
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
|
||||
BaselineCacheIRStubKind::Monitored,
|
||||
|
@ -2140,7 +2141,7 @@ DoGetPropSuperFallback(JSContext* cx, BaselineFrame* frame, ICGetProp_Fallback*
|
|||
RootedValue idVal(cx, StringValue(name));
|
||||
GetPropIRGenerator gen(cx, script, pc, CacheKind::GetPropSuper, stub->state().mode(),
|
||||
&isTemporarilyUnoptimizable, val, idVal, receiver,
|
||||
CanAttachGetter::Yes);
|
||||
GetPropertyResultFlags::All);
|
||||
if (gen.tryAttachStub()) {
|
||||
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
|
||||
BaselineCacheIRStubKind::Monitored,
|
||||
|
|
Загрузка…
Ссылка в новой задаче