diff options
Diffstat (limited to 'compiler/optimizing/code_generator.cc')
-rw-r--r-- | compiler/optimizing/code_generator.cc | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index cdfd989bb8..8d9a7b71e9 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -638,6 +638,40 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction, uint32_t dex_pc) { } } +bool CodeGenerator::CanMoveNullCheckToUser(HNullCheck* null_check) { + HInstruction* first_next_not_move = null_check->GetNextDisregardingMoves(); + return (first_next_not_move != nullptr) && first_next_not_move->CanDoImplicitNullCheck(); +} + +void CodeGenerator::MaybeRecordImplicitNullCheck(HInstruction* instr) { + // If we are from a static path don't record the pc as we can't throw NPE. + // NB: having the checks here makes the code much less verbose in the arch + // specific code generators. + if (instr->IsStaticFieldSet() || instr->IsStaticFieldGet()) { + return; + } + + if (!compiler_options_.GetImplicitNullChecks()) { + return; + } + + if (!instr->CanDoImplicitNullCheck()) { + return; + } + + // Find the first previous instruction which is not a move. + HInstruction* first_prev_not_move = instr->GetPreviousDisregardingMoves(); + + // If the instruction is a null check it means that `instr` is the first user + // and needs to record the pc. + if (first_prev_not_move != nullptr && first_prev_not_move->IsNullCheck()) { + HNullCheck* null_check = first_prev_not_move->AsNullCheck(); + // TODO: The parallel moves modify the environment. Their changes need to be reverted + // otherwise the stack maps at the throw point will not be correct. + RecordPcInfo(null_check, null_check->GetDexPc()); + } +} + void CodeGenerator::SaveLiveRegisters(LocationSummary* locations) { RegisterSet* register_set = locations->GetLiveRegisters(); size_t stack_offset = first_register_slot_in_slow_path_; |