blob: 4f862d6ac4ae207b5ac2bd3610bb2d463aa135e8 [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
Brian Carlstrom25c33252011-09-18 15:58:35 -070029 void CompileForTest(bool direct, const char* method_name, const char* method_sig) {
30 // Compile the native method before starting the runtime
buzbeec143c552011-08-20 17:38:58 -070031 Class* c = class_linker_->FindClass("LMyClass;", class_loader_);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070032 Method* method;
33 if (direct) {
buzbeec143c552011-08-20 17:38:58 -070034 method = c->FindDirectMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070035 } else {
buzbeec143c552011-08-20 17:38:58 -070036 method = c->FindVirtualMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070037 }
38 ASSERT_TRUE(method != NULL);
Brian Carlstrom25c33252011-09-18 15:58:35 -070039 if (method->GetCode() != NULL) {
40 return;
41 }
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070042 CompileMethod(method);
Elliott Hughes1240dad2011-09-09 16:24:50 -070043 ASSERT_TRUE(method->GetCode() != NULL);
Brian Carlstrom25c33252011-09-18 15:58:35 -070044 }
45
46 void SetupForTest(bool direct, const char* method_name, const char* method_sig,
47 void* native_fnptr) {
48 CompileForTest(direct, method_name, method_sig);
49 if (!runtime_->IsStarted()) {
50 runtime_->Start();
51 }
52
53 // JNI operations after runtime start
54 env_ = Thread::Current()->GetJniEnv();
55 jklass_ = env_->FindClass("MyClass");
56 ASSERT_TRUE(jklass_ != NULL);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070057
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070058 if (direct) {
59 jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
60 } else {
61 jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
62 }
63 ASSERT_TRUE(jmethod_ != NULL);
64
Ian Rogersbdb03912011-09-14 00:55:44 -070065 if (native_fnptr != NULL) {
Shih-wei Liao31384c52011-09-06 15:27:45 -070066 JNINativeMethod methods[] = {{method_name, method_sig, native_fnptr}};
67 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1));
Ian Rogersbdb03912011-09-14 00:55:44 -070068 } else {
69 env_->UnregisterNatives(jklass_);
Shih-wei Liao31384c52011-09-06 15:27:45 -070070 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070071
72 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
73 jobj_ = env_->NewObject(jklass_, constructor);
74 ASSERT_TRUE(jobj_ != NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070075 }
76
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070077 public:
78 static jclass jklass_;
79 static jobject jobj_;
80 protected:
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070081 const ClassLoader* class_loader_;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070082 JNIEnv* env_;
83 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -070084};
85
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070086jclass JniCompilerTest::jklass_;
87jobject JniCompilerTest::jobj_;
88
Ian Rogersb033c752011-07-20 12:22:35 -070089int gJava_MyClass_foo_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070090void Java_MyClass_foo(JNIEnv* env, jobject thisObj) {
Ian Rogers408f79a2011-08-23 18:22:33 -070091 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -070092 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070093 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
94 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -070095 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -070096 gJava_MyClass_foo_calls++;
97}
98
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070099TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
100 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
101
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) {
110 SetupForTest(false,
111 "bar",
112 "(I)I",
113 NULL /* dlsym will find &Java_MyClass_bar later */);
114
115 std::string path("libarttest.so");
116 std::string reason;
117 ASSERT_TRUE(Runtime::Current()->GetJavaVM()->LoadNativeLibrary(
118 path, const_cast<ClassLoader*>(class_loader_), reason))
119 << path << ": " << reason;
120
121 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
122 EXPECT_EQ(25, result);
123}
124
Ian Rogersb033c752011-07-20 12:22:35 -0700125int gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700126jint Java_MyClass_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700127 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700128 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700129 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
130 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700131 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700132 gJava_MyClass_fooI_calls++;
133 return x;
134}
135
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700136TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
137 SetupForTest(false, "fooI", "(I)I",
138 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) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700151 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700152 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700153 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
154 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700155 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700156 gJava_MyClass_fooII_calls++;
157 return x - y; // non-commutative operator
158}
159
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700160TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
161 SetupForTest(false, "fooII", "(II)I",
162 reinterpret_cast<void*>(&Java_MyClass_fooII));
163
164 EXPECT_EQ(0, gJava_MyClass_fooII_calls);
165 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
166 EXPECT_EQ(99 - 10, result);
167 EXPECT_EQ(1, gJava_MyClass_fooII_calls);
168 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
169 0xCAFED00D);
170 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
171 EXPECT_EQ(2, gJava_MyClass_fooII_calls);
172}
173
Ian Rogers9b269d22011-09-04 14:06:05 -0700174int gJava_MyClass_fooJJ_calls = 0;
175jlong Java_MyClass_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
176 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
177 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
178 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
179 EXPECT_TRUE(thisObj != NULL);
180 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
181 gJava_MyClass_fooJJ_calls++;
182 return x - y; // non-commutative operator
183}
184
185TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
186 SetupForTest(false, "fooJJ", "(JJ)J",
187 reinterpret_cast<void*>(&Java_MyClass_fooJJ));
188
189 EXPECT_EQ(0, gJava_MyClass_fooJJ_calls);
190 jlong a = 0x1234567890ABCDEFll;
191 jlong b = 0xFEDCBA0987654321ll;
192 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
193 EXPECT_EQ(a - b, result);
194 EXPECT_EQ(1, gJava_MyClass_fooJJ_calls);
195 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
196 EXPECT_EQ(b - a, result);
197 EXPECT_EQ(2, gJava_MyClass_fooJJ_calls);
198}
199
Ian Rogersb033c752011-07-20 12:22:35 -0700200int gJava_MyClass_fooDD_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700201jdouble Java_MyClass_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700202 EXPECT_EQ(1u, 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_fooDD_calls++;
208 return x - y; // non-commutative operator
209}
210
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700211TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
212 SetupForTest(false, "fooDD", "(DD)D",
213 reinterpret_cast<void*>(&Java_MyClass_fooDD));
214
215 EXPECT_EQ(0, gJava_MyClass_fooDD_calls);
216 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
217 99.0, 10.0);
218 EXPECT_EQ(99.0 - 10.0, result);
219 EXPECT_EQ(1, gJava_MyClass_fooDD_calls);
220 jdouble a = 3.14159265358979323846;
221 jdouble b = 0.69314718055994530942;
222 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
223 EXPECT_EQ(a - b, result);
224 EXPECT_EQ(2, gJava_MyClass_fooDD_calls);
225}
226
Ian Rogersb033c752011-07-20 12:22:35 -0700227int gJava_MyClass_fooIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700228jobject Java_MyClass_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700229 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700230 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700231 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700232 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
233 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700234 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700235 gJava_MyClass_fooIOO_calls++;
236 switch (x) {
237 case 1:
238 return y;
239 case 2:
240 return z;
241 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700242 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700243 }
244}
245
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700246TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
247 SetupForTest(false, "fooIOO",
248 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
249 reinterpret_cast<void*>(&Java_MyClass_fooIOO));
250
251 EXPECT_EQ(0, gJava_MyClass_fooIOO_calls);
252 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
253 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
254 EXPECT_EQ(1, gJava_MyClass_fooIOO_calls);
255
256 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
257 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
258 EXPECT_EQ(2, gJava_MyClass_fooIOO_calls);
259 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
260 EXPECT_TRUE(env_->IsSameObject(NULL, result));
261 EXPECT_EQ(3, gJava_MyClass_fooIOO_calls);
262 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
263 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
264 EXPECT_EQ(4, gJava_MyClass_fooIOO_calls);
265
266 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
267 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
268 EXPECT_EQ(5, gJava_MyClass_fooIOO_calls);
269 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
270 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
271 EXPECT_EQ(6, gJava_MyClass_fooIOO_calls);
272 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
273 EXPECT_TRUE(env_->IsSameObject(NULL, result));
274 EXPECT_EQ(7, gJava_MyClass_fooIOO_calls);
275}
276
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700277int gJava_MyClass_fooSII_calls = 0;
278jint Java_MyClass_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
279 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
280 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
281 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
282 EXPECT_TRUE(klass != NULL);
283 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
284 gJava_MyClass_fooSII_calls++;
285 return x + y;
286}
287
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700288TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
289 SetupForTest(true, "fooSII",
290 "(II)I",
291 reinterpret_cast<void*>(&Java_MyClass_fooSII));
292
293 EXPECT_EQ(0, gJava_MyClass_fooSII_calls);
294 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
295 EXPECT_EQ(50, result);
296 EXPECT_EQ(1, gJava_MyClass_fooSII_calls);
297}
298
Ian Rogers7a99c112011-09-07 12:48:27 -0700299int gJava_MyClass_fooSDD_calls = 0;
300jdouble Java_MyClass_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
301 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
302 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
303 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
304 EXPECT_TRUE(klass != NULL);
305 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
306 gJava_MyClass_fooSDD_calls++;
307 return x - y; // non-commutative operator
308}
309
310TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
311 SetupForTest(true, "fooSDD", "(DD)D",
312 reinterpret_cast<void*>(&Java_MyClass_fooSDD));
313
314 EXPECT_EQ(0, gJava_MyClass_fooSDD_calls);
315 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
316 EXPECT_EQ(99.0 - 10.0, result);
317 EXPECT_EQ(1, gJava_MyClass_fooSDD_calls);
318 jdouble a = 3.14159265358979323846;
319 jdouble b = 0.69314718055994530942;
320 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
321 EXPECT_EQ(a - b, result);
322 EXPECT_EQ(2, gJava_MyClass_fooSDD_calls);
323}
324
Ian Rogersb033c752011-07-20 12:22:35 -0700325int gJava_MyClass_fooSIOO_calls = 0;
Elliott Hughes330304d2011-08-12 14:28:05 -0700326jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700327 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700328 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700329 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700330 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
331 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700332 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersb033c752011-07-20 12:22:35 -0700333 gJava_MyClass_fooSIOO_calls++;
334 switch (x) {
335 case 1:
336 return y;
337 case 2:
338 return z;
339 default:
340 return klass;
341 }
342}
343
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700344
345TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
346 SetupForTest(true, "fooSIOO",
347 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
348 reinterpret_cast<void*>(&Java_MyClass_fooSIOO));
349
350 EXPECT_EQ(0, gJava_MyClass_fooSIOO_calls);
351 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
352 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
353 EXPECT_EQ(1, gJava_MyClass_fooSIOO_calls);
354
355 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
356 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
357 EXPECT_EQ(2, gJava_MyClass_fooSIOO_calls);
358 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
359 EXPECT_TRUE(env_->IsSameObject(NULL, result));
360 EXPECT_EQ(3, gJava_MyClass_fooSIOO_calls);
361 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
362 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
363 EXPECT_EQ(4, gJava_MyClass_fooSIOO_calls);
364
365 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
366 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
367 EXPECT_EQ(5, gJava_MyClass_fooSIOO_calls);
368 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
369 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
370 EXPECT_EQ(6, gJava_MyClass_fooSIOO_calls);
371 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
372 EXPECT_TRUE(env_->IsSameObject(NULL, result));
373 EXPECT_EQ(7, gJava_MyClass_fooSIOO_calls);
374}
375
Ian Rogersdf20fe02011-07-20 20:34:16 -0700376int gJava_MyClass_fooSSIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700377jobject Java_MyClass_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersdf20fe02011-07-20 20:34:16 -0700378 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700379 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700380 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700381 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
382 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700383 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700384 gJava_MyClass_fooSSIOO_calls++;
385 switch (x) {
386 case 1:
387 return y;
388 case 2:
389 return z;
390 default:
391 return klass;
392 }
393}
394
Ian Rogersdf20fe02011-07-20 20:34:16 -0700395TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700396 SetupForTest(true, "fooSSIOO",
397 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
398 reinterpret_cast<void*>(&Java_MyClass_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700399
Ian Rogersdf20fe02011-07-20 20:34:16 -0700400 EXPECT_EQ(0, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700401 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
402 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700403 EXPECT_EQ(1, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700404
405 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
406 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700407 EXPECT_EQ(2, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700408 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
409 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700410 EXPECT_EQ(3, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700411 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
412 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700413 EXPECT_EQ(4, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700414
415 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
416 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700417 EXPECT_EQ(5, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700418 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
419 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700420 EXPECT_EQ(6, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700421 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
422 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700423 EXPECT_EQ(7, gJava_MyClass_fooSSIOO_calls);
424}
425
Elliott Hughesa2501992011-08-26 19:39:54 -0700426void Java_MyClass_throwException(JNIEnv* env, jobject) {
427 jclass c = env->FindClass("java/lang/RuntimeException");
428 env->ThrowNew(c, "hello");
429}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700430
Elliott Hughesa2501992011-08-26 19:39:54 -0700431TEST_F(JniCompilerTest, ExceptionHandling) {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700432 // all compilation needs to happen before SetupForTest calls Runtime::Start
433 CompileForTest(false, "foo", "()V");
434 CompileForTest(false, "throwException", "()V");
435 CompileForTest(false, "foo", "()V");
436
Ian Rogers45a76cb2011-07-21 22:00:15 -0700437 gJava_MyClass_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700438
Ian Rogers67375ac2011-09-14 00:55:44 -0700439 // Check a single call of a JNI method is ok
Elliott Hughesa2501992011-08-26 19:39:54 -0700440 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700441 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700442 EXPECT_EQ(1, gJava_MyClass_foo_calls);
Ian Rogers67375ac2011-09-14 00:55:44 -0700443 EXPECT_FALSE(Thread::Current()->IsExceptionPending());
Elliott Hughesa2501992011-08-26 19:39:54 -0700444
Ian Rogers67375ac2011-09-14 00:55:44 -0700445 // Get class for exception we expect to be thrown
446 Class* jlre = class_linker_->FindClass("Ljava/lang/RuntimeException;", class_loader_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700447 SetupForTest(false, "throwException", "()V", reinterpret_cast<void*>(&Java_MyClass_throwException));
Ian Rogers67375ac2011-09-14 00:55:44 -0700448 // Call Java_MyClass_throwException (JNI method that throws exception)
Elliott Hughesa2501992011-08-26 19:39:54 -0700449 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
450 EXPECT_EQ(1, gJava_MyClass_foo_calls);
Ian Rogers67375ac2011-09-14 00:55:44 -0700451 EXPECT_TRUE(Thread::Current()->IsExceptionPending());
452 EXPECT_TRUE(Thread::Current()->GetException()->InstanceOf(jlre));
453 Thread::Current()->ClearException();
Elliott Hughesa2501992011-08-26 19:39:54 -0700454
Ian Rogers67375ac2011-09-14 00:55:44 -0700455 // Check a single call of a JNI method is ok
Elliott Hughesa2501992011-08-26 19:39:54 -0700456 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700457 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700458 EXPECT_EQ(2, gJava_MyClass_foo_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700459}
460
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700461jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
462 if (i <= 0) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700463 // We want to check raw Object*/Array* below
464 ScopedJniThreadState ts(env);
465
466 // Build stack trace
467 jobject internal = Thread::Current()->CreateInternalStackTrace();
468 jobjectArray ste_array =
469 Thread::InternalStackTraceToStackTraceElementArray(internal, env);
470 ObjectArray<StackTraceElement>* trace_array =
471 Decode<ObjectArray<StackTraceElement>*>(env, ste_array);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700472 EXPECT_TRUE(trace_array != NULL);
473 EXPECT_EQ(11, trace_array->GetLength());
474
Ian Rogersaaa20802011-09-11 21:47:37 -0700475 // Check stack trace entries have expected values
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700476 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
477 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
Ian Rogersaaa20802011-09-11 21:47:37 -0700478 StackTraceElement* ste = trace_array->Get(i);
479 EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
480 EXPECT_STREQ("MyClass", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
481 EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700482 }
Ian Rogersaaa20802011-09-11 21:47:37 -0700483
484 // end recursion
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700485 return 0;
486 } else {
487 jclass jklass = env->FindClass("MyClass");
488 EXPECT_TRUE(jklass != NULL);
489 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
490 EXPECT_TRUE(jmethod != NULL);
491
Ian Rogersaaa20802011-09-11 21:47:37 -0700492 // Recurse with i - 1
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700493 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
Ian Rogersaaa20802011-09-11 21:47:37 -0700494
495 // Return sum of all depths
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700496 return i + result;
497 }
498}
499
500TEST_F(JniCompilerTest, NativeStackTraceElement) {
501 SetupForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
502 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
Ian Rogersaaa20802011-09-11 21:47:37 -0700503 EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700504}
505
Ian Rogers9b269d22011-09-04 14:06:05 -0700506jobject Java_MyClass_fooO(JNIEnv* env, jobject thisObj, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700507 return env->NewGlobalRef(x);
508}
509
Ian Rogersb9231c82011-09-05 22:13:19 -0700510TEST_F(JniCompilerTest, ReturnGlobalRef) {
Ian Rogers9b269d22011-09-04 14:06:05 -0700511 SetupForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
512 reinterpret_cast<void*>(&Java_MyClass_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700513 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
514 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
515 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
516}
517
Ian Rogersb9231c82011-09-05 22:13:19 -0700518void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
519 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
520 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700521 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700522 EXPECT_EQ(1234, src_pos);
523 EXPECT_EQ(5678, dst_pos);
524 EXPECT_EQ(9876, length);
525}
526
527TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
528 SetupForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
529 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700530 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700531}
532
Ian Rogers67375ac2011-09-14 00:55:44 -0700533jboolean my_casi(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jint expected, jint newval) {
534 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, unsafe));
535 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj));
536 EXPECT_EQ(0x12345678ABCDEF88ll, offset);
537 EXPECT_EQ(static_cast<jint>(0xCAFEF00D), expected);
538 EXPECT_EQ(static_cast<jint>(0xEBADF00D), newval);
539 return JNI_TRUE;
540}
541
542TEST_F(JniCompilerTest, CompareAndSwapInt) {
543 SetupForTest(false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
544 reinterpret_cast<void*>(&my_casi));
545 jboolean result = env_->CallBooleanMethod(jobj_, jmethod_, jobj_, 0x12345678ABCDEF88ll, 0xCAFEF00D, 0xEBADF00D);
546 EXPECT_EQ(result, JNI_TRUE);
547}
548
Ian Rogersb033c752011-07-20 12:22:35 -0700549} // namespace art