Bug 1497107: Add ensureBallast call to freezePropertiesForCommonPrototype r=nbp

Differential Revision: https://phabricator.services.mozilla.com/D12184

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Iain Ireland 2018-11-19 12:54:06 +00:00
Родитель 518cff2972
Коммит f9a231f0e5
3 изменённых файлов: 70 добавлений и 20 удалений

Просмотреть файл

@ -0,0 +1,37 @@
function makeChain(n, base) {
var curr = base;
for (var i = 0; i < n; i++) {
curr = Object.create(curr);
var propname = "level" + i;
curr[propname] = true;
}
return curr;
}
function BaseClass() {
this.base = true;
}
Object.defineProperty(BaseClass.prototype, "getter", {get: function() { with({}){}; return this.base; }});
function victim(arg) {
if (arg.getter) {
return 3;
} else {
return 4;
}
}
let root = new BaseClass();
let chains = [];
for (var i = 0; i < 6; i++) {
chains.push(makeChain(500, root));
}
with({}){};
for (var i = 0; i < 1000 / 6; i++) {
with({}){};
for (var j = 0; j < chains.length; j++) {
victim(chains[j]);
}
}

Просмотреть файл

@ -10401,7 +10401,7 @@ IonBuilder::commonPrototypeWithGetterSetter(TemporaryTypeSet* types, PropertyNam
return foundProto;
}
void
AbortReasonOr<Ok>
IonBuilder::freezePropertiesForCommonPrototype(TemporaryTypeSet* types, PropertyName* name,
JSObject* foundProto,
bool allowEmptyTypesforGlobal/* = false*/)
@ -10419,6 +10419,10 @@ IonBuilder::freezePropertiesForCommonPrototype(TemporaryTypeSet* types, Property
}
while (true) {
if (!alloc().ensureBallast()) {
return abort(AbortReason::Alloc);
}
HeapTypeSetKey property = key->property(NameToId(name));
MOZ_ALWAYS_TRUE(!property.isOwnProperty(constraints(), allowEmptyTypesforGlobal));
@ -10431,9 +10435,10 @@ IonBuilder::freezePropertiesForCommonPrototype(TemporaryTypeSet* types, Property
key = TypeSet::ObjectKey::get(key->proto().toObjectOrNull());
}
}
return Ok();
}
bool
AbortReasonOr<bool>
IonBuilder::testCommonGetterSetter(TemporaryTypeSet* types, PropertyName* name,
bool isGetter, JSFunction* getterOrSetter,
MDefinition** guard,
@ -10455,7 +10460,7 @@ IonBuilder::testCommonGetterSetter(TemporaryTypeSet* types, PropertyName* name,
// We can optimize the getter/setter, so freeze all involved properties to
// ensure there isn't a lower shadowing getter or setter installed in the
// future.
freezePropertiesForCommonPrototype(types, name, foundProto, guardGlobal);
MOZ_TRY(freezePropertiesForCommonPrototype(types, name, foundProto, guardGlobal));
// Add a shape guard on the prototype we found the property on. The rest of
// the prototype chain is guarded by TI freezes, except when name is a global
@ -11518,9 +11523,10 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
if (!isOwnProperty) {
// If it's not an own property, try to use TI to avoid shape guards.
// For own properties we use the path below.
canUseTIForGetter = testCommonGetterSetter(objTypes, name, /* isGetter = */ true,
commonGetter, &guard,
globalShape, &globalGuard);
MOZ_TRY_VAR(canUseTIForGetter,
testCommonGetterSetter(objTypes, name, /* isGetter = */ true,
commonGetter, &guard,
globalShape, &globalGuard));
}
if (!canUseTIForGetter) {
// If it's an own property or type information is bad, we can still
@ -11536,9 +11542,11 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
&commonGetter))
{
// Try to use TI to guard on this getter.
if (!testCommonGetterSetter(objTypes, name, /* isGetter = */ true,
commonGetter, &guard))
{
bool canUseTIForGetter = false;
MOZ_TRY_VAR(canUseTIForGetter,
testCommonGetterSetter(objTypes, name, /* isGetter = */ true,
commonGetter, &guard));
if (!canUseTIForGetter) {
return Ok();
}
} else {
@ -12183,8 +12191,9 @@ IonBuilder::setPropTryCommonSetter(bool* emitted, MDefinition* obj,
if (!isOwnProperty) {
// If it's not an own property, try to use TI to avoid shape guards.
// For own properties we use the path below.
canUseTIForSetter = testCommonGetterSetter(objTypes, name, /* isGetter = */ false,
commonSetter, &guard);
MOZ_TRY_VAR(canUseTIForSetter,
testCommonGetterSetter(objTypes, name, /* isGetter = */ false,
commonSetter, &guard));
}
if (!canUseTIForSetter) {
// If it's an own property or type information is bad, we can still
@ -12200,9 +12209,11 @@ IonBuilder::setPropTryCommonSetter(bool* emitted, MDefinition* obj,
&commonSetter))
{
// Try to use TI to guard on this setter.
if (!testCommonGetterSetter(objTypes, name, /* isGetter = */ false,
commonSetter, &guard))
{
bool canUseTIForSetter = false;
MOZ_TRY_VAR(canUseTIForSetter,
testCommonGetterSetter(objTypes, name, /* isGetter = */ false,
commonSetter, &guard));
if (!canUseTIForSetter) {
return Ok();
}
} else {

Просмотреть файл

@ -808,15 +808,17 @@ class IonBuilder
NativeObject* commonPrototypeWithGetterSetter(TemporaryTypeSet* types, PropertyName* name,
bool isGetter, JSFunction* getterOrSetter,
bool* guardGlobal);
void freezePropertiesForCommonPrototype(TemporaryTypeSet* types, PropertyName* name,
JSObject* foundProto, bool allowEmptyTypesForGlobal = false);
AbortReasonOr<Ok> freezePropertiesForCommonPrototype(TemporaryTypeSet* types,
PropertyName* name, JSObject* foundProto,
bool allowEmptyTypesForGlobal = false);
/*
* Callers must pass a non-null globalGuard if they pass a non-null globalShape.
*/
bool testCommonGetterSetter(TemporaryTypeSet* types, PropertyName* name,
bool isGetter, JSFunction* getterOrSetter,
MDefinition** guard, Shape* globalShape = nullptr,
MDefinition** globalGuard = nullptr);
AbortReasonOr<bool> testCommonGetterSetter(TemporaryTypeSet* types, PropertyName* name,
bool isGetter, JSFunction* getterOrSetter,
MDefinition** guard,
Shape* globalShape = nullptr,
MDefinition** globalGuard = nullptr);
AbortReasonOr<bool> testShouldDOMCall(TypeSet* inTypes,
JSFunction* func, JSJitInfo::OpType opType);