diff options
Diffstat (limited to 'compiler/optimizing/code_generator.cc')
-rw-r--r-- | compiler/optimizing/code_generator.cc | 82 |
1 files changed, 68 insertions, 14 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 6f424ce11d..9665b0e2ae 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -54,6 +54,7 @@ void CodeGenerator::CompileBaseline(CodeAllocator* allocator, bool is_leaf) { + GetGraph()->GetTemporariesVRegSlots() + 1 /* filler */, 0, /* the baseline compiler does not have live registers at slow path */ + 0, /* the baseline compiler does not have live registers at slow path */ GetGraph()->GetMaximumNumberOfOutVRegs() + 1 /* current method */); GenerateFrameEntry(); @@ -136,14 +137,16 @@ size_t CodeGenerator::FindTwoFreeConsecutiveAlignedEntries(bool* array, size_t l } void CodeGenerator::ComputeFrameSize(size_t number_of_spill_slots, - size_t maximum_number_of_live_registers, + size_t maximum_number_of_live_core_registers, + size_t maximum_number_of_live_fp_registers, size_t number_of_out_slots) { first_register_slot_in_slow_path_ = (number_of_out_slots + number_of_spill_slots) * kVRegSize; SetFrameSize(RoundUp( number_of_spill_slots * kVRegSize + number_of_out_slots * kVRegSize - + maximum_number_of_live_registers * GetWordSize() + + maximum_number_of_live_core_registers * GetWordSize() + + maximum_number_of_live_fp_registers * GetFloatingPointSpillSlotSize() + FrameEntrySpillSize(), kStackAlignment)); } @@ -325,24 +328,27 @@ bool CodeGenerator::GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) con return current->GetBlockId() + 1 == next->GetBlockId(); } -CodeGenerator* CodeGenerator::Create(ArenaAllocator* allocator, - HGraph* graph, - InstructionSet instruction_set) { +CodeGenerator* CodeGenerator::Create(HGraph* graph, + InstructionSet instruction_set, + const InstructionSetFeatures& isa_features, + const CompilerOptions& compiler_options) { switch (instruction_set) { case kArm: case kThumb2: { - return new (allocator) arm::CodeGeneratorARM(graph); + return new arm::CodeGeneratorARM(graph, + *isa_features.AsArmInstructionSetFeatures(), + compiler_options); } case kArm64: { - return new (allocator) arm64::CodeGeneratorARM64(graph); + return new arm64::CodeGeneratorARM64(graph, compiler_options); } case kMips: return nullptr; case kX86: { - return new (allocator) x86::CodeGeneratorX86(graph); + return new x86::CodeGeneratorX86(graph, compiler_options); } case kX86_64: { - return new (allocator) x86_64::CodeGeneratorX86_64(graph); + return new x86_64::CodeGeneratorX86_64(graph, compiler_options); } default: return nullptr; @@ -374,7 +380,7 @@ void CodeGenerator::BuildNativeGCMap( } } -void CodeGenerator::BuildMappingTable(std::vector<uint8_t>* data, SrcMap* src_map) const { +void CodeGenerator::BuildMappingTable(std::vector<uint8_t>* data, DefaultSrcMap* src_map) const { uint32_t pc2dex_data_size = 0u; uint32_t pc2dex_entries = pc_infos_.Size(); uint32_t pc2dex_offset = 0u; @@ -618,12 +624,62 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction, uint32_t dex_pc) { break; } + case Location::kFpuRegisterPair : { + stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInFpuRegister, location.low()); + stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInFpuRegister, location.high()); + ++i; + DCHECK_LT(i, environment_size); + break; + } + + case Location::kRegisterPair : { + stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInRegister, location.low()); + stack_map_stream_.AddDexRegisterEntry(DexRegisterMap::kInRegister, location.high()); + ++i; + DCHECK_LT(i, environment_size); + break; + } + default: LOG(FATAL) << "Unexpected kind " << location.GetKind(); } } } +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_; @@ -684,11 +740,9 @@ void CodeGenerator::ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend } void CodeGenerator::EmitParallelMoves(Location from1, Location to1, Location from2, Location to2) { - MoveOperands move1(from1, to1, nullptr); - MoveOperands move2(from2, to2, nullptr); HParallelMove parallel_move(GetGraph()->GetArena()); - parallel_move.AddMove(&move1); - parallel_move.AddMove(&move2); + parallel_move.AddMove(from1, to1, nullptr); + parallel_move.AddMove(from2, to2, nullptr); GetMoveResolver()->EmitNativeCode(¶llel_move); } |