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