blob: 9328e8588e1c12088b9a8b086e050cad8a1cee7e [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
Ian Rogersbdb03912011-09-14 00:55:44 -070056 if (native_fnptr != NULL) {
Shih-wei Liao31384c52011-09-06 15:27:45 -070057 JNINativeMethod methods[] = {{method_name, method_sig, native_fnptr}};
58 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1));
Ian Rogersbdb03912011-09-14 00:55:44 -070059 } else {
60 env_->UnregisterNatives(jklass_);
Shih-wei Liao31384c52011-09-06 15:27:45 -070061 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070062
63 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
64 jobj_ = env_->NewObject(jklass_, constructor);
65 ASSERT_TRUE(jobj_ != NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070066 }
67
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070068 public:
69 static jclass jklass_;
70 static jobject jobj_;
71 protected:
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070072 const ClassLoader* class_loader_;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070073 JNIEnv* env_;
74 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -070075};
76
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070077jclass JniCompilerTest::jklass_;
78jobject JniCompilerTest::jobj_;
79
Ian Rogersb033c752011-07-20 12:22:35 -070080int gJava_MyClass_foo_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070081void Java_MyClass_foo(JNIEnv* env, jobject thisObj) {
Ian Rogers408f79a2011-08-23 18:22:33 -070082 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -070083 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070084 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
85 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -070086 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -070087 gJava_MyClass_foo_calls++;
88}
89
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070090TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
91 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
92
93 EXPECT_EQ(0, gJava_MyClass_foo_calls);
94 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
95 EXPECT_EQ(1, gJava_MyClass_foo_calls);
96 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
97 EXPECT_EQ(2, gJava_MyClass_foo_calls);
98}
99
Shih-wei Liao31384c52011-09-06 15:27:45 -0700100TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
101 SetupForTest(false,
102 "bar",
103 "(I)I",
104 NULL /* dlsym will find &Java_MyClass_bar later */);
105
106 std::string path("libarttest.so");
107 std::string reason;
108 ASSERT_TRUE(Runtime::Current()->GetJavaVM()->LoadNativeLibrary(
109 path, const_cast<ClassLoader*>(class_loader_), reason))
110 << path << ": " << reason;
111
112 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
113 EXPECT_EQ(25, result);
114}
115
Ian Rogersb033c752011-07-20 12:22:35 -0700116int gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700117jint Java_MyClass_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700118 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700119 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700120 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
121 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700122 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700123 gJava_MyClass_fooI_calls++;
124 return x;
125}
126
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700127TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
128 SetupForTest(false, "fooI", "(I)I",
129 reinterpret_cast<void*>(&Java_MyClass_fooI));
130
131 EXPECT_EQ(0, gJava_MyClass_fooI_calls);
132 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
133 EXPECT_EQ(42, result);
134 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
135 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
136 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
137 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
138}
139
Ian Rogersb033c752011-07-20 12:22:35 -0700140int gJava_MyClass_fooII_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700141jint Java_MyClass_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700142 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700143 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700144 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
145 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700146 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700147 gJava_MyClass_fooII_calls++;
148 return x - y; // non-commutative operator
149}
150
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700151TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
152 SetupForTest(false, "fooII", "(II)I",
153 reinterpret_cast<void*>(&Java_MyClass_fooII));
154
155 EXPECT_EQ(0, gJava_MyClass_fooII_calls);
156 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
157 EXPECT_EQ(99 - 10, result);
158 EXPECT_EQ(1, gJava_MyClass_fooII_calls);
159 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
160 0xCAFED00D);
161 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
162 EXPECT_EQ(2, gJava_MyClass_fooII_calls);
163}
164
Ian Rogers9b269d22011-09-04 14:06:05 -0700165int gJava_MyClass_fooJJ_calls = 0;
166jlong Java_MyClass_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
167 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
168 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
169 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
170 EXPECT_TRUE(thisObj != NULL);
171 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
172 gJava_MyClass_fooJJ_calls++;
173 return x - y; // non-commutative operator
174}
175
176TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
177 SetupForTest(false, "fooJJ", "(JJ)J",
178 reinterpret_cast<void*>(&Java_MyClass_fooJJ));
179
180 EXPECT_EQ(0, gJava_MyClass_fooJJ_calls);
181 jlong a = 0x1234567890ABCDEFll;
182 jlong b = 0xFEDCBA0987654321ll;
183 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
184 EXPECT_EQ(a - b, result);
185 EXPECT_EQ(1, gJava_MyClass_fooJJ_calls);
186 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
187 EXPECT_EQ(b - a, result);
188 EXPECT_EQ(2, gJava_MyClass_fooJJ_calls);
189}
190
Ian Rogersb033c752011-07-20 12:22:35 -0700191int gJava_MyClass_fooDD_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700192jdouble Java_MyClass_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700193 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700194 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700195 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
196 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700197 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700198 gJava_MyClass_fooDD_calls++;
199 return x - y; // non-commutative operator
200}
201
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700202TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
203 SetupForTest(false, "fooDD", "(DD)D",
204 reinterpret_cast<void*>(&Java_MyClass_fooDD));
205
206 EXPECT_EQ(0, gJava_MyClass_fooDD_calls);
207 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
208 99.0, 10.0);
209 EXPECT_EQ(99.0 - 10.0, result);
210 EXPECT_EQ(1, gJava_MyClass_fooDD_calls);
211 jdouble a = 3.14159265358979323846;
212 jdouble b = 0.69314718055994530942;
213 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
214 EXPECT_EQ(a - b, result);
215 EXPECT_EQ(2, gJava_MyClass_fooDD_calls);
216}
217
Ian Rogersb033c752011-07-20 12:22:35 -0700218int gJava_MyClass_fooIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700219jobject Java_MyClass_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700220 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700221 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700222 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700223 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
224 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700225 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Ian Rogersb033c752011-07-20 12:22:35 -0700226 gJava_MyClass_fooIOO_calls++;
227 switch (x) {
228 case 1:
229 return y;
230 case 2:
231 return z;
232 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700233 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700234 }
235}
236
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700237TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
238 SetupForTest(false, "fooIOO",
239 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
240 reinterpret_cast<void*>(&Java_MyClass_fooIOO));
241
242 EXPECT_EQ(0, gJava_MyClass_fooIOO_calls);
243 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
244 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
245 EXPECT_EQ(1, gJava_MyClass_fooIOO_calls);
246
247 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
248 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
249 EXPECT_EQ(2, gJava_MyClass_fooIOO_calls);
250 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
251 EXPECT_TRUE(env_->IsSameObject(NULL, result));
252 EXPECT_EQ(3, gJava_MyClass_fooIOO_calls);
253 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
254 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
255 EXPECT_EQ(4, gJava_MyClass_fooIOO_calls);
256
257 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
258 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
259 EXPECT_EQ(5, gJava_MyClass_fooIOO_calls);
260 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
261 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
262 EXPECT_EQ(6, gJava_MyClass_fooIOO_calls);
263 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
264 EXPECT_TRUE(env_->IsSameObject(NULL, result));
265 EXPECT_EQ(7, gJava_MyClass_fooIOO_calls);
266}
267
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700268int gJava_MyClass_fooSII_calls = 0;
269jint Java_MyClass_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
270 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
271 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
272 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
273 EXPECT_TRUE(klass != NULL);
274 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
275 gJava_MyClass_fooSII_calls++;
276 return x + y;
277}
278
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700279TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
280 SetupForTest(true, "fooSII",
281 "(II)I",
282 reinterpret_cast<void*>(&Java_MyClass_fooSII));
283
284 EXPECT_EQ(0, gJava_MyClass_fooSII_calls);
285 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
286 EXPECT_EQ(50, result);
287 EXPECT_EQ(1, gJava_MyClass_fooSII_calls);
288}
289
Ian Rogers7a99c112011-09-07 12:48:27 -0700290int gJava_MyClass_fooSDD_calls = 0;
291jdouble Java_MyClass_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
292 EXPECT_EQ(1u, Thread::Current()->NumSirtReferences());
293 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
294 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
295 EXPECT_TRUE(klass != NULL);
296 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
297 gJava_MyClass_fooSDD_calls++;
298 return x - y; // non-commutative operator
299}
300
301TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
302 SetupForTest(true, "fooSDD", "(DD)D",
303 reinterpret_cast<void*>(&Java_MyClass_fooSDD));
304
305 EXPECT_EQ(0, gJava_MyClass_fooSDD_calls);
306 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
307 EXPECT_EQ(99.0 - 10.0, result);
308 EXPECT_EQ(1, gJava_MyClass_fooSDD_calls);
309 jdouble a = 3.14159265358979323846;
310 jdouble b = 0.69314718055994530942;
311 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
312 EXPECT_EQ(a - b, result);
313 EXPECT_EQ(2, gJava_MyClass_fooSDD_calls);
314}
315
Ian Rogersb033c752011-07-20 12:22:35 -0700316int gJava_MyClass_fooSIOO_calls = 0;
Elliott Hughes330304d2011-08-12 14:28:05 -0700317jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700318 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700319 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersb033c752011-07-20 12:22:35 -0700320 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700321 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
322 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700323 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersb033c752011-07-20 12:22:35 -0700324 gJava_MyClass_fooSIOO_calls++;
325 switch (x) {
326 case 1:
327 return y;
328 case 2:
329 return z;
330 default:
331 return klass;
332 }
333}
334
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700335
336TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
337 SetupForTest(true, "fooSIOO",
338 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
339 reinterpret_cast<void*>(&Java_MyClass_fooSIOO));
340
341 EXPECT_EQ(0, gJava_MyClass_fooSIOO_calls);
342 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
343 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
344 EXPECT_EQ(1, gJava_MyClass_fooSIOO_calls);
345
346 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
347 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
348 EXPECT_EQ(2, gJava_MyClass_fooSIOO_calls);
349 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
350 EXPECT_TRUE(env_->IsSameObject(NULL, result));
351 EXPECT_EQ(3, gJava_MyClass_fooSIOO_calls);
352 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
353 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
354 EXPECT_EQ(4, gJava_MyClass_fooSIOO_calls);
355
356 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
357 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
358 EXPECT_EQ(5, gJava_MyClass_fooSIOO_calls);
359 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
360 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
361 EXPECT_EQ(6, gJava_MyClass_fooSIOO_calls);
362 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
363 EXPECT_TRUE(env_->IsSameObject(NULL, result));
364 EXPECT_EQ(7, gJava_MyClass_fooSIOO_calls);
365}
366
Ian Rogersdf20fe02011-07-20 20:34:16 -0700367int gJava_MyClass_fooSSIOO_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700368jobject Java_MyClass_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersdf20fe02011-07-20 20:34:16 -0700369 jobject z) {
Ian Rogers408f79a2011-08-23 18:22:33 -0700370 EXPECT_EQ(3u, Thread::Current()->NumSirtReferences());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700371 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700372 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
373 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700374 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700375 gJava_MyClass_fooSSIOO_calls++;
376 switch (x) {
377 case 1:
378 return y;
379 case 2:
380 return z;
381 default:
382 return klass;
383 }
384}
385
Ian Rogersdf20fe02011-07-20 20:34:16 -0700386TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700387 SetupForTest(true, "fooSSIOO",
388 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
389 reinterpret_cast<void*>(&Java_MyClass_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700390
Ian Rogersdf20fe02011-07-20 20:34:16 -0700391 EXPECT_EQ(0, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700392 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
393 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700394 EXPECT_EQ(1, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700395
396 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
397 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700398 EXPECT_EQ(2, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700399 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
400 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700401 EXPECT_EQ(3, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700402 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
403 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700404 EXPECT_EQ(4, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700405
406 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
407 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700408 EXPECT_EQ(5, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700409 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
410 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700411 EXPECT_EQ(6, gJava_MyClass_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700412 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
413 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Ian Rogersdf20fe02011-07-20 20:34:16 -0700414 EXPECT_EQ(7, gJava_MyClass_fooSSIOO_calls);
415}
416
Elliott Hughes8d768a92011-09-14 16:35:25 -0700417// TODO: this is broken now we have thread suspend implemented.
Ian Rogers45a76cb2011-07-21 22:00:15 -0700418int gSuspendCounterHandler_calls;
419void SuspendCountHandler(Method** frame) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700420 // Check we came here in the native state then transition to runnable to work
421 // on the Object*
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700422 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogersaaa20802011-09-11 21:47:37 -0700423 ScopedJniThreadState ts(Thread::Current()->GetJniEnv());
424
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700425 EXPECT_TRUE((*frame)->GetName()->Equals("fooI"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700426 gSuspendCounterHandler_calls++;
Elliott Hughes8d768a92011-09-14 16:35:25 -0700427 //Thread::Current()->DecrementSuspendCount();
Ian Rogers45a76cb2011-07-21 22:00:15 -0700428}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700429
Elliott Hughes8d768a92011-09-14 16:35:25 -0700430TEST_F(JniCompilerTest, DISABLED_SuspendCountAcknowledgement) {
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700431 SetupForTest(false, "fooI", "(I)I",
432 reinterpret_cast<void*>(&Java_MyClass_fooI));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700433 Thread::Current()->RegisterSuspendCountEntryPoint(&SuspendCountHandler);
434
Ian Rogers45a76cb2011-07-21 22:00:15 -0700435 gJava_MyClass_fooI_calls = 0;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700436 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
437 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700438 EXPECT_EQ(1, gJava_MyClass_fooI_calls);
439 EXPECT_EQ(0, gSuspendCounterHandler_calls);
Elliott Hughes8d768a92011-09-14 16:35:25 -0700440 //Thread::Current()->IncrementSuspendCount();
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700441 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
442 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700443 EXPECT_EQ(2, gJava_MyClass_fooI_calls);
444 EXPECT_EQ(1, gSuspendCounterHandler_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700445 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
446 EXPECT_EQ(42, result);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700447 EXPECT_EQ(3, gJava_MyClass_fooI_calls);
448 EXPECT_EQ(1, gSuspendCounterHandler_calls);
449}
450
451int gExceptionHandler_calls;
452void ExceptionHandler(Method** frame) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700453 // Check we came here in the native state then transition to runnable to work
454 // on the Object*
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700455 EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
Ian Rogersaaa20802011-09-11 21:47:37 -0700456 ScopedJniThreadState ts(Thread::Current()->GetJniEnv());
457
Elliott Hughesa2501992011-08-26 19:39:54 -0700458 EXPECT_TRUE((*frame)->GetName()->Equals("throwException"));
Ian Rogers45a76cb2011-07-21 22:00:15 -0700459 gExceptionHandler_calls++;
460 Thread::Current()->ClearException();
461}
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700462
Elliott Hughesa2501992011-08-26 19:39:54 -0700463void Java_MyClass_throwException(JNIEnv* env, jobject) {
464 jclass c = env->FindClass("java/lang/RuntimeException");
465 env->ThrowNew(c, "hello");
466}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700467
Elliott Hughesa2501992011-08-26 19:39:54 -0700468TEST_F(JniCompilerTest, ExceptionHandling) {
469 Thread::Current()->RegisterExceptionEntryPoint(&ExceptionHandler);
470 gExceptionHandler_calls = 0;
Ian Rogers45a76cb2011-07-21 22:00:15 -0700471 gJava_MyClass_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700472
473 SetupForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClass_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700474 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700475 EXPECT_EQ(1, gJava_MyClass_foo_calls);
476 EXPECT_EQ(0, gExceptionHandler_calls);
Elliott Hughesa2501992011-08-26 19:39:54 -0700477
478 SetupForTest(false, "throwException", "()V", reinterpret_cast<void*>(&Java_MyClass_throwException));
479 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
480 EXPECT_EQ(1, gJava_MyClass_foo_calls);
481 EXPECT_EQ(1, gExceptionHandler_calls);
482
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(2, gJava_MyClass_foo_calls);
486 EXPECT_EQ(1, gExceptionHandler_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700487}
488
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700489jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
490 if (i <= 0) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700491 // We want to check raw Object*/Array* below
492 ScopedJniThreadState ts(env);
493
494 // Build stack trace
495 jobject internal = Thread::Current()->CreateInternalStackTrace();
496 jobjectArray ste_array =
497 Thread::InternalStackTraceToStackTraceElementArray(internal, env);
498 ObjectArray<StackTraceElement>* trace_array =
499 Decode<ObjectArray<StackTraceElement>*>(env, ste_array);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700500 EXPECT_TRUE(trace_array != NULL);
501 EXPECT_EQ(11, trace_array->GetLength());
502
Ian Rogersaaa20802011-09-11 21:47:37 -0700503 // Check stack trace entries have expected values
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700504 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
505 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
Ian Rogersaaa20802011-09-11 21:47:37 -0700506 StackTraceElement* ste = trace_array->Get(i);
507 EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
508 EXPECT_STREQ("MyClass", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
509 EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700510 }
Ian Rogersaaa20802011-09-11 21:47:37 -0700511
512 // end recursion
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700513 return 0;
514 } else {
515 jclass jklass = env->FindClass("MyClass");
516 EXPECT_TRUE(jklass != NULL);
517 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
518 EXPECT_TRUE(jmethod != NULL);
519
Ian Rogersaaa20802011-09-11 21:47:37 -0700520 // Recurse with i - 1
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700521 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
Ian Rogersaaa20802011-09-11 21:47:37 -0700522
523 // Return sum of all depths
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700524 return i + result;
525 }
526}
527
528TEST_F(JniCompilerTest, NativeStackTraceElement) {
529 SetupForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&Java_MyClass_nativeUpCall));
530 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
Ian Rogersaaa20802011-09-11 21:47:37 -0700531 EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700532}
533
Ian Rogers9b269d22011-09-04 14:06:05 -0700534jobject Java_MyClass_fooO(JNIEnv* env, jobject thisObj, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700535 return env->NewGlobalRef(x);
536}
537
Ian Rogersb9231c82011-09-05 22:13:19 -0700538TEST_F(JniCompilerTest, ReturnGlobalRef) {
Ian Rogers9b269d22011-09-04 14:06:05 -0700539 SetupForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
540 reinterpret_cast<void*>(&Java_MyClass_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700541 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
542 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
543 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
544}
545
Ian Rogersb9231c82011-09-05 22:13:19 -0700546void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
547 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
548 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700549 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700550 EXPECT_EQ(1234, src_pos);
551 EXPECT_EQ(5678, dst_pos);
552 EXPECT_EQ(9876, length);
553}
554
555TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
556 SetupForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
557 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700558 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700559}
560
Ian Rogersb033c752011-07-20 12:22:35 -0700561} // namespace art