mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1040593 (attempt 2) - Partly allocate elements for |new Array(N)| when N > 2048. r=jandem,bhackett.
--HG-- extra : rebase_source : 2bcccb3aa1543649eb30cd8c43680fc09ec6df91
This commit is contained in:
parent
4987707ff9
commit
f00cea7994
@ -45,7 +45,7 @@ js::CreateRegExpMatchResult(JSContext *cx, HandleString input, const MatchPairs
|
|||||||
size_t numPairs = matches.length();
|
size_t numPairs = matches.length();
|
||||||
JS_ASSERT(numPairs > 0);
|
JS_ASSERT(numPairs > 0);
|
||||||
|
|
||||||
RootedObject arr(cx, NewDenseAllocatedArrayWithTemplate(cx, numPairs, templateObject));
|
RootedObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, templateObject));
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1904,7 +1904,7 @@ FindPath(JSContext *cx, unsigned argc, jsval *vp)
|
|||||||
//
|
//
|
||||||
// { node: undefined, edge: <string> }
|
// { node: undefined, edge: <string> }
|
||||||
size_t length = nodes.length();
|
size_t length = nodes.length();
|
||||||
RootedObject result(cx, NewDenseAllocatedArray(cx, length));
|
RootedObject result(cx, NewDenseFullyAllocatedArray(cx, length));
|
||||||
if (!result)
|
if (!result)
|
||||||
return false;
|
return false;
|
||||||
result->ensureDenseInitializedLength(cx, 0, length);
|
result->ensureDenseInitializedLength(cx, 0, length);
|
||||||
|
@ -3926,7 +3926,7 @@ ParseNode::getConstantValue(ExclusiveContext *cx, AllowConstantObjects allowObje
|
|||||||
pn = pn_head;
|
pn = pn_head;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedObject obj(cx, NewDenseAllocatedArray(cx, count, nullptr, MaybeSingletonObject));
|
RootedObject obj(cx, NewDenseFullyAllocatedArray(cx, count, nullptr, MaybeSingletonObject));
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -5581,7 +5581,7 @@ IonBuilder::jsop_newarray(uint32_t count)
|
|||||||
|
|
||||||
MNewArray *ins = MNewArray::New(alloc(), constraints(), count, templateConst,
|
MNewArray *ins = MNewArray::New(alloc(), constraints(), count, templateConst,
|
||||||
templateObject->type()->initialHeap(constraints()),
|
templateObject->type()->initialHeap(constraints()),
|
||||||
MNewArray::NewArray_Allocating);
|
NewArray_FullyAllocating);
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
|
|
||||||
@ -8313,7 +8313,7 @@ IonBuilder::jsop_rest()
|
|||||||
|
|
||||||
MNewArray *array = MNewArray::New(alloc(), constraints(), numRest, templateConst,
|
MNewArray *array = MNewArray::New(alloc(), constraints(), numRest, templateConst,
|
||||||
templateObject->type()->initialHeap(constraints()),
|
templateObject->type()->initialHeap(constraints()),
|
||||||
MNewArray::NewArray_Allocating);
|
NewArray_FullyAllocating);
|
||||||
current->add(array);
|
current->add(array);
|
||||||
|
|
||||||
if (numRest == 0) {
|
if (numRest == 0) {
|
||||||
|
@ -283,7 +283,7 @@ IonBuilder::InliningStatus
|
|||||||
IonBuilder::inlineArray(CallInfo &callInfo)
|
IonBuilder::inlineArray(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
uint32_t initLength = 0;
|
uint32_t initLength = 0;
|
||||||
MNewArray::AllocatingBehaviour allocating = MNewArray::NewArray_Unallocating;
|
AllocatingBehaviour allocating = NewArray_Unallocating;
|
||||||
|
|
||||||
JSObject *templateObject = inspector->getTemplateObjectForNative(pc, js_Array);
|
JSObject *templateObject = inspector->getTemplateObjectForNative(pc, js_Array);
|
||||||
if (!templateObject)
|
if (!templateObject)
|
||||||
@ -293,7 +293,7 @@ IonBuilder::inlineArray(CallInfo &callInfo)
|
|||||||
// Multiple arguments imply array initialization, not just construction.
|
// Multiple arguments imply array initialization, not just construction.
|
||||||
if (callInfo.argc() >= 2) {
|
if (callInfo.argc() >= 2) {
|
||||||
initLength = callInfo.argc();
|
initLength = callInfo.argc();
|
||||||
allocating = MNewArray::NewArray_Allocating;
|
allocating = NewArray_FullyAllocating;
|
||||||
|
|
||||||
types::TypeObjectKey *type = types::TypeObjectKey::get(templateObject);
|
types::TypeObjectKey *type = types::TypeObjectKey::get(templateObject);
|
||||||
if (!type->unknownProperties()) {
|
if (!type->unknownProperties()) {
|
||||||
@ -328,8 +328,11 @@ IonBuilder::inlineArray(CallInfo &callInfo)
|
|||||||
if (initLength != templateObject->as<ArrayObject>().length())
|
if (initLength != templateObject->as<ArrayObject>().length())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (initLength <= ArrayObject::EagerAllocationMaxLength)
|
// Don't inline large allocations.
|
||||||
allocating = MNewArray::NewArray_Allocating;
|
if (initLength > ArrayObject::EagerAllocationMaxLength)
|
||||||
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
|
allocating = NewArray_FullyAllocating;
|
||||||
}
|
}
|
||||||
|
|
||||||
callInfo.setImplicitlyUsedUnchecked();
|
callInfo.setImplicitlyUsedUnchecked();
|
||||||
|
@ -3033,10 +3033,9 @@ MNewArray::shouldUseVM() const
|
|||||||
size_t arraySlots =
|
size_t arraySlots =
|
||||||
gc::GetGCKindSlots(templateObject()->tenuredGetAllocKind()) - ObjectElements::VALUES_PER_HEADER;
|
gc::GetGCKindSlots(templateObject()->tenuredGetAllocKind()) - ObjectElements::VALUES_PER_HEADER;
|
||||||
|
|
||||||
// Allocate space using the VMCall
|
// Allocate space using the VMCall when mir hints it needs to get allocated
|
||||||
// when mir hints it needs to get allocated immediately,
|
// immediately, but only when data doesn't fit the available array slots.
|
||||||
// but only when data doesn't fit the available array slots.
|
bool allocating = allocatingBehaviour() != NewArray_Unallocating && count() > arraySlots;
|
||||||
bool allocating = isAllocating() && count() > arraySlots;
|
|
||||||
|
|
||||||
return templateObject()->hasSingletonType() || allocating;
|
return templateObject()->hasSingletonType() || allocating;
|
||||||
}
|
}
|
||||||
|
@ -2115,12 +2115,6 @@ typedef AlwaysTenured<Shape*> AlwaysTenuredShape;
|
|||||||
|
|
||||||
class MNewArray : public MUnaryInstruction
|
class MNewArray : public MUnaryInstruction
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
enum AllocatingBehaviour {
|
|
||||||
NewArray_Allocating,
|
|
||||||
NewArray_Unallocating
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Number of space to allocate for the array.
|
// Number of space to allocate for the array.
|
||||||
uint32_t count_;
|
uint32_t count_;
|
||||||
@ -2165,8 +2159,8 @@ class MNewArray : public MUnaryInstruction
|
|||||||
return initialHeap_;
|
return initialHeap_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAllocating() const {
|
AllocatingBehaviour allocatingBehaviour() const {
|
||||||
return allocating_ == NewArray_Allocating;
|
return allocating_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the code generator should call through to the
|
// Returns true if the code generator should call through to the
|
||||||
|
@ -981,14 +981,14 @@ MNewArray::writeRecoverData(CompactBufferWriter &writer) const
|
|||||||
MOZ_ASSERT(canRecoverOnBailout());
|
MOZ_ASSERT(canRecoverOnBailout());
|
||||||
writer.writeUnsigned(uint32_t(RInstruction::Recover_NewArray));
|
writer.writeUnsigned(uint32_t(RInstruction::Recover_NewArray));
|
||||||
writer.writeUnsigned(count());
|
writer.writeUnsigned(count());
|
||||||
writer.writeByte(isAllocating());
|
writer.writeByte(uint8_t(allocatingBehaviour()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RNewArray::RNewArray(CompactBufferReader &reader)
|
RNewArray::RNewArray(CompactBufferReader &reader)
|
||||||
{
|
{
|
||||||
count_ = reader.readUnsigned();
|
count_ = reader.readUnsigned();
|
||||||
isAllocating_ = reader.readByte();
|
allocatingBehaviour_ = AllocatingBehaviour(reader.readByte());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1006,7 +1006,7 @@ RNewArray::recover(JSContext *cx, SnapshotIterator &iter) const
|
|||||||
if (!templateObject->hasSingletonType())
|
if (!templateObject->hasSingletonType())
|
||||||
type = templateObject->type();
|
type = templateObject->type();
|
||||||
|
|
||||||
JSObject *resultObject = NewDenseArray(cx, count_, type, isAllocating_);
|
JSObject *resultObject = NewDenseArray(cx, count_, type, allocatingBehaviour_);
|
||||||
if (!resultObject)
|
if (!resultObject)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
|
||||||
|
#include "jsarray.h"
|
||||||
|
|
||||||
#include "jit/Snapshots.h"
|
#include "jit/Snapshots.h"
|
||||||
|
|
||||||
struct JSContext;
|
struct JSContext;
|
||||||
@ -505,7 +507,7 @@ class RNewArray MOZ_FINAL : public RInstruction
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
uint32_t count_;
|
uint32_t count_;
|
||||||
bool isAllocating_;
|
AllocatingBehaviour allocatingBehaviour_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RINSTRUCTION_HEADER_(NewArray)
|
RINSTRUCTION_HEADER_(NewArray)
|
||||||
|
@ -508,7 +508,7 @@ IsArrayEscaped(MInstruction *ins)
|
|||||||
|
|
||||||
// The array is probably too large to be represented efficiently with
|
// The array is probably too large to be represented efficiently with
|
||||||
// MArrayState, and we do not want to make huge allocations during bailouts.
|
// MArrayState, and we do not want to make huge allocations during bailouts.
|
||||||
if (!ins->toNewArray()->isAllocating()) {
|
if (ins->toNewArray()->allocatingBehaviour() == NewArray_Unallocating) {
|
||||||
JitSpewDef(JitSpew_Escape, "Array is not allocated\n", ins);
|
JitSpewDef(JitSpew_Escape, "Array is not allocated\n", ins);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,7 @@ NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *typeArg)
|
|||||||
NewObjectKind newKind = !type ? SingletonObject : GenericObject;
|
NewObjectKind newKind = !type ? SingletonObject : GenericObject;
|
||||||
if (type && type->shouldPreTenure())
|
if (type && type->shouldPreTenure())
|
||||||
newKind = TenuredObject;
|
newKind = TenuredObject;
|
||||||
RootedObject obj(cx, NewDenseAllocatedArray(cx, count, nullptr, newKind));
|
RootedObject obj(cx, NewDenseFullyAllocatedArray(cx, count, nullptr, newKind));
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -3773,7 +3773,7 @@ JS_NewArrayObject(JSContext *cx, size_t length)
|
|||||||
AssertHeapIsIdle(cx);
|
AssertHeapIsIdle(cx);
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
|
|
||||||
return NewDenseAllocatedArray(cx, length);
|
return NewDenseFullyAllocatedArray(cx, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include "mozilla/FloatingPoint.h"
|
#include "mozilla/FloatingPoint.h"
|
||||||
#include "mozilla/MathAlgorithms.h"
|
#include "mozilla/MathAlgorithms.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jsatom.h"
|
#include "jsatom.h"
|
||||||
#include "jscntxt.h"
|
#include "jscntxt.h"
|
||||||
@ -165,7 +167,7 @@ ToId(JSContext *cx, uint32_t index, MutableHandleId id)
|
|||||||
* to JSVAL_VOID. This function assumes that the location pointed by vp is
|
* to JSVAL_VOID. This function assumes that the location pointed by vp is
|
||||||
* properly rooted and can be used as GC-protected storage for temporaries.
|
* properly rooted and can be used as GC-protected storage for temporaries.
|
||||||
*/
|
*/
|
||||||
template<typename IndexType>
|
template <typename IndexType>
|
||||||
static inline bool
|
static inline bool
|
||||||
DoGetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
DoGetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||||
IndexType index, bool *hole, MutableHandleValue vp)
|
IndexType index, bool *hole, MutableHandleValue vp)
|
||||||
@ -190,7 +192,7 @@ DoGetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename IndexType>
|
template <typename IndexType>
|
||||||
static void
|
static void
|
||||||
AssertGreaterThanZero(IndexType index)
|
AssertGreaterThanZero(IndexType index)
|
||||||
{
|
{
|
||||||
@ -204,7 +206,7 @@ AssertGreaterThanZero(uint32_t index)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename IndexType>
|
template <typename IndexType>
|
||||||
static bool
|
static bool
|
||||||
GetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
GetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||||
IndexType index, bool *hole, MutableHandleValue vp)
|
IndexType index, bool *hole, MutableHandleValue vp)
|
||||||
@ -227,7 +229,7 @@ GetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
|||||||
return DoGetElement(cx, obj, receiver, index, hole, vp);
|
return DoGetElement(cx, obj, receiver, index, hole, vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename IndexType>
|
template <typename IndexType>
|
||||||
static inline bool
|
static inline bool
|
||||||
GetElement(JSContext *cx, HandleObject obj, IndexType index, bool *hole, MutableHandleValue vp)
|
GetElement(JSContext *cx, HandleObject obj, IndexType index, bool *hole, MutableHandleValue vp)
|
||||||
{
|
{
|
||||||
@ -1738,7 +1740,7 @@ MatchNumericComparator(JSContext *cx, const Value &v)
|
|||||||
return Match_None;
|
return Match_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename C>
|
template <typename K, typename C>
|
||||||
static inline bool
|
static inline bool
|
||||||
MergeSortByKey(K keys, size_t len, K scratch, C comparator, AutoValueVector *vec)
|
MergeSortByKey(K keys, size_t len, K scratch, C comparator, AutoValueVector *vec)
|
||||||
{
|
{
|
||||||
@ -2445,7 +2447,7 @@ js::array_splice_impl(JSContext *cx, unsigned argc, Value *vp, bool returnValueI
|
|||||||
TryReuseArrayType(obj, arr);
|
TryReuseArrayType(obj, arr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
arr = NewDenseAllocatedArray(cx, actualDeleteCount);
|
arr = NewDenseFullyAllocatedArray(cx, actualDeleteCount);
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return false;
|
return false;
|
||||||
TryReuseArrayType(obj, arr);
|
TryReuseArrayType(obj, arr);
|
||||||
@ -2754,7 +2756,7 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
begin = end;
|
begin = end;
|
||||||
|
|
||||||
Rooted<ArrayObject*> narr(cx);
|
Rooted<ArrayObject*> narr(cx);
|
||||||
narr = NewDenseAllocatedArray(cx, end - begin);
|
narr = NewDenseFullyAllocatedArray(cx, end - begin);
|
||||||
if (!narr)
|
if (!narr)
|
||||||
return false;
|
return false;
|
||||||
TryReuseArrayType(obj, narr);
|
TryReuseArrayType(obj, narr);
|
||||||
@ -2843,7 +2845,7 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
RootedValue thisv(cx, args.length() >= 2 ? args[1] : UndefinedValue());
|
RootedValue thisv(cx, args.length() >= 2 ? args[1] : UndefinedValue());
|
||||||
|
|
||||||
/* Step 6. */
|
/* Step 6. */
|
||||||
RootedObject arr(cx, NewDenseAllocatedArray(cx, 0));
|
RootedObject arr(cx, NewDenseFullyAllocatedArray(cx, 0));
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return false;
|
return false;
|
||||||
TypeObject *newtype = GetTypeCallerInitObject(cx, JSProto_Array);
|
TypeObject *newtype = GetTypeCallerInitObject(cx, JSProto_Array);
|
||||||
@ -3084,11 +3086,13 @@ js_Array(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate dense elements eagerly for small arrays, to avoid reallocating
|
* Allocate up to |EagerAllocationMaxLength| dense elements eagerly, to
|
||||||
* elements when filling the array.
|
* avoid reallocating elements when filling the array.
|
||||||
*/
|
*/
|
||||||
bool allocateArray = length <= ArrayObject::EagerAllocationMaxLength;
|
AllocatingBehaviour allocating = (length <= ArrayObject::EagerAllocationMaxLength)
|
||||||
RootedObject obj(cx, NewDenseArray(cx, length, type, allocateArray));
|
? NewArray_FullyAllocating
|
||||||
|
: NewArray_PartlyAllocating;
|
||||||
|
RootedObject obj(cx, NewDenseArray(cx, length, type, allocating));
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -3178,7 +3182,7 @@ EnsureNewArrayElements(ExclusiveContext *cx, JSObject *obj, uint32_t length)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool allocateCapacity>
|
template <uint32_t maxLength>
|
||||||
static MOZ_ALWAYS_INLINE ArrayObject *
|
static MOZ_ALWAYS_INLINE ArrayObject *
|
||||||
NewArray(ExclusiveContext *cxArg, uint32_t length,
|
NewArray(ExclusiveContext *cxArg, uint32_t length,
|
||||||
JSObject *protoArg, NewObjectKind newKind = GenericObject)
|
JSObject *protoArg, NewObjectKind newKind = GenericObject)
|
||||||
@ -3201,8 +3205,11 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
|
|||||||
ArrayObject *arr = &obj->as<ArrayObject>();
|
ArrayObject *arr = &obj->as<ArrayObject>();
|
||||||
arr->setFixedElements();
|
arr->setFixedElements();
|
||||||
arr->setLength(cx, length);
|
arr->setLength(cx, length);
|
||||||
if (allocateCapacity && !EnsureNewArrayElements(cx, arr, length))
|
if (maxLength > 0 &&
|
||||||
|
!EnsureNewArrayElements(cx, arr, std::min(maxLength, length)))
|
||||||
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
return arr;
|
return arr;
|
||||||
} else {
|
} else {
|
||||||
RootedObject proto(cxArg, protoArg);
|
RootedObject proto(cxArg, protoArg);
|
||||||
@ -3259,7 +3266,7 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
|
|||||||
cxArg->global(), allocKind, arr);
|
cxArg->global(), allocKind, arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allocateCapacity && !EnsureNewArrayElements(cxArg, arr, length))
|
if (maxLength > 0 && !EnsureNewArrayElements(cxArg, arr, std::min(maxLength, length)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
probes::CreateObject(cxArg, arr);
|
probes::CreateObject(cxArg, arr);
|
||||||
@ -3270,36 +3277,49 @@ ArrayObject * JS_FASTCALL
|
|||||||
js::NewDenseEmptyArray(JSContext *cx, JSObject *proto /* = nullptr */,
|
js::NewDenseEmptyArray(JSContext *cx, JSObject *proto /* = nullptr */,
|
||||||
NewObjectKind newKind /* = GenericObject */)
|
NewObjectKind newKind /* = GenericObject */)
|
||||||
{
|
{
|
||||||
return NewArray<false>(cx, 0, proto, newKind);
|
return NewArray<0>(cx, 0, proto, newKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayObject * JS_FASTCALL
|
ArrayObject * JS_FASTCALL
|
||||||
js::NewDenseAllocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto /* = nullptr */,
|
js::NewDenseFullyAllocatedArray(ExclusiveContext *cx, uint32_t length,
|
||||||
NewObjectKind newKind /* = GenericObject */)
|
JSObject *proto /* = nullptr */,
|
||||||
|
NewObjectKind newKind /* = GenericObject */)
|
||||||
{
|
{
|
||||||
return NewArray<true>(cx, length, proto, newKind);
|
return NewArray<JSObject::NELEMENTS_LIMIT>(cx, length, proto, newKind);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayObject * JS_FASTCALL
|
||||||
|
js::NewDensePartlyAllocatedArray(ExclusiveContext *cx, uint32_t length,
|
||||||
|
JSObject *proto /* = nullptr */,
|
||||||
|
NewObjectKind newKind /* = GenericObject */)
|
||||||
|
{
|
||||||
|
return NewArray<ArrayObject::EagerAllocationMaxLength>(cx, length, proto, newKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayObject * JS_FASTCALL
|
ArrayObject * JS_FASTCALL
|
||||||
js::NewDenseUnallocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto /* = nullptr */,
|
js::NewDenseUnallocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto /* = nullptr */,
|
||||||
NewObjectKind newKind /* = GenericObject */)
|
NewObjectKind newKind /* = GenericObject */)
|
||||||
{
|
{
|
||||||
return NewArray<false>(cx, length, proto, newKind);
|
return NewArray<0>(cx, length, proto, newKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayObject * JS_FASTCALL
|
ArrayObject * JS_FASTCALL
|
||||||
js::NewDenseArray(ExclusiveContext *cx, uint32_t length, HandleTypeObject type, bool allocateArray)
|
js::NewDenseArray(ExclusiveContext *cx, uint32_t length, HandleTypeObject type,
|
||||||
|
AllocatingBehaviour allocating)
|
||||||
{
|
{
|
||||||
NewObjectKind newKind = !type ? SingletonObject : GenericObject;
|
NewObjectKind newKind = !type ? SingletonObject : GenericObject;
|
||||||
if (type && type->shouldPreTenure())
|
if (type && type->shouldPreTenure())
|
||||||
newKind = TenuredObject;
|
newKind = TenuredObject;
|
||||||
|
|
||||||
// Allocate dense elements eagerly for small arrays, to avoid reallocating
|
ArrayObject *arr;
|
||||||
// elements when filling the array.
|
if (allocating == NewArray_Unallocating) {
|
||||||
ArrayObject *arr = allocateArray
|
arr = NewDenseUnallocatedArray(cx, length, nullptr, newKind);
|
||||||
? NewDenseAllocatedArray(cx, length, nullptr, newKind)
|
} else if (allocating == NewArray_PartlyAllocating) {
|
||||||
: NewDenseUnallocatedArray(cx, length, nullptr, newKind);
|
arr = NewDensePartlyAllocatedArray(cx, length, nullptr, newKind);
|
||||||
|
} else {
|
||||||
|
JS_ASSERT(allocating == NewArray_FullyAllocating);
|
||||||
|
arr = NewDenseFullyAllocatedArray(cx, length, nullptr, newKind);
|
||||||
|
}
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -3320,7 +3340,7 @@ js::NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32
|
|||||||
{
|
{
|
||||||
JS_ASSERT(!src->isIndexed());
|
JS_ASSERT(!src->isIndexed());
|
||||||
|
|
||||||
ArrayObject* arr = NewArray<true>(cx, length, proto);
|
ArrayObject* arr = NewArray<JSObject::NELEMENTS_LIMIT>(cx, length, proto);
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -3340,7 +3360,7 @@ ArrayObject *
|
|||||||
js::NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values,
|
js::NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values,
|
||||||
JSObject *proto /* = nullptr */, NewObjectKind newKind /* = GenericObject */)
|
JSObject *proto /* = nullptr */, NewObjectKind newKind /* = GenericObject */)
|
||||||
{
|
{
|
||||||
ArrayObject* arr = NewArray<true>(cx, length, proto);
|
ArrayObject* arr = NewArray<JSObject::NELEMENTS_LIMIT>(cx, length, proto);
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -3355,7 +3375,7 @@ js::NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArrayObject *
|
ArrayObject *
|
||||||
js::NewDenseAllocatedArrayWithTemplate(JSContext *cx, uint32_t length, JSObject *templateObject)
|
js::NewDenseFullyAllocatedArrayWithTemplate(JSContext *cx, uint32_t length, JSObject *templateObject)
|
||||||
{
|
{
|
||||||
gc::AllocKind allocKind = GuessArrayGCKind(length);
|
gc::AllocKind allocKind = GuessArrayGCKind(length);
|
||||||
JS_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_));
|
JS_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_));
|
||||||
|
@ -48,11 +48,6 @@ extern ArrayObject * JS_FASTCALL
|
|||||||
NewDenseEmptyArray(JSContext *cx, JSObject *proto = nullptr,
|
NewDenseEmptyArray(JSContext *cx, JSObject *proto = nullptr,
|
||||||
NewObjectKind newKind = GenericObject);
|
NewObjectKind newKind = GenericObject);
|
||||||
|
|
||||||
/* Create a dense array with length and capacity == 'length', initialized length set to 0. */
|
|
||||||
extern ArrayObject * JS_FASTCALL
|
|
||||||
NewDenseAllocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto = nullptr,
|
|
||||||
NewObjectKind newKind = GenericObject);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a dense array with a set length, but without allocating space for the
|
* Create a dense array with a set length, but without allocating space for the
|
||||||
* contents. This is useful, e.g., when accepting length from the user.
|
* contents. This is useful, e.g., when accepting length from the user.
|
||||||
@ -61,12 +56,32 @@ extern ArrayObject * JS_FASTCALL
|
|||||||
NewDenseUnallocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto = nullptr,
|
NewDenseUnallocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto = nullptr,
|
||||||
NewObjectKind newKind = GenericObject);
|
NewObjectKind newKind = GenericObject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a dense array with length and capacity == |length|, initialized length set to 0,
|
||||||
|
* but with only |EagerAllocationMaxLength| elements allocated.
|
||||||
|
*/
|
||||||
|
extern ArrayObject * JS_FASTCALL
|
||||||
|
NewDensePartlyAllocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto = nullptr,
|
||||||
|
NewObjectKind newKind = GenericObject);
|
||||||
|
|
||||||
|
/* Create a dense array with length and capacity == 'length', initialized length set to 0. */
|
||||||
|
extern ArrayObject * JS_FASTCALL
|
||||||
|
NewDenseFullyAllocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto = nullptr,
|
||||||
|
NewObjectKind newKind = GenericObject);
|
||||||
|
|
||||||
|
enum AllocatingBehaviour {
|
||||||
|
NewArray_Unallocating,
|
||||||
|
NewArray_PartlyAllocating,
|
||||||
|
NewArray_FullyAllocating
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a dense array with a set length, but only allocates space for the
|
* Create a dense array with a set length, but only allocates space for the
|
||||||
* contents if the length is not excessive.
|
* contents if the length is not excessive.
|
||||||
*/
|
*/
|
||||||
extern ArrayObject * JS_FASTCALL
|
extern ArrayObject * JS_FASTCALL
|
||||||
NewDenseArray(ExclusiveContext *cx, uint32_t length, HandleTypeObject type, bool allocateArray);
|
NewDenseArray(ExclusiveContext *cx, uint32_t length, HandleTypeObject type,
|
||||||
|
AllocatingBehaviour allocating);
|
||||||
|
|
||||||
/* Create a dense array with a copy of the dense array elements in src. */
|
/* Create a dense array with a copy of the dense array elements in src. */
|
||||||
extern ArrayObject *
|
extern ArrayObject *
|
||||||
@ -79,7 +94,7 @@ NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, JSObjec
|
|||||||
|
|
||||||
/* Create a dense array based on templateObject with the given length. */
|
/* Create a dense array based on templateObject with the given length. */
|
||||||
extern ArrayObject *
|
extern ArrayObject *
|
||||||
NewDenseAllocatedArrayWithTemplate(JSContext *cx, uint32_t length, JSObject *templateObject);
|
NewDenseFullyAllocatedArrayWithTemplate(JSContext *cx, uint32_t length, JSObject *templateObject);
|
||||||
|
|
||||||
/* Create a dense array with the same copy-on-write elements as another object. */
|
/* Create a dense array with the same copy-on-write elements as another object. */
|
||||||
extern JSObject *
|
extern JSObject *
|
||||||
|
@ -2372,7 +2372,7 @@ js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
|
|||||||
JS_ASSERT(srcObj->getElementsHeader()->ownerObject() == srcObj);
|
JS_ASSERT(srcObj->getElementsHeader()->ownerObject() == srcObj);
|
||||||
|
|
||||||
size_t length = srcObj->as<ArrayObject>().length();
|
size_t length = srcObj->as<ArrayObject>().length();
|
||||||
RootedObject res(cx, NewDenseAllocatedArray(cx, length, nullptr, MaybeSingletonObject));
|
RootedObject res(cx, NewDenseFullyAllocatedArray(cx, length, nullptr, MaybeSingletonObject));
|
||||||
if (!res)
|
if (!res)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -724,7 +724,7 @@ NodeBuilder::newArray(NodeVector &elts, MutableHandleValue dst)
|
|||||||
js_ReportAllocationOverflow(cx);
|
js_ReportAllocationOverflow(cx);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
RootedObject array(cx, NewDenseAllocatedArray(cx, uint32_t(len)));
|
RootedObject array(cx, NewDenseFullyAllocatedArray(cx, uint32_t(len)));
|
||||||
if (!array)
|
if (!array)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -14,8 +14,10 @@ namespace js {
|
|||||||
class ArrayObject : public JSObject
|
class ArrayObject : public JSObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Array(x) eagerly allocates dense elements if x <= this value.
|
// Array(x) eagerly allocates dense elements if x <= this value. Without
|
||||||
static const uint32_t EagerAllocationMaxLength = 2048;
|
// the subtraction the max would roll over to the next power-of-two (4096)
|
||||||
|
// due to the way that growElements() and goodAllocated() work.
|
||||||
|
static const uint32_t EagerAllocationMaxLength = 2048 - ObjectElements::VALUES_PER_HEADER;
|
||||||
|
|
||||||
static const Class class_;
|
static const Class class_;
|
||||||
|
|
||||||
|
@ -2183,7 +2183,7 @@ bool
|
|||||||
Debugger::getDebuggees(JSContext *cx, unsigned argc, Value *vp)
|
Debugger::getDebuggees(JSContext *cx, unsigned argc, Value *vp)
|
||||||
{
|
{
|
||||||
THIS_DEBUGGER(cx, argc, vp, "getDebuggees", args, dbg);
|
THIS_DEBUGGER(cx, argc, vp, "getDebuggees", args, dbg);
|
||||||
RootedObject arrobj(cx, NewDenseAllocatedArray(cx, dbg->debuggees.count()));
|
RootedObject arrobj(cx, NewDenseFullyAllocatedArray(cx, dbg->debuggees.count()));
|
||||||
if (!arrobj)
|
if (!arrobj)
|
||||||
return false;
|
return false;
|
||||||
arrobj->ensureDenseInitializedLength(cx, 0, dbg->debuggees.count());
|
arrobj->ensureDenseInitializedLength(cx, 0, dbg->debuggees.count());
|
||||||
@ -2938,7 +2938,7 @@ Debugger::findScripts(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
if (!query.findScripts(&scripts))
|
if (!query.findScripts(&scripts))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RootedObject result(cx, NewDenseAllocatedArray(cx, scripts.length()));
|
RootedObject result(cx, NewDenseFullyAllocatedArray(cx, scripts.length()));
|
||||||
if (!result)
|
if (!result)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -5217,7 +5217,7 @@ DebuggerObject_getParameterNames(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedObject result(cx, NewDenseAllocatedArray(cx, fun->nargs()));
|
RootedObject result(cx, NewDenseFullyAllocatedArray(cx, fun->nargs()));
|
||||||
if (!result)
|
if (!result)
|
||||||
return false;
|
return false;
|
||||||
result->ensureDenseInitializedLength(cx, 0, fun->nargs());
|
result->ensureDenseInitializedLength(cx, 0, fun->nargs());
|
||||||
|
@ -191,7 +191,7 @@ DebuggerMemory::drainAllocationsLog(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
|
|
||||||
size_t length = dbg->allocationsLogLength;
|
size_t length = dbg->allocationsLogLength;
|
||||||
|
|
||||||
RootedObject result(cx, NewDenseAllocatedArray(cx, length));
|
RootedObject result(cx, NewDenseFullyAllocatedArray(cx, length));
|
||||||
if (!result)
|
if (!result)
|
||||||
return false;
|
return false;
|
||||||
result->ensureDenseInitializedLength(cx, 0, length);
|
result->ensureDenseInitializedLength(cx, 0, length);
|
||||||
|
@ -3071,7 +3071,7 @@ CASE(JSOP_NEWARRAY)
|
|||||||
unsigned count = GET_UINT24(REGS.pc);
|
unsigned count = GET_UINT24(REGS.pc);
|
||||||
RootedObject &obj = rootObject0;
|
RootedObject &obj = rootObject0;
|
||||||
NewObjectKind newKind = UseNewTypeForInitializer(script, REGS.pc, &ArrayObject::class_);
|
NewObjectKind newKind = UseNewTypeForInitializer(script, REGS.pc, &ArrayObject::class_);
|
||||||
obj = NewDenseAllocatedArray(cx, count, nullptr, newKind);
|
obj = NewDenseFullyAllocatedArray(cx, count, nullptr, newKind);
|
||||||
if (!obj || !SetInitializerObjectType(cx, script, REGS.pc, obj, newKind))
|
if (!obj || !SetInitializerObjectType(cx, script, REGS.pc, obj, newKind))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -409,7 +409,7 @@ js::intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
uint32_t length = args[0].toInt32();
|
uint32_t length = args[0].toInt32();
|
||||||
|
|
||||||
// Make a new buffer and initialize it up to length.
|
// Make a new buffer and initialize it up to length.
|
||||||
RootedObject buffer(cx, NewDenseAllocatedArray(cx, length));
|
RootedObject buffer(cx, NewDenseFullyAllocatedArray(cx, length));
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user