diff options
Diffstat (limited to 'compiler/driver')
| -rw-r--r-- | compiler/driver/compiled_code_storage.h | 73 | ||||
| -rw-r--r-- | compiler/driver/compiled_method_storage.cc | 288 | ||||
| -rw-r--r-- | compiler/driver/compiled_method_storage.h | 135 | ||||
| -rw-r--r-- | compiler/driver/compiled_method_storage_test.cc | 101 | ||||
| -rw-r--r-- | compiler/driver/compiler_options.cc | 33 | ||||
| -rw-r--r-- | compiler/driver/compiler_options.h | 37 | ||||
| -rw-r--r-- | compiler/driver/compiler_options_map-inl.h | 4 | ||||
| -rw-r--r-- | compiler/driver/compiler_options_map.h | 3 | ||||
| -rw-r--r-- | compiler/driver/dex_compilation_unit.cc | 2 | ||||
| -rw-r--r-- | compiler/driver/dex_compilation_unit.h | 3 | ||||
| -rw-r--r-- | compiler/driver/simple_compiler_options_map.h | 3 |
11 files changed, 131 insertions, 551 deletions
diff --git a/compiler/driver/compiled_code_storage.h b/compiler/driver/compiled_code_storage.h new file mode 100644 index 0000000000..cef7398ec1 --- /dev/null +++ b/compiler/driver/compiled_code_storage.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 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_COMPILER_DRIVER_COMPILED_CODE_STORAGE_H_ +#define ART_COMPILER_DRIVER_COMPILED_CODE_STORAGE_H_ + +#include <string> + +#include "base/array_ref.h" +#include "base/macros.h" + +namespace art HIDDEN { + +namespace linker { +class LinkerPatch; +} // namespace linker + +class CompiledMethod; +enum class InstructionSet; + +// Interface for storing AOT-compiled artifacts. +// These artifacts include compiled method code and related stack maps and +// linker patches as well as the compiled thunk code required for some kinds +// of linker patches. +// +// This interface is used for passing AOT-compiled code and metadata produced +// by the `libart-compiler` to `dex2oat`. The `CompiledMethod` created by +// `dex2oat` is completely opaque to the `libart-compiler`. +class CompiledCodeStorage { + public: + virtual CompiledMethod* CreateCompiledMethod(InstructionSet instruction_set, + ArrayRef<const uint8_t> code, + ArrayRef<const uint8_t> stack_map, + ArrayRef<const uint8_t> cfi, + ArrayRef<const linker::LinkerPatch> patches, + bool is_intrinsic) = 0; + + // TODO: Rewrite the interface for passing thunks to the `dex2oat` to reduce + // locking. The `OptimizingCompiler` is currently calling `GetThunkCode()` + // and locking a mutex there for every `LinkerPatch` that needs a thunk to + // check whether we need to compile it. Using a thunk compiler interface, + // we could drive this from the `dex2oat` side and lock the mutex at most + // once per `CreateCompiledMethod()` for any number of patches. + virtual ArrayRef<const uint8_t> GetThunkCode(const linker::LinkerPatch& patch, + /*out*/ std::string* debug_name = nullptr) = 0; + virtual void SetThunkCode(const linker::LinkerPatch& patch, + ArrayRef<const uint8_t> code, + const std::string& debug_name) = 0; + + protected: + CompiledCodeStorage() {} + ~CompiledCodeStorage() {} + + private: + DISALLOW_COPY_AND_ASSIGN(CompiledCodeStorage); +}; + +} // namespace art + +#endif // ART_COMPILER_DRIVER_COMPILED_CODE_STORAGE_H_ diff --git a/compiler/driver/compiled_method_storage.cc b/compiler/driver/compiled_method_storage.cc deleted file mode 100644 index 4857ec0931..0000000000 --- a/compiler/driver/compiled_method_storage.cc +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -#include <algorithm> -#include <ostream> - -#include "compiled_method_storage.h" - -#include <android-base/logging.h> - -#include "base/data_hash.h" -#include "base/utils.h" -#include "compiled_method.h" -#include "linker/linker_patch.h" -#include "thread-current-inl.h" -#include "utils/dedupe_set-inl.h" -#include "utils/swap_space.h" - -namespace art { - -namespace { // anonymous namespace - -template <typename T> -const LengthPrefixedArray<T>* CopyArray(SwapSpace* swap_space, const ArrayRef<const T>& array) { - DCHECK(!array.empty()); - SwapAllocator<uint8_t> allocator(swap_space); - void* storage = allocator.allocate(LengthPrefixedArray<T>::ComputeSize(array.size())); - LengthPrefixedArray<T>* array_copy = new(storage) LengthPrefixedArray<T>(array.size()); - std::copy(array.begin(), array.end(), array_copy->begin()); - return array_copy; -} - -template <typename T> -void ReleaseArray(SwapSpace* swap_space, const LengthPrefixedArray<T>* array) { - SwapAllocator<uint8_t> allocator(swap_space); - size_t size = LengthPrefixedArray<T>::ComputeSize(array->size()); - array->~LengthPrefixedArray<T>(); - allocator.deallocate(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(array)), size); -} - -} // anonymous namespace - -template <typename T, typename DedupeSetType> -inline const LengthPrefixedArray<T>* CompiledMethodStorage::AllocateOrDeduplicateArray( - const ArrayRef<const T>& data, - DedupeSetType* dedupe_set) { - if (data.empty()) { - return nullptr; - } else if (!DedupeEnabled()) { - return CopyArray(swap_space_.get(), data); - } else { - return dedupe_set->Add(Thread::Current(), data); - } -} - -template <typename T> -inline void CompiledMethodStorage::ReleaseArrayIfNotDeduplicated( - const LengthPrefixedArray<T>* array) { - if (array != nullptr && !DedupeEnabled()) { - ReleaseArray(swap_space_.get(), array); - } -} - -template <typename ContentType> -class CompiledMethodStorage::DedupeHashFunc { - private: - static constexpr bool kUseMurmur3Hash = true; - - public: - size_t operator()(const ArrayRef<ContentType>& array) const { - return DataHash()(array); - } -}; - -template <typename T> -class CompiledMethodStorage::LengthPrefixedArrayAlloc { - public: - explicit LengthPrefixedArrayAlloc(SwapSpace* swap_space) - : swap_space_(swap_space) { - } - - const LengthPrefixedArray<T>* Copy(const ArrayRef<const T>& array) { - return CopyArray(swap_space_, array); - } - - void Destroy(const LengthPrefixedArray<T>* array) { - ReleaseArray(swap_space_, array); - } - - private: - SwapSpace* const swap_space_; -}; - -class CompiledMethodStorage::ThunkMapKey { - public: - ThunkMapKey(linker::LinkerPatch::Type type, uint32_t custom_value1, uint32_t custom_value2) - : type_(type), custom_value1_(custom_value1), custom_value2_(custom_value2) {} - - bool operator<(const ThunkMapKey& other) const { - if (custom_value1_ != other.custom_value1_) { - return custom_value1_ < other.custom_value1_; - } - if (custom_value2_ != other.custom_value2_) { - return custom_value2_ < other.custom_value2_; - } - return type_ < other.type_; - } - - private: - linker::LinkerPatch::Type type_; - uint32_t custom_value1_; - uint32_t custom_value2_; -}; - -class CompiledMethodStorage::ThunkMapValue { - public: - ThunkMapValue(std::vector<uint8_t, SwapAllocator<uint8_t>>&& code, - const std::string& debug_name) - : code_(std::move(code)), debug_name_(debug_name) {} - - ArrayRef<const uint8_t> GetCode() const { - return ArrayRef<const uint8_t>(code_); - } - - const std::string& GetDebugName() const { - return debug_name_; - } - - private: - std::vector<uint8_t, SwapAllocator<uint8_t>> code_; - std::string debug_name_; -}; - -CompiledMethodStorage::CompiledMethodStorage(int swap_fd) - : swap_space_(swap_fd == -1 ? nullptr : new SwapSpace(swap_fd, 10 * MB)), - dedupe_enabled_(true), - dedupe_code_("dedupe code", LengthPrefixedArrayAlloc<uint8_t>(swap_space_.get())), - dedupe_vmap_table_("dedupe vmap table", - LengthPrefixedArrayAlloc<uint8_t>(swap_space_.get())), - dedupe_cfi_info_("dedupe cfi info", LengthPrefixedArrayAlloc<uint8_t>(swap_space_.get())), - dedupe_linker_patches_("dedupe cfi info", - LengthPrefixedArrayAlloc<linker::LinkerPatch>(swap_space_.get())), - thunk_map_lock_("thunk_map_lock"), - thunk_map_(std::less<ThunkMapKey>(), SwapAllocator<ThunkMapValueType>(swap_space_.get())) { -} - -CompiledMethodStorage::~CompiledMethodStorage() { - // All done by member destructors. -} - -void CompiledMethodStorage::DumpMemoryUsage(std::ostream& os, bool extended) const { - if (swap_space_.get() != nullptr) { - const size_t swap_size = swap_space_->GetSize(); - os << " swap=" << PrettySize(swap_size) << " (" << swap_size << "B)"; - } - if (extended) { - Thread* self = Thread::Current(); - os << "\nCode dedupe: " << dedupe_code_.DumpStats(self); - os << "\nVmap table dedupe: " << dedupe_vmap_table_.DumpStats(self); - os << "\nCFI info dedupe: " << dedupe_cfi_info_.DumpStats(self); - } -} - -const LengthPrefixedArray<uint8_t>* CompiledMethodStorage::DeduplicateCode( - const ArrayRef<const uint8_t>& code) { - return AllocateOrDeduplicateArray(code, &dedupe_code_); -} - -void CompiledMethodStorage::ReleaseCode(const LengthPrefixedArray<uint8_t>* code) { - ReleaseArrayIfNotDeduplicated(code); -} - -size_t CompiledMethodStorage::UniqueCodeEntries() const { - DCHECK(DedupeEnabled()); - return dedupe_code_.Size(Thread::Current()); -} - -const LengthPrefixedArray<uint8_t>* CompiledMethodStorage::DeduplicateVMapTable( - const ArrayRef<const uint8_t>& table) { - return AllocateOrDeduplicateArray(table, &dedupe_vmap_table_); -} - -void CompiledMethodStorage::ReleaseVMapTable(const LengthPrefixedArray<uint8_t>* table) { - ReleaseArrayIfNotDeduplicated(table); -} - -size_t CompiledMethodStorage::UniqueVMapTableEntries() const { - DCHECK(DedupeEnabled()); - return dedupe_vmap_table_.Size(Thread::Current()); -} - -const LengthPrefixedArray<uint8_t>* CompiledMethodStorage::DeduplicateCFIInfo( - const ArrayRef<const uint8_t>& cfi_info) { - return AllocateOrDeduplicateArray(cfi_info, &dedupe_cfi_info_); -} - -void CompiledMethodStorage::ReleaseCFIInfo(const LengthPrefixedArray<uint8_t>* cfi_info) { - ReleaseArrayIfNotDeduplicated(cfi_info); -} - -size_t CompiledMethodStorage::UniqueCFIInfoEntries() const { - DCHECK(DedupeEnabled()); - return dedupe_cfi_info_.Size(Thread::Current()); -} - -const LengthPrefixedArray<linker::LinkerPatch>* CompiledMethodStorage::DeduplicateLinkerPatches( - const ArrayRef<const linker::LinkerPatch>& linker_patches) { - return AllocateOrDeduplicateArray(linker_patches, &dedupe_linker_patches_); -} - -void CompiledMethodStorage::ReleaseLinkerPatches( - const LengthPrefixedArray<linker::LinkerPatch>* linker_patches) { - ReleaseArrayIfNotDeduplicated(linker_patches); -} - -size_t CompiledMethodStorage::UniqueLinkerPatchesEntries() const { - DCHECK(DedupeEnabled()); - return dedupe_linker_patches_.Size(Thread::Current()); -} - -CompiledMethodStorage::ThunkMapKey CompiledMethodStorage::GetThunkMapKey( - const linker::LinkerPatch& linker_patch) { - uint32_t custom_value1 = 0u; - uint32_t custom_value2 = 0u; - switch (linker_patch.GetType()) { - case linker::LinkerPatch::Type::kCallEntrypoint: - custom_value1 = linker_patch.EntrypointOffset(); - break; - case linker::LinkerPatch::Type::kBakerReadBarrierBranch: - custom_value1 = linker_patch.GetBakerCustomValue1(); - custom_value2 = linker_patch.GetBakerCustomValue2(); - break; - case linker::LinkerPatch::Type::kCallRelative: - // No custom values. - break; - default: - LOG(FATAL) << "Unexpected patch type: " << linker_patch.GetType(); - UNREACHABLE(); - } - return ThunkMapKey(linker_patch.GetType(), custom_value1, custom_value2); -} - -ArrayRef<const uint8_t> CompiledMethodStorage::GetThunkCode(const linker::LinkerPatch& linker_patch, - /*out*/ std::string* debug_name) { - ThunkMapKey key = GetThunkMapKey(linker_patch); - MutexLock lock(Thread::Current(), thunk_map_lock_); - auto it = thunk_map_.find(key); - if (it != thunk_map_.end()) { - const ThunkMapValue& value = it->second; - if (debug_name != nullptr) { - *debug_name = value.GetDebugName(); - } - return value.GetCode(); - } else { - if (debug_name != nullptr) { - *debug_name = std::string(); - } - return ArrayRef<const uint8_t>(); - } -} - -void CompiledMethodStorage::SetThunkCode(const linker::LinkerPatch& linker_patch, - ArrayRef<const uint8_t> code, - const std::string& debug_name) { - DCHECK(!code.empty()); - ThunkMapKey key = GetThunkMapKey(linker_patch); - std::vector<uint8_t, SwapAllocator<uint8_t>> code_copy( - code.begin(), code.end(), SwapAllocator<uint8_t>(swap_space_.get())); - ThunkMapValue value(std::move(code_copy), debug_name); - MutexLock lock(Thread::Current(), thunk_map_lock_); - // Note: Multiple threads can try and compile the same thunk, so this may not create a new entry. - thunk_map_.emplace(key, std::move(value)); -} - -} // namespace art diff --git a/compiler/driver/compiled_method_storage.h b/compiler/driver/compiled_method_storage.h deleted file mode 100644 index f9f34017eb..0000000000 --- a/compiler/driver/compiled_method_storage.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2015 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_COMPILER_DRIVER_COMPILED_METHOD_STORAGE_H_ -#define ART_COMPILER_DRIVER_COMPILED_METHOD_STORAGE_H_ - -#include <iosfwd> -#include <map> -#include <memory> - -#include "base/array_ref.h" -#include "base/length_prefixed_array.h" -#include "base/macros.h" -#include "utils/dedupe_set.h" -#include "utils/swap_space.h" - -namespace art { - -namespace linker { -class LinkerPatch; -} // namespace linker - -class CompiledMethodStorage { - public: - explicit CompiledMethodStorage(int swap_fd); - ~CompiledMethodStorage(); - - void DumpMemoryUsage(std::ostream& os, bool extended) const; - - void SetDedupeEnabled(bool dedupe_enabled) { - dedupe_enabled_ = dedupe_enabled; - } - bool DedupeEnabled() const { - return dedupe_enabled_; - } - - SwapAllocator<void> GetSwapSpaceAllocator() { - return SwapAllocator<void>(swap_space_.get()); - } - - const LengthPrefixedArray<uint8_t>* DeduplicateCode(const ArrayRef<const uint8_t>& code); - void ReleaseCode(const LengthPrefixedArray<uint8_t>* code); - size_t UniqueCodeEntries() const; - - const LengthPrefixedArray<uint8_t>* DeduplicateVMapTable(const ArrayRef<const uint8_t>& table); - void ReleaseVMapTable(const LengthPrefixedArray<uint8_t>* table); - size_t UniqueVMapTableEntries() const; - - const LengthPrefixedArray<uint8_t>* DeduplicateCFIInfo(const ArrayRef<const uint8_t>& cfi_info); - void ReleaseCFIInfo(const LengthPrefixedArray<uint8_t>* cfi_info); - size_t UniqueCFIInfoEntries() const; - - const LengthPrefixedArray<linker::LinkerPatch>* DeduplicateLinkerPatches( - const ArrayRef<const linker::LinkerPatch>& linker_patches); - void ReleaseLinkerPatches(const LengthPrefixedArray<linker::LinkerPatch>* linker_patches); - size_t UniqueLinkerPatchesEntries() const; - - // Returns the code associated with the given patch. - // If the code has not been set, returns empty data. - // If `debug_name` is not null, stores the associated debug name in `*debug_name`. - ArrayRef<const uint8_t> GetThunkCode(const linker::LinkerPatch& linker_patch, - /*out*/ std::string* debug_name = nullptr); - - // Sets the code and debug name associated with the given patch. - void SetThunkCode(const linker::LinkerPatch& linker_patch, - ArrayRef<const uint8_t> code, - const std::string& debug_name); - - private: - class ThunkMapKey; - class ThunkMapValue; - using ThunkMapValueType = std::pair<const ThunkMapKey, ThunkMapValue>; - using ThunkMap = std::map<ThunkMapKey, - ThunkMapValue, - std::less<ThunkMapKey>, - SwapAllocator<ThunkMapValueType>>; - static_assert(std::is_same<ThunkMapValueType, ThunkMap::value_type>::value, "Value type check."); - - static ThunkMapKey GetThunkMapKey(const linker::LinkerPatch& linker_patch); - - template <typename T, typename DedupeSetType> - const LengthPrefixedArray<T>* AllocateOrDeduplicateArray(const ArrayRef<const T>& data, - DedupeSetType* dedupe_set); - - template <typename T> - void ReleaseArrayIfNotDeduplicated(const LengthPrefixedArray<T>* array); - - // DeDuplication data structures. - template <typename ContentType> - class DedupeHashFunc; - - template <typename T> - class LengthPrefixedArrayAlloc; - - template <typename T> - using ArrayDedupeSet = DedupeSet<ArrayRef<const T>, - LengthPrefixedArray<T>, - LengthPrefixedArrayAlloc<T>, - size_t, - DedupeHashFunc<const T>, - 4>; - - // Swap pool and allocator used for native allocations. May be file-backed. Needs to be first - // as other fields rely on this. - std::unique_ptr<SwapSpace> swap_space_; - - bool dedupe_enabled_; - - ArrayDedupeSet<uint8_t> dedupe_code_; - ArrayDedupeSet<uint8_t> dedupe_vmap_table_; - ArrayDedupeSet<uint8_t> dedupe_cfi_info_; - ArrayDedupeSet<linker::LinkerPatch> dedupe_linker_patches_; - - Mutex thunk_map_lock_; - ThunkMap thunk_map_ GUARDED_BY(thunk_map_lock_); - - DISALLOW_COPY_AND_ASSIGN(CompiledMethodStorage); -}; - -} // namespace art - -#endif // ART_COMPILER_DRIVER_COMPILED_METHOD_STORAGE_H_ diff --git a/compiler/driver/compiled_method_storage_test.cc b/compiler/driver/compiled_method_storage_test.cc deleted file mode 100644 index 05eacd848d..0000000000 --- a/compiler/driver/compiled_method_storage_test.cc +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -#include "compiled_method_storage.h" - -#include <gtest/gtest.h> - -#include "compiled_method-inl.h" - -namespace art { - -TEST(CompiledMethodStorage, Deduplicate) { - CompiledMethodStorage storage(/* swap_fd= */ -1); - - ASSERT_TRUE(storage.DedupeEnabled()); // The default. - - const uint8_t raw_code1[] = { 1u, 2u, 3u }; - const uint8_t raw_code2[] = { 4u, 3u, 2u, 1u }; - ArrayRef<const uint8_t> code[] = { - ArrayRef<const uint8_t>(raw_code1), - ArrayRef<const uint8_t>(raw_code2), - }; - const uint8_t raw_vmap_table1[] = { 2, 4, 6 }; - const uint8_t raw_vmap_table2[] = { 7, 5, 3, 1 }; - ArrayRef<const uint8_t> vmap_table[] = { - ArrayRef<const uint8_t>(raw_vmap_table1), - ArrayRef<const uint8_t>(raw_vmap_table2), - }; - const uint8_t raw_cfi_info1[] = { 1, 3, 5 }; - const uint8_t raw_cfi_info2[] = { 8, 6, 4, 2 }; - ArrayRef<const uint8_t> cfi_info[] = { - ArrayRef<const uint8_t>(raw_cfi_info1), - ArrayRef<const uint8_t>(raw_cfi_info2), - }; - const linker::LinkerPatch raw_patches1[] = { - linker::LinkerPatch::IntrinsicReferencePatch(0u, 0u, 0u), - linker::LinkerPatch::RelativeMethodPatch(4u, nullptr, 0u, 1u), - }; - const linker::LinkerPatch raw_patches2[] = { - linker::LinkerPatch::IntrinsicReferencePatch(0u, 0u, 0u), - linker::LinkerPatch::RelativeMethodPatch(4u, nullptr, 0u, 2u), - }; - ArrayRef<const linker::LinkerPatch> patches[] = { - ArrayRef<const linker::LinkerPatch>(raw_patches1), - ArrayRef<const linker::LinkerPatch>(raw_patches2), - }; - - std::vector<CompiledMethod*> compiled_methods; - compiled_methods.reserve(1u << 4); - for (auto&& c : code) { - for (auto&& v : vmap_table) { - for (auto&& f : cfi_info) { - for (auto&& p : patches) { - compiled_methods.push_back(CompiledMethod::SwapAllocCompiledMethod( - &storage, InstructionSet::kNone, c, v, f, p)); - } - } - } - } - constexpr size_t code_bit = 1u << 3; - constexpr size_t vmap_table_bit = 1u << 2; - constexpr size_t cfi_info_bit = 1u << 1; - constexpr size_t patches_bit = 1u << 0; - CHECK_EQ(compiled_methods.size(), 1u << 4); - for (size_t i = 0; i != compiled_methods.size(); ++i) { - for (size_t j = 0; j != compiled_methods.size(); ++j) { - CompiledMethod* lhs = compiled_methods[i]; - CompiledMethod* rhs = compiled_methods[j]; - bool same_code = ((i ^ j) & code_bit) == 0u; - bool same_vmap_table = ((i ^ j) & vmap_table_bit) == 0u; - bool same_cfi_info = ((i ^ j) & cfi_info_bit) == 0u; - bool same_patches = ((i ^ j) & patches_bit) == 0u; - ASSERT_EQ(same_code, lhs->GetQuickCode().data() == rhs->GetQuickCode().data()) - << i << " " << j; - ASSERT_EQ(same_vmap_table, lhs->GetVmapTable().data() == rhs->GetVmapTable().data()) - << i << " " << j; - ASSERT_EQ(same_cfi_info, lhs->GetCFIInfo().data() == rhs->GetCFIInfo().data()) - << i << " " << j; - ASSERT_EQ(same_patches, lhs->GetPatches().data() == rhs->GetPatches().data()) - << i << " " << j; - } - } - for (CompiledMethod* method : compiled_methods) { - CompiledMethod::ReleaseSwapAllocatedCompiledMethod(&storage, method); - } -} - -} // namespace art diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc index 51cd999b6d..603596f3bc 100644 --- a/compiler/driver/compiler_options.cc +++ b/compiler/driver/compiler_options.cc @@ -23,6 +23,7 @@ #include "arch/instruction_set.h" #include "arch/instruction_set_features.h" +#include "art_method-inl.h" #include "base/runtime_debug.h" #include "base/string_view_cpp20.h" #include "base/variant_map.h" @@ -30,12 +31,11 @@ #include "cmdline_parser.h" #include "compiler_options_map-inl.h" #include "dex/dex_file-inl.h" -#include "dex/verification_results.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" #include "simple_compiler_options_map.h" -namespace art { +namespace art HIDDEN { CompilerOptions::CompilerOptions() : compiler_filter_(CompilerFilter::kDefaultCompilerFilter), @@ -48,7 +48,6 @@ CompilerOptions::CompilerOptions() no_inline_from_(), dex_files_for_oat_file_(), image_classes_(), - verification_results_(nullptr), compiler_type_(CompilerType::kAotCompiler), image_type_(ImageType::kNone), multi_image_(false), @@ -146,14 +145,34 @@ bool CompilerOptions::ParseCompilerOptions(const std::vector<std::string>& optio bool CompilerOptions::IsImageClass(const char* descriptor) const { // Historical note: We used to hold the set indirectly and there was a distinction between an - // empty set and a null, null meaning to include all classes. However, the distiction has been + // empty set and a null, null meaning to include all classes. However, the distinction has been // removed; if we don't have a profile, we treat it as an empty set of classes. b/77340429 return image_classes_.find(std::string_view(descriptor)) != image_classes_.end(); } -const VerificationResults* CompilerOptions::GetVerificationResults() const { - DCHECK(Runtime::Current()->IsAotCompiler()); - return verification_results_; +bool CompilerOptions::IsPreloadedClass(const char* pretty_descriptor) const { + return preloaded_classes_.find(std::string_view(pretty_descriptor)) != preloaded_classes_.end(); +} + +bool CompilerOptions::ShouldCompileWithClinitCheck(ArtMethod* method) const { + if (method != nullptr && + Runtime::Current()->IsAotCompiler() && + method->IsStatic() && + !method->IsConstructor() && + // Compiled code for native methods never do a clinit check, so we may put the resolution + // trampoline for native methods. This means that it's possible post zygote fork for the + // entry to be dirtied. We could resolve this by either: + // - Make these methods use the generic JNI entrypoint, but that's not + // desirable for a method that is in the profile. + // - Ensure the declaring class of such native methods are always in the + // preloaded-classes list. + // - Emit the clinit check in the compiled code of native methods. + !method->IsNative()) { + ScopedObjectAccess soa(Thread::Current()); + ObjPtr<mirror::Class> cls = method->GetDeclaringClass<kWithoutReadBarrier>(); + return cls->IsInBootImageAndNotInPreloadedClasses(); + } + return false; } } // namespace art diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index 1bffdb11ed..c8a41ce24b 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -30,7 +30,7 @@ #include "base/utils.h" #include "optimizing/register_allocator.h" -namespace art { +namespace art HIDDEN { namespace jit { class JitCompiler; @@ -44,11 +44,11 @@ namespace linker { class Arm64RelativePatcherTest; } // namespace linker +class ArtMethod; class DexFile; enum class InstructionSet; class InstructionSetFeatures; class ProfileCompilationInfo; -class VerificationResults; // Enum for CheckProfileMethodsCompiled. Outside CompilerOptions so it can be forward-declared. enum class ProfileMethodsCheck : uint8_t { @@ -83,8 +83,8 @@ class CompilerOptions final { kAppImage, // Creating app image. }; - CompilerOptions(); - ~CompilerOptions(); + EXPORT CompilerOptions(); + EXPORT ~CompilerOptions(); CompilerFilter::Filter GetCompilerFilter() const { return compiler_filter_; @@ -114,12 +114,10 @@ class CompilerOptions final { return compiler_filter_ == CompilerFilter::kAssumeVerified; } - bool VerifyAtRuntime() const { - return compiler_filter_ == CompilerFilter::kExtract; - } - bool IsAnyCompilationEnabled() const { - return CompilerFilter::IsAnyCompilationEnabled(compiler_filter_); + return CompilerFilter::IsAnyCompilationEnabled(compiler_filter_) && + // TODO(riscv64): remove this when we have compiler support for RISC-V + GetInstructionSet() != InstructionSet::kRiscv64; } size_t GetHugeMethodThreshold() const { @@ -298,9 +296,11 @@ class CompilerOptions final { return image_classes_; } - bool IsImageClass(const char* descriptor) const; + EXPORT bool IsImageClass(const char* descriptor) const; - const VerificationResults* GetVerificationResults() const; + // Returns whether the given `pretty_descriptor` is in the list of preloaded + // classes. `pretty_descriptor` should be the result of calling `PrettyDescriptor`. + EXPORT bool IsPreloadedClass(const char* pretty_descriptor) const; bool ParseCompilerOptions(const std::vector<std::string>& options, bool ignore_unrecognized, @@ -383,9 +383,15 @@ class CompilerOptions final { return ContainsElement(GetDexFilesForOatFile(), dex_file); } + // If this is a static non-constructor method in the boot classpath, and its class isn't + // initialized at compile-time, or won't be initialized by the zygote, add + // initialization checks at entry. This will avoid the need of trampolines + // which at runtime we will need to dirty after initialization. + EXPORT bool ShouldCompileWithClinitCheck(ArtMethod* method) const; + private: - bool ParseDumpInitFailures(const std::string& option, std::string* error_msg); - bool ParseRegisterAllocationStrategy(const std::string& option, std::string* error_msg); + EXPORT bool ParseDumpInitFailures(const std::string& option, std::string* error_msg); + EXPORT bool ParseRegisterAllocationStrategy(const std::string& option, std::string* error_msg); CompilerFilter::Filter compiler_filter_; size_t huge_method_threshold_; @@ -408,8 +414,9 @@ class CompilerOptions final { // Must not be empty for real boot image, only for tests pretending to compile boot image. HashSet<std::string> image_classes_; - // Results of AOT verification. - const VerificationResults* verification_results_; + // Classes listed in the preloaded-classes file, used for boot image and + // boot image extension compilation. + HashSet<std::string> preloaded_classes_; CompilerType compiler_type_; ImageType image_type_; diff --git a/compiler/driver/compiler_options_map-inl.h b/compiler/driver/compiler_options_map-inl.h index fcbc0f2f5c..79a59625f5 100644 --- a/compiler/driver/compiler_options_map-inl.h +++ b/compiler/driver/compiler_options_map-inl.h @@ -29,7 +29,7 @@ #include "cmdline_parser.h" #include "compiler_options.h" -namespace art { +namespace art HIDDEN { template <> struct CmdlineType<CompilerFilter::Filter> : CmdlineTypeParser<CompilerFilter::Filter> { @@ -118,6 +118,7 @@ inline bool ReadCompilerOptions(Base& map, CompilerOptions* options, std::string template <typename Map, typename Builder> inline void AddCompilerOptionsArgumentParserOptions(Builder& b) { + // clang-format off b. Define("--compiler-filter=_") .template WithType<CompilerFilter::Filter>() @@ -256,6 +257,7 @@ inline void AddCompilerOptionsArgumentParserOptions(Builder& b) { .template WithType<unsigned int>() .WithHelp("Maximum solid block size for compressed images.") .IntoKey(Map::MaxImageBlockSize); + // clang-format on } #pragma GCC diagnostic pop diff --git a/compiler/driver/compiler_options_map.h b/compiler/driver/compiler_options_map.h index 7e2f8466e0..b2dd57d00e 100644 --- a/compiler/driver/compiler_options_map.h +++ b/compiler/driver/compiler_options_map.h @@ -21,10 +21,11 @@ #include <vector> #include "base/compiler_filter.h" +#include "base/macros.h" #include "base/variant_map.h" #include "cmdline_types.h" -namespace art { +namespace art HIDDEN { enum class ProfileMethodsCheck : uint8_t; diff --git a/compiler/driver/dex_compilation_unit.cc b/compiler/driver/dex_compilation_unit.cc index 0d0f074917..ccebfa9c07 100644 --- a/compiler/driver/dex_compilation_unit.cc +++ b/compiler/driver/dex_compilation_unit.cc @@ -25,7 +25,7 @@ #include "mirror/dex_cache.h" #include "scoped_thread_state_change-inl.h" -namespace art { +namespace art HIDDEN { DexCompilationUnit::DexCompilationUnit(Handle<mirror::ClassLoader> class_loader, ClassLinker* class_linker, diff --git a/compiler/driver/dex_compilation_unit.h b/compiler/driver/dex_compilation_unit.h index def90fa4e1..d595c0a4b2 100644 --- a/compiler/driver/dex_compilation_unit.h +++ b/compiler/driver/dex_compilation_unit.h @@ -20,11 +20,12 @@ #include <stdint.h> #include "base/arena_object.h" +#include "base/macros.h" #include "dex/code_item_accessors.h" #include "dex/dex_file.h" #include "handle.h" -namespace art { +namespace art HIDDEN { namespace mirror { class Class; class ClassLoader; diff --git a/compiler/driver/simple_compiler_options_map.h b/compiler/driver/simple_compiler_options_map.h index e7a51a4995..6663c0c509 100644 --- a/compiler/driver/simple_compiler_options_map.h +++ b/compiler/driver/simple_compiler_options_map.h @@ -23,9 +23,10 @@ #include <memory> #include "compiler_options_map-inl.h" +#include "base/macros.h" #include "base/variant_map.h" -namespace art { +namespace art HIDDEN { template <typename TValue> struct SimpleParseArgumentMapKey : VariantMapKey<TValue> { |