/ runtime / JSGenericTypedArrayViewInlines.h
JSGenericTypedArrayViewInlines.h
  1  /*
  2   * Copyright (C) 2013-2019 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  #pragma once
 27  
 28  #include "ArrayBufferView.h"
 29  #include "DeferGC.h"
 30  #include "Error.h"
 31  #include "ExceptionHelpers.h"
 32  #include "JSArrayBuffer.h"
 33  #include "JSCellInlines.h"
 34  #include "JSGenericTypedArrayView.h"
 35  #include "TypeError.h"
 36  #include "TypedArrays.h"
 37  #include <wtf/text/StringConcatenateNumbers.h>
 38  
 39  namespace JSC {
 40  
 41  template<typename Adaptor>
 42  JSGenericTypedArrayView<Adaptor>::JSGenericTypedArrayView(
 43      VM& vm, ConstructionContext& context)
 44      : Base(vm, context)
 45  {
 46  }
 47  
 48  template<typename Adaptor>
 49  JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
 50      JSGlobalObject* globalObject, Structure* structure, unsigned length)
 51  {
 52      VM& vm = globalObject->vm();
 53      auto scope = DECLARE_THROW_SCOPE(vm);
 54      ConstructionContext context(vm, structure, length, sizeof(typename Adaptor::Type));
 55      if (!context) {
 56          throwOutOfMemoryError(globalObject, scope);
 57          return nullptr;
 58      }
 59      JSGenericTypedArrayView* result =
 60          new (NotNull, allocateCell<JSGenericTypedArrayView>(vm.heap))
 61          JSGenericTypedArrayView(vm, context);
 62      result->finishCreation(vm);
 63      return result;
 64  }
 65  
 66  template<typename Adaptor>
 67  JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createWithFastVector(
 68      JSGlobalObject* globalObject, Structure* structure, unsigned length, void* vector)
 69  {
 70      VM& vm = globalObject->vm();
 71      ConstructionContext context(structure, length, vector);
 72      RELEASE_ASSERT(context);
 73      JSGenericTypedArrayView* result =
 74          new (NotNull, allocateCell<JSGenericTypedArrayView>(vm.heap))
 75          JSGenericTypedArrayView(vm, context);
 76      result->finishCreation(vm);
 77      return result;
 78  }
 79  
 80  template<typename Adaptor>
 81  JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createUninitialized(JSGlobalObject* globalObject, Structure* structure, unsigned length)
 82  {
 83      VM& vm = globalObject->vm();
 84      auto scope = DECLARE_THROW_SCOPE(vm);
 85      ConstructionContext context(
 86          vm, structure, length, sizeof(typename Adaptor::Type),
 87          ConstructionContext::DontInitialize);
 88      if (!context) {
 89          throwOutOfMemoryError(globalObject, scope);
 90          return nullptr;
 91      }
 92      JSGenericTypedArrayView* result =
 93          new (NotNull, allocateCell<JSGenericTypedArrayView>(vm.heap))
 94          JSGenericTypedArrayView(vm, context);
 95      result->finishCreation(vm);
 96      return result;
 97  }
 98  
 99  template<typename Adaptor>
100  JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
101      JSGlobalObject* globalObject, Structure* structure, RefPtr<ArrayBuffer>&& buffer,
102      unsigned byteOffset, unsigned length)
103  {
104      VM& vm = globalObject->vm();
105      auto scope = DECLARE_THROW_SCOPE(vm);
106      size_t size = sizeof(typename Adaptor::Type);
107      ASSERT(buffer);
108      if (!ArrayBufferView::verifySubRangeLength(*buffer, byteOffset, length, size)) {
109          throwException(globalObject, scope, createRangeError(globalObject, "Length out of range of buffer"));
110          return nullptr;
111      }
112      if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, size)) {
113          throwException(globalObject, scope, createRangeError(globalObject, "Byte offset is not aligned"));
114          return nullptr;
115      }
116      ConstructionContext context(vm, structure, WTFMove(buffer), byteOffset, 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      VM& vm, Structure* structure, RefPtr<typename Adaptor::ViewType>&& impl)
128  {
129      ConstructionContext context(vm, structure, impl->possiblySharedBuffer(), impl->byteOffset(), impl->length());
130      ASSERT(context);
131      JSGenericTypedArrayView* result =
132          new (NotNull, allocateCell<JSGenericTypedArrayView>(vm.heap))
133          JSGenericTypedArrayView(vm, context);
134      result->finishCreation(vm);
135      return result;
136  }
137  
138  template<typename Adaptor>
139  JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
140      Structure* structure, JSGlobalObject* globalObject,
141      RefPtr<typename Adaptor::ViewType>&& impl)
142  {
143      return create(globalObject->vm(), structure, WTFMove(impl));
144  }
145  
146  template<typename Adaptor>
147  bool JSGenericTypedArrayView<Adaptor>::validateRange(
148      JSGlobalObject* globalObject, unsigned offset, unsigned length)
149  {
150      VM& vm = globalObject->vm();
151      auto scope = DECLARE_THROW_SCOPE(vm);
152      if (canAccessRangeQuickly(offset, length))
153          return true;
154      
155      throwException(globalObject, scope, createRangeError(globalObject, "Range consisting of offset and length are out of bounds"));
156      return false;
157  }
158  
159  template<typename Adaptor>
160  template<typename OtherAdaptor>
161  bool JSGenericTypedArrayView<Adaptor>::setWithSpecificType(
162      JSGlobalObject* globalObject, unsigned offset, JSGenericTypedArrayView<OtherAdaptor>* other,
163      unsigned otherOffset, unsigned length, CopyType type)
164  {
165      // Handle the hilarious case: the act of getting the length could have resulted
166      // in detaching. Well, no. That'll never happen because there cannot be
167      // side-effects on getting the length of a typed array. But predicting where there
168      // are, or aren't, side-effects is a fool's game so we resort to this cheap
169      // check. Worst case, if we're wrong, people start seeing less things get copied
170      // but we won't have a security vulnerability.
171      length = std::min(length, other->length());
172  
173      RELEASE_ASSERT(other->canAccessRangeQuickly(otherOffset, length));
174      if (!validateRange(globalObject, offset, length))
175          return false;
176      
177      // This method doesn't support copying between the same array. Note that
178      // set() will only call this if the types differ, which implicitly guarantees
179      // that we can't be the same array. This is relevant because the way we detect
180      // non-overlapping is by checking if either (a) either array doesn't have a
181      // backing buffer or (b) the backing buffers are different, but that doesn't
182      // catch the case where it's the *same* array - fortunately though, this code
183      // path never needs to worry about that case.
184      ASSERT(static_cast<JSCell*>(this) != static_cast<JSCell*>(other));
185      
186      // 1) If the two arrays are non-overlapping, we can copy in any order we like
187      //    and we don't need an intermediate buffer. Arrays are definitely
188      //    non-overlapping if either one of them has no backing buffer (that means
189      //    that it *owns* its philosophical backing buffer) or if they have
190      //    different backing buffers.
191      // 2) If the two arrays overlap but have the same element size, we can do a
192      //    memmove-like copy where we flip-flop direction based on which vector
193      //    starts before the other:
194      //    A) If the destination vector is before the source vector, then a forward
195      //       copy is in order.
196      //    B) If the destination vector is after the source vector, then a backward
197      //       copy is in order.
198      // 3) If we have different element sizes and there is a chance of overlap then
199      //    we need an intermediate vector.
200      
201      // NB. Comparisons involving elementSize will be constant-folded by template
202      // specialization.
203  
204      unsigned otherElementSize = sizeof(typename OtherAdaptor::Type);
205  
206      // Handle cases (1) and (2A).
207      if (!hasArrayBuffer() || !other->hasArrayBuffer()
208          || existingBuffer() != other->existingBuffer()
209          || (elementSize == otherElementSize && vector() <= other->vector())
210          || type == CopyType::LeftToRight) {
211          for (unsigned i = 0; i < length; ++i) {
212              setIndexQuicklyToNativeValue(
213                  offset + i, OtherAdaptor::template convertTo<Adaptor>(
214                      other->getIndexQuicklyAsNativeValue(i + otherOffset)));
215          }
216          return true;
217      }
218  
219      // Now we either have (2B) or (3) - so first we try to cover (2B).
220      if (elementSize == otherElementSize) {
221          for (unsigned i = length; i--;) {
222              setIndexQuicklyToNativeValue(
223                  offset + i, OtherAdaptor::template convertTo<Adaptor>(
224                      other->getIndexQuicklyAsNativeValue(i + otherOffset)));
225          }
226          return true;
227      }
228      
229      // Fail: we need an intermediate transfer buffer (i.e. case (3)).
230      Vector<typename Adaptor::Type, 32> transferBuffer(length);
231      for (unsigned i = length; i--;) {
232          transferBuffer[i] = OtherAdaptor::template convertTo<Adaptor>(
233              other->getIndexQuicklyAsNativeValue(i + otherOffset));
234      }
235      for (unsigned i = length; i--;)
236          setIndexQuicklyToNativeValue(offset + i, transferBuffer[i]);
237      
238      return true;
239  }
240  
241  template<typename Adaptor>
242  bool JSGenericTypedArrayView<Adaptor>::set(
243      JSGlobalObject* globalObject, unsigned offset, JSObject* object, unsigned objectOffset, unsigned length, CopyType type)
244  {
245      VM& vm = globalObject->vm();
246      auto scope = DECLARE_THROW_SCOPE(vm);
247  
248      const ClassInfo* ci = object->classInfo(vm);
249      if (ci->typedArrayStorageType == Adaptor::typeValue) {
250          // The super fast case: we can just memcpy since we're the same type.
251          JSGenericTypedArrayView* other = jsCast<JSGenericTypedArrayView*>(object);
252          length = std::min(length, other->length());
253          
254          RELEASE_ASSERT(other->canAccessRangeQuickly(objectOffset, length));
255          bool success = validateRange(globalObject, offset, length);
256          EXCEPTION_ASSERT(!scope.exception() == success);
257          if (!success)
258              return false;
259  
260          memmove(typedVector() + offset, other->typedVector() + objectOffset, length * elementSize);
261          return true;
262      }
263      
264      switch (ci->typedArrayStorageType) {
265      case TypeInt8:
266          RELEASE_AND_RETURN(scope, setWithSpecificType<Int8Adaptor>(
267              globalObject, offset, jsCast<JSInt8Array*>(object), objectOffset, length, type));
268      case TypeInt16:
269          RELEASE_AND_RETURN(scope, setWithSpecificType<Int16Adaptor>(
270              globalObject, offset, jsCast<JSInt16Array*>(object), objectOffset, length, type));
271      case TypeInt32:
272          RELEASE_AND_RETURN(scope, setWithSpecificType<Int32Adaptor>(
273              globalObject, offset, jsCast<JSInt32Array*>(object), objectOffset, length, type));
274      case TypeUint8:
275          RELEASE_AND_RETURN(scope, setWithSpecificType<Uint8Adaptor>(
276              globalObject, offset, jsCast<JSUint8Array*>(object), objectOffset, length, type));
277      case TypeUint8Clamped:
278          RELEASE_AND_RETURN(scope, setWithSpecificType<Uint8ClampedAdaptor>(
279              globalObject, offset, jsCast<JSUint8ClampedArray*>(object), objectOffset, length, type));
280      case TypeUint16:
281          RELEASE_AND_RETURN(scope, setWithSpecificType<Uint16Adaptor>(
282              globalObject, offset, jsCast<JSUint16Array*>(object), objectOffset, length, type));
283      case TypeUint32:
284          RELEASE_AND_RETURN(scope, setWithSpecificType<Uint32Adaptor>(
285              globalObject, offset, jsCast<JSUint32Array*>(object), objectOffset, length, type));
286      case TypeFloat32:
287          RELEASE_AND_RETURN(scope, setWithSpecificType<Float32Adaptor>(
288              globalObject, offset, jsCast<JSFloat32Array*>(object), objectOffset, length, type));
289      case TypeFloat64:
290          RELEASE_AND_RETURN(scope, setWithSpecificType<Float64Adaptor>(
291              globalObject, offset, jsCast<JSFloat64Array*>(object), objectOffset, length, type));
292      case NotTypedArray:
293      case TypeDataView: {
294          bool success = validateRange(globalObject, offset, length);
295          EXCEPTION_ASSERT(!scope.exception() == success);
296          if (!success)
297              return false;
298  
299          // We could optimize this case. But right now, we don't.
300          for (unsigned i = 0; i < length; ++i) {
301              JSValue value = object->get(globalObject, i + objectOffset);
302              RETURN_IF_EXCEPTION(scope, false);
303              bool success = setIndex(globalObject, offset + i, value);
304              EXCEPTION_ASSERT(!scope.exception() || !success);
305              if (!success) {
306                  if (isDetached())
307                      throwTypeError(globalObject, scope, typedArrayBufferHasBeenDetachedErrorMessage);
308                  return false;
309              }
310          }
311          return true;
312      } }
313      
314      RELEASE_ASSERT_NOT_REACHED();
315      return false;
316  }
317  
318  template<typename Adaptor>
319  RefPtr<typename Adaptor::ViewType> JSGenericTypedArrayView<Adaptor>::possiblySharedTypedImpl()
320  {
321      return Adaptor::ViewType::tryCreate(possiblySharedBuffer(), byteOffset(), length());
322  }
323  
324  template<typename Adaptor>
325  RefPtr<typename Adaptor::ViewType> JSGenericTypedArrayView<Adaptor>::unsharedTypedImpl()
326  {
327      return Adaptor::ViewType::tryCreate(unsharedBuffer(), byteOffset(), length());
328  }
329  
330  template<typename Adaptor>
331  ArrayBuffer* JSGenericTypedArrayView<Adaptor>::existingBuffer()
332  {
333      return existingBufferInButterfly();
334  }
335  
336  template<typename Adaptor>
337  bool JSGenericTypedArrayView<Adaptor>::getOwnPropertySlot(
338      JSObject* object, JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot& slot)
339  {
340      JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
341  
342      if (Optional<uint32_t> index = parseIndex(propertyName)) {
343          static_assert(std::is_final_v<JSGenericTypedArrayView<Adaptor>>, "getOwnPropertySlotByIndex must not be overridden");
344          return getOwnPropertySlotByIndex(thisObject, globalObject, index.value(), slot);
345      }
346  
347      if (isCanonicalNumericIndexString(propertyName))
348          return false;
349  
350      return Base::getOwnPropertySlot(thisObject, globalObject, propertyName, slot);
351  }
352  
353  template<typename Adaptor>
354  bool JSGenericTypedArrayView<Adaptor>::put(
355      JSCell* cell, JSGlobalObject* globalObject, PropertyName propertyName, JSValue value,
356      PutPropertySlot& slot)
357  {
358      JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
359  
360      if (Optional<uint32_t> index = parseIndex(propertyName)) {
361          static_assert(std::is_final_v<JSGenericTypedArrayView<Adaptor>>, "putByIndex must not be overridden");
362          return putByIndex(thisObject, globalObject, index.value(), value, slot.isStrictMode());
363      }
364  
365      if (isCanonicalNumericIndexString(propertyName)) {
366          // Cases like '-0', '1.1', etc. are still obliged to give the RHS a chance to throw.
367          toNativeFromValue<Adaptor>(globalObject, value);
368          return true;
369      }
370  
371      return Base::put(thisObject, globalObject, propertyName, value, slot);
372  }
373  
374  template<typename Adaptor>
375  bool JSGenericTypedArrayView<Adaptor>::defineOwnProperty(
376      JSObject* object, JSGlobalObject* globalObject, PropertyName propertyName,
377      const PropertyDescriptor& descriptor, bool shouldThrow)
378  {
379      VM& vm = globalObject->vm();
380      auto scope = DECLARE_THROW_SCOPE(vm);
381      JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
382  
383      if (Optional<uint32_t> index = parseIndex(propertyName)) {
384          auto throwTypeErrorIfNeeded = [&] (const char* errorMessage) -> bool {
385              if (shouldThrow)
386                  throwTypeError(globalObject, scope, makeString(errorMessage, *index));
387              return false;
388          };
389  
390          if (index.value() >= thisObject->m_length)
391              return false;
392  
393          if (descriptor.isAccessorDescriptor())
394              return throwTypeErrorIfNeeded("Attempting to store accessor property on a typed array at index: ");
395  
396          if (descriptor.configurablePresent() && !descriptor.configurable())
397              return throwTypeErrorIfNeeded("Attempting to store non-configurable property on a typed array at index: ");
398  
399          if (descriptor.enumerablePresent() && !descriptor.enumerable())
400              return throwTypeErrorIfNeeded("Attempting to store non-enumerable property on a typed array at index: ");
401  
402          if (descriptor.writablePresent() && !descriptor.writable())
403              return throwTypeErrorIfNeeded("Attempting to store non-writable property on a typed array at index: ");
404  
405          if (descriptor.value())
406              RELEASE_AND_RETURN(scope, thisObject->setIndex(globalObject, index.value(), descriptor.value()));
407  
408          return true;
409      }
410  
411      if (isCanonicalNumericIndexString(propertyName))
412          return false;
413  
414      RELEASE_AND_RETURN(scope, Base::defineOwnProperty(thisObject, globalObject, propertyName, descriptor, shouldThrow));
415  }
416  
417  template<typename Adaptor>
418  bool JSGenericTypedArrayView<Adaptor>::deleteProperty(
419      JSCell* cell, JSGlobalObject* globalObject, PropertyName propertyName, DeletePropertySlot& slot)
420  {
421      JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
422  
423      if (Optional<uint32_t> index = parseIndex(propertyName)) {
424          static_assert(std::is_final_v<JSGenericTypedArrayView<Adaptor>>, "deletePropertyByIndex must not be overridden");
425          return deletePropertyByIndex(thisObject, globalObject, index.value());
426      }
427  
428      if (isCanonicalNumericIndexString(propertyName))
429          return true;
430  
431      return Base::deleteProperty(thisObject, globalObject, propertyName, slot);
432  }
433  
434  template<typename Adaptor>
435  bool JSGenericTypedArrayView<Adaptor>::getOwnPropertySlotByIndex(
436      JSObject* object, JSGlobalObject*, unsigned propertyName, PropertySlot& slot)
437  {
438      JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
439  
440      if (thisObject->isDetached() || !thisObject->canGetIndexQuickly(propertyName))
441          return false;
442  
443      slot.setValue(thisObject, static_cast<unsigned>(PropertyAttribute::None), thisObject->getIndexQuickly(propertyName));
444      return true;
445  }
446  
447  template<typename Adaptor>
448  bool JSGenericTypedArrayView<Adaptor>::putByIndex(
449      JSCell* cell, JSGlobalObject* globalObject, unsigned propertyName, JSValue value, bool)
450  {
451      JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
452      thisObject->setIndex(globalObject, propertyName, value);
453      return true;
454  }
455  
456  template<typename Adaptor>
457  bool JSGenericTypedArrayView<Adaptor>::deletePropertyByIndex(
458      JSCell* cell, JSGlobalObject*, unsigned propertyName)
459  {
460      // Integer-indexed elements can't be deleted, so we must return false when the index is valid.
461      JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
462      return thisObject->isDetached() || propertyName >= thisObject->m_length;
463  }
464  
465  template<typename Adaptor>
466  void JSGenericTypedArrayView<Adaptor>::getOwnPropertyNames(
467      JSObject* object, JSGlobalObject* globalObject, PropertyNameArray& array, DontEnumPropertiesMode mode)
468  {
469      VM& vm = globalObject->vm();
470      JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
471  
472      if (array.includeStringProperties()) {
473          for (unsigned i = 0; i < thisObject->m_length; ++i)
474              array.add(Identifier::from(vm, i));
475      }
476      
477      thisObject->getOwnNonIndexPropertyNames(globalObject, array, mode);
478  }
479  
480  template<typename Adaptor>
481  size_t JSGenericTypedArrayView<Adaptor>::estimatedSize(JSCell* cell, VM& vm)
482  {
483      JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
484  
485      if (thisObject->m_mode == OversizeTypedArray)
486          return Base::estimatedSize(thisObject, vm) + thisObject->byteSize();
487      if (thisObject->m_mode == FastTypedArray && thisObject->hasVector())
488          return Base::estimatedSize(thisObject, vm) + thisObject->byteSize();
489  
490      return Base::estimatedSize(thisObject, vm);
491  }
492  
493  template<typename Adaptor>
494  void JSGenericTypedArrayView<Adaptor>::visitChildren(JSCell* cell, SlotVisitor& visitor)
495  {
496      JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
497      ASSERT_GC_OBJECT_INHERITS(thisObject, info());
498      Base::visitChildren(thisObject, visitor);
499  
500      TypedArrayMode mode;
501      void* vector;
502      size_t byteSize;
503      
504      {
505          auto locker = holdLock(thisObject->cellLock());
506          mode = thisObject->m_mode;
507          vector = thisObject->vector();
508          byteSize = thisObject->byteSize();
509      }
510      
511      switch (mode) {
512      case FastTypedArray: {
513          if (vector)
514              visitor.markAuxiliary(vector);
515          break;
516      }
517          
518      case OversizeTypedArray: {
519          visitor.reportExtraMemoryVisited(byteSize);
520          break;
521      }
522          
523      case WastefulTypedArray:
524          break;
525          
526      case DataViewMode:
527          RELEASE_ASSERT_NOT_REACHED();
528          break;
529      }
530  }
531  
532  } // namespace JSC