summaryrefslogtreecommitdiff
path: root/compiler/optimizing/code_generator.cc
diff options
context:
space:
mode:
authorCalin Juravle <calin@google.com>2015-01-12 18:45:46 +0000
committerCalin Juravle <calin@google.com>2015-01-21 14:26:35 +0000
commit77520bca97ec44e3758510cebd0f20e3bb4584ea (patch)
tree2e3be6fdc182e5cf5ae390019457af5e9c1ed242 /compiler/optimizing/code_generator.cc
parent4d2c611bf17ff309abfa152e56c0b98a21ec8787 (diff)
Record implicit null checks at the actual invoke time.
ImplicitNullChecks are recorded only for instructions directly (see NB below) preceeded by NullChecks in the graph. This way we avoid recording redundant safepoints and minimize the code size increase. NB: ParallalelMoves might be inserted by the register allocator between the NullChecks and their uses. These modify the environment and the correct action would be to reverse their modification. This will be addressed in a follow-up CL. Change-Id: Ie50006e5a4bd22932dcf11348f5a655d253cd898
Diffstat (limited to 'compiler/optimizing/code_generator.cc')
-rw-r--r--compiler/optimizing/code_generator.cc34
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_;