blob: 20c403cc5ff43447dcbc046685fffe26cad53c9c [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"
Ian Rogersaaa20802011-09-11 21:47:37 -070017#include "scoped_jni_thread_state.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070018#include "thread.h"
Ian Rogersb033c752011-07-20 12:22:35 -070019
20namespace art {
21
Brian Carlstromf734cf52011-08-17 16:28:14 -070022class JniCompilerTest : public CommonTest {
Ian Rogersb033c752011-07-20 12:22:35 -070023 protected:
24 virtual void SetUp() {
Brian Carlstromf734cf52011-08-17 16:28:14 -070025 CommonTest::SetUp();
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070026 class_loader_ = LoadDex("MyClassNatives");
Ian Rogersb033c752011-07-20 12:22:35 -070027 }
28
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070029 void SetupForTest(bool direct, const char* method_name,
30 const char* method_sig, void* native_fnptr) {
buzbeec143c552011-08-20 17:38:58 -070031 env_ = Thread::Current()->GetJniEnv();
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070032
buzbeec143c552011-08-20 17:38:58 -070033 jklass_ = env_->FindClass("MyClass");
34 ASSERT_TRUE(jklass_ != NULL);
35
36 Class* c = class_linker_->FindClass("LMyClass;", class_loader_);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070037 Method* method;
38 if (direct) {
buzbeec143c552011-08-20 17:38:58 -070039 method = c->FindDirectMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070040 } else {
buzbeec143c552011-08-20 17:38:58 -070041 method = c->FindVirtualMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070042 }
43 ASSERT_TRUE(method != NULL);
44
45 // Compile the native method
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070046 CompileMethod(method);
Elliott Hughes1240dad2011-09-09 16:24:50 -070047 ASSERT_TRUE(method->GetCode() != NULL);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070048
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070049 if (direct) {
50 jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
51 } else {
52 jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
53 }
54 ASSERT_TRUE(jmethod_ != NULL);
55
Shih-wei Liao31384c52011-09-06 15:27:45 -070056 if (native_fnptr) {
57 JNINativeMethod methods[] = {{method_name, method_sig, native_fnptr}};
58 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1));
59 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070060
61 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
62 jobj_ = env_->NewObject(jklass_, constructor);
63 ASSERT_TRUE(jobj_ != NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070064 }
65
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070066 public:
67 static jclass jklass_;
68 static jobject jobj_;
69 protected:
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070070 const ClassLoader* class_loader_;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070071 JNIEnv* env_;
72 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -070073};
74
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070075jclass JniCompilerTest::jklass_;
76jobject JniCompilerTest::jobj_;
77
Ian Rogersb033c752011-07-20 12:22:35 -070078int gJava_MyClass_foo_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070079void Java_MyClass_foo(JNIEnv* env, jobject thisObj) {
Ian Rogers408f79a2011-08-23 18:22:33 -070080 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -070081 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070082 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
83 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -070084 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -070085 gJava_MyClass_foo_calls++;
86}
87
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070088TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
89 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
90
91 EXPECT_EQ(0, gJava_MyClass_foo_calls);
92 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
93 EXPECT_EQ(1, gJava_MyClass_foo_calls);
94 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
95 EXPECT_EQ(2, gJava_MyClass_foo_calls);
96}
97
Shih-wei Liao31384c52011-09-06 15:27:45 -070098TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
99 SetupForTest(false,
100 "bar",
101 "(I)I",
102 NULL /* dlsym will find &Java_MyClass_bar later */);
103
104 std::string path("libarttest.so");
105 std::string reason;
106 ASSERT_TRUE(Runtime::Current()->GetJavaVM()->LoadNativeLibrary(
107 path, const_cast<ClassLoader*>(class_loader_), reason))
108 << path << ": " << reason;
109
110 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
111 EXPECT_EQ(25, result);
112}
113
Ian Rogersb033c752011-07-20 12:22:35 -0700114int gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700115jint Java_MyClass_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700116 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700117 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700118 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
119 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700120 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700121 gJava_MyClass_fooI_calls++;
122 return x;
123}
124
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700125TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
126 SetupForTest(false, "fooI", "(I)I",
127 reinterpret_cast<void*>(&Java_MyClass_fooI));
128
129 EXPECT_EQ(0, gJava_MyClass_fooI_calls);
130 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
131 EXPECT_EQ(42, result);
132 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
133 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
134 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
135 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
136}
137
Ian Rogersb033c752011-07-20 12:22:35 -0700138int gJava_MyClass_fooII_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700139jint Java_MyClass_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700140 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700141 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700142 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
143 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700144 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700145 gJava_MyClass_fooII_calls++;
146 return x - y; // non-commutative operator
147}
148
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700149TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
150 SetupForTest(false, "fooII", "(II)I",
151 reinterpret_cast<void*>(&Java_MyClass_fooII));
152
153 EXPECT_EQ(0, gJava_MyClass_fooII_calls);
154 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
155 EXPECT_EQ(99 - 10, result);
156 EXPECT_EQ(1, gJava_MyClass_fooII_calls);
157 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
158 0xCAFED00D);
159 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
160 EXPECT_EQ(2, gJava_MyClass_fooII_calls);
161}
162
Ian Rogers9b269d22011-09-04 14:06:05 -0700163int gJava_MyClass_fooJJ_calls = 0;
164jlong Java_MyClass_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
165 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
166 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
167 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
168 EXPECT_TRUE(thisObj != NULL);
169 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
170 gJava_MyClass_fooJJ_calls++;
171 return x - y; // non-commutative operator
172}
173
174TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
175 SetupForTest(false, "fooJJ", "(JJ)J",
176 reinterpret_cast<void*>(&Java_MyClass_fooJJ));
177
178 EXPECT_EQ(0, gJava_MyClass_fooJJ_calls);
179 jlong a = 0x1234567890ABCDEFll;
180 jlong b = 0xFEDCBA0987654321ll;
181 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
182 EXPECT_EQ(a - b, result);
183 EXPECT_EQ(1, gJava_MyClass_fooJJ_calls);
184 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
185 EXPECT_EQ(b - a, result);
186 EXPECT_EQ(2, gJava_MyClass_fooJJ_calls);
187}
188
Ian Rogersb033c752011-07-20 12:22:35 -0700189int gJava_MyClass_fooDD_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700190jdouble Java_MyClass_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700191 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700192 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700193 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
194 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700195 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700196 gJava_MyClass_fooDD_calls++;
197 return x - y; // non-commutative operator
198}
199
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700200TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
201 SetupForTest(false, "fooDD", "(DD)D",
202 reinterpret_cast<void*>(&Java_MyClass_fooDD));
203
204 EXPECT_EQ(0, gJava_MyClass_fooDD_calls);
205 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
206 99.0, 10.0);
207 EXPECT_EQ(99.0 - 10.0, result);
208 EXPECT_EQ(1, gJava_MyClass_fooDD_calls);
209 jdouble a = 3.14159265358979323846;
210 jdouble b = 0.69314718055994530942;
211 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
212 EXPECT_EQ(a - b, result);
213 EXPECT_EQ(2, gJava_MyClass_fooDD_calls);
214}
215
Ian Rogersb033c752011-07-20 12:22:35 -0700216int gJava_MyClass_fooIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700217jobject Java_MyClass_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700218 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700219 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700220 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700221 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
222 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700223 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700224 gJava_MyClass_fooIOO_calls++;
225 switch (x) {
226 case 1:
227 return y;
228 case 2:
229 return z;
230 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700231 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700232 }
233}
234
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700235TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700236#if !defined(__arm__)
237 UNIMPLEMENTED(WARNING) << "needs X86Assembler::Call(FrameOffset base, Offset offset, ManagedRegister)";
238 return;
239#endif
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700240 SetupForTest(false, "fooIOO",
241 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
242 reinterpret_cast<void*>(&Java_MyClass_fooIOO));
243
244 EXPECT_EQ(0, gJava_MyClass_fooIOO_calls);
245 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
246 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
247 EXPECT_EQ(1, gJava_MyClass_fooIOO_calls);
248
249 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
250 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
251 EXPECT_EQ(2, gJava_MyClass_fooIOO_calls);
252 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
253 EXPECT_TRUE(env_->IsSameObject(NULL, result));
254 EXPECT_EQ(3, gJava_MyClass_fooIOO_calls);
255 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
256 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
257 EXPECT_EQ(4, gJava_MyClass_fooIOO_calls);
258
259 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
260 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
261 EXPECT_EQ(5, gJava_MyClass_fooIOO_calls);
262 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
263 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
264 EXPECT_EQ(6, gJava_MyClass_fooIOO_calls);
265 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
266 EXPECT_TRUE(env_->IsSameObject(NULL, result));
267 EXPECT_EQ(7, gJava_MyClass_fooIOO_calls);
268}
269
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700270int gJava_MyClass_fooSII_calls = 0;
271jint Java_MyClass_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
272 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
273 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
274 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
275 EXPECT_TRUE(klass != NULL);
276 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
277 gJava_MyClass_fooSII_calls++;
278 return x + y;
279}
280
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700281TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
282 SetupForTest(true, "fooSII",
283 "(II)I",
284 reinterpret_cast<void*>(&Java_MyClass_fooSII));
285
286 EXPECT_EQ(0, gJava_MyClass_fooSII_calls);
287 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
288 EXPECT_EQ(50, result);
289 EXPECT_EQ(1, gJava_MyClass_fooSII_calls);
290}
291
Ian Rogers7a99c112011-09-07 12:48:27 -0700292int gJava_MyClass_fooSDD_calls = 0;
293jdouble Java_MyClass_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
294 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
295 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
296 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
297 EXPECT_TRUE(klass != NULL);
298 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
299 gJava_MyClass_fooSDD_calls++;
300 return x - y; // non-commutative operator
301}
302
303TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
304 SetupForTest(true, "fooSDD", "(DD)D",
305 reinterpret_cast<void*>(&Java_MyClass_fooSDD));
306
307 EXPECT_EQ(0, gJava_MyClass_fooSDD_calls);
308 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
309 EXPECT_EQ(99.0 - 10.0, result);
310 EXPECT_EQ(1, gJava_MyClass_fooSDD_calls);
311 jdouble a = 3.14159265358979323846;
312 jdouble b = 0.69314718055994530942;
313 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
314 EXPECT_EQ(a - b, result);
315 EXPECT_EQ(2, gJava_MyClass_fooSDD_calls);
316}
317
Ian Rogersb033c752011-07-20 12:22:35 -0700318int gJava_MyClass_fooSIOO_calls = 0;
Elliott Hughes330304d2011-08-12 14:28:05 -0700319jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700320 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700321 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700322 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700323 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
324 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700325 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersb033c752011-07-20 12:22:35 -0700326 gJava_MyClass_fooSIOO_calls++;
327 switch (x) {
328 case 1:
329 return y;
330 case 2:
331 return z;
332 default:
333 return klass;
334 }
335}
336
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700337
338TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700339#if !defined(__arm__)
340 UNIMPLEMENTED(WARNING) << "needs X86Assembler::Call(FrameOffset base, Offset offset, ManagedRegister)";
341 return;
342#endif
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700343 SetupForTest(true, "fooSIOO",
344 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
345 reinterpret_cast<void*>(&Java_MyClass_fooSIOO));
346
347 EXPECT_EQ(0, gJava_MyClass_fooSIOO_calls);
348 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
349 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
350 EXPECT_EQ(1, gJava_MyClass_fooSIOO_calls);
351
352 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
353 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
354 EXPECT_EQ(2, gJava_MyClass_fooSIOO_calls);
355 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
356 EXPECT_TRUE(env_->IsSameObject(NULL, result));
357 EXPECT_EQ(3, gJava_MyClass_fooSIOO_calls);
358 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
359 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
360 EXPECT_EQ(4, gJava_MyClass_fooSIOO_calls);
361
362 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
363 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
364 EXPECT_EQ(5, gJava_MyClass_fooSIOO_calls);
365 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
366 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
367 EXPECT_EQ(6, gJava_MyClass_fooSIOO_calls);
368 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
369 EXPECT_TRUE(env_->IsSameObject(NULL, result));
370 EXPECT_EQ(7, gJava_MyClass_fooSIOO_calls);
371}
372
Ian Rogersdf20fe02011-07-20 20:34:16 -0700373int gJava_MyClass_fooSSIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700374jobject Java_MyClass_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersdf20fe02011-07-20 20:34:16 -0700375 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700376 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700377 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700378 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
379 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700380 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700381 gJava_MyClass_fooSSIOO_calls++;
382 switch (x) {
383 case 1:
384 return y;
385 case 2:
386 return z;
387 default:
388 return klass;
389 }
390}
391
Ian Rogersdf20fe02011-07-20 20:34:16 -0700392TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700393#if !defined(__arm__)
394 UNIMPLEMENTED(WARNING) << "needs X86Assembler::Call(FrameOffset base, Offset offset, ManagedRegister)";
395 return;
396#endif
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700397 SetupForTest(true, "fooSSIOO",
398 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
399 reinterpret_cast<void*>(&Java_MyClass_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700400
Ian Rogersdf20fe02011-07-20 20:34:16 -0700401 EXPECT_EQ(0, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700402 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
403 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700404 EXPECT_EQ(1, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700405
406 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
407 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700408 EXPECT_EQ(2, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700409 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
410 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700411 EXPECT_EQ(3, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700412 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
413 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700414 EXPECT_EQ(4, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700415
416 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
417 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700418 EXPECT_EQ(5, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700419 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
420 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700421 EXPECT_EQ(6, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700422 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
423 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700424 EXPECT_EQ(7, gJava_MyClass_fooSSIOO_calls);
425}
426
Elliott Hughes8d768a92011-09-14 16:35:25 -0700427// TODO: this is broken now we have thread suspend implemented.
Ian Rogers45a76cb2011-07-21 22:00:15 -0700428int gSuspendCounterHandler_calls;
429void SuspendCountHandler(Method** frame) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700430 // Check we came here in the native state then transition to runnable to work
431 // on the Object*
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700432 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogersaaa20802011-09-11 21:47:37 -0700433 ScopedJniThreadState ts(Thread::Current()->GetJniEnv());
434
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700435 EXPECT_TRUE((*frame)->GetName()->Equals("fooI"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700436 gSuspendCounterHandler_calls++;
Elliott Hughes8d768a92011-09-14 16:35:25 -0700437 //Thread::Current()->DecrementSuspendCount();
Ian Rogers45a76cb2011-07-21 22:00:15 -0700438}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700439
Elliott Hughes8d768a92011-09-14 16:35:25 -0700440TEST_F(JniCompilerTest, DISABLED_SuspendCountAcknowledgement) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700441 SetupForTest(false, "fooI", "(I)I",
442 reinterpret_cast<void*>(&Java_MyClass_fooI));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700443 Thread::Current()->RegisterSuspendCountEntryPoint(&SuspendCountHandler);
444
Ian Rogers45a76cb2011-07-21 22:00:15 -0700445 gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700446 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
447 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700448 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
449 EXPECT_EQ(0, gSuspendCounterHandler_calls);
Elliott Hughes8d768a92011-09-14 16:35:25 -0700450 //Thread::Current()->IncrementSuspendCount();
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700451 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
452 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700453 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
454 EXPECT_EQ(1, gSuspendCounterHandler_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700455 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
456 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700457 EXPECT_EQ(3, gJava_MyClass_fooI_calls);
458 EXPECT_EQ(1, gSuspendCounterHandler_calls);
459}
460
461int gExceptionHandler_calls;
462void ExceptionHandler(Method** frame) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700463 // Check we came here in the native state then transition to runnable to work
464 // on the Object*
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700465 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogersaaa20802011-09-11 21:47:37 -0700466 ScopedJniThreadState ts(Thread::Current()->GetJniEnv());
467
Elliott Hughesa2501992011-08-26 19:39:54 -0700468 EXPECT_TRUE((*frame)->GetName()->Equals("throwException"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700469 gExceptionHandler_calls++;
470 Thread::Current()->ClearException();
471}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700472
Elliott Hughesa2501992011-08-26 19:39:54 -0700473void Java_MyClass_throwException(JNIEnv* env, jobject) {
474 jclass c = env->FindClass("java/lang/RuntimeException");
475 env->ThrowNew(c, "hello");
476}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700477
Elliott Hughesa2501992011-08-26 19:39:54 -0700478TEST_F(JniCompilerTest, ExceptionHandling) {
479 Thread::Current()->RegisterExceptionEntryPoint(&ExceptionHandler);
480 gExceptionHandler_calls = 0;
Ian Rogers45a76cb2011-07-21 22:00:15 -0700481 gJava_MyClass_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700482
483 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700484 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700485 EXPECT_EQ(1, gJava_MyClass_foo_calls);
486 EXPECT_EQ(0, gExceptionHandler_calls);
Elliott Hughesa2501992011-08-26 19:39:54 -0700487
488 SetupForTest(false, "throwException", "()V", reinterpret_cast<void*>(&Java_MyClass_throwException));
489 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
490 EXPECT_EQ(1, gJava_MyClass_foo_calls);
491 EXPECT_EQ(1, gExceptionHandler_calls);
492
493 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700494 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700495 EXPECT_EQ(2, gJava_MyClass_foo_calls);
496 EXPECT_EQ(1, gExceptionHandler_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700497}
498
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700499jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
500 if (i <= 0) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700501 // We want to check raw Object*/Array* below
502 ScopedJniThreadState ts(env);
503
504 // Build stack trace
505 jobject internal = Thread::Current()->CreateInternalStackTrace();
506 jobjectArray ste_array =
507 Thread::InternalStackTraceToStackTraceElementArray(internal, env);
508 ObjectArray<StackTraceElement>* trace_array =
509 Decode<ObjectArray<StackTraceElement>*>(env, ste_array);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700510 EXPECT_TRUE(trace_array != NULL);
511 EXPECT_EQ(11, trace_array->GetLength());
512
Ian Rogersaaa20802011-09-11 21:47:37 -0700513 // Check stack trace entries have expected values
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700514 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
515 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
Ian Rogersaaa20802011-09-11 21:47:37 -0700516 StackTraceElement* ste = trace_array->Get(i);
517 EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
518 EXPECT_STREQ("MyClass", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
519 EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700520 }
Ian Rogersaaa20802011-09-11 21:47:37 -0700521
522 // end recursion
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700523 return 0;
524 } else {
525 jclass jklass = env->FindClass("MyClass");
526 EXPECT_TRUE(jklass != NULL);
527 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
528 EXPECT_TRUE(jmethod != NULL);
529
Ian Rogersaaa20802011-09-11 21:47:37 -0700530 // Recurse with i - 1
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700531 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
Ian Rogersaaa20802011-09-11 21:47:37 -0700532
533 // Return sum of all depths
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700534 return i + result;
535 }
536}
537
538TEST_F(JniCompilerTest, NativeStackTraceElement) {
539 SetupForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
540 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
Ian Rogersaaa20802011-09-11 21:47:37 -0700541 EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700542}
543
Ian Rogers9b269d22011-09-04 14:06:05 -0700544jobject Java_MyClass_fooO(JNIEnv* env, jobject thisObj, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700545 return env->NewGlobalRef(x);
546}
547
Ian Rogersb9231c82011-09-05 22:13:19 -0700548TEST_F(JniCompilerTest, ReturnGlobalRef) {
Brian Carlstrom16192862011-09-12 17:50:06 -0700549#if !defined(__arm__)
550 UNIMPLEMENTED(WARNING) << "needs X86Assembler::Call(FrameOffset base, Offset offset, ManagedRegister)";
551 return;
552#endif
Ian Rogers9b269d22011-09-04 14:06:05 -0700553 SetupForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
554 reinterpret_cast<void*>(&Java_MyClass_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700555 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
556 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
557 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
558}
559
Ian Rogersb9231c82011-09-05 22:13:19 -0700560void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
561 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
562 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700563 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700564 EXPECT_EQ(1234, src_pos);
565 EXPECT_EQ(5678, dst_pos);
566 EXPECT_EQ(9876, length);
567}
568
569TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
570 SetupForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
571 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700572 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700573}
574
Ian Rogersb033c752011-07-20 12:22:35 -0700575} // namespace art