Commit 8e62d2d4 authored by Tom Anderson's avatar Tom Anderson Committed by Commit Bot

[XProto] Move SendRequest() into source file

Most of SendRequest doesn't depend on the template parameter |Reply|,
so move the common code into a non-template function defined in the
source file.  This should hopefully reduce binary size since
SendRequest() gets instantiated for every Request type (654 in total).

BUG=1066670
R=sky

Change-Id: Iee5934f42b1c4ceb02b3279452e4cadbb7a620fe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2268841Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#783074}
parent 2b64742d
...@@ -54,4 +54,66 @@ size_t UnretainedRefCountedMemory::size() const { ...@@ -54,4 +54,66 @@ size_t UnretainedRefCountedMemory::size() const {
UnretainedRefCountedMemory::~UnretainedRefCountedMemory() = default; UnretainedRefCountedMemory::~UnretainedRefCountedMemory() = default;
base::Optional<unsigned int> SendRequestImpl(x11::Connection* connection,
WriteBuffer* buf,
bool is_void) {
xcb_protocol_request_t xpr{
.ext = nullptr,
.isvoid = is_void,
};
struct RequestHeader {
uint8_t major_opcode;
uint8_t minor_opcode;
uint16_t length;
};
struct ExtendedRequestHeader {
RequestHeader header;
uint32_t long_length;
};
static_assert(sizeof(ExtendedRequestHeader) == 8, "");
auto& first_buffer = buf->GetBuffers()[0];
DCHECK_GE(first_buffer->size(), sizeof(RequestHeader));
auto* old_header = reinterpret_cast<RequestHeader*>(
const_cast<uint8_t*>(first_buffer->data()));
ExtendedRequestHeader new_header{*old_header, 0};
// Requests are always a multiple of 4 bytes on the wire. Because of this,
// the length field represents the size in chunks of 4 bytes.
DCHECK_EQ(buf->offset() % 4, 0UL);
size_t size32 = buf->offset() / 4;
// XCB requires 2 iovecs for its own internal usage.
std::vector<struct iovec> io{{nullptr, 0}, {nullptr, 0}};
if (size32 < connection->setup().maximum_request_length) {
// Regular request
old_header->length = size32;
} else if (size32 < connection->extended_max_request_length()) {
// BigRequests extension request
DCHECK_EQ(new_header.header.length, 0U);
new_header.long_length = size32 + 1;
io.push_back({&new_header, sizeof(ExtendedRequestHeader)});
first_buffer = base::MakeRefCounted<OffsetRefCountedMemory>(
first_buffer, sizeof(RequestHeader),
first_buffer->size() - sizeof(RequestHeader));
} else {
LOG(ERROR) << "Cannot send request of length " << buf->offset();
return base::nullopt;
}
for (auto& buffer : buf->GetBuffers())
io.push_back({const_cast<uint8_t*>(buffer->data()), buffer->size()});
xpr.count = io.size() - 2;
xcb_connection_t* conn = connection->XcbConnection();
auto flags = XCB_REQUEST_CHECKED | XCB_REQUEST_RAW;
auto sequence = xcb_send_request(conn, flags, &io[2], &xpr);
if (xcb_connection_has_error(conn))
return base::nullopt;
return sequence;
}
} // namespace x11 } // namespace x11
...@@ -136,68 +136,14 @@ inline void Align(ReadBuffer* buf, size_t align) { ...@@ -136,68 +136,14 @@ inline void Align(ReadBuffer* buf, size_t align) {
Pad(buf, (align - (buf->offset % align)) % align); Pad(buf, (align - (buf->offset % align)) % align);
} }
base::Optional<unsigned int> SendRequestImpl(x11::Connection* connection,
WriteBuffer* buf,
bool is_void);
template <typename Reply> template <typename Reply>
Future<Reply> SendRequest(x11::Connection* connection, WriteBuffer* buf) { Future<Reply> SendRequest(x11::Connection* connection, WriteBuffer* buf) {
// Clang crashes when the value of |is_void| is inlined below, auto sequence = SendRequestImpl(connection, buf, std::is_void<Reply>::value);
// so keep this variable outside of |xpr|. return {sequence ? connection : nullptr, sequence};
constexpr bool is_void = std::is_void<Reply>::value;
xcb_protocol_request_t xpr{
.ext = nullptr,
.isvoid = is_void,
};
struct RequestHeader {
uint8_t major_opcode;
uint8_t minor_opcode;
uint16_t length;
};
struct ExtendedRequestHeader {
RequestHeader header;
uint32_t long_length;
};
static_assert(sizeof(ExtendedRequestHeader) == 8, "");
auto& first_buffer = buf->GetBuffers()[0];
DCHECK_GE(first_buffer->size(), sizeof(RequestHeader));
auto* old_header = reinterpret_cast<RequestHeader*>(
const_cast<uint8_t*>(first_buffer->data()));
ExtendedRequestHeader new_header{*old_header, 0};
// Requests are always a multiple of 4 bytes on the wire. Because of this,
// the length field represents the size in chunks of 4 bytes.
DCHECK_EQ(buf->offset() % 4, 0UL);
size_t size32 = buf->offset() / 4;
// XCB requires 2 iovecs for its own internal usage.
std::vector<struct iovec> io{{nullptr, 0}, {nullptr, 0}};
if (size32 < connection->setup().maximum_request_length) {
// Regular request
old_header->length = size32;
} else if (size32 < connection->extended_max_request_length()) {
// BigRequests extension request
DCHECK_EQ(new_header.header.length, 0U);
new_header.long_length = size32 + 1;
io.push_back({&new_header, sizeof(ExtendedRequestHeader)});
first_buffer = base::MakeRefCounted<OffsetRefCountedMemory>(
first_buffer, sizeof(RequestHeader),
first_buffer->size() - sizeof(RequestHeader));
} else {
LOG(ERROR) << "Cannot send request of length " << buf->offset();
return {nullptr, base::nullopt};
}
for (auto& buffer : buf->GetBuffers())
io.push_back({const_cast<uint8_t*>(buffer->data()), buffer->size()});
xpr.count = io.size() - 2;
xcb_connection_t* conn = connection->XcbConnection();
auto flags = XCB_REQUEST_CHECKED | XCB_REQUEST_RAW;
auto sequence = xcb_send_request(conn, flags, &io[2], &xpr);
if (xcb_connection_has_error(conn))
return {nullptr, base::nullopt};
return {connection, sequence};
} }
// Helper function for xcbproto popcount. Given an integral type, returns the // Helper function for xcbproto popcount. Given an integral type, returns the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment