Bug 911708 - Check non-object Ion-specialized types statically in ICs. (r=bhackett)

This commit is contained in:
Eric Faust 2013-09-09 16:25:56 -07:00
parent e04dce65ad
commit 464fee6713
4 changed files with 54 additions and 25 deletions

View File

@ -0,0 +1,8 @@
function x() {
yield x
}
new(x)
ParallelArray([7247], function() {
--x
eval("")
})

View File

@ -1946,8 +1946,8 @@ IonCache::destroy()
}
bool
SetPropertyIC::attachNativeExisting(JSContext *cx, IonScript *ion,
HandleObject obj, HandleShape shape)
SetPropertyIC::attachNativeExisting(JSContext *cx, IonScript *ion, HandleObject obj,
HandleShape shape, bool checkTypeset)
{
JS_ASSERT(obj->isNative());
@ -1961,7 +1961,7 @@ SetPropertyIC::attachNativeExisting(JSContext *cx, IonScript *ion,
// Guard that the incoming value is in the type set for the property
// if a type barrier is required.
if (needsTypeBarrier() && !value().constant()) {
if (needsTypeBarrier()) {
// We can't do anything that would change the HeapTypeSet, so
// just guard that it's already there.
@ -1971,29 +1971,28 @@ SetPropertyIC::attachNativeExisting(JSContext *cx, IonScript *ion,
Address(object(), JSObject::offsetOfType()),
ImmGCPtr(type), &failures);
if (!type->unknownProperties()) {
if (checkTypeset) {
TypedOrValueRegister valReg = value().reg();
RootedId id(cx, types::IdToTypeId(AtomToId(name())));
types::HeapTypeSet *propTypes = type->maybeGetProperty(cx, id);
JS_ASSERT(propTypes);
JS_ASSERT(!propTypes->unknown());
if (!propTypes->unknown()) {
Label barrierSuccess;
Label barrierFailure;
Label barrierSuccess;
Label barrierFailure;
Register scratchReg = object();
masm.push(scratchReg);
Register scratchReg = object();
masm.push(scratchReg);
masm.guardTypeSet(valReg, propTypes, scratchReg,
&barrierSuccess, &barrierFailure);
masm.guardTypeSet(valReg, propTypes, scratchReg,
&barrierSuccess, &barrierFailure);
masm.bind(&barrierFailure);
masm.pop(object());
masm.jump(&failures);
masm.bind(&barrierFailure);
masm.pop(object());
masm.jump(&failures);
masm.bind(&barrierSuccess);
masm.pop(object());
}
masm.bind(&barrierSuccess);
masm.pop(object());
}
}
@ -2605,7 +2604,7 @@ SetPropertyIC::attachNativeAdding(JSContext *cx, IonScript *ion, JSObject *obj,
static bool
IsPropertySetInlineable(JSContext *cx, const SetPropertyIC &cache, HandleObject obj,
HandleId id, MutableHandleShape pshape)
HandleId id, MutableHandleShape pshape, bool *checkTypeset)
{
if (!obj->isNative())
return false;
@ -2624,20 +2623,39 @@ IsPropertySetInlineable(JSContext *cx, const SetPropertyIC &cache, HandleObject
if (!shape->writable())
return false;
bool shouldCheck = false;
types::TypeObject *type = obj->getType(cx);
if (cache.needsTypeBarrier() && !type->unknownProperties()) {
RootedId typeId(cx, types::IdToTypeId(id));
types::HeapTypeSet *propTypes = type->maybeGetProperty(cx, typeId);
if (!propTypes)
return false;
if (cache.value().constant() && !propTypes->unknown()) {
// If the input is a constant, then don't bother if the barrier will always fail.
if (!propTypes->hasType(types::GetValueType(cache.value().value())))
return false;
if (!propTypes->unknown()) {
shouldCheck = true;
ConstantOrRegister val = cache.value();
if (val.constant()) {
// If the input is a constant, then don't bother if the barrier will always fail.
if (!propTypes->hasType(types::GetValueType(cache.value().value())))
return false;
shouldCheck = false;
} else {
TypedOrValueRegister reg = val.reg();
// We can do the same trick as above for primitive types of specialized registers.
// TIs handling of objects is complicated enough to warrant a runtime
// check, as we can't statically handle the case where the typeset
// contains the specific object, but doesn't have ANYOBJECT set.
if (reg.hasTyped() && reg.type() != MIRType_Object) {
JSValueType valType = ValueTypeFromMIRType(reg.type());
if (!propTypes->hasType(types::Type::PrimitiveType(valType)))
return false;
shouldCheck = false;
}
}
}
}
pshape.set(shape);
*checkTypeset = shouldCheck;
return true;
}
@ -2744,8 +2762,9 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
}
}
RootedShape shape(cx);
if (!addedSetterStub && IsPropertySetInlineable(cx, cache, obj, id, &shape)) {
if (!cache.attachNativeExisting(cx, ion, obj, shape))
bool checkTypeset;
if (!addedSetterStub && IsPropertySetInlineable(cx, cache, obj, id, &shape, &checkTypeset)) {
if (!cache.attachNativeExisting(cx, ion, obj, shape, checkTypeset))
return false;
addedSetterStub = true;
} else if (!addedSetterStub) {

View File

@ -687,7 +687,8 @@ class SetPropertyIC : public RepatchIonCache
return hasGenericProxyStub_;
}
bool attachNativeExisting(JSContext *cx, IonScript *ion, HandleObject obj, HandleShape shape);
bool attachNativeExisting(JSContext *cx, IonScript *ion, HandleObject obj,
HandleShape shape, bool checkTypeset);
bool attachSetterCall(JSContext *cx, IonScript *ion, HandleObject obj,
HandleObject holder, HandleShape shape, void *returnAddr);
bool attachNativeAdding(JSContext *cx, IonScript *ion, JSObject *obj, HandleShape oldshape,

View File

@ -620,6 +620,7 @@ class MacroAssembler : public MacroAssemblerSpecific
Register extractObject(const TypedOrValueRegister &reg, Register scratch) {
if (reg.hasValue())
return extractObject(reg.valueReg(), scratch);
JS_ASSERT(reg.type() == MIRType_Object);
return reg.typedReg().gpr();
}