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