Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6b60f38

Browse filesBrowse files
joyeecheungtargos
authored andcommitted
src: use AliasedUint32Array for encodeInto results
Getting the buffer from a TypedArray created from the JS land incurs a copy. For encodeInto() results we can just use an AliasedArray and let the binding always own the store. PR-URL: #46658 Reviewed-By: Darshan Sen <raisinten@gmail.com>
1 parent dcba3a0 commit 6b60f38
Copy full SHA for 6b60f38

File tree

Expand file treeCollapse file tree

3 files changed

+41
-26
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+41
-26
lines changed
Open diff view settings
Collapse file

‎lib/internal/encoding.js‎

Copy file name to clipboardExpand all lines: lib/internal/encoding.js
+8-7Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ const {
1313
StringPrototypeSlice,
1414
Symbol,
1515
SymbolToStringTag,
16-
Uint32Array,
1716
Uint8Array,
1817
} = primordials;
1918

@@ -49,12 +48,12 @@ const {
4948
validateString,
5049
validateObject,
5150
} = require('internal/validators');
52-
51+
const binding = internalBinding('encoding_binding');
5352
const {
5453
encodeInto,
5554
encodeUtf8String,
5655
decodeUTF8,
57-
} = internalBinding('encoding_binding');
56+
} = binding;
5857

5958
const { Buffer } = require('buffer');
6059

@@ -318,8 +317,6 @@ function getEncodingFromLabel(label) {
318317
return encodings.get(trimAsciiWhitespace(label.toLowerCase()));
319318
}
320319

321-
const encodeIntoResults = new Uint32Array(2);
322-
323320
class TextEncoder {
324321
constructor() {
325322
this[kEncoder] = true;
@@ -340,8 +337,12 @@ class TextEncoder {
340337
validateString(src, 'src');
341338
if (!dest || !isUint8Array(dest))
342339
throw new ERR_INVALID_ARG_TYPE('dest', 'Uint8Array', dest);
343-
encodeInto(src, dest, encodeIntoResults);
344-
return { read: encodeIntoResults[0], written: encodeIntoResults[1] };
340+
341+
encodeInto(src, dest);
342+
// We need to read from the binding here since the buffer gets refreshed
343+
// from the snapshot.
344+
const { 0: read, 1: written } = binding.encodeIntoResults;
345+
return { read, written };
345346
}
346347

347348
[inspect](depth, opts) {
Collapse file

‎src/encoding_binding.cc‎

Copy file name to clipboardExpand all lines: src/encoding_binding.cc
+27-17Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,30 @@ using v8::Local;
2020
using v8::MaybeLocal;
2121
using v8::Object;
2222
using v8::String;
23-
using v8::Uint8Array;
2423
using v8::Uint32Array;
24+
using v8::Uint8Array;
2525
using v8::Value;
2626

27-
BindingData::BindingData(Environment* env, Local<Object> object)
28-
: SnapshotableObject(env, object, type_int) {}
27+
void BindingData::MemoryInfo(MemoryTracker* tracker) const {
28+
tracker->TrackField("encode_into_results_buffer",
29+
encode_into_results_buffer_);
30+
}
31+
32+
BindingData::BindingData(Realm* realm, v8::Local<v8::Object> object)
33+
: SnapshotableObject(realm, object, type_int),
34+
encode_into_results_buffer_(realm->isolate(), kEncodeIntoResultsLength) {
35+
object
36+
->Set(realm->context(),
37+
FIXED_ONE_BYTE_STRING(realm->isolate(), "encodeIntoResults"),
38+
encode_into_results_buffer_.GetJSArray())
39+
.Check();
40+
}
2941

3042
bool BindingData::PrepareForSerialization(Local<Context> context,
3143
v8::SnapshotCreator* creator) {
44+
// We'll just re-initialize the buffers in the constructor since their
45+
// contents can be thrown away once consumed in the previous call.
46+
encode_into_results_buffer_.Release();
3247
// Return true because we need to maintain the reference to the binding from
3348
// JS land.
3449
return true;
@@ -47,19 +62,19 @@ void BindingData::Deserialize(Local<Context> context,
4762
InternalFieldInfoBase* info) {
4863
DCHECK_EQ(index, BaseObject::kEmbedderType);
4964
v8::HandleScope scope(context->GetIsolate());
50-
Environment* env = Environment::GetCurrent(context);
65+
Realm* realm = Realm::GetCurrent(context);
5166
// Recreate the buffer in the constructor.
52-
BindingData* binding = env->AddBindingData<BindingData>(context, holder);
67+
BindingData* binding = realm->AddBindingData<BindingData>(context, holder);
5368
CHECK_NOT_NULL(binding);
5469
}
5570

5671
void BindingData::EncodeInto(const FunctionCallbackInfo<Value>& args) {
5772
Environment* env = Environment::GetCurrent(args);
5873
Isolate* isolate = env->isolate();
59-
CHECK_GE(args.Length(), 3);
74+
CHECK_GE(args.Length(), 2);
6075
CHECK(args[0]->IsString());
6176
CHECK(args[1]->IsUint8Array());
62-
CHECK(args[2]->IsUint32Array());
77+
BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
6378

6479
Local<String> source = args[0].As<String>();
6580

@@ -68,21 +83,16 @@ void BindingData::EncodeInto(const FunctionCallbackInfo<Value>& args) {
6883
char* write_result = static_cast<char*>(buf->Data()) + dest->ByteOffset();
6984
size_t dest_length = dest->ByteLength();
7085

71-
// results = [ read, written ]
72-
Local<Uint32Array> result_arr = args[2].As<Uint32Array>();
73-
uint32_t* results = reinterpret_cast<uint32_t*>(
74-
static_cast<char*>(result_arr->Buffer()->Data()) +
75-
result_arr->ByteOffset());
76-
7786
int nchars;
7887
int written = source->WriteUtf8(
7988
isolate,
8089
write_result,
8190
dest_length,
8291
&nchars,
8392
String::NO_NULL_TERMINATION | String::REPLACE_INVALID_UTF8);
84-
results[0] = nchars;
85-
results[1] = written;
93+
94+
binding_data->encode_into_results_buffer_[0] = nchars;
95+
binding_data->encode_into_results_buffer_[1] = written;
8696
}
8797

8898
// Encode a single string to a UTF-8 Uint8Array (not Buffer).
@@ -175,9 +185,9 @@ void BindingData::Initialize(Local<Object> target,
175185
Local<Value> unused,
176186
Local<Context> context,
177187
void* priv) {
178-
Environment* env = Environment::GetCurrent(context);
188+
Realm* realm = Realm::GetCurrent(context);
179189
BindingData* const binding_data =
180-
env->AddBindingData<BindingData>(context, target);
190+
realm->AddBindingData<BindingData>(context, target);
181191
if (binding_data == nullptr) return;
182192

183193
SetMethod(context, target, "encodeInto", EncodeInto);
Collapse file

‎src/encoding_binding.h‎

Copy file name to clipboardExpand all lines: src/encoding_binding.h
+6-2Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ class ExternalReferenceRegistry;
1414
namespace encoding_binding {
1515
class BindingData : public SnapshotableObject {
1616
public:
17-
BindingData(Environment* env, v8::Local<v8::Object> obj);
17+
BindingData(Realm* realm, v8::Local<v8::Object> obj);
1818

1919
using InternalFieldInfo = InternalFieldInfoBase;
2020

2121
SERIALIZABLE_OBJECT_METHODS()
2222
SET_BINDING_ID(encoding_binding_data)
2323

24-
SET_NO_MEMORY_INFO()
24+
void MemoryInfo(MemoryTracker* tracker) const override;
2525
SET_SELF_SIZE(BindingData)
2626
SET_MEMORY_INFO_NAME(BindingData)
2727

@@ -35,6 +35,10 @@ class BindingData : public SnapshotableObject {
3535
void* priv);
3636
static void RegisterTimerExternalReferences(
3737
ExternalReferenceRegistry* registry);
38+
39+
private:
40+
static constexpr size_t kEncodeIntoResultsLength = 2;
41+
AliasedUint32Array encode_into_results_buffer_;
3842
};
3943

4044
} // namespace encoding_binding

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.