diff options
Diffstat (limited to 'compiler/optimizing/builder.cc')
| -rw-r--r-- | compiler/optimizing/builder.cc | 148 |
1 files changed, 14 insertions, 134 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index c7430e7eb6..05e1356ed8 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -32,114 +32,12 @@ #include "nodes.h" #include "primitive.h" #include "scoped_thread_state_change.h" +#include "ssa_builder.h" #include "thread.h" #include "utils/dex_cache_arrays_layout-inl.h" namespace art { -/** - * Helper class to add HTemporary instructions. This class is used when - * converting a DEX instruction to multiple HInstruction, and where those - * instructions do not die at the following instruction, but instead spans - * multiple instructions. - */ -class Temporaries : public ValueObject { - public: - explicit Temporaries(HGraph* graph) : graph_(graph), index_(0) {} - - void Add(HInstruction* instruction) { - HInstruction* temp = new (graph_->GetArena()) HTemporary(index_, instruction->GetDexPc()); - instruction->GetBlock()->AddInstruction(temp); - - DCHECK(temp->GetPrevious() == instruction); - - size_t offset; - if (instruction->GetType() == Primitive::kPrimLong - || instruction->GetType() == Primitive::kPrimDouble) { - offset = 2; - } else { - offset = 1; - } - index_ += offset; - - graph_->UpdateTemporariesVRegSlots(index_); - } - - private: - HGraph* const graph_; - - // Current index in the temporary stack, updated by `Add`. - size_t index_; -}; - -class SwitchTable : public ValueObject { - public: - SwitchTable(const Instruction& instruction, uint32_t dex_pc, bool sparse) - : instruction_(instruction), dex_pc_(dex_pc), sparse_(sparse) { - int32_t table_offset = instruction.VRegB_31t(); - const uint16_t* table = reinterpret_cast<const uint16_t*>(&instruction) + table_offset; - if (sparse) { - CHECK_EQ(table[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature)); - } else { - CHECK_EQ(table[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature)); - } - num_entries_ = table[1]; - values_ = reinterpret_cast<const int32_t*>(&table[2]); - } - - uint16_t GetNumEntries() const { - return num_entries_; - } - - void CheckIndex(size_t index) const { - if (sparse_) { - // In a sparse table, we have num_entries_ keys and num_entries_ values, in that order. - DCHECK_LT(index, 2 * static_cast<size_t>(num_entries_)); - } else { - // In a packed table, we have the starting key and num_entries_ values. - DCHECK_LT(index, 1 + static_cast<size_t>(num_entries_)); - } - } - - int32_t GetEntryAt(size_t index) const { - CheckIndex(index); - return values_[index]; - } - - uint32_t GetDexPcForIndex(size_t index) const { - CheckIndex(index); - return dex_pc_ + - (reinterpret_cast<const int16_t*>(values_ + index) - - reinterpret_cast<const int16_t*>(&instruction_)); - } - - // Index of the first value in the table. - size_t GetFirstValueIndex() const { - if (sparse_) { - // In a sparse table, we have num_entries_ keys and num_entries_ values, in that order. - return num_entries_; - } else { - // In a packed table, we have the starting key and num_entries_ values. - return 1; - } - } - - private: - const Instruction& instruction_; - const uint32_t dex_pc_; - - // Whether this is a sparse-switch table (or a packed-switch one). - const bool sparse_; - - // This can't be const as it needs to be computed off of the given instruction, and complicated - // expressions in the initializer list seemed very ugly. - uint16_t num_entries_; - - const int32_t* values_; - - DISALLOW_COPY_AND_ASSIGN(SwitchTable); -}; - void HGraphBuilder::InitializeLocals(uint16_t count) { graph_->SetNumberOfVRegs(count); locals_.resize(count); @@ -351,7 +249,7 @@ void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item) // loop for synchronized blocks. if (block->HasThrowingInstructions()) { // Try to find a TryItem covering the block. - DCHECK_NE(block->GetDexPc(), kNoDexPc) << "Block must have a dec_pc to find its TryItem."; + DCHECK_NE(block->GetDexPc(), kNoDexPc) << "Block must have a dex_pc to find its TryItem."; const int32_t try_item_idx = DexFile::FindTryItem(code_item, block->GetDexPc()); if (try_item_idx != -1) { // Block throwing and in a TryItem. Store the try block information. @@ -425,7 +323,8 @@ void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item) } } -bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { +GraphAnalysisResult HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item, + StackHandleScopeCollection* handles) { DCHECK(graph_->GetBlocks().empty()); const uint16_t* code_ptr = code_item.insns_; @@ -452,12 +351,12 @@ bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { // start a new block, and create these blocks. if (!ComputeBranchTargets(code_ptr, code_end, &number_of_branches)) { MaybeRecordStat(MethodCompilationStat::kNotCompiledBranchOutsideMethodCode); - return false; + return kAnalysisInvalidBytecode; } // Note that the compiler driver is null when unit testing. if ((compiler_driver_ != nullptr) && SkipCompilation(code_item, number_of_branches)) { - return false; + return kAnalysisInvalidBytecode; } // Find locations where we want to generate extra stackmaps for native debugging. @@ -488,7 +387,7 @@ bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { } } if (!AnalyzeDexInstruction(instruction, dex_pc)) { - return false; + return kAnalysisInvalidBytecode; } dex_pc += instruction.SizeInCodeUnits(); code_ptr += instruction.SizeInCodeUnits(); @@ -507,7 +406,13 @@ bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { // non-exceptional edges to have been created. InsertTryBoundaryBlocks(code_item); - return true; + GraphAnalysisResult result = graph_->BuildDominatorTree(); + if (result != kAnalysisSuccess) { + return result; + } + + graph_->InitializeInexactObjectRTI(handles); + return SsaBuilder(graph_, handles).BuildSsa(); } void HGraphBuilder::MaybeUpdateCurrentBlock(size_t dex_pc) { @@ -1234,12 +1139,10 @@ bool HGraphBuilder::HandleInvoke(HInvoke* invoke, size_t start_index = 0; size_t argument_index = 0; if (invoke->GetOriginalInvokeType() != InvokeType::kStatic) { // Instance call. - Temporaries temps(graph_); HInstruction* arg = LoadLocal( is_range ? register_index : args[0], Primitive::kPrimNot, invoke->GetDexPc()); HNullCheck* null_check = new (arena_) HNullCheck(arg, invoke->GetDexPc()); current_block_->AddInstruction(null_check); - temps.Add(null_check); invoke->SetArgumentAt(0, null_check); start_index = 1; argument_index = 1; @@ -1337,9 +1240,6 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, ? GetFieldAccessType(*dex_file_, field_index) : resolved_field->GetTypeAsPrimitiveType(); if (is_put) { - Temporaries temps(graph_); - // We need one temporary for the null check. - temps.Add(null_check); HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc); HInstruction* field_set = nullptr; if (resolved_field == nullptr) { @@ -1524,8 +1424,6 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, uint16_t class_def_index = klass->GetDexClassDefIndex(); if (is_put) { // We need to keep the class alive before loading the value. - Temporaries temps(graph_); - temps.Add(cls); HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc); DCHECK_EQ(value->GetType(), field_type); current_block_->AddInstruction(new (arena_) HStaticFieldSet(cls, @@ -1578,9 +1476,7 @@ void HGraphBuilder::BuildCheckedDivRem(uint16_t out_vreg, || (type == Primitive::kPrimInt && second->AsIntConstant()->GetValue() == 0) || (type == Primitive::kPrimLong && second->AsLongConstant()->GetValue() == 0)) { second = new (arena_) HDivZeroCheck(second, dex_pc); - Temporaries temps(graph_); current_block_->AddInstruction(second); - temps.Add(current_block_->GetLastInstruction()); } if (isDiv) { @@ -1599,21 +1495,15 @@ void HGraphBuilder::BuildArrayAccess(const Instruction& instruction, uint8_t array_reg = instruction.VRegB_23x(); uint8_t index_reg = instruction.VRegC_23x(); - // We need one temporary for the null check, one for the index, and one for the length. - Temporaries temps(graph_); - HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot, dex_pc); object = new (arena_) HNullCheck(object, dex_pc); current_block_->AddInstruction(object); - temps.Add(object); HInstruction* length = new (arena_) HArrayLength(object, dex_pc); current_block_->AddInstruction(length); - temps.Add(length); HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt, dex_pc); index = new (arena_) HBoundsCheck(index, length, dex_pc); current_block_->AddInstruction(index); - temps.Add(index); if (is_put) { HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type, dex_pc); // TODO: Insert a type check node if the type is Object. @@ -1654,8 +1544,6 @@ void HGraphBuilder::BuildFilledNewArray(uint32_t dex_pc, bool is_reference_array = (primitive == 'L') || (primitive == '['); Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt; - Temporaries temps(graph_); - temps.Add(object); for (size_t i = 0; i < number_of_vreg_arguments; ++i) { HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type, dex_pc); HInstruction* index = graph_->GetIntConstant(i, dex_pc); @@ -1680,11 +1568,9 @@ void HGraphBuilder::BuildFillArrayData(HInstruction* object, } void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) { - Temporaries temps(graph_); HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot, dex_pc); HNullCheck* null_check = new (arena_) HNullCheck(array, dex_pc); current_block_->AddInstruction(null_check); - temps.Add(null_check); HInstruction* length = new (arena_) HArrayLength(null_check, dex_pc); current_block_->AddInstruction(length); @@ -1801,10 +1687,6 @@ void HGraphBuilder::BuildTypeCheck(const Instruction& instruction, compiler_driver_->CanAssumeTypeIsPresentInDexCache(dex_file, type_index)); current_block_->AddInstruction(cls); - // The class needs a temporary before being used by the type check. - Temporaries temps(graph_); - temps.Add(cls); - TypeCheckKind check_kind = ComputeTypeCheckKind(resolved_class); if (instruction.Opcode() == Instruction::INSTANCE_OF) { current_block_->AddInstruction(new (arena_) HInstanceOf(object, cls, check_kind, dex_pc)); @@ -2883,8 +2765,6 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 case Instruction::ARRAY_LENGTH: { HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot, dex_pc); - // No need for a temporary for the null check, it is the only input of the following - // instruction. object = new (arena_) HNullCheck(object, dex_pc); current_block_->AddInstruction(object); current_block_->AddInstruction(new (arena_) HArrayLength(object, dex_pc)); |