diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/common_compiler_test.h | 60 | ||||
| -rw-r--r-- | compiler/image_writer.cc | 8 | ||||
| -rw-r--r-- | compiler/oat_test.cc | 3 | ||||
| -rw-r--r-- | compiler/oat_writer.cc | 55 | ||||
| -rw-r--r-- | compiler/oat_writer.h | 21 |
5 files changed, 95 insertions, 52 deletions
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h index fdf09a50a6..8bba84a9c1 100644 --- a/compiler/common_compiler_test.h +++ b/compiler/common_compiler_test.h @@ -132,34 +132,24 @@ static inline InstructionSetFeatures ParseFeatureList(std::string str) { class CommonCompilerTest : public CommonRuntimeTest { public: - static void MakeExecutable(const std::vector<uint8_t>& code) { - CHECK_NE(code.size(), 0U); - MakeExecutable(&code[0], code.size()); - } - // Create an OatMethod based on pointers (for unit tests). OatFile::OatMethod CreateOatMethod(const void* code, const size_t frame_size_in_bytes, const uint32_t core_spill_mask, const uint32_t fp_spill_mask, - const uint8_t* mapping_table, - const uint8_t* vmap_table, const uint8_t* gc_map) { + CHECK(code != nullptr); const byte* base; - uint32_t code_offset, mapping_table_offset, vmap_table_offset, gc_map_offset; - if (mapping_table == nullptr && vmap_table == nullptr && gc_map == nullptr) { + uint32_t code_offset, gc_map_offset; + if (gc_map == nullptr) { base = reinterpret_cast<const byte*>(code); // Base of data points at code. base -= kPointerSize; // Move backward so that code_offset != 0. code_offset = kPointerSize; - mapping_table_offset = 0; - vmap_table_offset = 0; gc_map_offset = 0; } else { // TODO: 64bit support. base = nullptr; // Base of data in oat file, ie 0. code_offset = PointerToLowMemUInt32(code); - mapping_table_offset = PointerToLowMemUInt32(mapping_table); - vmap_table_offset = PointerToLowMemUInt32(vmap_table); gc_map_offset = PointerToLowMemUInt32(gc_map); } return OatFile::OatMethod(base, @@ -167,8 +157,6 @@ class CommonCompilerTest : public CommonRuntimeTest { frame_size_in_bytes, core_spill_mask, fp_spill_mask, - mapping_table_offset, - vmap_table_offset, gc_map_offset); } @@ -185,19 +173,44 @@ class CommonCompilerTest : public CommonRuntimeTest { } if (compiled_method != nullptr) { const std::vector<uint8_t>* code = compiled_method->GetQuickCode(); - if (code == nullptr) { + const void* code_ptr; + if (code != nullptr) { + uint32_t code_size = code->size(); + CHECK_NE(0u, code_size); + const std::vector<uint8_t>& vmap_table = compiled_method->GetVmapTable(); + uint32_t vmap_table_offset = vmap_table.empty() ? 0u + : sizeof(OatMethodHeader) + vmap_table.size(); + const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable(); + uint32_t mapping_table_offset = mapping_table.empty() ? 0u + : sizeof(OatMethodHeader) + vmap_table.size() + mapping_table.size(); + OatMethodHeader method_header(vmap_table_offset, mapping_table_offset, code_size); + + header_code_and_maps_chunks_.push_back(std::vector<uint8_t>()); + std::vector<uint8_t>* chunk = &header_code_and_maps_chunks_.back(); + size_t size = sizeof(method_header) + code_size + vmap_table.size() + mapping_table.size(); + size_t code_offset = compiled_method->AlignCode(size - code_size); + size_t padding = code_offset - (size - code_size); + chunk->reserve(padding + size); + chunk->resize(sizeof(method_header)); + memcpy(&(*chunk)[0], &method_header, sizeof(method_header)); + chunk->insert(chunk->begin(), vmap_table.begin(), vmap_table.end()); + chunk->insert(chunk->begin(), mapping_table.begin(), mapping_table.end()); + chunk->insert(chunk->begin(), padding, 0); + chunk->insert(chunk->end(), code->begin(), code->end()); + CHECK_EQ(padding + size, chunk->size()); + code_ptr = &(*chunk)[code_offset]; + } else { code = compiled_method->GetPortableCode(); + code_ptr = &(*code)[0]; } - MakeExecutable(*code); - const void* method_code = CompiledMethod::CodePointer(&(*code)[0], + MakeExecutable(code_ptr, code->size()); + const void* method_code = CompiledMethod::CodePointer(code_ptr, compiled_method->GetInstructionSet()); LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code; OatFile::OatMethod oat_method = CreateOatMethod(method_code, compiled_method->GetFrameSizeInBytes(), compiled_method->GetCoreSpillMask(), compiled_method->GetFpSpillMask(), - &compiled_method->GetMappingTable()[0], - &compiled_method->GetVmapTable()[0], nullptr); oat_method.LinkMethod(method); method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge); @@ -211,8 +224,6 @@ class CommonCompilerTest : public CommonRuntimeTest { kStackAlignment, 0, 0, - nullptr, - nullptr, nullptr); oat_method.LinkMethod(method); method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge); @@ -230,8 +241,6 @@ class CommonCompilerTest : public CommonRuntimeTest { sirt_size, callee_save_method->GetCoreSpillMask(), callee_save_method->GetFpSpillMask(), - nullptr, - nullptr, nullptr); oat_method.LinkMethod(method); method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge); @@ -436,6 +445,9 @@ class CommonCompilerTest : public CommonRuntimeTest { private: UniquePtr<MemMap> image_reservation_; + + // Chunks must not move their storage after being created - use the node-based std::list. + std::list<std::vector<uint8_t> > header_code_and_maps_chunks_; }; } // namespace art diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 3400b01994..c35d4007b5 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -680,14 +680,6 @@ void ImageWriter::FixupMethod(ArtMethod* orig, ArtMethod* copy) { copy->SetNativeMethod<kVerifyNone>(GetOatAddress(jni_dlsym_lookup_offset_)); } else { // Normal (non-abstract non-native) methods have various tables to relocate. - uint32_t mapping_table_off = orig->GetOatMappingTableOffset(); - const byte* mapping_table = GetOatAddress(mapping_table_off); - copy->SetMappingTable<kVerifyNone>(mapping_table); - - uint32_t vmap_table_offset = orig->GetOatVmapTableOffset(); - const byte* vmap_table = GetOatAddress(vmap_table_offset); - copy->SetVmapTable<kVerifyNone>(vmap_table); - uint32_t native_gc_map_offset = orig->GetOatNativeGcMapOffset(); const byte* native_gc_map = GetOatAddress(native_gc_map_offset); copy->SetNativeGcMap<kVerifyNone>(reinterpret_cast<const uint8_t*>(native_gc_map)); diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index 766ef7b135..b5d39232ca 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -176,7 +176,8 @@ TEST_F(OatTest, OatHeaderSizeCheck) { // If this test is failing and you have to update these constants, // it is time to update OatHeader::kOatVersion EXPECT_EQ(80U, sizeof(OatHeader)); - EXPECT_EQ(28U, sizeof(OatMethodOffsets)); + EXPECT_EQ(20U, sizeof(OatMethodOffsets)); + EXPECT_EQ(12U, sizeof(OatMethodHeader)); } TEST_F(OatTest, OatHeaderIsValid) { diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 2114fe921d..bbc9c3e325 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -155,12 +155,15 @@ struct OatWriter::MappingTableDataAccess { } static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE { - return oat_class->method_offsets_[method_offsets_index].mapping_table_offset_; + uint32_t offset = oat_class->method_headers_[method_offsets_index].mapping_table_offset_; + return offset == 0u ? 0u : + (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset; } static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset) ALWAYS_INLINE { - oat_class->method_offsets_[method_offsets_index].mapping_table_offset_ = offset; + oat_class->method_headers_[method_offsets_index].mapping_table_offset_ = + (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset; } static const char* Name() ALWAYS_INLINE { @@ -174,12 +177,15 @@ struct OatWriter::VmapTableDataAccess { } static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE { - return oat_class->method_offsets_[method_offsets_index].vmap_table_offset_; + uint32_t offset = oat_class->method_headers_[method_offsets_index].vmap_table_offset_; + return offset == 0u ? 0u : + (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset; } static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset) ALWAYS_INLINE { - oat_class->method_offsets_[method_offsets_index].vmap_table_offset_ = offset; + oat_class->method_headers_[method_offsets_index].vmap_table_offset_ = + (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset; } static const char* Name() ALWAYS_INLINE { @@ -368,17 +374,22 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { } } + DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size()); + OatMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_]; + method_header->code_size_ = code_size; + // Deduplicate code arrays. - auto code_iter = dedupe_map_.find(quick_code); + auto code_iter = dedupe_map_.find(compiled_method); if (code_iter != dedupe_map_.end()) { quick_code_offset = code_iter->second; + FixupMethodHeader(method_header, quick_code_offset - thumb_offset); } else { - dedupe_map_.Put(quick_code, quick_code_offset); - OatMethodHeader method_header(code_size); - offset_ += sizeof(method_header); // Method header is prepended before code. - writer_->oat_header_->UpdateChecksum(&method_header, sizeof(method_header)); - offset_ += code_size; + dedupe_map_.Put(compiled_method, quick_code_offset); + FixupMethodHeader(method_header, quick_code_offset - thumb_offset); + writer_->oat_header_->UpdateChecksum(method_header, sizeof(*method_header)); + offset_ += sizeof(*method_header); // Method header is prepended before code. writer_->oat_header_->UpdateChecksum(&(*quick_code)[0], code_size); + offset_ += code_size; } } frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); @@ -420,9 +431,22 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { } private: + static void FixupMethodHeader(OatMethodHeader* method_header, uint32_t code_offset) { + // The code offset was 0 when the mapping/vmap table offset was set, so it's set + // to 0-offset and we need to adjust it by code_offset. + if (method_header->mapping_table_offset_ != 0u) { + method_header->mapping_table_offset_ += code_offset; + DCHECK_LT(method_header->mapping_table_offset_, code_offset); + } + if (method_header->vmap_table_offset_ != 0u) { + method_header->vmap_table_offset_ += code_offset; + DCHECK_LT(method_header->vmap_table_offset_, code_offset); + } + } + // Deduplication is already done on a pointer basis by the compiler driver, // so we can simply compare the pointers to find out if things are duplicated. - SafeMap<const std::vector<uint8_t>*, uint32_t> dedupe_map_; + SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_; }; template <typename DataAccess> @@ -477,7 +501,7 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor { OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); - OatMethodOffsets offsets(0u, kStackAlignment, 0u, 0u, 0u, 0u, 0u); + OatMethodOffsets offsets(0u, kStackAlignment, 0u, 0u, 0u); if (compiled_method != nullptr) { DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); offsets = oat_class->method_offsets_[method_offsets_index_]; @@ -511,8 +535,6 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor { offsets.frame_size_in_bytes_ = callee_save_method->GetFrameSizeInBytes() + sirt_size; offsets.core_spill_mask_ = callee_save_method->GetCoreSpillMask(); offsets.fp_spill_mask_ = callee_save_method->GetFpSpillMask(); - DCHECK_EQ(offsets.mapping_table_offset_, 0u); - DCHECK_EQ(offsets.vmap_table_offset_, 0u); DCHECK_EQ(offsets.gc_map_offset_, 0u); } @@ -528,10 +550,8 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor { method->SetFrameSizeInBytes(offsets.frame_size_in_bytes_); method->SetCoreSpillMask(offsets.core_spill_mask_); method->SetFpSpillMask(offsets.fp_spill_mask_); - method->SetOatMappingTableOffset(offsets.mapping_table_offset_); // Portable code offsets are set by ElfWriterMclinker::FixupCompiledCodeOffset after linking. method->SetQuickOatCodeOffset(offsets.code_offset_); - method->SetOatVmapTableOffset(offsets.vmap_table_offset_); method->SetOatNativeGcMapOffset(offsets.gc_map_offset_); return true; @@ -584,7 +604,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { offset_ + sizeof(OatMethodHeader) + compiled_method->CodeDelta()) << PrettyMethod(it.GetMemberIndex(), *dex_file_); if (method_offsets.code_offset_ >= offset_) { - OatMethodHeader method_header(code_size); + const OatMethodHeader& method_header = oat_class->method_headers_[method_offsets_index_]; if (!out->WriteFully(&method_header, sizeof(method_header))) { ReportWriteFailure("method header", it); return false; @@ -1153,6 +1173,7 @@ OatWriter::OatClass::OatClass(size_t offset, status_ = status; method_offsets_.resize(num_non_null_compiled_methods); + method_headers_.resize(num_non_null_compiled_methods); uint32_t oat_method_offsets_offset_from_oat_class = sizeof(type_) + sizeof(status_); if (type_ == kOatClassSomeCompiled) { diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h index 1abacd831a..7cdd5329bd 100644 --- a/compiler/oat_writer.h +++ b/compiler/oat_writer.h @@ -225,12 +225,13 @@ class OatWriter { // not is kOatClassBitmap, the bitmap will be NULL. BitVector* method_bitmap_; - // OatMethodOffsets for each CompiledMethod present in the - // OatClass. Note that some may be missing if + // OatMethodOffsets and OatMethodHeaders for each CompiledMethod + // present in the OatClass. Note that some may be missing if // OatClass::compiled_methods_ contains NULL values (and // oat_method_offsets_offsets_from_oat_class_ should contain 0 // values in this case). std::vector<OatMethodOffsets> method_offsets_; + std::vector<OatMethodHeader> method_headers_; private: DISALLOW_COPY_AND_ASSIGN(OatClass); @@ -299,6 +300,22 @@ class OatWriter { uint32_t size_oat_class_method_bitmaps_; uint32_t size_oat_class_method_offsets_; + struct CodeOffsetsKeyComparator { + bool operator()(const CompiledMethod* lhs, const CompiledMethod* rhs) const { + if (lhs->GetQuickCode() != rhs->GetQuickCode()) { + return lhs->GetQuickCode() < rhs->GetQuickCode(); + } + // If the code is the same, all other fields are likely to be the same as well. + if (UNLIKELY(&lhs->GetMappingTable() != &rhs->GetMappingTable())) { + return &lhs->GetMappingTable() < &rhs->GetMappingTable(); + } + if (UNLIKELY(&lhs->GetVmapTable() != &rhs->GetVmapTable())) { + return &lhs->GetVmapTable() < &rhs->GetVmapTable(); + } + return false; + } + }; + DISALLOW_COPY_AND_ASSIGN(OatWriter); }; |