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" 18#include "base/mutex.h" 19#include "base/systrace.h" 20#include "callee_save_frame.h" 21#include "interpreter/interpreter.h" 22#include "obj_ptr-inl.h" // TODO: Find the other include that isn't complete, and clean this up. 23#include "quick_exception_handler.h" 24#include "thread.h" 25 26namespace art { 27 28NO_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 { 44 ScopedTrace trace(std::string("Deoptimization ") + GetDeoptimizationKindName(kind)); 45 if (single_frame) { 46 exception_handler.DeoptimizeSingleFrame(kind); 47 } else { 48 exception_handler.DeoptimizeStack(); 49 } 50 } 51 uintptr_t return_pc = exception_handler.UpdateInstrumentationStack(); 52 if (exception_handler.IsFullFragmentDone()) { 53 exception_handler.DoLongJump(true); 54 } else { 55 exception_handler.DeoptimizePartialFragmentFixup(return_pc); 56 // We cannot smash the caller-saves, as we need the ArtMethod in a parameter register that would 57 // be caller-saved. This has the downside that we cannot track incorrect register usage down the 58 // line. 59 exception_handler.DoLongJump(false); 60 } 61} 62 63extern "C" NO_RETURN void artDeoptimize(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) { 64 ScopedQuickEntrypointChecks sqec(self); 65 artDeoptimizeImpl(self, DeoptimizationKind::kFullFrame, false); 66} 67 68// This is called directly from compiled code by an HDeoptimize. 69extern "C" NO_RETURN void artDeoptimizeFromCompiledCode(DeoptimizationKind kind, Thread* self) 70 REQUIRES_SHARED(Locks::mutator_lock_) { 71 ScopedQuickEntrypointChecks sqec(self); 72 // Before deoptimizing to interpreter, we must push the deoptimization context. 73 JValue return_value; 74 return_value.SetJ(0); // we never deoptimize from compiled code with an invoke result. 75 self->PushDeoptimizationContext(return_value, false, /* from_code */ true, self->GetException()); 76 artDeoptimizeImpl(self, kind, true); 77} 78 79} // namespace art 80