blob: 31b14c96bec807c5b93ff10bb69d87e5e831ac0b [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Ian Rogersb033c752011-07-20 12:22:35 -070016
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070017#include "class_linker.h"
18#include "common_test.h"
19#include "dex_file.h"
Elliott Hughes90a33692011-08-30 13:27:07 -070020#include "gtest/gtest.h"
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070021#include "indirect_reference_table.h"
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070022#include "jni_internal.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070023#include "mem_map.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070024#include "runtime.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070025#include "ScopedLocalRef.h"
26#include "scoped_thread_state_change.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070027#include "thread.h"
Elliott Hughesa168c832012-06-12 15:34:20 -070028#include "UniquePtr.h"
Ian Rogersb033c752011-07-20 12:22:35 -070029
Elliott Hughesb264f082012-04-06 17:10:10 -070030extern "C" JNIEXPORT jint JNICALL Java_MyClassNatives_bar(JNIEnv*, jobject, jint count) {
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -080031 return count + 1;
32}
33
Elliott Hughesb264f082012-04-06 17:10:10 -070034extern "C" JNIEXPORT jint JNICALL Java_MyClassNatives_sbar(JNIEnv*, jclass, jint count) {
Ian Rogers1cefdbd2012-02-29 09:34:50 -080035 return count + 1;
36}
37
Ian Rogersb033c752011-07-20 12:22:35 -070038namespace art {
39
Brian Carlstromf734cf52011-08-17 16:28:14 -070040class JniCompilerTest : public CommonTest {
Ian Rogersb033c752011-07-20 12:22:35 -070041 protected:
Ian Rogers00f7d0e2012-07-19 15:28:27 -070042 void CompileForTest(jobject class_loader, bool direct,
Brian Carlstrom40381fb2011-10-19 14:13:40 -070043 const char* method_name, const char* method_sig) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070044 ScopedObjectAccess soa(Thread::Current());
Brian Carlstrom25c33252011-09-18 15:58:35 -070045 // Compile the native method before starting the runtime
Ian Rogers00f7d0e2012-07-19 15:28:27 -070046 Class* c = class_linker_->FindClass("LMyClassNatives;", soa.Decode<ClassLoader*>(class_loader));
Mathieu Chartier66f19252012-09-18 08:57:04 -070047 AbstractMethod* method;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070048 if (direct) {
buzbeec143c552011-08-20 17:38:58 -070049 method = c->FindDirectMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070050 } else {
buzbeec143c552011-08-20 17:38:58 -070051 method = c->FindVirtualMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070052 }
Brian Carlstromfc7120c2012-08-27 13:43:25 -070053 ASSERT_TRUE(method != NULL) << method_name << " " << method_sig;
Brian Carlstrom25c33252011-09-18 15:58:35 -070054 if (method->GetCode() != NULL) {
55 return;
56 }
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070057 CompileMethod(method);
Brian Carlstromfc7120c2012-08-27 13:43:25 -070058 ASSERT_TRUE(method->GetCode() != NULL) << method_name << " " << method_sig;
Brian Carlstrom25c33252011-09-18 15:58:35 -070059 }
60
Ian Rogers00f7d0e2012-07-19 15:28:27 -070061 void SetUpForTest(bool direct, const char* method_name, const char* method_sig,
Brian Carlstrom25c33252011-09-18 15:58:35 -070062 void* native_fnptr) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070063 // Initialize class loader and compile method when runtime not started.
64 if (!runtime_->IsStarted()){
65 {
66 ScopedObjectAccess soa(Thread::Current());
67 class_loader_ = LoadDex("MyClassNatives");
68 }
69 CompileForTest(class_loader_, direct, method_name, method_sig);
70 // Start runtime.
71 Thread::Current()->TransitionFromSuspendedToRunnable();
Brian Carlstrom25c33252011-09-18 15:58:35 -070072 runtime_->Start();
73 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -070074 // JNI operations after runtime start.
Brian Carlstrom25c33252011-09-18 15:58:35 -070075 env_ = Thread::Current()->GetJniEnv();
Elliott Hughesb264f082012-04-06 17:10:10 -070076 jklass_ = env_->FindClass("MyClassNatives");
Brian Carlstromfc7120c2012-08-27 13:43:25 -070077 ASSERT_TRUE(jklass_ != NULL) << method_name << " " << method_sig;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070078
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070079 if (direct) {
80 jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
81 } else {
82 jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
83 }
Brian Carlstromfc7120c2012-08-27 13:43:25 -070084 ASSERT_TRUE(jmethod_ != NULL) << method_name << " " << method_sig;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070085
Ian Rogersbdb03912011-09-14 00:55:44 -070086 if (native_fnptr != NULL) {
Elliott Hughesb25c3f62012-03-26 16:35:06 -070087 JNINativeMethod methods[] = { { method_name, method_sig, native_fnptr } };
Brian Carlstromfc7120c2012-08-27 13:43:25 -070088 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1))
89 << method_name << " " << method_sig;
Ian Rogersbdb03912011-09-14 00:55:44 -070090 } else {
91 env_->UnregisterNatives(jklass_);
Shih-wei Liao31384c52011-09-06 15:27:45 -070092 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070093
94 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
95 jobj_ = env_->NewObject(jklass_, constructor);
Brian Carlstromfc7120c2012-08-27 13:43:25 -070096 ASSERT_TRUE(jobj_ != NULL) << method_name << " " << method_sig;
Ian Rogersb033c752011-07-20 12:22:35 -070097 }
98
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070099 public:
100 static jclass jklass_;
101 static jobject jobj_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700102 static jobject class_loader_;
103
Elliott Hughesa21039c2012-06-21 12:09:25 -0700104
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700105 protected:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700106 JNIEnv* env_;
107 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -0700108};
109
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700110jclass JniCompilerTest::jklass_;
111jobject JniCompilerTest::jobj_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700112jobject JniCompilerTest::class_loader_;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700113
Elliott Hughesb264f082012-04-06 17:10:10 -0700114int gJava_MyClassNatives_foo_calls = 0;
115void Java_MyClassNatives_foo(JNIEnv* env, jobject thisObj) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700116 // 1 = thisObj
117 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
118 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700119 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700120 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogersb726dcb2012-09-05 08:57:23 -0700121 Locks::mutator_lock_->AssertNotHeld();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700122 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700123 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
124 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700125 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700126 gJava_MyClassNatives_foo_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700127}
128
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700129TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700130 SetUpForTest(false, "foo", "()V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700131 reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700132
Elliott Hughesb264f082012-04-06 17:10:10 -0700133 EXPECT_EQ(0, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700134 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700135 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700136 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700137 EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700138}
139
Shih-wei Liao31384c52011-09-06 15:27:45 -0700140TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700141 SetUpForTest(false, "bar", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700142 NULL /* calling through stub will link with &Java_MyClassNatives_bar */);
Shih-wei Liao31384c52011-09-06 15:27:45 -0700143
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700144 ScopedObjectAccess soa(Thread::Current());
Shih-wei Liao31384c52011-09-06 15:27:45 -0700145 std::string reason;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700146 ASSERT_TRUE(
147 Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<ClassLoader*>(class_loader_),
148 reason)) << reason;
Shih-wei Liao31384c52011-09-06 15:27:45 -0700149
150 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
151 EXPECT_EQ(25, result);
152}
153
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800154TEST_F(JniCompilerTest, CompileAndRunStaticIntMethodThroughStub) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700155 SetUpForTest(true, "sbar", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700156 NULL /* calling through stub will link with &Java_MyClassNatives_sbar */);
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800157
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700158 ScopedObjectAccess soa(Thread::Current());
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800159 std::string reason;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700160 ASSERT_TRUE(
161 Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<ClassLoader*>(class_loader_),
162 reason)) << reason;
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800163
164 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42);
165 EXPECT_EQ(43, result);
166}
167
Elliott Hughesb264f082012-04-06 17:10:10 -0700168int gJava_MyClassNatives_fooI_calls = 0;
169jint Java_MyClassNatives_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700170 // 1 = thisObj
171 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
172 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700173 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700174 EXPECT_EQ(kNative, Thread::Current()->GetState());
175 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700176 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
177 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700178 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700179 gJava_MyClassNatives_fooI_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700180 return x;
181}
182
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700183TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700184 SetUpForTest(false, "fooI", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700185 reinterpret_cast<void*>(&Java_MyClassNatives_fooI));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700186
Elliott Hughesb264f082012-04-06 17:10:10 -0700187 EXPECT_EQ(0, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700188 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
189 EXPECT_EQ(42, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700190 EXPECT_EQ(1, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700191 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
192 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700193 EXPECT_EQ(2, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700194}
195
Elliott Hughesb264f082012-04-06 17:10:10 -0700196int gJava_MyClassNatives_fooII_calls = 0;
197jint Java_MyClassNatives_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700198 // 1 = thisObj
199 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
200 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700201 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700202 EXPECT_EQ(kNative, Thread::Current()->GetState());
203 }
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_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700207 gJava_MyClassNatives_fooII_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700208 return x - y; // non-commutative operator
209}
210
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700211TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700212 SetUpForTest(false, "fooII", "(II)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700213 reinterpret_cast<void*>(&Java_MyClassNatives_fooII));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700214
Elliott Hughesb264f082012-04-06 17:10:10 -0700215 EXPECT_EQ(0, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700216 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
217 EXPECT_EQ(99 - 10, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700218 EXPECT_EQ(1, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700219 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
220 0xCAFED00D);
221 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700222 EXPECT_EQ(2, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700223}
224
Elliott Hughesb264f082012-04-06 17:10:10 -0700225int gJava_MyClassNatives_fooJJ_calls = 0;
226jlong Java_MyClassNatives_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700227 // 1 = thisObj
228 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
229 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700230 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700231 EXPECT_EQ(kNative, Thread::Current()->GetState());
232 }
Ian Rogers9b269d22011-09-04 14:06:05 -0700233 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
234 EXPECT_TRUE(thisObj != NULL);
235 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700236 gJava_MyClassNatives_fooJJ_calls++;
Ian Rogers9b269d22011-09-04 14:06:05 -0700237 return x - y; // non-commutative operator
238}
239
240TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700241 SetUpForTest(false, "fooJJ", "(JJ)J",
Elliott Hughesb264f082012-04-06 17:10:10 -0700242 reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ));
Ian Rogers9b269d22011-09-04 14:06:05 -0700243
Elliott Hughesb264f082012-04-06 17:10:10 -0700244 EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700245 jlong a = 0x1234567890ABCDEFll;
246 jlong b = 0xFEDCBA0987654321ll;
247 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
248 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700249 EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700250 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
251 EXPECT_EQ(b - a, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700252 EXPECT_EQ(2, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700253}
254
Elliott Hughesb264f082012-04-06 17:10:10 -0700255int gJava_MyClassNatives_fooDD_calls = 0;
256jdouble Java_MyClassNatives_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700257 // 1 = thisObj
258 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
259 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700260 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700261 EXPECT_EQ(kNative, Thread::Current()->GetState());
262 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700263 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
264 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700265 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700266 gJava_MyClassNatives_fooDD_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700267 return x - y; // non-commutative operator
268}
269
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700270TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700271 SetUpForTest(false, "fooDD", "(DD)D",
Elliott Hughesb264f082012-04-06 17:10:10 -0700272 reinterpret_cast<void*>(&Java_MyClassNatives_fooDD));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700273
Elliott Hughesb264f082012-04-06 17:10:10 -0700274 EXPECT_EQ(0, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700275 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
276 99.0, 10.0);
277 EXPECT_EQ(99.0 - 10.0, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700278 EXPECT_EQ(1, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700279 jdouble a = 3.14159265358979323846;
280 jdouble b = 0.69314718055994530942;
281 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
282 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700283 EXPECT_EQ(2, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700284}
285
Elliott Hughes3e778f72012-05-21 15:29:52 -0700286int gJava_MyClassNatives_fooJJ_synchronized_calls = 0;
287jlong Java_MyClassNatives_fooJJ_synchronized(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700288 // 1 = thisObj
289 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
290 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700291 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700292 EXPECT_EQ(kNative, Thread::Current()->GetState());
293 }
Elliott Hughes3e778f72012-05-21 15:29:52 -0700294 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
295 EXPECT_TRUE(thisObj != NULL);
296 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
297 gJava_MyClassNatives_fooJJ_synchronized_calls++;
298 return x | y;
299}
300
301TEST_F(JniCompilerTest, CompileAndRun_fooJJ_synchronized) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700302 SetUpForTest(false, "fooJJ_synchronized", "(JJ)J",
Elliott Hughes3e778f72012-05-21 15:29:52 -0700303 reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ_synchronized));
304
305 EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_synchronized_calls);
306 jlong a = 0x1000000020000000ULL;
307 jlong b = 0x00ff000000aa0000ULL;
308 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
309 EXPECT_EQ(a | b, result);
310 EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_synchronized_calls);
311}
312
Elliott Hughesb264f082012-04-06 17:10:10 -0700313int gJava_MyClassNatives_fooIOO_calls = 0;
314jobject Java_MyClassNatives_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700315 jobject z) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700316 // 3 = this + y + z
317 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
318 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700319 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700320 EXPECT_EQ(kNative, Thread::Current()->GetState());
321 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700322 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
323 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700324 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700325 gJava_MyClassNatives_fooIOO_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700326 switch (x) {
327 case 1:
328 return y;
329 case 2:
330 return z;
331 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700332 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700333 }
334}
335
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700336TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700337 SetUpForTest(false, "fooIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700338 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700339 reinterpret_cast<void*>(&Java_MyClassNatives_fooIOO));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700340
Elliott Hughesb264f082012-04-06 17:10:10 -0700341 EXPECT_EQ(0, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700342 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
343 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700344 EXPECT_EQ(1, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700345
346 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
347 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700348 EXPECT_EQ(2, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700349 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
350 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700351 EXPECT_EQ(3, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700352 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
353 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700354 EXPECT_EQ(4, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700355
356 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
357 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700358 EXPECT_EQ(5, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700359 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
360 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700361 EXPECT_EQ(6, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700362 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
363 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700364 EXPECT_EQ(7, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700365}
366
Elliott Hughesb264f082012-04-06 17:10:10 -0700367int gJava_MyClassNatives_fooSII_calls = 0;
368jint Java_MyClassNatives_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700369 // 1 = klass
370 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
371 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700372 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700373 EXPECT_EQ(kNative, Thread::Current()->GetState());
374 }
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700375 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
376 EXPECT_TRUE(klass != NULL);
377 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700378 gJava_MyClassNatives_fooSII_calls++;
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700379 return x + y;
380}
381
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700382TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700383 SetUpForTest(true, "fooSII", "(II)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700384 reinterpret_cast<void*>(&Java_MyClassNatives_fooSII));
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700385
Elliott Hughesb264f082012-04-06 17:10:10 -0700386 EXPECT_EQ(0, gJava_MyClassNatives_fooSII_calls);
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700387 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
388 EXPECT_EQ(50, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700389 EXPECT_EQ(1, gJava_MyClassNatives_fooSII_calls);
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700390}
391
Elliott Hughesb264f082012-04-06 17:10:10 -0700392int gJava_MyClassNatives_fooSDD_calls = 0;
393jdouble Java_MyClassNatives_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700394 // 1 = klass
395 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
396 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700397 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700398 EXPECT_EQ(kNative, Thread::Current()->GetState());
399 }
Ian Rogers7a99c112011-09-07 12:48:27 -0700400 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
401 EXPECT_TRUE(klass != NULL);
402 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700403 gJava_MyClassNatives_fooSDD_calls++;
Ian Rogers7a99c112011-09-07 12:48:27 -0700404 return x - y; // non-commutative operator
405}
406
407TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700408 SetUpForTest(true, "fooSDD", "(DD)D",
Elliott Hughesb264f082012-04-06 17:10:10 -0700409 reinterpret_cast<void*>(&Java_MyClassNatives_fooSDD));
Ian Rogers7a99c112011-09-07 12:48:27 -0700410
Elliott Hughesb264f082012-04-06 17:10:10 -0700411 EXPECT_EQ(0, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700412 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
413 EXPECT_EQ(99.0 - 10.0, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700414 EXPECT_EQ(1, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700415 jdouble a = 3.14159265358979323846;
416 jdouble b = 0.69314718055994530942;
417 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
418 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700419 EXPECT_EQ(2, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700420}
421
Elliott Hughesb264f082012-04-06 17:10:10 -0700422int gJava_MyClassNatives_fooSIOO_calls = 0;
423jobject Java_MyClassNatives_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700424 jobject z) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700425 // 3 = klass + y + z
426 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
427 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700428 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700429 EXPECT_EQ(kNative, Thread::Current()->GetState());
430 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700431 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
432 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700433 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700434 gJava_MyClassNatives_fooSIOO_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700435 switch (x) {
436 case 1:
437 return y;
438 case 2:
439 return z;
440 default:
441 return klass;
442 }
443}
444
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700445
446TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700447 SetUpForTest(true, "fooSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700448 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700449 reinterpret_cast<void*>(&Java_MyClassNatives_fooSIOO));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700450
Elliott Hughesb264f082012-04-06 17:10:10 -0700451 EXPECT_EQ(0, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700452 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
453 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700454 EXPECT_EQ(1, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700455
456 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
457 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700458 EXPECT_EQ(2, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700459 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
460 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700461 EXPECT_EQ(3, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700462 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
463 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700464 EXPECT_EQ(4, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700465
466 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
467 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700468 EXPECT_EQ(5, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700469 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
470 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700471 EXPECT_EQ(6, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700472 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
473 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700474 EXPECT_EQ(7, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700475}
476
Elliott Hughesb264f082012-04-06 17:10:10 -0700477int gJava_MyClassNatives_fooSSIOO_calls = 0;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700478jobject Java_MyClassNatives_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y, jobject z) {
479 // 3 = klass + y + z
480 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
481 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700482 MutexLock mu(*Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700483 EXPECT_EQ(kNative, Thread::Current()->GetState());
484 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700485 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
486 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700487 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700488 gJava_MyClassNatives_fooSSIOO_calls++;
Ian Rogersdf20fe02011-07-20 20:34:16 -0700489 switch (x) {
490 case 1:
491 return y;
492 case 2:
493 return z;
494 default:
495 return klass;
496 }
497}
498
Ian Rogersdf20fe02011-07-20 20:34:16 -0700499TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700500 SetUpForTest(true, "fooSSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700501 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700502 reinterpret_cast<void*>(&Java_MyClassNatives_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700503
Elliott Hughesb264f082012-04-06 17:10:10 -0700504 EXPECT_EQ(0, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700505 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
506 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700507 EXPECT_EQ(1, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700508
509 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
510 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700511 EXPECT_EQ(2, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700512 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
513 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700514 EXPECT_EQ(3, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700515 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
516 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700517 EXPECT_EQ(4, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700518
519 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
520 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700521 EXPECT_EQ(5, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700522 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
523 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700524 EXPECT_EQ(6, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700525 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
526 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700527 EXPECT_EQ(7, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogersdf20fe02011-07-20 20:34:16 -0700528}
529
Elliott Hughesb264f082012-04-06 17:10:10 -0700530void Java_MyClassNatives_throwException(JNIEnv* env, jobject) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700531 jclass c = env->FindClass("java/lang/RuntimeException");
532 env->ThrowNew(c, "hello");
533}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700534
Elliott Hughesa2501992011-08-26 19:39:54 -0700535TEST_F(JniCompilerTest, ExceptionHandling) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700536 {
537 ASSERT_FALSE(runtime_->IsStarted());
538 ScopedObjectAccess soa(Thread::Current());
539 class_loader_ = LoadDex("MyClassNatives");
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700540
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700541 // all compilation needs to happen before Runtime::Start
542 CompileForTest(class_loader_, false, "foo", "()V");
543 CompileForTest(class_loader_, false, "throwException", "()V");
544 CompileForTest(class_loader_, false, "foo", "()V");
545 }
546 // Start runtime to avoid re-initialization in SetupForTest.
547 Thread::Current()->TransitionFromSuspendedToRunnable();
548 runtime_->Start();
Brian Carlstrom25c33252011-09-18 15:58:35 -0700549
Elliott Hughesb264f082012-04-06 17:10:10 -0700550 gJava_MyClassNatives_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700551
Ian Rogers67375ac2011-09-14 00:55:44 -0700552 // Check a single call of a JNI method is ok
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700553 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700554 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700555 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogers67375ac2011-09-14 00:55:44 -0700556 EXPECT_FALSE(Thread::Current()->IsExceptionPending());
Elliott Hughesa2501992011-08-26 19:39:54 -0700557
Ian Rogers67375ac2011-09-14 00:55:44 -0700558 // Get class for exception we expect to be thrown
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700559 ScopedLocalRef<jclass> jlre(env_, env_->FindClass("java/lang/RuntimeException"));
560 SetUpForTest(false, "throwException", "()V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700561 reinterpret_cast<void*>(&Java_MyClassNatives_throwException));
562 // Call Java_MyClassNatives_throwException (JNI method that throws exception)
Elliott Hughesa2501992011-08-26 19:39:54 -0700563 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700564 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700565 EXPECT_TRUE(env_->ExceptionCheck() == JNI_TRUE);
566 ScopedLocalRef<jthrowable> exception(env_, env_->ExceptionOccurred());
567 env_->ExceptionClear();
568 EXPECT_TRUE(env_->IsInstanceOf(exception.get(), jlre.get()));
Elliott Hughesa2501992011-08-26 19:39:54 -0700569
Ian Rogers67375ac2011-09-14 00:55:44 -0700570 // Check a single call of a JNI method is ok
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700571 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700572 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700573 EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700574}
575
Elliott Hughesb264f082012-04-06 17:10:10 -0700576jint Java_MyClassNatives_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700577 if (i <= 0) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700578 // We want to check raw Object*/Array* below
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700579 ScopedObjectAccess soa(env);
Ian Rogersaaa20802011-09-11 21:47:37 -0700580
581 // Build stack trace
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700582 jobject internal = Thread::Current()->CreateInternalStackTrace(soa);
Elliott Hughes01158d72011-09-19 19:47:10 -0700583 jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal);
Ian Rogersaaa20802011-09-11 21:47:37 -0700584 ObjectArray<StackTraceElement>* trace_array =
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700585 soa.Decode<ObjectArray<StackTraceElement>*>(ste_array);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700586 EXPECT_TRUE(trace_array != NULL);
587 EXPECT_EQ(11, trace_array->GetLength());
588
Ian Rogersaaa20802011-09-11 21:47:37 -0700589 // Check stack trace entries have expected values
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700590 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
591 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
Ian Rogersaaa20802011-09-11 21:47:37 -0700592 StackTraceElement* ste = trace_array->Get(i);
593 EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -0700594 EXPECT_STREQ("MyClassNatives", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
Ian Rogersaaa20802011-09-11 21:47:37 -0700595 EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700596 }
Ian Rogersaaa20802011-09-11 21:47:37 -0700597
598 // end recursion
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700599 return 0;
600 } else {
Elliott Hughesb264f082012-04-06 17:10:10 -0700601 jclass jklass = env->FindClass("MyClassNatives");
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700602 EXPECT_TRUE(jklass != NULL);
603 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
604 EXPECT_TRUE(jmethod != NULL);
605
Ian Rogersaaa20802011-09-11 21:47:37 -0700606 // Recurse with i - 1
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700607 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
Ian Rogersaaa20802011-09-11 21:47:37 -0700608
609 // Return sum of all depths
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700610 return i + result;
611 }
612}
613
614TEST_F(JniCompilerTest, NativeStackTraceElement) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700615 SetUpForTest(false, "fooI", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700616 reinterpret_cast<void*>(&Java_MyClassNatives_nativeUpCall));
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700617 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
Ian Rogersaaa20802011-09-11 21:47:37 -0700618 EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700619}
620
Elliott Hughesb264f082012-04-06 17:10:10 -0700621jobject Java_MyClassNatives_fooO(JNIEnv* env, jobject, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700622 return env->NewGlobalRef(x);
623}
624
Ian Rogersb9231c82011-09-05 22:13:19 -0700625TEST_F(JniCompilerTest, ReturnGlobalRef) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700626 SetUpForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700627 reinterpret_cast<void*>(&Java_MyClassNatives_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700628 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
629 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
630 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
631}
632
Ian Rogersdc51b792011-09-22 20:41:37 -0700633jint local_ref_test(JNIEnv* env, jobject thisObj, jint x) {
634 // Add 10 local references
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700635 ScopedObjectAccess soa(env);
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700636 for (int i = 0; i < 10; i++) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700637 soa.AddLocalReference<jobject>(soa.Decode<Object*>(thisObj));
Ian Rogersdc51b792011-09-22 20:41:37 -0700638 }
639 return x+1;
640}
641
642TEST_F(JniCompilerTest, LocalReferenceTableClearingTest) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700643 SetUpForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&local_ref_test));
Ian Rogersdc51b792011-09-22 20:41:37 -0700644 // 1000 invocations of a method that adds 10 local references
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700645 for (int i = 0; i < 1000; i++) {
Ian Rogersdc51b792011-09-22 20:41:37 -0700646 jint result = env_->CallIntMethod(jobj_, jmethod_, i);
647 EXPECT_TRUE(result == i + 1);
648 }
649}
650
Ian Rogersb9231c82011-09-05 22:13:19 -0700651void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
652 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
653 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700654 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700655 EXPECT_EQ(1234, src_pos);
656 EXPECT_EQ(5678, dst_pos);
657 EXPECT_EQ(9876, length);
658}
659
660TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700661 SetUpForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
Ian Rogersb9231c82011-09-05 22:13:19 -0700662 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700663 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700664}
665
Ian Rogers67375ac2011-09-14 00:55:44 -0700666jboolean my_casi(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jint expected, jint newval) {
667 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, unsafe));
668 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj));
669 EXPECT_EQ(0x12345678ABCDEF88ll, offset);
670 EXPECT_EQ(static_cast<jint>(0xCAFEF00D), expected);
671 EXPECT_EQ(static_cast<jint>(0xEBADF00D), newval);
672 return JNI_TRUE;
673}
674
675TEST_F(JniCompilerTest, CompareAndSwapInt) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700676 SetUpForTest(false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
Ian Rogers67375ac2011-09-14 00:55:44 -0700677 reinterpret_cast<void*>(&my_casi));
678 jboolean result = env_->CallBooleanMethod(jobj_, jmethod_, jobj_, 0x12345678ABCDEF88ll, 0xCAFEF00D, 0xEBADF00D);
679 EXPECT_EQ(result, JNI_TRUE);
680}
681
Ian Rogersc7792842012-03-03 15:36:20 -0800682jint my_gettext(JNIEnv* env, jclass klass, jlong val1, jobject obj1, jlong val2, jobject obj2) {
683 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
684 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj1));
685 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj2));
686 EXPECT_EQ(0x12345678ABCDEF88ll, val1);
687 EXPECT_EQ(0x7FEDCBA987654321ll, val2);
688 return 42;
689}
690
691TEST_F(JniCompilerTest, GetText) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700692 SetUpForTest(true, "getText", "(JLjava/lang/Object;JLjava/lang/Object;)I",
Ian Rogersc7792842012-03-03 15:36:20 -0800693 reinterpret_cast<void*>(&my_gettext));
694 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 0x12345678ABCDEF88ll, jobj_,
695 0x7FEDCBA987654321ll, jobj_);
696 EXPECT_EQ(result, 42);
697}
698
Brian Carlstromfc7120c2012-08-27 13:43:25 -0700699TEST_F(JniCompilerTest, GetSinkPropertiesNative) {
700 SetUpForTest(false, "getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", NULL);
701 // This space intentionally left blank. Just testing compilation succeeds.
702}
703
Elliott Hughesb264f082012-04-06 17:10:10 -0700704// This should return jclass, but we're imitating a bug pattern.
705jobject Java_MyClassNatives_instanceMethodThatShouldReturnClass(JNIEnv* env, jobject) {
706 return env->NewStringUTF("not a class!");
707}
708
709// This should return jclass, but we're imitating a bug pattern.
710jobject Java_MyClassNatives_staticMethodThatShouldReturnClass(JNIEnv* env, jclass) {
711 return env->NewStringUTF("not a class!");
712}
713
714TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Instance) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700715 SetUpForTest(false, "instanceMethodThatShouldReturnClass", "()Ljava/lang/Class;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700716 reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldReturnClass));
717
718 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700719 // TODO: check type of returns with portable JNI compiler.
720 // This native method is bad, and tries to return a jstring as a jclass.
721 env_->CallObjectMethod(jobj_, jmethod_);
722 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
723
724 // Here, we just call the method incorrectly; we should catch that too.
Elliott Hughesb264f082012-04-06 17:10:10 -0700725 env_->CallVoidMethod(jobj_, jmethod_);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700726 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
727 env_->CallStaticVoidMethod(jklass_, jmethod_);
728 check_jni_abort_catcher.Check("calling non-static method java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass() with CallStaticVoidMethodV");
Elliott Hughesb264f082012-04-06 17:10:10 -0700729}
730
731TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Static) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700732 SetUpForTest(true, "staticMethodThatShouldReturnClass", "()Ljava/lang/Class;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700733 reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldReturnClass));
734
735 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700736 // TODO: check type of returns with portable JNI compiler.
737 // This native method is bad, and tries to return a jstring as a jclass.
738 env_->CallStaticObjectMethod(jklass_, jmethod_);
739 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass()");
740
741 // Here, we just call the method incorrectly; we should catch that too.
742 env_->CallStaticVoidMethod(jklass_, jmethod_);
743 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass()");
Elliott Hughesb264f082012-04-06 17:10:10 -0700744 env_->CallVoidMethod(jobj_, jmethod_);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700745 check_jni_abort_catcher.Check("calling static method java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass() with CallVoidMethodV");
Elliott Hughesb264f082012-04-06 17:10:10 -0700746}
747
748// This should take jclass, but we're imitating a bug pattern.
749void Java_MyClassNatives_instanceMethodThatShouldTakeClass(JNIEnv*, jobject, jclass) {
750}
751
752// This should take jclass, but we're imitating a bug pattern.
753void Java_MyClassNatives_staticMethodThatShouldTakeClass(JNIEnv*, jclass, jclass) {
754}
755
756TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Instance) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700757 SetUpForTest(false, "instanceMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700758 reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldTakeClass));
759
760 CheckJniAbortCatcher check_jni_abort_catcher;
761 // We deliberately pass a bad second argument here.
762 env_->CallVoidMethod(jobj_, jmethod_, 123, env_->NewStringUTF("not a class!"));
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700763 check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.instanceMethodThatShouldTakeClass(int, java.lang.Class)");
Elliott Hughesb264f082012-04-06 17:10:10 -0700764}
765
766TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Static) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700767 SetUpForTest(true, "staticMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700768 reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldTakeClass));
769
770 CheckJniAbortCatcher check_jni_abort_catcher;
771 // We deliberately pass a bad second argument here.
772 env_->CallStaticVoidMethod(jklass_, jmethod_, 123, env_->NewStringUTF("not a class!"));
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700773 check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.staticMethodThatShouldTakeClass(int, java.lang.Class)");
Elliott Hughesb264f082012-04-06 17:10:10 -0700774}
775
Ian Rogersb033c752011-07-20 12:22:35 -0700776} // namespace art