summaryrefslogtreecommitdiff
path: root/compiler/driver
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/driver')
-rw-r--r--compiler/driver/compiled_code_storage.h73
-rw-r--r--compiler/driver/compiled_method_storage.cc288
-rw-r--r--compiler/driver/compiled_method_storage.h135
-rw-r--r--compiler/driver/compiled_method_storage_test.cc101
-rw-r--r--compiler/driver/compiler_options.cc33
-rw-r--r--compiler/driver/compiler_options.h37
-rw-r--r--compiler/driver/compiler_options_map-inl.h4
-rw-r--r--compiler/driver/compiler_options_map.h3
-rw-r--r--compiler/driver/dex_compilation_unit.cc2
-rw-r--r--compiler/driver/dex_compilation_unit.h3
-rw-r--r--compiler/driver/simple_compiler_options_map.h3
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> {