1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "base/logging.h" // For VLOG_IS_ON. 18 #include "base/mutex.h" 19 #include "callee_save_frame.h" 20 #include "interpreter/interpreter.h" 21 #include "obj_ptr-inl.h" // TODO: Find the other include that isn't complete, and clean this up. 22 #include "quick_exception_handler.h" 23 #include "runtime.h" 24 #include "thread.h" 25 26 namespace art { 27 28 NO_RETURN static void artDeoptimizeImpl(Thread* self, DeoptimizationKind kind, bool single_frame) 29 REQUIRES_SHARED(Locks::mutator_lock_) { 30 Runtime::Current()->IncrementDeoptimizationCount(kind); 31 if (VLOG_IS_ON(deopt)) { 32 if (single_frame) { 33 // Deopt logging will be in DeoptimizeSingleFrame. It is there to take advantage of the 34 // specialized visitor that will show whether a method is Quick or Shadow. 35 } else { 36 LOG(INFO) << "Deopting:"; 37 self->Dump(LOG_STREAM(INFO)); 38 } 39 } 40 41 self->AssertHasDeoptimizationContext(); 42 QuickExceptionHandler exception_handler(self, true); 43 if (single_frame) { 44 exception_handler.DeoptimizeSingleFrame(kind); 45 } else { 46 exception_handler.DeoptimizeStack(); 47 } 48 uintptr_t return_pc = exception_handler.UpdateInstrumentationStack(); 49 if (exception_handler.IsFullFragmentDone()) { 50 exception_handler.DoLongJump(true); 51 } else { 52 exception_handler.DeoptimizePartialFragmentFixup(return_pc); 53 // We cannot smash the caller-saves, as we need the ArtMethod in a parameter register that would 54 // be caller-saved. This has the downside that we cannot track incorrect register usage down the 55 // line. 56 exception_handler.DoLongJump(false); 57 } 58 } 59 60 extern "C" NO_RETURN void artDeoptimize(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) { 61 ScopedQuickEntrypointChecks sqec(self); 62 artDeoptimizeImpl(self, DeoptimizationKind::kFullFrame, false); 63 } 64 65 // This is called directly from compiled code by an HDeoptimize. 66 extern "C" NO_RETURN void artDeoptimizeFromCompiledCode(DeoptimizationKind kind, Thread* self) 67 REQUIRES_SHARED(Locks::mutator_lock_) { 68 ScopedQuickEntrypointChecks sqec(self); 69 // Before deoptimizing to interpreter, we must push the deoptimization context. 70 JValue return_value; 71 return_value.SetJ(0); // we never deoptimize from compiled code with an invoke result. 72 self->PushDeoptimizationContext(return_value, 73 /* is_reference= */ false, 74 self->GetException(), 75 /* from_code= */ true, 76 DeoptimizationMethodType::kDefault); 77 artDeoptimizeImpl(self, kind, true); 78 } 79 80 } // namespace art 81