summaryrefslogtreecommitdiffstats
path: root/js/src/vm/UnboxedObject-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm/UnboxedObject-inl.h')
-rw-r--r--js/src/vm/UnboxedObject-inl.h840
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