summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.gtest.mk6
-rw-r--r--compiler/optimizing/code_generator_x86.cc8
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc57
-rw-r--r--oatdump/oatdump.cc25
-rw-r--r--oatdump/oatdump_test.cc7
-rw-r--r--oatdump/oatdump_test.h39
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: