stack.cc revision 11d1b0c31ddd710d26068da8e0e4621002205b4b
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"
216d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
22bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes#include "thread_list.h"
2368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
2411d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesnamespace art {
2511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
2611d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesint oatVRegOffset(const DexFile::CodeItem* code_item,
276d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers                  uint32_t core_spills, uint32_t fp_spills,
286d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers                  size_t frame_size, int reg);
293320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
3068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughesbool Frame::HasMethod() const {
313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  return GetMethod() != NULL && (!GetMethod()->IsCalleeSaveMethod());
3268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
3368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
3468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughesvoid Frame::Next() {
3568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  size_t frame_size = GetMethod()->GetFrameSizeInBytes();
3668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  DCHECK_NE(frame_size, 0u);
3768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  DCHECK_LT(frame_size, 1024u);
3868e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  byte* next_sp = reinterpret_cast<byte*>(sp_) + frame_size;
3968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  sp_ = reinterpret_cast<Method**>(next_sp);
4068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  if (*sp_ != NULL) {
4168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes    DCHECK((*sp_)->GetClass() == Method::GetMethodClass() ||
4268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes        (*sp_)->GetClass() == Method::GetConstructorClass());
4368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  }
4468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
4568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
4668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughesuintptr_t Frame::GetReturnPC() const {
4768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  byte* pc_addr = reinterpret_cast<byte*>(sp_) + GetMethod()->GetReturnPcOffsetInBytes();
4868e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  return *reinterpret_cast<uintptr_t*>(pc_addr);
4968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
5068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
51e343b76af81a005ef64f5e75a555389fd9147dabjeffhaovoid Frame::SetReturnPC(uintptr_t pc) {
52e343b76af81a005ef64f5e75a555389fd9147dabjeffhao  byte* pc_addr = reinterpret_cast<byte*>(sp_) + GetMethod()->GetReturnPcOffsetInBytes();
53e343b76af81a005ef64f5e75a555389fd9147dabjeffhao  *reinterpret_cast<uintptr_t*>(pc_addr) = pc;
54e343b76af81a005ef64f5e75a555389fd9147dabjeffhao}
55e343b76af81a005ef64f5e75a555389fd9147dabjeffhao
566d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogersuint32_t Frame::GetVReg(const DexFile::CodeItem* code_item, uint32_t core_spills,
576d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers                        uint32_t fp_spills, size_t frame_size, int vreg) const {
586d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  int offset = oatVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
5968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  byte* vreg_addr = reinterpret_cast<byte*>(sp_) + offset;
601bba14f20039b6e706b719fdd5754eb30088d014Elliott Hughes  return *reinterpret_cast<uint32_t*>(vreg_addr);
6168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
6268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
636d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogersuint32_t Frame::GetVReg(Method* m, int vreg) const {
646d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  DCHECK(m == GetMethod());
6511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes  const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
666d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  DCHECK(code_item != NULL);  // can't be NULL or how would we compile its instructions?
676d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  uint32_t core_spills = m->GetCoreSpillMask();
686d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  uint32_t fp_spills = m->GetFpSpillMask();
696d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  size_t frame_size = m->GetFrameSizeInBytes();
706d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  return GetVReg(code_item, core_spills, fp_spills, frame_size, vreg);
716d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers}
726d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers
736d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogersvoid Frame::SetVReg(Method* m, int vreg, uint32_t new_value) {
746d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  DCHECK(m == GetMethod());
7511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes  const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
766d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  DCHECK(code_item != NULL);  // can't be NULL or how would we compile its instructions?
776d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  uint32_t core_spills = m->GetCoreSpillMask();
786d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  uint32_t fp_spills = m->GetFpSpillMask();
796d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  size_t frame_size = m->GetFrameSizeInBytes();
806d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  int offset = oatVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
81cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  byte* vreg_addr = reinterpret_cast<byte*>(sp_) + offset;
82cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  *reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
83cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes}
84cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes
8568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughesuintptr_t Frame::LoadCalleeSave(int num) const {
8668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  // Callee saves are held at the top of the frame
8768e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  Method* method = GetMethod();
8868e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  DCHECK(method != NULL);
8968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  size_t frame_size = method->GetFrameSizeInBytes();
9068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  byte* save_addr = reinterpret_cast<byte*>(sp_) + frame_size - ((num + 1) * kPointerSize);
9168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes#if defined(__i386__)
9268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  save_addr -= kPointerSize;  // account for return address
9368e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes#endif
9468e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  return *reinterpret_cast<uintptr_t*>(save_addr);
9568e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
9668e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
9768e76526e98432625464022cb26f66b9ef6f5af4Elliott HughesMethod* Frame::NextMethod() const {
9868e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  byte* next_sp = reinterpret_cast<byte*>(sp_) + GetMethod()->GetFrameSizeInBytes();
9968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes  return *reinterpret_cast<Method**>(next_sp);
10068e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}
10168e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes
102bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesclass StackGetter {
103bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes public:
104bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  StackGetter(JNIEnv* env, Thread* thread) : env_(env), thread_(thread), trace_(NULL) {
105bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  }
106bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
107bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  static void Callback(void* arg) {
108bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes    reinterpret_cast<StackGetter*>(arg)->Callback();
109bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  }
110bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
111bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  jobject GetTrace() {
112bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes    return trace_;
113bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  }
114bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
115bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes private:
116bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  void Callback() {
117bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes    trace_ = thread_->CreateInternalStackTrace(env_);
118bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  }
119bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
120bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  JNIEnv* env_;
121bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  Thread* thread_;
122bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  jobject trace_;
123bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes};
124bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
125bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesjobject GetThreadStack(JNIEnv* env, Thread* thread) {
126bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  ThreadList* thread_list = Runtime::Current()->GetThreadList();
127bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  StackGetter stack_getter(env, thread);
128bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  thread_list->RunWhileSuspended(thread, StackGetter::Callback, &stack_getter);
129bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes  return stack_getter.GetTrace();
130bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes}
131bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
13268e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes}  // namespace art
133