Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/native/clr/host/gc-bridge.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <cerrno>
#include <cinttypes>
#include <pthread.h>
#include <semaphore.h>

Expand Down Expand Up @@ -128,13 +129,13 @@ void GCBridge::log_mark_cross_references_args_if_enabled (MarkCrossReferencesArg
return;
}

log_info (LOG_GC, "cross references callback invoked with {} sccs and {} xrefs.", args->ComponentCount, args->CrossReferenceCount);
log_infof (LOG_GC, "cross references callback invoked with %zu sccs and %zu xrefs.", args->ComponentCount, args->CrossReferenceCount);

JNIEnv *env = OSBridge::ensure_jnienv ();

for (size_t i = 0; i < args->ComponentCount; ++i) {
const StronglyConnectedComponent &scc = args->Components [i];
log_info (LOG_GC, "group {} with {} objects", i, scc.Count);
log_infof (LOG_GC, "group %zu with %zu objects", i, scc.Count);
for (size_t j = 0; j < scc.Count; ++j) {
log_handle_context (env, scc.Contexts [j]);
}
Expand All @@ -147,7 +148,7 @@ void GCBridge::log_mark_cross_references_args_if_enabled (MarkCrossReferencesArg
for (size_t i = 0; i < args->CrossReferenceCount; ++i) {
size_t source_index = args->CrossReferences [i].SourceGroupIndex;
size_t dest_index = args->CrossReferences [i].DestinationGroupIndex;
log_info_nocheck_fmt (LOG_GC, "xref [{}] {} -> {}", i, source_index, dest_index);
log_writef (LOG_GC, LogLevel::Info, "xref [%zu] %zu -> %zu", i, source_index, dest_index);
}
}

Expand All @@ -161,10 +162,10 @@ void GCBridge::log_handle_context (JNIEnv *env, HandleContext *ctx) noexcept
jclass java_class = env->GetObjectClass (handle);
if (java_class != nullptr) {
char *class_name = Host::get_java_class_name_for_TypeManager (java_class);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 💡 Native memory — Good, necessary change: wrapping class_name in optional_string() guards the %s conversion. Host::get_java_class_name_for_TypeManager() genuinely returns nullptr on several paths (null/failed Class.getName, OOM on UTF8 conversion — see host-shared.cc), and passing a raw nullptr to a printf %s is undefined behavior (crash on most C libraries), whereas the old std::format {} on a char* silently formatted it. This migration is more robust than the code it replaces, not just equivalent.

Rule: Guard printf %s against nullptr (repo optional_string convention)

log_info (LOG_GC, "gref {:#x} [{}]", reinterpret_cast<intptr_t> (handle), class_name);
log_infof (LOG_GC, "gref 0x%" PRIxPTR " [%s]", reinterpret_cast<uintptr_t> (handle), optional_string (class_name));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 💡 Native C++ — Nice correctness improvement: switching the handle from intptr_t to uintptr_t here means large 64-bit handle addresses (high bit set) now format as plain 0x... hex. The old std::format {:#x} on a signed intptr_t would render negative values as -0x..., which is misleading for a pointer/gref. The explicit 0x prefix + %" PRIxPTR " correctly mirrors the previous {:#x} output for typical values.

Rule: Use unsigned width-matched types for pointer hex formatting

free (class_name);
env->DeleteLocalRef (java_class);
} else {
log_info (LOG_GC, "gref {:#x} [unknown class]", reinterpret_cast<intptr_t> (handle));
log_infof (LOG_GC, "gref 0x%" PRIxPTR " [unknown class]", reinterpret_cast<uintptr_t> (handle));
}
}