Skip to content

[SourceKit] Avoid one memcpy on potentially big sourcekit response data #30929

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace sourcekitd {

class CompactArrayBuilderImpl {
public:
std::unique_ptr<llvm::MemoryBuffer> createBuffer() const;
std::unique_ptr<llvm::MemoryBuffer> createBuffer(CustomBufferKind Kind) const;
void appendTo(llvm::SmallVectorImpl<char> &Buf) const;
unsigned copyInto(char *BufPtr) const;
size_t sizeInBytes() const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class ResponseBuilder {
void setBool(SourceKit::UIdent Key, bool val);
Array setArray(SourceKit::UIdent Key);
Dictionary setDictionary(SourceKit::UIdent Key);
void setCustomBuffer(SourceKit::UIdent Key, CustomBufferKind Kind,
void setCustomBuffer(SourceKit::UIdent Key,
std::unique_ptr<llvm::MemoryBuffer> MemBuf);

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ void CodeCompletionResultsArrayBuilder::add(

std::unique_ptr<llvm::MemoryBuffer>
CodeCompletionResultsArrayBuilder::createBuffer() {
return Impl.Builder.createBuffer();
return Impl.Builder.createBuffer(
CustomBufferKind::CodeCompletionResultsArray);
}

namespace {
Expand Down
9 changes: 6 additions & 3 deletions tools/SourceKit/tools/sourcekitd/lib/API/CompactArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,13 @@ unsigned CompactArrayBuilderImpl::getOffsetForString(StringRef Str) {
}

std::unique_ptr<llvm::MemoryBuffer>
CompactArrayBuilderImpl::createBuffer() const {
CompactArrayBuilderImpl::createBuffer(CustomBufferKind Kind) const {
auto bodySize = sizeInBytes();
std::unique_ptr<llvm::WritableMemoryBuffer> Buf;
Buf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(sizeInBytes());
copyInto(Buf->getBufferStart(), Buf->getBufferSize());
Buf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
sizeof(uint64_t) + bodySize);
*reinterpret_cast<uint64_t*>(Buf->getBufferStart()) = (uint64_t)Kind;
copyInto(Buf->getBufferStart() + sizeof(uint64_t), bodySize);
return std::move(Buf);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,16 +244,21 @@ std::unique_ptr<llvm::MemoryBuffer> DocStructureArrayBuilder::createBuffer() {
size_t structureArrayBufferSize = impl.structureArrayBuffer.size();
size_t structureBufferSize = impl.structureBuilder.sizeInBytes();

size_t kindSize = sizeof(uint64_t);

// Header:
// * offset of each section start (5)
// * offset of top structure array (relative to structure array section) (1)
size_t headerSize = sizeof(uint64_t) * 6;

auto result = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
inheritedTypesBufferSize + attrsBufferSize + elementsBufferSize +
structureArrayBufferSize + structureBufferSize + headerSize);
structureArrayBufferSize + structureBufferSize + headerSize + kindSize);

*reinterpret_cast<uint64_t *>(result->getBufferStart()) =
(uint64_t)CustomBufferKind::DocStructureArray;

char *start = result->getBufferStart();
char *start = result->getBufferStart() + kindSize;
char *headerPtr = start;
char *ptr = start + headerSize;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void DocSupportAnnotationArrayBuilder::add(const DocEntityInfo &Info) {

std::unique_ptr<llvm::MemoryBuffer>
DocSupportAnnotationArrayBuilder::createBuffer() {
return Impl.Builder.createBuffer();
return Impl.Builder.createBuffer(CustomBufferKind::DocSupportAnnotationArray);
}

namespace {
Expand Down
11 changes: 7 additions & 4 deletions tools/SourceKit/tools/sourcekitd/lib/API/ExpressionTypeArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,18 @@ struct ExpressionTypeArrayBuilder::Implementation {
return reader.count();
}

std::unique_ptr<llvm::MemoryBuffer> createBuffer() {
std::unique_ptr<llvm::MemoryBuffer> createBuffer(CustomBufferKind Kind) {
std::array<CompactArrayBuilderImpl*, 3> builders =
{&builder, &strBuilder, &protoBuilder};
auto kindSize = sizeof(uint64_t);
size_t headerSize = sizeof(uint64_t) * builders.size();
auto allSize = headerSize;
auto allSize = kindSize + headerSize;
for (auto *b: builders)
allSize += b->sizeInBytes();
auto result = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(allSize);
char *start = result->getBufferStart();
*reinterpret_cast<uint64_t*>(result->getBufferStart()) = (uint64_t)Kind;

char *start = result->getBufferStart() + kindSize;
char *headerPtr = start;
char *ptr = start + headerSize;
auto addBuilder = [&](CompactArrayBuilderImpl& buffer) {
Expand Down Expand Up @@ -223,7 +226,7 @@ void ExpressionTypeArrayBuilder::add(const ExpressionType &expType) {

std::unique_ptr<llvm::MemoryBuffer>
ExpressionTypeArrayBuilder::createBuffer() {
return Impl.createBuffer();
return Impl.createBuffer(CustomBufferKind::ExpressionTypeArray);
}

VariantFunctions ExpressionTypeArrayBuilder::Funcs = {
Expand Down
31 changes: 12 additions & 19 deletions tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1422,9 +1422,7 @@ class SKDocConsumer : public DocInfoConsumer {
}

sourcekitd_response_t createResponse() {
TopDict.setCustomBuffer(KeyAnnotations,
CustomBufferKind::DocSupportAnnotationArray,
AnnotationsBuilder.createBuffer());
TopDict.setCustomBuffer(KeyAnnotations, AnnotationsBuilder.createBuffer());
return RespBuilder.createResponse();
}

Expand Down Expand Up @@ -1866,8 +1864,7 @@ static void reportExpressionTypeInfo(const RequestResult<ExpressionTypesInFile>
for (auto &R: Info.Results) {
ArrBuilder.add(R);
}
Dict.setCustomBuffer(KeyExpressionTypeList, CustomBufferKind::ExpressionTypeArray,
ArrBuilder.createBuffer());
Dict.setCustomBuffer(KeyExpressionTypeList, ArrBuilder.createBuffer());
Rec(Builder.createResponse());
}

Expand Down Expand Up @@ -1924,8 +1921,7 @@ class SKCodeCompletionConsumer : public CodeCompletionConsumer {
return createErrorRequestFailed(ErrorDescription.c_str());

RespBuilder.getDictionary().setCustomBuffer(KeyResults,
CustomBufferKind::CodeCompletionResultsArray,
ResultsBuilder.createBuffer());
ResultsBuilder.createBuffer());
return RespBuilder.createResponse();
}

Expand Down Expand Up @@ -2558,18 +2554,13 @@ sourcekitd_response_t SKEditorConsumer::createResponse() {
return Error;

if (Opts.EnableSyntaxMap) {
Dict.setCustomBuffer(KeySyntaxMap,
CustomBufferKind::TokenAnnotationsArray,
SyntaxMap.createBuffer());
Dict.setCustomBuffer(KeySyntaxMap, SyntaxMap.createBuffer());
}
if (!SemanticAnnotations.empty()) {
Dict.setCustomBuffer(KeyAnnotations,
CustomBufferKind::TokenAnnotationsArray,
SemanticAnnotations.createBuffer());
Dict.setCustomBuffer(KeyAnnotations, SemanticAnnotations.createBuffer());
}
if (Opts.EnableStructure) {
Dict.setCustomBuffer(KeySubStructure, CustomBufferKind::DocStructureArray,
DocStructure.createBuffer());
Dict.setCustomBuffer(KeySubStructure, DocStructure.createBuffer());
}


Expand Down Expand Up @@ -2756,11 +2747,13 @@ void serializeSyntaxTreeAsByteTree(
*SyntaxTree.getRaw(), UserInfo);

std::unique_ptr<llvm::WritableMemoryBuffer> Buf =
llvm::WritableMemoryBuffer::getNewUninitMemBuffer(Stream.data().size());
memcpy(Buf->getBufferStart(), Stream.data().data(), Stream.data().size());
llvm::WritableMemoryBuffer::getNewUninitMemBuffer(sizeof(uint64_t) + Stream.data().size());
*reinterpret_cast<uint64_t*>(Buf->getBufferStart()) =
(uint64_t)CustomBufferKind::RawData;
memcpy(Buf->getBufferStart() + sizeof(uint64_t),
Stream.data().data(), Stream.data().size());

Dict.setCustomBuffer(KeySerializedSyntaxTree, CustomBufferKind::RawData,
std::move(Buf));
Dict.setCustomBuffer(KeySerializedSyntaxTree, std::move(Buf));

auto EndClock = clock();
LOG_SECTION("incrParse Performance", InfoLowPrio) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ bool TokenAnnotationsArrayBuilder::empty() const {

std::unique_ptr<llvm::MemoryBuffer>
TokenAnnotationsArrayBuilder::createBuffer() {
return Impl.Builder.createBuffer();
return Impl.Builder.createBuffer(CustomBufferKind::TokenAnnotationsArray);
}

namespace {
Expand Down
24 changes: 10 additions & 14 deletions tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-InProc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,19 +237,15 @@ class SKDBool: public SKDObject {

class SKDCustomData: public SKDObject {
public:
SKDCustomData(CustomBufferKind BufferKind,
std::unique_ptr<llvm::MemoryBuffer>& MemBuf)
: SKDObject(ObjectKind::CustomData), BufferKind(BufferKind),
BufferPtr(llvm::MemoryBuffer::getMemBufferCopy(
MemBuf->getBuffer(),
MemBuf->getBufferIdentifier()))
SKDCustomData(std::unique_ptr<llvm::MemoryBuffer> MemBuf)
: SKDObject(ObjectKind::CustomData), BufferPtr(std::move(MemBuf))
{}

SKDCustomData(SKDCustomData const&) = delete;
SKDCustomData &operator=(SKDCustomData const&) = delete;

sourcekitd_variant_type_t getVariantType() const override {
switch (BufferKind) {
switch (getBufferKind()) {
case CustomBufferKind::TokenAnnotationsArray:
case CustomBufferKind::DocSupportAnnotationArray:
case CustomBufferKind::CodeCompletionResultsArray:
Expand All @@ -266,23 +262,24 @@ class SKDCustomData: public SKDObject {
}

CustomBufferKind getBufferKind() const {
return BufferKind;
return ((CustomBufferKind)*(const uint64_t*)_getStartPtr());
}

const void *getDataPtr() const override {
return BufferPtr->getBuffer().data();
return ((const void*)(((const uint64_t*)_getStartPtr())+1));
}

size_t getDataSize() const override {
return BufferPtr->getBuffer().size();
return BufferPtr->getBuffer().size() - sizeof(uint64_t);
}

static bool classof(const SKDObject *O) {
return O->getKind() == ObjectKind::CustomData;
}
private:
CustomBufferKind BufferKind;
std::unique_ptr<llvm::MemoryBuffer> BufferPtr;

const void *_getStartPtr() const { return BufferPtr->getBuffer().data(); }
};

class SKDError: public SKDObject {
Expand Down Expand Up @@ -675,10 +672,9 @@ ResponseBuilder::Dictionary::setDictionary(UIdent Key) {
}

void ResponseBuilder::Dictionary::setCustomBuffer(
SourceKit::UIdent Key,
CustomBufferKind Kind, std::unique_ptr<llvm::MemoryBuffer> MemBuf) {
SourceKit::UIdent Key, std::unique_ptr<llvm::MemoryBuffer> MemBuf) {
static_cast<SKDObject *>(Impl)->set(SKDUIDFromUIdent(Key),
new SKDCustomData(Kind, MemBuf));
new SKDCustomData(std::move(MemBuf)));
}

ResponseBuilder::Array
Expand Down
16 changes: 3 additions & 13 deletions tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,19 +258,9 @@ ResponseBuilder::Dictionary::setDictionary(UIdent Key) {
}

void ResponseBuilder::Dictionary::setCustomBuffer(
SourceKit::UIdent Key,
CustomBufferKind Kind, std::unique_ptr<llvm::MemoryBuffer> MemBuf) {

std::unique_ptr<llvm::WritableMemoryBuffer> CustomBuf;
CustomBuf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
sizeof(uint64_t) + MemBuf->getBufferSize());
char *BufPtr = CustomBuf->getBufferStart();
*reinterpret_cast<uint64_t*>(BufPtr) = (uint64_t)Kind;
BufPtr += sizeof(uint64_t);
memcpy(BufPtr, MemBuf->getBufferStart(), MemBuf->getBufferSize());

xpc_object_t xdata = xpc_data_create(CustomBuf->getBufferStart(),
CustomBuf->getBufferSize());
SourceKit::UIdent Key, std::unique_ptr<llvm::MemoryBuffer> Buf) {
xpc_object_t xdata = xpc_data_create(Buf->getBufferStart(),
Buf->getBufferSize());
xpc_dictionary_set_value(Impl, Key.c_str(), xdata);
xpc_release(xdata);
}
Expand Down