blob: 3ffc184de9a8b92d62db4eeea72aff93498afa1b [file] [log] [blame]
Ian Rogersb033c752011-07-20 12:22:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
Ian Rogersb033c752011-07-20 12:22:35 -07002
Elliott Hughes90a33692011-08-30 13:27:07 -07003#include "jni_compiler.h"
4
Ian Rogersb033c752011-07-20 12:22:35 -07005#include <sys/mman.h>
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07006
Elliott Hughes90a33692011-08-30 13:27:07 -07007#include "UniquePtr.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07008#include "assembler.h"
9#include "class_linker.h"
10#include "common_test.h"
11#include "dex_file.h"
Elliott Hughes90a33692011-08-30 13:27:07 -070012#include "gtest/gtest.h"
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070013#include "indirect_reference_table.h"
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070014#include "jni_internal.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070015#include "mem_map.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070016#include "runtime.h"
17#include "thread.h"
Ian Rogersb033c752011-07-20 12:22:35 -070018
19namespace art {
20
Brian Carlstromf734cf52011-08-17 16:28:14 -070021class JniCompilerTest : public CommonTest {
Ian Rogersb033c752011-07-20 12:22:35 -070022 protected:
23 virtual void SetUp() {
Brian Carlstromf734cf52011-08-17 16:28:14 -070024 CommonTest::SetUp();
Brian Carlstrom9f30b382011-08-28 22:41:38 -070025 dex_.reset(OpenTestDexFile("MyClassNatives"));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070026 class_loader_ = AllocPathClassLoader(dex_.get());
buzbeec143c552011-08-20 17:38:58 -070027 Thread::Current()->SetClassLoaderOverride(class_loader_);
Ian Rogersb033c752011-07-20 12:22:35 -070028 }
29
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070030 void SetupForTest(bool direct, const char* method_name,
31 const char* method_sig, void* native_fnptr) {
buzbeec143c552011-08-20 17:38:58 -070032 env_ = Thread::Current()->GetJniEnv();
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070033
buzbeec143c552011-08-20 17:38:58 -070034 jklass_ = env_->FindClass("MyClass");
35 ASSERT_TRUE(jklass_ != NULL);
36
37 Class* c = class_linker_->FindClass("LMyClass;", class_loader_);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070038 Method* method;
39 if (direct) {
buzbeec143c552011-08-20 17:38:58 -070040 method = c->FindDirectMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070041 } else {
buzbeec143c552011-08-20 17:38:58 -070042 method = c->FindVirtualMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070043 }
44 ASSERT_TRUE(method != NULL);
45
46 // Compile the native method
47 jni_compiler.Compile(&jni_asm, method);
buzbeec143c552011-08-20 17:38:58 -070048 ASSERT_TRUE(method->HasCode());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070049
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070050 if (direct) {
51 jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
52 } else {
53 jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
54 }
55 ASSERT_TRUE(jmethod_ != NULL);
56
57 JNINativeMethod methods[] = {{method_name, method_sig, native_fnptr}};
58 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1));
59
60 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
61 jobj_ = env_->NewObject(jklass_, constructor);
62 ASSERT_TRUE(jobj_ != NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070063 }
64
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070065 public:
66 static jclass jklass_;
67 static jobject jobj_;
68 protected:
Elliott Hughes90a33692011-08-30 13:27:07 -070069 UniquePtr<const DexFile> dex_;
Brian Carlstrom8a487412011-08-29 20:08:52 -070070 const PathClassLoader* class_loader_;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070071 Assembler jni_asm;
72 JniCompiler jni_compiler;
73 JNIEnv* env_;
74 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -070075};
76
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070077jclass JniCompilerTest::jklass_;
78jobject JniCompilerTest::jobj_;
79
Ian Rogersb033c752011-07-20 12:22:35 -070080int gJava_MyClass_foo_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070081void Java_MyClass_foo(JNIEnv* env, jobject thisObj) {
Ian Rogers408f79a2011-08-23 18:22:33 -070082 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -070083 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070084 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
85 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -070086 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -070087 gJava_MyClass_foo_calls++;
88}
89
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070090TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
91 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
92
93 EXPECT_EQ(0, gJava_MyClass_foo_calls);
94 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
95 EXPECT_EQ(1, gJava_MyClass_foo_calls);
96 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
97 EXPECT_EQ(2, gJava_MyClass_foo_calls);
98}
99
Ian Rogersb033c752011-07-20 12:22:35 -0700100int gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700101jint Java_MyClass_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700102 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700103 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700104 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
105 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700106 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700107 gJava_MyClass_fooI_calls++;
108 return x;
109}
110
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700111TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
112 SetupForTest(false, "fooI", "(I)I",
113 reinterpret_cast<void*>(&Java_MyClass_fooI));
114
115 EXPECT_EQ(0, gJava_MyClass_fooI_calls);
116 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
117 EXPECT_EQ(42, result);
118 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
119 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
120 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
121 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
122}
123
Ian Rogersb033c752011-07-20 12:22:35 -0700124int gJava_MyClass_fooII_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700125jint Java_MyClass_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700126 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700127 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700128 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
129 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700130 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700131 gJava_MyClass_fooII_calls++;
132 return x - y; // non-commutative operator
133}
134
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700135TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
136 SetupForTest(false, "fooII", "(II)I",
137 reinterpret_cast<void*>(&Java_MyClass_fooII));
138
139 EXPECT_EQ(0, gJava_MyClass_fooII_calls);
140 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
141 EXPECT_EQ(99 - 10, result);
142 EXPECT_EQ(1, gJava_MyClass_fooII_calls);
143 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
144 0xCAFED00D);
145 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
146 EXPECT_EQ(2, gJava_MyClass_fooII_calls);
147}
148
Ian Rogersb033c752011-07-20 12:22:35 -0700149int gJava_MyClass_fooDD_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700150jdouble Java_MyClass_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700151 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700152 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700153 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
154 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700155 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700156 gJava_MyClass_fooDD_calls++;
157 return x - y; // non-commutative operator
158}
159
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700160TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
161 SetupForTest(false, "fooDD", "(DD)D",
162 reinterpret_cast<void*>(&Java_MyClass_fooDD));
163
164 EXPECT_EQ(0, gJava_MyClass_fooDD_calls);
165 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
166 99.0, 10.0);
167 EXPECT_EQ(99.0 - 10.0, result);
168 EXPECT_EQ(1, gJava_MyClass_fooDD_calls);
169 jdouble a = 3.14159265358979323846;
170 jdouble b = 0.69314718055994530942;
171 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
172 EXPECT_EQ(a - b, result);
173 EXPECT_EQ(2, gJava_MyClass_fooDD_calls);
174}
175
Ian Rogersb033c752011-07-20 12:22:35 -0700176int gJava_MyClass_fooIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700177jobject Java_MyClass_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700178 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700179 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700180 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700181 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
182 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700183 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700184 gJava_MyClass_fooIOO_calls++;
185 switch (x) {
186 case 1:
187 return y;
188 case 2:
189 return z;
190 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700191 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700192 }
193}
194
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700195TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
196 SetupForTest(false, "fooIOO",
197 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
198 reinterpret_cast<void*>(&Java_MyClass_fooIOO));
199
200 EXPECT_EQ(0, gJava_MyClass_fooIOO_calls);
201 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
202 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
203 EXPECT_EQ(1, gJava_MyClass_fooIOO_calls);
204
205 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
206 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
207 EXPECT_EQ(2, gJava_MyClass_fooIOO_calls);
208 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
209 EXPECT_TRUE(env_->IsSameObject(NULL, result));
210 EXPECT_EQ(3, gJava_MyClass_fooIOO_calls);
211 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
212 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
213 EXPECT_EQ(4, gJava_MyClass_fooIOO_calls);
214
215 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
216 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
217 EXPECT_EQ(5, gJava_MyClass_fooIOO_calls);
218 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
219 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
220 EXPECT_EQ(6, gJava_MyClass_fooIOO_calls);
221 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
222 EXPECT_TRUE(env_->IsSameObject(NULL, result));
223 EXPECT_EQ(7, gJava_MyClass_fooIOO_calls);
224}
225
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700226int gJava_MyClass_fooSII_calls = 0;
227jint Java_MyClass_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
228 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
229 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
230 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
231 EXPECT_TRUE(klass != NULL);
232 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
233 gJava_MyClass_fooSII_calls++;
234 return x + y;
235}
236
237
238TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
239 SetupForTest(true, "fooSII",
240 "(II)I",
241 reinterpret_cast<void*>(&Java_MyClass_fooSII));
242
243 EXPECT_EQ(0, gJava_MyClass_fooSII_calls);
244 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
245 EXPECT_EQ(50, result);
246 EXPECT_EQ(1, gJava_MyClass_fooSII_calls);
247}
248
Ian Rogersb033c752011-07-20 12:22:35 -0700249int gJava_MyClass_fooSIOO_calls = 0;
Elliott Hughes330304d2011-08-12 14:28:05 -0700250jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700251 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700252 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700253 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700254 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
255 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700256 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersb033c752011-07-20 12:22:35 -0700257 gJava_MyClass_fooSIOO_calls++;
258 switch (x) {
259 case 1:
260 return y;
261 case 2:
262 return z;
263 default:
264 return klass;
265 }
266}
267
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700268
269TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
270 SetupForTest(true, "fooSIOO",
271 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
272 reinterpret_cast<void*>(&Java_MyClass_fooSIOO));
273
274 EXPECT_EQ(0, gJava_MyClass_fooSIOO_calls);
275 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
276 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
277 EXPECT_EQ(1, gJava_MyClass_fooSIOO_calls);
278
279 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
280 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
281 EXPECT_EQ(2, gJava_MyClass_fooSIOO_calls);
282 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
283 EXPECT_TRUE(env_->IsSameObject(NULL, result));
284 EXPECT_EQ(3, gJava_MyClass_fooSIOO_calls);
285 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
286 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
287 EXPECT_EQ(4, gJava_MyClass_fooSIOO_calls);
288
289 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
290 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
291 EXPECT_EQ(5, gJava_MyClass_fooSIOO_calls);
292 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
293 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
294 EXPECT_EQ(6, gJava_MyClass_fooSIOO_calls);
295 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
296 EXPECT_TRUE(env_->IsSameObject(NULL, result));
297 EXPECT_EQ(7, gJava_MyClass_fooSIOO_calls);
298}
299
Ian Rogersdf20fe02011-07-20 20:34:16 -0700300int gJava_MyClass_fooSSIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700301jobject Java_MyClass_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersdf20fe02011-07-20 20:34:16 -0700302 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700303 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700304 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700305 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
306 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700307 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700308 gJava_MyClass_fooSSIOO_calls++;
309 switch (x) {
310 case 1:
311 return y;
312 case 2:
313 return z;
314 default:
315 return klass;
316 }
317}
318
Ian Rogersdf20fe02011-07-20 20:34:16 -0700319TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700320 SetupForTest(true, "fooSSIOO",
321 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
322 reinterpret_cast<void*>(&Java_MyClass_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700323
Ian Rogersdf20fe02011-07-20 20:34:16 -0700324 EXPECT_EQ(0, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700325 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
326 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700327 EXPECT_EQ(1, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700328
329 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
330 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700331 EXPECT_EQ(2, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700332 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
333 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700334 EXPECT_EQ(3, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700335 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
336 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700337 EXPECT_EQ(4, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700338
339 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
340 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700341 EXPECT_EQ(5, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700342 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
343 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700344 EXPECT_EQ(6, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700345 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
346 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700347 EXPECT_EQ(7, gJava_MyClass_fooSSIOO_calls);
348}
349
Ian Rogers45a76cb2011-07-21 22:00:15 -0700350int gSuspendCounterHandler_calls;
351void SuspendCountHandler(Method** frame) {
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700352 EXPECT_TRUE((*frame)->GetName()->Equals("fooI"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700353 gSuspendCounterHandler_calls++;
354 Thread::Current()->DecrementSuspendCount();
355}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700356
Ian Rogers0d666d82011-08-14 16:03:46 -0700357TEST_F(JniCompilerTest, SuspendCountAcknowledgement) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700358 SetupForTest(false, "fooI", "(I)I",
359 reinterpret_cast<void*>(&Java_MyClass_fooI));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700360 Thread::Current()->RegisterSuspendCountEntryPoint(&SuspendCountHandler);
361
Ian Rogers45a76cb2011-07-21 22:00:15 -0700362 gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700363 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
364 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700365 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
366 EXPECT_EQ(0, gSuspendCounterHandler_calls);
367 Thread::Current()->IncrementSuspendCount();
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700368 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
369 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700370 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
371 EXPECT_EQ(1, gSuspendCounterHandler_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700372 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
373 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700374 EXPECT_EQ(3, gJava_MyClass_fooI_calls);
375 EXPECT_EQ(1, gSuspendCounterHandler_calls);
376}
377
378int gExceptionHandler_calls;
379void ExceptionHandler(Method** frame) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700380 EXPECT_TRUE((*frame)->GetName()->Equals("throwException"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700381 gExceptionHandler_calls++;
382 Thread::Current()->ClearException();
383}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700384
Elliott Hughesa2501992011-08-26 19:39:54 -0700385void Java_MyClass_throwException(JNIEnv* env, jobject) {
386 jclass c = env->FindClass("java/lang/RuntimeException");
387 env->ThrowNew(c, "hello");
388}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700389
Elliott Hughesa2501992011-08-26 19:39:54 -0700390TEST_F(JniCompilerTest, ExceptionHandling) {
391 Thread::Current()->RegisterExceptionEntryPoint(&ExceptionHandler);
392 gExceptionHandler_calls = 0;
Ian Rogers45a76cb2011-07-21 22:00:15 -0700393 gJava_MyClass_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700394
395 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700396 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700397 EXPECT_EQ(1, gJava_MyClass_foo_calls);
398 EXPECT_EQ(0, gExceptionHandler_calls);
Elliott Hughesa2501992011-08-26 19:39:54 -0700399
400 SetupForTest(false, "throwException", "()V", reinterpret_cast<void*>(&Java_MyClass_throwException));
401 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
402 EXPECT_EQ(1, gJava_MyClass_foo_calls);
403 EXPECT_EQ(1, gExceptionHandler_calls);
404
405 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700406 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700407 EXPECT_EQ(2, gJava_MyClass_foo_calls);
408 EXPECT_EQ(1, gExceptionHandler_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700409}
410
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700411jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
412 if (i <= 0) {
413 ObjectArray<StackTraceElement>* trace_array = Thread::Current()->AllocStackTrace();
414 EXPECT_TRUE(trace_array != NULL);
415 EXPECT_EQ(11, trace_array->GetLength());
416
417 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
418 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
419 EXPECT_STREQ("MyClassNatives.java", trace_array->Get(i)->GetFileName()->ToModifiedUtf8().c_str());
420 EXPECT_STREQ("MyClass", trace_array->Get(i)->GetDeclaringClass()->ToModifiedUtf8().c_str());
421 EXPECT_STREQ("fooI", trace_array->Get(i)->GetMethodName()->ToModifiedUtf8().c_str());
422 }
423 return 0;
424 } else {
425 jclass jklass = env->FindClass("MyClass");
426 EXPECT_TRUE(jklass != NULL);
427 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
428 EXPECT_TRUE(jmethod != NULL);
429
430 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
431 return i + result;
432 }
433}
434
435TEST_F(JniCompilerTest, NativeStackTraceElement) {
436 SetupForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
437 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
438 EXPECT_EQ(55, result);
439}
440
Ian Rogersb033c752011-07-20 12:22:35 -0700441} // namespace art