blob: bc7b3a3b24052e863d25c3c547ff92f718f9359a [file] [log] [blame]
Shih-wei Liao9407c602011-09-16 10:36:43 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include <stdio.h>
4
5#include "UniquePtr.h"
6#include "class_linker.h"
7#include "common_test.h"
8#include "dex_verifier.h"
9// #include "heap.h"
10#include "object.h"
11#include "jni.h"
12
13namespace art {
14
15#define REG(method, reg_vector, reg) \
16 ( ((reg) < (method)->NumRegisters()) && \
17 (( *((reg_vector) + (reg)/8) >> ((reg) % 8) ) & 0x01) )
18
19#define EXPECT_REGS(...) do { \
20 int t[] = {__VA_ARGS__}; \
21 int t_size = sizeof(t) / sizeof(*t); \
22 for (int i = 0; i < t_size; ++i) \
23 EXPECT_TRUE(REG(m, reg_vector, t[i])); \
24 } while(false)
25
26static int gJava_StackWalk_refmap_calls = 0;
27
28struct ReferenceMapVisitor : public Thread::StackVisitor {
29 ReferenceMapVisitor() {
30 }
31
32 void VisitFrame(const Frame& frame, uintptr_t pc) {
33 Method* m = frame.GetMethod();
34 if (!m ||m->IsNative()) {
35 return;
36 }
37 LOG(INFO) << "At " << PrettyMethod(m, false);
38
39 art::DexVerifier::RegisterMap* map = new art::DexVerifier::RegisterMap(
40 m->GetRegisterMapHeader(),
41 m->GetRegisterMapData());
42
43 if (!pc) {
44 // pc == NULL: m is either a native method or a phony method
45 return;
46 }
47 if (m->IsPhony()) {
48 LOG(WARNING) << "no PC for " << PrettyMethod(m);
49 return;
50 }
51
52 const uint8_t* reg_vector = art::DexVerifier::RegisterMapGetLine(map, m->ToDexPC(pc));
53 std::string m_name = m->GetName()->ToModifiedUtf8();
54
55 // Given the method name and the number of times the method has been called,
56 // we know the Dex registers with live reference values. Assert that what we
57 // find is what is expected.
58 if (m_name.compare("f") == 0) {
59 if (gJava_StackWalk_refmap_calls == 1) {
60 EXPECT_EQ(0U, m->ToDexPC(pc));
61 EXPECT_REGS(1);
62 } else {
63 CHECK(gJava_StackWalk_refmap_calls == 2);
64 EXPECT_EQ(4U, m->ToDexPC(pc));
65 EXPECT_REGS(1); // Note that v1 is not in the minimal root set
66 }
67 } else if (m_name.compare("g") == 0) {
68 if (gJava_StackWalk_refmap_calls == 1) {
69 EXPECT_EQ(0xaU, m->ToDexPC(pc));
70 EXPECT_REGS(1, 2, 3);
71 } else {
72 CHECK(gJava_StackWalk_refmap_calls == 2);
73 EXPECT_EQ(0xaU, m->ToDexPC(pc));
74 EXPECT_REGS(1, 2, 3);
75 }
76 } else if (m_name.compare("shlemiel") == 0) {
77 if (gJava_StackWalk_refmap_calls == 1) {
78 EXPECT_EQ(0x2d5U, m->ToDexPC(pc));
79 EXPECT_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25);
80 } else {
81 CHECK(gJava_StackWalk_refmap_calls == 2);
82 EXPECT_EQ(0x2d5U, m->ToDexPC(pc));
83 EXPECT_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25);
84 }
85 }
86
87 LOG(INFO) << reg_vector;
88 }
89};
90
91extern "C"
92JNIEXPORT jint JNICALL Java_StackWalk_refmap(JNIEnv* env, jobject thisObj, jint count) {
93 EXPECT_EQ(count, 0);
94 gJava_StackWalk_refmap_calls++;
95
96 // Visitor
97 ReferenceMapVisitor mapper;
98 Thread::Current()->WalkStack(&mapper);
99
100 return count + 1;
101}
102
103extern "C"
104JNIEXPORT jint JNICALL Java_StackWalk_refmap2(JNIEnv* env, jobject thisObj, jint count) {
105 gJava_StackWalk_refmap_calls++;
106
107 // Visitor
108 ReferenceMapVisitor mapper;
109 Thread::Current()->WalkStack(&mapper);
110
111 return count + 1;
112}
113
114}