mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-18 10:23:08 +09:00
Remove functors for array natives.
This commit is contained in:
parent
ea2349157d
commit
18166cf949
3 changed files with 59 additions and 230 deletions
|
|
@ -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,32 +1096,12 @@ 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,
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue