⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsarray.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org) *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved. *  Copyright (C) 2003 Peter Kelly (pmk@post.com) *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * *  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 * */#include "config.h"#include "JSArray.h"#include "ArrayPrototype.h"#include "PropertyNameArray.h"#include <wtf/AVLTree.h>#include <wtf/Assertions.h>#include <Operations.h>#define CHECK_ARRAY_CONSISTENCY 0using namespace std;using namespace WTF;namespace JSC {ASSERT_CLASS_FITS_IN_CELL(JSArray);// 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 identifer, 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.//   * 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.// The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize// function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage// size calculation cannot overflow.  (sizeof(ArrayStorage) - sizeof(JSValuePtr)) +// (vectorLength * sizeof(JSValuePtr)) must be <= 0xFFFFFFFFU (which is maximum value of size_t).#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(JSValuePtr))) / sizeof(JSValuePtr))// 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>.#define MIN_SPARSE_ARRAY_INDEX 10000U#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// 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 const unsigned minDensityMultiplier = 8;const ClassInfo JSArray::info = {"Array", 0, 0, 0};static inline size_t storageSize(unsigned vectorLength){    ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH);    // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH)    // - as asserted above - the following calculation cannot overflow.    size_t size = (sizeof(ArrayStorage) - sizeof(JSValuePtr)) + (vectorLength * sizeof(JSValuePtr));    // Assertion to detect integer overflow in previous calculation (should not be possible, provided that    // MAX_STORAGE_VECTOR_LENGTH is correctly defined).    ASSERT(((size - (sizeof(ArrayStorage) - sizeof(JSValuePtr))) / sizeof(JSValuePtr) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(JSValuePtr))));    return size;}static inline unsigned increasedVectorLength(unsigned newLength){    ASSERT(newLength <= MAX_STORAGE_VECTOR_LENGTH);    // Mathematically equivalent to:    //   increasedLength = (newLength * 3 + 1) / 2;    // or:    //   increasedLength = (unsigned)ceil(newLength * 1.5));    // This form is not prone to internal overflow.    unsigned increasedLength = newLength + (newLength >> 1) + (newLength & 1);    ASSERT(increasedLength >= newLength);    return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH);}static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues){    return length / minDensityMultiplier <= numValues;}#if !CHECK_ARRAY_CONSISTENCYinline void JSArray::checkConsistency(ConsistencyCheckType){}#endifJSArray::JSArray(PassRefPtr<Structure> structure)    : JSObject(structure){    unsigned initialCapacity = 0;    m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));    m_fastAccessCutoff = 0;    m_storage->m_vectorLength = initialCapacity;    m_storage->m_length = 0;    checkConsistency();}JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength)    : JSObject(structure){    unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX);    m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));    m_fastAccessCutoff = 0;    m_storage->m_vectorLength = initialCapacity;    m_storage->m_length = initialLength;    Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValuePtr));    checkConsistency();}JSArray::JSArray(ExecState* exec, PassRefPtr<Structure> structure, const ArgList& list)    : JSObject(structure){    unsigned length = list.size();    m_fastAccessCutoff = length;    ArrayStorage* storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(length)));    storage->m_vectorLength = length;    storage->m_numValuesInVector = length;    storage->m_sparseValueMap = 0;    storage->m_length = length;    size_t i = 0;    ArgList::const_iterator end = list.end();    for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i)        storage->m_vector[i] = (*it).jsValue(exec);    m_storage = storage;    Heap::heap(this)->reportExtraMemoryCost(storageSize(length));    checkConsistency();}JSArray::~JSArray(){    checkConsistency(DestructorConsistencyCheck);    delete m_storage->m_sparseValueMap;    fastFree(m_storage);}bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot){    ArrayStorage* storage = m_storage;    if (i >= storage->m_length) {        if (i > MAX_ARRAY_INDEX)            return getOwnPropertySlot(exec, Identifier::from(exec, i), slot);        return false;    }    if (i < storage->m_vectorLength) {        JSValuePtr& valueSlot = storage->m_vector[i];        if (valueSlot) {            slot.setValueSlot(&valueSlot);            return true;        }    } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {        if (i >= MIN_SPARSE_ARRAY_INDEX) {            SparseArrayValueMap::iterator it = map->find(i);            if (it != map->end()) {                slot.setValueSlot(&it->second);                return true;            }        }    }    return false;}bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot){    if (propertyName == exec->propertyNames().length) {        slot.setValue(jsNumber(exec, length()));        return true;    }    bool isArrayIndex;    unsigned i = propertyName.toArrayIndex(&isArrayIndex);    if (isArrayIndex)        return JSArray::getOwnPropertySlot(exec, i, slot);    return JSObject::getOwnPropertySlot(exec, propertyName, slot);}// ECMA 15.4.5.1void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot){    bool isArrayIndex;    unsigned i = propertyName.toArrayIndex(&isArrayIndex);    if (isArrayIndex) {        put(exec, i, value);        return;    }    if (propertyName == exec->propertyNames().length) {        unsigned newLength = value.toUInt32(exec);        if (value.toNumber(exec) != static_cast<double>(newLength)) {            throwError(exec, RangeError, "Invalid array length.");            return;        }        setLength(newLength);        return;    }    JSObject::put(exec, propertyName, value, slot);}void JSArray::put(ExecState* exec, unsigned i, JSValuePtr value){    checkConsistency();    unsigned length = m_storage->m_length;    if (i >= length && i <= MAX_ARRAY_INDEX) {        length = i + 1;        m_storage->m_length = length;    }    if (i < m_storage->m_vectorLength) {        JSValuePtr& valueSlot = m_storage->m_vector[i];        if (valueSlot) {            valueSlot = value;            checkConsistency();            return;        }        valueSlot = value;        if (++m_storage->m_numValuesInVector == m_storage->m_length)            m_fastAccessCutoff = m_storage->m_length;        checkConsistency();        return;    }    putSlowCase(exec, i, value);}NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValuePtr value){    ArrayStorage* storage = m_storage;    SparseArrayValueMap* map = storage->m_sparseValueMap;    if (i >= MIN_SPARSE_ARRAY_INDEX) {        if (i > MAX_ARRAY_INDEX) {            PutPropertySlot slot;            put(exec, Identifier::from(exec, i), value, slot);            return;        }        // We miss some cases where we could compact the storage, such as a large array that is being filled from the end        // (which will only be compacted as we reach indices that are less than cutoff) - but this makes the check much faster.        if ((i > MAX_STORAGE_VECTOR_INDEX) || !isDenseEnoughForVector(i + 1, storage->m_numValuesInVector + 1)) {            if (!map) {                map = new SparseArrayValueMap;                storage->m_sparseValueMap = map;            }            map->set(i, value);            return;        }    }    // We have decided that we'll put the new item into the vector.    // Fast case is when there is no sparse map, so we can increase the vector size without moving values from it.    if (!map || map->isEmpty()) {        if (increaseVectorLength(i + 1)) {            storage = m_storage;            storage->m_vector[i] = value;            if (++storage->m_numValuesInVector == storage->m_length)                m_fastAccessCutoff = storage->m_length;            checkConsistency();        } else            throwOutOfMemoryError(exec);        return;    }    // Decide how many values it would be best to move from the map.    unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;    unsigned newVectorLength = increasedVectorLength(i + 1);    for (unsigned j = max(storage->m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)        newNumValuesInVector += map->contains(j);    if (i >= MIN_SPARSE_ARRAY_INDEX)        newNumValuesInVector -= map->contains(i);    if (isDenseEnoughForVector(newVectorLength, newNumValuesInVector)) {        unsigned proposedNewNumValuesInVector = newNumValuesInVector;        // If newVectorLength is already the maximum - MAX_STORAGE_VECTOR_LENGTH - then do not attempt to grow any further.        while (newVectorLength < MAX_STORAGE_VECTOR_LENGTH) {            unsigned proposedNewVectorLength = increasedVectorLength(newVectorLength + 1);            for (unsigned j = max(newVectorLength, MIN_SPARSE_ARRAY_INDEX); j < proposedNewVectorLength; ++j)                proposedNewNumValuesInVector += map->contains(j);            if (!isDenseEnoughForVector(proposedNewVectorLength, proposedNewNumValuesInVector))                break;            newVectorLength = proposedNewVectorLength;            newNumValuesInVector = proposedNewNumValuesInVector;        }    }    storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength)));    if (!storage) {        throwOutOfMemoryError(exec);        return;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -