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