d803a08cb475b3654b958611b9ce851ccf61b01b
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSGenericTypedArrayViewInlines.h
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 #ifndef JSGenericTypedArrayViewInlines_h
27 #define JSGenericTypedArrayViewInlines_h
28
29 #include "ArrayBufferView.h"
30 #include "DeferGC.h"
31 #include "Error.h"
32 #include "ExceptionHelpers.h"
33 #include "JSArrayBuffer.h"
34 #include "JSGenericTypedArrayView.h"
35 #include "Reject.h"
36 #include "TypedArrays.h"
37
38 namespace JSC {
39
40 template<typename Adaptor>
41 JSGenericTypedArrayView<Adaptor>::JSGenericTypedArrayView(
42     VM& vm, ConstructionContext& context)
43     : Base(vm, context)
44 {
45 }
46
47 template<typename Adaptor>
48 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
49     ExecState* exec, Structure* structure, unsigned length)
50 {
51     VM& vm = exec->vm();
52     auto scope = DECLARE_THROW_SCOPE(vm);
53     ConstructionContext context(vm, structure, length, sizeof(typename Adaptor::Type));
54     if (!context) {
55         throwOutOfMemoryError(exec, scope);
56         return nullptr;
57     }
58     JSGenericTypedArrayView* result =
59         new (NotNull, allocateCell<JSGenericTypedArrayView>(vm.heap))
60         JSGenericTypedArrayView(vm, context);
61     result->finishCreation(vm);
62     return result;
63 }
64
65 template<typename Adaptor>
66 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createUninitialized(
67     ExecState* exec, Structure* structure, unsigned length)
68 {
69     VM& vm = exec->vm();
70     auto scope = DECLARE_THROW_SCOPE(vm);
71     ConstructionContext context(
72         vm, structure, length, sizeof(typename Adaptor::Type),
73         ConstructionContext::DontInitialize);
74     if (!context) {
75         throwOutOfMemoryError(exec, scope);
76         return nullptr;
77     }
78     JSGenericTypedArrayView* result =
79         new (NotNull, allocateCell<JSGenericTypedArrayView>(vm.heap))
80         JSGenericTypedArrayView(vm, context);
81     result->finishCreation(vm);
82     return result;
83 }
84
85 template<typename Adaptor>
86 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
87     ExecState* exec, Structure* structure, PassRefPtr<ArrayBuffer> passedBuffer,
88     unsigned byteOffset, unsigned length)
89 {
90     VM& vm = exec->vm();
91     auto scope = DECLARE_THROW_SCOPE(vm);
92     RefPtr<ArrayBuffer> buffer = passedBuffer;
93     size_t size = sizeof(typename Adaptor::Type);
94     if (!ArrayBufferView::verifySubRangeLength(buffer, byteOffset, length, size)) {
95         throwException(exec, scope, createRangeError(exec, "Length out of range of buffer"));
96         return nullptr;
97     }
98     if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, size)) {
99         throwException(exec, scope, createRangeError(exec, "Byte offset is not aligned"));
100         return nullptr;
101     }
102     ConstructionContext context(vm, structure, buffer, byteOffset, length);
103     ASSERT(context);
104     JSGenericTypedArrayView* result =
105         new (NotNull, allocateCell<JSGenericTypedArrayView>(vm.heap))
106         JSGenericTypedArrayView(vm, context);
107     result->finishCreation(vm);
108     return result;
109 }
110
111 template<typename Adaptor>
112 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
113     VM& vm, Structure* structure, PassRefPtr<typename Adaptor::ViewType> impl)
114 {
115     RefPtr<ArrayBuffer> buffer = impl->buffer();
116     ConstructionContext context(vm, structure, buffer, impl->byteOffset(), impl->length());
117     ASSERT(context);
118     JSGenericTypedArrayView* result =
119         new (NotNull, allocateCell<JSGenericTypedArrayView>(vm.heap))
120         JSGenericTypedArrayView(vm, context);
121     result->finishCreation(vm);
122     return result;
123 }
124
125 template<typename Adaptor>
126 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
127     Structure* structure, JSGlobalObject* globalObject,
128     PassRefPtr<typename Adaptor::ViewType> impl)
129 {
130     return create(globalObject->vm(), structure, impl);
131 }
132
133 template<typename Adaptor>
134 bool JSGenericTypedArrayView<Adaptor>::validateRange(
135     ExecState* exec, unsigned offset, unsigned length)
136 {
137     VM& vm = exec->vm();
138     auto scope = DECLARE_THROW_SCOPE(vm);
139     if (canAccessRangeQuickly(offset, length))
140         return true;
141     
142     throwException(exec, scope, createRangeError(exec, "Range consisting of offset and length are out of bounds"));
143     return false;
144 }
145
146 template<typename Adaptor>
147 template<typename OtherAdaptor>
148 bool JSGenericTypedArrayView<Adaptor>::setWithSpecificType(
149     ExecState* exec, unsigned offset, JSGenericTypedArrayView<OtherAdaptor>* other,
150     unsigned otherOffset, unsigned length, CopyType type)
151 {
152     // Handle the hilarious case: the act of getting the length could have resulted
153     // in neutering. Well, no. That'll never happen because there cannot be
154     // side-effects on getting the length of a typed array. But predicting where there
155     // are, or aren't, side-effects is a fool's game so we resort to this cheap
156     // check. Worst case, if we're wrong, people start seeing less things get copied
157     // but we won't have a security vulnerability.
158     length = std::min(length, other->length());
159
160     RELEASE_ASSERT(other->canAccessRangeQuickly(otherOffset, length));
161     if (!validateRange(exec, offset, length))
162         return false;
163     
164     // This method doesn't support copying between the same array. Note that
165     // set() will only call this if the types differ, which implicitly guarantees
166     // that we can't be the same array. This is relevant because the way we detect
167     // non-overlapping is by checking if either (a) either array doesn't have a
168     // backing buffer or (b) the backing buffers are different, but that doesn't
169     // catch the case where it's the *same* array - fortunately though, this code
170     // path never needs to worry about that case.
171     ASSERT(static_cast<JSCell*>(this) != static_cast<JSCell*>(other));
172     
173     // 1) If the two arrays are non-overlapping, we can copy in any order we like
174     //    and we don't need an intermediate buffer. Arrays are definitely
175     //    non-overlapping if either one of them has no backing buffer (that means
176     //    that it *owns* its philosophical backing buffer) or if they have
177     //    different backing buffers.
178     // 2) If the two arrays overlap but have the same element size, we can do a
179     //    memmove-like copy where we flip-flop direction based on which vector
180     //    starts before the other:
181     //    A) If the destination vector is before the source vector, then a forward
182     //       copy is in order.
183     //    B) If the destination vector is after the source vector, then a backward
184     //       copy is in order.
185     // 3) If we have different element sizes and there is a chance of overlap then
186     //    we need an intermediate vector.
187     
188     // NB. Comparisons involving elementSize will be constant-folded by template
189     // specialization.
190
191     unsigned otherElementSize = sizeof(typename OtherAdaptor::Type);
192
193     // Handle cases (1) and (2A).
194     if (!hasArrayBuffer() || !other->hasArrayBuffer()
195         || existingBuffer() != other->existingBuffer()
196         || (elementSize == otherElementSize && vector() <= other->vector())
197         || type == CopyType::LeftToRight) {
198         for (unsigned i = 0; i < length; ++i) {
199             setIndexQuicklyToNativeValue(
200                 offset + i, OtherAdaptor::template convertTo<Adaptor>(
201                     other->getIndexQuicklyAsNativeValue(i + otherOffset)));
202         }
203         return true;
204     }
205
206     // Now we either have (2B) or (3) - so first we try to cover (2B).
207     if (elementSize == otherElementSize) {
208         for (unsigned i = length; i--;) {
209             setIndexQuicklyToNativeValue(
210                 offset + i, OtherAdaptor::template convertTo<Adaptor>(
211                     other->getIndexQuicklyAsNativeValue(i + otherOffset)));
212         }
213         return true;
214     }
215     
216     // Fail: we need an intermediate transfer buffer (i.e. case (3)).
217     Vector<typename Adaptor::Type, 32> transferBuffer(length);
218     for (unsigned i = length; i--;) {
219         transferBuffer[i] = OtherAdaptor::template convertTo<Adaptor>(
220             other->getIndexQuicklyAsNativeValue(i + otherOffset));
221     }
222     for (unsigned i = length; i--;)
223         setIndexQuicklyToNativeValue(offset + i, transferBuffer[i]);
224     
225     return true;
226 }
227
228 template<typename Adaptor>
229 bool JSGenericTypedArrayView<Adaptor>::set(
230     ExecState* exec, unsigned offset, JSObject* object, unsigned objectOffset, unsigned length, CopyType type)
231 {
232     const ClassInfo* ci = object->classInfo();
233     if (ci->typedArrayStorageType == Adaptor::typeValue) {
234         // The super fast case: we can just memcpy since we're the same type.
235         JSGenericTypedArrayView* other = jsCast<JSGenericTypedArrayView*>(object);
236         length = std::min(length, other->length());
237         
238         RELEASE_ASSERT(other->canAccessRangeQuickly(objectOffset, length));
239         if (!validateRange(exec, offset, length))
240             return false;
241
242         memmove(typedVector() + offset, other->typedVector() + objectOffset, length * elementSize);
243         return true;
244     }
245     
246     switch (ci->typedArrayStorageType) {
247     case TypeInt8:
248         return setWithSpecificType<Int8Adaptor>(
249             exec, offset, jsCast<JSInt8Array*>(object), objectOffset, length, type);
250     case TypeInt16:
251         return setWithSpecificType<Int16Adaptor>(
252             exec, offset, jsCast<JSInt16Array*>(object), objectOffset, length, type);
253     case TypeInt32:
254         return setWithSpecificType<Int32Adaptor>(
255             exec, offset, jsCast<JSInt32Array*>(object), objectOffset, length, type);
256     case TypeUint8:
257         return setWithSpecificType<Uint8Adaptor>(
258             exec, offset, jsCast<JSUint8Array*>(object), objectOffset, length, type);
259     case TypeUint8Clamped:
260         return setWithSpecificType<Uint8ClampedAdaptor>(
261             exec, offset, jsCast<JSUint8ClampedArray*>(object), objectOffset, length, type);
262     case TypeUint16:
263         return setWithSpecificType<Uint16Adaptor>(
264             exec, offset, jsCast<JSUint16Array*>(object), objectOffset, length, type);
265     case TypeUint32:
266         return setWithSpecificType<Uint32Adaptor>(
267             exec, offset, jsCast<JSUint32Array*>(object), objectOffset, length, type);
268     case TypeFloat32:
269         return setWithSpecificType<Float32Adaptor>(
270             exec, offset, jsCast<JSFloat32Array*>(object), objectOffset, length, type);
271     case TypeFloat64:
272         return setWithSpecificType<Float64Adaptor>(
273             exec, offset, jsCast<JSFloat64Array*>(object), objectOffset, length, type);
274     case NotTypedArray:
275     case TypeDataView: {
276         if (!validateRange(exec, offset, length))
277             return false;
278
279         // We could optimize this case. But right now, we don't.
280         for (unsigned i = 0; i < length; ++i) {
281             JSValue value = object->get(exec, i + objectOffset);
282             if (!setIndex(exec, offset + i, value))
283                 return false;
284         }
285         return true;
286     } }
287     
288     RELEASE_ASSERT_NOT_REACHED();
289     return false;
290 }
291
292 template<typename Adaptor>
293 ArrayBuffer* JSGenericTypedArrayView<Adaptor>::existingBuffer()
294 {
295     return existingBufferInButterfly();
296 }
297
298 template<typename Adaptor>
299 EncodedJSValue JSGenericTypedArrayView<Adaptor>::throwNeuteredTypedArrayTypeError(ExecState* exec, EncodedJSValue object, PropertyName)
300 {
301     VM& vm = exec->vm();
302     auto scope = DECLARE_THROW_SCOPE(vm);
303     ASSERT_UNUSED(object, jsCast<JSGenericTypedArrayView*>(JSValue::decode(object))->isNeutered());
304     return throwVMTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
305 }
306
307 template<typename Adaptor>
308 bool JSGenericTypedArrayView<Adaptor>::getOwnPropertySlot(
309     JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
310 {
311     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
312
313     if (Optional<uint32_t> index = parseIndex(propertyName)) {
314         if (thisObject->isNeutered()) {
315             slot.setCustom(thisObject, None, throwNeuteredTypedArrayTypeError);
316             return true;
317         }
318
319         if (thisObject->canGetIndexQuickly(index.value()))
320             slot.setValue(thisObject, DontDelete | ReadOnly, thisObject->getIndexQuickly(index.value()));
321         else
322             slot.setValue(thisObject, DontDelete | ReadOnly, jsUndefined());
323         return true;
324     }
325     
326     return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
327 }
328
329 template<typename Adaptor>
330 bool JSGenericTypedArrayView<Adaptor>::put(
331     JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value,
332     PutPropertySlot& slot)
333 {
334     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
335
336     // https://tc39.github.io/ecma262/#sec-integer-indexed-exotic-objects-set-p-v-receiver
337     // Ignore the receiver even if the receiver is altered to non base value.
338     // 9.4.5.5-2-b-i Return ? IntegerIndexedElementSet(O, numericIndex, V).
339     if (Optional<uint32_t> index = parseIndex(propertyName))
340         return putByIndex(thisObject, exec, index.value(), value, slot.isStrictMode());
341     
342     return Base::put(thisObject, exec, propertyName, value, slot);
343 }
344
345 template<typename Adaptor>
346 bool JSGenericTypedArrayView<Adaptor>::defineOwnProperty(
347     JSObject* object, ExecState* exec, PropertyName propertyName,
348     const PropertyDescriptor& descriptor, bool shouldThrow)
349 {
350     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
351
352     if (parseIndex(propertyName)) {
353         if (descriptor.isAccessorDescriptor())
354             return reject(exec, shouldThrow, "Attempting to store accessor indexed property on a typed array.");
355
356         if (descriptor.configurable())
357             return reject(exec, shouldThrow, "Attempting to configure non-configurable property.");
358
359         if (!descriptor.enumerable() || !descriptor.writable())
360             return reject(exec, shouldThrow, "Attempting to store non-enumerable or non-writable indexed property on a typed array.");
361
362         if (descriptor.value()) {
363             PutPropertySlot unused(JSValue(thisObject), shouldThrow);
364             return thisObject->put(thisObject, exec, propertyName, descriptor.value(), unused);
365         }
366         return true;
367     }
368     
369     return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
370 }
371
372 template<typename Adaptor>
373 bool JSGenericTypedArrayView<Adaptor>::deleteProperty(
374     JSCell* cell, ExecState* exec, PropertyName propertyName)
375 {
376     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
377
378     if (thisObject->isNeutered())
379         return reject(exec, true, typedArrayBufferHasBeenDetachedErrorMessage);
380
381     if (parseIndex(propertyName))
382         return false;
383     
384     return Base::deleteProperty(thisObject, exec, propertyName);
385 }
386
387 template<typename Adaptor>
388 bool JSGenericTypedArrayView<Adaptor>::getOwnPropertySlotByIndex(
389     JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot& slot)
390 {
391     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
392
393     if (thisObject->isNeutered()) {
394         slot.setCustom(thisObject, None, throwNeuteredTypedArrayTypeError);
395         return true;
396     }
397
398     if (propertyName > MAX_ARRAY_INDEX) {
399         return thisObject->methodTable()->getOwnPropertySlot(
400             thisObject, exec, Identifier::from(exec, propertyName), slot);
401     }
402     
403     if (!thisObject->canGetIndexQuickly(propertyName))
404         return false;
405     
406     slot.setValue(thisObject, None, thisObject->getIndexQuickly(propertyName));
407     return true;
408 }
409
410 template<typename Adaptor>
411 bool JSGenericTypedArrayView<Adaptor>::putByIndex(
412     JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
413 {
414     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
415
416     if (propertyName > MAX_ARRAY_INDEX) {
417         PutPropertySlot slot(JSValue(thisObject), shouldThrow);
418         return thisObject->methodTable()->put(thisObject, exec, Identifier::from(exec, propertyName), value, slot);
419     }
420     
421     return thisObject->setIndex(exec, propertyName, value);
422 }
423
424 template<typename Adaptor>
425 bool JSGenericTypedArrayView<Adaptor>::deletePropertyByIndex(
426     JSCell* cell, ExecState* exec, unsigned propertyName)
427 {
428     return cell->methodTable()->deleteProperty(cell, exec, Identifier::from(exec, propertyName));
429 }
430
431 template<typename Adaptor>
432 void JSGenericTypedArrayView<Adaptor>::getOwnPropertyNames(
433     JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode)
434 {
435     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
436
437     if (array.includeStringProperties()) {
438         for (unsigned i = 0; i < thisObject->m_length; ++i)
439             array.add(Identifier::from(exec, i));
440     }
441     
442     return Base::getOwnPropertyNames(object, exec, array, mode);
443 }
444
445 template<typename Adaptor>
446 size_t JSGenericTypedArrayView<Adaptor>::estimatedSize(JSCell* cell)
447 {
448     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
449
450     if (thisObject->m_mode == OversizeTypedArray)
451         return Base::estimatedSize(thisObject) + thisObject->byteSize();
452     if (thisObject->m_mode == FastTypedArray && thisObject->m_vector)
453         return Base::estimatedSize(thisObject) + thisObject->byteSize();
454
455     return Base::estimatedSize(thisObject);
456 }
457
458 template<typename Adaptor>
459 void JSGenericTypedArrayView<Adaptor>::visitChildren(JSCell* cell, SlotVisitor& visitor)
460 {
461     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
462     
463     switch (thisObject->m_mode) {
464     case FastTypedArray: {
465         if (thisObject->m_vector)
466             visitor.copyLater(thisObject, TypedArrayVectorCopyToken, thisObject->m_vector.get(), thisObject->byteSize());
467         break;
468     }
469         
470     case OversizeTypedArray: {
471         visitor.reportExtraMemoryVisited(thisObject->byteSize());
472         break;
473     }
474         
475     case WastefulTypedArray:
476         break;
477         
478     case DataViewMode:
479         RELEASE_ASSERT_NOT_REACHED();
480         break;
481     }
482     
483     Base::visitChildren(thisObject, visitor);
484 }
485
486 template<typename Adaptor>
487 void JSGenericTypedArrayView<Adaptor>::copyBackingStore(
488     JSCell* cell, CopyVisitor& visitor, CopyToken token)
489 {
490     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
491     
492     if (token == TypedArrayVectorCopyToken
493         && visitor.checkIfShouldCopy(thisObject->m_vector.get())) {
494         ASSERT(thisObject->m_vector);
495         void* oldVector = thisObject->vector();
496         void* newVector = visitor.allocateNewSpace(thisObject->byteSize());
497         memcpy(newVector, oldVector, thisObject->byteSize());
498         thisObject->m_vector.setWithoutBarrier(static_cast<char*>(newVector));
499         visitor.didCopy(oldVector, thisObject->byteSize());
500     }
501     
502     Base::copyBackingStore(thisObject, visitor, token);
503 }
504
505 template<typename Adaptor>
506 ArrayBuffer* JSGenericTypedArrayView<Adaptor>::slowDownAndWasteMemory(JSArrayBufferView* object)
507 {
508     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
509     
510     // We play this game because we want this to be callable even from places that
511     // don't have access to ExecState* or the VM, and we only allocate so little
512     // memory here that it's not necessary to trigger a GC - just accounting what
513     // we have done is good enough. The sort of bizarro exception to the "allocating
514     // little memory" is when we transfer a backing buffer into the C heap; this
515     // will temporarily get counted towards heap footprint (incorrectly, in the case
516     // of adopting an oversize typed array) but we don't GC here anyway. That's
517     // almost certainly fine. The worst case is if you created a ton of fast typed
518     // arrays, and did nothing but caused all of them to slow down and waste memory.
519     // In that case, your memory footprint will double before the GC realizes what's
520     // up. But if you do *anything* to trigger a GC watermark check, it will know
521     // that you *had* done those allocations and it will GC appropriately.
522     Heap* heap = Heap::heap(thisObject);
523     VM& vm = *heap->vm();
524     DeferGCForAWhile deferGC(*heap);
525     
526     ASSERT(!thisObject->hasIndexingHeader());
527
528     RELEASE_ASSERT(!thisObject->hasIndexingHeader());
529     thisObject->m_butterfly.set(vm, thisObject, Butterfly::createOrGrowArrayRight(
530         thisObject->butterfly(), vm, thisObject, thisObject->structure(),
531         thisObject->structure()->outOfLineCapacity(), false, 0, 0));
532
533     RefPtr<ArrayBuffer> buffer;
534     
535     switch (thisObject->m_mode) {
536     case FastTypedArray:
537         buffer = ArrayBuffer::create(thisObject->vector(), thisObject->byteLength());
538         break;
539         
540     case OversizeTypedArray:
541         // FIXME: consider doing something like "subtracting" from extra memory
542         // cost, since right now this case will cause the GC to think that we reallocated
543         // the whole buffer.
544         buffer = ArrayBuffer::createAdopted(thisObject->vector(), thisObject->byteLength());
545         break;
546         
547     default:
548         RELEASE_ASSERT_NOT_REACHED();
549         break;
550     }
551
552     thisObject->butterfly()->indexingHeader()->setArrayBuffer(buffer.get());
553     thisObject->m_vector.setWithoutBarrier(static_cast<char*>(buffer->data()));
554     thisObject->m_mode = WastefulTypedArray;
555     heap->addReference(thisObject, buffer.get());
556     
557     return buffer.get();
558 }
559
560 template<typename Adaptor>
561 PassRefPtr<ArrayBufferView>
562 JSGenericTypedArrayView<Adaptor>::getTypedArrayImpl(JSArrayBufferView* object)
563 {
564     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
565     return thisObject->typedImpl();
566 }
567
568 } // namespace JSC
569
570 #endif // JSGenericTypedArrayViewInlines_h
571