summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
author Mingyao Yang <mingyao@google.com> 2016-04-15 17:30:05 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2016-04-15 17:30:05 +0000
commit05241f4edbf6960aac7c04b0b98d05f16a23962b (patch)
tree7b02580b8833e8411f061b6a162a58ecffd6ceaf /compiler/optimizing
parent6233bff5bd04bb6030929ed6f55e34dde09aa8f3 (diff)
parent062157f4e07b525728fa58f4ec57ffe1bf15d545 (diff)
Merge "Enable allocation elimination as part of LSE"
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/instruction_builder.cc8
-rw-r--r--compiler/optimizing/load_store_elimination.cc23
-rw-r--r--compiler/optimizing/nodes.h17
3 files changed, 25 insertions, 23 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index f5e49c2235..12cb826395 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -897,12 +897,12 @@ bool HInstructionBuilder::BuildNewInstance(uint16_t type_index, uint32_t dex_pc)
Handle<mirror::DexCache> outer_dex_cache = outer_compilation_unit_->GetDexCache();
bool finalizable;
- bool can_throw = NeedsAccessCheck(type_index, dex_cache, &finalizable);
+ bool needs_access_check = NeedsAccessCheck(type_index, dex_cache, &finalizable);
// Only the non-resolved entrypoint handles the finalizable class case. If we
// need access checks, then we haven't resolved the method and the class may
// again be finalizable.
- QuickEntrypointEnum entrypoint = (finalizable || can_throw)
+ QuickEntrypointEnum entrypoint = (finalizable || needs_access_check)
? kQuickAllocObject
: kQuickAllocObjectInitialized;
@@ -917,7 +917,7 @@ bool HInstructionBuilder::BuildNewInstance(uint16_t type_index, uint32_t dex_pc)
outer_dex_file,
IsOutermostCompilingClass(type_index),
dex_pc,
- /*needs_access_check*/ can_throw,
+ needs_access_check,
compiler_driver_->CanAssumeTypeIsPresentInDexCache(outer_dex_cache, type_index));
AppendInstruction(load_class);
@@ -933,7 +933,7 @@ bool HInstructionBuilder::BuildNewInstance(uint16_t type_index, uint32_t dex_pc)
dex_pc,
type_index,
*dex_compilation_unit_->GetDexFile(),
- can_throw,
+ needs_access_check,
finalizable,
entrypoint));
return true;
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index e1977b1798..ac7ed86d1d 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -480,7 +480,7 @@ class HeapLocationCollector : public HGraphVisitor {
// alias analysis and won't be as effective.
bool has_volatile_; // If there are volatile field accesses.
bool has_monitor_operations_; // If there are monitor operations.
- bool may_deoptimize_;
+ bool may_deoptimize_; // Only true for HDeoptimize with single-frame deoptimization.
DISALLOW_COPY_AND_ASSIGN(HeapLocationCollector);
};
@@ -551,19 +551,20 @@ class LSEVisitor : public HGraphVisitor {
}
// At this point, stores in possibly_removed_stores_ can be safely removed.
- size = possibly_removed_stores_.size();
- for (size_t i = 0; i < size; i++) {
+ for (size_t i = 0, e = possibly_removed_stores_.size(); i < e; i++) {
HInstruction* store = possibly_removed_stores_[i];
DCHECK(store->IsInstanceFieldSet() || store->IsStaticFieldSet() || store->IsArraySet());
store->GetBlock()->RemoveInstruction(store);
}
- // TODO: remove unnecessary allocations.
- // Eliminate instructions in singleton_new_instances_ that:
- // - don't have uses,
- // - don't have finalizers,
- // - are instantiable and accessible,
- // - have no/separate clinit check.
+ // Eliminate allocations that are not used.
+ for (size_t i = 0, e = singleton_new_instances_.size(); i < e; i++) {
+ HInstruction* new_instance = singleton_new_instances_[i];
+ if (!new_instance->HasNonEnvironmentUses()) {
+ new_instance->RemoveEnvironmentUsers();
+ new_instance->GetBlock()->RemoveInstruction(new_instance);
+ }
+ }
}
private:
@@ -969,8 +970,8 @@ class LSEVisitor : public HGraphVisitor {
if (!heap_location_collector_.MayDeoptimize() &&
ref_info->IsSingletonAndNotReturned() &&
!new_instance->IsFinalizable() &&
- !new_instance->CanThrow()) {
- // TODO: add new_instance to singleton_new_instances_ and enable allocation elimination.
+ !new_instance->NeedsAccessCheck()) {
+ singleton_new_instances_.push_back(new_instance);
}
ArenaVector<HInstruction*>& heap_values =
heap_values_for_[new_instance->GetBlock()->GetBlockId()];
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index dc5a8fa9cb..69f0b514f9 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -3652,14 +3652,14 @@ class HNewInstance : public HExpression<2> {
uint32_t dex_pc,
uint16_t type_index,
const DexFile& dex_file,
- bool can_throw,
+ bool needs_access_check,
bool finalizable,
QuickEntrypointEnum entrypoint)
: HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc),
type_index_(type_index),
dex_file_(dex_file),
entrypoint_(entrypoint) {
- SetPackedFlag<kFlagCanThrow>(can_throw);
+ SetPackedFlag<kFlagNeedsAccessCheck>(needs_access_check);
SetPackedFlag<kFlagFinalizable>(finalizable);
SetRawInputAt(0, cls);
SetRawInputAt(1, current_method);
@@ -3671,10 +3671,11 @@ class HNewInstance : public HExpression<2> {
// Calls runtime so needs an environment.
bool NeedsEnvironment() const OVERRIDE { return true; }
- // It may throw when called on type that's not instantiable/accessible.
- // It can throw OOME.
- // TODO: distinguish between the two cases so we can for example allow allocation elimination.
- bool CanThrow() const OVERRIDE { return GetPackedFlag<kFlagCanThrow>() || true; }
+ // Can throw errors when out-of-memory or if it's not instantiable/accessible.
+ bool CanThrow() const OVERRIDE { return true; }
+
+ // Needs to call into runtime to make sure it's instantiable/accessible.
+ bool NeedsAccessCheck() const { return GetPackedFlag<kFlagNeedsAccessCheck>(); }
bool IsFinalizable() const { return GetPackedFlag<kFlagFinalizable>(); }
@@ -3691,8 +3692,8 @@ class HNewInstance : public HExpression<2> {
DECLARE_INSTRUCTION(NewInstance);
private:
- static constexpr size_t kFlagCanThrow = kNumberOfExpressionPackedBits;
- static constexpr size_t kFlagFinalizable = kFlagCanThrow + 1;
+ static constexpr size_t kFlagNeedsAccessCheck = kNumberOfExpressionPackedBits;
+ static constexpr size_t kFlagFinalizable = kFlagNeedsAccessCheck + 1;
static constexpr size_t kNumberOfNewInstancePackedBits = kFlagFinalizable + 1;
static_assert(kNumberOfNewInstancePackedBits <= kMaxNumberOfPackedBits,
"Too many packed fields.");