mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1176751 - Eagerly convert unboxed arrays to native arrays more often during Ion compilation, r=jandem.
This commit is contained in:
parent
c2edf74b86
commit
1333cfd846
@ -7724,6 +7724,8 @@ IonBuilder::jsop_getelem()
|
||||
}
|
||||
|
||||
obj = maybeUnboxForPropertyAccess(obj);
|
||||
if (obj->type() == MIRType_Object)
|
||||
obj = convertUnboxedObjects(obj);
|
||||
|
||||
bool emitted = false;
|
||||
|
||||
@ -8766,7 +8768,7 @@ IonBuilder::jsop_setelem()
|
||||
|
||||
MDefinition* value = current->pop();
|
||||
MDefinition* index = current->pop();
|
||||
MDefinition* object = current->pop();
|
||||
MDefinition* object = convertUnboxedObjects(current->pop());
|
||||
|
||||
trackTypeInfo(TrackedTypeSite::Receiver, object->type(), object->resultTypeSet());
|
||||
trackTypeInfo(TrackedTypeSite::Index, index->type(), index->resultTypeSet());
|
||||
@ -9478,8 +9480,7 @@ IonBuilder::jsop_rest()
|
||||
}
|
||||
|
||||
uint32_t
|
||||
IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed,
|
||||
BaselineInspector::ObjectGroupVector& convertUnboxedGroups)
|
||||
IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed)
|
||||
{
|
||||
if (!types || types->unknownObject()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::NoTypeInfo);
|
||||
@ -9503,21 +9504,6 @@ IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
// If we encounter a group for an unboxed property which has a
|
||||
// corresponding native group, look for a definite slot in that native
|
||||
// group, and force conversion of incoming objects to the native group.
|
||||
if (key->isGroup() && key->group()->maybeUnboxedLayout()) {
|
||||
if (ObjectGroup* nativeGroup = key->group()->unboxedLayout().nativeGroup()) {
|
||||
if (!convertUnboxedGroups.append(key->group()))
|
||||
CrashAtUnhandlableOOM("IonBuilder::getDefiniteSlot");
|
||||
key = TypeSet::ObjectKey::get(nativeGroup);
|
||||
if (key->unknownProperties()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::UnknownProperties);
|
||||
return UINT32_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeapTypeSetKey property = key->property(NameToId(name));
|
||||
if (!property.maybeTypes() ||
|
||||
!property.maybeTypes()->definiteProperty() ||
|
||||
@ -10033,6 +10019,8 @@ IonBuilder::jsop_getprop(PropertyName* name)
|
||||
}
|
||||
|
||||
obj = maybeUnboxForPropertyAccess(obj);
|
||||
if (obj->type() == MIRType_Object)
|
||||
obj = convertUnboxedObjects(obj);
|
||||
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
obj, name, types);
|
||||
@ -10513,12 +10501,43 @@ IonBuilder::getPropTryComplexPropOfTypedObject(bool* emitted,
|
||||
fieldPrediction, fieldTypeObj);
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
IonBuilder::convertUnboxedObjects(MDefinition* obj)
|
||||
{
|
||||
// If obj might be in any particular unboxed group which should be
|
||||
// converted to a native representation, perform that conversion. This does
|
||||
// not guarantee the object will not have such a group afterwards, if the
|
||||
// object's possible groups are not precisely known.
|
||||
TemporaryTypeSet* types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return obj;
|
||||
|
||||
BaselineInspector::ObjectGroupVector list(alloc());
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
TypeSet::ObjectKey* key = obj->resultTypeSet()->getObject(i);
|
||||
if (!key || !key->isGroup())
|
||||
continue;
|
||||
|
||||
if (UnboxedLayout* layout = key->group()->maybeUnboxedLayout()) {
|
||||
if (layout->nativeGroup() && !list.append(key->group()))
|
||||
CrashAtUnhandlableOOM("IonBuilder::convertUnboxedObjects");
|
||||
}
|
||||
}
|
||||
|
||||
return convertUnboxedObjects(obj, list);
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
IonBuilder::convertUnboxedObjects(MDefinition* obj,
|
||||
const BaselineInspector::ObjectGroupVector& list)
|
||||
{
|
||||
for (size_t i = 0; i < list.length(); i++) {
|
||||
obj = MConvertUnboxedObjectToNative::New(alloc(), obj, list[i]);
|
||||
ObjectGroup* group = list[i];
|
||||
if (TemporaryTypeSet* types = obj->resultTypeSet()) {
|
||||
if (!types->hasType(TypeSet::ObjectType(group)))
|
||||
continue;
|
||||
}
|
||||
obj = MConvertUnboxedObjectToNative::New(alloc(), obj, group);
|
||||
current->add(obj->toInstruction());
|
||||
}
|
||||
return obj;
|
||||
@ -10530,10 +10549,8 @@ IonBuilder::getPropTryDefiniteSlot(bool* emitted, MDefinition* obj, PropertyName
|
||||
{
|
||||
MOZ_ASSERT(*emitted == false);
|
||||
|
||||
BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
|
||||
|
||||
uint32_t nfixed;
|
||||
uint32_t slot = getDefiniteSlot(obj->resultTypeSet(), name, &nfixed, convertUnboxedGroups);
|
||||
uint32_t slot = getDefiniteSlot(obj->resultTypeSet(), name, &nfixed);
|
||||
if (slot == UINT32_MAX)
|
||||
return true;
|
||||
|
||||
@ -10543,8 +10560,6 @@ IonBuilder::getPropTryDefiniteSlot(bool* emitted, MDefinition* obj, PropertyName
|
||||
obj = guard;
|
||||
}
|
||||
|
||||
obj = convertUnboxedObjects(obj, convertUnboxedGroups);
|
||||
|
||||
MInstruction* load;
|
||||
if (slot < nfixed) {
|
||||
load = MLoadFixedSlot::New(alloc(), obj, slot);
|
||||
@ -11151,7 +11166,7 @@ bool
|
||||
IonBuilder::jsop_setprop(PropertyName* name)
|
||||
{
|
||||
MDefinition* value = current->pop();
|
||||
MDefinition* obj = current->pop();
|
||||
MDefinition* obj = convertUnboxedObjects(current->pop());
|
||||
|
||||
bool emitted = false;
|
||||
startTrackingOptimizations();
|
||||
@ -11450,10 +11465,8 @@ IonBuilder::setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
|
||||
return true;
|
||||
}
|
||||
|
||||
BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
|
||||
|
||||
uint32_t nfixed;
|
||||
uint32_t slot = getDefiniteSlot(obj->resultTypeSet(), name, &nfixed, convertUnboxedGroups);
|
||||
uint32_t slot = getDefiniteSlot(obj->resultTypeSet(), name, &nfixed);
|
||||
if (slot == UINT32_MAX)
|
||||
return true;
|
||||
|
||||
@ -11471,8 +11484,6 @@ IonBuilder::setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
|
||||
writeBarrier |= property.needsBarrier(constraints());
|
||||
}
|
||||
|
||||
obj = convertUnboxedObjects(obj, convertUnboxedGroups);
|
||||
|
||||
MInstruction* store;
|
||||
if (slot < nfixed) {
|
||||
store = MStoreFixedSlot::New(alloc(), obj, slot, value);
|
||||
@ -12308,8 +12319,8 @@ IonBuilder::jsop_setaliasedvar(ScopeCoordinate sc)
|
||||
bool
|
||||
IonBuilder::jsop_in()
|
||||
{
|
||||
MDefinition* obj = current->peek(-1);
|
||||
MDefinition* id = current->peek(-2);
|
||||
MDefinition* obj = convertUnboxedObjects(current->pop());
|
||||
MDefinition* id = current->pop();
|
||||
|
||||
do {
|
||||
if (shouldAbortOnPreliminaryGroups(obj))
|
||||
@ -12324,11 +12335,9 @@ IonBuilder::jsop_in()
|
||||
if (ElementAccessHasExtraIndexedProperty(constraints(), obj))
|
||||
break;
|
||||
|
||||
return jsop_in_dense(unboxedType);
|
||||
return jsop_in_dense(obj, id, unboxedType);
|
||||
} while (false);
|
||||
|
||||
current->pop();
|
||||
current->pop();
|
||||
MIn* ins = MIn::New(alloc(), id, obj);
|
||||
|
||||
current->add(ins);
|
||||
@ -12338,11 +12347,8 @@ IonBuilder::jsop_in()
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_in_dense(JSValueType unboxedType)
|
||||
IonBuilder::jsop_in_dense(MDefinition* obj, MDefinition* id, JSValueType unboxedType)
|
||||
{
|
||||
MDefinition* obj = current->pop();
|
||||
MDefinition* id = current->pop();
|
||||
|
||||
bool needsHoleCheck = !ElementAccessIsPacked(constraints(), obj);
|
||||
|
||||
// Ensure id is an integer.
|
||||
|
@ -692,7 +692,7 @@ class IonBuilder
|
||||
bool jsop_isnoiter();
|
||||
bool jsop_iterend();
|
||||
bool jsop_in();
|
||||
bool jsop_in_dense(JSValueType unboxedType);
|
||||
bool jsop_in_dense(MDefinition* obj, MDefinition* id, JSValueType unboxedType);
|
||||
bool jsop_instanceof();
|
||||
bool jsop_getaliasedvar(ScopeCoordinate sc);
|
||||
bool jsop_setaliasedvar(ScopeCoordinate sc);
|
||||
@ -927,8 +927,8 @@ class IonBuilder
|
||||
JSObject* testSingletonProperty(JSObject* obj, PropertyName* name);
|
||||
JSObject* testSingletonPropertyTypes(MDefinition* obj, PropertyName* name);
|
||||
|
||||
uint32_t getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed,
|
||||
BaselineInspector::ObjectGroupVector& convertUnboxedGroups);
|
||||
uint32_t getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed);
|
||||
MDefinition* convertUnboxedObjects(MDefinition* obj);
|
||||
MDefinition* convertUnboxedObjects(MDefinition* obj,
|
||||
const BaselineInspector::ObjectGroupVector& list);
|
||||
uint32_t getUnboxedOffset(TemporaryTypeSet* types, PropertyName* name,
|
||||
|
@ -632,7 +632,7 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
|
||||
OBJECT_FLAG_LENGTH_OVERFLOW |
|
||||
OBJECT_FLAG_ITERATED;
|
||||
|
||||
MDefinition* obj = callInfo.thisArg();
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
|
||||
TemporaryTypeSet* thisTypes = obj->resultTypeSet();
|
||||
if (!thisTypes)
|
||||
return InliningStatus_NotInlined;
|
||||
@ -758,7 +758,7 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* obj = callInfo.thisArg();
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
|
||||
MDefinition* value = callInfo.getArg(0);
|
||||
if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
|
||||
&obj, nullptr, &value, /* canModify = */ false))
|
||||
@ -839,17 +839,20 @@ IonBuilder::inlineArrayConcat(CallInfo& callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* thisArg = convertUnboxedObjects(callInfo.thisArg());
|
||||
MDefinition* objArg = convertUnboxedObjects(callInfo.getArg(0));
|
||||
|
||||
// Ensure |this|, argument and result are objects.
|
||||
if (getInlineReturnType() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
if (thisArg->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.getArg(0)->type() != MIRType_Object)
|
||||
if (objArg->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// |this| and the argument must be dense arrays.
|
||||
TemporaryTypeSet* thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet* argTypes = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet* thisTypes = thisArg->resultTypeSet();
|
||||
TemporaryTypeSet* argTypes = objArg->resultTypeSet();
|
||||
if (!thisTypes || !argTypes)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
@ -874,10 +877,10 @@ IonBuilder::inlineArrayConcat(CallInfo& callInfo)
|
||||
|
||||
JSValueType unboxedType = JSVAL_TYPE_MAGIC;
|
||||
if (clasp == &UnboxedArrayObject::class_) {
|
||||
unboxedType = UnboxedArrayElementType(constraints(), callInfo.thisArg(), nullptr);
|
||||
unboxedType = UnboxedArrayElementType(constraints(), thisArg, nullptr);
|
||||
if (unboxedType == JSVAL_TYPE_MAGIC)
|
||||
return InliningStatus_NotInlined;
|
||||
if (unboxedType != UnboxedArrayElementType(constraints(), callInfo.getArg(0), nullptr))
|
||||
if (unboxedType != UnboxedArrayElementType(constraints(), objArg, nullptr))
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
@ -937,8 +940,7 @@ IonBuilder::inlineArrayConcat(CallInfo& callInfo)
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
MArrayConcat* ins = MArrayConcat::New(alloc(), constraints(),
|
||||
callInfo.thisArg(), callInfo.getArg(0),
|
||||
MArrayConcat* ins = MArrayConcat::New(alloc(), constraints(), thisArg, objArg,
|
||||
templateObj,
|
||||
templateObj->group()->initialHeap(constraints()),
|
||||
unboxedType);
|
||||
@ -958,10 +960,12 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
|
||||
|
||||
// Ensure |this| and result are objects.
|
||||
if (getInlineReturnType() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
if (obj->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Arguments for the sliced region must be integers.
|
||||
@ -975,7 +979,7 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
||||
}
|
||||
|
||||
// |this| must be a dense array.
|
||||
TemporaryTypeSet* thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet* thisTypes = obj->resultTypeSet();
|
||||
if (!thisTypes)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
@ -991,7 +995,7 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
||||
|
||||
JSValueType unboxedType = JSVAL_TYPE_MAGIC;
|
||||
if (clasp == &UnboxedArrayObject::class_) {
|
||||
unboxedType = UnboxedArrayElementType(constraints(), callInfo.thisArg(), nullptr);
|
||||
unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
|
||||
if (unboxedType == JSVAL_TYPE_MAGIC)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
@ -1038,18 +1042,18 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
||||
if (callInfo.argc() > 1) {
|
||||
end = callInfo.getArg(1);
|
||||
} else if (clasp == &ArrayObject::class_) {
|
||||
MElements* elements = MElements::New(alloc(), callInfo.thisArg());
|
||||
MElements* elements = MElements::New(alloc(), obj);
|
||||
current->add(elements);
|
||||
|
||||
end = MArrayLength::New(alloc(), elements);
|
||||
current->add(end->toInstruction());
|
||||
} else {
|
||||
end = MUnboxedArrayLength::New(alloc(), callInfo.thisArg());
|
||||
end = MUnboxedArrayLength::New(alloc(), obj);
|
||||
current->add(end->toInstruction());
|
||||
}
|
||||
|
||||
MArraySlice* ins = MArraySlice::New(alloc(), constraints(),
|
||||
callInfo.thisArg(), begin, end,
|
||||
obj, begin, end,
|
||||
templateObj,
|
||||
templateObj->group()->initialHeap(constraints()),
|
||||
unboxedType);
|
||||
@ -2114,7 +2118,7 @@ IonBuilder::inlineDefineDataProperty(CallInfo& callInfo)
|
||||
if (callInfo.argc() != 3)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* obj = callInfo.getArg(0);
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.getArg(0));
|
||||
MDefinition* id = callInfo.getArg(1);
|
||||
MDefinition* value = callInfo.getArg(2);
|
||||
|
||||
|
@ -4757,6 +4757,35 @@ MArrayJoin::foldsTo(TempAllocator& alloc)
|
||||
return MStringReplace::New(alloc, string, pattern, replacement);
|
||||
}
|
||||
|
||||
MConvertUnboxedObjectToNative*
|
||||
MConvertUnboxedObjectToNative::New(TempAllocator& alloc, MDefinition* obj, ObjectGroup* group)
|
||||
{
|
||||
MConvertUnboxedObjectToNative* res = new(alloc) MConvertUnboxedObjectToNative(obj, group);
|
||||
|
||||
ObjectGroup* nativeGroup = group->unboxedLayout().nativeGroup();
|
||||
|
||||
// Make a new type set for the result of this instruction which replaces
|
||||
// the input group with the native group we will convert it to.
|
||||
TemporaryTypeSet* types = obj->resultTypeSet();
|
||||
if (types && !types->unknownObject()) {
|
||||
TemporaryTypeSet* newTypes = types->cloneWithoutObjects(alloc.lifoAlloc());
|
||||
if (newTypes) {
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
TypeSet::ObjectKey* key = types->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
if (key->unknownProperties() || !key->isGroup() || key->group() != group)
|
||||
newTypes->addType(TypeSet::ObjectType(key), alloc.lifoAlloc());
|
||||
else
|
||||
newTypes->addType(TypeSet::ObjectType(nativeGroup), alloc.lifoAlloc());
|
||||
}
|
||||
res->setResultTypeSet(newTypes);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessIsDenseNative(CompilerConstraintList* constraints,
|
||||
MDefinition* obj, MDefinition* id)
|
||||
|
@ -9049,9 +9049,7 @@ class MConvertUnboxedObjectToNative
|
||||
INSTRUCTION_HEADER(ConvertUnboxedObjectToNative)
|
||||
|
||||
static MConvertUnboxedObjectToNative* New(TempAllocator& alloc, MDefinition* obj,
|
||||
ObjectGroup* group) {
|
||||
return new(alloc) MConvertUnboxedObjectToNative(obj, group);
|
||||
}
|
||||
ObjectGroup* group);
|
||||
|
||||
MDefinition* object() const {
|
||||
return getOperand(0);
|
||||
|
Loading…
Reference in New Issue
Block a user