JSArray.h 8.13 KB
Newer Older
1 2
/*
 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3
 *  Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 *  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
mjs's avatar
mjs committed
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 19 20
 *
 */

darin@apple.com's avatar
darin@apple.com committed
21 22
#ifndef JSArray_h
#define JSArray_h
23

darin@apple.com's avatar
darin@apple.com committed
24
#include "JSObject.h"
25

26
namespace JSC {
27

ggaren@apple.com's avatar
ggaren@apple.com committed
28
    typedef HashMap<unsigned, JSValue> SparseArrayValueMap;
29 30

    struct ArrayStorage {
ggaren@apple.com's avatar
ggaren@apple.com committed
31
        unsigned m_length;
32 33 34
        unsigned m_numValuesInVector;
        SparseArrayValueMap* m_sparseValueMap;
        void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily.
35
        size_t reportedMapCapacity;
ggaren@apple.com's avatar
ggaren@apple.com committed
36
        JSValue m_vector[1];
37 38 39
    };

    class JSArray : public JSObject {
40
        friend class JIT;
41
        friend class Walker;
42

43
    public:
44 45 46
        explicit JSArray(NonNullPassRefPtr<Structure>);
        JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength);
        JSArray(NonNullPassRefPtr<Structure>, const ArgList& initialValues);
47 48 49 50
        virtual ~JSArray();

        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
51
        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
ggaren@apple.com's avatar
ggaren@apple.com committed
52
        virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem.
53

sfalken@apple.com's avatar
sfalken@apple.com committed
54
        static JS_EXPORTDATA const ClassInfo info;
55

ggaren@apple.com's avatar
ggaren@apple.com committed
56
        unsigned length() const { return m_storage->m_length; }
57 58 59
        void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray.

        void sort(ExecState*);
ggaren@apple.com's avatar
ggaren@apple.com committed
60 61
        void sort(ExecState*, JSValue compareFunction, CallType, const CallData&);
        void sortNumeric(ExecState*, JSValue compareFunction, CallType, const CallData&);
62

ggaren@apple.com's avatar
ggaren@apple.com committed
63 64
        void push(ExecState*, JSValue);
        JSValue pop();
65

66
        bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
ggaren@apple.com's avatar
ggaren@apple.com committed
67
        JSValue getIndex(unsigned i)
68 69 70 71 72
        {
            ASSERT(canGetIndex(i));
            return m_storage->m_vector[i];
        }

73 74
        bool canSetIndex(unsigned i) { return i < m_vectorLength; }
        void setIndex(unsigned i, JSValue v)
75 76
        {
            ASSERT(canSetIndex(i));
77 78 79 80 81 82 83
            JSValue& x = m_storage->m_vector[i];
            if (!x) {
                ++m_storage->m_numValuesInVector;
                if (i >= m_storage->m_length)
                    m_storage->m_length = i + 1;
            }
            x = v;
84 85
        }

86
        void fillArgList(ExecState*, MarkedArgumentBuffer&);
87
        void copyToRegisters(ExecState*, Register*, uint32_t);
weinig@apple.com's avatar
weinig@apple.com committed
88

ggaren@apple.com's avatar
ggaren@apple.com committed
89
        static PassRefPtr<Structure> createStructure(JSValue prototype)
darin@apple.com's avatar
darin@apple.com committed
90
        {
91
            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
darin@apple.com's avatar
darin@apple.com committed
92
        }
oliver@apple.com's avatar
oliver@apple.com committed
93 94
        
        inline void markChildrenDirect(MarkStack& markStack);
darin@apple.com's avatar
darin@apple.com committed
95

96
    protected:
97
        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
ggaren@apple.com's avatar
ggaren@apple.com committed
98
        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
99 100
        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
        virtual bool deleteProperty(ExecState*, unsigned propertyName);
oliver@apple.com's avatar
oliver@apple.com committed
101
        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
102
        virtual void markChildren(MarkStack&);
103 104 105 106 107 108 109 110

        void* lazyCreationData();
        void setLazyCreationData(void*);

    private:
        virtual const ClassInfo* classInfo() const { return &info; }

        bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
ggaren@apple.com's avatar
ggaren@apple.com committed
111
        void putSlowCase(ExecState*, unsigned propertyName, JSValue);
112 113 114 115 116 117 118 119

        bool increaseVectorLength(unsigned newLength);
        
        unsigned compactForSorting();

        enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
        void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);

120
        unsigned m_vectorLength;
121 122 123
        ArrayStorage* m_storage;
    };

ggaren@apple.com's avatar
ggaren@apple.com committed
124
    JSArray* asArray(JSValue);
darin@apple.com's avatar
darin@apple.com committed
125

126 127 128 129 130 131
    inline JSArray* asArray(JSCell* cell)
    {
        ASSERT(cell->inherits(&JSArray::info));
        return static_cast<JSArray*>(cell);
    }

ggaren@apple.com's avatar
ggaren@apple.com committed
132
    inline JSArray* asArray(JSValue value)
darin@apple.com's avatar
darin@apple.com committed
133
    {
134
        return asArray(value.asCell());
darin@apple.com's avatar
darin@apple.com committed
135 136
    }

137 138 139 140
    inline bool isJSArray(JSGlobalData* globalData, JSValue v)
    {
        return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr;
    }
141
    inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; }
142

143 144
    inline void JSArray::markChildrenDirect(MarkStack& markStack)
    {
oliver@apple.com's avatar
oliver@apple.com committed
145 146 147
        JSObject::markChildrenDirect(markStack);
        
        ArrayStorage* storage = m_storage;
148

149
        unsigned usedVectorLength = std::min(storage->m_length, m_vectorLength);
oliver@apple.com's avatar
oliver@apple.com committed
150
        markStack.appendValues(storage->m_vector, usedVectorLength, MayContainNullValues);
151

oliver@apple.com's avatar
oliver@apple.com committed
152 153 154 155 156 157 158
        if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
            SparseArrayValueMap::iterator end = map->end();
            for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
                markStack.append(it->second);
        }
    }

159 160 161
    inline void MarkStack::markChildren(JSCell* cell)
    {
        ASSERT(Heap::isCellMarked(cell));
162
        if (!cell->structure()->typeInfo().overridesMarkChildren()) {
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
#ifdef NDEBUG
            asObject(cell)->markChildrenDirect(*this);
#else
            ASSERT(!m_isCheckingForDefaultMarkViolation);
            m_isCheckingForDefaultMarkViolation = true;
            cell->markChildren(*this);
            ASSERT(m_isCheckingForDefaultMarkViolation);
            m_isCheckingForDefaultMarkViolation = false;
#endif
            return;
        }
        if (cell->vptr() == m_jsArrayVPtr) {
            asArray(cell)->markChildrenDirect(*this);
            return;
        }
        cell->markChildren(*this);
    }

oliver@apple.com's avatar
oliver@apple.com committed
181 182 183 184 185 186 187 188 189 190 191 192
    inline void MarkStack::drain()
    {
        while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
            while (!m_markSets.isEmpty() && m_values.size() < 50) {
                ASSERT(!m_markSets.isEmpty());
                MarkSet& current = m_markSets.last();
                ASSERT(current.m_values);
                JSValue* end = current.m_end;
                ASSERT(current.m_values);
                ASSERT(current.m_values != end);
            findNextUnmarkedNullValue:
                ASSERT(current.m_values != end);
193
                JSValue value = *current.m_values;
oliver@apple.com's avatar
oliver@apple.com committed
194
                current.m_values++;
195 196 197

                JSCell* cell;
                if (!value || !value.isCell() || Heap::isCellMarked(cell = value.asCell())) {
oliver@apple.com's avatar
oliver@apple.com committed
198 199 200 201 202 203
                    if (current.m_values == end) {
                        m_markSets.removeLast();
                        continue;
                    }
                    goto findNextUnmarkedNullValue;
                }
204 205 206

                Heap::markCell(cell);
                if (cell->structure()->typeInfo().type() < CompoundType) {
oliver@apple.com's avatar
oliver@apple.com committed
207 208 209 210 211 212
                    if (current.m_values == end) {
                        m_markSets.removeLast();
                        continue;
                    }
                    goto findNextUnmarkedNullValue;
                }
213

oliver@apple.com's avatar
oliver@apple.com committed
214 215 216
                if (current.m_values == end)
                    m_markSets.removeLast();

217
                markChildren(cell);
oliver@apple.com's avatar
oliver@apple.com committed
218
            }
219 220
            while (!m_values.isEmpty())
                markChildren(m_values.removeLast());
oliver@apple.com's avatar
oliver@apple.com committed
221 222 223
        }
    }
    
224
} // namespace JSC
225

226
#endif // JSArray_h