]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSArrayBufferView.cpp
da0cde256ca0c999c35aa5caeb123709bd790c94
[apple/javascriptcore.git] / runtime / JSArrayBufferView.cpp
1 /*
2 * Copyright (C) 2013 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, 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.reportExtraMemoryCost(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_vector(static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset)
92 , m_length(length)
93 , m_mode(WastefulTypedArray)
94 {
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_vector(static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset)
105 , m_length(length)
106 , m_mode(DataViewMode)
107 , m_butterfly(0)
108 {
109 }
110
111 JSArrayBufferView::JSArrayBufferView(VM& vm, ConstructionContext& context)
112 : Base(vm, context.structure(), context.butterfly())
113 , m_vector(context.vector())
114 , m_length(context.length())
115 , m_mode(context.mode())
116 {
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 bool JSArrayBufferView::getOwnPropertySlot(
140 JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
141 {
142 JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object);
143 if (propertyName == exec->propertyNames().byteOffset) {
144 slot.setValue(thisObject, DontDelete | ReadOnly, jsNumber(thisObject->byteOffset()));
145 return true;
146 }
147
148 if (propertyName == exec->propertyNames().buffer) {
149 slot.setValue(
150 thisObject, DontDelete | ReadOnly, exec->vm().m_typedArrayController->toJS(
151 exec, thisObject->globalObject(), thisObject->buffer()));
152 return true;
153 }
154
155 return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
156 }
157
158 void JSArrayBufferView::put(
159 JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value,
160 PutPropertySlot& slot)
161 {
162 JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell);
163 if (propertyName == exec->propertyNames().byteLength
164 || propertyName == exec->propertyNames().byteOffset
165 || propertyName == exec->propertyNames().buffer) {
166 reject(exec, slot.isStrictMode(), "Attempting to write to read-only typed array property.");
167 return;
168 }
169
170 Base::put(thisObject, exec, propertyName, value, slot);
171 }
172
173 bool JSArrayBufferView::defineOwnProperty(
174 JSObject* object, ExecState* exec, PropertyName propertyName,
175 const PropertyDescriptor& descriptor, bool shouldThrow)
176 {
177 JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object);
178 if (propertyName == exec->propertyNames().byteLength
179 || propertyName == exec->propertyNames().byteOffset
180 || propertyName == exec->propertyNames().buffer)
181 return reject(exec, shouldThrow, "Attempting to define read-only typed array property.");
182
183 return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
184 }
185
186 bool JSArrayBufferView::deleteProperty(
187 JSCell* cell, ExecState* exec, PropertyName propertyName)
188 {
189 JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell);
190 if (propertyName == exec->propertyNames().byteLength
191 || propertyName == exec->propertyNames().byteOffset
192 || propertyName == exec->propertyNames().buffer)
193 return false;
194
195 return Base::deleteProperty(thisObject, exec, propertyName);
196 }
197
198 void JSArrayBufferView::getOwnNonIndexPropertyNames(
199 JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode)
200 {
201 JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object);
202
203 // length/byteOffset/byteLength are DontEnum, at least in Firefox.
204 if (mode == IncludeDontEnumProperties) {
205 array.add(exec->propertyNames().byteOffset);
206 array.add(exec->propertyNames().byteLength);
207 array.add(exec->propertyNames().buffer);
208 }
209
210 Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode);
211 }
212
213 void JSArrayBufferView::finalize(JSCell* cell)
214 {
215 JSArrayBufferView* thisObject = static_cast<JSArrayBufferView*>(cell);
216 ASSERT(thisObject->m_mode == OversizeTypedArray || thisObject->m_mode == WastefulTypedArray);
217 if (thisObject->m_mode == OversizeTypedArray)
218 fastFree(thisObject->m_vector);
219 }
220
221 } // namespace JSC
222