protovm: improve stacktrace messages Change-Id: I62a38178ef3b44f19b1be96ad6366b0865db47c4
diff --git a/src/protovm/error_handling.h b/src/protovm/error_handling.h index bfbef71..2cac23d 100644 --- a/src/protovm/error_handling.h +++ b/src/protovm/error_handling.h
@@ -23,6 +23,7 @@ #include <new> #include <string> #include <type_traits> +#include <utility> #include <vector> #include "perfetto/base/compiler.h" @@ -69,26 +70,35 @@ return status_abort; \ } while (0) -#define PROTOVM_RETURN(s, ...) \ - do { \ - if (s.IsAbort()) { \ - LogStacktraceMessage(s.stacktrace(), \ - ::perfetto::base::LoggingBasename(__FILE__), \ - __LINE__, ##__VA_ARGS__); \ - } \ - return s; \ +#define PROTOVM_RETURN(s, ...) \ + do { \ + static_assert( \ + std::is_lvalue_reference_v<decltype((s))> && \ + !std::is_reference_v<decltype(s)>, \ + "PROTOVM_RETURN accepts only plain local variables. Supporting " \ + "references or rvalues would prevent NRVO in the normal (not error " \ + "handling) path (see \"return std::move\" in " \ + "PROTOVM_RETURN_IF_NOT_OK). Rvalues should be assigned to a local " \ + "variable before being passed to PROTOVM_RETURN."); \ + if ((s).IsAbort()) { \ + LogStacktraceMessage((s).stacktrace(), \ + ::perfetto::base::LoggingBasename(__FILE__), \ + __LINE__, ##__VA_ARGS__); \ + } \ + return (s); \ } while (0) #define PROTOVM_RETURN_IF_NOT_OK(s, ...) \ do { \ - if (s.IsAbort()) { \ - LogStacktraceMessage(s.stacktrace(), \ + auto&& status_or = (s); \ + if (status_or.IsAbort()) { \ + LogStacktraceMessage(status_or.stacktrace(), \ ::perfetto::base::LoggingBasename(__FILE__), \ __LINE__, ##__VA_ARGS__); \ - return s; \ + return std::move(status_or); \ } \ - if (!s.IsOk()) { \ - return s; \ + if (!status_or.IsOk()) { \ + return std::move(status_or); \ } \ } while (0)
diff --git a/src/protovm/parser.cc b/src/protovm/parser.cc index bc0e1fc..18b2254 100644 --- a/src/protovm/parser.cc +++ b/src/protovm/parser.cc
@@ -69,12 +69,11 @@ const protos::pbzero::VmInstruction::Decoder& instruction) { if (instruction.has_select()) { auto status = ParseSelect(instruction); - PROTOVM_RETURN(status, "select"); + PROTOVM_RETURN(status); } if (instruction.has_reg_load()) { - auto status = ParseRegLoad(instruction); - PROTOVM_RETURN_IF_NOT_OK(status, "reg_load"); + PROTOVM_RETURN_IF_NOT_OK(ParseRegLoad(instruction)); } else if (instruction.has_del()) { PROTOVM_ASSIGN_OR_RETURN(bool is_root, cursors_.dst.IsRoot()); if (cursors_.innermost_saved_dst != nullptr && @@ -89,11 +88,9 @@ PROTOVM_ABORT( "del would invalidate a cursor saved by an enclosing select"); } - auto status = executor_->Delete(&cursors_.dst); - PROTOVM_RETURN_IF_NOT_OK(status, "del"); + PROTOVM_RETURN_IF_NOT_OK(executor_->Delete(&cursors_.dst), "del"); } else if (instruction.has_merge()) { - auto status = ParseMerge(instruction); - PROTOVM_RETURN_IF_NOT_OK(status, "merge"); + PROTOVM_RETURN_IF_NOT_OK(ParseMerge(instruction)); } else if (instruction.has_set()) { auto status = executor_->Set(&cursors_); PROTOVM_RETURN_IF_NOT_OK(status, "set"); @@ -113,8 +110,7 @@ if (merge.del_if_src_empty()) flags |= Executor::MergeFlags::kDelIfSrcEmpty; auto status = executor_->Merge(&cursors_, flags); - PROTOVM_RETURN_IF_NOT_OK(status); - return status; + PROTOVM_RETURN(status, "merge"); } StatusOr<void> Parser::ParseRegLoad( @@ -130,9 +126,7 @@ cursors_.selected = saved_selected; - PROTOVM_RETURN_IF_NOT_OK(status); - - return status; + PROTOVM_RETURN(status, "reg_load"); } StatusOr<void> Parser::ParseSelect( @@ -141,9 +135,10 @@ cursors_.innermost_saved_dst = &saved_cursors.dst; protos::pbzero::VmOpSelect::Decoder select(instruction.select()); - cursors_.selected = !select.has_cursor() - ? CursorEnum::VM_CURSOR_SRC - : static_cast<CursorEnum>(select.cursor()); + CursorEnum selected_cursor = !select.has_cursor() + ? CursorEnum::VM_CURSOR_SRC + : static_cast<CursorEnum>(select.cursor()); + cursors_.selected = selected_cursor; cursors_.create_if_not_exist = select.create_if_not_exist(); if (cursors_.selected == CursorEnum::VM_CURSOR_SRC && @@ -155,7 +150,7 @@ auto status = ParseSelectRec(instruction, select.relative_path()); cursors_ = saved_cursors; - return status; + PROTOVM_RETURN(status, "select (cursor = %d)", selected_cursor); } StatusOr<void> Parser::ParseSelectRec( @@ -260,7 +255,9 @@ PROTOVM_RETURN_IF_NOT_OK(status, "enter field (id = %d)", static_cast<int>(curr_component.field_id())); - return ParseSelectRec(instruction, it_path_component); + auto status_select = ParseSelectRec(instruction, it_path_component); + PROTOVM_RETURN(status_select, "field (id = %d)", + static_cast<int>(curr_component.field_id())); } } // namespace protovm