Make use of ArrayObjects in favor of generic JS objects.

ArrayObjects has been a thing for years but been under-used. About time
they are used where prudent.
This commit is contained in:
wolfbeast 2019-06-12 03:19:09 +00:00 committed by Roy Tam
commit 87f3c86484
14 changed files with 57 additions and 96 deletions

View file

@ -6281,8 +6281,8 @@ ParseNode::getConstantValue(ExclusiveContext* cx, AllowConstantObjects allowObje
}
MOZ_ASSERT(idx == count);
JSObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
newKind, arrayKind);
ArrayObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
newKind, arrayKind);
if (!obj)
return false;

View file

@ -2055,7 +2055,7 @@ BaselineCompiler::emit_JSOP_SPREADCALLARRAY()
return emit_JSOP_NEWARRAY();
}
typedef JSObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject, gc::InitialHeap);
typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject, gc::InitialHeap);
const VMFunction jit::NewArrayCopyOnWriteInfo =
FunctionInfo<NewArrayCopyOnWriteFn>(js::NewDenseCopyOnWriteArray, "NewDenseCopyOnWriteArray");
@ -4136,14 +4136,14 @@ BaselineCompiler::emit_JSOP_REST()
{
frame.syncStack(0);
JSObject* templateObject =
ArrayObject* templateObject =
ObjectGroup::newArrayObject(cx, nullptr, 0, TenuredObject,
ObjectGroup::NewArrayKind::UnknownIndex);
if (!templateObject)
return false;
// Call IC.
ICRest_Fallback::Compiler compiler(cx, &templateObject->as<ArrayObject>());
ICRest_Fallback::Compiler compiler(cx, templateObject);
if (!emitOpIC(compiler.getStub(&stubSpace_)))
return false;

View file

@ -5765,10 +5765,10 @@ static bool
CopyArray(JSContext* cx, HandleArrayObject arr, MutableHandleValue result)
{
uint32_t length = arr->length();
JSObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject);
ArrayObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject);
if (!nobj)
return false;
EnsureArrayGroupAnalyzed(cx, nobj);
EnsureArrayGroupAnalyzed(cx, nobj); //XXX
CopyBoxedOrUnboxedDenseElements(cx, nobj, arr, 0, 0, length);
result.setObject(*nobj);
@ -8547,8 +8547,8 @@ static bool DoRestFallback(JSContext* cx, BaselineFrame* frame, ICRest_Fallback*
unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0;
Value* rest = frame->argv() + numFormals;
JSObject* obj = ObjectGroup::newArrayObject(cx, rest, numRest, GenericObject,
ObjectGroup::NewArrayKind::UnknownIndex);
ArrayObject* obj = ObjectGroup::newArrayObject(cx, rest, numRest, GenericObject,
ObjectGroup::NewArrayKind::UnknownIndex);
if (!obj)
return false;
res.setObject(*obj);

View file

@ -5169,11 +5169,11 @@ static JSObject*
NewArrayWithGroup(JSContext* cx, uint32_t length, HandleObjectGroup group,
bool convertDoubleElements)
{
JSObject* res = NewFullyAllocatedArrayTryUseGroup(cx, group, length);
ArrayObject* res = NewFullyAllocatedArrayTryUseGroup(cx, group, length);
if (!res)
return nullptr;
if (convertDoubleElements)
res->as<ArrayObject>().setShouldConvertDoubleElements();
res->setShouldConvertDoubleElements();
return res;
}
@ -5319,7 +5319,7 @@ CodeGenerator::visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir)
masm.bind(ool->rejoin());
}
typedef JSObject* (*ArrayConstructorOneArgFn)(JSContext*, HandleObjectGroup, int32_t length);
typedef ArrayObject* (*ArrayConstructorOneArgFn)(JSContext*, HandleObjectGroup, int32_t length);
static const VMFunction ArrayConstructorOneArgInfo =
FunctionInfo<ArrayConstructorOneArgFn>(ArrayConstructorOneArg, "ArrayConstructorOneArg");
@ -7765,7 +7765,7 @@ CodeGenerator::visitSinCos(LSinCos *lir)
masm.freeStack(sizeof(double) * 2);
}
typedef JSObject* (*StringSplitFn)(JSContext*, HandleObjectGroup, HandleString, HandleString, uint32_t);
typedef ArrayObject* (*StringSplitFn)(JSContext*, HandleObjectGroup, HandleString, HandleString, uint32_t);
static const VMFunction StringSplitInfo =
FunctionInfo<StringSplitFn>(js::str_split_string, "str_split_string");

View file

@ -1355,7 +1355,7 @@ RNewArray::recover(JSContext* cx, SnapshotIterator& iter) const
RootedValue result(cx);
RootedObjectGroup group(cx, templateObject->group());
JSObject* resultObject = NewFullyAllocatedArrayTryUseGroup(cx, group, count_);
ArrayObject* resultObject = NewFullyAllocatedArrayTryUseGroup(cx, group, count_);
if (!resultObject)
return false;

View file

@ -2811,7 +2811,7 @@ SliceSlowly(JSContext* cx, HandleObject obj, HandleObject receiver,
}
static bool
SliceSparse(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end, HandleObject result)
SliceSparse(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end, HandleArrayObject result)
{
MOZ_ASSERT(begin <= end);
@ -2866,7 +2866,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be
if (initlen > begin)
count = Min<size_t>(initlen - begin, end - begin);
RootedObject narr(cx, NewFullyAllocatedArrayTryReuseGroup(cx, obj, count));
RootedArrayObject narr(cx, NewFullyAllocatedArrayTryReuseGroup(cx, obj, count));
if (!narr)
return false;
@ -2882,7 +2882,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be
return true;
}
RootedObject narr(cx, NewPartlyAllocatedArrayTryReuseGroup(cx, obj, end - begin));
RootedArrayObject narr(cx, NewPartlyAllocatedArrayTryReuseGroup(cx, obj, end - begin));
if (!narr)
return false;
@ -3069,7 +3069,7 @@ array_isArray(JSContext* cx, unsigned argc, Value* vp)
static bool
ArrayFromCallArgs(JSContext* cx, CallArgs& args, HandleObject proto = nullptr)
{
JSObject* obj = NewCopiedArrayForCallingAllocationSite(cx, args.array(), args.length(), proto);
ArrayObject* obj = NewCopiedArrayForCallingAllocationSite(cx, args.array(), args.length(), proto);
if (!obj)
return false;
@ -3234,7 +3234,7 @@ ArrayConstructorImpl(JSContext* cx, CallArgs& args, bool isConstructor)
}
}
JSObject* obj = NewPartlyAllocatedArrayForCallingAllocationSite(cx, length, proto);
ArrayObject* obj = NewPartlyAllocatedArrayForCallingAllocationSite(cx, length, proto);
if (!obj)
return false;
@ -3260,7 +3260,7 @@ js::array_construct(JSContext* cx, unsigned argc, Value* vp)
return ArrayConstructorImpl(cx, args, /* isConstructor = */ false);
}
JSObject*
ArrayObject*
js::ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt)
{
if (lengthInt < 0) {
@ -3555,7 +3555,7 @@ js::NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSOb
return arr;
}
JSObject*
ArrayObject*
js::NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap)
{
MOZ_ASSERT(!gc::IsInsideNursery(templateObject));
@ -3573,7 +3573,7 @@ js::NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc
// specified group cannot be used, ensure that the created array at least has
// the given [[Prototype]].
template <uint32_t maxLength>
static inline JSObject*
static inline ArrayObject*
NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
NewObjectKind newKind = GenericObject)
{
@ -3603,14 +3603,14 @@ NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length
return res;
}
JSObject*
ArrayObject*
js::NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
NewObjectKind newKind)
{
return NewArrayTryUseGroup<UINT32_MAX>(cx, group, length, newKind);
}
JSObject*
ArrayObject*
js::NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length)
{
return NewArrayTryUseGroup<ArrayObject::EagerAllocationMaxLength>(cx, group, length);
@ -3624,7 +3624,7 @@ js::NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup g
// |length| is larger than the input object's initialized length (in which case
// UnboxedArrayObject::MaximumCapacity might be exceeded).
template <uint32_t maxLength>
static inline JSObject*
static inline ArrayObject*
NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
NewObjectKind newKind = GenericObject)
{
@ -3641,20 +3641,20 @@ NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
return NewArrayTryUseGroup<maxLength>(cx, group, length, newKind);
}
JSObject*
ArrayObject*
js::NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
NewObjectKind newKind)
{
return NewArrayTryReuseGroup<UINT32_MAX>(cx, obj, length, newKind);
}
JSObject*
ArrayObject*
js::NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length)
{
return NewArrayTryReuseGroup<ArrayObject::EagerAllocationMaxLength>(cx, obj, length);
}
JSObject*
ArrayObject*
js::NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
NewObjectKind newKind)
{
@ -3664,7 +3664,7 @@ js::NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
return NewArrayTryUseGroup<UINT32_MAX>(cx, group, length, newKind);
}
JSObject*
ArrayObject*
js::NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto)
{
RootedObjectGroup group(cx, ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array, proto));
@ -3673,44 +3673,12 @@ js::NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length
return NewArrayTryUseGroup<ArrayObject::EagerAllocationMaxLength>(cx, group, length);
}
bool
js::MaybeAnalyzeBeforeCreatingLargeArray(ExclusiveContext* cx, HandleObjectGroup group,
const Value* vp, size_t length)
{
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 false;
DebugOnly<DenseElementResult> result =
SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, 0, vp, nlength,
ShouldUpdateTypes::Update);
MOZ_ASSERT(result.value == DenseElementResult::Success);
}
objects->maybeAnalyze(cx, group, /* forceAnalyze = */ true);
}
}
return true;
}
JSObject*
ArrayObject*
js::NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
const Value* vp, size_t length, NewObjectKind newKind,
ShouldUpdateTypes updateTypes)
{
if (!MaybeAnalyzeBeforeCreatingLargeArray(cx, group, vp, length))
return nullptr;
JSObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind);
ArrayObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind);
if (!obj)
return nullptr;
@ -3722,7 +3690,7 @@ js::NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
return obj;
}
JSObject*
ArrayObject*
js::NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
HandleObject proto /* = nullptr */)
{

View file

@ -72,30 +72,30 @@ extern ArrayObject*
NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSObject* templateObject);
/* Create a dense array with the same copy-on-write elements as another object. */
extern JSObject*
extern ArrayObject*
NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap);
// The methods below can create either boxed or unboxed arrays.
extern JSObject*
extern ArrayObject*
NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
NewObjectKind newKind = GenericObject);
extern JSObject*
extern ArrayObject*
NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length);
extern JSObject*
extern ArrayObject*
NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
NewObjectKind newKind = GenericObject);
extern JSObject*
extern ArrayObject*
NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length);
extern JSObject*
extern ArrayObject*
NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
NewObjectKind newKind = GenericObject);
extern JSObject*
extern ArrayObject*
NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto);
enum class ShouldUpdateTypes
@ -104,17 +104,13 @@ enum class ShouldUpdateTypes
DontUpdate
};
extern bool
MaybeAnalyzeBeforeCreatingLargeArray(ExclusiveContext* cx, HandleObjectGroup group,
const Value* vp, size_t length);
extern JSObject*
extern ArrayObject*
NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
const Value* vp, size_t length,
NewObjectKind newKind = GenericObject,
ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
extern JSObject*
extern ArrayObject*
NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
HandleObject proto = nullptr);
@ -202,7 +198,7 @@ array_splice(JSContext* cx, unsigned argc, js::Value* vp);
extern bool
NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v);
extern JSObject*
extern ArrayObject*
ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt);
#ifdef DEBUG

View file

@ -2369,7 +2369,7 @@ js::str_replace_string_raw(JSContext* cx, HandleString string, HandleString patt
}
// ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
static JSObject*
static ArrayObject*
SplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleLinearString sep,
HandleObjectGroup group)
{
@ -2466,7 +2466,7 @@ SplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleLinearS
}
// Fast-path for splitting a string into a character array via split("").
static JSObject*
static ArrayObject*
CharSplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleObjectGroup group)
{
size_t strLength = str->length();
@ -2491,7 +2491,7 @@ CharSplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleObj
}
// ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
JSObject*
ArrayObject*
js::str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep, uint32_t limit)
{

View file

@ -465,7 +465,7 @@ FileEscapedString(FILE* fp, const char* chars, size_t length, uint32_t quote)
return res;
}
JSObject*
ArrayObject*
str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep,
uint32_t limit);

View file

@ -606,8 +606,8 @@ JSONParserBase::finishArray(MutableHandleValue vp, ElementVector& elements)
{
MOZ_ASSERT(&elements == &stack.back().elements());
JSObject* obj = ObjectGroup::newArrayObject(cx, elements.begin(), elements.length(),
GenericObject);
ArrayObject* obj = ObjectGroup::newArrayObject(cx, elements.begin(), elements.length(),
GenericObject);
if (!obj)
return false;

View file

@ -774,7 +774,7 @@ GetValueTypeForTable(const Value& v)
return type;
}
/* static */ JSObject*
/* static */ ArrayObject*
ObjectGroup::newArrayObject(ExclusiveContext* cx,
const Value* vp, size_t length,
NewObjectKind newKind, NewArrayKind arrayKind)
@ -854,11 +854,8 @@ ObjectGroup::newArrayObject(ExclusiveContext* cx,
}
// The type of the elements being added will already be reflected in type
// information, but make sure when creating an unboxed array that the
// common element type is suitable for the unboxed representation.
// information.
ShouldUpdateTypes updateTypes = ShouldUpdateTypes::DontUpdate;
if (!MaybeAnalyzeBeforeCreatingLargeArray(cx, group, vp, length))
return nullptr;
if (group->maybePreliminaryObjects())
group->maybePreliminaryObjects()->maybeAnalyze(cx, group);

View file

@ -505,11 +505,11 @@ class ObjectGroup : public gc::TenuredCell
UnknownIndex // Make an array with an unknown element type.
};
// Create an ArrayObject or UnboxedArrayObject with the specified elements
// and a group specialized for the elements.
static JSObject* newArrayObject(ExclusiveContext* cx, const Value* vp, size_t length,
NewObjectKind newKind,
NewArrayKind arrayKind = NewArrayKind::Normal);
// Create an ArrayObject with the specified elements and a group specialized
// for the elements.
static ArrayObject* newArrayObject(ExclusiveContext* cx, const Value* vp, size_t length,
NewObjectKind newKind,
NewArrayKind arrayKind = NewArrayKind::Normal);
// Create a PlainObject or UnboxedPlainObject with the specified properties
// and a group specialized for those properties.

View file

@ -82,7 +82,7 @@ InterpreterFrame::isNonGlobalEvalFrame() const
return isEvalFrame() && script()->bodyScope()->as<EvalScope>().isNonGlobal();
}
JSObject*
ArrayObject*
InterpreterFrame::createRestParameter(JSContext* cx)
{
MOZ_ASSERT(script()->hasRest());

View file

@ -523,7 +523,7 @@ class InterpreterFrame
ArgumentsObject& argsObj() const;
void initArgsObj(ArgumentsObject& argsobj);
JSObject* createRestParameter(JSContext* cx);
ArrayObject* createRestParameter(JSContext* cx);
/*
* Environment chain