Bug 1096016 - Fix post barrier insertion for MStoreUnboxedObjectOrNull, r=nmatsakis.

This commit is contained in:
Brian Hackett 2014-11-16 17:10:24 -07:00
parent 7f8acfe395
commit 4b75bdf2e6
6 changed files with 81 additions and 49 deletions

View File

@ -0,0 +1,13 @@
if (typeof TypedObject === "undefined")
quit();
var T = TypedObject;
var ObjectStruct = new T.StructType({f: T.Object});
var o = new ObjectStruct();
function testGC(o, p) {
for (var i = 0; i < 5; i++) {
minorgc();
o.f >>= p;
}
}
testGC(o, {});

View File

@ -11321,9 +11321,6 @@ IonBuilder::storeReferenceTypedObjectValue(MDefinition *typedObj,
ReferenceTypeDescr::Type type,
MDefinition *value)
{
if (NeedsPostBarrier(info(), value))
current->add(MPostWriteBarrier::New(alloc(), typedObj, value));
// Find location within the owner object.
MDefinition *elements, *scaledOffset;
size_t alignment = ReferenceTypeDescr::alignment(type);
@ -11332,12 +11329,20 @@ IonBuilder::storeReferenceTypedObjectValue(MDefinition *typedObj,
MInstruction *store;
switch (type) {
case ReferenceTypeDescr::TYPE_ANY:
if (NeedsPostBarrier(info(), value))
current->add(MPostWriteBarrier::New(alloc(), typedObj, value));
store = MStoreElement::New(alloc(), elements, scaledOffset, value, false);
break;
case ReferenceTypeDescr::TYPE_OBJECT:
store = MStoreUnboxedObjectOrNull::New(alloc(), elements, scaledOffset, value);
// Note: We cannot necessarily tell at this point whether a post
// barrier is needed, because the type policy may insert ToObjectOrNull
// instructions later, and those may require a post barrier. Therefore,
// defer the insertion of post barriers to the type policy.
store = MStoreUnboxedObjectOrNull::New(alloc(), elements, scaledOffset, value, typedObj);
break;
case ReferenceTypeDescr::TYPE_STRING:
// Strings are not nursery allocated, so these writes do not need post
// barriers.
store = MStoreUnboxedString::New(alloc(), elements, scaledOffset, value);
break;
}

View File

@ -2456,7 +2456,8 @@ LIRGenerator::visitPostWriteBarrier(MPostWriteBarrier *ins)
{
#ifdef JSGC_GENERATIONAL
switch (ins->value()->type()) {
case MIRType_Object: {
case MIRType_Object:
case MIRType_ObjectOrNull: {
LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
LPostWriteBarrierO *lir =
new(alloc()) LPostWriteBarrierO(useRegisterOrConstant(ins->object()),

View File

@ -8004,15 +8004,18 @@ class MStoreElementHole
// Store an unboxed object or null pointer to a vector.
class MStoreUnboxedObjectOrNull
: public MAryInstruction<3>,
public ConvertToObjectOrNullPolicy<2>::Data
: public MAryInstruction<4>,
public StoreUnboxedObjectOrNullPolicy::Data
{
MStoreUnboxedObjectOrNull(MDefinition *elements, MDefinition *index, MDefinition *value) {
MStoreUnboxedObjectOrNull(MDefinition *elements, MDefinition *index,
MDefinition *value, MDefinition *typedObj) {
initOperand(0, elements);
initOperand(1, index);
initOperand(2, value);
initOperand(3, typedObj);
MOZ_ASSERT(elements->type() == MIRType_Elements);
MOZ_ASSERT(index->type() == MIRType_Int32);
MOZ_ASSERT(typedObj->type() == MIRType_Object);
}
public:
@ -8020,8 +8023,8 @@ class MStoreUnboxedObjectOrNull
static MStoreUnboxedObjectOrNull *New(TempAllocator &alloc,
MDefinition *elements, MDefinition *index,
MDefinition *value) {
return new(alloc) MStoreUnboxedObjectOrNull(elements, index, value);
MDefinition *value, MDefinition *typedObj) {
return new(alloc) MStoreUnboxedObjectOrNull(elements, index, value, typedObj);
}
MDefinition *elements() const {
return getOperand(0);
@ -8032,11 +8035,19 @@ class MStoreUnboxedObjectOrNull
MDefinition *value() const {
return getOperand(2);
}
MDefinition *typedObj() const {
return getOperand(3);
}
AliasSet getAliasSet() const {
// Use AliasSet::Element for reference typed object fields.
return AliasSet::Store(AliasSet::Element);
}
// For StoreUnboxedObjectOrNullPolicy.
void setValue(MDefinition *def) {
replaceOperand(2, def);
}
ALLOW_CLONE(MStoreUnboxedObjectOrNull)
};

View File

@ -407,31 +407,6 @@ template bool ConvertToStringPolicy<0>::staticAdjustInputs(TempAllocator &alloc,
template bool ConvertToStringPolicy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
template bool ConvertToStringPolicy<2>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
template <unsigned Op>
bool
ConvertToObjectOrNullPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
{
MDefinition *in = ins->getOperand(Op);
if (in->type() == MIRType_Object ||
in->type() == MIRType_Null ||
in->type() == MIRType_ObjectOrNull)
{
return true;
}
MToObjectOrNull *replace = MToObjectOrNull::New(alloc, in);
ins->block()->insertBefore(ins, replace);
ins->replaceOperand(Op, replace);
if (!BoxPolicy<0>::staticAdjustInputs(alloc, replace))
return false;
return true;
}
template bool ConvertToObjectOrNullPolicy<2>::staticAdjustInputs(TempAllocator &alloc,
MInstruction *ins);
template <unsigned Op>
bool
IntPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def)
@ -869,6 +844,39 @@ StoreTypedArrayElementStaticPolicy::adjustInputs(TempAllocator &alloc, MInstruct
adjustValueInput(alloc, ins, store->viewType(), store->value(), 1);
}
bool
StoreUnboxedObjectOrNullPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
{
// Change the value input to a ToObjectOrNull instruction if it might be
// a non-null primitive. Insert a post barrier for the instruction's object
// and whatever its new value is, unless the value is definitely null.
MStoreUnboxedObjectOrNull *store = ins->toStoreUnboxedObjectOrNull();
MDefinition *value = store->value();
if (value->type() == MIRType_Object ||
value->type() == MIRType_Null ||
value->type() == MIRType_ObjectOrNull)
{
if (value->type() != MIRType_Null) {
MInstruction *barrier = MPostWriteBarrier::New(alloc, store->typedObj(), value);
store->block()->insertBefore(store, barrier);
}
return true;
}
MToObjectOrNull *replace = MToObjectOrNull::New(alloc, value);
store->block()->insertBefore(store, replace);
store->setValue(replace);
if (!BoxPolicy<0>::staticAdjustInputs(alloc, replace))
return false;
MInstruction *barrier = MPostWriteBarrier::New(alloc, store->typedObj(), replace);
store->block()->insertBefore(store, barrier);
return true;
}
bool
ClampPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
{
@ -956,6 +964,7 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
_(StoreTypedArrayElementStaticPolicy) \
_(StoreTypedArrayHolePolicy) \
_(StoreTypedArrayPolicy) \
_(StoreUnboxedObjectOrNullPolicy) \
_(TestPolicy) \
_(ToDoublePolicy) \
_(ToInt32Policy) \
@ -968,7 +977,6 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
_(ConvertToInt32Policy<0>) \
_(ConvertToStringPolicy<0>) \
_(ConvertToStringPolicy<2>) \
_(ConvertToObjectOrNullPolicy<2>) \
_(DoublePolicy<0>) \
_(FloatingPointPolicy<0>) \
_(IntPolicy<0>) \

View File

@ -148,19 +148,6 @@ class ConvertToStringPolicy : public TypePolicy
}
};
// Expect an object or null value for operand Op. Else a ToObjectOrNull
// instruction is inserted.
template <unsigned Op>
class ConvertToObjectOrNullPolicy : public TypePolicy
{
public:
EMPTY_DATA_;
static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
return staticAdjustInputs(alloc, def);
}
};
// Expect an Int for operand Op. If the input is a Value, it is unboxed.
template <unsigned Op>
class IntPolicy : public BoxInputsPolicy
@ -397,6 +384,13 @@ class StoreTypedArrayElementStaticPolicy : public StoreTypedArrayPolicy
bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
};
class StoreUnboxedObjectOrNullPolicy : public TypePolicy
{
public:
EMPTY_DATA_;
bool adjustInputs(TempAllocator &alloc, MInstruction *def);
};
// Accepts integers and doubles. Everything else is boxed.
class ClampPolicy : public BoxInputsPolicy
{