diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2015-05-07 11:57:35 +0100 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2015-05-11 14:17:22 +0100 |
commit | 0a23d74dc2751440822960eab218be4cb8843647 (patch) | |
tree | 39d69de5d812826c4065d0acd38a58cd983f21f0 /compiler | |
parent | cdeb0b5fede4c06488f43a212591e661d946bc78 (diff) | |
download | android_art-0a23d74dc2751440822960eab218be4cb8843647.tar.gz android_art-0a23d74dc2751440822960eab218be4cb8843647.tar.bz2 android_art-0a23d74dc2751440822960eab218be4cb8843647.zip |
Add a parent environment to HEnvironment.
This code has no functionality change. It adds a placeholder
for chaining inlined frames.
Change-Id: I5ec57335af76ee406052345b947aad98a6a4423a
Diffstat (limited to 'compiler')
31 files changed, 309 insertions, 138 deletions
diff --git a/compiler/optimizing/bounds_check_elimination_test.cc b/compiler/optimizing/bounds_check_elimination_test.cc index 97be778dbd..163458f75c 100644 --- a/compiler/optimizing/bounds_check_elimination_test.cc +++ b/compiler/optimizing/bounds_check_elimination_test.cc @@ -42,7 +42,7 @@ TEST(BoundsCheckEliminationTest, NarrowingRangeArrayBoundsElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); graph->SetHasBoundsChecks(true); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); @@ -147,7 +147,7 @@ TEST(BoundsCheckEliminationTest, OverflowArrayBoundsElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); graph->SetHasBoundsChecks(true); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); @@ -219,7 +219,7 @@ TEST(BoundsCheckEliminationTest, UnderflowArrayBoundsElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); graph->SetHasBoundsChecks(true); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); @@ -291,7 +291,7 @@ TEST(BoundsCheckEliminationTest, ConstantArrayBoundsElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); graph->SetHasBoundsChecks(true); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); @@ -364,7 +364,7 @@ static HGraph* BuildSSAGraph1(ArenaAllocator* allocator, int initial, int increment, IfCondition cond = kCondGE) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); graph->SetHasBoundsChecks(true); HBasicBlock* entry = new (allocator) HBasicBlock(graph); @@ -501,7 +501,7 @@ static HGraph* BuildSSAGraph2(ArenaAllocator* allocator, int initial, int increment = -1, IfCondition cond = kCondLE) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); graph->SetHasBoundsChecks(true); HBasicBlock* entry = new (allocator) HBasicBlock(graph); @@ -632,7 +632,7 @@ static HGraph* BuildSSAGraph3(ArenaAllocator* allocator, int initial, int increment, IfCondition cond) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); graph->SetHasBoundsChecks(true); HBasicBlock* entry = new (allocator) HBasicBlock(graph); @@ -743,7 +743,7 @@ static HGraph* BuildSSAGraph4(ArenaAllocator* allocator, HInstruction** bounds_check, int initial, IfCondition cond = kCondGE) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); graph->SetHasBoundsChecks(true); HBasicBlock* entry = new (allocator) HBasicBlock(graph); @@ -868,7 +868,7 @@ TEST(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); graph->SetHasBoundsChecks(true); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index cfe121e0ec..0e776b31f7 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -100,11 +100,11 @@ static bool CheckTypeConsistency(HInstruction* instruction) { for (size_t i = 0; i < instruction->EnvironmentSize(); ++i) { if (environment->GetInstructionAt(i) != nullptr) { Primitive::Type type = environment->GetInstructionAt(i)->GetType(); - DCHECK(CheckType(type, locations->GetEnvironmentAt(i))) - << type << " " << locations->GetEnvironmentAt(i); + DCHECK(CheckType(type, environment->GetLocationAt(i))) + << type << " " << environment->GetLocationAt(i); } else { - DCHECK(locations->GetEnvironmentAt(i).IsInvalid()) - << locations->GetEnvironmentAt(i); + DCHECK(environment->GetLocationAt(i).IsInvalid()) + << environment->GetLocationAt(i); } } return true; @@ -680,6 +680,11 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction, locations->GetStackMask(), environment_size, inlining_depth); + if (environment != nullptr) { + // TODO: Handle parent environment. + DCHECK(environment->GetParent() == nullptr); + DCHECK_EQ(environment->GetDexPc(), dex_pc); + } // Walk over the environment, and record the location of dex registers. for (size_t i = 0; i < environment_size; ++i) { @@ -689,7 +694,7 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction, continue; } - Location location = locations->GetEnvironmentAt(i); + Location location = environment->GetLocationAt(i); switch (location.GetKind()) { case Location::kConstant: { DCHECK_EQ(current, location.GetConstant()); diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index 94f56e5d3e..bfed1a89de 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -225,7 +225,7 @@ static void RunCodeOptimized(HGraph* graph, static void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) { ArenaPool pool; ArenaAllocator arena(&pool); - HGraph* graph = new (&arena) HGraph(&arena); + HGraph* graph = CreateGraph(&arena); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); bool graph_built = builder.BuildGraph(*item); @@ -238,7 +238,7 @@ static void TestCode(const uint16_t* data, bool has_result = false, int32_t expe static void TestCodeLong(const uint16_t* data, bool has_result, int64_t expected) { ArenaPool pool; ArenaAllocator arena(&pool); - HGraph* graph = new (&arena) HGraph(&arena); + HGraph* graph = CreateGraph(&arena); HGraphBuilder builder(graph, Primitive::kPrimLong); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); bool graph_built = builder.BuildGraph(*item); @@ -504,7 +504,7 @@ TEST(CodegenTest, NonMaterializedCondition) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -623,7 +623,7 @@ TEST(CodegenTest, MaterializedCondition1) { for (size_t i = 0; i < arraysize(lhs); i++) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry_block); @@ -669,7 +669,7 @@ TEST(CodegenTest, MaterializedCondition2) { for (size_t i = 0; i < arraysize(lhs); i++) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry_block); diff --git a/compiler/optimizing/dominator_test.cc b/compiler/optimizing/dominator_test.cc index 61a7697301..78ae1dd960 100644 --- a/compiler/optimizing/dominator_test.cc +++ b/compiler/optimizing/dominator_test.cc @@ -27,7 +27,7 @@ namespace art { static void TestCode(const uint16_t* data, const int* blocks, size_t blocks_length) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); bool graph_built = builder.BuildGraph(*item); diff --git a/compiler/optimizing/find_loops_test.cc b/compiler/optimizing/find_loops_test.cc index 8f69f4d1d5..29aa97a83a 100644 --- a/compiler/optimizing/find_loops_test.cc +++ b/compiler/optimizing/find_loops_test.cc @@ -28,7 +28,7 @@ namespace art { static HGraph* TestCode(const uint16_t* data, ArenaAllocator* allocator) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); builder.BuildGraph(*item); diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index bb27a94702..fd28f0b83f 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -386,8 +386,9 @@ void SSAChecker::VisitInstruction(HInstruction* instruction) { // Ensure an instruction having an environment is dominated by the // instructions contained in the environment. - HEnvironment* environment = instruction->GetEnvironment(); - if (environment != nullptr) { + for (HEnvironment* environment = instruction->GetEnvironment(); + environment != nullptr; + environment = environment->GetParent()) { for (size_t i = 0, e = environment->Size(); i < e; ++i) { HInstruction* env_instruction = environment->GetInstructionAt(i); if (env_instruction != nullptr diff --git a/compiler/optimizing/graph_checker_test.cc b/compiler/optimizing/graph_checker_test.cc index 923468ff16..eca0d9344f 100644 --- a/compiler/optimizing/graph_checker_test.cc +++ b/compiler/optimizing/graph_checker_test.cc @@ -30,7 +30,7 @@ namespace art { * 1: Exit */ HGraph* CreateSimpleCFG(ArenaAllocator* allocator) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); HBasicBlock* entry_block = new (allocator) HBasicBlock(graph); entry_block->AddInstruction(new (allocator) HGoto()); graph->AddBlock(entry_block); diff --git a/compiler/optimizing/graph_test.cc b/compiler/optimizing/graph_test.cc index 50398b4790..59d50926ad 100644 --- a/compiler/optimizing/graph_test.cc +++ b/compiler/optimizing/graph_test.cc @@ -73,7 +73,7 @@ TEST(GraphTest, IfSuccessorSimpleJoinBlock1) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry_block = createEntryBlock(graph, &allocator); HBasicBlock* if_block = createIfBlock(graph, &allocator); HBasicBlock* if_true = createGotoBlock(graph, &allocator); @@ -108,7 +108,7 @@ TEST(GraphTest, IfSuccessorSimpleJoinBlock2) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry_block = createEntryBlock(graph, &allocator); HBasicBlock* if_block = createIfBlock(graph, &allocator); HBasicBlock* if_false = createGotoBlock(graph, &allocator); @@ -143,7 +143,7 @@ TEST(GraphTest, IfSuccessorMultipleBackEdges1) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry_block = createEntryBlock(graph, &allocator); HBasicBlock* if_block = createIfBlock(graph, &allocator); HBasicBlock* return_block = createReturnBlock(graph, &allocator); @@ -178,7 +178,7 @@ TEST(GraphTest, IfSuccessorMultipleBackEdges2) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry_block = createEntryBlock(graph, &allocator); HBasicBlock* if_block = createIfBlock(graph, &allocator); HBasicBlock* return_block = createReturnBlock(graph, &allocator); @@ -213,7 +213,7 @@ TEST(GraphTest, IfSuccessorMultiplePreHeaders1) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry_block = createEntryBlock(graph, &allocator); HBasicBlock* first_if_block = createIfBlock(graph, &allocator); HBasicBlock* if_block = createIfBlock(graph, &allocator); @@ -252,7 +252,7 @@ TEST(GraphTest, IfSuccessorMultiplePreHeaders2) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry_block = createEntryBlock(graph, &allocator); HBasicBlock* first_if_block = createIfBlock(graph, &allocator); HBasicBlock* if_block = createIfBlock(graph, &allocator); @@ -288,7 +288,7 @@ TEST(GraphTest, InsertInstructionBefore) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* block = createGotoBlock(graph, &allocator); HInstruction* got = block->GetLastInstruction(); ASSERT_TRUE(got->IsControlFlow()); diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index ca9cbc3d01..7130127136 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -211,17 +211,22 @@ class HGraphVisualizerPrinter : public HGraphVisitor { output_ << "]"; } if (instruction->HasEnvironment()) { - HEnvironment* env = instruction->GetEnvironment(); - output_ << " (env: [ "; - for (size_t i = 0, e = env->Size(); i < e; ++i) { - HInstruction* insn = env->GetInstructionAt(i); - if (insn != nullptr) { - output_ << GetTypeId(insn->GetType()) << insn->GetId() << " "; - } else { - output_ << " _ "; + output_ << " (env:"; + for (HEnvironment* environment = instruction->GetEnvironment(); + environment != nullptr; + environment = environment->GetParent()) { + output_ << " [ "; + for (size_t i = 0, e = environment->Size(); i < e; ++i) { + HInstruction* insn = environment->GetInstructionAt(i); + if (insn != nullptr) { + output_ << GetTypeId(insn->GetType()) << insn->GetId() << " "; + } else { + output_ << " _ "; + } } + output_ << "]"; } - output_ << "])"; + output_ << ")"; } if (IsPass(SsaLivenessAnalysis::kLivenessPassName) && is_after_pass_ diff --git a/compiler/optimizing/gvn_test.cc b/compiler/optimizing/gvn_test.cc index a81d49aa0c..c3ce7e142a 100644 --- a/compiler/optimizing/gvn_test.cc +++ b/compiler/optimizing/gvn_test.cc @@ -29,7 +29,7 @@ TEST(GVNTest, LocalFieldElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -78,7 +78,7 @@ TEST(GVNTest, GlobalFieldElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -133,7 +133,7 @@ TEST(GVNTest, LoopFieldElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -220,7 +220,7 @@ TEST(GVNTest, LoopSideEffects) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index ada32db047..afffc7ab4f 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -170,7 +170,11 @@ bool HInliner::TryBuildAndInline(Handle<mirror::ArtMethod> resolved_method, nullptr); HGraph* callee_graph = new (graph_->GetArena()) HGraph( - graph_->GetArena(), graph_->IsDebuggable(), graph_->GetCurrentInstructionId()); + graph_->GetArena(), + caller_dex_file, + method_index, + graph_->IsDebuggable(), + graph_->GetCurrentInstructionId()); OptimizingCompilerStats inline_stats; HGraphBuilder builder(callee_graph, diff --git a/compiler/optimizing/licm.cc b/compiler/optimizing/licm.cc index bf9b8e59c5..2535ea274a 100644 --- a/compiler/optimizing/licm.cc +++ b/compiler/optimizing/licm.cc @@ -39,8 +39,9 @@ static bool InputsAreDefinedBeforeLoop(HInstruction* instruction) { } } - if (instruction->HasEnvironment()) { - HEnvironment* environment = instruction->GetEnvironment(); + for (HEnvironment* environment = instruction->GetEnvironment(); + environment != nullptr; + environment = environment->GetParent()) { for (size_t i = 0, e = environment->Size(); i < e; ++i) { HInstruction* input = environment->GetInstructionAt(i); if (input != nullptr) { @@ -63,13 +64,15 @@ static bool InputsAreDefinedBeforeLoop(HInstruction* instruction) { * If `environment` has a loop header phi, we replace it with its first input. */ static void UpdateLoopPhisIn(HEnvironment* environment, HLoopInformation* info) { - for (size_t i = 0, e = environment->Size(); i < e; ++i) { - HInstruction* input = environment->GetInstructionAt(i); - if (input != nullptr && IsPhiOf(input, info->GetHeader())) { - environment->RemoveAsUserOfInput(i); - HInstruction* incoming = input->InputAt(0); - environment->SetRawEnvAt(i, incoming); - incoming->AddEnvUseAt(environment, i); + for (; environment != nullptr; environment = environment->GetParent()) { + for (size_t i = 0, e = environment->Size(); i < e; ++i) { + HInstruction* input = environment->GetInstructionAt(i); + if (input != nullptr && IsPhiOf(input, info->GetHeader())) { + environment->RemoveAsUserOfInput(i); + HInstruction* incoming = input->InputAt(0); + environment->SetRawEnvAt(i, incoming); + incoming->AddEnvUseAt(environment, i); + } } } } diff --git a/compiler/optimizing/linearize_test.cc b/compiler/optimizing/linearize_test.cc index 7818c606db..4f259b5095 100644 --- a/compiler/optimizing/linearize_test.cc +++ b/compiler/optimizing/linearize_test.cc @@ -39,7 +39,7 @@ namespace art { static void TestCode(const uint16_t* data, const int* expected_order, size_t number_of_blocks) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); bool graph_built = builder.BuildGraph(*item); diff --git a/compiler/optimizing/live_ranges_test.cc b/compiler/optimizing/live_ranges_test.cc index 52367730ed..7cb00a1923 100644 --- a/compiler/optimizing/live_ranges_test.cc +++ b/compiler/optimizing/live_ranges_test.cc @@ -32,7 +32,7 @@ namespace art { static HGraph* BuildGraph(const uint16_t* data, ArenaAllocator* allocator) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); builder.BuildGraph(*item); diff --git a/compiler/optimizing/liveness_test.cc b/compiler/optimizing/liveness_test.cc index 191433955b..9d7d0b6c67 100644 --- a/compiler/optimizing/liveness_test.cc +++ b/compiler/optimizing/liveness_test.cc @@ -46,7 +46,7 @@ static void DumpBitVector(BitVector* vector, static void TestCode(const uint16_t* data, const char* expected) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); bool graph_built = builder.BuildGraph(*item); diff --git a/compiler/optimizing/locations.cc b/compiler/optimizing/locations.cc index a1ae67009e..42aba04828 100644 --- a/compiler/optimizing/locations.cc +++ b/compiler/optimizing/locations.cc @@ -25,8 +25,6 @@ LocationSummary::LocationSummary(HInstruction* instruction, bool intrinsified) : inputs_(instruction->GetBlock()->GetGraph()->GetArena(), instruction->InputCount()), temps_(instruction->GetBlock()->GetGraph()->GetArena(), 0), - environment_(instruction->GetBlock()->GetGraph()->GetArena(), - instruction->EnvironmentSize()), output_overlaps_(Location::kOutputOverlap), call_kind_(call_kind), stack_mask_(nullptr), @@ -37,10 +35,6 @@ LocationSummary::LocationSummary(HInstruction* instruction, for (size_t i = 0; i < instruction->InputCount(); ++i) { inputs_.Put(i, Location()); } - environment_.SetSize(instruction->EnvironmentSize()); - for (size_t i = 0; i < instruction->EnvironmentSize(); ++i) { - environment_.Put(i, Location()); - } instruction->SetLocations(this); if (NeedsSafepoint()) { diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h index c3a99150c4..09bbb33042 100644 --- a/compiler/optimizing/locations.h +++ b/compiler/optimizing/locations.h @@ -525,14 +525,6 @@ class LocationSummary : public ArenaObject<kArenaAllocMisc> { return temps_.Size(); } - void SetEnvironmentAt(uint32_t at, Location location) { - environment_.Put(at, location); - } - - Location GetEnvironmentAt(uint32_t at) const { - return environment_.Get(at); - } - Location Out() const { return output_; } bool CanCall() const { return call_kind_ != kNoCall; } @@ -602,7 +594,6 @@ class LocationSummary : public ArenaObject<kArenaAllocMisc> { private: GrowableArray<Location> inputs_; GrowableArray<Location> temps_; - GrowableArray<Location> environment_; // Whether the output overlaps with any of the inputs. If it overlaps, then it cannot // share the same register as the inputs. Location::OutputOverlap output_overlaps_; diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 85c0361f46..b9e58c7032 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -37,8 +37,9 @@ static void RemoveAsUser(HInstruction* instruction) { instruction->RemoveAsUserOfInput(i); } - HEnvironment* environment = instruction->GetEnvironment(); - if (environment != nullptr) { + for (HEnvironment* environment = instruction->GetEnvironment(); + environment != nullptr; + environment = environment->GetParent()) { for (size_t i = 0, e = environment->Size(); i < e; ++i) { if (environment->GetInstructionAt(i) != nullptr) { environment->RemoveAsUserOfInput(i); diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 5fc0470310..031761e7f7 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -117,7 +117,11 @@ class HInstructionList { // Control-flow graph of a method. Contains a list of basic blocks. class HGraph : public ArenaObject<kArenaAllocMisc> { public: - HGraph(ArenaAllocator* arena, bool debuggable = false, int start_instruction_id = 0) + HGraph(ArenaAllocator* arena, + const DexFile& dex_file, + uint32_t method_idx, + bool debuggable = false, + int start_instruction_id = 0) : arena_(arena), blocks_(arena, kDefaultNumberOfBlocks), reverse_post_order_(arena, kDefaultNumberOfBlocks), @@ -131,6 +135,8 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { has_bounds_checks_(false), debuggable_(debuggable), current_instruction_id_(start_instruction_id), + dex_file_(dex_file), + method_idx_(method_idx), cached_null_constant_(nullptr), cached_int_constants_(std::less<int32_t>(), arena->Adapter()), cached_float_constants_(std::less<int32_t>(), arena->Adapter()), @@ -263,6 +269,14 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const; + const DexFile& GetDexFile() const { + return dex_file_; + } + + uint32_t GetMethodIdx() const { + return method_idx_; + } + private: void VisitBlockForDominatorTree(HBasicBlock* block, HBasicBlock* predecessor, @@ -339,6 +353,12 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { // The current id to assign to a newly added instruction. See HInstruction.id_. int32_t current_instruction_id_; + // The dex file from which the method is from. + const DexFile& dex_file_; + + // The method index in the dex file. + const uint32_t method_idx_; + // Cached constants. HNullConstant* cached_null_constant_; ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_; @@ -934,6 +954,14 @@ class HUseList : public ValueObject { return first_ != nullptr && first_->next_ == nullptr; } + size_t SizeSlow() const { + size_t count = 0; + for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) { + ++count; + } + return count; + } + private: HUseListNode<T>* first_; }; @@ -1060,12 +1088,38 @@ class SideEffects : public ValueObject { // A HEnvironment object contains the values of virtual registers at a given location. class HEnvironment : public ArenaObject<kArenaAllocMisc> { public: - HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) - : vregs_(arena, number_of_vregs) { + HEnvironment(ArenaAllocator* arena, + size_t number_of_vregs, + const DexFile& dex_file, + uint32_t method_idx, + uint32_t dex_pc) + : vregs_(arena, number_of_vregs), + locations_(arena, number_of_vregs), + parent_(nullptr), + dex_file_(dex_file), + method_idx_(method_idx), + dex_pc_(dex_pc) { vregs_.SetSize(number_of_vregs); for (size_t i = 0; i < number_of_vregs; i++) { vregs_.Put(i, HUserRecord<HEnvironment*>()); } + + locations_.SetSize(number_of_vregs); + for (size_t i = 0; i < number_of_vregs; ++i) { + locations_.Put(i, Location()); + } + } + + void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) { + parent_ = new (allocator) HEnvironment(allocator, + parent->Size(), + parent->GetDexFile(), + parent->GetMethodIdx(), + parent->GetDexPc()); + if (parent->GetParent() != nullptr) { + parent_->SetAndCopyParentChain(allocator, parent->GetParent()); + } + parent_->CopyFrom(parent); } void CopyFrom(const GrowableArray<HInstruction*>& locals); @@ -1088,6 +1142,28 @@ class HEnvironment : public ArenaObject<kArenaAllocMisc> { size_t Size() const { return vregs_.Size(); } + HEnvironment* GetParent() const { return parent_; } + + void SetLocationAt(size_t index, Location location) { + locations_.Put(index, location); + } + + Location GetLocationAt(size_t index) const { + return locations_.Get(index); + } + + uint32_t GetDexPc() const { + return dex_pc_; + } + + uint32_t GetMethodIdx() const { + return method_idx_; + } + + const DexFile& GetDexFile() const { + return dex_file_; + } + private: // Record instructions' use entries of this environment for constant-time removal. // It should only be called by HInstruction when a new environment use is added. @@ -1098,6 +1174,11 @@ class HEnvironment : public ArenaObject<kArenaAllocMisc> { } GrowableArray<HUserRecord<HEnvironment*> > vregs_; + GrowableArray<Location> locations_; + HEnvironment* parent_; + const DexFile& dex_file_; + const uint32_t method_idx_; + const uint32_t dex_pc_; friend class HInstruction; @@ -1229,6 +1310,11 @@ class HInstruction : public ArenaObject<kArenaAllocMisc> { } virtual bool NeedsEnvironment() const { return false; } + virtual uint32_t GetDexPc() const { + LOG(FATAL) << "GetDexPc() cannot be called on an instruction that" + " does not need an environment"; + UNREACHABLE(); + } virtual bool IsControlFlow() const { return false; } virtual bool CanThrow() const { return false; } bool HasSideEffects() const { return side_effects_.HasSideEffects(); } @@ -1306,14 +1392,30 @@ class HInstruction : public ArenaObject<kArenaAllocMisc> { // copying, the uses lists are being updated. void CopyEnvironmentFrom(HEnvironment* environment) { ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena(); - environment_ = new (allocator) HEnvironment(allocator, environment->Size()); + environment_ = new (allocator) HEnvironment( + allocator, + environment->Size(), + environment->GetDexFile(), + environment->GetMethodIdx(), + environment->GetDexPc()); environment_->CopyFrom(environment); + if (environment->GetParent() != nullptr) { + environment_->SetAndCopyParentChain(allocator, environment->GetParent()); + } } void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment, HBasicBlock* block) { ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena(); - environment_ = new (allocator) HEnvironment(allocator, environment->Size()); + environment_ = new (allocator) HEnvironment( + allocator, + environment->Size(), + environment->GetDexFile(), + environment->GetMethodIdx(), + environment->GetDexPc()); + if (environment->GetParent() != nullptr) { + environment_->SetAndCopyParentChain(allocator, environment->GetParent()); + } environment_->CopyFromWithLoopPhiAdjustment(environment, block); } @@ -1690,7 +1792,7 @@ class HDeoptimize : public HTemplateInstruction<1> { bool NeedsEnvironment() const OVERRIDE { return true; } bool CanThrow() const OVERRIDE { return true; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } DECLARE_INSTRUCTION(Deoptimize); @@ -2259,7 +2361,7 @@ class HInvoke : public HInstruction { Primitive::Type GetType() const OVERRIDE { return return_type_; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } uint32_t GetDexMethodIndex() const { return dex_method_index_; } @@ -2476,7 +2578,7 @@ class HNewInstance : public HExpression<0> { type_index_(type_index), entrypoint_(entrypoint) {} - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } uint16_t GetTypeIndex() const { return type_index_; } // Calls runtime so needs an environment. @@ -2528,7 +2630,7 @@ class HNewArray : public HExpression<1> { SetRawInputAt(0, length); } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } uint16_t GetTypeIndex() const { return type_index_; } // Calls runtime so needs an environment. @@ -2623,7 +2725,7 @@ class HDiv : public HBinaryOperation { return (y == -1) ? -x : x / y; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } DECLARE_INSTRUCTION(Div); @@ -2650,7 +2752,7 @@ class HRem : public HBinaryOperation { return (y == -1) ? 0 : x % y; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } DECLARE_INSTRUCTION(Rem); @@ -2677,7 +2779,7 @@ class HDivZeroCheck : public HExpression<1> { bool NeedsEnvironment() const OVERRIDE { return true; } bool CanThrow() const OVERRIDE { return true; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } DECLARE_INSTRUCTION(DivZeroCheck); @@ -2872,7 +2974,7 @@ class HTypeConversion : public HExpression<1> { // Required by the x86 and ARM code generators when producing calls // to the runtime. - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } bool CanBeMoved() const OVERRIDE { return true; } bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; } @@ -2982,7 +3084,7 @@ class HNullCheck : public HExpression<1> { bool CanBeNull() const OVERRIDE { return false; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } DECLARE_INSTRUCTION(NullCheck); @@ -3145,7 +3247,7 @@ class HArraySet : public HTemplateInstruction<3> { bool NeedsTypeCheck() const { return needs_type_check_; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } HInstruction* GetArray() const { return InputAt(0); } HInstruction* GetIndex() const { return InputAt(1); } @@ -3215,7 +3317,7 @@ class HBoundsCheck : public HExpression<2> { bool CanThrow() const OVERRIDE { return true; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } DECLARE_INSTRUCTION(BoundsCheck); @@ -3261,7 +3363,7 @@ class HSuspendCheck : public HTemplateInstruction<0> { return true; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } void SetSlowPath(SlowPathCode* slow_path) { slow_path_ = slow_path; } SlowPathCode* GetSlowPath() const { return slow_path_; } @@ -3300,7 +3402,7 @@ class HLoadClass : public HExpression<0> { size_t ComputeHashCode() const OVERRIDE { return type_index_; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } uint16_t GetTypeIndex() const { return type_index_; } bool IsReferrersClass() const { return is_referrers_class_; } @@ -3374,7 +3476,7 @@ class HLoadString : public HExpression<0> { size_t ComputeHashCode() const OVERRIDE { return string_index_; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } uint32_t GetStringIndex() const { return string_index_; } // TODO: Can we deopt or debug when we resolve a string? @@ -3412,7 +3514,7 @@ class HClinitCheck : public HExpression<1> { return true; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); } @@ -3512,7 +3614,7 @@ class HThrow : public HTemplateInstruction<1> { bool CanThrow() const OVERRIDE { return true; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } DECLARE_INSTRUCTION(Throw); @@ -3546,7 +3648,7 @@ class HInstanceOf : public HExpression<2> { return false; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } bool IsClassFinal() const { return class_is_final_; } @@ -3621,7 +3723,7 @@ class HCheckCast : public HTemplateInstruction<2> { bool MustDoNullCheck() const { return must_do_null_check_; } void ClearMustDoNullCheck() { must_do_null_check_ = false; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } bool IsClassFinal() const { return class_is_final_; } @@ -3667,7 +3769,7 @@ class HMonitorOperation : public HTemplateInstruction<1> { bool NeedsEnvironment() const OVERRIDE { return true; } bool CanThrow() const OVERRIDE { return true; } - uint32_t GetDexPc() const { return dex_pc_; } + uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } bool IsEnter() const { return kind_ == kEnter; } diff --git a/compiler/optimizing/nodes_test.cc b/compiler/optimizing/nodes_test.cc index 4e83ce576c..2736453ccc 100644 --- a/compiler/optimizing/nodes_test.cc +++ b/compiler/optimizing/nodes_test.cc @@ -16,6 +16,7 @@ #include "base/arena_allocator.h" #include "nodes.h" +#include "optimizing_unit_test.h" #include "gtest/gtest.h" @@ -29,7 +30,7 @@ TEST(Node, RemoveInstruction) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -49,7 +50,8 @@ TEST(Node, RemoveInstruction) { first_block->AddSuccessor(exit_block); exit_block->AddInstruction(new (&allocator) HExit()); - HEnvironment* environment = new (&allocator) HEnvironment(&allocator, 1); + HEnvironment* environment = new (&allocator) HEnvironment( + &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0); null_check->SetRawEnvironment(environment); environment->SetRawEnvAt(0, parameter); parameter->AddEnvUseAt(null_check->GetEnvironment(), 0); @@ -70,7 +72,7 @@ TEST(Node, InsertInstruction) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -96,7 +98,7 @@ TEST(Node, AddInstruction) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -112,4 +114,51 @@ TEST(Node, AddInstruction) { ASSERT_TRUE(parameter->GetUses().HasOnlyOneUse()); } +TEST(Node, ParentEnvironment) { + ArenaPool pool; + ArenaAllocator allocator(&pool); + + HGraph* graph = CreateGraph(&allocator); + HBasicBlock* entry = new (&allocator) HBasicBlock(graph); + graph->AddBlock(entry); + graph->SetEntryBlock(entry); + HInstruction* parameter1 = new (&allocator) HParameterValue(0, Primitive::kPrimNot); + HInstruction* with_environment = new (&allocator) HNullCheck(parameter1, 0); + entry->AddInstruction(parameter1); + entry->AddInstruction(with_environment); + entry->AddInstruction(new (&allocator) HExit()); + + ASSERT_TRUE(parameter1->HasUses()); + ASSERT_TRUE(parameter1->GetUses().HasOnlyOneUse()); + + HEnvironment* environment = new (&allocator) HEnvironment( + &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0); + GrowableArray<HInstruction*> array(&allocator, 1); + array.Add(parameter1); + + environment->CopyFrom(array); + with_environment->SetRawEnvironment(environment); + + ASSERT_TRUE(parameter1->HasEnvironmentUses()); + ASSERT_TRUE(parameter1->GetEnvUses().HasOnlyOneUse()); + + HEnvironment* parent1 = new (&allocator) HEnvironment( + &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0); + parent1->CopyFrom(array); + + ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u); + + HEnvironment* parent2 = new (&allocator) HEnvironment( + &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0); + parent2->CopyFrom(array); + parent1->SetAndCopyParentChain(&allocator, parent2); + + // One use for parent2, and one other use for the new parent of parent1. + ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 4u); + + // We have copied the parent chain. So we now have two more uses. + environment->SetAndCopyParentChain(&allocator, parent1); + ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 6u); +} + } // namespace art diff --git a/compiler/optimizing/optimizing_cfi_test.cc b/compiler/optimizing/optimizing_cfi_test.cc index b2c13adf35..7aea249c42 100644 --- a/compiler/optimizing/optimizing_cfi_test.cc +++ b/compiler/optimizing/optimizing_cfi_test.cc @@ -21,6 +21,7 @@ #include "cfi_test.h" #include "gtest/gtest.h" #include "optimizing/code_generator.h" +#include "optimizing/optimizing_unit_test.h" #include "utils/assembler.h" #include "optimizing/optimizing_cfi_test_expected.inc" @@ -45,10 +46,10 @@ class OptimizingCFITest : public CFITest { std::unique_ptr<const InstructionSetFeatures> isa_features; std::string error; isa_features.reset(InstructionSetFeatures::FromVariant(isa, "default", &error)); - HGraph graph(&allocator); + HGraph* graph = CreateGraph(&allocator); // Generate simple frame with some spills. std::unique_ptr<CodeGenerator> code_gen( - CodeGenerator::Create(&graph, isa, *isa_features.get(), opts)); + CodeGenerator::Create(graph, isa, *isa_features.get(), opts)); const int frame_size = 64; int core_reg = 0; int fp_reg = 0; diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 05451bcaa6..e993d778d4 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -512,7 +512,7 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite ArenaAllocator arena(Runtime::Current()->GetArenaPool()); HGraph* graph = new (&arena) HGraph( - &arena, compiler_driver->GetCompilerOptions().GetDebuggable()); + &arena, dex_file, method_idx, compiler_driver->GetCompilerOptions().GetDebuggable()); // For testing purposes, we put a special marker on method names that should be compiled // with this compiler. This makes sure we're not regressing. diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h index 6b236927da..4f8ec65e43 100644 --- a/compiler/optimizing/optimizing_unit_test.h +++ b/compiler/optimizing/optimizing_unit_test.h @@ -72,11 +72,16 @@ void RemoveSuspendChecks(HGraph* graph) { } } +inline HGraph* CreateGraph(ArenaAllocator* allocator) { + return new (allocator) HGraph( + allocator, *reinterpret_cast<DexFile*>(allocator->Alloc(sizeof(DexFile))), -1); +} + // Create a control-flow graph from Dex instructions. inline HGraph* CreateCFG(ArenaAllocator* allocator, const uint16_t* data, Primitive::Type return_type = Primitive::kPrimInt) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); HGraphBuilder builder(graph, return_type); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); diff --git a/compiler/optimizing/pretty_printer_test.cc b/compiler/optimizing/pretty_printer_test.cc index 293fde978e..c56100dfa1 100644 --- a/compiler/optimizing/pretty_printer_test.cc +++ b/compiler/optimizing/pretty_printer_test.cc @@ -30,7 +30,7 @@ namespace art { static void TestCode(const uint16_t* data, const char* expected) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); bool graph_built = builder.BuildGraph(*item); diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc index 2375595978..f53f846326 100644 --- a/compiler/optimizing/register_allocator.cc +++ b/compiler/optimizing/register_allocator.cc @@ -1534,9 +1534,10 @@ void RegisterAllocator::ConnectSiblings(LiveInterval* interval) { } while (env_use != nullptr && env_use->GetPosition() <= range->GetEnd()) { - DCHECK(current->CoversSlow(env_use->GetPosition()) || (env_use->GetPosition() == range->GetEnd())); - LocationSummary* locations = env_use->GetUser()->GetLocations(); - locations->SetEnvironmentAt(env_use->GetInputIndex(), source); + DCHECK(current->CoversSlow(env_use->GetPosition()) + || (env_use->GetPosition() == range->GetEnd())); + HEnvironment* environment = env_use->GetUser()->GetEnvironment(); + environment->SetLocationAt(env_use->GetInputIndex(), source); env_use = env_use->GetNext(); } diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc index 8c6d904a4c..b72ffb8bf7 100644 --- a/compiler/optimizing/register_allocator_test.cc +++ b/compiler/optimizing/register_allocator_test.cc @@ -38,7 +38,7 @@ namespace art { static bool Check(const uint16_t* data) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); builder.BuildGraph(*item); @@ -60,7 +60,7 @@ static bool Check(const uint16_t* data) { TEST(RegisterAllocatorTest, ValidateIntervals) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); std::unique_ptr<const X86InstructionSetFeatures> features_x86( X86InstructionSetFeatures::FromCppDefines()); x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions()); @@ -255,7 +255,7 @@ TEST(RegisterAllocatorTest, Loop2) { } static HGraph* BuildSSAGraph(const uint16_t* data, ArenaAllocator* allocator) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); builder.BuildGraph(*item); @@ -463,7 +463,7 @@ static HGraph* BuildIfElseWithPhi(ArenaAllocator* allocator, HPhi** phi, HInstruction** input1, HInstruction** input2) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); HBasicBlock* entry = new (allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -593,7 +593,7 @@ TEST(RegisterAllocatorTest, PhiHint) { static HGraph* BuildFieldReturn(ArenaAllocator* allocator, HInstruction** field, HInstruction** ret) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); HBasicBlock* entry = new (allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -661,7 +661,7 @@ TEST(RegisterAllocatorTest, ExpectedInRegisterHint) { static HGraph* BuildTwoSubs(ArenaAllocator* allocator, HInstruction** first_sub, HInstruction** second_sub) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); HBasicBlock* entry = new (allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -731,7 +731,7 @@ TEST(RegisterAllocatorTest, SameAsFirstInputHint) { static HGraph* BuildDiv(ArenaAllocator* allocator, HInstruction** div) { - HGraph* graph = new (allocator) HGraph(allocator); + HGraph* graph = CreateGraph(allocator); HBasicBlock* entry = new (allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -783,7 +783,7 @@ TEST(RegisterAllocatorTest, SpillInactive) { // Create a synthesized graph to please the register_allocator and // ssa_liveness_analysis code. ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc index 2a713cc0a3..59a2852735 100644 --- a/compiler/optimizing/ssa_builder.cc +++ b/compiler/optimizing/ssa_builder.cc @@ -543,7 +543,11 @@ void SsaBuilder::VisitInstruction(HInstruction* instruction) { return; } HEnvironment* environment = new (GetGraph()->GetArena()) HEnvironment( - GetGraph()->GetArena(), current_locals_->Size()); + GetGraph()->GetArena(), + current_locals_->Size(), + GetGraph()->GetDexFile(), + GetGraph()->GetMethodIdx(), + instruction->GetDexPc()); environment->CopyFrom(*current_locals_); instruction->SetRawEnvironment(environment); } diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc index 09a664834f..250eb04a1c 100644 --- a/compiler/optimizing/ssa_liveness_analysis.cc +++ b/compiler/optimizing/ssa_liveness_analysis.cc @@ -218,10 +218,11 @@ void SsaLivenessAnalysis::ComputeLiveRanges() { // Process the environment first, because we know their uses come after // or at the same liveness position of inputs. - if (current->HasEnvironment()) { + for (HEnvironment* environment = current->GetEnvironment(); + environment != nullptr; + environment = environment->GetParent()) { // 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); bool should_be_live = ShouldBeLiveForEnvironment(instruction); @@ -231,7 +232,7 @@ void SsaLivenessAnalysis::ComputeLiveRanges() { } if (instruction != nullptr) { instruction->GetLiveInterval()->AddUse( - current, i, /* is_environment */ true, should_be_live); + current, environment, i, should_be_live); } } } @@ -243,7 +244,7 @@ void SsaLivenessAnalysis::ComputeLiveRanges() { // to be materialized. if (input->HasSsaIndex()) { live_in->SetBit(input->GetSsaIndex()); - input->GetLiveInterval()->AddUse(current, i, /* is_environment */ false); + input->GetLiveInterval()->AddUse(current, /* environment */ nullptr, i); } } } diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h index b550d8ad8e..82c5454bb0 100644 --- a/compiler/optimizing/ssa_liveness_analysis.h +++ b/compiler/optimizing/ssa_liveness_analysis.h @@ -104,13 +104,13 @@ class LiveRange FINAL : public ArenaObject<kArenaAllocMisc> { class UsePosition : public ArenaObject<kArenaAllocMisc> { public: UsePosition(HInstruction* user, + HEnvironment* environment, size_t input_index, - bool is_environment, size_t position, UsePosition* next) : user_(user), + environment_(environment), input_index_(input_index), - is_environment_(is_environment), position_(position), next_(next) { DCHECK((user == nullptr) @@ -129,7 +129,7 @@ class UsePosition : public ArenaObject<kArenaAllocMisc> { HInstruction* GetUser() const { return user_; } - bool GetIsEnvironment() const { return is_environment_; } + bool GetIsEnvironment() const { return environment_ != nullptr; } bool IsSynthesized() const { return user_ == nullptr; } size_t GetInputIndex() const { return input_index_; } @@ -144,7 +144,7 @@ class UsePosition : public ArenaObject<kArenaAllocMisc> { UsePosition* Dup(ArenaAllocator* allocator) const { return new (allocator) UsePosition( - user_, input_index_, is_environment_, position_, + user_, environment_, input_index_, position_, next_ == nullptr ? nullptr : next_->Dup(allocator)); } @@ -159,8 +159,8 @@ class UsePosition : public ArenaObject<kArenaAllocMisc> { private: HInstruction* const user_; + HEnvironment* const environment_; const size_t input_index_; - const bool is_environment_; const size_t position_; UsePosition* next_; @@ -237,15 +237,16 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { DCHECK(first_env_use_ == nullptr) << "A temporary cannot have environment user"; size_t position = instruction->GetLifetimePosition(); first_use_ = new (allocator_) UsePosition( - instruction, temp_index, /* is_environment */ false, position, first_use_); + instruction, /* environment */ nullptr, temp_index, position, first_use_); AddRange(position, position + 1); } void AddUse(HInstruction* instruction, + HEnvironment* environment, size_t input_index, - bool is_environment, bool keep_alive = false) { // Set the use within the instruction. + bool is_environment = (environment != nullptr); size_t position = instruction->GetLifetimePosition() + 1; LocationSummary* locations = instruction->GetLocations(); if (!is_environment) { @@ -279,7 +280,7 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { } DCHECK(first_use_->GetPosition() + 1 == position); UsePosition* new_use = new (allocator_) UsePosition( - instruction, input_index, is_environment, position, cursor->GetNext()); + instruction, environment, input_index, position, cursor->GetNext()); cursor->SetNext(new_use); if (first_range_->GetEnd() == first_use_->GetPosition()) { first_range_->end_ = position; @@ -289,10 +290,10 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { if (is_environment) { first_env_use_ = new (allocator_) UsePosition( - instruction, input_index, is_environment, position, first_env_use_); + instruction, environment, input_index, position, first_env_use_); } else { first_use_ = new (allocator_) UsePosition( - instruction, input_index, is_environment, position, first_use_); + instruction, environment, input_index, position, first_use_); } if (is_environment && !keep_alive) { @@ -331,7 +332,7 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { AddBackEdgeUses(*block); } first_use_ = new (allocator_) UsePosition( - instruction, input_index, false, block->GetLifetimeEnd(), first_use_); + instruction, /* environment */ nullptr, input_index, block->GetLifetimeEnd(), first_use_); } void AddRange(size_t start, size_t end) { @@ -989,8 +990,11 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { || back_edge_use_position > last_in_new_list->GetPosition()); UsePosition* new_use = new (allocator_) UsePosition( - nullptr, UsePosition::kNoInput, /* is_environment */ false, - back_edge_use_position, nullptr); + /* user */ nullptr, + /* environment */ nullptr, + UsePosition::kNoInput, + back_edge_use_position, + /* next */ nullptr); if (last_in_new_list != nullptr) { // Going outward. The latest created use needs to point to the new use. diff --git a/compiler/optimizing/ssa_test.cc b/compiler/optimizing/ssa_test.cc index 4cc9c3ea96..fb3e7d798c 100644 --- a/compiler/optimizing/ssa_test.cc +++ b/compiler/optimizing/ssa_test.cc @@ -78,7 +78,7 @@ static void ReNumberInstructions(HGraph* graph) { static void TestCode(const uint16_t* data, const char* expected) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); bool graph_built = builder.BuildGraph(*item); diff --git a/compiler/optimizing/suspend_check_test.cc b/compiler/optimizing/suspend_check_test.cc index a5a0eb2114..5ca66a1de6 100644 --- a/compiler/optimizing/suspend_check_test.cc +++ b/compiler/optimizing/suspend_check_test.cc @@ -30,7 +30,7 @@ namespace art { static void TestCode(const uint16_t* data) { ArenaPool pool; ArenaAllocator allocator(&pool); - HGraph* graph = new (&allocator) HGraph(&allocator); + HGraph* graph = CreateGraph(&allocator); HGraphBuilder builder(graph); const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); bool graph_built = builder.BuildGraph(*item); |