mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-16 06:54:00 +00:00
Bug 870821 - Seed observed values for integer CALLELEM ops with the possible targets, r=jandem.
This commit is contained in:
parent
8f6fd44283
commit
5d18297de0
@ -6274,6 +6274,14 @@ IonBuilder::jsop_getelem_dense()
|
||||
MDefinition *obj = current->pop();
|
||||
|
||||
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
|
||||
|
||||
if (JSOp(*pc) == JSOP_CALLELEM && !id->mightBeType(MIRType_String) && types->noConstraints()) {
|
||||
// Indexed call on an element of an array. Populate the observed types
|
||||
// with any objects that could be in the array, to avoid extraneous
|
||||
// type barriers.
|
||||
AddObjectsForPropertyRead(cx, obj, NULL, types);
|
||||
}
|
||||
|
||||
bool barrier = PropertyReadNeedsTypeBarrier(cx, obj, NULL, types);
|
||||
bool needsHoleCheck = !ElementAccessIsPacked(cx, obj);
|
||||
|
||||
|
@ -2413,10 +2413,7 @@ ion::DenseNativeElementType(JSContext *cx, MDefinition *obj)
|
||||
unsigned count = types->getObjectCount();
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (types->getSingleObject(i))
|
||||
return MIRType_None;
|
||||
|
||||
if (types::TypeObject *object = types->getTypeObject(i)) {
|
||||
if (types::TypeObject *object = types->getTypeOrSingleObject(cx, i)) {
|
||||
if (object->unknownProperties())
|
||||
return MIRType_None;
|
||||
|
||||
@ -2518,17 +2515,8 @@ ion::PropertyReadNeedsTypeBarrier(JSContext *cx, MDefinition *obj, PropertyName
|
||||
|
||||
bool updateObserved = types->getObjectCount() == 1;
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeObject *object = types->getTypeObject(i);
|
||||
if (!object) {
|
||||
JSObject *singleton = types->getSingleObject(i);
|
||||
if (!singleton)
|
||||
continue;
|
||||
object = singleton->getType(cx);
|
||||
if (!object)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (PropertyReadNeedsTypeBarrier(cx, object, name, observed, updateObserved))
|
||||
types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
|
||||
if (object && PropertyReadNeedsTypeBarrier(cx, object, name, observed, updateObserved))
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2547,10 +2535,7 @@ ion::PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *nam
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
if (types->getSingleObject(i))
|
||||
return false;
|
||||
|
||||
if (types::TypeObject *object = types->getTypeObject(i)) {
|
||||
if (types::TypeObject *object = types->getTypeOrSingleObject(cx, i)) {
|
||||
if (object->unknownProperties())
|
||||
return false;
|
||||
|
||||
@ -2564,6 +2549,48 @@ ion::PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *nam
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ion::AddObjectsForPropertyRead(JSContext *cx, MDefinition *obj, PropertyName *name,
|
||||
types::StackTypeSet *observed)
|
||||
{
|
||||
// Add objects to observed which *could* be observed by reading name from obj,
|
||||
// to hopefully avoid unnecessary type barriers and code invalidations.
|
||||
|
||||
JS_ASSERT(observed->noConstraints());
|
||||
|
||||
types::StackTypeSet *types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject()) {
|
||||
observed->addType(cx, types::Type::AnyObjectType());
|
||||
return;
|
||||
}
|
||||
|
||||
jsid id = name ? types::IdToTypeId(NameToId(name)) : JSID_VOID;
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
|
||||
if (!object)
|
||||
continue;
|
||||
|
||||
if (object->unknownProperties()) {
|
||||
observed->addType(cx, types::Type::AnyObjectType());
|
||||
return;
|
||||
}
|
||||
|
||||
types::HeapTypeSet *property = object->getProperty(cx, JSID_VOID, false);
|
||||
if (property->unknownObject()) {
|
||||
observed->addType(cx, types::Type::AnyObjectType());
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < property->getObjectCount(); i++) {
|
||||
if (types::TypeObject *object = property->getTypeObject(i))
|
||||
observed->addType(cx, types::Type::ObjectType(object));
|
||||
else if (JSObject *object = property->getSingleObject(i))
|
||||
observed->addType(cx, types::Type::ObjectType(object));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
TryAddTypeBarrierForWrite(JSContext *cx, MBasicBlock *current, types::StackTypeSet *objTypes,
|
||||
jsid id, MDefinition **pvalue)
|
||||
@ -2578,15 +2605,9 @@ TryAddTypeBarrierForWrite(JSContext *cx, MBasicBlock *current, types::StackTypeS
|
||||
types::HeapTypeSet *aggregateProperty = NULL;
|
||||
|
||||
for (size_t i = 0; i < objTypes->getObjectCount(); i++) {
|
||||
types::TypeObject *object = objTypes->getTypeObject(i);
|
||||
if (!object) {
|
||||
JSObject *singleton = objTypes->getSingleObject(i);
|
||||
if (!singleton)
|
||||
continue;
|
||||
object = singleton->getType(cx);
|
||||
if (!object)
|
||||
return false;
|
||||
}
|
||||
types::TypeObject *object = objTypes->getTypeOrSingleObject(cx, i);
|
||||
if (!object)
|
||||
continue;
|
||||
|
||||
if (object->unknownProperties())
|
||||
return false;
|
||||
@ -2683,19 +2704,8 @@ ion::PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinit
|
||||
|
||||
bool success = true;
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeObject *object = types->getTypeObject(i);
|
||||
if (!object) {
|
||||
JSObject *singleton = types->getSingleObject(i);
|
||||
if (!singleton)
|
||||
continue;
|
||||
object = singleton->getType(cx);
|
||||
if (!object) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (object->unknownProperties())
|
||||
types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
|
||||
if (!object || object->unknownProperties())
|
||||
continue;
|
||||
|
||||
types::HeapTypeSet *property = object->getProperty(cx, id, false);
|
||||
@ -2727,13 +2737,8 @@ ion::PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinit
|
||||
|
||||
types::TypeObject *excluded = NULL;
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeObject *object = types->getTypeObject(i);
|
||||
if (!object) {
|
||||
if (types->getSingleObject(i))
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
if (object->unknownProperties())
|
||||
types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
|
||||
if (!object || object->unknownProperties())
|
||||
continue;
|
||||
|
||||
types::HeapTypeSet *property = object->getProperty(cx, id, false);
|
||||
|
@ -8112,6 +8112,8 @@ bool PropertyReadNeedsTypeBarrier(JSContext *cx, types::TypeObject *object, Prop
|
||||
bool PropertyReadNeedsTypeBarrier(JSContext *cx, MDefinition *obj, PropertyName *name,
|
||||
types::StackTypeSet *observed);
|
||||
bool PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *name);
|
||||
void AddObjectsForPropertyRead(JSContext *cx, MDefinition *obj, PropertyName *name,
|
||||
types::StackTypeSet *observed);
|
||||
bool PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinition **pobj,
|
||||
PropertyName *name, MDefinition **pvalue,
|
||||
bool canModify = true);
|
||||
|
@ -496,6 +496,7 @@ class TypeSet
|
||||
inline TypeObjectKey *getObject(unsigned i) const;
|
||||
inline JSObject *getSingleObject(unsigned i) const;
|
||||
inline TypeObject *getTypeObject(unsigned i) const;
|
||||
inline TypeObject *getTypeOrSingleObject(JSContext *cx, unsigned i) const;
|
||||
|
||||
void setOwnProperty(bool configurable) {
|
||||
flags |= TYPE_FLAG_OWN_PROPERTY;
|
||||
|
@ -1560,6 +1560,22 @@ TypeSet::getTypeObject(unsigned i) const
|
||||
return (key && !(uintptr_t(key) & 1)) ? (TypeObject *) key : NULL;
|
||||
}
|
||||
|
||||
inline TypeObject *
|
||||
TypeSet::getTypeOrSingleObject(JSContext *cx, unsigned i) const
|
||||
{
|
||||
JS_ASSERT(cx->compartment->activeAnalysis);
|
||||
TypeObject *type = getTypeObject(i);
|
||||
if (!type) {
|
||||
JSObject *singleton = getSingleObject(i);
|
||||
if (!singleton)
|
||||
return NULL;
|
||||
type = singleton->getType(cx);
|
||||
if (!type)
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// TypeCallsite
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
x
Reference in New Issue
Block a user