buffer: reduce overhead of StringBytes::Encode for UCS2

Currently calling StringBytes::Encode on a UCS2 buffer
results in two copies of the buffer and the usage of
std::vector::assign makes the memory usage unpredictable,
and therefore hard to test against.

This patch makes the memory usage more predictable by
allocating the memory using node::UncheckedMalloc and
handles the memory allocation failure properly. Only
one copy of the buffer will be created and it will
be freed upon GC of the string.

PR-URL: https://github.com/nodejs/node/pull/19798
Refs: https://github.com/nodejs/node/pull/19739
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Joyee Cheung
2018-04-04 21:23:34 +08:00
parent 95dc59010b
commit e5f8924064

View File

@@ -720,15 +720,19 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,
// Buffer, so we need to reorder on BE platforms. See
// http://nodejs.org/api/buffer.html regarding Node's "ucs2"
// encoding specification
std::vector<uint16_t> dst;
if (IsBigEndian()) {
dst.assign(buf, buf + buflen);
size_t nbytes = buflen * sizeof(dst[0]);
SwapBytes16(reinterpret_cast<char*>(&dst[0]), nbytes);
buf = &dst[0];
uint16_t* dst = node::UncheckedMalloc<uint16_t>(buflen);
if (dst == nullptr) {
*error = SB_MALLOC_FAILED_ERROR;
return MaybeLocal<Value>();
}
size_t nbytes = buflen * sizeof(uint16_t);
memcpy(dst, buf, nbytes);
SwapBytes16(reinterpret_cast<char*>(dst), nbytes);
return ExternTwoByteString::New(isolate, dst, buflen, error);
} else {
return ExternTwoByteString::NewFromCopy(isolate, buf, buflen, error);
}
return ExternTwoByteString::NewFromCopy(isolate, buf, buflen, error);
}
MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,