summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/common_compiler_test.cc20
-rw-r--r--compiler/common_compiler_test.h2
-rw-r--r--compiler/optimizing/scheduler.cc31
-rw-r--r--compiler/optimizing/scheduler_test.cc18
-rw-r--r--compiler/utils/swap_space.cc1
5 files changed, 55 insertions, 17 deletions
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 87197becf9..2f017662e2 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -221,7 +221,7 @@ void CommonCompilerTest::TearDown() {
callbacks_.reset();
verification_results_.reset();
compiler_options_.reset();
- image_reservation_.reset();
+ image_reservation_.Reset();
CommonRuntimeTest::TearDown();
}
@@ -323,18 +323,18 @@ void CommonCompilerTest::ReserveImageSpace() {
// accidentally end up colliding with the fixed memory address when we need to load the image.
std::string error_msg;
MemMap::Init();
- image_reservation_.reset(MemMap::MapAnonymous("image reservation",
- reinterpret_cast<uint8_t*>(ART_BASE_ADDRESS),
- (size_t)120 * 1024 * 1024, // 120MB
- PROT_NONE,
- false /* no need for 4gb flag with fixed mmap*/,
- false /* not reusing existing reservation */,
- &error_msg));
- CHECK(image_reservation_.get() != nullptr) << error_msg;
+ image_reservation_ = MemMap::MapAnonymous("image reservation",
+ reinterpret_cast<uint8_t*>(ART_BASE_ADDRESS),
+ (size_t)120 * 1024 * 1024, // 120MB
+ PROT_NONE,
+ false /* no need for 4gb flag with fixed mmap */,
+ false /* not reusing existing reservation */,
+ &error_msg);
+ CHECK(image_reservation_.IsValid()) << error_msg;
}
void CommonCompilerTest::UnreserveImageSpace() {
- image_reservation_.reset();
+ image_reservation_.Reset();
}
void CommonCompilerTest::SetDexFilesForOatFile(const std::vector<const DexFile*>& dex_files) {
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index db38110400..366489c58f 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -115,7 +115,7 @@ class CommonCompilerTest : public CommonRuntimeTest {
std::unique_ptr<CompilerDriver> compiler_driver_;
private:
- std::unique_ptr<MemMap> image_reservation_;
+ MemMap image_reservation_;
// Chunks must not move their storage after being created - use the node-based std::list.
std::list<std::vector<uint8_t>> header_code_and_maps_chunks_;
diff --git a/compiler/optimizing/scheduler.cc b/compiler/optimizing/scheduler.cc
index 1aa16f45bc..df897a4904 100644
--- a/compiler/optimizing/scheduler.cc
+++ b/compiler/optimizing/scheduler.cc
@@ -280,6 +280,23 @@ bool SchedulingGraph::HasSideEffectDependency(HInstruction* node,
return false;
}
+// Check if the specified instruction is a better candidate which more likely will
+// have other instructions depending on it.
+static bool IsBetterCandidateWithMoreLikelyDependencies(HInstruction* new_candidate,
+ HInstruction* old_candidate) {
+ if (!new_candidate->GetSideEffects().Includes(old_candidate->GetSideEffects())) {
+ // Weaker side effects.
+ return false;
+ }
+ if (old_candidate->GetSideEffects().Includes(new_candidate->GetSideEffects())) {
+ // Same side effects, check if `new_candidate` has stronger `CanThrow()`.
+ return new_candidate->CanThrow() && !old_candidate->CanThrow();
+ } else {
+ // Stronger side effects, check if `new_candidate` has at least as strong `CanThrow()`.
+ return new_candidate->CanThrow() || !old_candidate->CanThrow();
+ }
+}
+
void SchedulingGraph::AddDependencies(HInstruction* instruction, bool is_scheduling_barrier) {
SchedulingNode* instruction_node = GetNode(instruction);
@@ -331,6 +348,7 @@ void SchedulingGraph::AddDependencies(HInstruction* instruction, bool is_schedul
// Side effect dependencies.
if (!instruction->GetSideEffects().DoesNothing() || instruction->CanThrow()) {
+ HInstruction* dep_chain_candidate = nullptr;
for (HInstruction* other = instruction->GetNext(); other != nullptr; other = other->GetNext()) {
SchedulingNode* other_node = GetNode(other);
if (other_node->IsSchedulingBarrier()) {
@@ -340,7 +358,18 @@ void SchedulingGraph::AddDependencies(HInstruction* instruction, bool is_schedul
break;
}
if (HasSideEffectDependency(other, instruction)) {
- AddOtherDependency(other_node, instruction_node);
+ if (dep_chain_candidate != nullptr &&
+ HasSideEffectDependency(other, dep_chain_candidate)) {
+ // Skip an explicit dependency to reduce memory usage, rely on the transitive dependency.
+ } else {
+ AddOtherDependency(other_node, instruction_node);
+ }
+ // Check if `other` is a better candidate which more likely will have other instructions
+ // depending on it.
+ if (dep_chain_candidate == nullptr ||
+ IsBetterCandidateWithMoreLikelyDependencies(other, dep_chain_candidate)) {
+ dep_chain_candidate = other;
+ }
}
}
}
diff --git a/compiler/optimizing/scheduler_test.cc b/compiler/optimizing/scheduler_test.cc
index fe23fb4cff..981fcc42a7 100644
--- a/compiler/optimizing/scheduler_test.cc
+++ b/compiler/optimizing/scheduler_test.cc
@@ -171,7 +171,9 @@ class SchedulerTest : public OptimizingUnitTest {
ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(array_set1, array_get1));
ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(array_set2, array_get2));
ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(array_get2, array_set1));
- ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(array_set2, array_set1));
+ // Unnecessary dependency is not stored, we rely on transitive dependencies.
+ // The array_set2 -> array_get2 -> array_set1 dependencies are tested above.
+ ASSERT_FALSE(scheduling_graph.HasImmediateOtherDependency(array_set2, array_set1));
// Env dependency.
ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(div_check, mul));
@@ -308,7 +310,9 @@ class SchedulerTest : public OptimizingUnitTest {
loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_j);
ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
- ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_j, arr_set_i));
+ // Unnecessary dependency is not stored, we rely on transitive dependencies.
+ // The arr_set_j -> arr_set_sub0 -> arr_set_add0 -> arr_set_i dependencies are tested below.
+ ASSERT_FALSE(scheduling_graph.HasImmediateOtherDependency(arr_set_j, arr_set_i));
// Test side effect dependency based on LSA analysis: array[i] and array[i+0]
loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
@@ -320,7 +324,10 @@ class SchedulerTest : public OptimizingUnitTest {
loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_sub0);
ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
- ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_sub0, arr_set_i));
+ // Unnecessary dependency is not stored, we rely on transitive dependencies.
+ ASSERT_FALSE(scheduling_graph.HasImmediateOtherDependency(arr_set_sub0, arr_set_i));
+ // Instead, we rely on arr_set_sub0 -> arr_set_add0 -> arr_set_i, the latter is tested above.
+ ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_sub0, arr_set_add0));
// Test side effect dependency based on LSA analysis: array[i] and array[i+1]
loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
@@ -335,11 +342,12 @@ class SchedulerTest : public OptimizingUnitTest {
ASSERT_FALSE(scheduling_graph.HasImmediateOtherDependency(arr_set_sub1, arr_set_add1));
// Test side effect dependency based on LSA analysis: array[j] and all others array accesses
- ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_j, arr_set_i));
- ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_j, arr_set_add0));
ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_j, arr_set_sub0));
ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_j, arr_set_add1));
ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_j, arr_set_sub1));
+ // Unnecessary dependencies are not stored, we rely on transitive dependencies.
+ ASSERT_FALSE(scheduling_graph.HasImmediateOtherDependency(arr_set_j, arr_set_i));
+ ASSERT_FALSE(scheduling_graph.HasImmediateOtherDependency(arr_set_j, arr_set_add0));
// Test that ArraySet and FieldSet should not have side effect dependency
ASSERT_FALSE(scheduling_graph.HasImmediateOtherDependency(arr_set_i, set_field10));
diff --git a/compiler/utils/swap_space.cc b/compiler/utils/swap_space.cc
index 1f9ad4242d..dee83d1c71 100644
--- a/compiler/utils/swap_space.cc
+++ b/compiler/utils/swap_space.cc
@@ -141,6 +141,7 @@ void* SwapSpace::Alloc(size_t size) {
it->size -= size;
} else {
// Changing in place would break the std::set<> ordering, we need to remove and insert.
+ // TODO: When C++17 becomes available, use std::map<>::extract(), modify, insert.
free_by_size_.erase(it);
free_by_size_.insert(new_value);
}