@@ -772,7 +772,6 @@ RecordReader::Py_GetStackFrameAndEntryInfo(
772
772
if (list == nullptr ) {
773
773
return nullptr ;
774
774
}
775
-
776
775
while (current_index != 0 && stacks_obtained++ != max_stacks) {
777
776
auto [frame_id, next_index] = d_tree.nextNode (current_index);
778
777
const auto & frame = d_frame_map.at (frame_id);
@@ -872,7 +871,6 @@ RecordReader::Py_GetNativeStackFrame(FrameTree::index_t index, size_t generation
872
871
if (list == nullptr ) {
873
872
return nullptr ;
874
873
}
875
-
876
874
while (current_index != 0 && stacks_obtained++ != max_stacks) {
877
875
auto frame = d_native_frames[current_index - 1 ];
878
876
current_index = frame.index ;
@@ -898,6 +896,18 @@ RecordReader::Py_GetNativeStackFrame(FrameTree::index_t index, size_t generation
898
896
return nullptr ;
899
897
}
900
898
899
+ struct hash_native_index_and_generation
900
+ {
901
+ std::size_t operator ()(std::pair<FrameTree::index_t , size_t > data) const
902
+ {
903
+ // Reduce the risk of the Python frame ID and native frame ID hashing
904
+ // to the same value and cancelling each other out by adding a fixed
905
+ // offset to one of them. Don't worry about collisions with the TID:
906
+ // it's of a fundamentally different type and collisions are unlikely.
907
+ return std::hash<FrameTree::index_t >{}(data.first ) xor std::hash<size_t >{}(data.second );
908
+ }
909
+ };
910
+
901
911
PyObject*
902
912
RecordReader::Py_ListGetNativeStackFrame (
903
913
std::vector<std::pair<FrameTree::index_t , size_t >>& index_generation_list,
@@ -907,7 +917,8 @@ RecordReader::Py_ListGetNativeStackFrame(
907
917
PyErr_SetString (PyExc_RuntimeError, " Stack tracking is disabled" );
908
918
return NULL ;
909
919
}
910
- std::unordered_set<FrameTree::index_t > cached_index;
920
+ using cache_t = std::pair<FrameTree::index_t , size_t >;
921
+ std::unordered_set<cache_t , hash_native_index_and_generation> cached_index;
911
922
PyObject* dict = PyDict_New ();
912
923
for (const auto & it : index_generation_list) {
913
924
const auto & index = it.first ;
@@ -920,10 +931,10 @@ RecordReader::Py_ListGetNativeStackFrame(
920
931
return nullptr ;
921
932
}
922
933
while (current_index != 0 && stacks_obtained++ != max_stacks) {
923
- if (cached_index.find (current_index) != cached_index.end ()) {
934
+ if (cached_index.find (cache_t { current_index, generation} ) != cached_index.end ()) {
924
935
break ;
925
936
} else {
926
- cached_index.insert (current_index);
937
+ cached_index.insert (cache_t { current_index, generation} );
927
938
}
928
939
auto frame = d_native_frames[current_index - 1 ];
929
940
current_index = frame.index ;
0 commit comments