src: simplify UnionBytes

Before this commit it was using a tagged union to store the one-byte and
two-byte pointers.

From a `sizeof(UnionBytes)` perspective that makes no difference - there
is a hole between the tag and the union - and it makes the code just a
little harder to reason about, IMO.

PR-URL: https://github.com/nodejs/node/pull/29116
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
Ben Noordhuis 2019-08-14 12:06:43 +02:00 committed by Rich Trott
parent 18405e66d2
commit 841df6a9b6

View File

@ -59,47 +59,40 @@ class NonOwningExternalTwoByteResource
class UnionBytes { class UnionBytes {
public: public:
UnionBytes(const uint16_t* data, size_t length) UnionBytes(const uint16_t* data, size_t length)
: is_one_byte_(false), two_bytes_(data), length_(length) {} : one_bytes_(nullptr), two_bytes_(data), length_(length) {}
UnionBytes(const uint8_t* data, size_t length) UnionBytes(const uint8_t* data, size_t length)
: is_one_byte_(true), one_bytes_(data), length_(length) {} : one_bytes_(data), two_bytes_(nullptr), length_(length) {}
UnionBytes(const UnionBytes&) = default; UnionBytes(const UnionBytes&) = default;
UnionBytes& operator=(const UnionBytes&) = default; UnionBytes& operator=(const UnionBytes&) = default;
UnionBytes(UnionBytes&&) = default; UnionBytes(UnionBytes&&) = default;
UnionBytes& operator=(UnionBytes&&) = default; UnionBytes& operator=(UnionBytes&&) = default;
bool is_one_byte() const { return is_one_byte_; } bool is_one_byte() const { return one_bytes_ != nullptr; }
const uint16_t* two_bytes_data() const { const uint16_t* two_bytes_data() const {
CHECK(!is_one_byte_);
CHECK_NOT_NULL(two_bytes_); CHECK_NOT_NULL(two_bytes_);
return two_bytes_; return two_bytes_;
} }
const uint8_t* one_bytes_data() const { const uint8_t* one_bytes_data() const {
CHECK(is_one_byte_);
CHECK_NOT_NULL(one_bytes_); CHECK_NOT_NULL(one_bytes_);
return one_bytes_; return one_bytes_;
} }
v8::Local<v8::String> ToStringChecked(v8::Isolate* isolate) const { v8::Local<v8::String> ToStringChecked(v8::Isolate* isolate) const {
if (is_one_byte_) { if (is_one_byte()) {
CHECK_NOT_NULL(one_bytes_);
NonOwningExternalOneByteResource* source = NonOwningExternalOneByteResource* source =
new NonOwningExternalOneByteResource(one_bytes_, length_); new NonOwningExternalOneByteResource(one_bytes_data(), length_);
return v8::String::NewExternalOneByte(isolate, source).ToLocalChecked(); return v8::String::NewExternalOneByte(isolate, source).ToLocalChecked();
} else { } else {
CHECK_NOT_NULL(two_bytes_);
NonOwningExternalTwoByteResource* source = NonOwningExternalTwoByteResource* source =
new NonOwningExternalTwoByteResource(two_bytes_, length_); new NonOwningExternalTwoByteResource(two_bytes_data(), length_);
return v8::String::NewExternalTwoByte(isolate, source).ToLocalChecked(); return v8::String::NewExternalTwoByte(isolate, source).ToLocalChecked();
} }
} }
size_t length() { return length_; } size_t length() { return length_; }
private: private:
bool is_one_byte_; const uint8_t* one_bytes_;
union { const uint16_t* two_bytes_;
const uint8_t* one_bytes_;
const uint16_t* two_bytes_;
};
size_t length_; size_t length_;
}; };