diff options
-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 { |