summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/common_compiler_test.cc16
-rw-r--r--compiler/common_compiler_test.h8
-rw-r--r--compiler/driver/compiled_method_storage_test.cc2
-rw-r--r--compiler/driver/compiler_driver.cc14
-rw-r--r--compiler/driver/compiler_driver.h11
-rw-r--r--compiler/driver/compiler_driver_test.cc53
-rw-r--r--compiler/jit/jit_compiler.cc2
-rw-r--r--dex2oat/dex2oat.cc74
-rw-r--r--dex2oat/dex2oat_image_test.cc43
-rw-r--r--dex2oat/dex2oat_options.cc14
-rw-r--r--dex2oat/dex2oat_options.def4
-rw-r--r--dex2oat/linker/oat_writer_test.cc2
-rw-r--r--dex2oat/linker/relative_patcher_test.h2
-rw-r--r--runtime/gc/space/region_space.cc67
-rw-r--r--runtime/gc/space/region_space.h5
-rwxr-xr-xtools/bisection_search/bisection_search.py4
16 files changed, 77 insertions, 244 deletions
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index d3e3a51f7a..96a0c1be4d 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -138,20 +138,6 @@ std::unordered_set<std::string>* CommonCompilerTest::GetImageClasses() {
return new std::unordered_set<std::string>();
}
-// Get the set of compiled classes given to the compiler-driver in SetUp. Note: the compiler
-// driver assumes ownership of the set, so the test should properly release the set.
-std::unordered_set<std::string>* CommonCompilerTest::GetCompiledClasses() {
- // Null, no selection of compiled-classes.
- return nullptr;
-}
-
-// Get the set of compiled methods given to the compiler-driver in SetUp. Note: the compiler
-// driver assumes ownership of the set, so the test should properly release the set.
-std::unordered_set<std::string>* CommonCompilerTest::GetCompiledMethods() {
- // Null, no selection of compiled-methods.
- return nullptr;
-}
-
// Get ProfileCompilationInfo that should be passed to the driver.
ProfileCompilationInfo* CommonCompilerTest::GetProfileCompilationInfo() {
// Null, profile information will not be taken into account.
@@ -190,8 +176,6 @@ void CommonCompilerTest::CreateCompilerDriver(Compiler::Kind kind,
isa,
instruction_set_features_.get(),
GetImageClasses(),
- GetCompiledClasses(),
- GetCompiledMethods(),
number_of_threads,
/* swap_fd */ -1,
GetProfileCompilationInfo()));
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 8af29d44f0..39c8bd817b 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -67,14 +67,6 @@ class CommonCompilerTest : public CommonRuntimeTest {
// driver assumes ownership of the set, so the test should properly release the set.
virtual std::unordered_set<std::string>* GetImageClasses();
- // Get the set of compiled classes given to the compiler-driver in SetUp. Note: the compiler
- // driver assumes ownership of the set, so the test should properly release the set.
- virtual std::unordered_set<std::string>* GetCompiledClasses();
-
- // Get the set of compiled methods given to the compiler-driver in SetUp. Note: the compiler
- // driver assumes ownership of the set, so the test should properly release the set.
- virtual std::unordered_set<std::string>* GetCompiledMethods();
-
virtual ProfileCompilationInfo* GetProfileCompilationInfo();
virtual CompilerFilter::Filter GetCompilerFilter() const {
diff --git a/compiler/driver/compiled_method_storage_test.cc b/compiler/driver/compiled_method_storage_test.cc
index 0769561d0e..42fbba5109 100644
--- a/compiler/driver/compiled_method_storage_test.cc
+++ b/compiler/driver/compiled_method_storage_test.cc
@@ -34,8 +34,6 @@ TEST(CompiledMethodStorage, Deduplicate) {
/* instruction_set_ */ InstructionSet::kNone,
/* instruction_set_features */ nullptr,
/* image_classes */ nullptr,
- /* compiled_classes */ nullptr,
- /* compiled_methods */ nullptr,
/* thread_count */ 1u,
/* swap_fd */ -1,
/* profile_compilation_info */ nullptr);
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 4093833e0b..41b7e7be47 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -264,8 +264,6 @@ CompilerDriver::CompilerDriver(
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features,
std::unordered_set<std::string>* image_classes,
- std::unordered_set<std::string>* compiled_classes,
- std::unordered_set<std::string>* compiled_methods,
size_t thread_count,
int swap_fd,
const ProfileCompilationInfo* profile_compilation_info)
@@ -279,8 +277,6 @@ CompilerDriver::CompilerDriver(
requires_constructor_barrier_lock_("constructor barrier lock"),
non_relative_linker_patch_count_(0u),
image_classes_(image_classes),
- classes_to_compile_(compiled_classes),
- methods_to_compile_(compiled_methods),
number_of_soft_verifier_failures_(0),
had_hard_verifier_failure_(false),
parallel_thread_count_(thread_count),
@@ -638,7 +634,6 @@ static void CompileMethodQuick(
(verified_method->GetEncounteredVerificationFailures() &
(verifier::VERIFY_ERROR_FORCE_INTERPRETER | verifier::VERIFY_ERROR_LOCKING)) == 0 &&
// Is eligable for compilation by methods-to-compile filter.
- driver->IsMethodToCompile(method_ref) &&
driver->ShouldCompileBasedOnProfile(method_ref);
if (compile) {
@@ -1065,15 +1060,6 @@ bool CompilerDriver::IsClassToCompile(const char* descriptor) const {
return classes_to_compile_->find(descriptor) != classes_to_compile_->end();
}
-bool CompilerDriver::IsMethodToCompile(const MethodReference& method_ref) const {
- if (methods_to_compile_ == nullptr) {
- return true;
- }
-
- std::string tmp = method_ref.PrettyMethod();
- return methods_to_compile_->find(tmp.c_str()) != methods_to_compile_->end();
-}
-
bool CompilerDriver::ShouldCompileBasedOnProfile(const MethodReference& method_ref) const {
// Profile compilation info may be null if no profile is passed.
if (!CompilerFilter::DependsOnProfile(compiler_options_->GetCompilerFilter())) {
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index a5462eefe2..55f3561e3a 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -100,8 +100,6 @@ class CompilerDriver {
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features,
std::unordered_set<std::string>* image_classes,
- std::unordered_set<std::string>* compiled_classes,
- std::unordered_set<std::string>* compiled_methods,
size_t thread_count,
int swap_fd,
const ProfileCompilationInfo* profile_compilation_info);
@@ -316,9 +314,6 @@ class CompilerDriver {
// Checks whether the provided class should be compiled, i.e., is in classes_to_compile_.
bool IsClassToCompile(const char* descriptor) const;
- // Checks whether the provided method should be compiled, i.e., is in method_to_compile_.
- bool IsMethodToCompile(const MethodReference& method_ref) const;
-
// Checks whether profile guided compilation is enabled and if the method should be compiled
// according to the profile file.
bool ShouldCompileBasedOnProfile(const MethodReference& method_ref) const;
@@ -505,12 +500,8 @@ class CompilerDriver {
// This option may be restricted to the boot image, depending on a flag in the implementation.
std::unique_ptr<std::unordered_set<std::string>> classes_to_compile_;
- // Specifies the methods that will be compiled. Note that if methods_to_compile_ is null,
- // all methods are eligible for compilation (compilation filters etc. will still apply).
- // This option may be restricted to the boot image, depending on a flag in the implementation.
- std::unique_ptr<std::unordered_set<std::string>> methods_to_compile_;
-
std::atomic<uint32_t> number_of_soft_verifier_failures_;
+
bool had_hard_verifier_failure_;
// A thread pool that can (potentially) run tasks in parallel.
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 162904c0e7..1332280d20 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -184,59 +184,6 @@ TEST_F(CompilerDriverTest, AbstractMethodErrorStub) {
}
}
-class CompilerDriverMethodsTest : public CompilerDriverTest {
- protected:
- std::unordered_set<std::string>* GetCompiledMethods() OVERRIDE {
- return new std::unordered_set<std::string>({
- "byte StaticLeafMethods.identity(byte)",
- "int StaticLeafMethods.sum(int, int, int)",
- "double StaticLeafMethods.sum(double, double, double, double)"
- });
- }
-};
-
-TEST_F(CompilerDriverMethodsTest, Selection) {
- Thread* self = Thread::Current();
- jobject class_loader;
- {
- ScopedObjectAccess soa(self);
- class_loader = LoadDex("StaticLeafMethods");
- }
- ASSERT_NE(class_loader, nullptr);
-
- // Need to enable dex-file writability. Methods rejected to be compiled will run through the
- // dex-to-dex compiler.
- for (const DexFile* dex_file : GetDexFiles(class_loader)) {
- ASSERT_TRUE(dex_file->EnableWrite());
- }
-
- CompileAll(class_loader);
-
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ScopedObjectAccess soa(self);
- StackHandleScope<1> hs(self);
- Handle<mirror::ClassLoader> h_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
- mirror::Class* klass = class_linker->FindClass(self, "LStaticLeafMethods;", h_loader);
- ASSERT_NE(klass, nullptr);
-
- std::unique_ptr<std::unordered_set<std::string>> expected(GetCompiledMethods());
-
- const auto pointer_size = class_linker->GetImagePointerSize();
- for (auto& m : klass->GetDirectMethods(pointer_size)) {
- std::string name = m.PrettyMethod(true);
- const void* code = m.GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
- ASSERT_NE(code, nullptr);
- if (expected->find(name) != expected->end()) {
- expected->erase(name);
- EXPECT_FALSE(class_linker->IsQuickToInterpreterBridge(code));
- } else {
- EXPECT_TRUE(class_linker->IsQuickToInterpreterBridge(code));
- }
- }
- EXPECT_TRUE(expected->empty());
-}
-
class CompilerDriverProfileTest : public CompilerDriverTest {
protected:
ProfileCompilationInfo* GetProfileCompilationInfo() OVERRIDE {
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index ac5c6fb01f..0de00a82fa 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -142,8 +142,6 @@ JitCompiler::JitCompiler() {
instruction_set,
instruction_set_features_.get(),
/* image_classes */ nullptr,
- /* compiled_classes */ nullptr,
- /* compiled_methods */ nullptr,
/* thread_count */ 1,
/* swap_fd */ -1,
/* profile_compilation_info */ nullptr));
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 2b4604e6ef..741bc64c96 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -629,10 +629,6 @@ class Dex2Oat FINAL {
image_classes_zip_filename_(nullptr),
image_classes_filename_(nullptr),
image_storage_mode_(ImageHeader::kStorageModeUncompressed),
- compiled_classes_zip_filename_(nullptr),
- compiled_classes_filename_(nullptr),
- compiled_methods_zip_filename_(nullptr),
- compiled_methods_filename_(nullptr),
passes_to_run_filename_(nullptr),
dirty_image_objects_filename_(nullptr),
multi_image_(false),
@@ -818,18 +814,6 @@ class Dex2Oat FINAL {
Usage("--image-classes-zip should be used with --image-classes");
}
- if (compiled_classes_filename_ != nullptr && !IsBootImage()) {
- Usage("--compiled-classes should only be used with --image");
- }
-
- if (compiled_classes_filename_ != nullptr && !boot_image_filename_.empty()) {
- Usage("--compiled-classes should not be used with --boot-image");
- }
-
- if (compiled_classes_zip_filename_ != nullptr && compiled_classes_filename_ == nullptr) {
- Usage("--compiled-classes-zip should be used with --compiled-classes");
- }
-
if (dex_filenames_.empty() && zip_fd_ == -1) {
Usage("Input must be supplied with either --dex-file or --zip-fd");
}
@@ -873,9 +857,7 @@ class Dex2Oat FINAL {
}
if (have_profile_file || have_profile_fd) {
- if (compiled_classes_filename_ != nullptr ||
- compiled_classes_zip_filename_ != nullptr ||
- image_classes_filename_ != nullptr ||
+ if (image_classes_filename_ != nullptr ||
image_classes_zip_filename_ != nullptr) {
Usage("Profile based image creation is not supported with image or compiled classes");
}
@@ -1210,10 +1192,6 @@ class Dex2Oat FINAL {
AssignIfExists(args, M::Threads, &thread_count_);
AssignIfExists(args, M::ImageClasses, &image_classes_filename_);
AssignIfExists(args, M::ImageClassesZip, &image_classes_zip_filename_);
- AssignIfExists(args, M::CompiledClasses, &compiled_classes_filename_);
- AssignIfExists(args, M::CompiledClassesZip, &compiled_classes_zip_filename_);
- AssignIfExists(args, M::CompiledMethods, &compiled_methods_filename_);
- AssignIfExists(args, M::CompiledMethodsZip, &compiled_methods_zip_filename_);
AssignIfExists(args, M::Passes, &passes_to_run_filename_);
AssignIfExists(args, M::BootImage, &parser_options->boot_image_filename);
AssignIfExists(args, M::AndroidRoot, &android_root_);
@@ -1535,8 +1513,7 @@ class Dex2Oat FINAL {
dex2oat::ReturnCode Setup() {
TimingLogger::ScopedTiming t("dex2oat Setup", timings_);
- if (!PrepareImageClasses() || !PrepareCompiledClasses() || !PrepareCompiledMethods() ||
- !PrepareDirtyObjects()) {
+ if (!PrepareImageClasses() || !PrepareDirtyObjects()) {
return dex2oat::ReturnCode::kOther;
}
@@ -1875,8 +1852,6 @@ class Dex2Oat FINAL {
instruction_set_,
instruction_set_features_.get(),
image_classes_.release(),
- compiled_classes_.release(),
- compiled_methods_.release(),
thread_count_,
swap_fd_,
profile_compilation_info_.get()));
@@ -2421,21 +2396,6 @@ class Dex2Oat FINAL {
return true;
}
- bool PrepareCompiledClasses() {
- // If --compiled-classes was specified, calculate the full list of classes to compile in the
- // image.
- if (compiled_classes_filename_ != nullptr) {
- compiled_classes_ =
- ReadClasses(compiled_classes_zip_filename_, compiled_classes_filename_, "compiled");
- if (compiled_classes_ == nullptr) {
- return false;
- }
- } else {
- compiled_classes_.reset(nullptr); // By default compile everything.
- }
- return true;
- }
-
static std::unique_ptr<std::unordered_set<std::string>> ReadClasses(const char* zip_filename,
const char* classes_filename,
const char* tag) {
@@ -2453,32 +2413,6 @@ class Dex2Oat FINAL {
return classes;
}
- bool PrepareCompiledMethods() {
- // If --compiled-methods was specified, read the methods to compile from the given file(s).
- if (compiled_methods_filename_ != nullptr) {
- std::string error_msg;
- if (compiled_methods_zip_filename_ != nullptr) {
- compiled_methods_.reset(ReadCommentedInputFromZip<std::unordered_set<std::string>>(
- compiled_methods_zip_filename_,
- compiled_methods_filename_,
- nullptr, // No post-processing.
- &error_msg));
- } else {
- compiled_methods_.reset(ReadCommentedInputFromFile<std::unordered_set<std::string>>(
- compiled_methods_filename_,
- nullptr)); // No post-processing.
- }
- if (compiled_methods_.get() == nullptr) {
- LOG(ERROR) << "Failed to create list of compiled methods from '"
- << compiled_methods_filename_ << "': " << error_msg;
- return false;
- }
- } else {
- compiled_methods_.reset(nullptr); // By default compile everything.
- }
- return true;
- }
-
bool PrepareDirtyObjects() {
if (dirty_image_objects_filename_ != nullptr) {
dirty_image_objects_.reset(ReadCommentedInputFromFile<std::unordered_set<std::string>>(
@@ -2919,10 +2853,6 @@ class Dex2Oat FINAL {
const char* image_classes_zip_filename_;
const char* image_classes_filename_;
ImageHeader::StorageMode image_storage_mode_;
- const char* compiled_classes_zip_filename_;
- const char* compiled_classes_filename_;
- const char* compiled_methods_zip_filename_;
- const char* compiled_methods_filename_;
const char* passes_to_run_filename_;
const char* dirty_image_objects_filename_;
std::unique_ptr<std::unordered_set<std::string>> image_classes_;
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index 6f1224916f..11c0c95060 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -239,9 +239,7 @@ TEST_F(Dex2oatImageTest, TestModesAndFilters) {
ImageSizes base_sizes = CompileImageAndGetSizes({});
ImageSizes image_classes_sizes;
ImageSizes compiled_classes_sizes;
- ImageSizes compiled_all_classes_sizes;
ImageSizes compiled_methods_sizes;
- ImageSizes compiled_all_methods_sizes;
ImageSizes profile_sizes;
std::cout << "Base compile sizes " << base_sizes << std::endl;
// Test image classes
@@ -257,65 +255,28 @@ TEST_F(Dex2oatImageTest, TestModesAndFilters) {
// Sanity check that dex is the same size.
EXPECT_EQ(image_classes_sizes.vdex_size, base_sizes.vdex_size);
}
- // Test compiled classes with all the classes.
- {
- ScratchFile classes;
- // Only compile every even class.
- GenerateClasses(classes.GetFile(), /*frequency*/ 1u);
- compiled_all_classes_sizes = CompileImageAndGetSizes(
- {"--compiled-classes=" + classes.GetFilename()});
- classes.Close();
- std::cout << "Compiled all classes sizes " << compiled_all_classes_sizes << std::endl;
- // Check that oat size is smaller since we didn't compile everything.
- EXPECT_EQ(compiled_all_classes_sizes.art_size, base_sizes.art_size);
- // TODO(mathieuc): Find a reliable way to check compiled code.
- // EXPECT_EQ(compiled_all_classes_sizes.oat_size, base_sizes.oat_size);
- EXPECT_EQ(compiled_all_classes_sizes.vdex_size, base_sizes.vdex_size);
- }
// Test compiled classes.
{
ScratchFile classes;
// Only compile every even class.
GenerateClasses(classes.GetFile(), /*frequency*/ 2u);
compiled_classes_sizes = CompileImageAndGetSizes(
- {"--image-classes=" + classes.GetFilename(),
- "--compiled-classes=" + classes.GetFilename()});
+ {"--image-classes=" + classes.GetFilename()});
classes.Close();
std::cout << "Compiled classes sizes " << compiled_classes_sizes << std::endl;
- // Check that oat size is smaller since we didn't compile everything.
- // TODO(mathieuc): Find a reliable way to check compiled code.
- // EXPECT_LT(compiled_classes_sizes.oat_size, base_sizes.oat_size);
// Art file should be smaller than image classes version since we included fewer classes in the
// list.
EXPECT_LT(compiled_classes_sizes.art_size, image_classes_sizes.art_size);
}
- // Test compiled methods.
- {
- ScratchFile methods;
- // Only compile every even class.
- GenerateMethods(methods.GetFile(), /*frequency*/ 1u);
- compiled_all_methods_sizes = CompileImageAndGetSizes(
- {"--compiled-methods=" + methods.GetFilename()});
- methods.Close();
- std::cout << "Compiled all methods sizes " << compiled_all_methods_sizes << std::endl;
- EXPECT_EQ(compiled_all_classes_sizes.art_size, base_sizes.art_size);
- // TODO(mathieuc): Find a reliable way to check compiled code. b/63746626
- // EXPECT_EQ(compiled_all_classes_sizes.oat_size, base_sizes.oat_size);
- EXPECT_EQ(compiled_all_classes_sizes.vdex_size, base_sizes.vdex_size);
- }
static size_t kMethodFrequency = 3;
static size_t kTypeFrequency = 4;
// Test compiling fewer methods and classes.
{
- ScratchFile methods;
ScratchFile classes;
// Only compile every even class.
- GenerateMethods(methods.GetFile(), kMethodFrequency);
GenerateClasses(classes.GetFile(), kTypeFrequency);
compiled_methods_sizes = CompileImageAndGetSizes(
- {"--image-classes=" + classes.GetFilename(),
- "--compiled-methods=" + methods.GetFilename()});
- methods.Close();
+ {"--image-classes=" + classes.GetFilename()});
classes.Close();
std::cout << "Compiled fewer methods sizes " << compiled_methods_sizes << std::endl;
}
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index 5843691a24..dbb00c22e9 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -157,19 +157,7 @@ static void AddSwapMappings(Builder& builder) {
static void AddCompilerMappings(Builder& builder) {
builder.
- Define("--compiled-classes=_")
- .WithType<std::string>()
- .IntoKey(M::CompiledClasses)
- .Define("--compiled-classes-zip=_")
- .WithType<std::string>()
- .IntoKey(M::CompiledClassesZip)
- .Define("--compiled-methods=_")
- .WithType<std::string>()
- .IntoKey(M::CompiledMethods)
- .Define("--compiled-methods-zip=_")
- .WithType<std::string>()
- .IntoKey(M::CompiledMethodsZip)
- .Define("--run-passes=_")
+ Define("--run-passes=_")
.WithType<std::string>()
.IntoKey(M::Passes)
.Define("--profile-file=_")
diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def
index 1a913a9bbf..7be8e56501 100644
--- a/dex2oat/dex2oat_options.def
+++ b/dex2oat/dex2oat_options.def
@@ -56,10 +56,6 @@ DEX2OAT_OPTIONS_KEY (std::vector<std::string>, ImageFilenames)
DEX2OAT_OPTIONS_KEY (std::string, ImageClasses)
DEX2OAT_OPTIONS_KEY (std::string, ImageClassesZip)
DEX2OAT_OPTIONS_KEY (ImageHeader::StorageMode, ImageFormat)
-DEX2OAT_OPTIONS_KEY (std::string, CompiledClasses)
-DEX2OAT_OPTIONS_KEY (std::string, CompiledClassesZip)
-DEX2OAT_OPTIONS_KEY (std::string, CompiledMethods)
-DEX2OAT_OPTIONS_KEY (std::string, CompiledMethodsZip)
DEX2OAT_OPTIONS_KEY (std::string, Passes)
DEX2OAT_OPTIONS_KEY (std::string, Base) // TODO: Hex string parsing.
DEX2OAT_OPTIONS_KEY (std::string, BootImage)
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index ea4e210b74..37e69f7706 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -110,8 +110,6 @@ class OatTest : public CommonCompilerTest {
insn_set,
insn_features_.get(),
/* image_classes */ nullptr,
- /* compiled_classes */ nullptr,
- /* compiled_methods */ nullptr,
/* thread_count */ 2,
/* swap_fd */ -1,
/* profile_compilation_info */ nullptr));
diff --git a/dex2oat/linker/relative_patcher_test.h b/dex2oat/linker/relative_patcher_test.h
index 3f7c8556c2..9cd51e9b46 100644
--- a/dex2oat/linker/relative_patcher_test.h
+++ b/dex2oat/linker/relative_patcher_test.h
@@ -49,8 +49,6 @@ class RelativePatcherTest : public testing::Test {
instruction_set,
/* instruction_set_features*/ nullptr,
/* image_classes */ nullptr,
- /* compiled_classes */ nullptr,
- /* compiled_methods */ nullptr,
/* thread_count */ 1u,
/* swap_fd */ -1,
/* profile_compilation_info */ nullptr),
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index 6a01c88c5d..74abe1c2ab 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -29,10 +29,19 @@ namespace space {
// value of the region size, evaculate the region.
static constexpr uint kEvacuateLivePercentThreshold = 75U;
-// If we protect the cleared regions.
+// Whether we protect the cleared regions.
// Only protect for target builds to prevent flaky test failures (b/63131961).
static constexpr bool kProtectClearedRegions = kIsTargetBuild;
+// Wether we poison memory areas occupied by dead objects in unevacuated regions.
+static constexpr bool kPoisonDeadObjectsInUnevacuatedRegions = kIsDebugBuild;
+
+// Special 32-bit value used to poison memory areas occupied by dead
+// objects in unevacuated regions. Dereferencing this value is expected
+// to trigger a memory protection fault, as it is unlikely that it
+// points to a valid, non-protected memory area.
+static constexpr uint32_t kPoisonDeadObject = 0xBADDB01D; // "BADDROID"
+
MemMap* RegionSpace::CreateMemMap(const std::string& name, size_t capacity,
uint8_t* requested_begin) {
CHECK_ALIGNED(capacity, kRegionSize);
@@ -370,6 +379,13 @@ void RegionSpace::ClearFromSpace(/* out */ uint64_t* cleared_bytes,
// as they are unevac regions that are live.
// Subtract one for the for-loop.
i += regions_to_clear_bitmap - 1;
+ } else {
+ // Only some allocated bytes are live in this unevac region.
+ // This should only happen for an allocated non-large region.
+ DCHECK(r->IsAllocated()) << r->State();
+ if (kPoisonDeadObjectsInUnevacuatedRegions) {
+ PoisonDeadObjectsInUnevacuatedRegion(r);
+ }
}
}
// Note r != last_checked_region if r->IsInUnevacFromSpace() was true above.
@@ -388,6 +404,55 @@ void RegionSpace::ClearFromSpace(/* out */ uint64_t* cleared_bytes,
num_evac_regions_ = 0;
}
+// Poison the memory area in range [`begin`, `end`) with value `kPoisonDeadObject`.
+static void PoisonUnevacuatedRange(uint8_t* begin, uint8_t* end) {
+ static constexpr size_t kPoisonDeadObjectSize = sizeof(kPoisonDeadObject);
+ static_assert(IsPowerOfTwo(kPoisonDeadObjectSize) &&
+ IsPowerOfTwo(RegionSpace::kAlignment) &&
+ (kPoisonDeadObjectSize < RegionSpace::kAlignment),
+ "RegionSpace::kAlignment should be a multiple of kPoisonDeadObjectSize"
+ " and both should be powers of 2");
+ DCHECK_ALIGNED(begin, kPoisonDeadObjectSize);
+ DCHECK_ALIGNED(end, kPoisonDeadObjectSize);
+ uint32_t* begin_addr = reinterpret_cast<uint32_t*>(begin);
+ uint32_t* end_addr = reinterpret_cast<uint32_t*>(end);
+ std::fill(begin_addr, end_addr, kPoisonDeadObject);
+}
+
+void RegionSpace::PoisonDeadObjectsInUnevacuatedRegion(Region* r) {
+ // The live byte count of `r` should be different from -1, as this
+ // region should neither be a newly allocated region nor an
+ // evacuated region.
+ DCHECK_NE(r->LiveBytes(), static_cast<size_t>(-1));
+
+ // Past-the-end address of the previously visited (live) object (or
+ // the beginning of the region, if `maybe_poison` has not run yet).
+ uint8_t* prev_obj_end = reinterpret_cast<uint8_t*>(r->Begin());
+
+ // Functor poisoning the space between `obj` and the previously
+ // visited (live) object (or the beginng of the region), if any.
+ auto maybe_poison = [this, &prev_obj_end](mirror::Object* obj) REQUIRES(Locks::mutator_lock_) {
+ DCHECK_ALIGNED(obj, kAlignment);
+ uint8_t* cur_obj_begin = reinterpret_cast<uint8_t*>(obj);
+ if (cur_obj_begin != prev_obj_end) {
+ // There is a gap (dead object(s)) between the previously
+ // visited (live) object (or the beginning of the region) and
+ // `obj`; poison that space.
+ PoisonUnevacuatedRange(prev_obj_end, cur_obj_begin);
+ }
+ prev_obj_end = reinterpret_cast<uint8_t*>(GetNextObject(obj));
+ };
+
+ // Visit live objects in `r` and poison gaps (dead objects) between them.
+ GetLiveBitmap()->VisitMarkedRange(reinterpret_cast<uintptr_t>(r->Begin()),
+ reinterpret_cast<uintptr_t>(r->Top()),
+ maybe_poison);
+ // Poison memory between the last live object and the end of the region, if any.
+ if (prev_obj_end < r->Top()) {
+ PoisonUnevacuatedRange(prev_obj_end, r->Top());
+ }
+}
+
void RegionSpace::LogFragmentationAllocFailure(std::ostream& os,
size_t /* failed_alloc_bytes */) {
size_t max_contiguous_allocation = 0;
diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h
index c7e18885db..ab18b1bcb9 100644
--- a/runtime/gc/space/region_space.h
+++ b/runtime/gc/space/region_space.h
@@ -595,6 +595,11 @@ class RegionSpace FINAL : public ContinuousMemMapAllocSpace {
/* out */ size_t* bytes_tl_bulk_allocated,
/* out */ size_t* next_region = nullptr) REQUIRES(region_lock_);
+ // Poison memory areas used by dead objects within unevacuated
+ // region `r`. This is meant to detect dangling references to dead
+ // objects earlier in debug mode.
+ void PoisonDeadObjectsInUnevacuatedRegion(Region* r);
+
Mutex region_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
uint32_t time_; // The time as the number of collections since the startup.
diff --git a/tools/bisection_search/bisection_search.py b/tools/bisection_search/bisection_search.py
index a1ac72df9f..250b5d178a 100755
--- a/tools/bisection_search/bisection_search.py
+++ b/tools/bisection_search/bisection_search.py
@@ -166,10 +166,6 @@ class Dex2OatWrapperTestable(object):
"""Prepare command to run."""
cmd = self._base_cmd[0:self._arguments_position]
# insert additional arguments before the first argument
- if compiled_methods is not None:
- self._test_env.WriteLines(self._compiled_methods_path, compiled_methods)
- cmd += ['-Xcompiler-option', '--compiled-methods={0}'.format(
- self._compiled_methods_path)]
if passes_to_run is not None:
self._test_env.WriteLines(self._passes_to_run_path, passes_to_run)
cmd += ['-Xcompiler-option', '--run-passes={0}'.format(