diff options
author | 2022-12-19 09:40:18 +0000 | |
---|---|---|
committer | 2023-01-04 15:15:23 +0000 | |
commit | 5497f749b4d35c7b0767d21cb487e2fee293cd07 (patch) | |
tree | ab9d266fa3e38628486b1dcdbdcbd43237851aed | |
parent | 3cde18ddf4a7af5aabd183eab59f052065270f10 (diff) |
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
-rw-r--r-- | runtime/instrumentation.cc | 37 | ||||
-rw-r--r-- | runtime/instrumentation.h | 4 | ||||
-rw-r--r-- | runtime/quick_exception_handler.cc | 6 | ||||
-rw-r--r-- | runtime/trace.cc | 2 | ||||
-rw-r--r-- | test/2246-trace-stream/expected-stdout.debuggable.txt | 72 | ||||
-rw-r--r-- | test/2246-trace-stream/expected-stdout.interpreter.txt | 68 | ||||
-rw-r--r-- | test/2246-trace-stream/expected-stdout.txt | 99 | ||||
-rw-r--r-- | test/2246-trace-stream/run.py | 14 | ||||
-rw-r--r-- | test/2246-trace-stream/src/Main.java | 14 |
9 files changed, 249 insertions, 67 deletions
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 13c2b57821..104c46532b 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -457,6 +457,30 @@ void Instrumentation::UpdateEntrypointsForDebuggable() { 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 @@ void InstrumentationInstallStack(Thread* thread, void* arg, bool deopt_all_frame 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 @@ void InstrumentationInstallStack(Thread* thread, void* arg, bool deopt_all_frame // 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 390d84a87a..aecad1f6e6 100644 --- a/runtime/instrumentation.h +++ b/runtime/instrumentation.h @@ -47,6 +47,7 @@ template <typename T> class Handle; template <typename T> class MutableHandle; struct NthCallerVisitor; union JValue; +class OatQuickMethodHeader; class SHARED_LOCKABLE ReaderWriterMutex; class ShadowFrame; class Thread; @@ -603,6 +604,9 @@ class Instrumentation { 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 eb9b47180f..1dc90097e0 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -476,6 +476,12 @@ class DeoptimizeStackVisitor final : public StackVisitor { } 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 eb0c04eb03..387816fa03 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -424,6 +424,8 @@ void Trace::Start(std::unique_ptr<File>&& trace_file_in, 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 0000000000..c9d7405c8b --- /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 0000000000..c51ce41de7 --- /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 0ee77f61d3..76d68f85c5 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 6881d714c8..6eb92655f8 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 39f3216d02..37870f14c1 100644 --- a/test/2246-trace-stream/src/Main.java +++ b/test/2246-trace-stream/src/Main.java @@ -36,19 +36,19 @@ public class Main { 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 @@ public class Main { 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 class Main { public void callLeafFunction() {} - public void doSomeWork() { + public void $noinline$doSomeWork() { callOuterFunction(); callLeafFunction(); } @@ -150,7 +150,7 @@ public class Main { 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 { |