Skip to content

Commit

Permalink
Resolve lifetime issues related to macro dependencies (part 3)
Browse files Browse the repository at this point in the history
  • Loading branch information
slavek-kucera authored Feb 9, 2023
1 parent 1c41380 commit 0bd9a96
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 105 deletions.
65 changes: 41 additions & 24 deletions CMakeSettings.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,5 @@
{
"configurations": [
{
"name": "x86-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x86" ],
"buildRoot": "${projectDir}\\build\\${name}",
"installRoot": "${projectDir}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"variables": []
},
{
"name": "x86-Release",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"inheritEnvironments": [ "msvc_x86" ],
"buildRoot": "${projectDir}\\build\\${name}",
"installRoot": "${projectDir}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"variables": []
},
{
"name": "x64-Debug",
"generator": "Ninja",
Expand Down Expand Up @@ -170,6 +146,47 @@
"wslPath": "${defaultWSLPath}",
"addressSanitizerRuntimeFlags": "detect_leaks=0",
"variables": []
},
{
"name": "x64-Debug-ASAN",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\build\\${name}",
"installRoot": "${projectDir}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x64_x64" ],
"variables": [
{
"name": "CMAKE_VS_JUST_MY_CODE_DEBUGGING",
"value": "On",
"type": "BOOL"
}
],
"addressSanitizerEnabled": true
},
{
"name": "x86-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x86" ],
"buildRoot": "${projectDir}\\build\\${name}",
"installRoot": "${projectDir}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": ""
},
{
"name": "x86-Release",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"inheritEnvironments": [ "msvc_x86" ],
"buildRoot": "${projectDir}\\build\\${name}",
"installRoot": "${projectDir}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": ""
}
]
}
13 changes: 5 additions & 8 deletions parser_library/src/workspaces/macro_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,14 @@

#include <array>

#include "analyzer.h"
#include "context/hlasm_context.h"
#include "context/special_instructions.h"
#include "file_manager.h"
#include "lsp/lsp_context.h"

namespace hlasm_plugin::parser_library::workspaces {

void macro_cache::collect_diags() const
{
// No collectible children
}

macro_cache::macro_cache(const file_manager& file_mngr, std::shared_ptr<file> macro_file)
: file_mngr_(&file_mngr)
, macro_file_(std::move(macro_file))
Expand Down Expand Up @@ -63,7 +60,7 @@ std::vector<cached_opsyn_mnemo> macro_cache_key::get_opsyn_state(context::hlasm_

macro_cache_key macro_cache_key::create_from_context(context::hlasm_context& hlasm_ctx, library_data data)
{
return { hlasm_ctx.opencode_location(), data, get_opsyn_state(hlasm_ctx) };
return { comparable_weak_ptr(hlasm_ctx.ids_ptr()), data, get_opsyn_state(hlasm_ctx) };
}

void macro_cache_key::sort_opsyn_state(std::vector<cached_opsyn_mnemo>& opsyn_state)
Expand Down Expand Up @@ -164,9 +161,9 @@ void macro_cache::save_macro(const macro_cache_key& key, const analyzer& analyze
cache_data.cached_member = analyzer.context().hlasm_ctx->get_copy_member(key.data.library_member);
}

void macro_cache::erase_cache_of_opencode(const utils::resource::resource_location& opencode_file_location)
void macro_cache::erase_unused()
{
std::erase_if(cache_, [&l = opencode_file_location](const auto& e) { return e.first.opencode_file_location == l; });
std::erase_if(cache_, [](const auto& e) { return e.first.related_open_code.expired(); });
}

} // namespace hlasm_plugin::parser_library::workspaces
113 changes: 84 additions & 29 deletions parser_library/src/workspaces/macro_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,24 @@
#ifndef HLASMPLUGIN_PARSERLIBRARY_MACRO_CACHE_H
#define HLASMPLUGIN_PARSERLIBRARY_MACRO_CACHE_H

#include <compare>
#include <map>
#include <memory>

#include "analyzer.h"
#include <variant>
#include <vector>

#include "context/copy_member.h"
#include "context/id_storage.h"
#include "lsp/macro_info.h"
#include "parse_lib_provider.h"
#include "protocol.h"

namespace hlasm_plugin::parser_library {
class analyzer;
} // namespace hlasm_plugin::parser_library
namespace hlasm_plugin::parser_library::context {
class hlasm_context;
} // namespace hlasm_plugin::parser_library::context

namespace hlasm_plugin::parser_library::workspaces {

Expand All @@ -29,6 +44,53 @@ struct cached_opsyn_mnemo
context::id_index from_instr;
context::id_index to_instr;
bool is_macro;

constexpr auto operator<=>(const cached_opsyn_mnemo&) const = default;
};

template<typename T>
class comparable_weak_ptr
{
std::weak_ptr<T> ptr;
T* direct_ptr;

public:
explicit comparable_weak_ptr(const std::shared_ptr<T>& s)
: ptr(s)
, direct_ptr(s.get())
{}

bool expired() const { return ptr.expired(); }
auto lock() const { return ptr.lock(); }

bool operator==(const comparable_weak_ptr& o) const
{
if (ptr.owner_before(o.ptr) || o.ptr.owner_before(ptr))
return false;
return std::compare_three_way()(direct_ptr, o.direct_ptr);
}
auto operator<=>(const comparable_weak_ptr& o) const
{
if (ptr.owner_before(o.ptr))
return std::strong_ordering::less;
if (o.ptr.owner_before(ptr))
return std::strong_ordering::greater;
return std::compare_three_way()(direct_ptr, o.direct_ptr);
}
bool operator==(const std::shared_ptr<T>& o) const
{
if (ptr.owner_before(o) || o.owner_before(ptr))
return false;
return std::compare_three_way()(direct_ptr, o.get());
}
auto operator<=>(const std::shared_ptr<T>& o) const
{
if (ptr.owner_before(o))
return std::strong_ordering::less;
if (o.owner_before(ptr))
return std::strong_ordering::greater;
return std::compare_three_way()(direct_ptr, o.get());
}
};

// Contains all the context that affects parsing an external file (macro or copy member)
Expand All @@ -37,32 +99,27 @@ struct macro_cache_key
[[nodiscard]] static macro_cache_key create_from_context(context::hlasm_context& hlasm_ctx, library_data data);
static void sort_opsyn_state(std::vector<cached_opsyn_mnemo>& opsyn_state);
static std::vector<cached_opsyn_mnemo> get_opsyn_state(context::hlasm_context& hlasm_ctx);
utils::resource::resource_location opencode_file_location;

comparable_weak_ptr<context::id_storage> related_open_code;
library_data data;
std::vector<cached_opsyn_mnemo> opsyn_state;
};

bool inline operator<(const cached_opsyn_mnemo& lhs, const cached_opsyn_mnemo& rhs)
{
const static auto tie_cached_opsyn_mnemo = [](const cached_opsyn_mnemo& item) {
return std::tie(item.from_instr, item.to_instr, item.is_macro);
};

return tie_cached_opsyn_mnemo(lhs) < tie_cached_opsyn_mnemo(rhs);
}
bool inline operator==(const cached_opsyn_mnemo& lhs, const cached_opsyn_mnemo& rhs)
{
return lhs.from_instr == rhs.from_instr && lhs.to_instr == rhs.to_instr && lhs.is_macro == rhs.is_macro;
}

bool inline operator<(const macro_cache_key& lhs, const macro_cache_key& rhs)
{
const static auto tie_macro_cache_key = [](const macro_cache_key& key) {
return std::tie(key.data.proc_kind, key.data.library_member, key.opsyn_state);
};

return tie_macro_cache_key(lhs) < tie_macro_cache_key(rhs);
}
bool operator==(const macro_cache_key&) const = default;
auto operator<=>(const macro_cache_key& o) const
{
if (auto c = related_open_code <=> o.related_open_code; c != 0)
return c;
if (auto c = data <=> o.data; c != 0)
return c;
if (auto c = opsyn_state.size() <=> o.opsyn_state.size(); c != 0)
return c;
// libc++ still does not support <=> for vector or lexicographical_compare_three_way
for (auto l = opsyn_state.begin(), r = o.opsyn_state.begin(); l != opsyn_state.end(); ++l, ++r)
if (auto c = *l <=> *r; c != 0)
return c;
return std::strong_ordering::equal;
}
};

using version_stamp =
std::unordered_map<utils::resource::resource_location, version_t, utils::resource::resource_location_hasher>;
Expand All @@ -76,7 +133,7 @@ struct macro_cache_data
std::variant<lsp::macro_info_ptr, context::copy_member_ptr> cached_member;
};

class macro_cache final : public diagnosable_impl
class macro_cache final
{
std::map<macro_cache_key, macro_cache_data> cache_;
const file_manager* file_mngr_;
Expand All @@ -88,13 +145,11 @@ class macro_cache final : public diagnosable_impl
// cached macro to the specified context. Returns true, if the macro was loaded.
bool load_from_cache(const macro_cache_key& key, const analyzing_context& ctx) const;
void save_macro(const macro_cache_key& key, const analyzer& analyzer);
void erase_cache_of_opencode(const utils::resource::resource_location& opencode_file_location);
void erase_unused();

private:
[[nodiscard]] const macro_cache_data* find_cached_data(const macro_cache_key& key) const;
[[nodiscard]] version_stamp get_copy_member_versions(context::macro_def_ptr ctx) const;

void collect_diags() const override;
};

} // namespace hlasm_plugin::parser_library::workspaces
Expand Down
4 changes: 4 additions & 0 deletions parser_library/src/workspaces/parse_lib_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef HLASMPLUGIN_PARSERLIBRARY_PARSE_LIB_PROVIDER_H
#define HLASMPLUGIN_PARSERLIBRARY_PARSE_LIB_PROVIDER_H

#include <compare>
#include <optional>
#include <string>
#include <string_view>
Expand All @@ -33,7 +34,10 @@ struct library_data
{
processing::processing_kind proc_kind;
context::id_index library_member;

constexpr auto operator<=>(const library_data&) const = default;
};

// Interface that the analyzer uses to parse macros and COPY files in separate files (libraries).
class parse_lib_provider
{
Expand Down
2 changes: 1 addition & 1 deletion parser_library/src/workspaces/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class processor_file : public processor
virtual const lsp::lsp_context* get_lsp_context() = 0;
virtual const std::set<utils::resource::resource_location>& files_to_close() = 0;
virtual const performance_metrics& get_metrics() = 0;
virtual void erase_cache_of_opencode(const utils::resource::resource_location& opencode_file_location) = 0;
virtual void erase_unused_cache_entries() = 0;
virtual bool has_lsp_info() const = 0;
virtual void retrieve_fade_messages(std::vector<fade_message_s>& fms) const = 0;
virtual const file_location& get_location() const = 0;
Expand Down
29 changes: 10 additions & 19 deletions parser_library/src/workspaces/processor_file_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ parse_result processor_file_impl::parse(parse_lib_provider& lib_provider,
collect_diags_from_child(*new_analyzer);

last_analyzer_ = std::move(new_analyzer);
last_analyzer_opencode_ = true;
last_analyzer_with_lsp = collect_hl;
last_hl_info_ = last_analyzer_->source_processor().semantic_tokens();

dependencies_.clear();
for (auto& file : last_analyzer_->hlasm_ctx().get_visited_files())
Expand Down Expand Up @@ -100,7 +100,7 @@ parse_result processor_file_impl::parse_macro(

const bool collect_hl = should_collect_hl(ctx.hlasm_ctx.get());
auto fms = std::make_shared<std::vector<fade_message_s>>();
auto a = std::make_unique<analyzer>(file_->get_text(),
analyzer a(file_->get_text(),
analyzer_options {
file_->get_location(),
&lib_provider,
Expand All @@ -110,18 +110,18 @@ parse_result processor_file_impl::parse_macro(
fms,
});

a->analyze(cancel_);
a.analyze(cancel_);

if (cancel_ && *cancel_)
return false;

diags().clear();
collect_diags_from_child(*a);
collect_diags_from_child(a);

macro_cache_.save_macro(cache_key, *a);
last_analyzer_ = std::move(a);
last_analyzer_opencode_ = false;
macro_cache_.save_macro(cache_key, a);
last_analyzer_with_lsp = collect_hl;
if (collect_hl)
last_hl_info_ = a.source_processor().semantic_tokens();

fade_messages_ = std::move(fms);

Expand All @@ -130,14 +130,7 @@ parse_result processor_file_impl::parse_macro(

const std::set<utils::resource::resource_location>& processor_file_impl::dependencies() { return dependencies_; }

const semantics::lines_info& processor_file_impl::get_hl_info()
{
if (last_analyzer_)
return last_analyzer_->source_processor().semantic_tokens();

const static semantics::lines_info empty_lines;
return empty_lines;
}
const semantics::lines_info& processor_file_impl::get_hl_info() { return last_hl_info_; }

const lsp::lsp_context* processor_file_impl::get_lsp_context()
{
Expand All @@ -157,10 +150,7 @@ const performance_metrics& processor_file_impl::get_metrics()
return metrics;
}

void processor_file_impl::erase_cache_of_opencode(const utils::resource::resource_location& opencode_file_location)
{
macro_cache_.erase_cache_of_opencode(opencode_file_location);
}
void processor_file_impl::erase_unused_cache_entries() { macro_cache_.erase_unused(); }

bool processor_file_impl::should_collect_hl(context::hlasm_context* ctx) const
{
Expand Down Expand Up @@ -189,6 +179,7 @@ bool processor_file_impl::current_version() const
void processor_file_impl::update_source()
{
last_analyzer_.reset();
last_hl_info_.clear();
used_files.clear();
file_ = file_mngr_.add_file(get_location());
macro_cache_ = macro_cache(file_mngr_, file_);
Expand Down
Loading

0 comments on commit 0bd9a96

Please sign in to comment.