Do not write full method signature in mini-debug-info.
Write only fully qualified method name to reduce the size.
This approximately halves the amount of string data which
in turn reduces the overhead of mini-debug-info from 3.5% to 3%.
Change-Id: Iba9b1d5af77bd90a6c93912ff10bded243d716ce
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index 94e5d76..012a71f 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -1339,8 +1339,9 @@
}
template <typename ElfTypes>
-void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
- const ArrayRef<const MethodDebugInfo>& method_infos) {
+static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
+ const ArrayRef<const MethodDebugInfo>& method_infos,
+ bool with_signature) {
bool generated_mapping_symbol = false;
auto* strtab = builder->GetStrTab();
auto* symtab = builder->GetSymTab();
@@ -1360,22 +1361,31 @@
strtab->Start();
strtab->Write(""); // strtab should start with empty string.
+ std::string last_name;
+ size_t last_name_offset = 0;
for (const MethodDebugInfo& info : method_infos) {
if (info.deduped_) {
continue; // Add symbol only for the first instance.
}
- std::string name = PrettyMethod(info.dex_method_index_, *info.dex_file_, true);
+ std::string name = PrettyMethod(info.dex_method_index_, *info.dex_file_, with_signature);
if (deduped_addresses.find(info.low_pc_) != deduped_addresses.end()) {
name += " [DEDUPED]";
}
+ // If we write method names without signature, we might see the same name multiple times.
+ size_t name_offset = (name == last_name ? last_name_offset : strtab->Write(name));
const auto* text = builder->GetText()->Exists() ? builder->GetText() : nullptr;
const bool is_relative = (text != nullptr);
uint32_t low_pc = info.low_pc_;
// Add in code delta, e.g., thumb bit 0 for Thumb2 code.
low_pc += info.compiled_method_->CodeDelta();
- symtab->Add(strtab->Write(name), text, low_pc,
- is_relative, info.high_pc_ - info.low_pc_, STB_GLOBAL, STT_FUNC);
+ symtab->Add(name_offset,
+ text,
+ low_pc,
+ is_relative,
+ info.high_pc_ - info.low_pc_,
+ STB_GLOBAL,
+ STT_FUNC);
// Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
// instructions, so that disassembler tools can correctly disassemble.
@@ -1388,6 +1398,9 @@
generated_mapping_symbol = true;
}
}
+
+ last_name = std::move(name);
+ last_name_offset = name_offset;
}
strtab->End();
@@ -1403,7 +1416,7 @@
const ArrayRef<const MethodDebugInfo>& method_infos,
CFIFormat cfi_format) {
// Add methods to .symtab.
- WriteDebugSymbols(builder, method_infos);
+ WriteDebugSymbols(builder, method_infos, true /* with_signature */);
// Generate CFI (stack unwinding information).
WriteCFISection(builder, method_infos, cfi_format);
// Write DWARF .debug_* sections.
@@ -1470,7 +1483,7 @@
builder->GetRoData()->WriteNoBitsSection(parent_builder->GetRoData()->GetSize());
builder->SetVirtualAddress(parent_builder->GetText()->GetAddress());
builder->GetText()->WriteNoBitsSection(parent_builder->GetText()->GetSize());
- WriteDebugSymbols(builder.get(), method_infos);
+ WriteDebugSymbols(builder.get(), method_infos, false /* with_signature */);
WriteCFISection(builder.get(), method_infos, DW_DEBUG_FRAME_FORMAT);
builder->End();
CHECK(builder->Good());
diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc
index 77301d2..87656bc 100644
--- a/test/137-cfi/cfi.cc
+++ b/test/137-cfi/cfi.cc
@@ -101,7 +101,12 @@
}
#endif
-extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindInProcess(JNIEnv*, jobject, jint, jboolean) {
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindInProcess(
+ JNIEnv*,
+ jobject,
+ jboolean full_signatrues,
+ jint,
+ jboolean) {
#if __linux__
if (IsPicImage()) {
LOG(INFO) << "Image is pic, in-process unwinding check bypassed.";
@@ -122,14 +127,21 @@
// We cannot really parse an exact stack, as the optimizing compiler may inline some functions.
// This is also risky, as deduping might play a trick on us, so the test needs to make sure that
// only unique functions are being expected.
+ // "mini-debug-info" does not include parameters to save space.
std::vector<std::string> seq = {
"Java_Main_unwindInProcess", // This function.
- "boolean Main.unwindInProcess(int, boolean)", // The corresponding Java native method frame.
+ "Main.unwindInProcess", // The corresponding Java native method frame.
+ "int java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)", // Framework method.
+ "Main.main" // The Java entry method.
+ };
+ std::vector<std::string> full_seq = {
+ "Java_Main_unwindInProcess", // This function.
+ "boolean Main.unwindInProcess(boolean, int, boolean)", // The corresponding Java native method frame.
"int java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)", // Framework method.
"void Main.main(java.lang.String[])" // The Java entry method.
};
- bool result = CheckStack(bt.get(), seq);
+ bool result = CheckStack(bt.get(), full_signatrues ? full_seq : seq);
if (!kCauseSegfault) {
return result ? JNI_TRUE : JNI_FALSE;
} else {
@@ -178,7 +190,11 @@
}
#endif
-extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindOtherProcess(JNIEnv*, jobject, jint pid_int) {
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindOtherProcess(
+ JNIEnv*,
+ jobject,
+ jboolean full_signatrues,
+ jint pid_int) {
#if __linux__
// TODO: What to do on Valgrind?
pid_t pid = static_cast<pid_t>(pid_int);
@@ -214,17 +230,27 @@
if (result) {
// See comment in unwindInProcess for non-exact stack matching.
+ // "mini-debug-info" does not include parameters to save space.
std::vector<std::string> seq = {
// "Java_Main_sleep", // The sleep function being executed in the
// other runtime.
// Note: For some reason, the name isn't
// resolved, so don't look for it right now.
+ "Main.sleep", // The corresponding Java native method frame.
+ "int java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)", // Framework method.
+ "Main.main" // The Java entry method.
+ };
+ std::vector<std::string> full_seq = {
+ // "Java_Main_sleep", // The sleep function being executed in the
+ // other runtime.
+ // Note: For some reason, the name isn't
+ // resolved, so don't look for it right now.
"boolean Main.sleep(int, boolean, double)", // The corresponding Java native method frame.
"int java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)", // Framework method.
"void Main.main(java.lang.String[])" // The Java entry method.
};
- result = CheckStack(bt.get(), seq);
+ result = CheckStack(bt.get(), full_signatrues ? full_seq : seq);
}
if (ptrace(PTRACE_DETACH, pid, 0, 0) != 0) {
diff --git a/test/137-cfi/run b/test/137-cfi/run
index 66575fc..6f4bcfe 100755
--- a/test/137-cfi/run
+++ b/test/137-cfi/run
@@ -15,7 +15,9 @@
# limitations under the License.
# Test with full DWARF debugging information.
-${RUN} "$@" -Xcompiler-option --generate-debug-info
+# Check full signatures of methods.
+${RUN} "$@" -Xcompiler-option --generate-debug-info --args --full-signatures
# Test with minimal compressed debugging information.
+# Check only method names (parameters are omitted to save space).
${RUN} "$@" -Xcompiler-option --generate-mini-debug-info
diff --git a/test/137-cfi/src/Main.java b/test/137-cfi/src/Main.java
index 5474c9b..7755338 100644
--- a/test/137-cfi/src/Main.java
+++ b/test/137-cfi/src/Main.java
@@ -34,19 +34,28 @@
private boolean secondary;
+ private boolean full_signatures;
+
private boolean passed;
- public Main(boolean secondary) {
+ public Main(boolean secondary, boolean full_signatures) {
this.secondary = secondary;
+ this.full_signatures = full_signatures;
}
public static void main(String[] args) throws Exception {
System.loadLibrary(args[0]);
boolean secondary = false;
- if (args.length > 0 && args[args.length - 1].equals("--secondary")) {
+ boolean full_signatures = false;
+ for (String arg : args) {
+ if (arg.equals("--secondary")) {
secondary = true;
+ }
+ if (arg.equals("--full-signatures")) {
+ full_signatures = true;
+ }
}
- new Main(secondary).run();
+ new Main(secondary, full_signatures).run();
}
private void run() {
@@ -96,7 +105,7 @@
throw new RuntimeException(e);
}
- if (!unwindOtherProcess(pid)) {
+ if (!unwindOtherProcess(full_signatures, pid)) {
System.out.println("Unwinding other process failed.");
}
} finally {
@@ -154,7 +163,7 @@
if (b) {
return sleep(2, b, 1.0);
} else {
- return unwindInProcess(1, b);
+ return unwindInProcess(full_signatures, 1, b);
}
}
@@ -162,6 +171,6 @@
public native boolean sleep(int i, boolean b, double dummy);
- public native boolean unwindInProcess(int i, boolean b);
- public native boolean unwindOtherProcess(int pid);
+ public native boolean unwindInProcess(boolean full_signatures, int i, boolean b);
+ public native boolean unwindOtherProcess(boolean full_signatures, int pid);
}
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index e004b6c..63ec2a0 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -74,6 +74,14 @@
fi
ARGS="${ARGS} $1"
shift
+ elif [ "x$1" = "x--args" ]; then
+ shift
+ if [ "x$1" = "x" ]; then
+ echo "$0 missing argument to --args" 1>&2
+ exit 1
+ fi
+ ARGS="${ARGS} $1"
+ shift
elif [ "x$1" = "x-Xcompiler-option" ]; then
shift
option="$1"