GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/aliased_buffer.h Lines: 51 51 100.0 %
Date: 2017-10-21 Branches: 11 24 45.8 %

Line Branch Exec Source
1
2
#ifndef SRC_ALIASED_BUFFER_H_
3
#define SRC_ALIASED_BUFFER_H_
4
5
#include "v8.h"
6
#include "util.h"
7
#include "util-inl.h"
8
9
namespace node {
10
11
/**
12
 * This class encapsulates the technique of having a native buffer mapped to
13
 * a JS object. Writes to the native buffer can happen efficiently without
14
 * going through JS, and the data is then available to user's via the exposed
15
 * JS object.
16
 *
17
 * While this technique is computationaly efficient, it is effectively a
18
 * write to JS program state w/out going through the standard
19
 * (monitored) API. Thus any VM capabilities to detect the modification are
20
 * circumvented.
21
 *
22
 * The encapsulation herein provides a placeholder where such writes can be
23
 * observed. Any notification APIs will be left as a future exercise.
24
 */
25
template <class NativeT, class V8T>
26
class AliasedBuffer {
27
 public:
28
6543
  AliasedBuffer(v8::Isolate* isolate, const size_t count)
29
      : isolate_(isolate),
30
        count_(count),
31
        byte_offset_(0),
32
13086
        free_buffer_(true) {
33

6543
    CHECK_GT(count, 0);
34
6543
    const v8::HandleScope handle_scope(isolate_);
35
36
6543
    const size_t sizeInBytes = sizeof(NativeT) * count;
37
38
    // allocate native buffer
39
6543
    buffer_ = Calloc<NativeT>(count);
40
41
    // allocate v8 ArrayBuffer
42
    v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
43
6543
        isolate_, buffer_, sizeInBytes);
44
45
    // allocate v8 TypedArray
46
6543
    v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, count);
47
13086
    js_array_ = v8::Global<V8T>(isolate, js_array);
48
6543
  }
49
50
  /**
51
   * Create an AliasedBuffer over a sub-region of another aliased buffer.
52
   * The two will share a v8::ArrayBuffer instance &
53
   * a native buffer, but will each read/write to different sections of the
54
   * native buffer.
55
   *
56
   *  Note that byte_offset must by aligned by sizeof(NativeT).
57
   */
58
695
  AliasedBuffer(v8::Isolate* isolate,
59
                const size_t byte_offset,
60
                const size_t count,
61
                const AliasedBuffer<uint8_t,
62
                v8::Uint8Array>& backing_buffer)
63
      : isolate_(isolate),
64
        count_(count),
65
        byte_offset_(byte_offset),
66
1390
        free_buffer_(false) {
67
695
    const v8::HandleScope handle_scope(isolate_);
68
69
695
    v8::Local<v8::ArrayBuffer> ab = backing_buffer.GetArrayBuffer();
70
71
    // validate that the byte_offset is aligned with sizeof(NativeT)
72

695
    CHECK_EQ(byte_offset & (sizeof(NativeT) - 1), 0);
73
    // validate this fits inside the backing buffer
74

1390
    CHECK_LE(sizeof(NativeT) * count,  ab->ByteLength() - byte_offset);
75
76
695
    buffer_ = reinterpret_cast<NativeT*>(
77
695
        const_cast<uint8_t*>(backing_buffer.GetNativeBuffer() + byte_offset));
78
79
695
    v8::Local<V8T> js_array = V8T::New(ab, byte_offset, count);
80
1390
    js_array_ = v8::Global<V8T>(isolate, js_array);
81
695
  }
82
83
79594
  AliasedBuffer(const AliasedBuffer& that)
84
      : isolate_(that.isolate_),
85
        count_(that.count_),
86
        byte_offset_(that.byte_offset_),
87
        buffer_(that.buffer_),
88
159188
        free_buffer_(false) {
89
238782
    js_array_ = v8::Global<V8T>(that.isolate_, that.GetJSArray());
90
79594
  }
91
92
86112
  ~AliasedBuffer() {
93



86112
    if (free_buffer_ && buffer_ != nullptr) {
94
5823
      free(buffer_);
95
    }
96
86112
    js_array_.Reset();
97
172224
  }
98
99
  /**
100
   * Helper class that is returned from operator[] to support assignment into
101
   * a specified location.
102
   */
103
  class Reference {
104
   public:
105
11502643
    Reference(AliasedBuffer<NativeT, V8T>* aliased_buffer, size_t index)
106
        : aliased_buffer_(aliased_buffer),
107
11502643
          index_(index) {
108
11502643
    }
109
110
    Reference(const Reference& that)
111
        : aliased_buffer_(that.aliased_buffer_),
112
          index_(that.index_) {
113
    }
114
115
4227150
    inline Reference& operator=(const NativeT &val) {
116
4227150
      aliased_buffer_->SetValue(index_, val);
117
4227150
      return *this;
118
    }
119
120
7275489
    operator NativeT() const {
121
7275489
      return aliased_buffer_->GetValue(index_);
122
    }
123
124
   private:
125
    AliasedBuffer<NativeT, V8T>* aliased_buffer_;
126
    size_t index_;
127
  };
128
129
  /**
130
   *  Get the underlying v8 TypedArray overlayed on top of the native buffer
131
   */
132
87384
  v8::Local<V8T> GetJSArray() const {
133
174768
    return js_array_.Get(isolate_);
134
  }
135
136
  /**
137
  *  Get the underlying v8::ArrayBuffer underlying the TypedArray and
138
  *  overlaying the native buffer
139
  */
140
695
  v8::Local<v8::ArrayBuffer> GetArrayBuffer() const {
141
1390
    return GetJSArray()->Buffer();
142
  }
143
144
  /**
145
   *  Get the underlying native buffer. Note that all reads/writes should occur
146
   *  through the GetValue/SetValue/operator[] methods
147
   */
148
695
  inline const NativeT* GetNativeBuffer() const {
149
695
    return buffer_;
150
  }
151
152
  /**
153
   *  Synonym for GetBuffer()
154
   */
155
  inline const NativeT* operator * () const {
156
    return GetNativeBuffer();
157
  }
158
159
  /**
160
   *  Set position index to given value.
161
   */
162
4227150
  inline void SetValue(const size_t index, NativeT value) {
163
#if defined(DEBUG) && DEBUG
164
    CHECK_LT(index, count_);
165
#endif
166
4227150
    buffer_[index] = value;
167
4227150
  }
168
169
  /**
170
   *  Get value at position index
171
   */
172
7275499
  inline const NativeT GetValue(const size_t index) const {
173
#if defined(DEBUG) && DEBUG
174
    CHECK_LT(index, count_);
175
#endif
176
7275499
    return buffer_[index];
177
  }
178
179
  /**
180
   *  Effectively, a synonym for GetValue/SetValue
181
   */
182
11502643
  Reference operator[](size_t index) {
183
11502643
    return Reference(this, index);
184
  }
185
186
  NativeT operator[](size_t index) const {
187
    return GetValue(index);
188
  }
189
190
 private:
191
  v8::Isolate* const isolate_;
192
  size_t count_;
193
  size_t byte_offset_;
194
  NativeT* buffer_;
195
  v8::Global<V8T> js_array_;
196
  bool free_buffer_;
197
};
198
}  // namespace node
199
200
#endif  // SRC_ALIASED_BUFFER_H_