blob: 938d733ee820225e3ef46036a69b8822bf4bf6ca [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:
Ian Rogersb033c752011-07-20 12:22:35 -070024
Brian Carlstrom40381fb2011-10-19 14:13:40 -070025 void CompileForTest(ClassLoader* class_loader, bool direct,
26 const char* method_name, const char* method_sig) {
Brian Carlstrom25c33252011-09-18 15:58:35 -070027 // Compile the native method before starting the runtime
Brian Carlstrom40381fb2011-10-19 14:13:40 -070028 Class* c = class_linker_->FindClass("LMyClass;", class_loader);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070029 Method* method;
30 if (direct) {
buzbeec143c552011-08-20 17:38:58 -070031 method = c->FindDirectMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070032 } else {
buzbeec143c552011-08-20 17:38:58 -070033 method = c->FindVirtualMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070034 }
35 ASSERT_TRUE(method != NULL);
Brian Carlstrom25c33252011-09-18 15:58:35 -070036 if (method->GetCode() != NULL) {
37 return;
38 }
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070039 CompileMethod(method);
Elliott Hughes1240dad2011-09-09 16:24:50 -070040 ASSERT_TRUE(method->GetCode() != NULL);
Brian Carlstrom25c33252011-09-18 15:58:35 -070041 }
42
Brian Carlstrom40381fb2011-10-19 14:13:40 -070043 void SetupForTest(ClassLoader* class_loader, bool direct,
44 const char* method_name, const char* method_sig,
Brian Carlstrom25c33252011-09-18 15:58:35 -070045 void* native_fnptr) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -070046 CompileForTest(class_loader, direct, method_name, method_sig);
Brian Carlstrom25c33252011-09-18 15:58:35 -070047 if (!runtime_->IsStarted()) {
48 runtime_->Start();
49 }
50
51 // JNI operations after runtime start
52 env_ = Thread::Current()->GetJniEnv();
53 jklass_ = env_->FindClass("MyClass");
54 ASSERT_TRUE(jklass_ != NULL);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070055
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070056 if (direct) {
57 jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
58 } else {
59 jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
60 }
61 ASSERT_TRUE(jmethod_ != NULL);
62
Ian Rogersbdb03912011-09-14 00:55:44 -070063 if (native_fnptr != NULL) {
Shih-wei Liao31384c52011-09-06 15:27:45 -070064 JNINativeMethod methods[] = {{method_name, method_sig, native_fnptr}};
65 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1));
Ian Rogersbdb03912011-09-14 00:55:44 -070066 } else {
67 env_->UnregisterNatives(jklass_);
Shih-wei Liao31384c52011-09-06 15:27:45 -070068 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070069
70 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
71 jobj_ = env_->NewObject(jklass_, constructor);
72 ASSERT_TRUE(jobj_ != NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070073 }
74
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070075 public:
76 static jclass jklass_;
77 static jobject jobj_;
78 protected:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070079 JNIEnv* env_;
80 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -070081};
82
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070083jclass JniCompilerTest::jklass_;
84jobject JniCompilerTest::jobj_;
85
Ian Rogersb033c752011-07-20 12:22:35 -070086int gJava_MyClass_foo_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070087void Java_MyClass_foo(JNIEnv* env, jobject thisObj) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -070088 // 2 = SirtRef<ClassLoader> + thisObj
89 EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -070090 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070091 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
92 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -070093 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -070094 gJava_MyClass_foo_calls++;
95}
96
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070097TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -070098 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
99 SetupForTest(class_loader.get(), false, "foo", "()V",
100 reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700101
102 EXPECT_EQ(0, gJava_MyClass_foo_calls);
103 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
104 EXPECT_EQ(1, gJava_MyClass_foo_calls);
105 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
106 EXPECT_EQ(2, gJava_MyClass_foo_calls);
107}
108
Shih-wei Liao31384c52011-09-06 15:27:45 -0700109TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700110 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
111 SetupForTest(class_loader.get(), false, "bar", "(I)I",
Shih-wei Liao31384c52011-09-06 15:27:45 -0700112 NULL /* dlsym will find &Java_MyClass_bar later */);
113
114 std::string path("libarttest.so");
115 std::string reason;
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700116 ASSERT_TRUE(Runtime::Current()->GetJavaVM()->LoadNativeLibrary(path, class_loader.get(), reason))
Shih-wei Liao31384c52011-09-06 15:27:45 -0700117 << path << ": " << reason;
118
119 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
120 EXPECT_EQ(25, result);
121}
122
Ian Rogersb033c752011-07-20 12:22:35 -0700123int gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700124jint Java_MyClass_fooI(JNIEnv* env, jobject thisObj, jint x) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700125 // 2 = SirtRef<ClassLoader> + thisObj
126 EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700127 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700128 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
129 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700130 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700131 gJava_MyClass_fooI_calls++;
132 return x;
133}
134
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700135TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700136 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
137 SetupForTest(class_loader.get(), false, "fooI", "(I)I",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700138 reinterpret_cast<void*>(&Java_MyClass_fooI));
139
140 EXPECT_EQ(0, gJava_MyClass_fooI_calls);
141 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
142 EXPECT_EQ(42, result);
143 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
144 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
145 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
146 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
147}
148
Ian Rogersb033c752011-07-20 12:22:35 -0700149int gJava_MyClass_fooII_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700150jint Java_MyClass_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700151 // 2 = SirtRef<ClassLoader> + thisObj
152 EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700153 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700154 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
155 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700156 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700157 gJava_MyClass_fooII_calls++;
158 return x - y; // non-commutative operator
159}
160
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700161TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700162 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
163 SetupForTest(class_loader.get(), false, "fooII", "(II)I",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700164 reinterpret_cast<void*>(&Java_MyClass_fooII));
165
166 EXPECT_EQ(0, gJava_MyClass_fooII_calls);
167 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
168 EXPECT_EQ(99 - 10, result);
169 EXPECT_EQ(1, gJava_MyClass_fooII_calls);
170 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
171 0xCAFED00D);
172 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
173 EXPECT_EQ(2, gJava_MyClass_fooII_calls);
174}
175
Ian Rogers9b269d22011-09-04 14:06:05 -0700176int gJava_MyClass_fooJJ_calls = 0;
177jlong Java_MyClass_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700178 // 2 = SirtRef<ClassLoader> + thisObj
179 EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
Ian Rogers9b269d22011-09-04 14:06:05 -0700180 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
181 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
182 EXPECT_TRUE(thisObj != NULL);
183 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
184 gJava_MyClass_fooJJ_calls++;
185 return x - y; // non-commutative operator
186}
187
188TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700189 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
190 SetupForTest(class_loader.get(), false, "fooJJ", "(JJ)J",
Ian Rogers9b269d22011-09-04 14:06:05 -0700191 reinterpret_cast<void*>(&Java_MyClass_fooJJ));
192
193 EXPECT_EQ(0, gJava_MyClass_fooJJ_calls);
194 jlong a = 0x1234567890ABCDEFll;
195 jlong b = 0xFEDCBA0987654321ll;
196 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
197 EXPECT_EQ(a - b, result);
198 EXPECT_EQ(1, gJava_MyClass_fooJJ_calls);
199 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
200 EXPECT_EQ(b - a, result);
201 EXPECT_EQ(2, gJava_MyClass_fooJJ_calls);
202}
203
Ian Rogersb033c752011-07-20 12:22:35 -0700204int gJava_MyClass_fooDD_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700205jdouble Java_MyClass_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700206 // 2 = SirtRef<ClassLoader> + thisObj
207 EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700208 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700209 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
210 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700211 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700212 gJava_MyClass_fooDD_calls++;
213 return x - y; // non-commutative operator
214}
215
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700216TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700217 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
218 SetupForTest(class_loader.get(), false, "fooDD", "(DD)D",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700219 reinterpret_cast<void*>(&Java_MyClass_fooDD));
220
221 EXPECT_EQ(0, gJava_MyClass_fooDD_calls);
222 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
223 99.0, 10.0);
224 EXPECT_EQ(99.0 - 10.0, result);
225 EXPECT_EQ(1, gJava_MyClass_fooDD_calls);
226 jdouble a = 3.14159265358979323846;
227 jdouble b = 0.69314718055994530942;
228 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
229 EXPECT_EQ(a - b, result);
230 EXPECT_EQ(2, gJava_MyClass_fooDD_calls);
231}
232
Ian Rogersb033c752011-07-20 12:22:35 -0700233int gJava_MyClass_fooIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700234jobject Java_MyClass_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700235 jobject z) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700236 // 4 = SirtRef<ClassLoader> + this + y + z
237 EXPECT_EQ(4U, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700238 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700239 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
240 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700241 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700242 gJava_MyClass_fooIOO_calls++;
243 switch (x) {
244 case 1:
245 return y;
246 case 2:
247 return z;
248 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700249 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700250 }
251}
252
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700253TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700254 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
255 SetupForTest(class_loader.get(), false, "fooIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700256 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
257 reinterpret_cast<void*>(&Java_MyClass_fooIOO));
258
259 EXPECT_EQ(0, gJava_MyClass_fooIOO_calls);
260 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
261 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
262 EXPECT_EQ(1, gJava_MyClass_fooIOO_calls);
263
264 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
265 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
266 EXPECT_EQ(2, gJava_MyClass_fooIOO_calls);
267 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
268 EXPECT_TRUE(env_->IsSameObject(NULL, result));
269 EXPECT_EQ(3, gJava_MyClass_fooIOO_calls);
270 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
271 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
272 EXPECT_EQ(4, gJava_MyClass_fooIOO_calls);
273
274 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
275 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
276 EXPECT_EQ(5, gJava_MyClass_fooIOO_calls);
277 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
278 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
279 EXPECT_EQ(6, gJava_MyClass_fooIOO_calls);
280 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
281 EXPECT_TRUE(env_->IsSameObject(NULL, result));
282 EXPECT_EQ(7, gJava_MyClass_fooIOO_calls);
283}
284
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700285int gJava_MyClass_fooSII_calls = 0;
286jint Java_MyClass_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700287 // 2 = SirtRef<ClassLoader> + klass
288 EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700289 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
290 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
291 EXPECT_TRUE(klass != NULL);
292 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
293 gJava_MyClass_fooSII_calls++;
294 return x + y;
295}
296
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700297TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700298 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
299 SetupForTest(class_loader.get(), true, "fooSII", "(II)I",
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700300 reinterpret_cast<void*>(&Java_MyClass_fooSII));
301
302 EXPECT_EQ(0, gJava_MyClass_fooSII_calls);
303 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
304 EXPECT_EQ(50, result);
305 EXPECT_EQ(1, gJava_MyClass_fooSII_calls);
306}
307
Ian Rogers7a99c112011-09-07 12:48:27 -0700308int gJava_MyClass_fooSDD_calls = 0;
309jdouble Java_MyClass_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700310 // 2 = SirtRef<ClassLoader> + klass
311 EXPECT_EQ(2U, Thread::Current()->NumSirtReferences());
Ian Rogers7a99c112011-09-07 12:48:27 -0700312 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
313 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
314 EXPECT_TRUE(klass != NULL);
315 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
316 gJava_MyClass_fooSDD_calls++;
317 return x - y; // non-commutative operator
318}
319
320TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700321 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
322 SetupForTest(class_loader.get(), true, "fooSDD", "(DD)D",
Ian Rogers7a99c112011-09-07 12:48:27 -0700323 reinterpret_cast<void*>(&Java_MyClass_fooSDD));
324
325 EXPECT_EQ(0, gJava_MyClass_fooSDD_calls);
326 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
327 EXPECT_EQ(99.0 - 10.0, result);
328 EXPECT_EQ(1, gJava_MyClass_fooSDD_calls);
329 jdouble a = 3.14159265358979323846;
330 jdouble b = 0.69314718055994530942;
331 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
332 EXPECT_EQ(a - b, result);
333 EXPECT_EQ(2, gJava_MyClass_fooSDD_calls);
334}
335
Ian Rogersb033c752011-07-20 12:22:35 -0700336int gJava_MyClass_fooSIOO_calls = 0;
Elliott Hughes330304d2011-08-12 14:28:05 -0700337jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700338 jobject z) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700339 // 4 = SirtRef<ClassLoader> + klass + y + z
340 EXPECT_EQ(4U, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700341 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700342 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
343 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700344 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersb033c752011-07-20 12:22:35 -0700345 gJava_MyClass_fooSIOO_calls++;
346 switch (x) {
347 case 1:
348 return y;
349 case 2:
350 return z;
351 default:
352 return klass;
353 }
354}
355
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700356
357TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700358 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
359 SetupForTest(class_loader.get(), true, "fooSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700360 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
361 reinterpret_cast<void*>(&Java_MyClass_fooSIOO));
362
363 EXPECT_EQ(0, gJava_MyClass_fooSIOO_calls);
364 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
365 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
366 EXPECT_EQ(1, gJava_MyClass_fooSIOO_calls);
367
368 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
369 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
370 EXPECT_EQ(2, gJava_MyClass_fooSIOO_calls);
371 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
372 EXPECT_TRUE(env_->IsSameObject(NULL, result));
373 EXPECT_EQ(3, gJava_MyClass_fooSIOO_calls);
374 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
375 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
376 EXPECT_EQ(4, gJava_MyClass_fooSIOO_calls);
377
378 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
379 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
380 EXPECT_EQ(5, gJava_MyClass_fooSIOO_calls);
381 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
382 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
383 EXPECT_EQ(6, gJava_MyClass_fooSIOO_calls);
384 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
385 EXPECT_TRUE(env_->IsSameObject(NULL, result));
386 EXPECT_EQ(7, gJava_MyClass_fooSIOO_calls);
387}
388
Ian Rogersdf20fe02011-07-20 20:34:16 -0700389int gJava_MyClass_fooSSIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700390jobject Java_MyClass_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersdf20fe02011-07-20 20:34:16 -0700391 jobject z) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700392 // 4 = SirtRef<ClassLoader> + klass + y + z
393 EXPECT_EQ(4U, Thread::Current()->NumSirtReferences());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700394 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700395 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
396 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700397 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700398 gJava_MyClass_fooSSIOO_calls++;
399 switch (x) {
400 case 1:
401 return y;
402 case 2:
403 return z;
404 default:
405 return klass;
406 }
407}
408
Ian Rogersdf20fe02011-07-20 20:34:16 -0700409TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700410 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
411 SetupForTest(class_loader.get(), true, "fooSSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700412 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
413 reinterpret_cast<void*>(&Java_MyClass_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700414
Ian Rogersdf20fe02011-07-20 20:34:16 -0700415 EXPECT_EQ(0, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700416 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
417 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700418 EXPECT_EQ(1, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700419
420 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
421 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700422 EXPECT_EQ(2, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700423 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
424 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700425 EXPECT_EQ(3, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700426 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
427 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700428 EXPECT_EQ(4, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700429
430 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
431 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700432 EXPECT_EQ(5, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700433 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
434 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700435 EXPECT_EQ(6, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700436 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
437 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700438 EXPECT_EQ(7, gJava_MyClass_fooSSIOO_calls);
439}
440
Elliott Hughesa2501992011-08-26 19:39:54 -0700441void Java_MyClass_throwException(JNIEnv* env, jobject) {
442 jclass c = env->FindClass("java/lang/RuntimeException");
443 env->ThrowNew(c, "hello");
444}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700445
Elliott Hughesa2501992011-08-26 19:39:54 -0700446TEST_F(JniCompilerTest, ExceptionHandling) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700447 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
448
Brian Carlstrom25c33252011-09-18 15:58:35 -0700449 // all compilation needs to happen before SetupForTest calls Runtime::Start
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700450 CompileForTest(class_loader.get(), false, "foo", "()V");
451 CompileForTest(class_loader.get(), false, "throwException", "()V");
452 CompileForTest(class_loader.get(), false, "foo", "()V");
Brian Carlstrom25c33252011-09-18 15:58:35 -0700453
Ian Rogers45a76cb2011-07-21 22:00:15 -0700454 gJava_MyClass_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700455
Ian Rogers67375ac2011-09-14 00:55:44 -0700456 // Check a single call of a JNI method is ok
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700457 SetupForTest(class_loader.get(), 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(1, gJava_MyClass_foo_calls);
Ian Rogers67375ac2011-09-14 00:55:44 -0700460 EXPECT_FALSE(Thread::Current()->IsExceptionPending());
Elliott Hughesa2501992011-08-26 19:39:54 -0700461
Ian Rogers67375ac2011-09-14 00:55:44 -0700462 // Get class for exception we expect to be thrown
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700463 Class* jlre = class_linker_->FindClass("Ljava/lang/RuntimeException;", class_loader.get());
464 SetupForTest(class_loader.get(), false, "throwException", "()V",
465 reinterpret_cast<void*>(&Java_MyClass_throwException));
Ian Rogers67375ac2011-09-14 00:55:44 -0700466 // Call Java_MyClass_throwException (JNI method that throws exception)
Elliott Hughesa2501992011-08-26 19:39:54 -0700467 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
468 EXPECT_EQ(1, gJava_MyClass_foo_calls);
Ian Rogers67375ac2011-09-14 00:55:44 -0700469 EXPECT_TRUE(Thread::Current()->IsExceptionPending());
470 EXPECT_TRUE(Thread::Current()->GetException()->InstanceOf(jlre));
471 Thread::Current()->ClearException();
Elliott Hughesa2501992011-08-26 19:39:54 -0700472
Ian Rogers67375ac2011-09-14 00:55:44 -0700473 // Check a single call of a JNI method is ok
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700474 SetupForTest(class_loader.get(), false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700475 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700476 EXPECT_EQ(2, gJava_MyClass_foo_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700477}
478
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700479jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
480 if (i <= 0) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700481 // We want to check raw Object*/Array* below
482 ScopedJniThreadState ts(env);
483
484 // Build stack trace
Elliott Hughes01158d72011-09-19 19:47:10 -0700485 jobject internal = Thread::Current()->CreateInternalStackTrace(env);
486 jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal);
Ian Rogersaaa20802011-09-11 21:47:37 -0700487 ObjectArray<StackTraceElement>* trace_array =
488 Decode<ObjectArray<StackTraceElement>*>(env, ste_array);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700489 EXPECT_TRUE(trace_array != NULL);
490 EXPECT_EQ(11, trace_array->GetLength());
491
Ian Rogersaaa20802011-09-11 21:47:37 -0700492 // Check stack trace entries have expected values
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700493 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
494 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
Ian Rogersaaa20802011-09-11 21:47:37 -0700495 StackTraceElement* ste = trace_array->Get(i);
496 EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
497 EXPECT_STREQ("MyClass", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
498 EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700499 }
Ian Rogersaaa20802011-09-11 21:47:37 -0700500
501 // end recursion
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700502 return 0;
503 } else {
504 jclass jklass = env->FindClass("MyClass");
505 EXPECT_TRUE(jklass != NULL);
506 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
507 EXPECT_TRUE(jmethod != NULL);
508
Ian Rogersaaa20802011-09-11 21:47:37 -0700509 // Recurse with i - 1
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700510 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
Ian Rogersaaa20802011-09-11 21:47:37 -0700511
512 // Return sum of all depths
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700513 return i + result;
514 }
515}
516
517TEST_F(JniCompilerTest, NativeStackTraceElement) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700518 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
519 SetupForTest(class_loader.get(), false, "fooI", "(I)I",
520 reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700521 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
Ian Rogersaaa20802011-09-11 21:47:37 -0700522 EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700523}
524
Ian Rogers9b269d22011-09-04 14:06:05 -0700525jobject Java_MyClass_fooO(JNIEnv* env, jobject thisObj, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700526 return env->NewGlobalRef(x);
527}
528
Ian Rogersb9231c82011-09-05 22:13:19 -0700529TEST_F(JniCompilerTest, ReturnGlobalRef) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700530 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
531 SetupForTest(class_loader.get(), false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
Ian Rogers9b269d22011-09-04 14:06:05 -0700532 reinterpret_cast<void*>(&Java_MyClass_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700533 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
534 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
535 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
536}
537
Ian Rogersdc51b792011-09-22 20:41:37 -0700538jint local_ref_test(JNIEnv* env, jobject thisObj, jint x) {
539 // Add 10 local references
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700540 for (int i = 0; i < 10; i++) {
Ian Rogersdc51b792011-09-22 20:41:37 -0700541 AddLocalReference<jobject>(env, Decode<Object*>(env, thisObj));
542 }
543 return x+1;
544}
545
546TEST_F(JniCompilerTest, LocalReferenceTableClearingTest) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700547 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
548 SetupForTest(class_loader.get(), false, "fooI", "(I)I", reinterpret_cast<void*>(&local_ref_test));
Ian Rogersdc51b792011-09-22 20:41:37 -0700549 // 1000 invocations of a method that adds 10 local references
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700550 for (int i=0; i < 1000; i++) {
Ian Rogersdc51b792011-09-22 20:41:37 -0700551 jint result = env_->CallIntMethod(jobj_, jmethod_, i);
552 EXPECT_TRUE(result == i + 1);
553 }
554}
555
Ian Rogersb9231c82011-09-05 22:13:19 -0700556void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
557 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
558 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700559 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700560 EXPECT_EQ(1234, src_pos);
561 EXPECT_EQ(5678, dst_pos);
562 EXPECT_EQ(9876, length);
563}
564
565TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700566 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
567 SetupForTest(class_loader.get(), true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
Ian Rogersb9231c82011-09-05 22:13:19 -0700568 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700569 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700570}
571
Ian Rogers67375ac2011-09-14 00:55:44 -0700572jboolean my_casi(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jint expected, jint newval) {
573 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, unsafe));
574 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj));
575 EXPECT_EQ(0x12345678ABCDEF88ll, offset);
576 EXPECT_EQ(static_cast<jint>(0xCAFEF00D), expected);
577 EXPECT_EQ(static_cast<jint>(0xEBADF00D), newval);
578 return JNI_TRUE;
579}
580
581TEST_F(JniCompilerTest, CompareAndSwapInt) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700582 SirtRef<ClassLoader> class_loader(LoadDex("MyClassNatives"));
583 SetupForTest(class_loader.get(), false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
Ian Rogers67375ac2011-09-14 00:55:44 -0700584 reinterpret_cast<void*>(&my_casi));
585 jboolean result = env_->CallBooleanMethod(jobj_, jmethod_, jobj_, 0x12345678ABCDEF88ll, 0xCAFEF00D, 0xEBADF00D);
586 EXPECT_EQ(result, JNI_TRUE);
587}
588
Ian Rogersb033c752011-07-20 12:22:35 -0700589} // namespace art