11cb0ef41Sopenharmony_ci#ifndef SRC_ALIASED_BUFFER_INL_H_
21cb0ef41Sopenharmony_ci#define SRC_ALIASED_BUFFER_INL_H_
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ci#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci#include "aliased_buffer.h"
71cb0ef41Sopenharmony_ci#include "util-inl.h"
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cinamespace node {
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_citypedef size_t AliasedBufferIndex;
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
141cb0ef41Sopenharmony_ciAliasedBufferBase<NativeT, V8T>::AliasedBufferBase(
151cb0ef41Sopenharmony_ci    v8::Isolate* isolate, const size_t count, const AliasedBufferIndex* index)
161cb0ef41Sopenharmony_ci    : isolate_(isolate), count_(count), byte_offset_(0), index_(index) {
171cb0ef41Sopenharmony_ci  CHECK_GT(count, 0);
181cb0ef41Sopenharmony_ci  if (index != nullptr) {
191cb0ef41Sopenharmony_ci    // Will be deserialized later.
201cb0ef41Sopenharmony_ci    return;
211cb0ef41Sopenharmony_ci  }
221cb0ef41Sopenharmony_ci  const v8::HandleScope handle_scope(isolate_);
231cb0ef41Sopenharmony_ci  const size_t size_in_bytes =
241cb0ef41Sopenharmony_ci      MultiplyWithOverflowCheck(sizeof(NativeT), count);
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci  // allocate v8 ArrayBuffer
271cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate_, size_in_bytes);
281cb0ef41Sopenharmony_ci  buffer_ = static_cast<NativeT*>(ab->Data());
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci  // allocate v8 TypedArray
311cb0ef41Sopenharmony_ci  v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, count);
321cb0ef41Sopenharmony_ci  js_array_ = v8::Global<V8T>(isolate, js_array);
331cb0ef41Sopenharmony_ci}
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
361cb0ef41Sopenharmony_ciAliasedBufferBase<NativeT, V8T>::AliasedBufferBase(
371cb0ef41Sopenharmony_ci    v8::Isolate* isolate,
381cb0ef41Sopenharmony_ci    const size_t byte_offset,
391cb0ef41Sopenharmony_ci    const size_t count,
401cb0ef41Sopenharmony_ci    const AliasedBufferBase<uint8_t, v8::Uint8Array>& backing_buffer,
411cb0ef41Sopenharmony_ci    const AliasedBufferIndex* index)
421cb0ef41Sopenharmony_ci    : isolate_(isolate),
431cb0ef41Sopenharmony_ci      count_(count),
441cb0ef41Sopenharmony_ci      byte_offset_(byte_offset),
451cb0ef41Sopenharmony_ci      index_(index) {
461cb0ef41Sopenharmony_ci  if (index != nullptr) {
471cb0ef41Sopenharmony_ci    // Will be deserialized later.
481cb0ef41Sopenharmony_ci    return;
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci  const v8::HandleScope handle_scope(isolate_);
511cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> ab = backing_buffer.GetArrayBuffer();
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  // validate that the byte_offset is aligned with sizeof(NativeT)
541cb0ef41Sopenharmony_ci  CHECK_EQ(byte_offset & (sizeof(NativeT) - 1), 0);
551cb0ef41Sopenharmony_ci  // validate this fits inside the backing buffer
561cb0ef41Sopenharmony_ci  CHECK_LE(MultiplyWithOverflowCheck(sizeof(NativeT), count),
571cb0ef41Sopenharmony_ci           ab->ByteLength() - byte_offset);
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  buffer_ = reinterpret_cast<NativeT*>(
601cb0ef41Sopenharmony_ci      const_cast<uint8_t*>(backing_buffer.GetNativeBuffer() + byte_offset));
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  v8::Local<V8T> js_array = V8T::New(ab, byte_offset, count);
631cb0ef41Sopenharmony_ci  js_array_ = v8::Global<V8T>(isolate, js_array);
641cb0ef41Sopenharmony_ci}
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
671cb0ef41Sopenharmony_ciAliasedBufferBase<NativeT, V8T>::AliasedBufferBase(
681cb0ef41Sopenharmony_ci    const AliasedBufferBase& that)
691cb0ef41Sopenharmony_ci    : isolate_(that.isolate_),
701cb0ef41Sopenharmony_ci      count_(that.count_),
711cb0ef41Sopenharmony_ci      byte_offset_(that.byte_offset_),
721cb0ef41Sopenharmony_ci      buffer_(that.buffer_) {
731cb0ef41Sopenharmony_ci  DCHECK_NULL(index_);
741cb0ef41Sopenharmony_ci  js_array_ = v8::Global<V8T>(that.isolate_, that.GetJSArray());
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
781cb0ef41Sopenharmony_ciAliasedBufferIndex AliasedBufferBase<NativeT, V8T>::Serialize(
791cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context, v8::SnapshotCreator* creator) {
801cb0ef41Sopenharmony_ci  DCHECK_NULL(index_);
811cb0ef41Sopenharmony_ci  return creator->AddData(context, GetJSArray());
821cb0ef41Sopenharmony_ci}
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
851cb0ef41Sopenharmony_ciinline void AliasedBufferBase<NativeT, V8T>::Deserialize(
861cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context) {
871cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(index_);
881cb0ef41Sopenharmony_ci  v8::Local<V8T> arr =
891cb0ef41Sopenharmony_ci      context->GetDataFromSnapshotOnce<V8T>(*index_).ToLocalChecked();
901cb0ef41Sopenharmony_ci  // These may not hold true for AliasedBuffers that have grown, so should
911cb0ef41Sopenharmony_ci  // be removed when we expand the snapshot support.
921cb0ef41Sopenharmony_ci  DCHECK_EQ(count_, arr->Length());
931cb0ef41Sopenharmony_ci  DCHECK_EQ(byte_offset_, arr->ByteOffset());
941cb0ef41Sopenharmony_ci  uint8_t* raw = static_cast<uint8_t*>(arr->Buffer()->Data());
951cb0ef41Sopenharmony_ci  buffer_ = reinterpret_cast<NativeT*>(raw + byte_offset_);
961cb0ef41Sopenharmony_ci  js_array_.Reset(isolate_, arr);
971cb0ef41Sopenharmony_ci  index_ = nullptr;
981cb0ef41Sopenharmony_ci}
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1011cb0ef41Sopenharmony_ciAliasedBufferBase<NativeT, V8T>& AliasedBufferBase<NativeT, V8T>::operator=(
1021cb0ef41Sopenharmony_ci    AliasedBufferBase<NativeT, V8T>&& that) noexcept {
1031cb0ef41Sopenharmony_ci  DCHECK_NULL(index_);
1041cb0ef41Sopenharmony_ci  this->~AliasedBufferBase();
1051cb0ef41Sopenharmony_ci  isolate_ = that.isolate_;
1061cb0ef41Sopenharmony_ci  count_ = that.count_;
1071cb0ef41Sopenharmony_ci  byte_offset_ = that.byte_offset_;
1081cb0ef41Sopenharmony_ci  buffer_ = that.buffer_;
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  js_array_.Reset(isolate_, that.js_array_.Get(isolate_));
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  that.buffer_ = nullptr;
1131cb0ef41Sopenharmony_ci  that.js_array_.Reset();
1141cb0ef41Sopenharmony_ci  return *this;
1151cb0ef41Sopenharmony_ci}
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1181cb0ef41Sopenharmony_civ8::Local<V8T> AliasedBufferBase<NativeT, V8T>::GetJSArray() const {
1191cb0ef41Sopenharmony_ci  DCHECK_NULL(index_);
1201cb0ef41Sopenharmony_ci  return js_array_.Get(isolate_);
1211cb0ef41Sopenharmony_ci}
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1241cb0ef41Sopenharmony_civoid AliasedBufferBase<NativeT, V8T>::Release() {
1251cb0ef41Sopenharmony_ci  DCHECK_NULL(index_);
1261cb0ef41Sopenharmony_ci  js_array_.Reset();
1271cb0ef41Sopenharmony_ci}
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1301cb0ef41Sopenharmony_civ8::Local<v8::ArrayBuffer> AliasedBufferBase<NativeT, V8T>::GetArrayBuffer()
1311cb0ef41Sopenharmony_ci    const {
1321cb0ef41Sopenharmony_ci  return GetJSArray()->Buffer();
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1361cb0ef41Sopenharmony_ciinline const NativeT* AliasedBufferBase<NativeT, V8T>::GetNativeBuffer() const {
1371cb0ef41Sopenharmony_ci  DCHECK_NULL(index_);
1381cb0ef41Sopenharmony_ci  return buffer_;
1391cb0ef41Sopenharmony_ci}
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1421cb0ef41Sopenharmony_ciinline const NativeT* AliasedBufferBase<NativeT, V8T>::operator*() const {
1431cb0ef41Sopenharmony_ci  return GetNativeBuffer();
1441cb0ef41Sopenharmony_ci}
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1471cb0ef41Sopenharmony_ciinline void AliasedBufferBase<NativeT, V8T>::SetValue(const size_t index,
1481cb0ef41Sopenharmony_ci                                                      NativeT value) {
1491cb0ef41Sopenharmony_ci  DCHECK_LT(index, count_);
1501cb0ef41Sopenharmony_ci  DCHECK_NULL(index_);
1511cb0ef41Sopenharmony_ci  buffer_[index] = value;
1521cb0ef41Sopenharmony_ci}
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1551cb0ef41Sopenharmony_ciinline const NativeT AliasedBufferBase<NativeT, V8T>::GetValue(
1561cb0ef41Sopenharmony_ci    const size_t index) const {
1571cb0ef41Sopenharmony_ci  DCHECK_NULL(index_);
1581cb0ef41Sopenharmony_ci  DCHECK_LT(index, count_);
1591cb0ef41Sopenharmony_ci  return buffer_[index];
1601cb0ef41Sopenharmony_ci}
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1631cb0ef41Sopenharmony_citypename AliasedBufferBase<NativeT, V8T>::Reference
1641cb0ef41Sopenharmony_ciAliasedBufferBase<NativeT, V8T>::operator[](size_t index) {
1651cb0ef41Sopenharmony_ci  DCHECK_NULL(index_);
1661cb0ef41Sopenharmony_ci  return Reference(this, index);
1671cb0ef41Sopenharmony_ci}
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1701cb0ef41Sopenharmony_ciNativeT AliasedBufferBase<NativeT, V8T>::operator[](size_t index) const {
1711cb0ef41Sopenharmony_ci  return GetValue(index);
1721cb0ef41Sopenharmony_ci}
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1751cb0ef41Sopenharmony_cisize_t AliasedBufferBase<NativeT, V8T>::Length() const {
1761cb0ef41Sopenharmony_ci  return count_;
1771cb0ef41Sopenharmony_ci}
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
1801cb0ef41Sopenharmony_civoid AliasedBufferBase<NativeT, V8T>::reserve(size_t new_capacity) {
1811cb0ef41Sopenharmony_ci  DCHECK_NULL(index_);
1821cb0ef41Sopenharmony_ci  DCHECK_GE(new_capacity, count_);
1831cb0ef41Sopenharmony_ci  DCHECK_EQ(byte_offset_, 0);
1841cb0ef41Sopenharmony_ci  const v8::HandleScope handle_scope(isolate_);
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci  const size_t old_size_in_bytes = sizeof(NativeT) * count_;
1871cb0ef41Sopenharmony_ci  const size_t new_size_in_bytes =
1881cb0ef41Sopenharmony_ci      MultiplyWithOverflowCheck(sizeof(NativeT), new_capacity);
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  // allocate v8 new ArrayBuffer
1911cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> ab =
1921cb0ef41Sopenharmony_ci      v8::ArrayBuffer::New(isolate_, new_size_in_bytes);
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  // allocate new native buffer
1951cb0ef41Sopenharmony_ci  NativeT* new_buffer = static_cast<NativeT*>(ab->Data());
1961cb0ef41Sopenharmony_ci  // copy old content
1971cb0ef41Sopenharmony_ci  memcpy(new_buffer, buffer_, old_size_in_bytes);
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci  // allocate v8 TypedArray
2001cb0ef41Sopenharmony_ci  v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, new_capacity);
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  // move over old v8 TypedArray
2031cb0ef41Sopenharmony_ci  js_array_ = std::move(v8::Global<V8T>(isolate_, js_array));
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  buffer_ = new_buffer;
2061cb0ef41Sopenharmony_ci  count_ = new_capacity;
2071cb0ef41Sopenharmony_ci}
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_citemplate <typename NativeT, typename V8T>
2101cb0ef41Sopenharmony_ciinline size_t AliasedBufferBase<NativeT, V8T>::SelfSize() const {
2111cb0ef41Sopenharmony_ci  return sizeof(*this);
2121cb0ef41Sopenharmony_ci}
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci#define VM(NativeT, V8T)                                                       \
2151cb0ef41Sopenharmony_ci  template <>                                                                  \
2161cb0ef41Sopenharmony_ci  inline const char* AliasedBufferBase<NativeT, v8::V8T>::MemoryInfoName()     \
2171cb0ef41Sopenharmony_ci      const {                                                                  \
2181cb0ef41Sopenharmony_ci    return "Aliased" #V8T;                                                     \
2191cb0ef41Sopenharmony_ci  }                                                                            \
2201cb0ef41Sopenharmony_ci  template <>                                                                  \
2211cb0ef41Sopenharmony_ci  inline void AliasedBufferBase<NativeT, v8::V8T>::MemoryInfo(                 \
2221cb0ef41Sopenharmony_ci      node::MemoryTracker* tracker) const {                                    \
2231cb0ef41Sopenharmony_ci    tracker->TrackField("js_array", js_array_);                                \
2241cb0ef41Sopenharmony_ci  }
2251cb0ef41Sopenharmony_ciALIASED_BUFFER_LIST(VM)
2261cb0ef41Sopenharmony_ci#undef VM
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci}  // namespace node
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci#endif  // SRC_ALIASED_BUFFER_INL_H_
233