blob: ca8f23a5dfc2f92f1d7ac09e143d28f8ea071fea [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_;
68 Assembler jni_asm_;
69 JniCompiler jni_compiler_;
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
Ian Rogersb033c752011-07-20 12:22:35 -070097int gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070098jint Java_MyClass_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers408f79a2011-08-23 18:22:33 -070099 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700100 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700101 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
102 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700103 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700104 gJava_MyClass_fooI_calls++;
105 return x;
106}
107
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700108TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
109 SetupForTest(false, "fooI", "(I)I",
110 reinterpret_cast<void*>(&Java_MyClass_fooI));
111
112 EXPECT_EQ(0, gJava_MyClass_fooI_calls);
113 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
114 EXPECT_EQ(42, result);
115 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
116 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
117 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
118 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
119}
120
Ian Rogersb033c752011-07-20 12:22:35 -0700121int gJava_MyClass_fooII_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700122jint Java_MyClass_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700123 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700124 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700125 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
126 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700127 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700128 gJava_MyClass_fooII_calls++;
129 return x - y; // non-commutative operator
130}
131
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700132TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
133 SetupForTest(false, "fooII", "(II)I",
134 reinterpret_cast<void*>(&Java_MyClass_fooII));
135
136 EXPECT_EQ(0, gJava_MyClass_fooII_calls);
137 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
138 EXPECT_EQ(99 - 10, result);
139 EXPECT_EQ(1, gJava_MyClass_fooII_calls);
140 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
141 0xCAFED00D);
142 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
143 EXPECT_EQ(2, gJava_MyClass_fooII_calls);
144}
145
Ian Rogers9b269d22011-09-04 14:06:05 -0700146int gJava_MyClass_fooJJ_calls = 0;
147jlong Java_MyClass_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
148 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
149 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
150 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
151 EXPECT_TRUE(thisObj != NULL);
152 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
153 gJava_MyClass_fooJJ_calls++;
154 return x - y; // non-commutative operator
155}
156
157TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
158 SetupForTest(false, "fooJJ", "(JJ)J",
159 reinterpret_cast<void*>(&Java_MyClass_fooJJ));
160
161 EXPECT_EQ(0, gJava_MyClass_fooJJ_calls);
162 jlong a = 0x1234567890ABCDEFll;
163 jlong b = 0xFEDCBA0987654321ll;
164 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
165 EXPECT_EQ(a - b, result);
166 EXPECT_EQ(1, gJava_MyClass_fooJJ_calls);
167 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
168 EXPECT_EQ(b - a, result);
169 EXPECT_EQ(2, gJava_MyClass_fooJJ_calls);
170}
171
Ian Rogersb033c752011-07-20 12:22:35 -0700172int gJava_MyClass_fooDD_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700173jdouble Java_MyClass_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700174 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700175 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700176 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
177 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700178 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700179 gJava_MyClass_fooDD_calls++;
180 return x - y; // non-commutative operator
181}
182
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700183TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
184 SetupForTest(false, "fooDD", "(DD)D",
185 reinterpret_cast<void*>(&Java_MyClass_fooDD));
186
187 EXPECT_EQ(0, gJava_MyClass_fooDD_calls);
188 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
189 99.0, 10.0);
190 EXPECT_EQ(99.0 - 10.0, result);
191 EXPECT_EQ(1, gJava_MyClass_fooDD_calls);
192 jdouble a = 3.14159265358979323846;
193 jdouble b = 0.69314718055994530942;
194 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
195 EXPECT_EQ(a - b, result);
196 EXPECT_EQ(2, gJava_MyClass_fooDD_calls);
197}
198
Ian Rogersb033c752011-07-20 12:22:35 -0700199int gJava_MyClass_fooIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700200jobject Java_MyClass_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700201 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700202 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700203 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700204 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
205 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700206 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700207 gJava_MyClass_fooIOO_calls++;
208 switch (x) {
209 case 1:
210 return y;
211 case 2:
212 return z;
213 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700214 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700215 }
216}
217
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700218TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
219 SetupForTest(false, "fooIOO",
220 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
221 reinterpret_cast<void*>(&Java_MyClass_fooIOO));
222
223 EXPECT_EQ(0, gJava_MyClass_fooIOO_calls);
224 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
225 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
226 EXPECT_EQ(1, gJava_MyClass_fooIOO_calls);
227
228 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
229 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
230 EXPECT_EQ(2, gJava_MyClass_fooIOO_calls);
231 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
232 EXPECT_TRUE(env_->IsSameObject(NULL, result));
233 EXPECT_EQ(3, gJava_MyClass_fooIOO_calls);
234 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
235 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
236 EXPECT_EQ(4, gJava_MyClass_fooIOO_calls);
237
238 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
239 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
240 EXPECT_EQ(5, gJava_MyClass_fooIOO_calls);
241 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
242 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
243 EXPECT_EQ(6, gJava_MyClass_fooIOO_calls);
244 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
245 EXPECT_TRUE(env_->IsSameObject(NULL, result));
246 EXPECT_EQ(7, gJava_MyClass_fooIOO_calls);
247}
248
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700249int gJava_MyClass_fooSII_calls = 0;
250jint Java_MyClass_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
251 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
252 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
253 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
254 EXPECT_TRUE(klass != NULL);
255 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
256 gJava_MyClass_fooSII_calls++;
257 return x + y;
258}
259
260
261TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
262 SetupForTest(true, "fooSII",
263 "(II)I",
264 reinterpret_cast<void*>(&Java_MyClass_fooSII));
265
266 EXPECT_EQ(0, gJava_MyClass_fooSII_calls);
267 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
268 EXPECT_EQ(50, result);
269 EXPECT_EQ(1, gJava_MyClass_fooSII_calls);
270}
271
Ian Rogersb033c752011-07-20 12:22:35 -0700272int gJava_MyClass_fooSIOO_calls = 0;
Elliott Hughes330304d2011-08-12 14:28:05 -0700273jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700274 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700275 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700276 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700277 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
278 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700279 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersb033c752011-07-20 12:22:35 -0700280 gJava_MyClass_fooSIOO_calls++;
281 switch (x) {
282 case 1:
283 return y;
284 case 2:
285 return z;
286 default:
287 return klass;
288 }
289}
290
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700291
292TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
293 SetupForTest(true, "fooSIOO",
294 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
295 reinterpret_cast<void*>(&Java_MyClass_fooSIOO));
296
297 EXPECT_EQ(0, gJava_MyClass_fooSIOO_calls);
298 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
299 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
300 EXPECT_EQ(1, gJava_MyClass_fooSIOO_calls);
301
302 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
303 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
304 EXPECT_EQ(2, gJava_MyClass_fooSIOO_calls);
305 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
306 EXPECT_TRUE(env_->IsSameObject(NULL, result));
307 EXPECT_EQ(3, gJava_MyClass_fooSIOO_calls);
308 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
309 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
310 EXPECT_EQ(4, gJava_MyClass_fooSIOO_calls);
311
312 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
313 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
314 EXPECT_EQ(5, gJava_MyClass_fooSIOO_calls);
315 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
316 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
317 EXPECT_EQ(6, gJava_MyClass_fooSIOO_calls);
318 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
319 EXPECT_TRUE(env_->IsSameObject(NULL, result));
320 EXPECT_EQ(7, gJava_MyClass_fooSIOO_calls);
321}
322
Ian Rogersdf20fe02011-07-20 20:34:16 -0700323int gJava_MyClass_fooSSIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700324jobject Java_MyClass_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersdf20fe02011-07-20 20:34:16 -0700325 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700326 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700327 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700328 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
329 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700330 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700331 gJava_MyClass_fooSSIOO_calls++;
332 switch (x) {
333 case 1:
334 return y;
335 case 2:
336 return z;
337 default:
338 return klass;
339 }
340}
341
Ian Rogersdf20fe02011-07-20 20:34:16 -0700342TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700343 SetupForTest(true, "fooSSIOO",
344 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
345 reinterpret_cast<void*>(&Java_MyClass_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700346
Ian Rogersdf20fe02011-07-20 20:34:16 -0700347 EXPECT_EQ(0, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700348 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
349 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700350 EXPECT_EQ(1, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700351
352 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
353 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700354 EXPECT_EQ(2, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700355 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
356 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700357 EXPECT_EQ(3, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700358 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
359 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700360 EXPECT_EQ(4, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700361
362 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
363 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700364 EXPECT_EQ(5, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700365 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
366 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700367 EXPECT_EQ(6, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700368 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
369 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700370 EXPECT_EQ(7, gJava_MyClass_fooSSIOO_calls);
371}
372
Ian Rogers45a76cb2011-07-21 22:00:15 -0700373int gSuspendCounterHandler_calls;
374void SuspendCountHandler(Method** frame) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700375 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
376 Thread::Current()->SetState(Thread::kRunnable);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700377 EXPECT_TRUE((*frame)->GetName()->Equals("fooI"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700378 gSuspendCounterHandler_calls++;
379 Thread::Current()->DecrementSuspendCount();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700380 Thread::Current()->SetState(Thread::kNative);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700381}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700382
Ian Rogers0d666d82011-08-14 16:03:46 -0700383TEST_F(JniCompilerTest, SuspendCountAcknowledgement) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700384 SetupForTest(false, "fooI", "(I)I",
385 reinterpret_cast<void*>(&Java_MyClass_fooI));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700386 Thread::Current()->RegisterSuspendCountEntryPoint(&SuspendCountHandler);
387
Ian Rogers45a76cb2011-07-21 22:00:15 -0700388 gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700389 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
390 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700391 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
392 EXPECT_EQ(0, gSuspendCounterHandler_calls);
393 Thread::Current()->IncrementSuspendCount();
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700394 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
395 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700396 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
397 EXPECT_EQ(1, gSuspendCounterHandler_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700398 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
399 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700400 EXPECT_EQ(3, gJava_MyClass_fooI_calls);
401 EXPECT_EQ(1, gSuspendCounterHandler_calls);
402}
403
404int gExceptionHandler_calls;
405void ExceptionHandler(Method** frame) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700406 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
407 Thread::Current()->SetState(Thread::kRunnable);
Elliott Hughesa2501992011-08-26 19:39:54 -0700408 EXPECT_TRUE((*frame)->GetName()->Equals("throwException"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700409 gExceptionHandler_calls++;
410 Thread::Current()->ClearException();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700411 Thread::Current()->SetState(Thread::kNative);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700412}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700413
Elliott Hughesa2501992011-08-26 19:39:54 -0700414void Java_MyClass_throwException(JNIEnv* env, jobject) {
415 jclass c = env->FindClass("java/lang/RuntimeException");
416 env->ThrowNew(c, "hello");
417}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700418
Elliott Hughesa2501992011-08-26 19:39:54 -0700419TEST_F(JniCompilerTest, ExceptionHandling) {
420 Thread::Current()->RegisterExceptionEntryPoint(&ExceptionHandler);
421 gExceptionHandler_calls = 0;
Ian Rogers45a76cb2011-07-21 22:00:15 -0700422 gJava_MyClass_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700423
424 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700425 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700426 EXPECT_EQ(1, gJava_MyClass_foo_calls);
427 EXPECT_EQ(0, gExceptionHandler_calls);
Elliott Hughesa2501992011-08-26 19:39:54 -0700428
429 SetupForTest(false, "throwException", "()V", reinterpret_cast<void*>(&Java_MyClass_throwException));
430 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
431 EXPECT_EQ(1, gJava_MyClass_foo_calls);
432 EXPECT_EQ(1, gExceptionHandler_calls);
433
434 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700435 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700436 EXPECT_EQ(2, gJava_MyClass_foo_calls);
437 EXPECT_EQ(1, gExceptionHandler_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700438}
439
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700440jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
441 if (i <= 0) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700442 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
443 Thread::Current()->SetState(Thread::kRunnable);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700444 ObjectArray<StackTraceElement>* trace_array = Thread::Current()->AllocStackTrace();
445 EXPECT_TRUE(trace_array != NULL);
446 EXPECT_EQ(11, trace_array->GetLength());
447
448 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
449 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
450 EXPECT_STREQ("MyClassNatives.java", trace_array->Get(i)->GetFileName()->ToModifiedUtf8().c_str());
451 EXPECT_STREQ("MyClass", trace_array->Get(i)->GetDeclaringClass()->ToModifiedUtf8().c_str());
452 EXPECT_STREQ("fooI", trace_array->Get(i)->GetMethodName()->ToModifiedUtf8().c_str());
453 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700454 Thread::Current()->SetState(Thread::kNative);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700455 return 0;
456 } else {
457 jclass jklass = env->FindClass("MyClass");
458 EXPECT_TRUE(jklass != NULL);
459 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
460 EXPECT_TRUE(jmethod != NULL);
461
462 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
463 return i + result;
464 }
465}
466
467TEST_F(JniCompilerTest, NativeStackTraceElement) {
468 SetupForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
469 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
470 EXPECT_EQ(55, result);
471}
472
Ian Rogers9b269d22011-09-04 14:06:05 -0700473jobject Java_MyClass_fooO(JNIEnv* env, jobject thisObj, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700474 return env->NewGlobalRef(x);
475}
476
Ian Rogersb9231c82011-09-05 22:13:19 -0700477TEST_F(JniCompilerTest, ReturnGlobalRef) {
Ian Rogers9b269d22011-09-04 14:06:05 -0700478 SetupForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
479 reinterpret_cast<void*>(&Java_MyClass_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700480 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
481 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
482 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
483}
484
Ian Rogersb9231c82011-09-05 22:13:19 -0700485void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
486 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
487 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700488 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700489 EXPECT_EQ(1234, src_pos);
490 EXPECT_EQ(5678, dst_pos);
491 EXPECT_EQ(9876, length);
492}
493
494TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
495 SetupForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
496 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700497 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700498}
499
Ian Rogersb033c752011-07-20 12:22:35 -0700500} // namespace art