c544cac3d7812ad5c406655b591609244969977b
[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 "Reject.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 JSArrayBufferView::ConstructionContext::ConstructionContext(
40     VM& vm, Structure* structure, uint32_t length, uint32_t elementSize,
41     InitializationMode mode)
42     : m_structure(0)
43     , m_length(length)
44     , m_butterfly(0)
45 {
46     if (length <= fastSizeLimit) {
47         // Attempt GC allocation.
48         void* temp = 0;
49         size_t size = sizeOf(length, elementSize);
50         // CopiedSpace only allows non-zero size allocations.
51         if (size && !vm.heap.tryAllocateStorage(0, size, &temp))
52             return;
53
54         m_structure = structure;
55         m_vector = temp;
56         m_mode = FastTypedArray;
57
58 #if USE(JSVALUE32_64)
59         if (mode == ZeroFill) {
60             uint64_t* asWords = static_cast<uint64_t*>(m_vector);
61             for (unsigned i = size / sizeof(uint64_t); i--;)
62                 asWords[i] = 0;
63         }
64 #endif // USE(JSVALUE32_64)
65         
66         return;
67     }
68
69     // Don't allow a typed array to use more than 2GB.
70     if (length > static_cast<unsigned>(INT_MAX) / elementSize)
71         return;
72     
73     if (mode == ZeroFill) {
74         if (!tryFastCalloc(length, elementSize).getValue(m_vector))
75             return;
76     } else {
77         if (!tryFastMalloc(length * elementSize).getValue(m_vector))
78             return;
79     }
80     
81     vm.heap.reportExtraMemoryAllocated(static_cast<size_t>(length) * elementSize);
82     
83     m_structure = structure;
84     m_mode = OversizeTypedArray;
85 }
86
87 JSArrayBufferView::ConstructionContext::ConstructionContext(
88     VM& vm, Structure* structure, PassRefPtr<ArrayBuffer> arrayBuffer,
89     unsigned byteOffset, unsigned length)
90     : m_structure(structure)
91     , m_length(length)
92     , m_mode(WastefulTypedArray)
93 {
94     m_vector = static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset;
95     IndexingHeader indexingHeader;
96     indexingHeader.setArrayBuffer(arrayBuffer.get());
97     m_butterfly = Butterfly::create(vm, 0, 0, 0, true, indexingHeader, 0);
98 }
99
100 JSArrayBufferView::ConstructionContext::ConstructionContext(
101     Structure* structure, PassRefPtr<ArrayBuffer> arrayBuffer,
102     unsigned byteOffset, unsigned length, DataViewTag)
103     : m_structure(structure)
104     , m_length(length)
105     , m_mode(DataViewMode)
106     , m_butterfly(0)
107 {
108     m_vector = static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset;
109 }
110
111 JSArrayBufferView::JSArrayBufferView(VM& vm, ConstructionContext& context)
112     : Base(vm, context.structure(), context.butterfly())
113     , m_length(context.length())
114     , m_mode(context.mode())
115 {
116     m_vector.setWithoutBarrier(static_cast<char*>(context.vector()));
117 }
118
119 void JSArrayBufferView::finishCreation(VM& vm)
120 {
121     Base::finishCreation(vm);
122     switch (m_mode) {
123     case FastTypedArray:
124         return;
125     case OversizeTypedArray:
126         vm.heap.addFinalizer(this, finalize);
127         return;
128     case WastefulTypedArray:
129         vm.heap.addReference(this, butterfly()->indexingHeader()->arrayBuffer());
130         return;
131     case DataViewMode:
132         ASSERT(!butterfly());
133         vm.heap.addReference(this, jsCast<JSDataView*>(this)->buffer());
134         return;
135     }
136     RELEASE_ASSERT_NOT_REACHED();
137 }
138
139 void JSArrayBufferView::visitChildren(JSCell* cell, SlotVisitor& visitor)
140 {
141     JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell);
142
143     if (thisObject->hasArrayBuffer()) {
144         ArrayBuffer* buffer = thisObject->buffer();
145         RELEASE_ASSERT(buffer);
146         visitor.addOpaqueRoot(buffer);
147     }
148     
149     Base::visitChildren(thisObject, visitor);
150 }
151
152 bool JSArrayBufferView::put(
153     JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value,
154     PutPropertySlot& slot)
155 {
156     JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell);
157
158     if (UNLIKELY(isThisValueAltered(slot, thisObject)))
159         return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
160     
161     return Base::put(thisObject, exec, propertyName, value, slot);
162 }
163     
164 void JSArrayBufferView::finalize(JSCell* cell)
165 {
166     JSArrayBufferView* thisObject = static_cast<JSArrayBufferView*>(cell);
167     ASSERT(thisObject->m_mode == OversizeTypedArray || thisObject->m_mode == WastefulTypedArray);
168     if (thisObject->m_mode == OversizeTypedArray)
169         fastFree(thisObject->m_vector.get());
170 }
171
172 } // namespace JSC
173
174 namespace WTF {
175
176 using namespace JSC;
177
178 void printInternal(PrintStream& out, TypedArrayMode mode)
179 {
180     switch (mode) {
181     case FastTypedArray:
182         out.print("FastTypedArray");
183         return;
184     case OversizeTypedArray:
185         out.print("OversizeTypedArray");
186         return;
187     case WastefulTypedArray:
188         out.print("WastefulTypedArray");
189         return;
190     case DataViewMode:
191         out.print("DataViewMode");
192         return;
193     }
194     RELEASE_ASSERT_NOT_REACHED();
195 }
196
197 } // namespace WTF
198