diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/compiled_method.h | 6 | ||||
| -rw-r--r-- | compiler/driver/compiler_driver.cc | 4 | ||||
| -rw-r--r-- | compiler/elf_builder.h | 81 | ||||
| -rw-r--r-- | compiler/elf_writer.h | 3 | ||||
| -rw-r--r-- | compiler/elf_writer_debug.cc | 94 | ||||
| -rw-r--r-- | compiler/elf_writer_debug.h | 10 | ||||
| -rw-r--r-- | compiler/elf_writer_quick.cc | 67 | ||||
| -rw-r--r-- | compiler/optimizing/bounds_check_elimination.cc | 41 | ||||
| -rw-r--r-- | compiler/optimizing/induction_var_range.cc | 9 | ||||
| -rw-r--r-- | compiler/optimizing/induction_var_range.h | 32 | ||||
| -rw-r--r-- | compiler/optimizing/nodes.cc | 1 | 
11 files changed, 232 insertions, 116 deletions
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h index 7a93613481..58876200ca 100644 --- a/compiler/compiled_method.h +++ b/compiler/compiled_method.h @@ -283,11 +283,13 @@ class LinkerPatch {      static_assert(sizeof(element_offset_) == sizeof(cmp1_), "needed by relational operators");    };    union { -    uint32_t cmp2_;             // Used for relational operators. +    // Note: To avoid uninitialized padding on 64-bit systems, we use `size_t` for `cmp2_`. +    // This allows a hashing function to treat an array of linker patches as raw memory. +    size_t cmp2_;             // Used for relational operators.      // Literal offset of the insn loading PC (same as literal_offset if it's the same insn,      // may be different if the PC-relative addressing needs multiple insns).      uint32_t pc_insn_offset_; -    static_assert(sizeof(pc_insn_offset_) == sizeof(cmp2_), "needed by relational operators"); +    static_assert(sizeof(pc_insn_offset_) <= sizeof(cmp2_), "needed by relational operators");    };    friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs); diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 6bc2a13299..f078bf6507 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -2306,9 +2306,9 @@ class SetVerifiedClassVisitor : public CompilationVisitor {            mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, soa.Self());            // Mark methods as pre-verified. If we don't do this, the interpreter will run with            // access checks. -          klass->SetPreverifiedFlagOnAllMethods( +          klass->SetSkipAccessChecksFlagOnAllMethods(                GetInstructionSetPointerSize(manager_->GetCompiler()->GetInstructionSet())); -          klass->SetPreverified(); +          klass->SetVerificationAttempted();          }          // Record the final class status if necessary.          ClassReference ref(manager_->GetDexFile(), class_def_index); diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h index 3d24d19919..b673eeb3b6 100644 --- a/compiler/elf_builder.h +++ b/compiler/elf_builder.h @@ -110,18 +110,27 @@ class ElfBuilder FINAL {        CHECK(sections.empty() || sections.back()->finished_);        // The first ELF section index is 1. Index 0 is reserved for NULL.        section_index_ = sections.size() + 1; -      // Push this section on the list of written sections. -      sections.push_back(this); +      // Page-align if we switch between allocated and non-allocated sections, +      // or if we change the type of allocation (e.g. executable vs non-executable). +      if (!sections.empty()) { +        if (header_.sh_flags != sections.back()->header_.sh_flags) { +          header_.sh_addralign = kPageSize; +        } +      }        // Align file position.        if (header_.sh_type != SHT_NOBITS) { -        header_.sh_offset = RoundUp(owner_->stream_.Seek(0, kSeekCurrent), header_.sh_addralign); -        owner_->stream_.Seek(header_.sh_offset, kSeekSet); +        header_.sh_offset = owner_->AlignFileOffset(header_.sh_addralign); +      } else { +        header_.sh_offset = 0;        }        // Align virtual memory address.        if ((header_.sh_flags & SHF_ALLOC) != 0) { -        header_.sh_addr = RoundUp(owner_->virtual_address_, header_.sh_addralign); -        owner_->virtual_address_ = header_.sh_addr; +        header_.sh_addr = owner_->AlignVirtualAddress(header_.sh_addralign); +      } else { +        header_.sh_addr = 0;        } +      // Push this section on the list of written sections. +      sections.push_back(this);      }      // Finish writing of this section. @@ -170,8 +179,8 @@ class ElfBuilder FINAL {      // and it will be zero-initialized when the ELF file is loaded in the running program.      void WriteNoBitsSection(Elf_Word size) {        DCHECK_NE(header_.sh_flags & SHF_ALLOC, 0u); -      Start();        header_.sh_type = SHT_NOBITS; +      Start();        header_.sh_size = size;        End();      } @@ -293,12 +302,13 @@ class ElfBuilder FINAL {          dynamic_(this, ".dynamic", SHT_DYNAMIC, SHF_ALLOC, &dynstr_, 0, kPageSize, sizeof(Elf_Dyn)),          eh_frame_(this, ".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),          eh_frame_hdr_(this, ".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0), -        strtab_(this, ".strtab", 0, kPageSize), +        strtab_(this, ".strtab", 0, 1),          symtab_(this, ".symtab", SHT_SYMTAB, 0, &strtab_),          debug_frame_(this, ".debug_frame", SHT_PROGBITS, 0, nullptr, 0, sizeof(Elf_Addr), 0),          debug_info_(this, ".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0),          debug_line_(this, ".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0),          shstrtab_(this, ".shstrtab", 0, 1), +        started_(false),          virtual_address_(0) {      text_.phdr_flags_ = PF_R | PF_X;      bss_.phdr_flags_ = PF_R | PF_W; @@ -351,22 +361,25 @@ class ElfBuilder FINAL {      other_sections_.push_back(std::move(s));    } -  // Set where the next section will be allocated in the virtual address space. -  void SetVirtualAddress(Elf_Addr address) { -    DCHECK_GE(address, virtual_address_); -    virtual_address_ = address; -  } - -  void Start() { -    // Reserve space for ELF header and program headers. -    // We do not know the number of headers until later, so -    // it is easiest to just reserve a fixed amount of space. -    int size = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * kMaxProgramHeaders; +  // Reserve space for ELF header and program headers. +  // We do not know the number of headers until later, so +  // it is easiest to just reserve a fixed amount of space. +  // Program headers are required for loading by the linker. +  // It is possible to omit them for ELF files used for debugging. +  void Start(bool write_program_headers = true) { +    int size = sizeof(Elf_Ehdr); +    if (write_program_headers) { +      size += sizeof(Elf_Phdr) * kMaxProgramHeaders; +    }      stream_.Seek(size, kSeekSet); +    started_ = true;      virtual_address_ += size; +    write_program_headers_ = write_program_headers;    }    void End() { +    DCHECK(started_); +      // Write section names and finish the section headers.      shstrtab_.Start();      shstrtab_.Write(""); @@ -386,8 +399,7 @@ class ElfBuilder FINAL {        shdrs.push_back(section->header_);      }      Elf_Off section_headers_offset; -    section_headers_offset = RoundUp(stream_.Seek(0, kSeekCurrent), sizeof(Elf_Off)); -    stream_.Seek(section_headers_offset, kSeekSet); +    section_headers_offset = AlignFileOffset(sizeof(Elf_Off));      stream_.WriteFully(shdrs.data(), shdrs.size() * sizeof(shdrs[0]));      // Flush everything else before writing the program headers. This should prevent @@ -395,14 +407,21 @@ class ElfBuilder FINAL {      // and partially written data if we suddenly lose power, for example.      stream_.Flush(); -    // Write the initial file headers. -    std::vector<Elf_Phdr> phdrs = MakeProgramHeaders(); +    // The main ELF header.      Elf_Ehdr elf_header = MakeElfHeader(isa_); -    elf_header.e_phoff = sizeof(Elf_Ehdr);      elf_header.e_shoff = section_headers_offset; -    elf_header.e_phnum = phdrs.size();      elf_header.e_shnum = shdrs.size();      elf_header.e_shstrndx = shstrtab_.GetSectionIndex(); + +    // Program headers (i.e. mmap instructions). +    std::vector<Elf_Phdr> phdrs; +    if (write_program_headers_) { +      phdrs = MakeProgramHeaders(); +      CHECK_LE(phdrs.size(), kMaxProgramHeaders); +      elf_header.e_phoff = sizeof(Elf_Ehdr); +      elf_header.e_phnum = phdrs.size(); +    } +      stream_.Seek(0, kSeekSet);      stream_.WriteFully(&elf_header, sizeof(elf_header));      stream_.WriteFully(phdrs.data(), phdrs.size() * sizeof(phdrs[0])); @@ -492,6 +511,14 @@ class ElfBuilder FINAL {      return &stream_;    } +  off_t AlignFileOffset(size_t alignment) { +     return stream_.Seek(RoundUp(stream_.Seek(0, kSeekCurrent), alignment), kSeekSet); +  } + +  Elf_Addr AlignVirtualAddress(size_t alignment) { +     return virtual_address_ = RoundUp(virtual_address_, alignment); +  } +   private:    static Elf_Ehdr MakeElfHeader(InstructionSet isa) {      Elf_Ehdr elf_header = Elf_Ehdr(); @@ -666,9 +693,13 @@ class ElfBuilder FINAL {    // List of used section in the order in which they were written.    std::vector<Section*> sections_; +  bool started_; +    // Used for allocation of virtual address space.    Elf_Addr virtual_address_; +  size_t write_program_headers_; +    DISALLOW_COPY_AND_ASSIGN(ElfBuilder);  }; diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h index c5a0fd50bd..5dbf7360f8 100644 --- a/compiler/elf_writer.h +++ b/compiler/elf_writer.h @@ -52,6 +52,9 @@ class ElfWriter {    virtual ~ElfWriter() {}    virtual void Start() = 0; +  virtual void PrepareDebugInfo(size_t rodata_section_size, +                                size_t text_section_size, +                                const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) = 0;    virtual OutputStream* StartRoData() = 0;    virtual void EndRoData(OutputStream* rodata) = 0;    virtual OutputStream* StartText() = 0; diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc index d1f50073a0..e2481b061c 100644 --- a/compiler/elf_writer_debug.cc +++ b/compiler/elf_writer_debug.cc @@ -1148,13 +1148,19 @@ class DebugInfoWriter {      writer.Write(types);    } -  void End() { +  void End(bool write_oat_patches) {      builder_->GetDebugInfo()->End(); -    builder_->WritePatches(".debug_info.oat_patches", -                           ArrayRef<const uintptr_t>(debug_info_patches_)); +    if (write_oat_patches) { +      builder_->WritePatches(".debug_info.oat_patches", +                             ArrayRef<const uintptr_t>(debug_info_patches_)); +    }      builder_->WriteSection(".debug_abbrev", &debug_abbrev_buffer_); -    builder_->WriteSection(".debug_loc", &debug_loc_); -    builder_->WriteSection(".debug_ranges", &debug_ranges_); +    if (!debug_loc_.empty()) { +      builder_->WriteSection(".debug_loc", &debug_loc_); +    } +    if (!debug_ranges_.empty()) { +      builder_->WriteSection(".debug_ranges", &debug_ranges_); +    }    }   private: @@ -1357,10 +1363,12 @@ class DebugLineWriter {      return buffer.size();    } -  void End() { +  void End(bool write_oat_patches) {      builder_->GetDebugLine()->End(); -    builder_->WritePatches(".debug_line.oat_patches", -                           ArrayRef<const uintptr_t>(debug_line_patches)); +    if (write_oat_patches) { +      builder_->WritePatches(".debug_line.oat_patches", +                             ArrayRef<const uintptr_t>(debug_line_patches)); +    }    }   private: @@ -1370,7 +1378,8 @@ class DebugLineWriter {  template<typename ElfTypes>  static void WriteDebugSections(ElfBuilder<ElfTypes>* builder, -                               const ArrayRef<const MethodDebugInfo>& method_infos) { +                               const ArrayRef<const MethodDebugInfo>& method_infos, +                               bool write_oat_patches) {    // Group the methods into compilation units based on source file.    std::vector<CompilationUnit> compilation_units;    const char* last_source_file = nullptr; @@ -1394,7 +1403,7 @@ static void WriteDebugSections(ElfBuilder<ElfTypes>* builder,      for (auto& compilation_unit : compilation_units) {        line_writer.WriteCompilationUnit(compilation_unit);      } -    line_writer.End(); +    line_writer.End(write_oat_patches);    }    // Write .debug_info section. @@ -1404,7 +1413,7 @@ static void WriteDebugSections(ElfBuilder<ElfTypes>* builder,      for (const auto& compilation_unit : compilation_units) {        info_writer.WriteCompilationUnit(compilation_unit);      } -    info_writer.End(); +    info_writer.End(write_oat_patches);    }  } @@ -1484,13 +1493,14 @@ static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,  template <typename ElfTypes>  void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,                      const ArrayRef<const MethodDebugInfo>& method_infos, -                    CFIFormat cfi_format) { +                    CFIFormat cfi_format, +                    bool write_oat_patches) {    // Add methods to .symtab.    WriteDebugSymbols(builder, method_infos, true /* with_signature */);    // Generate CFI (stack unwinding information). -  WriteCFISection(builder, method_infos, cfi_format, true /* write_oat_patches */); +  WriteCFISection(builder, method_infos, cfi_format, write_oat_patches);    // Write DWARF .debug_* sections. -  WriteDebugSections(builder, method_infos); +  WriteDebugSections(builder, method_infos, write_oat_patches);  }  static void XzCompress(const std::vector<uint8_t>* src, std::vector<uint8_t>* dst) { @@ -1539,20 +1549,20 @@ static void XzCompress(const std::vector<uint8_t>* src, std::vector<uint8_t>* ds  }  template <typename ElfTypes> -void WriteMiniDebugInfo(ElfBuilder<ElfTypes>* parent_builder, -                        const ArrayRef<const MethodDebugInfo>& method_infos) { -  const InstructionSet isa = parent_builder->GetIsa(); +std::vector<uint8_t> MakeMiniDebugInfoInternal( +    InstructionSet isa, +    size_t rodata_section_size, +    size_t text_section_size, +    const ArrayRef<const MethodDebugInfo>& method_infos) {    std::vector<uint8_t> buffer;    buffer.reserve(KB);    VectorOutputStream out("Mini-debug-info ELF file", &buffer);    std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));    builder->Start(); -  // Write .rodata and .text as NOBITS sections. -  // This allows tools to detect virtual address relocation of the parent ELF file. -  builder->SetVirtualAddress(parent_builder->GetRoData()->GetAddress()); -  builder->GetRoData()->WriteNoBitsSection(parent_builder->GetRoData()->GetSize()); -  builder->SetVirtualAddress(parent_builder->GetText()->GetAddress()); -  builder->GetText()->WriteNoBitsSection(parent_builder->GetText()->GetSize()); +  // Mirror .rodata and .text as NOBITS sections. +  // It is needed to detected relocations after compression. +  builder->GetRoData()->WriteNoBitsSection(rodata_section_size); +  builder->GetText()->WriteNoBitsSection(text_section_size);    WriteDebugSymbols(builder.get(), method_infos, false /* with_signature */);    WriteCFISection(builder.get(), method_infos, DW_DEBUG_FRAME_FORMAT, false /* write_oat_paches */);    builder->End(); @@ -1560,7 +1570,19 @@ void WriteMiniDebugInfo(ElfBuilder<ElfTypes>* parent_builder,    std::vector<uint8_t> compressed_buffer;    compressed_buffer.reserve(buffer.size() / 4);    XzCompress(&buffer, &compressed_buffer); -  parent_builder->WriteSection(".gnu_debugdata", &compressed_buffer); +  return compressed_buffer; +} + +std::vector<uint8_t> MakeMiniDebugInfo( +    InstructionSet isa, +    size_t rodata_size, +    size_t text_size, +    const ArrayRef<const MethodDebugInfo>& method_infos) { +  if (Is64BitInstructionSet(isa)) { +    return MakeMiniDebugInfoInternal<ElfTypes64>(isa, rodata_size, text_size, method_infos); +  } else { +    return MakeMiniDebugInfoInternal<ElfTypes32>(isa, rodata_size, text_size, method_infos); +  }  }  template <typename ElfTypes> @@ -1571,10 +1593,12 @@ static ArrayRef<const uint8_t> WriteDebugElfFileForMethodInternal(    buffer.reserve(KB);    VectorOutputStream out("Debug ELF file", &buffer);    std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out)); -  builder->Start(); +  // No program headers since the ELF file is not linked and has no allocated sections. +  builder->Start(false /* write_program_headers */);    WriteDebugInfo(builder.get(),                   ArrayRef<const MethodDebugInfo>(&method_info, 1), -                 DW_DEBUG_FRAME_FORMAT); +                 DW_DEBUG_FRAME_FORMAT, +                 false /* write_oat_patches */);    builder->End();    CHECK(builder->Good());    // Make a copy of the buffer.  We want to shrink it anyway. @@ -1601,12 +1625,12 @@ static ArrayRef<const uint8_t> WriteDebugElfFileForClassesInternal(    buffer.reserve(KB);    VectorOutputStream out("Debug ELF file", &buffer);    std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out)); -  builder->Start(); - +  // No program headers since the ELF file is not linked and has no allocated sections. +  builder->Start(false /* write_program_headers */);    DebugInfoWriter<ElfTypes> info_writer(builder.get());    info_writer.Start();    info_writer.WriteTypes(types); -  info_writer.End(); +  info_writer.End(false /* write_oat_patches */);    builder->End();    CHECK(builder->Good()); @@ -1630,17 +1654,13 @@ ArrayRef<const uint8_t> WriteDebugElfFileForClasses(const InstructionSet isa,  template void WriteDebugInfo<ElfTypes32>(      ElfBuilder<ElfTypes32>* builder,      const ArrayRef<const MethodDebugInfo>& method_infos, -    CFIFormat cfi_format); +    CFIFormat cfi_format, +    bool write_oat_patches);  template void WriteDebugInfo<ElfTypes64>(      ElfBuilder<ElfTypes64>* builder,      const ArrayRef<const MethodDebugInfo>& method_infos, -    CFIFormat cfi_format); -template void WriteMiniDebugInfo<ElfTypes32>( -    ElfBuilder<ElfTypes32>* builder, -    const ArrayRef<const MethodDebugInfo>& method_infos); -template void WriteMiniDebugInfo<ElfTypes64>( -    ElfBuilder<ElfTypes64>* builder, -    const ArrayRef<const MethodDebugInfo>& method_infos); +    CFIFormat cfi_format, +    bool write_oat_patches);  }  // namespace dwarf  }  // namespace art diff --git a/compiler/elf_writer_debug.h b/compiler/elf_writer_debug.h index e19da088da..e289197971 100644 --- a/compiler/elf_writer_debug.h +++ b/compiler/elf_writer_debug.h @@ -33,11 +33,13 @@ struct MethodDebugInfo;  template <typename ElfTypes>  void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,                      const ArrayRef<const MethodDebugInfo>& method_infos, -                    CFIFormat cfi_format); +                    CFIFormat cfi_format, +                    bool write_oat_patches); -template <typename ElfTypes> -void WriteMiniDebugInfo(ElfBuilder<ElfTypes>* builder, -                        const ArrayRef<const MethodDebugInfo>& method_infos); +std::vector<uint8_t> MakeMiniDebugInfo(InstructionSet isa, +                                       size_t rodata_section_size, +                                       size_t text_section_size, +                                       const ArrayRef<const MethodDebugInfo>& method_infos);  ArrayRef<const uint8_t> WriteDebugElfFileForMethod(const dwarf::MethodDebugInfo& method_info); diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc index 6bf080a083..759a6d633a 100644 --- a/compiler/elf_writer_quick.cc +++ b/compiler/elf_writer_quick.cc @@ -33,6 +33,8 @@  #include "leb128.h"  #include "linker/buffered_output_stream.h"  #include "linker/file_output_stream.h" +#include "thread-inl.h" +#include "thread_pool.h"  #include "utils.h"  namespace art { @@ -46,6 +48,37 @@ namespace art {  // Let's use .debug_frame because it is easier to strip or compress.  constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT; +class DebugInfoTask : public Task { + public: +  DebugInfoTask(InstructionSet isa, +                size_t rodata_section_size, +                size_t text_section_size, +                const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) +      : isa_(isa), +        rodata_section_size_(rodata_section_size), +        text_section_size_(text_section_size), +        method_infos_(method_infos) { +  } + +  void Run(Thread*) { +    result_ = dwarf::MakeMiniDebugInfo(isa_, +                                       rodata_section_size_, +                                       text_section_size_, +                                       method_infos_); +  } + +  std::vector<uint8_t>* GetResult() { +    return &result_; +  } + + private: +  InstructionSet isa_; +  size_t rodata_section_size_; +  size_t text_section_size_; +  const ArrayRef<const dwarf::MethodDebugInfo>& method_infos_; +  std::vector<uint8_t> result_; +}; +  template <typename ElfTypes>  class ElfWriterQuick FINAL : public ElfWriter {   public: @@ -55,6 +88,9 @@ class ElfWriterQuick FINAL : public ElfWriter {    ~ElfWriterQuick();    void Start() OVERRIDE; +  void PrepareDebugInfo(size_t rodata_section_size, +                        size_t text_section_size, +                        const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) OVERRIDE;    OutputStream* StartRoData() OVERRIDE;    void EndRoData(OutputStream* rodata) OVERRIDE;    OutputStream* StartText() OVERRIDE; @@ -75,6 +111,8 @@ class ElfWriterQuick FINAL : public ElfWriter {    File* const elf_file_;    std::unique_ptr<BufferedOutputStream> output_stream_;    std::unique_ptr<ElfBuilder<ElfTypes>> builder_; +  std::unique_ptr<DebugInfoTask> debug_info_task_; +  std::unique_ptr<ThreadPool> debug_info_thread_pool_;    DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);  }; @@ -147,15 +185,38 @@ void ElfWriterQuick<ElfTypes>::WriteDynamicSection() {  }  template <typename ElfTypes> +void ElfWriterQuick<ElfTypes>::PrepareDebugInfo( +    size_t rodata_section_size, +    size_t text_section_size, +    const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) { +  if (compiler_options_->GetGenerateMiniDebugInfo()) { +    // Prepare the mini-debug-info in background while we do other I/O. +    Thread* self = Thread::Current(); +    debug_info_task_ = std::unique_ptr<DebugInfoTask>( +        new DebugInfoTask(builder_->GetIsa(), +                          rodata_section_size, +                          text_section_size, +                          method_infos)); +    debug_info_thread_pool_ = std::unique_ptr<ThreadPool>( +        new ThreadPool("Mini-debug-info writer", 1)); +    debug_info_thread_pool_->AddTask(self, debug_info_task_.get()); +    debug_info_thread_pool_->StartWorkers(self); +  } +} + +template <typename ElfTypes>  void ElfWriterQuick<ElfTypes>::WriteDebugInfo(      const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) {    if (compiler_options_->GetGenerateDebugInfo()) {      // Generate all the debug information we can. -    dwarf::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat); +    dwarf::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat, true /* write_oat_patches */);    }    if (compiler_options_->GetGenerateMiniDebugInfo()) { -    // Generate only some information and compress it. -    dwarf::WriteMiniDebugInfo(builder_.get(), method_infos); +    // Wait for the mini-debug-info generation to finish and write it to disk. +    Thread* self = Thread::Current(); +    DCHECK(debug_info_thread_pool_ != nullptr); +    debug_info_thread_pool_->Wait(self, true, false); +    builder_->WriteSection(".gnu_debugdata", debug_info_task_->GetResult());    }  } diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc index eee6116098..c307522f2b 100644 --- a/compiler/optimizing/bounds_check_elimination.cc +++ b/compiler/optimizing/bounds_check_elimination.cc @@ -1227,27 +1227,28 @@ class BCEVisitor : public HGraphVisitor {      InductionVarRange::Value v1;      InductionVarRange::Value v2;      bool needs_finite_test = false; -    induction_range_.GetInductionRange(context, index, &v1, &v2, &needs_finite_test); -    do { -      if (v1.is_known && (v1.a_constant == 0 || v1.a_constant == 1) && -          v2.is_known && (v2.a_constant == 0 || v2.a_constant == 1)) { -        DCHECK(v1.a_constant == 1 || v1.instruction == nullptr); -        DCHECK(v2.a_constant == 1 || v2.instruction == nullptr); -        ValueRange index_range(GetGraph()->GetArena(), -                               ValueBound(v1.instruction, v1.b_constant), -                               ValueBound(v2.instruction, v2.b_constant)); -        // If analysis reveals a certain OOB, disable dynamic BCE. -        if (index_range.GetLower().LessThan(array_range->GetLower()) || -            index_range.GetUpper().GreaterThan(array_range->GetUpper())) { -          *try_dynamic_bce = false; -          return false; -        } -        // Use analysis for static bce only if loop is finite. -        if (!needs_finite_test && index_range.FitsIn(array_range)) { -          return true; +    if (induction_range_.GetInductionRange(context, index, &v1, &v2, &needs_finite_test)) { +      do { +        if (v1.is_known && (v1.a_constant == 0 || v1.a_constant == 1) && +            v2.is_known && (v2.a_constant == 0 || v2.a_constant == 1)) { +          DCHECK(v1.a_constant == 1 || v1.instruction == nullptr); +          DCHECK(v2.a_constant == 1 || v2.instruction == nullptr); +          ValueRange index_range(GetGraph()->GetArena(), +                                 ValueBound(v1.instruction, v1.b_constant), +                                 ValueBound(v2.instruction, v2.b_constant)); +          // If analysis reveals a certain OOB, disable dynamic BCE. +          if (index_range.GetLower().LessThan(array_range->GetLower()) || +              index_range.GetUpper().GreaterThan(array_range->GetUpper())) { +            *try_dynamic_bce = false; +            return false; +          } +          // Use analysis for static bce only if loop is finite. +          if (!needs_finite_test && index_range.FitsIn(array_range)) { +            return true; +          }          } -      } -    } while (induction_range_.RefineOuter(&v1, &v2)); +      } while (induction_range_.RefineOuter(&v1, &v2)); +    }      return false;    } diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc index ae15fcf381..9566c29adf 100644 --- a/compiler/optimizing/induction_var_range.cc +++ b/compiler/optimizing/induction_var_range.cc @@ -93,7 +93,7 @@ InductionVarRange::InductionVarRange(HInductionVarAnalysis* induction_analysis)    DCHECK(induction_analysis != nullptr);  } -void InductionVarRange::GetInductionRange(HInstruction* context, +bool InductionVarRange::GetInductionRange(HInstruction* context,                                            HInstruction* instruction,                                            /*out*/Value* min_val,                                            /*out*/Value* max_val, @@ -111,12 +111,9 @@ void InductionVarRange::GetInductionRange(HInstruction* context,      *min_val = GetVal(info, trip, in_body, /* is_min */ true);      *max_val = SimplifyMax(GetVal(info, trip, in_body, /* is_min */ false));      *needs_finite_test = NeedsTripCount(info) && IsUnsafeTripCount(trip); -  } else { -    // No loop to analyze. -    *min_val = Value(); -    *max_val = Value(); -    *needs_finite_test = false; +    return true;    } +  return false;  // Nothing known  }  bool InductionVarRange::RefineOuter(/*in-out*/Value* min_val, /*in-out*/Value* max_val) const { diff --git a/compiler/optimizing/induction_var_range.h b/compiler/optimizing/induction_var_range.h index 974b8fba06..3cb7b4bfd5 100644 --- a/compiler/optimizing/induction_var_range.h +++ b/compiler/optimizing/induction_var_range.h @@ -60,13 +60,13 @@ class InductionVarRange {     * Given a context denoted by the first instruction, returns a possibly conservative     * lower and upper bound on the instruction's value in the output parameters min_val     * and max_val, respectively. The need_finite_test flag denotes if an additional finite-test -   * is needed to protect the range evaluation inside its loop. +   * is needed to protect the range evaluation inside its loop. Returns false on failure.     */ -  void GetInductionRange(HInstruction* context, +  bool GetInductionRange(HInstruction* context,                           HInstruction* instruction, -                         /*out*/Value* min_val, -                         /*out*/Value* max_val, -                         /*out*/bool* needs_finite_test); +                         /*out*/ Value* min_val, +                         /*out*/ Value* max_val, +                         /*out*/ bool* needs_finite_test);    /** Refines the values with induction of next outer loop. Returns true on change. */    bool RefineOuter(/*in-out*/Value* min_val, /*in-out*/Value* max_val) const; @@ -79,8 +79,8 @@ class InductionVarRange {     */    bool CanGenerateCode(HInstruction* context,                         HInstruction* instruction, -                       /*out*/bool* needs_finite_test, -                       /*out*/bool* needs_taken_test); +                       /*out*/ bool* needs_finite_test, +                       /*out*/ bool* needs_taken_test);    /**     * Generates the actual code in the HIR for the lower and upper bound expressions on the @@ -101,8 +101,8 @@ class InductionVarRange {                           HInstruction* instruction,                           HGraph* graph,                           HBasicBlock* block, -                         /*out*/HInstruction** lower, -                         /*out*/HInstruction** upper); +                         /*out*/ HInstruction** lower, +                         /*out*/ HInstruction** upper);    /**     * Generates explicit taken-test for the loop in the given context. Code is generated in @@ -113,7 +113,7 @@ class InductionVarRange {    void GenerateTakenTest(HInstruction* context,                           HGraph* graph,                           HBasicBlock* block, -                         /*out*/HInstruction** taken_test); +                         /*out*/ HInstruction** taken_test);   private:    bool NeedsTripCount(HInductionVarAnalysis::InductionInfo* info) const; @@ -168,17 +168,17 @@ class InductionVarRange {                      HInstruction* instruction,                      HGraph* graph,                      HBasicBlock* block, -                    /*out*/HInstruction** lower, -                    /*out*/HInstruction** upper, -                    /*out*/HInstruction** taken_test, -                    /*out*/bool* needs_finite_test, -                    /*out*/bool* needs_taken_test) const; +                    /*out*/ HInstruction** lower, +                    /*out*/ HInstruction** upper, +                    /*out*/ HInstruction** taken_test, +                    /*out*/ bool* needs_finite_test, +                    /*out*/ bool* needs_taken_test) const;    bool GenerateCode(HInductionVarAnalysis::InductionInfo* info,                      HInductionVarAnalysis::InductionInfo* trip,                      HGraph* graph,                      HBasicBlock* block, -                    /*out*/HInstruction** result, +                    /*out*/ HInstruction** result,                      bool in_body,                      bool is_min) const; diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index c057eca434..3dda8501d2 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -858,7 +858,6 @@ void HEnvironment::CopyFromWithLoopPhiAdjustment(HEnvironment* env,        // At the end of the loop pre-header, the corresponding value for instruction        // is the first input of the phi.        HInstruction* initial = instruction->AsPhi()->InputAt(0); -      DCHECK(initial->GetBlock()->Dominates(loop_header));        SetRawEnvAt(i, initial);        initial->AddEnvUseAt(this, i);      } else {  |