summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2011-09-19 11:11:44 -0700
committerIan Rogers <irogers@google.com>2011-09-19 13:06:22 -0700
commit9086572fa809d1a19d886b467e4da3ce42016982 (patch)
tree15e28b57d4500d7daff225f993affabbbd22cefb
parent47d913865f35576b39a3b7f17720c344a6b99fa5 (diff)
downloadart-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.h13
-rw-r--r--src/thread.cc33
-rw-r--r--src/thread.h3
-rw-r--r--test/IntMath/IntMath.java2
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");