diff options
author | Vladimir Marko <vmarko@google.com> | 2014-04-28 09:09:06 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-04-28 09:09:07 +0000 |
commit | 990d46f3333dce06a640ced697ee069330a73d7c (patch) | |
tree | 7caf896723665029823c73e2bec87e6db97ec428 /runtime | |
parent | bf25f7e3a007ecfe4b2bcfa0a9abcb784ff54e26 (diff) | |
parent | 8a630577ed2d9e9571c3434c505e5de223b23c07 (diff) | |
download | art-990d46f3333dce06a640ced697ee069330a73d7c.zip art-990d46f3333dce06a640ced697ee069330a73d7c.tar.gz art-990d46f3333dce06a640ced697ee069330a73d7c.tar.bz2 |
Merge "Move mapping table and vmap table offsets to OatMethodHeader."
Diffstat (limited to 'runtime')
-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 |
15 files changed, 181 insertions, 143 deletions
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; |