diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2015-03-11 15:11:19 +0000 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2015-03-12 17:55:01 +0000 |
commit | 915b9d0c13bb5091875d868fbfa551d7b65d7477 (patch) | |
tree | 63822d7081b0da33ccda2019dd52025f0ecedb35 /compiler/optimizing | |
parent | bf5565a75876a84c8c2401df597d922a7870a8f2 (diff) | |
download | art-915b9d0c13bb5091875d868fbfa551d7b65d7477.tar.gz art-915b9d0c13bb5091875d868fbfa551d7b65d7477.tar.bz2 art-915b9d0c13bb5091875d868fbfa551d7b65d7477.zip |
Tweak liveness when instructions are used in environments.
Instructions remain live when debuggable, but only instructions
with object types remain live when non-debuggable.
Enable StackVisitor::GetThisObject for optimizing.
Change-Id: Id87b2cbf33a02450059acc9993995782e5f28987
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/code_generator.cc | 5 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/ssa_builder.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/ssa_liveness_analysis.cc | 5 | ||||
-rw-r--r-- | compiler/optimizing/ssa_liveness_analysis.h | 24 |
5 files changed, 35 insertions, 4 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index ed3f949af..38fb051f6 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -695,6 +695,11 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction, uint32_t dex_pc) { break; } + case Location::kInvalid: { + stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kNone, 0); + break; + } + default: LOG(FATAL) << "Unexpected kind " << location.GetKind(); } diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index d4498a6d4..55639d437 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -1104,6 +1104,7 @@ class HInstruction : public ArenaObject<kArenaAllocMisc> { bool HasUses() const { return !uses_.IsEmpty() || !env_uses_.IsEmpty(); } bool HasEnvironmentUses() const { return !env_uses_.IsEmpty(); } + bool HasNonEnvironmentUses() const { return !uses_.IsEmpty(); } // Does this instruction strictly dominate `other_instruction`? // Returns false if this instruction and `other_instruction` are the same. diff --git a/compiler/optimizing/ssa_builder.h b/compiler/optimizing/ssa_builder.h index b414fb294..24dc44951 100644 --- a/compiler/optimizing/ssa_builder.h +++ b/compiler/optimizing/ssa_builder.h @@ -33,7 +33,9 @@ static constexpr int kDefaultNumberOfLoops = 2; * * (a) Dex registers that do not require merging (that is, they do not * have different values at a join block) are available to all their - * environment uses. + * environment uses. Note that it does not imply the instruction will + * have a physical location after register allocation. See the + * SsaLivenessAnalysis phase. * * (b) Dex registers that require merging, and the merging gives * incompatible types, will be killed for environment uses of that merge. diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc index d009390a0..c0d6f42ca 100644 --- a/compiler/optimizing/ssa_liveness_analysis.cc +++ b/compiler/optimizing/ssa_liveness_analysis.cc @@ -230,11 +230,12 @@ void SsaLivenessAnalysis::ComputeLiveRanges() { } if (current->HasEnvironment()) { - // All instructions in the environment must be live. + // Handle environment uses. See statements (b) and (c) of the + // SsaLivenessAnalysis. HEnvironment* environment = current->GetEnvironment(); for (size_t i = 0, e = environment->Size(); i < e; ++i) { HInstruction* instruction = environment->GetInstructionAt(i); - if (instruction != nullptr) { + if (ShouldBeLiveForEnvironment(instruction)) { DCHECK(instruction->HasSsaIndex()); live_in->SetBit(instruction->GetSsaIndex()); instruction->GetLiveInterval()->AddUse(current, i, true); diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h index 5787f0cc4..b57029d1a 100644 --- a/compiler/optimizing/ssa_liveness_analysis.h +++ b/compiler/optimizing/ssa_liveness_analysis.h @@ -302,7 +302,7 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { first_range_->start_ = from; } else { // Instruction without uses. - DCHECK(!defined_by_->HasUses()); + DCHECK(!defined_by_->HasNonEnvironmentUses()); DCHECK(from == defined_by_->GetLifetimePosition()); first_range_ = last_range_ = new (allocator_) LiveRange(from, from + 2, nullptr); } @@ -798,6 +798,22 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { DISALLOW_COPY_AND_ASSIGN(LiveInterval); }; +/** + * Analysis that computes the liveness of instructions: + * + * (a) Non-environment uses of an instruction always make + * the instruction live. + * (b) Environment uses of an instruction whose type is + * object (that is, non-primitive), make the instruction live. + * This is due to having to keep alive objects that have + * finalizers deleting native objects. + * (c) When the graph has the debuggable property, environment uses + * of an instruction that has a primitive type make the instruction live. + * If the graph does not have the debuggable property, the environment + * use has no effect, and may get a 'none' value after register allocation. + * + * (b) and (c) are implemented through SsaLivenessAnalysis::ShouldBeLiveForEnvironment. + */ class SsaLivenessAnalysis : public ValueObject { public: SsaLivenessAnalysis(const HGraph& graph, CodeGenerator* codegen) @@ -882,6 +898,12 @@ class SsaLivenessAnalysis : public ValueObject { // Update the live_out set of the block and returns whether it has changed. bool UpdateLiveOut(const HBasicBlock& block); + static bool ShouldBeLiveForEnvironment(HInstruction* instruction) { + if (instruction == nullptr) return false; + if (instruction->GetBlock()->GetGraph()->IsDebuggable()) return true; + return instruction->GetType() == Primitive::kPrimNot; + } + const HGraph& graph_; CodeGenerator* const codegen_; GrowableArray<HBasicBlock*> linear_order_; |