summaryrefslogtreecommitdiffstats
path: root/js/src/jsarray.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsarray.cpp')
-rw-r--r--js/src/jsarray.cpp166
1 files changed, 58 insertions, 108 deletions
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 0d6f78fcf..9abc99e34 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -333,37 +333,31 @@ js::GetElementsWithAdder(JSContext* cx, HandleObject obj, HandleObject receiver,
return true;
}
-template <JSValueType Type>
-DenseElementResult
-GetBoxedOrUnboxedDenseElements(JSObject* aobj, uint32_t length, Value* vp)
+static bool
+GetDenseElements(NativeObject* aobj, uint32_t length, Value* vp)
{
MOZ_ASSERT(!ObjectMayHaveExtraIndexedProperties(aobj));
- if (length > aobj->as<NativeObject>().getDenseInitializedLength())
- return DenseElementResult::Incomplete;
+ if (length > aobj->getDenseInitializedLength())
+ return false;
for (size_t i = 0; i < length; i++) {
- vp[i] = aobj->as<NativeObject>().getDenseElement(i);
+ vp[i] = aobj->getDenseElement(i);
// No other indexed properties so hole => undefined.
if (vp[i].isMagic(JS_ELEMENTS_HOLE))
vp[i] = UndefinedValue();
}
- return DenseElementResult::Success;
+ return true;
}
-DefineBoxedOrUnboxedFunctor3(GetBoxedOrUnboxedDenseElements,
- JSObject*, uint32_t, Value*);
-
bool
js::GetElements(JSContext* cx, HandleObject aobj, uint32_t length, Value* vp)
{
if (!ObjectMayHaveExtraIndexedProperties(aobj)) {
- GetBoxedOrUnboxedDenseElementsFunctor functor(aobj, length, vp);
- DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, aobj);
- if (result != DenseElementResult::Incomplete)
- return result == DenseElementResult::Success;
+ if (GetDenseElements(&aobj->as<NativeObject>(), length, vp))
+ return true;
}
if (aobj->is<ArgumentsObject>()) {
@@ -1061,32 +1055,32 @@ struct StringSeparatorOp
}
};
-template <typename SeparatorOp, JSValueType Type>
-static DenseElementResult
-ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_t length,
+template <typename SeparatorOp>
+static bool
+ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleNativeObject obj, uint64_t length,
StringBuffer& sb, uint32_t* numProcessed)
{
// This loop handles all elements up to initializedLength. If
// length > initLength we rely on the second loop to add the
// other elements.
MOZ_ASSERT(*numProcessed == 0);
- uint32_t initLength = Min<uint32_t>(obj->as<NativeObject>().getDenseInitializedLength(),
+ uint32_t initLength = Min<uint32_t>(obj->getDenseInitializedLength(),
length);
while (*numProcessed < initLength) {
if (!CheckForInterrupt(cx))
- return DenseElementResult::Failure;
+ return false;
Value elem = obj->as<NativeObject>().getDenseElement(*numProcessed);
if (elem.isString()) {
if (!sb.append(elem.toString()))
- return DenseElementResult::Failure;
+ return false;
} else if (elem.isNumber()) {
if (!NumberValueToStringBuffer(cx, elem, sb))
- return DenseElementResult::Failure;
+ return false;
} else if (elem.isBoolean()) {
if (!BooleanToStringBuffer(elem.toBoolean(), sb))
- return DenseElementResult::Failure;
+ return false;
} else if (elem.isObject() || elem.isSymbol()) {
/*
* Object stringifying could modify the initialized length or make
@@ -1102,33 +1096,13 @@ ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_
}
if (++(*numProcessed) != length && !sepOp(cx, sb))
- return DenseElementResult::Failure;
+ return false;
}
- return DenseElementResult::Incomplete;
+ return true;
}
template <typename SeparatorOp>
-struct ArrayJoinDenseKernelFunctor {
- JSContext* cx;
- SeparatorOp sepOp;
- HandleObject obj;
- uint32_t length;
- StringBuffer& sb;
- uint32_t* numProcessed;
-
- ArrayJoinDenseKernelFunctor(JSContext* cx, SeparatorOp sepOp, HandleObject obj,
- uint32_t length, StringBuffer& sb, uint32_t* numProcessed)
- : cx(cx), sepOp(sepOp), obj(obj), length(length), sb(sb), numProcessed(numProcessed)
- {}
-
- template <JSValueType Type>
- DenseElementResult operator()() {
- return ArrayJoinDenseKernel<SeparatorOp, Type>(cx, sepOp, obj, length, sb, numProcessed);
- }
-};
-
-template <typename SeparatorOp>
static bool
ArrayJoinKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_t length,
StringBuffer& sb)
@@ -1136,10 +1110,10 @@ ArrayJoinKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_t len
uint32_t i = 0;
if (!ObjectMayHaveExtraIndexedProperties(obj)) {
- ArrayJoinDenseKernelFunctor<SeparatorOp> functor(cx, sepOp, obj, length, sb, &i);
- DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
- if (result == DenseElementResult::Failure)
+ if (!ArrayJoinDenseKernel<SeparatorOp>(cx, sepOp, obj.as<NativeObject>(), length, sb, &i))
+ {
return false;
+ }
}
if (i != length) {
@@ -1260,7 +1234,7 @@ js::array_join(JSContext* cx, unsigned argc, Value* vp)
}
// Step 11
- JSString *str = sb.finishString();
+ JSString* str = sb.finishString();
if (!str)
return false;
@@ -1360,15 +1334,14 @@ InitArrayElements(JSContext* cx, HandleObject obj, uint32_t start,
return true;
}
-template <JSValueType Type>
-DenseElementResult
-ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
+static DenseElementResult
+ArrayReverseDenseKernel(JSContext* cx, HandleNativeObject obj, uint32_t length)
{
/* An empty array or an array with no elements is already reversed. */
- if (length == 0 || obj->as<NativeObject>().getDenseInitializedLength() == 0)
+ if (length == 0 || obj->getDenseInitializedLength() == 0)
return DenseElementResult::Success;
- if (obj->as<NativeObject>().denseElementsAreFrozen())
+ if (obj->denseElementsAreFrozen())
return DenseElementResult::Incomplete;
/*
@@ -1380,26 +1353,26 @@ ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
* holes in the array at its start) and ensure that the capacity is
* sufficient to hold all the elements in the array if it were full.
*/
- DenseElementResult result = obj->as<NativeObject>().ensureDenseElements(cx, length, 0);
+ DenseElementResult result = obj->ensureDenseElements(cx, length, 0);
if (result != DenseElementResult::Success)
return result;
/* Fill out the array's initialized length to its proper length. */
- obj->as<NativeObject>().ensureDenseInitializedLength(cx, length, 0);
+ obj->ensureDenseInitializedLength(cx, length, 0);
RootedValue origlo(cx), orighi(cx);
uint32_t lo = 0, hi = length - 1;
for (; lo < hi; lo++, hi--) {
- origlo = obj->as<NativeObject>().getDenseElement(lo);
- orighi = obj->as<NativeObject>().getDenseElement(hi);
- obj->as<NativeObject>().setDenseElement(lo, orighi);
+ origlo = obj->getDenseElement(lo);
+ orighi = obj->getDenseElement(hi);
+ obj->setDenseElement(lo, orighi);
if (orighi.isMagic(JS_ELEMENTS_HOLE) &&
!SuppressDeletedProperty(cx, obj, INT_TO_JSID(lo)))
{
return DenseElementResult::Failure;
}
- obj->as<NativeObject>().setDenseElement(hi, origlo);
+ obj->setDenseElement(hi, origlo);
if (origlo.isMagic(JS_ELEMENTS_HOLE) &&
!SuppressDeletedProperty(cx, obj, INT_TO_JSID(hi)))
{
@@ -1410,9 +1383,6 @@ ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
return DenseElementResult::Success;
}
-DefineBoxedOrUnboxedFunctor3(ArrayReverseDenseKernel,
- JSContext*, HandleObject, uint32_t);
-
bool
js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
{
@@ -1427,8 +1397,8 @@ js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
return false;
if (!ObjectMayHaveExtraIndexedProperties(obj)) {
- ArrayReverseDenseKernelFunctor functor(cx, obj, len);
- DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
+ DenseElementResult result =
+ ArrayReverseDenseKernel(cx, obj.as<NativeObject>(), uint32_t(len));
if (result != DenseElementResult::Incomplete) {
/*
* Per ECMA-262, don't update the length of the array, even if the new
@@ -2137,33 +2107,20 @@ js::array_pop(JSContext* cx, unsigned argc, Value* vp)
return SetLengthProperty(cx, obj, index);
}
-template <JSValueType Type>
-static inline DenseElementResult
-ShiftMoveBoxedOrUnboxedDenseElements(JSObject* obj)
+void
+js::ArrayShiftMoveElements(NativeObject* obj)
{
- MOZ_ASSERT(obj->isNative());
+ MOZ_ASSERT_IF(obj->is<ArrayObject>(), obj->as<ArrayObject>().lengthIsWritable());
- size_t initlen = obj->as<NativeObject>().getDenseInitializedLength();
+ size_t initlen = obj->getDenseInitializedLength();
+ MOZ_ASSERT(initlen > 0);
/*
* At this point the length and initialized length have already been
* decremented and the result fetched, so just shift the array elements
* themselves.
*/
- obj->as<NativeObject>().moveDenseElementsNoPreBarrier(0, 1, initlen);
-
- return DenseElementResult::Success;
-}
-
-DefineBoxedOrUnboxedFunctor1(ShiftMoveBoxedOrUnboxedDenseElements, JSObject*);
-
-void
-js::ArrayShiftMoveElements(JSObject* obj)
-{
- MOZ_ASSERT_IF(obj->is<ArrayObject>(), obj->as<ArrayObject>().lengthIsWritable());
-
- ShiftMoveBoxedOrUnboxedDenseElementsFunctor functor(obj);
- JS_ALWAYS_TRUE(CallBoxedOrUnboxedSpecialization(functor, obj) == DenseElementResult::Success);
+ obj->moveDenseElementsNoPreBarrier(0, 1, initlen - 1);
}
static inline void
@@ -2175,8 +2132,7 @@ SetInitializedLength(JSContext* cx, NativeObject* obj, size_t initlen)
obj->shrinkElements(cx, initlen);
}
-template <JSValueType Type>
-DenseElementResult
+static DenseElementResult
ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
{
if (ObjectMayHaveExtraIndexedProperties(obj))
@@ -2205,9 +2161,6 @@ ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
return DenseElementResult::Success;
}
-DefineBoxedOrUnboxedFunctor3(ArrayShiftDenseKernel,
- JSContext*, HandleObject, MutableHandleValue);
-
/* ES5 15.4.4.9 */
bool
js::array_shift(JSContext* cx, unsigned argc, Value* vp)
@@ -2239,8 +2192,7 @@ js::array_shift(JSContext* cx, unsigned argc, Value* vp)
uint32_t newlen = len - 1;
/* Fast paths. */
- ArrayShiftDenseKernelFunctor functor(cx, obj, args.rval());
- DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
+ DenseElementResult result = ArrayShiftDenseKernel(cx, obj, args.rval());
if (result != DenseElementResult::Incomplete) {
if (result == DenseElementResult::Failure)
return false;
@@ -2999,11 +2951,10 @@ js::array_slice(JSContext* cx, unsigned argc, Value* vp)
return true;
}
-template <JSValueType Type>
-DenseElementResult
-ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t endArg, JSObject* result)
+static bool
+ArraySliceDenseKernel(JSContext* cx, ArrayObject* arr, int32_t beginArg, int32_t endArg, ArrayObject* result)
{
- int32_t length = obj->as<ArrayObject>().length();
+ int32_t length = arr->length();
uint32_t begin = NormalizeSliceTerm(beginArg, length);
uint32_t end = NormalizeSliceTerm(endArg, length);
@@ -3011,34 +2962,33 @@ ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t en
if (begin > end)
begin = end;
- size_t initlen = obj->as<NativeObject>().getDenseInitializedLength();
+ size_t initlen = arr->getDenseInitializedLength();
size_t count = Min<size_t>(initlen - begin, end - begin);
if (initlen > begin) {
if (count) {
- if (!result->as<ArrayObject>().ensureElements(cx, count))
- return DenseElementResult::Failure;
- CopyBoxedOrUnboxedDenseElements(cx, result, obj, 0, begin, count);
+ if (!result->ensureElements(cx, count))
+ return false;
+ CopyBoxedOrUnboxedDenseElements(cx, result, arr, 0, begin, count);
}
}
- MOZ_ASSERT(count >= result->as<ArrayObject>().length());
- result->as<ArrayObject>().setLength(cx, count);
+ MOZ_ASSERT(count >= result->length());
+ result->setLength(cx, count);
- return DenseElementResult::Success;
+ return true;
}
-DefineBoxedOrUnboxedFunctor5(ArraySliceDenseKernel,
- JSContext*, JSObject*, int32_t, int32_t, JSObject*);
-
JSObject*
js::array_slice_dense(JSContext* cx, HandleObject obj, int32_t begin, int32_t end,
HandleObject result)
{
if (result && IsArraySpecies(cx, obj)) {
- ArraySliceDenseKernelFunctor functor(cx, obj, begin, end, result);
- DenseElementResult rv = CallBoxedOrUnboxedSpecialization(functor, result);
- MOZ_ASSERT(rv != DenseElementResult::Incomplete);
- return rv == DenseElementResult::Success ? result : nullptr;
+ if (!ArraySliceDenseKernel(cx, &obj->as<ArrayObject>(), begin, end,
+ &result->as<ArrayObject>()))
+ {
+ return nullptr;
+ }
+ return result;
}
// Slower path if the JIT wasn't able to allocate an object inline.