JSArrayBufferView.h 7.38 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
/*
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#ifndef JSArrayBufferView_h
#define JSArrayBufferView_h

#include "JSObject.h"

namespace JSC {

// This class serves two purposes:
//
// 1) It provides those parts of JSGenericTypedArrayView that don't depend
//    on template parameters.
//
// 2) It represents the DOM/WebCore-visible "JSArrayBufferView" type, which
//    C++ code uses when it wants to pass around a view of an array buffer
//    without concern for the actual type of the view.
//
// These two roles are quite different. (1) is just a matter of optimizing
// compile and link times by having as much code and data as possible not
// be subject to template specialization. (2) is *almost* a matter of
// semantics; indeed at the very least it is a matter of obeying a contract
// that we have with WebCore right now.
//
// One convenient thing that saves us from too much crazy is that
// ArrayBufferView is not instantiable.

// Typed array views have different modes depending on how big they are and
// whether the user has done anything that requires a separate backing
// buffer or the DOM-specified neutering capabilities.
enum TypedArrayMode {
    // Small and fast typed array. B is unused, V points to a vector
    // allocated in copied space, and M = FastTypedArray. V's liveness is
    // determined entirely by the view's liveness.
    FastTypedArray,
    
    // A large typed array that still attempts not to waste too much
    // memory. B is initialized to point to a slot that could hold a
    // buffer pointer, V points to a vector allocated using fastCalloc(),
    // and M = OversizeTypedArray. V's liveness is determined entirely by
    // the view's liveness, and the view will add a finalizer to delete V.
    OversizeTypedArray,
    
    // A typed array that was used in some crazy way. B's IndexingHeader
    // is hijacked to contain a reference to the native array buffer. The
    // native typed array view points back to the JS view. V points to a
    // vector allocated using who-knows-what, and M = WastefulTypedArray.
    // The view does not own the vector.
    WastefulTypedArray,
73 74 75 76 77 78
    
    // A data view. B is unused, V points to a vector allocated using who-
    // knows-what, and M = DataViewMode. The view does not own the vector.
    // There is an extra field (in JSDataView) that points to the
    // ArrayBuffer.
    DataViewMode
79 80
};

81 82 83 84 85
inline bool hasArrayBuffer(TypedArrayMode mode)
{
    return mode >= WastefulTypedArray;
}

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
// When WebCore uses a JSArrayBufferView, it expects to be able to get the native
// ArrayBuffer and little else. This requires slowing down and wasting memory,
// and then accessing things via the Butterfly. When JS uses a JSArrayBufferView
// it is always via the usual methods in the MethodTable, so this class's
// implementation of those has no need to even exist - we could at any time sink
// code into JSGenericTypedArrayView if it was convenient.

class JSArrayBufferView : public JSNonFinalObject {
public:
    typedef JSNonFinalObject Base;
    
    static const unsigned fastSizeLimit = 1000;
    
    static size_t sizeOf(uint32_t length, uint32_t elementSize)
    {
        return (length * elementSize + sizeof(EncodedJSValue) - 1)
            & ~(sizeof(EncodedJSValue) - 1);
    }

105 106 107 108 109 110
    static size_t allocationSize(size_t inlineCapacity)
    {
        ASSERT_UNUSED(inlineCapacity, !inlineCapacity);
        return sizeof(JSArrayBufferView);
    }
        
111 112 113 114 115 116 117 118 119 120 121 122 123
protected:
    class ConstructionContext {
        WTF_MAKE_NONCOPYABLE(ConstructionContext);
        
    public:
        enum InitializationMode { ZeroFill, DontInitialize };
        
        JS_EXPORT_PRIVATE ConstructionContext(VM&, Structure*, uint32_t length, uint32_t elementSize, InitializationMode = ZeroFill);
        
        JS_EXPORT_PRIVATE ConstructionContext(
            VM&, Structure*, PassRefPtr<ArrayBuffer>,
            unsigned byteOffset, unsigned length);
        
124 125 126 127 128
        enum DataViewTag { DataView };
        ConstructionContext(
            Structure*, PassRefPtr<ArrayBuffer>,
            unsigned byteOffset, unsigned length, DataViewTag);
        
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
        bool operator!() const { return !m_structure; }
        
        Structure* structure() const { return m_structure; }
        void* vector() const { return m_vector; }
        uint32_t length() const { return m_length; }
        TypedArrayMode mode() const { return m_mode; }
        Butterfly* butterfly() const { return m_butterfly; }
        
    private:
        Structure* m_structure;
        void* m_vector;
        uint32_t m_length;
        TypedArrayMode m_mode;
        Butterfly* m_butterfly;
    };
    
    JS_EXPORT_PRIVATE JSArrayBufferView(VM&, ConstructionContext&);
    JS_EXPORT_PRIVATE void finishCreation(VM&);
    
    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
    static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
150
    static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
151 152 153 154 155 156
    static bool deleteProperty(JSCell*, ExecState*, PropertyName);
    
    static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    
public:
    TypedArrayMode mode() const { return m_mode; }
157 158
    bool hasArrayBuffer() const { return JSC::hasArrayBuffer(mode()); }
    
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
    ArrayBuffer* buffer();
    PassRefPtr<ArrayBufferView> impl();
    void neuter();
    
    void* vector() { return m_vector; }
    unsigned byteOffset();
    unsigned length() const { return m_length; }

    DECLARE_EXPORT_INFO;
    
    static ptrdiff_t offsetOfVector() { return OBJECT_OFFSETOF(JSArrayBufferView, m_vector); }
    static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(JSArrayBufferView, m_length); }
    static ptrdiff_t offsetOfMode() { return OBJECT_OFFSETOF(JSArrayBufferView, m_mode); }

private:
    static void finalize(JSCell*);

protected:
    static const unsigned StructureFlags = OverridesGetPropertyNames | OverridesGetOwnPropertySlot | Base::StructureFlags;
178 179
    
    ArrayBuffer* existingBufferInButterfly();
180 181 182 183 184 185 186 187 188 189

    void* m_vector;
    uint32_t m_length;
    TypedArrayMode m_mode;
};

} // namespace JSC

#endif // JSArrayBufferView_h