diff options
| author | 2016-09-12 15:48:22 +0000 | |
|---|---|---|
| committer | 2016-09-12 15:48:23 +0000 | |
| commit | 6ee9a333553b7e7268b5bdab14974475ff385106 (patch) | |
| tree | ed38b36182bfb48bf8f5aed5c7f3fd78aaea2c48 /compiler/optimizing/code_generator.cc | |
| parent | a5d718a9f8ef51e41a1485a0f6ab201aec4c0c82 (diff) | |
| parent | 7aa7560683626c7893011271c241b3265ded1dc3 (diff) | |
Merge "Use implicit null checks inside try blocks."
Diffstat (limited to 'compiler/optimizing/code_generator.cc')
| -rw-r--r-- | compiler/optimizing/code_generator.cc | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 2087888f4e..ac7d5fe427 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -1081,13 +1081,6 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo } } -bool CodeGenerator::IsImplicitNullCheckAllowed(HNullCheck* null_check) const { - return compiler_options_.GetImplicitNullChecks() && - // Null checks which might throw into a catch block need to save live - // registers and therefore cannot be done implicitly. - !null_check->CanThrowIntoCatchBlock(); -} - bool CodeGenerator::CanMoveNullCheckToUser(HNullCheck* null_check) { HInstruction* first_next_not_move = null_check->GetNextDisregardingMoves(); @@ -1096,6 +1089,10 @@ bool CodeGenerator::CanMoveNullCheckToUser(HNullCheck* null_check) { } void CodeGenerator::MaybeRecordImplicitNullCheck(HInstruction* instr) { + if (!compiler_options_.GetImplicitNullChecks()) { + return; + } + // 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. @@ -1114,16 +1111,31 @@ void CodeGenerator::MaybeRecordImplicitNullCheck(HInstruction* instr) { // 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(); - if (IsImplicitNullCheckAllowed(null_check)) { - // 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()); - } + // 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()); } } +LocationSummary* CodeGenerator::CreateNullCheckLocations(HNullCheck* null_check) { + // Note: Using kNoCall allows the method to be treated as leaf (and eliminate the + // HSuspendCheck from entry block). However, it will still get a valid stack frame + // because the HNullCheck needs an environment. + LocationSummary::CallKind call_kind = LocationSummary::kNoCall; + // When throwing from a try block, we may need to retrieve dalvik registers from + // physical registers. For implicit null checks, this is done by using kSaveEverything + // runtime method but for explicit null checks we need to save live registers. + if (!compiler_options_.GetImplicitNullChecks() && null_check->CanThrowIntoCatchBlock()) { + call_kind = LocationSummary::kCallOnSlowPath; + } + LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(null_check, call_kind); + locations->SetInAt(0, Location::RequiresRegister()); + DCHECK(!null_check->HasUses()); + return locations; +} + void CodeGenerator::GenerateNullCheck(HNullCheck* instruction) { - if (IsImplicitNullCheckAllowed(instruction)) { + if (compiler_options_.GetImplicitNullChecks()) { MaybeRecordStat(kImplicitNullCheckGenerated); GenerateImplicitNullCheck(instruction); } else { |