Remove excessive headers from JavaScriptCore
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSArrayBufferView.cpp
1 /*
2  * Copyright (C) 2013-2017 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 #include "config.h"
27 #include "JSArrayBufferView.h"
28
29 #include "JSArrayBuffer.h"
30 #include "JSCInlines.h"
31 #include "TypeError.h"
32 #include "TypedArrayController.h"
33
34 namespace JSC {
35
36 const ClassInfo JSArrayBufferView::s_info = {
37     "ArrayBufferView", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayBufferView)
38 };
39
40 String JSArrayBufferView::toStringName(const JSObject*, ExecState*)
41 {
42     return ASCIILiteral("Object");
43 }
44
45 JSArrayBufferView::ConstructionContext::ConstructionContext(
46     Structure* structure, uint32_t length, void* vector)
47     : m_structure(structure)
48     , m_vector(vector)
49     , m_length(length)
50     , m_mode(FastTypedArray)
51     , m_butterfly(nullptr)
52 {
53     RELEASE_ASSERT(length <= fastSizeLimit);
54 }
55
56 JSArrayBufferView::ConstructionContext::ConstructionContext(
57     VM& vm, Structure* structure, uint32_t length, uint32_t elementSize,
58     InitializationMode mode)
59     : m_structure(0)
60     , m_length(length)
61     , m_butterfly(0)
62 {
63     if (length <= fastSizeLimit) {
64         // Attempt GC allocation.
65         void* temp;
66         size_t size = sizeOf(length, elementSize);
67         if (size) {
68             temp = vm.auxiliarySpace.tryAllocate(nullptr, size);
69             if (!temp)
70                 return;
71         } else
72             temp = nullptr;
73
74         m_structure = structure;
75         m_vector = temp;
76         m_mode = FastTypedArray;
77
78         if (mode == ZeroFill) {
79             uint64_t* asWords = static_cast<uint64_t*>(m_vector);
80             for (unsigned i = size / sizeof(uint64_t); i--;)
81                 asWords[i] = 0;
82         }
83         
84         return;
85     }
86
87     // Don't allow a typed array to use more than 2GB.
88     if (length > static_cast<unsigned>(INT_MAX) / elementSize)
89         return;
90     
91     if (mode == ZeroFill) {
92         if (!tryFastCalloc(length, elementSize).getValue(m_vector))
93             return;
94     } else {
95         if (!tryFastMalloc(length * elementSize).getValue(m_vector))
96             return;
97     }
98     
99     vm.heap.reportExtraMemoryAllocated(static_cast<size_t>(length) * elementSize);
100     
101     m_structure = structure;
102     m_mode = OversizeTypedArray;
103 }
104
105 JSArrayBufferView::ConstructionContext::ConstructionContext(
106     VM& vm, Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer,
107     unsigned byteOffset, unsigned length)
108     : m_structure(structure)
109     , m_length(length)
110     , m_mode(WastefulTypedArray)
111 {
112     m_vector = static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset;
113     IndexingHeader indexingHeader;
114     indexingHeader.setArrayBuffer(arrayBuffer.get());
115     m_butterfly = Butterfly::create(vm, 0, 0, 0, true, indexingHeader, 0);
116 }
117
118 JSArrayBufferView::ConstructionContext::ConstructionContext(
119     Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer,
120     unsigned byteOffset, unsigned length, DataViewTag)
121     : m_structure(structure)
122     , m_length(length)
123     , m_mode(DataViewMode)
124     , m_butterfly(0)
125 {
126     m_vector = static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset;
127 }
128
129 JSArrayBufferView::JSArrayBufferView(VM& vm, ConstructionContext& context)
130     : Base(vm, context.structure(), context.butterfly())
131     , m_length(context.length())
132     , m_mode(context.mode())
133 {
134     m_vector.setWithoutBarrier(context.vector());
135 }
136
137 void JSArrayBufferView::finishCreation(VM& vm)
138 {
139     Base::finishCreation(vm);
140     switch (m_mode) {
141     case FastTypedArray:
142         return;
143     case OversizeTypedArray:
144         vm.heap.addFinalizer(this, finalize);
145         return;
146     case WastefulTypedArray:
147         vm.heap.addReference(this, butterfly()->indexingHeader()->arrayBuffer());
148         return;
149     case DataViewMode:
150         ASSERT(!butterfly());
151         vm.heap.addReference(this, jsCast<JSDataView*>(this)->possiblySharedBuffer());
152         return;
153     }
154     RELEASE_ASSERT_NOT_REACHED();
155 }
156
157 void JSArrayBufferView::visitChildren(JSCell* cell, SlotVisitor& visitor)
158 {
159     JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell);
160
161     if (thisObject->hasArrayBuffer()) {
162         WTF::loadLoadFence();
163         ArrayBuffer* buffer = thisObject->possiblySharedBuffer();
164         RELEASE_ASSERT(buffer);
165         visitor.addOpaqueRoot(buffer);
166     }
167     
168     Base::visitChildren(thisObject, visitor);
169 }
170
171 bool JSArrayBufferView::put(
172     JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value,
173     PutPropertySlot& slot)
174 {
175     JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell);
176
177     if (UNLIKELY(isThisValueAltered(slot, thisObject)))
178         return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
179     
180     return Base::put(thisObject, exec, propertyName, value, slot);
181 }
182
183 ArrayBuffer* JSArrayBufferView::unsharedBuffer()
184 {
185     ArrayBuffer* result = possiblySharedBuffer();
186     RELEASE_ASSERT(!result->isShared());
187     return result;
188 }
189     
190 void JSArrayBufferView::finalize(JSCell* cell)
191 {
192     JSArrayBufferView* thisObject = static_cast<JSArrayBufferView*>(cell);
193     ASSERT(thisObject->m_mode == OversizeTypedArray || thisObject->m_mode == WastefulTypedArray);
194     if (thisObject->m_mode == OversizeTypedArray)
195         fastFree(thisObject->m_vector.get());
196 }
197
198 JSArrayBuffer* JSArrayBufferView::unsharedJSBuffer(ExecState* exec)
199 {
200     return exec->vm().m_typedArrayController->toJS(exec, globalObject(), unsharedBuffer());
201 }
202
203 JSArrayBuffer* JSArrayBufferView::possiblySharedJSBuffer(ExecState* exec)
204 {
205     return exec->vm().m_typedArrayController->toJS(exec, globalObject(), possiblySharedBuffer());
206 }
207
208 void JSArrayBufferView::neuter()
209 {
210     RELEASE_ASSERT(hasArrayBuffer());
211     RELEASE_ASSERT(!isShared());
212     m_length = 0;
213     m_vector.clear();
214 }
215
216 } // namespace JSC
217
218 namespace WTF {
219
220 using namespace JSC;
221
222 void printInternal(PrintStream& out, TypedArrayMode mode)
223 {
224     switch (mode) {
225     case FastTypedArray:
226         out.print("FastTypedArray");
227         return;
228     case OversizeTypedArray:
229         out.print("OversizeTypedArray");
230         return;
231     case WastefulTypedArray:
232         out.print("WastefulTypedArray");
233         return;
234     case DataViewMode:
235         out.print("DataViewMode");
236         return;
237     }
238     RELEASE_ASSERT_NOT_REACHED();
239 }
240
241 } // namespace WTF
242