mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1096016
- Fix post barrier insertion for MStoreUnboxedObjectOrNull, r=nmatsakis.
This commit is contained in:
parent
7f8acfe395
commit
4b75bdf2e6
13
js/src/jit-test/tests/TypedObject/bug1096016.js
Normal file
13
js/src/jit-test/tests/TypedObject/bug1096016.js
Normal 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, {});
|
@ -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;
|
||||
}
|
||||
|
@ -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()),
|
||||
|
@ -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)
|
||||
};
|
||||
|
||||
|
@ -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>) \
|
||||
|
@ -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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user