diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ac52a9a666..712e2d932a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,7 @@ +2018-03-20 Stephen Roberts + + * gdb/symtab.c (find_pc_sect_line): now uses binary search. + 2018-03-19 Tom Tromey * rust-exp.y (struct_expr_tail, struct_expr_list): Add plain diff --git a/gdb/symtab.c b/gdb/symtab.c index 894a2537d6..41aaef7582 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3046,8 +3046,6 @@ find_symbol_at_address (CORE_ADDR address) find the one whose first PC is closer than that of the next line in this symtab. */ -/* If it's worth the effort, we could be using a binary search. */ - struct symtab_and_line find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) { @@ -3214,15 +3212,17 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) if (item->pc > pc && (!alt || item->pc < alt->pc)) alt = item; - for (i = 0; i < len; i++, item++) - { - /* Leave prev pointing to the linetable entry for the last line - that started at or before PC. */ - if (item->pc > pc) - break; + auto pc_compare = [](const CORE_ADDR & pc, + const struct linetable_entry & lhs)->bool + { + return pc < lhs.pc; + }; - prev = item; - } + struct linetable_entry *first = item; + struct linetable_entry *last = item + len; + item = std::upper_bound (first, last, pc, pc_compare); + if (item != first) + prev = item - 1; /* Found a matching item. */ /* At this point, prev points at the line whose start addr is <= pc, and item points at the next line. If we ran off the end of the linetable @@ -3247,7 +3247,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) /* If another line (denoted by ITEM) is in the linetable and its PC is after BEST's PC, but before the current BEST_END, then use ITEM's PC as the new best_end. */ - if (best && i < len && item->pc > best->pc + if (best && item < last && item->pc > best->pc && (best_end == 0 || best_end > item->pc)) best_end = item->pc; } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index f155ffee71..ca0dadf36b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-03-20 Stephen Roberts + + * gdb.perf/template-breakpoints.cc: New file. + * gdb.perf/template-breakpoints.exp: New file. + * gdb.perf/template-breakpoints.py: New file. + 2018-03-19 Tom Tromey * gdb.rust/simple.rs (main): Add local variables field1, field2, diff --git a/gdb/testsuite/gdb.perf/template-breakpoints.cc b/gdb/testsuite/gdb.perf/template-breakpoints.cc new file mode 100644 index 0000000000..726270a3a8 --- /dev/null +++ b/gdb/testsuite/gdb.perf/template-breakpoints.cc @@ -0,0 +1,97 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright (C) 2018 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +template +struct ThirdDimension +{ + int + value () const + { + ThirdDimension d3; + return d3.value(); + } +}; + +template +struct ThirdDimension +{ + int + value () const + { + // Please note - this testcase sets a breakpoint on the following line. + // It is therefore sensitive to line numbers. If any changes are made to + // this file, please ensure that the testcase is updated to reflect this. + std::cout << "Value: " << VAL << std::endl; + return VAL; + } +}; + +template +struct SecondDimension +{ + int + value () const + { + SecondDimension d1; + ThirdDimension d2; + return d1.value() + d2.value(); + } +}; + +template +struct SecondDimension +{ + int + value () const + { + ThirdDimension d2; + return d2.value(); + } +}; + +template +struct FirstDimension +{ + int + value () const + { + FirstDimension d1; + SecondDimension d2; + return d1.value() + d2.value(); + } +}; + +template +struct FirstDimension<0, J, K, VAL> +{ + int + value () const + { + SecondDimension<0, J, K, VAL> d2; + return d2.value(); + } +}; + +int +main (int argc, char *argv[]) +{ + FirstDimension product; + std::cout << product.value() << std::endl; + return 0; +} diff --git a/gdb/testsuite/gdb.perf/template-breakpoints.exp b/gdb/testsuite/gdb.perf/template-breakpoints.exp new file mode 100644 index 0000000000..d69553d8ad --- /dev/null +++ b/gdb/testsuite/gdb.perf/template-breakpoints.exp @@ -0,0 +1,65 @@ +# Copyright (C) 2018 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This test case is to test the performance of GDB when setting breakpoints +# on heavily temlatized C++ code. + +# Parameters: +# EXPANSION_DEPTH: knob to control how many times template expansions occur + +load_lib perftest.exp + +if [skip_perf_tests] { + return 0 +} + +standard_testfile .cc +set executable $testfile +set expfile $testfile.exp + +# make check-perf RUNTESTFLAGS='template-breakpoints.exp EXPANSION_DEPTH=40' +if ![info exists EXPANSION_DEPTH] { + set EXPANSION_DEPTH 40 +} + +PerfTest::assemble { + global EXPANSION_DEPTH + global srcdir subdir srcfile + + set compile_flags {c++ debug} + lappend compile_flags "additional_flags=-DEXPANSION_DEPTH=${EXPANSION_DEPTH}" + + if { [gdb_compile "$srcdir/$subdir/$srcfile" ${binfile} executable $compile_flags] != ""} { + return -1 + } + + return 0 +} { + global binfile + + clean_restart $binfile + + if ![runto_main] { + fail "can't run to main" + return -1 + } + + return 0 +} { + + gdb_test "python TemplateBreakpoints().run()" + + return 0 +} diff --git a/gdb/testsuite/gdb.perf/template-breakpoints.py b/gdb/testsuite/gdb.perf/template-breakpoints.py new file mode 100644 index 0000000000..d85941bf33 --- /dev/null +++ b/gdb/testsuite/gdb.perf/template-breakpoints.py @@ -0,0 +1,33 @@ +# Copyright (C) 2018 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from perftest import perftest + +class TemplateBreakpoints (perftest.TestCaseWithBasicMeasurements): + def __init__(self): + super (TemplateBreakpoints, self).__init__ ("template-breakpoints") + + def warm_up(self): + for _ in range(0, 2): + gdb.Breakpoint("template-breakpoints.cc:38").delete() + + def _do_test(self, bpcount): + for _ in range(1, bpcount): + gdb.Breakpoint("template-breakpoints.cc:38").delete() + + def execute_test(self): + for bpcount in range(1, 10): + tfunc = lambda bound_bpcount=bpcount: self._do_test(bound_bpcount) + self.measure.measure(tfunc, bpcount)