11cb0ef41Sopenharmony_ci#ifndef SRC_ALIASED_BUFFER_H_ 21cb0ef41Sopenharmony_ci#define SRC_ALIASED_BUFFER_H_ 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ci#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ci#include <cinttypes> 71cb0ef41Sopenharmony_ci#include "memory_tracker.h" 81cb0ef41Sopenharmony_ci#include "v8.h" 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_cinamespace node { 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_citypedef size_t AliasedBufferIndex; 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ci/** 151cb0ef41Sopenharmony_ci * Do not use this class directly when creating instances of it - use the 161cb0ef41Sopenharmony_ci * Aliased*Array defined at the end of this file instead. 171cb0ef41Sopenharmony_ci * 181cb0ef41Sopenharmony_ci * This class encapsulates the technique of having a native buffer mapped to 191cb0ef41Sopenharmony_ci * a JS object. Writes to the native buffer can happen efficiently without 201cb0ef41Sopenharmony_ci * going through JS, and the data is then available to user's via the exposed 211cb0ef41Sopenharmony_ci * JS object. 221cb0ef41Sopenharmony_ci * 231cb0ef41Sopenharmony_ci * While this technique is computationally efficient, it is effectively a 241cb0ef41Sopenharmony_ci * write to JS program state w/out going through the standard 251cb0ef41Sopenharmony_ci * (monitored) API. Thus any VM capabilities to detect the modification are 261cb0ef41Sopenharmony_ci * circumvented. 271cb0ef41Sopenharmony_ci * 281cb0ef41Sopenharmony_ci * The encapsulation herein provides a placeholder where such writes can be 291cb0ef41Sopenharmony_ci * observed. Any notification APIs will be left as a future exercise. 301cb0ef41Sopenharmony_ci */ 311cb0ef41Sopenharmony_citemplate <class NativeT, class V8T> 321cb0ef41Sopenharmony_ciclass AliasedBufferBase : public MemoryRetainer { 331cb0ef41Sopenharmony_ci public: 341cb0ef41Sopenharmony_ci static_assert(std::is_scalar<NativeT>::value); 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci AliasedBufferBase(v8::Isolate* isolate, 371cb0ef41Sopenharmony_ci const size_t count, 381cb0ef41Sopenharmony_ci const AliasedBufferIndex* index = nullptr); 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci /** 411cb0ef41Sopenharmony_ci * Create an AliasedBufferBase over a sub-region of another aliased buffer. 421cb0ef41Sopenharmony_ci * The two will share a v8::ArrayBuffer instance & 431cb0ef41Sopenharmony_ci * a native buffer, but will each read/write to different sections of the 441cb0ef41Sopenharmony_ci * native buffer. 451cb0ef41Sopenharmony_ci * 461cb0ef41Sopenharmony_ci * Note that byte_offset must by aligned by sizeof(NativeT). 471cb0ef41Sopenharmony_ci */ 481cb0ef41Sopenharmony_ci // TODO(refack): refactor into a non-owning `AliasedBufferBaseView` 491cb0ef41Sopenharmony_ci AliasedBufferBase( 501cb0ef41Sopenharmony_ci v8::Isolate* isolate, 511cb0ef41Sopenharmony_ci const size_t byte_offset, 521cb0ef41Sopenharmony_ci const size_t count, 531cb0ef41Sopenharmony_ci const AliasedBufferBase<uint8_t, v8::Uint8Array>& backing_buffer, 541cb0ef41Sopenharmony_ci const AliasedBufferIndex* index = nullptr); 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci AliasedBufferBase(const AliasedBufferBase& that); 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci AliasedBufferIndex Serialize(v8::Local<v8::Context> context, 591cb0ef41Sopenharmony_ci v8::SnapshotCreator* creator); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci inline void Deserialize(v8::Local<v8::Context> context); 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci AliasedBufferBase& operator=(AliasedBufferBase&& that) noexcept; 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci /** 661cb0ef41Sopenharmony_ci * Helper class that is returned from operator[] to support assignment into 671cb0ef41Sopenharmony_ci * a specified location. 681cb0ef41Sopenharmony_ci */ 691cb0ef41Sopenharmony_ci class Reference { 701cb0ef41Sopenharmony_ci public: 711cb0ef41Sopenharmony_ci Reference(AliasedBufferBase<NativeT, V8T>* aliased_buffer, size_t index) 721cb0ef41Sopenharmony_ci : aliased_buffer_(aliased_buffer), index_(index) {} 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci Reference(const Reference& that) 751cb0ef41Sopenharmony_ci : aliased_buffer_(that.aliased_buffer_), 761cb0ef41Sopenharmony_ci index_(that.index_) { 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci inline Reference& operator=(const NativeT& val) { 801cb0ef41Sopenharmony_ci aliased_buffer_->SetValue(index_, val); 811cb0ef41Sopenharmony_ci return *this; 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci inline Reference& operator=(const Reference& val) { 851cb0ef41Sopenharmony_ci return *this = static_cast<NativeT>(val); 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci operator NativeT() const { 891cb0ef41Sopenharmony_ci return aliased_buffer_->GetValue(index_); 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci inline Reference& operator+=(const NativeT& val) { 931cb0ef41Sopenharmony_ci const NativeT current = aliased_buffer_->GetValue(index_); 941cb0ef41Sopenharmony_ci aliased_buffer_->SetValue(index_, current + val); 951cb0ef41Sopenharmony_ci return *this; 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci inline Reference& operator+=(const Reference& val) { 991cb0ef41Sopenharmony_ci return this->operator+=(static_cast<NativeT>(val)); 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci inline Reference& operator-=(const NativeT& val) { 1031cb0ef41Sopenharmony_ci const NativeT current = aliased_buffer_->GetValue(index_); 1041cb0ef41Sopenharmony_ci aliased_buffer_->SetValue(index_, current - val); 1051cb0ef41Sopenharmony_ci return *this; 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci private: 1091cb0ef41Sopenharmony_ci AliasedBufferBase<NativeT, V8T>* aliased_buffer_; 1101cb0ef41Sopenharmony_ci size_t index_; 1111cb0ef41Sopenharmony_ci }; 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci /** 1141cb0ef41Sopenharmony_ci * Get the underlying v8 TypedArray overlayed on top of the native buffer 1151cb0ef41Sopenharmony_ci */ 1161cb0ef41Sopenharmony_ci v8::Local<V8T> GetJSArray() const; 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci void Release(); 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci /** 1211cb0ef41Sopenharmony_ci * Get the underlying v8::ArrayBuffer underlying the TypedArray and 1221cb0ef41Sopenharmony_ci * overlaying the native buffer 1231cb0ef41Sopenharmony_ci */ 1241cb0ef41Sopenharmony_ci v8::Local<v8::ArrayBuffer> GetArrayBuffer() const; 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci /** 1271cb0ef41Sopenharmony_ci * Get the underlying native buffer. Note that all reads/writes should occur 1281cb0ef41Sopenharmony_ci * through the GetValue/SetValue/operator[] methods 1291cb0ef41Sopenharmony_ci */ 1301cb0ef41Sopenharmony_ci inline const NativeT* GetNativeBuffer() const; 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci /** 1331cb0ef41Sopenharmony_ci * Synonym for GetBuffer() 1341cb0ef41Sopenharmony_ci */ 1351cb0ef41Sopenharmony_ci inline const NativeT* operator*() const; 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci /** 1381cb0ef41Sopenharmony_ci * Set position index to given value. 1391cb0ef41Sopenharmony_ci */ 1401cb0ef41Sopenharmony_ci inline void SetValue(const size_t index, NativeT value); 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci /** 1431cb0ef41Sopenharmony_ci * Get value at position index 1441cb0ef41Sopenharmony_ci */ 1451cb0ef41Sopenharmony_ci inline const NativeT GetValue(const size_t index) const; 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci /** 1481cb0ef41Sopenharmony_ci * Effectively, a synonym for GetValue/SetValue 1491cb0ef41Sopenharmony_ci */ 1501cb0ef41Sopenharmony_ci Reference operator[](size_t index); 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci NativeT operator[](size_t index) const; 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci size_t Length() const; 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci // Should only be used to extend the array. 1571cb0ef41Sopenharmony_ci // Should only be used on an owning array, not one created as a sub array of 1581cb0ef41Sopenharmony_ci // an owning `AliasedBufferBase`. 1591cb0ef41Sopenharmony_ci void reserve(size_t new_capacity); 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci inline size_t SelfSize() const override; 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci inline const char* MemoryInfoName() const override; 1641cb0ef41Sopenharmony_ci inline void MemoryInfo(node::MemoryTracker* tracker) const override; 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci private: 1671cb0ef41Sopenharmony_ci v8::Isolate* isolate_ = nullptr; 1681cb0ef41Sopenharmony_ci size_t count_ = 0; 1691cb0ef41Sopenharmony_ci size_t byte_offset_ = 0; 1701cb0ef41Sopenharmony_ci NativeT* buffer_ = nullptr; 1711cb0ef41Sopenharmony_ci v8::Global<V8T> js_array_; 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci // Deserialize data 1741cb0ef41Sopenharmony_ci const AliasedBufferIndex* index_ = nullptr; 1751cb0ef41Sopenharmony_ci}; 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci#define ALIASED_BUFFER_LIST(V) \ 1781cb0ef41Sopenharmony_ci V(int8_t, Int8Array) \ 1791cb0ef41Sopenharmony_ci V(uint8_t, Uint8Array) \ 1801cb0ef41Sopenharmony_ci V(int16_t, Int16Array) \ 1811cb0ef41Sopenharmony_ci V(uint16_t, Uint16Array) \ 1821cb0ef41Sopenharmony_ci V(int32_t, Int32Array) \ 1831cb0ef41Sopenharmony_ci V(uint32_t, Uint32Array) \ 1841cb0ef41Sopenharmony_ci V(float, Float32Array) \ 1851cb0ef41Sopenharmony_ci V(double, Float64Array) \ 1861cb0ef41Sopenharmony_ci V(int64_t, BigInt64Array) 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci#define V(NativeT, V8T) \ 1891cb0ef41Sopenharmony_ci typedef AliasedBufferBase<NativeT, v8::V8T> Aliased##V8T; 1901cb0ef41Sopenharmony_ciALIASED_BUFFER_LIST(V) 1911cb0ef41Sopenharmony_ci#undef V 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci} // namespace node 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci#endif // SRC_ALIASED_BUFFER_H_ 198