stack.cc revision cccd84f1f972f1a260c3be418c8388a5d30cf59e
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"
2068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes#include "object.h"
21bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes#include "thread_list.h"
2268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstromint oatVRegOffsetFromMethod(art::Method* method, int reg);
243320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
2568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughesnamespace art {
2668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
2768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughesbool Frame::HasMethod() const {
283320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  return GetMethod() != NULL && (!GetMethod()->IsCalleeSaveMethod());
2968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
3068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
3168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughesvoid Frame::Next() {
3268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  size_t frame_size = GetMethod()->GetFrameSizeInBytes();
3368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  DCHECK_NE(frame_size, 0u);
3468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  DCHECK_LT(frame_size, 1024u);
3568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  byte* next_sp = reinterpret_cast<byte*>(sp_) + frame_size;
3668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  sp_ = reinterpret_cast<Method**>(next_sp);
3768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  if (*sp_ != NULL) {
3868e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes    DCHECK((*sp_)->GetClass() == Method::GetMethodClass() ||
3968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes        (*sp_)->GetClass() == Method::GetConstructorClass());
4068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  }
4168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
4268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
4368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughesuintptr_t Frame::GetReturnPC() const {
4468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  byte* pc_addr = reinterpret_cast<byte*>(sp_) + GetMethod()->GetReturnPcOffsetInBytes();
4568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  return *reinterpret_cast<uintptr_t*>(pc_addr);
4668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
4768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
481bba14f20039b6e706b719fdd5754eb30088d014Elliott Hughesuint32_t Frame::GetVReg(Method* method, int vreg) const {
4968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  DCHECK(method == GetMethod());
5068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  int offset = oatVRegOffsetFromMethod(method, vreg);
5168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  byte* vreg_addr = reinterpret_cast<byte*>(sp_) + offset;
521bba14f20039b6e706b719fdd5754eb30088d014Elliott Hughes  return *reinterpret_cast<uint32_t*>(vreg_addr);
5368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
5468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
55cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughesvoid Frame::SetVReg(Method* method, int vreg, uint32_t new_value) {
56cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  DCHECK(method == GetMethod());
57cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  int offset = oatVRegOffsetFromMethod(method, vreg);
58cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  byte* vreg_addr = reinterpret_cast<byte*>(sp_) + offset;
59cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  *reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
60cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes}
61cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes
6268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughesuintptr_t Frame::LoadCalleeSave(int num) const {
6368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  // Callee saves are held at the top of the frame
6468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  Method* method = GetMethod();
6568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  DCHECK(method != NULL);
6668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  size_t frame_size = method->GetFrameSizeInBytes();
6768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  byte* save_addr = reinterpret_cast<byte*>(sp_) + frame_size - ((num + 1) * kPointerSize);
6868e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes#if defined(__i386__)
6968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  save_addr -= kPointerSize;  // account for return address
7068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes#endif
7168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  return *reinterpret_cast<uintptr_t*>(save_addr);
7268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
7368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
7468e76526e98432625464022cb26f66b9ef6f5af4Elliott HughesMethod* Frame::NextMethod() const {
7568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  byte* next_sp = reinterpret_cast<byte*>(sp_) + GetMethod()->GetFrameSizeInBytes();
7668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  return *reinterpret_cast<Method**>(next_sp);
7768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
7868e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
79bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesclass StackGetter {
80bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes public:
81bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  StackGetter(JNIEnv* env, Thread* thread) : env_(env), thread_(thread), trace_(NULL) {
82bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  }
83bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
84bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  static void Callback(void* arg) {
85bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes    reinterpret_cast<StackGetter*>(arg)->Callback();
86bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  }
87bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
88bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  jobject GetTrace() {
89bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes    return trace_;
90bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  }
91bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
92bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes private:
93bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  void Callback() {
94bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes    trace_ = thread_->CreateInternalStackTrace(env_);
95bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  }
96bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
97bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  JNIEnv* env_;
98bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  Thread* thread_;
99bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  jobject trace_;
100bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes};
101bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
102bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesjobject GetThreadStack(JNIEnv* env, Thread* thread) {
103bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  ThreadList* thread_list = Runtime::Current()->GetThreadList();
104bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  StackGetter stack_getter(env, thread);
105bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  thread_list->RunWhileSuspended(thread, StackGetter::Callback, &stack_getter);
106bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  return stack_getter.GetTrace();
107bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes}
108bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
10968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}  // namespace art
110