1 /* 2 * Copyright (C) 2014 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 #ifndef ART_RUNTIME_QUICK_EXCEPTION_HANDLER_H_ 18 #define ART_RUNTIME_QUICK_EXCEPTION_HANDLER_H_ 19 20 #include "base/logging.h" 21 #include "base/macros.h" 22 #include "base/mutex.h" 23 #include "stack.h" // StackReference 24 25 namespace art { 26 27 namespace mirror { 28 class Throwable; 29 } // namespace mirror 30 class ArtMethod; 31 class Context; 32 class Thread; 33 class ShadowFrame; 34 35 // Manages exception delivery for Quick backend. 36 class QuickExceptionHandler { 37 public: 38 QuickExceptionHandler(Thread* self, bool is_deoptimization) 39 SHARED_REQUIRES(Locks::mutator_lock_); 40 41 NO_RETURN ~QuickExceptionHandler() { 42 LOG(FATAL) << "UNREACHABLE"; // Expected to take long jump. 43 UNREACHABLE(); 44 } 45 46 // Find the catch handler for the given exception. 47 void FindCatch(mirror::Throwable* exception) SHARED_REQUIRES(Locks::mutator_lock_); 48 49 // Deoptimize the stack to the upcall. For every compiled frame, we create a "copy" 50 // shadow frame that will be executed with the interpreter. 51 void DeoptimizeStack() SHARED_REQUIRES(Locks::mutator_lock_); 52 void DeoptimizeSingleFrame() SHARED_REQUIRES(Locks::mutator_lock_); 53 void DeoptimizeSingleFrameArchDependentFixup() SHARED_REQUIRES(Locks::mutator_lock_); 54 55 // Update the instrumentation stack by removing all methods that will be unwound 56 // by the exception being thrown. 57 void UpdateInstrumentationStack() SHARED_REQUIRES(Locks::mutator_lock_); 58 59 // Set up environment before delivering an exception to optimized code. 60 void SetCatchEnvironmentForOptimizedHandler(StackVisitor* stack_visitor) 61 SHARED_REQUIRES(Locks::mutator_lock_); 62 63 // Long jump either to a catch handler or to the upcall. 64 NO_RETURN void DoLongJump(bool smash_caller_saves = true) SHARED_REQUIRES(Locks::mutator_lock_); 65 66 void SetHandlerQuickFrame(ArtMethod** handler_quick_frame) { 67 handler_quick_frame_ = handler_quick_frame; 68 } 69 70 void SetHandlerQuickFramePc(uintptr_t handler_quick_frame_pc) { 71 handler_quick_frame_pc_ = handler_quick_frame_pc; 72 } 73 74 void SetHandlerMethodHeader(const OatQuickMethodHeader* handler_method_header) { 75 handler_method_header_ = handler_method_header; 76 } 77 78 void SetHandlerQuickArg0(uintptr_t handler_quick_arg0) { 79 handler_quick_arg0_ = handler_quick_arg0; 80 } 81 82 ArtMethod* GetHandlerMethod() const { 83 return handler_method_; 84 } 85 86 void SetHandlerMethod(ArtMethod* handler_quick_method) { 87 handler_method_ = handler_quick_method; 88 } 89 90 uint32_t GetHandlerDexPc() const { 91 return handler_dex_pc_; 92 } 93 94 void SetHandlerDexPc(uint32_t dex_pc) { 95 handler_dex_pc_ = dex_pc; 96 } 97 98 void SetClearException(bool clear_exception) { 99 clear_exception_ = clear_exception; 100 } 101 102 void SetHandlerFrameDepth(size_t frame_depth) { 103 handler_frame_depth_ = frame_depth; 104 } 105 106 // Walk the stack frames of the given thread, printing out non-runtime methods with their types 107 // of frames. Helps to verify that single-frame deopt really only deopted one frame. 108 static void DumpFramesWithType(Thread* self, bool details = false) 109 SHARED_REQUIRES(Locks::mutator_lock_); 110 111 private: 112 Thread* const self_; 113 Context* const context_; 114 // Should we deoptimize the stack? 115 const bool is_deoptimization_; 116 // Is method tracing active? 117 const bool method_tracing_active_; 118 // Quick frame with found handler or last frame if no handler found. 119 ArtMethod** handler_quick_frame_; 120 // PC to branch to for the handler. 121 uintptr_t handler_quick_frame_pc_; 122 // Quick code of the handler. 123 const OatQuickMethodHeader* handler_method_header_; 124 // The value for argument 0. 125 uintptr_t handler_quick_arg0_; 126 // The handler method to report to the debugger. 127 ArtMethod* handler_method_; 128 // The handler's dex PC, zero implies an uncaught exception. 129 uint32_t handler_dex_pc_; 130 // Should the exception be cleared as the catch block has no move-exception? 131 bool clear_exception_; 132 // Frame depth of the catch handler or the upcall. 133 size_t handler_frame_depth_; 134 135 DISALLOW_COPY_AND_ASSIGN(QuickExceptionHandler); 136 }; 137 138 } // namespace art 139 #endif // ART_RUNTIME_QUICK_EXCEPTION_HANDLER_H_ 140