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

📄 jsarray.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    // a toString call raises an exception.    for (size_t i = 0; i < lengthNotIncludingUndefined; i++)        values[i].second = values[i].first.toString(exec);    if (exec->hadException())        return;    // FIXME: Since we sort by string value, a fast algorithm might be to use a radix sort. That would be O(N) rather    // than O(N log N).#if HAVE(MERGESORT)    mergesort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort);#else    // FIXME: The qsort library function is likely to not be a stable sort.    // ECMAScript-262 does not specify a stable sort, but in practice, browsers perform a stable sort.    qsort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort);#endif    // FIXME: If the toString function changed the length of the array, this might be    // modifying the vector incorrectly.    for (size_t i = 0; i < lengthNotIncludingUndefined; i++)        m_storage->m_vector[i] = values[i].first;    checkConsistency(SortConsistencyCheck);}struct AVLTreeNodeForArrayCompare {    JSValuePtr value;    // Child pointers.  The high bit of gt is robbed and used as the    // balance factor sign.  The high bit of lt is robbed and used as    // the magnitude of the balance factor.    int32_t gt;    int32_t lt;};struct AVLTreeAbstractorForArrayCompare {    typedef int32_t handle; // Handle is an index into m_nodes vector.    typedef JSValuePtr key;    typedef int32_t size;    Vector<AVLTreeNodeForArrayCompare> m_nodes;    ExecState* m_exec;    JSValuePtr m_compareFunction;    CallType m_compareCallType;    const CallData* m_compareCallData;    JSValuePtr m_globalThisValue;    handle get_less(handle h) { return m_nodes[h].lt & 0x7FFFFFFF; }    void set_less(handle h, handle lh) { m_nodes[h].lt &= 0x80000000; m_nodes[h].lt |= lh; }    handle get_greater(handle h) { return m_nodes[h].gt & 0x7FFFFFFF; }    void set_greater(handle h, handle gh) { m_nodes[h].gt &= 0x80000000; m_nodes[h].gt |= gh; }    int get_balance_factor(handle h)    {        if (m_nodes[h].gt & 0x80000000)            return -1;        return static_cast<unsigned>(m_nodes[h].lt) >> 31;    }    void set_balance_factor(handle h, int bf)    {        if (bf == 0) {            m_nodes[h].lt &= 0x7FFFFFFF;            m_nodes[h].gt &= 0x7FFFFFFF;        } else {            m_nodes[h].lt |= 0x80000000;            if (bf < 0)                m_nodes[h].gt |= 0x80000000;            else                m_nodes[h].gt &= 0x7FFFFFFF;        }    }    int compare_key_key(key va, key vb)    {        ASSERT(!va.isUndefined());        ASSERT(!vb.isUndefined());        if (m_exec->hadException())            return 1;        ArgList arguments;        arguments.append(va);        arguments.append(vb);        double compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, m_globalThisValue, arguments).toNumber(m_exec);        return (compareResult < 0) ? -1 : 1; // Not passing equality through, because we need to store all values, even if equivalent.    }    int compare_key_node(key k, handle h) { return compare_key_key(k, m_nodes[h].value); }    int compare_node_node(handle h1, handle h2) { return compare_key_key(m_nodes[h1].value, m_nodes[h2].value); }    static handle null() { return 0x7FFFFFFF; }};void JSArray::sort(ExecState* exec, JSValuePtr compareFunction, CallType callType, const CallData& callData){    checkConsistency();    // FIXME: This ignores exceptions raised in the compare function or in toNumber.    // The maximum tree depth is compiled in - but the caller is clearly up to no good    // if a larger array is passed.    ASSERT(m_storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max()));    if (m_storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max()))        return;    if (!m_storage->m_length)        return;    unsigned usedVectorLength = min(m_storage->m_length, m_storage->m_vectorLength);    AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items    tree.abstractor().m_exec = exec;    tree.abstractor().m_compareFunction = compareFunction;    tree.abstractor().m_compareCallType = callType;    tree.abstractor().m_compareCallData = &callData;    tree.abstractor().m_globalThisValue = exec->globalThisValue();    tree.abstractor().m_nodes.resize(usedVectorLength + (m_storage->m_sparseValueMap ? m_storage->m_sparseValueMap->size() : 0));    if (!tree.abstractor().m_nodes.begin()) {        throwOutOfMemoryError(exec);        return;    }    // FIXME: If the compare function modifies the array, the vector, map, etc. could be modified    // right out from under us while we're building the tree here.    unsigned numDefined = 0;    unsigned numUndefined = 0;    // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree.    for (; numDefined < usedVectorLength; ++numDefined) {        JSValuePtr v = m_storage->m_vector[numDefined];        if (!v || v.isUndefined())            break;        tree.abstractor().m_nodes[numDefined].value = v;        tree.insert(numDefined);    }    for (unsigned i = numDefined; i < usedVectorLength; ++i) {        JSValuePtr v = m_storage->m_vector[i];        if (v) {            if (v.isUndefined())                ++numUndefined;            else {                tree.abstractor().m_nodes[numDefined].value = v;                tree.insert(numDefined);                ++numDefined;            }        }    }    unsigned newUsedVectorLength = numDefined + numUndefined;    if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {        newUsedVectorLength += map->size();        if (newUsedVectorLength > m_storage->m_vectorLength) {            // Check that it is possible to allocate an array large enough to hold all the entries.            if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) {                throwOutOfMemoryError(exec);                return;            }        }        SparseArrayValueMap::iterator end = map->end();        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {            tree.abstractor().m_nodes[numDefined].value = it->second;            tree.insert(numDefined);            ++numDefined;        }        delete map;        m_storage->m_sparseValueMap = 0;    }    ASSERT(tree.abstractor().m_nodes.size() >= numDefined);    // FIXME: If the compare function changed the length of the array, the following might be    // modifying the vector incorrectly.    // Copy the values back into m_storage.    AVLTree<AVLTreeAbstractorForArrayCompare, 44>::Iterator iter;    iter.start_iter_least(tree);    for (unsigned i = 0; i < numDefined; ++i) {        m_storage->m_vector[i] = tree.abstractor().m_nodes[*iter].value;        ++iter;    }    // Put undefined values back in.    for (unsigned i = numDefined; i < newUsedVectorLength; ++i)        m_storage->m_vector[i] = jsUndefined();    // Ensure that unused values in the vector are zeroed out.    for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)        m_storage->m_vector[i] = noValue();    m_fastAccessCutoff = newUsedVectorLength;    m_storage->m_numValuesInVector = newUsedVectorLength;    checkConsistency(SortConsistencyCheck);}void JSArray::fillArgList(ExecState* exec, ArgList& args){    unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);    unsigned i = 0;    for (; i < fastAccessLength; ++i)        args.append(getIndex(i));    for (; i < m_storage->m_length; ++i)        args.append(get(exec, i));}unsigned JSArray::compactForSorting(){    checkConsistency();    ArrayStorage* storage = m_storage;    unsigned usedVectorLength = min(m_storage->m_length, storage->m_vectorLength);    unsigned numDefined = 0;    unsigned numUndefined = 0;    for (; numDefined < usedVectorLength; ++numDefined) {        JSValuePtr v = storage->m_vector[numDefined];        if (!v || v.isUndefined())            break;    }    for (unsigned i = numDefined; i < usedVectorLength; ++i) {        JSValuePtr v = storage->m_vector[i];        if (v) {            if (v.isUndefined())                ++numUndefined;            else                storage->m_vector[numDefined++] = v;        }    }    unsigned newUsedVectorLength = numDefined + numUndefined;    if (SparseArrayValueMap* map = storage->m_sparseValueMap) {        newUsedVectorLength += map->size();        if (newUsedVectorLength > storage->m_vectorLength) {            // Check that it is possible to allocate an array large enough to hold all the entries - if not,            // exception is thrown by caller.            if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength))                return 0;            storage = m_storage;        }        SparseArrayValueMap::iterator end = map->end();        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)            storage->m_vector[numDefined++] = it->second;        delete map;        storage->m_sparseValueMap = 0;    }    for (unsigned i = numDefined; i < newUsedVectorLength; ++i)        storage->m_vector[i] = jsUndefined();    for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)        storage->m_vector[i] = noValue();    m_fastAccessCutoff = newUsedVectorLength;    storage->m_numValuesInVector = newUsedVectorLength;    checkConsistency(SortConsistencyCheck);    return numDefined;}void* JSArray::lazyCreationData(){    return m_storage->lazyCreationData;}void JSArray::setLazyCreationData(void* d){    m_storage->lazyCreationData = d;}#if CHECK_ARRAY_CONSISTENCYvoid JSArray::checkConsistency(ConsistencyCheckType type){    ASSERT(m_storage);    if (type == SortConsistencyCheck)        ASSERT(!m_storage->m_sparseValueMap);    ASSERT(m_fastAccessCutoff <= m_storage->m_length);    ASSERT(m_fastAccessCutoff <= m_storage->m_numValuesInVector);    unsigned numValuesInVector = 0;    for (unsigned i = 0; i < m_storage->m_vectorLength; ++i) {        if (JSValuePtr value = m_storage->m_vector[i]) {            ASSERT(i < m_storage->m_length);            if (type != DestructorConsistencyCheck)                value->type(); // Likely to crash if the object was deallocated.            ++numValuesInVector;        } else {            ASSERT(i >= m_fastAccessCutoff);            if (type == SortConsistencyCheck)                ASSERT(i >= m_storage->m_numValuesInVector);        }    }    ASSERT(numValuesInVector == m_storage->m_numValuesInVector);    if (m_storage->m_sparseValueMap) {        SparseArrayValueMap::iterator end = m_storage->m_sparseValueMap->end();        for (SparseArrayValueMap::iterator it = m_storage->m_sparseValueMap->begin(); it != end; ++it) {            unsigned index = it->first;            ASSERT(index < m_storage->m_length);            ASSERT(index >= m_storage->m_vectorLength);            ASSERT(index <= MAX_ARRAY_INDEX);            ASSERT(it->second);            if (type != DestructorConsistencyCheck)                it->second->type(); // Likely to crash if the object was deallocated.        }    }}#endifJSArray* constructEmptyArray(ExecState* exec){    return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());}JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength){    return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength);}JSArray* constructArray(ExecState* exec, JSValuePtr singleItemValue){    ArgList values;    values.append(singleItemValue);    return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), values);}JSArray* constructArray(ExecState* exec, const ArgList& values){    return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), values);}} // namespace JSC

⌨️ 快捷键说明

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