Skip to content

Commit

Permalink
perf: Make address operations less expensive
Browse files Browse the repository at this point in the history
  • Loading branch information
slavek-kucera authored Aug 4, 2023
1 parent e2f6709 commit 5bcdc67
Show file tree
Hide file tree
Showing 21 changed files with 591 additions and 376 deletions.
357 changes: 225 additions & 132 deletions parser_library/src/context/ordinary_assembly/address.cpp

Large diffs are not rendered by default.

43 changes: 32 additions & 11 deletions parser_library/src/context/ordinary_assembly/address.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <compare>
#include <memory>
#include <span>
#include <utility>
#include <variant>
#include <vector>
Expand Down Expand Up @@ -44,33 +45,53 @@ struct address
const section* owner = nullptr;
id_index qualifier;

friend bool operator==(const base&, const base&) = default;
friend auto operator<=>(const base&, const base&) = default;
};

using space_entry = std::pair<space_ptr, int>;
using base_entry = std::pair<base, int>;

struct space_list
{
space_list() = default;
template<typename T>
explicit space_list(std::shared_ptr<T> ptr)
: spaces(*ptr)
, owner(std::move(ptr))
{}
explicit space_list(std::span<const space_entry> spaces, std::shared_ptr<void> owner)
: spaces(spaces)
, owner(std::move(owner))
{}

std::span<const space_entry> spaces;
std::shared_ptr<void> owner;

bool empty() const { return spaces.empty(); }
};

private:
// list of bases and their counts to which is the address relative
std::vector<base_entry> bases_;
// offset relative to bases
int offset_ = 0;
// list of spaces with their counts this address contains
std::vector<space_entry> spaces_;
space_list spaces_;

public:
// list of bases and their counts to which is the address relative
const std::vector<base_entry>& bases() const;
std::vector<base_entry>& bases();
// offset relative to bases
int offset() const;
int unresolved_offset() const;
// list of spaces with their counts this address contains
std::vector<space_entry>& spaces();
const std::vector<space_entry>& spaces() const;
std::vector<space_entry> normalized_spaces() const;
static std::pair<std::vector<space_entry>, int> normalized_spaces(std::span<const space_entry> spaces);
std::pair<std::vector<space_entry>, int> normalized_spaces() const;

address() = default;
address(base address_base, int offset, const space_storage& spaces);
address(base address_base, int offset, space_storage&& spaces);

address operator+(const address& addr) const;
address operator+(int offs) const;
Expand All @@ -83,11 +104,13 @@ struct address
bool is_simple() const;
bool has_dependant_space() const;
bool has_unresolved_space() const;

void normalize();
bool has_spaces() const;

private:
address(std::vector<base_entry> bases, int offset, std::vector<space_entry> spaces);
address(std::vector<base_entry> bases, int offset, space_list spaces);

friend struct address_resolver;
friend class location_counter;
};

enum class space_kind
Expand Down Expand Up @@ -125,9 +148,7 @@ struct space
// replace space with another
static void resolve(space_ptr this_space, space_ptr value);
// fill space with the whole address
static void resolve(space_ptr this_space, address value);
// common resolver for 2 methods above
static void resolve(space_ptr this_space, std::variant<space_ptr, address> value);
static void resolve(space_ptr this_space, int length, std::vector<address::space_entry> unresolved);

bool resolved() const { return resolved_; }
int resolved_length;
Expand Down
62 changes: 33 additions & 29 deletions parser_library/src/context/ordinary_assembly/address_resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@

using namespace hlasm_plugin::parser_library::context;

address_resolver::address_resolver(address dependency_address_)
address_resolver::address_resolver(address dependency_address_, size_t boundary)
: dependency_address(std::move(dependency_address_))
{
cached_deps_.unresolved_address = extract_dep_address(dependency_address);
}
, boundary(boundary)
{}

dependency_collector address_resolver::get_dependencies(dependency_solver&) const
{
return extract_dep_address(dependency_address);
return extract_dep_address(dependency_address, boundary);
}

symbol_value address_resolver::resolve(dependency_solver&) const
Expand All @@ -40,25 +39,22 @@ symbol_value address_resolver::resolve(dependency_solver&) const
return dependency_address.offset();
}

address address_resolver::extract_dep_address(const address& addr)
address address_resolver::extract_dep_address(const address& addr, size_t boundary)
{
address tmp(address::base {}, 0, {});
auto spaces = addr.normalized_spaces();
for (auto it = spaces.rbegin(); it != spaces.rend(); ++it)
{
tmp.spaces().push_back(*it);
if (it->first->kind == space_kind::ALIGNMENT || it->first->kind == space_kind::LOCTR_SET
|| it->first->kind == space_kind::LOCTR_MAX)
break;
}
return tmp;
auto [spaces, _] = addr.normalized_spaces();
auto enough = std::find_if(spaces.rbegin(), spaces.rend(), [boundary](const auto& e) {
return e.first->kind == space_kind::ALIGNMENT && e.first->align.boundary >= boundary
|| e.first->kind == space_kind::LOCTR_SET || e.first->kind == space_kind::LOCTR_MAX;
});
if (enough != spaces.rend())
spaces.erase(spaces.begin(), std::prev(enough.base()));
return address({}, 0, address::space_list(std::make_shared<std::vector<address::space_entry>>(std::move(spaces))));
}

alignable_address_resolver::alignable_address_resolver(
address dependency_address, std::vector<address> base_addrs, size_t boundary, int offset)
: address_resolver(std::move(dependency_address))
: address_resolver(std::move(dependency_address), boundary)
, base_addrs(std::move(base_addrs))
, boundary(boundary)
, offset(offset)
{}

Expand All @@ -70,15 +66,6 @@ symbol_value alignable_address_resolver::resolve(const address& addr) const
return addr.offset() + (symbol_value::abs_value_t)al + offset;
}

alignable_address_resolver::alignable_address_resolver(
address dependency_address_, std::vector<address>& base_addrs_, size_t boundary_, int offset_, bool)
: address_resolver(std::move(dependency_address_))
, base_addrs(std::move(base_addrs_))
, boundary(boundary_)
, offset(offset_)
{}


alignable_address_abs_part_resolver::alignable_address_abs_part_resolver(const resolvable* dependency_source)
: dependency_source_(dependency_source)
{}
Expand All @@ -101,7 +88,10 @@ symbol_value alignable_address_abs_part_resolver::resolve(dependency_solver& sol
}

aggregate_address_resolver::aggregate_address_resolver(std::vector<address> base_addrs, size_t boundary, int offset)
: alignable_address_resolver(base_addrs.back(), base_addrs, boundary, offset, false)
: last_base_addrs(base_addrs.size() - 1)
, base_addrs(std::move(base_addrs))
, boundary(boundary)
, offset(offset)
{}

symbol_value aggregate_address_resolver::resolve(dependency_solver&) const
Expand All @@ -117,5 +107,19 @@ symbol_value aggregate_address_resolver::resolve(dependency_solver&) const
}
}

return alignable_address_resolver::resolve(base_addrs[idx]);
auto al = boundary ? (boundary - base_addrs[idx].offset() % boundary) % boundary : 0;
return base_addrs[idx].offset() + (symbol_value::abs_value_t)al + offset;
}

dependency_collector aggregate_address_resolver::get_dependencies(dependency_solver&) const
{
while (last_base_addrs != -1)
{
auto addr = address_resolver::extract_dep_address(base_addrs[last_base_addrs], boundary);
if (addr.has_unresolved_space())
return std::move(addr);

--last_base_addrs;
}
return dependency_collector();
}
24 changes: 15 additions & 9 deletions parser_library/src/context/ordinary_assembly/address_resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,41 +30,47 @@ using addr_res_ptr = std::unique_ptr<address_resolver_base>;
// structure wrapping address providing resolvable interface to it
struct address_resolver : public address_resolver_base
{
explicit address_resolver(address dependency_address);
explicit address_resolver(address dependency_address, size_t boundary);

dependency_collector get_dependencies(dependency_solver& solver) const override;

symbol_value resolve(dependency_solver& solver) const override;

static address extract_dep_address(const address& addr, size_t boundary);

protected:
address dependency_address;
dependency_collector cached_deps_;
static address extract_dep_address(const address& addr);
size_t boundary;
};

// provides resolvable interface for address that require certain alignment
struct alignable_address_resolver : public address_resolver
struct alignable_address_resolver final : public address_resolver
{
alignable_address_resolver(
address dependency_address, std::vector<address> base_addrs, size_t boundary, int offset);

symbol_value resolve(dependency_solver& solver) const override;

protected:
private:
std::vector<address> base_addrs;
size_t boundary;
int offset;
symbol_value resolve(const address& addr) const;
alignable_address_resolver(
address dependency_address, std::vector<address>& base_addrs, size_t boundary, int offset, bool);
};

// provides resolvable interface for the agregate of addresses
struct aggregate_address_resolver final : public alignable_address_resolver
struct aggregate_address_resolver final : public address_resolver_base
{
aggregate_address_resolver(std::vector<address> base_addrs, size_t boundary, int offset);

symbol_value resolve(dependency_solver& solver) const override;

dependency_collector get_dependencies(dependency_solver& solver) const override;

private:
mutable size_t last_base_addrs;
std::vector<address> base_addrs;
size_t boundary;
int offset;
};

// provides resolvable interface for absolute part of the address
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ dependency_collector::dependency_collector(id_index undefined_symbol)

dependency_collector::dependency_collector(address u_a)
: unresolved_address(std::move(u_a))
{
unresolved_address->normalize();
}
{}

dependency_collector::dependency_collector(attr_ref attribute_reference)
{
Expand Down Expand Up @@ -110,7 +108,7 @@ dependency_collector& hlasm_plugin::parser_library::context::dependency_collecto

if (unresolved_address)
{
auto& spaces = unresolved_address->spaces();
auto [spaces, _] = unresolved_address->normalized_spaces();
utils::merge_unsorted(unresolved_spaces,
std::make_move_iterator(spaces.begin()),
std::make_move_iterator(spaces.end()),
Expand All @@ -121,8 +119,12 @@ dependency_collector& hlasm_plugin::parser_library::context::dependency_collecto

if (dc.unresolved_address)
{
utils::merge_unsorted(
unresolved_spaces, dc.unresolved_address->spaces(), merge_spaces_comparator(), merge_spaces());
auto [spaces, _] = dc.unresolved_address->normalized_spaces();
utils::merge_unsorted(unresolved_spaces,
std::make_move_iterator(spaces.begin()),
std::make_move_iterator(spaces.end()),
merge_spaces_comparator(),
merge_spaces());
}

return *this;
Expand Down Expand Up @@ -169,7 +171,6 @@ void dependency_collector::add_sub(const dependency_collector& holder, bool add)
unresolved_address = *unresolved_address + (*holder.unresolved_address);
else
unresolved_address = *unresolved_address - (*holder.unresolved_address);
adjust_address(*unresolved_address);
}
else if (!unresolved_address && holder.unresolved_address)
{
Expand All @@ -187,20 +188,22 @@ void dependency_collector::div_mul(const dependency_collector& holder)
else
{
if (unresolved_address)
utils::merge_unsorted(
unresolved_spaces, unresolved_address->spaces(), merge_spaces_comparator(), merge_spaces());
{
auto [spaces, _] = unresolved_address->normalized_spaces();
utils::merge_unsorted(unresolved_spaces,
std::make_move_iterator(spaces.begin()),
std::make_move_iterator(spaces.end()),
merge_spaces_comparator(),
merge_spaces());
}
if (holder.unresolved_address)
utils::merge_unsorted(
unresolved_spaces, holder.unresolved_address->spaces(), merge_spaces_comparator(), merge_spaces());
{
auto [spaces, _] = holder.unresolved_address->normalized_spaces();
utils::merge_unsorted(unresolved_spaces,
std::make_move_iterator(spaces.begin()),
std::make_move_iterator(spaces.end()),
merge_spaces_comparator(),
merge_spaces());
}
}
}

void dependency_collector::adjust_address(address& addr)
{
auto known_spaces = std::partition(addr.spaces().begin(), addr.spaces().end(), [](auto& entry) {
return entry.first->kind == context::space_kind::LOCTR_UNKNOWN;
});

if (known_spaces != addr.spaces().begin())
addr.spaces().erase(known_spaces, addr.spaces().end());
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ struct dependency_collector
void add_sub(const dependency_collector& holder, bool add);

void div_mul(const dependency_collector& holder);

static void adjust_address(address& addr);
};

} // namespace hlasm_plugin::parser_library::context
Expand Down
Loading

0 comments on commit 5bcdc67

Please sign in to comment.