blob: 59a042359c44dff75935c39f5ce886b30a8a47b6 [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 Carlstrom9baa4ae2011-09-01 21:14:14 -070025 class_loader_ = LoadDex("MyClassNatives");
Ian Rogersb033c752011-07-20 12:22:35 -070026 }
27
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070028 void SetupForTest(bool direct, const char* method_name,
29 const char* method_sig, void* native_fnptr) {
buzbeec143c552011-08-20 17:38:58 -070030 env_ = Thread::Current()->GetJniEnv();
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070031
buzbeec143c552011-08-20 17:38:58 -070032 jklass_ = env_->FindClass("MyClass");
33 ASSERT_TRUE(jklass_ != NULL);
34
35 Class* c = class_linker_->FindClass("LMyClass;", class_loader_);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070036 Method* method;
37 if (direct) {
buzbeec143c552011-08-20 17:38:58 -070038 method = c->FindDirectMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070039 } else {
buzbeec143c552011-08-20 17:38:58 -070040 method = c->FindVirtualMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070041 }
42 ASSERT_TRUE(method != NULL);
43
44 // Compile the native method
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070045 CompileMethod(method);
buzbeec143c552011-08-20 17:38:58 -070046 ASSERT_TRUE(method->HasCode());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070047
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070048 if (direct) {
49 jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
50 } else {
51 jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
52 }
53 ASSERT_TRUE(jmethod_ != NULL);
54
55 JNINativeMethod methods[] = {{method_name, method_sig, native_fnptr}};
56 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1));
57
58 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
59 jobj_ = env_->NewObject(jklass_, constructor);
60 ASSERT_TRUE(jobj_ != NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070061 }
62
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070063 public:
64 static jclass jklass_;
65 static jobject jobj_;
66 protected:
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070067 const ClassLoader* class_loader_;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070068 JNIEnv* env_;
69 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -070070};
71
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070072jclass JniCompilerTest::jklass_;
73jobject JniCompilerTest::jobj_;
74
Ian Rogersb033c752011-07-20 12:22:35 -070075int gJava_MyClass_foo_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070076void Java_MyClass_foo(JNIEnv* env, jobject thisObj) {
Ian Rogers408f79a2011-08-23 18:22:33 -070077 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -070078 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070079 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
80 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -070081 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -070082 gJava_MyClass_foo_calls++;
83}
84
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070085TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
86 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
87
88 EXPECT_EQ(0, gJava_MyClass_foo_calls);
89 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
90 EXPECT_EQ(1, gJava_MyClass_foo_calls);
91 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
92 EXPECT_EQ(2, gJava_MyClass_foo_calls);
93}
94
Ian Rogersb033c752011-07-20 12:22:35 -070095int gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070096jint Java_MyClass_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers408f79a2011-08-23 18:22:33 -070097 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -070098 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070099 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
100 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700101 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700102 gJava_MyClass_fooI_calls++;
103 return x;
104}
105
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700106TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
107 SetupForTest(false, "fooI", "(I)I",
108 reinterpret_cast<void*>(&Java_MyClass_fooI));
109
110 EXPECT_EQ(0, gJava_MyClass_fooI_calls);
111 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
112 EXPECT_EQ(42, result);
113 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
114 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
115 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
116 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
117}
118
Ian Rogersb033c752011-07-20 12:22:35 -0700119int gJava_MyClass_fooII_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700120jint Java_MyClass_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700121 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700122 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700123 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
124 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700125 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700126 gJava_MyClass_fooII_calls++;
127 return x - y; // non-commutative operator
128}
129
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700130TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
131 SetupForTest(false, "fooII", "(II)I",
132 reinterpret_cast<void*>(&Java_MyClass_fooII));
133
134 EXPECT_EQ(0, gJava_MyClass_fooII_calls);
135 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
136 EXPECT_EQ(99 - 10, result);
137 EXPECT_EQ(1, gJava_MyClass_fooII_calls);
138 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
139 0xCAFED00D);
140 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
141 EXPECT_EQ(2, gJava_MyClass_fooII_calls);
142}
143
Ian Rogers9b269d22011-09-04 14:06:05 -0700144int gJava_MyClass_fooJJ_calls = 0;
145jlong Java_MyClass_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
146 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
147 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
148 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
149 EXPECT_TRUE(thisObj != NULL);
150 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
151 gJava_MyClass_fooJJ_calls++;
152 return x - y; // non-commutative operator
153}
154
155TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
156 SetupForTest(false, "fooJJ", "(JJ)J",
157 reinterpret_cast<void*>(&Java_MyClass_fooJJ));
158
159 EXPECT_EQ(0, gJava_MyClass_fooJJ_calls);
160 jlong a = 0x1234567890ABCDEFll;
161 jlong b = 0xFEDCBA0987654321ll;
162 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
163 EXPECT_EQ(a - b, result);
164 EXPECT_EQ(1, gJava_MyClass_fooJJ_calls);
165 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
166 EXPECT_EQ(b - a, result);
167 EXPECT_EQ(2, gJava_MyClass_fooJJ_calls);
168}
169
Ian Rogersb033c752011-07-20 12:22:35 -0700170int gJava_MyClass_fooDD_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700171jdouble Java_MyClass_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700172 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700173 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700174 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
175 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700176 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700177 gJava_MyClass_fooDD_calls++;
178 return x - y; // non-commutative operator
179}
180
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700181TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
182 SetupForTest(false, "fooDD", "(DD)D",
183 reinterpret_cast<void*>(&Java_MyClass_fooDD));
184
185 EXPECT_EQ(0, gJava_MyClass_fooDD_calls);
186 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
187 99.0, 10.0);
188 EXPECT_EQ(99.0 - 10.0, result);
189 EXPECT_EQ(1, gJava_MyClass_fooDD_calls);
190 jdouble a = 3.14159265358979323846;
191 jdouble b = 0.69314718055994530942;
192 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
193 EXPECT_EQ(a - b, result);
194 EXPECT_EQ(2, gJava_MyClass_fooDD_calls);
195}
196
Ian Rogersb033c752011-07-20 12:22:35 -0700197int gJava_MyClass_fooIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700198jobject Java_MyClass_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700199 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700200 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700201 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700202 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
203 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700204 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700205 gJava_MyClass_fooIOO_calls++;
206 switch (x) {
207 case 1:
208 return y;
209 case 2:
210 return z;
211 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700212 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700213 }
214}
215
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700216TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
217 SetupForTest(false, "fooIOO",
218 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
219 reinterpret_cast<void*>(&Java_MyClass_fooIOO));
220
221 EXPECT_EQ(0, gJava_MyClass_fooIOO_calls);
222 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
223 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
224 EXPECT_EQ(1, gJava_MyClass_fooIOO_calls);
225
226 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
227 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
228 EXPECT_EQ(2, gJava_MyClass_fooIOO_calls);
229 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
230 EXPECT_TRUE(env_->IsSameObject(NULL, result));
231 EXPECT_EQ(3, gJava_MyClass_fooIOO_calls);
232 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
233 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
234 EXPECT_EQ(4, gJava_MyClass_fooIOO_calls);
235
236 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
237 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
238 EXPECT_EQ(5, gJava_MyClass_fooIOO_calls);
239 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
240 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
241 EXPECT_EQ(6, gJava_MyClass_fooIOO_calls);
242 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
243 EXPECT_TRUE(env_->IsSameObject(NULL, result));
244 EXPECT_EQ(7, gJava_MyClass_fooIOO_calls);
245}
246
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700247int gJava_MyClass_fooSII_calls = 0;
248jint Java_MyClass_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
249 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
250 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
251 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
252 EXPECT_TRUE(klass != NULL);
253 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
254 gJava_MyClass_fooSII_calls++;
255 return x + y;
256}
257
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700258TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
259 SetupForTest(true, "fooSII",
260 "(II)I",
261 reinterpret_cast<void*>(&Java_MyClass_fooSII));
262
263 EXPECT_EQ(0, gJava_MyClass_fooSII_calls);
264 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
265 EXPECT_EQ(50, result);
266 EXPECT_EQ(1, gJava_MyClass_fooSII_calls);
267}
268
Ian Rogers7a99c112011-09-07 12:48:27 -0700269int gJava_MyClass_fooSDD_calls = 0;
270jdouble Java_MyClass_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
271 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
272 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
273 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
274 EXPECT_TRUE(klass != NULL);
275 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
276 gJava_MyClass_fooSDD_calls++;
277 return x - y; // non-commutative operator
278}
279
280TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
281 SetupForTest(true, "fooSDD", "(DD)D",
282 reinterpret_cast<void*>(&Java_MyClass_fooSDD));
283
284 EXPECT_EQ(0, gJava_MyClass_fooSDD_calls);
285 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
286 EXPECT_EQ(99.0 - 10.0, result);
287 EXPECT_EQ(1, gJava_MyClass_fooSDD_calls);
288 jdouble a = 3.14159265358979323846;
289 jdouble b = 0.69314718055994530942;
290 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
291 EXPECT_EQ(a - b, result);
292 EXPECT_EQ(2, gJava_MyClass_fooSDD_calls);
293}
294
Ian Rogersb033c752011-07-20 12:22:35 -0700295int gJava_MyClass_fooSIOO_calls = 0;
Elliott Hughes330304d2011-08-12 14:28:05 -0700296jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700297 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700298 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700299 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700300 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
301 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700302 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersb033c752011-07-20 12:22:35 -0700303 gJava_MyClass_fooSIOO_calls++;
304 switch (x) {
305 case 1:
306 return y;
307 case 2:
308 return z;
309 default:
310 return klass;
311 }
312}
313
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700314
315TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
316 SetupForTest(true, "fooSIOO",
317 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
318 reinterpret_cast<void*>(&Java_MyClass_fooSIOO));
319
320 EXPECT_EQ(0, gJava_MyClass_fooSIOO_calls);
321 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
322 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
323 EXPECT_EQ(1, gJava_MyClass_fooSIOO_calls);
324
325 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
326 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
327 EXPECT_EQ(2, gJava_MyClass_fooSIOO_calls);
328 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
329 EXPECT_TRUE(env_->IsSameObject(NULL, result));
330 EXPECT_EQ(3, gJava_MyClass_fooSIOO_calls);
331 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
332 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
333 EXPECT_EQ(4, gJava_MyClass_fooSIOO_calls);
334
335 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
336 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
337 EXPECT_EQ(5, gJava_MyClass_fooSIOO_calls);
338 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
339 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
340 EXPECT_EQ(6, gJava_MyClass_fooSIOO_calls);
341 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
342 EXPECT_TRUE(env_->IsSameObject(NULL, result));
343 EXPECT_EQ(7, gJava_MyClass_fooSIOO_calls);
344}
345
Ian Rogersdf20fe02011-07-20 20:34:16 -0700346int gJava_MyClass_fooSSIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700347jobject Java_MyClass_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersdf20fe02011-07-20 20:34:16 -0700348 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700349 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700350 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700351 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
352 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700353 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700354 gJava_MyClass_fooSSIOO_calls++;
355 switch (x) {
356 case 1:
357 return y;
358 case 2:
359 return z;
360 default:
361 return klass;
362 }
363}
364
Ian Rogersdf20fe02011-07-20 20:34:16 -0700365TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700366 SetupForTest(true, "fooSSIOO",
367 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
368 reinterpret_cast<void*>(&Java_MyClass_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700369
Ian Rogersdf20fe02011-07-20 20:34:16 -0700370 EXPECT_EQ(0, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700371 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
372 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700373 EXPECT_EQ(1, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700374
375 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
376 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700377 EXPECT_EQ(2, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700378 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
379 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700380 EXPECT_EQ(3, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700381 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
382 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700383 EXPECT_EQ(4, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700384
385 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
386 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700387 EXPECT_EQ(5, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700388 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
389 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700390 EXPECT_EQ(6, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700391 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
392 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700393 EXPECT_EQ(7, gJava_MyClass_fooSSIOO_calls);
394}
395
Ian Rogers45a76cb2011-07-21 22:00:15 -0700396int gSuspendCounterHandler_calls;
397void SuspendCountHandler(Method** frame) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700398 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
399 Thread::Current()->SetState(Thread::kRunnable);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700400 EXPECT_TRUE((*frame)->GetName()->Equals("fooI"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700401 gSuspendCounterHandler_calls++;
402 Thread::Current()->DecrementSuspendCount();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700403 Thread::Current()->SetState(Thread::kNative);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700404}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700405
Ian Rogers0d666d82011-08-14 16:03:46 -0700406TEST_F(JniCompilerTest, SuspendCountAcknowledgement) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700407 SetupForTest(false, "fooI", "(I)I",
408 reinterpret_cast<void*>(&Java_MyClass_fooI));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700409 Thread::Current()->RegisterSuspendCountEntryPoint(&SuspendCountHandler);
410
Ian Rogers45a76cb2011-07-21 22:00:15 -0700411 gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700412 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
413 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700414 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
415 EXPECT_EQ(0, gSuspendCounterHandler_calls);
416 Thread::Current()->IncrementSuspendCount();
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700417 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
418 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700419 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
420 EXPECT_EQ(1, gSuspendCounterHandler_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700421 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
422 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700423 EXPECT_EQ(3, gJava_MyClass_fooI_calls);
424 EXPECT_EQ(1, gSuspendCounterHandler_calls);
425}
426
427int gExceptionHandler_calls;
428void ExceptionHandler(Method** frame) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700429 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
430 Thread::Current()->SetState(Thread::kRunnable);
Elliott Hughesa2501992011-08-26 19:39:54 -0700431 EXPECT_TRUE((*frame)->GetName()->Equals("throwException"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700432 gExceptionHandler_calls++;
433 Thread::Current()->ClearException();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700434 Thread::Current()->SetState(Thread::kNative);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700435}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700436
Elliott Hughesa2501992011-08-26 19:39:54 -0700437void Java_MyClass_throwException(JNIEnv* env, jobject) {
438 jclass c = env->FindClass("java/lang/RuntimeException");
439 env->ThrowNew(c, "hello");
440}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700441
Elliott Hughesa2501992011-08-26 19:39:54 -0700442TEST_F(JniCompilerTest, ExceptionHandling) {
443 Thread::Current()->RegisterExceptionEntryPoint(&ExceptionHandler);
444 gExceptionHandler_calls = 0;
Ian Rogers45a76cb2011-07-21 22:00:15 -0700445 gJava_MyClass_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700446
447 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700448 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700449 EXPECT_EQ(1, gJava_MyClass_foo_calls);
450 EXPECT_EQ(0, gExceptionHandler_calls);
Elliott Hughesa2501992011-08-26 19:39:54 -0700451
452 SetupForTest(false, "throwException", "()V", reinterpret_cast<void*>(&Java_MyClass_throwException));
453 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
454 EXPECT_EQ(1, gJava_MyClass_foo_calls);
455 EXPECT_EQ(1, gExceptionHandler_calls);
456
457 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700458 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700459 EXPECT_EQ(2, gJava_MyClass_foo_calls);
460 EXPECT_EQ(1, gExceptionHandler_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700461}
462
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700463jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
464 if (i <= 0) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700465 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
466 Thread::Current()->SetState(Thread::kRunnable);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700467 ObjectArray<StackTraceElement>* trace_array = Thread::Current()->AllocStackTrace();
468 EXPECT_TRUE(trace_array != NULL);
469 EXPECT_EQ(11, trace_array->GetLength());
470
471 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
472 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
473 EXPECT_STREQ("MyClassNatives.java", trace_array->Get(i)->GetFileName()->ToModifiedUtf8().c_str());
474 EXPECT_STREQ("MyClass", trace_array->Get(i)->GetDeclaringClass()->ToModifiedUtf8().c_str());
475 EXPECT_STREQ("fooI", trace_array->Get(i)->GetMethodName()->ToModifiedUtf8().c_str());
476 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700477 Thread::Current()->SetState(Thread::kNative);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700478 return 0;
479 } else {
480 jclass jklass = env->FindClass("MyClass");
481 EXPECT_TRUE(jklass != NULL);
482 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
483 EXPECT_TRUE(jmethod != NULL);
484
485 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
486 return i + result;
487 }
488}
489
490TEST_F(JniCompilerTest, NativeStackTraceElement) {
491 SetupForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
492 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
493 EXPECT_EQ(55, result);
494}
495
Ian Rogers9b269d22011-09-04 14:06:05 -0700496jobject Java_MyClass_fooO(JNIEnv* env, jobject thisObj, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700497 return env->NewGlobalRef(x);
498}
499
Ian Rogersb9231c82011-09-05 22:13:19 -0700500TEST_F(JniCompilerTest, ReturnGlobalRef) {
Ian Rogers9b269d22011-09-04 14:06:05 -0700501 SetupForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
502 reinterpret_cast<void*>(&Java_MyClass_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700503 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
504 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
505 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
506}
507
Ian Rogersb9231c82011-09-05 22:13:19 -0700508void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
509 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
510 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700511 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700512 EXPECT_EQ(1234, src_pos);
513 EXPECT_EQ(5678, dst_pos);
514 EXPECT_EQ(9876, length);
515}
516
517TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
518 SetupForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
519 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700520 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700521}
522
Ian Rogersb033c752011-07-20 12:22:35 -0700523} // namespace art