Backed out changeset 94eed55e5a5b (bug 1040593) on a CLOSED TREE

This commit is contained in:
Wes Kocher 2014-09-04 18:00:59 -07:00
parent 339c5be1f1
commit e334302b6f
21 changed files with 75 additions and 108 deletions

View File

@ -45,7 +45,7 @@ js::CreateRegExpMatchResult(JSContext *cx, HandleString input, const MatchPairs
size_t numPairs = matches.length();
JS_ASSERT(numPairs > 0);
RootedObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, templateObject));
RootedObject arr(cx, NewDenseAllocatedArrayWithTemplate(cx, numPairs, templateObject));
if (!arr)
return false;

View File

@ -1904,7 +1904,7 @@ FindPath(JSContext *cx, unsigned argc, jsval *vp)
//
// { node: undefined, edge: <string> }
size_t length = nodes.length();
RootedObject result(cx, NewDenseFullyAllocatedArray(cx, length));
RootedObject result(cx, NewDenseAllocatedArray(cx, length));
if (!result)
return false;
result->ensureDenseInitializedLength(cx, 0, length);

View File

@ -3926,7 +3926,7 @@ ParseNode::getConstantValue(ExclusiveContext *cx, AllowConstantObjects allowObje
pn = pn_head;
}
RootedObject obj(cx, NewDenseFullyAllocatedArray(cx, count, nullptr, MaybeSingletonObject));
RootedObject obj(cx, NewDenseAllocatedArray(cx, count, nullptr, MaybeSingletonObject));
if (!obj)
return false;

View File

@ -5581,7 +5581,7 @@ IonBuilder::jsop_newarray(uint32_t count)
MNewArray *ins = MNewArray::New(alloc(), constraints(), count, templateConst,
templateObject->type()->initialHeap(constraints()),
NewArray_FullyAllocating);
MNewArray::NewArray_Allocating);
current->add(ins);
current->push(ins);
@ -8313,7 +8313,7 @@ IonBuilder::jsop_rest()
MNewArray *array = MNewArray::New(alloc(), constraints(), numRest, templateConst,
templateObject->type()->initialHeap(constraints()),
NewArray_FullyAllocating);
MNewArray::NewArray_Allocating);
current->add(array);
if (numRest == 0) {

View File

@ -283,7 +283,7 @@ IonBuilder::InliningStatus
IonBuilder::inlineArray(CallInfo &callInfo)
{
uint32_t initLength = 0;
AllocatingBehaviour allocating = NewArray_Unallocating;
MNewArray::AllocatingBehaviour allocating = MNewArray::NewArray_Unallocating;
JSObject *templateObject = inspector->getTemplateObjectForNative(pc, js_Array);
if (!templateObject)
@ -293,7 +293,7 @@ IonBuilder::inlineArray(CallInfo &callInfo)
// Multiple arguments imply array initialization, not just construction.
if (callInfo.argc() >= 2) {
initLength = callInfo.argc();
allocating = NewArray_FullyAllocating;
allocating = MNewArray::NewArray_Allocating;
types::TypeObjectKey *type = types::TypeObjectKey::get(templateObject);
if (!type->unknownProperties()) {
@ -328,11 +328,8 @@ IonBuilder::inlineArray(CallInfo &callInfo)
if (initLength != templateObject->as<ArrayObject>().length())
return InliningStatus_NotInlined;
// Don't inline large allocations.
if (initLength > ArrayObject::EagerAllocationMaxLength)
return InliningStatus_NotInlined;
allocating = NewArray_FullyAllocating;
if (initLength <= ArrayObject::EagerAllocationMaxLength)
allocating = MNewArray::NewArray_Allocating;
}
callInfo.setImplicitlyUsedUnchecked();

View File

@ -3033,9 +3033,10 @@ MNewArray::shouldUseVM() const
size_t arraySlots =
gc::GetGCKindSlots(templateObject()->tenuredGetAllocKind()) - ObjectElements::VALUES_PER_HEADER;
// Allocate space using the VMCall when mir hints it needs to get allocated
// immediately, but only when data doesn't fit the available array slots.
bool allocating = allocatingBehaviour() != NewArray_Unallocating && count() > arraySlots;
// Allocate space using the VMCall
// when mir hints it needs to get allocated immediately,
// but only when data doesn't fit the available array slots.
bool allocating = isAllocating() && count() > arraySlots;
return templateObject()->hasSingletonType() || allocating;
}

View File

@ -2115,6 +2115,12 @@ typedef AlwaysTenured<Shape*> AlwaysTenuredShape;
class MNewArray : public MUnaryInstruction
{
public:
enum AllocatingBehaviour {
NewArray_Allocating,
NewArray_Unallocating
};
private:
// Number of space to allocate for the array.
uint32_t count_;
@ -2159,8 +2165,8 @@ class MNewArray : public MUnaryInstruction
return initialHeap_;
}
AllocatingBehaviour allocatingBehaviour() const {
return allocating_;
bool isAllocating() const {
return allocating_ == NewArray_Allocating;
}
// Returns true if the code generator should call through to the

View File

@ -981,14 +981,14 @@ MNewArray::writeRecoverData(CompactBufferWriter &writer) const
MOZ_ASSERT(canRecoverOnBailout());
writer.writeUnsigned(uint32_t(RInstruction::Recover_NewArray));
writer.writeUnsigned(count());
writer.writeByte(uint8_t(allocatingBehaviour()));
writer.writeByte(isAllocating());
return true;
}
RNewArray::RNewArray(CompactBufferReader &reader)
{
count_ = reader.readUnsigned();
allocatingBehaviour_ = AllocatingBehaviour(reader.readByte());
isAllocating_ = reader.readByte();
}
bool
@ -1006,7 +1006,7 @@ RNewArray::recover(JSContext *cx, SnapshotIterator &iter) const
if (!templateObject->hasSingletonType())
type = templateObject->type();
JSObject *resultObject = NewDenseArray(cx, count_, type, allocatingBehaviour_);
JSObject *resultObject = NewDenseArray(cx, count_, type, isAllocating_);
if (!resultObject)
return false;

View File

@ -505,7 +505,7 @@ class RNewArray MOZ_FINAL : public RInstruction
{
private:
uint32_t count_;
AllocatingBehaviour allocatingBehaviour_;
bool isAllocating_;
public:
RINSTRUCTION_HEADER_(NewArray)

View File

@ -508,7 +508,7 @@ IsArrayEscaped(MInstruction *ins)
// The array is probably too large to be represented efficiently with
// MArrayState, and we do not want to make huge allocations during bailouts.
if (ins->toNewArray()->allocatingBehaviour() == NewArray_Unallocating) {
if (!ins->toNewArray()->isAllocating()) {
JitSpewDef(JitSpew_Escape, "Array is not allocated\n", ins);
return true;
}

View File

@ -315,7 +315,7 @@ NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *typeArg)
NewObjectKind newKind = !type ? SingletonObject : GenericObject;
if (type && type->shouldPreTenure())
newKind = TenuredObject;
RootedObject obj(cx, NewDenseFullyAllocatedArray(cx, count, nullptr, newKind));
RootedObject obj(cx, NewDenseAllocatedArray(cx, count, nullptr, newKind));
if (!obj)
return nullptr;

View File

@ -3773,7 +3773,7 @@ JS_NewArrayObject(JSContext *cx, size_t length)
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return NewDenseFullyAllocatedArray(cx, length);
return NewDenseAllocatedArray(cx, length);
}
JS_PUBLIC_API(bool)

View File

@ -11,8 +11,6 @@
#include "mozilla/FloatingPoint.h"
#include "mozilla/MathAlgorithms.h"
#include <algorithm>
#include "jsapi.h"
#include "jsatom.h"
#include "jscntxt.h"
@ -167,7 +165,7 @@ ToId(JSContext *cx, uint32_t index, MutableHandleId id)
* 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.
*/
template <typename IndexType>
template<typename IndexType>
static inline bool
DoGetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
IndexType index, bool *hole, MutableHandleValue vp)
@ -192,7 +190,7 @@ DoGetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
return true;
}
template <typename IndexType>
template<typename IndexType>
static void
AssertGreaterThanZero(IndexType index)
{
@ -206,7 +204,7 @@ AssertGreaterThanZero(uint32_t index)
{
}
template <typename IndexType>
template<typename IndexType>
static bool
GetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
IndexType index, bool *hole, MutableHandleValue vp)
@ -229,7 +227,7 @@ GetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
return DoGetElement(cx, obj, receiver, index, hole, vp);
}
template <typename IndexType>
template<typename IndexType>
static inline bool
GetElement(JSContext *cx, HandleObject obj, IndexType index, bool *hole, MutableHandleValue vp)
{
@ -1740,7 +1738,7 @@ MatchNumericComparator(JSContext *cx, const Value &v)
return Match_None;
}
template <typename K, typename C>
template<typename K, typename C>
static inline bool
MergeSortByKey(K keys, size_t len, K scratch, C comparator, AutoValueVector *vec)
{
@ -2447,7 +2445,7 @@ js::array_splice_impl(JSContext *cx, unsigned argc, Value *vp, bool returnValueI
TryReuseArrayType(obj, arr);
}
} else {
arr = NewDenseFullyAllocatedArray(cx, actualDeleteCount);
arr = NewDenseAllocatedArray(cx, actualDeleteCount);
if (!arr)
return false;
TryReuseArrayType(obj, arr);
@ -2756,7 +2754,7 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
begin = end;
Rooted<ArrayObject*> narr(cx);
narr = NewDenseFullyAllocatedArray(cx, end - begin);
narr = NewDenseAllocatedArray(cx, end - begin);
if (!narr)
return false;
TryReuseArrayType(obj, narr);
@ -2845,7 +2843,7 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
RootedValue thisv(cx, args.length() >= 2 ? args[1] : UndefinedValue());
/* Step 6. */
RootedObject arr(cx, NewDenseFullyAllocatedArray(cx, 0));
RootedObject arr(cx, NewDenseAllocatedArray(cx, 0));
if (!arr)
return false;
TypeObject *newtype = GetTypeCallerInitObject(cx, JSProto_Array);
@ -3086,13 +3084,11 @@ js_Array(JSContext *cx, unsigned argc, Value *vp)
}
/*
* Allocate up to |EagerAllocationMaxLength| dense elements eagerly, to
* avoid reallocating elements when filling the array.
* Allocate dense elements eagerly for small arrays, to avoid reallocating
* elements when filling the array.
*/
AllocatingBehaviour allocating = (length <= ArrayObject::EagerAllocationMaxLength)
? NewArray_FullyAllocating
: NewArray_PartlyAllocating;
RootedObject obj(cx, NewDenseArray(cx, length, type, allocating));
bool allocateArray = length <= ArrayObject::EagerAllocationMaxLength;
RootedObject obj(cx, NewDenseArray(cx, length, type, allocateArray));
if (!obj)
return false;
@ -3182,7 +3178,7 @@ EnsureNewArrayElements(ExclusiveContext *cx, JSObject *obj, uint32_t length)
return true;
}
template <uint32_t maxLength>
template<bool allocateCapacity>
static MOZ_ALWAYS_INLINE ArrayObject *
NewArray(ExclusiveContext *cxArg, uint32_t length,
JSObject *protoArg, NewObjectKind newKind = GenericObject)
@ -3205,11 +3201,8 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
ArrayObject *arr = &obj->as<ArrayObject>();
arr->setFixedElements();
arr->setLength(cx, length);
if (maxLength > 0 &&
!EnsureNewArrayElements(cx, arr, std::min(maxLength, length)))
{
if (allocateCapacity && !EnsureNewArrayElements(cx, arr, length))
return nullptr;
}
return arr;
} else {
RootedObject proto(cxArg, protoArg);
@ -3266,7 +3259,7 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
cxArg->global(), allocKind, arr);
}
if (maxLength > 0 && !EnsureNewArrayElements(cxArg, arr, std::min(maxLength, length)))
if (allocateCapacity && !EnsureNewArrayElements(cxArg, arr, length))
return nullptr;
probes::CreateObject(cxArg, arr);
@ -3277,49 +3270,36 @@ ArrayObject * JS_FASTCALL
js::NewDenseEmptyArray(JSContext *cx, JSObject *proto /* = nullptr */,
NewObjectKind newKind /* = GenericObject */)
{
return NewArray<0>(cx, 0, proto, newKind);
return NewArray<false>(cx, 0, proto, newKind);
}
ArrayObject * JS_FASTCALL
js::NewDenseFullyAllocatedArray(ExclusiveContext *cx, uint32_t length,
JSObject *proto /* = nullptr */,
NewObjectKind newKind /* = GenericObject */)
js::NewDenseAllocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto /* = nullptr */,
NewObjectKind newKind /* = GenericObject */)
{
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);
return NewArray<true>(cx, length, proto, newKind);
}
ArrayObject * JS_FASTCALL
js::NewDenseUnallocatedArray(ExclusiveContext *cx, uint32_t length, JSObject *proto /* = nullptr */,
NewObjectKind newKind /* = GenericObject */)
{
return NewArray<0>(cx, length, proto, newKind);
return NewArray<false>(cx, length, proto, newKind);
}
ArrayObject * JS_FASTCALL
js::NewDenseArray(ExclusiveContext *cx, uint32_t length, HandleTypeObject type,
AllocatingBehaviour allocating)
js::NewDenseArray(ExclusiveContext *cx, uint32_t length, HandleTypeObject type, bool allocateArray)
{
NewObjectKind newKind = !type ? SingletonObject : GenericObject;
if (type && type->shouldPreTenure())
newKind = TenuredObject;
ArrayObject *arr;
if (allocating == NewArray_Unallocating) {
arr = NewDenseUnallocatedArray(cx, length, nullptr, newKind);
} else if (allocating == NewArray_PartlyAllocating) {
arr = NewDensePartlyAllocatedArray(cx, length, nullptr, newKind);
} else {
JS_ASSERT(allocating == NewArray_FullyAllocating);
arr = NewDenseFullyAllocatedArray(cx, length, nullptr, newKind);
}
// Allocate dense elements eagerly for small arrays, to avoid reallocating
// elements when filling the array.
ArrayObject *arr = allocateArray
? NewDenseAllocatedArray(cx, length, nullptr, newKind)
: NewDenseUnallocatedArray(cx, length, nullptr, newKind);
if (!arr)
return nullptr;
@ -3340,7 +3320,7 @@ js::NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32
{
JS_ASSERT(!src->isIndexed());
ArrayObject* arr = NewArray<JSObject::NELEMENTS_LIMIT>(cx, length, proto);
ArrayObject* arr = NewArray<true>(cx, length, proto);
if (!arr)
return nullptr;
@ -3360,7 +3340,7 @@ ArrayObject *
js::NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values,
JSObject *proto /* = nullptr */, NewObjectKind newKind /* = GenericObject */)
{
ArrayObject* arr = NewArray<JSObject::NELEMENTS_LIMIT>(cx, length, proto);
ArrayObject* arr = NewArray<true>(cx, length, proto);
if (!arr)
return nullptr;
@ -3375,7 +3355,7 @@ js::NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values,
}
ArrayObject *
js::NewDenseFullyAllocatedArrayWithTemplate(JSContext *cx, uint32_t length, JSObject *templateObject)
js::NewDenseAllocatedArrayWithTemplate(JSContext *cx, uint32_t length, JSObject *templateObject)
{
gc::AllocKind allocKind = GuessArrayGCKind(length);
JS_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_));

View File

@ -48,6 +48,11 @@ extern ArrayObject * JS_FASTCALL
NewDenseEmptyArray(JSContext *cx, JSObject *proto = nullptr,
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
* contents. This is useful, e.g., when accepting length from the user.
@ -56,32 +61,12 @@ extern ArrayObject * JS_FASTCALL
NewDenseUnallocatedArray(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,
* 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
* contents if the length is not excessive.
*/
extern ArrayObject * JS_FASTCALL
NewDenseArray(ExclusiveContext *cx, uint32_t length, HandleTypeObject type,
AllocatingBehaviour allocating);
NewDenseArray(ExclusiveContext *cx, uint32_t length, HandleTypeObject type, bool allocateArray);
/* Create a dense array with a copy of the dense array elements in src. */
extern ArrayObject *
@ -94,7 +79,7 @@ NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, JSObjec
/* Create a dense array based on templateObject with the given length. */
extern ArrayObject *
NewDenseFullyAllocatedArrayWithTemplate(JSContext *cx, uint32_t length, JSObject *templateObject);
NewDenseAllocatedArrayWithTemplate(JSContext *cx, uint32_t length, JSObject *templateObject);
/* Create a dense array with the same copy-on-write elements as another object. */
extern JSObject *

View File

@ -2372,7 +2372,7 @@ js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
JS_ASSERT(srcObj->getElementsHeader()->ownerObject() == srcObj);
size_t length = srcObj->as<ArrayObject>().length();
RootedObject res(cx, NewDenseFullyAllocatedArray(cx, length, nullptr, MaybeSingletonObject));
RootedObject res(cx, NewDenseAllocatedArray(cx, length, nullptr, MaybeSingletonObject));
if (!res)
return nullptr;

View File

@ -724,7 +724,7 @@ NodeBuilder::newArray(NodeVector &elts, MutableHandleValue dst)
js_ReportAllocationOverflow(cx);
return false;
}
RootedObject array(cx, NewDenseFullyAllocatedArray(cx, uint32_t(len)));
RootedObject array(cx, NewDenseAllocatedArray(cx, uint32_t(len)));
if (!array)
return false;

View File

@ -14,10 +14,8 @@ namespace js {
class ArrayObject : public JSObject
{
public:
// Array(x) eagerly allocates dense elements if x <= this value. Without
// 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;
// Array(x) eagerly allocates dense elements if x <= this value.
static const uint32_t EagerAllocationMaxLength = 2048;
static const Class class_;

View File

@ -2183,7 +2183,7 @@ bool
Debugger::getDebuggees(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "getDebuggees", args, dbg);
RootedObject arrobj(cx, NewDenseFullyAllocatedArray(cx, dbg->debuggees.count()));
RootedObject arrobj(cx, NewDenseAllocatedArray(cx, dbg->debuggees.count()));
if (!arrobj)
return false;
arrobj->ensureDenseInitializedLength(cx, 0, dbg->debuggees.count());
@ -2938,7 +2938,7 @@ Debugger::findScripts(JSContext *cx, unsigned argc, Value *vp)
if (!query.findScripts(&scripts))
return false;
RootedObject result(cx, NewDenseFullyAllocatedArray(cx, scripts.length()));
RootedObject result(cx, NewDenseAllocatedArray(cx, scripts.length()));
if (!result)
return false;
@ -5217,7 +5217,7 @@ DebuggerObject_getParameterNames(JSContext *cx, unsigned argc, Value *vp)
return true;
}
RootedObject result(cx, NewDenseFullyAllocatedArray(cx, fun->nargs()));
RootedObject result(cx, NewDenseAllocatedArray(cx, fun->nargs()));
if (!result)
return false;
result->ensureDenseInitializedLength(cx, 0, fun->nargs());

View File

@ -191,7 +191,7 @@ DebuggerMemory::drainAllocationsLog(JSContext *cx, unsigned argc, Value *vp)
size_t length = dbg->allocationsLogLength;
RootedObject result(cx, NewDenseFullyAllocatedArray(cx, length));
RootedObject result(cx, NewDenseAllocatedArray(cx, length));
if (!result)
return false;
result->ensureDenseInitializedLength(cx, 0, length);

View File

@ -3071,7 +3071,7 @@ CASE(JSOP_NEWARRAY)
unsigned count = GET_UINT24(REGS.pc);
RootedObject &obj = rootObject0;
NewObjectKind newKind = UseNewTypeForInitializer(script, REGS.pc, &ArrayObject::class_);
obj = NewDenseFullyAllocatedArray(cx, count, nullptr, newKind);
obj = NewDenseAllocatedArray(cx, count, nullptr, newKind);
if (!obj || !SetInitializerObjectType(cx, script, REGS.pc, obj, newKind))
goto error;

View File

@ -409,7 +409,7 @@ js::intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp)
uint32_t length = args[0].toInt32();
// Make a new buffer and initialize it up to length.
RootedObject buffer(cx, NewDenseFullyAllocatedArray(cx, length));
RootedObject buffer(cx, NewDenseAllocatedArray(cx, length));
if (!buffer)
return false;