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
38namespace art {
39
40static constexpr bool kDebugExceptionDelivery = false;
41static constexpr size_t kInvalidFrameDepth = 0xffffffff;
42
43QuickExceptionHandler::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.
60class CatchBlockStackVisitor FINAL : public StackVisitor {
61 public:
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
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:
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
144void 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
184static 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
216void 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.
284class DeoptimizeStackVisitor FINAL : public StackVisitor {
285 public:
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
302  ArtMethod* GetSingleFrameDeoptMethod() const {
303    return single_frame_deopt_method_;
304  }
305
306  const OatQuickMethodHeader* GetSingleFrameDeoptQuickMethodHeader() const {
307    return single_frame_deopt_quick_method_header_;
308  }
309
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
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:
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
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
511void 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
526void 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
537void 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
565void 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.
586class InstrumentationStackVisitor : public StackVisitor {
587 public:
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
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
615  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
626uintptr_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
641void 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.
656class DumpFramesWithTypeStackVisitor FINAL : public StackVisitor {
657 public:
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
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
699void QuickExceptionHandler::DumpFramesWithType(Thread* self, bool details) {
700  DumpFramesWithTypeStackVisitor visitor(self, details);
701  visitor.WalkStack(true);
702}
703
704}  // namespace art
705