37
37
#include < compare>
38
38
#include < cstdint>
39
39
#include < iomanip>
40
+ #include < iterator>
40
41
#include < map>
41
42
#include < string>
42
43
#include < string_view>
@@ -966,6 +967,168 @@ struct error_entry
966
967
};
967
968
968
969
970
+ // -----------------------------------------------------------------------
971
+ //
972
+ // stable_vector: a simple segmented vector with limited interface
973
+ // that doesn't invalidate by moving memory
974
+ //
975
+ // -----------------------------------------------------------------------
976
+ //
977
+ template <typename T>
978
+ class stable_vector
979
+ {
980
+ static constexpr size_t PageSize = 3 ; // 1'000;
981
+
982
+ std::vector< std::vector<T> > data;
983
+
984
+ auto add_segment () -> void {
985
+ data.push_back ( {} );
986
+ data.back ().reserve (PageSize);
987
+ }
988
+
989
+ public:
990
+ stable_vector () {
991
+ add_segment ();
992
+ }
993
+
994
+ auto empty () const -> bool {
995
+ return data.size () == 1 && data.back ().empty ();
996
+ }
997
+
998
+ auto size () const -> size_t {
999
+ return (data.size () - 1 ) * PageSize + data.back ().size ();
1000
+ }
1001
+
1002
+ auto ssize () const -> ptrdiff_t {
1003
+ return unsafe_narrow<ptrdiff_t >(size ());
1004
+ }
1005
+
1006
+ auto operator [](size_t idx) -> T& {
1007
+ testing.enforce (idx < size ());
1008
+ return data[idx / PageSize][idx % PageSize];
1009
+ }
1010
+
1011
+ auto operator [](size_t idx) const -> T const & {
1012
+ testing.enforce (idx < size ());
1013
+ return data[idx / PageSize][idx % PageSize];
1014
+ }
1015
+
1016
+ auto back () -> T& {
1017
+ return data.back ().back ();
1018
+ }
1019
+
1020
+ auto push_back (T const & t) -> void {
1021
+ if (data.back ().size () == data.back ().capacity ()) {
1022
+ add_segment ();
1023
+ }
1024
+ data.back ().push_back (t);
1025
+ }
1026
+
1027
+ template < class ... Args >
1028
+ auto emplace_back ( Args&&... args ) -> T& {
1029
+ if (data.back ().size () == data.back ().capacity ()) {
1030
+ add_segment ();
1031
+ }
1032
+ return data.back ().emplace_back (CPP2_FORWARD (args)...);
1033
+ }
1034
+
1035
+ auto pop_back () -> void {
1036
+ data.back ().pop_back ();
1037
+ if (data.back ().size () == 0 ) {
1038
+ data.pop_back ();
1039
+ }
1040
+ }
1041
+
1042
+ // -------------------------------------------------------------------
1043
+ // Debug interface
1044
+ //
1045
+ auto debug_print () -> void {
1046
+ std::cout << " stable_vector:\n " ;
1047
+ for (auto i = 0 ; auto & chunk : data) {
1048
+ std::cout << " -- page " << i++ << " --\n " ;
1049
+ for (auto e : chunk) {
1050
+ std::cout << e << ' ' ;
1051
+ }
1052
+ std::cout << " \n " ;
1053
+ }
1054
+ }
1055
+
1056
+ // -------------------------------------------------------------------
1057
+ // Iterator interface
1058
+ //
1059
+ class iterator {
1060
+ stable_vector* v;
1061
+ size_t pos = 0 ;
1062
+ public:
1063
+ using value_type = T;
1064
+ using difference_type = std::ptrdiff_t ;
1065
+ using pointer = T*;
1066
+ using reference = T&;
1067
+ using iterator_category = std::random_access_iterator_tag;
1068
+
1069
+ iterator ( stable_vector* v_ = nullptr , size_t pos_ = 0 ) : v{v_}, pos{pos_} { }
1070
+ auto operator ++ () -> void { if (pos < v->size ()) { ++pos; } }
1071
+ auto operator -- () -> void { if (pos > 0 ) { --pos; } }
1072
+ auto operator += (size_t off) -> void { if (pos + off < v->size ()) { pos += off; } else { pos = v->size (); } }
1073
+ auto operator -= (size_t off) -> void { if (pos - off > 0 ) { pos -= off; } else { pos = 0 ; } }
1074
+ auto operator * () -> T& { return (*v)[pos ]; }
1075
+ auto operator -> () -> T* { return &(*v)[pos ]; }
1076
+ auto operator [] (size_t off) -> T& { return (*v)[pos + off]; }
1077
+ auto operator + (size_t off) -> iterator { auto i = *this ; i += off; return i; }
1078
+ auto operator - (size_t off) -> iterator { auto i = *this ; i -= off; return i; }
1079
+ auto operator - (iterator const & that) -> ptrdiff_t { return pos - that.pos ; }
1080
+ auto operator <=>(iterator const &) const -> std::strong_ordering = default ;
1081
+ };
1082
+
1083
+ class const_iterator {
1084
+ stable_vector const * v;
1085
+ size_t pos = 0 ;
1086
+ public:
1087
+ using value_type = const T;
1088
+ using difference_type = std::ptrdiff_t ;
1089
+ using pointer = T const *;
1090
+ using reference = T const &;
1091
+ using iterator_category = std::random_access_iterator_tag;
1092
+
1093
+ const_iterator ( stable_vector const * v_ = nullptr , size_t pos_ = 0 ) : v{v_}, pos{pos_} { }
1094
+ auto operator ++ () -> void { if (pos < v->size ()) { ++pos; } }
1095
+ auto operator -- () -> void { if (pos > 0 ) { --pos; } }
1096
+ auto operator += (size_t off) -> void { if (pos + off < v->size ()) { pos += off; } else { pos = v->size (); } }
1097
+ auto operator -= (size_t off) -> void { if (pos - off > 0 ) { pos -= off; } else { pos = 0 ; } }
1098
+ auto operator * () -> T const & { return (*v)[pos ]; }
1099
+ auto operator -> () -> T const * { return &(*v)[pos ]; }
1100
+ auto operator [] (size_t off) -> T const & { return (*v)[pos + off]; }
1101
+ auto operator + (size_t off) -> const_iterator { auto i = *this ; i += off; return i; }
1102
+ auto operator - (size_t off) -> const_iterator { auto i = *this ; i -= off; return i; }
1103
+ auto operator - (const_iterator const & that) -> ptrdiff_t { return pos - that.pos ; }
1104
+ auto operator <=>(const_iterator const &) const -> std::strong_ordering = default ;
1105
+ };
1106
+
1107
+ auto begin () -> iterator { return {this , 0 }; }
1108
+ auto end () -> iterator { return {this , size ()}; }
1109
+ auto begin () const -> const_iterator { return {this , 0 }; }
1110
+ auto end () const -> const_iterator { return {this , size ()}; }
1111
+ auto cbegin () const -> const_iterator { return {this , 0 }; }
1112
+ auto cend () const -> const_iterator { return {this , size ()}; }
1113
+ };
1114
+
1115
+ template <typename T>
1116
+ auto operator + (size_t off, typename stable_vector<T>::iterator const & it) -> typename stable_vector<T>::iterator { auto i = it; i += off; return i; }
1117
+
1118
+ template <typename T>
1119
+ auto operator + (size_t off, typename stable_vector<T>::const_iterator const & it) -> typename stable_vector<T>::const_iterator { auto i = it; i += off; return i; }
1120
+
1121
+ // And now jump over to std:: to drop in the size/ssize overloads
1122
+ }
1123
+ namespace std {
1124
+ template <typename T>
1125
+ auto size (cpp2::stable_vector<T> const & v) -> ptrdiff_t { return v. size (); }
1126
+ template <typename T>
1127
+ auto ssize (cpp2::stable_vector<T> const & v) -> ptrdiff_t { return v.ssize (); }
1128
+ }
1129
+ namespace cpp2 {
1130
+
1131
+
969
1132
// -----------------------------------------------------------------------
970
1133
//
971
1134
// Internal instrumentation
@@ -1088,7 +1251,7 @@ std::vector<stackinstr::entry> stackinstr::largest;
1088
1251
// Example: Today I wanted to measure how long get_declaration_of is
1089
1252
// taking. So add this line at the start of that function's body:
1090
1253
//
1091
- // auto guard = scope_timer("get_declaration_of");
1254
+ // auto timer = scope_timer("get_declaration_of");
1092
1255
//
1093
1256
// Recompile cppfront, then run with -verbose:
1094
1257
//
@@ -1115,14 +1278,14 @@ std::vector<stackinstr::entry> stackinstr::largest;
1115
1278
// enclose that in { } with a scope_timer:
1116
1279
//
1117
1280
// {
1118
- // auto guard = scope_timer("get_declaration_of step 1, initial find loop");
1281
+ // auto timer1 = scope_timer("get_declaration_of step 1, initial find loop");
1119
1282
// /* the code I want to measure */
1120
1283
// }
1121
1284
//
1122
1285
// - Immediately after that, install a second timer to measure the
1123
1286
// second loop which covers the entire rest of the function body:
1124
1287
//
1125
- // auto guard2 = scope_timer("get_declaration_of step 2, rest of lookup");
1288
+ // auto timer2 = scope_timer("get_declaration_of step 2, rest of lookup");
1126
1289
// /* followed by the rest of the function's body */
1127
1290
//
1128
1291
// - And, since it's easy, throw in a third timer to measure one
@@ -1132,7 +1295,7 @@ std::vector<stackinstr::entry> stackinstr::largest;
1132
1295
// timer at those points in each loop iteration to measure just
1133
1296
// the sum of all those loop fragments):
1134
1297
//
1135
- // auto guard = scope_timer("get_declaration_of step 2b, 'move this' branch");
1298
+ // auto timer2b = scope_timer("get_declaration_of step 2b, 'move this' branch");
1136
1299
//
1137
1300
// Recompile cppfront and run again with -verbose... sample output:
1138
1301
//
0 commit comments