зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1175165
- Eagerly analyze large array literals to see if an unboxed representation can be used, r=jandem.
This commit is contained in:
Родитель
262c0bd498
Коммит
043ab3c977
|
@ -3544,9 +3544,9 @@ NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length
|
|||
|
||||
JSObject*
|
||||
js::NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
|
||||
NewObjectKind newKind)
|
||||
NewObjectKind newKind, bool forceAnalyze)
|
||||
{
|
||||
return NewArrayTryUseGroup<UINT32_MAX>(cx, group, length, newKind);
|
||||
return NewArrayTryUseGroup<UINT32_MAX>(cx, group, length, newKind, forceAnalyze);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -3617,7 +3617,31 @@ js::NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
|
|||
const Value* vp, size_t length, NewObjectKind newKind,
|
||||
ShouldUpdateTypes updateTypes)
|
||||
{
|
||||
JSObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind);
|
||||
bool forceAnalyze = false;
|
||||
|
||||
static const size_t EagerPreliminaryObjectAnalysisThreshold = 800;
|
||||
|
||||
// Force analysis to see if an unboxed array can be used when making a
|
||||
// sufficiently large array, to avoid excessive analysis and copying later
|
||||
// on. If this is the first array of its group that is being created, first
|
||||
// make a dummy array with the initial elements of the array we are about
|
||||
// to make, so there is some basis for the unboxed array analysis.
|
||||
if (length > EagerPreliminaryObjectAnalysisThreshold) {
|
||||
if (PreliminaryObjectArrayWithTemplate* objects = group->maybePreliminaryObjects()) {
|
||||
if (objects->empty()) {
|
||||
size_t nlength = Min<size_t>(length, 100);
|
||||
JSObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, nlength);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
DebugOnly<DenseElementResult> result =
|
||||
SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, 0, vp, nlength, updateTypes);
|
||||
MOZ_ASSERT(result.value == DenseElementResult::Success);
|
||||
}
|
||||
}
|
||||
forceAnalyze = true;
|
||||
}
|
||||
|
||||
JSObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind, forceAnalyze);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::In
|
|||
|
||||
extern JSObject*
|
||||
NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
NewObjectKind newKind = GenericObject, bool forceAnalyze = false);
|
||||
|
||||
extern JSObject*
|
||||
NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length);
|
||||
|
|
|
@ -835,21 +835,20 @@ ObjectGroup::newArrayObject(ExclusiveContext* cx,
|
|||
ObjectGroupCompartment::ArrayObjectKey key(elementType);
|
||||
DependentAddPtr<ObjectGroupCompartment::ArrayObjectTable> p(cx, *table, key);
|
||||
|
||||
if (!p) {
|
||||
RootedArrayObject obj(cx, NewDenseCopiedArray(cx, length, vp, nullptr, TenuredObject));
|
||||
if (!obj)
|
||||
RootedObjectGroup group(cx);
|
||||
if (p) {
|
||||
group = p->value();
|
||||
} else {
|
||||
RootedObject proto(cx);
|
||||
if (!GetBuiltinPrototype(cx, JSProto_Array, &proto))
|
||||
return nullptr;
|
||||
|
||||
Rooted<TaggedProto> proto(cx, TaggedProto(obj->getProto()));
|
||||
RootedObjectGroup group(cx, ObjectGroupCompartment::makeGroup(cx, &ArrayObject::class_,
|
||||
proto));
|
||||
Rooted<TaggedProto> taggedProto(cx, TaggedProto(proto));
|
||||
group = ObjectGroupCompartment::makeGroup(cx, &ArrayObject::class_, taggedProto);
|
||||
if (!group)
|
||||
return nullptr;
|
||||
|
||||
AddTypePropertyId(cx, group, nullptr, JSID_VOID, elementType);
|
||||
|
||||
obj->setGroup(group);
|
||||
|
||||
if (elementType != TypeSet::UnknownType()) {
|
||||
// Keep track of the initial objects we create with this type.
|
||||
// If the initial ones have a consistent shape and property types, we
|
||||
|
@ -859,16 +858,12 @@ ObjectGroup::newArrayObject(ExclusiveContext* cx,
|
|||
if (!preliminaryObjects)
|
||||
return nullptr;
|
||||
group->setPreliminaryObjects(preliminaryObjects);
|
||||
preliminaryObjects->registerNewObject(obj);
|
||||
}
|
||||
|
||||
if (!p.add(cx, *table, key, group))
|
||||
return nullptr;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
RootedObjectGroup group(cx, p->value());
|
||||
return NewCopiedArrayTryUseGroup(cx, group, vp, length, newKind,
|
||||
ShouldUpdateTypes::DontUpdate);
|
||||
}
|
||||
|
|
|
@ -3373,6 +3373,16 @@ PreliminaryObjectArray::full() const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PreliminaryObjectArray::empty() const
|
||||
{
|
||||
for (size_t i = 0; i < COUNT; i++) {
|
||||
if (objects[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PreliminaryObjectArray::sweep()
|
||||
{
|
||||
|
|
|
@ -799,6 +799,7 @@ class PreliminaryObjectArray
|
|||
}
|
||||
|
||||
bool full() const;
|
||||
bool empty() const;
|
||||
void sweep();
|
||||
};
|
||||
|
||||
|
|
|
@ -963,6 +963,18 @@ const Class UnboxedPlainObject::class_ = {
|
|||
// UnboxedArrayObject
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <JSValueType Type>
|
||||
DenseElementResult
|
||||
AppendUnboxedDenseElements(UnboxedArrayObject* obj, uint32_t initlen, AutoValueVector* values)
|
||||
{
|
||||
for (size_t i = 0; i < initlen; i++)
|
||||
values->infallibleAppend(obj->getElementSpecific<Type>(i));
|
||||
return DenseElementResult::Success;
|
||||
}
|
||||
|
||||
DefineBoxedOrUnboxedFunctor3(AppendUnboxedDenseElements,
|
||||
UnboxedArrayObject*, uint32_t, AutoValueVector*);
|
||||
|
||||
/* static */ bool
|
||||
UnboxedArrayObject::convertToNative(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
|
@ -977,10 +989,12 @@ UnboxedArrayObject::convertToNative(JSContext* cx, JSObject* obj)
|
|||
size_t initlen = obj->as<UnboxedArrayObject>().initializedLength();
|
||||
|
||||
AutoValueVector values(cx);
|
||||
for (size_t i = 0; i < initlen; i++) {
|
||||
if (!values.append(obj->as<UnboxedArrayObject>().getElement(i)))
|
||||
return false;
|
||||
}
|
||||
if (!values.reserve(initlen))
|
||||
return false;
|
||||
|
||||
AppendUnboxedDenseElementsFunctor functor(&obj->as<UnboxedArrayObject>(), initlen, &values);
|
||||
DebugOnly<DenseElementResult> result = CallBoxedOrUnboxedSpecialization(functor, obj);
|
||||
MOZ_ASSERT(result == DenseElementResult::Success);
|
||||
|
||||
obj->setGroup(layout.nativeGroup());
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче