Skip to content

Commit

Permalink
Partially revert ecfe25e for performance reasons.
Browse files Browse the repository at this point in the history
ecfe25e: "Fix #25: Overload candidates overflow" was somewhat detrimental for
performance (~5x in MSVC Debug mode), since this code is run on every function
call. So instead of using a std::vector, revert to the statically allocated
10-element array but check for overflows. Since the array (except for the first
element if it is the only one) is only used to generate the ambiguity error
message, just discard addidional elements, keeping track of how many there were
and display that number in the error message if > 0.
  • Loading branch information
Oberon00 committed Jan 28, 2015
1 parent d749496 commit 3495d39
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 11 deletions.
23 changes: 15 additions & 8 deletions luabind/detail/call.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
# include <boost/type_traits/is_void.hpp>
# include <luabind/lua_include.hpp>

# include <vector>

namespace luabind { namespace detail {

struct invoke_context;
Expand Down Expand Up @@ -56,17 +54,22 @@ struct LUABIND_API invoke_context
{
invoke_context()
: best_score((std::numeric_limits<int>::max)())
, candidate_index(0)
, additional_candidates(0)
{}

operator bool() const
{
return candidates.size() == 1;
return candidate_index == 1;
}

void format_error(lua_State* L, function_object const* overloads) const;

std::vector<function_object const*> candidates;
BOOST_STATIC_CONSTANT(int, max_candidates = 10);
function_object const* candidates[max_candidates];
int best_score;
int candidate_index;
int additional_candidates;
};

template <class F, class Signature, class Policies, class IsVoid>
Expand Down Expand Up @@ -264,12 +267,16 @@ invoke_normal
if (score >= 0 && score < ctx.best_score)
{
ctx.best_score = score;
ctx.candidates.clear();
ctx.candidates.push_back(&self);
ctx.candidates[0] = &self;
ctx.candidate_index = 1;
ctx.additional_candidates = 0;
}
else if (score == ctx.best_score)
{
ctx.candidates.push_back(&self);
if (ctx.candidate_index < invoke_context::max_candidates)
ctx.candidates[ctx.candidate_index++] = &self;
else
++ctx.additional_candidates;
}

int results = 0;
Expand All @@ -279,7 +286,7 @@ invoke_normal
results = self.next->call(L, ctx);
}

if (score == ctx.best_score && ctx.candidates.size() == 1)
if (score == ctx.best_score && ctx.candidate_index == 1)
{
# ifndef LUABIND_INVOKE_VOID
result_converter.apply(
Expand Down
11 changes: 9 additions & 2 deletions src/function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ void invoke_context::format_error(
char const* function_name =
overloads->name.empty() ? "<unknown>" : overloads->name.c_str();

if (candidates.empty())
if (candidate_index == 0)
{
lua_pushliteral(L, "No matching overload found, candidates:");
for (function_object const* f = overloads; f != 0; f = f->next)
Expand All @@ -118,12 +118,19 @@ void invoke_context::format_error(
{
// Ambiguous
lua_pushliteral(L, "Ambiguous, candidates:");
for (std::size_t i = 0; i < candidates.size(); ++i)
for (int i = 0; i < candidate_index; ++i)
{
lua_pushliteral(L, "\n");
candidates[i]->format_signature(L, function_name);
lua_concat(L, 3); // Inefficient, but does not use up the stack.
}
if (additional_candidates)
{
BOOST_ASSERT(candidate_index == max_candidates);
lua_pushfstring(L, "\nand %d additional overload(s) not shown",
additional_candidates);
lua_concat(L, 2);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/test_function_overload_overflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ void test_main(lua_State* L)
"void f()\n" // 8
"void f()\n" // 9
"void f()\n" // 10
"void f()"); // 11
"and 1 additional overload(s) not shown"); // 11
}

0 comments on commit 3495d39

Please sign in to comment.