diff options
| -rw-r--r-- | build/Android.gtest.mk | 6 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 8 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 57 | ||||
| -rw-r--r-- | oatdump/oatdump.cc | 25 | ||||
| -rw-r--r-- | oatdump/oatdump_test.cc | 7 | ||||
| -rw-r--r-- | oatdump/oatdump_test.h | 39 |
6 files changed, 84 insertions, 58 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index b342abe17c..b483e5f6f2 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -300,11 +300,13 @@ ART_GTEST_oatdump_test_HOST_DEPS := \ $(HOST_CORE_IMAGE_DEFAULT_64) \ $(HOST_CORE_IMAGE_DEFAULT_32) \ oatdumpd-host \ - oatdumpds-host + oatdumpds-host \ + dexdump2-host ART_GTEST_oatdump_test_TARGET_DEPS := \ $(TARGET_CORE_IMAGE_DEFAULT_64) \ $(TARGET_CORE_IMAGE_DEFAULT_32) \ - oatdumpd-target + oatdumpd-target \ + dexdump2-target ART_GTEST_oatdump_image_test_HOST_DEPS := $(ART_GTEST_oatdump_test_HOST_DEPS) ART_GTEST_oatdump_image_test_TARGET_DEPS := $(ART_GTEST_oatdump_test_TARGET_DEPS) ART_GTEST_oatdump_app_test_HOST_DEPS := $(ART_GTEST_oatdump_test_HOST_DEPS) \ diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 4053f557d9..82d1fda878 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -6755,8 +6755,8 @@ static size_t NumberOfInstanceOfTemps(TypeCheckKind type_check_kind) { return 0; } -// Interface case has 3 temps, one for holding the number of interfaces, one for the current -// interface pointer, one for loading the current interface. +// Interface case has 2 temps, one for holding the number of interfaces, one for the current +// interface pointer, the current interface is compared in memory. // The other checks have one temp for loading the object's class. static size_t NumberOfCheckCastTemps(TypeCheckKind type_check_kind) { if (type_check_kind == TypeCheckKind::kInterfaceCheck) { @@ -7069,9 +7069,7 @@ void LocationsBuilderX86::VisitCheckCast(HCheckCast* instruction) { } else { locations->SetInAt(1, Location::Any()); } - // Note that TypeCheckSlowPathX86 uses this "temp" register too. - locations->AddTemp(Location::RequiresRegister()); - // When read barriers are enabled, we need an additional temporary register for some cases. + // Add temps for read barriers and other uses. One is used by TypeCheckSlowPathX86. locations->AddRegisterTemps(NumberOfCheckCastTemps(type_check_kind)); } diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 496d79d6c8..322b0cfc4c 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -6063,24 +6063,26 @@ void InstructionCodeGeneratorX86_64::VisitThrow(HThrow* instruction) { CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>(); } -static bool CheckCastTypeCheckNeedsATemporary(TypeCheckKind type_check_kind) { - if (type_check_kind == TypeCheckKind::kInterfaceCheck) { - // We need a temporary for holding the iftable length. - return true; - } - return kEmitCompilerReadBarrier && +// Temp is used for read barrier. +static size_t NumberOfInstanceOfTemps(TypeCheckKind type_check_kind) { + if (kEmitCompilerReadBarrier && !kUseBakerReadBarrier && (type_check_kind == TypeCheckKind::kAbstractClassCheck || type_check_kind == TypeCheckKind::kClassHierarchyCheck || - type_check_kind == TypeCheckKind::kArrayObjectCheck); + type_check_kind == TypeCheckKind::kArrayObjectCheck)) { + return 1; + } + return 0; } -static bool InstanceOfTypeCheckNeedsATemporary(TypeCheckKind type_check_kind) { - return kEmitCompilerReadBarrier && - !kUseBakerReadBarrier && - (type_check_kind == TypeCheckKind::kAbstractClassCheck || - type_check_kind == TypeCheckKind::kClassHierarchyCheck || - type_check_kind == TypeCheckKind::kArrayObjectCheck); +// Interface case has 2 temps, one for holding the number of interfaces, one for the current +// interface pointer, the current interface is compared in memory. +// The other checks have one temp for loading the object's class. +static size_t NumberOfCheckCastTemps(TypeCheckKind type_check_kind) { + if (type_check_kind == TypeCheckKind::kInterfaceCheck) { + return 2; + } + return 1 + NumberOfInstanceOfTemps(type_check_kind); } void LocationsBuilderX86_64::VisitInstanceOf(HInstanceOf* instruction) { @@ -6121,11 +6123,7 @@ void LocationsBuilderX86_64::VisitInstanceOf(HInstanceOf* instruction) { } // Note that TypeCheckSlowPathX86_64 uses this "out" register too. locations->SetOut(Location::RequiresRegister()); - // When read barriers are enabled, we need a temporary register for - // some cases. - if (InstanceOfTypeCheckNeedsATemporary(type_check_kind)) { - locations->AddTemp(Location::RequiresRegister()); - } + locations->AddRegisterTemps(NumberOfInstanceOfTemps(type_check_kind)); } void InstructionCodeGeneratorX86_64::VisitInstanceOf(HInstanceOf* instruction) { @@ -6136,9 +6134,9 @@ void InstructionCodeGeneratorX86_64::VisitInstanceOf(HInstanceOf* instruction) { Location cls = locations->InAt(1); Location out_loc = locations->Out(); CpuRegister out = out_loc.AsRegister<CpuRegister>(); - Location maybe_temp_loc = InstanceOfTypeCheckNeedsATemporary(type_check_kind) ? - locations->GetTemp(0) : - Location::NoLocation(); + const size_t num_temps = NumberOfInstanceOfTemps(type_check_kind); + DCHECK_LE(num_temps, 1u); + Location maybe_temp_loc = (num_temps >= 1u) ? locations->GetTemp(0) : Location::NoLocation(); uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value(); uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value(); @@ -6401,14 +6399,8 @@ void LocationsBuilderX86_64::VisitCheckCast(HCheckCast* instruction) { } else { locations->SetInAt(1, Location::Any()); } - - // Note that TypeCheckSlowPathX86_64 uses this "temp" register too. - locations->AddTemp(Location::RequiresRegister()); - // When read barriers are enabled, we need an additional temporary - // register for some cases. - if (CheckCastTypeCheckNeedsATemporary(type_check_kind)) { - locations->AddTemp(Location::RequiresRegister()); - } + // Add temps for read barriers and other uses. One is used by TypeCheckSlowPathX86. + locations->AddRegisterTemps(NumberOfCheckCastTemps(type_check_kind)); } void InstructionCodeGeneratorX86_64::VisitCheckCast(HCheckCast* instruction) { @@ -6419,9 +6411,10 @@ void InstructionCodeGeneratorX86_64::VisitCheckCast(HCheckCast* instruction) { Location cls = locations->InAt(1); Location temp_loc = locations->GetTemp(0); CpuRegister temp = temp_loc.AsRegister<CpuRegister>(); - Location maybe_temp2_loc = CheckCastTypeCheckNeedsATemporary(type_check_kind) ? - locations->GetTemp(1) : - Location::NoLocation(); + const size_t num_temps = NumberOfCheckCastTemps(type_check_kind); + DCHECK_GE(num_temps, 1u); + DCHECK_LE(num_temps, 2u); + Location maybe_temp2_loc = (num_temps >= 2u) ? locations->GetTemp(1) : Location::NoLocation(); const uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); const uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value(); const uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value(); diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 433ed9aaee..3bff123386 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -1180,6 +1180,17 @@ class OatDumper { } } + // Update header for shared section. + uint32_t shared_section_offset = 0u; + uint32_t shared_section_size = 0u; + if (dex_file->IsCompactDexFile()) { + CompactDexFile::Header* const header = + reinterpret_cast<CompactDexFile::Header*>(const_cast<uint8_t*>(dex_file->Begin())); + shared_section_offset = header->data_off_; + shared_section_size = header->data_size_; + // The shared section will be serialized right after the dex file. + header->data_off_ = header->file_size_; + } // Verify output directory exists if (!OS::DirectoryExists(options_.export_dex_location_)) { // TODO: Extend OS::DirectoryExists if symlink support is required @@ -1226,16 +1237,22 @@ class OatDumper { return false; } - bool success = false; - success = file->WriteFully(dex_file->Begin(), fsize); - // } - + bool success = file->WriteFully(dex_file->Begin(), fsize); if (!success) { os << "Failed to write dex file"; file->Erase(); return false; } + if (shared_section_size != 0) { + success = file->WriteFully(dex_file->Begin() + shared_section_offset, shared_section_size); + if (!success) { + os << "Failed to write shared data section"; + file->Erase(); + return false; + } + } + if (file->FlushCloseOrErase() != 0) { os << "Flush and close failed"; return false; diff --git a/oatdump/oatdump_test.cc b/oatdump/oatdump_test.cc index 00344691e0..b4eddb91f9 100644 --- a/oatdump/oatdump_test.cc +++ b/oatdump/oatdump_test.cc @@ -72,9 +72,16 @@ TEST_F(OatDumpTest, TestSymbolizeStatic) { } TEST_F(OatDumpTest, TestExportDex) { + // Test is failing on target, b/77469384. + TEST_DISABLED_FOR_TARGET(); std::string error_msg; ASSERT_TRUE(Exec(kDynamic, kModeOat, {"--export-dex-to=" + tmp_dir_}, kListOnly, &error_msg)) << error_msg; + const std::string dex_location = tmp_dir_+ "/core-oj-hostdex.jar_export.dex"; + const std::string dexdump2 = GetExecutableFilePath("dexdump2", + /*is_debug*/false, + /*is_static*/false); + ASSERT_TRUE(ForkAndExecAndWait({dexdump2, "-d", dex_location}, &error_msg)) << error_msg; } TEST_F(OatDumpTest, TestExportDexStatic) { TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS(); diff --git a/oatdump/oatdump_test.h b/oatdump/oatdump_test.h index fac0bb234e..b85730d25e 100644 --- a/oatdump/oatdump_test.h +++ b/oatdump/oatdump_test.h @@ -70,20 +70,24 @@ class OatDumpTest : public CommonRuntimeTest { kStatic, // oatdump(d)s, dex2oat(d)s }; - // Returns path to the oatdump/dex2oat binary. - std::string GetExecutableFilePath(Flavor flavor, const char* name) { + // Returns path to the oatdump/dex2oat/dexdump binary. + std::string GetExecutableFilePath(const char* name, bool is_debug, bool is_static) { std::string root = GetTestAndroidRoot(); root += "/bin/"; root += name; - if (kIsDebugBuild) { + if (is_debug) { root += "d"; } - if (flavor == kStatic) { + if (is_static) { root += "s"; } return root; } + std::string GetExecutableFilePath(Flavor flavor, const char* name) { + return GetExecutableFilePath(name, kIsDebugBuild, flavor == kStatic); + } + enum Mode { kModeOat, kModeOatWithBootImage, @@ -127,17 +131,7 @@ class OatDumpTest : public CommonRuntimeTest { }; exec_argv.insert(exec_argv.end(), args.begin(), args.end()); - pid_t pid; - int pipe_fd; - bool result = ForkAndExec(exec_argv, &pid, &pipe_fd, error_msg); - if (result) { - close(pipe_fd); - int status = 0; - if (waitpid(pid, &status, 0) != -1) { - result = (status == 0); - } - } - return result; + return ForkAndExecAndWait(exec_argv, error_msg); } // Run the test with custom arguments. @@ -300,6 +294,21 @@ class OatDumpTest : public CommonRuntimeTest { } } + bool ForkAndExecAndWait(const std::vector<std::string>& exec_argv, + /*out*/ std::string* error_msg) { + pid_t pid; + int pipe_fd; + bool result = ForkAndExec(exec_argv, &pid, &pipe_fd, error_msg); + if (result) { + close(pipe_fd); + int status = 0; + if (waitpid(pid, &status, 0) != -1) { + result = (status == 0); + } + } + return result; + } + std::string tmp_dir_; private: |