Bug 870821 - Seed observed values for integer CALLELEM ops with the possible targets, r=jandem.

This commit is contained in:
Brian Hackett 2013-05-22 16:48:19 -06:00
parent 4a0ec07f52
commit d836361354
5 changed files with 80 additions and 48 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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
/////////////////////////////////////////////////////////////////////