summaryrefslogtreecommitdiffstats
path: root/compiler/oat_test.cc
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-08-16 14:36:13 -0700
committerIan Rogers <irogers@google.com>2013-08-16 14:57:10 -0700
commit0e480cad5d2cf0904b98b7b56e90280e9b97ba30 (patch)
tree56e12c8d362e1c6aaef38e8d1f7e54ade1b3a21c /compiler/oat_test.cc
parentd2b0f33cf01601f040494f4f882e60f70b527930 (diff)
downloadart-0e480cad5d2cf0904b98b7b56e90280e9b97ba30.tar.gz
art-0e480cad5d2cf0904b98b7b56e90280e9b97ba30.tar.bz2
art-0e480cad5d2cf0904b98b7b56e90280e9b97ba30.zip
Move output_stream files out of runtime.
Also move image_test and oat_test that are more writing tests. Change-Id: I6af1400d8e745bbf87f626ca87dae3e2d85b40f1
Diffstat (limited to 'compiler/oat_test.cc')
-rw-r--r--compiler/oat_test.cc168
1 files changed, 168 insertions, 0 deletions
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
new file mode 100644
index 000000000..74b5da9ef
--- /dev/null
+++ b/compiler/oat_test.cc
@@ -0,0 +1,168 @@
+/*
+ * 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/art_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::ArtMethod* 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
+ InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86;
+ compiler_driver_.reset(new CompilerDriver(compiler_backend, insn_set, false, NULL, 2, true));
+ jobject class_loader = NULL;
+ if (compile) {
+ base::TimingLogger timings("OatTest::WriteRead", false, false);
+ compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), timings);
+ }
+
+ ScopedObjectAccess soa(Thread::Current());
+ ScratchFile tmp;
+ OatWriter oat_writer(class_linker->GetBootClassPath(),
+ 42U,
+ 4096U,
+ "lue.art",
+ compiler_driver_.get());
+ bool success = compiler_driver_->WriteElf(GetTestAndroidRoot(),
+ !kIsTargetBuild,
+ class_linker->GetBootClassPath(),
+ oat_writer,
+ tmp.GetFile());
+ ASSERT_TRUE(success);
+
+ if (compile) { // OatWriter strips the code, regenerate to compare
+ base::TimingLogger timings("CommonTest::WriteRead", false, false);
+ compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), timings);
+ }
+ UniquePtr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), tmp.GetFilename(), NULL, false));
+ 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(64U, 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