From 842a3dfc8e674a5f3469b83b4f5f2b528c11e742 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Fri, 10 Nov 2023 10:30:46 +0100 Subject: [PATCH] Reduce string allocations on hot parse path. When waiting for input we pass down strings for a possible error message and the triggering location. In generated code these are always literals. With this patch we do not take them as owning strings, but instead as views into existing strings to minimize allocations. In the case of error messages the created low-level exception objects already had used string_views, so this also aligns the APIs. Closes #1589. --- spicy/runtime/include/parser.h | 11 ++++++----- spicy/runtime/src/parser.cc | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/spicy/runtime/include/parser.h b/spicy/runtime/include/parser.h index 1793bbb751..db742a6535 100644 --- a/spicy/runtime/include/parser.h +++ b/spicy/runtime/include/parser.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -316,7 +317,7 @@ inline auto parsers() { */ class ParseError : public hilti::rt::RecoverableFailure { public: - ParseError(const std::string& msg, const std::string& location = "") : RecoverableFailure(msg, location) {} + ParseError(std::string_view msg, std::string_view location = "") : RecoverableFailure(msg, location) {} ParseError(const hilti::rt::result::Error& e) : RecoverableFailure(e.description()) {} @@ -336,7 +337,7 @@ class Backtrack : public ParseError { class MissingData : public ParseError { public: - MissingData(const std::string& location = "") : ParseError("missing data", location) {} + MissingData(std::string_view location = "") : ParseError("missing data", location) {} ~MissingData() override; /* required to create vtable, see hilti::rt::Exception */ }; @@ -452,8 +453,8 @@ extern void waitForEod(hilti::rt::ValueReference& data, // NO * has been reached */ extern void waitForInput(hilti::rt::ValueReference& data, // NOLINT(google-runtime-references) - const hilti::rt::stream::View& cur, uint64_t min, const std::string& error_msg, - const std::string& location, + const hilti::rt::stream::View& cur, uint64_t min, std::string_view error_msg, + std::string_view location, hilti::rt::StrongReference filters); /** @@ -484,7 +485,7 @@ extern bool waitForInputOrEod(hilti::rt::ValueReference& data * has been reached */ extern void waitForInput(hilti::rt::ValueReference& data, // NOLINT(google-runtime-references) - const hilti::rt::stream::View& cur, const std::string& error_msg, const std::string& location, + const hilti::rt::stream::View& cur, std::string_view error_msg, std::string_view location, const hilti::rt::StrongReference& filters); /** diff --git a/spicy/runtime/src/parser.cc b/spicy/runtime/src/parser.cc index 27e9291279..b684a1837d 100644 --- a/spicy/runtime/src/parser.cc +++ b/spicy/runtime/src/parser.cc @@ -105,14 +105,14 @@ void detail::waitForEod(hilti::rt::ValueReference& data, cons } void detail::waitForInput(hilti::rt::ValueReference& data, const hilti::rt::stream::View& cur, - uint64_t min, const std::string& error_msg, const std::string& location, + uint64_t min, std::string_view error_msg, std::string_view location, hilti::rt::StrongReference filters) { // NOLINT(performance-unnecessary-value-param) while ( min > cur.size() ) if ( ! waitForInputOrEod(data, cur, filters) ) { SPICY_RT_DEBUG_VERBOSE( hilti::rt::fmt("insufficient input at end of data for stream %p (which is not ok here)", data.get())); - throw ParseError(error_msg, location); + throw ParseError(std::string(error_msg), std::string(location)); } } @@ -156,12 +156,12 @@ bool detail::waitForInputOrEod(hilti::rt::ValueReference& dat } void detail::waitForInput(hilti::rt::ValueReference& data, const hilti::rt::stream::View& cur, - const std::string& error_msg, const std::string& location, + std::string_view error_msg, std::string_view location, const hilti::rt::StrongReference& filters) { if ( ! waitForInputOrEod(data, cur, filters) ) { SPICY_RT_DEBUG_VERBOSE( hilti::rt::fmt("insufficient input at end of data for stream %p (which is not ok here)", data.get())); - throw ParseError(error_msg, location); + throw ParseError(std::string(error_msg), std::string(location)); } }