Skip to content

Commit

Permalink
refactor: Reduce indirections in addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
slavek-kucera authored May 23, 2024
1 parent 08b4313 commit 0d5aee8
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 20 deletions.
47 changes: 27 additions & 20 deletions parser_library/src/context/ordinary_assembly/address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,10 @@ address::address(base address_base, int offset, const space_storage& spaces)
if (spaces.empty())
return;

auto new_spaces = std::make_shared<std::vector<space_entry>>(); // libc++14 space_entry[]
new_spaces->reserve(spaces.size());
for (auto& space : spaces)
new_spaces->emplace_back(space, 1);
auto new_spaces = std::make_shared<space_entry[]>(spaces.size());
std::ranges::transform(spaces, new_spaces.get(), [](const auto& space) { return std::pair(space, 1); });

spaces_.spaces = *new_spaces;
spaces_.spaces = std::span(new_spaces.get(), spaces.size());
spaces_.owner = std::move(new_spaces);
}

Expand All @@ -199,12 +197,10 @@ address::address(base address_base, int offset, space_storage&& spaces)
if (spaces.empty())
return;

auto new_spaces = std::make_shared<std::vector<space_entry>>();
new_spaces->reserve(spaces.size());
for (auto& space : spaces)
new_spaces->emplace_back(std::move(space), 1);
auto new_spaces = std::make_shared<space_entry[]>(spaces.size());
std::ranges::transform(spaces, new_spaces.get(), [](auto& space) { return std::pair(std::move(space), 1); });

spaces_.spaces = *new_spaces;
spaces_.spaces = std::span(new_spaces.get(), spaces.size());
spaces_.owner = std::move(new_spaces);
}

Expand All @@ -223,16 +219,22 @@ address::base_list merge_bases(const address::base_list& l, const address::base_
{
if (l.empty())
{
auto result = std::make_shared<std::vector<address::base_entry>>(r.bases.begin(), r.bases.end());
for (auto& [_, cnt] : *result)
cnt *= -1;
return address::base_list(std::move(result));
const auto total = std::ranges::size(r.bases);
auto result_owner = std::make_shared<address::base_entry[]>(total);
std::span result(result_owner.get(), total);

std::ranges::transform(r.bases, result.begin(), [](auto e) {
e.second *= -1;
return e;
});

return address::base_list(result, std::move(result_owner));
}
if (std::ranges::equal(l.bases, r.bases))
return {};
}

auto result = std::make_shared<std::vector<address::base_entry>>(); // libc++14 base_entry[]
auto result = std::make_shared<std::vector<address::base_entry>>();

result->reserve(l.bases.size() + r.bases.size());

Expand Down Expand Up @@ -334,13 +336,18 @@ address address::operator-(int offs) const { return address(bases_, offset_ - of
address address::operator-() const
{
auto [spaces, off] = normalized_spaces();
auto inv_bases = std::make_shared<std::vector<address::base_entry>>(
bases_.bases.begin(), bases_.bases.end()); // libc++14 base_entry[]
for (auto& [_, cnt] : *inv_bases)
cnt = -cnt;
const auto total = std::ranges::size(bases_.bases);
auto inv_bases_owner = std::make_shared<address::base_entry[]>(total);
std::span inv_bases(inv_bases_owner.get(), total);

std::ranges::transform(bases_.bases, inv_bases.begin(), [](auto b) {
b.second = -b.second;
return b;
});

for (auto& s : spaces)
s.second = -s.second;
return address(address::base_list(std::move(inv_bases)),
return address(address::base_list(inv_bases, std::move(inv_bases_owner)),
-offset_ - off,
space_list(std::make_shared<std::vector<space_entry>>(std::move(spaces))));
}
Expand Down
36 changes: 36 additions & 0 deletions parser_library/test/context/address_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "context/ordinary_assembly/section.h"
#include "library_info_transitional.h"

using namespace ::testing;

// test for
// address class

Expand Down Expand Up @@ -66,3 +68,37 @@ TEST(address, has_unresolved_spaces)

ASSERT_FALSE(addr.has_unresolved_space());
}

TEST(address, constructors)
{
hlasm_context ctx;
auto sect = ctx.ord_ctx.set_section(id_index("TEST"), section_kind::COMMON, {}, library_info_transitional::empty);

auto sp1 = ctx.ord_ctx.current_section()->current_location_counter().set_value_undefined(0, 0);
auto sp2 = ctx.ord_ctx.current_section()->current_location_counter().register_ordinary_space(halfword);

space_storage spaces { sp2 };

address addr1({ sect, id_index() }, 12345, spaces);
address addr2({ sect, id_index() }, 12345, std::move(spaces));

auto diff = addr1 - addr2;

EXPECT_TRUE(diff.bases().empty());
EXPECT_FALSE(diff.has_spaces());
EXPECT_EQ(diff.offset(), 0);
}

TEST(address, subtract_optimization)
{
hlasm_context ctx;
auto sect = ctx.ord_ctx.set_section(id_index("TEST"), section_kind::COMMON, {}, library_info_transitional::empty);

address addr2({ sect, id_index() }, 12345, {});

auto diff = address() - addr2;

std::array expected_bases { address::base_entry { sect, -1 } };

EXPECT_THAT(diff.bases(), Pointwise(Eq(), expected_bases));
}

0 comments on commit 0d5aee8

Please sign in to comment.