mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 911708 - Check non-object Ion-specialized types statically in ICs. (r=bhackett)
This commit is contained in:
parent
e04dce65ad
commit
464fee6713
8
js/src/jit-test/tests/ion/bug911708.js
Normal file
8
js/src/jit-test/tests/ion/bug911708.js
Normal file
@ -0,0 +1,8 @@
|
||||
function x() {
|
||||
yield x
|
||||
}
|
||||
new(x)
|
||||
ParallelArray([7247], function() {
|
||||
--x
|
||||
eval("")
|
||||
})
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -620,6 +620,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
Register extractObject(const TypedOrValueRegister ®, Register scratch) {
|
||||
if (reg.hasValue())
|
||||
return extractObject(reg.valueReg(), scratch);
|
||||
JS_ASSERT(reg.type() == MIRType_Object);
|
||||
return reg.typedReg().gpr();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user