diff options
Diffstat (limited to 'compiler/optimizing/builder.cc')
-rw-r--r-- | compiler/optimizing/builder.cc | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 955deaa0ae..c50960666a 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -190,37 +190,37 @@ void HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) { template<typename T> void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_pc) { int32_t target_offset = instruction.GetTargetOffset(); - PotentiallyAddSuspendCheck(target_offset, dex_pc); + HBasicBlock* branch_target = FindBlockStartingAt(dex_pc + target_offset); + HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits()); + DCHECK(branch_target != nullptr); + DCHECK(fallthrough_target != nullptr); + PotentiallyAddSuspendCheck(branch_target, dex_pc); HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt); HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); T* comparison = new (arena_) T(first, second); current_block_->AddInstruction(comparison); HInstruction* ifinst = new (arena_) HIf(comparison); current_block_->AddInstruction(ifinst); - HBasicBlock* target = FindBlockStartingAt(dex_pc + target_offset); - DCHECK(target != nullptr); - current_block_->AddSuccessor(target); - target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits()); - DCHECK(target != nullptr); - current_block_->AddSuccessor(target); + current_block_->AddSuccessor(branch_target); + current_block_->AddSuccessor(fallthrough_target); current_block_ = nullptr; } template<typename T> void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc) { int32_t target_offset = instruction.GetTargetOffset(); - PotentiallyAddSuspendCheck(target_offset, dex_pc); + HBasicBlock* branch_target = FindBlockStartingAt(dex_pc + target_offset); + HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits()); + DCHECK(branch_target != nullptr); + DCHECK(fallthrough_target != nullptr); + PotentiallyAddSuspendCheck(branch_target, dex_pc); HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt); T* comparison = new (arena_) T(value, GetIntConstant(0)); current_block_->AddInstruction(comparison); HInstruction* ifinst = new (arena_) HIf(comparison); current_block_->AddInstruction(ifinst); - HBasicBlock* target = FindBlockStartingAt(dex_pc + target_offset); - DCHECK(target != nullptr); - current_block_->AddSuccessor(target); - target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits()); - DCHECK(target != nullptr); - current_block_->AddSuccessor(target); + current_block_->AddSuccessor(branch_target); + current_block_->AddSuccessor(fallthrough_target); current_block_ = nullptr; } @@ -847,7 +847,10 @@ void HGraphBuilder::BuildFilledNewArray(uint32_t dex_pc, uint32_t* args, uint32_t register_index) { HInstruction* length = GetIntConstant(number_of_vreg_arguments); - HInstruction* object = new (arena_) HNewArray(length, dex_pc, type_index); + QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index) + ? kQuickAllocArrayWithAccessCheck + : kQuickAllocArray; + HInstruction* object = new (arena_) HNewArray(length, dex_pc, type_index, entrypoint); current_block_->AddInstruction(object); const char* descriptor = dex_file_->StringByTypeIdx(type_index); @@ -987,6 +990,11 @@ bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction, return true; } +bool HGraphBuilder::NeedsAccessCheck(uint32_t type_index) const { + return !compiler_driver_->CanAccessInstantiableTypeWithoutChecks( + dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index); +} + void HGraphBuilder::BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc) { SwitchTable table(instruction, dex_pc, false); @@ -1026,7 +1034,9 @@ void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t bool is_last_case, const SwitchTable& table, HInstruction* value, int32_t case_value_int, int32_t target_offset, uint32_t dex_pc) { - PotentiallyAddSuspendCheck(target_offset, dex_pc); + HBasicBlock* case_target = FindBlockStartingAt(dex_pc + target_offset); + DCHECK(case_target != nullptr); + PotentiallyAddSuspendCheck(case_target, dex_pc); // The current case's value. HInstruction* this_case_value = GetIntConstant(case_value_int); @@ -1038,8 +1048,6 @@ void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t current_block_->AddInstruction(ifinst); // Case hit: use the target offset to determine where to go. - HBasicBlock* case_target = FindBlockStartingAt(dex_pc + target_offset); - DCHECK(case_target != nullptr); current_block_->AddSuccessor(case_target); // Case miss: go to the next case (or default fall-through). @@ -1064,10 +1072,19 @@ void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t } } -void HGraphBuilder::PotentiallyAddSuspendCheck(int32_t target_offset, uint32_t dex_pc) { +void HGraphBuilder::PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc) { + int32_t target_offset = target->GetDexPc() - dex_pc; if (target_offset <= 0) { - // Unconditionnally add a suspend check to backward branches. We can remove - // them after we recognize loops in the graph. + // DX generates back edges to the first encountered return. We can save + // time of later passes by not adding redundant suspend checks. + HInstruction* last_in_target = target->GetLastInstruction(); + if (last_in_target != nullptr && + (last_in_target->IsReturn() || last_in_target->IsReturnVoid())) { + return; + } + + // Add a suspend check to backward branches which may potentially loop. We + // can remove them after we recognize loops in the graph. current_block_->AddInstruction(new (arena_) HSuspendCheck(dex_pc)); } } @@ -1189,9 +1206,9 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 case Instruction::GOTO_16: case Instruction::GOTO_32: { int32_t offset = instruction.GetTargetOffset(); - PotentiallyAddSuspendCheck(offset, dex_pc); HBasicBlock* target = FindBlockStartingAt(offset + dex_pc); DCHECK(target != nullptr); + PotentiallyAddSuspendCheck(target, dex_pc); current_block_->AddInstruction(new (arena_) HGoto()); current_block_->AddSuccessor(target); current_block_ = nullptr; @@ -1772,16 +1789,24 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 } case Instruction::NEW_INSTANCE: { - current_block_->AddInstruction( - new (arena_) HNewInstance(dex_pc, instruction.VRegB_21c())); + uint16_t type_index = instruction.VRegB_21c(); + QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index) + ? kQuickAllocObjectWithAccessCheck + : kQuickAllocObject; + + current_block_->AddInstruction(new (arena_) HNewInstance(dex_pc, type_index, entrypoint)); UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); break; } case Instruction::NEW_ARRAY: { + uint16_t type_index = instruction.VRegC_22c(); HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt); + QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index) + ? kQuickAllocArrayWithAccessCheck + : kQuickAllocArray; current_block_->AddInstruction( - new (arena_) HNewArray(length, dex_pc, instruction.VRegC_22c())); + new (arena_) HNewArray(length, dex_pc, type_index, entrypoint)); UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction()); break; } |