Revert #1091 Remove unboxed object code phase 1 + extras.

This should be the last code backout for this. merging this branch
should get us back to the way we were (+ additional code changes for
later changes) as fasr as the unused unboxed code is concerned.
This commit is contained in:
wolfbeast 2020-02-23 19:43:47 +01:00 committed by Roy Tam
commit 2996c783d8
37 changed files with 1545 additions and 102 deletions

View file

@ -2630,6 +2630,40 @@ jit::EqualTypes(MIRType type1, TemporaryTypeSet* typeset1,
return typeset1->equals(typeset2);
}
// Tests whether input/inputTypes can always be stored to an unboxed
// object/array property with the given unboxed type.
bool
jit::CanStoreUnboxedType(TempAllocator& alloc,
JSValueType unboxedType, MIRType input, TypeSet* inputTypes)
{
TemporaryTypeSet types;
switch (unboxedType) {
case JSVAL_TYPE_BOOLEAN:
case JSVAL_TYPE_INT32:
case JSVAL_TYPE_DOUBLE:
case JSVAL_TYPE_STRING:
types.addType(TypeSet::PrimitiveType(unboxedType), alloc.lifoAlloc());
break;
case JSVAL_TYPE_OBJECT:
types.addType(TypeSet::AnyObjectType(), alloc.lifoAlloc());
types.addType(TypeSet::NullType(), alloc.lifoAlloc());
break;
default:
MOZ_CRASH("Bad unboxed type");
}
return TypeSetIncludes(&types, input, inputTypes);
}
static bool
CanStoreUnboxedType(TempAllocator& alloc, JSValueType unboxedType, MDefinition* value)
{
return CanStoreUnboxedType(alloc, unboxedType, value->type(), value->resultTypeSet());
}
bool
MPhi::specializeType(TempAllocator& alloc)
{
@ -4776,8 +4810,35 @@ MBeta::printOpcode(GenericPrinter& out) const
bool
MCreateThisWithTemplate::canRecoverOnBailout() const
{
MOZ_ASSERT(templateObject()->is<PlainObject>());
MOZ_ASSERT(!templateObject()->as<PlainObject>().denseElementsAreCopyOnWrite());
MOZ_ASSERT(templateObject()->is<PlainObject>() || templateObject()->is<UnboxedPlainObject>());
MOZ_ASSERT_IF(templateObject()->is<PlainObject>(),
!templateObject()->as<PlainObject>().denseElementsAreCopyOnWrite());
return true;
}
bool
OperandIndexMap::init(TempAllocator& alloc, JSObject* templateObject)
{
const UnboxedLayout& layout =
templateObject->as<UnboxedPlainObject>().layoutDontCheckGeneration();
const UnboxedLayout::PropertyVector& properties = layout.properties();
MOZ_ASSERT(properties.length() < 255);
// Allocate an array of indexes, where the top of each field correspond to
// the index of the operand in the MObjectState instance.
if (!map.init(alloc, layout.size()))
return false;
// Reset all indexes to 0, which is an error code.
for (size_t i = 0; i < map.length(); i++)
map[i] = 0;
// Map the property offsets to the indexes of MObjectState operands.
uint8_t index = 1;
for (size_t i = 0; i < properties.length(); i++, index++)
map[properties[i].offset] = index;
return true;
}
@ -4797,11 +4858,17 @@ MObjectState::MObjectState(JSObject *templateObject, OperandIndexMap* operandInd
setResultType(MIRType::Object);
setRecoveredOnBailout();
MOZ_ASSERT(templateObject->is<NativeObject>());
NativeObject* nativeObject = &templateObject->as<NativeObject>();
numSlots_ = nativeObject->slotSpan();
numFixedSlots_ = nativeObject->numFixedSlots();
if (templateObject->is<NativeObject>()) {
NativeObject* nativeObject = &templateObject->as<NativeObject>();
numSlots_ = nativeObject->slotSpan();
numFixedSlots_ = nativeObject->numFixedSlots();
} else {
const UnboxedLayout& layout =
templateObject->as<UnboxedPlainObject>().layoutDontCheckGeneration();
// Same as UnboxedLayout::makeNativeGroup
numSlots_ = layout.properties().length();
numFixedSlots_ = gc::GetGCKindSlots(layout.getAllocKind());
}
operandIndex_ = operandIndex;
}
@ -4838,21 +4905,39 @@ MObjectState::initFromTemplateObject(TempAllocator& alloc, MDefinition* undefine
// the template object. This is needed to account values which are baked in
// the template objects and not visible in IonMonkey, such as the
// uninitialized-lexical magic value of call objects.
NativeObject& nativeObject = templateObject->as<NativeObject>();
MOZ_ASSERT(nativeObject.slotSpan() == numSlots());
if (templateObject->is<UnboxedPlainObject>()) {
UnboxedPlainObject& unboxedObject = templateObject->as<UnboxedPlainObject>();
const UnboxedLayout& layout = unboxedObject.layoutDontCheckGeneration();
const UnboxedLayout::PropertyVector& properties = layout.properties();
MOZ_ASSERT(templateObject->is<NativeObject>());
for (size_t i = 0; i < numSlots(); i++) {
Value val = nativeObject.getSlot(i);
MDefinition *def = undefinedVal;
if (!val.isUndefined()) {
MConstant* ins = val.isObject() ?
MConstant::NewConstraintlessObject(alloc, &val.toObject()) :
MConstant::New(alloc, val);
block()->insertBefore(this, ins);
def = ins;
for (size_t i = 0; i < properties.length(); i++) {
Value val = unboxedObject.getValue(properties[i], /* maybeUninitialized = */ true);
MDefinition *def = undefinedVal;
if (!val.isUndefined()) {
MConstant* ins = val.isObject() ?
MConstant::NewConstraintlessObject(alloc, &val.toObject()) :
MConstant::New(alloc, val);
block()->insertBefore(this, ins);
def = ins;
}
initSlot(i, def);
}
} else {
NativeObject& nativeObject = templateObject->as<NativeObject>();
MOZ_ASSERT(nativeObject.slotSpan() == numSlots());
for (size_t i = 0; i < numSlots(); i++) {
Value val = nativeObject.getSlot(i);
MDefinition *def = undefinedVal;
if (!val.isUndefined()) {
MConstant* ins = val.isObject() ?
MConstant::NewConstraintlessObject(alloc, &val.toObject()) :
MConstant::New(alloc, val);
block()->insertBefore(this, ins);
def = ins;
}
initSlot(i, def);
}
initSlot(i, def);
}
return true;
}
@ -4863,7 +4948,14 @@ MObjectState::New(TempAllocator& alloc, MDefinition* obj)
JSObject* templateObject = templateObjectOf(obj);
MOZ_ASSERT(templateObject, "Unexpected object creation.");
MObjectState* res = new(alloc) MObjectState(templateObject, nullptr);
OperandIndexMap* operandIndex = nullptr;
if (templateObject->is<UnboxedPlainObject>()) {
operandIndex = new(alloc) OperandIndexMap;
if (!operandIndex || !operandIndex->init(alloc, templateObject))
return nullptr;
}
MObjectState* res = new(alloc) MObjectState(templateObject, operandIndex);
if (!res || !res->init(alloc, obj))
return nullptr;
return res;
@ -5770,6 +5862,35 @@ MGetFirstDollarIndex::foldsTo(TempAllocator& alloc)
return MConstant::New(alloc, Int32Value(index));
}
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)
@ -5824,6 +5945,8 @@ jit::UnboxedArrayElementType(CompilerConstraintList* constraints, MDefinition* o
elementType = layout.elementType();
else
return JSVAL_TYPE_MAGIC;
key->watchStateChangeForUnboxedConvertedToNative(constraints);
}
return elementType;
@ -6447,6 +6570,23 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator& alloc, CompilerConstraintList*
}
}
// Perform additional filtering to make sure that any unboxed property
// being written can accommodate the value.
for (size_t i = 0; i < types->getObjectCount(); i++) {
TypeSet::ObjectKey* key = types->getObject(i);
if (key && key->isGroup() && key->group()->maybeUnboxedLayout()) {
const UnboxedLayout& layout = key->group()->unboxedLayout();
if (name) {
const UnboxedLayout::Property* property = layout.lookup(name);
if (property && !CanStoreUnboxedType(alloc, property->type, *pvalue))
return true;
} else {
if (layout.isArray() && !CanStoreUnboxedType(alloc, layout.elementType(), *pvalue))
return true;
}
}
}
if (success)
return false;
@ -6477,6 +6617,17 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator& alloc, CompilerConstraintList*
MOZ_ASSERT(excluded);
// If the excluded object is a group with an unboxed layout, make sure it
// does not have a corresponding native group. Objects with the native
// group might appear even though they are not in the type set.
if (excluded->isGroup()) {
if (UnboxedLayout* layout = excluded->group()->maybeUnboxedLayout()) {
if (layout->nativeGroup())
return true;
excluded->watchStateChangeForUnboxedConvertedToNative(constraints);
}
}
*pobj = AddGroupGuard(alloc, current, *pobj, excluded, /* bailOnEquality = */ true);
return false;
}