summaryrefslogtreecommitdiffstats
path: root/runtime/oat_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/oat_test.cc')
-rw-r--r--runtime/oat_test.cc170
1 files changed, 170 insertions, 0 deletions
diff --git a/runtime/oat_test.cc b/runtime/oat_test.cc
new file mode 100644
index 000000000..f41a7bad9
--- /dev/null
+++ b/runtime/oat_test.cc
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "compiler/oat_writer.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/object-inl.h"
+#include "oat_file.h"
+#include "vector_output_stream.h"
+
+#include "common_test.h"
+
+namespace art {
+
+class OatTest : public CommonTest {
+ protected:
+ void CheckMethod(mirror::AbstractMethod* method,
+ const OatFile::OatMethod& oat_method,
+ const DexFile* dex_file)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ const CompiledMethod* compiled_method =
+ compiler_driver_->GetCompiledMethod(MethodReference(dex_file,
+ method->GetDexMethodIndex()));
+
+ if (compiled_method == NULL) {
+ EXPECT_TRUE(oat_method.GetCode() == NULL) << PrettyMethod(method) << " "
+ << oat_method.GetCode();
+#if !defined(ART_USE_PORTABLE_COMPILER)
+ EXPECT_EQ(oat_method.GetFrameSizeInBytes(), static_cast<uint32_t>(kStackAlignment));
+ EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
+ EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
+#endif
+ } else {
+ const void* oat_code = oat_method.GetCode();
+ EXPECT_TRUE(oat_code != NULL) << PrettyMethod(method);
+ uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(oat_code), 2);
+ oat_code = reinterpret_cast<const void*>(oat_code_aligned);
+
+ const std::vector<uint8_t>& code = compiled_method->GetCode();
+ size_t code_size = code.size() * sizeof(code[0]);
+ EXPECT_EQ(0, memcmp(oat_code, &code[0], code_size))
+ << PrettyMethod(method) << " " << code_size;
+ CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
+#if !defined(ART_USE_PORTABLE_COMPILER)
+ EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
+ EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
+ EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
+#endif
+ }
+ }
+};
+
+TEST_F(OatTest, WriteRead) {
+ const bool compile = false; // DISABLED_ due to the time to compile libcore
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+
+ // TODO: make selectable
+#if defined(ART_USE_PORTABLE_COMPILER)
+ CompilerBackend compiler_backend = kPortable;
+#else
+ CompilerBackend compiler_backend = kQuick;
+#endif
+ compiler_driver_.reset(new CompilerDriver(compiler_backend, kThumb2, false, NULL, 2, false,
+ true, true));
+ jobject class_loader = NULL;
+ if (compile) {
+ compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath());
+ }
+
+ ScopedObjectAccess soa(Thread::Current());
+ ScratchFile tmp;
+ std::vector<uint8_t> oat_contents;
+ VectorOutputStream output_stream(tmp.GetFilename(), oat_contents);
+ bool success_oat = OatWriter::Create(output_stream,
+ class_linker->GetBootClassPath(),
+ 42U,
+ 4096U,
+ "lue.art",
+ *compiler_driver_.get());
+ ASSERT_TRUE(success_oat);
+ bool success_elf = compiler_driver_->WriteElf(GetTestAndroidRoot(),
+ !kIsTargetBuild,
+ class_linker->GetBootClassPath(),
+ oat_contents,
+ tmp.GetFile());
+ ASSERT_TRUE(success_elf);
+
+ if (compile) { // OatWriter strips the code, regenerate to compare
+ compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath());
+ }
+ UniquePtr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), tmp.GetFilename(), NULL));
+ ASSERT_TRUE(oat_file.get() != NULL);
+ const OatHeader& oat_header = oat_file->GetOatHeader();
+ ASSERT_TRUE(oat_header.IsValid());
+ ASSERT_EQ(2U, oat_header.GetDexFileCount()); // core and conscrypt
+ ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
+ ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatDataBegin());
+ ASSERT_EQ("lue.art", oat_header.GetImageFileLocation());
+
+ const DexFile* dex_file = java_lang_dex_file_;
+ const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file->GetLocation());
+ CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
+ for (size_t i = 0; i < dex_file->NumClassDefs(); i++) {
+ const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
+ const byte* class_data = dex_file->GetClassData(class_def);
+ size_t num_virtual_methods =0;
+ if (class_data != NULL) {
+ ClassDataItemIterator it(*dex_file, class_data);
+ num_virtual_methods = it.NumVirtualMethods();
+ }
+ const char* descriptor = dex_file->GetClassDescriptor(class_def);
+
+ UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(i));
+
+ mirror::Class* klass = class_linker->FindClass(descriptor, NULL);
+
+ size_t method_index = 0;
+ for (size_t i = 0; i < klass->NumDirectMethods(); i++, method_index++) {
+ CheckMethod(klass->GetDirectMethod(i),
+ oat_class->GetOatMethod(method_index), dex_file);
+ }
+ for (size_t i = 0; i < num_virtual_methods; i++, method_index++) {
+ CheckMethod(klass->GetVirtualMethod(i),
+ oat_class->GetOatMethod(method_index), dex_file);
+ }
+ }
+}
+
+TEST_F(OatTest, OatHeaderSizeCheck) {
+ // If this test is failing and you have to update these constants,
+ // it is time to update OatHeader::kOatVersion
+ EXPECT_EQ(52U, sizeof(OatHeader));
+ EXPECT_EQ(28U, sizeof(OatMethodOffsets));
+}
+
+TEST_F(OatTest, OatHeaderIsValid) {
+ InstructionSet instruction_set = kX86;
+ std::vector<const DexFile*> dex_files;
+ uint32_t image_file_location_oat_checksum = 0;
+ uint32_t image_file_location_oat_begin = 0;
+ const std::string image_file_location;
+ OatHeader oat_header(instruction_set,
+ &dex_files,
+ image_file_location_oat_checksum,
+ image_file_location_oat_begin,
+ image_file_location);
+ ASSERT_TRUE(oat_header.IsValid());
+
+ char* magic = const_cast<char*>(oat_header.GetMagic());
+ strcpy(magic, ""); // bad magic
+ ASSERT_FALSE(oat_header.IsValid());
+ strcpy(magic, "oat\n000"); // bad version
+ ASSERT_FALSE(oat_header.IsValid());
+}
+
+} // namespace art