зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
518cff2972
Коммит
f9a231f0e5
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче