diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/class_linker.cc | 13 | ||||
| -rw-r--r-- | src/class_linker.h | 4 | ||||
| -rw-r--r-- | src/dex_file.cc | 5 | ||||
| -rw-r--r-- | src/dex_file.h | 4 | ||||
| -rw-r--r-- | src/exception.h | 22 | ||||
| -rw-r--r-- | src/exception_test.cc | 36 | ||||
| -rw-r--r-- | src/object.cc | 13 | ||||
| -rw-r--r-- | src/object.h | 47 | ||||
| -rw-r--r-- | src/thread.cc | 36 | ||||
| -rw-r--r-- | src/thread.h | 14 |
10 files changed, 166 insertions, 28 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index 3907d07ca6..3c72dad6ab 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -30,6 +30,7 @@ const char* ClassLinker::class_roots_descriptors_[kClassRootsMax] = { "Ljava/lang/ClassLoader;", "Ldalvik/system/BaseDexClassLoader;", "Ldalvik/system/PathClassLoader;", + "Ljava/lang/StackTraceElement;", "Z", "B", "C", @@ -47,6 +48,7 @@ const char* ClassLinker::class_roots_descriptors_[kClassRootsMax] = { "[I", "[J", "[S", + "[Ljava/lang/StackTraceElement;", }; ClassLinker* ClassLinker::Create(const std::vector<const DexFile*>& boot_class_path, Space* space) { @@ -237,12 +239,15 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path) { SetClassRoot(kFloatArrayClass, FindSystemClass("[F")); SetClassRoot(kLongArrayClass, FindSystemClass("[J")); SetClassRoot(kShortArrayClass, FindSystemClass("[S")); + SetClassRoot(kJavaLangStackTraceElement, FindSystemClass("Ljava/lang/StackTraceElement;")); + SetClassRoot(kJavaLangStackTraceElementArrayClass, FindSystemClass("[Ljava/lang/StackTraceElement;")); BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); + StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); FinishInit(); } @@ -342,6 +347,7 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path, Space LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); PathClassLoader::SetClass(GetClassRoot(kDalvikSystemPathClassLoader)); + StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); FinishInit(); } @@ -415,6 +421,7 @@ ClassLinker::~ClassLinker() { LongArray::ResetArrayClass(); ShortArray::ResetArrayClass(); PathClassLoader::ResetClass(); + StackTraceElement::ResetClass(); } DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) { @@ -446,6 +453,12 @@ Method* ClassLinker::AllocMethod() { return down_cast<Method*>(GetClassRoot(kJavaLangReflectMethod)->NewInstance()); } +ObjectArray<StackTraceElement>* ClassLinker::AllocStackTraceElementArray(size_t length) { + return ObjectArray<StackTraceElement>::Alloc( + GetClassRoot(kJavaLangStackTraceElementArrayClass), + length); +} + Class* ClassLinker::FindClass(const StringPiece& descriptor, const ClassLoader* class_loader) { // TODO: remove this contrived parent class loader check when we have a real ClassLoader. diff --git a/src/class_linker.h b/src/class_linker.h index c8488254a9..88e1a67839 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -104,6 +104,8 @@ class ClassLinker { const DexFile& FindDexFile(const DexCache* dex_cache) const; DexCache* FindDexCache(const DexFile& dex_file) const; + ObjectArray<StackTraceElement>* AllocStackTraceElementArray(size_t length); + private: ClassLinker(); @@ -239,6 +241,7 @@ class ClassLinker { kJavaLangClassLoader, kDalvikSystemBaseDexClassLoader, kDalvikSystemPathClassLoader, + kJavaLangStackTraceElement, kPrimitiveBoolean, kPrimitiveByte, kPrimitiveChar, @@ -256,6 +259,7 @@ class ClassLinker { kIntArrayClass, kLongArrayClass, kShortArrayClass, + kJavaLangStackTraceElementArrayClass, kClassRootsMax, }; ObjectArray<Class>* class_roots_; diff --git a/src/dex_file.cc b/src/dex_file.cc index 3489086dde..01eb099561 100644 --- a/src/dex_file.cc +++ b/src/dex_file.cc @@ -532,7 +532,10 @@ DexFile::ValueType DexFile::ReadEncodedValue(const byte** stream, return static_cast<ValueType>(type); } -String* DexFile::dexArtStringById(uint32_t idx) const { +String* DexFile::dexArtStringById(int32_t idx) const { + if (idx == -1) { + return NULL; + } return String::AllocFromModifiedUtf8(dexStringById(idx)); } diff --git a/src/dex_file.h b/src/dex_file.h index 2dcb3b2ca5..db7a54b680 100644 --- a/src/dex_file.h +++ b/src/dex_file.h @@ -535,7 +535,7 @@ class DexFile { return dexStringById(idx, &unicode_length); } - String* dexArtStringById(uint32_t idx) const; + String* dexArtStringById(int32_t idx) const; // Get the descriptor string associated with a given type index. const char* dexStringByTypeIdx(uint32_t idx, int32_t* unicode_length) const { @@ -548,7 +548,7 @@ class DexFile { return dexStringById(type_id.descriptor_idx_); } - String* dexArtStringByTypeIdx(uint32_t idx) const { + String* dexArtStringByTypeIdx(int32_t idx) const { const TypeId& type_id = GetTypeId(idx); return dexArtStringById(type_id.descriptor_idx_); } diff --git a/src/exception.h b/src/exception.h deleted file mode 100644 index 5b31e86449..0000000000 --- a/src/exception.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. - -#ifndef ART_SRC_EXCEPTION_H_ -#define ART_SRC_EXCEPTION_H_ - -#include "class_linker.h" -#include "dex_file.h" -#include "object.h" -#include "thread.h" - -namespace art { - -struct InternalStackTrace { - const Method* method; - const uint16_t* pc; -}; - -extern InternalStackTrace *GetStackTrace(uint16_t stack_depth); - -} - -#endif // ART_SRC_EXCEPTION_H_ diff --git a/src/exception_test.cc b/src/exception_test.cc index 99fd9548d3..4337d7a1fe 100644 --- a/src/exception_test.cc +++ b/src/exception_test.cc @@ -73,8 +73,12 @@ class ExceptionTest : public CommonTest { ASSERT_TRUE(my_klass_ != NULL); method_f_ = my_klass_->FindVirtualMethod("f", "()I"); ASSERT_TRUE(method_f_ != NULL); + method_f_->SetFrameSizeInBytes(8); + method_f_->SetReturnPcOffsetInBytes(4); method_g_ = my_klass_->FindVirtualMethod("g", "(I)V"); ASSERT_TRUE(method_g_ != NULL); + method_g_->SetFrameSizeInBytes(8); + method_g_->SetReturnPcOffsetInBytes(4); } DexFile::CatchHandlerItem FindCatchHandlerItem(Method* method, @@ -132,4 +136,36 @@ TEST_F(ExceptionTest, FindCatchHandler) { ASSERT_EQ(true, iter.HasNext()); } +TEST_F(ExceptionTest, StackTraceElement) { + enum {STACK_SIZE = 1000}; + uint32_t top_of_stack = 0; + uintptr_t fake_stack[STACK_SIZE]; + fake_stack[top_of_stack++] = reinterpret_cast<uintptr_t>(method_g_); + fake_stack[top_of_stack++] = 3; + fake_stack[top_of_stack++] = reinterpret_cast<uintptr_t>(method_f_); + fake_stack[top_of_stack++] = 3; + + Thread* thread = Thread::Current(); + thread->SetTopOfStack(fake_stack); + + Thread::InternalStackTrace* traces = thread->GetStackTrace(2); + ObjectArray<StackTraceElement>* trace_array = thread->GetStackTraceElement(2, traces); + delete[] traces; + + ASSERT_TRUE(trace_array->Get(0) != NULL); + EXPECT_STREQ("java.lang.MyClass", trace_array->Get(0)->GetDeclaringClass()->ToModifiedUtf8().c_str()); + EXPECT_STREQ("MyClass.java", trace_array->Get(0)->GetFileName()->ToModifiedUtf8().c_str()); + EXPECT_STREQ("g", trace_array->Get(0)->GetMethodName()->ToModifiedUtf8().c_str()); + EXPECT_EQ(22u, trace_array->Get(0)->GetLineNumber()); + + ASSERT_TRUE(trace_array->Get(1) != NULL); + EXPECT_STREQ("java.lang.MyClass", trace_array->Get(1)->GetDeclaringClass()->ToModifiedUtf8().c_str()); + EXPECT_STREQ("MyClass.java", trace_array->Get(1)->GetFileName()->ToModifiedUtf8().c_str()); + EXPECT_STREQ("f", trace_array->Get(1)->GetMethodName()->ToModifiedUtf8().c_str()); + EXPECT_EQ(7u, trace_array->Get(1)->GetLineNumber()); +} + +// TODO: Test with native frame: For native frame, lineno should be -2 to +// indicate it is native. That is how libcore tells from the StackTraceElement. + } // namespace art diff --git a/src/object.cc b/src/object.cc index 5d64466a8e..175e687a6d 100644 --- a/src/object.cc +++ b/src/object.cc @@ -602,6 +602,19 @@ void PathClassLoader::ResetClass() { dalvik_system_PathClassLoader_ = NULL; } +Class* StackTraceElement::java_lang_StackTraceElement_ = NULL; + +void StackTraceElement::SetClass(Class* java_lang_StackTraceElement) { + CHECK(java_lang_StackTraceElement_ == NULL); + CHECK(java_lang_StackTraceElement != NULL); + java_lang_StackTraceElement_ = java_lang_StackTraceElement; +} + +void StackTraceElement::ResetClass() { + CHECK(java_lang_StackTraceElement_ != NULL); + java_lang_StackTraceElement_ = NULL; +} + static const char* kClassStatusNames[] = { "Error", "NotReady", diff --git a/src/object.h b/src/object.h index 6c8fd6b354..e306d74d4f 100644 --- a/src/object.h +++ b/src/object.h @@ -1681,6 +1681,53 @@ class Throwable : public Object { DISALLOW_IMPLICIT_CONSTRUCTORS(Throwable); }; +class StackTraceElement : public Object { + public: + const String* GetDeclaringClass() const { + return declaring_class_; + } + + const String* GetMethodName() const { + return method_name_; + } + + const String* GetFileName() const { + return file_name_; + } + + uint32_t GetLineNumber() const { + return line_number_; + } + + static StackTraceElement* Alloc(const String* declaring_class, const String* method_name, + const String* file_name, uint32_t line_number) { + StackTraceElement* trace = down_cast<StackTraceElement*>(GetStackTraceElement()->NewInstance()); + trace->declaring_class_ = declaring_class; + trace->method_name_ = method_name; + trace->file_name_ = file_name; + trace->line_number_ = line_number; + return trace; + } + + static void SetClass(Class* java_lang_StackTraceElement); + + static void ResetClass(); + + private: + const String* declaring_class_; + const String* method_name_; + const String* file_name_; + uint32_t line_number_; + + static Class* GetStackTraceElement() { + DCHECK(java_lang_StackTraceElement_ != NULL); + return java_lang_StackTraceElement_; + } + + static Class* java_lang_StackTraceElement_; + DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceElement); +}; + inline bool Object::IsString() const { // TODO use "klass_ == String::GetJavaLangString()" instead? return klass_ == klass_->descriptor_->klass_; diff --git a/src/thread.cc b/src/thread.cc index 2f43e23291..047c89d5e4 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -119,10 +119,10 @@ void Frame::Next() { sp_ = reinterpret_cast<const Method**>(next_sp); } -void* Frame::GetPC() const { +uintptr_t Frame::GetPC() const { byte* pc_addr = reinterpret_cast<byte*>(sp_) + GetMethod()->GetReturnPcOffsetInBytes(); - return reinterpret_cast<void*>(pc_addr); + return *reinterpret_cast<uintptr_t*>(pc_addr); } const Method* Frame::NextMethod() const { @@ -309,6 +309,38 @@ Object* Thread::DecodeJObject(jobject obj) { return result; } +// TODO: Replaces trace.method and trace.pc with IntArray nad +// ObjectArray<Method>. +Thread::InternalStackTrace* Thread::GetStackTrace(uint16_t length) { + Frame frame = Thread::Current()->GetTopOfStack(); + InternalStackTrace *traces = new InternalStackTrace[length]; + for (uint16_t i = 0; i < length && frame.HasNext(); ++i, frame.Next()) { + traces[i].method = frame.GetMethod(); + traces[i].pc = frame.GetPC(); + } + return traces; +} + +ObjectArray<StackTraceElement>* Thread::GetStackTraceElement(uint16_t length, InternalStackTrace *raw_trace) { + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + ObjectArray<StackTraceElement>* java_traces = class_linker->AllocStackTraceElementArray(length); + + for (uint16_t i = 0; i < length; ++i) { + // Prepare parameter for StackTraceElement(String cls, String method, String file, int line) + const Method* method = raw_trace[i].method; + const Class* klass = method->GetDeclaringClass(); + const DexFile& dex_file = class_linker->FindDexFile(klass->GetDexCache()); + String* readable_descriptor = String::AllocFromModifiedUtf8(PrettyDescriptor(klass->GetDescriptor()).c_str()); + + StackTraceElement* obj = + StackTraceElement::Alloc(readable_descriptor, + method->GetName(), String::AllocFromModifiedUtf8(klass->source_file_), + dex_file.GetLineNumFromPC(method, method->ToDexPC(raw_trace[i].pc))); + java_traces->Set(i, obj); + } + return java_traces; +} + void Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) { std::string msg; va_list args; diff --git a/src/thread.h b/src/thread.h index e8ca1566d5..8a3a49b81f 100644 --- a/src/thread.h +++ b/src/thread.h @@ -27,6 +27,8 @@ class Runtime; class Thread; class ThreadList; class Throwable; +class StackTraceElement; +template<class T> class ObjectArray; class Mutex { public: @@ -131,7 +133,7 @@ class Frame { void Next(); - void* GetPC() const; + uintptr_t GetPC() const; const Method** GetSP() const { return sp_; @@ -388,6 +390,16 @@ class Thread { class_loader_override_ = class_loader_override; } + struct InternalStackTrace { + const Method* method; + uintptr_t pc; + }; + + // Get the top length frames information + InternalStackTrace* GetStackTrace(uint16_t length); + + ObjectArray<StackTraceElement>* GetStackTraceElement(uint16_t length, InternalStackTrace *raw_trace); + private: Thread() : id_(1234), |