diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/common_compiler_test.cc | 20 | ||||
| -rw-r--r-- | compiler/common_compiler_test.h | 2 | ||||
| -rw-r--r-- | compiler/optimizing/scheduler.cc | 31 | ||||
| -rw-r--r-- | compiler/optimizing/scheduler_test.cc | 18 | ||||
| -rw-r--r-- | compiler/utils/swap_space.cc | 1 |
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); } |