mirror of
https://github.com/darlinghq/darling-JavaScriptCore.git
synced 2024-11-23 04:09:40 +00:00
153 lines
6.0 KiB
C++
153 lines
6.0 KiB
C++
/*
|
|
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
|
|
* Copyright (C) 2003-2019 Apple Inc. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "IndexingHeader.h"
|
|
#include "PureNaN.h"
|
|
#include "WriteBarrier.h"
|
|
|
|
namespace JSC {
|
|
|
|
// Overview of JSArray
|
|
//
|
|
// Properties of JSArray objects may be stored in one of three locations:
|
|
// * The regular JSObject property map.
|
|
// * A storage vector.
|
|
// * A sparse map of array entries.
|
|
//
|
|
// Properties with non-numeric identifiers, with identifiers that are not representable
|
|
// as an unsigned integer, or where the value is greater than MAX_ARRAY_INDEX
|
|
// (specifically, this is only one property - the value 0xFFFFFFFFU as an unsigned 32-bit
|
|
// integer) are not considered array indices and will be stored in the JSObject property map.
|
|
//
|
|
// All properties with a numeric identifier, representable as an unsigned integer i,
|
|
// where (i <= MAX_ARRAY_INDEX), are an array index and will be stored in either the
|
|
// storage vector or the sparse map. An array index i will be handled in the following
|
|
// fashion:
|
|
//
|
|
// * Where (i < MIN_SPARSE_ARRAY_INDEX) the value will be stored in the storage vector,
|
|
// unless the array is in SparseMode in which case all properties go into the map.
|
|
// * Where (MIN_SPARSE_ARRAY_INDEX <= i <= MAX_STORAGE_VECTOR_INDEX) the value will either
|
|
// be stored in the storage vector or in the sparse array, depending on the density of
|
|
// data that would be stored in the vector (a vector being used where at least
|
|
// (1 / minDensityMultiplier) of the entries would be populated).
|
|
// * Where (MAX_STORAGE_VECTOR_INDEX < i <= MAX_ARRAY_INDEX) the value will always be stored
|
|
// in the sparse array.
|
|
|
|
// Define the maximum storage vector length to be 2^32 / sizeof(JSValue) / 2 to ensure that
|
|
// there is no risk of overflow.
|
|
#define MAX_STORAGE_VECTOR_LENGTH IndexingHeader::maximumLength
|
|
|
|
// These values have to be macros to be used in max() and min() without introducing
|
|
// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
|
|
|
|
// If you grow an ArrayStorage array by more than this, then the array will go sparse. Note that we
|
|
// could probably make this smaller (it's large because it used to be conflated with
|
|
// MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH).
|
|
#define MIN_SPARSE_ARRAY_INDEX 100000U
|
|
// If you try to allocate a contiguous array larger than this, then we will allocate an ArrayStorage
|
|
// array instead. We allow for an array that occupies 1GB of VM.
|
|
#define MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH (1024 * 1024 * 1024 / 8)
|
|
#define MAX_STORAGE_VECTOR_INDEX (MAX_STORAGE_VECTOR_LENGTH - 1)
|
|
// 0xFFFFFFFF is a bit weird -- is not an array index even though it's an integer.
|
|
#define MAX_ARRAY_INDEX 0xFFFFFFFEU
|
|
|
|
static_assert(MIN_SPARSE_ARRAY_INDEX <= MAX_STORAGE_VECTOR_INDEX, "MIN_SPARSE_ARRAY_INDEX must be less than or equal to MAX_STORAGE_VECTOR_INDEX");
|
|
static_assert(MAX_STORAGE_VECTOR_INDEX <= MAX_ARRAY_INDEX, "MAX_STORAGE_VECTOR_INDEX must be less than or equal to MAX_ARRAY_INDEX");
|
|
|
|
// The value BASE_XXX_VECTOR_LEN is the maximum number of vector elements we'll allocate
|
|
// for an array that was created with a sepcified length (e.g. a = new Array(123))
|
|
#define BASE_CONTIGUOUS_VECTOR_LEN 3U
|
|
#define BASE_CONTIGUOUS_VECTOR_LEN_EMPTY 5U
|
|
#define BASE_CONTIGUOUS_VECTOR_LEN_MIN 3U
|
|
#define BASE_CONTIGUOUS_VECTOR_LEN_MAX 25U
|
|
#define BASE_ARRAY_STORAGE_VECTOR_LEN 4U
|
|
|
|
// The upper bound to the size we'll grow a zero length array when the first element
|
|
// is added.
|
|
#define FIRST_ARRAY_STORAGE_VECTOR_GROW 4U
|
|
|
|
#define MIN_BEYOND_LENGTH_SPARSE_INDEX 1000
|
|
|
|
// Our policy for when to use a vector and when to use a sparse map.
|
|
// For all array indices under MIN_SPARSE_ARRAY_INDEX, we always use a vector.
|
|
// When indices greater than MIN_SPARSE_ARRAY_INDEX are involved, we use a vector
|
|
// as long as it is 1/8 full. If more sparse than that, we use a map.
|
|
static constexpr unsigned minDensityMultiplier = 8;
|
|
|
|
inline bool isDenseEnoughForVector(unsigned length, unsigned numValues)
|
|
{
|
|
return length / minDensityMultiplier <= numValues;
|
|
}
|
|
|
|
inline bool indexIsSufficientlyBeyondLengthForSparseMap(unsigned i, unsigned length)
|
|
{
|
|
return i >= MIN_BEYOND_LENGTH_SPARSE_INDEX && i > length;
|
|
}
|
|
|
|
inline IndexingHeader indexingHeaderForArrayStorage(unsigned length, unsigned vectorLength)
|
|
{
|
|
IndexingHeader result;
|
|
result.setPublicLength(length);
|
|
result.setVectorLength(vectorLength);
|
|
return result;
|
|
}
|
|
|
|
inline IndexingHeader baseIndexingHeaderForArrayStorage(unsigned length)
|
|
{
|
|
return indexingHeaderForArrayStorage(length, BASE_ARRAY_STORAGE_VECTOR_LEN);
|
|
}
|
|
|
|
#if USE(JSVALUE64)
|
|
JS_EXPORT_PRIVATE void clearArrayMemset(WriteBarrier<Unknown>* base, unsigned count);
|
|
JS_EXPORT_PRIVATE void clearArrayMemset(double* base, unsigned count);
|
|
#endif // USE(JSVALUE64)
|
|
|
|
ALWAYS_INLINE void clearArray(WriteBarrier<Unknown>* base, unsigned count)
|
|
{
|
|
#if USE(JSVALUE64)
|
|
const unsigned minCountForMemset = 100;
|
|
if (count >= minCountForMemset) {
|
|
clearArrayMemset(base, count);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
for (unsigned i = count; i--;)
|
|
base[i].clear();
|
|
}
|
|
|
|
ALWAYS_INLINE void clearArray(double* base, unsigned count)
|
|
{
|
|
#if USE(JSVALUE64)
|
|
const unsigned minCountForMemset = 100;
|
|
if (count >= minCountForMemset) {
|
|
clearArrayMemset(base, count);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
for (unsigned i = count; i--;)
|
|
base[i] = PNaN;
|
|
}
|
|
|
|
} // namespace JSC
|