Backed out changeset fdf5862a8c00 (bug 1176451) a=backout

This commit is contained in:
Wes Kocher 2015-08-06 18:38:22 -07:00
parent 3fc4028393
commit 4f23694eb2
7 changed files with 91 additions and 289 deletions

View File

@ -9541,7 +9541,7 @@ TryAttachFunCallStub(JSContext* cx, ICCall_Fallback* stub, HandleScript script,
static bool
GetTemplateObjectForNative(JSContext* cx, Native native, const CallArgs& args,
MutableHandleObject res, bool* skipAttach)
MutableHandleObject res)
{
// Check for natives to which template objects can be attached. This is
// done to provide templates to Ion for inlining these natives later on.
@ -9557,17 +9557,10 @@ GetTemplateObjectForNative(JSContext* cx, Native native, const CallArgs& args,
count = args[0].toInt32();
if (count <= ArrayObject::EagerAllocationMaxLength) {
ObjectGroup* group = ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array);
if (!group)
return false;
if (group->maybePreliminaryObjects()) {
*skipAttach = true;
return true;
}
// With this and other array templates, set forceAnalyze so that we
// don't end up with a template whose structure might change later.
res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, count, TenuredObject));
res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, count, TenuredObject,
/* forceAnalyze = */ true));
if (!res)
return false;
return true;
@ -9575,30 +9568,17 @@ GetTemplateObjectForNative(JSContext* cx, Native native, const CallArgs& args,
}
if (native == js::array_concat || native == js::array_slice) {
if (args.thisv().isObject()) {
JSObject* obj = &args.thisv().toObject();
if (!obj->isSingleton()) {
if (obj->group()->maybePreliminaryObjects()) {
*skipAttach = true;
return true;
}
res.set(NewFullyAllocatedArrayTryReuseGroup(cx, &args.thisv().toObject(), 0,
TenuredObject));
return !!res;
}
if (args.thisv().isObject() && !args.thisv().toObject().isSingleton()) {
res.set(NewFullyAllocatedArrayTryReuseGroup(cx, &args.thisv().toObject(), 0,
TenuredObject, /* forceAnalyze = */ true));
if (!res)
return false;
}
}
if (native == js::str_split && args.length() == 1 && args[0].isString()) {
ObjectGroup* group = ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array);
if (!group)
return false;
if (group->maybePreliminaryObjects()) {
*skipAttach = true;
return true;
}
res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, 0, TenuredObject));
res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, 0, TenuredObject,
/* forceAnalyze = */ true));
if (!res)
return false;
return true;
@ -9897,15 +9877,9 @@ TryAttachCallStub(JSContext* cx, ICCall_Fallback* stub, HandleScript script, jsb
RootedObject templateObject(cx);
if (MOZ_LIKELY(!isSpread)) {
bool skipAttach = false;
CallArgs args = CallArgsFromVp(argc, vp);
if (!GetTemplateObjectForNative(cx, fun->native(), args, &templateObject, &skipAttach))
if (!GetTemplateObjectForNative(cx, fun->native(), args, &templateObject))
return false;
if (skipAttach) {
*handled = true;
return true;
}
MOZ_ASSERT_IF(templateObject, !templateObject->group()->maybePreliminaryObjects());
}
JitSpew(JitSpew_BaselineIC, " Generating Call_Native stub (fun=%p, cons=%s, spread=%s)",

View File

@ -7222,23 +7222,22 @@ CodeGenerator::visitArrayConcat(LArrayConcat* lir)
// inline and pass it to the stub. Else, we just pass nullptr and the stub falls
// back to a slow path.
Label fail, call;
if (lir->mir()->unboxedThis()) {
masm.load32(Address(lhs, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), temp1);
masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), temp1);
masm.branch32(Assembler::NotEqual, Address(lhs, UnboxedArrayObject::offsetOfLength()), temp1, &fail);
} else {
if (lir->mir()->unboxedType() == JSVAL_TYPE_MAGIC) {
masm.loadPtr(Address(lhs, NativeObject::offsetOfElements()), temp1);
masm.load32(Address(temp1, ObjectElements::offsetOfInitializedLength()), temp2);
masm.branch32(Assembler::NotEqual, Address(temp1, ObjectElements::offsetOfLength()), temp2, &fail);
}
if (lir->mir()->unboxedArg()) {
masm.load32(Address(rhs, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), temp1);
masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), temp1);
masm.branch32(Assembler::NotEqual, Address(rhs, UnboxedArrayObject::offsetOfLength()), temp1, &fail);
} else {
masm.loadPtr(Address(rhs, NativeObject::offsetOfElements()), temp1);
masm.load32(Address(temp1, ObjectElements::offsetOfInitializedLength()), temp2);
masm.branch32(Assembler::NotEqual, Address(temp1, ObjectElements::offsetOfLength()), temp2, &fail);
} else {
masm.load32(Address(lhs, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), temp1);
masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), temp1);
masm.branch32(Assembler::NotEqual, Address(lhs, UnboxedArrayObject::offsetOfLength()), temp1, &fail);
masm.load32(Address(rhs, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), temp1);
masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), temp1);
masm.branch32(Assembler::NotEqual, Address(rhs, UnboxedArrayObject::offsetOfLength()), temp1, &fail);
}
// Try to allocate an object.

View File

@ -864,10 +864,9 @@ IonBuilder::inlineArrayConcat(CallInfo& callInfo)
if (!thisTypes || !argTypes)
return InliningStatus_NotInlined;
const Class* thisClasp = thisTypes->getKnownClass(constraints());
if (thisClasp != &ArrayObject::class_ && thisClasp != &UnboxedArrayObject::class_)
const Class* clasp = thisTypes->getKnownClass(constraints());
if (clasp != &ArrayObject::class_ && clasp != &UnboxedArrayObject::class_)
return InliningStatus_NotInlined;
bool unboxedThis = (thisClasp == &UnboxedArrayObject::class_);
if (thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_SPARSE_INDEXES |
OBJECT_FLAG_LENGTH_OVERFLOW))
{
@ -875,10 +874,8 @@ IonBuilder::inlineArrayConcat(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
const Class* argClasp = argTypes->getKnownClass(constraints());
if (argClasp != &ArrayObject::class_ && argClasp != &UnboxedArrayObject::class_)
if (argTypes->getKnownClass(constraints()) != clasp)
return InliningStatus_NotInlined;
bool unboxedArg = (argClasp == &UnboxedArrayObject::class_);
if (argTypes->hasObjectFlags(constraints(), OBJECT_FLAG_SPARSE_INDEXES |
OBJECT_FLAG_LENGTH_OVERFLOW))
{
@ -886,6 +883,15 @@ IonBuilder::inlineArrayConcat(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
JSValueType unboxedType = JSVAL_TYPE_MAGIC;
if (clasp == &UnboxedArrayObject::class_) {
unboxedType = UnboxedArrayElementType(constraints(), thisArg, nullptr);
if (unboxedType == JSVAL_TYPE_MAGIC)
return InliningStatus_NotInlined;
if (unboxedType != UnboxedArrayElementType(constraints(), objArg, nullptr))
return InliningStatus_NotInlined;
}
// Watch out for indexed properties on the prototype.
if (ArrayPrototypeHasIndexedProperty(this, script())) {
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
@ -945,7 +951,7 @@ IonBuilder::inlineArrayConcat(CallInfo& callInfo)
MArrayConcat* ins = MArrayConcat::New(alloc(), constraints(), thisArg, objArg,
templateObj,
templateObj->group()->initialHeap(constraints()),
unboxedThis, unboxedArg);
unboxedType);
current->add(ins);
current->push(ins);

View File

@ -9186,16 +9186,14 @@ class MArrayConcat
{
CompilerObject templateObj_;
gc::InitialHeap initialHeap_;
bool unboxedThis_, unboxedArg_;
JSValueType unboxedType_;
MArrayConcat(CompilerConstraintList* constraints, MDefinition* lhs, MDefinition* rhs,
JSObject* templateObj, gc::InitialHeap initialHeap,
bool unboxedThis, bool unboxedArg)
JSObject* templateObj, gc::InitialHeap initialHeap, JSValueType unboxedType)
: MBinaryInstruction(lhs, rhs),
templateObj_(templateObj),
initialHeap_(initialHeap),
unboxedThis_(unboxedThis),
unboxedArg_(unboxedArg)
unboxedType_(unboxedType)
{
setResultType(MIRType_Object);
setResultTypeSet(MakeSingletonTypeSet(constraints, templateObj));
@ -9207,10 +9205,10 @@ class MArrayConcat
static MArrayConcat* New(TempAllocator& alloc, CompilerConstraintList* constraints,
MDefinition* lhs, MDefinition* rhs,
JSObject* templateObj, gc::InitialHeap initialHeap,
bool unboxedThis, bool unboxedArg)
JSValueType unboxedType)
{
return new(alloc) MArrayConcat(constraints, lhs, rhs, templateObj,
initialHeap, unboxedThis, unboxedArg);
initialHeap, unboxedType);
}
JSObject* templateObj() const {
@ -9221,17 +9219,12 @@ class MArrayConcat
return initialHeap_;
}
bool unboxedThis() const {
return unboxedThis_;
}
bool unboxedArg() const {
return unboxedArg_;
JSValueType unboxedType() const {
return unboxedType_;
}
AliasSet getAliasSet() const override {
return AliasSet::Store(AliasSet::BoxedOrUnboxedElements(unboxedThis() ? JSVAL_TYPE_INT32 : JSVAL_TYPE_MAGIC) |
AliasSet::BoxedOrUnboxedElements(unboxedArg() ? JSVAL_TYPE_INT32 : JSVAL_TYPE_MAGIC) |
return AliasSet::Store(AliasSet::BoxedOrUnboxedElements(unboxedType()) |
AliasSet::ObjectFields);
}
bool possiblyCalls() const override {

View File

@ -2563,41 +2563,40 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
return true;
}
template <JSValueType TypeOne, JSValueType TypeTwo>
template <JSValueType Type>
DenseElementResult
ArrayConcatDenseKernel(JSContext* cx, JSObject* obj1, JSObject* obj2, JSObject* result)
{
uint32_t initlen1 = GetBoxedOrUnboxedInitializedLength<TypeOne>(obj1);
uint32_t initlen1 = GetBoxedOrUnboxedInitializedLength<Type>(obj1);
MOZ_ASSERT(initlen1 == GetAnyBoxedOrUnboxedArrayLength(obj1));
uint32_t initlen2 = GetBoxedOrUnboxedInitializedLength<TypeTwo>(obj2);
uint32_t initlen2 = GetBoxedOrUnboxedInitializedLength<Type>(obj2);
MOZ_ASSERT(initlen2 == GetAnyBoxedOrUnboxedArrayLength(obj2));
/* No overflow here due to nelements limit. */
uint32_t len = initlen1 + initlen2;
MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength<TypeOne>(result) == 0);
MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength<Type>(result) == 0);
DenseElementResult rv = EnsureBoxedOrUnboxedDenseElements<TypeOne>(cx, result, len);
if (rv != DenseElementResult::Success)
return rv;
if (!EnsureBoxedOrUnboxedDenseElements<Type>(cx, result, len))
return DenseElementResult::Failure;
CopyBoxedOrUnboxedDenseElements<TypeOne, TypeOne>(cx, result, obj1, 0, 0, initlen1);
CopyBoxedOrUnboxedDenseElements<TypeOne, TypeTwo>(cx, result, obj2, initlen1, 0, initlen2);
CopyBoxedOrUnboxedDenseElements<Type>(cx, result, obj1, 0, 0, initlen1);
CopyBoxedOrUnboxedDenseElements<Type>(cx, result, obj2, initlen1, 0, initlen2);
SetAnyBoxedOrUnboxedArrayLength(cx, result, len);
return DenseElementResult::Success;
}
DefineBoxedOrUnboxedFunctorPair4(ArrayConcatDenseKernel,
JSContext*, JSObject*, JSObject*, JSObject*);
DefineBoxedOrUnboxedFunctor4(ArrayConcatDenseKernel,
JSContext*, JSObject*, JSObject*, JSObject*);
bool
js::array_concat_dense(JSContext* cx, HandleObject obj1, HandleObject obj2,
HandleObject result)
{
ArrayConcatDenseKernelFunctor functor(cx, obj1, obj2, result);
DenseElementResult rv = CallBoxedOrUnboxedSpecialization(functor, obj1, obj2);
DenseElementResult rv = CallBoxedOrUnboxedSpecialization(functor, result);
MOZ_ASSERT(rv != DenseElementResult::Incomplete);
return rv == DenseElementResult::Success;
}
@ -2628,63 +2627,17 @@ js::array_concat(JSContext* cx, unsigned argc, Value* vp)
narr = NewFullyAllocatedArrayTryReuseGroup(cx, aobj, initlen);
if (!narr)
return false;
CopyAnyBoxedOrUnboxedDenseElements(cx, narr, aobj, 0, 0, initlen);
SetAnyBoxedOrUnboxedArrayLength(cx, narr, length);
DebugOnly<DenseElementResult> result =
CopyAnyBoxedOrUnboxedDenseElements(cx, narr, aobj, 0, 0, initlen);
MOZ_ASSERT(result.value == DenseElementResult::Success);
args.rval().setObject(*narr);
if (argc == 0)
return true;
argc--;
p++;
if (length == initlen) {
while (argc) {
HandleValue v = HandleValue::fromMarkedLocation(p);
if (!v.isObject())
break;
RootedObject obj(cx, &v.toObject());
// This should be IsConcatSpreadable
if (!IsArray(obj, cx) || ObjectMayHaveExtraIndexedProperties(obj))
break;
uint32_t argLength;
if (!GetLengthProperty(cx, obj, &argLength))
return false;
initlen = GetAnyBoxedOrUnboxedInitializedLength(obj);
if (argLength != initlen)
break;
DenseElementResult result =
EnsureAnyBoxedOrUnboxedDenseElements(cx, narr, length + argLength);
if (result == DenseElementResult::Failure)
return false;
if (result == DenseElementResult::Incomplete)
break;
SetAnyBoxedOrUnboxedInitializedLength(cx, narr, length + argLength);
bool success = true;
for (size_t i = 0; i < initlen; i++) {
Value v = GetAnyBoxedOrUnboxedDenseElement(obj, i);
if (!InitAnyBoxedOrUnboxedDenseElement(cx, narr, length + i, v)) {
success = false;
break;
}
}
if (!success) {
SetAnyBoxedOrUnboxedInitializedLength(cx, narr, length);
break;
}
length += argLength;
SetAnyBoxedOrUnboxedArrayLength(cx, narr, length);
argc--;
p++;
}
}
} else {
narr = NewDenseEmptyArray(cx);
if (!narr)
@ -2981,10 +2934,9 @@ ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t en
if (initlen > begin) {
size_t count = Min<size_t>(initlen - begin, end - begin);
if (count) {
DenseElementResult rv = EnsureBoxedOrUnboxedDenseElements<Type>(cx, result, count);
if (rv != DenseElementResult::Success)
return rv;
CopyBoxedOrUnboxedDenseElements<Type, Type>(cx, result, obj, 0, begin, count);
if (!EnsureBoxedOrUnboxedDenseElements<Type>(cx, result, count))
return DenseElementResult::Failure;
CopyBoxedOrUnboxedDenseElements<Type>(cx, result, obj, 0, begin, count);
}
}

View File

@ -272,12 +272,6 @@ UnboxedArrayObject::triggerPreBarrier(size_t index)
// Combined methods for NativeObject and UnboxedArrayObject accesses.
/////////////////////////////////////////////////////////////////////
static inline bool
HasAnyBoxedOrUnboxedDenseElements(JSObject* obj)
{
return obj->isNative() || obj->is<UnboxedArrayObject>();
}
static inline size_t
GetAnyBoxedOrUnboxedInitializedLength(JSObject* obj)
{
@ -336,16 +330,6 @@ SetAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, con
return obj->as<UnboxedArrayObject>().setElement(cx, index, value);
}
static inline bool
InitAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
{
if (obj->isNative()) {
obj->as<NativeObject>().initDenseElementWithType(cx, index, value);
return true;
}
return obj->as<UnboxedArrayObject>().initElement(cx, index, value);
}
/////////////////////////////////////////////////////////////////////
// Template methods for NativeObject and UnboxedArrayObject accesses.
/////////////////////////////////////////////////////////////////////
@ -433,19 +417,19 @@ SetBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const
}
template <JSValueType Type>
static inline DenseElementResult
static inline bool
EnsureBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count)
{
if (Type == JSVAL_TYPE_MAGIC) {
if (!obj->as<ArrayObject>().ensureElements(cx, count))
return DenseElementResult::Failure;
return false;
} else {
if (obj->as<UnboxedArrayObject>().capacity() < count) {
if (!obj->as<UnboxedArrayObject>().growElements(cx, count))
return DenseElementResult::Failure;
return false;
}
}
return DenseElementResult::Success;
return true;
}
template <JSValueType Type>
@ -563,54 +547,33 @@ MoveBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, uint32_t dstStart,
return DenseElementResult::Success;
}
template <JSValueType DstType, JSValueType SrcType>
template <JSValueType Type>
static inline DenseElementResult
CopyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
uint32_t dstStart, uint32_t srcStart, uint32_t length)
{
MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<SrcType>(src));
MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<DstType>(dst));
MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength<DstType>(dst) == dstStart);
MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength<DstType>(src) >= srcStart + length);
MOZ_ASSERT(GetBoxedOrUnboxedCapacity<DstType>(dst) >= dstStart + length);
MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<Type>(src));
MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<Type>(dst));
MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength<Type>(dst) == dstStart);
MOZ_ASSERT(GetBoxedOrUnboxedCapacity<Type>(dst) >= length);
SetBoxedOrUnboxedInitializedLength<DstType>(cx, dst, dstStart + length);
SetBoxedOrUnboxedInitializedLength<Type>(cx, dst, dstStart + length);
if (DstType == JSVAL_TYPE_MAGIC) {
if (SrcType == JSVAL_TYPE_MAGIC) {
const Value* vp = src->as<NativeObject>().getDenseElements() + srcStart;
dst->as<NativeObject>().initDenseElements(dstStart, vp, length);
} else {
for (size_t i = 0; i < length; i++) {
Value v = GetBoxedOrUnboxedDenseElement<SrcType>(src, srcStart + i);
dst->as<NativeObject>().initDenseElement(dstStart + i, v);
}
}
} else if (DstType == SrcType) {
if (Type == JSVAL_TYPE_MAGIC) {
const Value* vp = src->as<NativeObject>().getDenseElements() + srcStart;
dst->as<NativeObject>().initDenseElements(dstStart, vp, length);
} else {
uint8_t* dstData = dst->as<UnboxedArrayObject>().elements();
uint8_t* srcData = src->as<UnboxedArrayObject>().elements();
size_t elementSize = UnboxedTypeSize(DstType);
size_t elementSize = UnboxedTypeSize(Type);
memcpy(dstData + dstStart * elementSize,
srcData + srcStart * elementSize,
length * elementSize);
// Add a store buffer entry if we might have copied a nursery pointer to dst.
if (UnboxedTypeNeedsPostBarrier(DstType) && !IsInsideNursery(dst))
if (UnboxedTypeNeedsPostBarrier(Type) && !IsInsideNursery(dst))
dst->runtimeFromMainThread()->gc.storeBuffer.putWholeCellFromMainThread(dst);
} else if (DstType == JSVAL_TYPE_DOUBLE && SrcType == JSVAL_TYPE_INT32) {
uint8_t* dstData = dst->as<UnboxedArrayObject>().elements();
uint8_t* srcData = src->as<UnboxedArrayObject>().elements();
for (size_t i = 0; i < length; i++) {
int32_t v = *reinterpret_cast<int32_t*>(srcData + (srcStart + i) * sizeof(int32_t));
*reinterpret_cast<double*>(dstData + (dstStart + i) * sizeof(double)) = v;
}
} else {
for (size_t i = 0; i < length; i++) {
Value v = GetBoxedOrUnboxedDenseElement<SrcType>(src, srcStart + i);
dst->as<UnboxedArrayObject>().initElementNoTypeChangeSpecific<DstType>(dstStart + i, v);
}
}
return DenseElementResult::Success;
@ -633,70 +596,19 @@ template <typename F>
DenseElementResult
CallBoxedOrUnboxedSpecialization(F f, JSObject* obj)
{
if (!HasAnyBoxedOrUnboxedDenseElements(obj))
return DenseElementResult::Incomplete;
switch (GetBoxedOrUnboxedType(obj)) {
case JSVAL_TYPE_MAGIC:
if (HasBoxedOrUnboxedDenseElements<JSVAL_TYPE_MAGIC>(obj))
return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC>();
case JSVAL_TYPE_BOOLEAN:
if (HasBoxedOrUnboxedDenseElements<JSVAL_TYPE_BOOLEAN>(obj))
return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_BOOLEAN>();
case JSVAL_TYPE_INT32:
if (HasBoxedOrUnboxedDenseElements<JSVAL_TYPE_INT32>(obj))
return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_INT32>();
case JSVAL_TYPE_DOUBLE:
if (HasBoxedOrUnboxedDenseElements<JSVAL_TYPE_DOUBLE>(obj))
return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_DOUBLE>();
case JSVAL_TYPE_STRING:
if (HasBoxedOrUnboxedDenseElements<JSVAL_TYPE_STRING>(obj))
return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_STRING>();
case JSVAL_TYPE_OBJECT:
if (HasBoxedOrUnboxedDenseElements<JSVAL_TYPE_OBJECT>(obj))
return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_OBJECT>();
default:
MOZ_CRASH();
}
}
// As above, except the specialization can reflect the unboxed type of two objects.
template <typename F>
DenseElementResult
CallBoxedOrUnboxedSpecialization(F f, JSObject* obj1, JSObject* obj2)
{
if (!HasAnyBoxedOrUnboxedDenseElements(obj1) || !HasAnyBoxedOrUnboxedDenseElements(obj2))
return DenseElementResult::Incomplete;
#define SPECIALIZE_OBJ2(TYPE) \
switch (GetBoxedOrUnboxedType(obj2)) { \
case JSVAL_TYPE_MAGIC: \
return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_MAGIC>(); \
case JSVAL_TYPE_BOOLEAN: \
return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_BOOLEAN>(); \
case JSVAL_TYPE_INT32: \
return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_INT32>(); \
case JSVAL_TYPE_DOUBLE: \
return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_DOUBLE>(); \
case JSVAL_TYPE_STRING: \
return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_STRING>(); \
case JSVAL_TYPE_OBJECT: \
return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_OBJECT>(); \
default: \
MOZ_CRASH(); \
}
switch (GetBoxedOrUnboxedType(obj1)) {
case JSVAL_TYPE_MAGIC:
SPECIALIZE_OBJ2(JSVAL_TYPE_MAGIC)
case JSVAL_TYPE_BOOLEAN:
SPECIALIZE_OBJ2(JSVAL_TYPE_BOOLEAN)
case JSVAL_TYPE_INT32:
SPECIALIZE_OBJ2(JSVAL_TYPE_INT32)
case JSVAL_TYPE_DOUBLE:
SPECIALIZE_OBJ2(JSVAL_TYPE_DOUBLE)
case JSVAL_TYPE_STRING:
SPECIALIZE_OBJ2(JSVAL_TYPE_STRING)
case JSVAL_TYPE_OBJECT:
SPECIALIZE_OBJ2(JSVAL_TYPE_OBJECT)
default:
MOZ_CRASH();
}
#undef SPECIALIZE_OBJ2
return DenseElementResult::Incomplete;
}
#undef DEPENDENT_TEMPLATE_HINT
@ -737,18 +649,6 @@ struct Signature ## Functor { \
} \
}
#define DefineBoxedOrUnboxedFunctorPair4(Signature, A, B, C, D) \
struct Signature ## Functor { \
A a; B b; C c; D d; \
Signature ## Functor(A a, B b, C c, D d) \
: a(a), b(b), c(c), d(d) \
{} \
template <JSValueType TypeOne, JSValueType TypeTwo> \
DenseElementResult operator()() { \
return Signature<TypeOne, TypeTwo>(a, b, c, d); \
} \
}
#define DefineBoxedOrUnboxedFunctor5(Signature, A, B, C, D, E) \
struct Signature ## Functor { \
A a; B b; C c; D d; E e; \
@ -773,18 +673,6 @@ struct Signature ## Functor { \
} \
}
#define DefineBoxedOrUnboxedFunctorPair6(Signature, A, B, C, D, E, F) \
struct Signature ## Functor { \
A a; B b; C c; D d; E e; F f; \
Signature ## Functor(A a, B b, C c, D d, E e, F f) \
: a(a), b(b), c(c), d(d), e(e), f(f) \
{} \
template <JSValueType TypeOne, JSValueType TypeTwo> \
DenseElementResult operator()() { \
return Signature<TypeOne, TypeTwo>(a, b, c, d, e, f); \
} \
}
DenseElementResult
SetOrExtendAnyBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj,
uint32_t start, const Value* vp, uint32_t count,
@ -801,7 +689,7 @@ CopyAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
void
SetAnyBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen);
DenseElementResult
bool
EnsureAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count);
} // namespace js

View File

@ -1671,9 +1671,11 @@ CombineArrayObjectElements(ExclusiveContext* cx, ArrayObject* obj, JSValueType*
{
if (obj->inDictionaryMode() ||
obj->lastProperty()->propid() != AtomToId(cx->names().length) ||
!obj->lastProperty()->previous()->isEmptyShape())
!obj->lastProperty()->previous()->isEmptyShape() ||
!obj->getDenseInitializedLength())
{
// Only use an unboxed representation if the object has no properties.
// Only use an unboxed representation if the object has at
// least one element, and no properties.
return false;
}
@ -1828,8 +1830,6 @@ UnboxedArrayObject::fillAfterConvert(ExclusiveContext* cx,
setLength(cx, NextValue(values, valueCursor).toInt32());
int32_t initlen = NextValue(values, valueCursor).toInt32();
if (!initlen)
return;
if (!growElements(cx, initlen))
CrashAtUnhandlableOOM("UnboxedArrayObject::fillAfterConvert");
@ -2055,15 +2055,15 @@ js::MoveAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj,
return CallBoxedOrUnboxedSpecialization(functor, obj);
}
DefineBoxedOrUnboxedFunctorPair6(CopyBoxedOrUnboxedDenseElements,
JSContext*, JSObject*, JSObject*, uint32_t, uint32_t, uint32_t);
DefineBoxedOrUnboxedFunctor6(CopyBoxedOrUnboxedDenseElements,
JSContext*, JSObject*, JSObject*, uint32_t, uint32_t, uint32_t);
DenseElementResult
js::CopyAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
uint32_t dstStart, uint32_t srcStart, uint32_t length)
{
CopyBoxedOrUnboxedDenseElementsFunctor functor(cx, dst, src, dstStart, srcStart, length);
return CallBoxedOrUnboxedSpecialization(functor, dst, src);
return CallBoxedOrUnboxedSpecialization(functor, dst);
}
DefineBoxedOrUnboxedFunctor3(SetBoxedOrUnboxedInitializedLength,
@ -2075,13 +2075,3 @@ js::SetAnyBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t i
SetBoxedOrUnboxedInitializedLengthFunctor functor(cx, obj, initlen);
JS_ALWAYS_TRUE(CallBoxedOrUnboxedSpecialization(functor, obj) == DenseElementResult::Success);
}
DefineBoxedOrUnboxedFunctor3(EnsureBoxedOrUnboxedDenseElements,
JSContext*, JSObject*, size_t);
DenseElementResult
js::EnsureAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t initlen)
{
EnsureBoxedOrUnboxedDenseElementsFunctor functor(cx, obj, initlen);
return CallBoxedOrUnboxedSpecialization(functor, obj);
}