Fix method tracing in non-debuggable runtimes
There are a few fixes needed for correctly supporting method tracing in
non-debuggable runtimes:
1. When we start method tracing we report method entry events for
methods already on the stack with the expectation that method exit
events would be called when method finishes. In non-debuggable
runtimes some of these may not support method exit events, so report
method entry events only if the frame supports them.
2. When method tracing is enabled, we switch the runtime to debuggable.
When we switch to debuggable runtime, we missed updating entrypoints
and deoptimizing boot image. Fix it so we get method entry / exit
events for all methods.
Also updates test 2246-method-trace to work in non-debuggable runtimes.
Bug: 259258187
Test: art/testrunner.py -t 2246
Change-Id: I040416c7cb72062c02312eedb5bcd41da09e53dc
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 13c2b57..104c465 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -457,6 +457,30 @@
runtime->GetClassLinker()->VisitClasses(&visitor);
}
+bool Instrumentation::MethodSupportsExitEvents(ArtMethod* method,
+ const OatQuickMethodHeader* header) {
+ if (header == nullptr) {
+ // Header can be a nullptr for runtime / proxy methods that doesn't support method exit hooks
+ // or for native methods that use generic jni stubs. Generic jni stubs support method exit
+ // hooks.
+ return method->IsNative();
+ }
+
+ if (header->IsNterpMethodHeader()) {
+ // Nterp doesn't support method exit events
+ return false;
+ }
+
+ DCHECK(header->IsOptimized());
+ if (CodeInfo::IsDebuggable(header->GetOptimizedCodeInfoPtr())) {
+ // For optimized code, we only support method entry / exit hooks if they are compiled as
+ // debuggable.
+ return true;
+ }
+
+ return false;
+}
+
// Places the instrumentation exit pc as the return PC for every quick frame. This also allows
// deoptimization of quick frames to interpreter frames. When force_deopt is
// true the frames have to be deoptimized. If the frame has a deoptimization
@@ -508,9 +532,15 @@
LOG(INFO) << " Processing quick frame for updating exit hooks " << DescribeLocation();
}
- // Record the method so we can call method entry callbacks for all non-runtime methods on
- // the stack. Runtime methods don't need method entry callbacks.
- stack_methods_.push_back(m);
+ const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
+ if (Runtime::Current()->GetInstrumentation()->MethodSupportsExitEvents(m, method_header)) {
+ // It is unexpected to see a method enter event but not a method exit event so record stack
+ // methods only for frames that support method exit events. Even if we deoptimize we make
+ // sure that we only call method exit event if the frame supported it in the first place.
+ // For ex: deoptimizing from JITed code with debug support calls a method exit hook but
+ // deoptimizing from nterp doesn't.
+ stack_methods_.push_back(m);
+ }
// If it is a JITed frame then just set the deopt bit if required otherwise continue.
// We need kForceDeoptForRedefinition to ensure we don't use any JITed code after a
@@ -519,7 +549,6 @@
// The CheckCallerForDeopt is an optimization which we only do for non-native JITed code for
// now. We can extend it to native methods but that needs reserving an additional stack slot.
// We don't do it currently since that wasn't important for debugger performance.
- const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
if (method_header != nullptr && method_header->HasShouldDeoptimizeFlag()) {
if (deopt_all_frames_) {
runtime_methods_need_deopt_check_ = true;
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 390d84a..aecad1f 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -47,6 +47,7 @@
template <typename T> class MutableHandle;
struct NthCallerVisitor;
union JValue;
+class OatQuickMethodHeader;
class SHARED_LOCKABLE ReaderWriterMutex;
class ShadowFrame;
class Thread;
@@ -603,6 +604,9 @@
InstrumentationLevel GetCurrentInstrumentationLevel() const;
+ bool MethodSupportsExitEvents(ArtMethod* method, const OatQuickMethodHeader* header)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
private:
// Returns true if moving to the given instrumentation level requires the installation of stubs.
// False otherwise.
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index eb9b471..1dc9009 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -476,6 +476,12 @@
} else {
HandleOptimizingDeoptimization(method, new_frame, updated_vregs);
}
+ // Update if method exit event needs to be reported. We should report exit event only if we
+ // have reported an entry event. So tell interpreter if/ an entry event was reported.
+ bool supports_exit_events =
+ Runtime::Current()->GetInstrumentation()->MethodSupportsExitEvents(
+ method, GetCurrentOatQuickMethodHeader());
+ new_frame->SetSkipMethodExitEvents(!supports_exit_events);
if (updated_vregs != nullptr) {
// Calling Thread::RemoveDebuggerShadowFrameMapping will also delete the updated_vregs
// array so this must come after we processed the frame.
diff --git a/runtime/trace.cc b/runtime/trace.cc
index eb0c04e..387816f 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -424,6 +424,8 @@
jit->GetJitCompiler()->SetDebuggableCompilerOption(true);
}
runtime->SetRuntimeDebugState(art::Runtime::RuntimeDebugState::kJavaDebuggable);
+ runtime->GetInstrumentation()->UpdateEntrypointsForDebuggable();
+ runtime->DeoptimizeBootImage();
}
runtime->GetInstrumentation()->AddListener(
the_trace_,
diff --git a/test/2246-trace-stream/expected-stdout.debuggable.txt b/test/2246-trace-stream/expected-stdout.debuggable.txt
new file mode 100644
index 0000000..c9d7405
--- /dev/null
+++ b/test/2246-trace-stream/expected-stdout.debuggable.txt
@@ -0,0 +1,72 @@
+.>> TestThread2246 java.lang.Thread run ()V Thread.java
+..>> TestThread2246 Main$$ExternalSyntheticLambda0 run ()V D8$$SyntheticClass
+...>> TestThread2246 Main lambda$main$0 ()V Main.java
+....>> TestThread2246 Main <init> ()V Main.java
+.....>> TestThread2246 java.lang.Object <init> ()V Object.java
+.....<< TestThread2246 java.lang.Object <init> ()V Object.java
+....<< TestThread2246 Main <init> ()V Main.java
+....>> TestThread2246 Main $noinline$doSomeWork ()V Main.java
+.....>> TestThread2246 Main callOuterFunction ()V Main.java
+......>> TestThread2246 Main callLeafFunction ()V Main.java
+......<< TestThread2246 Main callLeafFunction ()V Main.java
+.....<< TestThread2246 Main callOuterFunction ()V Main.java
+.....>> TestThread2246 Main callLeafFunction ()V Main.java
+.....<< TestThread2246 Main callLeafFunction ()V Main.java
+....<< TestThread2246 Main $noinline$doSomeWork ()V Main.java
+...<< TestThread2246 Main lambda$main$0 ()V Main.java
+..<< TestThread2246 Main$$ExternalSyntheticLambda0 run ()V D8$$SyntheticClass
+.<< TestThread2246 java.lang.Thread run ()V Thread.java
+.>> main Main main ([Ljava/lang/String;)V Main.java
+..>> main Main$VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V Main.java
+...>> main java.lang.reflect.Method invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; Method.java
+....>> main dalvik.system.VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V VMDebug.java
+.....>> main dalvik.system.VMDebug startMethodTracingFd (Ljava/lang/String;IIIZIZ)V VMDebug.java
+.....<< main dalvik.system.VMDebug startMethodTracingFd (Ljava/lang/String;IIIZIZ)V VMDebug.java
+....<< main dalvik.system.VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V VMDebug.java
+...<< main java.lang.reflect.Method invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; Method.java
+..<< main Main$VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V Main.java
+..>> main java.lang.Thread start ()V Thread.java
+...>> main java.lang.ThreadGroup add (Ljava/lang/Thread;)V ThreadGroup.java
+...<< main java.lang.ThreadGroup add (Ljava/lang/Thread;)V ThreadGroup.java
+...>> main java.lang.Thread nativeCreate (Ljava/lang/Thread;JZ)V Thread.java
+...<< main java.lang.Thread nativeCreate (Ljava/lang/Thread;JZ)V Thread.java
+..<< main java.lang.Thread start ()V Thread.java
+..>> main java.lang.Thread join ()V Thread.java
+...>> main java.lang.Thread join (J)V Thread.java
+....>> main java.lang.System currentTimeMillis ()J System.java
+....<< main java.lang.System currentTimeMillis ()J System.java
+....>> main java.lang.Thread isAlive ()Z Thread.java
+....<< main java.lang.Thread isAlive ()Z Thread.java
+....>> main java.lang.Object wait (J)V Object.java
+.....>> main java.lang.Object wait (JI)V Object.java
+.....<< main java.lang.Object wait (JI)V Object.java
+....<< main java.lang.Object wait (J)V Object.java
+....>> main java.lang.Thread isAlive ()Z Thread.java
+....<< main java.lang.Thread isAlive ()Z Thread.java
+...<< main java.lang.Thread join (J)V Thread.java
+..<< main java.lang.Thread join ()V Thread.java
+..>> main Main $noinline$doSomeWork ()V Main.java
+...>> main Main callOuterFunction ()V Main.java
+....>> main Main callLeafFunction ()V Main.java
+....<< main Main callLeafFunction ()V Main.java
+...<< main Main callOuterFunction ()V Main.java
+...>> main Main callLeafFunction ()V Main.java
+...<< main Main callLeafFunction ()V Main.java
+..<< main Main $noinline$doSomeWork ()V Main.java
+..>> main Main doSomeWorkThrow ()V Main.java
+...>> main Main callThrowFunction ()V Main.java
+....>> main java.lang.Exception <init> (Ljava/lang/String;)V Exception.java
+.....>> main java.lang.Throwable <init> (Ljava/lang/String;)V Throwable.java
+......>> main java.lang.Object <init> ()V Object.java
+......<< main java.lang.Object <init> ()V Object.java
+......>> main java.util.Collections emptyList ()Ljava/util/List; Collections.java
+......<< main java.util.Collections emptyList ()Ljava/util/List; Collections.java
+......>> main java.lang.Throwable fillInStackTrace ()Ljava/lang/Throwable; Throwable.java
+.......>> main java.lang.Throwable nativeFillInStackTrace ()Ljava/lang/Object; Throwable.java
+.......<< main java.lang.Throwable nativeFillInStackTrace ()Ljava/lang/Object; Throwable.java
+......<< main java.lang.Throwable fillInStackTrace ()Ljava/lang/Throwable; Throwable.java
+.....<< main java.lang.Throwable <init> (Ljava/lang/String;)V Throwable.java
+....<< main java.lang.Exception <init> (Ljava/lang/String;)V Exception.java
+...<<E main Main callThrowFunction ()V Main.java
+..<< main Main doSomeWorkThrow ()V Main.java
+..>> main Main$VMDebug $noinline$stopMethodTracing ()V Main.java
diff --git a/test/2246-trace-stream/expected-stdout.interpreter.txt b/test/2246-trace-stream/expected-stdout.interpreter.txt
new file mode 100644
index 0000000..c51ce41
--- /dev/null
+++ b/test/2246-trace-stream/expected-stdout.interpreter.txt
@@ -0,0 +1,68 @@
+.>> TestThread2246 java.lang.Thread run ()V Thread.java
+..>> TestThread2246 Main$$ExternalSyntheticLambda0 run ()V D8$$SyntheticClass
+...>> TestThread2246 Main lambda$main$0 ()V Main.java
+....>> TestThread2246 Main <init> ()V Main.java
+.....>> TestThread2246 java.lang.Object <init> ()V Object.java
+.....<< TestThread2246 java.lang.Object <init> ()V Object.java
+....<< TestThread2246 Main <init> ()V Main.java
+....>> TestThread2246 Main $noinline$doSomeWork ()V Main.java
+.....>> TestThread2246 Main callOuterFunction ()V Main.java
+......>> TestThread2246 Main callLeafFunction ()V Main.java
+......<< TestThread2246 Main callLeafFunction ()V Main.java
+.....<< TestThread2246 Main callOuterFunction ()V Main.java
+.....>> TestThread2246 Main callLeafFunction ()V Main.java
+.....<< TestThread2246 Main callLeafFunction ()V Main.java
+....<< TestThread2246 Main $noinline$doSomeWork ()V Main.java
+...<< TestThread2246 Main lambda$main$0 ()V Main.java
+..<< TestThread2246 Main$$ExternalSyntheticLambda0 run ()V D8$$SyntheticClass
+.<< TestThread2246 java.lang.Thread run ()V Thread.java
+.>> main Main main ([Ljava/lang/String;)V Main.java
+..>> main Main$VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V Main.java
+...>> main dalvik.system.VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V VMDebug.java
+...<< main dalvik.system.VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V VMDebug.java
+..<< main Main$VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V Main.java
+..>> main java.lang.Thread start ()V Thread.java
+...>> main java.lang.ThreadGroup add (Ljava/lang/Thread;)V ThreadGroup.java
+...<< main java.lang.ThreadGroup add (Ljava/lang/Thread;)V ThreadGroup.java
+...>> main java.lang.Thread nativeCreate (Ljava/lang/Thread;JZ)V Thread.java
+...<< main java.lang.Thread nativeCreate (Ljava/lang/Thread;JZ)V Thread.java
+..<< main java.lang.Thread start ()V Thread.java
+..>> main java.lang.Thread join ()V Thread.java
+...>> main java.lang.Thread join (J)V Thread.java
+....>> main java.lang.System currentTimeMillis ()J System.java
+....<< main java.lang.System currentTimeMillis ()J System.java
+....>> main java.lang.Thread isAlive ()Z Thread.java
+....<< main java.lang.Thread isAlive ()Z Thread.java
+....>> main java.lang.Object wait (J)V Object.java
+.....>> main java.lang.Object wait (JI)V Object.java
+.....<< main java.lang.Object wait (JI)V Object.java
+....<< main java.lang.Object wait (J)V Object.java
+....>> main java.lang.Thread isAlive ()Z Thread.java
+....<< main java.lang.Thread isAlive ()Z Thread.java
+...<< main java.lang.Thread join (J)V Thread.java
+..<< main java.lang.Thread join ()V Thread.java
+..>> main Main $noinline$doSomeWork ()V Main.java
+...>> main Main callOuterFunction ()V Main.java
+....>> main Main callLeafFunction ()V Main.java
+....<< main Main callLeafFunction ()V Main.java
+...<< main Main callOuterFunction ()V Main.java
+...>> main Main callLeafFunction ()V Main.java
+...<< main Main callLeafFunction ()V Main.java
+..<< main Main $noinline$doSomeWork ()V Main.java
+..>> main Main doSomeWorkThrow ()V Main.java
+...>> main Main callThrowFunction ()V Main.java
+....>> main java.lang.Exception <init> (Ljava/lang/String;)V Exception.java
+.....>> main java.lang.Throwable <init> (Ljava/lang/String;)V Throwable.java
+......>> main java.lang.Object <init> ()V Object.java
+......<< main java.lang.Object <init> ()V Object.java
+......>> main java.util.Collections emptyList ()Ljava/util/List; Collections.java
+......<< main java.util.Collections emptyList ()Ljava/util/List; Collections.java
+......>> main java.lang.Throwable fillInStackTrace ()Ljava/lang/Throwable; Throwable.java
+.......>> main java.lang.Throwable nativeFillInStackTrace ()Ljava/lang/Object; Throwable.java
+.......<< main java.lang.Throwable nativeFillInStackTrace ()Ljava/lang/Object; Throwable.java
+......<< main java.lang.Throwable fillInStackTrace ()Ljava/lang/Throwable; Throwable.java
+.....<< main java.lang.Throwable <init> (Ljava/lang/String;)V Throwable.java
+....<< main java.lang.Exception <init> (Ljava/lang/String;)V Exception.java
+...<<E main Main callThrowFunction ()V Main.java
+..<< main Main doSomeWorkThrow ()V Main.java
+..>> main Main$VMDebug $noinline$stopMethodTracing ()V Main.java
diff --git a/test/2246-trace-stream/expected-stdout.txt b/test/2246-trace-stream/expected-stdout.txt
index 0ee77f6..76d68f8 100644
--- a/test/2246-trace-stream/expected-stdout.txt
+++ b/test/2246-trace-stream/expected-stdout.txt
@@ -5,68 +5,59 @@
.....>> TestThread2246 java.lang.Object <init> ()V Object.java
.....<< TestThread2246 java.lang.Object <init> ()V Object.java
....<< TestThread2246 Main <init> ()V Main.java
-....>> TestThread2246 Main doSomeWork ()V Main.java
+....>> TestThread2246 Main $noinline$doSomeWork ()V Main.java
.....>> TestThread2246 Main callOuterFunction ()V Main.java
......>> TestThread2246 Main callLeafFunction ()V Main.java
......<< TestThread2246 Main callLeafFunction ()V Main.java
.....<< TestThread2246 Main callOuterFunction ()V Main.java
.....>> TestThread2246 Main callLeafFunction ()V Main.java
.....<< TestThread2246 Main callLeafFunction ()V Main.java
-....<< TestThread2246 Main doSomeWork ()V Main.java
+....<< TestThread2246 Main $noinline$doSomeWork ()V Main.java
...<< TestThread2246 Main lambda$main$0 ()V Main.java
..<< TestThread2246 Main$$ExternalSyntheticLambda0 run ()V D8$$SyntheticClass
.<< TestThread2246 java.lang.Thread run ()V Thread.java
-.>> main Main main ([Ljava/lang/String;)V Main.java
-..>> main Main$VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V Main.java
-...>> main java.lang.reflect.Method invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; Method.java
-....>> main dalvik.system.VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V VMDebug.java
-.....>> main dalvik.system.VMDebug startMethodTracingFd (Ljava/lang/String;IIIZIZ)V VMDebug.java
-.....<< main dalvik.system.VMDebug startMethodTracingFd (Ljava/lang/String;IIIZIZ)V VMDebug.java
-....<< main dalvik.system.VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V VMDebug.java
-...<< main java.lang.reflect.Method invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; Method.java
-..<< main Main$VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V Main.java
-..>> main java.lang.Thread start ()V Thread.java
-...>> main java.lang.ThreadGroup add (Ljava/lang/Thread;)V ThreadGroup.java
-...<< main java.lang.ThreadGroup add (Ljava/lang/Thread;)V ThreadGroup.java
-...>> main java.lang.Thread nativeCreate (Ljava/lang/Thread;JZ)V Thread.java
-...<< main java.lang.Thread nativeCreate (Ljava/lang/Thread;JZ)V Thread.java
-..<< main java.lang.Thread start ()V Thread.java
-..>> main java.lang.Thread join ()V Thread.java
-...>> main java.lang.Thread join (J)V Thread.java
-....>> main java.lang.System currentTimeMillis ()J System.java
-....<< main java.lang.System currentTimeMillis ()J System.java
-....>> main java.lang.Thread isAlive ()Z Thread.java
-....<< main java.lang.Thread isAlive ()Z Thread.java
-....>> main java.lang.Object wait (J)V Object.java
-.....>> main java.lang.Object wait (JI)V Object.java
-.....<< main java.lang.Object wait (JI)V Object.java
-....<< main java.lang.Object wait (J)V Object.java
-....>> main java.lang.Thread isAlive ()Z Thread.java
-....<< main java.lang.Thread isAlive ()Z Thread.java
-...<< main java.lang.Thread join (J)V Thread.java
-..<< main java.lang.Thread join ()V Thread.java
-..>> main Main doSomeWork ()V Main.java
-...>> main Main callOuterFunction ()V Main.java
-....>> main Main callLeafFunction ()V Main.java
-....<< main Main callLeafFunction ()V Main.java
-...<< main Main callOuterFunction ()V Main.java
+.>> main java.lang.Thread start ()V Thread.java
+..>> main java.lang.ThreadGroup add (Ljava/lang/Thread;)V ThreadGroup.java
+..<< main java.lang.ThreadGroup add (Ljava/lang/Thread;)V ThreadGroup.java
+..>> main java.lang.Thread nativeCreate (Ljava/lang/Thread;JZ)V Thread.java
+..<< main java.lang.Thread nativeCreate (Ljava/lang/Thread;JZ)V Thread.java
+.<< main java.lang.Thread start ()V Thread.java
+.>> main java.lang.Thread join ()V Thread.java
+..>> main java.lang.Thread join (J)V Thread.java
+...>> main java.lang.System currentTimeMillis ()J System.java
+...<< main java.lang.System currentTimeMillis ()J System.java
+...>> main java.lang.Thread isAlive ()Z Thread.java
+...<< main java.lang.Thread isAlive ()Z Thread.java
+...>> main java.lang.Object wait (J)V Object.java
+....>> main java.lang.Object wait (JI)V Object.java
+....<< main java.lang.Object wait (JI)V Object.java
+...<< main java.lang.Object wait (J)V Object.java
+...>> main java.lang.Thread isAlive ()Z Thread.java
+...<< main java.lang.Thread isAlive ()Z Thread.java
+..<< main java.lang.Thread join (J)V Thread.java
+.<< main java.lang.Thread join ()V Thread.java
+.>> main Main $noinline$doSomeWork ()V Main.java
+..>> main Main callOuterFunction ()V Main.java
...>> main Main callLeafFunction ()V Main.java
...<< main Main callLeafFunction ()V Main.java
-..<< main Main doSomeWork ()V Main.java
-..>> main Main doSomeWorkThrow ()V Main.java
-...>> main Main callThrowFunction ()V Main.java
-....>> main java.lang.Exception <init> (Ljava/lang/String;)V Exception.java
-.....>> main java.lang.Throwable <init> (Ljava/lang/String;)V Throwable.java
-......>> main java.lang.Object <init> ()V Object.java
-......<< main java.lang.Object <init> ()V Object.java
-......>> main java.util.Collections emptyList ()Ljava/util/List; Collections.java
-......<< main java.util.Collections emptyList ()Ljava/util/List; Collections.java
-......>> main java.lang.Throwable fillInStackTrace ()Ljava/lang/Throwable; Throwable.java
-.......>> main java.lang.Throwable nativeFillInStackTrace ()Ljava/lang/Object; Throwable.java
-.......<< main java.lang.Throwable nativeFillInStackTrace ()Ljava/lang/Object; Throwable.java
-......<< main java.lang.Throwable fillInStackTrace ()Ljava/lang/Throwable; Throwable.java
-.....<< main java.lang.Throwable <init> (Ljava/lang/String;)V Throwable.java
-....<< main java.lang.Exception <init> (Ljava/lang/String;)V Exception.java
-...<<E main Main callThrowFunction ()V Main.java
-..<< main Main doSomeWorkThrow ()V Main.java
-..>> main Main$VMDebug stopMethodTracing ()V Main.java
+..<< main Main callOuterFunction ()V Main.java
+..>> main Main callLeafFunction ()V Main.java
+..<< main Main callLeafFunction ()V Main.java
+.<< main Main $noinline$doSomeWork ()V Main.java
+.>> main Main doSomeWorkThrow ()V Main.java
+..>> main Main callThrowFunction ()V Main.java
+...>> main java.lang.Exception <init> (Ljava/lang/String;)V Exception.java
+....>> main java.lang.Throwable <init> (Ljava/lang/String;)V Throwable.java
+.....>> main java.lang.Object <init> ()V Object.java
+.....<< main java.lang.Object <init> ()V Object.java
+.....>> main java.util.Collections emptyList ()Ljava/util/List; Collections.java
+.....<< main java.util.Collections emptyList ()Ljava/util/List; Collections.java
+.....>> main java.lang.Throwable fillInStackTrace ()Ljava/lang/Throwable; Throwable.java
+......>> main java.lang.Throwable nativeFillInStackTrace ()Ljava/lang/Object; Throwable.java
+......<< main java.lang.Throwable nativeFillInStackTrace ()Ljava/lang/Object; Throwable.java
+.....<< main java.lang.Throwable fillInStackTrace ()Ljava/lang/Throwable; Throwable.java
+....<< main java.lang.Throwable <init> (Ljava/lang/String;)V Throwable.java
+...<< main java.lang.Exception <init> (Ljava/lang/String;)V Exception.java
+..<<E main Main callThrowFunction ()V Main.java
+.<< main Main doSomeWorkThrow ()V Main.java
+.>> main Main$VMDebug $noinline$stopMethodTracing ()V Main.java
diff --git a/test/2246-trace-stream/run.py b/test/2246-trace-stream/run.py
index 6881d71..6eb9265 100644
--- a/test/2246-trace-stream/run.py
+++ b/test/2246-trace-stream/run.py
@@ -18,5 +18,15 @@
def run(ctx, args):
# The expected output is different in debuggable and non debuggable. Just
# enable debuggable for now.
- # TODO(mythria): Also add tests for non-debuggable mode.
- ctx.default_run(args, Xcompiler_option=["--debuggable"])
+ ctx.default_run(args)
+
+ print(args);
+ if ("--debuggable" in args.Xcompiler_option):
+ # On debuggable runtimes we disable oat code in boot images right at the start
+ # so we get events for all methods including methods optimized in boot images.
+ ctx.expected_stdout = ctx.expected_stdout.with_suffix(".debuggable.txt")
+ elif ("--interpreter" in args.Xcompiler_option) or args.interpreter:
+ # On forced interpreter runtimes we don't get method events for optimized
+ # methods in boot images but get events for a few more methods that would
+ # have otherwise used nterp.
+ ctx.expected_stdout = ctx.expected_stdout.with_suffix(".interpreter.txt")
diff --git a/test/2246-trace-stream/src/Main.java b/test/2246-trace-stream/src/Main.java
index 39f3216..37870f1 100644
--- a/test/2246-trace-stream/src/Main.java
+++ b/test/2246-trace-stream/src/Main.java
@@ -36,19 +36,19 @@
Main m = new Main();
Thread t = new Thread(() -> {
Main m1 = new Main();
- m1.doSomeWork();
+ m1.$noinline$doSomeWork();
}, "TestThread2246");
try {
if (VMDebug.getMethodTracingMode() != 0) {
- VMDebug.stopMethodTracing();
+ VMDebug.$noinline$stopMethodTracing();
}
VMDebug.startMethodTracing(file.getPath(), out_file.getFD(), 0, 0, false, 0, true);
t.start();
t.join();
- m.doSomeWork();
+ m.$noinline$doSomeWork();
m.doSomeWorkThrow();
- VMDebug.stopMethodTracing();
+ VMDebug.$noinline$stopMethodTracing();
out_file.close();
m.CheckTraceFileFormat(file);
} finally {
@@ -83,7 +83,7 @@
if (!seen_stop_tracing_method) {
System.out.println(event_string);
}
- if (event_string.contains("Main$VMDebug stopMethodTracing")) {
+ if (event_string.contains("Main$VMDebug $noinline$stopMethodTracing")) {
seen_stop_tracing_method = true;
}
}
@@ -111,7 +111,7 @@
public void callLeafFunction() {}
- public void doSomeWork() {
+ public void $noinline$doSomeWork() {
callOuterFunction();
callLeafFunction();
}
@@ -150,7 +150,7 @@
startMethodTracingMethod.invoke(
null, filename, fd, bufferSize, flags, samplingEnabled, intervalUs, streaming);
}
- public static void stopMethodTracing() throws Exception {
+ public static void $noinline$stopMethodTracing() throws Exception {
stopMethodTracingMethod.invoke(null);
}
public static int getMethodTracingMode() throws Exception {