Skip to content

Commit

Permalink
Allow a Node to be constructed with an explicit UUID.
Browse files Browse the repository at this point in the history
This allows the deserialization code to perform better because it
doesn't create a UUID which is then immediately overwritten. It also
allows us to remove some private, friendly interfaces from Node.
  • Loading branch information
AaronBallman committed Jul 20, 2020
1 parent 19b0af4 commit c0fed57
Show file tree
Hide file tree
Showing 23 changed files with 135 additions and 67 deletions.
1 change: 1 addition & 0 deletions include/gtirb/AuxDataContainer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ class GTIRB_EXPORT_API AuxDataContainer : public Node {

protected:
AuxDataContainer(Context& C, Kind knd);
AuxDataContainer(Context& C, Kind knd, const UUID& Uuid);

private:
AuxDataSet AuxDatas;
Expand Down
21 changes: 21 additions & 0 deletions include/gtirb/ByteInterval.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1936,6 +1936,9 @@ class GTIRB_EXPORT_API ByteInterval : public Node {
private:
ByteInterval(Context& C);

ByteInterval(Context& C, std::optional<Addr> A, uint64_t S, uint64_t InitSize,
const UUID& Uuid);

ByteInterval(Context& C, std::optional<Addr> A, uint64_t S,
uint64_t InitSize);

Expand All @@ -1947,11 +1950,29 @@ class GTIRB_EXPORT_API ByteInterval : public Node {
Bytes.resize(InitSize);
}

template <typename InputIterator>
ByteInterval(Context& C, std::optional<Addr> A, uint64_t S, uint64_t InitSize,
InputIterator Begin, InputIterator End, const UUID& Uuid)
: ByteInterval(C, A, S, 0, Uuid) {
Bytes.insert(Bytes.end(), Begin, End);
Bytes.resize(InitSize);
}

void setParent(Section* S, ByteIntervalObserver* O) {
Parent = S;
Observer = O;
}

template <typename InputIterator>
static ByteInterval*
Create(Context& C, std::optional<Addr> Address, InputIterator Begin,
InputIterator End, std::optional<uint64_t> Size,
std::optional<uint64_t> InitSize, const UUID& Uuid) {
return C.Create<ByteInterval>(
C, Address, Size ? *Size : std::distance(Begin, End),
InitSize ? *InitSize : std::distance(Begin, End), Begin, End, Uuid);
}

/// \brief The protobuf message type used for serializing ByteInterval.
using MessageType = proto::ByteInterval;

Expand Down
1 change: 1 addition & 0 deletions include/gtirb/CfgNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class GTIRB_EXPORT_API CfgNode : public Node {
/// \endcond
protected:
CfgNode(Context& C, Kind Knd) : Node(C, Knd) {}
CfgNode(Context& C, Kind Knd, const UUID& Uuid) : Node(C, Knd, Uuid) {}
};

} // namespace gtirb
Expand Down
7 changes: 7 additions & 0 deletions include/gtirb/CodeBlock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,19 @@ class GTIRB_EXPORT_API CodeBlock : public CfgNode {
CodeBlock(Context& C) : CfgNode(C, Kind::CodeBlock) {}
CodeBlock(Context& C, uint64_t S, uint64_t Decode)
: CfgNode(C, Kind::CodeBlock), Size(S), DecodeMode(Decode) {}
CodeBlock(Context& C, uint64_t S, uint64_t Decode, const UUID& Uuid)
: CfgNode(C, Kind::CodeBlock, Uuid), Size(S), DecodeMode(Decode) {}

void setParent(ByteInterval* BI, CodeBlockObserver* O) {
Parent = BI;
Observer = O;
}

static CodeBlock* Create(Context& C, uint64_t Size, uint64_t DecodeMode,
const UUID& Uuid) {
return C.Create<CodeBlock>(C, Size, DecodeMode, Uuid);
}

/// \brief The protobuf message type used for serializing CodeBlock.
using MessageType = proto::CodeBlock;

Expand Down
7 changes: 6 additions & 1 deletion include/gtirb/DataBlock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,14 @@ class DataBlock;
///
class GTIRB_EXPORT_API DataBlock : public Node {
DataBlock(Context& C) : Node(C, Kind::DataBlock) {}

DataBlock(Context& C, uint64_t S, const UUID& Uuid)
: Node(C, Kind::DataBlock, Uuid), Size(S) {}
DataBlock(Context& C, uint64_t S) : Node(C, Kind::DataBlock), Size(S) {}

static DataBlock* Create(Context& C, uint64_t S, const UUID& Uuid) {
return C.Create<DataBlock>(C, S, Uuid);
}

public:
/// \brief Create an unitialized DataBlock object.
/// \param C The Context in which this DataBlock will be held.
Expand Down
5 changes: 5 additions & 0 deletions include/gtirb/IR.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ class IR;

class GTIRB_EXPORT_API IR : public AuxDataContainer {
IR(Context& C);
IR(Context& C, const UUID& Uuid);

static IR* Create(Context& C, const UUID& Uuid) {
return C.Create<IR>(C, Uuid);
}

struct by_name {};
struct by_pointer {};
Expand Down
5 changes: 5 additions & 0 deletions include/gtirb/Module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ class GTIRB_EXPORT_API Module : public AuxDataContainer {

Module(Context& C);
Module(Context& C, const std::string& N);
Module(Context& C, const std::string& N, const UUID& Uuid);

static Module* Create(Context& C, const UUID& Uuid) {
return C.Create<Module>(C, "", Uuid);
}

public:
/// \brief Create a Module object in its default state.
Expand Down
11 changes: 3 additions & 8 deletions include/gtirb/Node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ class GTIRB_EXPORT_API Node {
/// \cond INTERNAL
Node(Context& C, Kind Knd);

/// \cond INTERNAL
Node(Context& C, Kind Knd, const UUID& Uuid);

private:
Kind K;
UUID Uuid;
Expand All @@ -125,14 +128,6 @@ class GTIRB_EXPORT_API Node {
// Context needs to own a move-only allocator.
Context* Ctx;

// Assign a new UUID to this node. This is only needed when deserializing
// objects, as there are no constructors allowing the user to set the UUID on
// construction.
void setUUID(UUID X);

// Allows unserialization in derived classes
friend bool setNodeUUIDFromBytes(Node* Node, const std::string& Bytes);

friend class Context; // Enables Context::Create
};

Expand Down
6 changes: 6 additions & 0 deletions include/gtirb/ProxyBlock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ class GTIRB_EXPORT_API ProxyBlock : public CfgNode {

private:
ProxyBlock(Context& C) : CfgNode(C, Kind::ProxyBlock) {}
ProxyBlock(Context& C, const UUID& Uuid)
: CfgNode(C, Kind::ProxyBlock, Uuid) {}

static ProxyBlock* Create(Context& C, const UUID& Uuid) {
return C.Create<ProxyBlock>(C, Uuid);
}

void setModule(Module* M) { Parent = M; }

Expand Down
6 changes: 6 additions & 0 deletions include/gtirb/Section.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ enum class SectionFlag : uint8_t {
class GTIRB_EXPORT_API Section : public Node {
Section(Context& C);
Section(Context& C, const std::string& N);
Section(Context& C, const std::string& N, const UUID& Uuid);

static Section* Create(Context& C, const std::string& Name,
const UUID& Uuid) {
return C.Create<Section>(C, Name, Uuid);
}

struct by_address {};
struct by_pointer {};
Expand Down
7 changes: 7 additions & 0 deletions include/gtirb/Symbol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ class GTIRB_EXPORT_API Symbol : public Node {
Symbol(Context& C) : Node(C, Kind::Symbol) {}
Symbol(Context& C, const std::string& N, bool AE)
: Node(C, Kind::Symbol), Name(N), AtEnd(AE) {}
Symbol(Context& C, const std::string& N, bool AE, const UUID& Uuid)
: Node(C, Kind::Symbol, Uuid), Name(N), AtEnd(AE) {}
Symbol(Context& C, Addr X, const std::string& N, bool AE)
: Node(C, Kind::Symbol), Payload(X), Name(N), AtEnd(AE) {}
template <typename NodeTy>
Expand All @@ -351,6 +353,11 @@ class GTIRB_EXPORT_API Symbol : public Node {
}
}

static Symbol* Create(Context& C, const std::string& Name, bool AtEnd,
const UUID& Uuid) {
return C.Create<Symbol>(C, Name, AtEnd, Uuid);
}

void setParent(Module* M, SymbolObserver* O) {
Parent = M;
Observer = O;
Expand Down
7 changes: 7 additions & 0 deletions src/AuxDataContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,11 @@ AuxDataContainer::AuxDataContainer(Context& C, Node::Kind knd) : Node(C, knd) {
// Once this is called, we outlaw registering new AuxData types.
TypeMap.Locked = true;
}

AuxDataContainer::AuxDataContainer(Context& C, Node::Kind knd, const UUID& Uuid)
: Node(C, knd, Uuid) {
// Once this is called, we outlaw registering new AuxData types.
TypeMap.Locked = true;
}

}; // namespace gtirb
19 changes: 12 additions & 7 deletions src/ByteInterval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ ByteInterval::ByteInterval(Context& C, std::optional<Addr> A, uint64_t S,
CBO(std::make_unique<CodeBlockObserverImpl>(this)),
DBO(std::make_unique<DataBlockObserverImpl>(this)) {}

ByteInterval::ByteInterval(Context& C, std::optional<Addr> A, uint64_t S,
uint64_t InitSize, const UUID& Uuid)
: Node(C, Kind::ByteInterval, Uuid), Address(A), Size(S), Bytes(InitSize),
CBO(std::make_unique<CodeBlockObserverImpl>(this)),
DBO(std::make_unique<DataBlockObserverImpl>(this)) {}

void ByteInterval::toProtobuf(MessageType* Message) const {
nodeUUIDToBytes(this, *Message->mutable_uuid());

Expand Down Expand Up @@ -83,9 +89,7 @@ void ByteInterval::toProtobuf(MessageType* Message) const {
ProtoBlock->set_offset(B.getOffset());
B.toProtobuf(ProtoBlock->mutable_data());
} break;
default: {
assert(!"unknown Node::Kind in ByteInterval::toProtobuf");
}
default: { assert(!"unknown Node::Kind in ByteInterval::toProtobuf"); }
}
}

Expand All @@ -103,12 +107,13 @@ ByteInterval* ByteInterval::fromProtobuf(Context& C,
A = Addr(Message.address());
}

UUID Id;
if (!uuidFromBytes(Message.uuid(), Id))
return nullptr;

ByteInterval* BI = ByteInterval::Create(
C, A, Message.contents().begin(), Message.contents().end(),
Message.size(), Message.contents().size());

if (!setNodeUUIDFromBytes(BI, Message.uuid()))
return nullptr;
Message.size(), Message.contents().size(), Id);

for (const auto& ProtoBlock : Message.blocks()) {
switch (ProtoBlock.value_case()) {
Expand Down
7 changes: 4 additions & 3 deletions src/CodeBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ void CodeBlock::toProtobuf(MessageType* Message) const {
CodeBlock* CodeBlock::fromProtobuf(Context& C, const MessageType& Message) {
// Because we do not have an offset, we cannot create the code block and
// set its parent at the same time.
auto* B = CodeBlock::Create(C, Message.size(), Message.decode_mode());
if (!setNodeUUIDFromBytes(B, Message.uuid()))
UUID Id;
if (!uuidFromBytes(Message.uuid(), Id))
return nullptr;
return B;

return CodeBlock::Create(C, Message.size(), Message.decode_mode(), Id);
}

uint64_t CodeBlock::getOffset() const {
Expand Down
9 changes: 5 additions & 4 deletions src/DataBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ void DataBlock::toProtobuf(MessageType* Message) const {
}

DataBlock* DataBlock::fromProtobuf(Context& C, const MessageType& Message) {
UUID Id;
if (!uuidFromBytes(Message.uuid(), Id))
return nullptr;

// Because we do not have an offset, we cannot create the data block and
// set its parent at the same time.
auto* DO = DataBlock::Create(C, Message.size());
if (!setNodeUUIDFromBytes(DO, Message.uuid()))
return nullptr;
return DO;
return DataBlock::Create(C, Message.size(), Id);
}

uint64_t DataBlock::getOffset() const {
Expand Down
10 changes: 8 additions & 2 deletions src/IR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ IR::IR(Context& C)
: AuxDataContainer(C, Kind::IR),
MO(std::make_unique<ModuleObserverImpl>(this)) {}

IR::IR(Context& C, const UUID& Uuid)
: AuxDataContainer(C, Kind::IR, Uuid),
MO(std::make_unique<ModuleObserverImpl>(this)) {}

class IRLoadErrorCategory : public std::error_category {
public:
const char* name() const noexcept override { return "gt.gtirb.ir"; }
Expand Down Expand Up @@ -134,9 +138,11 @@ void IR::toProtobuf(MessageType* Message) const {
}

IR* IR::fromProtobuf(Context& C, const MessageType& Message) {
auto* I = IR::Create(C);
if (!setNodeUUIDFromBytes(I, Message.uuid()))
UUID Id;
if (!uuidFromBytes(Message.uuid(), Id))
return nullptr;

auto* I = IR::Create(C, Id);
for (const auto& Elt : Message.modules()) {
auto* M = Module::fromProtobuf(C, Elt);
if (!M)
Expand Down
13 changes: 8 additions & 5 deletions src/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,14 @@ class Module::SymbolObserverImpl : public SymbolObserver {
};

Module::Module(Context& C) : Module(C, std::string{}) {}

Module::Module(Context& C, const std::string& N)
: AuxDataContainer(C, Kind::Module), Name(N),
SecObs(std::make_unique<SectionObserverImpl>(this)),
SymObs(std::make_unique<SymbolObserverImpl>(this)) {}
Module::Module(Context& C, const std::string& N, const UUID& Uuid)
: AuxDataContainer(C, Kind::Module, Uuid), Name(N),
SecObs(std::make_unique<SectionObserverImpl>(this)),
SymObs(std::make_unique<SymbolObserverImpl>(this)) {}

void Module::toProtobuf(MessageType* Message) const {
nodeUUIDToBytes(this, *Message->mutable_uuid());
Expand Down Expand Up @@ -110,9 +113,11 @@ static void nodeMapFromProtobuf(Context& C, std::map<T, U*>& Values,
}

Module* Module::fromProtobuf(Context& C, const MessageType& Message) {
Module* M = Module::Create(C);
if (!setNodeUUIDFromBytes(M, Message.uuid()))
UUID Id;
if (!uuidFromBytes(Message.uuid(), Id))
return nullptr;

Module* M = Module::Create(C, Id);
M->BinaryPath = Message.binary_path();
M->PreferredAddr = Addr(Message.preferred_addr());
M->RebaseDelta = Message.rebase_delta();
Expand All @@ -139,7 +144,6 @@ Module* Module::fromProtobuf(Context& C, const MessageType& Message) {
}
for (const auto& ProtoS : Message.sections()) {
for (const auto& ProtoBI : ProtoS.byte_intervals()) {
UUID Id;
if (!uuidFromBytes(ProtoBI.uuid(), Id))
return nullptr;
auto* BI = dyn_cast_or_null<ByteInterval>(getByUUID(C, Id));
Expand All @@ -150,7 +154,6 @@ Module* Module::fromProtobuf(Context& C, const MessageType& Message) {
}
}
if (!Message.entry_point().empty()) {
UUID Id;
if (!uuidFromBytes(Message.entry_point(), Id))
return nullptr;
M->EntryPoint = dyn_cast_or_null<CodeBlock>(Node::getByUUID(C, Id));
Expand Down
14 changes: 4 additions & 10 deletions src/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,11 @@ using namespace gtirb;
// TODO: accessing this object between threads requires synchronization.
static boost::uuids::random_generator UUIDGenerator;

Node::Node(Context& C, Kind Knd) : K(Knd), Uuid(UUIDGenerator()), Ctx(&C) {
Node::Node(Context& C, Kind Knd, const UUID& Uuid)
: K(Knd), Uuid(Uuid), Ctx(&C) {
Ctx->registerNode(Uuid, this);
}

Node::~Node() noexcept { Ctx->unregisterNode(this); }

void Node::setUUID(UUID X) {
// UUID should not previously exist
assert(Ctx->findNode(X) == nullptr && "UUID already registered");
Node::Node(Context& C, Kind Knd) : Node(C, Knd, UUIDGenerator()) {}

Ctx->unregisterNode(this);
this->Uuid = X;
Ctx->registerNode(Uuid, this);
}
Node::~Node() noexcept { Ctx->unregisterNode(this); }
7 changes: 4 additions & 3 deletions src/ProxyBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ void ProxyBlock::toProtobuf(MessageType* Message) const {
}

ProxyBlock* ProxyBlock::fromProtobuf(Context& C, const MessageType& Message) {
ProxyBlock* P = Create(C);
if (!setNodeUUIDFromBytes(P, Message.uuid()))
UUID Id;
if (!uuidFromBytes(Message.uuid(), Id))
return nullptr;
return P;

return Create(C, Id);
}

// Present for testing purposes only.
Expand Down
Loading

0 comments on commit c0fed57

Please sign in to comment.