diff options
author | Bert Belder <bertbelder@gmail.com> | 2019-05-02 00:18:18 +0200 |
---|---|---|
committer | Bert Belder <bertbelder@gmail.com> | 2019-05-02 06:25:44 +0200 |
commit | ae0544b7ce8370fcd9322dd10a8c2ebdcbabe75c (patch) | |
tree | daf4280ceb1e6a4da127f3db9eea06837082b113 | |
parent | c05cbc8eac91a9e1ab9b87c688ac4392eff01445 (diff) |
core: remove support for moving deno_buf ownership from C++ to JavaScript
The functionality hasn't been in use for a long time. Without this feature,
the `alloc_ptr` and `alloc_len` fields are no longer necessary.
-rw-r--r-- | core/libdeno.rs | 15 | ||||
-rw-r--r-- | core/libdeno/binding.cc | 85 | ||||
-rw-r--r-- | core/libdeno/deno.h | 6 | ||||
-rw-r--r-- | core/libdeno/internal.h | 2 | ||||
-rw-r--r-- | core/libdeno/libdeno_test.cc | 72 | ||||
-rw-r--r-- | core/libdeno/test.h | 2 |
6 files changed, 39 insertions, 143 deletions
diff --git a/core/libdeno.rs b/core/libdeno.rs index 4853c318e..046caaef6 100644 --- a/core/libdeno.rs +++ b/core/libdeno.rs @@ -19,16 +19,9 @@ pub struct isolate { _unused: [u8; 0], } -/// If "alloc_ptr" is not null, this type represents a buffer which is created -/// in C side, and then passed to Rust side by `deno_recv_cb`. Finally it should -/// be moved back to C side by `deno_respond`. If it is not passed to -/// `deno_respond` in the end, it will be leaked. -/// -/// If "alloc_ptr" is null, this type represents a borrowed slice. +/// This type represents a borrowed slice. #[repr(C)] pub struct deno_buf { - alloc_ptr: *const u8, - alloc_len: usize, data_ptr: *const u8, data_len: usize, } @@ -41,8 +34,6 @@ impl deno_buf { #[inline] pub fn empty() -> Self { Self { - alloc_ptr: null(), - alloc_len: 0, data_ptr: null(), data_len: 0, } @@ -51,8 +42,6 @@ impl deno_buf { #[inline] pub unsafe fn from_raw_parts(ptr: *const u8, len: usize) -> Self { Self { - alloc_ptr: null(), - alloc_len: 0, data_ptr: ptr, data_len: len, } @@ -64,8 +53,6 @@ impl<'a> From<&'a [u8]> for deno_buf { #[inline] fn from(x: &'a [u8]) -> Self { Self { - alloc_ptr: null(), - alloc_len: 0, data_ptr: x.as_ref().as_ptr(), data_len: x.len(), } diff --git a/core/libdeno/binding.cc b/core/libdeno/binding.cc index 80f733b4f..8001534ff 100644 --- a/core/libdeno/binding.cc +++ b/core/libdeno/binding.cc @@ -167,57 +167,33 @@ v8::Local<v8::Uint8Array> ImportBuf(DenoIsolate* d, deno_buf buf) { return v8::Local<v8::Uint8Array>(); } - if (buf.alloc_ptr == nullptr) { - // If alloc_ptr isn't set, we memcpy. - // This is currently used for flatbuffers created in Rust. - - // To avoid excessively allocating new ArrayBuffers, we try to reuse a - // single global ArrayBuffer. The caveat is that users must extract data - // from it before the next tick. We only do this for ArrayBuffers less than - // 1024 bytes. - v8::Local<v8::ArrayBuffer> ab; - void* data; - if (buf.data_len > GLOBAL_IMPORT_BUF_SIZE) { - // Simple case. We allocate a new ArrayBuffer for this. - ab = v8::ArrayBuffer::New(d->isolate_, buf.data_len); - data = ab->GetContents().Data(); + // To avoid excessively allocating new ArrayBuffers, we try to reuse a single + // global ArrayBuffer. The caveat is that users must extract data from it + // before the next tick. We only do this for ArrayBuffers less than 1024 + // bytes. + v8::Local<v8::ArrayBuffer> ab; + void* data; + if (buf.data_len > GLOBAL_IMPORT_BUF_SIZE) { + // Simple case. We allocate a new ArrayBuffer for this. + ab = v8::ArrayBuffer::New(d->isolate_, buf.data_len); + data = ab->GetContents().Data(); + } else { + // Fast case. We reuse the global ArrayBuffer. + if (d->global_import_buf_.IsEmpty()) { + // Lazily initialize it. + DCHECK_NULL(d->global_import_buf_ptr_); + ab = v8::ArrayBuffer::New(d->isolate_, GLOBAL_IMPORT_BUF_SIZE); + d->global_import_buf_.Reset(d->isolate_, ab); + d->global_import_buf_ptr_ = ab->GetContents().Data(); } else { - // Fast case. We reuse the global ArrayBuffer. - if (d->global_import_buf_.IsEmpty()) { - // Lazily initialize it. - DCHECK_NULL(d->global_import_buf_ptr_); - ab = v8::ArrayBuffer::New(d->isolate_, GLOBAL_IMPORT_BUF_SIZE); - d->global_import_buf_.Reset(d->isolate_, ab); - d->global_import_buf_ptr_ = ab->GetContents().Data(); - } else { - DCHECK(d->global_import_buf_ptr_); - ab = d->global_import_buf_.Get(d->isolate_); - } - data = d->global_import_buf_ptr_; + DCHECK(d->global_import_buf_ptr_); + ab = d->global_import_buf_.Get(d->isolate_); } - memcpy(data, buf.data_ptr, buf.data_len); - auto view = v8::Uint8Array::New(ab, 0, buf.data_len); - return view; - } else { - auto ab = v8::ArrayBuffer::New( - d->isolate_, reinterpret_cast<void*>(buf.alloc_ptr), buf.alloc_len, - v8::ArrayBufferCreationMode::kInternalized); - auto view = - v8::Uint8Array::New(ab, buf.data_ptr - buf.alloc_ptr, buf.data_len); - return view; + data = d->global_import_buf_ptr_; } -} - -static deno_buf GetContents(v8::Isolate* isolate, - v8::Local<v8::ArrayBufferView> view) { - auto ab = view->Buffer(); - auto contents = ab->GetContents(); - deno_buf buf; - buf.alloc_ptr = reinterpret_cast<uint8_t*>(contents.Data()); - buf.alloc_len = contents.ByteLength(); - buf.data_ptr = buf.alloc_ptr + view->ByteOffset(); - buf.data_len = view->ByteLength(); - return buf; + memcpy(data, buf.data_ptr, buf.data_len); + auto view = v8::Uint8Array::New(ab, 0, buf.data_len); + return view; } // Sets the recv_ callback. @@ -247,13 +223,12 @@ void Send(const v8::FunctionCallbackInfo<v8::Value>& args) { v8::HandleScope handle_scope(isolate); - deno_buf control = {nullptr, 0u, nullptr, 0u}; - if (args.Length() > 0) { - v8::Local<v8::Value> control_v = args[0]; - if (control_v->IsArrayBufferView()) { - control = - GetContents(isolate, v8::Local<v8::ArrayBufferView>::Cast(control_v)); - } + deno_buf control = {nullptr, 0}; + if (args[0]->IsArrayBufferView()) { + auto view = v8::Local<v8::ArrayBufferView>::Cast(args[0]); + auto data = + reinterpret_cast<uint8_t*>(view->Buffer()->GetContents().Data()); + control = {data + view->ByteOffset(), view->ByteLength()}; } PinnedBuf zero_copy = diff --git a/core/libdeno/deno.h b/core/libdeno/deno.h index f83f00834..f8bc9a82d 100644 --- a/core/libdeno/deno.h +++ b/core/libdeno/deno.h @@ -17,10 +17,8 @@ typedef deno::PinnedBuf::Raw deno_pinned_buf; // Data that gets transmitted. typedef struct { - uint8_t* alloc_ptr; // Start of memory allocation (from `new uint8_t[len]`). - size_t alloc_len; // Length of the memory allocation. - uint8_t* data_ptr; // Start of logical contents (within the allocation). - size_t data_len; // Length of logical contents. + uint8_t* data_ptr; + size_t data_len; } deno_buf; typedef struct { diff --git a/core/libdeno/internal.h b/core/libdeno/internal.h index b75cc9717..5e0051a8a 100644 --- a/core/libdeno/internal.h +++ b/core/libdeno/internal.h @@ -157,7 +157,7 @@ static intptr_t external_references[] = { reinterpret_cast<intptr_t>(MessageCallback), 0}; -static const deno_buf empty_buf = {nullptr, 0, nullptr, 0}; +static const deno_buf empty_buf = {nullptr, 0}; static const deno_snapshot empty_snapshot = {nullptr, 0}; Deno* NewFromSnapshot(void* user_data, deno_recv_cb cb); diff --git a/core/libdeno/libdeno_test.cc b/core/libdeno/libdeno_test.cc index 70ea5581c..ad4240da5 100644 --- a/core/libdeno/libdeno_test.cc +++ b/core/libdeno/libdeno_test.cc @@ -41,17 +41,6 @@ TEST(LibDenoTest, ErrorsCorrectly) { deno_delete(d); } -deno_buf strbuf(const char* str) { - auto len = strlen(str); - deno_buf buf; - buf.alloc_ptr = new uint8_t[len]; - buf.alloc_len = len; - buf.data_ptr = buf.alloc_ptr; - buf.data_len = len; - memcpy(buf.data_ptr, str, len); - return buf; -} - void assert_null(deno_pinned_buf b) { EXPECT_EQ(b.data_ptr, nullptr); EXPECT_EQ(b.data_len, 0u); @@ -85,7 +74,8 @@ TEST(LibDenoTest, RecvReturnBar) { EXPECT_EQ(buf.data_ptr[0], 'a'); EXPECT_EQ(buf.data_ptr[1], 'b'); EXPECT_EQ(buf.data_ptr[2], 'c'); - deno_respond(d, user_data, strbuf("bar")); + uint8_t response[] = {'b', 'a', 'r'}; + deno_respond(d, user_data, {response, sizeof response}); }; Deno* d = deno_new(deno_config{0, snapshot, empty, recv_cb}); deno_execute(d, d, "a.js", "RecvReturnBar()"); @@ -101,60 +91,6 @@ TEST(LibDenoTest, DoubleRecvFails) { deno_delete(d); } -TEST(LibDenoTest, SendRecvSlice) { - static int count = 0; - auto recv_cb = [](auto user_data, auto buf, auto zero_copy_buf) { - auto d = reinterpret_cast<Deno*>(user_data); - assert_null(zero_copy_buf); - static const size_t alloc_len = 1024; - size_t i = count++; - // Check the size and offset of the slice. - size_t data_offset = buf.data_ptr - buf.alloc_ptr; - EXPECT_EQ(data_offset, i * 11); - EXPECT_EQ(buf.data_len, alloc_len - i * 30); - EXPECT_EQ(buf.alloc_len, alloc_len); - // Check values written by the JS side. - EXPECT_EQ(buf.data_ptr[0], 100 + i); - EXPECT_EQ(buf.data_ptr[buf.data_len - 1], 100 - i); - // Make copy of the backing buffer -- this is currently necessary - // because deno_respond() takes ownership over the buffer, but we are - // not given ownership of `buf` by our caller. - uint8_t* alloc_ptr = new uint8_t[alloc_len]; - memcpy(alloc_ptr, buf.alloc_ptr, alloc_len); - // Make a slice that is a bit shorter than the original. - deno_buf buf2{alloc_ptr, alloc_len, alloc_ptr + data_offset, - buf.data_len - 19}; - // Place some values into the buffer for the JS side to verify. - buf2.data_ptr[0] = 200 + i; - buf2.data_ptr[buf2.data_len - 1] = 200 - i; - // Send back. - deno_respond(d, user_data, buf2); - }; - Deno* d = deno_new(deno_config{0, snapshot, empty, recv_cb}); - deno_execute(d, d, "a.js", "SendRecvSlice()"); - EXPECT_EQ(nullptr, deno_last_exception(d)); - EXPECT_EQ(count, 5); - deno_delete(d); -} - -TEST(LibDenoTest, JSSendArrayBufferViewTypes) { - static int count = 0; - auto recv_cb = [](auto _, auto buf, auto zero_copy_buf) { - assert_null(zero_copy_buf); - count++; - size_t data_offset = buf.data_ptr - buf.alloc_ptr; - EXPECT_EQ(data_offset, 2468u); - EXPECT_EQ(buf.data_len, 1000u); - EXPECT_EQ(buf.alloc_len, 4321u); - EXPECT_EQ(buf.data_ptr[0], count); - }; - Deno* d = deno_new(deno_config{0, snapshot, empty, recv_cb}); - deno_execute(d, nullptr, "a.js", "JSSendArrayBufferViewTypes()"); - EXPECT_EQ(nullptr, deno_last_exception(d)); - EXPECT_EQ(count, 3); - deno_delete(d); -} - TEST(LibDenoTest, TypedArraySnapshots) { Deno* d = deno_new(deno_config{0, snapshot, empty, nullptr}); deno_execute(d, nullptr, "a.js", "TypedArraySnapshots()"); @@ -266,7 +202,7 @@ TEST(LibDenoTest, EncodeErrorBug) { TEST(LibDenoTest, Shared) { uint8_t s[] = {0, 1, 2}; - deno_buf shared = {nullptr, 0, s, 3}; + deno_buf shared = {s, sizeof s}; Deno* d = deno_new(deno_config{0, snapshot, shared, nullptr}); deno_execute(d, nullptr, "a.js", "Shared()"); EXPECT_EQ(nullptr, deno_last_exception(d)); @@ -301,7 +237,7 @@ TEST(LibDenoTest, LibDenoEvalContextError) { TEST(LibDenoTest, SharedAtomics) { int32_t s[] = {0, 1, 2}; - deno_buf shared = {nullptr, 0, reinterpret_cast<uint8_t*>(s), sizeof s}; + deno_buf shared = {reinterpret_cast<uint8_t*>(s), sizeof s}; Deno* d = deno_new(deno_config{0, empty_snapshot, shared, nullptr}); deno_execute(d, nullptr, "a.js", "Atomics.add(new Int32Array(Deno.core.shared), 0, 1)"); diff --git a/core/libdeno/test.h b/core/libdeno/test.h index d7e6a3f80..4ae83f810 100644 --- a/core/libdeno/test.h +++ b/core/libdeno/test.h @@ -6,7 +6,7 @@ #include "testing/gtest/include/gtest/gtest.h" extern deno_snapshot snapshot; // Loaded in libdeno/test.cc -const deno_buf empty = {nullptr, 0, nullptr, 0}; +const deno_buf empty = {nullptr, 0}; const deno_snapshot empty_snapshot = {nullptr, 0}; #endif // TEST_H_ |