diff options
| author | 2011-10-15 18:40:39 -0700 | |
|---|---|---|
| committer | 2011-10-15 18:42:21 -0700 | |
| commit | 63433ba79fbe063881c263f8b348fb990c25a83e (patch) | |
| tree | eaab2d75b9e390ae71c1101538818a8830152e71 | |
| parent | 8e1b4ff0870dab12388b7064526a70bdd67082f6 (diff) | |
Add a unit test for ReferenceMap that involves try-catch-finally.
Stress test the ReferenceMap when the program may have out-of-bound
exception.
Change-Id: Iec892d9564c501794571a7c52519ac539a792d6e
| -rw-r--r-- | build/Android.common.mk | 4 | ||||
| -rw-r--r-- | build/Android.oattest.mk | 1 | ||||
| -rw-r--r-- | src/stack_walk_refmap.cc | 172 | ||||
| -rw-r--r-- | test/ReferenceMap/ReferenceMap.java | 33 |
4 files changed, 209 insertions, 1 deletions
diff --git a/build/Android.common.mk b/build/Android.common.mk index 319d673e20..f72db43a59 100644 --- a/build/Android.common.mk +++ b/build/Android.common.mk @@ -186,7 +186,8 @@ LIBART_HOST_SRC_FILES := \ LIBARTTEST_COMMON_SRC_FILES := \ src/base64.cc \ src/jni_tests.cc \ - src/stack_walk.cc + src/stack_walk.cc \ + src/stack_walk_refmap.cc TEST_COMMON_SRC_FILES := \ src/class_linker_test.cc \ @@ -238,6 +239,7 @@ TEST_DEX_DIRECTORIES := \ Nested \ ProtoCompare \ ProtoCompare2 \ + ReferenceMap \ StackWalk \ StackWalk2 \ StaticLeafMethods \ diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk index 801cc4297a..876a7d3fc7 100644 --- a/build/Android.oattest.mk +++ b/build/Android.oattest.mk @@ -78,6 +78,7 @@ $(eval $(call declare-test-test-target,Invoke,)) $(eval $(call declare-test-test-target,ExceptionTest,)) $(eval $(call declare-test-test-target,SystemMethods,)) $(eval $(call declare-test-test-target,MemUsage,)) +$(eval $(call declare-test-test-target,ReferenceMap,)) $(eval $(call declare-test-test-target,StackWalk,)) # TODO: Enable when the StackWalk2 tests are passing diff --git a/src/stack_walk_refmap.cc b/src/stack_walk_refmap.cc new file mode 100644 index 0000000000..c19ccf97a4 --- /dev/null +++ b/src/stack_walk_refmap.cc @@ -0,0 +1,172 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +#include <stdio.h> + +#include "UniquePtr.h" +#include "class_linker.h" +#include "dex_verifier.h" +#include "object.h" +#include "jni.h" + +namespace art { + +#define REG(method, reg_vector, reg) \ + ( ((reg) < (method)->NumRegisters()) && \ + (( *((reg_vector) + (reg)/8) >> ((reg) % 8) ) & 0x01) ) + +#define CHECK_REGS(...) do { \ + int t[] = {__VA_ARGS__}; \ + int t_size = sizeof(t) / sizeof(*t); \ + for (int i = 0; i < t_size; ++i) \ + EXPECT_TRUE(REG(m, reg_vector, t[i])) << "Error: Reg " << i << " is not in RegisterMap"; \ + } while(false) + +// << "Error: Reg " << i << " is not in RegisterMap"; + +struct ReferenceMap2Visitor : public Thread::StackVisitor { + ReferenceMap2Visitor() { + } + + void VisitFrame(const Frame& frame, uintptr_t pc) { + Method* m = frame.GetMethod(); + if (!m ||m->IsNative()) { + return; + } + LOG(INFO) << "At " << PrettyMethod(m, false); + + art::DexVerifier::RegisterMap* map = new art::DexVerifier::RegisterMap( + m->GetRegisterMapHeader(), + m->GetRegisterMapData()); + + if (!pc) { + // pc == NULL: m is either a native method or a phony method + return; + } + if (m->IsCalleeSaveMethod()) { + LOG(WARNING) << "no PC for " << PrettyMethod(m); + return; + } + + const uint8_t* reg_vector = NULL; + std::string m_name = m->GetName()->ToModifiedUtf8(); + + // Given the method name and the number of times the method has been called, + // we know the Dex registers with live reference values. Assert that what we + // find is what is expected. + if (m_name.compare("f") == 0) { + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x01U); + if (reg_vector) { + LOG(WARNING) << "Reg1: " << *reg_vector << *(reg_vector+1); + CHECK_REGS(7); //v7: this + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x02U); + if (reg_vector) { + LOG(WARNING) << "Reg2: " << *reg_vector << *(reg_vector+1); + CHECK_REGS(7); //v7: this + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x03U); + if (reg_vector) { + LOG(WARNING) << "Reg3: " << std::hex << reg_vector[0] << reg_vector[1]; + CHECK_REGS(7); //v7: this + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x05U); + if (reg_vector) { + LOG(WARNING) << "Reg4: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 7); //v0: x, v7: this + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x06U); + if (reg_vector) { + LOG(WARNING) << "Reg5: " << std::hex << reg_vector[0] << reg_vector[1]; + CHECK_REGS(0, 7); //v0: x, v7: this + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x08U); + if (reg_vector) { + LOG(WARNING) << "Reg6: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 2, 7); //v0: x, v2: y, v7: this + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x0bU); + if (reg_vector) { + LOG(WARNING) << "Reg7: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 2, 7); //v0: x, v2: y, v7: this + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x0cU); + if (reg_vector) { + LOG(WARNING) << "Reg8: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 2, 7); //v0: x, v2: y, v7: this + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x38U); + if (reg_vector) { + LOG(WARNING) << "Reg9: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 2, 7); //v0: x, v2: y, v7: this + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x39U); + if (reg_vector) { + LOG(WARNING) << "Reg10: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 2, 7, 1); //v0: x, v2: y, v7: this, v1: ex + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x3aU); + if (reg_vector) { + LOG(WARNING) << "Reg11: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 2, 7, 1); //v0: x, v2: y, v7: this, v1: y + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x16U); + if (reg_vector) { + LOG(WARNING) << "Reg12: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 7, 1); //v0: x, v7: this, v1: y + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x20U); + if (reg_vector) { + LOG(WARNING) << "Reg13: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 7, 1); //v0: x, v7: this, v1: y + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x22U); + if (reg_vector) { + LOG(WARNING) << "Reg14: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 7, 1); //v0: x, v7: this, v1: y + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x25U); + if (reg_vector) { + LOG(WARNING) << "Reg15: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0); //v0: x, v7: this, v1: y + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x26U); + if (reg_vector) { + LOG(WARNING) << "Reg16: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 7, 1); //v0: y, v7: this, v1: y + } + + reg_vector = art::DexVerifier::RegisterMapGetLine(map, 0x14U); + if (reg_vector) { + LOG(WARNING) << "Reg17: " << std::hex << *reg_vector << *(reg_vector+1); + CHECK_REGS(0, 7); //v0: y, v7: this + } + } + + } +}; + +extern "C" +JNIEXPORT jint JNICALL Java_ReferenceMap_refmap(JNIEnv* env, jobject thisObj, jint count) { + // Visitor + ReferenceMap2Visitor mapper; + Thread::Current()->WalkStack(&mapper); + + return count + 1; +} + +} diff --git a/test/ReferenceMap/ReferenceMap.java b/test/ReferenceMap/ReferenceMap.java new file mode 100644 index 0000000000..5904d0256c --- /dev/null +++ b/test/ReferenceMap/ReferenceMap.java @@ -0,0 +1,33 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +public class ReferenceMap { + public ReferenceMap() { + } + + Object f() { + Object x[] = new Object[2]; + Object y = null; + try { + y = new Object(); + x[2] = y; // out-of-bound exception + } catch(Exception ex) { + if (y == null) { + x[1] = new Object(); + } + } finally { + x[1] = y; + refmap(0); + }; + return y; + } + native int refmap(int x); + + static { + System.loadLibrary("arttest"); + } + + public static void main(String[] args) { + ReferenceMap rm = new ReferenceMap(); + rm.f(); + } +} |