mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 08:42:13 +00:00
Bug 1225821 - Add type write barrier to SetPropertyIC dense element stub. r=bhackett
This commit is contained in:
parent
ba8444d785
commit
2c74f213c1
22
js/src/jit-test/tests/ion/dense-elem-write-barrier.js
Normal file
22
js/src/jit-test/tests/ion/dense-elem-write-barrier.js
Normal file
@ -0,0 +1,22 @@
|
||||
var arr = [];
|
||||
for (var i=0; i<20; i++) {
|
||||
arr.push(new Int32Array(2000));
|
||||
}
|
||||
arr.push([null, null]);
|
||||
|
||||
function test(o, x) {
|
||||
assertEq(o[0], x);
|
||||
}
|
||||
|
||||
function f() {
|
||||
for (var i=0; i<3100; i++) {
|
||||
var o = arr[i % arr.length];
|
||||
if (o.length > 10 || i > 2000) {
|
||||
var val = (i > 3000 ? 1 : null);
|
||||
o[0] = val;
|
||||
if (o.length < 5)
|
||||
test(o, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
f();
|
@ -9863,17 +9863,11 @@ IonBuilder::setElemTryCache(bool* emitted, MDefinition* object,
|
||||
|
||||
bool barrier = true;
|
||||
|
||||
if (index->mightBeType(MIRType_Int32)) {
|
||||
// Bail if we might have a barriered write to a dense element, as the
|
||||
// dense element stub doesn't support this yet.
|
||||
if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
|
||||
&object, nullptr, &value, /* canModify = */ true))
|
||||
{
|
||||
trackOptimizationOutcome(TrackedOutcome::NeedsTypeBarrier);
|
||||
return true;
|
||||
}
|
||||
if (index->type() == MIRType_Int32)
|
||||
barrier = false;
|
||||
if (index->type() == MIRType_Int32 &&
|
||||
!PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
|
||||
&object, nullptr, &value, /* canModify = */ true))
|
||||
{
|
||||
barrier = false;
|
||||
}
|
||||
|
||||
// We can avoid worrying about holes in the IC if we know a priori we are safe
|
||||
@ -9890,7 +9884,7 @@ IonBuilder::setElemTryCache(bool* emitted, MDefinition* object,
|
||||
if (NeedsPostBarrier(info(), value))
|
||||
current->add(MPostWriteBarrier::New(alloc(), object, value));
|
||||
|
||||
// Emit SetElementCache.
|
||||
// Emit SetPropertyCache.
|
||||
bool strict = JSOp(*pc) == JSOP_STRICTSETELEM;
|
||||
MSetPropertyCache* ins =
|
||||
MSetPropertyCache::New(alloc(), object, index, value, strict, barrier, guardHoles);
|
||||
|
@ -2251,8 +2251,8 @@ CheckTypeSetForWrite(MacroAssembler& masm, JSObject* obj, jsid id,
|
||||
{
|
||||
TypedOrValueRegister valReg = value.reg();
|
||||
ObjectGroup* group = obj->group();
|
||||
if (group->unknownProperties())
|
||||
return;
|
||||
MOZ_ASSERT(!group->unknownProperties());
|
||||
|
||||
HeapTypeSet* propTypes = group->maybeGetProperty(id);
|
||||
MOZ_ASSERT(propTypes);
|
||||
|
||||
@ -2272,11 +2272,9 @@ GenerateSetSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
|
||||
|
||||
// Guard that the incoming value is in the type set for the property
|
||||
// if a type barrier is required.
|
||||
if (needsTypeBarrier) {
|
||||
// We can't do anything that would change the HeapTypeSet, so
|
||||
// just guard that it's already there.
|
||||
if (checkTypeset)
|
||||
CheckTypeSetForWrite(masm, obj, shape->propid(), tempReg, value, failures);
|
||||
if (checkTypeset) {
|
||||
MOZ_ASSERT(needsTypeBarrier);
|
||||
CheckTypeSetForWrite(masm, obj, shape->propid(), tempReg, value, failures);
|
||||
}
|
||||
|
||||
NativeObject::slotsSizeMustNotOverflow();
|
||||
@ -3131,8 +3129,9 @@ IsPropertySetInlineable(NativeObject* obj, HandleId id, MutableHandleShape pshap
|
||||
if (!pshape->writable())
|
||||
return false;
|
||||
|
||||
if (needsTypeBarrier)
|
||||
return CanInlineSetPropTypeCheck(obj, id, val, checkTypeset);
|
||||
*checkTypeset = false;
|
||||
if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, id, val, checkTypeset))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -3199,10 +3198,10 @@ IsPropertyAddInlineable(JSContext* cx, NativeObject* obj, HandleId id, ConstantO
|
||||
if (obj->group()->newScript() && !obj->group()->newScript()->analyzed())
|
||||
return false;
|
||||
|
||||
if (needsTypeBarrier)
|
||||
return CanInlineSetPropTypeCheck(obj, id, val, checkTypeset);
|
||||
|
||||
*checkTypeset = false;
|
||||
if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, id, val, checkTypeset))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3289,6 +3288,7 @@ CanAttachSetUnboxed(JSContext* cx, HandleObject obj, HandleId id, ConstantOrRegi
|
||||
|
||||
const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(id);
|
||||
if (property) {
|
||||
*checkTypeset = false;
|
||||
if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, id, val, checkTypeset))
|
||||
return false;
|
||||
*unboxedOffset = property->offset;
|
||||
@ -3314,6 +3314,7 @@ CanAttachSetUnboxedExpando(JSContext* cx, HandleObject obj, HandleId id, Constan
|
||||
if (!shape || !shape->hasDefaultSetter() || !shape->hasSlot() || !shape->writable())
|
||||
return false;
|
||||
|
||||
*checkTypeset = false;
|
||||
if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, id, val, checkTypeset))
|
||||
return false;
|
||||
|
||||
@ -3342,6 +3343,7 @@ CanAttachAddUnboxedExpando(JSContext* cx, HandleObject obj, HandleShape oldShape
|
||||
if (PrototypeChainShadowsPropertyAdd(cx, obj, id))
|
||||
return false;
|
||||
|
||||
*checkTypeset = false;
|
||||
if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, id, val, checkTypeset))
|
||||
return false;
|
||||
|
||||
@ -3426,7 +3428,7 @@ SetPropertyIC::tryAttachNative(JSContext* cx, HandleScript outerScript, IonScrip
|
||||
|
||||
RootedShape shape(cx);
|
||||
RootedObject holder(cx);
|
||||
bool checkTypeset;
|
||||
bool checkTypeset = false;
|
||||
NativeSetPropCacheability canCache = CanAttachNativeSetProp(cx, obj, id, value(), needsTypeBarrier(),
|
||||
&holder, &shape, &checkTypeset);
|
||||
switch (canCache) {
|
||||
@ -4180,7 +4182,8 @@ GetPropertyIC::tryAttachArgumentsElement(JSContext* cx, HandleScript outerScript
|
||||
}
|
||||
|
||||
static bool
|
||||
IsDenseElementSetInlineable(JSObject* obj, const Value& idval)
|
||||
IsDenseElementSetInlineable(JSObject* obj, const Value& idval, ConstantOrRegister val,
|
||||
bool needsTypeBarrier, bool* checkTypeset)
|
||||
{
|
||||
if (!obj->is<ArrayObject>())
|
||||
return false;
|
||||
@ -4208,6 +4211,10 @@ IsDenseElementSetInlineable(JSObject* obj, const Value& idval)
|
||||
curObj = curObj->getProto();
|
||||
}
|
||||
|
||||
*checkTypeset = false;
|
||||
if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, JSID_VOID, val, checkTypeset))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4277,7 +4284,7 @@ static bool
|
||||
GenerateSetDenseElement(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
|
||||
JSObject* obj, const Value& idval, bool guardHoles, Register object,
|
||||
TypedOrValueRegister index, ConstantOrRegister value, Register tempToUnboxIndex,
|
||||
Register temp)
|
||||
Register temp, bool needsTypeBarrier, bool checkTypeset)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
MOZ_ASSERT(idval.isInt32());
|
||||
@ -4290,6 +4297,14 @@ GenerateSetDenseElement(JSContext* cx, MacroAssembler& masm, IonCache::StubAttac
|
||||
return false;
|
||||
masm.branchTestObjShape(Assembler::NotEqual, object, shape, &failures);
|
||||
|
||||
// Guard that the incoming value is in the type set for the property
|
||||
// if a type barrier is required.
|
||||
if (needsTypeBarrier) {
|
||||
masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), &failures);
|
||||
if (checkTypeset)
|
||||
CheckTypeSetForWrite(masm, obj, JSID_VOID, temp, value, &failures);
|
||||
}
|
||||
|
||||
// Ensure the index is an int32 value.
|
||||
Register indexReg;
|
||||
if (index.hasValue()) {
|
||||
@ -4377,7 +4392,11 @@ SetPropertyIC::tryAttachDenseElement(JSContext* cx, HandleScript outerScript, Io
|
||||
MOZ_ASSERT(!*emitted);
|
||||
MOZ_ASSERT(canAttachStub());
|
||||
|
||||
if (hasDenseStub() || !IsDenseElementSetInlineable(obj, idval))
|
||||
if (hasDenseStub())
|
||||
return true;
|
||||
|
||||
bool checkTypeset = false;
|
||||
if (!IsDenseElementSetInlineable(obj, idval, value(), needsTypeBarrier(), &checkTypeset))
|
||||
return true;
|
||||
|
||||
*emitted = true;
|
||||
@ -4386,7 +4405,8 @@ SetPropertyIC::tryAttachDenseElement(JSContext* cx, HandleScript outerScript, Io
|
||||
StubAttacher attacher(*this);
|
||||
if (!GenerateSetDenseElement(cx, masm, attacher, obj, idval,
|
||||
guardHoles(), object(), id().reg(),
|
||||
value(), tempToUnboxIndex(), temp()))
|
||||
value(), tempToUnboxIndex(), temp(),
|
||||
needsTypeBarrier(), checkTypeset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user