diff options
-rw-r--r-- | js/src/jsarray.cpp | 166 | ||||
-rw-r--r-- | js/src/jsarray.h | 2 | ||||
-rw-r--r-- | js/src/vm/UnboxedObject-inl.h | 121 |
3 files changed, 59 insertions, 230 deletions
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 0d6f78fcfe..9abc99e347 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. diff --git a/js/src/jsarray.h b/js/src/jsarray.h index ecde87c3bc..1bee742ced 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -168,7 +168,7 @@ extern bool array_join(JSContext* cx, unsigned argc, js::Value* vp); extern void -ArrayShiftMoveElements(JSObject* obj); +ArrayShiftMoveElements(NativeObject* obj); extern bool array_shift(JSContext* cx, unsigned argc, js::Value* vp); diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h index b308464fed..711a064f27 100644 --- a/js/src/vm/UnboxedObject-inl.h +++ b/js/src/vm/UnboxedObject-inl.h @@ -244,127 +244,6 @@ CopyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src, return DenseElementResult::Success; } -///////////////////////////////////////////////////////////////////// -// Dispatch to specialized methods based on the type of an object. -///////////////////////////////////////////////////////////////////// - -// Goop to fix MSVC. See DispatchTraceKindTyped in TraceKind.h. -// The clang-cl front end defines _MSC_VER, but still requires the explicit -// template declaration, so we must test for __clang__ here as well. -#if defined(_MSC_VER) && !defined(__clang__) -# define DEPENDENT_TEMPLATE_HINT -#else -# define DEPENDENT_TEMPLATE_HINT template -#endif - -// Function to dispatch a method specialized to whatever boxed or unboxed dense -// elements which an input object has. -template <typename F> -DenseElementResult -CallBoxedOrUnboxedSpecialization(F f, JSObject* obj) -{ - if (!obj->isNative()) - return DenseElementResult::Incomplete; - return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC>(); -} - -// 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 (!obj1->isNative() || !obj2->isNative()) - return DenseElementResult::Incomplete; - - return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC, JSVAL_TYPE_MAGIC>(); -} - -#undef DEPENDENT_TEMPLATE_HINT - -#define DefineBoxedOrUnboxedFunctor1(Signature, A) \ -struct Signature ## Functor { \ - A a; \ - explicit Signature ## Functor(A a) \ - : a(a) \ - {} \ - template <JSValueType Type> \ - DenseElementResult operator()() { \ - return Signature<Type>(a); \ - } \ -} - -#define DefineBoxedOrUnboxedFunctor3(Signature, A, B, C) \ -struct Signature ## Functor { \ - A a; B b; C c; \ - Signature ## Functor(A a, B b, C c) \ - : a(a), b(b), c(c) \ - {} \ - template <JSValueType Type> \ - DenseElementResult operator()() { \ - return Signature<Type>(a, b, c); \ - } \ -} - -#define DefineBoxedOrUnboxedFunctor4(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 Type> \ - DenseElementResult operator()() { \ - return Signature<Type>(a, b, c, d); \ - } \ -} - -#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; \ - Signature ## Functor(A a, B b, C c, D d, E e) \ - : a(a), b(b), c(c), d(d), e(e) \ - {} \ - template <JSValueType Type> \ - DenseElementResult operator()() { \ - return Signature<Type>(a, b, c, d, e); \ - } \ -} - -#define DefineBoxedOrUnboxedFunctor6(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 Type> \ - DenseElementResult operator()() { \ - return Signature<Type>(a, b, c, d, e, f); \ - } \ -} - -#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); \ - } \ -} - } // namespace js #endif // vm_UnboxedObject_inl_h |