blob: 4692f822606224de6da2a478a99d0b93eaf81450 [file] [log] [blame]
// Copyright 2011 Google Inc. All Rights Reserved.
#include "class_linker.h"
#include "common_test.h"
#include "compiler.h"
#include "compiler_test.h"
#include "dex_cache.h"
#include "dex_file.h"
#include "heap.h"
#include "object.h"
#include "scoped_ptr.h"
#include <stdint.h>
#include <stdio.h>
#include "gtest/gtest.h"
namespace art {
class CompilerTest : public CommonTest {
};
TEST_F(CompilerTest, CompileLibCore) {
Compiler compiler;
compiler.Compile(boot_class_path_);
// All libcore references should resolve
const DexFile* dex = java_lang_dex_file_.get();
DexCache* dex_cache = class_linker_->FindDexCache(*dex);
EXPECT_EQ(dex->NumStringIds(), dex_cache->NumStrings());
for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
String* string = dex_cache->GetResolvedString(i);
EXPECT_TRUE(string != NULL);
}
EXPECT_EQ(dex->NumTypeIds(), dex_cache->NumTypes());
for (size_t i = 0; i < dex_cache->NumTypes(); i++) {
Class* type = dex_cache->GetResolvedType(i);
EXPECT_TRUE(type != NULL);
}
EXPECT_EQ(dex->NumMethodIds(), dex_cache->NumMethods());
for (size_t i = 0; i < dex_cache->NumMethods(); i++) {
// TODO: ClassLinker::ResolveMethod
// Method* method = dex_cache->GetResolvedMethod(i);
// EXPECT_TRUE(method != NULL);
}
EXPECT_EQ(dex->NumFieldIds(), dex_cache->NumFields());
for (size_t i = 0; i < dex_cache->NumFields(); i++) {
// TODO: ClassLinker::ResolveField
// Field* field = dex_cache->GetResolvedField(i);
// EXPECT_TRUE(field != NULL);
}
}
#if defined(__arm__)
TEST_F(CompilerTest, BasicCodegen) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kFibonacciDex,
"kFibonacciDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("Fibonacci");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "fibonacci", "(I)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, 10);
LOG(INFO) << "Fibonacci[10] is " << result;
ASSERT_EQ(55, result);
}
TEST_F(CompilerTest, UnopTest) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "unopTest", "(I)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, 38);
LOG(INFO) << "unopTest(38) == " << result;
ASSERT_EQ(37, result);
}
#if 0 // Does filled array - needs load-time class resolution
TEST_F(CompilerTest, ShiftTest1) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "shiftTest1", "()I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m);
ASSERT_EQ(0, result);
}
#endif
TEST_F(CompilerTest, ShiftTest2) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "shiftTest2", "()I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m);
ASSERT_EQ(0, result);
}
TEST_F(CompilerTest, UnsignedShiftTest) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "unsignedShiftTest", "()I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m);
ASSERT_EQ(0, result);
}
#if 0 // Fail subtest #3, long to int conversion w/ truncation.
TEST_F(CompilerTest, ConvTest) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "convTest", "()I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m);
ASSERT_EQ(0, result);
}
#endif
TEST_F(CompilerTest, CharSubTest) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "charSubTest", "()I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m);
ASSERT_EQ(0, result);
}
#if 0 // Needs array allocation & r9 to be set up with Thread*
TEST_F(CompilerTest, IntOperTest) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "intOperTest", "(II)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, 70000, -3);
ASSERT_EQ(0, result);
}
#endif
#if 0 // Needs array allocation & r9 to be set up with Thread*
TEST_F(CompilerTest, Lit16Test) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "lit16Test", "(I)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, 77777);
ASSERT_EQ(0, result);
}
#endif
#if 0 // Needs array allocation & r9 to be set up with Thread*
TEST_F(CompilerTest, Lit8Test) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "lit8Test", "(I)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, -55555);
ASSERT_EQ(0, result);
}
#endif
#if 0 // Needs array allocation & r9 to be set up with Thread*
TEST_F(CompilerTest, Lit8Test) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "lit8Test", "(I)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, -55555);
ASSERT_EQ(0, result);
}
#endif
#if 0 // Needs array allocation & r9 to be set up with Thread*
TEST_F(CompilerTest, IntShiftTest) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "intShiftTest", "(II)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, 0xff00aa01, 8);
ASSERT_EQ(0, result);
}
#endif
#if 0 // Needs array allocation & r9 to be set up with Thread*
TEST_F(CompilerTest, LongOperTest) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "longOperTest", "(LL)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, 70000000000L, 3);
ASSERT_EQ(0, result);
}
#endif
#if 0 // Needs array allocation & r9 to be set up with Thread*
TEST_F(CompilerTest, LongShiftTest) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "longShiftTest", "(LL)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, 0xd5aa96deff00aa01, 8);
ASSERT_EQ(0, result);
}
#endif
TEST_F(CompilerTest, SwitchTest1) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "switchTest", "(I)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, 1);
ASSERT_EQ(1234, result);
}
TEST_F(CompilerTest, IntCompare) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "testIntCompare", "(IIII)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, -5, 4, 4, 0);
ASSERT_EQ(1111, result);
}
TEST_F(CompilerTest, LongCompare) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "testLongCompare", "(JJJJ)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, -5LL, -4294967287LL, 4LL, 8LL);
ASSERT_EQ(2222, result);
}
TEST_F(CompilerTest, FloatCompare) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "testFloatCompare", "(FFFF)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, -5.0f, 4.0f, 4.0f,
(1.0f/0.0f) / (1.0f/0.0f));
ASSERT_EQ(3333, result);
}
TEST_F(CompilerTest, DoubleCompare) {
scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kIntMathDex,
"kIntMathDex"));
PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get());
Thread::Current()->SetClassLoaderOverride(class_loader);
JNIEnv* env = Thread::Current()->GetJniEnv();
jclass c = env->FindClass("IntMath");
ASSERT_TRUE(c != NULL);
jmethodID m = env->GetStaticMethodID(c, "testDoubleCompare", "(DDDD)I");
ASSERT_TRUE(m != NULL);
jint result = env->CallStaticIntMethod(c, m, -5.0, 4.0, 4.0,
(1.0/0.0) / (1.0/0.0));
ASSERT_EQ(4444, result);
}
#endif // Arm
} // namespace art