Don't enable intrinsic optimizations in debuggable runtime

We have optimizations that generate code inline for intrinsics instead
of leaving them as invoke for better performance. Some debug features
like method entry / exit or setting a breakpoint on intrinsics wouldn't
work if intrinsics are inlined. So disable those optimizations in
debuggable runtimes.

Also update 988-method-trace test to test intrinsics on JITed code.

Test: art/test.py -t 988
Bug: 279547861
Change-Id: Ic7c61d1b1541ff534faa24ccec5c2d0b574b0537
diff --git a/compiler/optimizing/critical_native_abi_fixup_arm.cc b/compiler/optimizing/critical_native_abi_fixup_arm.cc
index 03fb26b..77e1566 100644
--- a/compiler/optimizing/critical_native_abi_fixup_arm.cc
+++ b/compiler/optimizing/critical_native_abi_fixup_arm.cc
@@ -74,7 +74,8 @@
           dispatch_info,
           kStatic,
           target_method,
-          HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+          HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+          !block->GetGraph()->IsDebuggable());
       // The intrinsic has no side effects and does not need environment or dex cache on ARM.
       new_input->SetSideEffects(SideEffects::None());
       IntrinsicOptimizations opt(new_input);
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index da498d4..4bf62f3 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -1321,7 +1321,8 @@
       dispatch_info,
       kDirect,
       MethodReference(method->GetDexFile(), method->GetDexMethodIndex()),
-      HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+      HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+      !graph_->IsDebuggable());
   HInputsRef inputs = invoke_instruction->GetInputs();
   DCHECK_EQ(inputs.size(), invoke_instruction->GetNumberOfArguments());
   for (size_t index = 0; index != inputs.size(); ++index) {
@@ -1527,7 +1528,8 @@
         invoke_instruction->GetMethodReference(),  // Use existing invoke's method's reference.
         method,
         MethodReference(method->GetDexFile(), method->GetDexMethodIndex()),
-        method->GetMethodIndex());
+        method->GetMethodIndex(),
+        !graph_->IsDebuggable());
     DCHECK_NE(new_invoke->GetIntrinsic(), Intrinsics::kNone);
     HInputsRef inputs = invoke_instruction->GetInputs();
     for (size_t index = 0; index != inputs.size(); ++index) {
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index f9a5138..fee9091 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -469,6 +469,9 @@
   current_block_ = graph_->GetEntryBlock();
   InitializeBlockLocals();
   InitializeParameters();
+  if (graph_->IsDebuggable() && code_generator_->GetCompilerOptions().IsJitCompiler()) {
+    AppendInstruction(new (allocator_) HMethodEntryHook(0u));
+  }
   AppendInstruction(new (allocator_) HGoto(0u));
 
   // Fill the body.
@@ -504,14 +507,21 @@
         dispatch_info,
         invoke_type,
         target_method,
-        HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+        HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+        !graph_->IsDebuggable());
     HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
   }
 
   // Add the return instruction.
   if (return_type_ == DataType::Type::kVoid) {
+    if (graph_->IsDebuggable() && code_generator_->GetCompilerOptions().IsJitCompiler()) {
+      AppendInstruction(new (allocator_) HMethodExitHook(graph_->GetNullConstant(), kNoDexPc));
+    }
     AppendInstruction(new (allocator_) HReturnVoid());
   } else {
+    if (graph_->IsDebuggable() && code_generator_->GetCompilerOptions().IsJitCompiler()) {
+      AppendInstruction(new (allocator_) HMethodExitHook(latest_result_, kNoDexPc));
+    }
     AppendInstruction(new (allocator_) HReturn(latest_result_));
   }
 
@@ -1050,7 +1060,8 @@
         dispatch_info,
         invoke_type,
         resolved_method_reference,
-        HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit);
+        HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit,
+        !graph_->IsDebuggable());
     return HandleStringInit(invoke, operands, shorty);
   }
 
@@ -1063,7 +1074,7 @@
   }
 
   // Try to build an HIR replacement for the intrinsic.
-  if (UNLIKELY(resolved_method->IsIntrinsic())) {
+  if (UNLIKELY(resolved_method->IsIntrinsic()) && !graph_->IsDebuggable()) {
     // All intrinsics are in the primary boot image, so their class can always be referenced
     // and we do not need to rely on the implicit class initialization check. The class should
     // be initialized but we do not require that here.
@@ -1114,7 +1125,8 @@
                                                     dispatch_info,
                                                     invoke_type,
                                                     resolved_method_reference,
-                                                    clinit_check_requirement);
+                                                    clinit_check_requirement,
+                                                    !graph_->IsDebuggable());
     if (clinit_check != nullptr) {
       // Add the class initialization check as last input of `invoke`.
       DCHECK_EQ(clinit_check_requirement, HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit);
@@ -1130,7 +1142,8 @@
                                              method_reference,
                                              resolved_method,
                                              resolved_method_reference,
-                                             /*vtable_index=*/ imt_or_vtable_index);
+                                             /*vtable_index=*/ imt_or_vtable_index,
+                                             !graph_->IsDebuggable());
   } else {
     DCHECK_EQ(invoke_type, kInterface);
     if (kIsDebugBuild) {
@@ -1151,7 +1164,8 @@
                                                resolved_method,
                                                resolved_method_reference,
                                                /*imt_index=*/ imt_or_vtable_index,
-                                               load_kind);
+                                               load_kind,
+                                               !graph_->IsDebuggable());
   }
   return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
 }
@@ -1350,12 +1364,14 @@
                                                         method_reference,
                                                         resolved_method,
                                                         resolved_method_reference,
-                                                        proto_idx);
+                                                        proto_idx,
+                                                        !graph_->IsDebuggable());
   if (!HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false)) {
     return false;
   }
 
-  if (invoke->GetIntrinsic() != Intrinsics::kMethodHandleInvoke &&
+  if (invoke->GetIntrinsic() != Intrinsics::kNone &&
+      invoke->GetIntrinsic() != Intrinsics::kMethodHandleInvoke &&
       invoke->GetIntrinsic() != Intrinsics::kMethodHandleInvokeExact &&
       VarHandleAccessorNeedsReturnTypeCheck(invoke, return_type)) {
     // Type check is needed because VarHandle intrinsics do not type check the retrieved reference.
@@ -1388,7 +1404,8 @@
                                                    call_site_idx,
                                                    return_type,
                                                    dex_pc,
-                                                   method_reference);
+                                                   method_reference,
+                                                   !graph_->IsDebuggable());
   return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
 }
 
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index bf51b5d..0c2fd5d 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -2465,7 +2465,7 @@
       DCHECK(method != nullptr);
       DCHECK(method->IsStatic());
       DCHECK(method->GetDeclaringClass() == system);
-      invoke->SetResolvedMethod(method);
+      invoke->SetResolvedMethod(method, !codegen_->GetGraph()->IsDebuggable());
       // Sharpen the new invoke. Note that we do not update the dex method index of
       // the invoke, as we would need to look it up in the current dex file, and it
       // is unlikely that it exists. The most usual situation for such typed
diff --git a/compiler/optimizing/load_store_analysis_test.cc b/compiler/optimizing/load_store_analysis_test.cc
index 17e7f1f..865febb 100644
--- a/compiler/optimizing/load_store_analysis_test.cc
+++ b/compiler/optimizing/load_store_analysis_test.cc
@@ -894,7 +894,8 @@
                             {},
                             InvokeType::kStatic,
                             { nullptr, 0 },
-                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                            !graph_->IsDebuggable());
   HInstruction* goto_left = new (GetAllocator()) HGoto();
   call_left->AsInvoke()->SetRawInputAt(0, new_inst);
   left->AddInstruction(call_left);
@@ -1003,7 +1004,8 @@
                             {},
                             InvokeType::kStatic,
                             { nullptr, 0 },
-                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                            !graph_->IsDebuggable());
   HInstruction* goto_left = new (GetAllocator()) HGoto();
   call_left->AsInvoke()->SetRawInputAt(0, new_inst);
   left->AddInstruction(call_left);
@@ -1126,7 +1128,8 @@
                             {},
                             InvokeType::kStatic,
                             { nullptr, 0 },
-                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                            !graph_->IsDebuggable());
   HInstruction* goto_left = new (GetAllocator()) HGoto();
   call_left->AsInvoke()->SetRawInputAt(0, new_inst);
   left->AddInstruction(call_left);
@@ -1406,7 +1409,8 @@
                             {},
                             InvokeType::kStatic,
                             {nullptr, 0},
-                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                            !graph_->IsDebuggable());
   HInstruction* goto_left = new (GetAllocator()) HGoto();
   call_left->AsInvoke()->SetRawInputAt(0, new_inst);
   left->AddInstruction(call_left);
@@ -1507,7 +1511,8 @@
                             {},
                             InvokeType::kStatic,
                             { nullptr, 0 },
-                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                            !graph_->IsDebuggable());
   HInstruction* goto_left = new (GetAllocator()) HGoto();
   call_left->AsInvoke()->SetRawInputAt(0, new_inst);
   left->AddInstruction(call_left);
@@ -1618,7 +1623,8 @@
                             {},
                             InvokeType::kStatic,
                             { nullptr, 0 },
-                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                            !graph_->IsDebuggable());
   HInstruction* goto_left = new (GetAllocator()) HGoto();
   call_left->AsInvoke()->SetRawInputAt(0, new_inst);
   left->AddInstruction(call_left);
@@ -1634,7 +1640,8 @@
                             {},
                             InvokeType::kStatic,
                             { nullptr, 0 },
-                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                            !graph_->IsDebuggable());
   HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
                                                                      c0,
                                                                      nullptr,
@@ -1803,7 +1810,8 @@
                             {},
                             InvokeType::kStatic,
                             { nullptr, 0 },
-                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                            !graph_->IsDebuggable());
   HInstruction* goto_left = new (GetAllocator()) HGoto();
   call_left->AsInvoke()->SetRawInputAt(0, new_inst);
   high_left->AddInstruction(call_left);
@@ -1859,7 +1867,8 @@
                             {},
                             InvokeType::kStatic,
                             { nullptr, 0 },
-                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                            !graph_->IsDebuggable());
   HInstruction* goto_low_left = new (GetAllocator()) HGoto();
   call_low_left->AsInvoke()->SetRawInputAt(0, new_inst);
   low_left->AddInstruction(call_low_left);
@@ -2016,7 +2025,8 @@
                             {},
                             InvokeType::kStatic,
                             {nullptr, 0},
-                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                            HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                            !graph_->IsDebuggable());
   HInstruction* goto_left_merge = new (GetAllocator()) HGoto();
   left_phi->SetRawInputAt(0, obj_param);
   left_phi->SetRawInputAt(1, new_inst);
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index c99cfab..3790058 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -3571,8 +3571,8 @@
   return kCanThrow;
 }
 
-void HInvoke::SetResolvedMethod(ArtMethod* method) {
-  if (method != nullptr && method->IsIntrinsic()) {
+void HInvoke::SetResolvedMethod(ArtMethod* method, bool enable_intrinsic_opt) {
+  if (method != nullptr && method->IsIntrinsic() && enable_intrinsic_opt) {
     Intrinsics intrinsic = static_cast<Intrinsics>(method->GetIntrinsic());
     SetIntrinsic(intrinsic,
                  NeedsEnvironmentIntrinsic(intrinsic),
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index fc5d219..28112d1 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4756,7 +4756,7 @@
   bool IsIntrinsic() const { return intrinsic_ != Intrinsics::kNone; }
 
   ArtMethod* GetResolvedMethod() const { return resolved_method_; }
-  void SetResolvedMethod(ArtMethod* method);
+  void SetResolvedMethod(ArtMethod* method, bool enable_intrinsic_opt);
 
   MethodReference GetMethodReference() const { return method_reference_; }
 
@@ -4785,7 +4785,8 @@
           MethodReference method_reference,
           ArtMethod* resolved_method,
           MethodReference resolved_method_reference,
-          InvokeType invoke_type)
+          InvokeType invoke_type,
+          bool enable_intrinsic_opt)
     : HVariableInputSizeInstruction(
           kind,
           return_type,
@@ -4801,7 +4802,7 @@
       intrinsic_optimizations_(0) {
     SetPackedField<InvokeTypeField>(invoke_type);
     SetPackedFlag<kFlagCanThrow>(true);
-    SetResolvedMethod(resolved_method);
+    SetResolvedMethod(resolved_method, enable_intrinsic_opt);
   }
 
   DEFAULT_COPY_CONSTRUCTOR(Invoke);
@@ -4834,7 +4835,8 @@
                 method_reference,
                 nullptr,
                 MethodReference(nullptr, 0u),
-                invoke_type) {
+                invoke_type,
+                /* enable_intrinsic_opt= */ false) {
   }
 
   bool IsClonable() const override { return true; }
@@ -4857,7 +4859,8 @@
                      // to pass intrinsic information to the HInvokePolymorphic node.
                      ArtMethod* resolved_method,
                      MethodReference resolved_method_reference,
-                     dex::ProtoIndex proto_idx)
+                     dex::ProtoIndex proto_idx,
+                     bool enable_intrinsic_opt)
       : HInvoke(kInvokePolymorphic,
                 allocator,
                 number_of_arguments,
@@ -4867,7 +4870,8 @@
                 method_reference,
                 resolved_method,
                 resolved_method_reference,
-                kPolymorphic),
+                kPolymorphic,
+                enable_intrinsic_opt),
         proto_idx_(proto_idx) {
   }
 
@@ -4889,7 +4893,8 @@
                 uint32_t call_site_index,
                 DataType::Type return_type,
                 uint32_t dex_pc,
-                MethodReference method_reference)
+                MethodReference method_reference,
+                bool enable_intrinsic_opt)
       : HInvoke(kInvokeCustom,
                 allocator,
                 number_of_arguments,
@@ -4899,7 +4904,8 @@
                 method_reference,
                 /* resolved_method= */ nullptr,
                 MethodReference(nullptr, 0u),
-                kStatic),
+                kStatic,
+                enable_intrinsic_opt),
       call_site_index_(call_site_index) {
   }
 
@@ -4946,7 +4952,8 @@
                         DispatchInfo dispatch_info,
                         InvokeType invoke_type,
                         MethodReference resolved_method_reference,
-                        ClinitCheckRequirement clinit_check_requirement)
+                        ClinitCheckRequirement clinit_check_requirement,
+                        bool enable_intrinsic_opt)
       : HInvoke(kInvokeStaticOrDirect,
                 allocator,
                 number_of_arguments,
@@ -4959,7 +4966,8 @@
                 method_reference,
                 resolved_method,
                 resolved_method_reference,
-                invoke_type),
+                invoke_type,
+                enable_intrinsic_opt),
         dispatch_info_(dispatch_info) {
     SetPackedField<ClinitCheckRequirementField>(clinit_check_requirement);
   }
@@ -5171,7 +5179,8 @@
                  MethodReference method_reference,
                  ArtMethod* resolved_method,
                  MethodReference resolved_method_reference,
-                 uint32_t vtable_index)
+                 uint32_t vtable_index,
+                 bool enable_intrinsic_opt)
       : HInvoke(kInvokeVirtual,
                 allocator,
                 number_of_arguments,
@@ -5181,7 +5190,8 @@
                 method_reference,
                 resolved_method,
                 resolved_method_reference,
-                kVirtual),
+                kVirtual,
+                enable_intrinsic_opt),
         vtable_index_(vtable_index) {
   }
 
@@ -5233,7 +5243,8 @@
                    ArtMethod* resolved_method,
                    MethodReference resolved_method_reference,
                    uint32_t imt_index,
-                   MethodLoadKind load_kind)
+                   MethodLoadKind load_kind,
+                   bool enable_intrinsic_opt)
       : HInvoke(kInvokeInterface,
                 allocator,
                 number_of_arguments + (NeedsCurrentMethod(load_kind) ? 1 : 0),
@@ -5243,7 +5254,8 @@
                 method_reference,
                 resolved_method,
                 resolved_method_reference,
-                kInterface),
+                kInterface,
+                enable_intrinsic_opt),
         imt_index_(imt_index),
         hidden_argument_load_kind_(load_kind) {
   }
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index f18ffc7..2e05c41 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -461,7 +461,8 @@
                               HInvokeStaticOrDirect::DispatchInfo{},
                               InvokeType::kStatic,
                               /* resolved_method_reference= */ method_reference,
-                              HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+                              HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+                              !graph_->IsDebuggable());
     for (auto [ins, idx] : ZipCount(MakeIterationRange(args))) {
       res->SetRawInputAt(idx, ins);
     }
diff --git a/test/988-method-trace/expected-stdout.txt b/test/988-method-trace/expected-stdout.txt
index 9460503..7ab727b 100644
--- a/test/988-method-trace/expected-stdout.txt
+++ b/test/988-method-trace/expected-stdout.txt
@@ -195,7 +195,7 @@
 .....<= public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace() -> <class java.lang.Error: java.lang.Error: Bad argument: -19 < 0
 	art.Test988.iter_fibonacci(Test988.java:280)
 	art.Test988$IterOp.applyAsInt(Test988.java:275)
-	art.Test988.doFibTest(Test988.java:413)
+	art.Test988.doFibTest(Test988.java:425)
 	art.Test988.run(Test988.java:369)
 	<additional hidden frames>
 >
@@ -214,7 +214,7 @@
 fibonacci(-19) -> java.lang.Error: Bad argument: -19 < 0
 	art.Test988.iter_fibonacci(Test988.java:280)
 	art.Test988$IterOp.applyAsInt(Test988.java:275)
-	art.Test988.doFibTest(Test988.java:413)
+	art.Test988.doFibTest(Test988.java:425)
 	art.Test988.run(Test988.java:369)
 	<additional hidden frames>
 
@@ -323,7 +323,7 @@
 .....<= public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace() -> <class java.lang.Error: java.lang.Error: Bad argument: -19 < 0
 	art.Test988.fibonacci(Test988.java:302)
 	art.Test988$RecurOp.applyAsInt(Test988.java:297)
-	art.Test988.doFibTest(Test988.java:413)
+	art.Test988.doFibTest(Test988.java:425)
 	art.Test988.run(Test988.java:370)
 	<additional hidden frames>
 >
@@ -342,7 +342,7 @@
 fibonacci(-19) -> java.lang.Error: Bad argument: -19 < 0
 	art.Test988.fibonacci(Test988.java:302)
 	art.Test988$RecurOp.applyAsInt(Test988.java:297)
-	art.Test988.doFibTest(Test988.java:413)
+	art.Test988.doFibTest(Test988.java:425)
 	art.Test988.run(Test988.java:370)
 	<additional hidden frames>
 
@@ -369,7 +369,7 @@
 .....<= public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace() -> <class java.lang.Error: java.lang.Error: bad argument
 	art.Test988.nativeFibonacci(Native Method)
 	art.Test988$NativeOp.applyAsInt(Test988.java:312)
-	art.Test988.doFibTest(Test988.java:413)
+	art.Test988.doFibTest(Test988.java:425)
 	art.Test988.run(Test988.java:371)
 	<additional hidden frames>
 >
@@ -388,7 +388,7 @@
 fibonacci(-19) -> java.lang.Error: bad argument
 	art.Test988.nativeFibonacci(Native Method)
 	art.Test988$NativeOp.applyAsInt(Test988.java:312)
-	art.Test988.doFibTest(Test988.java:413)
+	art.Test988.doFibTest(Test988.java:425)
 	art.Test988.run(Test988.java:371)
 	<additional hidden frames>
 
@@ -561,13 +561,13 @@
 ..=> public int java.lang.String.length()
 ..<= public int java.lang.String.length() -> <class java.lang.Integer: 17>
 ..=> public synchronized java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String)
-..<= public synchronized java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String) -> <class java.lang.StringBuffer: some large string bufferhello>
+..<= public synchronized java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String) -> <class java.lang.StringBuffer: some large string bufferhellohello>
 ..=> public synchronized int java.lang.StringBuffer.length()
 ..<= public synchronized int java.lang.StringBuffer.length() -> <class java.lang.Integer: 29>
 ..=> public synchronized java.lang.String java.lang.StringBuffer.toString()
 ..<= public synchronized java.lang.String java.lang.StringBuffer.toString() -> <class java.lang.String: some large string bufferhello>
 ..=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
-..<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: some large string builderhello>
+..<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: some large string builderhellohello>
 ..=> public int java.lang.StringBuilder.length()
 ..<= public int java.lang.StringBuilder.length() -> <class java.lang.Integer: 30>
 ..=> public java.lang.String java.lang.StringBuilder.toString()
@@ -585,3 +585,284 @@
 => public static java.lang.Thread java.lang.Thread.currentThread()
 <= public static java.lang.Thread java.lang.Thread.currentThread() -> <<non-deterministic>: <non-deterministic>>
 => public static void art.Trace.disableTracing(java.lang.Thread)
+<= public static void art.Trace.enableTracing(java.lang.Class,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.Thread) -> <null: null>
+<= public static void art.Trace.enableMethodTracing(java.lang.Class,java.lang.reflect.Method,java.lang.reflect.Method,java.lang.Thread) -> <null: null>
+=> static void art.Test988$IntrinsicsTest.doTest()
+=> static void art.Test988Intrinsics.test()
+.=> public static long java.lang.Double.doubleToRawLongBits(double)
+.<= public static long java.lang.Double.doubleToRawLongBits(double) -> <class java.lang.Long: 0>
+.=> public static long java.lang.Double.doubleToLongBits(double)
+..=> public static boolean java.lang.Double.isNaN(double)
+..<= public static boolean java.lang.Double.isNaN(double) -> <class java.lang.Boolean: false>
+..=> public static long java.lang.Double.doubleToRawLongBits(double)
+..<= public static long java.lang.Double.doubleToRawLongBits(double) -> <class java.lang.Long: 0>
+.<= public static long java.lang.Double.doubleToLongBits(double) -> <class java.lang.Long: 0>
+.=> public static boolean java.lang.Double.isInfinite(double)
+.<= public static boolean java.lang.Double.isInfinite(double) -> <class java.lang.Boolean: false>
+.=> public static boolean java.lang.Double.isNaN(double)
+.<= public static boolean java.lang.Double.isNaN(double) -> <class java.lang.Boolean: false>
+.=> public static double java.lang.Double.longBitsToDouble(long)
+.<= public static double java.lang.Double.longBitsToDouble(long) -> <class java.lang.Double: 0.0>
+.=> public static int java.lang.Float.floatToRawIntBits(float)
+.<= public static int java.lang.Float.floatToRawIntBits(float) -> <class java.lang.Integer: 0>
+.=> public static int java.lang.Float.floatToIntBits(float)
+..=> public static boolean java.lang.Float.isNaN(float)
+..<= public static boolean java.lang.Float.isNaN(float) -> <class java.lang.Boolean: false>
+..=> public static int java.lang.Float.floatToRawIntBits(float)
+..<= public static int java.lang.Float.floatToRawIntBits(float) -> <class java.lang.Integer: 0>
+.<= public static int java.lang.Float.floatToIntBits(float) -> <class java.lang.Integer: 0>
+.=> public static boolean java.lang.Float.isInfinite(float)
+.<= public static boolean java.lang.Float.isInfinite(float) -> <class java.lang.Boolean: false>
+.=> public static boolean java.lang.Float.isNaN(float)
+.<= public static boolean java.lang.Float.isNaN(float) -> <class java.lang.Boolean: false>
+.=> public static float java.lang.Float.intBitsToFloat(int)
+.<= public static float java.lang.Float.intBitsToFloat(int) -> <class java.lang.Float: 0.0>
+.=> public static int java.lang.Integer.reverse(int)
+..=> public static int java.lang.Integer.reverseBytes(int)
+..<= public static int java.lang.Integer.reverseBytes(int) -> <class java.lang.Integer: 0>
+.<= public static int java.lang.Integer.reverse(int) -> <class java.lang.Integer: 0>
+.=> public static int java.lang.Integer.reverseBytes(int)
+.<= public static int java.lang.Integer.reverseBytes(int) -> <class java.lang.Integer: 0>
+.=> public static int java.lang.Integer.bitCount(int)
+.<= public static int java.lang.Integer.bitCount(int) -> <class java.lang.Integer: 0>
+.=> public static int java.lang.Integer.compare(int,int)
+.<= public static int java.lang.Integer.compare(int,int) -> <class java.lang.Integer: 0>
+.=> public static int java.lang.Integer.highestOneBit(int)
+..=> public static int java.lang.Integer.numberOfLeadingZeros(int)
+..<= public static int java.lang.Integer.numberOfLeadingZeros(int) -> <class java.lang.Integer: 32>
+.<= public static int java.lang.Integer.highestOneBit(int) -> <class java.lang.Integer: 0>
+.=> public static int java.lang.Integer.lowestOneBit(int)
+.<= public static int java.lang.Integer.lowestOneBit(int) -> <class java.lang.Integer: 0>
+.=> public static int java.lang.Integer.numberOfLeadingZeros(int)
+.<= public static int java.lang.Integer.numberOfLeadingZeros(int) -> <class java.lang.Integer: 32>
+.=> public static int java.lang.Integer.numberOfTrailingZeros(int)
+.<= public static int java.lang.Integer.numberOfTrailingZeros(int) -> <class java.lang.Integer: 32>
+.=> public static int java.lang.Integer.rotateRight(int,int)
+.<= public static int java.lang.Integer.rotateRight(int,int) -> <class java.lang.Integer: 0>
+.=> public static int java.lang.Integer.rotateLeft(int,int)
+.<= public static int java.lang.Integer.rotateLeft(int,int) -> <class java.lang.Integer: 0>
+.=> public static int java.lang.Integer.signum(int)
+.<= public static int java.lang.Integer.signum(int) -> <class java.lang.Integer: 0>
+.=> public static long java.lang.Long.reverse(long)
+..=> public static long java.lang.Long.reverseBytes(long)
+..<= public static long java.lang.Long.reverseBytes(long) -> <class java.lang.Long: 0>
+.<= public static long java.lang.Long.reverse(long) -> <class java.lang.Long: 0>
+.=> public static long java.lang.Long.reverseBytes(long)
+.<= public static long java.lang.Long.reverseBytes(long) -> <class java.lang.Long: 0>
+.=> public static int java.lang.Long.bitCount(long)
+.<= public static int java.lang.Long.bitCount(long) -> <class java.lang.Integer: 0>
+.=> public static int java.lang.Long.compare(long,long)
+.<= public static int java.lang.Long.compare(long,long) -> <class java.lang.Integer: 0>
+.=> public static long java.lang.Long.highestOneBit(long)
+..=> public static int java.lang.Long.numberOfLeadingZeros(long)
+..<= public static int java.lang.Long.numberOfLeadingZeros(long) -> <class java.lang.Integer: 64>
+.<= public static long java.lang.Long.highestOneBit(long) -> <class java.lang.Long: 0>
+.=> public static long java.lang.Long.lowestOneBit(long)
+.<= public static long java.lang.Long.lowestOneBit(long) -> <class java.lang.Long: 0>
+.=> public static int java.lang.Long.numberOfLeadingZeros(long)
+..=> public static int java.lang.Integer.numberOfLeadingZeros(int)
+..<= public static int java.lang.Integer.numberOfLeadingZeros(int) -> <class java.lang.Integer: 32>
+.<= public static int java.lang.Long.numberOfLeadingZeros(long) -> <class java.lang.Integer: 64>
+.=> public static int java.lang.Long.numberOfTrailingZeros(long)
+..=> public static int java.lang.Integer.numberOfTrailingZeros(int)
+..<= public static int java.lang.Integer.numberOfTrailingZeros(int) -> <class java.lang.Integer: 32>
+.<= public static int java.lang.Long.numberOfTrailingZeros(long) -> <class java.lang.Integer: 64>
+.=> public static long java.lang.Long.rotateRight(long,int)
+.<= public static long java.lang.Long.rotateRight(long,int) -> <class java.lang.Long: 0>
+.=> public static long java.lang.Long.rotateLeft(long,int)
+.<= public static long java.lang.Long.rotateLeft(long,int) -> <class java.lang.Long: 0>
+.=> public static int java.lang.Long.signum(long)
+.<= public static int java.lang.Long.signum(long) -> <class java.lang.Integer: 0>
+.=> public static short java.lang.Short.reverseBytes(short)
+.<= public static short java.lang.Short.reverseBytes(short) -> <class java.lang.Short: 0>
+.=> public static double java.lang.Math.abs(double)
+..=> public static long java.lang.Double.doubleToRawLongBits(double)
+..<= public static long java.lang.Double.doubleToRawLongBits(double) -> <class java.lang.Long: 0>
+..=> public static double java.lang.Double.longBitsToDouble(long)
+..<= public static double java.lang.Double.longBitsToDouble(long) -> <class java.lang.Double: 0.0>
+.<= public static double java.lang.Math.abs(double) -> <class java.lang.Double: 0.0>
+.=> public static float java.lang.Math.abs(float)
+..=> public static int java.lang.Float.floatToRawIntBits(float)
+..<= public static int java.lang.Float.floatToRawIntBits(float) -> <class java.lang.Integer: 0>
+..=> public static float java.lang.Float.intBitsToFloat(int)
+..<= public static float java.lang.Float.intBitsToFloat(int) -> <class java.lang.Float: 0.0>
+.<= public static float java.lang.Math.abs(float) -> <class java.lang.Float: 0.0>
+.=> public static long java.lang.Math.abs(long)
+.<= public static long java.lang.Math.abs(long) -> <class java.lang.Long: 0>
+.=> public static int java.lang.Math.abs(int)
+.<= public static int java.lang.Math.abs(int) -> <class java.lang.Integer: 0>
+.=> public static double java.lang.Math.min(double,double)
+..=> public static long java.lang.Double.doubleToRawLongBits(double)
+..<= public static long java.lang.Double.doubleToRawLongBits(double) -> <class java.lang.Long: 0>
+.<= public static double java.lang.Math.min(double,double) -> <class java.lang.Double: 0.0>
+.=> public static float java.lang.Math.min(float,float)
+..=> public static int java.lang.Float.floatToRawIntBits(float)
+..<= public static int java.lang.Float.floatToRawIntBits(float) -> <class java.lang.Integer: 0>
+.<= public static float java.lang.Math.min(float,float) -> <class java.lang.Float: 0.0>
+.=> public static long java.lang.Math.min(long,long)
+.<= public static long java.lang.Math.min(long,long) -> <class java.lang.Long: 0>
+.=> public static int java.lang.Math.min(int,int)
+.<= public static int java.lang.Math.min(int,int) -> <class java.lang.Integer: 0>
+.=> public static double java.lang.Math.max(double,double)
+..=> public static long java.lang.Double.doubleToRawLongBits(double)
+..<= public static long java.lang.Double.doubleToRawLongBits(double) -> <class java.lang.Long: 0>
+.<= public static double java.lang.Math.max(double,double) -> <class java.lang.Double: 0.0>
+.=> public static float java.lang.Math.max(float,float)
+..=> public static int java.lang.Float.floatToRawIntBits(float)
+..<= public static int java.lang.Float.floatToRawIntBits(float) -> <class java.lang.Integer: 0>
+.<= public static float java.lang.Math.max(float,float) -> <class java.lang.Float: 0.0>
+.=> public static long java.lang.Math.max(long,long)
+.<= public static long java.lang.Math.max(long,long) -> <class java.lang.Long: 0>
+.=> public static int java.lang.Math.max(int,int)
+.<= public static int java.lang.Math.max(int,int) -> <class java.lang.Integer: 0>
+.=> public static double java.lang.Math.cos(double)
+.<= public static double java.lang.Math.cos(double) -> <class java.lang.Double: 1.0>
+.=> public static double java.lang.Math.sin(double)
+.<= public static double java.lang.Math.sin(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.acos(double)
+.<= public static double java.lang.Math.acos(double) -> <class java.lang.Double: 1.5707963267948966>
+.=> public static double java.lang.Math.asin(double)
+.<= public static double java.lang.Math.asin(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.atan(double)
+.<= public static double java.lang.Math.atan(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.atan2(double,double)
+.<= public static double java.lang.Math.atan2(double,double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.cbrt(double)
+.<= public static double java.lang.Math.cbrt(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.cosh(double)
+.<= public static double java.lang.Math.cosh(double) -> <class java.lang.Double: 1.0>
+.=> public static double java.lang.Math.exp(double)
+.<= public static double java.lang.Math.exp(double) -> <class java.lang.Double: 1.0>
+.=> public static double java.lang.Math.expm1(double)
+.<= public static double java.lang.Math.expm1(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.hypot(double,double)
+.<= public static double java.lang.Math.hypot(double,double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.log(double)
+.<= public static double java.lang.Math.log(double) -> <class java.lang.Double: -Infinity>
+.=> public static double java.lang.Math.log10(double)
+.<= public static double java.lang.Math.log10(double) -> <class java.lang.Double: -Infinity>
+.=> public static double java.lang.Math.nextAfter(double,double)
+.<= public static double java.lang.Math.nextAfter(double,double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.sinh(double)
+.<= public static double java.lang.Math.sinh(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.tan(double)
+.<= public static double java.lang.Math.tan(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.tanh(double)
+.<= public static double java.lang.Math.tanh(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.sqrt(double)
+.<= public static double java.lang.Math.sqrt(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.ceil(double)
+.<= public static double java.lang.Math.ceil(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.floor(double)
+.<= public static double java.lang.Math.floor(double) -> <class java.lang.Double: 0.0>
+.=> public static double java.lang.Math.rint(double)
+.<= public static double java.lang.Math.rint(double) -> <class java.lang.Double: 0.0>
+.=> public static long java.lang.Math.round(double)
+..=> public static long java.lang.Double.doubleToRawLongBits(double)
+..<= public static long java.lang.Double.doubleToRawLongBits(double) -> <class java.lang.Long: 0>
+.<= public static long java.lang.Math.round(double) -> <class java.lang.Long: 0>
+.=> public static int java.lang.Math.round(float)
+..=> public static int java.lang.Float.floatToRawIntBits(float)
+..<= public static int java.lang.Float.floatToRawIntBits(float) -> <class java.lang.Integer: 0>
+.<= public static int java.lang.Math.round(float) -> <class java.lang.Integer: 0>
+.=> public static java.lang.Thread java.lang.Thread.currentThread()
+.<= public static java.lang.Thread java.lang.Thread.currentThread() -> <<non-deterministic>: <non-deterministic>>
+.=> public char java.lang.String.charAt(int)
+.<= public char java.lang.String.charAt(int) -> <class java.lang.Character: s>
+.=> public int java.lang.String.compareTo(java.lang.String)
+.<= public int java.lang.String.compareTo(java.lang.String) -> <class java.lang.Integer: 11>
+.=> public boolean java.lang.String.equals(java.lang.Object)
+.<= public boolean java.lang.String.equals(java.lang.Object) -> <class java.lang.Boolean: false>
+.=> public int java.lang.String.indexOf(int)
+..=> public int java.lang.String.indexOf(int,int)
+..<= public int java.lang.String.indexOf(int,int) -> <class java.lang.Integer: -1>
+.<= public int java.lang.String.indexOf(int) -> <class java.lang.Integer: -1>
+.=> public int java.lang.String.indexOf(int,int)
+..=> public int java.lang.String.length()
+..<= public int java.lang.String.length() -> <class java.lang.Integer: 17>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: s>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: o>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: m>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: e>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character:  >
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: l>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: a>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: r>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: g>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: e>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character:  >
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: s>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: t>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: r>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: i>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: n>
+..=> public char java.lang.String.charAt(int)
+..<= public char java.lang.String.charAt(int) -> <class java.lang.Character: g>
+.<= public int java.lang.String.indexOf(int,int) -> <class java.lang.Integer: -1>
+.=> public int java.lang.String.indexOf(java.lang.String)
+..=> public int java.lang.String.indexOf(java.lang.String,int)
+..<= public int java.lang.String.indexOf(java.lang.String,int) -> <class java.lang.Integer: -1>
+.<= public int java.lang.String.indexOf(java.lang.String) -> <class java.lang.Integer: -1>
+.=> public int java.lang.String.indexOf(java.lang.String,int)
+..=> private static int java.lang.String.indexOf(java.lang.String,java.lang.String,int)
+..<= private static int java.lang.String.indexOf(java.lang.String,java.lang.String,int) -> <class java.lang.Integer: -1>
+.<= public int java.lang.String.indexOf(java.lang.String,int) -> <class java.lang.Integer: -1>
+.=> public boolean java.lang.String.isEmpty()
+.<= public boolean java.lang.String.isEmpty() -> <class java.lang.Boolean: false>
+.=> public int java.lang.String.length()
+.<= public int java.lang.String.length() -> <class java.lang.Integer: 17>
+.=> public synchronized java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String)
+..=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String)
+..<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String) -> <class java.lang.StringBuffer: some large string bufferhellohello>
+.<= public synchronized java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String) -> <class java.lang.StringBuffer: some large string bufferhellohello>
+.=> public synchronized int java.lang.StringBuffer.length()
+.<= public synchronized int java.lang.StringBuffer.length() -> <class java.lang.Integer: 34>
+.=> public synchronized java.lang.String java.lang.StringBuffer.toString()
+..=> final boolean java.lang.AbstractStringBuilder.isLatin1()
+..<= final boolean java.lang.AbstractStringBuilder.isLatin1() -> <class java.lang.Boolean: true>
+..=> public static java.lang.String java.lang.StringLatin1.newString(byte[],int,int)
+..<= public static java.lang.String java.lang.StringLatin1.newString(byte[],int,int) -> <class java.lang.String: some large string bufferhellohello>
+.<= public synchronized java.lang.String java.lang.StringBuffer.toString() -> <class java.lang.String: some large string bufferhellohello>
+.=> public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)
+..=> public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String)
+..<= public java.lang.AbstractStringBuilder java.lang.AbstractStringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: some large string builderhellohello>
+.<= public java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) -> <class java.lang.StringBuilder: some large string builderhellohello>
+.=> public int java.lang.StringBuilder.length()
+..=> public int java.lang.AbstractStringBuilder.length()
+..<= public int java.lang.AbstractStringBuilder.length() -> <class java.lang.Integer: 35>
+.<= public int java.lang.StringBuilder.length() -> <class java.lang.Integer: 35>
+.=> public java.lang.String java.lang.StringBuilder.toString()
+..=> final boolean java.lang.AbstractStringBuilder.isLatin1()
+..<= final boolean java.lang.AbstractStringBuilder.isLatin1() -> <class java.lang.Boolean: true>
+..=> public static java.lang.String java.lang.StringLatin1.newString(byte[],int,int)
+..<= public static java.lang.String java.lang.StringLatin1.newString(byte[],int,int) -> <class java.lang.String: some large string builderhellohello>
+.<= public java.lang.String java.lang.StringBuilder.toString() -> <class java.lang.String: some large string builderhellohello>
+.=> public static java.lang.Integer java.lang.Integer.valueOf(int)
+.<= public static java.lang.Integer java.lang.Integer.valueOf(int) -> <class java.lang.Integer: 0>
+.=> public static boolean java.lang.Thread.interrupted()
+.<= public static boolean java.lang.Thread.interrupted() -> <class java.lang.Boolean: false>
+<= static void art.Test988Intrinsics.test() -> <null: null>
+=> public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
+<= public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int) -> <null: null>
+=> public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
+<= public static void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int) -> <null: null>
+<= static void art.Test988$IntrinsicsTest.doTest() -> <null: null>
+=> public static java.lang.Thread java.lang.Thread.currentThread()
+<= public static java.lang.Thread java.lang.Thread.currentThread() -> <<non-deterministic>: <non-deterministic>>
+=> public static void art.Trace.disableTracing(java.lang.Thread)
diff --git a/test/988-method-trace/src/Main.java b/test/988-method-trace/src/Main.java
index 9dd1142..4797c71 100644
--- a/test/988-method-trace/src/Main.java
+++ b/test/988-method-trace/src/Main.java
@@ -17,5 +17,13 @@
 public class Main {
   public static void main(String[] args) throws Exception {
     art.Test988.run();
+
+    // Test calls to intrinsics from JITed code.
+    ensureJitCompiled(art.Test988Intrinsics.class, "test");
+    art.Test988.testJitIntrinsics();
+
+    art.Test988.printResults();
   }
+
+  public static native void ensureJitCompiled(Class<?> cls, String methodName);
 }
diff --git a/test/988-method-trace/src/art/Test988.java b/test/988-method-trace/src/art/Test988.java
index 227ce62..4a6de6e 100644
--- a/test/988-method-trace/src/art/Test988.java
+++ b/test/988-method-trace/src/art/Test988.java
@@ -377,7 +377,19 @@
         sMethodTracingIgnore = false;
         // Turn off method tracing so we don't have to deal with print internals.
         Trace.disableTracing(Thread.currentThread());
-        printResults();
+    }
+
+    public static void testJitIntrinsics() throws Exception {
+        Trace.enableMethodTracing(
+            Test988.class,
+            Test988.class.getDeclaredMethod("notifyMethodEntry", Executable.class),
+            Test988.class.getDeclaredMethod(
+                "notifyMethodExit", Executable.class, Boolean.TYPE, Object.class),
+            Thread.currentThread());
+        sMethodTracingIgnore = true;
+        IntrinsicsTest.doTest();
+        sMethodTracingIgnore = false;
+        Trace.disableTracing(Thread.currentThread());
     }
 
     // This ensures that all classes we touch are loaded before we start recording traces. This
diff --git a/test/988-method-trace/src/art/Test988Intrinsics.java b/test/988-method-trace/src/art/Test988Intrinsics.java
index 3069f1a..fe68d3e 100644
--- a/test/988-method-trace/src/art/Test988Intrinsics.java
+++ b/test/988-method-trace/src/art/Test988Intrinsics.java
@@ -22,114 +22,116 @@
 
 package art;
 
-class Test988Intrinsics {
-  // Pre-initialize *all* instance variables used so that their constructors are not in the trace.
-  static java.lang.String instance_java_lang_String = "some large string";
-  static java.lang.StringBuffer instance_java_lang_StringBuffer = new java.lang.StringBuffer("some large string buffer");
-  static java.lang.StringBuilder instance_java_lang_StringBuilder = new java.lang.StringBuilder("some large string builder");
+public class Test988Intrinsics {
+    // Pre-initialize *all* instance variables used so that their constructors are not in the trace.
+    static java.lang.String instance_java_lang_String = "some large string";
+    static java.lang.StringBuffer instance_java_lang_StringBuffer =
+            new java.lang.StringBuffer("some large string buffer");
+    static java.lang.StringBuilder instance_java_lang_StringBuilder =
+            new java.lang.StringBuilder("some large string builder");
 
-  static void initialize() {
-    // Ensure all static variables are initialized.
-    // In addition, pre-load classes here so that we don't see diverging class loading traces.
-    java.lang.Double.class.toString();
-    java.lang.Float.class.toString();
-    java.lang.Integer.class.toString();
-    java.lang.Long.class.toString();
-    java.lang.Short.class.toString();
-    java.lang.Math.class.toString();
-    java.lang.Thread.class.toString();
-    java.lang.String.class.toString();
-    java.lang.StringBuffer.class.toString();
-    java.lang.StringBuilder.class.toString();
-  }
+    static void initialize() {
+        // Ensure all static variables are initialized.
+        // In addition, pre-load classes here so that we don't see diverging class loading traces.
+        java.lang.Double.class.toString();
+        java.lang.Float.class.toString();
+        java.lang.Integer.class.toString();
+        java.lang.Long.class.toString();
+        java.lang.Short.class.toString();
+        java.lang.Math.class.toString();
+        java.lang.Thread.class.toString();
+        java.lang.String.class.toString();
+        java.lang.StringBuffer.class.toString();
+        java.lang.StringBuilder.class.toString();
+    }
 
-  static void test() {
-    // Call each intrinsic from art/runtime/intrinsics_list.h to make sure they are traced.
-    java.lang.Double.doubleToRawLongBits(0.0);
-    java.lang.Double.doubleToLongBits(0.0);
-    java.lang.Double.isInfinite(0.0);
-    java.lang.Double.isNaN(0.0);
-    java.lang.Double.longBitsToDouble(0L);
-    java.lang.Float.floatToRawIntBits(0.0f);
-    java.lang.Float.floatToIntBits(0.0f);
-    java.lang.Float.isInfinite(0.0f);
-    java.lang.Float.isNaN(0.0f);
-    java.lang.Float.intBitsToFloat(0);
-    java.lang.Integer.reverse(0);
-    java.lang.Integer.reverseBytes(0);
-    java.lang.Integer.bitCount(0);
-    java.lang.Integer.compare(0, 0);
-    java.lang.Integer.highestOneBit(0);
-    java.lang.Integer.lowestOneBit(0);
-    java.lang.Integer.numberOfLeadingZeros(0);
-    java.lang.Integer.numberOfTrailingZeros(0);
-    java.lang.Integer.rotateRight(0, 0);
-    java.lang.Integer.rotateLeft(0, 0);
-    java.lang.Integer.signum(0);
-    java.lang.Long.reverse(0L);
-    java.lang.Long.reverseBytes(0L);
-    java.lang.Long.bitCount(0L);
-    java.lang.Long.compare(0L, 0L);
-    java.lang.Long.highestOneBit(0L);
-    java.lang.Long.lowestOneBit(0L);
-    java.lang.Long.numberOfLeadingZeros(0L);
-    java.lang.Long.numberOfTrailingZeros(0L);
-    java.lang.Long.rotateRight(0L, 0);
-    java.lang.Long.rotateLeft(0L, 0);
-    java.lang.Long.signum(0L);
-    java.lang.Short.reverseBytes((short)0);
-    java.lang.Math.abs(0.0);
-    java.lang.Math.abs(0.0f);
-    java.lang.Math.abs(0L);
-    java.lang.Math.abs(0);
-    java.lang.Math.min(0.0, 0.0);
-    java.lang.Math.min(0.0f, 0.0f);
-    java.lang.Math.min(0L, 0L);
-    java.lang.Math.min(0, 0);
-    java.lang.Math.max(0.0, 0.0);
-    java.lang.Math.max(0.0f, 0.0f);
-    java.lang.Math.max(0L, 0L);
-    java.lang.Math.max(0, 0);
-    java.lang.Math.cos(0.0);
-    java.lang.Math.sin(0.0);
-    java.lang.Math.acos(0.0);
-    java.lang.Math.asin(0.0);
-    java.lang.Math.atan(0.0);
-    java.lang.Math.atan2(0.0, 0.0);
-    java.lang.Math.cbrt(0.0);
-    java.lang.Math.cosh(0.0);
-    java.lang.Math.exp(0.0);
-    java.lang.Math.expm1(0.0);
-    java.lang.Math.hypot(0.0, 0.0);
-    java.lang.Math.log(0.0);
-    java.lang.Math.log10(0.0);
-    java.lang.Math.nextAfter(0.0, 0.0);
-    java.lang.Math.sinh(0.0);
-    java.lang.Math.tan(0.0);
-    java.lang.Math.tanh(0.0);
-    java.lang.Math.sqrt(0.0);
-    java.lang.Math.ceil(0.0);
-    java.lang.Math.floor(0.0);
-    java.lang.Math.rint(0.0);
-    java.lang.Math.round(0.0);
-    java.lang.Math.round(0.0f);
-    java.lang.Thread.currentThread();
-    instance_java_lang_String.charAt(0);
-    instance_java_lang_String.compareTo("hello");
-    instance_java_lang_String.equals((java.lang.Object)null);
-    instance_java_lang_String.indexOf(0);
-    instance_java_lang_String.indexOf(0, 0);
-    instance_java_lang_String.indexOf("hello");
-    instance_java_lang_String.indexOf("hello", 0);
-    instance_java_lang_String.isEmpty();
-    instance_java_lang_String.length();
-    instance_java_lang_StringBuffer.append("hello");
-    instance_java_lang_StringBuffer.length();
-    instance_java_lang_StringBuffer.toString();
-    instance_java_lang_StringBuilder.append("hello");
-    instance_java_lang_StringBuilder.length();
-    instance_java_lang_StringBuilder.toString();
-    java.lang.Integer.valueOf(0);
-    java.lang.Thread.interrupted();
-  }
+    static void test() {
+        // Call each intrinsic from art/runtime/intrinsics_list.h to make sure they are traced.
+        java.lang.Double.doubleToRawLongBits(0.0);
+        java.lang.Double.doubleToLongBits(0.0);
+        java.lang.Double.isInfinite(0.0);
+        java.lang.Double.isNaN(0.0);
+        java.lang.Double.longBitsToDouble(0L);
+        java.lang.Float.floatToRawIntBits(0.0f);
+        java.lang.Float.floatToIntBits(0.0f);
+        java.lang.Float.isInfinite(0.0f);
+        java.lang.Float.isNaN(0.0f);
+        java.lang.Float.intBitsToFloat(0);
+        java.lang.Integer.reverse(0);
+        java.lang.Integer.reverseBytes(0);
+        java.lang.Integer.bitCount(0);
+        java.lang.Integer.compare(0, 0);
+        java.lang.Integer.highestOneBit(0);
+        java.lang.Integer.lowestOneBit(0);
+        java.lang.Integer.numberOfLeadingZeros(0);
+        java.lang.Integer.numberOfTrailingZeros(0);
+        java.lang.Integer.rotateRight(0, 0);
+        java.lang.Integer.rotateLeft(0, 0);
+        java.lang.Integer.signum(0);
+        java.lang.Long.reverse(0L);
+        java.lang.Long.reverseBytes(0L);
+        java.lang.Long.bitCount(0L);
+        java.lang.Long.compare(0L, 0L);
+        java.lang.Long.highestOneBit(0L);
+        java.lang.Long.lowestOneBit(0L);
+        java.lang.Long.numberOfLeadingZeros(0L);
+        java.lang.Long.numberOfTrailingZeros(0L);
+        java.lang.Long.rotateRight(0L, 0);
+        java.lang.Long.rotateLeft(0L, 0);
+        java.lang.Long.signum(0L);
+        java.lang.Short.reverseBytes((short) 0);
+        java.lang.Math.abs(0.0);
+        java.lang.Math.abs(0.0f);
+        java.lang.Math.abs(0L);
+        java.lang.Math.abs(0);
+        java.lang.Math.min(0.0, 0.0);
+        java.lang.Math.min(0.0f, 0.0f);
+        java.lang.Math.min(0L, 0L);
+        java.lang.Math.min(0, 0);
+        java.lang.Math.max(0.0, 0.0);
+        java.lang.Math.max(0.0f, 0.0f);
+        java.lang.Math.max(0L, 0L);
+        java.lang.Math.max(0, 0);
+        java.lang.Math.cos(0.0);
+        java.lang.Math.sin(0.0);
+        java.lang.Math.acos(0.0);
+        java.lang.Math.asin(0.0);
+        java.lang.Math.atan(0.0);
+        java.lang.Math.atan2(0.0, 0.0);
+        java.lang.Math.cbrt(0.0);
+        java.lang.Math.cosh(0.0);
+        java.lang.Math.exp(0.0);
+        java.lang.Math.expm1(0.0);
+        java.lang.Math.hypot(0.0, 0.0);
+        java.lang.Math.log(0.0);
+        java.lang.Math.log10(0.0);
+        java.lang.Math.nextAfter(0.0, 0.0);
+        java.lang.Math.sinh(0.0);
+        java.lang.Math.tan(0.0);
+        java.lang.Math.tanh(0.0);
+        java.lang.Math.sqrt(0.0);
+        java.lang.Math.ceil(0.0);
+        java.lang.Math.floor(0.0);
+        java.lang.Math.rint(0.0);
+        java.lang.Math.round(0.0);
+        java.lang.Math.round(0.0f);
+        java.lang.Thread.currentThread();
+        instance_java_lang_String.charAt(0);
+        instance_java_lang_String.compareTo("hello");
+        instance_java_lang_String.equals((java.lang.Object) null);
+        instance_java_lang_String.indexOf(0);
+        instance_java_lang_String.indexOf(0, 0);
+        instance_java_lang_String.indexOf("hello");
+        instance_java_lang_String.indexOf("hello", 0);
+        instance_java_lang_String.isEmpty();
+        instance_java_lang_String.length();
+        instance_java_lang_StringBuffer.append("hello");
+        instance_java_lang_StringBuffer.length();
+        instance_java_lang_StringBuffer.toString();
+        instance_java_lang_StringBuilder.append("hello");
+        instance_java_lang_StringBuilder.length();
+        instance_java_lang_StringBuilder.toString();
+        java.lang.Integer.valueOf(0);
+        java.lang.Thread.interrupted();
+    }
 }