diff options
Diffstat (limited to 'js/src/vm/UnboxedObject-inl.h')
-rw-r--r-- | js/src/vm/UnboxedObject-inl.h | 840 |
1 files changed, 0 insertions, 840 deletions
diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h deleted file mode 100644 index 93ad7bf28..000000000 --- a/js/src/vm/UnboxedObject-inl.h +++ /dev/null @@ -1,840 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef vm_UnboxedObject_inl_h -#define vm_UnboxedObject_inl_h - -#include "vm/UnboxedObject.h" - -#include "gc/StoreBuffer-inl.h" -#include "vm/ArrayObject-inl.h" -#include "vm/NativeObject-inl.h" - -namespace js { - -static inline Value -GetUnboxedValue(uint8_t* p, JSValueType type, bool maybeUninitialized) -{ - switch (type) { - case JSVAL_TYPE_BOOLEAN: - return BooleanValue(*p != 0); - - case JSVAL_TYPE_INT32: - return Int32Value(*reinterpret_cast<int32_t*>(p)); - - case JSVAL_TYPE_DOUBLE: { - // During unboxed plain object creation, non-GC thing properties are - // left uninitialized. This is normally fine, since the properties will - // be filled in shortly, but if they are read before that happens we - // need to make sure that doubles are canonical. - double d = *reinterpret_cast<double*>(p); - if (maybeUninitialized) - return DoubleValue(JS::CanonicalizeNaN(d)); - return DoubleValue(d); - } - - case JSVAL_TYPE_STRING: - return StringValue(*reinterpret_cast<JSString**>(p)); - - case JSVAL_TYPE_OBJECT: - return ObjectOrNullValue(*reinterpret_cast<JSObject**>(p)); - - default: - MOZ_CRASH("Invalid type for unboxed value"); - } -} - -static inline void -SetUnboxedValueNoTypeChange(JSObject* unboxedObject, - uint8_t* p, JSValueType type, const Value& v, - bool preBarrier) -{ - switch (type) { - case JSVAL_TYPE_BOOLEAN: - *p = v.toBoolean(); - return; - - case JSVAL_TYPE_INT32: - *reinterpret_cast<int32_t*>(p) = v.toInt32(); - return; - - case JSVAL_TYPE_DOUBLE: - *reinterpret_cast<double*>(p) = v.toNumber(); - return; - - case JSVAL_TYPE_STRING: { - MOZ_ASSERT(!IsInsideNursery(v.toString())); - JSString** np = reinterpret_cast<JSString**>(p); - if (preBarrier) - JSString::writeBarrierPre(*np); - *np = v.toString(); - return; - } - - case JSVAL_TYPE_OBJECT: { - JSObject** np = reinterpret_cast<JSObject**>(p); - - // Manually trigger post barriers on the whole object. If we treat - // the pointer as a HeapPtrObject we will get confused later if the - // object is converted to its native representation. - JSObject* obj = v.toObjectOrNull(); - if (IsInsideNursery(obj) && !IsInsideNursery(unboxedObject)) { - JSRuntime* rt = unboxedObject->runtimeFromMainThread(); - rt->gc.storeBuffer.putWholeCell(unboxedObject); - } - - if (preBarrier) - JSObject::writeBarrierPre(*np); - *np = obj; - return; - } - - default: - MOZ_CRASH("Invalid type for unboxed value"); - } -} - -static inline bool -SetUnboxedValue(ExclusiveContext* cx, JSObject* unboxedObject, jsid id, - uint8_t* p, JSValueType type, const Value& v, bool preBarrier) -{ - switch (type) { - case JSVAL_TYPE_BOOLEAN: - if (v.isBoolean()) { - *p = v.toBoolean(); - return true; - } - return false; - - case JSVAL_TYPE_INT32: - if (v.isInt32()) { - *reinterpret_cast<int32_t*>(p) = v.toInt32(); - return true; - } - return false; - - case JSVAL_TYPE_DOUBLE: - if (v.isNumber()) { - *reinterpret_cast<double*>(p) = v.toNumber(); - return true; - } - return false; - - case JSVAL_TYPE_STRING: - if (v.isString()) { - MOZ_ASSERT(!IsInsideNursery(v.toString())); - JSString** np = reinterpret_cast<JSString**>(p); - if (preBarrier) - JSString::writeBarrierPre(*np); - *np = v.toString(); - return true; - } - return false; - - case JSVAL_TYPE_OBJECT: - if (v.isObjectOrNull()) { - JSObject** np = reinterpret_cast<JSObject**>(p); - - // Update property types when writing object properties. Types for - // other properties were captured when the unboxed layout was - // created. - AddTypePropertyId(cx, unboxedObject, id, v); - - // As above, trigger post barriers on the whole object. - JSObject* obj = v.toObjectOrNull(); - if (IsInsideNursery(v.toObjectOrNull()) && !IsInsideNursery(unboxedObject)) { - JSRuntime* rt = unboxedObject->runtimeFromMainThread(); - rt->gc.storeBuffer.putWholeCell(unboxedObject); - } - - if (preBarrier) - JSObject::writeBarrierPre(*np); - *np = obj; - return true; - } - return false; - - default: - MOZ_CRASH("Invalid type for unboxed value"); - } -} - -///////////////////////////////////////////////////////////////////// -// UnboxedPlainObject -///////////////////////////////////////////////////////////////////// - -inline const UnboxedLayout& -UnboxedPlainObject::layout() const -{ - return group()->unboxedLayout(); -} - -///////////////////////////////////////////////////////////////////// -// UnboxedArrayObject -///////////////////////////////////////////////////////////////////// - -inline const UnboxedLayout& -UnboxedArrayObject::layout() const -{ - return group()->unboxedLayout(); -} - -inline void -UnboxedArrayObject::setLength(ExclusiveContext* cx, uint32_t length) -{ - if (length > INT32_MAX) { - // Track objects with overflowing lengths in type information. - MarkObjectGroupFlags(cx, this, OBJECT_FLAG_LENGTH_OVERFLOW); - } - - length_ = length; -} - -inline void -UnboxedArrayObject::setInitializedLength(uint32_t initlen) -{ - if (initlen < initializedLength()) { - switch (elementType()) { - case JSVAL_TYPE_STRING: - for (size_t i = initlen; i < initializedLength(); i++) - triggerPreBarrier<JSVAL_TYPE_STRING>(i); - break; - case JSVAL_TYPE_OBJECT: - for (size_t i = initlen; i < initializedLength(); i++) - triggerPreBarrier<JSVAL_TYPE_OBJECT>(i); - break; - default: - MOZ_ASSERT(!UnboxedTypeNeedsPreBarrier(elementType())); - } - } - setInitializedLengthNoBarrier(initlen); -} - -template <JSValueType Type> -inline bool -UnboxedArrayObject::setElementSpecific(ExclusiveContext* cx, size_t index, const Value& v) -{ - MOZ_ASSERT(index < initializedLength()); - MOZ_ASSERT(Type == elementType()); - uint8_t* p = elements() + index * UnboxedTypeSize(Type); - return SetUnboxedValue(cx, this, JSID_VOID, p, elementType(), v, /* preBarrier = */ true); -} - -template <JSValueType Type> -inline void -UnboxedArrayObject::setElementNoTypeChangeSpecific(size_t index, const Value& v) -{ - MOZ_ASSERT(index < initializedLength()); - MOZ_ASSERT(Type == elementType()); - uint8_t* p = elements() + index * UnboxedTypeSize(Type); - return SetUnboxedValueNoTypeChange(this, p, elementType(), v, /* preBarrier = */ true); -} - -template <JSValueType Type> -inline bool -UnboxedArrayObject::initElementSpecific(ExclusiveContext* cx, size_t index, const Value& v) -{ - MOZ_ASSERT(index < initializedLength()); - MOZ_ASSERT(Type == elementType()); - uint8_t* p = elements() + index * UnboxedTypeSize(Type); - return SetUnboxedValue(cx, this, JSID_VOID, p, elementType(), v, /* preBarrier = */ false); -} - -template <JSValueType Type> -inline void -UnboxedArrayObject::initElementNoTypeChangeSpecific(size_t index, const Value& v) -{ - MOZ_ASSERT(index < initializedLength()); - MOZ_ASSERT(Type == elementType()); - uint8_t* p = elements() + index * UnboxedTypeSize(Type); - return SetUnboxedValueNoTypeChange(this, p, elementType(), v, /* preBarrier = */ false); -} - -template <JSValueType Type> -inline Value -UnboxedArrayObject::getElementSpecific(size_t index) -{ - MOZ_ASSERT(index < initializedLength()); - MOZ_ASSERT(Type == elementType()); - uint8_t* p = elements() + index * UnboxedTypeSize(Type); - return GetUnboxedValue(p, Type, /* maybeUninitialized = */ false); -} - -template <JSValueType Type> -inline void -UnboxedArrayObject::triggerPreBarrier(size_t index) -{ - MOZ_ASSERT(UnboxedTypeNeedsPreBarrier(Type)); - - uint8_t* p = elements() + index * UnboxedTypeSize(Type); - - switch (Type) { - case JSVAL_TYPE_STRING: { - JSString** np = reinterpret_cast<JSString**>(p); - JSString::writeBarrierPre(*np); - break; - } - - case JSVAL_TYPE_OBJECT: { - JSObject** np = reinterpret_cast<JSObject**>(p); - JSObject::writeBarrierPre(*np); - break; - } - - default: - MOZ_CRASH("Bad type"); - } -} - -///////////////////////////////////////////////////////////////////// -// 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) -{ - if (obj->isNative()) - return obj->as<NativeObject>().getDenseInitializedLength(); - if (obj->is<UnboxedArrayObject>()) - return obj->as<UnboxedArrayObject>().initializedLength(); - return 0; -} - -static inline size_t -GetAnyBoxedOrUnboxedCapacity(JSObject* obj) -{ - if (obj->isNative()) - return obj->as<NativeObject>().getDenseCapacity(); - if (obj->is<UnboxedArrayObject>()) - return obj->as<UnboxedArrayObject>().capacity(); - return 0; -} - -static inline Value -GetAnyBoxedOrUnboxedDenseElement(JSObject* obj, size_t index) -{ - if (obj->isNative()) - return obj->as<NativeObject>().getDenseElement(index); - return obj->as<UnboxedArrayObject>().getElement(index); -} - -static inline size_t -GetAnyBoxedOrUnboxedArrayLength(JSObject* obj) -{ - if (obj->is<ArrayObject>()) - return obj->as<ArrayObject>().length(); - return obj->as<UnboxedArrayObject>().length(); -} - -static inline void -SetAnyBoxedOrUnboxedArrayLength(JSContext* cx, JSObject* obj, size_t length) -{ - if (obj->is<ArrayObject>()) { - MOZ_ASSERT(length >= obj->as<ArrayObject>().length()); - obj->as<ArrayObject>().setLength(cx, length); - } else { - MOZ_ASSERT(length >= obj->as<UnboxedArrayObject>().length()); - obj->as<UnboxedArrayObject>().setLength(cx, length); - } -} - -static inline bool -SetAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value) -{ - if (obj->isNative()) { - obj->as<NativeObject>().setDenseElementWithType(cx, index, value); - return true; - } - 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. -///////////////////////////////////////////////////////////////////// - -static inline JSValueType -GetBoxedOrUnboxedType(JSObject* obj) -{ - if (obj->isNative()) - return JSVAL_TYPE_MAGIC; - return obj->as<UnboxedArrayObject>().elementType(); -} - -template <JSValueType Type> -static inline bool -HasBoxedOrUnboxedDenseElements(JSObject* obj) -{ - if (Type == JSVAL_TYPE_MAGIC) - return obj->isNative(); - return obj->is<UnboxedArrayObject>() && obj->as<UnboxedArrayObject>().elementType() == Type; -} - -template <JSValueType Type> -static inline size_t -GetBoxedOrUnboxedInitializedLength(JSObject* obj) -{ - if (Type == JSVAL_TYPE_MAGIC) - return obj->as<NativeObject>().getDenseInitializedLength(); - return obj->as<UnboxedArrayObject>().initializedLength(); -} - -template <JSValueType Type> -static inline DenseElementResult -SetBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen) -{ - size_t oldInitlen = GetBoxedOrUnboxedInitializedLength<Type>(obj); - if (Type == JSVAL_TYPE_MAGIC) { - obj->as<NativeObject>().setDenseInitializedLength(initlen); - if (initlen < oldInitlen) - obj->as<NativeObject>().shrinkElements(cx, initlen); - } else { - obj->as<UnboxedArrayObject>().setInitializedLength(initlen); - if (initlen < oldInitlen) - obj->as<UnboxedArrayObject>().shrinkElements(cx, initlen); - } - return DenseElementResult::Success; -} - -template <JSValueType Type> -static inline size_t -GetBoxedOrUnboxedCapacity(JSObject* obj) -{ - if (Type == JSVAL_TYPE_MAGIC) - return obj->as<NativeObject>().getDenseCapacity(); - return obj->as<UnboxedArrayObject>().capacity(); -} - -template <JSValueType Type> -static inline Value -GetBoxedOrUnboxedDenseElement(JSObject* obj, size_t index) -{ - if (Type == JSVAL_TYPE_MAGIC) - return obj->as<NativeObject>().getDenseElement(index); - return obj->as<UnboxedArrayObject>().getElementSpecific<Type>(index); -} - -template <JSValueType Type> -static inline void -SetBoxedOrUnboxedDenseElementNoTypeChange(JSObject* obj, size_t index, const Value& value) -{ - if (Type == JSVAL_TYPE_MAGIC) - obj->as<NativeObject>().setDenseElement(index, value); - else - obj->as<UnboxedArrayObject>().setElementNoTypeChangeSpecific<Type>(index, value); -} - -template <JSValueType Type> -static inline bool -SetBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value) -{ - if (Type == JSVAL_TYPE_MAGIC) { - obj->as<NativeObject>().setDenseElementWithType(cx, index, value); - return true; - } - return obj->as<UnboxedArrayObject>().setElementSpecific<Type>(cx, index, value); -} - -template <JSValueType Type> -static inline DenseElementResult -EnsureBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count) -{ - if (Type == JSVAL_TYPE_MAGIC) { - if (!obj->as<ArrayObject>().ensureElements(cx, count)) - return DenseElementResult::Failure; - } else { - if (obj->as<UnboxedArrayObject>().capacity() < count) { - if (!obj->as<UnboxedArrayObject>().growElements(cx, count)) - return DenseElementResult::Failure; - } - } - return DenseElementResult::Success; -} - -template <JSValueType Type> -static inline DenseElementResult -SetOrExtendBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj, - uint32_t start, const Value* vp, uint32_t count, - ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update) -{ - if (Type == JSVAL_TYPE_MAGIC) { - NativeObject* nobj = &obj->as<NativeObject>(); - - if (nobj->denseElementsAreFrozen()) - return DenseElementResult::Incomplete; - - if (obj->is<ArrayObject>() && - !obj->as<ArrayObject>().lengthIsWritable() && - start + count >= obj->as<ArrayObject>().length()) - { - return DenseElementResult::Incomplete; - } - - DenseElementResult result = nobj->ensureDenseElements(cx, start, count); - if (result != DenseElementResult::Success) - return result; - - if (obj->is<ArrayObject>() && start + count >= obj->as<ArrayObject>().length()) - obj->as<ArrayObject>().setLengthInt32(start + count); - - if (updateTypes == ShouldUpdateTypes::DontUpdate && !nobj->shouldConvertDoubleElements()) { - nobj->copyDenseElements(start, vp, count); - } else { - for (size_t i = 0; i < count; i++) - nobj->setDenseElementWithType(cx, start + i, vp[i]); - } - - return DenseElementResult::Success; - } - - UnboxedArrayObject* nobj = &obj->as<UnboxedArrayObject>(); - - if (start > nobj->initializedLength()) - return DenseElementResult::Incomplete; - - if (start + count >= UnboxedArrayObject::MaximumCapacity) - return DenseElementResult::Incomplete; - - if (start + count > nobj->capacity() && !nobj->growElements(cx, start + count)) - return DenseElementResult::Failure; - - size_t oldInitlen = nobj->initializedLength(); - - // Overwrite any existing elements covered by the new range. If we fail - // after this point due to some incompatible type being written to the - // object's elements, afterwards the contents will be different from when - // we started. The caller must retry the operation using a generic path, - // which will overwrite the already-modified elements as well as the ones - // that were left alone. - size_t i = 0; - if (updateTypes == ShouldUpdateTypes::DontUpdate) { - for (size_t j = start; i < count && j < oldInitlen; i++, j++) - nobj->setElementNoTypeChangeSpecific<Type>(j, vp[i]); - } else { - for (size_t j = start; i < count && j < oldInitlen; i++, j++) { - if (!nobj->setElementSpecific<Type>(cx, j, vp[i])) - return DenseElementResult::Incomplete; - } - } - - if (i != count) { - obj->as<UnboxedArrayObject>().setInitializedLength(start + count); - if (updateTypes == ShouldUpdateTypes::DontUpdate) { - for (; i < count; i++) - nobj->initElementNoTypeChangeSpecific<Type>(start + i, vp[i]); - } else { - for (; i < count; i++) { - if (!nobj->initElementSpecific<Type>(cx, start + i, vp[i])) { - nobj->setInitializedLengthNoBarrier(oldInitlen); - return DenseElementResult::Incomplete; - } - } - } - } - - if (start + count >= nobj->length()) - nobj->setLength(cx, start + count); - - return DenseElementResult::Success; -} - -template <JSValueType Type> -static inline DenseElementResult -MoveBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, uint32_t dstStart, uint32_t srcStart, - uint32_t length) -{ - MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<Type>(obj)); - - if (Type == JSVAL_TYPE_MAGIC) { - if (obj->as<NativeObject>().denseElementsAreFrozen()) - return DenseElementResult::Incomplete; - - if (!obj->as<NativeObject>().maybeCopyElementsForWrite(cx)) - return DenseElementResult::Failure; - obj->as<NativeObject>().moveDenseElements(dstStart, srcStart, length); - } else { - uint8_t* data = obj->as<UnboxedArrayObject>().elements(); - size_t elementSize = UnboxedTypeSize(Type); - - if (UnboxedTypeNeedsPreBarrier(Type) && - JS::shadow::Zone::asShadowZone(obj->zone())->needsIncrementalBarrier()) - { - // Trigger pre barriers on any elements we are overwriting. See - // NativeObject::moveDenseElements. No post barrier is needed as - // only whole cell post barriers are used with unboxed objects. - for (size_t i = 0; i < length; i++) - obj->as<UnboxedArrayObject>().triggerPreBarrier<Type>(dstStart + i); - } - - memmove(data + dstStart * elementSize, - data + srcStart * elementSize, - length * elementSize); - } - - return DenseElementResult::Success; -} - -template <JSValueType DstType, JSValueType SrcType> -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<SrcType>(src) >= srcStart + length); - MOZ_ASSERT(GetBoxedOrUnboxedCapacity<DstType>(dst) >= dstStart + length); - - SetBoxedOrUnboxedInitializedLength<DstType>(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) { - uint8_t* dstData = dst->as<UnboxedArrayObject>().elements(); - uint8_t* srcData = src->as<UnboxedArrayObject>().elements(); - size_t elementSize = UnboxedTypeSize(DstType); - - 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)) - dst->runtimeFromMainThread()->gc.storeBuffer.putWholeCell(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; -} - -///////////////////////////////////////////////////////////////////// -// 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 (!HasAnyBoxedOrUnboxedDenseElements(obj)) - return DenseElementResult::Incomplete; - switch (GetBoxedOrUnboxedType(obj)) { - case JSVAL_TYPE_MAGIC: - return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC>(); - case JSVAL_TYPE_BOOLEAN: - return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_BOOLEAN>(); - case JSVAL_TYPE_INT32: - return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_INT32>(); - case JSVAL_TYPE_DOUBLE: - return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_DOUBLE>(); - case JSVAL_TYPE_STRING: - return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_STRING>(); - case JSVAL_TYPE_OBJECT: - 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 -} - -#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); \ - } \ -} - -DenseElementResult -SetOrExtendAnyBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj, - uint32_t start, const Value* vp, uint32_t count, - ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update); - -DenseElementResult -MoveAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, - uint32_t dstStart, uint32_t srcStart, uint32_t length); - -DenseElementResult -CopyAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src, - uint32_t dstStart, uint32_t srcStart, uint32_t length); - -void -SetAnyBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen); - -DenseElementResult -EnsureAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count); - -} // namespace js - -#endif // vm_UnboxedObject_inl_h |