stack.cc revision 0399dde18753aa9bd2bd0d7cf60beef154d164a4
168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes/*
268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes * Copyright (C) 2011 The Android Open Source Project
368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes *
468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes * you may not use this file except in compliance with the License.
668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes * You may obtain a copy of the License at
768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes *
868e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes *
1068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes * Unless required by applicable law or agreed to in writing, software
1168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
1268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes * See the License for the specific language governing permissions and
1468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes * limitations under the License.
1568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes */
1668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
1768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes#include "stack.h"
1868e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
1968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes#include "compiler.h"
200399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers#include "oat/runtime/context.h"
2168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes#include "object.h"
226d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
23bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes#include "thread_list.h"
2468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
2511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesnamespace art {
2611d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
270399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersclass StackGetter {
280399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers public:
290399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  StackGetter(JNIEnv* env, Thread* thread) : env_(env), thread_(thread), trace_(NULL) {
300399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  }
3168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
320399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  static void Callback(void* arg) {
330399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    reinterpret_cast<StackGetter*>(arg)->Callback();
3468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  }
350399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers
360399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  jobject GetTrace() {
370399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    return trace_;
380399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  }
390399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers
400399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers private:
410399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  void Callback() {
420399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    trace_ = thread_->CreateInternalStackTrace(env_);
430399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  }
440399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers
450399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  JNIEnv* env_;
460399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  Thread* thread_;
470399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  jobject trace_;
480399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers};
490399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers
500399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersjobject GetThreadStack(JNIEnv* env, Thread* thread) {
510399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  ThreadList* thread_list = Runtime::Current()->GetThreadList();
520399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  StackGetter stack_getter(env, thread);
530399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  thread_list->RunWhileSuspended(thread, StackGetter::Callback, &stack_getter);
540399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  return stack_getter.GetTrace();
5568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
5668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
570399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersvoid ManagedStack::PushManagedStackFragment(ManagedStack* fragment) {
580399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  // Copy this top fragment into given fragment.
590399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  memcpy(fragment, this, sizeof(ManagedStack));
600399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  // Clear this fragment, which has become the top.
610399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  memset(this, 0, sizeof(ManagedStack));
620399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  // Link our top fragment onto the given fragment.
630399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  link_ = fragment;
6468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
6568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
660399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersvoid ManagedStack::PopManagedStackFragment(const ManagedStack& fragment) {
670399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  DCHECK(&fragment == link_);
680399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  // Copy this given fragment back to the top.
690399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  memcpy(this, &fragment, sizeof(ManagedStack));
70e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}
71e343b76af81a005ef64f5e75a555389fd9147dabjeffhao
720399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogerssize_t ManagedStack::NumShadowFrameReferences() const {
730399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  size_t count = 0;
740399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  for (const ManagedStack* current_fragment = this; current_fragment != NULL;
750399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers       current_fragment = current_fragment->GetLink()) {
760399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; current_frame != NULL;
770399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers         current_frame = current_frame->GetLink()) {
780399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      count += current_frame->NumberOfReferences();
790399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    }
80efccc565091b3409ed1372615b4ea4e2f6c39323buzbee  }
810399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  return count;
82b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes}
83b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
840399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersbool ManagedStack::ShadowFramesContain(Object** shadow_frame_entry) const {
850399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  for (const ManagedStack* current_fragment = this; current_fragment != NULL;
860399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers       current_fragment = current_fragment->GetLink()) {
870399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; current_frame != NULL;
880399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers         current_frame = current_frame->GetLink()) {
890399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      if (current_frame->Contains(shadow_frame_entry)) {
900399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        return true;
910399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      }
920399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    }
930399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  }
940399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  return false;
9568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
9668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
970399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersuint32_t StackVisitor::GetDexPc() const {
980399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  if (cur_shadow_frame_ != NULL) {
990399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    return cur_shadow_frame_->GetDexPC();
1000399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  } else if (cur_quick_frame_ != NULL) {
1010399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    return GetMethod()->ToDexPC(AdjustQuickFramePcForDexPcComputation(cur_quick_frame_pc_));
1020399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  } else {
1030399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    return 0;
1040399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  }
1050399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers}
1060399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers
1070399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersuint32_t StackVisitor::GetVReg(Method* m, int vreg) const {
1086d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  DCHECK(m == GetMethod());
1096d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  uint32_t core_spills = m->GetCoreSpillMask();
1100399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  const VmapTable vmap_table(m->GetVmapTableRaw());
1110399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  uint32_t vmap_offset;
1120399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  // TODO: IsInContext stops before spotting floating point registers.
1130399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  if (vmap_table.IsInContext(vreg, vmap_offset)) {
1140399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    // Compute the register we need to load from the context.
1150399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    uint32_t spill_mask = core_spills;
1160399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    CHECK_LT(vmap_offset, static_cast<uint32_t>(__builtin_popcount(spill_mask)));
1170399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    uint32_t matches = 0;
1180399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    uint32_t spill_shifts = 0;
1190399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    while (matches != (vmap_offset + 1)) {
1200399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      DCHECK_NE(spill_mask, 0u);
1210399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      matches += spill_mask & 1;  // Add 1 if the low bit is set.
1220399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      spill_mask >>= 1;
1230399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      spill_shifts++;
1240399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    }
1250399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    spill_shifts--;  // Wind back one as we want the last match.
1260399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    return GetGPR(spill_shifts);
1270399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  } else {
1280399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
1290399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    DCHECK(code_item != NULL);  // can't be NULL or how would we compile its instructions?
1300399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    uint32_t fp_spills = m->GetFpSpillMask();
1310399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    size_t frame_size = m->GetFrameSizeInBytes();
1320399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    return GetVReg(code_item, core_spills, fp_spills, frame_size, vreg);
1330399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  }
1346d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers}
1356d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers
1360399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersvoid StackVisitor::SetVReg(Method* m, int vreg, uint32_t new_value) {
1376d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  DCHECK(m == GetMethod());
1380399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  const VmapTable vmap_table(m->GetVmapTableRaw());
1390399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  uint32_t vmap_offset;
1400399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  // TODO: IsInContext stops before spotting floating point registers.
1410399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  if (vmap_table.IsInContext(vreg, vmap_offset)) {
1420399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    UNIMPLEMENTED(FATAL);
1430399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  }
14411d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes  const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
1456d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  DCHECK(code_item != NULL);  // can't be NULL or how would we compile its instructions?
1466d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  uint32_t core_spills = m->GetCoreSpillMask();
1476d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  uint32_t fp_spills = m->GetFpSpillMask();
1486d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  size_t frame_size = m->GetFrameSizeInBytes();
149b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
1500399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  byte* vreg_addr = reinterpret_cast<byte*>(GetCurrentQuickFrame()) + offset;
151cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  *reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
152cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes}
153cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes
1540399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersuintptr_t StackVisitor::GetGPR(uint32_t reg) const {
1550399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  return context_->GetGPR(reg);
15668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
15768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
1580399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersuintptr_t StackVisitor::GetReturnPc() const {
1590399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  Method** sp = GetCurrentQuickFrame();
1600399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  CHECK(sp != NULL);
1610399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  byte* pc_addr = reinterpret_cast<byte*>(sp) + GetMethod()->GetReturnPcOffsetInBytes();
1620399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  return *reinterpret_cast<uintptr_t*>(pc_addr);
16368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
16468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
1650399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersvoid StackVisitor::SetReturnPc(uintptr_t new_ret_pc) {
1660399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  Method** sp = GetCurrentQuickFrame();
1670399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  CHECK(sp != NULL);
1680399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  byte* pc_addr = reinterpret_cast<byte*>(sp) + GetMethod()->GetReturnPcOffsetInBytes();
1690399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  *reinterpret_cast<uintptr_t*>(pc_addr) = new_ret_pc;
1700399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers}
171bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
1720399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogerssize_t StackVisitor::ComputeNumFrames() const {
1730399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  struct NumFramesVisitor : public StackVisitor {
1740399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    explicit NumFramesVisitor(const ManagedStack* stack,
1750399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers                              const std::vector<TraceStackFrame>* trace_stack) :
1760399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers                                StackVisitor(stack, trace_stack), frames(0) {}
177bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
1780399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    virtual bool VisitFrame() {
1790399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      frames++;
1800399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      return true;
1810399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    }
1820399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    size_t frames;
1830399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  };
184bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
1850399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  NumFramesVisitor visitor(stack_start_, trace_stack_);
1860399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  visitor.WalkStack(true);
1870399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  return visitor.frames;
1880399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers}
189bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
1900399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersvoid StackVisitor::SanityCheckFrame() {
1910399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers#ifndef NDEBUG
1920399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  Method* method = GetMethod();
1930399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  CHECK(method->GetClass() == Method::GetMethodClass() ||
1940399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        method->GetClass() == Method::GetConstructorClass());
1950399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  if (cur_quick_frame_ != NULL) {
1960399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    method->AssertPcIsWithinCode(AdjustQuickFramePcForDexPcComputation(cur_quick_frame_pc_));
1970399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    // Frame sanity.
1980399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    size_t frame_size = method->GetFrameSizeInBytes();
1990399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    CHECK_NE(frame_size, 0u);
2000399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    CHECK_LT(frame_size, 1024u);
2010399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    size_t return_pc_offset = method->GetReturnPcOffsetInBytes();
2020399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    CHECK_LT(return_pc_offset, frame_size);
2030399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  }
2040399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers#endif
2050399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers}
206bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
2070399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersvoid StackVisitor::WalkStack(bool include_transitions) {
2080399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  bool method_tracing_active = Runtime::Current()->IsMethodTracingActive();
2090399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  uint32_t trace_stack_depth = 0;
2100399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  for (const ManagedStack* current_fragment = stack_start_; current_fragment != NULL;
2110399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers       current_fragment = current_fragment->GetLink()) {
2120399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    cur_shadow_frame_ = current_fragment->GetTopShadowFrame();
2130399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    cur_quick_frame_ = current_fragment->GetTopQuickFrame();
2140399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    cur_quick_frame_pc_ = current_fragment->GetTopQuickFramePc();
2150399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    if (cur_quick_frame_ != NULL) {  // Handle quick stack frames.
2160399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      // Can't be both a shadow and a quick fragment.
2170399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      DCHECK(current_fragment->GetTopShadowFrame() == NULL);
2180399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      Method* method = *cur_quick_frame_;
2190399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      do {
2200399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        SanityCheckFrame();
2210399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        bool should_continue = VisitFrame();
2220399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        if (UNLIKELY(!should_continue)) {
2230399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers          return;
2240399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        }
2250399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        if (context_ != NULL) {
2260399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers          context_->FillCalleeSaves(*this);
2270399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        }
2280399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        size_t frame_size = method->GetFrameSizeInBytes();
2290399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        // Compute PC for next stack frame from return PC.
2300399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        size_t return_pc_offset = method->GetReturnPcOffsetInBytes();
2310399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        byte* return_pc_addr = reinterpret_cast<byte*>(cur_quick_frame_) + return_pc_offset;
2320399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        uintptr_t return_pc = *reinterpret_cast<uintptr_t*>(return_pc_addr);
2330399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        if (UNLIKELY(method_tracing_active)) {
2340399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers          // While profiling, the return pc is restored from the side stack, except when walking
2350399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers          // the stack for an exception where the side stack will be unwound in VisitFrame.
2360399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers          // TODO: stop using include_transitions as a proxy for is this the catch block visitor.
2370399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers          if (IsTraceExitPc(return_pc) && !include_transitions) {
2380399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers            // TODO: unify trace and managed stack.
2390399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers            TraceStackFrame trace_frame = GetTraceStackFrame(trace_stack_depth);
2400399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers            trace_stack_depth++;
2410399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers            CHECK(trace_frame.method_ == GetMethod()) << "Excepted: " << PrettyMethod(method)
2420399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers                << " Found: " << PrettyMethod(GetMethod());
2430399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers            return_pc = trace_frame.return_pc_;
2440399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers          }
2450399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        }
2460399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        cur_quick_frame_pc_ = return_pc;
2470399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        byte* next_frame = reinterpret_cast<byte*>(cur_quick_frame_) + frame_size;
2480399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        cur_quick_frame_ = reinterpret_cast<Method**>(next_frame);
2490399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        cur_depth_++;
2500399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        method = *cur_quick_frame_;
2510399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      } while (method != NULL);
2520399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    } else if (cur_shadow_frame_ != NULL) {
2530399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      do {
2540399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        SanityCheckFrame();
2550399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        bool should_continue = VisitFrame();
2560399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        if (UNLIKELY(!should_continue)) {
2570399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers          return;
2580399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        }
2590399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        cur_depth_++;
2600399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        cur_shadow_frame_ = cur_shadow_frame_->GetLink();
2610399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      } while(cur_shadow_frame_ != NULL);
2620399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    }
2630399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    cur_depth_++;
2640399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    if (include_transitions) {
2650399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      bool should_continue = VisitFrame();
2660399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      if (!should_continue) {
2670399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers        return;
2680399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers      }
2690399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers    }
2700399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  }
271bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes}
272bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
27368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}  // namespace art
274