Remove poisoning of typed array vector
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSArrayBufferView.h
1 /*
2  * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #include "AuxiliaryBarrier.h"
29 #include "JSObject.h"
30
31 namespace JSC {
32
33 class LLIntOffsetsExtractor;
34
35 // This class serves two purposes:
36 //
37 // 1) It provides those parts of JSGenericTypedArrayView that don't depend
38 //    on template parameters.
39 //
40 // 2) It represents the DOM/WebCore-visible "JSArrayBufferView" type, which
41 //    C++ code uses when it wants to pass around a view of an array buffer
42 //    without concern for the actual type of the view.
43 //
44 // These two roles are quite different. (1) is just a matter of optimizing
45 // compile and link times by having as much code and data as possible not
46 // be subject to template specialization. (2) is *almost* a matter of
47 // semantics; indeed at the very least it is a matter of obeying a contract
48 // that we have with WebCore right now.
49 //
50 // One convenient thing that saves us from too much crazy is that
51 // ArrayBufferView is not instantiable.
52
53 // Typed array views have different modes depending on how big they are and
54 // whether the user has done anything that requires a separate backing
55 // buffer or the DOM-specified neutering capabilities.
56 enum TypedArrayMode : uint32_t {
57     // Small and fast typed array. B is unused, V points to a vector
58     // allocated in copied space, and M = FastTypedArray. V's liveness is
59     // determined entirely by the view's liveness.
60     FastTypedArray,
61     
62     // A large typed array that still attempts not to waste too much
63     // memory. B is initialized to point to a slot that could hold a
64     // buffer pointer, V points to a vector allocated using fastCalloc(),
65     // and M = OversizeTypedArray. V's liveness is determined entirely by
66     // the view's liveness, and the view will add a finalizer to delete V.
67     OversizeTypedArray,
68     
69     // A typed array that was used in some crazy way. B's IndexingHeader
70     // is hijacked to contain a reference to the native array buffer. The
71     // native typed array view points back to the JS view. V points to a
72     // vector allocated using who-knows-what, and M = WastefulTypedArray.
73     // The view does not own the vector.
74     WastefulTypedArray,
75     
76     // A data view. B is unused, V points to a vector allocated using who-
77     // knows-what, and M = DataViewMode. The view does not own the vector.
78     // There is an extra field (in JSDataView) that points to the
79     // ArrayBuffer.
80     DataViewMode
81 };
82
83 inline bool hasArrayBuffer(TypedArrayMode mode)
84 {
85     return mode >= WastefulTypedArray;
86 }
87
88 // When WebCore uses a JSArrayBufferView, it expects to be able to get the native
89 // ArrayBuffer and little else. This requires slowing down and wasting memory,
90 // and then accessing things via the Butterfly. When JS uses a JSArrayBufferView
91 // it is always via the usual methods in the MethodTable, so this class's
92 // implementation of those has no need to even exist - we could at any time sink
93 // code into JSGenericTypedArrayView if it was convenient.
94
95 class JSArrayBufferView : public JSNonFinalObject {
96 public:
97     typedef JSNonFinalObject Base;
98     static const unsigned fastSizeLimit = 1000;
99     
100     static size_t sizeOf(uint32_t length, uint32_t elementSize)
101     {
102         return (length * elementSize + sizeof(EncodedJSValue) - 1)
103             & ~(sizeof(EncodedJSValue) - 1);
104     }
105
106     static size_t allocationSize(Checked<size_t> inlineCapacity)
107     {
108         ASSERT_UNUSED(inlineCapacity, !inlineCapacity);
109         return sizeof(JSArrayBufferView);
110     }
111         
112 protected:
113     class ConstructionContext {
114         WTF_MAKE_NONCOPYABLE(ConstructionContext);
115         
116     public:
117         enum InitializationMode { ZeroFill, DontInitialize };
118         
119         JS_EXPORT_PRIVATE ConstructionContext(VM&, Structure*, uint32_t length, uint32_t elementSize, InitializationMode = ZeroFill);
120         
121         // This is only for constructing fast typed arrays. It's used by the JIT's slow path.
122         ConstructionContext(Structure*, uint32_t length, void* vector);
123         
124         JS_EXPORT_PRIVATE ConstructionContext(
125             VM&, Structure*, RefPtr<ArrayBuffer>&&,
126             unsigned byteOffset, unsigned length);
127         
128         enum DataViewTag { DataView };
129         ConstructionContext(
130             Structure*, RefPtr<ArrayBuffer>&&,
131             unsigned byteOffset, unsigned length, DataViewTag);
132         
133         bool operator!() const { return !m_structure; }
134         
135         Structure* structure() const { return m_structure; }
136         void* vector() const { return m_vector.getMayBeNull(); }
137         uint32_t length() const { return m_length; }
138         TypedArrayMode mode() const { return m_mode; }
139         Butterfly* butterfly() const { return m_butterfly; }
140         
141     private:
142         Structure* m_structure;
143         CagedPtr<Gigacage::Primitive, void> m_vector;
144         uint32_t m_length;
145         TypedArrayMode m_mode;
146         Butterfly* m_butterfly;
147     };
148     
149     JS_EXPORT_PRIVATE JSArrayBufferView(VM&, ConstructionContext&);
150     JS_EXPORT_PRIVATE void finishCreation(VM&);
151     
152     static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
153
154     static void visitChildren(JSCell*, SlotVisitor&);
155     
156 public:
157     TypedArrayMode mode() const { return m_mode; }
158     bool hasArrayBuffer() const { return JSC::hasArrayBuffer(mode()); }
159     
160     bool isShared();
161     JS_EXPORT_PRIVATE ArrayBuffer* unsharedBuffer();
162     ArrayBuffer* possiblySharedBuffer();
163     JSArrayBuffer* unsharedJSBuffer(ExecState* exec);
164     JSArrayBuffer* possiblySharedJSBuffer(ExecState* exec);
165     RefPtr<ArrayBufferView> unsharedImpl();
166     RefPtr<ArrayBufferView> possiblySharedImpl();
167     bool isNeutered() { return hasArrayBuffer() && !vector(); }
168     void neuter();
169     
170     void* vector() const { return m_vector.getMayBeNull(); }
171     
172     unsigned byteOffset();
173     unsigned length() const { return m_length; }
174
175     DECLARE_EXPORT_INFO;
176     
177     static ptrdiff_t offsetOfVector() { return OBJECT_OFFSETOF(JSArrayBufferView, m_vector); }
178     static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(JSArrayBufferView, m_length); }
179     static ptrdiff_t offsetOfMode() { return OBJECT_OFFSETOF(JSArrayBufferView, m_mode); }
180     
181     static RefPtr<ArrayBufferView> toWrapped(VM&, JSValue);
182
183 private:
184     static void finalize(JSCell*);
185
186 protected:
187     friend class LLIntOffsetsExtractor;
188
189     ArrayBuffer* existingBufferInButterfly();
190
191     static String toStringName(const JSObject*, ExecState*);
192
193     CagedBarrierPtr<Gigacage::Primitive, void> m_vector;
194     uint32_t m_length;
195     TypedArrayMode m_mode;
196 };
197
198 } // namespace JSC
199
200 namespace WTF {
201
202 JS_EXPORT_PRIVATE void printInternal(PrintStream&, JSC::TypedArrayMode);
203
204 } // namespace WTF