diff options
author | Ian Rogers <irogers@google.com> | 2011-09-19 11:11:44 -0700 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2011-09-19 13:06:22 -0700 |
commit | 9086572fa809d1a19d886b467e4da3ce42016982 (patch) | |
tree | 15e28b57d4500d7daff225f993affabbbd22cefb | |
parent | 47d913865f35576b39a3b7f17720c344a6b99fa5 (diff) | |
download | art-9086572fa809d1a19d886b467e4da3ce42016982.zip art-9086572fa809d1a19d886b467e4da3ce42016982.tar.gz art-9086572fa809d1a19d886b467e4da3ce42016982.tar.bz2 |
Fix for implicit null test for oat.
This change also cleans up the notion of the callee save method with a
"IsPhony" call. Stack visitors check whether the frame they are on has a
legitimate method with "HasMethod".
Change-Id: I8ac0fdd595c1e764fdc22cfa9c6a394595f7e141
-rw-r--r-- | src/object.h | 13 | ||||
-rw-r--r-- | src/thread.cc | 33 | ||||
-rw-r--r-- | src/thread.h | 3 | ||||
-rw-r--r-- | test/IntMath/IntMath.java | 2 |
4 files changed, 35 insertions, 16 deletions
diff --git a/src/object.h b/src/object.h index efdb424..2a4078d 100644 --- a/src/object.h +++ b/src/object.h @@ -902,7 +902,7 @@ class MANAGED Method : public AccessibleObject { void SetInvokeStub(const ByteArray* invoke_stub_array); - uint32_t GetCoreSpillMask() { + uint32_t GetCoreSpillMask() const { return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, core_spill_mask_), false); } @@ -912,7 +912,7 @@ class MANAGED Method : public AccessibleObject { core_spill_mask, false); } - uint32_t GetFpSpillMask() { + uint32_t GetFpSpillMask() const { return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, fp_spill_mask_), false); } @@ -922,6 +922,15 @@ class MANAGED Method : public AccessibleObject { fp_spill_mask, false); } + // Is this a hand crafted method used for something like describing callee saves? + bool IsPhony() const { + bool result = + NULL == GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Method, declaring_class_), false); + // Check that if we do think it is phony it looks like the callee save method + DCHECK(!result || GetCoreSpillMask() != 0); + return result; + } + // Converts a native PC to a dex PC. TODO: this is a no-op // until we associate a PC mapping table with each method. uint32_t ToDexPC(const uintptr_t pc) const; diff --git a/src/thread.cc b/src/thread.cc index 153f20f..737faff 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -382,6 +382,10 @@ void Frame::Next() { (*sp_)->GetClass()->GetDescriptor()->Equals("Ljava/lang/reflect/Method;")); } +bool Frame::HasMethod() const { + return GetMethod() != NULL && (!GetMethod()->IsPhony()); +} + uintptr_t Frame::GetReturnPC() const { byte* pc_addr = reinterpret_cast<byte*>(sp_) + GetMethod()->GetReturnPcOffsetInBytes(); @@ -693,6 +697,9 @@ struct StackDumpVisitor : public Thread::StackVisitor { } void VisitFrame(const Frame& frame, uintptr_t pc) { + if (!frame.HasMethod()) { + return; + } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); Method* m = frame.GetMethod(); @@ -1053,8 +1060,10 @@ class CountStackDepthVisitor : public Thread::StackVisitor { virtual void VisitFrame(const Frame& frame, uintptr_t pc) { // We want to skip frames up to and including the exception's constructor. + // Note we also skip the frame if it doesn't have a method (namely the callee + // save frame) DCHECK(gThrowable != NULL); - if (skipping_ && !gThrowable->IsAssignableFrom(frame.GetMethod()->GetDeclaringClass())) { + if (skipping_ && frame.HasMethod() && !gThrowable->IsAssignableFrom(frame.GetMethod()->GetDeclaringClass())) { skipping_ = false; } if (!skipping_) { @@ -1307,17 +1316,17 @@ class CatchBlockStackVisitor : public Thread::StackVisitor { return; } uint32_t dex_pc = DexFile::kDexNoIndex; - if (pc > 0) { - if (method->IsNative()) { - native_method_count_++; - } else { - // Move the PC back 2 bytes as a call will frequently terminate the - // decoding of a particular instruction and we want to make sure we - // get the Dex PC of the instruction with the call and not the - // instruction following. - pc -= 2; - dex_pc = method->ToDexPC(pc); - } + if (method->IsPhony()) { + // ignore callee save method + } else if (method->IsNative()) { + native_method_count_++; + } else { + // Move the PC back 2 bytes as a call will frequently terminate the + // decoding of a particular instruction and we want to make sure we + // get the Dex PC of the instruction with the call and not the + // instruction following. + pc -= 2; + dex_pc = method->ToDexPC(pc); } if (dex_pc != DexFile::kDexNoIndex) { uint32_t found_dex_pc = method->FindCatchBlock(to_find_, dex_pc); diff --git a/src/thread.h b/src/thread.h index 6f1bcc3..0be4aa6 100644 --- a/src/thread.h +++ b/src/thread.h @@ -130,6 +130,9 @@ class PACKED Frame { sp_ = sp; } + // Is this a frame for a real method (native or with dex code) + bool HasMethod() const; + private: Method* NextMethod() const; diff --git a/test/IntMath/IntMath.java b/test/IntMath/IntMath.java index f437f99..a38525e 100644 --- a/test/IntMath/IntMath.java +++ b/test/IntMath/IntMath.java @@ -961,7 +961,6 @@ class IntMath extends IntMathBase { System.out.println("catchBlock(1000) FAILED: " + res); failure = true; } -if (false) { // TODO: restore when fixed res = catchBlock(7000); if (res == 7777) { System.out.println("catchBlock(7000) PASSED"); @@ -969,7 +968,6 @@ if (false) { // TODO: restore when fixed System.out.println("catchBlock(7000) FAILED: " + res); failure = true; } -} res = catchBlockNoThrow(1000); if (res == 1123) { System.out.println("catchBlockNoThrow PASSED"); |