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 #include "quick_exception_handler.h"
18 
19 #include "arch/context.h"
20 #include "art_method-inl.h"
21 #include "base/enums.h"
22 #include "base/logging.h"  // For VLOG_IS_ON.
23 #include "dex/dex_file_types.h"
24 #include "dex/dex_instruction.h"
25 #include "entrypoints/entrypoint_utils.h"
26 #include "entrypoints/quick/quick_entrypoints_enum.h"
27 #include "entrypoints/runtime_asm_entrypoints.h"
28 #include "handle_scope-inl.h"
29 #include "jit/jit.h"
30 #include "jit/jit_code_cache.h"
31 #include "mirror/class-inl.h"
32 #include "mirror/class_loader.h"
33 #include "mirror/throwable.h"
34 #include "oat_quick_method_header.h"
35 #include "stack.h"
36 #include "stack_map.h"
37 
38 namespace art {
39 
40 static constexpr bool kDebugExceptionDelivery = false;
41 static constexpr size_t kInvalidFrameDepth = 0xffffffff;
42 
QuickExceptionHandler(Thread * self,bool is_deoptimization)43 QuickExceptionHandler::QuickExceptionHandler(Thread* self, bool is_deoptimization)
44     : self_(self),
45       context_(self->GetLongJumpContext()),
46       is_deoptimization_(is_deoptimization),
47       method_tracing_active_(is_deoptimization ||
48                              Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()),
49       handler_quick_frame_(nullptr),
50       handler_quick_frame_pc_(0),
51       handler_method_header_(nullptr),
52       handler_quick_arg0_(0),
53       handler_method_(nullptr),
54       handler_dex_pc_(0),
55       clear_exception_(false),
56       handler_frame_depth_(kInvalidFrameDepth),
57       full_fragment_done_(false) {}
58 
59 // Finds catch handler.
60 class CatchBlockStackVisitor FINAL : public StackVisitor {
61  public:
CatchBlockStackVisitor(Thread * self,Context * context,Handle<mirror::Throwable> * exception,QuickExceptionHandler * exception_handler)62   CatchBlockStackVisitor(Thread* self, Context* context, Handle<mirror::Throwable>* exception,
63                          QuickExceptionHandler* exception_handler)
64       REQUIRES_SHARED(Locks::mutator_lock_)
65       : StackVisitor(self, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
66         exception_(exception),
67         exception_handler_(exception_handler) {
68   }
69 
VisitFrame()70   bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
71     ArtMethod* method = GetMethod();
72     exception_handler_->SetHandlerFrameDepth(GetFrameDepth());
73     if (method == nullptr) {
74       // This is the upcall, we remember the frame and last pc so that we may long jump to them.
75       exception_handler_->SetHandlerQuickFramePc(GetCurrentQuickFramePc());
76       exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
77       exception_handler_->SetHandlerMethodHeader(GetCurrentOatQuickMethodHeader());
78       uint32_t next_dex_pc;
79       ArtMethod* next_art_method;
80       bool has_next = GetNextMethodAndDexPc(&next_art_method, &next_dex_pc);
81       // Report the method that did the down call as the handler.
82       exception_handler_->SetHandlerDexPc(next_dex_pc);
83       exception_handler_->SetHandlerMethod(next_art_method);
84       if (!has_next) {
85         // No next method? Check exception handler is set up for the unhandled exception handler
86         // case.
87         DCHECK_EQ(0U, exception_handler_->GetHandlerDexPc());
88         DCHECK(nullptr == exception_handler_->GetHandlerMethod());
89       }
90       return false;  // End stack walk.
91     }
92     if (method->IsRuntimeMethod()) {
93       // Ignore callee save method.
94       DCHECK(method->IsCalleeSaveMethod());
95       return true;
96     }
97     return HandleTryItems(method);
98   }
99 
100  private:
HandleTryItems(ArtMethod * method)101   bool HandleTryItems(ArtMethod* method)
102       REQUIRES_SHARED(Locks::mutator_lock_) {
103     uint32_t dex_pc = dex::kDexNoIndex;
104     if (!method->IsNative()) {
105       dex_pc = GetDexPc();
106     }
107     if (dex_pc != dex::kDexNoIndex) {
108       bool clear_exception = false;
109       StackHandleScope<1> hs(GetThread());
110       Handle<mirror::Class> to_find(hs.NewHandle((*exception_)->GetClass()));
111       uint32_t found_dex_pc = method->FindCatchBlock(to_find, dex_pc, &clear_exception);
112       exception_handler_->SetClearException(clear_exception);
113       if (found_dex_pc != dex::kDexNoIndex) {
114         exception_handler_->SetHandlerMethod(method);
115         exception_handler_->SetHandlerDexPc(found_dex_pc);
116         exception_handler_->SetHandlerQuickFramePc(
117             GetCurrentOatQuickMethodHeader()->ToNativeQuickPc(
118                 method, found_dex_pc, /* is_catch_handler */ true));
119         exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
120         exception_handler_->SetHandlerMethodHeader(GetCurrentOatQuickMethodHeader());
121         return false;  // End stack walk.
122       } else if (UNLIKELY(GetThread()->HasDebuggerShadowFrames())) {
123         // We are going to unwind this frame. Did we prepare a shadow frame for debugging?
124         size_t frame_id = GetFrameId();
125         ShadowFrame* frame = GetThread()->FindDebuggerShadowFrame(frame_id);
126         if (frame != nullptr) {
127           // We will not execute this shadow frame so we can safely deallocate it.
128           GetThread()->RemoveDebuggerShadowFrameMapping(frame_id);
129           ShadowFrame::DeleteDeoptimizedFrame(frame);
130         }
131       }
132     }
133     return true;  // Continue stack walk.
134   }
135 
136   // The exception we're looking for the catch block of.
137   Handle<mirror::Throwable>* exception_;
138   // The quick exception handler we're visiting for.
139   QuickExceptionHandler* const exception_handler_;
140 
141   DISALLOW_COPY_AND_ASSIGN(CatchBlockStackVisitor);
142 };
143 
FindCatch(ObjPtr<mirror::Throwable> exception)144 void QuickExceptionHandler::FindCatch(ObjPtr<mirror::Throwable> exception) {
145   DCHECK(!is_deoptimization_);
146   StackHandleScope<1> hs(self_);
147   Handle<mirror::Throwable> exception_ref(hs.NewHandle(exception));
148   if (kDebugExceptionDelivery) {
149     ObjPtr<mirror::String> msg = exception_ref->GetDetailMessage();
150     std::string str_msg(msg != nullptr ? msg->ToModifiedUtf8() : "");
151     self_->DumpStack(LOG_STREAM(INFO) << "Delivering exception: " << exception_ref->PrettyTypeOf()
152                      << ": " << str_msg << "\n");
153   }
154 
155   // Walk the stack to find catch handler.
156   CatchBlockStackVisitor visitor(self_, context_, &exception_ref, this);
157   visitor.WalkStack(true);
158 
159   if (kDebugExceptionDelivery) {
160     if (*handler_quick_frame_ == nullptr) {
161       LOG(INFO) << "Handler is upcall";
162     }
163     if (handler_method_ != nullptr) {
164       const DexFile* dex_file = handler_method_->GetDeclaringClass()->GetDexCache()->GetDexFile();
165       int line_number = annotations::GetLineNumFromPC(dex_file, handler_method_, handler_dex_pc_);
166       LOG(INFO) << "Handler: " << handler_method_->PrettyMethod() << " (line: "
167                 << line_number << ")";
168     }
169   }
170   // Exception was cleared as part of delivery.
171   DCHECK(!self_->IsExceptionPending());
172   if (!clear_exception_) {
173     // Put exception back in root set with clear throw location.
174     self_->SetException(exception_ref.Get());
175   }
176   // If the handler is in optimized code, we need to set the catch environment.
177   if (*handler_quick_frame_ != nullptr &&
178       handler_method_header_ != nullptr &&
179       handler_method_header_->IsOptimized()) {
180     SetCatchEnvironmentForOptimizedHandler(&visitor);
181   }
182 }
183 
ToVRegKind(DexRegisterLocation::Kind kind)184 static VRegKind ToVRegKind(DexRegisterLocation::Kind kind) {
185   // Slightly hacky since we cannot map DexRegisterLocationKind and VRegKind
186   // one to one. However, StackVisitor::GetVRegFromOptimizedCode only needs to
187   // distinguish between core/FPU registers and low/high bits on 64-bit.
188   switch (kind) {
189     case DexRegisterLocation::Kind::kConstant:
190     case DexRegisterLocation::Kind::kInStack:
191       // VRegKind is ignored.
192       return VRegKind::kUndefined;
193 
194     case DexRegisterLocation::Kind::kInRegister:
195       // Selects core register. For 64-bit registers, selects low 32 bits.
196       return VRegKind::kLongLoVReg;
197 
198     case DexRegisterLocation::Kind::kInRegisterHigh:
199       // Selects core register. For 64-bit registers, selects high 32 bits.
200       return VRegKind::kLongHiVReg;
201 
202     case DexRegisterLocation::Kind::kInFpuRegister:
203       // Selects FPU register. For 64-bit registers, selects low 32 bits.
204       return VRegKind::kDoubleLoVReg;
205 
206     case DexRegisterLocation::Kind::kInFpuRegisterHigh:
207       // Selects FPU register. For 64-bit registers, selects high 32 bits.
208       return VRegKind::kDoubleHiVReg;
209 
210     default:
211       LOG(FATAL) << "Unexpected vreg location " << kind;
212       UNREACHABLE();
213   }
214 }
215 
SetCatchEnvironmentForOptimizedHandler(StackVisitor * stack_visitor)216 void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor* stack_visitor) {
217   DCHECK(!is_deoptimization_);
218   DCHECK(*handler_quick_frame_ != nullptr) << "Method should not be called on upcall exceptions";
219   DCHECK(handler_method_ != nullptr && handler_method_header_->IsOptimized());
220 
221   if (kDebugExceptionDelivery) {
222     self_->DumpStack(LOG_STREAM(INFO) << "Setting catch phis: ");
223   }
224 
225   CodeItemDataAccessor accessor(handler_method_->DexInstructionData());
226   const size_t number_of_vregs = accessor.RegistersSize();
227   CodeInfo code_info = handler_method_header_->GetOptimizedCodeInfo();
228   CodeInfoEncoding encoding = code_info.ExtractEncoding();
229 
230   // Find stack map of the catch block.
231   StackMap catch_stack_map = code_info.GetCatchStackMapForDexPc(GetHandlerDexPc(), encoding);
232   DCHECK(catch_stack_map.IsValid());
233   DexRegisterMap catch_vreg_map =
234       code_info.GetDexRegisterMapOf(catch_stack_map, encoding, number_of_vregs);
235   if (!catch_vreg_map.IsValid()) {
236     return;
237   }
238 
239   // Find stack map of the throwing instruction.
240   StackMap throw_stack_map =
241       code_info.GetStackMapForNativePcOffset(stack_visitor->GetNativePcOffset(), encoding);
242   DCHECK(throw_stack_map.IsValid());
243   DexRegisterMap throw_vreg_map =
244       code_info.GetDexRegisterMapOf(throw_stack_map, encoding, number_of_vregs);
245   DCHECK(throw_vreg_map.IsValid());
246 
247   // Copy values between them.
248   for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
249     DexRegisterLocation::Kind catch_location =
250         catch_vreg_map.GetLocationKind(vreg, number_of_vregs, code_info, encoding);
251     if (catch_location == DexRegisterLocation::Kind::kNone) {
252       continue;
253     }
254     DCHECK(catch_location == DexRegisterLocation::Kind::kInStack);
255 
256     // Get vreg value from its current location.
257     uint32_t vreg_value;
258     VRegKind vreg_kind = ToVRegKind(throw_vreg_map.GetLocationKind(vreg,
259                                                                    number_of_vregs,
260                                                                    code_info,
261                                                                    encoding));
262     bool get_vreg_success = stack_visitor->GetVReg(stack_visitor->GetMethod(),
263                                                    vreg,
264                                                    vreg_kind,
265                                                    &vreg_value);
266     CHECK(get_vreg_success) << "VReg " << vreg << " was optimized out ("
267                             << "method=" << ArtMethod::PrettyMethod(stack_visitor->GetMethod())
268                             << ", dex_pc=" << stack_visitor->GetDexPc() << ", "
269                             << "native_pc_offset=" << stack_visitor->GetNativePcOffset() << ")";
270 
271     // Copy value to the catch phi's stack slot.
272     int32_t slot_offset = catch_vreg_map.GetStackOffsetInBytes(vreg,
273                                                                number_of_vregs,
274                                                                code_info,
275                                                                encoding);
276     ArtMethod** frame_top = stack_visitor->GetCurrentQuickFrame();
277     uint8_t* slot_address = reinterpret_cast<uint8_t*>(frame_top) + slot_offset;
278     uint32_t* slot_ptr = reinterpret_cast<uint32_t*>(slot_address);
279     *slot_ptr = vreg_value;
280   }
281 }
282 
283 // Prepares deoptimization.
284 class DeoptimizeStackVisitor FINAL : public StackVisitor {
285  public:
DeoptimizeStackVisitor(Thread * self,Context * context,QuickExceptionHandler * exception_handler,bool single_frame)286   DeoptimizeStackVisitor(Thread* self,
287                          Context* context,
288                          QuickExceptionHandler* exception_handler,
289                          bool single_frame)
290       REQUIRES_SHARED(Locks::mutator_lock_)
291       : StackVisitor(self, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
292         exception_handler_(exception_handler),
293         prev_shadow_frame_(nullptr),
294         stacked_shadow_frame_pushed_(false),
295         single_frame_deopt_(single_frame),
296         single_frame_done_(false),
297         single_frame_deopt_method_(nullptr),
298         single_frame_deopt_quick_method_header_(nullptr),
299         callee_method_(nullptr) {
300   }
301 
GetSingleFrameDeoptMethod() const302   ArtMethod* GetSingleFrameDeoptMethod() const {
303     return single_frame_deopt_method_;
304   }
305 
GetSingleFrameDeoptQuickMethodHeader() const306   const OatQuickMethodHeader* GetSingleFrameDeoptQuickMethodHeader() const {
307     return single_frame_deopt_quick_method_header_;
308   }
309 
FinishStackWalk()310   void FinishStackWalk() REQUIRES_SHARED(Locks::mutator_lock_) {
311     // This is the upcall, or the next full frame in single-frame deopt, or the
312     // code isn't deoptimizeable. We remember the frame and last pc so that we
313     // may long jump to them.
314     exception_handler_->SetHandlerQuickFramePc(GetCurrentQuickFramePc());
315     exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
316     exception_handler_->SetHandlerMethodHeader(GetCurrentOatQuickMethodHeader());
317     if (!stacked_shadow_frame_pushed_) {
318       // In case there is no deoptimized shadow frame for this upcall, we still
319       // need to push a nullptr to the stack since there is always a matching pop after
320       // the long jump.
321       GetThread()->PushStackedShadowFrame(nullptr,
322                                           StackedShadowFrameType::kDeoptimizationShadowFrame);
323       stacked_shadow_frame_pushed_ = true;
324     }
325     if (GetMethod() == nullptr) {
326       exception_handler_->SetFullFragmentDone(true);
327     } else {
328       CHECK(callee_method_ != nullptr) << GetMethod()->PrettyMethod(false);
329       exception_handler_->SetHandlerQuickArg0(reinterpret_cast<uintptr_t>(callee_method_));
330     }
331   }
332 
VisitFrame()333   bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
334     exception_handler_->SetHandlerFrameDepth(GetFrameDepth());
335     ArtMethod* method = GetMethod();
336     if (method == nullptr || single_frame_done_) {
337       FinishStackWalk();
338       return false;  // End stack walk.
339     } else if (method->IsRuntimeMethod()) {
340       // Ignore callee save method.
341       DCHECK(method->IsCalleeSaveMethod());
342       return true;
343     } else if (method->IsNative()) {
344       // If we return from JNI with a pending exception and want to deoptimize, we need to skip
345       // the native method.
346       // The top method is a runtime method, the native method comes next.
347       CHECK_EQ(GetFrameDepth(), 1U);
348       callee_method_ = method;
349       return true;
350     } else if (!single_frame_deopt_ &&
351                !Runtime::Current()->IsAsyncDeoptimizeable(GetCurrentQuickFramePc())) {
352       // We hit some code that's not deoptimizeable. However, Single-frame deoptimization triggered
353       // from compiled code is always allowed since HDeoptimize always saves the full environment.
354       LOG(WARNING) << "Got request to deoptimize un-deoptimizable method "
355                    << method->PrettyMethod();
356       FinishStackWalk();
357       return false;  // End stack walk.
358     } else {
359       // Check if a shadow frame already exists for debugger's set-local-value purpose.
360       const size_t frame_id = GetFrameId();
361       ShadowFrame* new_frame = GetThread()->FindDebuggerShadowFrame(frame_id);
362       const bool* updated_vregs;
363       CodeItemDataAccessor accessor(method->DexInstructionData());
364       const size_t num_regs = accessor.RegistersSize();
365       if (new_frame == nullptr) {
366         new_frame = ShadowFrame::CreateDeoptimizedFrame(num_regs, nullptr, method, GetDexPc());
367         updated_vregs = nullptr;
368       } else {
369         updated_vregs = GetThread()->GetUpdatedVRegFlags(frame_id);
370         DCHECK(updated_vregs != nullptr);
371       }
372       HandleOptimizingDeoptimization(method, new_frame, updated_vregs);
373       if (updated_vregs != nullptr) {
374         // Calling Thread::RemoveDebuggerShadowFrameMapping will also delete the updated_vregs
375         // array so this must come after we processed the frame.
376         GetThread()->RemoveDebuggerShadowFrameMapping(frame_id);
377         DCHECK(GetThread()->FindDebuggerShadowFrame(frame_id) == nullptr);
378       }
379       if (prev_shadow_frame_ != nullptr) {
380         prev_shadow_frame_->SetLink(new_frame);
381       } else {
382         // Will be popped after the long jump after DeoptimizeStack(),
383         // right before interpreter::EnterInterpreterFromDeoptimize().
384         stacked_shadow_frame_pushed_ = true;
385         GetThread()->PushStackedShadowFrame(
386             new_frame, StackedShadowFrameType::kDeoptimizationShadowFrame);
387       }
388       prev_shadow_frame_ = new_frame;
389 
390       if (single_frame_deopt_ && !IsInInlinedFrame()) {
391         // Single-frame deopt ends at the first non-inlined frame and needs to store that method.
392         single_frame_done_ = true;
393         single_frame_deopt_method_ = method;
394         single_frame_deopt_quick_method_header_ = GetCurrentOatQuickMethodHeader();
395       }
396       callee_method_ = method;
397       return true;
398     }
399   }
400 
401  private:
HandleOptimizingDeoptimization(ArtMethod * m,ShadowFrame * new_frame,const bool * updated_vregs)402   void HandleOptimizingDeoptimization(ArtMethod* m,
403                                       ShadowFrame* new_frame,
404                                       const bool* updated_vregs)
405       REQUIRES_SHARED(Locks::mutator_lock_) {
406     const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
407     CodeInfo code_info = method_header->GetOptimizedCodeInfo();
408     uintptr_t native_pc_offset = method_header->NativeQuickPcOffset(GetCurrentQuickFramePc());
409     CodeInfoEncoding encoding = code_info.ExtractEncoding();
410     StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
411     CodeItemDataAccessor accessor(m->DexInstructionData());
412     const size_t number_of_vregs = accessor.RegistersSize();
413     uint32_t register_mask = code_info.GetRegisterMaskOf(encoding, stack_map);
414     BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, stack_map);
415     DexRegisterMap vreg_map = IsInInlinedFrame()
416         ? code_info.GetDexRegisterMapAtDepth(GetCurrentInliningDepth() - 1,
417                                              code_info.GetInlineInfoOf(stack_map, encoding),
418                                              encoding,
419                                              number_of_vregs)
420         : code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_vregs);
421 
422     if (!vreg_map.IsValid()) {
423       return;
424     }
425 
426     for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
427       if (updated_vregs != nullptr && updated_vregs[vreg]) {
428         // Keep the value set by debugger.
429         continue;
430       }
431 
432       DexRegisterLocation::Kind location =
433           vreg_map.GetLocationKind(vreg, number_of_vregs, code_info, encoding);
434       static constexpr uint32_t kDeadValue = 0xEBADDE09;
435       uint32_t value = kDeadValue;
436       bool is_reference = false;
437 
438       switch (location) {
439         case DexRegisterLocation::Kind::kInStack: {
440           const int32_t offset = vreg_map.GetStackOffsetInBytes(vreg,
441                                                                 number_of_vregs,
442                                                                 code_info,
443                                                                 encoding);
444           const uint8_t* addr = reinterpret_cast<const uint8_t*>(GetCurrentQuickFrame()) + offset;
445           value = *reinterpret_cast<const uint32_t*>(addr);
446           uint32_t bit = (offset >> 2);
447           if (bit < encoding.stack_mask.encoding.BitSize() && stack_mask.LoadBit(bit)) {
448             is_reference = true;
449           }
450           break;
451         }
452         case DexRegisterLocation::Kind::kInRegister:
453         case DexRegisterLocation::Kind::kInRegisterHigh:
454         case DexRegisterLocation::Kind::kInFpuRegister:
455         case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
456           uint32_t reg = vreg_map.GetMachineRegister(vreg, number_of_vregs, code_info, encoding);
457           bool result = GetRegisterIfAccessible(reg, ToVRegKind(location), &value);
458           CHECK(result);
459           if (location == DexRegisterLocation::Kind::kInRegister) {
460             if (((1u << reg) & register_mask) != 0) {
461               is_reference = true;
462             }
463           }
464           break;
465         }
466         case DexRegisterLocation::Kind::kConstant: {
467           value = vreg_map.GetConstant(vreg, number_of_vregs, code_info, encoding);
468           if (value == 0) {
469             // Make it a reference for extra safety.
470             is_reference = true;
471           }
472           break;
473         }
474         case DexRegisterLocation::Kind::kNone: {
475           break;
476         }
477         default: {
478           LOG(FATAL)
479               << "Unexpected location kind "
480               << vreg_map.GetLocationInternalKind(vreg,
481                                                   number_of_vregs,
482                                                   code_info,
483                                                   encoding);
484           UNREACHABLE();
485         }
486       }
487       if (is_reference) {
488         new_frame->SetVRegReference(vreg, reinterpret_cast<mirror::Object*>(value));
489       } else {
490         new_frame->SetVReg(vreg, value);
491       }
492     }
493   }
494 
GetVRegKind(uint16_t reg,const std::vector<int32_t> & kinds)495   static VRegKind GetVRegKind(uint16_t reg, const std::vector<int32_t>& kinds) {
496     return static_cast<VRegKind>(kinds.at(reg * 2));
497   }
498 
499   QuickExceptionHandler* const exception_handler_;
500   ShadowFrame* prev_shadow_frame_;
501   bool stacked_shadow_frame_pushed_;
502   const bool single_frame_deopt_;
503   bool single_frame_done_;
504   ArtMethod* single_frame_deopt_method_;
505   const OatQuickMethodHeader* single_frame_deopt_quick_method_header_;
506   ArtMethod* callee_method_;
507 
508   DISALLOW_COPY_AND_ASSIGN(DeoptimizeStackVisitor);
509 };
510 
PrepareForLongJumpToInvokeStubOrInterpreterBridge()511 void QuickExceptionHandler::PrepareForLongJumpToInvokeStubOrInterpreterBridge() {
512   if (full_fragment_done_) {
513     // Restore deoptimization exception. When returning from the invoke stub,
514     // ArtMethod::Invoke() will see the special exception to know deoptimization
515     // is needed.
516     self_->SetException(Thread::GetDeoptimizationException());
517   } else {
518     // PC needs to be of the quick-to-interpreter bridge.
519     int32_t offset;
520     offset = GetThreadOffset<kRuntimePointerSize>(kQuickQuickToInterpreterBridge).Int32Value();
521     handler_quick_frame_pc_ = *reinterpret_cast<uintptr_t*>(
522         reinterpret_cast<uint8_t*>(self_) + offset);
523   }
524 }
525 
DeoptimizeStack()526 void QuickExceptionHandler::DeoptimizeStack() {
527   DCHECK(is_deoptimization_);
528   if (kDebugExceptionDelivery) {
529     self_->DumpStack(LOG_STREAM(INFO) << "Deoptimizing: ");
530   }
531 
532   DeoptimizeStackVisitor visitor(self_, context_, this, false);
533   visitor.WalkStack(true);
534   PrepareForLongJumpToInvokeStubOrInterpreterBridge();
535 }
536 
DeoptimizeSingleFrame(DeoptimizationKind kind)537 void QuickExceptionHandler::DeoptimizeSingleFrame(DeoptimizationKind kind) {
538   DCHECK(is_deoptimization_);
539 
540   DeoptimizeStackVisitor visitor(self_, context_, this, true);
541   visitor.WalkStack(true);
542 
543   // Compiled code made an explicit deoptimization.
544   ArtMethod* deopt_method = visitor.GetSingleFrameDeoptMethod();
545   DCHECK(deopt_method != nullptr);
546   if (VLOG_IS_ON(deopt) || kDebugExceptionDelivery) {
547     LOG(INFO) << "Single-frame deopting: "
548               << deopt_method->PrettyMethod()
549               << " due to "
550               << GetDeoptimizationKindName(kind);
551     DumpFramesWithType(self_, /* details */ true);
552   }
553   if (Runtime::Current()->UseJitCompilation()) {
554     Runtime::Current()->GetJit()->GetCodeCache()->InvalidateCompiledCodeFor(
555         deopt_method, visitor.GetSingleFrameDeoptQuickMethodHeader());
556   } else {
557     // Transfer the code to interpreter.
558     Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
559         deopt_method, GetQuickToInterpreterBridge());
560   }
561 
562   PrepareForLongJumpToInvokeStubOrInterpreterBridge();
563 }
564 
DeoptimizePartialFragmentFixup(uintptr_t return_pc)565 void QuickExceptionHandler::DeoptimizePartialFragmentFixup(uintptr_t return_pc) {
566   // At this point, the instrumentation stack has been updated. We need to install
567   // the real return pc on stack, in case instrumentation stub is stored there,
568   // so that the interpreter bridge code can return to the right place.
569   if (return_pc != 0) {
570     uintptr_t* pc_addr = reinterpret_cast<uintptr_t*>(handler_quick_frame_);
571     CHECK(pc_addr != nullptr);
572     pc_addr--;
573     *reinterpret_cast<uintptr_t*>(pc_addr) = return_pc;
574   }
575 
576   // Architecture-dependent work. This is to get the LR right for x86 and x86-64.
577   if (kRuntimeISA == InstructionSet::kX86 || kRuntimeISA == InstructionSet::kX86_64) {
578     // On x86, the return address is on the stack, so just reuse it. Otherwise we would have to
579     // change how longjump works.
580     handler_quick_frame_ = reinterpret_cast<ArtMethod**>(
581         reinterpret_cast<uintptr_t>(handler_quick_frame_) - sizeof(void*));
582   }
583 }
584 
585 // Unwinds all instrumentation stack frame prior to catch handler or upcall.
586 class InstrumentationStackVisitor : public StackVisitor {
587  public:
InstrumentationStackVisitor(Thread * self,size_t frame_depth)588   InstrumentationStackVisitor(Thread* self, size_t frame_depth)
589       REQUIRES_SHARED(Locks::mutator_lock_)
590       : StackVisitor(self, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
591         frame_depth_(frame_depth),
592         instrumentation_frames_to_pop_(0) {
593     CHECK_NE(frame_depth_, kInvalidFrameDepth);
594   }
595 
VisitFrame()596   bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
597     size_t current_frame_depth = GetFrameDepth();
598     if (current_frame_depth < frame_depth_) {
599       CHECK(GetMethod() != nullptr);
600       if (UNLIKELY(reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc()) == GetReturnPc())) {
601         if (!IsInInlinedFrame()) {
602           // We do not count inlined frames, because we do not instrument them. The reason we
603           // include them in the stack walking is the check against `frame_depth_`, which is
604           // given to us by a visitor that visits inlined frames.
605           ++instrumentation_frames_to_pop_;
606         }
607       }
608       return true;
609     } else {
610       // We reached the frame of the catch handler or the upcall.
611       return false;
612     }
613   }
614 
GetInstrumentationFramesToPop() const615   size_t GetInstrumentationFramesToPop() const {
616     return instrumentation_frames_to_pop_;
617   }
618 
619  private:
620   const size_t frame_depth_;
621   size_t instrumentation_frames_to_pop_;
622 
623   DISALLOW_COPY_AND_ASSIGN(InstrumentationStackVisitor);
624 };
625 
UpdateInstrumentationStack()626 uintptr_t QuickExceptionHandler::UpdateInstrumentationStack() {
627   uintptr_t return_pc = 0;
628   if (method_tracing_active_) {
629     InstrumentationStackVisitor visitor(self_, handler_frame_depth_);
630     visitor.WalkStack(true);
631 
632     size_t instrumentation_frames_to_pop = visitor.GetInstrumentationFramesToPop();
633     instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
634     for (size_t i = 0; i < instrumentation_frames_to_pop; ++i) {
635       return_pc = instrumentation->PopMethodForUnwind(self_, is_deoptimization_);
636     }
637   }
638   return return_pc;
639 }
640 
DoLongJump(bool smash_caller_saves)641 void QuickExceptionHandler::DoLongJump(bool smash_caller_saves) {
642   // Place context back on thread so it will be available when we continue.
643   self_->ReleaseLongJumpContext(context_);
644   context_->SetSP(reinterpret_cast<uintptr_t>(handler_quick_frame_));
645   CHECK_NE(handler_quick_frame_pc_, 0u);
646   context_->SetPC(handler_quick_frame_pc_);
647   context_->SetArg0(handler_quick_arg0_);
648   if (smash_caller_saves) {
649     context_->SmashCallerSaves();
650   }
651   context_->DoLongJump();
652   UNREACHABLE();
653 }
654 
655 // Prints out methods with their type of frame.
656 class DumpFramesWithTypeStackVisitor FINAL : public StackVisitor {
657  public:
DumpFramesWithTypeStackVisitor(Thread * self,bool show_details=false)658   explicit DumpFramesWithTypeStackVisitor(Thread* self, bool show_details = false)
659       REQUIRES_SHARED(Locks::mutator_lock_)
660       : StackVisitor(self, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
661         show_details_(show_details) {}
662 
VisitFrame()663   bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
664     ArtMethod* method = GetMethod();
665     if (show_details_) {
666       LOG(INFO) << "|> pc   = " << std::hex << GetCurrentQuickFramePc();
667       LOG(INFO) << "|> addr = " << std::hex << reinterpret_cast<uintptr_t>(GetCurrentQuickFrame());
668       if (GetCurrentQuickFrame() != nullptr && method != nullptr) {
669         LOG(INFO) << "|> ret  = " << std::hex << GetReturnPc();
670       }
671     }
672     if (method == nullptr) {
673       // Transition, do go on, we want to unwind over bridges, all the way.
674       if (show_details_) {
675         LOG(INFO) << "N  <transition>";
676       }
677       return true;
678     } else if (method->IsRuntimeMethod()) {
679       if (show_details_) {
680         LOG(INFO) << "R  " << method->PrettyMethod(true);
681       }
682       return true;
683     } else {
684       bool is_shadow = GetCurrentShadowFrame() != nullptr;
685       LOG(INFO) << (is_shadow ? "S" : "Q")
686                 << ((!is_shadow && IsInInlinedFrame()) ? "i" : " ")
687                 << " "
688                 << method->PrettyMethod(true);
689       return true;  // Go on.
690     }
691   }
692 
693  private:
694   bool show_details_;
695 
696   DISALLOW_COPY_AND_ASSIGN(DumpFramesWithTypeStackVisitor);
697 };
698 
DumpFramesWithType(Thread * self,bool details)699 void QuickExceptionHandler::DumpFramesWithType(Thread* self, bool details) {
700   DumpFramesWithTypeStackVisitor visitor(self, details);
701   visitor.WalkStack(true);
702 }
703 
704 }  // namespace art
705