зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1204073 - Optimize GETELEM with constant string-or-symbol index better in Ion. r=bhackett
This commit is contained in:
Родитель
1e0c0f6319
Коммит
54366d34b4
|
@ -7587,21 +7587,21 @@ ClassHasEffectlessLookup(const Class* clasp)
|
|||
// Return whether an object might have a property for name which is not
|
||||
// accounted for by type information.
|
||||
static bool
|
||||
ObjectHasExtraOwnProperty(CompileCompartment* comp, TypeSet::ObjectKey* object, PropertyName* name)
|
||||
ObjectHasExtraOwnProperty(CompileCompartment* comp, TypeSet::ObjectKey* object, jsid id)
|
||||
{
|
||||
// Some typed object properties are not reflected in type information.
|
||||
if (object->isGroup() && object->group()->maybeTypeDescr())
|
||||
return object->group()->typeDescr().hasProperty(comp->runtime()->names(), NameToId(name));
|
||||
return object->group()->typeDescr().hasProperty(comp->runtime()->names(), id);
|
||||
|
||||
const Class* clasp = object->clasp();
|
||||
|
||||
// Array |length| properties are not reflected in type information.
|
||||
if (clasp == &ArrayObject::class_)
|
||||
return name == comp->runtime()->names().length;
|
||||
return JSID_IS_ATOM(id, comp->runtime()->names().length);
|
||||
|
||||
// Resolve hooks can install new properties on objects on demand.
|
||||
JSObject* singleton = object->isSingleton() ? object->singleton() : nullptr;
|
||||
return ClassMayResolveId(comp->runtime()->names(), clasp, NameToId(name), singleton);
|
||||
return ClassMayResolveId(comp->runtime()->names(), clasp, id, singleton);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -7629,7 +7629,7 @@ IonBuilder::insertRecompileCheck()
|
|||
}
|
||||
|
||||
JSObject*
|
||||
IonBuilder::testSingletonProperty(JSObject* obj, PropertyName* name)
|
||||
IonBuilder::testSingletonProperty(JSObject* obj, jsid id)
|
||||
{
|
||||
// We would like to completely no-op property/global accesses which can
|
||||
// produce only a particular JSObject. When indicating the access result is
|
||||
|
@ -7651,19 +7651,19 @@ IonBuilder::testSingletonProperty(JSObject* obj, PropertyName* name)
|
|||
|
||||
TypeSet::ObjectKey* objKey = TypeSet::ObjectKey::get(obj);
|
||||
if (analysisContext)
|
||||
objKey->ensureTrackedProperty(analysisContext, NameToId(name));
|
||||
objKey->ensureTrackedProperty(analysisContext, id);
|
||||
|
||||
if (objKey->unknownProperties())
|
||||
return nullptr;
|
||||
|
||||
HeapTypeSetKey property = objKey->property(NameToId(name));
|
||||
HeapTypeSetKey property = objKey->property(id);
|
||||
if (property.isOwnProperty(constraints())) {
|
||||
if (obj->isSingleton())
|
||||
return property.singleton(constraints());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (ObjectHasExtraOwnProperty(compartment, objKey, name))
|
||||
if (ObjectHasExtraOwnProperty(compartment, objKey, id))
|
||||
return nullptr;
|
||||
|
||||
obj = checkNurseryObject(obj->getProto());
|
||||
|
@ -7673,7 +7673,7 @@ IonBuilder::testSingletonProperty(JSObject* obj, PropertyName* name)
|
|||
}
|
||||
|
||||
JSObject*
|
||||
IonBuilder::testSingletonPropertyTypes(MDefinition* obj, PropertyName* name)
|
||||
IonBuilder::testSingletonPropertyTypes(MDefinition* obj, jsid id)
|
||||
{
|
||||
// As for TestSingletonProperty, but the input is any value in a type set
|
||||
// rather than a specific object.
|
||||
|
@ -7684,7 +7684,7 @@ IonBuilder::testSingletonPropertyTypes(MDefinition* obj, PropertyName* name)
|
|||
|
||||
JSObject* objectSingleton = types ? types->maybeSingleton() : nullptr;
|
||||
if (objectSingleton)
|
||||
return testSingletonProperty(objectSingleton, name);
|
||||
return testSingletonProperty(objectSingleton, id);
|
||||
|
||||
MIRType objType = obj->type();
|
||||
if (objType == MIRType_Value && types)
|
||||
|
@ -7722,20 +7722,20 @@ IonBuilder::testSingletonPropertyTypes(MDefinition* obj, PropertyName* name)
|
|||
if (!key)
|
||||
continue;
|
||||
if (analysisContext)
|
||||
key->ensureTrackedProperty(analysisContext, NameToId(name));
|
||||
key->ensureTrackedProperty(analysisContext, id);
|
||||
|
||||
const Class* clasp = key->clasp();
|
||||
if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(compartment, key, name))
|
||||
if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(compartment, key, id))
|
||||
return nullptr;
|
||||
if (key->unknownProperties())
|
||||
return nullptr;
|
||||
HeapTypeSetKey property = key->property(NameToId(name));
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
if (property.isOwnProperty(constraints()))
|
||||
return nullptr;
|
||||
|
||||
if (JSObject* proto = checkNurseryObject(key->proto().toObjectOrNull())) {
|
||||
// Test this type.
|
||||
JSObject* thisSingleton = testSingletonProperty(proto, name);
|
||||
JSObject* thisSingleton = testSingletonProperty(proto, id);
|
||||
if (!thisSingleton)
|
||||
return nullptr;
|
||||
if (singleton) {
|
||||
|
@ -7757,7 +7757,7 @@ IonBuilder::testSingletonPropertyTypes(MDefinition* obj, PropertyName* name)
|
|||
|
||||
JSObject* proto = GetBuiltinPrototypePure(&script()->global(), key);
|
||||
if (proto)
|
||||
return testSingletonProperty(proto, name);
|
||||
return testSingletonProperty(proto, id);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -7986,7 +7986,7 @@ IonBuilder::getStaticName(JSObject* staticObject, PropertyName* name, bool* psuc
|
|||
if (barrier == BarrierKind::NoBarrier) {
|
||||
// Try to inline properties holding a known constant object.
|
||||
if (singleton) {
|
||||
if (testSingletonProperty(staticObject, name) == singleton)
|
||||
if (testSingletonProperty(staticObject, id) == singleton)
|
||||
return pushConstant(ObjectValue(*singleton));
|
||||
}
|
||||
|
||||
|
@ -8221,6 +8221,11 @@ IonBuilder::jsop_getelem()
|
|||
if (!getElemTryTypedObject(&emitted, obj, index) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Note: no trackOptimizationAttempt call is needed, getElemTryGetProp
|
||||
// will call it.
|
||||
if (!getElemTryGetProp(&emitted, obj, index) || emitted)
|
||||
return emitted;
|
||||
|
||||
trackOptimizationAttempt(TrackedStrategy::GetElem_Dense);
|
||||
if (!getElemTryDense(&emitted, obj, index) || emitted)
|
||||
return emitted;
|
||||
|
@ -8621,6 +8626,36 @@ IonBuilder::pushDerivedTypedObject(bool* emitted,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getElemTryGetProp(bool* emitted, MDefinition* obj, MDefinition* index)
|
||||
{
|
||||
// If index is a constant string or symbol, try to optimize this GETELEM
|
||||
// as a GETPROP.
|
||||
|
||||
MOZ_ASSERT(*emitted == false);
|
||||
|
||||
if (!index->isConstantValue())
|
||||
return true;
|
||||
|
||||
jsid id;
|
||||
if (!ValueToIdPure(index->constantValue(), &id))
|
||||
return true;
|
||||
|
||||
if (id != IdToTypeId(id))
|
||||
return true;
|
||||
|
||||
TemporaryTypeSet* types = bytecodeTypes(pc);
|
||||
|
||||
trackOptimizationAttempt(TrackedStrategy::GetProp_Constant);
|
||||
if (!getPropTryConstant(emitted, obj, id, types) || *emitted) {
|
||||
if (*emitted)
|
||||
index->setImplicitlyUsedUnchecked();
|
||||
return *emitted;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index)
|
||||
{
|
||||
|
@ -10195,7 +10230,7 @@ IonBuilder::objectsHaveCommonPrototype(TemporaryTypeSet* types, PropertyName* na
|
|||
if (!ClassHasEffectlessLookup(clasp))
|
||||
return false;
|
||||
JSObject* singleton = key->isSingleton() ? key->singleton() : nullptr;
|
||||
if (ObjectHasExtraOwnProperty(compartment, key, name)) {
|
||||
if (ObjectHasExtraOwnProperty(compartment, key, NameToId(name))) {
|
||||
if (!singleton || !singleton->is<GlobalObject>())
|
||||
return false;
|
||||
*guardGlobal = true;
|
||||
|
@ -10372,14 +10407,14 @@ IonBuilder::annotateGetPropertyCache(MDefinition* obj, MGetPropertyCache* getPro
|
|||
JSObject* proto = checkNurseryObject(key->proto().toObject());
|
||||
|
||||
const Class* clasp = key->clasp();
|
||||
if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(compartment, key, name))
|
||||
if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(compartment, key, NameToId(name)))
|
||||
continue;
|
||||
|
||||
HeapTypeSetKey ownTypes = key->property(NameToId(name));
|
||||
if (ownTypes.isOwnProperty(constraints()))
|
||||
continue;
|
||||
|
||||
JSObject* singleton = testSingletonProperty(proto, name);
|
||||
JSObject* singleton = testSingletonProperty(proto, NameToId(name));
|
||||
if (!singleton || !singleton->is<JSFunction>())
|
||||
continue;
|
||||
|
||||
|
@ -10630,7 +10665,7 @@ IonBuilder::jsop_getprop(PropertyName* name)
|
|||
// In this case we still need the getprop call so that the later
|
||||
// analysis knows when the |this| value has been read from.
|
||||
if (info().isAnalysis()) {
|
||||
if (!getPropTryConstant(&emitted, obj, name, types) || emitted)
|
||||
if (!getPropTryConstant(&emitted, obj, NameToId(name), types) || emitted)
|
||||
return emitted;
|
||||
}
|
||||
|
||||
|
@ -10649,7 +10684,7 @@ IonBuilder::jsop_getprop(PropertyName* name)
|
|||
if (!forceInlineCaches()) {
|
||||
// Try to hardcode known constants.
|
||||
trackOptimizationAttempt(TrackedStrategy::GetProp_Constant);
|
||||
if (!getPropTryConstant(&emitted, obj, name, types) || emitted)
|
||||
if (!getPropTryConstant(&emitted, obj, NameToId(name), types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to emit SIMD getter loads
|
||||
|
@ -10861,8 +10896,7 @@ IonBuilder::getPropTryArgumentsCallee(bool* emitted, MDefinition* obj, PropertyN
|
|||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryConstant(bool* emitted, MDefinition* obj, PropertyName* name,
|
||||
TemporaryTypeSet* types)
|
||||
IonBuilder::getPropTryConstant(bool* emitted, MDefinition* obj, jsid id, TemporaryTypeSet* types)
|
||||
{
|
||||
MOZ_ASSERT(*emitted == false);
|
||||
|
||||
|
@ -10873,7 +10907,7 @@ IonBuilder::getPropTryConstant(bool* emitted, MDefinition* obj, PropertyName* na
|
|||
return true;
|
||||
}
|
||||
|
||||
JSObject* singleton = testSingletonPropertyTypes(obj, name);
|
||||
JSObject* singleton = testSingletonPropertyTypes(obj, id);
|
||||
if (!singleton) {
|
||||
trackOptimizationOutcome(TrackedOutcome::NotSingleton);
|
||||
return true;
|
||||
|
@ -11692,7 +11726,7 @@ IonBuilder::getPropTryInnerize(bool* emitted, MDefinition* obj, PropertyName* na
|
|||
// we'd produce here.
|
||||
|
||||
trackOptimizationAttempt(TrackedStrategy::GetProp_Constant);
|
||||
if (!getPropTryConstant(emitted, inner, name, types) || *emitted)
|
||||
if (!getPropTryConstant(emitted, inner, NameToId(name), types) || *emitted)
|
||||
return *emitted;
|
||||
|
||||
trackOptimizationAttempt(TrackedStrategy::GetProp_StaticName);
|
||||
|
|
|
@ -425,8 +425,7 @@ class IonBuilder
|
|||
TemporaryTypeSet* types);
|
||||
bool getPropTryArgumentsLength(bool* emitted, MDefinition* obj);
|
||||
bool getPropTryArgumentsCallee(bool* emitted, MDefinition* obj, PropertyName* name);
|
||||
bool getPropTryConstant(bool* emitted, MDefinition* obj, PropertyName* name,
|
||||
TemporaryTypeSet* types);
|
||||
bool getPropTryConstant(bool* emitted, MDefinition* obj, jsid id, TemporaryTypeSet* types);
|
||||
bool getPropTryDefiniteSlot(bool* emitted, MDefinition* obj, PropertyName* name,
|
||||
BarrierKind barrier, TemporaryTypeSet* types);
|
||||
bool getPropTryUnboxed(bool* emitted, MDefinition* obj, PropertyName* name,
|
||||
|
@ -585,6 +584,7 @@ class IonBuilder
|
|||
|
||||
// jsop_getelem() helpers.
|
||||
bool getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index);
|
||||
bool getElemTryGetProp(bool* emitted, MDefinition* obj, MDefinition* index);
|
||||
bool getElemTryTypedStatic(bool* emitted, MDefinition* obj, MDefinition* index);
|
||||
bool getElemTryTypedArray(bool* emitted, MDefinition* obj, MDefinition* index);
|
||||
bool getElemTryTypedObject(bool* emitted, MDefinition* obj, MDefinition* index);
|
||||
|
@ -960,8 +960,8 @@ class IonBuilder
|
|||
|
||||
MGetPropertyCache* getInlineableGetPropertyCache(CallInfo& callInfo);
|
||||
|
||||
JSObject* testSingletonProperty(JSObject* obj, PropertyName* name);
|
||||
JSObject* testSingletonPropertyTypes(MDefinition* obj, PropertyName* name);
|
||||
JSObject* testSingletonProperty(JSObject* obj, jsid id);
|
||||
JSObject* testSingletonPropertyTypes(MDefinition* obj, jsid id);
|
||||
|
||||
uint32_t getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed);
|
||||
MDefinition* convertUnboxedObjects(MDefinition* obj);
|
||||
|
|
|
@ -795,7 +795,7 @@ class MDefinition : public MNode
|
|||
MIR_OPCODE_LIST(OPCODE_CASTS)
|
||||
# undef OPCODE_CASTS
|
||||
|
||||
bool isConstantValue() {
|
||||
bool isConstantValue() const {
|
||||
return isConstant() || (isBox() && getOperand(0)->isConstant());
|
||||
}
|
||||
const Value& constantValue();
|
||||
|
|
Загрузка…
Ссылка в новой задаче