/usr/include/nodejs/src/aliased_buffer.h is in nodejs-dev 8.10.0~dfsg-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | #ifndef SRC_ALIASED_BUFFER_H_
#define SRC_ALIASED_BUFFER_H_
#include "v8.h"
#include "util-inl.h"
namespace node {
/**
* This class encapsulates the technique of having a native buffer mapped to
* a JS object. Writes to the native buffer can happen efficiently without
* going through JS, and the data is then available to user's via the exposed
* JS object.
*
* While this technique is computationaly efficient, it is effectively a
* write to JS program state w/out going through the standard
* (monitored) API. Thus any VM capabilities to detect the modification are
* circumvented.
*
* The encapsulation herein provides a placeholder where such writes can be
* observed. Any notification APIs will be left as a future exercise.
*/
template <class NativeT, class V8T>
class AliasedBuffer {
public:
AliasedBuffer(v8::Isolate* isolate, const size_t count)
: isolate_(isolate),
count_(count),
byte_offset_(0),
free_buffer_(true) {
CHECK_GT(count, 0);
const v8::HandleScope handle_scope(isolate_);
const size_t sizeInBytes = sizeof(NativeT) * count;
// allocate native buffer
buffer_ = Calloc<NativeT>(count);
// allocate v8 ArrayBuffer
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
isolate_, buffer_, sizeInBytes);
// allocate v8 TypedArray
v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, count);
js_array_ = v8::Global<V8T>(isolate, js_array);
}
/**
* Create an AliasedBuffer over a sub-region of another aliased buffer.
* The two will share a v8::ArrayBuffer instance &
* a native buffer, but will each read/write to different sections of the
* native buffer.
*
* Note that byte_offset must by aligned by sizeof(NativeT).
*/
AliasedBuffer(v8::Isolate* isolate,
const size_t byte_offset,
const size_t count,
const AliasedBuffer<uint8_t,
v8::Uint8Array>& backing_buffer)
: isolate_(isolate),
count_(count),
byte_offset_(byte_offset),
free_buffer_(false) {
const v8::HandleScope handle_scope(isolate_);
v8::Local<v8::ArrayBuffer> ab = backing_buffer.GetArrayBuffer();
// validate that the byte_offset is aligned with sizeof(NativeT)
CHECK_EQ(byte_offset & (sizeof(NativeT) - 1), 0);
// validate this fits inside the backing buffer
CHECK_LE(sizeof(NativeT) * count, ab->ByteLength() - byte_offset);
buffer_ = reinterpret_cast<NativeT*>(
const_cast<uint8_t*>(backing_buffer.GetNativeBuffer() + byte_offset));
v8::Local<V8T> js_array = V8T::New(ab, byte_offset, count);
js_array_ = v8::Global<V8T>(isolate, js_array);
}
AliasedBuffer(const AliasedBuffer& that)
: isolate_(that.isolate_),
count_(that.count_),
byte_offset_(that.byte_offset_),
buffer_(that.buffer_),
free_buffer_(false) {
js_array_ = v8::Global<V8T>(that.isolate_, that.GetJSArray());
}
~AliasedBuffer() {
if (free_buffer_ && buffer_ != nullptr) {
free(buffer_);
}
js_array_.Reset();
}
AliasedBuffer& operator=(AliasedBuffer&& that) {
this->~AliasedBuffer();
isolate_ = that.isolate_;
count_ = that.count_;
byte_offset_ = that.byte_offset_;
buffer_ = that.buffer_;
free_buffer_ = that.free_buffer_;
js_array_.Reset(isolate_, that.js_array_.Get(isolate_));
that.buffer_ = nullptr;
that.js_array_.Reset();
return *this;
}
/**
* Helper class that is returned from operator[] to support assignment into
* a specified location.
*/
class Reference {
public:
Reference(AliasedBuffer<NativeT, V8T>* aliased_buffer, size_t index)
: aliased_buffer_(aliased_buffer),
index_(index) {
}
Reference(const Reference& that)
: aliased_buffer_(that.aliased_buffer_),
index_(that.index_) {
}
template <typename T>
inline Reference& operator=(const T& val) {
aliased_buffer_->SetValue(index_, val);
return *this;
}
// This is not caught by the template operator= above.
inline Reference& operator=(const Reference& val) {
return *this = static_cast<NativeT>(val);
}
operator NativeT() const {
return aliased_buffer_->GetValue(index_);
}
private:
AliasedBuffer<NativeT, V8T>* aliased_buffer_;
size_t index_;
};
/**
* Get the underlying v8 TypedArray overlayed on top of the native buffer
*/
v8::Local<V8T> GetJSArray() const {
return js_array_.Get(isolate_);
}
/**
* Get the underlying v8::ArrayBuffer underlying the TypedArray and
* overlaying the native buffer
*/
v8::Local<v8::ArrayBuffer> GetArrayBuffer() const {
return GetJSArray()->Buffer();
}
/**
* Get the underlying native buffer. Note that all reads/writes should occur
* through the GetValue/SetValue/operator[] methods
*/
inline const NativeT* GetNativeBuffer() const {
return buffer_;
}
/**
* Synonym for GetBuffer()
*/
inline const NativeT* operator * () const {
return GetNativeBuffer();
}
/**
* Set position index to given value.
*/
inline void SetValue(const size_t index, NativeT value) {
#if defined(DEBUG) && DEBUG
CHECK_LT(index, count_);
#endif
buffer_[index] = value;
}
/**
* Get value at position index
*/
inline const NativeT GetValue(const size_t index) const {
#if defined(DEBUG) && DEBUG
CHECK_LT(index, count_);
#endif
return buffer_[index];
}
/**
* Effectively, a synonym for GetValue/SetValue
*/
Reference operator[](size_t index) {
return Reference(this, index);
}
NativeT operator[](size_t index) const {
return GetValue(index);
}
size_t Length() const {
return count_;
}
private:
v8::Isolate* isolate_;
size_t count_;
size_t byte_offset_;
NativeT* buffer_;
v8::Global<V8T> js_array_;
bool free_buffer_;
};
} // namespace node
#endif // SRC_ALIASED_BUFFER_H_
|