diff options
-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 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 2 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 1 | ||||
-rw-r--r-- | runtime/base/bit_vector.cc | 80 | ||||
-rw-r--r-- | runtime/base/bit_vector.h | 8 | ||||
-rw-r--r-- | runtime/class_linker.cc | 4 | ||||
-rw-r--r-- | runtime/class_linker.h | 5 | ||||
-rw-r--r-- | runtime/class_linker_test.cc | 2 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.h | 4 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc | 1 | ||||
-rw-r--r-- | runtime/exception_test.cc | 32 | ||||
-rw-r--r-- | runtime/instrumentation.cc | 12 | ||||
-rw-r--r-- | runtime/mirror/art_method-inl.h | 33 | ||||
-rw-r--r-- | runtime/mirror/art_method.cc | 38 | ||||
-rw-r--r-- | runtime/mirror/art_method.h | 51 | ||||
-rw-r--r-- | runtime/oat.cc | 19 | ||||
-rw-r--r-- | runtime/oat.h | 15 | ||||
-rw-r--r-- | runtime/oat_file-inl.h | 60 | ||||
-rw-r--r-- | runtime/oat_file.cc | 27 | ||||
-rw-r--r-- | runtime/oat_file.h | 21 |
24 files changed, 350 insertions, 212 deletions
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h index fdf09a5..8bba84a 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 3400b01..c35d400 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 766ef7b..b5d3923 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 2114fe9..bbc9c3e 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 1abacd8..7cdd532 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); }; diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index d4ad3c6..d3e56da 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -110,7 +110,7 @@ static void Usage(const char* fmt, ...) { UsageError(" Example: --oat-file=/system/framework/boot.oat"); UsageError(""); UsageError(" --oat-fd=<number>: specifies the oat output destination via a file descriptor."); - UsageError(" Example: --oat-file=/system/framework/boot.oat"); + UsageError(" Example: --oat-fd=6"); UsageError(""); UsageError(" --oat-location=<oat-name>: specifies a symbolic name for the file corresponding"); UsageError(" to the file descriptor specified by --oat-fd."); diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 5054f96..1a67952 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -44,6 +44,7 @@ #include "mirror/object_array-inl.h" #include "noop_compiler_callbacks.h" #include "oat.h" +#include "oat_file-inl.h" #include "object_utils.h" #include "os.h" #include "runtime.h" diff --git a/runtime/base/bit_vector.cc b/runtime/base/bit_vector.cc index d8ef962..12c0352 100644 --- a/runtime/base/bit_vector.cc +++ b/runtime/base/bit_vector.cc @@ -157,33 +157,27 @@ void BitVector::Intersect(const BitVector* src) { * Union with another bit vector. */ void BitVector::Union(const BitVector* src) { - uint32_t src_size = src->storage_size_; + // Get the highest bit to determine how much we need to expand. + int highest_bit = src->GetHighestBitSet(); + + // If src has no bit set, we are done: there is no need for a union with src. + if (highest_bit == -1) { + return; + } - // Get our size, we use this variable for the last loop of the method: - // - It can change in the if block if src is of a different size. - uint32_t size = storage_size_; + // Update src_size to how many cells we actually care about: where the bit is + 1. + uint32_t src_size = BitsToWords(highest_bit + 1); // Is the storage size smaller than src's? if (storage_size_ < src_size) { - // Get the highest bit to determine how much we need to expand. - int highest_bit = src->GetHighestBitSet(); - - // If src has no bit set, we are done: there is no need for a union with src. - if (highest_bit == -1) { - return; - } - // Set it to reallocate. SetBit(highest_bit); // Paranoid: storage size should be big enough to hold this bit now. DCHECK_LT(static_cast<uint32_t> (highest_bit), storage_size_ * sizeof(*(storage_)) * 8); - - // Update the size, our size can now not be bigger than the src size - size = storage_size_; } - for (uint32_t idx = 0; idx < size; idx++) { + for (uint32_t idx = 0; idx < src_size; idx++) { storage_[idx] |= src->GetRawStorageWord(idx); } } @@ -284,6 +278,23 @@ int BitVector::GetHighestBitSet() const { return -1; } +bool BitVector::EnsureSizeAndClear(unsigned int num) { + // Check if the bitvector is expandable. + if (IsExpandable() == false) { + return false; + } + + if (num > 0) { + // Now try to expand by setting the last bit. + SetBit(num - 1); + } + + // We must clear all bits as per our specification. + ClearAllBits(); + + return true; +} + void BitVector::Copy(const BitVector *src) { // Get highest bit set, we only need to copy till then. int highest_bit = src->GetHighestBitSet(); @@ -328,4 +339,41 @@ uint32_t BitVector::NumSetBits(const uint32_t* storage, uint32_t end) { return count; } +void BitVector::Dump(std::ostream& os, const char *prefix) { + std::ostringstream buffer; + DumpHelper(buffer, prefix); + os << buffer << std::endl; +} + +void BitVector::DumpDot(FILE* file, const char* prefix, bool last_entry) { + std::ostringstream buffer; + Dump(buffer, prefix); + + // Now print it to the file. + fprintf(file, " {%s}", buffer.str().c_str()); + + // If it isn't the last entry, add a |. + if (last_entry == false) { + fprintf(file, "|"); + } + + // Add the \n. + fprintf(file, "\\\n"); +} + +void BitVector::DumpHelper(std::ostringstream& buffer, const char* prefix) { + // Initialize it. + if (prefix != nullptr) { + buffer << prefix; + } + + int max = GetHighestBitSet(); + + for (int i = 0; i <= max; i++) { + if (IsBitSet(i)) { + buffer << i << " "; + } + } +} + } // namespace art diff --git a/runtime/base/bit_vector.h b/runtime/base/bit_vector.h index a496dbd..db29c49 100644 --- a/runtime/base/bit_vector.h +++ b/runtime/base/bit_vector.h @@ -142,6 +142,14 @@ class BitVector { // Number of bits set in range [0, end) in storage. (No range check.) static uint32_t NumSetBits(const uint32_t* storage, uint32_t end); + bool EnsureSizeAndClear(unsigned int num); + + void Dump(std::ostream& os, const char* prefix); + void DumpDot(FILE* file, const char* prefix, bool last_entry = false); + + protected: + void DumpHelper(std::ostringstream& buffer, const char* prefix); + private: Allocator* const allocator_; const bool expandable_; // expand bitmap if we run out? diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 58b82f0..338133c 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -185,7 +185,8 @@ ClassLinker::ClassLinker(InternTable* intern_table) quick_resolution_trampoline_(nullptr), portable_imt_conflict_trampoline_(nullptr), quick_imt_conflict_trampoline_(nullptr), - quick_generic_jni_trampoline_(nullptr) { + quick_generic_jni_trampoline_(nullptr), + quick_to_interpreter_bridge_trampoline_(nullptr) { CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax)); memset(find_array_class_cache_, 0, kFindArrayCacheSize * sizeof(mirror::Class*)); } @@ -1002,6 +1003,7 @@ void ClassLinker::InitFromImage() { portable_imt_conflict_trampoline_ = oat_file.GetOatHeader().GetPortableImtConflictTrampoline(); quick_imt_conflict_trampoline_ = oat_file.GetOatHeader().GetQuickImtConflictTrampoline(); quick_generic_jni_trampoline_ = oat_file.GetOatHeader().GetQuickGenericJniTrampoline(); + quick_to_interpreter_bridge_trampoline_ = oat_file.GetOatHeader().GetQuickToInterpreterBridge(); mirror::Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); mirror::ObjectArray<mirror::DexCache>* dex_caches = dex_caches_object->AsObjectArray<mirror::DexCache>(); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index a14d1d1..9771318 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -369,6 +369,10 @@ class ClassLinker { return quick_imt_conflict_trampoline_; } + const void* GetQuickToInterpreterBridgeTrampoline() const { + return quick_to_interpreter_bridge_trampoline_; + } + InternTable* GetInternTable() const { return intern_table_; } @@ -658,6 +662,7 @@ class ClassLinker { const void* portable_imt_conflict_trampoline_; const void* quick_imt_conflict_trampoline_; const void* quick_generic_jni_trampoline_; + const void* quick_to_interpreter_bridge_trampoline_; friend class ImageWriter; // for GetClassRoots FRIEND_TEST(ClassLinkerTest, ClassRootDescriptors); diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 5b72a44..1218357 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -485,8 +485,6 @@ struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> { offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_portable_compiled_code_), "entryPointFromPortableCompiledCode")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_quick_compiled_code_), "entryPointFromQuickCompiledCode")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, gc_map_), "gcMap")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_mapping_table_), "quickMappingTable")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_vmap_table_), "quickVmapTable")); // alphabetical 32-bit offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags")); diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index 8b48b36..05912bf 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -761,6 +761,10 @@ static inline const void* GetQuickGenericJniTrampoline(ClassLinker* class_linker return class_linker->GetQuickGenericJniTrampoline(); } +static inline const void* GetQuickToInterpreterBridgeTrampoline(ClassLinker* class_linker) { + return class_linker->GetQuickToInterpreterBridgeTrampoline(); +} + extern "C" void art_portable_proxy_invoke_handler(); static inline const void* GetPortableProxyInvokeHandler() { return reinterpret_cast<void*>(art_portable_proxy_invoke_handler); diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc index 633f580..60c5377 100644 --- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc @@ -32,6 +32,7 @@ extern "C" const void* artInstrumentationMethodEntryFromCode(mirror::ArtMethod* FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs); instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); const void* result = instrumentation->GetQuickCodeFor(method); + DCHECK(result != GetQuickToInterpreterBridgeTrampoline(Runtime::Current()->GetClassLinker())); bool interpreter_entry = (result == GetQuickToInterpreterBridge()); instrumentation->PushInstrumentationStackFrame(self, method->IsStatic() ? NULL : this_object, method, lr, interpreter_entry); diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc index 208eb74..97a8367 100644 --- a/runtime/exception_test.cc +++ b/runtime/exception_test.cc @@ -49,10 +49,6 @@ class ExceptionTest : public CommonRuntimeTest { dex_ = my_klass_->GetDexCache()->GetDexFile(); uint32_t code_size = 12; - fake_code_.push_back((code_size >> 24) & 0xFF); - fake_code_.push_back((code_size >> 16) & 0xFF); - fake_code_.push_back((code_size >> 8) & 0xFF); - fake_code_.push_back((code_size >> 0) & 0xFF); for (size_t i = 0 ; i < code_size; i++) { fake_code_.push_back(0x70 | i); } @@ -74,20 +70,35 @@ class ExceptionTest : public CommonRuntimeTest { fake_gc_map_.push_back(0); // 0 entries. fake_gc_map_.push_back(0); + const std::vector<uint8_t>& fake_vmap_table_data = fake_vmap_table_data_.GetData(); + const std::vector<uint8_t>& fake_mapping_data = fake_mapping_data_.GetData(); + uint32_t vmap_table_offset = sizeof(OatMethodHeader) + fake_vmap_table_data.size(); + uint32_t mapping_table_offset = vmap_table_offset + fake_mapping_data.size(); + OatMethodHeader method_header(vmap_table_offset, mapping_table_offset, code_size); + fake_header_code_and_maps_.resize(sizeof(method_header)); + memcpy(&fake_header_code_and_maps_[0], &method_header, sizeof(method_header)); + fake_header_code_and_maps_.insert(fake_header_code_and_maps_.begin(), + fake_vmap_table_data.begin(), fake_vmap_table_data.end()); + fake_header_code_and_maps_.insert(fake_header_code_and_maps_.begin(), + fake_mapping_data.begin(), fake_mapping_data.end()); + fake_header_code_and_maps_.insert(fake_header_code_and_maps_.end(), + fake_code_.begin(), fake_code_.end()); + + // NOTE: Don't align the code (it will not be executed) but check that the Thumb2 + // adjustment will be a NOP, see ArtMethod::EntryPointToCodePointer(). + CHECK_EQ(mapping_table_offset & 1u, 0u); + const uint8_t* code_ptr = &fake_header_code_and_maps_[mapping_table_offset]; + method_f_ = my_klass_->FindVirtualMethod("f", "()I"); ASSERT_TRUE(method_f_ != NULL); method_f_->SetFrameSizeInBytes(4 * kPointerSize); - method_f_->SetEntryPointFromQuickCompiledCode(&fake_code_[sizeof(code_size)]); - method_f_->SetMappingTable(&fake_mapping_data_.GetData()[0]); - method_f_->SetVmapTable(&fake_vmap_table_data_.GetData()[0]); + method_f_->SetEntryPointFromQuickCompiledCode(code_ptr); method_f_->SetNativeGcMap(&fake_gc_map_[0]); method_g_ = my_klass_->FindVirtualMethod("g", "(I)V"); ASSERT_TRUE(method_g_ != NULL); method_g_->SetFrameSizeInBytes(4 * kPointerSize); - method_g_->SetEntryPointFromQuickCompiledCode(&fake_code_[sizeof(code_size)]); - method_g_->SetMappingTable(&fake_mapping_data_.GetData()[0]); - method_g_->SetVmapTable(&fake_vmap_table_data_.GetData()[0]); + method_g_->SetEntryPointFromQuickCompiledCode(code_ptr); method_g_->SetNativeGcMap(&fake_gc_map_[0]); } @@ -97,6 +108,7 @@ class ExceptionTest : public CommonRuntimeTest { Leb128EncodingVector fake_mapping_data_; Leb128EncodingVector fake_vmap_table_data_; std::vector<uint8_t> fake_gc_map_; + std::vector<uint8_t> fake_header_code_and_maps_; mirror::ArtMethod* method_f_; mirror::ArtMethod* method_g_; diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 2cd7f49..77d29dd 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -94,6 +94,7 @@ static void UpdateEntrypoints(mirror::ArtMethod* method, const void* quick_code, } if (!method->IsResolutionMethod()) { if (quick_code == GetQuickToInterpreterBridge() || + quick_code == GetQuickToInterpreterBridgeTrampoline(Runtime::Current()->GetClassLinker()) || (quick_code == GetQuickResolutionTrampoline(Runtime::Current()->GetClassLinker()) && Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly() && !method->IsNative() && !method->IsProxyMethod())) { @@ -147,6 +148,7 @@ void Instrumentation::InstallStubsForMethod(mirror::ArtMethod* method) { // Do not overwrite interpreter to prevent from posting method entry/exit events twice. new_portable_code = class_linker->GetPortableOatCodeFor(method, &have_portable_code); new_quick_code = class_linker->GetQuickOatCodeFor(method); + DCHECK(new_quick_code != GetQuickToInterpreterBridgeTrampoline(class_linker)); if (entry_exit_stubs_installed_ && new_quick_code != GetQuickToInterpreterBridge()) { DCHECK(new_portable_code != GetPortableToInterpreterBridge()); new_portable_code = GetPortableToInterpreterBridge(); @@ -562,7 +564,8 @@ void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* q new_quick_code = GetQuickToInterpreterBridge(); new_have_portable_code = false; } else if (quick_code == GetQuickResolutionTrampoline(Runtime::Current()->GetClassLinker()) || - quick_code == GetQuickToInterpreterBridge()) { + quick_code == GetQuickToInterpreterBridgeTrampoline(Runtime::Current()->GetClassLinker()) || + quick_code == GetQuickToInterpreterBridge()) { DCHECK((portable_code == GetPortableResolutionTrampoline(Runtime::Current()->GetClassLinker())) || (portable_code == GetPortableToInterpreterBridge())); new_portable_code = portable_code; @@ -709,9 +712,10 @@ const void* Instrumentation::GetQuickCodeFor(mirror::ArtMethod* method) const { Runtime* runtime = Runtime::Current(); if (LIKELY(!instrumentation_stubs_installed_)) { const void* code = method->GetEntryPointFromQuickCompiledCode(); - DCHECK(code != NULL); - if (LIKELY(code != GetQuickResolutionTrampoline(runtime->GetClassLinker()) && - code != GetQuickToInterpreterBridge())) { + DCHECK(code != nullptr); + if (LIKELY(code != GetQuickResolutionTrampoline(runtime->GetClassLinker())) && + LIKELY(code != GetQuickToInterpreterBridgeTrampoline(runtime->GetClassLinker())) && + LIKELY(code != GetQuickToInterpreterBridge())) { return code; } } diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h index 5d62b88..6e1f062 100644 --- a/runtime/mirror/art_method-inl.h +++ b/runtime/mirror/art_method-inl.h @@ -78,13 +78,11 @@ inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() { inline uint32_t ArtMethod::GetCodeSize() { DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this); - uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromQuickCompiledCode()); - if (code == 0) { - return 0; + const void* code = EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode()); + if (code == nullptr) { + return 0u; } - // TODO: make this Thumb2 specific - code &= ~0x1; - return reinterpret_cast<OatMethodHeader*>(code)[-1].code_size_; + return reinterpret_cast<const OatMethodHeader*>(code)[-1].code_size_; } inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) { @@ -124,7 +122,8 @@ inline void ArtMethod::AssertPcIsWithinQuickCode(uintptr_t pc) { return; } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - if (code == GetQuickResolutionTrampoline(class_linker)) { + if (code == GetQuickResolutionTrampoline(class_linker) || + code == GetQuickToInterpreterBridgeTrampoline(class_linker)) { return; } DCHECK(IsWithinQuickCode(pc)) @@ -154,26 +153,6 @@ inline void ArtMethod::SetPortableOatCodeOffset(uint32_t code_offset) { SetEntryPointFromPortableCompiledCode(reinterpret_cast<void*>(code_offset)); } -inline uint32_t ArtMethod::GetOatMappingTableOffset() { - DCHECK(!Runtime::Current()->IsStarted()); - return PointerToLowMemUInt32(GetMappingTable()); -} - -inline void ArtMethod::SetOatMappingTableOffset(uint32_t mapping_table_offset) { - DCHECK(!Runtime::Current()->IsStarted()); - SetMappingTable(reinterpret_cast<const uint8_t*>(mapping_table_offset)); -} - -inline uint32_t ArtMethod::GetOatVmapTableOffset() { - DCHECK(!Runtime::Current()->IsStarted()); - return PointerToLowMemUInt32(GetVmapTable()); -} - -inline void ArtMethod::SetOatVmapTableOffset(uint32_t vmap_table_offset) { - DCHECK(!Runtime::Current()->IsStarted()); - SetVmapTable(reinterpret_cast<uint8_t*>(vmap_table_offset)); -} - inline void ArtMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) { DCHECK(!Runtime::Current()->IsStarted()); SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset)); diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc index 726004b..90bcbab 100644 --- a/runtime/mirror/art_method.cc +++ b/runtime/mirror/art_method.cc @@ -368,5 +368,43 @@ void ArtMethod::UnregisterNative(Thread* self) { RegisterNative(self, GetJniDlsymLookupStub(), false); } +const void* ArtMethod::GetOatCodePointer() { + if (IsPortableCompiled() || IsNative() || IsAbstract() || IsRuntimeMethod() || IsProxyMethod()) { + return nullptr; + } + Runtime* runtime = Runtime::Current(); + const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(this); + // On failure, instead of nullptr we get the quick-to-interpreter-bridge (but not the trampoline). + DCHECK(entry_point != GetQuickToInterpreterBridgeTrampoline(runtime->GetClassLinker())); + if (entry_point == GetQuickToInterpreterBridge()) { + return nullptr; + } + return EntryPointToCodePointer(entry_point); +} + +const uint8_t* ArtMethod::GetMappingTable() { + const void* code = GetOatCodePointer(); + if (code == nullptr) { + return nullptr; + } + uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].mapping_table_offset_; + if (UNLIKELY(offset == 0u)) { + return nullptr; + } + return reinterpret_cast<const uint8_t*>(code) - offset; +} + +const uint8_t* ArtMethod::GetVmapTable() { + const void* code = GetOatCodePointer(); + if (code == nullptr) { + return nullptr; + } + uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].vmap_table_offset_; + if (UNLIKELY(offset == 0u)) { + return nullptr; + } + return reinterpret_cast<const uint8_t*>(code) - offset; +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h index 4462036..b3b9ca7 100644 --- a/runtime/mirror/art_method.h +++ b/runtime/mirror/art_method.h @@ -21,6 +21,7 @@ #include "dex_file.h" #include "invoke_type.h" #include "modifiers.h" +#include "oat.h" #include "object.h" #include "object_callbacks.h" @@ -261,7 +262,6 @@ class MANAGED ArtMethod : public Object { EntryPointFromQuickCompiledCodeOffset(), entry_point_from_quick_compiled_code, false); } - uint32_t GetCodeSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool IsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -286,37 +286,20 @@ class MANAGED ArtMethod : public Object { void SetQuickOatCodeOffset(uint32_t code_offset); void SetPortableOatCodeOffset(uint32_t code_offset); - // Callers should wrap the uint8_t* in a MappingTable instance for convenient access. - const uint8_t* GetMappingTable() { - return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_), - false); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - void SetMappingTable(const uint8_t* mapping_table) { - SetFieldPtr<false, true, kVerifyFlags>( - OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_), mapping_table, false); + static const void* EntryPointToCodePointer(const void* entry_point) ALWAYS_INLINE { + uintptr_t code = reinterpret_cast<uintptr_t>(entry_point); + code &= ~0x1; // TODO: Make this Thumb2 specific. + return reinterpret_cast<const void*>(code); } - uint32_t GetOatMappingTableOffset(); + // Actual pointer to compiled oat code or nullptr. + const void* GetOatCodePointer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetOatMappingTableOffset(uint32_t mapping_table_offset); + // Callers should wrap the uint8_t* in a MappingTable instance for convenient access. + const uint8_t* GetMappingTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Callers should wrap the uint8_t* in a VmapTable instance for convenient access. - const uint8_t* GetVmapTable() { - return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_), - false); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - void SetVmapTable(const uint8_t* vmap_table) { - SetFieldPtr<false, true, kVerifyFlags>( - OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_), vmap_table, false); - } - - uint32_t GetOatVmapTableOffset(); - - void SetOatVmapTableOffset(uint32_t vmap_table_offset); + const uint8_t* GetVmapTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); const uint8_t* GetNativeGcMap() { return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), false); @@ -471,20 +454,6 @@ class MANAGED ArtMethod : public Object { // offsets for the quick compiler and dex PCs for the portable. uint64_t gc_map_; - // --- Quick compiler meta-data. --- - // TODO: merge and place in native heap, such as done with the code size. - - // Pointer to a data structure created by the quick compiler to map between dex PCs and native - // PCs, and vice-versa. - uint64_t quick_mapping_table_; - - // When a register is promoted into a register, the spill mask holds which registers hold dex - // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth - // is vmap_table_[N]. vmap_table_[0] holds the length of the table. - uint64_t quick_vmap_table_; - - // --- End of quick compiler meta-data. --- - // Access flags; low 16 bits are defined by spec. uint32_t access_flags_; diff --git a/runtime/oat.cc b/runtime/oat.cc index d01dc72..c1a48e9 100644 --- a/runtime/oat.cc +++ b/runtime/oat.cc @@ -22,7 +22,7 @@ namespace art { const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' }; -const uint8_t OatHeader::kOatVersion[] = { '0', '2', '1', '\0' }; +const uint8_t OatHeader::kOatVersion[] = { '0', '2', '2', '\0' }; OatHeader::OatHeader() { memset(this, 0, sizeof(*this)); @@ -348,8 +348,6 @@ OatMethodOffsets::OatMethodOffsets() frame_size_in_bytes_(0), core_spill_mask_(0), fp_spill_mask_(0), - mapping_table_offset_(0), - vmap_table_offset_(0), gc_map_offset_(0) {} @@ -357,27 +355,28 @@ OatMethodOffsets::OatMethodOffsets(uint32_t code_offset, uint32_t frame_size_in_bytes, uint32_t core_spill_mask, uint32_t fp_spill_mask, - uint32_t mapping_table_offset, - uint32_t vmap_table_offset, uint32_t gc_map_offset ) : code_offset_(code_offset), frame_size_in_bytes_(frame_size_in_bytes), core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask), - mapping_table_offset_(mapping_table_offset), - vmap_table_offset_(vmap_table_offset), gc_map_offset_(gc_map_offset) {} OatMethodOffsets::~OatMethodOffsets() {} OatMethodHeader::OatMethodHeader() - : code_size_(0) + : mapping_table_offset_(0), + vmap_table_offset_(0), + code_size_(0) {} -OatMethodHeader::OatMethodHeader(uint32_t code_size) - : code_size_(code_size) +OatMethodHeader::OatMethodHeader(uint32_t vmap_table_offset, uint32_t mapping_table_offset, + uint32_t code_size) + : mapping_table_offset_(mapping_table_offset), + vmap_table_offset_(vmap_table_offset), + code_size_(code_size) {} OatMethodHeader::~OatMethodHeader() {} diff --git a/runtime/oat.h b/runtime/oat.h index 035aba1..e9dfae9 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -119,9 +119,9 @@ class PACKED(4) OatHeader { DISALLOW_COPY_AND_ASSIGN(OatHeader); }; -// OatMethodOffsets are currently 7x32-bits=224-bits long, so if we can +// OatMethodOffsets are currently 5x32-bits=160-bits long, so if we can // save even one OatMethodOffsets struct, the more complicated encoding -// using a bitmap pays for itself since few classes will have 224 +// using a bitmap pays for itself since few classes will have 160 // methods. enum OatClassType { kOatClassAllCompiled = 0, // OatClass is followed by an OatMethodOffsets for each method. @@ -140,8 +140,6 @@ class PACKED(4) OatMethodOffsets { uint32_t frame_size_in_bytes, uint32_t core_spill_mask, uint32_t fp_spill_mask, - uint32_t mapping_table_offset, - uint32_t vmap_table_offset, uint32_t gc_map_offset); ~OatMethodOffsets(); @@ -150,8 +148,6 @@ class PACKED(4) OatMethodOffsets { uint32_t frame_size_in_bytes_; uint32_t core_spill_mask_; uint32_t fp_spill_mask_; - uint32_t mapping_table_offset_; - uint32_t vmap_table_offset_; uint32_t gc_map_offset_; }; @@ -160,10 +156,15 @@ class PACKED(4) OatMethodHeader { public: OatMethodHeader(); - explicit OatMethodHeader(uint32_t code_size); + explicit OatMethodHeader(uint32_t mapping_table_offset, uint32_t vmap_table_offset, + uint32_t code_size); ~OatMethodHeader(); + // The offset in bytes from the start of the mapping table to the end of the header. + uint32_t mapping_table_offset_; + // The offset in bytes from the start of the vmap table to the end of the header. + uint32_t vmap_table_offset_; // The code size in bytes. uint32_t code_size_; }; diff --git a/runtime/oat_file-inl.h b/runtime/oat_file-inl.h new file mode 100644 index 0000000..00ae797 --- /dev/null +++ b/runtime/oat_file-inl.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_OAT_FILE_INL_H_ +#define ART_RUNTIME_OAT_FILE_INL_H_ + +#include "oat_file.h" + +namespace art { + +inline uint32_t OatFile::OatMethod::GetMappingTableOffset() const { + const uint8_t* mapping_table = GetMappingTable(); + return static_cast<uint32_t>(mapping_table != nullptr ? mapping_table - begin_ : 0u); +} + +inline uint32_t OatFile::OatMethod::GetVmapTableOffset() const { + const uint8_t* vmap_table = GetVmapTable(); + return static_cast<uint32_t>(vmap_table != nullptr ? vmap_table - begin_ : 0u); +} + +inline const uint8_t* OatFile::OatMethod::GetMappingTable() const { + const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode()); + if (code == nullptr) { + return nullptr; + } + uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].mapping_table_offset_; + if (UNLIKELY(offset == 0u)) { + return nullptr; + } + return reinterpret_cast<const uint8_t*>(code) - offset; +} + +inline const uint8_t* OatFile::OatMethod::GetVmapTable() const { + const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode()); + if (code == nullptr) { + return nullptr; + } + uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].vmap_table_offset_; + if (UNLIKELY(offset == 0u)) { + return nullptr; + } + return reinterpret_cast<const uint8_t*>(code) - offset; +} + +} // namespace art + +#endif // ART_RUNTIME_OAT_FILE_INL_H_ diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 0aff8c3..56e1f05 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -464,7 +464,7 @@ const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index. if (methods_pointer_ == NULL) { CHECK_EQ(kOatClassNoneCompiled, type_); - return OatMethod(NULL, 0, 0, 0, 0, 0, 0, 0); + return OatMethod(NULL, 0, 0, 0, 0, 0); } size_t methods_pointer_index; if (bitmap_ == NULL) { @@ -473,7 +473,7 @@ const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) } else { CHECK_EQ(kOatClassSomeCompiled, type_); if (!BitVector::IsBitSet(bitmap_, method_index)) { - return OatMethod(NULL, 0, 0, 0, 0, 0, 0, 0); + return OatMethod(NULL, 0, 0, 0, 0, 0); } size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index); methods_pointer_index = num_set_bits; @@ -485,8 +485,6 @@ const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) oat_method_offsets.frame_size_in_bytes_, oat_method_offsets.core_spill_mask_, oat_method_offsets.fp_spill_mask_, - oat_method_offsets.mapping_table_offset_, - oat_method_offsets.vmap_table_offset_, oat_method_offsets.gc_map_offset_); } @@ -495,32 +493,13 @@ OatFile::OatMethod::OatMethod(const byte* base, const size_t frame_size_in_bytes, const uint32_t core_spill_mask, const uint32_t fp_spill_mask, - const uint32_t mapping_table_offset, - const uint32_t vmap_table_offset, const uint32_t gc_map_offset) : begin_(base), code_offset_(code_offset), frame_size_in_bytes_(frame_size_in_bytes), core_spill_mask_(core_spill_mask), fp_spill_mask_(fp_spill_mask), - mapping_table_offset_(mapping_table_offset), - vmap_table_offset_(vmap_table_offset), native_gc_map_offset_(gc_map_offset) { - if (kIsDebugBuild) { - if (mapping_table_offset_ != 0) { // implies non-native, non-stub code - if (vmap_table_offset_ == 0) { - CHECK_EQ(0U, static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) + - __builtin_popcount(fp_spill_mask_))); - } else { - VmapTable vmap_table(reinterpret_cast<const uint8_t*>(begin_ + vmap_table_offset_)); - - CHECK_EQ(vmap_table.Size(), static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) + - __builtin_popcount(fp_spill_mask_))); - } - } else { - CHECK_EQ(vmap_table_offset_, 0U); - } - } } OatFile::OatMethod::~OatMethod() {} @@ -543,8 +522,6 @@ void OatFile::OatMethod::LinkMethod(mirror::ArtMethod* method) const { method->SetFrameSizeInBytes(frame_size_in_bytes_); method->SetCoreSpillMask(core_spill_mask_); method->SetFpSpillMask(fp_spill_mask_); - method->SetMappingTable(GetMappingTable()); - method->SetVmapTable(GetVmapTable()); method->SetNativeGcMap(GetNativeGcMap()); // Used by native methods in work around JNI mode. } diff --git a/runtime/oat_file.h b/runtime/oat_file.h index 10f64cc..5f6cb1e 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -87,12 +87,6 @@ class OatFile { uint32_t GetFpSpillMask() const { return fp_spill_mask_; } - uint32_t GetMappingTableOffset() const { - return mapping_table_offset_; - } - uint32_t GetVmapTableOffset() const { - return vmap_table_offset_; - } uint32_t GetNativeGcMapOffset() const { return native_gc_map_offset_; } @@ -122,16 +116,15 @@ class OatFile { } uint32_t GetQuickCodeSize() const; - const uint8_t* GetMappingTable() const { - return GetOatPointer<const uint8_t*>(mapping_table_offset_); - } - const uint8_t* GetVmapTable() const { - return GetOatPointer<const uint8_t*>(vmap_table_offset_); - } const uint8_t* GetNativeGcMap() const { return GetOatPointer<const uint8_t*>(native_gc_map_offset_); } + uint32_t GetMappingTableOffset() const; + uint32_t GetVmapTableOffset() const; + const uint8_t* GetMappingTable() const; + const uint8_t* GetVmapTable() const; + ~OatMethod(); // Create an OatMethod with offsets relative to the given base address @@ -140,8 +133,6 @@ class OatFile { const size_t frame_size_in_bytes, const uint32_t core_spill_mask, const uint32_t fp_spill_mask, - const uint32_t mapping_table_offset, - const uint32_t vmap_table_offset, const uint32_t gc_map_offset); private: @@ -159,8 +150,6 @@ class OatFile { size_t frame_size_in_bytes_; uint32_t core_spill_mask_; uint32_t fp_spill_mask_; - uint32_t mapping_table_offset_; - uint32_t vmap_table_offset_; uint32_t native_gc_map_offset_; friend class OatClass; |