blob: 216350bc4550f798c4ea62ca8114a6745dd5b1d1 [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);
Elliott Hughes1240dad2011-09-09 16:24:50 -070046 ASSERT_TRUE(method->GetCode() != NULL);
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
Shih-wei Liao31384c52011-09-06 15:27:45 -070055 if (native_fnptr) {
56 JNINativeMethod methods[] = {{method_name, method_sig, native_fnptr}};
57 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1));
58 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070059
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:
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070069 const ClassLoader* class_loader_;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070070 JNIEnv* env_;
71 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -070072};
73
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070074jclass JniCompilerTest::jklass_;
75jobject JniCompilerTest::jobj_;
76
Ian Rogersb033c752011-07-20 12:22:35 -070077int gJava_MyClass_foo_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070078void Java_MyClass_foo(JNIEnv* env, jobject thisObj) {
Ian Rogers408f79a2011-08-23 18:22:33 -070079 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -070080 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070081 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
82 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -070083 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -070084 gJava_MyClass_foo_calls++;
85}
86
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070087TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
88 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
89
90 EXPECT_EQ(0, gJava_MyClass_foo_calls);
91 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
92 EXPECT_EQ(1, gJava_MyClass_foo_calls);
93 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
94 EXPECT_EQ(2, gJava_MyClass_foo_calls);
95}
96
Shih-wei Liao31384c52011-09-06 15:27:45 -070097TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
98 SetupForTest(false,
99 "bar",
100 "(I)I",
101 NULL /* dlsym will find &Java_MyClass_bar later */);
102
103 std::string path("libarttest.so");
104 std::string reason;
105 ASSERT_TRUE(Runtime::Current()->GetJavaVM()->LoadNativeLibrary(
106 path, const_cast<ClassLoader*>(class_loader_), reason))
107 << path << ": " << reason;
108
109 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
110 EXPECT_EQ(25, result);
111}
112
Ian Rogersb033c752011-07-20 12:22:35 -0700113int gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700114jint Java_MyClass_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700115 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700116 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700117 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
118 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700119 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700120 gJava_MyClass_fooI_calls++;
121 return x;
122}
123
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700124TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
125 SetupForTest(false, "fooI", "(I)I",
126 reinterpret_cast<void*>(&Java_MyClass_fooI));
127
128 EXPECT_EQ(0, gJava_MyClass_fooI_calls);
129 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
130 EXPECT_EQ(42, result);
131 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
132 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
133 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
134 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
135}
136
Ian Rogersb033c752011-07-20 12:22:35 -0700137int gJava_MyClass_fooII_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700138jint Java_MyClass_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700139 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700140 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700141 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
142 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700143 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700144 gJava_MyClass_fooII_calls++;
145 return x - y; // non-commutative operator
146}
147
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700148TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
149 SetupForTest(false, "fooII", "(II)I",
150 reinterpret_cast<void*>(&Java_MyClass_fooII));
151
152 EXPECT_EQ(0, gJava_MyClass_fooII_calls);
153 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
154 EXPECT_EQ(99 - 10, result);
155 EXPECT_EQ(1, gJava_MyClass_fooII_calls);
156 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
157 0xCAFED00D);
158 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
159 EXPECT_EQ(2, gJava_MyClass_fooII_calls);
160}
161
Ian Rogers9b269d22011-09-04 14:06:05 -0700162int gJava_MyClass_fooJJ_calls = 0;
163jlong Java_MyClass_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
164 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
165 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
166 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
167 EXPECT_TRUE(thisObj != NULL);
168 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
169 gJava_MyClass_fooJJ_calls++;
170 return x - y; // non-commutative operator
171}
172
173TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
174 SetupForTest(false, "fooJJ", "(JJ)J",
175 reinterpret_cast<void*>(&Java_MyClass_fooJJ));
176
177 EXPECT_EQ(0, gJava_MyClass_fooJJ_calls);
178 jlong a = 0x1234567890ABCDEFll;
179 jlong b = 0xFEDCBA0987654321ll;
180 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
181 EXPECT_EQ(a - b, result);
182 EXPECT_EQ(1, gJava_MyClass_fooJJ_calls);
183 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
184 EXPECT_EQ(b - a, result);
185 EXPECT_EQ(2, gJava_MyClass_fooJJ_calls);
186}
187
Ian Rogersb033c752011-07-20 12:22:35 -0700188int gJava_MyClass_fooDD_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700189jdouble Java_MyClass_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700190 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700191 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700192 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
193 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700194 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700195 gJava_MyClass_fooDD_calls++;
196 return x - y; // non-commutative operator
197}
198
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700199TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
200 SetupForTest(false, "fooDD", "(DD)D",
201 reinterpret_cast<void*>(&Java_MyClass_fooDD));
202
203 EXPECT_EQ(0, gJava_MyClass_fooDD_calls);
204 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
205 99.0, 10.0);
206 EXPECT_EQ(99.0 - 10.0, result);
207 EXPECT_EQ(1, gJava_MyClass_fooDD_calls);
208 jdouble a = 3.14159265358979323846;
209 jdouble b = 0.69314718055994530942;
210 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
211 EXPECT_EQ(a - b, result);
212 EXPECT_EQ(2, gJava_MyClass_fooDD_calls);
213}
214
Ian Rogersb033c752011-07-20 12:22:35 -0700215int gJava_MyClass_fooIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700216jobject Java_MyClass_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700217 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700218 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700219 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700220 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
221 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700222 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700223 gJava_MyClass_fooIOO_calls++;
224 switch (x) {
225 case 1:
226 return y;
227 case 2:
228 return z;
229 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700230 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700231 }
232}
233
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700234TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
235 SetupForTest(false, "fooIOO",
236 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
237 reinterpret_cast<void*>(&Java_MyClass_fooIOO));
238
239 EXPECT_EQ(0, gJava_MyClass_fooIOO_calls);
240 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
241 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
242 EXPECT_EQ(1, gJava_MyClass_fooIOO_calls);
243
244 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
245 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
246 EXPECT_EQ(2, gJava_MyClass_fooIOO_calls);
247 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
248 EXPECT_TRUE(env_->IsSameObject(NULL, result));
249 EXPECT_EQ(3, gJava_MyClass_fooIOO_calls);
250 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
251 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
252 EXPECT_EQ(4, gJava_MyClass_fooIOO_calls);
253
254 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
255 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
256 EXPECT_EQ(5, gJava_MyClass_fooIOO_calls);
257 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
258 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
259 EXPECT_EQ(6, gJava_MyClass_fooIOO_calls);
260 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
261 EXPECT_TRUE(env_->IsSameObject(NULL, result));
262 EXPECT_EQ(7, gJava_MyClass_fooIOO_calls);
263}
264
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700265int gJava_MyClass_fooSII_calls = 0;
266jint Java_MyClass_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
267 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
268 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
269 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
270 EXPECT_TRUE(klass != NULL);
271 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
272 gJava_MyClass_fooSII_calls++;
273 return x + y;
274}
275
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700276TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
277 SetupForTest(true, "fooSII",
278 "(II)I",
279 reinterpret_cast<void*>(&Java_MyClass_fooSII));
280
281 EXPECT_EQ(0, gJava_MyClass_fooSII_calls);
282 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
283 EXPECT_EQ(50, result);
284 EXPECT_EQ(1, gJava_MyClass_fooSII_calls);
285}
286
Ian Rogers7a99c112011-09-07 12:48:27 -0700287int gJava_MyClass_fooSDD_calls = 0;
288jdouble Java_MyClass_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
289 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
290 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
291 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
292 EXPECT_TRUE(klass != NULL);
293 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
294 gJava_MyClass_fooSDD_calls++;
295 return x - y; // non-commutative operator
296}
297
298TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
299 SetupForTest(true, "fooSDD", "(DD)D",
300 reinterpret_cast<void*>(&Java_MyClass_fooSDD));
301
302 EXPECT_EQ(0, gJava_MyClass_fooSDD_calls);
303 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
304 EXPECT_EQ(99.0 - 10.0, result);
305 EXPECT_EQ(1, gJava_MyClass_fooSDD_calls);
306 jdouble a = 3.14159265358979323846;
307 jdouble b = 0.69314718055994530942;
308 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
309 EXPECT_EQ(a - b, result);
310 EXPECT_EQ(2, gJava_MyClass_fooSDD_calls);
311}
312
Ian Rogersb033c752011-07-20 12:22:35 -0700313int gJava_MyClass_fooSIOO_calls = 0;
Elliott Hughes330304d2011-08-12 14:28:05 -0700314jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700315 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700316 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700317 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700318 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
319 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700320 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersb033c752011-07-20 12:22:35 -0700321 gJava_MyClass_fooSIOO_calls++;
322 switch (x) {
323 case 1:
324 return y;
325 case 2:
326 return z;
327 default:
328 return klass;
329 }
330}
331
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700332
333TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
334 SetupForTest(true, "fooSIOO",
335 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
336 reinterpret_cast<void*>(&Java_MyClass_fooSIOO));
337
338 EXPECT_EQ(0, gJava_MyClass_fooSIOO_calls);
339 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
340 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
341 EXPECT_EQ(1, gJava_MyClass_fooSIOO_calls);
342
343 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
344 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
345 EXPECT_EQ(2, gJava_MyClass_fooSIOO_calls);
346 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
347 EXPECT_TRUE(env_->IsSameObject(NULL, result));
348 EXPECT_EQ(3, gJava_MyClass_fooSIOO_calls);
349 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
350 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
351 EXPECT_EQ(4, gJava_MyClass_fooSIOO_calls);
352
353 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
354 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
355 EXPECT_EQ(5, gJava_MyClass_fooSIOO_calls);
356 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
357 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
358 EXPECT_EQ(6, gJava_MyClass_fooSIOO_calls);
359 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
360 EXPECT_TRUE(env_->IsSameObject(NULL, result));
361 EXPECT_EQ(7, gJava_MyClass_fooSIOO_calls);
362}
363
Ian Rogersdf20fe02011-07-20 20:34:16 -0700364int gJava_MyClass_fooSSIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700365jobject Java_MyClass_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersdf20fe02011-07-20 20:34:16 -0700366 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700367 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700368 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700369 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
370 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700371 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700372 gJava_MyClass_fooSSIOO_calls++;
373 switch (x) {
374 case 1:
375 return y;
376 case 2:
377 return z;
378 default:
379 return klass;
380 }
381}
382
Ian Rogersdf20fe02011-07-20 20:34:16 -0700383TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700384 SetupForTest(true, "fooSSIOO",
385 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
386 reinterpret_cast<void*>(&Java_MyClass_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700387
Ian Rogersdf20fe02011-07-20 20:34:16 -0700388 EXPECT_EQ(0, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700389 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
390 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700391 EXPECT_EQ(1, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700392
393 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
394 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700395 EXPECT_EQ(2, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700396 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
397 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700398 EXPECT_EQ(3, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700399 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
400 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700401 EXPECT_EQ(4, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700402
403 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
404 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700405 EXPECT_EQ(5, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700406 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
407 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700408 EXPECT_EQ(6, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700409 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
410 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700411 EXPECT_EQ(7, gJava_MyClass_fooSSIOO_calls);
412}
413
Ian Rogers45a76cb2011-07-21 22:00:15 -0700414int gSuspendCounterHandler_calls;
415void SuspendCountHandler(Method** frame) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700416 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
417 Thread::Current()->SetState(Thread::kRunnable);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700418 EXPECT_TRUE((*frame)->GetName()->Equals("fooI"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700419 gSuspendCounterHandler_calls++;
420 Thread::Current()->DecrementSuspendCount();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700421 Thread::Current()->SetState(Thread::kNative);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700422}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700423
Ian Rogers0d666d82011-08-14 16:03:46 -0700424TEST_F(JniCompilerTest, SuspendCountAcknowledgement) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700425 SetupForTest(false, "fooI", "(I)I",
426 reinterpret_cast<void*>(&Java_MyClass_fooI));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700427 Thread::Current()->RegisterSuspendCountEntryPoint(&SuspendCountHandler);
428
Ian Rogers45a76cb2011-07-21 22:00:15 -0700429 gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700430 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
431 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700432 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
433 EXPECT_EQ(0, gSuspendCounterHandler_calls);
434 Thread::Current()->IncrementSuspendCount();
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700435 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
436 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700437 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
438 EXPECT_EQ(1, gSuspendCounterHandler_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700439 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
440 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700441 EXPECT_EQ(3, gJava_MyClass_fooI_calls);
442 EXPECT_EQ(1, gSuspendCounterHandler_calls);
443}
444
445int gExceptionHandler_calls;
446void ExceptionHandler(Method** frame) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700447 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
448 Thread::Current()->SetState(Thread::kRunnable);
Elliott Hughesa2501992011-08-26 19:39:54 -0700449 EXPECT_TRUE((*frame)->GetName()->Equals("throwException"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700450 gExceptionHandler_calls++;
451 Thread::Current()->ClearException();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700452 Thread::Current()->SetState(Thread::kNative);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700453}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700454
Elliott Hughesa2501992011-08-26 19:39:54 -0700455void Java_MyClass_throwException(JNIEnv* env, jobject) {
456 jclass c = env->FindClass("java/lang/RuntimeException");
457 env->ThrowNew(c, "hello");
458}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700459
Elliott Hughesa2501992011-08-26 19:39:54 -0700460TEST_F(JniCompilerTest, ExceptionHandling) {
461 Thread::Current()->RegisterExceptionEntryPoint(&ExceptionHandler);
462 gExceptionHandler_calls = 0;
Ian Rogers45a76cb2011-07-21 22:00:15 -0700463 gJava_MyClass_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700464
465 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700466 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700467 EXPECT_EQ(1, gJava_MyClass_foo_calls);
468 EXPECT_EQ(0, gExceptionHandler_calls);
Elliott Hughesa2501992011-08-26 19:39:54 -0700469
470 SetupForTest(false, "throwException", "()V", reinterpret_cast<void*>(&Java_MyClass_throwException));
471 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
472 EXPECT_EQ(1, gJava_MyClass_foo_calls);
473 EXPECT_EQ(1, gExceptionHandler_calls);
474
475 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700476 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700477 EXPECT_EQ(2, gJava_MyClass_foo_calls);
478 EXPECT_EQ(1, gExceptionHandler_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700479}
480
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700481jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
482 if (i <= 0) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700483 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
484 Thread::Current()->SetState(Thread::kRunnable);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700485 ObjectArray<StackTraceElement>* trace_array = Thread::Current()->AllocStackTrace();
486 EXPECT_TRUE(trace_array != NULL);
487 EXPECT_EQ(11, trace_array->GetLength());
488
489 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
490 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
491 EXPECT_STREQ("MyClassNatives.java", trace_array->Get(i)->GetFileName()->ToModifiedUtf8().c_str());
492 EXPECT_STREQ("MyClass", trace_array->Get(i)->GetDeclaringClass()->ToModifiedUtf8().c_str());
493 EXPECT_STREQ("fooI", trace_array->Get(i)->GetMethodName()->ToModifiedUtf8().c_str());
494 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700495 Thread::Current()->SetState(Thread::kNative);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700496 return 0;
497 } else {
498 jclass jklass = env->FindClass("MyClass");
499 EXPECT_TRUE(jklass != NULL);
500 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
501 EXPECT_TRUE(jmethod != NULL);
502
503 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
504 return i + result;
505 }
506}
507
508TEST_F(JniCompilerTest, NativeStackTraceElement) {
509 SetupForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
510 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
511 EXPECT_EQ(55, result);
512}
513
Ian Rogers9b269d22011-09-04 14:06:05 -0700514jobject Java_MyClass_fooO(JNIEnv* env, jobject thisObj, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700515 return env->NewGlobalRef(x);
516}
517
Ian Rogersb9231c82011-09-05 22:13:19 -0700518TEST_F(JniCompilerTest, ReturnGlobalRef) {
Ian Rogers9b269d22011-09-04 14:06:05 -0700519 SetupForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
520 reinterpret_cast<void*>(&Java_MyClass_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700521 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
522 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
523 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
524}
525
Ian Rogersb9231c82011-09-05 22:13:19 -0700526void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
527 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
528 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700529 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700530 EXPECT_EQ(1234, src_pos);
531 EXPECT_EQ(5678, dst_pos);
532 EXPECT_EQ(9876, length);
533}
534
535TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
536 SetupForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
537 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700538 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700539}
540
Ian Rogersb033c752011-07-20 12:22:35 -0700541} // namespace art