]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/JSArrayBufferView.cpp
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / runtime / JSArrayBufferView.cpp
CommitLineData
81345200
A
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
33namespace JSC {
34
35const ClassInfo JSArrayBufferView::s_info = {
36 "ArrayBufferView", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSArrayBufferView)
37};
38
39JSArrayBufferView::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
87JSArrayBufferView::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
100JSArrayBufferView::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
111JSArrayBufferView::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
119void 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
139bool 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
158void 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
173bool 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
186bool 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
198void 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
213void 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