diff options
308 files changed, 15926 insertions, 9774 deletions
diff --git a/benchmark/Android.bp b/benchmark/Android.bp index 606734bd41..3995ca2022 100644 --- a/benchmark/Android.bp +++ b/benchmark/Android.bp @@ -17,7 +17,7 @@ art_cc_library { name: "libartbenchmark", host_supported: true, - defaults: ["art_defaults" ], + defaults: ["art_defaults"], srcs: [ "jni_loader.cc", "jobject-benchmark/jobject_benchmark.cc", @@ -31,15 +31,6 @@ art_cc_library { "libbase", "libnativehelper", ], - clang: true, - target: { - android: { - shared_libs: ["libdl"], - }, - host: { - host_ldlibs: ["-ldl", "-lpthread"], - }, - }, cflags: [ "-Wno-frame-larger-than=", ], @@ -49,7 +40,10 @@ art_cc_library { name: "libartbenchmark-micronative-host", host_supported: true, device_supported: false, - defaults: ["art_debug_defaults", "art_defaults" ], + defaults: [ + "art_debug_defaults", + "art_defaults", + ], srcs: [ "jni_loader.cc", "micro-native/micro_native.cc", @@ -60,12 +54,6 @@ art_cc_library { ], header_libs: ["jni_headers"], stl: "libc++_static", - clang: true, - target: { - host: { - host_ldlibs: ["-ldl", "-lpthread"], - }, - }, cflags: [ "-Wno-frame-larger-than=", ], diff --git a/build/Android.bp b/build/Android.bp index 65df933619..8e8a2f68d8 100644 --- a/build/Android.bp +++ b/build/Android.bp @@ -20,7 +20,6 @@ art_global_defaults { // Additional flags are computed by art.go name: "art_defaults", - clang: true, cflags: [ // Base set of cflags used by all things ART. "-fno-rtti", @@ -90,9 +89,6 @@ art_global_defaults { // Apple, it's a pain. "-Wmissing-noreturn", ], - host_ldlibs: [ - "-lrt", - ], }, host: { cflags: [ @@ -109,10 +105,6 @@ art_global_defaults { "-msse4.2", "-mpopcnt", ], - host_ldlibs: [ - "-ldl", - "-lpthread", - ], }, }, diff --git a/compiler/Android.bp b/compiler/Android.bp index 14756792c0..30448904f9 100644 --- a/compiler/Android.bp +++ b/compiler/Android.bp @@ -23,7 +23,6 @@ art_cc_defaults { name: "libart-compiler-defaults", defaults: ["art_defaults"], host_supported: true, - clang: true, srcs: [ "compiled_method.cc", "debug/elf_debug_writer.cc", @@ -54,6 +53,7 @@ art_cc_defaults { "optimizing/code_sinking.cc", "optimizing/constant_folding.cc", "optimizing/constructor_fence_redundancy_elimination.cc", + "optimizing/data_type.cc", "optimizing/dead_code_elimination.cc", "optimizing/escape.cc", "optimizing/graph_checker.cc", @@ -181,10 +181,6 @@ art_cc_defaults { }, }, target: { - host: { - // For compiler driver TLS. - host_ldlibs: ["-lpthread"], - }, android: { // For atrace. shared_libs: ["libcutils"], @@ -204,10 +200,10 @@ gensrcs { cmd: "$(location generate-operator-out.py) art/compiler $(in) > $(out)", tool_files: ["generate-operator-out.py"], srcs: [ - "compiled_method.h", "dex/dex_to_dex_compiler.h", "driver/compiler_driver.h", "driver/compiler_options.h", + "linker/linker_patch.h", "optimizing/locations.h", "utils/arm/constants_arm.h", @@ -310,16 +306,18 @@ art_cc_test { "art_gtest_defaults", ], srcs: [ - "compiled_method_test.cc", "debug/dwarf/dwarf_test.cc", + "debug/src_map_elem_test.cc", "dex/dex_to_dex_decompiler_test.cc", "driver/compiled_method_storage_test.cc", "driver/compiler_driver_test.cc", "exception_test.cc", "jni/jni_compiler_test.cc", + "linker/linker_patch_test.cc", "linker/method_bss_mapping_encoder_test.cc", "linker/output_stream_test.cc", "optimizing/bounds_check_elimination_test.cc", + "optimizing/data_type_test.cc", "optimizing/dominator_test.cc", "optimizing/find_loops_test.cc", "optimizing/graph_checker_test.cc", diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc index 0d38620b1a..500fc4ae9a 100644 --- a/compiler/common_compiler_test.cc +++ b/compiler/common_compiler_test.cc @@ -22,7 +22,7 @@ #include "base/callee_save_type.h" #include "base/enums.h" #include "class_linker.h" -#include "compiled_method.h" +#include "compiled_method-inl.h" #include "dex/quick_compiler_callbacks.h" #include "dex/verification_results.h" #include "driver/compiler_driver.h" diff --git a/compiler/compiled_method-inl.h b/compiler/compiled_method-inl.h new file mode 100644 index 0000000000..c43274782e --- /dev/null +++ b/compiler/compiled_method-inl.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 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_COMPILED_METHOD_INL_H_ +#define ART_COMPILER_COMPILED_METHOD_INL_H_ + +#include "compiled_method.h" + +#include "base/array_ref.h" +#include "base/length_prefixed_array.h" +#include "linker/linker_patch.h" + +namespace art { + +inline ArrayRef<const uint8_t> CompiledCode::GetQuickCode() const { + return GetArray(quick_code_); +} + +template <typename T> +inline ArrayRef<const T> CompiledCode::GetArray(const LengthPrefixedArray<T>* array) { + if (array == nullptr) { + return ArrayRef<const T>(); + } + DCHECK_NE(array->size(), 0u); + return ArrayRef<const T>(&array->At(0), array->size()); +} + +inline ArrayRef<const uint8_t> CompiledMethod::GetMethodInfo() const { + return GetArray(method_info_); +} + +inline ArrayRef<const uint8_t> CompiledMethod::GetVmapTable() const { + return GetArray(vmap_table_); +} + +inline ArrayRef<const uint8_t> CompiledMethod::GetCFIInfo() const { + return GetArray(cfi_info_); +} + +inline ArrayRef<const linker::LinkerPatch> CompiledMethod::GetPatches() const { + return GetArray(patches_); +} + +} // namespace art + +#endif // ART_COMPILER_COMPILED_METHOD_INL_H_ diff --git a/compiler/compiled_method.cc b/compiler/compiled_method.cc index 0d9021fcfb..111469fe89 100644 --- a/compiler/compiled_method.cc +++ b/compiler/compiled_method.cc @@ -22,7 +22,8 @@ namespace art { -CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set, +CompiledCode::CompiledCode(CompilerDriver* compiler_driver, + InstructionSet instruction_set, const ArrayRef<const uint8_t>& quick_code) : compiler_driver_(compiler_driver), instruction_set_(instruction_set), @@ -77,8 +78,7 @@ size_t CompiledCode::CodeDelta(InstructionSet instruction_set) { } } -const void* CompiledCode::CodePointer(const void* code_pointer, - InstructionSet instruction_set) { +const void* CompiledCode::CodePointer(const void* code_pointer, InstructionSet instruction_set) { switch (instruction_set) { case kArm: case kArm64: @@ -108,7 +108,7 @@ CompiledMethod::CompiledMethod(CompilerDriver* driver, const ArrayRef<const uint8_t>& method_info, const ArrayRef<const uint8_t>& vmap_table, const ArrayRef<const uint8_t>& cfi_info, - const ArrayRef<const LinkerPatch>& patches) + const ArrayRef<const linker::LinkerPatch>& patches) : CompiledCode(driver, instruction_set, quick_code), frame_size_in_bytes_(frame_size_in_bytes), core_spill_mask_(core_spill_mask), @@ -129,7 +129,7 @@ CompiledMethod* CompiledMethod::SwapAllocCompiledMethod( const ArrayRef<const uint8_t>& method_info, const ArrayRef<const uint8_t>& vmap_table, const ArrayRef<const uint8_t>& cfi_info, - const ArrayRef<const LinkerPatch>& patches) { + const ArrayRef<const linker::LinkerPatch>& patches) { SwapAllocator<CompiledMethod> alloc(driver->GetCompiledMethodStorage()->GetSwapSpaceAllocator()); CompiledMethod* ret = alloc.allocate(1); alloc.construct(ret, diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h index 5ef6cbff78..892bc592db 100644 --- a/compiler/compiled_method.h +++ b/compiler/compiled_method.h @@ -17,27 +17,28 @@ #ifndef ART_COMPILER_COMPILED_METHOD_H_ #define ART_COMPILER_COMPILED_METHOD_H_ -#include <iosfwd> #include <memory> #include <string> #include <vector> #include "arch/instruction_set.h" -#include "base/array_ref.h" -#include "base/bit_utils.h" -#include "base/length_prefixed_array.h" -#include "dex_file_types.h" -#include "method_reference.h" namespace art { +template <typename T> class ArrayRef; class CompilerDriver; class CompiledMethodStorage; +template<typename T> class LengthPrefixedArray; + +namespace linker { +class LinkerPatch; +} // namespace linker class CompiledCode { public: // For Quick to supply an code blob - CompiledCode(CompilerDriver* compiler_driver, InstructionSet instruction_set, + CompiledCode(CompilerDriver* compiler_driver, + InstructionSet instruction_set, const ArrayRef<const uint8_t>& quick_code); virtual ~CompiledCode(); @@ -46,9 +47,7 @@ class CompiledCode { return instruction_set_; } - ArrayRef<const uint8_t> GetQuickCode() const { - return GetArray(quick_code_); - } + ArrayRef<const uint8_t> GetQuickCode() const; bool operator==(const CompiledCode& rhs) const; @@ -66,18 +65,11 @@ class CompiledCode { // Returns a pointer suitable for invoking the code at the argument // code_pointer address. Mainly to cope with kThumb2 where the // lower bit must be set to indicate Thumb mode. - static const void* CodePointer(const void* code_pointer, - InstructionSet instruction_set); + static const void* CodePointer(const void* code_pointer, InstructionSet instruction_set); protected: template <typename T> - static ArrayRef<const T> GetArray(const LengthPrefixedArray<T>* array) { - if (array == nullptr) { - return ArrayRef<const T>(); - } - DCHECK_NE(array->size(), 0u); - return ArrayRef<const T>(&array->At(0), array->size()); - } + static ArrayRef<const T> GetArray(const LengthPrefixedArray<T>* array); CompilerDriver* GetCompilerDriver() { return compiler_driver_; @@ -92,298 +84,6 @@ class CompiledCode { const LengthPrefixedArray<uint8_t>* const quick_code_; }; -class SrcMapElem { - public: - uint32_t from_; - int32_t to_; -}; - -inline bool operator<(const SrcMapElem& lhs, const SrcMapElem& rhs) { - if (lhs.from_ != rhs.from_) { - return lhs.from_ < rhs.from_; - } - return lhs.to_ < rhs.to_; -} - -inline bool operator==(const SrcMapElem& lhs, const SrcMapElem& rhs) { - return lhs.from_ == rhs.from_ && lhs.to_ == rhs.to_; -} - -class LinkerPatch { - public: - // Note: We explicitly specify the underlying type of the enum because GCC - // would otherwise select a bigger underlying type and then complain that - // 'art::LinkerPatch::patch_type_' is too small to hold all - // values of 'enum class art::LinkerPatch::Type' - // which is ridiculous given we have only a handful of values here. If we - // choose to squeeze the Type into fewer than 8 bits, we'll have to declare - // patch_type_ as an uintN_t and do explicit static_cast<>s. - enum class Type : uint8_t { - kMethodRelative, // NOTE: Actual patching is instruction_set-dependent. - kMethodBssEntry, // NOTE: Actual patching is instruction_set-dependent. - kCall, - kCallRelative, // NOTE: Actual patching is instruction_set-dependent. - kTypeRelative, // NOTE: Actual patching is instruction_set-dependent. - kTypeClassTable, // NOTE: Actual patching is instruction_set-dependent. - kTypeBssEntry, // NOTE: Actual patching is instruction_set-dependent. - kStringRelative, // NOTE: Actual patching is instruction_set-dependent. - kStringInternTable, // NOTE: Actual patching is instruction_set-dependent. - kStringBssEntry, // NOTE: Actual patching is instruction_set-dependent. - kBakerReadBarrierBranch, // NOTE: Actual patching is instruction_set-dependent. - }; - - static LinkerPatch RelativeMethodPatch(size_t literal_offset, - const DexFile* target_dex_file, - uint32_t pc_insn_offset, - uint32_t target_method_idx) { - LinkerPatch patch(literal_offset, Type::kMethodRelative, target_dex_file); - patch.method_idx_ = target_method_idx; - patch.pc_insn_offset_ = pc_insn_offset; - return patch; - } - - static LinkerPatch MethodBssEntryPatch(size_t literal_offset, - const DexFile* target_dex_file, - uint32_t pc_insn_offset, - uint32_t target_method_idx) { - LinkerPatch patch(literal_offset, Type::kMethodBssEntry, target_dex_file); - patch.method_idx_ = target_method_idx; - patch.pc_insn_offset_ = pc_insn_offset; - return patch; - } - - static LinkerPatch CodePatch(size_t literal_offset, - const DexFile* target_dex_file, - uint32_t target_method_idx) { - LinkerPatch patch(literal_offset, Type::kCall, target_dex_file); - patch.method_idx_ = target_method_idx; - return patch; - } - - static LinkerPatch RelativeCodePatch(size_t literal_offset, - const DexFile* target_dex_file, - uint32_t target_method_idx) { - LinkerPatch patch(literal_offset, Type::kCallRelative, target_dex_file); - patch.method_idx_ = target_method_idx; - return patch; - } - - static LinkerPatch RelativeTypePatch(size_t literal_offset, - const DexFile* target_dex_file, - uint32_t pc_insn_offset, - uint32_t target_type_idx) { - LinkerPatch patch(literal_offset, Type::kTypeRelative, target_dex_file); - patch.type_idx_ = target_type_idx; - patch.pc_insn_offset_ = pc_insn_offset; - return patch; - } - - static LinkerPatch TypeClassTablePatch(size_t literal_offset, - const DexFile* target_dex_file, - uint32_t pc_insn_offset, - uint32_t target_type_idx) { - LinkerPatch patch(literal_offset, Type::kTypeClassTable, target_dex_file); - patch.type_idx_ = target_type_idx; - patch.pc_insn_offset_ = pc_insn_offset; - return patch; - } - - static LinkerPatch TypeBssEntryPatch(size_t literal_offset, - const DexFile* target_dex_file, - uint32_t pc_insn_offset, - uint32_t target_type_idx) { - LinkerPatch patch(literal_offset, Type::kTypeBssEntry, target_dex_file); - patch.type_idx_ = target_type_idx; - patch.pc_insn_offset_ = pc_insn_offset; - return patch; - } - - static LinkerPatch RelativeStringPatch(size_t literal_offset, - const DexFile* target_dex_file, - uint32_t pc_insn_offset, - uint32_t target_string_idx) { - LinkerPatch patch(literal_offset, Type::kStringRelative, target_dex_file); - patch.string_idx_ = target_string_idx; - patch.pc_insn_offset_ = pc_insn_offset; - return patch; - } - - static LinkerPatch StringInternTablePatch(size_t literal_offset, - const DexFile* target_dex_file, - uint32_t pc_insn_offset, - uint32_t target_string_idx) { - LinkerPatch patch(literal_offset, Type::kStringInternTable, target_dex_file); - patch.string_idx_ = target_string_idx; - patch.pc_insn_offset_ = pc_insn_offset; - return patch; - } - - static LinkerPatch StringBssEntryPatch(size_t literal_offset, - const DexFile* target_dex_file, - uint32_t pc_insn_offset, - uint32_t target_string_idx) { - LinkerPatch patch(literal_offset, Type::kStringBssEntry, target_dex_file); - patch.string_idx_ = target_string_idx; - patch.pc_insn_offset_ = pc_insn_offset; - return patch; - } - - static LinkerPatch BakerReadBarrierBranchPatch(size_t literal_offset, - uint32_t custom_value1 = 0u, - uint32_t custom_value2 = 0u) { - LinkerPatch patch(literal_offset, Type::kBakerReadBarrierBranch, nullptr); - patch.baker_custom_value1_ = custom_value1; - patch.baker_custom_value2_ = custom_value2; - return patch; - } - - LinkerPatch(const LinkerPatch& other) = default; - LinkerPatch& operator=(const LinkerPatch& other) = default; - - size_t LiteralOffset() const { - return literal_offset_; - } - - Type GetType() const { - return patch_type_; - } - - bool IsPcRelative() const { - switch (GetType()) { - case Type::kMethodRelative: - case Type::kMethodBssEntry: - case Type::kCallRelative: - case Type::kTypeRelative: - case Type::kTypeClassTable: - case Type::kTypeBssEntry: - case Type::kStringRelative: - case Type::kStringInternTable: - case Type::kStringBssEntry: - case Type::kBakerReadBarrierBranch: - return true; - default: - return false; - } - } - - MethodReference TargetMethod() const { - DCHECK(patch_type_ == Type::kMethodRelative || - patch_type_ == Type::kMethodBssEntry || - patch_type_ == Type::kCall || - patch_type_ == Type::kCallRelative); - return MethodReference(target_dex_file_, method_idx_); - } - - const DexFile* TargetTypeDexFile() const { - DCHECK(patch_type_ == Type::kTypeRelative || - patch_type_ == Type::kTypeClassTable || - patch_type_ == Type::kTypeBssEntry); - return target_dex_file_; - } - - dex::TypeIndex TargetTypeIndex() const { - DCHECK(patch_type_ == Type::kTypeRelative || - patch_type_ == Type::kTypeClassTable || - patch_type_ == Type::kTypeBssEntry); - return dex::TypeIndex(type_idx_); - } - - const DexFile* TargetStringDexFile() const { - DCHECK(patch_type_ == Type::kStringRelative || - patch_type_ == Type::kStringInternTable || - patch_type_ == Type::kStringBssEntry); - return target_dex_file_; - } - - dex::StringIndex TargetStringIndex() const { - DCHECK(patch_type_ == Type::kStringRelative || - patch_type_ == Type::kStringInternTable || - patch_type_ == Type::kStringBssEntry); - return dex::StringIndex(string_idx_); - } - - uint32_t PcInsnOffset() const { - DCHECK(patch_type_ == Type::kMethodRelative || - patch_type_ == Type::kMethodBssEntry || - patch_type_ == Type::kTypeRelative || - patch_type_ == Type::kTypeClassTable || - patch_type_ == Type::kTypeBssEntry || - patch_type_ == Type::kStringRelative || - patch_type_ == Type::kStringInternTable || - patch_type_ == Type::kStringBssEntry); - return pc_insn_offset_; - } - - uint32_t GetBakerCustomValue1() const { - DCHECK(patch_type_ == Type::kBakerReadBarrierBranch); - return baker_custom_value1_; - } - - uint32_t GetBakerCustomValue2() const { - DCHECK(patch_type_ == Type::kBakerReadBarrierBranch); - return baker_custom_value2_; - } - - private: - LinkerPatch(size_t literal_offset, Type patch_type, const DexFile* target_dex_file) - : target_dex_file_(target_dex_file), - literal_offset_(literal_offset), - patch_type_(patch_type) { - cmp1_ = 0u; - cmp2_ = 0u; - // The compiler rejects methods that are too big, so the compiled code - // of a single method really shouln't be anywhere close to 16MiB. - DCHECK(IsUint<24>(literal_offset)); - } - - const DexFile* target_dex_file_; - // TODO: Clean up naming. Some patched locations are literals but others are not. - uint32_t literal_offset_ : 24; // Method code size up to 16MiB. - Type patch_type_ : 8; - union { - uint32_t cmp1_; // Used for relational operators. - uint32_t method_idx_; // Method index for Call/Method patches. - uint32_t type_idx_; // Type index for Type patches. - uint32_t string_idx_; // String index for String patches. - uint32_t baker_custom_value1_; - static_assert(sizeof(method_idx_) == sizeof(cmp1_), "needed by relational operators"); - static_assert(sizeof(type_idx_) == sizeof(cmp1_), "needed by relational operators"); - static_assert(sizeof(string_idx_) == sizeof(cmp1_), "needed by relational operators"); - static_assert(sizeof(baker_custom_value1_) == sizeof(cmp1_), "needed by relational operators"); - }; - union { - // Note: To avoid uninitialized padding on 64-bit systems, we use `size_t` for `cmp2_`. - // This allows a hashing function to treat an array of linker patches as raw memory. - size_t cmp2_; // Used for relational operators. - // Literal offset of the insn loading PC (same as literal_offset if it's the same insn, - // may be different if the PC-relative addressing needs multiple insns). - uint32_t pc_insn_offset_; - uint32_t baker_custom_value2_; - static_assert(sizeof(pc_insn_offset_) <= sizeof(cmp2_), "needed by relational operators"); - static_assert(sizeof(baker_custom_value2_) <= sizeof(cmp2_), "needed by relational operators"); - }; - - friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs); - friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs); -}; -std::ostream& operator<<(std::ostream& os, const LinkerPatch::Type& type); - -inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) { - return lhs.literal_offset_ == rhs.literal_offset_ && - lhs.patch_type_ == rhs.patch_type_ && - lhs.target_dex_file_ == rhs.target_dex_file_ && - lhs.cmp1_ == rhs.cmp1_ && - lhs.cmp2_ == rhs.cmp2_; -} - -inline bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs) { - return (lhs.literal_offset_ != rhs.literal_offset_) ? lhs.literal_offset_ < rhs.literal_offset_ - : (lhs.patch_type_ != rhs.patch_type_) ? lhs.patch_type_ < rhs.patch_type_ - : (lhs.target_dex_file_ != rhs.target_dex_file_) ? lhs.target_dex_file_ < rhs.target_dex_file_ - : (lhs.cmp1_ != rhs.cmp1_) ? lhs.cmp1_ < rhs.cmp1_ - : lhs.cmp2_ < rhs.cmp2_; -} - class CompiledMethod FINAL : public CompiledCode { public: // Constructs a CompiledMethod. @@ -398,7 +98,7 @@ class CompiledMethod FINAL : public CompiledCode { const ArrayRef<const uint8_t>& method_info, const ArrayRef<const uint8_t>& vmap_table, const ArrayRef<const uint8_t>& cfi_info, - const ArrayRef<const LinkerPatch>& patches); + const ArrayRef<const linker::LinkerPatch>& patches); virtual ~CompiledMethod(); @@ -412,7 +112,7 @@ class CompiledMethod FINAL : public CompiledCode { const ArrayRef<const uint8_t>& method_info, const ArrayRef<const uint8_t>& vmap_table, const ArrayRef<const uint8_t>& cfi_info, - const ArrayRef<const LinkerPatch>& patches); + const ArrayRef<const linker::LinkerPatch>& patches); static void ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m); @@ -428,21 +128,13 @@ class CompiledMethod FINAL : public CompiledCode { return fp_spill_mask_; } - ArrayRef<const uint8_t> GetMethodInfo() const { - return GetArray(method_info_); - } + ArrayRef<const uint8_t> GetMethodInfo() const; - ArrayRef<const uint8_t> GetVmapTable() const { - return GetArray(vmap_table_); - } + ArrayRef<const uint8_t> GetVmapTable() const; - ArrayRef<const uint8_t> GetCFIInfo() const { - return GetArray(cfi_info_); - } + ArrayRef<const uint8_t> GetCFIInfo() const; - ArrayRef<const LinkerPatch> GetPatches() const { - return GetArray(patches_); - } + ArrayRef<const linker::LinkerPatch> GetPatches() const; private: // For quick code, the size of the activation used by the code. @@ -458,7 +150,7 @@ class CompiledMethod FINAL : public CompiledCode { // For quick code, a FDE entry for the debug_frame section. const LengthPrefixedArray<uint8_t>* const cfi_info_; // For quick code, linker patches needed by the method. - const LengthPrefixedArray<LinkerPatch>* const patches_; + const LengthPrefixedArray<linker::LinkerPatch>* const patches_; }; } // namespace art diff --git a/compiler/debug/elf_debug_line_writer.h b/compiler/debug/elf_debug_line_writer.h index cf5d65efac..49d52c45c2 100644 --- a/compiler/debug/elf_debug_line_writer.h +++ b/compiler/debug/elf_debug_line_writer.h @@ -20,10 +20,10 @@ #include <unordered_set> #include <vector> -#include "compiled_method.h" #include "debug/dwarf/debug_line_opcode_writer.h" #include "debug/dwarf/headers.h" #include "debug/elf_compilation_unit.h" +#include "debug/src_map_elem.h" #include "dex_file-inl.h" #include "linker/elf_builder.h" #include "stack_map.h" diff --git a/compiler/debug/method_debug_info.h b/compiler/debug/method_debug_info.h index 567891087a..a8225fa2b4 100644 --- a/compiler/debug/method_debug_info.h +++ b/compiler/debug/method_debug_info.h @@ -19,7 +19,8 @@ #include <string> -#include "compiled_method.h" +#include "arch/instruction_set.h" +#include "base/array_ref.h" #include "dex_file.h" namespace art { diff --git a/compiler/debug/src_map_elem.h b/compiler/debug/src_map_elem.h new file mode 100644 index 0000000000..5286b8c4dc --- /dev/null +++ b/compiler/debug/src_map_elem.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2017 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_DEBUG_SRC_MAP_ELEM_H_ +#define ART_COMPILER_DEBUG_SRC_MAP_ELEM_H_ + +#include <stdint.h> + +namespace art { + +class SrcMapElem { + public: + uint32_t from_; + int32_t to_; +}; + +inline bool operator<(const SrcMapElem& lhs, const SrcMapElem& rhs) { + if (lhs.from_ != rhs.from_) { + return lhs.from_ < rhs.from_; + } + return lhs.to_ < rhs.to_; +} + +inline bool operator==(const SrcMapElem& lhs, const SrcMapElem& rhs) { + return lhs.from_ == rhs.from_ && lhs.to_ == rhs.to_; +} + +} // namespace art + +#endif // ART_COMPILER_DEBUG_SRC_MAP_ELEM_H_ diff --git a/compiler/debug/src_map_elem_test.cc b/compiler/debug/src_map_elem_test.cc new file mode 100644 index 0000000000..ceaa53fa99 --- /dev/null +++ b/compiler/debug/src_map_elem_test.cc @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 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 <gtest/gtest.h> + +#include "src_map_elem.h" + +#include "base/macros.h" + +namespace art { +namespace debug { + +TEST(SrcMapElem, Operators) { + SrcMapElem elems[] = { + { 1u, -1 }, + { 1u, 0 }, + { 1u, 1 }, + { 2u, -1 }, + { 2u, 0 }, // Index 4. + { 2u, 1 }, + { 2u, 0u }, // Index 6: Arbitrarily add identical SrcMapElem with index 4. + }; + + for (size_t i = 0; i != arraysize(elems); ++i) { + for (size_t j = 0; j != arraysize(elems); ++j) { + bool expected = (i != 6u ? i : 4u) == (j != 6u ? j : 4u); + EXPECT_EQ(expected, elems[i] == elems[j]) << i << " " << j; + } + } + + for (size_t i = 0; i != arraysize(elems); ++i) { + for (size_t j = 0; j != arraysize(elems); ++j) { + bool expected = (i != 6u ? i : 4u) < (j != 6u ? j : 4u); + EXPECT_EQ(expected, elems[i] < elems[j]) << i << " " << j; + } + } +} + +} // namespace debug +} // namespace art diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc index 9d57b965ab..7581962a86 100644 --- a/compiler/dex/dex_to_dex_compiler.cc +++ b/compiler/dex/dex_to_dex_compiler.cc @@ -374,8 +374,8 @@ CompiledMethod* ArtCompileDEX( // Dex pc is not serialized, only used for checking the instructions. Since we access the // array based on the index of the quickened instruction, the indexes must line up perfectly. // The reader side uses the NeedsIndexForInstruction function too. - const Instruction* inst = Instruction::At(code_item->insns_ + info.dex_pc); - CHECK(QuickenInfoTable::NeedsIndexForInstruction(inst)) << inst->Opcode(); + const Instruction& inst = code_item->InstructionAt(info.dex_pc); + CHECK(QuickenInfoTable::NeedsIndexForInstruction(&inst)) << inst.Opcode(); // Add the index. quicken_data.push_back(static_cast<uint8_t>(info.dex_member_index >> 0)); quicken_data.push_back(static_cast<uint8_t>(info.dex_member_index >> 8)); @@ -395,7 +395,7 @@ CompiledMethod* ArtCompileDEX( ArrayRef<const uint8_t>(), // method_info ArrayRef<const uint8_t>(quicken_data), // vmap_table ArrayRef<const uint8_t>(), // cfi data - ArrayRef<const LinkerPatch>()); + ArrayRef<const linker::LinkerPatch>()); } return nullptr; } diff --git a/compiler/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc index e36d416e9f..6637be2811 100644 --- a/compiler/dex/dex_to_dex_decompiler_test.cc +++ b/compiler/dex/dex_to_dex_decompiler_test.cc @@ -18,7 +18,7 @@ #include "class_linker.h" #include "common_compiler_test.h" -#include "compiled_method.h" +#include "compiled_method-inl.h" #include "compiler_callbacks.h" #include "dex_file.h" #include "driver/compiler_driver.h" diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc index c8e3d5edd8..925863ef0e 100644 --- a/compiler/dex/inline_method_analyser.cc +++ b/compiler/dex/inline_method_analyser.cc @@ -64,14 +64,14 @@ class Matcher { private: explicit Matcher(const DexFile::CodeItem* code_item) : code_item_(code_item), - instruction_(Instruction::At(code_item->insns_)), + instruction_(code_item->Instructions().begin()), pos_(0u), mark_(0u) { } static bool DoMatch(const DexFile::CodeItem* code_item, MatchFn* const* pattern, size_t size); const DexFile::CodeItem* const code_item_; - const Instruction* instruction_; + DexInstructionIterator instruction_; size_t pos_; size_t mark_; }; @@ -93,7 +93,7 @@ bool Matcher::Required(Matcher* matcher) { return false; } matcher->pos_ += 1u; - matcher->instruction_ = matcher->instruction_->Next(); + ++matcher->instruction_; return true; } @@ -105,7 +105,7 @@ bool Matcher::Repeated(Matcher* matcher) { return true; } matcher->pos_ = matcher->mark_; - matcher->instruction_ = matcher->instruction_->Next(); + ++matcher->instruction_; return true; } @@ -301,26 +301,27 @@ bool DoAnalyseConstructor(const DexFile::CodeItem* code_item, // Verify the invoke, prevent a few odd cases and collect IPUTs. uint16_t this_vreg = code_item->registers_size_ - code_item->ins_size_; uint16_t zero_vreg_mask = 0u; - for (const Instruction* instruction = Instruction::At(code_item->insns_); - instruction->Opcode() != Instruction::RETURN_VOID; - instruction = instruction->Next()) { - if (instruction->Opcode() == Instruction::INVOKE_DIRECT) { - ArtMethod* target_method = GetTargetConstructor(method, instruction); + + for (const Instruction& instruction : code_item->Instructions()) { + if (instruction.Opcode() == Instruction::RETURN_VOID) { + break; + } else if (instruction.Opcode() == Instruction::INVOKE_DIRECT) { + ArtMethod* target_method = GetTargetConstructor(method, &instruction); if (target_method == nullptr) { return false; } // We allow forwarding constructors only if they pass more arguments // to prevent infinite recursion. if (target_method->GetDeclaringClass() == method->GetDeclaringClass() && - instruction->VRegA_35c() <= code_item->ins_size_) { + instruction.VRegA_35c() <= code_item->ins_size_) { return false; } - size_t forwarded = CountForwardedConstructorArguments(code_item, instruction, zero_vreg_mask); + size_t forwarded = CountForwardedConstructorArguments(code_item, &instruction, zero_vreg_mask); if (forwarded == static_cast<size_t>(-1)) { return false; } if (target_method->GetDeclaringClass()->IsObjectClass()) { - DCHECK_EQ(Instruction::At(target_method->GetCodeItem()->insns_)->Opcode(), + DCHECK_EQ(target_method->GetCodeItem()->Instructions().begin()->Opcode(), Instruction::RETURN_VOID); } else { const DexFile::CodeItem* target_code_item = target_method->GetCodeItem(); @@ -345,15 +346,15 @@ bool DoAnalyseConstructor(const DexFile::CodeItem* code_item, return false; } } - } else if (IsInstructionDirectConst(instruction->Opcode())) { - zero_vreg_mask |= GetZeroVRegMask(instruction); + } else if (IsInstructionDirectConst(instruction.Opcode())) { + zero_vreg_mask |= GetZeroVRegMask(&instruction); if ((zero_vreg_mask & (1u << this_vreg)) != 0u) { return false; // Overwriting `this` is unsupported. } } else { - DCHECK(IsInstructionIPut(instruction->Opcode())); - DCHECK_EQ(instruction->VRegB_22c(), this_vreg); - if (!RecordConstructorIPut(method, instruction, this_vreg, zero_vreg_mask, iputs)) { + DCHECK(IsInstructionIPut(instruction.Opcode())); + DCHECK_EQ(instruction.VRegB_22c(), this_vreg); + if (!RecordConstructorIPut(method, &instruction, this_vreg, zero_vreg_mask, iputs)) { return false; } } @@ -447,8 +448,7 @@ bool InlineMethodAnalyser::AnalyseMethodCode(const DexFile::CodeItem* code_item, // We currently support only plain return or 2-instruction methods. DCHECK_NE(code_item->insns_size_in_code_units_, 0u); - const Instruction* instruction = Instruction::At(code_item->insns_); - Instruction::Code opcode = instruction->Opcode(); + Instruction::Code opcode = code_item->Instructions().begin()->Opcode(); switch (opcode) { case Instruction::RETURN_VOID: @@ -519,7 +519,7 @@ bool InlineMethodAnalyser::IsSyntheticAccessor(MethodReference ref) { bool InlineMethodAnalyser::AnalyseReturnMethod(const DexFile::CodeItem* code_item, InlineMethod* result) { - const Instruction* return_instruction = Instruction::At(code_item->insns_); + DexInstructionIterator return_instruction = code_item->Instructions().begin(); Instruction::Code return_opcode = return_instruction->Opcode(); uint32_t reg = return_instruction->VRegA_11x(); uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_; @@ -541,7 +541,7 @@ bool InlineMethodAnalyser::AnalyseReturnMethod(const DexFile::CodeItem* code_ite bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item, InlineMethod* result) { - const Instruction* instruction = Instruction::At(code_item->insns_); + DexInstructionIterator instruction = code_item->Instructions().begin(); const Instruction* return_instruction = instruction->Next(); Instruction::Code return_opcode = return_instruction->Opcode(); if (return_opcode != Instruction::RETURN && @@ -575,7 +575,7 @@ bool InlineMethodAnalyser::AnalyseIGetMethod(const DexFile::CodeItem* code_item, bool is_static, ArtMethod* method, InlineMethod* result) { - const Instruction* instruction = Instruction::At(code_item->insns_); + DexInstructionIterator instruction = code_item->Instructions().begin(); Instruction::Code opcode = instruction->Opcode(); DCHECK(IsInstructionIGet(opcode)); @@ -639,7 +639,7 @@ bool InlineMethodAnalyser::AnalyseIPutMethod(const DexFile::CodeItem* code_item, bool is_static, ArtMethod* method, InlineMethod* result) { - const Instruction* instruction = Instruction::At(code_item->insns_); + DexInstructionIterator instruction = code_item->Instructions().begin(); Instruction::Code opcode = instruction->Opcode(); DCHECK(IsInstructionIPut(opcode)); diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc index e46dc597fa..9c5b63232e 100644 --- a/compiler/dex/verified_method.cc +++ b/compiler/dex/verified_method.cc @@ -64,24 +64,21 @@ void VerifiedMethod::GenerateSafeCastSet(verifier::MethodVerifier* method_verifi if (method_verifier->HasFailures()) { return; } - const DexFile::CodeItem* code_item = method_verifier->CodeItem(); - const Instruction* inst = Instruction::At(code_item->insns_); - const Instruction* end = Instruction::At(code_item->insns_ + - code_item->insns_size_in_code_units_); - - for (; inst < end; inst = inst->Next()) { - Instruction::Code code = inst->Opcode(); + IterationRange<DexInstructionIterator> instructions = method_verifier->CodeItem()->Instructions(); + for (auto it = instructions.begin(); it != instructions.end(); ++it) { + const Instruction& inst = *it; + const Instruction::Code code = inst.Opcode(); if (code == Instruction::CHECK_CAST) { - uint32_t dex_pc = inst->GetDexPc(code_item->insns_); + const uint32_t dex_pc = it.GetDexPC(instructions.begin()); if (!method_verifier->GetInstructionFlags(dex_pc).IsVisited()) { // Do not attempt to quicken this instruction, it's unreachable anyway. continue; } const verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc); const verifier::RegType& reg_type(line->GetRegisterType(method_verifier, - inst->VRegA_21c())); + inst.VRegA_21c())); const verifier::RegType& cast_type = - method_verifier->ResolveCheckedClass(dex::TypeIndex(inst->VRegB_21c())); + method_verifier->ResolveCheckedClass(dex::TypeIndex(inst.VRegB_21c())); // Pass null for the method verifier to not record the VerifierDeps dependency // if the types are not assignable. if (cast_type.IsStrictlyAssignableFrom(reg_type, /* method_verifier */ nullptr)) { diff --git a/compiler/driver/compiled_method_storage.cc b/compiler/driver/compiled_method_storage.cc index 528b0a215b..c739333cee 100644 --- a/compiler/driver/compiled_method_storage.cc +++ b/compiler/driver/compiled_method_storage.cc @@ -21,6 +21,7 @@ #include "base/logging.h" #include "compiled_method.h" +#include "linker/linker_patch.h" #include "thread-current-inl.h" #include "utils.h" #include "utils/dedupe_set-inl.h" @@ -178,7 +179,7 @@ CompiledMethodStorage::CompiledMethodStorage(int swap_fd) 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<LinkerPatch>(swap_space_.get())) { + LengthPrefixedArrayAlloc<linker::LinkerPatch>(swap_space_.get())) { } CompiledMethodStorage::~CompiledMethodStorage() { @@ -234,13 +235,13 @@ void CompiledMethodStorage::ReleaseCFIInfo(const LengthPrefixedArray<uint8_t>* c ReleaseArrayIfNotDeduplicated(cfi_info); } -const LengthPrefixedArray<LinkerPatch>* CompiledMethodStorage::DeduplicateLinkerPatches( - const ArrayRef<const LinkerPatch>& linker_patches) { +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<LinkerPatch>* linker_patches) { + const LengthPrefixedArray<linker::LinkerPatch>* linker_patches) { ReleaseArrayIfNotDeduplicated(linker_patches); } diff --git a/compiler/driver/compiled_method_storage.h b/compiler/driver/compiled_method_storage.h index 27011e8955..249f06c20f 100644 --- a/compiler/driver/compiled_method_storage.h +++ b/compiler/driver/compiled_method_storage.h @@ -28,7 +28,9 @@ namespace art { +namespace linker { class LinkerPatch; +} // namespace linker class CompiledMethodStorage { public: @@ -61,9 +63,9 @@ class CompiledMethodStorage { const LengthPrefixedArray<uint8_t>* DeduplicateCFIInfo(const ArrayRef<const uint8_t>& cfi_info); void ReleaseCFIInfo(const LengthPrefixedArray<uint8_t>* cfi_info); - const LengthPrefixedArray<LinkerPatch>* DeduplicateLinkerPatches( - const ArrayRef<const LinkerPatch>& linker_patches); - void ReleaseLinkerPatches(const LengthPrefixedArray<LinkerPatch>* linker_patches); + const LengthPrefixedArray<linker::LinkerPatch>* DeduplicateLinkerPatches( + const ArrayRef<const linker::LinkerPatch>& linker_patches); + void ReleaseLinkerPatches(const LengthPrefixedArray<linker::LinkerPatch>* linker_patches); private: template <typename T, typename DedupeSetType> @@ -98,7 +100,7 @@ class CompiledMethodStorage { ArrayDedupeSet<uint8_t> dedupe_method_info_; ArrayDedupeSet<uint8_t> dedupe_vmap_table_; ArrayDedupeSet<uint8_t> dedupe_cfi_info_; - ArrayDedupeSet<LinkerPatch> dedupe_linker_patches_; + ArrayDedupeSet<linker::LinkerPatch> dedupe_linker_patches_; DISALLOW_COPY_AND_ASSIGN(CompiledMethodStorage); }; diff --git a/compiler/driver/compiled_method_storage_test.cc b/compiler/driver/compiled_method_storage_test.cc index 2ec2af587e..e1ea6304eb 100644 --- a/compiler/driver/compiled_method_storage_test.cc +++ b/compiler/driver/compiled_method_storage_test.cc @@ -18,7 +18,7 @@ #include <gtest/gtest.h> -#include "compiled_method.h" +#include "compiled_method-inl.h" #include "compiler_driver.h" #include "compiler_options.h" #include "dex/verification_results.h" @@ -70,17 +70,17 @@ TEST(CompiledMethodStorage, Deduplicate) { ArrayRef<const uint8_t>(raw_cfi_info1), ArrayRef<const uint8_t>(raw_cfi_info2), }; - const LinkerPatch raw_patches1[] = { - LinkerPatch::CodePatch(0u, nullptr, 1u), - LinkerPatch::RelativeMethodPatch(4u, nullptr, 0u, 1u), + const linker::LinkerPatch raw_patches1[] = { + linker::LinkerPatch::CodePatch(0u, nullptr, 1u), + linker::LinkerPatch::RelativeMethodPatch(4u, nullptr, 0u, 1u), }; - const LinkerPatch raw_patches2[] = { - LinkerPatch::CodePatch(0u, nullptr, 1u), - LinkerPatch::RelativeMethodPatch(4u, nullptr, 0u, 2u), + const linker::LinkerPatch raw_patches2[] = { + linker::LinkerPatch::CodePatch(0u, nullptr, 1u), + linker::LinkerPatch::RelativeMethodPatch(4u, nullptr, 0u, 2u), }; - ArrayRef<const LinkerPatch> patches[] = { - ArrayRef<const LinkerPatch>(raw_patches1), - ArrayRef<const LinkerPatch>(raw_patches2), + ArrayRef<const linker::LinkerPatch> patches[] = { + ArrayRef<const linker::LinkerPatch>(raw_patches1), + ArrayRef<const linker::LinkerPatch>(raw_patches2), }; std::vector<CompiledMethod*> compiled_methods; diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 678f090532..7573367788 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -37,7 +37,7 @@ #include "base/time_utils.h" #include "base/timing_logger.h" #include "class_linker-inl.h" -#include "compiled_method.h" +#include "compiled_method-inl.h" #include "compiler.h" #include "compiler_callbacks.h" #include "compiler_driver-inl.h" @@ -55,6 +55,7 @@ #include "handle_scope-inl.h" #include "intrinsics_enum.h" #include "jni_internal.h" +#include "linker/linker_patch.h" #include "mirror/class-inl.h" #include "mirror/class_loader.h" #include "mirror/dex_cache-inl.h" @@ -618,7 +619,7 @@ static void CompileMethod(Thread* self, if (compiled_method != nullptr) { // Count non-relative linker patches. size_t non_relative_linker_patch_count = 0u; - for (const LinkerPatch& patch : compiled_method->GetPatches()) { + for (const linker::LinkerPatch& patch : compiled_method->GetPatches()) { if (!patch.IsPcRelative()) { ++non_relative_linker_patch_count; } @@ -761,18 +762,14 @@ static void ResolveConstStrings(Handle<mirror::DexCache> dex_cache, return; } - const uint16_t* code_ptr = code_item->insns_; - const uint16_t* code_end = code_item->insns_ + code_item->insns_size_in_code_units_; ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); - - while (code_ptr < code_end) { - const Instruction* inst = Instruction::At(code_ptr); - switch (inst->Opcode()) { + for (const Instruction& inst : code_item->Instructions()) { + switch (inst.Opcode()) { case Instruction::CONST_STRING: case Instruction::CONST_STRING_JUMBO: { - dex::StringIndex string_index((inst->Opcode() == Instruction::CONST_STRING) - ? inst->VRegB_21c() - : inst->VRegB_31c()); + dex::StringIndex string_index((inst.Opcode() == Instruction::CONST_STRING) + ? inst.VRegB_21c() + : inst.VRegB_31c()); mirror::String* string = class_linker->ResolveString(dex_file, string_index, dex_cache); CHECK(string != nullptr) << "Could not allocate a string when forcing determinism"; break; @@ -781,8 +778,6 @@ static void ResolveConstStrings(Handle<mirror::DexCache> dex_cache, default: break; } - - code_ptr += inst->SizeInCodeUnits(); } } @@ -2438,21 +2433,16 @@ class InitializeClassVisitor : public CompilationVisitor { if (clinit != nullptr) { const DexFile::CodeItem* code_item = clinit->GetCodeItem(); DCHECK(code_item != nullptr); - const Instruction* inst = Instruction::At(code_item->insns_); - - const uint32_t insns_size = code_item->insns_size_in_code_units_; - for (uint32_t dex_pc = 0; dex_pc < insns_size;) { - if (inst->Opcode() == Instruction::CONST_STRING) { + for (const Instruction& inst : code_item->Instructions()) { + if (inst.Opcode() == Instruction::CONST_STRING) { ObjPtr<mirror::String> s = class_linker->ResolveString( - *dex_file, dex::StringIndex(inst->VRegB_21c()), h_dex_cache); + *dex_file, dex::StringIndex(inst.VRegB_21c()), h_dex_cache); CHECK(s != nullptr); - } else if (inst->Opcode() == Instruction::CONST_STRING_JUMBO) { + } else if (inst.Opcode() == Instruction::CONST_STRING_JUMBO) { ObjPtr<mirror::String> s = class_linker->ResolveString( - *dex_file, dex::StringIndex(inst->VRegB_31c()), h_dex_cache); + *dex_file, dex::StringIndex(inst.VRegB_31c()), h_dex_cache); CHECK(s != nullptr); } - dex_pc += inst->SizeInCodeUnits(); - inst = inst->Next(); } } } diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc index 5fdf9ff07c..511a44af04 100644 --- a/compiler/jit/jit_compiler.cc +++ b/compiler/jit/jit_compiler.cc @@ -175,7 +175,8 @@ bool JitCompiler::CompileMethod(Thread* self, ArtMethod* method, bool osr) { DCHECK(!method->IsProxyMethod()); DCHECK(method->GetDeclaringClass()->IsResolved()); - TimingLogger logger("JIT compiler timing logger", true, VLOG_IS_ON(jit)); + TimingLogger logger( + "JIT compiler timing logger", true, VLOG_IS_ON(jit), TimingLogger::TimingKind::kThreadCpu); self->AssertNoPendingException(); Runtime* runtime = Runtime::Current(); diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc index e7e4647866..c66a2a62eb 100644 --- a/compiler/jni/quick/jni_compiler.cc +++ b/compiler/jni/quick/jni_compiler.cc @@ -665,7 +665,7 @@ static CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver* driver, /* method_info */ ArrayRef<const uint8_t>(), /* vmap_table */ ArrayRef<const uint8_t>(), ArrayRef<const uint8_t>(*jni_asm->cfi().data()), - ArrayRef<const LinkerPatch>()); + ArrayRef<const linker::LinkerPatch>()); } // Copy a single parameter from the managed to the JNI calling convention. diff --git a/compiler/linker/arm/relative_patcher_arm_base.cc b/compiler/linker/arm/relative_patcher_arm_base.cc index cb6522cbbb..2cb23d1710 100644 --- a/compiler/linker/arm/relative_patcher_arm_base.cc +++ b/compiler/linker/arm/relative_patcher_arm_base.cc @@ -17,9 +17,10 @@ #include "linker/arm/relative_patcher_arm_base.h" #include "base/stl_util.h" -#include "compiled_method.h" +#include "compiled_method-inl.h" #include "debug/method_debug_info.h" #include "dex_file_types.h" +#include "linker/linker_patch.h" #include "linker/output_stream.h" #include "oat.h" #include "oat_quick_method_header.h" diff --git a/compiler/linker/arm/relative_patcher_thumb2.cc b/compiler/linker/arm/relative_patcher_thumb2.cc index 704feeb387..f84fea378d 100644 --- a/compiler/linker/arm/relative_patcher_thumb2.cc +++ b/compiler/linker/arm/relative_patcher_thumb2.cc @@ -21,6 +21,7 @@ #include "base/bit_utils.h" #include "compiled_method.h" #include "entrypoints/quick/quick_entrypoints_enum.h" +#include "linker/linker_patch.h" #include "lock_word.h" #include "mirror/array-inl.h" #include "mirror/object.h" diff --git a/compiler/linker/arm64/relative_patcher_arm64.cc b/compiler/linker/arm64/relative_patcher_arm64.cc index 82f502a3af..828c99ba86 100644 --- a/compiler/linker/arm64/relative_patcher_arm64.cc +++ b/compiler/linker/arm64/relative_patcher_arm64.cc @@ -20,10 +20,11 @@ #include "arch/arm64/instruction_set_features_arm64.h" #include "art_method.h" #include "base/bit_utils.h" -#include "compiled_method.h" +#include "compiled_method-inl.h" #include "driver/compiler_driver.h" #include "entrypoints/quick/quick_entrypoints_enum.h" #include "heap_poisoning.h" +#include "linker/linker_patch.h" #include "linker/output_stream.h" #include "lock_word.h" #include "mirror/array-inl.h" diff --git a/compiler/linker/linker_patch.h b/compiler/linker/linker_patch.h new file mode 100644 index 0000000000..0ac149029a --- /dev/null +++ b/compiler/linker/linker_patch.h @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2017 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_LINKER_LINKER_PATCH_H_ +#define ART_COMPILER_LINKER_LINKER_PATCH_H_ + +#include <iosfwd> +#include <stdint.h> + +#include "base/bit_utils.h" +#include "base/logging.h" +#include "method_reference.h" + +namespace art { + +class DexFile; + +namespace linker { + +class LinkerPatch { + public: + // Note: We explicitly specify the underlying type of the enum because GCC + // would otherwise select a bigger underlying type and then complain that + // 'art::LinkerPatch::patch_type_' is too small to hold all + // values of 'enum class art::LinkerPatch::Type' + // which is ridiculous given we have only a handful of values here. If we + // choose to squeeze the Type into fewer than 8 bits, we'll have to declare + // patch_type_ as an uintN_t and do explicit static_cast<>s. + enum class Type : uint8_t { + kMethodRelative, // NOTE: Actual patching is instruction_set-dependent. + kMethodBssEntry, // NOTE: Actual patching is instruction_set-dependent. + kCall, + kCallRelative, // NOTE: Actual patching is instruction_set-dependent. + kTypeRelative, // NOTE: Actual patching is instruction_set-dependent. + kTypeClassTable, // NOTE: Actual patching is instruction_set-dependent. + kTypeBssEntry, // NOTE: Actual patching is instruction_set-dependent. + kStringRelative, // NOTE: Actual patching is instruction_set-dependent. + kStringInternTable, // NOTE: Actual patching is instruction_set-dependent. + kStringBssEntry, // NOTE: Actual patching is instruction_set-dependent. + kBakerReadBarrierBranch, // NOTE: Actual patching is instruction_set-dependent. + }; + + static LinkerPatch RelativeMethodPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_method_idx) { + LinkerPatch patch(literal_offset, Type::kMethodRelative, target_dex_file); + patch.method_idx_ = target_method_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + + static LinkerPatch MethodBssEntryPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_method_idx) { + LinkerPatch patch(literal_offset, Type::kMethodBssEntry, target_dex_file); + patch.method_idx_ = target_method_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + + static LinkerPatch CodePatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t target_method_idx) { + LinkerPatch patch(literal_offset, Type::kCall, target_dex_file); + patch.method_idx_ = target_method_idx; + return patch; + } + + static LinkerPatch RelativeCodePatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t target_method_idx) { + LinkerPatch patch(literal_offset, Type::kCallRelative, target_dex_file); + patch.method_idx_ = target_method_idx; + return patch; + } + + static LinkerPatch RelativeTypePatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_type_idx) { + LinkerPatch patch(literal_offset, Type::kTypeRelative, target_dex_file); + patch.type_idx_ = target_type_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + + static LinkerPatch TypeClassTablePatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_type_idx) { + LinkerPatch patch(literal_offset, Type::kTypeClassTable, target_dex_file); + patch.type_idx_ = target_type_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + + static LinkerPatch TypeBssEntryPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_type_idx) { + LinkerPatch patch(literal_offset, Type::kTypeBssEntry, target_dex_file); + patch.type_idx_ = target_type_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + + static LinkerPatch RelativeStringPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_string_idx) { + LinkerPatch patch(literal_offset, Type::kStringRelative, target_dex_file); + patch.string_idx_ = target_string_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + + static LinkerPatch StringInternTablePatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_string_idx) { + LinkerPatch patch(literal_offset, Type::kStringInternTable, target_dex_file); + patch.string_idx_ = target_string_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + + static LinkerPatch StringBssEntryPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_string_idx) { + LinkerPatch patch(literal_offset, Type::kStringBssEntry, target_dex_file); + patch.string_idx_ = target_string_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + + static LinkerPatch BakerReadBarrierBranchPatch(size_t literal_offset, + uint32_t custom_value1 = 0u, + uint32_t custom_value2 = 0u) { + LinkerPatch patch(literal_offset, Type::kBakerReadBarrierBranch, nullptr); + patch.baker_custom_value1_ = custom_value1; + patch.baker_custom_value2_ = custom_value2; + return patch; + } + + LinkerPatch(const LinkerPatch& other) = default; + LinkerPatch& operator=(const LinkerPatch& other) = default; + + size_t LiteralOffset() const { + return literal_offset_; + } + + Type GetType() const { + return patch_type_; + } + + bool IsPcRelative() const { + switch (GetType()) { + case Type::kMethodRelative: + case Type::kMethodBssEntry: + case Type::kCallRelative: + case Type::kTypeRelative: + case Type::kTypeClassTable: + case Type::kTypeBssEntry: + case Type::kStringRelative: + case Type::kStringInternTable: + case Type::kStringBssEntry: + case Type::kBakerReadBarrierBranch: + return true; + default: + return false; + } + } + + MethodReference TargetMethod() const { + DCHECK(patch_type_ == Type::kMethodRelative || + patch_type_ == Type::kMethodBssEntry || + patch_type_ == Type::kCall || + patch_type_ == Type::kCallRelative); + return MethodReference(target_dex_file_, method_idx_); + } + + const DexFile* TargetTypeDexFile() const { + DCHECK(patch_type_ == Type::kTypeRelative || + patch_type_ == Type::kTypeClassTable || + patch_type_ == Type::kTypeBssEntry); + return target_dex_file_; + } + + dex::TypeIndex TargetTypeIndex() const { + DCHECK(patch_type_ == Type::kTypeRelative || + patch_type_ == Type::kTypeClassTable || + patch_type_ == Type::kTypeBssEntry); + return dex::TypeIndex(type_idx_); + } + + const DexFile* TargetStringDexFile() const { + DCHECK(patch_type_ == Type::kStringRelative || + patch_type_ == Type::kStringInternTable || + patch_type_ == Type::kStringBssEntry); + return target_dex_file_; + } + + dex::StringIndex TargetStringIndex() const { + DCHECK(patch_type_ == Type::kStringRelative || + patch_type_ == Type::kStringInternTable || + patch_type_ == Type::kStringBssEntry); + return dex::StringIndex(string_idx_); + } + + uint32_t PcInsnOffset() const { + DCHECK(patch_type_ == Type::kMethodRelative || + patch_type_ == Type::kMethodBssEntry || + patch_type_ == Type::kTypeRelative || + patch_type_ == Type::kTypeClassTable || + patch_type_ == Type::kTypeBssEntry || + patch_type_ == Type::kStringRelative || + patch_type_ == Type::kStringInternTable || + patch_type_ == Type::kStringBssEntry); + return pc_insn_offset_; + } + + uint32_t GetBakerCustomValue1() const { + DCHECK(patch_type_ == Type::kBakerReadBarrierBranch); + return baker_custom_value1_; + } + + uint32_t GetBakerCustomValue2() const { + DCHECK(patch_type_ == Type::kBakerReadBarrierBranch); + return baker_custom_value2_; + } + + private: + LinkerPatch(size_t literal_offset, Type patch_type, const DexFile* target_dex_file) + : target_dex_file_(target_dex_file), + literal_offset_(literal_offset), + patch_type_(patch_type) { + cmp1_ = 0u; + cmp2_ = 0u; + // The compiler rejects methods that are too big, so the compiled code + // of a single method really shouln't be anywhere close to 16MiB. + DCHECK(IsUint<24>(literal_offset)); + } + + const DexFile* target_dex_file_; + // TODO: Clean up naming. Some patched locations are literals but others are not. + uint32_t literal_offset_ : 24; // Method code size up to 16MiB. + Type patch_type_ : 8; + union { + uint32_t cmp1_; // Used for relational operators. + uint32_t method_idx_; // Method index for Call/Method patches. + uint32_t type_idx_; // Type index for Type patches. + uint32_t string_idx_; // String index for String patches. + uint32_t baker_custom_value1_; + static_assert(sizeof(method_idx_) == sizeof(cmp1_), "needed by relational operators"); + static_assert(sizeof(type_idx_) == sizeof(cmp1_), "needed by relational operators"); + static_assert(sizeof(string_idx_) == sizeof(cmp1_), "needed by relational operators"); + static_assert(sizeof(baker_custom_value1_) == sizeof(cmp1_), "needed by relational operators"); + }; + union { + // Note: To avoid uninitialized padding on 64-bit systems, we use `size_t` for `cmp2_`. + // This allows a hashing function to treat an array of linker patches as raw memory. + size_t cmp2_; // Used for relational operators. + // Literal offset of the insn loading PC (same as literal_offset if it's the same insn, + // may be different if the PC-relative addressing needs multiple insns). + uint32_t pc_insn_offset_; + uint32_t baker_custom_value2_; + static_assert(sizeof(pc_insn_offset_) <= sizeof(cmp2_), "needed by relational operators"); + static_assert(sizeof(baker_custom_value2_) <= sizeof(cmp2_), "needed by relational operators"); + }; + + friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs); + friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs); +}; +std::ostream& operator<<(std::ostream& os, const LinkerPatch::Type& type); + +inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) { + return lhs.literal_offset_ == rhs.literal_offset_ && + lhs.patch_type_ == rhs.patch_type_ && + lhs.target_dex_file_ == rhs.target_dex_file_ && + lhs.cmp1_ == rhs.cmp1_ && + lhs.cmp2_ == rhs.cmp2_; +} + +inline bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs) { + return (lhs.literal_offset_ != rhs.literal_offset_) ? lhs.literal_offset_ < rhs.literal_offset_ + : (lhs.patch_type_ != rhs.patch_type_) ? lhs.patch_type_ < rhs.patch_type_ + : (lhs.target_dex_file_ != rhs.target_dex_file_) ? lhs.target_dex_file_ < rhs.target_dex_file_ + : (lhs.cmp1_ != rhs.cmp1_) ? lhs.cmp1_ < rhs.cmp1_ + : lhs.cmp2_ < rhs.cmp2_; +} + +} // namespace linker +} // namespace art + +#endif // ART_COMPILER_LINKER_LINKER_PATCH_H_ diff --git a/compiler/compiled_method_test.cc b/compiler/linker/linker_patch_test.cc index f4a72cf2cc..e87dc8de6b 100644 --- a/compiler/compiled_method_test.cc +++ b/compiler/linker/linker_patch_test.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright (C) 2017 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. @@ -16,37 +16,12 @@ #include <gtest/gtest.h> -#include "compiled_method.h" +#include "linker_patch.h" namespace art { +namespace linker { -TEST(CompiledMethod, SrcMapElemOperators) { - SrcMapElem elems[] = { - { 1u, -1 }, - { 1u, 0 }, - { 1u, 1 }, - { 2u, -1 }, - { 2u, 0 }, // Index 4. - { 2u, 1 }, - { 2u, 0u }, // Index 6: Arbitrarily add identical SrcMapElem with index 4. - }; - - for (size_t i = 0; i != arraysize(elems); ++i) { - for (size_t j = 0; j != arraysize(elems); ++j) { - bool expected = (i != 6u ? i : 4u) == (j != 6u ? j : 4u); - EXPECT_EQ(expected, elems[i] == elems[j]) << i << " " << j; - } - } - - for (size_t i = 0; i != arraysize(elems); ++i) { - for (size_t j = 0; j != arraysize(elems); ++j) { - bool expected = (i != 6u ? i : 4u) < (j != 6u ? j : 4u); - EXPECT_EQ(expected, elems[i] < elems[j]) << i << " " << j; - } - } -} - -TEST(CompiledMethod, LinkerPatchOperators) { +TEST(LinkerPatch, LinkerPatchOperators) { const DexFile* dex_file1 = reinterpret_cast<const DexFile*>(1); const DexFile* dex_file2 = reinterpret_cast<const DexFile*>(2); LinkerPatch patches[] = { @@ -191,4 +166,5 @@ TEST(CompiledMethod, LinkerPatchOperators) { } } +} // namespace linker } // namespace art diff --git a/compiler/linker/mips/relative_patcher_mips.cc b/compiler/linker/mips/relative_patcher_mips.cc index 408ac22976..69e0846cb7 100644 --- a/compiler/linker/mips/relative_patcher_mips.cc +++ b/compiler/linker/mips/relative_patcher_mips.cc @@ -18,6 +18,7 @@ #include "compiled_method.h" #include "debug/method_debug_info.h" +#include "linker/linker_patch.h" namespace art { namespace linker { diff --git a/compiler/linker/mips64/relative_patcher_mips64.cc b/compiler/linker/mips64/relative_patcher_mips64.cc index 2bcd98a2b0..aae5746278 100644 --- a/compiler/linker/mips64/relative_patcher_mips64.cc +++ b/compiler/linker/mips64/relative_patcher_mips64.cc @@ -18,6 +18,7 @@ #include "compiled_method.h" #include "debug/method_debug_info.h" +#include "linker/linker_patch.h" namespace art { namespace linker { diff --git a/compiler/linker/relative_patcher.h b/compiler/linker/relative_patcher.h index e079946e71..548e12896a 100644 --- a/compiler/linker/relative_patcher.h +++ b/compiler/linker/relative_patcher.h @@ -28,7 +28,6 @@ namespace art { class CompiledMethod; -class LinkerPatch; namespace debug { struct MethodDebugInfo; @@ -36,6 +35,7 @@ struct MethodDebugInfo; namespace linker { +class LinkerPatch; class OutputStream; /** diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h index f7dbc1ef1c..6297dd0481 100644 --- a/compiler/linker/relative_patcher_test.h +++ b/compiler/linker/relative_patcher_test.h @@ -21,7 +21,7 @@ #include "arch/instruction_set_features.h" #include "base/array_ref.h" #include "base/macros.h" -#include "compiled_method.h" +#include "compiled_method-inl.h" #include "dex/verification_results.h" #include "driver/compiler_driver.h" #include "driver/compiler_options.h" diff --git a/compiler/linker/x86/relative_patcher_x86.cc b/compiler/linker/x86/relative_patcher_x86.cc index 6967b0b6c2..cdd2cef13a 100644 --- a/compiler/linker/x86/relative_patcher_x86.cc +++ b/compiler/linker/x86/relative_patcher_x86.cc @@ -17,6 +17,7 @@ #include "linker/x86/relative_patcher_x86.h" #include "compiled_method.h" +#include "linker/linker_patch.h" namespace art { namespace linker { diff --git a/compiler/linker/x86_64/relative_patcher_x86_64.cc b/compiler/linker/x86_64/relative_patcher_x86_64.cc index 156ece9909..9633564999 100644 --- a/compiler/linker/x86_64/relative_patcher_x86_64.cc +++ b/compiler/linker/x86_64/relative_patcher_x86_64.cc @@ -17,6 +17,7 @@ #include "linker/x86_64/relative_patcher_x86_64.h" #include "compiled_method.h" +#include "linker/linker_patch.h" namespace art { namespace linker { diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc index a170734ff2..a7f7bce07a 100644 --- a/compiler/optimizing/bounds_check_elimination.cc +++ b/compiler/optimizing/bounds_check_elimination.cc @@ -927,7 +927,7 @@ class BCEVisitor : public HGraphVisitor { void VisitPhi(HPhi* phi) OVERRIDE { if (phi->IsLoopHeaderPhi() - && (phi->GetType() == Primitive::kPrimInt) + && (phi->GetType() == DataType::Type::kInt32) && HasSameInputAtBackEdges(phi)) { HInstruction* instruction = phi->InputAt(1); HInstruction *left; @@ -1261,8 +1261,8 @@ class BCEVisitor : public HGraphVisitor { DCHECK_GE(min_c, 0); } else { HInstruction* lower = new (GetGraph()->GetArena()) - HAdd(Primitive::kPrimInt, base, GetGraph()->GetIntConstant(min_c)); - upper = new (GetGraph()->GetArena()) HAdd(Primitive::kPrimInt, base, upper); + HAdd(DataType::Type::kInt32, base, GetGraph()->GetIntConstant(min_c)); + upper = new (GetGraph()->GetArena()) HAdd(DataType::Type::kInt32, base, upper); block->InsertInstructionBefore(lower, bounds_check); block->InsertInstructionBefore(upper, bounds_check); InsertDeoptInBlock(bounds_check, new (GetGraph()->GetArena()) HAbove(lower, upper)); @@ -1801,7 +1801,7 @@ class BCEVisitor : public HGraphVisitor { // Scan all instructions in a new deoptimization block. for (HInstructionIterator it(true_block->GetInstructions()); !it.Done(); it.Advance()) { HInstruction* instruction = it.Current(); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); HPhi* phi = nullptr; // Scan all uses of an instruction and replace each later use with a phi node. const HUseList<HInstruction*>& uses = instruction->GetUses(); @@ -1844,20 +1844,20 @@ class BCEVisitor : public HGraphVisitor { */ HPhi* NewPhi(HBasicBlock* new_preheader, HInstruction* instruction, - Primitive::Type type) { + DataType::Type type) { HGraph* graph = GetGraph(); HInstruction* zero; switch (type) { - case Primitive::kPrimNot: zero = graph->GetNullConstant(); break; - case Primitive::kPrimFloat: zero = graph->GetFloatConstant(0); break; - case Primitive::kPrimDouble: zero = graph->GetDoubleConstant(0); break; + case DataType::Type::kReference: zero = graph->GetNullConstant(); break; + case DataType::Type::kFloat32: zero = graph->GetFloatConstant(0); break; + case DataType::Type::kFloat64: zero = graph->GetDoubleConstant(0); break; default: zero = graph->GetConstant(type, 0); break; } HPhi* phi = new (graph->GetArena()) HPhi(graph->GetArena(), kNoRegNumber, /*number_of_inputs*/ 2, HPhi::ToPhiType(type)); phi->SetRawInputAt(0, instruction); phi->SetRawInputAt(1, zero); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { phi->SetReferenceTypeInfo(instruction->GetReferenceTypeInfo()); } new_preheader->AddPhi(phi); diff --git a/compiler/optimizing/bounds_check_elimination_test.cc b/compiler/optimizing/bounds_check_elimination_test.cc index 2aaf05833c..851838c4b8 100644 --- a/compiler/optimizing/bounds_check_elimination_test.cc +++ b/compiler/optimizing/bounds_check_elimination_test.cc @@ -70,10 +70,10 @@ TEST_F(BoundsCheckEliminationTest, NarrowingRangeArrayBoundsElimination) { HBasicBlock* entry = new (&allocator_) HBasicBlock(graph_); graph_->AddBlock(entry); graph_->SetEntryBlock(entry); - HInstruction* parameter1 = new (&allocator_) - HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); // array - HInstruction* parameter2 = new (&allocator_) - HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); // i + HInstruction* parameter1 = new (&allocator_) HParameterValue( + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); // array + HInstruction* parameter2 = new (&allocator_) HParameterValue( + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); // i entry->AddInstruction(parameter1); entry->AddInstruction(parameter2); @@ -95,7 +95,7 @@ TEST_F(BoundsCheckEliminationTest, NarrowingRangeArrayBoundsElimination) { HBoundsCheck* bounds_check2 = new (&allocator_) HBoundsCheck(parameter2, array_length, 0); HArraySet* array_set = new (&allocator_) HArraySet( - null_check, bounds_check2, constant_1, Primitive::kPrimInt, 0); + null_check, bounds_check2, constant_1, DataType::Type::kInt32, 0); block2->AddInstruction(null_check); block2->AddInstruction(array_length); block2->AddInstruction(bounds_check2); @@ -119,7 +119,7 @@ TEST_F(BoundsCheckEliminationTest, NarrowingRangeArrayBoundsElimination) { HBoundsCheck* bounds_check4 = new (&allocator_) HBoundsCheck(parameter2, array_length, 0); array_set = new (&allocator_) HArraySet( - null_check, bounds_check4, constant_1, Primitive::kPrimInt, 0); + null_check, bounds_check4, constant_1, DataType::Type::kInt32, 0); block4->AddInstruction(null_check); block4->AddInstruction(array_length); block4->AddInstruction(bounds_check4); @@ -132,7 +132,7 @@ TEST_F(BoundsCheckEliminationTest, NarrowingRangeArrayBoundsElimination) { HBoundsCheck* bounds_check5 = new (&allocator_) HBoundsCheck(parameter2, array_length, 0); array_set = new (&allocator_) HArraySet( - null_check, bounds_check5, constant_1, Primitive::kPrimInt, 0); + null_check, bounds_check5, constant_1, DataType::Type::kInt32, 0); block5->AddInstruction(null_check); block5->AddInstruction(array_length); block5->AddInstruction(bounds_check5); @@ -167,10 +167,10 @@ TEST_F(BoundsCheckEliminationTest, OverflowArrayBoundsElimination) { HBasicBlock* entry = new (&allocator_) HBasicBlock(graph_); graph_->AddBlock(entry); graph_->SetEntryBlock(entry); - HInstruction* parameter1 = new (&allocator_) - HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); // array - HInstruction* parameter2 = new (&allocator_) - HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); // i + HInstruction* parameter1 = new (&allocator_) HParameterValue( + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); // array + HInstruction* parameter2 = new (&allocator_) HParameterValue( + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); // i entry->AddInstruction(parameter1); entry->AddInstruction(parameter2); @@ -188,7 +188,7 @@ TEST_F(BoundsCheckEliminationTest, OverflowArrayBoundsElimination) { HBasicBlock* block2 = new (&allocator_) HBasicBlock(graph_); graph_->AddBlock(block2); - HInstruction* add = new (&allocator_) HAdd(Primitive::kPrimInt, parameter2, constant_max_int); + HInstruction* add = new (&allocator_) HAdd(DataType::Type::kInt32, parameter2, constant_max_int); HNullCheck* null_check = new (&allocator_) HNullCheck(parameter1, 0); HArrayLength* array_length = new (&allocator_) HArrayLength(null_check, 0); HInstruction* cmp2 = new (&allocator_) HGreaterThanOrEqual(add, array_length); @@ -204,7 +204,7 @@ TEST_F(BoundsCheckEliminationTest, OverflowArrayBoundsElimination) { HBoundsCheck* bounds_check = new (&allocator_) HBoundsCheck(add, array_length, 0); HArraySet* array_set = new (&allocator_) HArraySet( - null_check, bounds_check, constant_1, Primitive::kPrimInt, 0); + null_check, bounds_check, constant_1, DataType::Type::kInt32, 0); block3->AddInstruction(bounds_check); block3->AddInstruction(array_set); @@ -231,10 +231,10 @@ TEST_F(BoundsCheckEliminationTest, UnderflowArrayBoundsElimination) { HBasicBlock* entry = new (&allocator_) HBasicBlock(graph_); graph_->AddBlock(entry); graph_->SetEntryBlock(entry); - HInstruction* parameter1 = new (&allocator_) - HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); // array - HInstruction* parameter2 = new (&allocator_) - HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); // i + HInstruction* parameter1 = new (&allocator_) HParameterValue( + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); // array + HInstruction* parameter2 = new (&allocator_) HParameterValue( + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); // i entry->AddInstruction(parameter1); entry->AddInstruction(parameter2); @@ -256,8 +256,8 @@ TEST_F(BoundsCheckEliminationTest, UnderflowArrayBoundsElimination) { HBasicBlock* block2 = new (&allocator_) HBasicBlock(graph_); graph_->AddBlock(block2); - HInstruction* sub1 = new (&allocator_) HSub(Primitive::kPrimInt, parameter2, constant_max_int); - HInstruction* sub2 = new (&allocator_) HSub(Primitive::kPrimInt, sub1, constant_max_int); + HInstruction* sub1 = new (&allocator_) HSub(DataType::Type::kInt32, parameter2, constant_max_int); + HInstruction* sub2 = new (&allocator_) HSub(DataType::Type::kInt32, sub1, constant_max_int); HInstruction* cmp2 = new (&allocator_) HLessThanOrEqual(sub2, constant_0); if_inst = new (&allocator_) HIf(cmp2); block2->AddInstruction(sub1); @@ -270,7 +270,7 @@ TEST_F(BoundsCheckEliminationTest, UnderflowArrayBoundsElimination) { HBoundsCheck* bounds_check = new (&allocator_) HBoundsCheck(sub2, array_length, 0); HArraySet* array_set = new (&allocator_) HArraySet( - null_check, bounds_check, constant_1, Primitive::kPrimInt, 0); + null_check, bounds_check, constant_1, DataType::Type::kInt32, 0); block3->AddInstruction(bounds_check); block3->AddInstruction(array_set); @@ -296,7 +296,7 @@ TEST_F(BoundsCheckEliminationTest, ConstantArrayBoundsElimination) { graph_->AddBlock(entry); graph_->SetEntryBlock(entry); HInstruction* parameter = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); entry->AddInstruction(parameter); HInstruction* constant_5 = graph_->GetIntConstant(5); @@ -313,7 +313,7 @@ TEST_F(BoundsCheckEliminationTest, ConstantArrayBoundsElimination) { HBoundsCheck* bounds_check6 = new (&allocator_) HBoundsCheck(constant_6, array_length, 0); HInstruction* array_set = new (&allocator_) HArraySet( - null_check, bounds_check6, constant_1, Primitive::kPrimInt, 0); + null_check, bounds_check6, constant_1, DataType::Type::kInt32, 0); block->AddInstruction(null_check); block->AddInstruction(array_length); block->AddInstruction(bounds_check6); @@ -324,7 +324,7 @@ TEST_F(BoundsCheckEliminationTest, ConstantArrayBoundsElimination) { HBoundsCheck* bounds_check5 = new (&allocator_) HBoundsCheck(constant_5, array_length, 0); array_set = new (&allocator_) HArraySet( - null_check, bounds_check5, constant_1, Primitive::kPrimInt, 0); + null_check, bounds_check5, constant_1, DataType::Type::kInt32, 0); block->AddInstruction(null_check); block->AddInstruction(array_length); block->AddInstruction(bounds_check5); @@ -335,7 +335,7 @@ TEST_F(BoundsCheckEliminationTest, ConstantArrayBoundsElimination) { HBoundsCheck* bounds_check4 = new (&allocator_) HBoundsCheck(constant_4, array_length, 0); array_set = new (&allocator_) HArraySet( - null_check, bounds_check4, constant_1, Primitive::kPrimInt, 0); + null_check, bounds_check4, constant_1, DataType::Type::kInt32, 0); block->AddInstruction(null_check); block->AddInstruction(array_length); block->AddInstruction(bounds_check4); @@ -365,7 +365,7 @@ static HInstruction* BuildSSAGraph1(HGraph* graph, graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter = new (allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); entry->AddInstruction(parameter); HInstruction* constant_initial = graph->GetIntConstant(initial); @@ -389,7 +389,7 @@ static HInstruction* BuildSSAGraph1(HGraph* graph, loop_header->AddSuccessor(loop_body); // false successor loop_body->AddSuccessor(loop_header); - HPhi* phi = new (allocator) HPhi(allocator, 0, 0, Primitive::kPrimInt); + HPhi* phi = new (allocator) HPhi(allocator, 0, 0, DataType::Type::kInt32); HInstruction* null_check = new (allocator) HNullCheck(parameter, 0); HInstruction* array_length = new (allocator) HArrayLength(null_check, 0); HInstruction* cmp = nullptr; @@ -411,9 +411,9 @@ static HInstruction* BuildSSAGraph1(HGraph* graph, array_length = new (allocator) HArrayLength(null_check, 0); HInstruction* bounds_check = new (allocator) HBoundsCheck(phi, array_length, 0); HInstruction* array_set = new (allocator) HArraySet( - null_check, bounds_check, constant_10, Primitive::kPrimInt, 0); + null_check, bounds_check, constant_10, DataType::Type::kInt32, 0); - HInstruction* add = new (allocator) HAdd(Primitive::kPrimInt, phi, constant_increment); + HInstruction* add = new (allocator) HAdd(DataType::Type::kInt32, phi, constant_increment); loop_body->AddInstruction(null_check); loop_body->AddInstruction(array_length); loop_body->AddInstruction(bounds_check); @@ -480,7 +480,7 @@ static HInstruction* BuildSSAGraph2(HGraph *graph, graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter = new (allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); entry->AddInstruction(parameter); HInstruction* constant_initial = graph->GetIntConstant(initial); @@ -509,7 +509,7 @@ static HInstruction* BuildSSAGraph2(HGraph *graph, loop_header->AddSuccessor(loop_body); // false successor loop_body->AddSuccessor(loop_header); - HPhi* phi = new (allocator) HPhi(allocator, 0, 0, Primitive::kPrimInt); + HPhi* phi = new (allocator) HPhi(allocator, 0, 0, DataType::Type::kInt32); HInstruction* cmp = nullptr; if (cond == kCondLE) { cmp = new (allocator) HLessThanOrEqual(phi, constant_initial); @@ -523,13 +523,13 @@ static HInstruction* BuildSSAGraph2(HGraph *graph, loop_header->AddInstruction(if_inst); phi->AddInput(array_length); - HInstruction* add = new (allocator) HAdd(Primitive::kPrimInt, phi, constant_minus_1); + HInstruction* add = new (allocator) HAdd(DataType::Type::kInt32, phi, constant_minus_1); null_check = new (allocator) HNullCheck(parameter, 0); array_length = new (allocator) HArrayLength(null_check, 0); HInstruction* bounds_check = new (allocator) HBoundsCheck(add, array_length, 0); HInstruction* array_set = new (allocator) HArraySet( - null_check, bounds_check, constant_10, Primitive::kPrimInt, 0); - HInstruction* add_phi = new (allocator) HAdd(Primitive::kPrimInt, phi, constant_increment); + null_check, bounds_check, constant_10, DataType::Type::kInt32, 0); + HInstruction* add_phi = new (allocator) HAdd(DataType::Type::kInt32, phi, constant_increment); loop_body->AddInstruction(add); loop_body->AddInstruction(null_check); loop_body->AddInstruction(array_length); @@ -617,7 +617,7 @@ static HInstruction* BuildSSAGraph3(HGraph* graph, loop_header->AddSuccessor(loop_body); // false successor loop_body->AddSuccessor(loop_header); - HPhi* phi = new (allocator) HPhi(allocator, 0, 0, Primitive::kPrimInt); + HPhi* phi = new (allocator) HPhi(allocator, 0, 0, DataType::Type::kInt32); HInstruction* cmp = nullptr; if (cond == kCondGE) { cmp = new (allocator) HGreaterThanOrEqual(phi, constant_10); @@ -635,8 +635,8 @@ static HInstruction* BuildSSAGraph3(HGraph* graph, HArrayLength* array_length = new (allocator) HArrayLength(null_check, 0); HInstruction* bounds_check = new (allocator) HBoundsCheck(phi, array_length, 0); HInstruction* array_set = new (allocator) HArraySet( - null_check, bounds_check, constant_10, Primitive::kPrimInt, 0); - HInstruction* add = new (allocator) HAdd(Primitive::kPrimInt, phi, constant_increment); + null_check, bounds_check, constant_10, DataType::Type::kInt32, 0); + HInstruction* add = new (allocator) HAdd(DataType::Type::kInt32, phi, constant_increment); loop_body->AddInstruction(null_check); loop_body->AddInstruction(array_length); loop_body->AddInstruction(bounds_check); @@ -691,7 +691,7 @@ static HInstruction* BuildSSAGraph4(HGraph* graph, graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter = new (allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); entry->AddInstruction(parameter); HInstruction* constant_initial = graph->GetIntConstant(initial); @@ -716,7 +716,7 @@ static HInstruction* BuildSSAGraph4(HGraph* graph, loop_header->AddSuccessor(loop_body); // false successor loop_body->AddSuccessor(loop_header); - HPhi* phi = new (allocator) HPhi(allocator, 0, 0, Primitive::kPrimInt); + HPhi* phi = new (allocator) HPhi(allocator, 0, 0, DataType::Type::kInt32); HInstruction* null_check = new (allocator) HNullCheck(parameter, 0); HInstruction* array_length = new (allocator) HArrayLength(null_check, 0); HInstruction* cmp = nullptr; @@ -735,13 +735,13 @@ static HInstruction* BuildSSAGraph4(HGraph* graph, null_check = new (allocator) HNullCheck(parameter, 0); array_length = new (allocator) HArrayLength(null_check, 0); - HInstruction* sub = new (allocator) HSub(Primitive::kPrimInt, array_length, phi); + HInstruction* sub = new (allocator) HSub(DataType::Type::kInt32, array_length, phi); HInstruction* add_minus_1 = new (allocator) - HAdd(Primitive::kPrimInt, sub, constant_minus_1); + HAdd(DataType::Type::kInt32, sub, constant_minus_1); HInstruction* bounds_check = new (allocator) HBoundsCheck(add_minus_1, array_length, 0); HInstruction* array_set = new (allocator) HArraySet( - null_check, bounds_check, constant_10, Primitive::kPrimInt, 0); - HInstruction* add = new (allocator) HAdd(Primitive::kPrimInt, phi, constant_1); + null_check, bounds_check, constant_10, DataType::Type::kInt32, 0); + HInstruction* add = new (allocator) HAdd(DataType::Type::kInt32, phi, constant_1); loop_body->AddInstruction(null_check); loop_body->AddInstruction(array_length); loop_body->AddInstruction(sub); @@ -794,7 +794,7 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { graph_->AddBlock(entry); graph_->SetEntryBlock(entry); HInstruction* parameter = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); entry->AddInstruction(parameter); HInstruction* constant_0 = graph_->GetIntConstant(0); @@ -812,10 +812,10 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { HBasicBlock* outer_header = new (&allocator_) HBasicBlock(graph_); graph_->AddBlock(outer_header); - HPhi* phi_i = new (&allocator_) HPhi(&allocator_, 0, 0, Primitive::kPrimInt); + HPhi* phi_i = new (&allocator_) HPhi(&allocator_, 0, 0, DataType::Type::kInt32); HNullCheck* null_check = new (&allocator_) HNullCheck(parameter, 0); HArrayLength* array_length = new (&allocator_) HArrayLength(null_check, 0); - HAdd* add = new (&allocator_) HAdd(Primitive::kPrimInt, array_length, constant_minus_1); + HAdd* add = new (&allocator_) HAdd(DataType::Type::kInt32, array_length, constant_minus_1); HInstruction* cmp = new (&allocator_) HGreaterThanOrEqual(phi_i, add); HIf* if_inst = new (&allocator_) HIf(cmp); outer_header->AddPhi(phi_i); @@ -828,11 +828,11 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { HBasicBlock* inner_header = new (&allocator_) HBasicBlock(graph_); graph_->AddBlock(inner_header); - HPhi* phi_j = new (&allocator_) HPhi(&allocator_, 0, 0, Primitive::kPrimInt); + HPhi* phi_j = new (&allocator_) HPhi(&allocator_, 0, 0, DataType::Type::kInt32); null_check = new (&allocator_) HNullCheck(parameter, 0); array_length = new (&allocator_) HArrayLength(null_check, 0); - HSub* sub = new (&allocator_) HSub(Primitive::kPrimInt, array_length, phi_i); - add = new (&allocator_) HAdd(Primitive::kPrimInt, sub, constant_minus_1); + HSub* sub = new (&allocator_) HSub(DataType::Type::kInt32, array_length, phi_i); + add = new (&allocator_) HAdd(DataType::Type::kInt32, sub, constant_minus_1); cmp = new (&allocator_) HGreaterThanOrEqual(phi_j, add); if_inst = new (&allocator_) HIf(cmp); inner_header->AddPhi(phi_j); @@ -850,17 +850,17 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { array_length = new (&allocator_) HArrayLength(null_check, 0); HBoundsCheck* bounds_check1 = new (&allocator_) HBoundsCheck(phi_j, array_length, 0); HArrayGet* array_get_j = new (&allocator_) - HArrayGet(null_check, bounds_check1, Primitive::kPrimInt, 0); + HArrayGet(null_check, bounds_check1, DataType::Type::kInt32, 0); inner_body_compare->AddInstruction(null_check); inner_body_compare->AddInstruction(array_length); inner_body_compare->AddInstruction(bounds_check1); inner_body_compare->AddInstruction(array_get_j); - HInstruction* j_plus_1 = new (&allocator_) HAdd(Primitive::kPrimInt, phi_j, constant_1); + HInstruction* j_plus_1 = new (&allocator_) HAdd(DataType::Type::kInt32, phi_j, constant_1); null_check = new (&allocator_) HNullCheck(parameter, 0); array_length = new (&allocator_) HArrayLength(null_check, 0); HBoundsCheck* bounds_check2 = new (&allocator_) HBoundsCheck(j_plus_1, array_length, 0); HArrayGet* array_get_j_plus_1 = new (&allocator_) - HArrayGet(null_check, bounds_check2, Primitive::kPrimInt, 0); + HArrayGet(null_check, bounds_check2, DataType::Type::kInt32, 0); cmp = new (&allocator_) HGreaterThanOrEqual(array_get_j, array_get_j_plus_1); if_inst = new (&allocator_) HIf(cmp); inner_body_compare->AddInstruction(j_plus_1); @@ -873,13 +873,13 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { HBasicBlock* inner_body_swap = new (&allocator_) HBasicBlock(graph_); graph_->AddBlock(inner_body_swap); - j_plus_1 = new (&allocator_) HAdd(Primitive::kPrimInt, phi_j, constant_1); + j_plus_1 = new (&allocator_) HAdd(DataType::Type::kInt32, phi_j, constant_1); // temp = array[j+1] null_check = new (&allocator_) HNullCheck(parameter, 0); array_length = new (&allocator_) HArrayLength(null_check, 0); HInstruction* bounds_check3 = new (&allocator_) HBoundsCheck(j_plus_1, array_length, 0); array_get_j_plus_1 = new (&allocator_) - HArrayGet(null_check, bounds_check3, Primitive::kPrimInt, 0); + HArrayGet(null_check, bounds_check3, DataType::Type::kInt32, 0); inner_body_swap->AddInstruction(j_plus_1); inner_body_swap->AddInstruction(null_check); inner_body_swap->AddInstruction(array_length); @@ -890,7 +890,7 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { array_length = new (&allocator_) HArrayLength(null_check, 0); HInstruction* bounds_check4 = new (&allocator_) HBoundsCheck(phi_j, array_length, 0); array_get_j = new (&allocator_) - HArrayGet(null_check, bounds_check4, Primitive::kPrimInt, 0); + HArrayGet(null_check, bounds_check4, DataType::Type::kInt32, 0); inner_body_swap->AddInstruction(null_check); inner_body_swap->AddInstruction(array_length); inner_body_swap->AddInstruction(bounds_check4); @@ -899,7 +899,7 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { array_length = new (&allocator_) HArrayLength(null_check, 0); HInstruction* bounds_check5 = new (&allocator_) HBoundsCheck(j_plus_1, array_length, 0); HArraySet* array_set_j_plus_1 = new (&allocator_) - HArraySet(null_check, bounds_check5, array_get_j, Primitive::kPrimInt, 0); + HArraySet(null_check, bounds_check5, array_get_j, DataType::Type::kInt32, 0); inner_body_swap->AddInstruction(null_check); inner_body_swap->AddInstruction(array_length); inner_body_swap->AddInstruction(bounds_check5); @@ -909,7 +909,7 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { array_length = new (&allocator_) HArrayLength(null_check, 0); HInstruction* bounds_check6 = new (&allocator_) HBoundsCheck(phi_j, array_length, 0); HArraySet* array_set_j = new (&allocator_) - HArraySet(null_check, bounds_check6, array_get_j_plus_1, Primitive::kPrimInt, 0); + HArraySet(null_check, bounds_check6, array_get_j_plus_1, DataType::Type::kInt32, 0); inner_body_swap->AddInstruction(null_check); inner_body_swap->AddInstruction(array_length); inner_body_swap->AddInstruction(bounds_check6); @@ -918,14 +918,14 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { HBasicBlock* inner_body_add = new (&allocator_) HBasicBlock(graph_); graph_->AddBlock(inner_body_add); - add = new (&allocator_) HAdd(Primitive::kPrimInt, phi_j, constant_1); + add = new (&allocator_) HAdd(DataType::Type::kInt32, phi_j, constant_1); inner_body_add->AddInstruction(add); inner_body_add->AddInstruction(new (&allocator_) HGoto()); phi_j->AddInput(add); HBasicBlock* outer_body_add = new (&allocator_) HBasicBlock(graph_); graph_->AddBlock(outer_body_add); - add = new (&allocator_) HAdd(Primitive::kPrimInt, phi_i, constant_1); + add = new (&allocator_) HAdd(DataType::Type::kInt32, phi_i, constant_1); outer_body_add->AddInstruction(add); outer_body_add->AddInstruction(new (&allocator_) HGoto()); phi_i->AddInput(add); @@ -965,7 +965,7 @@ TEST_F(BoundsCheckEliminationTest, ModArrayBoundsElimination) { graph_->AddBlock(entry); graph_->SetEntryBlock(entry); HInstruction* param_i = new (&allocator_) - HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); + HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); entry->AddInstruction(param_i); HInstruction* constant_0 = graph_->GetIntConstant(0); @@ -994,7 +994,7 @@ TEST_F(BoundsCheckEliminationTest, ModArrayBoundsElimination) { loop_header->AddSuccessor(loop_body); // false successor loop_body->AddSuccessor(loop_header); - HPhi* phi = new (&allocator_) HPhi(&allocator_, 0, 0, Primitive::kPrimInt); + HPhi* phi = new (&allocator_) HPhi(&allocator_, 0, 0, DataType::Type::kInt32); HInstruction* cmp = new (&allocator_) HGreaterThanOrEqual(phi, constant_200); HInstruction* if_inst = new (&allocator_) HIf(cmp); loop_header->AddPhi(phi); @@ -1005,38 +1005,38 @@ TEST_F(BoundsCheckEliminationTest, ModArrayBoundsElimination) { ////////////////////////////////////////////////////////////////////////////////// // LOOP BODY: // array[i % 10] = 10; - HRem* i_mod_10 = new (&allocator_) HRem(Primitive::kPrimInt, phi, constant_10, 0); + HRem* i_mod_10 = new (&allocator_) HRem(DataType::Type::kInt32, phi, constant_10, 0); HBoundsCheck* bounds_check_i_mod_10 = new (&allocator_) HBoundsCheck(i_mod_10, constant_10, 0); HInstruction* array_set = new (&allocator_) HArraySet( - new_array, bounds_check_i_mod_10, constant_10, Primitive::kPrimInt, 0); + new_array, bounds_check_i_mod_10, constant_10, DataType::Type::kInt32, 0); loop_body->AddInstruction(i_mod_10); loop_body->AddInstruction(bounds_check_i_mod_10); loop_body->AddInstruction(array_set); // array[i % 1] = 10; - HRem* i_mod_1 = new (&allocator_) HRem(Primitive::kPrimInt, phi, constant_1, 0); + HRem* i_mod_1 = new (&allocator_) HRem(DataType::Type::kInt32, phi, constant_1, 0); HBoundsCheck* bounds_check_i_mod_1 = new (&allocator_) HBoundsCheck(i_mod_1, constant_10, 0); array_set = new (&allocator_) HArraySet( - new_array, bounds_check_i_mod_1, constant_10, Primitive::kPrimInt, 0); + new_array, bounds_check_i_mod_1, constant_10, DataType::Type::kInt32, 0); loop_body->AddInstruction(i_mod_1); loop_body->AddInstruction(bounds_check_i_mod_1); loop_body->AddInstruction(array_set); // array[i % 200] = 10; - HRem* i_mod_200 = new (&allocator_) HRem(Primitive::kPrimInt, phi, constant_1, 0); + HRem* i_mod_200 = new (&allocator_) HRem(DataType::Type::kInt32, phi, constant_1, 0); HBoundsCheck* bounds_check_i_mod_200 = new (&allocator_) HBoundsCheck(i_mod_200, constant_10, 0); array_set = new (&allocator_) HArraySet( - new_array, bounds_check_i_mod_200, constant_10, Primitive::kPrimInt, 0); + new_array, bounds_check_i_mod_200, constant_10, DataType::Type::kInt32, 0); loop_body->AddInstruction(i_mod_200); loop_body->AddInstruction(bounds_check_i_mod_200); loop_body->AddInstruction(array_set); // array[i % -10] = 10; - HRem* i_mod_minus_10 = new (&allocator_) HRem(Primitive::kPrimInt, phi, constant_minus_10, 0); + HRem* i_mod_minus_10 = new (&allocator_) HRem(DataType::Type::kInt32, phi, constant_minus_10, 0); HBoundsCheck* bounds_check_i_mod_minus_10 = new (&allocator_) HBoundsCheck( i_mod_minus_10, constant_10, 0); array_set = new (&allocator_) HArraySet( - new_array, bounds_check_i_mod_minus_10, constant_10, Primitive::kPrimInt, 0); + new_array, bounds_check_i_mod_minus_10, constant_10, DataType::Type::kInt32, 0); loop_body->AddInstruction(i_mod_minus_10); loop_body->AddInstruction(bounds_check_i_mod_minus_10); loop_body->AddInstruction(array_set); @@ -1044,11 +1044,11 @@ TEST_F(BoundsCheckEliminationTest, ModArrayBoundsElimination) { // array[i%array.length] = 10; HNullCheck* null_check = new (&allocator_) HNullCheck(new_array, 0); HArrayLength* array_length = new (&allocator_) HArrayLength(null_check, 0); - HRem* i_mod_array_length = new (&allocator_) HRem(Primitive::kPrimInt, phi, array_length, 0); + HRem* i_mod_array_length = new (&allocator_) HRem(DataType::Type::kInt32, phi, array_length, 0); HBoundsCheck* bounds_check_i_mod_array_len = new (&allocator_) HBoundsCheck( i_mod_array_length, array_length, 0); array_set = new (&allocator_) HArraySet( - null_check, bounds_check_i_mod_array_len, constant_10, Primitive::kPrimInt, 0); + null_check, bounds_check_i_mod_array_len, constant_10, DataType::Type::kInt32, 0); loop_body->AddInstruction(null_check); loop_body->AddInstruction(array_length); loop_body->AddInstruction(i_mod_array_length); @@ -1056,11 +1056,11 @@ TEST_F(BoundsCheckEliminationTest, ModArrayBoundsElimination) { loop_body->AddInstruction(array_set); // array[param_i % 10] = 10; - HRem* param_i_mod_10 = new (&allocator_) HRem(Primitive::kPrimInt, param_i, constant_10, 0); + HRem* param_i_mod_10 = new (&allocator_) HRem(DataType::Type::kInt32, param_i, constant_10, 0); HBoundsCheck* bounds_check_param_i_mod_10 = new (&allocator_) HBoundsCheck( param_i_mod_10, constant_10, 0); array_set = new (&allocator_) HArraySet( - new_array, bounds_check_param_i_mod_10, constant_10, Primitive::kPrimInt, 0); + new_array, bounds_check_param_i_mod_10, constant_10, DataType::Type::kInt32, 0); loop_body->AddInstruction(param_i_mod_10); loop_body->AddInstruction(bounds_check_param_i_mod_10); loop_body->AddInstruction(array_set); @@ -1069,11 +1069,11 @@ TEST_F(BoundsCheckEliminationTest, ModArrayBoundsElimination) { null_check = new (&allocator_) HNullCheck(new_array, 0); array_length = new (&allocator_) HArrayLength(null_check, 0); HRem* param_i_mod_array_length = new (&allocator_) HRem( - Primitive::kPrimInt, param_i, array_length, 0); + DataType::Type::kInt32, param_i, array_length, 0); HBoundsCheck* bounds_check_param_i_mod_array_len = new (&allocator_) HBoundsCheck( param_i_mod_array_length, array_length, 0); array_set = new (&allocator_) HArraySet( - null_check, bounds_check_param_i_mod_array_len, constant_10, Primitive::kPrimInt, 0); + null_check, bounds_check_param_i_mod_array_len, constant_10, DataType::Type::kInt32, 0); loop_body->AddInstruction(null_check); loop_body->AddInstruction(array_length); loop_body->AddInstruction(param_i_mod_array_length); @@ -1081,7 +1081,7 @@ TEST_F(BoundsCheckEliminationTest, ModArrayBoundsElimination) { loop_body->AddInstruction(array_set); // i++; - HInstruction* add = new (&allocator_) HAdd(Primitive::kPrimInt, phi, constant_1); + HInstruction* add = new (&allocator_) HAdd(DataType::Type::kInt32, phi, constant_1); loop_body->AddInstruction(add); loop_body->AddInstruction(new (&allocator_) HGoto()); phi->AddInput(add); diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 0d9d3d4c92..0e708ed408 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -20,17 +20,52 @@ #include "base/arena_bit_vector.h" #include "base/bit_vector-inl.h" #include "base/logging.h" +#include "data_type-inl.h" #include "dex/verified_method.h" #include "driver/compiler_options.h" #include "mirror/class_loader.h" #include "mirror/dex_cache.h" #include "nodes.h" -#include "primitive.h" #include "thread.h" #include "utils/dex_cache_arrays_layout-inl.h" namespace art { +HGraphBuilder::HGraphBuilder(HGraph* graph, + DexCompilationUnit* dex_compilation_unit, + const DexCompilationUnit* const outer_compilation_unit, + CompilerDriver* driver, + CodeGenerator* code_generator, + OptimizingCompilerStats* compiler_stats, + const uint8_t* interpreter_metadata, + Handle<mirror::DexCache> dex_cache, + VariableSizedHandleScope* handles) + : graph_(graph), + dex_file_(&graph->GetDexFile()), + code_item_(*dex_compilation_unit->GetCodeItem()), + dex_compilation_unit_(dex_compilation_unit), + compiler_driver_(driver), + compilation_stats_(compiler_stats), + block_builder_(graph, dex_file_, code_item_), + ssa_builder_(graph, + dex_compilation_unit->GetClassLoader(), + dex_compilation_unit->GetDexCache(), + handles), + instruction_builder_(graph, + &block_builder_, + &ssa_builder_, + dex_file_, + code_item_, + DataType::FromShorty(dex_compilation_unit_->GetShorty()[0]), + dex_compilation_unit, + outer_compilation_unit, + driver, + code_generator, + interpreter_metadata, + compiler_stats, + dex_cache, + handles) {} + bool HGraphBuilder::SkipCompilation(size_t number_of_branches) { if (compiler_driver_ == nullptr) { // Note that the compiler driver is null when unit testing. diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 2c9a9efadf..9524fe2534 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -27,7 +27,6 @@ #include "instruction_builder.h" #include "nodes.h" #include "optimizing_compiler_stats.h" -#include "primitive.h" #include "ssa_builder.h" namespace art { @@ -39,45 +38,18 @@ class HGraphBuilder : public ValueObject { HGraphBuilder(HGraph* graph, DexCompilationUnit* dex_compilation_unit, const DexCompilationUnit* const outer_compilation_unit, - const DexFile* dex_file, - const DexFile::CodeItem& code_item, CompilerDriver* driver, CodeGenerator* code_generator, OptimizingCompilerStats* compiler_stats, const uint8_t* interpreter_metadata, Handle<mirror::DexCache> dex_cache, - VariableSizedHandleScope* handles) - : graph_(graph), - dex_file_(dex_file), - code_item_(code_item), - dex_compilation_unit_(dex_compilation_unit), - compiler_driver_(driver), - compilation_stats_(compiler_stats), - block_builder_(graph, dex_file, code_item), - ssa_builder_(graph, - dex_compilation_unit->GetClassLoader(), - dex_compilation_unit->GetDexCache(), - handles), - instruction_builder_(graph, - &block_builder_, - &ssa_builder_, - dex_file, - code_item_, - Primitive::GetType(dex_compilation_unit_->GetShorty()[0]), - dex_compilation_unit, - outer_compilation_unit, - driver, - code_generator, - interpreter_metadata, - compiler_stats, - dex_cache, - handles) {} + VariableSizedHandleScope* handles); // Only for unit testing. HGraphBuilder(HGraph* graph, const DexFile::CodeItem& code_item, VariableSizedHandleScope* handles, - Primitive::Type return_type = Primitive::kPrimInt) + DataType::Type return_type = DataType::Type::kInt32) : graph_(graph), dex_file_(nullptr), code_item_(code_item), diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 1e5f1ec00f..3cb37926af 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -68,35 +68,35 @@ namespace art { static constexpr bool kEnableDexLayoutOptimizations = false; // Return whether a location is consistent with a type. -static bool CheckType(Primitive::Type type, Location location) { +static bool CheckType(DataType::Type type, Location location) { if (location.IsFpuRegister() || (location.IsUnallocated() && (location.GetPolicy() == Location::kRequiresFpuRegister))) { - return (type == Primitive::kPrimFloat) || (type == Primitive::kPrimDouble); + return (type == DataType::Type::kFloat32) || (type == DataType::Type::kFloat64); } else if (location.IsRegister() || (location.IsUnallocated() && (location.GetPolicy() == Location::kRequiresRegister))) { - return Primitive::IsIntegralType(type) || (type == Primitive::kPrimNot); + return DataType::IsIntegralType(type) || (type == DataType::Type::kReference); } else if (location.IsRegisterPair()) { - return type == Primitive::kPrimLong; + return type == DataType::Type::kInt64; } else if (location.IsFpuRegisterPair()) { - return type == Primitive::kPrimDouble; + return type == DataType::Type::kFloat64; } else if (location.IsStackSlot()) { - return (Primitive::IsIntegralType(type) && type != Primitive::kPrimLong) - || (type == Primitive::kPrimFloat) - || (type == Primitive::kPrimNot); + return (DataType::IsIntegralType(type) && type != DataType::Type::kInt64) + || (type == DataType::Type::kFloat32) + || (type == DataType::Type::kReference); } else if (location.IsDoubleStackSlot()) { - return (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble); + return (type == DataType::Type::kInt64) || (type == DataType::Type::kFloat64); } else if (location.IsConstant()) { if (location.GetConstant()->IsIntConstant()) { - return Primitive::IsIntegralType(type) && (type != Primitive::kPrimLong); + return DataType::IsIntegralType(type) && (type != DataType::Type::kInt64); } else if (location.GetConstant()->IsNullConstant()) { - return type == Primitive::kPrimNot; + return type == DataType::Type::kReference; } else if (location.GetConstant()->IsLongConstant()) { - return type == Primitive::kPrimLong; + return type == DataType::Type::kInt64; } else if (location.GetConstant()->IsFloatConstant()) { - return type == Primitive::kPrimFloat; + return type == DataType::Type::kFloat32; } else { return location.GetConstant()->IsDoubleConstant() - && (type == Primitive::kPrimDouble); + && (type == DataType::Type::kFloat64); } } else { return location.IsInvalid() || (location.GetPolicy() == Location::kAny); @@ -130,7 +130,7 @@ static bool CheckTypeConsistency(HInstruction* instruction) { HEnvironment* environment = instruction->GetEnvironment(); for (size_t i = 0; i < instruction->EnvironmentSize(); ++i) { if (environment->GetInstructionAt(i) != nullptr) { - Primitive::Type type = environment->GetInstructionAt(i)->GetType(); + DataType::Type type = environment->GetInstructionAt(i)->GetType(); DCHECK(CheckType(type, environment->GetLocationAt(i))) << type << " " << environment->GetLocationAt(i); } else { @@ -157,10 +157,10 @@ uint32_t CodeGenerator::GetArrayLengthOffset(HArrayLength* array_length) { } uint32_t CodeGenerator::GetArrayDataOffset(HArrayGet* array_get) { - DCHECK(array_get->GetType() == Primitive::kPrimChar || !array_get->IsStringCharAt()); + DCHECK(array_get->GetType() == DataType::Type::kUint16 || !array_get->IsStringCharAt()); return array_get->IsStringCharAt() ? mirror::String::ValueOffset().Uint32Value() - : mirror::Array::DataOffset(Primitive::ComponentSize(array_get->GetType())).Uint32Value(); + : mirror::Array::DataOffset(DataType::Size(array_get->GetType())).Uint32Value(); } bool CodeGenerator::GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const { @@ -288,7 +288,8 @@ void CodeGenerator::Finalize(CodeAllocator* allocator) { GetAssembler()->FinalizeInstructions(code); } -void CodeGenerator::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches ATTRIBUTE_UNUSED) { +void CodeGenerator::EmitLinkerPatches( + ArenaVector<linker::LinkerPatch>* linker_patches ATTRIBUTE_UNUSED) { // No linker patches by default. } @@ -412,7 +413,7 @@ void CodeGenerator::GenerateInvokePolymorphicCall(HInvokePolymorphic* invoke) { void CodeGenerator::CreateUnresolvedFieldLocationSummary( HInstruction* field_access, - Primitive::Type field_type, + DataType::Type field_type, const FieldAccessCallingConvention& calling_convention) { bool is_instance = field_access->IsUnresolvedInstanceFieldGet() || field_access->IsUnresolvedInstanceFieldSet(); @@ -434,7 +435,7 @@ void CodeGenerator::CreateUnresolvedFieldLocationSummary( // regardless of the the type. Because of that we forced to special case // the access to floating point values. if (is_get) { - if (Primitive::IsFloatingPointType(field_type)) { + if (DataType::IsFloatingPointType(field_type)) { // The return value will be stored in regular registers while register // allocator expects it in a floating point register. // Note We don't need to request additional temps because the return @@ -447,7 +448,7 @@ void CodeGenerator::CreateUnresolvedFieldLocationSummary( } } else { size_t set_index = is_instance ? 1 : 0; - if (Primitive::IsFloatingPointType(field_type)) { + if (DataType::IsFloatingPointType(field_type)) { // The set value comes from a float location while the calling convention // expects it in a regular register location. Allocate a temp for it and // make the transfer at codegen. @@ -462,7 +463,7 @@ void CodeGenerator::CreateUnresolvedFieldLocationSummary( void CodeGenerator::GenerateUnresolvedFieldAccess( HInstruction* field_access, - Primitive::Type field_type, + DataType::Type field_type, uint32_t field_index, uint32_t dex_pc, const FieldAccessCallingConvention& calling_convention) { @@ -475,51 +476,52 @@ void CodeGenerator::GenerateUnresolvedFieldAccess( bool is_get = field_access->IsUnresolvedInstanceFieldGet() || field_access->IsUnresolvedStaticFieldGet(); - if (!is_get && Primitive::IsFloatingPointType(field_type)) { + if (!is_get && DataType::IsFloatingPointType(field_type)) { // Copy the float value to be set into the calling convention register. // Note that using directly the temp location is problematic as we don't // support temp register pairs. To avoid boilerplate conversion code, use // the location from the calling convention. MoveLocation(calling_convention.GetSetValueLocation(field_type, is_instance), locations->InAt(is_instance ? 1 : 0), - (Primitive::Is64BitType(field_type) ? Primitive::kPrimLong : Primitive::kPrimInt)); + (DataType::Is64BitType(field_type) ? DataType::Type::kInt64 + : DataType::Type::kInt32)); } QuickEntrypointEnum entrypoint = kQuickSet8Static; // Initialize to anything to avoid warnings. switch (field_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: entrypoint = is_instance ? (is_get ? kQuickGetBooleanInstance : kQuickSet8Instance) : (is_get ? kQuickGetBooleanStatic : kQuickSet8Static); break; - case Primitive::kPrimByte: + case DataType::Type::kInt8: entrypoint = is_instance ? (is_get ? kQuickGetByteInstance : kQuickSet8Instance) : (is_get ? kQuickGetByteStatic : kQuickSet8Static); break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: entrypoint = is_instance ? (is_get ? kQuickGetShortInstance : kQuickSet16Instance) : (is_get ? kQuickGetShortStatic : kQuickSet16Static); break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: entrypoint = is_instance ? (is_get ? kQuickGetCharInstance : kQuickSet16Instance) : (is_get ? kQuickGetCharStatic : kQuickSet16Static); break; - case Primitive::kPrimInt: - case Primitive::kPrimFloat: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: entrypoint = is_instance ? (is_get ? kQuickGet32Instance : kQuickSet32Instance) : (is_get ? kQuickGet32Static : kQuickSet32Static); break; - case Primitive::kPrimNot: + case DataType::Type::kReference: entrypoint = is_instance ? (is_get ? kQuickGetObjInstance : kQuickSetObjInstance) : (is_get ? kQuickGetObjStatic : kQuickSetObjStatic); break; - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: entrypoint = is_instance ? (is_get ? kQuickGet64Instance : kQuickSet64Instance) : (is_get ? kQuickGet64Static : kQuickSet64Static); @@ -529,7 +531,7 @@ void CodeGenerator::GenerateUnresolvedFieldAccess( } InvokeRuntime(entrypoint, field_access, dex_pc, nullptr); - if (is_get && Primitive::IsFloatingPointType(field_type)) { + if (is_get && DataType::IsFloatingPointType(field_type)) { MoveLocation(locations->Out(), calling_convention.GetReturnLocation(field_type), field_type); } } @@ -720,12 +722,10 @@ static void CheckLoopEntriesCanBeUsedForOsr(const HGraph& graph, } } ArenaVector<size_t> covered(loop_headers.size(), 0, graph.GetArena()->Adapter(kArenaAllocMisc)); - const uint16_t* code_ptr = code_item.insns_; - const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_; - - size_t dex_pc = 0; - while (code_ptr < code_end) { - const Instruction& instruction = *Instruction::At(code_ptr); + IterationRange<DexInstructionIterator> instructions = code_item.Instructions(); + for (auto it = instructions.begin(); it != instructions.end(); ++it) { + const uint32_t dex_pc = it.GetDexPC(instructions.begin()); + const Instruction& instruction = *it; if (instruction.IsBranch()) { uint32_t target = dex_pc + instruction.GetTargetOffset(); CheckCovers(target, graph, code_info, loop_headers, &covered); @@ -741,8 +741,6 @@ static void CheckLoopEntriesCanBeUsedForOsr(const HGraph& graph, CheckCovers(target, graph, code_info, loop_headers, &covered); } } - dex_pc += instruction.SizeInCodeUnits(); - code_ptr += instruction.SizeInCodeUnits(); } for (size_t i = 0; i < covered.size(); ++i) { @@ -779,8 +777,8 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction, return; } if (instruction->IsRem()) { - Primitive::Type type = instruction->AsRem()->GetResultType(); - if ((type == Primitive::kPrimFloat) || (type == Primitive::kPrimDouble)) { + DataType::Type type = instruction->AsRem()->GetResultType(); + if ((type == DataType::Type::kFloat32) || (type == DataType::Type::kFloat64)) { return; } } @@ -1051,7 +1049,7 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo if (slow_path != nullptr && slow_path->IsCoreRegisterSaved(id)) { uint32_t offset = slow_path->GetStackOffsetOfCoreRegister(id); stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset); - if (current->GetType() == Primitive::kPrimLong) { + if (current->GetType() == DataType::Type::kInt64) { stack_map_stream_.AddDexRegisterEntry( DexRegisterLocation::Kind::kInStack, offset + kVRegSize); ++i; @@ -1059,7 +1057,7 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo } } else { stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister, id); - if (current->GetType() == Primitive::kPrimLong) { + if (current->GetType() == DataType::Type::kInt64) { stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegisterHigh, id); ++i; DCHECK_LT(i, environment_size); @@ -1073,7 +1071,7 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo if (slow_path != nullptr && slow_path->IsFpuRegisterSaved(id)) { uint32_t offset = slow_path->GetStackOffsetOfFpuRegister(id); stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset); - if (current->GetType() == Primitive::kPrimDouble) { + if (current->GetType() == DataType::Type::kFloat64) { stack_map_stream_.AddDexRegisterEntry( DexRegisterLocation::Kind::kInStack, offset + kVRegSize); ++i; @@ -1081,7 +1079,7 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo } } else { stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister, id); - if (current->GetType() == Primitive::kPrimDouble) { + if (current->GetType() == DataType::Type::kFloat64) { stack_map_stream_.AddDexRegisterEntry( DexRegisterLocation::Kind::kInFpuRegisterHigh, id); ++i; @@ -1225,7 +1223,7 @@ void CodeGenerator::ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend LiveInterval* interval = current->GetLiveInterval(); // We only need to clear bits of loop phis containing objects and allocated in register. // Loop phis allocated on stack already have the object in the stack. - if (current->GetType() == Primitive::kPrimNot + if (current->GetType() == DataType::Type::kReference && interval->HasRegister() && interval->HasSpillSlot()) { locations->ClearStackBit(interval->GetSpillSlot() / kVRegSize); @@ -1235,10 +1233,10 @@ void CodeGenerator::ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend void CodeGenerator::EmitParallelMoves(Location from1, Location to1, - Primitive::Type type1, + DataType::Type type1, Location from2, Location to2, - Primitive::Type type2) { + DataType::Type type2) { HParallelMove parallel_move(GetGraph()->GetArena()); parallel_move.AddMove(from1, to1, type1, nullptr); parallel_move.AddMove(from2, to2, type2, nullptr); diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index 30c2b52242..ac3c8394e6 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -61,9 +61,12 @@ class Assembler; class CodeGenerator; class CompilerDriver; class CompilerOptions; -class LinkerPatch; class ParallelMoveResolver; +namespace linker { +class LinkerPatch; +} // namespace linker + class CodeAllocator { public: CodeAllocator() {} @@ -143,8 +146,8 @@ class SlowPathCode : public DeletableArenaObject<kArenaAllocSlowPaths> { class InvokeDexCallingConventionVisitor { public: - virtual Location GetNextLocation(Primitive::Type type) = 0; - virtual Location GetReturnLocation(Primitive::Type type) const = 0; + virtual Location GetNextLocation(DataType::Type type) = 0; + virtual Location GetReturnLocation(DataType::Type type) const = 0; virtual Location GetMethodLocation() const = 0; protected: @@ -166,9 +169,9 @@ class FieldAccessCallingConvention { public: virtual Location GetObjectLocation() const = 0; virtual Location GetFieldIndexLocation() const = 0; - virtual Location GetReturnLocation(Primitive::Type type) const = 0; - virtual Location GetSetValueLocation(Primitive::Type type, bool is_instance) const = 0; - virtual Location GetFpuLocation(Primitive::Type type) const = 0; + virtual Location GetReturnLocation(DataType::Type type) const = 0; + virtual Location GetSetValueLocation(DataType::Type type, bool is_instance) const = 0; + virtual Location GetFpuLocation(DataType::Type type) const = 0; virtual ~FieldAccessCallingConvention() {} protected: @@ -205,12 +208,12 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { virtual void Initialize() = 0; virtual void Finalize(CodeAllocator* allocator); - virtual void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches); + virtual void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches); virtual void GenerateFrameEntry() = 0; virtual void GenerateFrameExit() = 0; virtual void Bind(HBasicBlock* block) = 0; virtual void MoveConstant(Location destination, int32_t value) = 0; - virtual void MoveLocation(Location dst, Location src, Primitive::Type dst_type) = 0; + virtual void MoveLocation(Location dst, Location src, DataType::Type dst_type) = 0; virtual void AddLocationAsTemp(Location location, LocationSummary* locations) = 0; virtual Assembler* GetAssembler() = 0; @@ -262,7 +265,7 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0; virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0; - virtual bool NeedsTwoRegisters(Primitive::Type type) const = 0; + virtual bool NeedsTwoRegisters(DataType::Type type) const = 0; // Returns whether we should split long moves in parallel moves. virtual bool ShouldSplitLongMoves() const { return false; } @@ -404,15 +407,15 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { void EmitParallelMoves(Location from1, Location to1, - Primitive::Type type1, + DataType::Type type1, Location from2, Location to2, - Primitive::Type type2); + DataType::Type type2); - static bool StoreNeedsWriteBarrier(Primitive::Type type, HInstruction* value) { + static bool StoreNeedsWriteBarrier(DataType::Type type, HInstruction* value) { // Check that null value is not represented as an integer constant. - DCHECK(type != Primitive::kPrimNot || !value->IsIntConstant()); - return type == Primitive::kPrimNot && !value->IsNullConstant(); + DCHECK(type != DataType::Type::kReference || !value->IsIntConstant()); + return type == DataType::Type::kReference && !value->IsNullConstant(); } @@ -501,12 +504,12 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { void CreateUnresolvedFieldLocationSummary( HInstruction* field_access, - Primitive::Type field_type, + DataType::Type field_type, const FieldAccessCallingConvention& calling_convention); void GenerateUnresolvedFieldAccess( HInstruction* field_access, - Primitive::Type field_type, + DataType::Type field_type, uint32_t field_index, uint32_t dex_pc, const FieldAccessCallingConvention& calling_convention); @@ -570,7 +573,7 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) = 0; // Copy the result of a call into the given target. - virtual void MoveFromReturnRegister(Location trg, Primitive::Type type) = 0; + virtual void MoveFromReturnRegister(Location trg, DataType::Type type) = 0; virtual void GenerateNop() = 0; diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 8814cfc251..42e9f68a76 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -31,6 +31,7 @@ #include "intrinsics.h" #include "intrinsics_arm64.h" #include "linker/arm64/relative_patcher_arm64.h" +#include "linker/linker_patch.h" #include "lock_word.h" #include "mirror/array-inl.h" #include "mirror/class-inl.h" @@ -143,24 +144,24 @@ inline Condition ARM64FPCondition(IfCondition cond, bool gt_bias) { } } -Location ARM64ReturnLocation(Primitive::Type return_type) { +Location ARM64ReturnLocation(DataType::Type return_type) { // Note that in practice, `LocationFrom(x0)` and `LocationFrom(w0)` create the // same Location object, and so do `LocationFrom(d0)` and `LocationFrom(s0)`, // but we use the exact registers for clarity. - if (return_type == Primitive::kPrimFloat) { + if (return_type == DataType::Type::kFloat32) { return LocationFrom(s0); - } else if (return_type == Primitive::kPrimDouble) { + } else if (return_type == DataType::Type::kFloat64) { return LocationFrom(d0); - } else if (return_type == Primitive::kPrimLong) { + } else if (return_type == DataType::Type::kInt64) { return LocationFrom(x0); - } else if (return_type == Primitive::kPrimVoid) { + } else if (return_type == DataType::Type::kVoid) { return Location::NoLocation(); } else { return LocationFrom(w0); } } -Location InvokeRuntimeCallingConvention::GetReturnLocation(Primitive::Type return_type) { +Location InvokeRuntimeCallingConvention::GetReturnLocation(DataType::Type return_type) { return ARM64ReturnLocation(return_type); } @@ -264,9 +265,12 @@ class BoundsCheckSlowPathARM64 : public SlowPathCodeARM64 { // We're moving two locations to locations that could overlap, so we need a parallel // move resolver. InvokeRuntimeCallingConvention calling_convention; - codegen->EmitParallelMoves( - locations->InAt(0), LocationFrom(calling_convention.GetRegisterAt(0)), Primitive::kPrimInt, - locations->InAt(1), LocationFrom(calling_convention.GetRegisterAt(1)), Primitive::kPrimInt); + codegen->EmitParallelMoves(locations->InAt(0), + LocationFrom(calling_convention.GetRegisterAt(0)), + DataType::Type::kInt32, + locations->InAt(1), + LocationFrom(calling_convention.GetRegisterAt(1)), + DataType::Type::kInt32); QuickEntrypointEnum entrypoint = instruction_->AsBoundsCheck()->IsStringCharAt() ? kQuickThrowStringBounds : kQuickThrowArrayBounds; @@ -355,7 +359,7 @@ class LoadClassSlowPathARM64 : public SlowPathCodeARM64 { // Move the class to the desired location. if (out.IsValid()) { DCHECK(out.IsRegister() && !locations->GetLiveRegisters()->ContainsCoreRegister(out.reg())); - Primitive::Type type = instruction_->GetType(); + DataType::Type type = instruction_->GetType(); arm64_codegen->MoveLocation(out, calling_convention.GetReturnLocation(type), type); } RestoreLiveRegisters(codegen, locations); @@ -375,7 +379,7 @@ class LoadClassSlowPathARM64 : public SlowPathCodeARM64 { { SingleEmissionCheckScope guard(arm64_codegen->GetVIXLAssembler()); __ Bind(strp_label); - __ str(RegisterFrom(locations->Out(), Primitive::kPrimNot), + __ str(RegisterFrom(locations->Out(), DataType::Type::kReference), MemOperand(bss_entry_temp_, /* offset placeholder */ 0)); } } @@ -426,7 +430,7 @@ class LoadStringSlowPathARM64 : public SlowPathCodeARM64 { __ Mov(calling_convention.GetRegisterAt(0).W(), string_index.index_); arm64_codegen->InvokeRuntime(kQuickResolveString, instruction_, instruction_->GetDexPc(), this); CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>(); - Primitive::Type type = instruction_->GetType(); + DataType::Type type = instruction_->GetType(); arm64_codegen->MoveLocation(locations->Out(), calling_convention.GetReturnLocation(type), type); RestoreLiveRegisters(codegen, locations); @@ -445,7 +449,7 @@ class LoadStringSlowPathARM64 : public SlowPathCodeARM64 { { SingleEmissionCheckScope guard(arm64_codegen->GetVIXLAssembler()); __ Bind(strp_label); - __ str(RegisterFrom(locations->Out(), Primitive::kPrimNot), + __ str(RegisterFrom(locations->Out(), DataType::Type::kReference), MemOperand(temp_, /* offset placeholder */ 0)); } @@ -552,14 +556,14 @@ class TypeCheckSlowPathARM64 : public SlowPathCodeARM64 { InvokeRuntimeCallingConvention calling_convention; codegen->EmitParallelMoves(locations->InAt(0), LocationFrom(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, locations->InAt(1), LocationFrom(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot); + DataType::Type::kReference); if (instruction_->IsInstanceOf()) { arm64_codegen->InvokeRuntime(kQuickInstanceofNonTrivial, instruction_, dex_pc, this); CheckEntrypointTypes<kQuickInstanceofNonTrivial, size_t, mirror::Object*, mirror::Class*>(); - Primitive::Type ret_type = instruction_->GetType(); + DataType::Type ret_type = instruction_->GetType(); Location ret_loc = calling_convention.GetReturnLocation(ret_type); arm64_codegen->MoveLocation(locations->Out(), ret_loc, ret_type); } else { @@ -620,17 +624,17 @@ class ArraySetSlowPathARM64 : public SlowPathCodeARM64 { parallel_move.AddMove( locations->InAt(0), LocationFrom(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove( locations->InAt(1), LocationFrom(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); parallel_move.AddMove( locations->InAt(2), LocationFrom(calling_convention.GetRegisterAt(2)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); @@ -1199,7 +1203,7 @@ class ReadBarrierForHeapReferenceSlowPathARM64 : public SlowPathCodeARM64 { void EmitNativeCode(CodeGenerator* codegen) OVERRIDE { CodeGeneratorARM64* arm64_codegen = down_cast<CodeGeneratorARM64*>(codegen); LocationSummary* locations = instruction_->GetLocations(); - Primitive::Type type = Primitive::kPrimNot; + DataType::Type type = DataType::Type::kReference; DCHECK(locations->CanCall()); DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(out_.reg())); DCHECK(instruction_->IsInstanceFieldGet() || @@ -1228,7 +1232,7 @@ class ReadBarrierForHeapReferenceSlowPathARM64 : public SlowPathCodeARM64 { // Handle `index_` for HArrayGet and UnsafeGetObject/UnsafeGetObjectVolatile intrinsics. if (instruction_->IsArrayGet()) { // Compute the actual memory offset and store it in `index`. - Register index_reg = RegisterFrom(index_, Primitive::kPrimInt); + Register index_reg = RegisterFrom(index_, DataType::Type::kInt32); DCHECK(locations->GetLiveRegisters()->ContainsCoreRegister(index_.reg())); if (codegen->IsCoreCalleeSaveRegister(index_.reg())) { // We are about to change the value of `index_reg` (see the @@ -1267,7 +1271,7 @@ class ReadBarrierForHeapReferenceSlowPathARM64 : public SlowPathCodeARM64 { // factor (2) cannot overflow in practice, as the runtime is // unable to allocate object arrays with a size larger than // 2^26 - 1 (that is, 2^28 - 4 bytes). - __ Lsl(index_reg, index_reg, Primitive::ComponentSizeShift(type)); + __ Lsl(index_reg, index_reg, DataType::SizeShift(type)); static_assert( sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t), "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes."); @@ -1302,7 +1306,7 @@ class ReadBarrierForHeapReferenceSlowPathARM64 : public SlowPathCodeARM64 { if (index.IsValid()) { parallel_move.AddMove(index, LocationFrom(calling_convention.GetRegisterAt(2)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); } else { @@ -1364,7 +1368,7 @@ class ReadBarrierForRootSlowPathARM64 : public SlowPathCodeARM64 { void EmitNativeCode(CodeGenerator* codegen) OVERRIDE { LocationSummary* locations = instruction_->GetLocations(); - Primitive::Type type = Primitive::kPrimNot; + DataType::Type type = DataType::Type::kReference; DCHECK(locations->CanCall()); DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(out_.reg())); DCHECK(instruction_->IsLoadClass() || instruction_->IsLoadString()) @@ -1386,7 +1390,7 @@ class ReadBarrierForRootSlowPathARM64 : public SlowPathCodeARM64 { // type); // // which would emit a 32-bit move, as `type` is a (32-bit wide) - // reference type (`Primitive::kPrimNot`). + // reference type (`DataType::Type::kReference`). __ Mov(calling_convention.GetRegisterAt(0), XRegisterFrom(out_)); arm64_codegen->InvokeRuntime(kQuickReadBarrierForRootSlow, instruction_, @@ -1410,26 +1414,26 @@ class ReadBarrierForRootSlowPathARM64 : public SlowPathCodeARM64 { #undef __ -Location InvokeDexCallingConventionVisitorARM64::GetNextLocation(Primitive::Type type) { +Location InvokeDexCallingConventionVisitorARM64::GetNextLocation(DataType::Type type) { Location next_location; - if (type == Primitive::kPrimVoid) { + if (type == DataType::Type::kVoid) { LOG(FATAL) << "Unreachable type " << type; } - if (Primitive::IsFloatingPointType(type) && + if (DataType::IsFloatingPointType(type) && (float_index_ < calling_convention.GetNumberOfFpuRegisters())) { next_location = LocationFrom(calling_convention.GetFpuRegisterAt(float_index_++)); - } else if (!Primitive::IsFloatingPointType(type) && + } else if (!DataType::IsFloatingPointType(type) && (gp_index_ < calling_convention.GetNumberOfRegisters())) { next_location = LocationFrom(calling_convention.GetRegisterAt(gp_index_++)); } else { size_t stack_offset = calling_convention.GetStackOffsetOf(stack_index_); - next_location = Primitive::Is64BitType(type) ? Location::DoubleStackSlot(stack_offset) - : Location::StackSlot(stack_offset); + next_location = DataType::Is64BitType(type) ? Location::DoubleStackSlot(stack_offset) + : Location::StackSlot(stack_offset); } // Space on the stack is reserved for all arguments. - stack_index_ += Primitive::Is64BitType(type) ? 2 : 1; + stack_index_ += DataType::Is64BitType(type) ? 2 : 1; return next_location; } @@ -1546,7 +1550,7 @@ void ParallelMoveResolverARM64::FreeScratchLocation(Location loc) { void ParallelMoveResolverARM64::EmitMove(size_t index) { MoveOperands* move = moves_[index]; - codegen_->MoveLocation(move->GetDestination(), move->GetSource(), Primitive::kPrimVoid); + codegen_->MoveLocation(move->GetDestination(), move->GetSource(), DataType::Type::kVoid); } void CodeGeneratorARM64::GenerateFrameEntry() { @@ -1637,7 +1641,7 @@ void CodeGeneratorARM64::Bind(HBasicBlock* block) { void CodeGeneratorARM64::MoveConstant(Location location, int32_t value) { DCHECK(location.IsRegister()); - __ Mov(RegisterFrom(location, Primitive::kPrimInt), value); + __ Mov(RegisterFrom(location, DataType::Type::kInt32), value); } void CodeGeneratorARM64::AddLocationAsTemp(Location location, LocationSummary* locations) { @@ -1744,15 +1748,15 @@ void CodeGeneratorARM64::MoveConstant(CPURegister destination, HConstant* consta } -static bool CoherentConstantAndType(Location constant, Primitive::Type type) { +static bool CoherentConstantAndType(Location constant, DataType::Type type) { DCHECK(constant.IsConstant()); HConstant* cst = constant.GetConstant(); - return (cst->IsIntConstant() && type == Primitive::kPrimInt) || + return (cst->IsIntConstant() && type == DataType::Type::kInt32) || // Null is mapped to a core W register, which we associate with kPrimInt. - (cst->IsNullConstant() && type == Primitive::kPrimInt) || - (cst->IsLongConstant() && type == Primitive::kPrimLong) || - (cst->IsFloatConstant() && type == Primitive::kPrimFloat) || - (cst->IsDoubleConstant() && type == Primitive::kPrimDouble); + (cst->IsNullConstant() && type == DataType::Type::kInt32) || + (cst->IsLongConstant() && type == DataType::Type::kInt64) || + (cst->IsFloatConstant() && type == DataType::Type::kFloat32) || + (cst->IsDoubleConstant() && type == DataType::Type::kFloat64); } // Allocate a scratch register from the VIXL pool, querying first @@ -1770,7 +1774,7 @@ static CPURegister AcquireFPOrCoreCPURegisterOfSize(vixl::aarch64::MacroAssemble void CodeGeneratorARM64::MoveLocation(Location destination, Location source, - Primitive::Type dst_type) { + DataType::Type dst_type) { if (source.Equals(destination)) { return; } @@ -1779,7 +1783,7 @@ void CodeGeneratorARM64::MoveLocation(Location destination, // locations. When moving from and to a register, the argument type can be // used to generate 32bit instead of 64bit moves. In debug mode we also // checks the coherency of the locations and the type. - bool unspecified_type = (dst_type == Primitive::kPrimVoid); + bool unspecified_type = (dst_type == DataType::Type::kVoid); if (destination.IsRegister() || destination.IsFpuRegister()) { if (unspecified_type) { @@ -1789,17 +1793,17 @@ void CodeGeneratorARM64::MoveLocation(Location destination, || src_cst->IsFloatConstant() || src_cst->IsNullConstant()))) { // For stack slots and 32bit constants, a 64bit type is appropriate. - dst_type = destination.IsRegister() ? Primitive::kPrimInt : Primitive::kPrimFloat; + dst_type = destination.IsRegister() ? DataType::Type::kInt32 : DataType::Type::kFloat32; } else { // If the source is a double stack slot or a 64bit constant, a 64bit // type is appropriate. Else the source is a register, and since the // type has not been specified, we chose a 64bit type to force a 64bit // move. - dst_type = destination.IsRegister() ? Primitive::kPrimLong : Primitive::kPrimDouble; + dst_type = destination.IsRegister() ? DataType::Type::kInt64 : DataType::Type::kFloat64; } } - DCHECK((destination.IsFpuRegister() && Primitive::IsFloatingPointType(dst_type)) || - (destination.IsRegister() && !Primitive::IsFloatingPointType(dst_type))); + DCHECK((destination.IsFpuRegister() && DataType::IsFloatingPointType(dst_type)) || + (destination.IsRegister() && !DataType::IsFloatingPointType(dst_type))); CPURegister dst = CPURegisterFrom(destination, dst_type); if (source.IsStackSlot() || source.IsDoubleStackSlot()) { DCHECK(dst.Is64Bits() == source.IsDoubleStackSlot()); @@ -1814,17 +1818,17 @@ void CodeGeneratorARM64::MoveLocation(Location destination, __ Mov(Register(dst), RegisterFrom(source, dst_type)); } else { DCHECK(destination.IsFpuRegister()); - Primitive::Type source_type = Primitive::Is64BitType(dst_type) - ? Primitive::kPrimLong - : Primitive::kPrimInt; + DataType::Type source_type = DataType::Is64BitType(dst_type) + ? DataType::Type::kInt64 + : DataType::Type::kInt32; __ Fmov(FPRegisterFrom(destination, dst_type), RegisterFrom(source, source_type)); } } else { DCHECK(source.IsFpuRegister()); if (destination.IsRegister()) { - Primitive::Type source_type = Primitive::Is64BitType(dst_type) - ? Primitive::kPrimDouble - : Primitive::kPrimFloat; + DataType::Type source_type = DataType::Is64BitType(dst_type) + ? DataType::Type::kFloat64 + : DataType::Type::kFloat32; __ Fmov(RegisterFrom(destination, dst_type), FPRegisterFrom(source, source_type)); } else { DCHECK(destination.IsFpuRegister()); @@ -1858,13 +1862,14 @@ void CodeGeneratorARM64::MoveLocation(Location destination, if (source.IsRegister() || source.IsFpuRegister()) { if (unspecified_type) { if (source.IsRegister()) { - dst_type = destination.IsStackSlot() ? Primitive::kPrimInt : Primitive::kPrimLong; + dst_type = destination.IsStackSlot() ? DataType::Type::kInt32 : DataType::Type::kInt64; } else { - dst_type = destination.IsStackSlot() ? Primitive::kPrimFloat : Primitive::kPrimDouble; + dst_type = + destination.IsStackSlot() ? DataType::Type::kFloat32 : DataType::Type::kFloat64; } } - DCHECK((destination.IsDoubleStackSlot() == Primitive::Is64BitType(dst_type)) && - (source.IsFpuRegister() == Primitive::IsFloatingPointType(dst_type))); + DCHECK((destination.IsDoubleStackSlot() == DataType::Is64BitType(dst_type)) && + (source.IsFpuRegister() == DataType::IsFloatingPointType(dst_type))); __ Str(CPURegisterFrom(source, dst_type), StackOperandFrom(destination)); } else if (source.IsConstant()) { DCHECK(unspecified_type || CoherentConstantAndType(source, dst_type)) @@ -1919,31 +1924,31 @@ void CodeGeneratorARM64::MoveLocation(Location destination, } } -void CodeGeneratorARM64::Load(Primitive::Type type, +void CodeGeneratorARM64::Load(DataType::Type type, CPURegister dst, const MemOperand& src) { switch (type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: __ Ldrb(Register(dst), src); break; - case Primitive::kPrimByte: + case DataType::Type::kInt8: __ Ldrsb(Register(dst), src); break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: __ Ldrsh(Register(dst), src); break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: __ Ldrh(Register(dst), src); break; - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - DCHECK_EQ(dst.Is64Bits(), Primitive::Is64BitType(type)); + case DataType::Type::kInt32: + case DataType::Type::kReference: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: + DCHECK_EQ(dst.Is64Bits(), DataType::Is64BitType(type)); __ Ldr(dst, src); break; - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; } } @@ -1955,7 +1960,7 @@ void CodeGeneratorARM64::LoadAcquire(HInstruction* instruction, MacroAssembler* masm = GetVIXLAssembler(); UseScratchRegisterScope temps(masm); Register temp_base = temps.AcquireX(); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); DCHECK(!src.IsPreIndex()); DCHECK(!src.IsPostIndex()); @@ -1966,7 +1971,7 @@ void CodeGeneratorARM64::LoadAcquire(HInstruction* instruction, // Ensure that between load and MaybeRecordImplicitNullCheck there are no pools emitted. MemOperand base = MemOperand(temp_base); switch (type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: { ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize); __ ldarb(Register(dst), base); @@ -1975,7 +1980,7 @@ void CodeGeneratorARM64::LoadAcquire(HInstruction* instruction, } } break; - case Primitive::kPrimByte: + case DataType::Type::kInt8: { ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize); __ ldarb(Register(dst), base); @@ -1983,9 +1988,9 @@ void CodeGeneratorARM64::LoadAcquire(HInstruction* instruction, MaybeRecordImplicitNullCheck(instruction); } } - __ Sbfx(Register(dst), Register(dst), 0, Primitive::ComponentSize(type) * kBitsPerByte); + __ Sbfx(Register(dst), Register(dst), 0, DataType::Size(type) * kBitsPerByte); break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: { ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize); __ ldarh(Register(dst), base); @@ -1994,7 +1999,7 @@ void CodeGeneratorARM64::LoadAcquire(HInstruction* instruction, } } break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: { ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize); __ ldarh(Register(dst), base); @@ -2002,12 +2007,12 @@ void CodeGeneratorARM64::LoadAcquire(HInstruction* instruction, MaybeRecordImplicitNullCheck(instruction); } } - __ Sbfx(Register(dst), Register(dst), 0, Primitive::ComponentSize(type) * kBitsPerByte); + __ Sbfx(Register(dst), Register(dst), 0, DataType::Size(type) * kBitsPerByte); break; - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: - DCHECK_EQ(dst.Is64Bits(), Primitive::Is64BitType(type)); + case DataType::Type::kInt32: + case DataType::Type::kReference: + case DataType::Type::kInt64: + DCHECK_EQ(dst.Is64Bits(), DataType::Is64BitType(type)); { ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize); __ ldar(Register(dst), base); @@ -2016,10 +2021,10 @@ void CodeGeneratorARM64::LoadAcquire(HInstruction* instruction, } } break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { DCHECK(dst.IsFPRegister()); - DCHECK_EQ(dst.Is64Bits(), Primitive::Is64BitType(type)); + DCHECK_EQ(dst.Is64Bits(), DataType::Is64BitType(type)); Register temp = dst.Is64Bits() ? temps.AcquireX() : temps.AcquireW(); { @@ -2032,39 +2037,39 @@ void CodeGeneratorARM64::LoadAcquire(HInstruction* instruction, __ Fmov(FPRegister(dst), temp); break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; } } } -void CodeGeneratorARM64::Store(Primitive::Type type, +void CodeGeneratorARM64::Store(DataType::Type type, CPURegister src, const MemOperand& dst) { switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: __ Strb(Register(src), dst); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: __ Strh(Register(src), dst); break; - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - DCHECK_EQ(src.Is64Bits(), Primitive::Is64BitType(type)); + case DataType::Type::kInt32: + case DataType::Type::kReference: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: + DCHECK_EQ(src.Is64Bits(), DataType::Is64BitType(type)); __ Str(src, dst); break; - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; } } void CodeGeneratorARM64::StoreRelease(HInstruction* instruction, - Primitive::Type type, + DataType::Type type, CPURegister src, const MemOperand& dst, bool needs_null_check) { @@ -2081,8 +2086,8 @@ void CodeGeneratorARM64::StoreRelease(HInstruction* instruction, MemOperand base = MemOperand(temp_base); // Ensure that between store and MaybeRecordImplicitNullCheck there are no pools emitted. switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: { ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize); __ stlrb(Register(src), base); @@ -2091,8 +2096,8 @@ void CodeGeneratorARM64::StoreRelease(HInstruction* instruction, } } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: { ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize); __ stlrh(Register(src), base); @@ -2101,10 +2106,10 @@ void CodeGeneratorARM64::StoreRelease(HInstruction* instruction, } } break; - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: - DCHECK_EQ(src.Is64Bits(), Primitive::Is64BitType(type)); + case DataType::Type::kInt32: + case DataType::Type::kReference: + case DataType::Type::kInt64: + DCHECK_EQ(src.Is64Bits(), DataType::Is64BitType(type)); { ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize); __ stlr(Register(src), base); @@ -2113,9 +2118,9 @@ void CodeGeneratorARM64::StoreRelease(HInstruction* instruction, } } break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { - DCHECK_EQ(src.Is64Bits(), Primitive::Is64BitType(type)); + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { + DCHECK_EQ(src.Is64Bits(), DataType::Is64BitType(type)); Register temp_src; if (src.IsZero()) { // The zero register is used to avoid synthesizing zero constants. @@ -2134,7 +2139,7 @@ void CodeGeneratorARM64::StoreRelease(HInstruction* instruction, } break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; } } @@ -2268,17 +2273,17 @@ enum UnimplementedInstructionBreakCode { void LocationsBuilderARM64::HandleBinaryOp(HBinaryOperation* instr) { DCHECK_EQ(instr->InputCount(), 2U); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr); - Primitive::Type type = instr->GetResultType(); + DataType::Type type = instr->GetResultType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, ARM64EncodableConstantOrRegister(instr->InputAt(1), instr)); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -2294,7 +2299,7 @@ void LocationsBuilderARM64::HandleFieldGet(HInstruction* instruction, DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet()); bool object_field_get_with_read_barrier = - kEmitCompilerReadBarrier && (instruction->GetType() == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (instruction->GetType() == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, object_field_get_with_read_barrier ? @@ -2317,7 +2322,7 @@ void LocationsBuilderARM64::HandleFieldGet(HInstruction* instruction, } } locations->SetInAt(0, Location::RequiresRegister()); - if (Primitive::IsFloatingPointType(instruction->GetType())) { + if (DataType::IsFloatingPointType(instruction->GetType())) { locations->SetOut(Location::RequiresFpuRegister()); } else { // The output overlaps for an object field get when read barriers @@ -2336,13 +2341,14 @@ void InstructionCodeGeneratorARM64::HandleFieldGet(HInstruction* instruction, Location base_loc = locations->InAt(0); Location out = locations->Out(); uint32_t offset = field_info.GetFieldOffset().Uint32Value(); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); MemOperand field = HeapOperand(InputRegisterAt(instruction, 0), field_info.GetFieldOffset()); - if (field_type == Primitive::kPrimNot && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { + if (kEmitCompilerReadBarrier && kUseBakerReadBarrier && + field_type == DataType::Type::kReference) { // Object FieldGet with Baker's read barrier case. // /* HeapReference<Object> */ out = *(base + offset) - Register base = RegisterFrom(base_loc, Primitive::kPrimNot); + Register base = RegisterFrom(base_loc, DataType::Type::kReference); Location maybe_temp = (locations->GetTempCount() != 0) ? locations->GetTemp(0) : Location::NoLocation(); // Note that potential implicit null checks are handled in this @@ -2369,7 +2375,7 @@ void InstructionCodeGeneratorARM64::HandleFieldGet(HInstruction* instruction, codegen_->Load(field_type, OutputCPURegister(instruction), field); codegen_->MaybeRecordImplicitNullCheck(instruction); } - if (field_type == Primitive::kPrimNot) { + if (field_type == DataType::Type::kReference) { // If read barriers are enabled, emit read barriers other than // Baker's using a slow path (and also unpoison the loaded // reference, if heap poisoning is enabled). @@ -2384,7 +2390,7 @@ void LocationsBuilderARM64::HandleFieldSet(HInstruction* instruction) { locations->SetInAt(0, Location::RequiresRegister()); if (IsConstantZeroBitPattern(instruction->InputAt(1))) { locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant())); - } else if (Primitive::IsFloatingPointType(instruction->InputAt(1)->GetType())) { + } else if (DataType::IsFloatingPointType(instruction->InputAt(1)->GetType())) { locations->SetInAt(1, Location::RequiresFpuRegister()); } else { locations->SetInAt(1, Location::RequiresRegister()); @@ -2400,14 +2406,14 @@ void InstructionCodeGeneratorARM64::HandleFieldSet(HInstruction* instruction, CPURegister value = InputCPURegisterOrZeroRegAt(instruction, 1); CPURegister source = value; Offset offset = field_info.GetFieldOffset(); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); { // We use a block to end the scratch scope before the write barrier, thus // freeing the temporary registers so they can be used in `MarkGCCard`. UseScratchRegisterScope temps(GetVIXLAssembler()); - if (kPoisonHeapReferences && field_type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && field_type == DataType::Type::kReference) { DCHECK(value.IsW()); Register temp = temps.AcquireW(); __ Mov(temp, value.W()); @@ -2432,11 +2438,11 @@ void InstructionCodeGeneratorARM64::HandleFieldSet(HInstruction* instruction, } void InstructionCodeGeneratorARM64::HandleBinaryOp(HBinaryOperation* instr) { - Primitive::Type type = instr->GetType(); + DataType::Type type = instr->GetType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { Register dst = OutputRegister(instr); Register lhs = InputRegisterAt(instr, 0); Operand rhs = InputOperandAt(instr, 1); @@ -2465,8 +2471,8 @@ void InstructionCodeGeneratorARM64::HandleBinaryOp(HBinaryOperation* instr) { } break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { FPRegister dst = OutputFPRegister(instr); FPRegister lhs = InputFPRegisterAt(instr, 0); FPRegister rhs = InputFPRegisterAt(instr, 1); @@ -2488,10 +2494,10 @@ void LocationsBuilderARM64::HandleShift(HBinaryOperation* instr) { DCHECK(instr->IsShl() || instr->IsShr() || instr->IsUShr()); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr); - Primitive::Type type = instr->GetResultType(); + DataType::Type type = instr->GetResultType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instr->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -2505,16 +2511,16 @@ void LocationsBuilderARM64::HandleShift(HBinaryOperation* instr) { void InstructionCodeGeneratorARM64::HandleShift(HBinaryOperation* instr) { DCHECK(instr->IsShl() || instr->IsShr() || instr->IsUShr()); - Primitive::Type type = instr->GetType(); + DataType::Type type = instr->GetType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { Register dst = OutputRegister(instr); Register lhs = InputRegisterAt(instr, 0); Operand rhs = InputOperandAt(instr, 1); if (rhs.IsImmediate()) { uint32_t shift_value = rhs.GetImmediate() & - (type == Primitive::kPrimInt ? kMaxIntShiftDistance : kMaxLongShiftDistance); + (type == DataType::Type::kInt32 ? kMaxIntShiftDistance : kMaxLongShiftDistance); if (instr->IsShl()) { __ Lsl(dst, lhs, shift_value); } else if (instr->IsShr()) { @@ -2557,7 +2563,7 @@ void InstructionCodeGeneratorARM64::VisitAnd(HAnd* instruction) { } void LocationsBuilderARM64::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instr) { - DCHECK(Primitive::IsIntegralType(instr->GetType())) << instr->GetType(); + DCHECK(DataType::IsIntegralType(instr->GetType())) << instr->GetType(); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr); locations->SetInAt(0, Location::RequiresRegister()); // There is no immediate variant of negated bitwise instructions in AArch64. @@ -2587,8 +2593,8 @@ void InstructionCodeGeneratorARM64::VisitBitwiseNegatedRight(HBitwiseNegatedRigh void LocationsBuilderARM64::VisitDataProcWithShifterOp( HDataProcWithShifterOp* instruction) { - DCHECK(instruction->GetType() == Primitive::kPrimInt || - instruction->GetType() == Primitive::kPrimLong); + DCHECK(instruction->GetType() == DataType::Type::kInt32 || + instruction->GetType() == DataType::Type::kInt64); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); if (instruction->GetInstrKind() == HInstruction::kNeg) { @@ -2602,9 +2608,9 @@ void LocationsBuilderARM64::VisitDataProcWithShifterOp( void InstructionCodeGeneratorARM64::VisitDataProcWithShifterOp( HDataProcWithShifterOp* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); HInstruction::InstructionKind kind = instruction->GetInstrKind(); - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); Register out = OutputRegister(instruction); Register left; if (kind != HInstruction::kNeg) { @@ -2730,7 +2736,7 @@ void InstructionCodeGeneratorARM64::VisitMultiplyAccumulate(HMultiplyAccumulate* // Avoid emitting code that could trigger Cortex A53's erratum 835769. // This fixup should be carried out for all multiply-accumulate instructions: // madd, msub, smaddl, smsubl, umaddl and umsubl. - if (instr->GetType() == Primitive::kPrimLong && + if (instr->GetType() == DataType::Type::kInt64 && codegen_->GetInstructionSetFeatures().NeedFixCortexA53_835769()) { MacroAssembler* masm = down_cast<CodeGeneratorARM64*>(codegen_)->GetVIXLAssembler(); vixl::aarch64::Instruction* prev = @@ -2759,7 +2765,7 @@ void InstructionCodeGeneratorARM64::VisitMultiplyAccumulate(HMultiplyAccumulate* void LocationsBuilderARM64::VisitArrayGet(HArrayGet* instruction) { bool object_array_get_with_read_barrier = - kEmitCompilerReadBarrier && (instruction->GetType() == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (instruction->GetType() == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, object_array_get_with_read_barrier ? @@ -2777,7 +2783,7 @@ void LocationsBuilderARM64::VisitArrayGet(HArrayGet* instruction) { // constant index loads we need a temporary only if the offset is too big. uint32_t offset = CodeGenerator::GetArrayDataOffset(instruction); uint32_t index = instruction->GetIndex()->AsIntConstant()->GetValue(); - offset += index << Primitive::ComponentSizeShift(Primitive::kPrimNot); + offset += index << DataType::SizeShift(DataType::Type::kReference); if (offset >= kReferenceLoadMinFarOffset) { locations->AddTemp(FixedTempLocation()); } @@ -2787,7 +2793,7 @@ void LocationsBuilderARM64::VisitArrayGet(HArrayGet* instruction) { } locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - if (Primitive::IsFloatingPointType(instruction->GetType())) { + if (DataType::IsFloatingPointType(instruction->GetType())) { locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); } else { // The output overlaps in the case of an object array get with @@ -2800,7 +2806,7 @@ void LocationsBuilderARM64::VisitArrayGet(HArrayGet* instruction) { } void InstructionCodeGeneratorARM64::VisitArrayGet(HArrayGet* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); Register obj = InputRegisterAt(instruction, 0); LocationSummary* locations = instruction->GetLocations(); Location index = locations->InAt(1); @@ -2813,18 +2819,18 @@ void InstructionCodeGeneratorARM64::VisitArrayGet(HArrayGet* instruction) { // The read barrier instrumentation of object ArrayGet instructions // does not support the HIntermediateAddress instruction. - DCHECK(!((type == Primitive::kPrimNot) && + DCHECK(!((type == DataType::Type::kReference) && instruction->GetArray()->IsIntermediateAddress() && kEmitCompilerReadBarrier)); - if (type == Primitive::kPrimNot && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { + if (type == DataType::Type::kReference && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { // Object ArrayGet with Baker's read barrier case. // Note that a potential implicit null check is handled in the // CodeGeneratorARM64::GenerateArrayLoadWithBakerReadBarrier call. DCHECK(!instruction->CanDoImplicitNullCheckOn(instruction->InputAt(0))); if (index.IsConstant()) { // Array load with a constant index can be treated as a field load. - offset += Int64ConstantFrom(index) << Primitive::ComponentSizeShift(type); + offset += Int64ConstantFrom(index) << DataType::SizeShift(type); Location maybe_temp = (locations->GetTempCount() != 0) ? locations->GetTemp(0) : Location::NoLocation(); codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction, @@ -2876,7 +2882,7 @@ void InstructionCodeGeneratorARM64::VisitArrayGet(HArrayGet* instruction) { HeapOperand(obj, offset + (Int64ConstantFrom(index) << 1))); __ Bind(&done); } else { - offset += Int64ConstantFrom(index) << Primitive::ComponentSizeShift(type); + offset += Int64ConstantFrom(index) << DataType::SizeShift(type); source = HeapOperand(obj, offset); } } else { @@ -2906,7 +2912,7 @@ void InstructionCodeGeneratorARM64::VisitArrayGet(HArrayGet* instruction) { HeapOperand(temp, XRegisterFrom(index), LSL, 1)); __ Bind(&done); } else { - source = HeapOperand(temp, XRegisterFrom(index), LSL, Primitive::ComponentSizeShift(type)); + source = HeapOperand(temp, XRegisterFrom(index), LSL, DataType::SizeShift(type)); } } if (!maybe_compressed_char_at) { @@ -2916,7 +2922,7 @@ void InstructionCodeGeneratorARM64::VisitArrayGet(HArrayGet* instruction) { codegen_->MaybeRecordImplicitNullCheck(instruction); } - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { static_assert( sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t), "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes."); @@ -2952,7 +2958,7 @@ void InstructionCodeGeneratorARM64::VisitArrayLength(HArrayLength* instruction) } void LocationsBuilderARM64::VisitArraySet(HArraySet* instruction) { - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck(); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary( @@ -2964,7 +2970,7 @@ void LocationsBuilderARM64::VisitArraySet(HArraySet* instruction) { locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); if (IsConstantZeroBitPattern(instruction->InputAt(2))) { locations->SetInAt(2, Location::ConstantLocation(instruction->InputAt(2)->AsConstant())); - } else if (Primitive::IsFloatingPointType(value_type)) { + } else if (DataType::IsFloatingPointType(value_type)) { locations->SetInAt(2, Location::RequiresFpuRegister()); } else { locations->SetInAt(2, Location::RequiresRegister()); @@ -2972,7 +2978,7 @@ void LocationsBuilderARM64::VisitArraySet(HArraySet* instruction) { } void InstructionCodeGeneratorARM64::VisitArraySet(HArraySet* instruction) { - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); LocationSummary* locations = instruction->GetLocations(); bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck(); bool needs_write_barrier = @@ -2982,14 +2988,14 @@ void InstructionCodeGeneratorARM64::VisitArraySet(HArraySet* instruction) { CPURegister value = InputCPURegisterOrZeroRegAt(instruction, 2); CPURegister source = value; Location index = locations->InAt(1); - size_t offset = mirror::Array::DataOffset(Primitive::ComponentSize(value_type)).Uint32Value(); + size_t offset = mirror::Array::DataOffset(DataType::Size(value_type)).Uint32Value(); MemOperand destination = HeapOperand(array); MacroAssembler* masm = GetVIXLAssembler(); if (!needs_write_barrier) { DCHECK(!may_need_runtime_call_for_type_check); if (index.IsConstant()) { - offset += Int64ConstantFrom(index) << Primitive::ComponentSizeShift(value_type); + offset += Int64ConstantFrom(index) << DataType::SizeShift(value_type); destination = HeapOperand(array, offset); } else { UseScratchRegisterScope temps(masm); @@ -3009,7 +3015,7 @@ void InstructionCodeGeneratorARM64::VisitArraySet(HArraySet* instruction) { destination = HeapOperand(temp, XRegisterFrom(index), LSL, - Primitive::ComponentSizeShift(value_type)); + DataType::SizeShift(value_type)); } { // Ensure that between store and MaybeRecordImplicitNullCheck there are no pools emitted. @@ -3027,13 +3033,13 @@ void InstructionCodeGeneratorARM64::VisitArraySet(HArraySet* instruction) { UseScratchRegisterScope temps(masm); Register temp = temps.AcquireSameSizeAs(array); if (index.IsConstant()) { - offset += Int64ConstantFrom(index) << Primitive::ComponentSizeShift(value_type); + offset += Int64ConstantFrom(index) << DataType::SizeShift(value_type); destination = HeapOperand(array, offset); } else { destination = HeapOperand(temp, XRegisterFrom(index), LSL, - Primitive::ComponentSizeShift(value_type)); + DataType::SizeShift(value_type)); } uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); @@ -3213,21 +3219,21 @@ void InstructionCodeGeneratorARM64::GenerateFcmp(HInstruction* instruction) { void LocationsBuilderARM64::VisitCompare(HCompare* compare) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall); - Primitive::Type in_type = compare->InputAt(0)->GetType(); + DataType::Type in_type = compare->InputAt(0)->GetType(); switch (in_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, ARM64EncodableConstantOrRegister(compare->InputAt(1), compare)); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, IsFloatingPointZeroConstant(compare->InputAt(1)) @@ -3242,18 +3248,18 @@ void LocationsBuilderARM64::VisitCompare(HCompare* compare) { } void InstructionCodeGeneratorARM64::VisitCompare(HCompare* compare) { - Primitive::Type in_type = compare->InputAt(0)->GetType(); + DataType::Type in_type = compare->InputAt(0)->GetType(); // 0 if: left == right // 1 if: left > right // -1 if: left < right switch (in_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: { Register result = OutputRegister(compare); Register left = InputRegisterAt(compare, 0); Operand right = InputOperandAt(compare, 1); @@ -3262,8 +3268,8 @@ void InstructionCodeGeneratorARM64::VisitCompare(HCompare* compare) { __ Cneg(result, result, lt); // result == -1 if LT or unchanged otherwise break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { Register result = OutputRegister(compare); GenerateFcmp(compare); __ Cset(result, ne); @@ -3278,7 +3284,7 @@ void InstructionCodeGeneratorARM64::VisitCompare(HCompare* compare) { void LocationsBuilderARM64::HandleCondition(HCondition* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); - if (Primitive::IsFloatingPointType(instruction->InputAt(0)->GetType())) { + if (DataType::IsFloatingPointType(instruction->InputAt(0)->GetType())) { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, IsFloatingPointZeroConstant(instruction->InputAt(1)) @@ -3304,7 +3310,7 @@ void InstructionCodeGeneratorARM64::HandleCondition(HCondition* instruction) { Register res = RegisterFrom(locations->Out(), instruction->GetType()); IfCondition if_cond = instruction->GetCondition(); - if (Primitive::IsFloatingPointType(instruction->InputAt(0)->GetType())) { + if (DataType::IsFloatingPointType(instruction->InputAt(0)->GetType())) { GenerateFcmp(instruction); __ Cset(res, ARM64FPCondition(if_cond, instruction->IsGtBias())); } else { @@ -3383,7 +3389,7 @@ void InstructionCodeGeneratorARM64::DivRemByPowerOfTwo(HBinaryOperation* instruc __ Neg(out, Operand(out, ASR, ctz_imm)); } } else { - int bits = instruction->GetResultType() == Primitive::kPrimInt ? 32 : 64; + int bits = instruction->GetResultType() == DataType::Type::kInt32 ? 32 : 64; __ Asr(temp, dividend, bits - 1); __ Lsr(temp, temp, bits - ctz_imm); __ Add(out, dividend, temp); @@ -3403,19 +3409,20 @@ void InstructionCodeGeneratorARM64::GenerateDivRemWithAnyConstant(HBinaryOperati Register dividend = InputRegisterAt(instruction, 0); int64_t imm = Int64FromConstant(second.GetConstant()); - Primitive::Type type = instruction->GetResultType(); - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DataType::Type type = instruction->GetResultType(); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); int64_t magic; int shift; - CalculateMagicAndShiftForDivRem(imm, type == Primitive::kPrimLong /* is_long */, &magic, &shift); + CalculateMagicAndShiftForDivRem( + imm, type == DataType::Type::kInt64 /* is_long */, &magic, &shift); UseScratchRegisterScope temps(GetVIXLAssembler()); Register temp = temps.AcquireSameSizeAs(out); // temp = get_high(dividend * magic) __ Mov(temp, magic); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { __ Smulh(temp, dividend, temp); } else { __ Smull(temp.X(), dividend, temp); @@ -3433,9 +3440,9 @@ void InstructionCodeGeneratorARM64::GenerateDivRemWithAnyConstant(HBinaryOperati } if (instruction->IsDiv()) { - __ Sub(out, temp, Operand(temp, ASR, type == Primitive::kPrimLong ? 63 : 31)); + __ Sub(out, temp, Operand(temp, ASR, type == DataType::Type::kInt64 ? 63 : 31)); } else { - __ Sub(temp, temp, Operand(temp, ASR, type == Primitive::kPrimLong ? 63 : 31)); + __ Sub(temp, temp, Operand(temp, ASR, type == DataType::Type::kInt64 ? 63 : 31)); // TODO: Strength reduction for msub. Register temp_imm = temps.AcquireSameSizeAs(out); __ Mov(temp_imm, imm); @@ -3445,8 +3452,8 @@ void InstructionCodeGeneratorARM64::GenerateDivRemWithAnyConstant(HBinaryOperati void InstructionCodeGeneratorARM64::GenerateDivRemIntegral(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - Primitive::Type type = instruction->GetResultType(); - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DataType::Type type = instruction->GetResultType(); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); LocationSummary* locations = instruction->GetLocations(); Register out = OutputRegister(instruction); @@ -3483,15 +3490,15 @@ void LocationsBuilderARM64::VisitDiv(HDiv* div) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall); switch (div->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(div->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -3503,15 +3510,15 @@ void LocationsBuilderARM64::VisitDiv(HDiv* div) { } void InstructionCodeGeneratorARM64::VisitDiv(HDiv* div) { - Primitive::Type type = div->GetResultType(); + DataType::Type type = div->GetResultType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: GenerateDivRemIntegral(div); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ Fdiv(OutputFPRegister(div), InputFPRegisterAt(div, 0), InputFPRegisterAt(div, 1)); break; @@ -3531,9 +3538,9 @@ void InstructionCodeGeneratorARM64::VisitDivZeroCheck(HDivZeroCheck* instruction codegen_->AddSlowPath(slow_path); Location value = instruction->GetLocations()->InAt(0); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); - if (!Primitive::IsIntegralType(type)) { + if (!DataType::IsIntegralType(type)) { LOG(FATAL) << "Unexpected type " << type << " for DivZeroCheck."; return; } @@ -3664,8 +3671,8 @@ void InstructionCodeGeneratorARM64::GenerateTestAndBranch(HInstruction* instruct // the comparison and its condition as the branch condition. HCondition* condition = cond->AsCondition(); - Primitive::Type type = condition->InputAt(0)->GetType(); - if (Primitive::IsFloatingPointType(type)) { + DataType::Type type = condition->InputAt(0)->GetType(); + if (DataType::IsFloatingPointType(type)) { GenerateFcmp(condition); if (true_target == nullptr) { IfCondition opposite_condition = condition->GetOppositeCondition(); @@ -3779,7 +3786,7 @@ void InstructionCodeGeneratorARM64::VisitShouldDeoptimizeFlag(HShouldDeoptimizeF static inline bool IsConditionOnFloatingPointValues(HInstruction* condition) { return condition->IsCondition() && - Primitive::IsFloatingPointType(condition->InputAt(0)->GetType()); + DataType::IsFloatingPointType(condition->InputAt(0)->GetType()); } static inline Condition GetConditionForSelect(HCondition* condition) { @@ -3790,7 +3797,7 @@ static inline Condition GetConditionForSelect(HCondition* condition) { void LocationsBuilderARM64::VisitSelect(HSelect* select) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(select); - if (Primitive::IsFloatingPointType(select->GetType())) { + if (DataType::IsFloatingPointType(select->GetType())) { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -3844,7 +3851,7 @@ void InstructionCodeGeneratorARM64::VisitSelect(HSelect* select) { csel_cond = GetConditionForSelect(cond->AsCondition()); } - if (Primitive::IsFloatingPointType(select->GetType())) { + if (DataType::IsFloatingPointType(select->GetType())) { __ Fcsel(OutputFPRegister(select), InputFPRegisterAt(select, 1), InputFPRegisterAt(select, 0), @@ -4754,10 +4761,10 @@ void CodeGeneratorARM64::EmitLdrOffsetPlaceholder(vixl::aarch64::Label* fixup_la __ ldr(out, MemOperand(base, /* offset placeholder */ 0)); } -template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> +template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> inline void CodeGeneratorARM64::EmitPcRelativeLinkerPatches( const ArenaDeque<PcRelativePatchInfo>& infos, - ArenaVector<LinkerPatch>* linker_patches) { + ArenaVector<linker::LinkerPatch>* linker_patches) { for (const PcRelativePatchInfo& info : infos) { linker_patches->push_back(Factory(info.label.GetLocation(), &info.target_dex_file, @@ -4766,7 +4773,7 @@ inline void CodeGeneratorARM64::EmitPcRelativeLinkerPatches( } } -void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) { +void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) { DCHECK(linker_patches->empty()); size_t size = pc_relative_method_patches_.size() + @@ -4778,28 +4785,28 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patc baker_read_barrier_patches_.size(); linker_patches->reserve(size); if (GetCompilerOptions().IsBootImage()) { - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(pc_relative_method_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeTypePatch>(pc_relative_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeStringPatch>(pc_relative_string_patches_, - linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>( + pc_relative_method_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>( + pc_relative_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>( + pc_relative_string_patches_, linker_patches); } else { DCHECK(pc_relative_method_patches_.empty()); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(pc_relative_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(pc_relative_string_patches_, - linker_patches); - } - EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(string_bss_entry_patches_, - linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>( + pc_relative_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>( + pc_relative_string_patches_, linker_patches); + } + EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( + method_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>( + type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>( + string_bss_entry_patches_, linker_patches); for (const BakerReadBarrierPatchInfo& info : baker_read_barrier_patches_) { - linker_patches->push_back(LinkerPatch::BakerReadBarrierBranchPatch(info.label.GetLocation(), - info.custom_data)); + linker_patches->push_back(linker::LinkerPatch::BakerReadBarrierBranchPatch( + info.label.GetLocation(), info.custom_data)); } DCHECK_EQ(size, linker_patches->size()); } @@ -4912,8 +4919,8 @@ void LocationsBuilderARM64::VisitLoadClass(HLoadClass* cls) { InvokeRuntimeCallingConvention calling_convention; caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0).GetCode())); DCHECK_EQ(calling_convention.GetRegisterAt(0).GetCode(), - RegisterFrom(calling_convention.GetReturnLocation(Primitive::kPrimNot), - Primitive::kPrimNot).GetCode()); + RegisterFrom(calling_convention.GetReturnLocation(DataType::Type::kReference), + DataType::Type::kReference).GetCode()); locations->SetCustomSlowPathCallerSaves(caller_saves); } else { // For non-Baker read barrier we have a temp-clobbering call. @@ -5107,8 +5114,8 @@ void LocationsBuilderARM64::VisitLoadString(HLoadString* load) { InvokeRuntimeCallingConvention calling_convention; caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0).GetCode())); DCHECK_EQ(calling_convention.GetRegisterAt(0).GetCode(), - RegisterFrom(calling_convention.GetReturnLocation(Primitive::kPrimNot), - Primitive::kPrimNot).GetCode()); + RegisterFrom(calling_convention.GetReturnLocation(DataType::Type::kReference), + DataType::Type::kReference).GetCode()); locations->SetCustomSlowPathCallerSaves(caller_saves); } else { // For non-Baker read barrier we have a temp-clobbering call. @@ -5240,15 +5247,15 @@ void LocationsBuilderARM64::VisitMul(HMul* mul) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(mul, LocationSummary::kNoCall); switch (mul->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -5261,13 +5268,13 @@ void LocationsBuilderARM64::VisitMul(HMul* mul) { void InstructionCodeGeneratorARM64::VisitMul(HMul* mul) { switch (mul->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: __ Mul(OutputRegister(mul), InputRegisterAt(mul, 0), InputRegisterAt(mul, 1)); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ Fmul(OutputFPRegister(mul), InputFPRegisterAt(mul, 0), InputFPRegisterAt(mul, 1)); break; @@ -5280,14 +5287,14 @@ void LocationsBuilderARM64::VisitNeg(HNeg* neg) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); switch (neg->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, ARM64EncodableConstantOrRegister(neg->InputAt(0), neg)); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); break; @@ -5299,13 +5306,13 @@ void LocationsBuilderARM64::VisitNeg(HNeg* neg) { void InstructionCodeGeneratorARM64::VisitNeg(HNeg* neg) { switch (neg->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: __ Neg(OutputRegister(neg), InputOperandAt(neg, 0)); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ Fneg(OutputFPRegister(neg), InputFPRegisterAt(neg, 0)); break; @@ -5342,7 +5349,7 @@ void LocationsBuilderARM64::VisitNewInstance(HNewInstance* instruction) { } else { locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0))); } - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference)); } void InstructionCodeGeneratorARM64::VisitNewInstance(HNewInstance* instruction) { @@ -5378,8 +5385,8 @@ void LocationsBuilderARM64::VisitNot(HNot* instruction) { void InstructionCodeGeneratorARM64::VisitNot(HNot* instruction) { switch (instruction->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: __ Mvn(OutputRegister(instruction), InputOperandAt(instruction, 0)); break; @@ -5486,22 +5493,22 @@ void InstructionCodeGeneratorARM64::VisitPhi(HPhi* instruction ATTRIBUTE_UNUSED) } void LocationsBuilderARM64::VisitRem(HRem* rem) { - Primitive::Type type = rem->GetResultType(); + DataType::Type type = rem->GetResultType(); LocationSummary::CallKind call_kind = - Primitive::IsFloatingPointType(type) ? LocationSummary::kCallOnMainOnly + DataType::IsFloatingPointType(type) ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall; LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(rem->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, LocationFrom(calling_convention.GetFpuRegisterAt(0))); locations->SetInAt(1, LocationFrom(calling_convention.GetFpuRegisterAt(1))); @@ -5516,20 +5523,21 @@ void LocationsBuilderARM64::VisitRem(HRem* rem) { } void InstructionCodeGeneratorARM64::VisitRem(HRem* rem) { - Primitive::Type type = rem->GetResultType(); + DataType::Type type = rem->GetResultType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GenerateDivRemIntegral(rem); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { - QuickEntrypointEnum entrypoint = (type == Primitive::kPrimFloat) ? kQuickFmodf : kQuickFmod; + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { + QuickEntrypointEnum entrypoint = + (type == DataType::Type::kFloat32) ? kQuickFmodf : kQuickFmod; codegen_->InvokeRuntime(entrypoint, rem, rem->GetDexPc()); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { CheckEntrypointTypes<kQuickFmodf, float, float, float>(); } else { CheckEntrypointTypes<kQuickFmod, double, double, double>(); @@ -5562,7 +5570,7 @@ void InstructionCodeGeneratorARM64::VisitMemoryBarrier(HMemoryBarrier* memory_ba void LocationsBuilderARM64::VisitReturn(HReturn* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); - Primitive::Type return_type = instruction->InputAt(0)->GetType(); + DataType::Type return_type = instruction->InputAt(0)->GetType(); locations->SetInAt(0, ARM64ReturnLocation(return_type)); } @@ -5734,21 +5742,21 @@ void InstructionCodeGeneratorARM64::VisitThrow(HThrow* instruction) { void LocationsBuilderARM64::VisitTypeConversion(HTypeConversion* conversion) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(conversion, LocationSummary::kNoCall); - Primitive::Type input_type = conversion->GetInputType(); - Primitive::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); DCHECK_NE(input_type, result_type); - if ((input_type == Primitive::kPrimNot) || (input_type == Primitive::kPrimVoid) || - (result_type == Primitive::kPrimNot) || (result_type == Primitive::kPrimVoid)) { + if ((input_type == DataType::Type::kReference) || (input_type == DataType::Type::kVoid) || + (result_type == DataType::Type::kReference) || (result_type == DataType::Type::kVoid)) { LOG(FATAL) << "Unexpected type conversion from " << input_type << " to " << result_type; } - if (Primitive::IsFloatingPointType(input_type)) { + if (DataType::IsFloatingPointType(input_type)) { locations->SetInAt(0, Location::RequiresFpuRegister()); } else { locations->SetInAt(0, Location::RequiresRegister()); } - if (Primitive::IsFloatingPointType(result_type)) { + if (DataType::IsFloatingPointType(result_type)) { locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); } else { locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -5756,18 +5764,18 @@ void LocationsBuilderARM64::VisitTypeConversion(HTypeConversion* conversion) { } void InstructionCodeGeneratorARM64::VisitTypeConversion(HTypeConversion* conversion) { - Primitive::Type result_type = conversion->GetResultType(); - Primitive::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); DCHECK_NE(input_type, result_type); - if (Primitive::IsIntegralType(result_type) && Primitive::IsIntegralType(input_type)) { - int result_size = Primitive::ComponentSize(result_type); - int input_size = Primitive::ComponentSize(input_type); + if (DataType::IsIntegralType(result_type) && DataType::IsIntegralType(input_type)) { + int result_size = DataType::Size(result_type); + int input_size = DataType::Size(input_type); int min_size = std::min(result_size, input_size); Register output = OutputRegister(conversion); Register source = InputRegisterAt(conversion, 0); - if (result_type == Primitive::kPrimInt && input_type == Primitive::kPrimLong) { + if (result_type == DataType::Type::kInt32 && input_type == DataType::Type::kInt64) { // 'int' values are used directly as W registers, discarding the top // bits, so we don't need to sign-extend and can just perform a move. // We do not pass the `kDiscardForSameWReg` argument to force clearing the @@ -5776,21 +5784,21 @@ void InstructionCodeGeneratorARM64::VisitTypeConversion(HTypeConversion* convers // 32bit input value as a 64bit value assuming that the top 32 bits are // zero. __ Mov(output.W(), source.W()); - } else if (result_type == Primitive::kPrimChar || - (input_type == Primitive::kPrimChar && input_size < result_size)) { + } else if (result_type == DataType::Type::kUint16 || + (input_type == DataType::Type::kUint16 && input_size < result_size)) { __ Ubfx(output, output.IsX() ? source.X() : source.W(), - 0, Primitive::ComponentSize(Primitive::kPrimChar) * kBitsPerByte); + 0, DataType::Size(DataType::Type::kUint16) * kBitsPerByte); } else { __ Sbfx(output, output.IsX() ? source.X() : source.W(), 0, min_size * kBitsPerByte); } - } else if (Primitive::IsFloatingPointType(result_type) && Primitive::IsIntegralType(input_type)) { + } else if (DataType::IsFloatingPointType(result_type) && DataType::IsIntegralType(input_type)) { __ Scvtf(OutputFPRegister(conversion), InputRegisterAt(conversion, 0)); - } else if (Primitive::IsIntegralType(result_type) && Primitive::IsFloatingPointType(input_type)) { - CHECK(result_type == Primitive::kPrimInt || result_type == Primitive::kPrimLong); + } else if (DataType::IsIntegralType(result_type) && DataType::IsFloatingPointType(input_type)) { + CHECK(result_type == DataType::Type::kInt32 || result_type == DataType::Type::kInt64); __ Fcvtzs(OutputRegister(conversion), InputFPRegisterAt(conversion, 0)); - } else if (Primitive::IsFloatingPointType(result_type) && - Primitive::IsFloatingPointType(input_type)) { + } else if (DataType::IsFloatingPointType(result_type) && + DataType::IsFloatingPointType(input_type)) { __ Fcvt(OutputFPRegister(conversion), InputFPRegisterAt(conversion, 0)); } else { LOG(FATAL) << "Unexpected or unimplemented type conversion from " << input_type @@ -5917,7 +5925,7 @@ void InstructionCodeGeneratorARM64::GenerateReferenceLoadOneRegister( uint32_t offset, Location maybe_temp, ReadBarrierOption read_barrier_option) { - Primitive::Type type = Primitive::kPrimNot; + DataType::Type type = DataType::Type::kReference; Register out_reg = RegisterFrom(out, type); if (read_barrier_option == kWithReadBarrier) { CHECK(kEmitCompilerReadBarrier); @@ -5957,7 +5965,7 @@ void InstructionCodeGeneratorARM64::GenerateReferenceLoadTwoRegisters( uint32_t offset, Location maybe_temp, ReadBarrierOption read_barrier_option) { - Primitive::Type type = Primitive::kPrimNot; + DataType::Type type = DataType::Type::kReference; Register out_reg = RegisterFrom(out, type); Register obj_reg = RegisterFrom(obj, type); if (read_barrier_option == kWithReadBarrier) { @@ -5994,7 +6002,7 @@ void InstructionCodeGeneratorARM64::GenerateGcRootFieldLoad( vixl::aarch64::Label* fixup_label, ReadBarrierOption read_barrier_option) { DCHECK(fixup_label == nullptr || offset == 0u); - Register root_reg = RegisterFrom(root, Primitive::kPrimNot); + Register root_reg = RegisterFrom(root, DataType::Type::kReference); if (read_barrier_option == kWithReadBarrier) { DCHECK(kEmitCompilerReadBarrier); if (kUseBakerReadBarrier) { @@ -6158,7 +6166,7 @@ void CodeGeneratorARM64::GenerateFieldLoadWithBakerReadBarrier(HInstruction* ins static_assert(BAKER_MARK_INTROSPECTION_FIELD_LDR_OFFSET == (kPoisonHeapReferences ? -8 : -4), "Field LDR must be 1 instruction (4B) before the return address label; " " 2 instructions (8B) for heap poisoning."); - Register ref_reg = RegisterFrom(ref, Primitive::kPrimNot); + Register ref_reg = RegisterFrom(ref, DataType::Type::kReference); __ ldr(ref_reg, MemOperand(base.X(), offset)); if (needs_null_check) { MaybeRecordImplicitNullCheck(instruction); @@ -6198,7 +6206,7 @@ void CodeGeneratorARM64::GenerateArrayLoadWithBakerReadBarrier(HInstruction* ins static_assert( sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t), "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes."); - size_t scale_factor = Primitive::ComponentSizeShift(Primitive::kPrimNot); + size_t scale_factor = DataType::SizeShift(DataType::Type::kReference); if (kBakerReadBarrierLinkTimeThunksEnableForArrays && !Runtime::Current()->UseJitCompilation()) { @@ -6223,8 +6231,8 @@ void CodeGeneratorARM64::GenerateArrayLoadWithBakerReadBarrier(HInstruction* ins // gray_return_address: DCHECK(index.IsValid()); - Register index_reg = RegisterFrom(index, Primitive::kPrimInt); - Register ref_reg = RegisterFrom(ref, Primitive::kPrimNot); + Register index_reg = RegisterFrom(index, DataType::Type::kInt32); + Register ref_reg = RegisterFrom(ref, DataType::Type::kReference); UseScratchRegisterScope temps(GetVIXLAssembler()); DCHECK(temps.IsAvailable(ip0)); @@ -6396,7 +6404,7 @@ void CodeGeneratorARM64::GenerateRawReferenceLoad(HInstruction* instruction, bool needs_null_check, bool use_load_acquire) { DCHECK(obj.IsW()); - Primitive::Type type = Primitive::kPrimNot; + DataType::Type type = DataType::Type::kReference; Register ref_reg = RegisterFrom(ref, type); // If needed, vixl::EmissionCheckScope guards are used to ensure diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h index 69c511907e..21da9557e5 100644 --- a/compiler/optimizing/code_generator_arm64.h +++ b/compiler/optimizing/code_generator_arm64.h @@ -100,7 +100,7 @@ const vixl::aarch64::CPURegList callee_saved_fp_registers(vixl::aarch64::CPURegi vixl::aarch64::kDRegSize, vixl::aarch64::d8.GetCode(), vixl::aarch64::d15.GetCode()); -Location ARM64ReturnLocation(Primitive::Type return_type); +Location ARM64ReturnLocation(DataType::Type return_type); class SlowPathCodeARM64 : public SlowPathCode { public: @@ -171,7 +171,7 @@ class InvokeRuntimeCallingConvention : public CallingConvention<vixl::aarch64::R kRuntimeParameterFpuRegistersLength, kArm64PointerSize) {} - Location GetReturnLocation(Primitive::Type return_type); + Location GetReturnLocation(DataType::Type return_type); private: DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); @@ -187,7 +187,7 @@ class InvokeDexCallingConvention : public CallingConvention<vixl::aarch64::Regis kParameterFPRegistersLength, kArm64PointerSize) {} - Location GetReturnLocation(Primitive::Type return_type) const { + Location GetReturnLocation(DataType::Type return_type) const { return ARM64ReturnLocation(return_type); } @@ -201,8 +201,8 @@ class InvokeDexCallingConventionVisitorARM64 : public InvokeDexCallingConvention InvokeDexCallingConventionVisitorARM64() {} virtual ~InvokeDexCallingConventionVisitorARM64() {} - Location GetNextLocation(Primitive::Type type) OVERRIDE; - Location GetReturnLocation(Primitive::Type return_type) const OVERRIDE { + Location GetNextLocation(DataType::Type type) OVERRIDE; + Location GetReturnLocation(DataType::Type return_type) const OVERRIDE { return calling_convention.GetReturnLocation(return_type); } Location GetMethodLocation() const OVERRIDE; @@ -223,16 +223,16 @@ class FieldAccessCallingConventionARM64 : public FieldAccessCallingConvention { Location GetFieldIndexLocation() const OVERRIDE { return helpers::LocationFrom(vixl::aarch64::x0); } - Location GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { + Location GetReturnLocation(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return helpers::LocationFrom(vixl::aarch64::x0); } - Location GetSetValueLocation(Primitive::Type type ATTRIBUTE_UNUSED, + Location GetSetValueLocation(DataType::Type type ATTRIBUTE_UNUSED, bool is_instance) const OVERRIDE { return is_instance ? helpers::LocationFrom(vixl::aarch64::x2) : helpers::LocationFrom(vixl::aarch64::x1); } - Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { + Location GetFpuLocation(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return helpers::LocationFrom(vixl::aarch64::d0); } @@ -498,13 +498,13 @@ class CodeGeneratorARM64 : public CodeGenerator { // Code generation helpers. void MoveConstant(vixl::aarch64::CPURegister destination, HConstant* constant); void MoveConstant(Location destination, int32_t value) OVERRIDE; - void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; + void MoveLocation(Location dst, Location src, DataType::Type dst_type) OVERRIDE; void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; - void Load(Primitive::Type type, + void Load(DataType::Type type, vixl::aarch64::CPURegister dst, const vixl::aarch64::MemOperand& src); - void Store(Primitive::Type type, + void Store(DataType::Type type, vixl::aarch64::CPURegister src, const vixl::aarch64::MemOperand& dst); void LoadAcquire(HInstruction* instruction, @@ -512,7 +512,7 @@ class CodeGeneratorARM64 : public CodeGenerator { const vixl::aarch64::MemOperand& src, bool needs_null_check); void StoreRelease(HInstruction* instruction, - Primitive::Type type, + DataType::Type type, vixl::aarch64::CPURegister src, const vixl::aarch64::MemOperand& dst, bool needs_null_check); @@ -531,7 +531,7 @@ class CodeGeneratorARM64 : public CodeGenerator { ParallelMoveResolverARM64* GetMoveResolver() OVERRIDE { return &move_resolver_; } - bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { + bool NeedsTwoRegisters(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return false; } @@ -557,7 +557,7 @@ class CodeGeneratorARM64 : public CodeGenerator { HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE; void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED, - Primitive::Type type ATTRIBUTE_UNUSED) OVERRIDE { + DataType::Type type ATTRIBUTE_UNUSED) OVERRIDE { UNIMPLEMENTED(FATAL); } @@ -627,7 +627,7 @@ class CodeGeneratorARM64 : public CodeGenerator { vixl::aarch64::Register out, vixl::aarch64::Register base); - void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; + void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) OVERRIDE; void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) OVERRIDE; @@ -805,9 +805,9 @@ class CodeGeneratorARM64 : public CodeGenerator { void EmitJumpTables(); - template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> + template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> static void EmitPcRelativeLinkerPatches(const ArenaDeque<PcRelativePatchInfo>& infos, - ArenaVector<LinkerPatch>* linker_patches); + ArenaVector<linker::LinkerPatch>* linker_patches); // Labels for each block that will be compiled. // We use a deque so that the `vixl::aarch64::Label` objects do not move in memory. diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index baf68c4e11..2b9e0febe8 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -30,6 +30,7 @@ #include "heap_poisoning.h" #include "intrinsics_arm_vixl.h" #include "linker/arm/relative_patcher_thumb2.h" +#include "linker/linker_patch.h" #include "mirror/array-inl.h" #include "mirror/class-inl.h" #include "thread.h" @@ -449,10 +450,10 @@ class BoundsCheckSlowPathARMVIXL : public SlowPathCodeARMVIXL { codegen->EmitParallelMoves( locations->InAt(0), LocationFrom(calling_convention.GetRegisterAt(0)), - Primitive::kPrimInt, + DataType::Type::kInt32, locations->InAt(1), LocationFrom(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt); + DataType::Type::kInt32); QuickEntrypointEnum entrypoint = instruction_->AsBoundsCheck()->IsStringCharAt() ? kQuickThrowStringBounds : kQuickThrowArrayBounds; @@ -640,10 +641,10 @@ class TypeCheckSlowPathARMVIXL : public SlowPathCodeARMVIXL { codegen->EmitParallelMoves(locations->InAt(0), LocationFrom(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, locations->InAt(1), LocationFrom(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot); + DataType::Type::kReference); if (instruction_->IsInstanceOf()) { arm_codegen->InvokeRuntime(kQuickInstanceofNonTrivial, instruction_, @@ -714,17 +715,17 @@ class ArraySetSlowPathARMVIXL : public SlowPathCodeARMVIXL { parallel_move.AddMove( locations->InAt(0), LocationFrom(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove( locations->InAt(1), LocationFrom(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); parallel_move.AddMove( locations->InAt(2), LocationFrom(calling_convention.GetRegisterAt(2)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); @@ -1364,16 +1365,16 @@ class ReadBarrierForHeapReferenceSlowPathARMVIXL : public SlowPathCodeARMVIXL { HParallelMove parallel_move(codegen->GetGraph()->GetArena()); parallel_move.AddMove(ref_, LocationFrom(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove(obj_, LocationFrom(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); if (index.IsValid()) { parallel_move.AddMove(index, LocationFrom(calling_convention.GetRegisterAt(2)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); } else { @@ -1640,7 +1641,7 @@ static Operand GetShifterOperand(vixl32::Register rm, ShiftType shift, uint32_t static void GenerateLongDataProc(HDataProcWithShifterOp* instruction, CodeGeneratorARMVIXL* codegen) { - DCHECK_EQ(instruction->GetType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64); DCHECK(HDataProcWithShifterOp::IsShiftOp(instruction->GetOpKind())); const LocationSummary* const locations = instruction->GetLocations(); @@ -1775,12 +1776,12 @@ static void GenerateVcmp(HInstruction* instruction, CodeGeneratorARMVIXL* codege // care here. DCHECK(rhs_loc.GetConstant()->IsArithmeticZero()); - const Primitive::Type type = instruction->InputAt(0)->GetType(); + const DataType::Type type = instruction->InputAt(0)->GetType(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ Vcmp(F32, InputSRegisterAt(instruction, 0), 0.0); } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); __ Vcmp(F64, InputDRegisterAt(instruction, 0), 0.0); } } else { @@ -1820,7 +1821,7 @@ static std::pair<vixl32::Condition, vixl32::Condition> GenerateLongTestConstant( HCondition* condition, bool invert, CodeGeneratorARMVIXL* codegen) { - DCHECK_EQ(condition->GetLeft()->GetType(), Primitive::kPrimLong); + DCHECK_EQ(condition->GetLeft()->GetType(), DataType::Type::kInt64); const LocationSummary* const locations = condition->GetLocations(); IfCondition cond = condition->GetCondition(); @@ -1941,7 +1942,7 @@ static std::pair<vixl32::Condition, vixl32::Condition> GenerateLongTest( HCondition* condition, bool invert, CodeGeneratorARMVIXL* codegen) { - DCHECK_EQ(condition->GetLeft()->GetType(), Primitive::kPrimLong); + DCHECK_EQ(condition->GetLeft()->GetType(), DataType::Type::kInt64); const LocationSummary* const locations = condition->GetLocations(); IfCondition cond = condition->GetCondition(); @@ -2011,7 +2012,7 @@ static std::pair<vixl32::Condition, vixl32::Condition> GenerateLongTest( static std::pair<vixl32::Condition, vixl32::Condition> GenerateTest(HCondition* condition, bool invert, CodeGeneratorARMVIXL* codegen) { - const Primitive::Type type = condition->GetLeft()->GetType(); + const DataType::Type type = condition->GetLeft()->GetType(); IfCondition cond = condition->GetCondition(); IfCondition opposite = condition->GetOppositeCondition(); std::pair<vixl32::Condition, vixl32::Condition> ret(eq, ne); @@ -2020,17 +2021,17 @@ static std::pair<vixl32::Condition, vixl32::Condition> GenerateTest(HCondition* std::swap(cond, opposite); } - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { ret = condition->GetLocations()->InAt(1).IsConstant() ? GenerateLongTestConstant(condition, invert, codegen) : GenerateLongTest(condition, invert, codegen); - } else if (Primitive::IsFloatingPointType(type)) { + } else if (DataType::IsFloatingPointType(type)) { GenerateVcmp(condition, codegen); __ Vmrs(RegisterOrAPSR_nzcv(kPcCode), FPSCR); ret = std::make_pair(ARMFPCondition(cond, condition->IsGtBias()), ARMFPCondition(opposite, condition->IsGtBias())); } else { - DCHECK(Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) << type; + DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type; __ Cmp(InputRegisterAt(condition, 0), InputOperandAt(condition, 1)); ret = std::make_pair(ARMCondition(cond), ARMCondition(opposite)); } @@ -2066,7 +2067,7 @@ static void GenerateConditionGeneric(HCondition* cond, CodeGeneratorARMVIXL* cod } static void GenerateEqualLong(HCondition* cond, CodeGeneratorARMVIXL* codegen) { - DCHECK_EQ(cond->GetLeft()->GetType(), Primitive::kPrimLong); + DCHECK_EQ(cond->GetLeft()->GetType(), DataType::Type::kInt64); const LocationSummary* const locations = cond->GetLocations(); IfCondition condition = cond->GetCondition(); @@ -2122,7 +2123,7 @@ static void GenerateEqualLong(HCondition* cond, CodeGeneratorARMVIXL* codegen) { } static void GenerateConditionLong(HCondition* cond, CodeGeneratorARMVIXL* codegen) { - DCHECK_EQ(cond->GetLeft()->GetType(), Primitive::kPrimLong); + DCHECK_EQ(cond->GetLeft()->GetType(), DataType::Type::kInt64); const LocationSummary* const locations = cond->GetLocations(); IfCondition condition = cond->GetCondition(); @@ -2187,11 +2188,11 @@ static void GenerateConditionLong(HCondition* cond, CodeGeneratorARMVIXL* codege static void GenerateConditionIntegralOrNonPrimitive(HCondition* cond, CodeGeneratorARMVIXL* codegen) { - const Primitive::Type type = cond->GetLeft()->GetType(); + const DataType::Type type = cond->GetLeft()->GetType(); - DCHECK(Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) << type; + DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type; - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { GenerateConditionLong(cond, codegen); return; } @@ -2277,12 +2278,12 @@ static void GenerateConditionIntegralOrNonPrimitive(HCondition* cond, } static bool CanEncodeConstantAs8BitImmediate(HConstant* constant) { - const Primitive::Type type = constant->GetType(); + const DataType::Type type = constant->GetType(); bool ret = false; - DCHECK(Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) << type; + DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type; - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { const uint64_t value = Uint64ConstantFrom(constant); ret = IsUint<8>(Low32Bits(value)) && IsUint<8>(High32Bits(value)); @@ -2294,7 +2295,7 @@ static bool CanEncodeConstantAs8BitImmediate(HConstant* constant) { } static Location Arm8BitEncodableConstantOrRegister(HInstruction* constant) { - DCHECK(!Primitive::IsFloatingPointType(constant->GetType())); + DCHECK(!DataType::IsFloatingPointType(constant->GetType())); if (constant->IsConstant() && CanEncodeConstantAs8BitImmediate(constant->AsConstant())) { return Location::ConstantLocation(constant->AsConstant()); @@ -2595,14 +2596,14 @@ void CodeGeneratorARMVIXL::Bind(HBasicBlock* block) { __ Bind(GetLabelOf(block)); } -Location InvokeDexCallingConventionVisitorARMVIXL::GetNextLocation(Primitive::Type type) { +Location InvokeDexCallingConventionVisitorARMVIXL::GetNextLocation(DataType::Type type) { switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: { uint32_t index = gp_index_++; uint32_t stack_index = stack_index_++; if (index < calling_convention.GetNumberOfRegisters()) { @@ -2612,7 +2613,7 @@ Location InvokeDexCallingConventionVisitorARMVIXL::GetNextLocation(Primitive::Ty } } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { uint32_t index = gp_index_; uint32_t stack_index = stack_index_; gp_index_ += 2; @@ -2635,7 +2636,7 @@ Location InvokeDexCallingConventionVisitorARMVIXL::GetNextLocation(Primitive::Ty } } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { uint32_t stack_index = stack_index_++; if (float_index_ % 2 == 0) { float_index_ = std::max(double_index_, float_index_); @@ -2647,7 +2648,7 @@ Location InvokeDexCallingConventionVisitorARMVIXL::GetNextLocation(Primitive::Ty } } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { double_index_ = std::max(double_index_, RoundUp(float_index_, 2)); uint32_t stack_index = stack_index_; stack_index_ += 2; @@ -2664,37 +2665,37 @@ Location InvokeDexCallingConventionVisitorARMVIXL::GetNextLocation(Primitive::Ty } } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unexpected parameter type " << type; break; } return Location::NoLocation(); } -Location InvokeDexCallingConventionVisitorARMVIXL::GetReturnLocation(Primitive::Type type) const { +Location InvokeDexCallingConventionVisitorARMVIXL::GetReturnLocation(DataType::Type type) const { switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: { return LocationFrom(r0); } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { return LocationFrom(s0); } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { return LocationFrom(r0, r1); } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { return LocationFrom(s0, s1); } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: return Location::NoLocation(); } @@ -2752,7 +2753,7 @@ void CodeGeneratorARMVIXL::MoveConstant(Location location, int32_t value) { __ Mov(RegisterFrom(location), value); } -void CodeGeneratorARMVIXL::MoveLocation(Location dst, Location src, Primitive::Type dst_type) { +void CodeGeneratorARMVIXL::MoveLocation(Location dst, Location src, DataType::Type dst_type) { // TODO(VIXL): Maybe refactor to have the 'move' implementation here and use it in // `ParallelMoveResolverARMVIXL::EmitMove`, as is done in the `arm64` backend. HParallelMove move(GetGraph()->GetArena()); @@ -2935,8 +2936,8 @@ void InstructionCodeGeneratorARMVIXL::GenerateTestAndBranch(HInstruction* instru // If this is a long or FP comparison that has been folded into // the HCondition, generate the comparison directly. - Primitive::Type type = condition->InputAt(0)->GetType(); - if (type == Primitive::kPrimLong || Primitive::IsFloatingPointType(type)) { + DataType::Type type = condition->InputAt(0)->GetType(); + if (type == DataType::Type::kInt64 || DataType::IsFloatingPointType(type)) { GenerateCompareTestAndBranch(condition, true_target, false_target, far_target); return; } @@ -3027,7 +3028,7 @@ void InstructionCodeGeneratorARMVIXL::VisitShouldDeoptimizeFlag(HShouldDeoptimiz void LocationsBuilderARMVIXL::VisitSelect(HSelect* select) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(select); - const bool is_floating_point = Primitive::IsFloatingPointType(select->GetType()); + const bool is_floating_point = DataType::IsFloatingPointType(select->GetType()); if (is_floating_point) { locations->SetInAt(0, Location::RequiresFpuRegister()); @@ -3055,7 +3056,7 @@ void LocationsBuilderARMVIXL::VisitSelect(HSelect* select) { void InstructionCodeGeneratorARMVIXL::VisitSelect(HSelect* select) { HInstruction* const condition = select->GetCondition(); const LocationSummary* const locations = select->GetLocations(); - const Primitive::Type type = select->GetType(); + const DataType::Type type = select->GetType(); const Location first = locations->InAt(0); const Location out = locations->Out(); const Location second = locations->InAt(1); @@ -3072,7 +3073,7 @@ void InstructionCodeGeneratorARMVIXL::VisitSelect(HSelect* select) { return; } - if (!Primitive::IsFloatingPointType(type)) { + if (!DataType::IsFloatingPointType(type)) { bool invert = false; if (out.Equals(second)) { @@ -3260,7 +3261,7 @@ void LocationsBuilderARMVIXL::HandleCondition(HCondition* cond) { new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall); // Handle the long/FP comparisons made in instruction simplification. switch (cond->InputAt(0)->GetType()) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(cond->InputAt(1))); if (!cond->IsEmittedAtUseSite()) { @@ -3268,8 +3269,8 @@ void LocationsBuilderARMVIXL::HandleCondition(HCondition* cond) { } break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, ArithmeticZeroOrFpuRegister(cond->InputAt(1))); if (!cond->IsEmittedAtUseSite()) { @@ -3291,22 +3292,22 @@ void InstructionCodeGeneratorARMVIXL::HandleCondition(HCondition* cond) { return; } - const Primitive::Type type = cond->GetLeft()->GetType(); + const DataType::Type type = cond->GetLeft()->GetType(); - if (Primitive::IsFloatingPointType(type)) { + if (DataType::IsFloatingPointType(type)) { GenerateConditionGeneric(cond, codegen_); return; } - DCHECK(Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) << type; + DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type; const IfCondition condition = cond->GetCondition(); // A condition with only one boolean input, or two boolean inputs without being equality or // inequality results from transformations done by the instruction simplifier, and is handled // as a regular condition with integral inputs. - if (type == Primitive::kPrimBoolean && - cond->GetRight()->GetType() == Primitive::kPrimBoolean && + if (type == DataType::Type::kBool && + cond->GetRight()->GetType() == DataType::Type::kBool && (condition == kCondEQ || condition == kCondNE)) { vixl32::Register left = InputRegisterAt(cond, 0); const vixl32::Register out = OutputRegister(cond); @@ -3669,19 +3670,19 @@ void LocationsBuilderARMVIXL::VisitNeg(HNeg* neg) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); switch (neg->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); break; @@ -3696,11 +3697,11 @@ void InstructionCodeGeneratorARMVIXL::VisitNeg(HNeg* neg) { Location out = locations->Out(); Location in = locations->InAt(0); switch (neg->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ Rsb(OutputRegister(neg), InputRegisterAt(neg, 0), 0); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // out.lo = 0 - in.lo (and update the carry/borrow (C) flag) __ Rsbs(LowRegisterFrom(out), LowRegisterFrom(in), 0); // We cannot emit an RSC (Reverse Subtract with Carry) @@ -3714,8 +3715,8 @@ void InstructionCodeGeneratorARMVIXL::VisitNeg(HNeg* neg) { __ Sub(HighRegisterFrom(out), HighRegisterFrom(out), HighRegisterFrom(in)); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ Vneg(OutputVRegister(neg), InputVRegister(neg)); break; @@ -3725,16 +3726,16 @@ void InstructionCodeGeneratorARMVIXL::VisitNeg(HNeg* neg) { } void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { - Primitive::Type result_type = conversion->GetResultType(); - Primitive::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); DCHECK_NE(result_type, input_type); // The float-to-long, double-to-long and long-to-float type conversions // rely on a call to the runtime. LocationSummary::CallKind call_kind = - (((input_type == Primitive::kPrimFloat || input_type == Primitive::kPrimDouble) - && result_type == Primitive::kPrimLong) - || (input_type == Primitive::kPrimLong && result_type == Primitive::kPrimFloat)) + (((input_type == DataType::Type::kFloat32 || input_type == DataType::Type::kFloat64) + && result_type == DataType::Type::kInt64) + || (input_type == DataType::Type::kInt64 && result_type == DataType::Type::kFloat32)) ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall; LocationSummary* locations = @@ -3744,15 +3745,15 @@ void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { // our bit representation makes it safe. switch (result_type) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to byte is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-byte' instruction. locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -3764,15 +3765,15 @@ void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to short is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-short' instruction. locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -3784,22 +3785,22 @@ void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-int' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-int' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); locations->AddTemp(Location::RequiresFpuRegister()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-int' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); @@ -3812,20 +3813,20 @@ void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-long' instruction. locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { // Processing a Dex `float-to-long' instruction. InvokeRuntimeCallingConventionARMVIXL calling_convention; locations->SetInAt(0, LocationFrom(calling_convention.GetFpuRegisterAt(0))); @@ -3833,7 +3834,7 @@ void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { // Processing a Dex `double-to-long' instruction. InvokeRuntimeCallingConventionARMVIXL calling_convention; locations->SetInAt(0, LocationFrom(calling_convention.GetFpuRegisterAt(0), @@ -3848,15 +3849,15 @@ void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to char is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: // Processing a Dex `int-to-char' instruction. locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -3868,20 +3869,20 @@ void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-float' instruction. locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { // Processing a Dex `long-to-float' instruction. InvokeRuntimeCallingConventionARMVIXL calling_convention; locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0), @@ -3890,7 +3891,7 @@ void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { break; } - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-float' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -3902,20 +3903,20 @@ void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { }; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-double' instruction. locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-double' instruction. locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); @@ -3923,7 +3924,7 @@ void LocationsBuilderARMVIXL::VisitTypeConversion(HTypeConversion* conversion) { locations->AddTemp(Location::RequiresFpuRegister()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-double' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -3945,21 +3946,21 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve LocationSummary* locations = conversion->GetLocations(); Location out = locations->Out(); Location in = locations->InAt(0); - Primitive::Type result_type = conversion->GetResultType(); - Primitive::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); DCHECK_NE(result_type, input_type); switch (result_type) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to byte is a result of code transformations. __ Sbfx(OutputRegister(conversion), LowRegisterFrom(in), 0, 8); break; - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-byte' instruction. __ Sbfx(OutputRegister(conversion), InputRegisterAt(conversion, 0), 0, 8); break; @@ -3970,17 +3971,17 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve } break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to short is a result of code transformations. __ Sbfx(OutputRegister(conversion), LowRegisterFrom(in), 0, 16); break; - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-short' instruction. __ Sbfx(OutputRegister(conversion), InputRegisterAt(conversion, 0), 0, 16); break; @@ -3991,9 +3992,9 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-int' instruction. DCHECK(out.IsRegister()); if (in.IsRegisterPair()) { @@ -4011,7 +4012,7 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve } break; - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { // Processing a Dex `float-to-int' instruction. vixl32::SRegister temp = LowSRegisterFrom(locations->GetTemp(0)); __ Vcvt(S32, F32, temp, InputSRegisterAt(conversion, 0)); @@ -4019,7 +4020,7 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { // Processing a Dex `double-to-int' instruction. vixl32::SRegister temp_s = LowSRegisterFrom(locations->GetTemp(0)); __ Vcvt(S32, F64, temp_s, DRegisterFrom(in)); @@ -4033,14 +4034,14 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-long' instruction. DCHECK(out.IsRegisterPair()); DCHECK(in.IsRegister()); @@ -4049,13 +4050,13 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve __ Asr(HighRegisterFrom(out), LowRegisterFrom(out), 31); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-long' instruction. codegen_->InvokeRuntime(kQuickF2l, conversion, conversion->GetDexPc()); CheckEntrypointTypes<kQuickF2l, int64_t, float>(); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-long' instruction. codegen_->InvokeRuntime(kQuickD2l, conversion, conversion->GetDexPc()); CheckEntrypointTypes<kQuickD2l, int64_t, double>(); @@ -4067,17 +4068,17 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve } break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to char is a result of code transformations. __ Ubfx(OutputRegister(conversion), LowRegisterFrom(in), 0, 16); break; - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: // Processing a Dex `int-to-char' instruction. __ Ubfx(OutputRegister(conversion), InputRegisterAt(conversion, 0), 0, 16); break; @@ -4088,27 +4089,27 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: { + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: { // Processing a Dex `int-to-float' instruction. __ Vmov(OutputSRegister(conversion), InputRegisterAt(conversion, 0)); __ Vcvt(F32, S32, OutputSRegister(conversion), OutputSRegister(conversion)); break; } - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-float' instruction. codegen_->InvokeRuntime(kQuickL2f, conversion, conversion->GetDexPc()); CheckEntrypointTypes<kQuickL2f, float, int64_t>(); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-float' instruction. __ Vcvt(F32, F64, OutputSRegister(conversion), DRegisterFrom(in)); break; @@ -4119,21 +4120,21 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve }; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: { + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: { // Processing a Dex `int-to-double' instruction. __ Vmov(LowSRegisterFrom(out), InputRegisterAt(conversion, 0)); __ Vcvt(F64, S32, DRegisterFrom(out), LowSRegisterFrom(out)); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { // Processing a Dex `long-to-double' instruction. vixl32::Register low = LowRegisterFrom(in); vixl32::Register high = HighRegisterFrom(in); @@ -4156,7 +4157,7 @@ void InstructionCodeGeneratorARMVIXL::VisitTypeConversion(HTypeConversion* conve break; } - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-double' instruction. __ Vcvt(F64, F32, DRegisterFrom(out), InputSRegisterAt(conversion, 0)); break; @@ -4177,22 +4178,22 @@ void LocationsBuilderARMVIXL::VisitAdd(HAdd* add) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall); switch (add->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(add->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, ArmEncodableConstantOrRegister(add->InputAt(1), ADD)); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -4211,12 +4212,12 @@ void InstructionCodeGeneratorARMVIXL::VisitAdd(HAdd* add) { Location second = locations->InAt(1); switch (add->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { __ Add(OutputRegister(add), InputRegisterAt(add, 0), InputOperandAt(add, 1)); } break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (second.IsConstant()) { uint64_t value = static_cast<uint64_t>(Int64FromConstant(second.GetConstant())); GenerateAddLongConst(out, first, value); @@ -4228,8 +4229,8 @@ void InstructionCodeGeneratorARMVIXL::VisitAdd(HAdd* add) { break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ Vadd(OutputVRegister(add), InputVRegisterAt(add, 0), InputVRegisterAt(add, 1)); break; @@ -4242,21 +4243,21 @@ void LocationsBuilderARMVIXL::VisitSub(HSub* sub) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub, LocationSummary::kNoCall); switch (sub->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(sub->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, ArmEncodableConstantOrRegister(sub->InputAt(1), SUB)); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -4273,12 +4274,12 @@ void InstructionCodeGeneratorARMVIXL::VisitSub(HSub* sub) { Location first = locations->InAt(0); Location second = locations->InAt(1); switch (sub->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { __ Sub(OutputRegister(sub), InputRegisterAt(sub, 0), InputOperandAt(sub, 1)); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (second.IsConstant()) { uint64_t value = static_cast<uint64_t>(Int64FromConstant(second.GetConstant())); GenerateAddLongConst(out, first, -value); @@ -4290,8 +4291,8 @@ void InstructionCodeGeneratorARMVIXL::VisitSub(HSub* sub) { break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ Vsub(OutputVRegister(sub), InputVRegisterAt(sub, 0), InputVRegisterAt(sub, 1)); break; @@ -4304,16 +4305,16 @@ void LocationsBuilderARMVIXL::VisitMul(HMul* mul) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(mul, LocationSummary::kNoCall); switch (mul->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -4331,11 +4332,11 @@ void InstructionCodeGeneratorARMVIXL::VisitMul(HMul* mul) { Location first = locations->InAt(0); Location second = locations->InAt(1); switch (mul->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { __ Mul(OutputRegister(mul), InputRegisterAt(mul, 0), InputRegisterAt(mul, 1)); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { vixl32::Register out_hi = HighRegisterFrom(out); vixl32::Register out_lo = LowRegisterFrom(out); vixl32::Register in1_hi = HighRegisterFrom(first); @@ -4368,8 +4369,8 @@ void InstructionCodeGeneratorARMVIXL::VisitMul(HMul* mul) { break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ Vmul(OutputVRegister(mul), InputVRegisterAt(mul, 0), InputVRegisterAt(mul, 1)); break; @@ -4380,7 +4381,7 @@ void InstructionCodeGeneratorARMVIXL::VisitMul(HMul* mul) { void InstructionCodeGeneratorARMVIXL::DivRemOneOrMinusOne(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - DCHECK(instruction->GetResultType() == Primitive::kPrimInt); + DCHECK(instruction->GetResultType() == DataType::Type::kInt32); Location second = instruction->GetLocations()->InAt(1); DCHECK(second.IsConstant()); @@ -4403,7 +4404,7 @@ void InstructionCodeGeneratorARMVIXL::DivRemOneOrMinusOne(HBinaryOperation* inst void InstructionCodeGeneratorARMVIXL::DivRemByPowerOfTwo(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - DCHECK(instruction->GetResultType() == Primitive::kPrimInt); + DCHECK(instruction->GetResultType() == DataType::Type::kInt32); LocationSummary* locations = instruction->GetLocations(); Location second = locations->InAt(1); @@ -4437,7 +4438,7 @@ void InstructionCodeGeneratorARMVIXL::DivRemByPowerOfTwo(HBinaryOperation* instr void InstructionCodeGeneratorARMVIXL::GenerateDivRemWithAnyConstant(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - DCHECK(instruction->GetResultType() == Primitive::kPrimInt); + DCHECK(instruction->GetResultType() == DataType::Type::kInt32); LocationSummary* locations = instruction->GetLocations(); Location second = locations->InAt(1); @@ -4480,7 +4481,7 @@ void InstructionCodeGeneratorARMVIXL::GenerateDivRemWithAnyConstant(HBinaryOpera void InstructionCodeGeneratorARMVIXL::GenerateDivRemConstantIntegral( HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - DCHECK(instruction->GetResultType() == Primitive::kPrimInt); + DCHECK(instruction->GetResultType() == DataType::Type::kInt32); Location second = instruction->GetLocations()->InAt(1); DCHECK(second.IsConstant()); @@ -4500,12 +4501,12 @@ void InstructionCodeGeneratorARMVIXL::GenerateDivRemConstantIntegral( void LocationsBuilderARMVIXL::VisitDiv(HDiv* div) { LocationSummary::CallKind call_kind = LocationSummary::kNoCall; - if (div->GetResultType() == Primitive::kPrimLong) { + if (div->GetResultType() == DataType::Type::kInt64) { // pLdiv runtime call. call_kind = LocationSummary::kCallOnMainOnly; - } else if (div->GetResultType() == Primitive::kPrimInt && div->InputAt(1)->IsConstant()) { + } else if (div->GetResultType() == DataType::Type::kInt32 && div->InputAt(1)->IsConstant()) { // sdiv will be replaced by other instruction sequence. - } else if (div->GetResultType() == Primitive::kPrimInt && + } else if (div->GetResultType() == DataType::Type::kInt32 && !codegen_->GetInstructionSetFeatures().HasDivideInstruction()) { // pIdivmod runtime call. call_kind = LocationSummary::kCallOnMainOnly; @@ -4514,7 +4515,7 @@ void LocationsBuilderARMVIXL::VisitDiv(HDiv* div) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, call_kind); switch (div->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { if (div->InputAt(1)->IsConstant()) { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::ConstantLocation(div->InputAt(1)->AsConstant())); @@ -4542,7 +4543,7 @@ void LocationsBuilderARMVIXL::VisitDiv(HDiv* div) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { InvokeRuntimeCallingConventionARMVIXL calling_convention; locations->SetInAt(0, LocationFrom( calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1))); @@ -4551,8 +4552,8 @@ void LocationsBuilderARMVIXL::VisitDiv(HDiv* div) { locations->SetOut(LocationFrom(r0, r1)); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -4569,7 +4570,7 @@ void InstructionCodeGeneratorARMVIXL::VisitDiv(HDiv* div) { Location rhs = div->GetLocations()->InAt(1); switch (div->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { if (rhs.IsConstant()) { GenerateDivRemConstantIntegral(div); } else if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) { @@ -4586,7 +4587,7 @@ void InstructionCodeGeneratorARMVIXL::VisitDiv(HDiv* div) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { InvokeRuntimeCallingConventionARMVIXL calling_convention; DCHECK(calling_convention.GetRegisterAt(0).Is(LowRegisterFrom(lhs))); DCHECK(calling_convention.GetRegisterAt(1).Is(HighRegisterFrom(lhs))); @@ -4600,8 +4601,8 @@ void InstructionCodeGeneratorARMVIXL::VisitDiv(HDiv* div) { break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ Vdiv(OutputVRegister(div), InputVRegisterAt(div, 0), InputVRegisterAt(div, 1)); break; @@ -4611,14 +4612,14 @@ void InstructionCodeGeneratorARMVIXL::VisitDiv(HDiv* div) { } void LocationsBuilderARMVIXL::VisitRem(HRem* rem) { - Primitive::Type type = rem->GetResultType(); + DataType::Type type = rem->GetResultType(); // Most remainders are implemented in the runtime. LocationSummary::CallKind call_kind = LocationSummary::kCallOnMainOnly; - if (rem->GetResultType() == Primitive::kPrimInt && rem->InputAt(1)->IsConstant()) { + if (rem->GetResultType() == DataType::Type::kInt32 && rem->InputAt(1)->IsConstant()) { // sdiv will be replaced by other instruction sequence. call_kind = LocationSummary::kNoCall; - } else if ((rem->GetResultType() == Primitive::kPrimInt) + } else if ((rem->GetResultType() == DataType::Type::kInt32) && codegen_->GetInstructionSetFeatures().HasDivideInstruction()) { // Have hardware divide instruction for int, do it with three instructions. call_kind = LocationSummary::kNoCall; @@ -4627,7 +4628,7 @@ void LocationsBuilderARMVIXL::VisitRem(HRem* rem) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { if (rem->InputAt(1)->IsConstant()) { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::ConstantLocation(rem->InputAt(1)->AsConstant())); @@ -4656,7 +4657,7 @@ void LocationsBuilderARMVIXL::VisitRem(HRem* rem) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { InvokeRuntimeCallingConventionARMVIXL calling_convention; locations->SetInAt(0, LocationFrom( calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1))); @@ -4666,7 +4667,7 @@ void LocationsBuilderARMVIXL::VisitRem(HRem* rem) { locations->SetOut(LocationFrom(r2, r3)); break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { InvokeRuntimeCallingConventionARMVIXL calling_convention; locations->SetInAt(0, LocationFrom(calling_convention.GetFpuRegisterAt(0))); locations->SetInAt(1, LocationFrom(calling_convention.GetFpuRegisterAt(1))); @@ -4674,7 +4675,7 @@ void LocationsBuilderARMVIXL::VisitRem(HRem* rem) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { InvokeRuntimeCallingConventionARMVIXL calling_convention; locations->SetInAt(0, LocationFrom( calling_convention.GetFpuRegisterAt(0), calling_convention.GetFpuRegisterAt(1))); @@ -4693,9 +4694,9 @@ void InstructionCodeGeneratorARMVIXL::VisitRem(HRem* rem) { LocationSummary* locations = rem->GetLocations(); Location second = locations->InAt(1); - Primitive::Type type = rem->GetResultType(); + DataType::Type type = rem->GetResultType(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { vixl32::Register reg1 = InputRegisterAt(rem, 0); vixl32::Register out_reg = OutputRegister(rem); if (second.IsConstant()) { @@ -4720,19 +4721,19 @@ void InstructionCodeGeneratorARMVIXL::VisitRem(HRem* rem) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { codegen_->InvokeRuntime(kQuickLmod, rem, rem->GetDexPc()); CheckEntrypointTypes<kQuickLmod, int64_t, int64_t, int64_t>(); break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { codegen_->InvokeRuntime(kQuickFmodf, rem, rem->GetDexPc()); CheckEntrypointTypes<kQuickFmodf, float, float, float>(); break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { codegen_->InvokeRuntime(kQuickFmod, rem, rem->GetDexPc()); CheckEntrypointTypes<kQuickFmod, double, double, double>(); break; @@ -4758,11 +4759,11 @@ void InstructionCodeGeneratorARMVIXL::VisitDivZeroCheck(HDivZeroCheck* instructi Location value = locations->InAt(0); switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: { if (value.IsRegister()) { __ CompareAndBranchIfZero(InputRegisterAt(instruction, 0), slow_path->GetEntryLabel()); } else { @@ -4773,7 +4774,7 @@ void InstructionCodeGeneratorARMVIXL::VisitDivZeroCheck(HDivZeroCheck* instructi } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (value.IsRegisterPair()) { UseScratchRegisterScope temps(GetVIXLAssembler()); vixl32::Register temp = temps.Acquire(); @@ -4890,13 +4891,13 @@ void LocationsBuilderARMVIXL::VisitRor(HRor* ror) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ror, LocationSummary::kNoCall); switch (ror->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(ror->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); if (ror->InputAt(1)->IsConstant()) { locations->SetInAt(1, Location::ConstantLocation(ror->InputAt(1)->AsConstant())); @@ -4914,13 +4915,13 @@ void LocationsBuilderARMVIXL::VisitRor(HRor* ror) { } void InstructionCodeGeneratorARMVIXL::VisitRor(HRor* ror) { - Primitive::Type type = ror->GetResultType(); + DataType::Type type = ror->GetResultType(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { HandleIntegerRotate(ror); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { HandleLongRotate(ror); break; } @@ -4937,7 +4938,7 @@ void LocationsBuilderARMVIXL::HandleShift(HBinaryOperation* op) { new (GetGraph()->GetArena()) LocationSummary(op, LocationSummary::kNoCall); switch (op->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RequiresRegister()); if (op->InputAt(1)->IsConstant()) { locations->SetInAt(1, Location::ConstantLocation(op->InputAt(1)->AsConstant())); @@ -4950,7 +4951,7 @@ void LocationsBuilderARMVIXL::HandleShift(HBinaryOperation* op) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); if (op->InputAt(1)->IsConstant()) { locations->SetInAt(1, Location::ConstantLocation(op->InputAt(1)->AsConstant())); @@ -4977,9 +4978,9 @@ void InstructionCodeGeneratorARMVIXL::HandleShift(HBinaryOperation* op) { Location first = locations->InAt(0); Location second = locations->InAt(1); - Primitive::Type type = op->GetResultType(); + DataType::Type type = op->GetResultType(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { vixl32::Register out_reg = OutputRegister(op); vixl32::Register first_reg = InputRegisterAt(op, 0); if (second.IsRegister()) { @@ -5008,7 +5009,7 @@ void InstructionCodeGeneratorARMVIXL::HandleShift(HBinaryOperation* op) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { vixl32::Register o_h = HighRegisterFrom(out); vixl32::Register o_l = LowRegisterFrom(out); @@ -5257,11 +5258,11 @@ void InstructionCodeGeneratorARMVIXL::VisitNot(HNot* not_) { Location out = locations->Out(); Location in = locations->InAt(0); switch (not_->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ Mvn(OutputRegister(not_), InputRegisterAt(not_, 0)); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: __ Mvn(LowRegisterFrom(out), LowRegisterFrom(in)); __ Mvn(HighRegisterFrom(out), HighRegisterFrom(in)); break; @@ -5286,20 +5287,20 @@ void LocationsBuilderARMVIXL::VisitCompare(HCompare* compare) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall); switch (compare->InputAt(0)->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); // Output overlaps because it is written before doing the low comparison. locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, ArithmeticZeroOrFpuRegister(compare->InputAt(1))); locations->SetOut(Location::RequiresRegister()); @@ -5318,21 +5319,21 @@ void InstructionCodeGeneratorARMVIXL::VisitCompare(HCompare* compare) { vixl32::Label less, greater, done; vixl32::Label* final_label = codegen_->GetFinalLabel(compare, &done); - Primitive::Type type = compare->InputAt(0)->GetType(); + DataType::Type type = compare->InputAt(0)->GetType(); vixl32::Condition less_cond = vixl32::Condition(kNone); switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: { // Emit move to `out` before the `Cmp`, as `Mov` might affect the status flags. __ Mov(out, 0); __ Cmp(RegisterFrom(left), RegisterFrom(right)); // Signed compare. less_cond = lt; break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { __ Cmp(HighRegisterFrom(left), HighRegisterFrom(right)); // Signed compare. __ B(lt, &less, /* far_target */ false); __ B(gt, &greater, /* far_target */ false); @@ -5342,8 +5343,8 @@ void InstructionCodeGeneratorARMVIXL::VisitCompare(HCompare* compare) { less_cond = lo; break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { __ Mov(out, 0); GenerateVcmp(compare, codegen_); // To branch on the FP compare result we transfer FPSCR to APSR (encoded as PC in VMRS). @@ -5454,14 +5455,14 @@ void LocationsBuilderARMVIXL::HandleFieldSet( new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); locations->SetInAt(0, Location::RequiresRegister()); - Primitive::Type field_type = field_info.GetFieldType(); - if (Primitive::IsFloatingPointType(field_type)) { + DataType::Type field_type = field_info.GetFieldType(); + if (DataType::IsFloatingPointType(field_type)) { locations->SetInAt(1, Location::RequiresFpuRegister()); } else { locations->SetInAt(1, Location::RequiresRegister()); } - bool is_wide = field_type == Primitive::kPrimLong || field_type == Primitive::kPrimDouble; + bool is_wide = field_type == DataType::Type::kInt64 || field_type == DataType::Type::kFloat64; bool generate_volatile = field_info.IsVolatile() && is_wide && !codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd(); @@ -5482,7 +5483,7 @@ void LocationsBuilderARMVIXL::HandleFieldSet( locations->AddTemp(Location::RequiresRegister()); locations->AddTemp(Location::RequiresRegister()); - if (field_type == Primitive::kPrimDouble) { + if (field_type == DataType::Type::kFloat64) { // For doubles we need two more registers to copy the value. locations->AddTemp(LocationFrom(r2)); locations->AddTemp(LocationFrom(r3)); @@ -5501,7 +5502,7 @@ void InstructionCodeGeneratorARMVIXL::HandleFieldSet(HInstruction* instruction, bool is_volatile = field_info.IsVolatile(); bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd(); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); uint32_t offset = field_info.GetFieldOffset().Uint32Value(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1)); @@ -5511,25 +5512,25 @@ void InstructionCodeGeneratorARMVIXL::HandleFieldSet(HInstruction* instruction, } switch (field_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: { + case DataType::Type::kBool: + case DataType::Type::kInt8: { GetAssembler()->StoreToOffset(kStoreByte, RegisterFrom(value), base, offset); break; } - case Primitive::kPrimShort: - case Primitive::kPrimChar: { + case DataType::Type::kInt16: + case DataType::Type::kUint16: { GetAssembler()->StoreToOffset(kStoreHalfword, RegisterFrom(value), base, offset); break; } - case Primitive::kPrimInt: - case Primitive::kPrimNot: { + case DataType::Type::kInt32: + case DataType::Type::kReference: { if (kPoisonHeapReferences && needs_write_barrier) { // Note that in the case where `value` is a null reference, // we do not enter this block, as a null reference does not // need poisoning. - DCHECK_EQ(field_type, Primitive::kPrimNot); + DCHECK_EQ(field_type, DataType::Type::kReference); vixl32::Register temp = RegisterFrom(locations->GetTemp(0)); __ Mov(temp, RegisterFrom(value)); GetAssembler()->PoisonHeapReference(temp); @@ -5540,7 +5541,7 @@ void InstructionCodeGeneratorARMVIXL::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (is_volatile && !atomic_ldrd_strd) { GenerateWideAtomicStore(base, offset, @@ -5556,12 +5557,12 @@ void InstructionCodeGeneratorARMVIXL::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { GetAssembler()->StoreSToOffset(SRegisterFrom(value), base, offset); break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { vixl32::DRegister value_reg = DRegisterFrom(value); if (is_volatile && !atomic_ldrd_strd) { vixl32::Register value_reg_lo = RegisterFrom(locations->GetTemp(0)); @@ -5583,13 +5584,13 @@ void InstructionCodeGeneratorARMVIXL::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); } // Longs and doubles are handled in the switch. - if (field_type != Primitive::kPrimLong && field_type != Primitive::kPrimDouble) { + if (field_type != DataType::Type::kInt64 && field_type != DataType::Type::kFloat64) { // TODO(VIXL): Here and for other calls to `MaybeRecordImplicitNullCheck` in this method, we // should use a scope and the assembler to emit the store instruction to guarantee that we // record the pc at the correct position. But the `Assembler` does not automatically handle @@ -5614,7 +5615,7 @@ void LocationsBuilderARMVIXL::HandleFieldGet(HInstruction* instruction, DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet()); bool object_field_get_with_read_barrier = - kEmitCompilerReadBarrier && (field_info.GetFieldType() == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (field_info.GetFieldType() == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, object_field_get_with_read_barrier ? @@ -5626,17 +5627,18 @@ void LocationsBuilderARMVIXL::HandleFieldGet(HInstruction* instruction, locations->SetInAt(0, Location::RequiresRegister()); bool volatile_for_double = field_info.IsVolatile() - && (field_info.GetFieldType() == Primitive::kPrimDouble) + && (field_info.GetFieldType() == DataType::Type::kFloat64) && !codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd(); // The output overlaps in case of volatile long: we don't want the // code generated by GenerateWideAtomicLoad to overwrite the // object's location. Likewise, in the case of an object field get // with read barriers enabled, we do not want the load to overwrite // the object's location, as we need it to emit the read barrier. - bool overlap = (field_info.IsVolatile() && (field_info.GetFieldType() == Primitive::kPrimLong)) || + bool overlap = + (field_info.IsVolatile() && (field_info.GetFieldType() == DataType::Type::kInt64)) || object_field_get_with_read_barrier; - if (Primitive::IsFloatingPointType(instruction->GetType())) { + if (DataType::IsFloatingPointType(instruction->GetType())) { locations->SetOut(Location::RequiresFpuRegister()); } else { locations->SetOut(Location::RequiresRegister(), @@ -5670,7 +5672,7 @@ void LocationsBuilderARMVIXL::HandleFieldGet(HInstruction* instruction, } Location LocationsBuilderARMVIXL::ArithmeticZeroOrFpuRegister(HInstruction* input) { - DCHECK(Primitive::IsFloatingPointType(input->GetType())) << input->GetType(); + DCHECK(DataType::IsFloatingPointType(input->GetType())) << input->GetType(); if ((input->IsFloatConstant() && (input->AsFloatConstant()->IsArithmeticZero())) || (input->IsDoubleConstant() && (input->AsDoubleConstant()->IsArithmeticZero()))) { return Location::ConstantLocation(input->AsConstant()); @@ -5681,7 +5683,7 @@ Location LocationsBuilderARMVIXL::ArithmeticZeroOrFpuRegister(HInstruction* inpu Location LocationsBuilderARMVIXL::ArmEncodableConstantOrRegister(HInstruction* constant, Opcode opcode) { - DCHECK(!Primitive::IsFloatingPointType(constant->GetType())); + DCHECK(!DataType::IsFloatingPointType(constant->GetType())); if (constant->IsConstant() && CanEncodeConstantAsImmediate(constant->AsConstant(), opcode)) { return Location::ConstantLocation(constant->AsConstant()); @@ -5692,7 +5694,7 @@ Location LocationsBuilderARMVIXL::ArmEncodableConstantOrRegister(HInstruction* c bool LocationsBuilderARMVIXL::CanEncodeConstantAsImmediate(HConstant* input_cst, Opcode opcode) { uint64_t value = static_cast<uint64_t>(Int64FromConstant(input_cst)); - if (Primitive::Is64BitType(input_cst->GetType())) { + if (DataType::Is64BitType(input_cst->GetType())) { Opcode high_opcode = opcode; SetCc low_set_cc = kCcDontCare; switch (opcode) { @@ -5757,31 +5759,31 @@ void InstructionCodeGeneratorARMVIXL::HandleFieldGet(HInstruction* instruction, Location out = locations->Out(); bool is_volatile = field_info.IsVolatile(); bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd(); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); uint32_t offset = field_info.GetFieldOffset().Uint32Value(); switch (field_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: GetAssembler()->LoadFromOffset(kLoadUnsignedByte, RegisterFrom(out), base, offset); break; - case Primitive::kPrimByte: + case DataType::Type::kInt8: GetAssembler()->LoadFromOffset(kLoadSignedByte, RegisterFrom(out), base, offset); break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: GetAssembler()->LoadFromOffset(kLoadSignedHalfword, RegisterFrom(out), base, offset); break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: GetAssembler()->LoadFromOffset(kLoadUnsignedHalfword, RegisterFrom(out), base, offset); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: GetAssembler()->LoadFromOffset(kLoadWord, RegisterFrom(out), base, offset); break; - case Primitive::kPrimNot: { + case DataType::Type::kReference: { // /* HeapReference<Object> */ out = *(base + offset) if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) { Location temp_loc = locations->GetTemp(0); @@ -5806,7 +5808,7 @@ void InstructionCodeGeneratorARMVIXL::HandleFieldGet(HInstruction* instruction, break; } - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (is_volatile && !atomic_ldrd_strd) { GenerateWideAtomicLoad(base, offset, LowRegisterFrom(out), HighRegisterFrom(out)); } else { @@ -5814,11 +5816,11 @@ void InstructionCodeGeneratorARMVIXL::HandleFieldGet(HInstruction* instruction, } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: GetAssembler()->LoadSFromOffset(SRegisterFrom(out), base, offset); break; - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { vixl32::DRegister out_dreg = DRegisterFrom(out); if (is_volatile && !atomic_ldrd_strd) { vixl32::Register lo = RegisterFrom(locations->GetTemp(0)); @@ -5835,12 +5837,12 @@ void InstructionCodeGeneratorARMVIXL::HandleFieldGet(HInstruction* instruction, break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); } - if (field_type == Primitive::kPrimNot || field_type == Primitive::kPrimDouble) { + if (field_type == DataType::Type::kReference || field_type == DataType::Type::kFloat64) { // Potential implicit null checks, in the case of reference or // double fields, are handled in the previous switch statement. } else { @@ -5854,7 +5856,7 @@ void InstructionCodeGeneratorARMVIXL::HandleFieldGet(HInstruction* instruction, } if (is_volatile) { - if (field_type == Primitive::kPrimNot) { + if (field_type == DataType::Type::kReference) { // Memory barriers, in the case of references, are also handled // in the previous switch statement. } else { @@ -5993,25 +5995,25 @@ void InstructionCodeGeneratorARMVIXL::VisitNullCheck(HNullCheck* instruction) { codegen_->GenerateNullCheck(instruction); } -static LoadOperandType GetLoadOperandType(Primitive::Type type) { +static LoadOperandType GetLoadOperandType(DataType::Type type) { switch (type) { - case Primitive::kPrimNot: + case DataType::Type::kReference: return kLoadWord; - case Primitive::kPrimBoolean: + case DataType::Type::kBool: return kLoadUnsignedByte; - case Primitive::kPrimByte: + case DataType::Type::kInt8: return kLoadSignedByte; - case Primitive::kPrimChar: + case DataType::Type::kUint16: return kLoadUnsignedHalfword; - case Primitive::kPrimShort: + case DataType::Type::kInt16: return kLoadSignedHalfword; - case Primitive::kPrimInt: + case DataType::Type::kInt32: return kLoadWord; - case Primitive::kPrimLong: + case DataType::Type::kInt64: return kLoadWordPair; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: return kLoadSWord; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: return kLoadDWord; default: LOG(FATAL) << "Unreachable type " << type; @@ -6019,23 +6021,23 @@ static LoadOperandType GetLoadOperandType(Primitive::Type type) { } } -static StoreOperandType GetStoreOperandType(Primitive::Type type) { +static StoreOperandType GetStoreOperandType(DataType::Type type) { switch (type) { - case Primitive::kPrimNot: + case DataType::Type::kReference: return kStoreWord; - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: return kStoreByte; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: return kStoreHalfword; - case Primitive::kPrimInt: + case DataType::Type::kInt32: return kStoreWord; - case Primitive::kPrimLong: + case DataType::Type::kInt64: return kStoreWordPair; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: return kStoreSWord; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: return kStoreDWord; default: LOG(FATAL) << "Unreachable type " << type; @@ -6043,66 +6045,66 @@ static StoreOperandType GetStoreOperandType(Primitive::Type type) { } } -void CodeGeneratorARMVIXL::LoadFromShiftedRegOffset(Primitive::Type type, +void CodeGeneratorARMVIXL::LoadFromShiftedRegOffset(DataType::Type type, Location out_loc, vixl32::Register base, vixl32::Register reg_index, vixl32::Condition cond) { - uint32_t shift_count = Primitive::ComponentSizeShift(type); + uint32_t shift_count = DataType::SizeShift(type); MemOperand mem_address(base, reg_index, vixl32::LSL, shift_count); switch (type) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: __ Ldrsb(cond, RegisterFrom(out_loc), mem_address); break; - case Primitive::kPrimBoolean: + case DataType::Type::kBool: __ Ldrb(cond, RegisterFrom(out_loc), mem_address); break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: __ Ldrsh(cond, RegisterFrom(out_loc), mem_address); break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: __ Ldrh(cond, RegisterFrom(out_loc), mem_address); break; - case Primitive::kPrimNot: - case Primitive::kPrimInt: + case DataType::Type::kReference: + case DataType::Type::kInt32: __ Ldr(cond, RegisterFrom(out_loc), mem_address); break; // T32 doesn't support LoadFromShiftedRegOffset mem address mode for these types. - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: default: LOG(FATAL) << "Unreachable type " << type; UNREACHABLE(); } } -void CodeGeneratorARMVIXL::StoreToShiftedRegOffset(Primitive::Type type, +void CodeGeneratorARMVIXL::StoreToShiftedRegOffset(DataType::Type type, Location loc, vixl32::Register base, vixl32::Register reg_index, vixl32::Condition cond) { - uint32_t shift_count = Primitive::ComponentSizeShift(type); + uint32_t shift_count = DataType::SizeShift(type); MemOperand mem_address(base, reg_index, vixl32::LSL, shift_count); switch (type) { - case Primitive::kPrimByte: - case Primitive::kPrimBoolean: + case DataType::Type::kInt8: + case DataType::Type::kBool: __ Strb(cond, RegisterFrom(loc), mem_address); break; - case Primitive::kPrimShort: - case Primitive::kPrimChar: + case DataType::Type::kInt16: + case DataType::Type::kUint16: __ Strh(cond, RegisterFrom(loc), mem_address); break; - case Primitive::kPrimNot: - case Primitive::kPrimInt: + case DataType::Type::kReference: + case DataType::Type::kInt32: __ Str(cond, RegisterFrom(loc), mem_address); break; // T32 doesn't support StoreToShiftedRegOffset mem address mode for these types. - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: default: LOG(FATAL) << "Unreachable type " << type; UNREACHABLE(); @@ -6111,7 +6113,7 @@ void CodeGeneratorARMVIXL::StoreToShiftedRegOffset(Primitive::Type type, void LocationsBuilderARMVIXL::VisitArrayGet(HArrayGet* instruction) { bool object_array_get_with_read_barrier = - kEmitCompilerReadBarrier && (instruction->GetType() == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (instruction->GetType() == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, object_array_get_with_read_barrier ? @@ -6122,7 +6124,7 @@ void LocationsBuilderARMVIXL::VisitArrayGet(HArrayGet* instruction) { } locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - if (Primitive::IsFloatingPointType(instruction->GetType())) { + if (DataType::IsFloatingPointType(instruction->GetType())) { locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); } else { // The output overlaps in the case of an object array get with @@ -6143,7 +6145,7 @@ void LocationsBuilderARMVIXL::VisitArrayGet(HArrayGet* instruction) { // constant index loads we need a temporary only if the offset is too big. uint32_t offset = CodeGenerator::GetArrayDataOffset(instruction); uint32_t index = instruction->GetIndex()->AsIntConstant()->GetValue(); - offset += index << Primitive::ComponentSizeShift(Primitive::kPrimNot); + offset += index << DataType::SizeShift(DataType::Type::kReference); if (offset >= kReferenceLoadMinFarOffset) { locations->AddTemp(Location::RequiresRegister()); } @@ -6172,18 +6174,18 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { Location index = locations->InAt(1); Location out_loc = locations->Out(); uint32_t data_offset = CodeGenerator::GetArrayDataOffset(instruction); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); const bool maybe_compressed_char_at = mirror::kUseStringCompression && instruction->IsStringCharAt(); HInstruction* array_instr = instruction->GetArray(); bool has_intermediate_address = array_instr->IsIntermediateAddress(); switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: { vixl32::Register length; if (maybe_compressed_char_at) { length = RegisterFrom(locations->GetTemp(0)); @@ -6206,7 +6208,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { data_offset + const_index); __ B(final_label); __ Bind(&uncompressed_load); - GetAssembler()->LoadFromOffset(GetLoadOperandType(Primitive::kPrimChar), + GetAssembler()->LoadFromOffset(GetLoadOperandType(DataType::Type::kUint16), RegisterFrom(out_loc), obj, data_offset + (const_index << 1)); @@ -6214,7 +6216,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { __ Bind(&done); } } else { - uint32_t full_offset = data_offset + (const_index << Primitive::ComponentSizeShift(type)); + uint32_t full_offset = data_offset + (const_index << DataType::SizeShift(type)); LoadOperandType load_type = GetLoadOperandType(type); GetAssembler()->LoadFromOffset(load_type, RegisterFrom(out_loc), obj, full_offset); @@ -6256,7 +6258,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { // The read barrier instrumentation of object ArrayGet // instructions does not support the HIntermediateAddress // instruction. @@ -6274,7 +6276,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { DCHECK(!instruction->CanDoImplicitNullCheckOn(instruction->InputAt(0))); if (index.IsConstant()) { // Array load with a constant index can be treated as a field load. - data_offset += Int32ConstantFrom(index) << Primitive::ComponentSizeShift(type); + data_offset += Int32ConstantFrom(index) << DataType::SizeShift(type); codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction, out_loc, obj, @@ -6333,7 +6335,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (index.IsConstant()) { size_t offset = (Int32ConstantFrom(index) << TIMES_8) + data_offset; @@ -6347,7 +6349,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { vixl32::SRegister out = SRegisterFrom(out_loc); if (index.IsConstant()) { size_t offset = (Int32ConstantFrom(index) << TIMES_4) + data_offset; @@ -6361,7 +6363,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (index.IsConstant()) { size_t offset = (Int32ConstantFrom(index) << TIMES_8) + data_offset; GetAssembler()->LoadDFromOffset(DRegisterFrom(out_loc), obj, offset); @@ -6374,12 +6376,12 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; UNREACHABLE(); } - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // Potential implicit null checks, in the case of reference // arrays, are handled in the previous switch statement. } else if (!maybe_compressed_char_at) { @@ -6390,7 +6392,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { } void LocationsBuilderARMVIXL::VisitArraySet(HArraySet* instruction) { - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); @@ -6404,7 +6406,7 @@ void LocationsBuilderARMVIXL::VisitArraySet(HArraySet* instruction) { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - if (Primitive::IsFloatingPointType(value_type)) { + if (DataType::IsFloatingPointType(value_type)) { locations->SetInAt(2, Location::RequiresFpuRegister()); } else { locations->SetInAt(2, Location::RequiresRegister()); @@ -6420,26 +6422,26 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { LocationSummary* locations = instruction->GetLocations(); vixl32::Register array = InputRegisterAt(instruction, 0); Location index = locations->InAt(1); - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); uint32_t data_offset = - mirror::Array::DataOffset(Primitive::ComponentSize(value_type)).Uint32Value(); + mirror::Array::DataOffset(DataType::Size(value_type)).Uint32Value(); Location value_loc = locations->InAt(2); HInstruction* array_instr = instruction->GetArray(); bool has_intermediate_address = array_instr->IsIntermediateAddress(); switch (value_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: { if (index.IsConstant()) { int32_t const_index = Int32ConstantFrom(index); uint32_t full_offset = - data_offset + (const_index << Primitive::ComponentSizeShift(value_type)); + data_offset + (const_index << DataType::SizeShift(value_type)); StoreOperandType store_type = GetStoreOperandType(value_type); GetAssembler()->StoreToOffset(store_type, RegisterFrom(value_loc), array, full_offset); } else { @@ -6463,7 +6465,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { vixl32::Register value = RegisterFrom(value_loc); // TryExtractArrayAccessAddress optimization is never applied for non-primitive ArraySet. // See the comment in instruction_simplifier_shared.cc. @@ -6576,7 +6578,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { // Note that in the case where `value` is a null reference, // we do not enter this block, as a null reference does not // need poisoning. - DCHECK_EQ(value_type, Primitive::kPrimNot); + DCHECK_EQ(value_type, DataType::Type::kReference); __ Mov(temp1, value); GetAssembler()->PoisonHeapReference(temp1); source = temp1; @@ -6617,7 +6619,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Location value = locations->InAt(2); if (index.IsConstant()) { size_t offset = @@ -6632,7 +6634,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { Location value = locations->InAt(2); DCHECK(value.IsFpuRegister()); if (index.IsConstant()) { @@ -6647,7 +6649,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { Location value = locations->InAt(2); DCHECK(value.IsFpuRegisterPair()); if (index.IsConstant()) { @@ -6662,13 +6664,13 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << value_type; UNREACHABLE(); } // Objects are handled in the switch. - if (value_type != Primitive::kPrimNot) { + if (value_type != DataType::Type::kReference) { // TODO(VIXL): Ensure we record the pc position immediately after the preceding store // instruction. codegen_->MaybeRecordImplicitNullCheck(instruction); @@ -7965,7 +7967,7 @@ void InstructionCodeGeneratorARMVIXL::VisitCheckCast(HCheckCast* instruction) { // Otherwise,the object is indeed an array, jump to label `check_non_primitive_component_type` // to further check that this component type is not a primitive type. GetAssembler()->LoadFromOffset(kLoadUnsignedHalfword, temp, temp, primitive_offset); - static_assert(Primitive::kPrimNot == 0, "Expected 0 for art::Primitive::kPrimNot"); + static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot"); __ CompareAndBranchIfNonZero(temp, type_check_slow_path->GetEntryLabel()); break; } @@ -8060,8 +8062,8 @@ void LocationsBuilderARMVIXL::VisitXor(HXor* instruction) { void LocationsBuilderARMVIXL::HandleBitwiseOperation(HBinaryOperation* instruction, Opcode opcode) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); - DCHECK(instruction->GetResultType() == Primitive::kPrimInt - || instruction->GetResultType() == Primitive::kPrimLong); + DCHECK(instruction->GetResultType() == DataType::Type::kInt32 + || instruction->GetResultType() == DataType::Type::kInt64); // Note: GVN reorders commutative operations to have the constant on the right hand side. locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, ArmEncodableConstantOrRegister(instruction->InputAt(1), opcode)); @@ -8083,8 +8085,8 @@ void InstructionCodeGeneratorARMVIXL::VisitXor(HXor* instruction) { void LocationsBuilderARMVIXL::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); - DCHECK(instruction->GetResultType() == Primitive::kPrimInt - || instruction->GetResultType() == Primitive::kPrimLong); + DCHECK(instruction->GetResultType() == DataType::Type::kInt32 + || instruction->GetResultType() == DataType::Type::kInt64); locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); @@ -8097,7 +8099,7 @@ void InstructionCodeGeneratorARMVIXL::VisitBitwiseNegatedRight(HBitwiseNegatedRi Location second = locations->InAt(1); Location out = locations->Out(); - if (instruction->GetResultType() == Primitive::kPrimInt) { + if (instruction->GetResultType() == DataType::Type::kInt32) { vixl32::Register first_reg = RegisterFrom(first); vixl32::Register second_reg = RegisterFrom(second); vixl32::Register out_reg = RegisterFrom(out); @@ -8118,7 +8120,7 @@ void InstructionCodeGeneratorARMVIXL::VisitBitwiseNegatedRight(HBitwiseNegatedRi return; } else { - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt64); vixl32::Register first_low = LowRegisterFrom(first); vixl32::Register first_high = HighRegisterFrom(first); vixl32::Register second_low = LowRegisterFrom(second); @@ -8146,11 +8148,11 @@ void InstructionCodeGeneratorARMVIXL::VisitBitwiseNegatedRight(HBitwiseNegatedRi void LocationsBuilderARMVIXL::VisitDataProcWithShifterOp( HDataProcWithShifterOp* instruction) { - DCHECK(instruction->GetType() == Primitive::kPrimInt || - instruction->GetType() == Primitive::kPrimLong); + DCHECK(instruction->GetType() == DataType::Type::kInt32 || + instruction->GetType() == DataType::Type::kInt64); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); - const bool overlap = instruction->GetType() == Primitive::kPrimLong && + const bool overlap = instruction->GetType() == DataType::Type::kInt64 && HDataProcWithShifterOp::IsExtensionOp(instruction->GetOpKind()); locations->SetInAt(0, Location::RequiresRegister()); @@ -8165,10 +8167,10 @@ void InstructionCodeGeneratorARMVIXL::VisitDataProcWithShifterOp( const HInstruction::InstructionKind kind = instruction->GetInstrKind(); const HDataProcWithShifterOp::OpKind op_kind = instruction->GetOpKind(); - if (instruction->GetType() == Primitive::kPrimInt) { + if (instruction->GetType() == DataType::Type::kInt32) { const vixl32::Register first = InputRegisterAt(instruction, 0); const vixl32::Register output = OutputRegister(instruction); - const vixl32::Register second = instruction->InputAt(1)->GetType() == Primitive::kPrimLong + const vixl32::Register second = instruction->InputAt(1)->GetType() == DataType::Type::kInt64 ? LowRegisterFrom(locations->InAt(1)) : InputRegisterAt(instruction, 1); @@ -8202,7 +8204,7 @@ void InstructionCodeGeneratorARMVIXL::VisitDataProcWithShifterOp( codegen_); } } else { - DCHECK_EQ(instruction->GetType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64); if (HDataProcWithShifterOp::IsExtensionOp(op_kind)) { const vixl32::Register second = InputRegisterAt(instruction, 1); @@ -8318,7 +8320,7 @@ void InstructionCodeGeneratorARMVIXL::HandleBitwiseOperation(HBinaryOperation* i if (second.IsConstant()) { uint64_t value = static_cast<uint64_t>(Int64FromConstant(second.GetConstant())); uint32_t value_low = Low32Bits(value); - if (instruction->GetResultType() == Primitive::kPrimInt) { + if (instruction->GetResultType() == DataType::Type::kInt32) { vixl32::Register first_reg = InputRegisterAt(instruction, 0); vixl32::Register out_reg = OutputRegister(instruction); if (instruction->IsAnd()) { @@ -8330,7 +8332,7 @@ void InstructionCodeGeneratorARMVIXL::HandleBitwiseOperation(HBinaryOperation* i GenerateEorConst(out_reg, first_reg, value_low); } } else { - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt64); uint32_t value_high = High32Bits(value); vixl32::Register first_low = LowRegisterFrom(first); vixl32::Register first_high = HighRegisterFrom(first); @@ -8351,7 +8353,7 @@ void InstructionCodeGeneratorARMVIXL::HandleBitwiseOperation(HBinaryOperation* i return; } - if (instruction->GetResultType() == Primitive::kPrimInt) { + if (instruction->GetResultType() == DataType::Type::kInt32) { vixl32::Register first_reg = InputRegisterAt(instruction, 0); vixl32::Register second_reg = InputRegisterAt(instruction, 1); vixl32::Register out_reg = OutputRegister(instruction); @@ -8364,7 +8366,7 @@ void InstructionCodeGeneratorARMVIXL::HandleBitwiseOperation(HBinaryOperation* i __ Eor(out_reg, first_reg, second_reg); } } else { - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt64); vixl32::Register first_low = LowRegisterFrom(first); vixl32::Register first_high = HighRegisterFrom(first); vixl32::Register second_low = LowRegisterFrom(second); @@ -8589,7 +8591,7 @@ void CodeGeneratorARMVIXL::GenerateFieldLoadWithBakerReadBarrier(HInstruction* i // gray_return_address: DCHECK_ALIGNED(offset, sizeof(mirror::HeapReference<mirror::Object>)); - vixl32::Register ref_reg = RegisterFrom(ref, Primitive::kPrimNot); + vixl32::Register ref_reg = RegisterFrom(ref, DataType::Type::kReference); bool narrow = CanEmitNarrowLdr(ref_reg, obj, offset); vixl32::Register base = obj; if (offset >= kReferenceLoadMinFarOffset) { @@ -8685,9 +8687,9 @@ void CodeGeneratorARMVIXL::GenerateArrayLoadWithBakerReadBarrier(HInstruction* i // gray_return_address: DCHECK(index.IsValid()); - vixl32::Register index_reg = RegisterFrom(index, Primitive::kPrimInt); - vixl32::Register ref_reg = RegisterFrom(ref, Primitive::kPrimNot); - vixl32::Register data_reg = RegisterFrom(temp, Primitive::kPrimInt); // Raw pointer. + vixl32::Register index_reg = RegisterFrom(index, DataType::Type::kInt32); + vixl32::Register ref_reg = RegisterFrom(ref, DataType::Type::kReference); + vixl32::Register data_reg = RegisterFrom(temp, DataType::Type::kInt32); // Raw pointer. DCHECK(!data_reg.Is(kBakerCcEntrypointRegister)); UseScratchRegisterScope temps(GetVIXLAssembler()); @@ -8835,7 +8837,7 @@ void CodeGeneratorARMVIXL::GenerateRawReferenceLoad(HInstruction* instruction, Location index, ScaleFactor scale_factor, bool needs_null_check) { - Primitive::Type type = Primitive::kPrimNot; + DataType::Type type = DataType::Type::kReference; vixl32::Register ref_reg = RegisterFrom(ref, type); // If needed, vixl::EmissionCheckScope guards are used to ensure @@ -9191,10 +9193,10 @@ VIXLUInt32Literal* CodeGeneratorARMVIXL::DeduplicateJitClassLiteral(const DexFil }); } -template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> +template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> inline void CodeGeneratorARMVIXL::EmitPcRelativeLinkerPatches( const ArenaDeque<PcRelativePatchInfo>& infos, - ArenaVector<LinkerPatch>* linker_patches) { + ArenaVector<linker::LinkerPatch>* linker_patches) { for (const PcRelativePatchInfo& info : infos) { const DexFile& dex_file = info.target_dex_file; size_t offset_or_index = info.offset_or_index; @@ -9211,7 +9213,7 @@ inline void CodeGeneratorARMVIXL::EmitPcRelativeLinkerPatches( } } -void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) { +void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) { DCHECK(linker_patches->empty()); size_t size = /* MOVW+MOVT for each entry */ 2u * pc_relative_method_patches_.size() + @@ -9223,28 +9225,28 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_pa baker_read_barrier_patches_.size(); linker_patches->reserve(size); if (GetCompilerOptions().IsBootImage()) { - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(pc_relative_method_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeTypePatch>(pc_relative_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeStringPatch>(pc_relative_string_patches_, - linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>( + pc_relative_method_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>( + pc_relative_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>( + pc_relative_string_patches_, linker_patches); } else { DCHECK(pc_relative_method_patches_.empty()); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(pc_relative_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(pc_relative_string_patches_, - linker_patches); - } - EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(string_bss_entry_patches_, - linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>( + pc_relative_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>( + pc_relative_string_patches_, linker_patches); + } + EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( + method_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>( + type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>( + string_bss_entry_patches_, linker_patches); for (const BakerReadBarrierPatchInfo& info : baker_read_barrier_patches_) { - linker_patches->push_back(LinkerPatch::BakerReadBarrierBranchPatch(info.label.GetLocation(), - info.custom_data)); + linker_patches->push_back(linker::LinkerPatch::BakerReadBarrierBranchPatch( + info.label.GetLocation(), info.custom_data)); } DCHECK_EQ(size, linker_patches->size()); } @@ -9391,13 +9393,13 @@ void InstructionCodeGeneratorARMVIXL::VisitPackedSwitch(HPackedSwitch* switch_in } // Copy the result of a call into the given target. -void CodeGeneratorARMVIXL::MoveFromReturnRegister(Location trg, Primitive::Type type) { +void CodeGeneratorARMVIXL::MoveFromReturnRegister(Location trg, DataType::Type type) { if (!trg.IsValid()) { - DCHECK_EQ(type, Primitive::kPrimVoid); + DCHECK_EQ(type, DataType::Type::kVoid); return; } - DCHECK_NE(type, Primitive::kPrimVoid); + DCHECK_NE(type, DataType::Type::kVoid); Location return_loc = InvokeDexCallingConventionVisitorARMVIXL().GetReturnLocation(type); if (return_loc.Equals(trg)) { @@ -9406,9 +9408,9 @@ void CodeGeneratorARMVIXL::MoveFromReturnRegister(Location trg, Primitive::Type // TODO: Consider pairs in the parallel move resolver, then this could be nicely merged // with the last branch. - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { TODO_VIXL32(FATAL); - } else if (type == Primitive::kPrimDouble) { + } else if (type == DataType::Type::kFloat64) { TODO_VIXL32(FATAL); } else { // Let the parallel move resolver take care of all of this. diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h index e78bc15614..58b85259e7 100644 --- a/compiler/optimizing/code_generator_arm_vixl.h +++ b/compiler/optimizing/code_generator_arm_vixl.h @@ -173,8 +173,8 @@ class InvokeDexCallingConventionVisitorARMVIXL : public InvokeDexCallingConventi InvokeDexCallingConventionVisitorARMVIXL() {} virtual ~InvokeDexCallingConventionVisitorARMVIXL() {} - Location GetNextLocation(Primitive::Type type) OVERRIDE; - Location GetReturnLocation(Primitive::Type type) const OVERRIDE; + Location GetNextLocation(DataType::Type type) OVERRIDE; + Location GetReturnLocation(DataType::Type type) const OVERRIDE; Location GetMethodLocation() const OVERRIDE; private: @@ -194,20 +194,20 @@ class FieldAccessCallingConventionARMVIXL : public FieldAccessCallingConvention Location GetFieldIndexLocation() const OVERRIDE { return helpers::LocationFrom(vixl::aarch32::r0); } - Location GetReturnLocation(Primitive::Type type) const OVERRIDE { - return Primitive::Is64BitType(type) + Location GetReturnLocation(DataType::Type type) const OVERRIDE { + return DataType::Is64BitType(type) ? helpers::LocationFrom(vixl::aarch32::r0, vixl::aarch32::r1) : helpers::LocationFrom(vixl::aarch32::r0); } - Location GetSetValueLocation(Primitive::Type type, bool is_instance) const OVERRIDE { - return Primitive::Is64BitType(type) + Location GetSetValueLocation(DataType::Type type, bool is_instance) const OVERRIDE { + return DataType::Is64BitType(type) ? helpers::LocationFrom(vixl::aarch32::r2, vixl::aarch32::r3) : (is_instance ? helpers::LocationFrom(vixl::aarch32::r2) : helpers::LocationFrom(vixl::aarch32::r1)); } - Location GetFpuLocation(Primitive::Type type) const OVERRIDE { - return Primitive::Is64BitType(type) + Location GetFpuLocation(DataType::Type type) const OVERRIDE { + return DataType::Is64BitType(type) ? helpers::LocationFrom(vixl::aarch32::s0, vixl::aarch32::s1) : helpers::LocationFrom(vixl::aarch32::s0); } @@ -434,7 +434,7 @@ class CodeGeneratorARMVIXL : public CodeGenerator { void GenerateFrameExit() OVERRIDE; void Bind(HBasicBlock* block) OVERRIDE; void MoveConstant(Location destination, int32_t value) OVERRIDE; - void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; + void MoveLocation(Location dst, Location src, DataType::Type dst_type) OVERRIDE; void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; @@ -475,12 +475,12 @@ class CodeGeneratorARMVIXL : public CodeGenerator { // Helper method to move a 32-bit value between two locations. void Move32(Location destination, Location source); - void LoadFromShiftedRegOffset(Primitive::Type type, + void LoadFromShiftedRegOffset(DataType::Type type, Location out_loc, vixl::aarch32::Register base, vixl::aarch32::Register reg_index, vixl::aarch32::Condition cond = vixl::aarch32::al); - void StoreToShiftedRegOffset(Primitive::Type type, + void StoreToShiftedRegOffset(DataType::Type type, Location out_loc, vixl::aarch32::Register base, vixl::aarch32::Register reg_index, @@ -522,8 +522,8 @@ class CodeGeneratorARMVIXL : public CodeGenerator { const ArmInstructionSetFeatures& GetInstructionSetFeatures() const { return isa_features_; } - bool NeedsTwoRegisters(Primitive::Type type) const OVERRIDE { - return type == Primitive::kPrimDouble || type == Primitive::kPrimLong; + bool NeedsTwoRegisters(DataType::Type type) const OVERRIDE { + return type == DataType::Type::kFloat64 || type == DataType::Type::kInt64; } void ComputeSpillMask() OVERRIDE; @@ -551,7 +551,7 @@ class CodeGeneratorARMVIXL : public CodeGenerator { void GenerateVirtualCall( HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE; - void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE; + void MoveFromReturnRegister(Location trg, DataType::Type type) OVERRIDE; // The PcRelativePatchInfo is used for PC-relative addressing of dex cache arrays // and boot image strings/types. The only difference is the interpretation of the @@ -594,7 +594,7 @@ class CodeGeneratorARMVIXL : public CodeGenerator { dex::TypeIndex type_index, Handle<mirror::Class> handle); - void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; + void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) OVERRIDE; void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) OVERRIDE; @@ -778,9 +778,9 @@ class CodeGeneratorARMVIXL : public CodeGenerator { PcRelativePatchInfo* NewPcRelativePatch(const DexFile& dex_file, uint32_t offset_or_index, ArenaDeque<PcRelativePatchInfo>* patches); - template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> + template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> static void EmitPcRelativeLinkerPatches(const ArenaDeque<PcRelativePatchInfo>& infos, - ArenaVector<LinkerPatch>* linker_patches); + ArenaVector<linker::LinkerPatch>* linker_patches); // Labels for each block that will be compiled. // We use a deque so that the `vixl::aarch32::Label` objects do not move in memory. diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index 6256722661..a7c85574ee 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -29,6 +29,7 @@ #include "heap_poisoning.h" #include "intrinsics.h" #include "intrinsics_mips.h" +#include "linker/linker_patch.h" #include "mirror/array-inl.h" #include "mirror/class-inl.h" #include "offsets.h" @@ -48,30 +49,30 @@ constexpr bool kBakerReadBarrierThunksEnableForFields = true; constexpr bool kBakerReadBarrierThunksEnableForArrays = true; constexpr bool kBakerReadBarrierThunksEnableForGcRoots = true; -Location MipsReturnLocation(Primitive::Type return_type) { +Location MipsReturnLocation(DataType::Type return_type) { switch (return_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: return Location::RegisterLocation(V0); - case Primitive::kPrimLong: + case DataType::Type::kInt64: return Location::RegisterPairLocation(V0, V1); - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: return Location::FpuRegisterLocation(F0); - case Primitive::kPrimVoid: + case DataType::Type::kVoid: return Location(); } UNREACHABLE(); } -Location InvokeDexCallingConventionVisitorMIPS::GetReturnLocation(Primitive::Type type) const { +Location InvokeDexCallingConventionVisitorMIPS::GetReturnLocation(DataType::Type type) const { return MipsReturnLocation(type); } @@ -79,16 +80,16 @@ Location InvokeDexCallingConventionVisitorMIPS::GetMethodLocation() const { return Location::RegisterLocation(kMethodRegisterArgument); } -Location InvokeDexCallingConventionVisitorMIPS::GetNextLocation(Primitive::Type type) { +Location InvokeDexCallingConventionVisitorMIPS::GetNextLocation(DataType::Type type) { Location next_location; switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: { uint32_t gp_index = gp_index_++; if (gp_index < calling_convention.GetNumberOfRegisters()) { next_location = Location::RegisterLocation(calling_convention.GetRegisterAt(gp_index)); @@ -99,7 +100,7 @@ Location InvokeDexCallingConventionVisitorMIPS::GetNextLocation(Primitive::Type break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { uint32_t gp_index = gp_index_; gp_index_ += 2; if (gp_index + 1 < calling_convention.GetNumberOfRegisters()) { @@ -122,32 +123,32 @@ Location InvokeDexCallingConventionVisitorMIPS::GetNextLocation(Primitive::Type // Note: both float and double types are stored in even FPU registers. On 32 bit FPU, double // will take up the even/odd pair, while floats are stored in even regs only. // On 64 bit FPU, both double and float are stored in even registers only. - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { uint32_t float_index = float_index_++; if (float_index < calling_convention.GetNumberOfFpuRegisters()) { next_location = Location::FpuRegisterLocation( calling_convention.GetFpuRegisterAt(float_index)); } else { size_t stack_offset = calling_convention.GetStackOffsetOf(stack_index_); - next_location = Primitive::Is64BitType(type) ? Location::DoubleStackSlot(stack_offset) - : Location::StackSlot(stack_offset); + next_location = DataType::Is64BitType(type) ? Location::DoubleStackSlot(stack_offset) + : Location::StackSlot(stack_offset); } break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unexpected parameter type " << type; break; } // Space on the stack is reserved for all arguments. - stack_index_ += Primitive::Is64BitType(type) ? 2 : 1; + stack_index_ += DataType::Is64BitType(type) ? 2 : 1; return next_location; } -Location InvokeRuntimeCallingConvention::GetReturnLocation(Primitive::Type type) { +Location InvokeRuntimeCallingConvention::GetReturnLocation(DataType::Type type) { return MipsReturnLocation(type); } @@ -172,10 +173,10 @@ class BoundsCheckSlowPathMIPS : public SlowPathCodeMIPS { InvokeRuntimeCallingConvention calling_convention; codegen->EmitParallelMoves(locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimInt, + DataType::Type::kInt32, locations->InAt(1), Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt); + DataType::Type::kInt32); QuickEntrypointEnum entrypoint = instruction_->AsBoundsCheck()->IsStringCharAt() ? kQuickThrowStringBounds : kQuickThrowArrayBounds; @@ -278,7 +279,7 @@ class LoadClassSlowPathMIPS : public SlowPathCodeMIPS { // Move the class to the desired location. if (out.IsValid()) { DCHECK(out.IsRegister() && !locations->GetLiveRegisters()->ContainsCoreRegister(out.reg())); - Primitive::Type type = instruction_->GetType(); + DataType::Type type = instruction_->GetType(); mips_codegen->MoveLocation(out, Location::RegisterLocation(calling_convention.GetRegisterAt(0)), type); @@ -290,7 +291,9 @@ class LoadClassSlowPathMIPS : public SlowPathCodeMIPS { // For non-Baker read barriers we need to re-calculate the address of // the class entry. const bool isR6 = mips_codegen->GetInstructionSetFeatures().IsR6(); - Register base = isR6 ? ZERO : locations->InAt(0).AsRegister<Register>(); + const bool has_irreducible_loops = codegen->GetGraph()->HasIrreducibleLoops(); + Register base = + (isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>(); CodeGeneratorMIPS::PcRelativePatchInfo* info_high = mips_codegen->NewTypeBssEntryPatch(cls_->GetDexFile(), type_index); CodeGeneratorMIPS::PcRelativePatchInfo* info_low = @@ -369,7 +372,7 @@ class LoadStringSlowPathMIPS : public SlowPathCodeMIPS { &info_low->label); } - Primitive::Type type = instruction_->GetType(); + DataType::Type type = instruction_->GetType(); mips_codegen->MoveLocation(locations->Out(), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), type); @@ -380,7 +383,9 @@ class LoadStringSlowPathMIPS : public SlowPathCodeMIPS { // For non-Baker read barriers we need to re-calculate the address of // the string entry. const bool isR6 = mips_codegen->GetInstructionSetFeatures().IsR6(); - Register base = isR6 ? ZERO : locations->InAt(0).AsRegister<Register>(); + const bool has_irreducible_loops = codegen->GetGraph()->HasIrreducibleLoops(); + Register base = + (isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>(); CodeGeneratorMIPS::PcRelativePatchInfo* info_high = mips_codegen->NewStringBssEntryPatch(load->GetDexFile(), string_index); CodeGeneratorMIPS::PcRelativePatchInfo* info_low = @@ -485,14 +490,14 @@ class TypeCheckSlowPathMIPS : public SlowPathCodeMIPS { InvokeRuntimeCallingConvention calling_convention; codegen->EmitParallelMoves(locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, locations->InAt(1), Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot); + DataType::Type::kReference); if (instruction_->IsInstanceOf()) { mips_codegen->InvokeRuntime(kQuickInstanceofNonTrivial, instruction_, dex_pc, this); CheckEntrypointTypes<kQuickInstanceofNonTrivial, size_t, mirror::Object*, mirror::Class*>(); - Primitive::Type ret_type = instruction_->GetType(); + DataType::Type ret_type = instruction_->GetType(); Location ret_loc = calling_convention.GetReturnLocation(ret_type); mips_codegen->MoveLocation(locations->Out(), ret_loc, ret_type); } else { @@ -554,17 +559,17 @@ class ArraySetSlowPathMIPS : public SlowPathCodeMIPS { parallel_move.AddMove( locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove( locations->InAt(1), Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); parallel_move.AddMove( locations->InAt(2), Location::RegisterLocation(calling_convention.GetRegisterAt(2)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); @@ -964,16 +969,16 @@ class ReadBarrierForHeapReferenceSlowPathMIPS : public SlowPathCodeMIPS { HParallelMove parallel_move(codegen->GetGraph()->GetArena()); parallel_move.AddMove(ref_, Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove(obj_, Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); if (index.IsValid()) { parallel_move.AddMove(index, Location::RegisterLocation(calling_convention.GetRegisterAt(2)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); } else { @@ -987,8 +992,8 @@ class ReadBarrierForHeapReferenceSlowPathMIPS : public SlowPathCodeMIPS { CheckEntrypointTypes< kQuickReadBarrierSlow, mirror::Object*, mirror::Object*, mirror::Object*, uint32_t>(); mips_codegen->MoveLocation(out_, - calling_convention.GetReturnLocation(Primitive::kPrimNot), - Primitive::kPrimNot); + calling_convention.GetReturnLocation(DataType::Type::kReference), + DataType::Type::kReference); RestoreLiveRegisters(codegen, locations); __ B(GetExitLabel()); @@ -1053,15 +1058,15 @@ class ReadBarrierForRootSlowPathMIPS : public SlowPathCodeMIPS { CodeGeneratorMIPS* mips_codegen = down_cast<CodeGeneratorMIPS*>(codegen); mips_codegen->MoveLocation(Location::RegisterLocation(calling_convention.GetRegisterAt(0)), root_, - Primitive::kPrimNot); + DataType::Type::kReference); mips_codegen->InvokeRuntime(kQuickReadBarrierForRootSlow, instruction_, instruction_->GetDexPc(), this); CheckEntrypointTypes<kQuickReadBarrierForRootSlow, mirror::Object*, GcRoot<mirror::Object>*>(); mips_codegen->MoveLocation(out_, - calling_convention.GetReturnLocation(Primitive::kPrimNot), - Primitive::kPrimNot); + calling_convention.GetReturnLocation(DataType::Type::kReference), + DataType::Type::kReference); RestoreLiveRegisters(codegen, locations); __ B(GetExitLabel()); @@ -1160,7 +1165,7 @@ void ParallelMoveResolverMIPS::EmitMove(size_t index) { void ParallelMoveResolverMIPS::EmitSwap(size_t index) { DCHECK_LT(index, moves_.size()); MoveOperands* move = moves_[index]; - Primitive::Type type = move->GetType(); + DataType::Type type = move->GetType(); Location loc1 = move->GetDestination(); Location loc2 = move->GetSource(); @@ -1181,12 +1186,12 @@ void ParallelMoveResolverMIPS::EmitSwap(size_t index) { } else if (loc1.IsFpuRegister() && loc2.IsFpuRegister()) { FRegister f1 = loc1.AsFpuRegister<FRegister>(); FRegister f2 = loc2.AsFpuRegister<FRegister>(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ MovS(FTMP, f2); __ MovS(f2, f1); __ MovS(f1, FTMP); } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); __ MovD(FTMP, f2); __ MovD(f2, f1); __ MovD(f1, FTMP); @@ -1194,7 +1199,7 @@ void ParallelMoveResolverMIPS::EmitSwap(size_t index) { } else if ((loc1.IsRegister() && loc2.IsFpuRegister()) || (loc1.IsFpuRegister() && loc2.IsRegister())) { // Swap FPR and GPR. - DCHECK_EQ(type, Primitive::kPrimFloat); // Can only swap a float. + DCHECK_EQ(type, DataType::Type::kFloat32); // Can only swap a float. FRegister f1 = loc1.IsFpuRegister() ? loc1.AsFpuRegister<FRegister>() : loc2.AsFpuRegister<FRegister>(); Register r2 = loc1.IsRegister() ? loc1.AsRegister<Register>() : loc2.AsRegister<Register>(); @@ -1216,7 +1221,7 @@ void ParallelMoveResolverMIPS::EmitSwap(size_t index) { } else if ((loc1.IsRegisterPair() && loc2.IsFpuRegister()) || (loc1.IsFpuRegister() && loc2.IsRegisterPair())) { // Swap FPR and GPR register pair. - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); FRegister f1 = loc1.IsFpuRegister() ? loc1.AsFpuRegister<FRegister>() : loc2.AsFpuRegister<FRegister>(); Register r2_l = loc1.IsRegisterPair() ? loc1.AsRegisterPairLow<Register>() @@ -1262,12 +1267,12 @@ void ParallelMoveResolverMIPS::EmitSwap(size_t index) { FRegister reg = loc1.IsFpuRegister() ? loc1.AsFpuRegister<FRegister>() : loc2.AsFpuRegister<FRegister>(); intptr_t offset = loc1.IsFpuRegister() ? loc2.GetStackIndex() : loc1.GetStackIndex(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ MovS(FTMP, reg); __ LoadSFromOffset(reg, SP, offset); __ StoreSToOffset(FTMP, SP, offset); } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); __ MovD(FTMP, reg); __ LoadDFromOffset(reg, SP, offset); __ StoreDToOffset(FTMP, SP, offset); @@ -1457,7 +1462,7 @@ VectorRegister VectorRegisterFrom(Location location) { void CodeGeneratorMIPS::MoveLocation(Location destination, Location source, - Primitive::Type dst_type) { + DataType::Type dst_type) { if (source.Equals(destination)) { return; } @@ -1493,10 +1498,10 @@ void CodeGeneratorMIPS::MoveLocation(Location destination, } } else if (destination.IsFpuRegister()) { if (source.IsRegister()) { - DCHECK(!Primitive::Is64BitType(dst_type)); + DCHECK(!DataType::Is64BitType(dst_type)); __ Mtc1(source.AsRegister<Register>(), destination.AsFpuRegister<FRegister>()); } else if (source.IsRegisterPair()) { - DCHECK(Primitive::Is64BitType(dst_type)); + DCHECK(DataType::Is64BitType(dst_type)); FRegister dst = destination.AsFpuRegister<FRegister>(); Register src_high = source.AsRegisterPairHigh<Register>(); Register src_low = source.AsRegisterPairLow<Register>(); @@ -1507,20 +1512,20 @@ void CodeGeneratorMIPS::MoveLocation(Location destination, __ MoveV(VectorRegisterFrom(destination), VectorRegisterFrom(source)); } else { - if (Primitive::Is64BitType(dst_type)) { + if (DataType::Is64BitType(dst_type)) { __ MovD(destination.AsFpuRegister<FRegister>(), source.AsFpuRegister<FRegister>()); } else { - DCHECK_EQ(dst_type, Primitive::kPrimFloat); + DCHECK_EQ(dst_type, DataType::Type::kFloat32); __ MovS(destination.AsFpuRegister<FRegister>(), source.AsFpuRegister<FRegister>()); } } } else if (source.IsSIMDStackSlot()) { __ LoadQFromOffset(destination.AsFpuRegister<FRegister>(), SP, source.GetStackIndex()); } else if (source.IsDoubleStackSlot()) { - DCHECK(Primitive::Is64BitType(dst_type)); + DCHECK(DataType::Is64BitType(dst_type)); __ LoadDFromOffset(destination.AsFpuRegister<FRegister>(), SP, source.GetStackIndex()); } else { - DCHECK(!Primitive::Is64BitType(dst_type)); + DCHECK(!DataType::Is64BitType(dst_type)); DCHECK(source.IsStackSlot()) << "Cannot move from " << source << " to " << destination; __ LoadSFromOffset(destination.AsFpuRegister<FRegister>(), SP, source.GetStackIndex()); } @@ -1628,10 +1633,10 @@ void CodeGeneratorMIPS::AddLocationAsTemp(Location location, LocationSummary* lo } } -template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> +template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> inline void CodeGeneratorMIPS::EmitPcRelativeLinkerPatches( const ArenaDeque<PcRelativePatchInfo>& infos, - ArenaVector<LinkerPatch>* linker_patches) { + ArenaVector<linker::LinkerPatch>* linker_patches) { for (const PcRelativePatchInfo& info : infos) { const DexFile& dex_file = info.target_dex_file; size_t offset_or_index = info.offset_or_index; @@ -1647,7 +1652,7 @@ inline void CodeGeneratorMIPS::EmitPcRelativeLinkerPatches( } } -void CodeGeneratorMIPS::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) { +void CodeGeneratorMIPS::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) { DCHECK(linker_patches->empty()); size_t size = pc_relative_method_patches_.size() + @@ -1658,25 +1663,25 @@ void CodeGeneratorMIPS::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patch string_bss_entry_patches_.size(); linker_patches->reserve(size); if (GetCompilerOptions().IsBootImage()) { - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(pc_relative_method_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeTypePatch>(pc_relative_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeStringPatch>(pc_relative_string_patches_, - linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>( + pc_relative_method_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>( + pc_relative_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>( + pc_relative_string_patches_, linker_patches); } else { DCHECK(pc_relative_method_patches_.empty()); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(pc_relative_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(pc_relative_string_patches_, - linker_patches); - } - EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(string_bss_entry_patches_, - linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>( + pc_relative_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>( + pc_relative_string_patches_, linker_patches); + } + EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( + method_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>( + type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>( + string_bss_entry_patches_, linker_patches); DCHECK_EQ(size, linker_patches->size()); } @@ -2017,9 +2022,9 @@ InstructionCodeGeneratorMIPS::InstructionCodeGeneratorMIPS(HGraph* graph, void LocationsBuilderMIPS::HandleBinaryOp(HBinaryOperation* instruction) { DCHECK_EQ(instruction->InputCount(), 2U); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); - Primitive::Type type = instruction->GetResultType(); + DataType::Type type = instruction->GetResultType(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RequiresRegister()); HInstruction* right = instruction->InputAt(1); bool can_use_imm = false; @@ -2042,15 +2047,15 @@ void LocationsBuilderMIPS::HandleBinaryOp(HBinaryOperation* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK(instruction->IsAdd() || instruction->IsSub()); locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); @@ -2063,11 +2068,11 @@ void LocationsBuilderMIPS::HandleBinaryOp(HBinaryOperation* instruction) { } void InstructionCodeGeneratorMIPS::HandleBinaryOp(HBinaryOperation* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { Register dst = locations->Out().AsRegister<Register>(); Register lhs = locations->InAt(0).AsRegister<Register>(); Location rhs_location = locations->InAt(1); @@ -2111,7 +2116,7 @@ void InstructionCodeGeneratorMIPS::HandleBinaryOp(HBinaryOperation* instruction) break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Register dst_high = locations->Out().AsRegisterPairHigh<Register>(); Register dst_low = locations->Out().AsRegisterPairLow<Register>(); Register lhs_high = locations->InAt(0).AsRegisterPairHigh<Register>(); @@ -2252,20 +2257,20 @@ void InstructionCodeGeneratorMIPS::HandleBinaryOp(HBinaryOperation* instruction) break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { FRegister dst = locations->Out().AsFpuRegister<FRegister>(); FRegister lhs = locations->InAt(0).AsFpuRegister<FRegister>(); FRegister rhs = locations->InAt(1).AsFpuRegister<FRegister>(); if (instruction->IsAdd()) { - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ AddS(dst, lhs, rhs); } else { __ AddD(dst, lhs, rhs); } } else { DCHECK(instruction->IsSub()); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ SubS(dst, lhs, rhs); } else { __ SubD(dst, lhs, rhs); @@ -2283,14 +2288,14 @@ void LocationsBuilderMIPS::HandleShift(HBinaryOperation* instr) { DCHECK(instr->IsShl() || instr->IsShr() || instr->IsUShr() || instr->IsRor()); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr); - Primitive::Type type = instr->GetResultType(); + DataType::Type type = instr->GetResultType(); switch (type) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instr->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instr->InputAt(1))); locations->SetOut(Location::RequiresRegister()); @@ -2305,20 +2310,20 @@ static constexpr size_t kMipsBitsPerWord = kMipsWordSize * kBitsPerByte; void InstructionCodeGeneratorMIPS::HandleShift(HBinaryOperation* instr) { DCHECK(instr->IsShl() || instr->IsShr() || instr->IsUShr() || instr->IsRor()); LocationSummary* locations = instr->GetLocations(); - Primitive::Type type = instr->GetType(); + DataType::Type type = instr->GetType(); Location rhs_location = locations->InAt(1); bool use_imm = rhs_location.IsConstant(); Register rhs_reg = use_imm ? ZERO : rhs_location.AsRegister<Register>(); int64_t rhs_imm = use_imm ? CodeGenerator::GetInt64ValueOf(rhs_location.GetConstant()) : 0; const uint32_t shift_mask = - (type == Primitive::kPrimInt) ? kMaxIntShiftDistance : kMaxLongShiftDistance; + (type == DataType::Type::kInt32) ? kMaxIntShiftDistance : kMaxLongShiftDistance; const uint32_t shift_value = rhs_imm & shift_mask; // Are the INS (Insert Bit Field) and ROTR instructions supported? bool has_ins_rotr = codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { Register dst = locations->Out().AsRegister<Register>(); Register lhs = locations->InAt(0).AsRegister<Register>(); if (use_imm) { @@ -2367,7 +2372,7 @@ void InstructionCodeGeneratorMIPS::HandleShift(HBinaryOperation* instr) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Register dst_high = locations->Out().AsRegisterPairHigh<Register>(); Register dst_low = locations->Out().AsRegisterPairLow<Register>(); Register lhs_high = locations->InAt(0).AsRegisterPairHigh<Register>(); @@ -2531,9 +2536,9 @@ void InstructionCodeGeneratorMIPS::VisitAnd(HAnd* instruction) { } void LocationsBuilderMIPS::VisitArrayGet(HArrayGet* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); bool object_array_get_with_read_barrier = - kEmitCompilerReadBarrier && (type == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (type == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, object_array_get_with_read_barrier @@ -2544,7 +2549,7 @@ void LocationsBuilderMIPS::VisitArrayGet(HArrayGet* instruction) { } locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - if (Primitive::IsFloatingPointType(type)) { + if (DataType::IsFloatingPointType(type)) { locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); } else { // The output overlaps in the case of an object array get with @@ -2583,11 +2588,11 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { uint32_t data_offset = CodeGenerator::GetArrayDataOffset(instruction); auto null_checker = GetImplicitNullChecker(instruction, codegen_); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); const bool maybe_compressed_char_at = mirror::kUseStringCompression && instruction->IsStringCharAt(); switch (type) { - case Primitive::kPrimBoolean: { + case DataType::Type::kBool: { Register out = out_loc.AsRegister<Register>(); if (index.IsConstant()) { size_t offset = @@ -2600,7 +2605,7 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimByte: { + case DataType::Type::kInt8: { Register out = out_loc.AsRegister<Register>(); if (index.IsConstant()) { size_t offset = @@ -2613,7 +2618,7 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimShort: { + case DataType::Type::kInt16: { Register out = out_loc.AsRegister<Register>(); if (index.IsConstant()) { size_t offset = @@ -2626,7 +2631,7 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimChar: { + case DataType::Type::kUint16: { Register out = out_loc.AsRegister<Register>(); if (maybe_compressed_char_at) { uint32_t count_offset = mirror::String::CountOffset().Uint32Value(); @@ -2678,7 +2683,7 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { DCHECK_EQ(sizeof(mirror::HeapReference<mirror::Object>), sizeof(int32_t)); Register out = out_loc.AsRegister<Register>(); if (index.IsConstant()) { @@ -2692,7 +2697,7 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { static_assert( sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t), "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes."); @@ -2752,7 +2757,7 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Register out = out_loc.AsRegisterPairLow<Register>(); if (index.IsConstant()) { size_t offset = @@ -2765,7 +2770,7 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { FRegister out = out_loc.AsFpuRegister<FRegister>(); if (index.IsConstant()) { size_t offset = @@ -2778,7 +2783,7 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { FRegister out = out_loc.AsFpuRegister<FRegister>(); if (index.IsConstant()) { size_t offset = @@ -2791,7 +2796,7 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); } @@ -2836,7 +2841,7 @@ Location LocationsBuilderMIPS::FpuRegisterOrConstantForStore(HInstruction* instr } void LocationsBuilderMIPS::VisitArraySet(HArraySet* instruction) { - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); @@ -2850,7 +2855,7 @@ void LocationsBuilderMIPS::VisitArraySet(HArraySet* instruction) { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - if (Primitive::IsFloatingPointType(instruction->InputAt(2)->GetType())) { + if (DataType::IsFloatingPointType(instruction->InputAt(2)->GetType())) { locations->SetInAt(2, FpuRegisterOrConstantForStore(instruction->InputAt(2))); } else { locations->SetInAt(2, RegisterOrZeroConstant(instruction->InputAt(2))); @@ -2866,7 +2871,7 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { Register obj = locations->InAt(0).AsRegister<Register>(); Location index = locations->InAt(1); Location value_location = locations->InAt(2); - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); @@ -2874,8 +2879,8 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { Register base_reg = index.IsConstant() ? obj : TMP; switch (value_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: { + case DataType::Type::kBool: + case DataType::Type::kInt8: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1; @@ -2892,8 +2897,8 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimShort: - case Primitive::kPrimChar: { + case DataType::Type::kInt16: + case DataType::Type::kUint16: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2; @@ -2910,7 +2915,7 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4; @@ -2927,7 +2932,7 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { if (value_location.IsConstant()) { // Just setting null. uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); @@ -3042,7 +3047,7 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8; @@ -3059,7 +3064,7 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4; @@ -3076,7 +3081,7 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8; @@ -3093,7 +3098,7 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); } @@ -3378,31 +3383,31 @@ void InstructionCodeGeneratorMIPS::VisitClinitCheck(HClinitCheck* check) { } void LocationsBuilderMIPS::VisitCompare(HCompare* compare) { - Primitive::Type in_type = compare->InputAt(0)->GetType(); + DataType::Type in_type = compare->InputAt(0)->GetType(); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall); switch (in_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); // Output overlaps because it is written before doing the low comparison. locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -3416,18 +3421,18 @@ void LocationsBuilderMIPS::VisitCompare(HCompare* compare) { void InstructionCodeGeneratorMIPS::VisitCompare(HCompare* instruction) { LocationSummary* locations = instruction->GetLocations(); Register res = locations->Out().AsRegister<Register>(); - Primitive::Type in_type = instruction->InputAt(0)->GetType(); + DataType::Type in_type = instruction->InputAt(0)->GetType(); bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); // 0 if: left == right // 1 if: left > right // -1 if: left < right switch (in_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: { Register lhs = locations->InAt(0).AsRegister<Register>(); Register rhs = locations->InAt(1).AsRegister<Register>(); __ Slt(TMP, lhs, rhs); @@ -3435,7 +3440,7 @@ void InstructionCodeGeneratorMIPS::VisitCompare(HCompare* instruction) { __ Subu(res, res, TMP); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { MipsLabel done; Register lhs_high = locations->InAt(0).AsRegisterPairHigh<Register>(); Register lhs_low = locations->InAt(0).AsRegisterPairLow<Register>(); @@ -3453,7 +3458,7 @@ void InstructionCodeGeneratorMIPS::VisitCompare(HCompare* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { bool gt_bias = instruction->IsGtBias(); FRegister lhs = locations->InAt(0).AsFpuRegister<FRegister>(); FRegister rhs = locations->InAt(1).AsFpuRegister<FRegister>(); @@ -3493,7 +3498,7 @@ void InstructionCodeGeneratorMIPS::VisitCompare(HCompare* instruction) { __ Bind(&done); break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { bool gt_bias = instruction->IsGtBias(); FRegister lhs = locations->InAt(0).AsFpuRegister<FRegister>(); FRegister rhs = locations->InAt(1).AsFpuRegister<FRegister>(); @@ -3543,13 +3548,13 @@ void LocationsBuilderMIPS::HandleCondition(HCondition* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); switch (instruction->InputAt(0)->GetType()) { default: - case Primitive::kPrimLong: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); break; @@ -3564,7 +3569,7 @@ void InstructionCodeGeneratorMIPS::HandleCondition(HCondition* instruction) { return; } - Primitive::Type type = instruction->InputAt(0)->GetType(); + DataType::Type type = instruction->InputAt(0)->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { @@ -3573,12 +3578,12 @@ void InstructionCodeGeneratorMIPS::HandleCondition(HCondition* instruction) { GenerateIntCompare(instruction->GetCondition(), locations); return; - case Primitive::kPrimLong: + case DataType::Type::kInt64: GenerateLongCompare(instruction->GetCondition(), locations); return; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: GenerateFpCompare(instruction->GetCondition(), instruction->IsGtBias(), type, locations); return; } @@ -3586,7 +3591,7 @@ void InstructionCodeGeneratorMIPS::HandleCondition(HCondition* instruction) { void InstructionCodeGeneratorMIPS::DivRemOneOrMinusOne(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimInt); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt32); LocationSummary* locations = instruction->GetLocations(); Location second = locations->InAt(1); @@ -3610,7 +3615,7 @@ void InstructionCodeGeneratorMIPS::DivRemOneOrMinusOne(HBinaryOperation* instruc void InstructionCodeGeneratorMIPS::DivRemByPowerOfTwo(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimInt); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt32); LocationSummary* locations = instruction->GetLocations(); Location second = locations->InAt(1); @@ -3659,7 +3664,7 @@ void InstructionCodeGeneratorMIPS::DivRemByPowerOfTwo(HBinaryOperation* instruct void InstructionCodeGeneratorMIPS::GenerateDivRemWithAnyConstant(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimInt); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt32); LocationSummary* locations = instruction->GetLocations(); Location second = locations->InAt(1); @@ -3710,7 +3715,7 @@ void InstructionCodeGeneratorMIPS::GenerateDivRemWithAnyConstant(HBinaryOperatio void InstructionCodeGeneratorMIPS::GenerateDivRemIntegral(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimInt); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt32); LocationSummary* locations = instruction->GetLocations(); Register out = locations->Out().AsRegister<Register>(); @@ -3749,21 +3754,21 @@ void InstructionCodeGeneratorMIPS::GenerateDivRemIntegral(HBinaryOperation* inst } void LocationsBuilderMIPS::VisitDiv(HDiv* div) { - Primitive::Type type = div->GetResultType(); - LocationSummary::CallKind call_kind = (type == Primitive::kPrimLong) + DataType::Type type = div->GetResultType(); + LocationSummary::CallKind call_kind = (type == DataType::Type::kInt64) ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall; LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, call_kind); switch (type) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(div->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::RegisterPairLocation( calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1))); @@ -3773,8 +3778,8 @@ void LocationsBuilderMIPS::VisitDiv(HDiv* div) { break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -3786,24 +3791,24 @@ void LocationsBuilderMIPS::VisitDiv(HDiv* div) { } void InstructionCodeGeneratorMIPS::VisitDiv(HDiv* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: GenerateDivRemIntegral(instruction); break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { codegen_->InvokeRuntime(kQuickLdiv, instruction, instruction->GetDexPc()); CheckEntrypointTypes<kQuickLdiv, int64_t, int64_t, int64_t>(); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { FRegister dst = locations->Out().AsFpuRegister<FRegister>(); FRegister lhs = locations->InAt(0).AsFpuRegister<FRegister>(); FRegister rhs = locations->InAt(1).AsFpuRegister<FRegister>(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ DivS(dst, lhs, rhs); } else { __ DivD(dst, lhs, rhs); @@ -3824,14 +3829,14 @@ void InstructionCodeGeneratorMIPS::VisitDivZeroCheck(HDivZeroCheck* instruction) SlowPathCodeMIPS* slow_path = new (GetGraph()->GetArena()) DivZeroCheckSlowPathMIPS(instruction); codegen_->AddSlowPath(slow_path); Location value = instruction->GetLocations()->InAt(0); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: { if (value.IsConstant()) { if (value.GetConstant()->AsIntConstant()->GetValue() == 0) { __ B(slow_path->GetEntryLabel()); @@ -3845,7 +3850,7 @@ void InstructionCodeGeneratorMIPS::VisitDivZeroCheck(HDivZeroCheck* instruction) } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (value.IsConstant()) { if (value.GetConstant()->AsLongConstant()->GetValue() == 0) { __ B(slow_path->GetEntryLabel()); @@ -4781,13 +4786,13 @@ void InstructionCodeGeneratorMIPS::GenerateLongCompareAndBranch(IfCondition cond void InstructionCodeGeneratorMIPS::GenerateFpCompare(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* locations) { Register dst = locations->Out().AsRegister<Register>(); FRegister lhs = locations->InAt(0).AsFpuRegister<FRegister>(); FRegister rhs = locations->InAt(1).AsFpuRegister<FRegister>(); bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { if (isR6) { switch (cond) { case kCondEQ: @@ -4894,7 +4899,7 @@ void InstructionCodeGeneratorMIPS::GenerateFpCompare(IfCondition cond, } } } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); if (isR6) { switch (cond) { case kCondEQ: @@ -5005,13 +5010,13 @@ void InstructionCodeGeneratorMIPS::GenerateFpCompare(IfCondition cond, bool InstructionCodeGeneratorMIPS::MaterializeFpCompareR2(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* input_locations, int cc) { FRegister lhs = input_locations->InAt(0).AsFpuRegister<FRegister>(); FRegister rhs = input_locations->InAt(1).AsFpuRegister<FRegister>(); CHECK(!codegen_->GetInstructionSetFeatures().IsR6()); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { switch (cond) { case kCondEQ: __ CeqS(cc, lhs, rhs); @@ -5052,7 +5057,7 @@ bool InstructionCodeGeneratorMIPS::MaterializeFpCompareR2(IfCondition cond, UNREACHABLE(); } } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); switch (cond) { case kCondEQ: __ CeqD(cc, lhs, rhs); @@ -5097,13 +5102,13 @@ bool InstructionCodeGeneratorMIPS::MaterializeFpCompareR2(IfCondition cond, bool InstructionCodeGeneratorMIPS::MaterializeFpCompareR6(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* input_locations, FRegister dst) { FRegister lhs = input_locations->InAt(0).AsFpuRegister<FRegister>(); FRegister rhs = input_locations->InAt(1).AsFpuRegister<FRegister>(); CHECK(codegen_->GetInstructionSetFeatures().IsR6()); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { switch (cond) { case kCondEQ: __ CmpEqS(dst, lhs, rhs); @@ -5144,7 +5149,7 @@ bool InstructionCodeGeneratorMIPS::MaterializeFpCompareR6(IfCondition cond, UNREACHABLE(); } } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); switch (cond) { case kCondEQ: __ CmpEqD(dst, lhs, rhs); @@ -5189,13 +5194,13 @@ bool InstructionCodeGeneratorMIPS::MaterializeFpCompareR6(IfCondition cond, void InstructionCodeGeneratorMIPS::GenerateFpCompareAndBranch(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* locations, MipsLabel* label) { FRegister lhs = locations->InAt(0).AsFpuRegister<FRegister>(); FRegister rhs = locations->InAt(1).AsFpuRegister<FRegister>(); bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { if (isR6) { switch (cond) { case kCondEQ: @@ -5290,7 +5295,7 @@ void InstructionCodeGeneratorMIPS::GenerateFpCompareAndBranch(IfCondition cond, } } } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); if (isR6) { switch (cond) { case kCondEQ: @@ -5432,7 +5437,7 @@ void InstructionCodeGeneratorMIPS::GenerateTestAndBranch(HInstruction* instructi // The condition instruction has not been materialized, use its inputs as // the comparison and its condition as the branch condition. HCondition* condition = cond->AsCondition(); - Primitive::Type type = condition->InputAt(0)->GetType(); + DataType::Type type = condition->InputAt(0)->GetType(); LocationSummary* locations = cond->GetLocations(); IfCondition if_cond = condition->GetCondition(); MipsLabel* branch_target = true_target; @@ -5446,11 +5451,11 @@ void InstructionCodeGeneratorMIPS::GenerateTestAndBranch(HInstruction* instructi default: GenerateIntCompareAndBranch(if_cond, locations, branch_target); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: GenerateLongCompareAndBranch(if_cond, locations, branch_target); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: GenerateFpCompareAndBranch(if_cond, condition->IsGtBias(), type, locations, branch_target); break; } @@ -5515,8 +5520,9 @@ static bool CanMoveConditionally(HSelect* select, bool is_r6, LocationSummary* l HInstruction* cond = select->InputAt(/* condition_input_index */ 2); HCondition* condition = cond->AsCondition(); - Primitive::Type cond_type = materialized ? Primitive::kPrimInt : condition->InputAt(0)->GetType(); - Primitive::Type dst_type = select->GetType(); + DataType::Type cond_type = + materialized ? DataType::Type::kInt32 : condition->InputAt(0)->GetType(); + DataType::Type dst_type = select->GetType(); HConstant* cst_true_value = select->GetTrueValue()->AsConstant(); HConstant* cst_false_value = select->GetFalseValue()->AsConstant(); @@ -5558,7 +5564,7 @@ static bool CanMoveConditionally(HSelect* select, bool is_r6, LocationSummary* l use_const_for_true_in = is_true_value_zero_constant; } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Moving long on int condition. if (is_r6) { if (is_true_value_zero_constant) { @@ -5581,8 +5587,8 @@ static bool CanMoveConditionally(HSelect* select, bool is_r6, LocationSummary* l use_const_for_true_in = is_true_value_zero_constant; } break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: // Moving float/double on int condition. if (is_r6) { if (materialized) { @@ -5613,12 +5619,12 @@ static bool CanMoveConditionally(HSelect* select, bool is_r6, LocationSummary* l break; } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // We don't materialize long comparison now // and use conditional branches instead. break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: switch (dst_type) { default: // Moving int on float/double condition. @@ -5646,7 +5652,7 @@ static bool CanMoveConditionally(HSelect* select, bool is_r6, LocationSummary* l use_const_for_true_in = is_true_value_zero_constant; } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Moving long on float/double condition. if (is_r6) { if (is_true_value_zero_constant) { @@ -5671,8 +5677,8 @@ static bool CanMoveConditionally(HSelect* select, bool is_r6, LocationSummary* l use_const_for_true_in = is_true_value_zero_constant; } break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: // Moving float/double on float/double condition. if (is_r6) { can_move_conditionally = true; @@ -5708,7 +5714,7 @@ static bool CanMoveConditionally(HSelect* select, bool is_r6, LocationSummary* l locations_to_set->SetInAt(0, Location::ConstantLocation(cst_false_value)); } else { locations_to_set->SetInAt(0, - Primitive::IsFloatingPointType(dst_type) + DataType::IsFloatingPointType(dst_type) ? Location::RequiresFpuRegister() : Location::RequiresRegister()); } @@ -5716,7 +5722,7 @@ static bool CanMoveConditionally(HSelect* select, bool is_r6, LocationSummary* l locations_to_set->SetInAt(1, Location::ConstantLocation(cst_true_value)); } else { locations_to_set->SetInAt(1, - Primitive::IsFloatingPointType(dst_type) + DataType::IsFloatingPointType(dst_type) ? Location::RequiresFpuRegister() : Location::RequiresRegister()); } @@ -5729,7 +5735,7 @@ static bool CanMoveConditionally(HSelect* select, bool is_r6, LocationSummary* l if (is_out_same_as_first_in) { locations_to_set->SetOut(Location::SameAsFirstInput()); } else { - locations_to_set->SetOut(Primitive::IsFloatingPointType(dst_type) + locations_to_set->SetOut(DataType::IsFloatingPointType(dst_type) ? Location::RequiresFpuRegister() : Location::RequiresRegister()); } @@ -5747,9 +5753,9 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR2(HSelect* select) { HInstruction* cond = select->InputAt(/* condition_input_index */ 2); Register cond_reg = TMP; int cond_cc = 0; - Primitive::Type cond_type = Primitive::kPrimInt; + DataType::Type cond_type = DataType::Type::kInt32; bool cond_inverted = false; - Primitive::Type dst_type = select->GetType(); + DataType::Type dst_type = select->GetType(); if (IsBooleanValueOrMaterializedCondition(cond)) { cond_reg = locations->InAt(/* condition_input_index */ 2).AsRegister<Register>(); @@ -5760,11 +5766,11 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR2(HSelect* select) { cond_type = condition->InputAt(0)->GetType(); switch (cond_type) { default: - DCHECK_NE(cond_type, Primitive::kPrimLong); + DCHECK_NE(cond_type, DataType::Type::kInt64); cond_inverted = MaterializeIntCompare(if_cond, cond_locations, cond_reg); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: cond_inverted = MaterializeFpCompareR2(if_cond, condition->IsGtBias(), cond_type, @@ -5794,7 +5800,7 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR2(HSelect* select) { __ Movn(dst.AsRegister<Register>(), src_reg, cond_reg); } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (cond_inverted) { __ Movz(dst.AsRegisterPairLow<Register>(), src_reg, cond_reg); __ Movz(dst.AsRegisterPairHigh<Register>(), src_reg_high, cond_reg); @@ -5803,14 +5809,14 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR2(HSelect* select) { __ Movn(dst.AsRegisterPairHigh<Register>(), src_reg_high, cond_reg); } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: if (cond_inverted) { __ MovzS(dst.AsFpuRegister<FRegister>(), src.AsFpuRegister<FRegister>(), cond_reg); } else { __ MovnS(dst.AsFpuRegister<FRegister>(), src.AsFpuRegister<FRegister>(), cond_reg); } break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: if (cond_inverted) { __ MovzD(dst.AsFpuRegister<FRegister>(), src.AsFpuRegister<FRegister>(), cond_reg); } else { @@ -5819,11 +5825,11 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR2(HSelect* select) { break; } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: LOG(FATAL) << "Unreachable"; UNREACHABLE(); - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: switch (dst_type) { default: if (cond_inverted) { @@ -5832,7 +5838,7 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR2(HSelect* select) { __ Movt(dst.AsRegister<Register>(), src_reg, cond_cc); } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (cond_inverted) { __ Movf(dst.AsRegisterPairLow<Register>(), src_reg, cond_cc); __ Movf(dst.AsRegisterPairHigh<Register>(), src_reg_high, cond_cc); @@ -5841,14 +5847,14 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR2(HSelect* select) { __ Movt(dst.AsRegisterPairHigh<Register>(), src_reg_high, cond_cc); } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: if (cond_inverted) { __ MovfS(dst.AsFpuRegister<FRegister>(), src.AsFpuRegister<FRegister>(), cond_cc); } else { __ MovtS(dst.AsFpuRegister<FRegister>(), src.AsFpuRegister<FRegister>(), cond_cc); } break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: if (cond_inverted) { __ MovfD(dst.AsFpuRegister<FRegister>(), src.AsFpuRegister<FRegister>(), cond_cc); } else { @@ -5868,9 +5874,9 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR6(HSelect* select) { HInstruction* cond = select->InputAt(/* condition_input_index */ 2); Register cond_reg = TMP; FRegister fcond_reg = FTMP; - Primitive::Type cond_type = Primitive::kPrimInt; + DataType::Type cond_type = DataType::Type::kInt32; bool cond_inverted = false; - Primitive::Type dst_type = select->GetType(); + DataType::Type dst_type = select->GetType(); if (IsBooleanValueOrMaterializedCondition(cond)) { cond_reg = locations->InAt(/* condition_input_index */ 2).AsRegister<Register>(); @@ -5881,11 +5887,11 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR6(HSelect* select) { cond_type = condition->InputAt(0)->GetType(); switch (cond_type) { default: - DCHECK_NE(cond_type, Primitive::kPrimLong); + DCHECK_NE(cond_type, DataType::Type::kInt64); cond_inverted = MaterializeIntCompare(if_cond, cond_locations, cond_reg); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: cond_inverted = MaterializeFpCompareR6(if_cond, condition->IsGtBias(), cond_type, @@ -5904,7 +5910,7 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR6(HSelect* select) { switch (dst_type) { default: - if (Primitive::IsFloatingPointType(cond_type)) { + if (DataType::IsFloatingPointType(cond_type)) { __ Mfc1(cond_reg, fcond_reg); } if (true_src.IsConstant()) { @@ -5931,8 +5937,8 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR6(HSelect* select) { __ Or(dst.AsRegister<Register>(), AT, TMP); } break; - case Primitive::kPrimLong: { - if (Primitive::IsFloatingPointType(cond_type)) { + case DataType::Type::kInt64: { + if (DataType::IsFloatingPointType(cond_type)) { __ Mfc1(cond_reg, fcond_reg); } Register dst_lo = dst.AsRegisterPairLow<Register>(); @@ -5961,8 +5967,8 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR6(HSelect* select) { } break; } - case Primitive::kPrimFloat: { - if (!Primitive::IsFloatingPointType(cond_type)) { + case DataType::Type::kFloat32: { + if (!DataType::IsFloatingPointType(cond_type)) { // sel*.fmt tests bit 0 of the condition register, account for that. __ Sltu(TMP, ZERO, cond_reg); __ Mtc1(TMP, fcond_reg); @@ -5996,8 +6002,8 @@ void InstructionCodeGeneratorMIPS::GenConditionalMoveR6(HSelect* select) { } break; } - case Primitive::kPrimDouble: { - if (!Primitive::IsFloatingPointType(cond_type)) { + case DataType::Type::kFloat64: { + if (!DataType::IsFloatingPointType(cond_type)) { // sel*.fmt tests bit 0 of the condition register, account for that. __ Sltu(TMP, ZERO, cond_reg); __ Mtc1(TMP, fcond_reg); @@ -6085,11 +6091,11 @@ void CodeGeneratorMIPS::GenerateNop() { } void LocationsBuilderMIPS::HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info) { - Primitive::Type field_type = field_info.GetFieldType(); - bool is_wide = (field_type == Primitive::kPrimLong) || (field_type == Primitive::kPrimDouble); + DataType::Type field_type = field_info.GetFieldType(); + bool is_wide = (field_type == DataType::Type::kInt64) || (field_type == DataType::Type::kFloat64); bool generate_volatile = field_info.IsVolatile() && is_wide; bool object_field_get_with_read_barrier = - kEmitCompilerReadBarrier && (field_type == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (field_type == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary( instruction, generate_volatile @@ -6106,18 +6112,18 @@ void LocationsBuilderMIPS::HandleFieldGet(HInstruction* instruction, const Field InvokeRuntimeCallingConvention calling_convention; // need A0 to hold base + offset locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0))); - if (field_type == Primitive::kPrimLong) { - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimLong)); + if (field_type == DataType::Type::kInt64) { + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kInt64)); } else { // Use Location::Any() to prevent situations when running out of available fp registers. locations->SetOut(Location::Any()); // Need some temp core regs since FP results are returned in core registers - Location reg = calling_convention.GetReturnLocation(Primitive::kPrimLong); + Location reg = calling_convention.GetReturnLocation(DataType::Type::kInt64); locations->AddTemp(Location::RegisterLocation(reg.AsRegisterPairLow<Register>())); locations->AddTemp(Location::RegisterLocation(reg.AsRegisterPairHigh<Register>())); } } else { - if (Primitive::IsFloatingPointType(instruction->GetType())) { + if (DataType::IsFloatingPointType(instruction->GetType())) { locations->SetOut(Location::RequiresFpuRegister()); } else { // The output overlaps in the case of an object field get with @@ -6141,7 +6147,7 @@ void LocationsBuilderMIPS::HandleFieldGet(HInstruction* instruction, const Field void InstructionCodeGeneratorMIPS::HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info, uint32_t dex_pc) { - Primitive::Type type = field_info.GetFieldType(); + DataType::Type type = field_info.GetFieldType(); LocationSummary* locations = instruction->GetLocations(); Location obj_loc = locations->InAt(0); Register obj = obj_loc.AsRegister<Register>(); @@ -6152,28 +6158,28 @@ void InstructionCodeGeneratorMIPS::HandleFieldGet(HInstruction* instruction, auto null_checker = GetImplicitNullChecker(instruction, codegen_); switch (type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: load_type = kLoadUnsignedByte; break; - case Primitive::kPrimByte: + case DataType::Type::kInt8: load_type = kLoadSignedByte; break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: load_type = kLoadSignedHalfword; break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: load_type = kLoadUnsignedHalfword; break; - case Primitive::kPrimInt: - case Primitive::kPrimFloat: - case Primitive::kPrimNot: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: + case DataType::Type::kReference: load_type = kLoadWord; break; - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: load_type = kLoadDoubleword; break; - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; UNREACHABLE(); } @@ -6186,7 +6192,7 @@ void InstructionCodeGeneratorMIPS::HandleFieldGet(HInstruction* instruction, codegen_->RecordPcInfo(instruction, instruction->GetDexPc()); codegen_->InvokeRuntime(kQuickA64Load, instruction, dex_pc); CheckEntrypointTypes<kQuickA64Load, int64_t, volatile const int64_t*>(); - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { // FP results are returned in core registers. Need to move them. if (dst_loc.IsFpuRegister()) { __ Mtc1(locations->GetTemp(1).AsRegister<Register>(), dst_loc.AsFpuRegister<FRegister>()); @@ -6205,7 +6211,7 @@ void InstructionCodeGeneratorMIPS::HandleFieldGet(HInstruction* instruction, } } } else { - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // /* HeapReference<Object> */ dst = *(obj + offset) if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) { Location temp_loc = @@ -6231,9 +6237,9 @@ void InstructionCodeGeneratorMIPS::HandleFieldGet(HInstruction* instruction, // reference, if heap poisoning is enabled). codegen_->MaybeGenerateReadBarrierSlow(instruction, dst_loc, dst_loc, obj_loc, offset); } - } else if (!Primitive::IsFloatingPointType(type)) { + } else if (!DataType::IsFloatingPointType(type)) { Register dst; - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { DCHECK(dst_loc.IsRegisterPair()); dst = dst_loc.AsRegisterPairLow<Register>(); } else { @@ -6244,7 +6250,7 @@ void InstructionCodeGeneratorMIPS::HandleFieldGet(HInstruction* instruction, } else { DCHECK(dst_loc.IsFpuRegister()); FRegister dst = dst_loc.AsFpuRegister<FRegister>(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ LoadSFromOffset(dst, obj, offset, null_checker); } else { __ LoadDFromOffset(dst, obj, offset, null_checker); @@ -6254,14 +6260,14 @@ void InstructionCodeGeneratorMIPS::HandleFieldGet(HInstruction* instruction, // Memory barriers, in the case of references, are handled in the // previous switch statement. - if (is_volatile && (type != Primitive::kPrimNot)) { + if (is_volatile && (type != DataType::Type::kReference)) { GenerateMemoryBarrier(MemBarrierKind::kLoadAny); } } void LocationsBuilderMIPS::HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info) { - Primitive::Type field_type = field_info.GetFieldType(); - bool is_wide = (field_type == Primitive::kPrimLong) || (field_type == Primitive::kPrimDouble); + DataType::Type field_type = field_info.GetFieldType(); + bool is_wide = (field_type == DataType::Type::kInt64) || (field_type == DataType::Type::kFloat64); bool generate_volatile = field_info.IsVolatile() && is_wide; LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary( instruction, generate_volatile ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall); @@ -6271,7 +6277,7 @@ void LocationsBuilderMIPS::HandleFieldSet(HInstruction* instruction, const Field InvokeRuntimeCallingConvention calling_convention; // need A0 to hold base + offset locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0))); - if (field_type == Primitive::kPrimLong) { + if (field_type == DataType::Type::kInt64) { locations->SetInAt(1, Location::RegisterPairLocation( calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3))); } else { @@ -6282,7 +6288,7 @@ void LocationsBuilderMIPS::HandleFieldSet(HInstruction* instruction, const Field locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(3))); } } else { - if (Primitive::IsFloatingPointType(field_type)) { + if (DataType::IsFloatingPointType(field_type)) { locations->SetInAt(1, FpuRegisterOrConstantForStore(instruction->InputAt(1))); } else { locations->SetInAt(1, RegisterOrZeroConstant(instruction->InputAt(1))); @@ -6294,7 +6300,7 @@ void InstructionCodeGeneratorMIPS::HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info, uint32_t dex_pc, bool value_can_be_null) { - Primitive::Type type = field_info.GetFieldType(); + DataType::Type type = field_info.GetFieldType(); LocationSummary* locations = instruction->GetLocations(); Register obj = locations->InAt(0).AsRegister<Register>(); Location value_location = locations->InAt(1); @@ -6305,24 +6311,24 @@ void InstructionCodeGeneratorMIPS::HandleFieldSet(HInstruction* instruction, auto null_checker = GetImplicitNullChecker(instruction, codegen_); switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: store_type = kStoreByte; break; - case Primitive::kPrimShort: - case Primitive::kPrimChar: + case DataType::Type::kInt16: + case DataType::Type::kUint16: store_type = kStoreHalfword; break; - case Primitive::kPrimInt: - case Primitive::kPrimFloat: - case Primitive::kPrimNot: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: + case DataType::Type::kReference: store_type = kStoreWord; break; - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: store_type = kStoreDoubleword; break; - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; UNREACHABLE(); } @@ -6337,7 +6343,7 @@ void InstructionCodeGeneratorMIPS::HandleFieldSet(HInstruction* instruction, // Do implicit Null check. __ Lw(ZERO, locations->GetTemp(0).AsRegister<Register>(), 0); codegen_->RecordPcInfo(instruction, instruction->GetDexPc()); - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { // Pass FP parameters in core registers. if (value_location.IsFpuRegister()) { __ Mfc1(locations->GetTemp(1).AsRegister<Register>(), @@ -6368,9 +6374,9 @@ void InstructionCodeGeneratorMIPS::HandleFieldSet(HInstruction* instruction, if (value_location.IsConstant()) { int64_t value = CodeGenerator::GetInt64ValueOf(value_location.GetConstant()); __ StoreConstToOffset(store_type, value, obj, offset, TMP, null_checker); - } else if (!Primitive::IsFloatingPointType(type)) { + } else if (!DataType::IsFloatingPointType(type)) { Register src; - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { src = value_location.AsRegisterPairLow<Register>(); } else { src = value_location.AsRegister<Register>(); @@ -6379,7 +6385,7 @@ void InstructionCodeGeneratorMIPS::HandleFieldSet(HInstruction* instruction, // Note that in the case where `value` is a null reference, // we do not enter this block, as a null reference does not // need poisoning. - DCHECK_EQ(type, Primitive::kPrimNot); + DCHECK_EQ(type, DataType::Type::kReference); __ PoisonHeapReference(TMP, src); __ StoreToOffset(store_type, TMP, obj, offset, null_checker); } else { @@ -6387,7 +6393,7 @@ void InstructionCodeGeneratorMIPS::HandleFieldSet(HInstruction* instruction, } } else { FRegister src = value_location.AsFpuRegister<FRegister>(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ StoreSToOffset(src, obj, offset, null_checker); } else { __ StoreDToOffset(src, obj, offset, null_checker); @@ -7332,7 +7338,8 @@ void LocationsBuilderMIPS::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invo DCHECK(!invoke->IsStaticWithExplicitClinitCheck()); bool is_r6 = codegen_->GetInstructionSetFeatures().IsR6(); - bool has_extra_input = invoke->HasPcRelativeMethodLoadKind() && !is_r6; + bool has_irreducible_loops = codegen_->GetGraph()->HasIrreducibleLoops(); + bool has_extra_input = invoke->HasPcRelativeMethodLoadKind() && !is_r6 && !has_irreducible_loops; IntrinsicLocationsBuilderMIPS intrinsic(codegen_); if (intrinsic.TryDispatch(invoke)) { @@ -7370,75 +7377,49 @@ static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorMIPS* codegen HLoadString::LoadKind CodeGeneratorMIPS::GetSupportedLoadStringKind( HLoadString::LoadKind desired_string_load_kind) { - // We disable PC-relative load on pre-R6 when there is an irreducible loop, as the optimization - // is incompatible with it. - // TODO: Create as many HMipsComputeBaseMethodAddress instructions as needed for methods - // with irreducible loops. - bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops(); - bool is_r6 = GetInstructionSetFeatures().IsR6(); - bool fallback_load = has_irreducible_loops && !is_r6; switch (desired_string_load_kind) { case HLoadString::LoadKind::kBootImageLinkTimePcRelative: case HLoadString::LoadKind::kBootImageInternTable: case HLoadString::LoadKind::kBssEntry: DCHECK(!Runtime::Current()->UseJitCompilation()); break; - case HLoadString::LoadKind::kBootImageAddress: - break; case HLoadString::LoadKind::kJitTableAddress: DCHECK(Runtime::Current()->UseJitCompilation()); - fallback_load = false; break; + case HLoadString::LoadKind::kBootImageAddress: case HLoadString::LoadKind::kRuntimeCall: - fallback_load = false; break; } - if (fallback_load) { - desired_string_load_kind = HLoadString::LoadKind::kRuntimeCall; - } return desired_string_load_kind; } HLoadClass::LoadKind CodeGeneratorMIPS::GetSupportedLoadClassKind( HLoadClass::LoadKind desired_class_load_kind) { - // We disable PC-relative load on pre-R6 when there is an irreducible loop, as the optimization - // is incompatible with it. - // TODO: Create as many HMipsComputeBaseMethodAddress instructions as needed for methods - // with irreducible loops. - bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops(); - bool is_r6 = GetInstructionSetFeatures().IsR6(); - bool fallback_load = has_irreducible_loops && !is_r6; switch (desired_class_load_kind) { case HLoadClass::LoadKind::kInvalid: LOG(FATAL) << "UNREACHABLE"; UNREACHABLE(); case HLoadClass::LoadKind::kReferrersClass: - fallback_load = false; break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageClassTable: case HLoadClass::LoadKind::kBssEntry: DCHECK(!Runtime::Current()->UseJitCompilation()); break; - case HLoadClass::LoadKind::kBootImageAddress: - break; case HLoadClass::LoadKind::kJitTableAddress: DCHECK(Runtime::Current()->UseJitCompilation()); - fallback_load = false; break; + case HLoadClass::LoadKind::kBootImageAddress: case HLoadClass::LoadKind::kRuntimeCall: - fallback_load = false; break; } - if (fallback_load) { - desired_class_load_kind = HLoadClass::LoadKind::kRuntimeCall; - } return desired_class_load_kind; } Register CodeGeneratorMIPS::GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke, Register temp) { CHECK(!GetInstructionSetFeatures().IsR6()); + CHECK(!GetGraph()->HasIrreducibleLoops()); CHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u); Location location = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex()); if (!invoke->GetLocations()->Intrinsified()) { @@ -7466,27 +7447,7 @@ Register CodeGeneratorMIPS::GetInvokeStaticOrDirectExtraParameter(HInvokeStaticO HInvokeStaticOrDirect::DispatchInfo CodeGeneratorMIPS::GetSupportedInvokeStaticOrDirectDispatch( const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, HInvokeStaticOrDirect* invoke ATTRIBUTE_UNUSED) { - HInvokeStaticOrDirect::DispatchInfo dispatch_info = desired_dispatch_info; - // We disable PC-relative load on pre-R6 when there is an irreducible loop, as the optimization - // is incompatible with it. - // TODO: Create as many HMipsComputeBaseMethodAddress instructions as needed for methods - // with irreducible loops. - bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops(); - bool is_r6 = GetInstructionSetFeatures().IsR6(); - bool fallback_load = has_irreducible_loops && !is_r6; - switch (dispatch_info.method_load_kind) { - case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative: - case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: - break; - default: - fallback_load = false; - break; - } - if (fallback_load) { - dispatch_info.method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall; - dispatch_info.method_load_data = 0; - } - return dispatch_info; + return desired_dispatch_info; } void CodeGeneratorMIPS::GenerateStaticOrDirectCall( @@ -7496,7 +7457,8 @@ void CodeGeneratorMIPS::GenerateStaticOrDirectCall( HInvokeStaticOrDirect::MethodLoadKind method_load_kind = invoke->GetMethodLoadKind(); HInvokeStaticOrDirect::CodePtrLocation code_ptr_location = invoke->GetCodePtrLocation(); bool is_r6 = GetInstructionSetFeatures().IsR6(); - Register base_reg = (invoke->HasPcRelativeMethodLoadKind() && !is_r6) + bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops(); + Register base_reg = (invoke->HasPcRelativeMethodLoadKind() && !is_r6 && !has_irreducible_loops) ? GetInvokeStaticOrDirectExtraParameter(invoke, temp.AsRegister<Register>()) : ZERO; @@ -7635,6 +7597,7 @@ void LocationsBuilderMIPS::VisitLoadClass(HLoadClass* cls) { } DCHECK(!cls->NeedsAccessCheck()); const bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); + const bool has_irreducible_loops = codegen_->GetGraph()->HasIrreducibleLoops(); const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage(); LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier) ? LocationSummary::kCallOnSlowPath @@ -7652,6 +7615,10 @@ void LocationsBuilderMIPS::VisitLoadClass(HLoadClass* cls) { if (isR6) { break; } + if (has_irreducible_loops) { + codegen_->ClobberRA(); + break; + } FALLTHROUGH_INTENDED; case HLoadClass::LoadKind::kReferrersClass: locations->SetInAt(0, Location::RequiresRegister()); @@ -7690,12 +7657,15 @@ void InstructionCodeGeneratorMIPS::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAF Register out = out_loc.AsRegister<Register>(); Register base_or_current_method_reg; bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); + bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops(); switch (load_kind) { // We need an extra register for PC-relative literals on R2. case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageAddress: + case HLoadClass::LoadKind::kBootImageClassTable: case HLoadClass::LoadKind::kBssEntry: - base_or_current_method_reg = isR6 ? ZERO : locations->InAt(0).AsRegister<Register>(); + base_or_current_method_reg = + (isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>(); break; case HLoadClass::LoadKind::kReferrersClass: case HLoadClass::LoadKind::kRuntimeCall: @@ -7741,9 +7711,13 @@ void InstructionCodeGeneratorMIPS::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAF uint32_t address = dchecked_integral_cast<uint32_t>( reinterpret_cast<uintptr_t>(cls->GetClass().Get())); DCHECK_NE(address, 0u); - __ LoadLiteral(out, - base_or_current_method_reg, - codegen_->DeduplicateBootImageAddressLiteral(address)); + if (isR6 || !has_irreducible_loops) { + __ LoadLiteral(out, + base_or_current_method_reg, + codegen_->DeduplicateBootImageAddressLiteral(address)); + } else { + __ LoadConst32(out, address); + } break; } case HLoadClass::LoadKind::kBootImageClassTable: { @@ -7848,6 +7822,7 @@ void LocationsBuilderMIPS::VisitLoadString(HLoadString* load) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(load, call_kind); HLoadString::LoadKind load_kind = load->GetLoadKind(); const bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); + const bool has_irreducible_loops = codegen_->GetGraph()->HasIrreducibleLoops(); switch (load_kind) { // We need an extra register for PC-relative literals on R2. case HLoadString::LoadKind::kBootImageAddress: @@ -7857,6 +7832,10 @@ void LocationsBuilderMIPS::VisitLoadString(HLoadString* load) { if (isR6) { break; } + if (has_irreducible_loops) { + codegen_->ClobberRA(); + break; + } FALLTHROUGH_INTENDED; // We need an extra register for PC-relative dex cache accesses. case HLoadString::LoadKind::kRuntimeCall: @@ -7895,13 +7874,15 @@ void InstructionCodeGeneratorMIPS::VisitLoadString(HLoadString* load) NO_THREAD_ Register out = out_loc.AsRegister<Register>(); Register base_or_current_method_reg; bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); + bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops(); switch (load_kind) { // We need an extra register for PC-relative literals on R2. case HLoadString::LoadKind::kBootImageAddress: case HLoadString::LoadKind::kBootImageLinkTimePcRelative: case HLoadString::LoadKind::kBootImageInternTable: case HLoadString::LoadKind::kBssEntry: - base_or_current_method_reg = isR6 ? ZERO : locations->InAt(0).AsRegister<Register>(); + base_or_current_method_reg = + (isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>(); break; default: base_or_current_method_reg = ZERO; @@ -7925,9 +7906,13 @@ void InstructionCodeGeneratorMIPS::VisitLoadString(HLoadString* load) NO_THREAD_ uint32_t address = dchecked_integral_cast<uint32_t>( reinterpret_cast<uintptr_t>(load->GetString().Get())); DCHECK_NE(address, 0u); - __ LoadLiteral(out, - base_or_current_method_reg, - codegen_->DeduplicateBootImageAddressLiteral(address)); + if (isR6 || !has_irreducible_loops) { + __ LoadLiteral(out, + base_or_current_method_reg, + codegen_->DeduplicateBootImageAddressLiteral(address)); + } else { + __ LoadConst32(out, address); + } return; } case HLoadString::LoadKind::kBootImageInternTable: { @@ -8026,15 +8011,15 @@ void LocationsBuilderMIPS::VisitMul(HMul* mul) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(mul, LocationSummary::kNoCall); switch (mul->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -8046,12 +8031,12 @@ void LocationsBuilderMIPS::VisitMul(HMul* mul) { } void InstructionCodeGeneratorMIPS::VisitMul(HMul* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); LocationSummary* locations = instruction->GetLocations(); bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { Register dst = locations->Out().AsRegister<Register>(); Register lhs = locations->InAt(0).AsRegister<Register>(); Register rhs = locations->InAt(1).AsRegister<Register>(); @@ -8063,7 +8048,7 @@ void InstructionCodeGeneratorMIPS::VisitMul(HMul* instruction) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Register dst_high = locations->Out().AsRegisterPairHigh<Register>(); Register dst_low = locations->Out().AsRegisterPairLow<Register>(); Register lhs_high = locations->InAt(0).AsRegisterPairHigh<Register>(); @@ -8100,12 +8085,12 @@ void InstructionCodeGeneratorMIPS::VisitMul(HMul* instruction) { } break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { FRegister dst = locations->Out().AsFpuRegister<FRegister>(); FRegister lhs = locations->InAt(0).AsFpuRegister<FRegister>(); FRegister rhs = locations->InAt(1).AsFpuRegister<FRegister>(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ MulS(dst, lhs, rhs); } else { __ MulD(dst, lhs, rhs); @@ -8121,14 +8106,14 @@ void LocationsBuilderMIPS::VisitNeg(HNeg* neg) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); switch (neg->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); break; @@ -8139,17 +8124,17 @@ void LocationsBuilderMIPS::VisitNeg(HNeg* neg) { } void InstructionCodeGeneratorMIPS::VisitNeg(HNeg* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { Register dst = locations->Out().AsRegister<Register>(); Register src = locations->InAt(0).AsRegister<Register>(); __ Subu(dst, ZERO, src); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Register dst_high = locations->Out().AsRegisterPairHigh<Register>(); Register dst_low = locations->Out().AsRegisterPairLow<Register>(); Register src_high = locations->InAt(0).AsRegisterPairHigh<Register>(); @@ -8160,11 +8145,11 @@ void InstructionCodeGeneratorMIPS::VisitNeg(HNeg* instruction) { __ Subu(dst_high, dst_high, TMP); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { FRegister dst = locations->Out().AsFpuRegister<FRegister>(); FRegister src = locations->InAt(0).AsFpuRegister<FRegister>(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ NegS(dst, src); } else { __ NegD(dst, src); @@ -8180,7 +8165,7 @@ void LocationsBuilderMIPS::VisitNewArray(HNewArray* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly); InvokeRuntimeCallingConvention calling_convention; - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference)); locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); } @@ -8204,7 +8189,7 @@ void LocationsBuilderMIPS::VisitNewInstance(HNewInstance* instruction) { } else { locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); } - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference)); } void InstructionCodeGeneratorMIPS::VisitNewInstance(HNewInstance* instruction) { @@ -8232,18 +8217,18 @@ void LocationsBuilderMIPS::VisitNot(HNot* instruction) { } void InstructionCodeGeneratorMIPS::VisitNot(HNot* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { Register dst = locations->Out().AsRegister<Register>(); Register src = locations->InAt(0).AsRegister<Register>(); __ Nor(dst, src, ZERO); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Register dst_high = locations->Out().AsRegisterPairHigh<Register>(); Register dst_low = locations->Out().AsRegisterPairLow<Register>(); Register src_high = locations->InAt(0).AsRegisterPairHigh<Register>(); @@ -8355,19 +8340,20 @@ void InstructionCodeGeneratorMIPS::VisitPhi(HPhi* instruction ATTRIBUTE_UNUSED) } void LocationsBuilderMIPS::VisitRem(HRem* rem) { - Primitive::Type type = rem->GetResultType(); - LocationSummary::CallKind call_kind = - (type == Primitive::kPrimInt) ? LocationSummary::kNoCall : LocationSummary::kCallOnMainOnly; + DataType::Type type = rem->GetResultType(); + LocationSummary::CallKind call_kind = (type == DataType::Type::kInt32) + ? LocationSummary::kNoCall + : LocationSummary::kCallOnMainOnly; LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind); switch (type) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(rem->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::RegisterPairLocation( calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1))); @@ -8377,8 +8363,8 @@ void LocationsBuilderMIPS::VisitRem(HRem* rem) { break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); locations->SetInAt(1, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(1))); @@ -8392,23 +8378,23 @@ void LocationsBuilderMIPS::VisitRem(HRem* rem) { } void InstructionCodeGeneratorMIPS::VisitRem(HRem* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); switch (type) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: GenerateDivRemIntegral(instruction); break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { codegen_->InvokeRuntime(kQuickLmod, instruction, instruction->GetDexPc()); CheckEntrypointTypes<kQuickLmod, int64_t, int64_t, int64_t>(); break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { codegen_->InvokeRuntime(kQuickFmodf, instruction, instruction->GetDexPc()); CheckEntrypointTypes<kQuickFmodf, float, float, float>(); break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { codegen_->InvokeRuntime(kQuickFmod, instruction, instruction->GetDexPc()); CheckEntrypointTypes<kQuickFmod, double, double, double>(); break; @@ -8437,7 +8423,7 @@ void InstructionCodeGeneratorMIPS::VisitMemoryBarrier(HMemoryBarrier* memory_bar void LocationsBuilderMIPS::VisitReturn(HReturn* ret) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret); - Primitive::Type return_type = ret->InputAt(0)->GetType(); + DataType::Type return_type = ret->InputAt(0)->GetType(); locations->SetInAt(0, MipsReturnLocation(return_type)); } @@ -8613,33 +8599,33 @@ void InstructionCodeGeneratorMIPS::VisitThrow(HThrow* instruction) { } void LocationsBuilderMIPS::VisitTypeConversion(HTypeConversion* conversion) { - Primitive::Type input_type = conversion->GetInputType(); - Primitive::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); DCHECK_NE(input_type, result_type); bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); - if ((input_type == Primitive::kPrimNot) || (input_type == Primitive::kPrimVoid) || - (result_type == Primitive::kPrimNot) || (result_type == Primitive::kPrimVoid)) { + if ((input_type == DataType::Type::kReference) || (input_type == DataType::Type::kVoid) || + (result_type == DataType::Type::kReference) || (result_type == DataType::Type::kVoid)) { LOG(FATAL) << "Unexpected type conversion from " << input_type << " to " << result_type; } LocationSummary::CallKind call_kind = LocationSummary::kNoCall; if (!isR6 && - ((Primitive::IsFloatingPointType(result_type) && input_type == Primitive::kPrimLong) || - (result_type == Primitive::kPrimLong && Primitive::IsFloatingPointType(input_type)))) { + ((DataType::IsFloatingPointType(result_type) && input_type == DataType::Type::kInt64) || + (result_type == DataType::Type::kInt64 && DataType::IsFloatingPointType(input_type)))) { call_kind = LocationSummary::kCallOnMainOnly; } LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(conversion, call_kind); if (call_kind == LocationSummary::kNoCall) { - if (Primitive::IsFloatingPointType(input_type)) { + if (DataType::IsFloatingPointType(input_type)) { locations->SetInAt(0, Location::RequiresFpuRegister()); } else { locations->SetInAt(0, Location::RequiresRegister()); } - if (Primitive::IsFloatingPointType(result_type)) { + if (DataType::IsFloatingPointType(result_type)) { locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); } else { locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -8647,10 +8633,10 @@ void LocationsBuilderMIPS::VisitTypeConversion(HTypeConversion* conversion) { } else { InvokeRuntimeCallingConvention calling_convention; - if (Primitive::IsFloatingPointType(input_type)) { + if (DataType::IsFloatingPointType(input_type)) { locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); } else { - DCHECK_EQ(input_type, Primitive::kPrimLong); + DCHECK_EQ(input_type, DataType::Type::kInt64); locations->SetInAt(0, Location::RegisterPairLocation( calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1))); } @@ -8661,14 +8647,14 @@ void LocationsBuilderMIPS::VisitTypeConversion(HTypeConversion* conversion) { void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversion) { LocationSummary* locations = conversion->GetLocations(); - Primitive::Type result_type = conversion->GetResultType(); - Primitive::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); bool has_sign_extension = codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(); bool isR6 = codegen_->GetInstructionSetFeatures().IsR6(); DCHECK_NE(input_type, result_type); - if (result_type == Primitive::kPrimLong && Primitive::IsIntegralType(input_type)) { + if (result_type == DataType::Type::kInt64 && DataType::IsIntegralType(input_type)) { Register dst_high = locations->Out().AsRegisterPairHigh<Register>(); Register dst_low = locations->Out().AsRegisterPairLow<Register>(); Register src = locations->InAt(0).AsRegister<Register>(); @@ -8677,17 +8663,17 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi __ Move(dst_low, src); } __ Sra(dst_high, src, 31); - } else if (Primitive::IsIntegralType(result_type) && Primitive::IsIntegralType(input_type)) { + } else if (DataType::IsIntegralType(result_type) && DataType::IsIntegralType(input_type)) { Register dst = locations->Out().AsRegister<Register>(); - Register src = (input_type == Primitive::kPrimLong) + Register src = (input_type == DataType::Type::kInt64) ? locations->InAt(0).AsRegisterPairLow<Register>() : locations->InAt(0).AsRegister<Register>(); switch (result_type) { - case Primitive::kPrimChar: + case DataType::Type::kUint16: __ Andi(dst, src, 0xFFFF); break; - case Primitive::kPrimByte: + case DataType::Type::kInt8: if (has_sign_extension) { __ Seb(dst, src); } else { @@ -8695,7 +8681,7 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi __ Sra(dst, dst, 24); } break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: if (has_sign_extension) { __ Seh(dst, src); } else { @@ -8703,7 +8689,7 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi __ Sra(dst, dst, 16); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: if (dst != src) { __ Move(dst, src); } @@ -8713,8 +8699,8 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi LOG(FATAL) << "Unexpected type conversion from " << input_type << " to " << result_type; } - } else if (Primitive::IsFloatingPointType(result_type) && Primitive::IsIntegralType(input_type)) { - if (input_type == Primitive::kPrimLong) { + } else if (DataType::IsFloatingPointType(result_type) && DataType::IsIntegralType(input_type)) { + if (input_type == DataType::Type::kInt64) { if (isR6) { // cvt.s.l/cvt.d.l requires MIPSR2+ with FR=1. MIPS32R6 is implemented as a secondary // architecture on top of MIPS64R6, which has FR=1, and therefore can use the instruction. @@ -8723,16 +8709,16 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi FRegister dst = locations->Out().AsFpuRegister<FRegister>(); __ Mtc1(src_low, FTMP); __ Mthc1(src_high, FTMP); - if (result_type == Primitive::kPrimFloat) { + if (result_type == DataType::Type::kFloat32) { __ Cvtsl(dst, FTMP); } else { __ Cvtdl(dst, FTMP); } } else { - QuickEntrypointEnum entrypoint = (result_type == Primitive::kPrimFloat) ? kQuickL2f - : kQuickL2d; + QuickEntrypointEnum entrypoint = + (result_type == DataType::Type::kFloat32) ? kQuickL2f : kQuickL2d; codegen_->InvokeRuntime(entrypoint, conversion, conversion->GetDexPc()); - if (result_type == Primitive::kPrimFloat) { + if (result_type == DataType::Type::kFloat32) { CheckEntrypointTypes<kQuickL2f, float, int64_t>(); } else { CheckEntrypointTypes<kQuickL2d, double, int64_t>(); @@ -8742,14 +8728,14 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi Register src = locations->InAt(0).AsRegister<Register>(); FRegister dst = locations->Out().AsFpuRegister<FRegister>(); __ Mtc1(src, FTMP); - if (result_type == Primitive::kPrimFloat) { + if (result_type == DataType::Type::kFloat32) { __ Cvtsw(dst, FTMP); } else { __ Cvtdw(dst, FTMP); } } - } else if (Primitive::IsIntegralType(result_type) && Primitive::IsFloatingPointType(input_type)) { - CHECK(result_type == Primitive::kPrimInt || result_type == Primitive::kPrimLong); + } else if (DataType::IsIntegralType(result_type) && DataType::IsFloatingPointType(input_type)) { + CHECK(result_type == DataType::Type::kInt32 || result_type == DataType::Type::kInt64); // When NAN2008=1 (R6), the truncate instruction caps the output at the minimum/maximum // value of the output type if the input is outside of the range after the truncation or @@ -8767,7 +8753,7 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi // instruction, which will handle such an input the same way irrespective of NAN2008. // Otherwise the input is compared to itself to determine whether it is a NaN or not // in order to return either zero or the minimum value. - if (result_type == Primitive::kPrimLong) { + if (result_type == DataType::Type::kInt64) { if (isR6) { // trunc.l.s/trunc.l.d requires MIPSR2+ with FR=1. MIPS32R6 is implemented as a secondary // architecture on top of MIPS64R6, which has FR=1, and therefore can use the instruction. @@ -8775,7 +8761,7 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi Register dst_high = locations->Out().AsRegisterPairHigh<Register>(); Register dst_low = locations->Out().AsRegisterPairLow<Register>(); - if (input_type == Primitive::kPrimFloat) { + if (input_type == DataType::Type::kFloat32) { __ TruncLS(FTMP, src); } else { __ TruncLD(FTMP, src); @@ -8783,10 +8769,10 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi __ Mfc1(dst_low, FTMP); __ Mfhc1(dst_high, FTMP); } else { - QuickEntrypointEnum entrypoint = (input_type == Primitive::kPrimFloat) ? kQuickF2l - : kQuickD2l; + QuickEntrypointEnum entrypoint = + (input_type == DataType::Type::kFloat32) ? kQuickF2l : kQuickD2l; codegen_->InvokeRuntime(entrypoint, conversion, conversion->GetDexPc()); - if (input_type == Primitive::kPrimFloat) { + if (input_type == DataType::Type::kFloat32) { CheckEntrypointTypes<kQuickF2l, int64_t, float>(); } else { CheckEntrypointTypes<kQuickD2l, int64_t, double>(); @@ -8799,7 +8785,7 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi MipsLabel done; if (!isR6) { - if (input_type == Primitive::kPrimFloat) { + if (input_type == DataType::Type::kFloat32) { uint32_t min_val = bit_cast<uint32_t, float>(std::numeric_limits<int32_t>::min()); __ LoadConst32(TMP, min_val); __ Mtc1(TMP, FTMP); @@ -8810,14 +8796,14 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi __ MoveToFpuHigh(TMP, FTMP); } - if (input_type == Primitive::kPrimFloat) { + if (input_type == DataType::Type::kFloat32) { __ ColeS(0, FTMP, src); } else { __ ColeD(0, FTMP, src); } __ Bc1t(0, &truncate); - if (input_type == Primitive::kPrimFloat) { + if (input_type == DataType::Type::kFloat32) { __ CeqS(0, src, src); } else { __ CeqD(0, src, src); @@ -8830,7 +8816,7 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi __ Bind(&truncate); } - if (input_type == Primitive::kPrimFloat) { + if (input_type == DataType::Type::kFloat32) { __ TruncWS(FTMP, src); } else { __ TruncWD(FTMP, src); @@ -8841,11 +8827,11 @@ void InstructionCodeGeneratorMIPS::VisitTypeConversion(HTypeConversion* conversi __ Bind(&done); } } - } else if (Primitive::IsFloatingPointType(result_type) && - Primitive::IsFloatingPointType(input_type)) { + } else if (DataType::IsFloatingPointType(result_type) && + DataType::IsFloatingPointType(input_type)) { FRegister dst = locations->Out().AsFpuRegister<FRegister>(); FRegister src = locations->InAt(0).AsFpuRegister<FRegister>(); - if (result_type == Primitive::kPrimFloat) { + if (result_type == DataType::Type::kFloat32) { __ Cvtsd(dst, src); } else { __ Cvtds(dst, src); diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h index f15f8c672a..5f2f90004d 100644 --- a/compiler/optimizing/code_generator_mips.h +++ b/compiler/optimizing/code_generator_mips.h @@ -81,8 +81,8 @@ class InvokeDexCallingConventionVisitorMIPS : public InvokeDexCallingConventionV InvokeDexCallingConventionVisitorMIPS() {} virtual ~InvokeDexCallingConventionVisitorMIPS() {} - Location GetNextLocation(Primitive::Type type) OVERRIDE; - Location GetReturnLocation(Primitive::Type type) const OVERRIDE; + Location GetNextLocation(DataType::Type type) OVERRIDE; + Location GetReturnLocation(DataType::Type type) const OVERRIDE; Location GetMethodLocation() const OVERRIDE; private: @@ -100,7 +100,7 @@ class InvokeRuntimeCallingConvention : public CallingConvention<Register, FRegis kRuntimeParameterFpuRegistersLength, kMipsPointerSize) {} - Location GetReturnLocation(Primitive::Type return_type); + Location GetReturnLocation(DataType::Type return_type); private: DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); @@ -116,17 +116,17 @@ class FieldAccessCallingConventionMIPS : public FieldAccessCallingConvention { Location GetFieldIndexLocation() const OVERRIDE { return Location::RegisterLocation(A0); } - Location GetReturnLocation(Primitive::Type type) const OVERRIDE { - return Primitive::Is64BitType(type) + Location GetReturnLocation(DataType::Type type) const OVERRIDE { + return DataType::Is64BitType(type) ? Location::RegisterPairLocation(V0, V1) : Location::RegisterLocation(V0); } - Location GetSetValueLocation(Primitive::Type type, bool is_instance) const OVERRIDE { - return Primitive::Is64BitType(type) + Location GetSetValueLocation(DataType::Type type, bool is_instance) const OVERRIDE { + return DataType::Is64BitType(type) ? Location::RegisterPairLocation(A2, A3) : (is_instance ? Location::RegisterLocation(A2) : Location::RegisterLocation(A1)); } - Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { + Location GetFpuLocation(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return Location::FpuRegisterLocation(F0); } @@ -304,14 +304,14 @@ class InstructionCodeGeneratorMIPS : public InstructionCodeGenerator { MipsLabel* label); void GenerateFpCompare(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* locations); // When the function returns `false` it means that the condition holds if the condition // code flag `cc` is non-zero and doesn't hold if `cc` is zero. If it returns `true`, // the roles of zero and non-zero values of the `cc` flag are exchanged. bool MaterializeFpCompareR2(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* input_locations, int cc); // When the function returns `false` it means that the condition holds if `dst` is non-zero @@ -319,12 +319,12 @@ class InstructionCodeGeneratorMIPS : public InstructionCodeGenerator { // `dst` are exchanged. bool MaterializeFpCompareR6(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* input_locations, FRegister dst); void GenerateFpCompareAndBranch(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* locations, MipsLabel* label); void GenerateTestAndBranch(HInstruction* instruction, @@ -395,7 +395,7 @@ class CodeGeneratorMIPS : public CodeGenerator { const MipsAssembler& GetAssembler() const OVERRIDE { return assembler_; } // Emit linker patches. - void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; + void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) OVERRIDE; void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) OVERRIDE; // Fast path implementation of ReadBarrier::Barrier for a heap @@ -518,7 +518,7 @@ class CodeGeneratorMIPS : public CodeGenerator { // Code generation helpers. - void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; + void MoveLocation(Location dst, Location src, DataType::Type dst_type) OVERRIDE; void MoveConstant(Location destination, int32_t value) OVERRIDE; @@ -541,8 +541,8 @@ class CodeGeneratorMIPS : public CodeGenerator { ParallelMoveResolver* GetMoveResolver() OVERRIDE { return &move_resolver_; } - bool NeedsTwoRegisters(Primitive::Type type) const OVERRIDE { - return type == Primitive::kPrimLong; + bool NeedsTwoRegisters(DataType::Type type) const OVERRIDE { + return type == DataType::Type::kInt64; } // Check if the desired_string_load_kind is supported. If it is, return it, @@ -567,7 +567,7 @@ class CodeGeneratorMIPS : public CodeGenerator { HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE; void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED, - Primitive::Type type ATTRIBUTE_UNUSED) OVERRIDE { + DataType::Type type ATTRIBUTE_UNUSED) OVERRIDE { UNIMPLEMENTED(FATAL) << "Not implemented on MIPS"; } @@ -679,9 +679,9 @@ class CodeGeneratorMIPS : public CodeGenerator { const PcRelativePatchInfo* info_high, ArenaDeque<PcRelativePatchInfo>* patches); - template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> + template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> void EmitPcRelativeLinkerPatches(const ArenaDeque<PcRelativePatchInfo>& infos, - ArenaVector<LinkerPatch>* linker_patches); + ArenaVector<linker::LinkerPatch>* linker_patches); // Labels for each block that will be compiled. MipsLabel* block_labels_; diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index e8ae2db019..7051ccefdc 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -27,6 +27,7 @@ #include "heap_poisoning.h" #include "intrinsics.h" #include "intrinsics_mips64.h" +#include "linker/linker_patch.h" #include "mirror/array-inl.h" #include "mirror/class-inl.h" #include "offsets.h" @@ -46,28 +47,28 @@ constexpr bool kBakerReadBarrierThunksEnableForFields = true; constexpr bool kBakerReadBarrierThunksEnableForArrays = true; constexpr bool kBakerReadBarrierThunksEnableForGcRoots = true; -Location Mips64ReturnLocation(Primitive::Type return_type) { +Location Mips64ReturnLocation(DataType::Type return_type) { switch (return_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: + case DataType::Type::kInt64: return Location::RegisterLocation(V0); - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: return Location::FpuRegisterLocation(F0); - case Primitive::kPrimVoid: + case DataType::Type::kVoid: return Location(); } UNREACHABLE(); } -Location InvokeDexCallingConventionVisitorMIPS64::GetReturnLocation(Primitive::Type type) const { +Location InvokeDexCallingConventionVisitorMIPS64::GetReturnLocation(DataType::Type type) const { return Mips64ReturnLocation(type); } @@ -75,34 +76,34 @@ Location InvokeDexCallingConventionVisitorMIPS64::GetMethodLocation() const { return Location::RegisterLocation(kMethodRegisterArgument); } -Location InvokeDexCallingConventionVisitorMIPS64::GetNextLocation(Primitive::Type type) { +Location InvokeDexCallingConventionVisitorMIPS64::GetNextLocation(DataType::Type type) { Location next_location; - if (type == Primitive::kPrimVoid) { + if (type == DataType::Type::kVoid) { LOG(FATAL) << "Unexpected parameter type " << type; } - if (Primitive::IsFloatingPointType(type) && + if (DataType::IsFloatingPointType(type) && (float_index_ < calling_convention.GetNumberOfFpuRegisters())) { next_location = Location::FpuRegisterLocation( calling_convention.GetFpuRegisterAt(float_index_++)); gp_index_++; - } else if (!Primitive::IsFloatingPointType(type) && + } else if (!DataType::IsFloatingPointType(type) && (gp_index_ < calling_convention.GetNumberOfRegisters())) { next_location = Location::RegisterLocation(calling_convention.GetRegisterAt(gp_index_++)); float_index_++; } else { size_t stack_offset = calling_convention.GetStackOffsetOf(stack_index_); - next_location = Primitive::Is64BitType(type) ? Location::DoubleStackSlot(stack_offset) - : Location::StackSlot(stack_offset); + next_location = DataType::Is64BitType(type) ? Location::DoubleStackSlot(stack_offset) + : Location::StackSlot(stack_offset); } // Space on the stack is reserved for all arguments. - stack_index_ += Primitive::Is64BitType(type) ? 2 : 1; + stack_index_ += DataType::Is64BitType(type) ? 2 : 1; return next_location; } -Location InvokeRuntimeCallingConvention::GetReturnLocation(Primitive::Type type) { +Location InvokeRuntimeCallingConvention::GetReturnLocation(DataType::Type type) { return Mips64ReturnLocation(type); } @@ -127,10 +128,10 @@ class BoundsCheckSlowPathMIPS64 : public SlowPathCodeMIPS64 { InvokeRuntimeCallingConvention calling_convention; codegen->EmitParallelMoves(locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimInt, + DataType::Type::kInt32, locations->InAt(1), Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt); + DataType::Type::kInt32); QuickEntrypointEnum entrypoint = instruction_->AsBoundsCheck()->IsStringCharAt() ? kQuickThrowStringBounds : kQuickThrowArrayBounds; @@ -235,7 +236,7 @@ class LoadClassSlowPathMIPS64 : public SlowPathCodeMIPS64 { // Move the class to the desired location. if (out.IsValid()) { DCHECK(out.IsRegister() && !locations->GetLiveRegisters()->ContainsCoreRegister(out.reg())); - Primitive::Type type = instruction_->GetType(); + DataType::Type type = instruction_->GetType(); mips64_codegen->MoveLocation(out, Location::RegisterLocation(calling_convention.GetRegisterAt(0)), type); @@ -330,7 +331,7 @@ class LoadStringSlowPathMIPS64 : public SlowPathCodeMIPS64 { /* placeholder */ 0x5678); } - Primitive::Type type = instruction_->GetType(); + DataType::Type type = instruction_->GetType(); mips64_codegen->MoveLocation(locations->Out(), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), type); @@ -445,14 +446,14 @@ class TypeCheckSlowPathMIPS64 : public SlowPathCodeMIPS64 { InvokeRuntimeCallingConvention calling_convention; codegen->EmitParallelMoves(locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, locations->InAt(1), Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot); + DataType::Type::kReference); if (instruction_->IsInstanceOf()) { mips64_codegen->InvokeRuntime(kQuickInstanceofNonTrivial, instruction_, dex_pc, this); CheckEntrypointTypes<kQuickInstanceofNonTrivial, size_t, mirror::Object*, mirror::Class*>(); - Primitive::Type ret_type = instruction_->GetType(); + DataType::Type ret_type = instruction_->GetType(); Location ret_loc = calling_convention.GetReturnLocation(ret_type); mips64_codegen->MoveLocation(locations->Out(), ret_loc, ret_type); } else { @@ -514,17 +515,17 @@ class ArraySetSlowPathMIPS64 : public SlowPathCodeMIPS64 { parallel_move.AddMove( locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove( locations->InAt(1), Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); parallel_move.AddMove( locations->InAt(2), Location::RegisterLocation(calling_convention.GetRegisterAt(2)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); @@ -822,7 +823,7 @@ class ReadBarrierForHeapReferenceSlowPathMIPS64 : public SlowPathCodeMIPS64 { void EmitNativeCode(CodeGenerator* codegen) OVERRIDE { CodeGeneratorMIPS64* mips64_codegen = down_cast<CodeGeneratorMIPS64*>(codegen); LocationSummary* locations = instruction_->GetLocations(); - Primitive::Type type = Primitive::kPrimNot; + DataType::Type type = DataType::Type::kReference; GpuRegister reg_out = out_.AsRegister<GpuRegister>(); DCHECK(locations->CanCall()); DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(reg_out)); @@ -911,16 +912,16 @@ class ReadBarrierForHeapReferenceSlowPathMIPS64 : public SlowPathCodeMIPS64 { HParallelMove parallel_move(codegen->GetGraph()->GetArena()); parallel_move.AddMove(ref_, Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove(obj_, Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); if (index.IsValid()) { parallel_move.AddMove(index, Location::RegisterLocation(calling_convention.GetRegisterAt(2)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); } else { @@ -986,7 +987,7 @@ class ReadBarrierForRootSlowPathMIPS64 : public SlowPathCodeMIPS64 { void EmitNativeCode(CodeGenerator* codegen) OVERRIDE { LocationSummary* locations = instruction_->GetLocations(); - Primitive::Type type = Primitive::kPrimNot; + DataType::Type type = DataType::Type::kReference; GpuRegister reg_out = out_.AsRegister<GpuRegister>(); DCHECK(locations->CanCall()); DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(reg_out)); @@ -1001,7 +1002,7 @@ class ReadBarrierForRootSlowPathMIPS64 : public SlowPathCodeMIPS64 { CodeGeneratorMIPS64* mips64_codegen = down_cast<CodeGeneratorMIPS64*>(codegen); mips64_codegen->MoveLocation(Location::RegisterLocation(calling_convention.GetRegisterAt(0)), root_, - Primitive::kPrimNot); + DataType::Type::kReference); mips64_codegen->InvokeRuntime(kQuickReadBarrierForRootSlow, instruction_, instruction_->GetDexPc(), @@ -1253,7 +1254,7 @@ void CodeGeneratorMIPS64::Bind(HBasicBlock* block) { void CodeGeneratorMIPS64::MoveLocation(Location destination, Location source, - Primitive::Type dst_type) { + DataType::Type dst_type) { if (source.Equals(destination)) { return; } @@ -1261,7 +1262,7 @@ void CodeGeneratorMIPS64::MoveLocation(Location destination, // A valid move can always be inferred from the destination and source // locations. When moving from and to a register, the argument type can be // used to generate 32bit instead of 64bit moves. - bool unspecified_type = (dst_type == Primitive::kPrimVoid); + bool unspecified_type = (dst_type == DataType::Type::kVoid); DCHECK_EQ(unspecified_type, false); if (destination.IsRegister() || destination.IsFpuRegister()) { @@ -1272,27 +1273,27 @@ void CodeGeneratorMIPS64::MoveLocation(Location destination, || src_cst->IsFloatConstant() || src_cst->IsNullConstant()))) { // For stack slots and 32bit constants, a 64bit type is appropriate. - dst_type = destination.IsRegister() ? Primitive::kPrimInt : Primitive::kPrimFloat; + dst_type = destination.IsRegister() ? DataType::Type::kInt32 : DataType::Type::kFloat32; } else { // If the source is a double stack slot or a 64bit constant, a 64bit // type is appropriate. Else the source is a register, and since the // type has not been specified, we chose a 64bit type to force a 64bit // move. - dst_type = destination.IsRegister() ? Primitive::kPrimLong : Primitive::kPrimDouble; + dst_type = destination.IsRegister() ? DataType::Type::kInt64 : DataType::Type::kFloat64; } } - DCHECK((destination.IsFpuRegister() && Primitive::IsFloatingPointType(dst_type)) || - (destination.IsRegister() && !Primitive::IsFloatingPointType(dst_type))); + DCHECK((destination.IsFpuRegister() && DataType::IsFloatingPointType(dst_type)) || + (destination.IsRegister() && !DataType::IsFloatingPointType(dst_type))); if (source.IsStackSlot() || source.IsDoubleStackSlot()) { // Move to GPR/FPR from stack LoadOperandType load_type = source.IsStackSlot() ? kLoadWord : kLoadDoubleword; - if (Primitive::IsFloatingPointType(dst_type)) { + if (DataType::IsFloatingPointType(dst_type)) { __ LoadFpuFromOffset(load_type, destination.AsFpuRegister<FpuRegister>(), SP, source.GetStackIndex()); } else { - // TODO: use load_type = kLoadUnsignedWord when type == Primitive::kPrimNot. + // TODO: use load_type = kLoadUnsignedWord when type == DataType::Type::kReference. __ LoadFromOffset(load_type, destination.AsRegister<GpuRegister>(), SP, @@ -1306,27 +1307,27 @@ void CodeGeneratorMIPS64::MoveLocation(Location destination, } else if (source.IsConstant()) { // Move to GPR/FPR from constant GpuRegister gpr = AT; - if (!Primitive::IsFloatingPointType(dst_type)) { + if (!DataType::IsFloatingPointType(dst_type)) { gpr = destination.AsRegister<GpuRegister>(); } - if (dst_type == Primitive::kPrimInt || dst_type == Primitive::kPrimFloat) { + if (dst_type == DataType::Type::kInt32 || dst_type == DataType::Type::kFloat32) { int32_t value = GetInt32ValueOf(source.GetConstant()->AsConstant()); - if (Primitive::IsFloatingPointType(dst_type) && value == 0) { + if (DataType::IsFloatingPointType(dst_type) && value == 0) { gpr = ZERO; } else { __ LoadConst32(gpr, value); } } else { int64_t value = GetInt64ValueOf(source.GetConstant()->AsConstant()); - if (Primitive::IsFloatingPointType(dst_type) && value == 0) { + if (DataType::IsFloatingPointType(dst_type) && value == 0) { gpr = ZERO; } else { __ LoadConst64(gpr, value); } } - if (dst_type == Primitive::kPrimFloat) { + if (dst_type == DataType::Type::kFloat32) { __ Mtc1(gpr, destination.AsFpuRegister<FpuRegister>()); - } else if (dst_type == Primitive::kPrimDouble) { + } else if (dst_type == DataType::Type::kFloat64) { __ Dmtc1(gpr, destination.AsFpuRegister<FpuRegister>()); } } else if (source.IsRegister()) { @@ -1335,7 +1336,7 @@ void CodeGeneratorMIPS64::MoveLocation(Location destination, __ Move(destination.AsRegister<GpuRegister>(), source.AsRegister<GpuRegister>()); } else { DCHECK(destination.IsFpuRegister()); - if (Primitive::Is64BitType(dst_type)) { + if (DataType::Is64BitType(dst_type)) { __ Dmtc1(source.AsRegister<GpuRegister>(), destination.AsFpuRegister<FpuRegister>()); } else { __ Mtc1(source.AsRegister<GpuRegister>(), destination.AsFpuRegister<FpuRegister>()); @@ -1348,16 +1349,16 @@ void CodeGeneratorMIPS64::MoveLocation(Location destination, VectorRegisterFrom(source)); } else { // Move to FPR from FPR - if (dst_type == Primitive::kPrimFloat) { + if (dst_type == DataType::Type::kFloat32) { __ MovS(destination.AsFpuRegister<FpuRegister>(), source.AsFpuRegister<FpuRegister>()); } else { - DCHECK_EQ(dst_type, Primitive::kPrimDouble); + DCHECK_EQ(dst_type, DataType::Type::kFloat64); __ MovD(destination.AsFpuRegister<FpuRegister>(), source.AsFpuRegister<FpuRegister>()); } } } else { DCHECK(destination.IsRegister()); - if (Primitive::Is64BitType(dst_type)) { + if (DataType::Is64BitType(dst_type)) { __ Dmfc1(destination.AsRegister<GpuRegister>(), source.AsFpuRegister<FpuRegister>()); } else { __ Mfc1(destination.AsRegister<GpuRegister>(), source.AsFpuRegister<FpuRegister>()); @@ -1386,13 +1387,14 @@ void CodeGeneratorMIPS64::MoveLocation(Location destination, if (source.IsRegister() || source.IsFpuRegister()) { if (unspecified_type) { if (source.IsRegister()) { - dst_type = destination.IsStackSlot() ? Primitive::kPrimInt : Primitive::kPrimLong; + dst_type = destination.IsStackSlot() ? DataType::Type::kInt32 : DataType::Type::kInt64; } else { - dst_type = destination.IsStackSlot() ? Primitive::kPrimFloat : Primitive::kPrimDouble; + dst_type = + destination.IsStackSlot() ? DataType::Type::kFloat32 : DataType::Type::kFloat64; } } - DCHECK((destination.IsDoubleStackSlot() == Primitive::Is64BitType(dst_type)) && - (source.IsFpuRegister() == Primitive::IsFloatingPointType(dst_type))); + DCHECK((destination.IsDoubleStackSlot() == DataType::Is64BitType(dst_type)) && + (source.IsFpuRegister() == DataType::IsFloatingPointType(dst_type))); // Move to stack from GPR/FPR StoreOperandType store_type = destination.IsStackSlot() ? kStoreWord : kStoreDoubleword; if (source.IsRegister()) { @@ -1441,7 +1443,7 @@ void CodeGeneratorMIPS64::MoveLocation(Location destination, } } -void CodeGeneratorMIPS64::SwapLocations(Location loc1, Location loc2, Primitive::Type type) { +void CodeGeneratorMIPS64::SwapLocations(Location loc1, Location loc2, DataType::Type type) { DCHECK(!loc1.IsConstant()); DCHECK(!loc2.IsConstant()); @@ -1465,12 +1467,12 @@ void CodeGeneratorMIPS64::SwapLocations(Location loc1, Location loc2, Primitive: // Swap 2 FPRs FpuRegister r1 = loc1.AsFpuRegister<FpuRegister>(); FpuRegister r2 = loc2.AsFpuRegister<FpuRegister>(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ MovS(FTMP, r1); __ MovS(r1, r2); __ MovS(r2, FTMP); } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); __ MovD(FTMP, r1); __ MovD(r1, r2); __ MovD(r2, FTMP); @@ -1481,7 +1483,7 @@ void CodeGeneratorMIPS64::SwapLocations(Location loc1, Location loc2, Primitive: Location mem_loc = is_slot1 ? loc1 : loc2; LoadOperandType load_type = mem_loc.IsStackSlot() ? kLoadWord : kLoadDoubleword; StoreOperandType store_type = mem_loc.IsStackSlot() ? kStoreWord : kStoreDoubleword; - // TODO: use load_type = kLoadUnsignedWord when type == Primitive::kPrimNot. + // TODO: use load_type = kLoadUnsignedWord when type == DataType::Type::kReference. __ LoadFromOffset(load_type, TMP, SP, mem_loc.GetStackIndex()); if (reg_loc.IsFpuRegister()) { __ StoreFpuToOffset(store_type, @@ -1541,10 +1543,10 @@ void CodeGeneratorMIPS64::MarkGCCard(GpuRegister object, } } -template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> +template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> inline void CodeGeneratorMIPS64::EmitPcRelativeLinkerPatches( const ArenaDeque<PcRelativePatchInfo>& infos, - ArenaVector<LinkerPatch>* linker_patches) { + ArenaVector<linker::LinkerPatch>* linker_patches) { for (const PcRelativePatchInfo& info : infos) { const DexFile& dex_file = info.target_dex_file; size_t offset_or_index = info.offset_or_index; @@ -1556,7 +1558,7 @@ inline void CodeGeneratorMIPS64::EmitPcRelativeLinkerPatches( } } -void CodeGeneratorMIPS64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) { +void CodeGeneratorMIPS64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) { DCHECK(linker_patches->empty()); size_t size = pc_relative_method_patches_.size() + @@ -1567,25 +1569,25 @@ void CodeGeneratorMIPS64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_pat string_bss_entry_patches_.size(); linker_patches->reserve(size); if (GetCompilerOptions().IsBootImage()) { - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(pc_relative_method_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeTypePatch>(pc_relative_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeStringPatch>(pc_relative_string_patches_, - linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>( + pc_relative_method_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>( + pc_relative_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>( + pc_relative_string_patches_, linker_patches); } else { DCHECK(pc_relative_method_patches_.empty()); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(pc_relative_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(pc_relative_string_patches_, - linker_patches); - } - EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(string_bss_entry_patches_, - linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>( + pc_relative_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>( + pc_relative_string_patches_, linker_patches); + } + EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( + method_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>( + type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>( + string_bss_entry_patches_, linker_patches); DCHECK_EQ(size, linker_patches->size()); } @@ -1858,10 +1860,10 @@ InstructionCodeGeneratorMIPS64::InstructionCodeGeneratorMIPS64(HGraph* graph, void LocationsBuilderMIPS64::HandleBinaryOp(HBinaryOperation* instruction) { DCHECK_EQ(instruction->InputCount(), 2U); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); - Primitive::Type type = instruction->GetResultType(); + DataType::Type type = instruction->GetResultType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); HInstruction* right = instruction->InputAt(1); bool can_use_imm = false; @@ -1884,8 +1886,8 @@ void LocationsBuilderMIPS64::HandleBinaryOp(HBinaryOperation* instruction) { } break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -1897,12 +1899,12 @@ void LocationsBuilderMIPS64::HandleBinaryOp(HBinaryOperation* instruction) { } void InstructionCodeGeneratorMIPS64::HandleBinaryOp(HBinaryOperation* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GpuRegister dst = locations->Out().AsRegister<GpuRegister>(); GpuRegister lhs = locations->InAt(0).AsRegister<GpuRegister>(); Location rhs_location = locations->InAt(1); @@ -1932,7 +1934,7 @@ void InstructionCodeGeneratorMIPS64::HandleBinaryOp(HBinaryOperation* instructio else __ Xor(dst, lhs, rhs_reg); } else if (instruction->IsAdd()) { - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { if (use_imm) __ Addiu(dst, lhs, rhs_imm); else @@ -1945,7 +1947,7 @@ void InstructionCodeGeneratorMIPS64::HandleBinaryOp(HBinaryOperation* instructio } } else { DCHECK(instruction->IsSub()); - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { if (use_imm) __ Addiu(dst, lhs, -rhs_imm); else @@ -1959,18 +1961,18 @@ void InstructionCodeGeneratorMIPS64::HandleBinaryOp(HBinaryOperation* instructio } break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { FpuRegister dst = locations->Out().AsFpuRegister<FpuRegister>(); FpuRegister lhs = locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister rhs = locations->InAt(1).AsFpuRegister<FpuRegister>(); if (instruction->IsAdd()) { - if (type == Primitive::kPrimFloat) + if (type == DataType::Type::kFloat32) __ AddS(dst, lhs, rhs); else __ AddD(dst, lhs, rhs); } else if (instruction->IsSub()) { - if (type == Primitive::kPrimFloat) + if (type == DataType::Type::kFloat32) __ SubS(dst, lhs, rhs); else __ SubD(dst, lhs, rhs); @@ -1988,10 +1990,10 @@ void LocationsBuilderMIPS64::HandleShift(HBinaryOperation* instr) { DCHECK(instr->IsShl() || instr->IsShr() || instr->IsUShr() || instr->IsRor()); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr); - Primitive::Type type = instr->GetResultType(); + DataType::Type type = instr->GetResultType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instr->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -2005,11 +2007,11 @@ void LocationsBuilderMIPS64::HandleShift(HBinaryOperation* instr) { void InstructionCodeGeneratorMIPS64::HandleShift(HBinaryOperation* instr) { DCHECK(instr->IsShl() || instr->IsShr() || instr->IsUShr() || instr->IsRor()); LocationSummary* locations = instr->GetLocations(); - Primitive::Type type = instr->GetType(); + DataType::Type type = instr->GetType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GpuRegister dst = locations->Out().AsRegister<GpuRegister>(); GpuRegister lhs = locations->InAt(0).AsRegister<GpuRegister>(); Location rhs_location = locations->InAt(1); @@ -2025,13 +2027,13 @@ void InstructionCodeGeneratorMIPS64::HandleShift(HBinaryOperation* instr) { if (use_imm) { uint32_t shift_value = rhs_imm & - (type == Primitive::kPrimInt ? kMaxIntShiftDistance : kMaxLongShiftDistance); + (type == DataType::Type::kInt32 ? kMaxIntShiftDistance : kMaxLongShiftDistance); if (shift_value == 0) { if (dst != lhs) { __ Move(dst, lhs); } - } else if (type == Primitive::kPrimInt) { + } else if (type == DataType::Type::kInt32) { if (instr->IsShl()) { __ Sll(dst, lhs, shift_value); } else if (instr->IsShr()) { @@ -2066,7 +2068,7 @@ void InstructionCodeGeneratorMIPS64::HandleShift(HBinaryOperation* instr) { } } } else { - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { if (instr->IsShl()) { __ Sllv(dst, lhs, rhs_reg); } else if (instr->IsShr()) { @@ -2112,9 +2114,9 @@ void InstructionCodeGeneratorMIPS64::VisitAnd(HAnd* instruction) { } void LocationsBuilderMIPS64::VisitArrayGet(HArrayGet* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); bool object_array_get_with_read_barrier = - kEmitCompilerReadBarrier && (type == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (type == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, object_array_get_with_read_barrier @@ -2125,7 +2127,7 @@ void LocationsBuilderMIPS64::VisitArrayGet(HArrayGet* instruction) { } locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - if (Primitive::IsFloatingPointType(type)) { + if (DataType::IsFloatingPointType(type)) { locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); } else { // The output overlaps in the case of an object array get with @@ -2164,11 +2166,11 @@ void InstructionCodeGeneratorMIPS64::VisitArrayGet(HArrayGet* instruction) { uint32_t data_offset = CodeGenerator::GetArrayDataOffset(instruction); auto null_checker = GetImplicitNullChecker(instruction, codegen_); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); const bool maybe_compressed_char_at = mirror::kUseStringCompression && instruction->IsStringCharAt(); switch (type) { - case Primitive::kPrimBoolean: { + case DataType::Type::kBool: { GpuRegister out = out_loc.AsRegister<GpuRegister>(); if (index.IsConstant()) { size_t offset = @@ -2181,7 +2183,7 @@ void InstructionCodeGeneratorMIPS64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimByte: { + case DataType::Type::kInt8: { GpuRegister out = out_loc.AsRegister<GpuRegister>(); if (index.IsConstant()) { size_t offset = @@ -2194,7 +2196,7 @@ void InstructionCodeGeneratorMIPS64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimShort: { + case DataType::Type::kInt16: { GpuRegister out = out_loc.AsRegister<GpuRegister>(); if (index.IsConstant()) { size_t offset = @@ -2207,7 +2209,7 @@ void InstructionCodeGeneratorMIPS64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimChar: { + case DataType::Type::kUint16: { GpuRegister out = out_loc.AsRegister<GpuRegister>(); if (maybe_compressed_char_at) { uint32_t count_offset = mirror::String::CountOffset().Uint32Value(); @@ -2259,10 +2261,11 @@ void InstructionCodeGeneratorMIPS64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { DCHECK_EQ(sizeof(mirror::HeapReference<mirror::Object>), sizeof(int32_t)); GpuRegister out = out_loc.AsRegister<GpuRegister>(); - LoadOperandType load_type = (type == Primitive::kPrimNot) ? kLoadUnsignedWord : kLoadWord; + LoadOperandType load_type = + (type == DataType::Type::kReference) ? kLoadUnsignedWord : kLoadWord; if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset; @@ -2274,7 +2277,7 @@ void InstructionCodeGeneratorMIPS64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { static_assert( sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t), "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes."); @@ -2334,7 +2337,7 @@ void InstructionCodeGeneratorMIPS64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { GpuRegister out = out_loc.AsRegister<GpuRegister>(); if (index.IsConstant()) { size_t offset = @@ -2347,7 +2350,7 @@ void InstructionCodeGeneratorMIPS64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { FpuRegister out = out_loc.AsFpuRegister<FpuRegister>(); if (index.IsConstant()) { size_t offset = @@ -2360,7 +2363,7 @@ void InstructionCodeGeneratorMIPS64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { FpuRegister out = out_loc.AsFpuRegister<FpuRegister>(); if (index.IsConstant()) { size_t offset = @@ -2373,7 +2376,7 @@ void InstructionCodeGeneratorMIPS64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); } @@ -2418,7 +2421,7 @@ Location LocationsBuilderMIPS64::FpuRegisterOrConstantForStore(HInstruction* ins } void LocationsBuilderMIPS64::VisitArraySet(HArraySet* instruction) { - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); @@ -2432,7 +2435,7 @@ void LocationsBuilderMIPS64::VisitArraySet(HArraySet* instruction) { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - if (Primitive::IsFloatingPointType(instruction->InputAt(2)->GetType())) { + if (DataType::IsFloatingPointType(instruction->InputAt(2)->GetType())) { locations->SetInAt(2, FpuRegisterOrConstantForStore(instruction->InputAt(2))); } else { locations->SetInAt(2, RegisterOrZeroConstant(instruction->InputAt(2))); @@ -2448,7 +2451,7 @@ void InstructionCodeGeneratorMIPS64::VisitArraySet(HArraySet* instruction) { GpuRegister obj = locations->InAt(0).AsRegister<GpuRegister>(); Location index = locations->InAt(1); Location value_location = locations->InAt(2); - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); @@ -2456,8 +2459,8 @@ void InstructionCodeGeneratorMIPS64::VisitArraySet(HArraySet* instruction) { GpuRegister base_reg = index.IsConstant() ? obj : TMP; switch (value_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: { + case DataType::Type::kBool: + case DataType::Type::kInt8: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1; @@ -2474,8 +2477,8 @@ void InstructionCodeGeneratorMIPS64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimShort: - case Primitive::kPrimChar: { + case DataType::Type::kInt16: + case DataType::Type::kUint16: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2; @@ -2492,7 +2495,7 @@ void InstructionCodeGeneratorMIPS64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4; @@ -2509,7 +2512,7 @@ void InstructionCodeGeneratorMIPS64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { if (value_location.IsConstant()) { // Just setting null. uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); @@ -2624,7 +2627,7 @@ void InstructionCodeGeneratorMIPS64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8; @@ -2641,7 +2644,7 @@ void InstructionCodeGeneratorMIPS64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4; @@ -2658,7 +2661,7 @@ void InstructionCodeGeneratorMIPS64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value(); if (index.IsConstant()) { data_offset += index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8; @@ -2675,7 +2678,7 @@ void InstructionCodeGeneratorMIPS64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); } @@ -2960,24 +2963,24 @@ void InstructionCodeGeneratorMIPS64::VisitClinitCheck(HClinitCheck* check) { } void LocationsBuilderMIPS64::VisitCompare(HCompare* compare) { - Primitive::Type in_type = compare->InputAt(0)->GetType(); + DataType::Type in_type = compare->InputAt(0)->GetType(); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare); switch (in_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(compare->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -2991,24 +2994,24 @@ void LocationsBuilderMIPS64::VisitCompare(HCompare* compare) { void InstructionCodeGeneratorMIPS64::VisitCompare(HCompare* instruction) { LocationSummary* locations = instruction->GetLocations(); GpuRegister res = locations->Out().AsRegister<GpuRegister>(); - Primitive::Type in_type = instruction->InputAt(0)->GetType(); + DataType::Type in_type = instruction->InputAt(0)->GetType(); // 0 if: left == right // 1 if: left > right // -1 if: left < right switch (in_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GpuRegister lhs = locations->InAt(0).AsRegister<GpuRegister>(); Location rhs_location = locations->InAt(1); bool use_imm = rhs_location.IsConstant(); GpuRegister rhs = ZERO; if (use_imm) { - if (in_type == Primitive::kPrimLong) { + if (in_type == DataType::Type::kInt64) { int64_t value = CodeGenerator::GetInt64ValueOf(rhs_location.GetConstant()->AsConstant()); if (value != 0) { rhs = AT; @@ -3030,7 +3033,7 @@ void InstructionCodeGeneratorMIPS64::VisitCompare(HCompare* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { FpuRegister lhs = locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister rhs = locations->InAt(1).AsFpuRegister<FpuRegister>(); Mips64Label done; @@ -3052,7 +3055,7 @@ void InstructionCodeGeneratorMIPS64::VisitCompare(HCompare* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { FpuRegister lhs = locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister rhs = locations->InAt(1).AsFpuRegister<FpuRegister>(); Mips64Label done; @@ -3083,13 +3086,13 @@ void LocationsBuilderMIPS64::HandleCondition(HCondition* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); switch (instruction->InputAt(0)->GetType()) { default: - case Primitive::kPrimLong: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); break; @@ -3104,18 +3107,18 @@ void InstructionCodeGeneratorMIPS64::HandleCondition(HCondition* instruction) { return; } - Primitive::Type type = instruction->InputAt(0)->GetType(); + DataType::Type type = instruction->InputAt(0)->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { default: // Integer case. GenerateIntLongCompare(instruction->GetCondition(), /* is64bit */ false, locations); return; - case Primitive::kPrimLong: + case DataType::Type::kInt64: GenerateIntLongCompare(instruction->GetCondition(), /* is64bit */ true, locations); return; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: GenerateFpCompare(instruction->GetCondition(), instruction->IsGtBias(), type, locations); return; } @@ -3123,7 +3126,7 @@ void InstructionCodeGeneratorMIPS64::HandleCondition(HCondition* instruction) { void InstructionCodeGeneratorMIPS64::DivRemOneOrMinusOne(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - Primitive::Type type = instruction->GetResultType(); + DataType::Type type = instruction->GetResultType(); LocationSummary* locations = instruction->GetLocations(); Location second = locations->InAt(1); @@ -3138,10 +3141,10 @@ void InstructionCodeGeneratorMIPS64::DivRemOneOrMinusOne(HBinaryOperation* instr __ Move(out, ZERO); } else { if (imm == -1) { - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { __ Subu(out, ZERO, dividend); } else { - DCHECK_EQ(type, Primitive::kPrimLong); + DCHECK_EQ(type, DataType::Type::kInt64); __ Dsubu(out, ZERO, dividend); } } else if (out != dividend) { @@ -3152,7 +3155,7 @@ void InstructionCodeGeneratorMIPS64::DivRemOneOrMinusOne(HBinaryOperation* instr void InstructionCodeGeneratorMIPS64::DivRemByPowerOfTwo(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - Primitive::Type type = instruction->GetResultType(); + DataType::Type type = instruction->GetResultType(); LocationSummary* locations = instruction->GetLocations(); Location second = locations->InAt(1); @@ -3165,7 +3168,7 @@ void InstructionCodeGeneratorMIPS64::DivRemByPowerOfTwo(HBinaryOperation* instru int ctz_imm = CTZ(abs_imm); if (instruction->IsDiv()) { - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { if (ctz_imm == 1) { // Fast path for division by +/-2, which is very common. __ Srl(TMP, dividend, 31); @@ -3179,7 +3182,7 @@ void InstructionCodeGeneratorMIPS64::DivRemByPowerOfTwo(HBinaryOperation* instru __ Subu(out, ZERO, out); } } else { - DCHECK_EQ(type, Primitive::kPrimLong); + DCHECK_EQ(type, DataType::Type::kInt64); if (ctz_imm == 1) { // Fast path for division by +/-2, which is very common. __ Dsrl32(TMP, dividend, 31); @@ -3202,7 +3205,7 @@ void InstructionCodeGeneratorMIPS64::DivRemByPowerOfTwo(HBinaryOperation* instru } } } else { - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { if (ctz_imm == 1) { // Fast path for modulo +/-2, which is very common. __ Sra(TMP, dividend, 31); @@ -3222,7 +3225,7 @@ void InstructionCodeGeneratorMIPS64::DivRemByPowerOfTwo(HBinaryOperation* instru __ Subu(out, out, TMP); } } else { - DCHECK_EQ(type, Primitive::kPrimLong); + DCHECK_EQ(type, DataType::Type::kInt64); if (ctz_imm == 1) { // Fast path for modulo +/-2, which is very common. __ Dsra32(TMP, dividend, 31); @@ -3265,17 +3268,17 @@ void InstructionCodeGeneratorMIPS64::GenerateDivRemWithAnyConstant(HBinaryOperat GpuRegister dividend = locations->InAt(0).AsRegister<GpuRegister>(); int64_t imm = Int64FromConstant(second.GetConstant()); - Primitive::Type type = instruction->GetResultType(); - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong) << type; + DataType::Type type = instruction->GetResultType(); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64) << type; int64_t magic; int shift; CalculateMagicAndShiftForDivRem(imm, - (type == Primitive::kPrimLong), + (type == DataType::Type::kInt64), &magic, &shift); - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { __ LoadConst32(TMP, magic); __ MuhR6(TMP, dividend, TMP); @@ -3330,8 +3333,8 @@ void InstructionCodeGeneratorMIPS64::GenerateDivRemWithAnyConstant(HBinaryOperat void InstructionCodeGeneratorMIPS64::GenerateDivRemIntegral(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - Primitive::Type type = instruction->GetResultType(); - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong) << type; + DataType::Type type = instruction->GetResultType(); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64) << type; LocationSummary* locations = instruction->GetLocations(); GpuRegister out = locations->Out().AsRegister<GpuRegister>(); @@ -3353,12 +3356,12 @@ void InstructionCodeGeneratorMIPS64::GenerateDivRemIntegral(HBinaryOperation* in GpuRegister dividend = locations->InAt(0).AsRegister<GpuRegister>(); GpuRegister divisor = second.AsRegister<GpuRegister>(); if (instruction->IsDiv()) { - if (type == Primitive::kPrimInt) + if (type == DataType::Type::kInt32) __ DivR6(out, dividend, divisor); else __ Ddiv(out, dividend, divisor); } else { - if (type == Primitive::kPrimInt) + if (type == DataType::Type::kInt32) __ ModR6(out, dividend, divisor); else __ Dmod(out, dividend, divisor); @@ -3370,15 +3373,15 @@ void LocationsBuilderMIPS64::VisitDiv(HDiv* div) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall); switch (div->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(div->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -3390,20 +3393,20 @@ void LocationsBuilderMIPS64::VisitDiv(HDiv* div) { } void InstructionCodeGeneratorMIPS64::VisitDiv(HDiv* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: GenerateDivRemIntegral(instruction); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { FpuRegister dst = locations->Out().AsFpuRegister<FpuRegister>(); FpuRegister lhs = locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister rhs = locations->InAt(1).AsFpuRegister<FpuRegister>(); - if (type == Primitive::kPrimFloat) + if (type == DataType::Type::kFloat32) __ DivS(dst, lhs, rhs); else __ DivD(dst, lhs, rhs); @@ -3425,9 +3428,9 @@ void InstructionCodeGeneratorMIPS64::VisitDivZeroCheck(HDivZeroCheck* instructio codegen_->AddSlowPath(slow_path); Location value = instruction->GetLocations()->InAt(0); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); - if (!Primitive::IsIntegralType(type)) { + if (!DataType::IsIntegralType(type)) { LOG(FATAL) << "Unexpected type " << type << " for DivZeroCheck."; return; } @@ -3863,12 +3866,12 @@ void InstructionCodeGeneratorMIPS64::GenerateIntLongCompareAndBranch(IfCondition void InstructionCodeGeneratorMIPS64::GenerateFpCompare(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* locations) { GpuRegister dst = locations->Out().AsRegister<GpuRegister>(); FpuRegister lhs = locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister rhs = locations->InAt(1).AsFpuRegister<FpuRegister>(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { switch (cond) { case kCondEQ: __ CmpEqS(FTMP, lhs, rhs); @@ -3921,7 +3924,7 @@ void InstructionCodeGeneratorMIPS64::GenerateFpCompare(IfCondition cond, UNREACHABLE(); } } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); switch (cond) { case kCondEQ: __ CmpEqD(FTMP, lhs, rhs); @@ -3978,12 +3981,12 @@ void InstructionCodeGeneratorMIPS64::GenerateFpCompare(IfCondition cond, bool InstructionCodeGeneratorMIPS64::MaterializeFpCompare(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* input_locations, FpuRegister dst) { FpuRegister lhs = input_locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister rhs = input_locations->InAt(1).AsFpuRegister<FpuRegister>(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { switch (cond) { case kCondEQ: __ CmpEqS(dst, lhs, rhs); @@ -4024,7 +4027,7 @@ bool InstructionCodeGeneratorMIPS64::MaterializeFpCompare(IfCondition cond, UNREACHABLE(); } } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); switch (cond) { case kCondEQ: __ CmpEqD(dst, lhs, rhs); @@ -4069,12 +4072,12 @@ bool InstructionCodeGeneratorMIPS64::MaterializeFpCompare(IfCondition cond, void InstructionCodeGeneratorMIPS64::GenerateFpCompareAndBranch(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* locations, Mips64Label* label) { FpuRegister lhs = locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister rhs = locations->InAt(1).AsFpuRegister<FpuRegister>(); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { switch (cond) { case kCondEQ: __ CmpEqS(FTMP, lhs, rhs); @@ -4121,7 +4124,7 @@ void InstructionCodeGeneratorMIPS64::GenerateFpCompareAndBranch(IfCondition cond UNREACHABLE(); } } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); switch (cond) { case kCondEQ: __ CmpEqD(FTMP, lhs, rhs); @@ -4215,7 +4218,7 @@ void InstructionCodeGeneratorMIPS64::GenerateTestAndBranch(HInstruction* instruc // The condition instruction has not been materialized, use its inputs as // the comparison and its condition as the branch condition. HCondition* condition = cond->AsCondition(); - Primitive::Type type = condition->InputAt(0)->GetType(); + DataType::Type type = condition->InputAt(0)->GetType(); LocationSummary* locations = cond->GetLocations(); IfCondition if_cond = condition->GetCondition(); Mips64Label* branch_target = true_target; @@ -4229,11 +4232,11 @@ void InstructionCodeGeneratorMIPS64::GenerateTestAndBranch(HInstruction* instruc default: GenerateIntLongCompareAndBranch(if_cond, /* is64bit */ false, locations, branch_target); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: GenerateIntLongCompareAndBranch(if_cond, /* is64bit */ true, locations, branch_target); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: GenerateFpCompareAndBranch(if_cond, condition->IsGtBias(), type, locations, branch_target); break; } @@ -4298,8 +4301,9 @@ static bool CanMoveConditionally(HSelect* select, LocationSummary* locations_to_ HInstruction* cond = select->InputAt(/* condition_input_index */ 2); HCondition* condition = cond->AsCondition(); - Primitive::Type cond_type = materialized ? Primitive::kPrimInt : condition->InputAt(0)->GetType(); - Primitive::Type dst_type = select->GetType(); + DataType::Type cond_type = + materialized ? DataType::Type::kInt32 : condition->InputAt(0)->GetType(); + DataType::Type dst_type = select->GetType(); HConstant* cst_true_value = select->GetTrueValue()->AsConstant(); HConstant* cst_false_value = select->GetFalseValue()->AsConstant(); @@ -4313,8 +4317,8 @@ static bool CanMoveConditionally(HSelect* select, LocationSummary* locations_to_ bool use_const_for_true_in = false; if (!cond->IsConstant()) { - if (!Primitive::IsFloatingPointType(cond_type)) { - if (!Primitive::IsFloatingPointType(dst_type)) { + if (!DataType::IsFloatingPointType(cond_type)) { + if (!DataType::IsFloatingPointType(dst_type)) { // Moving int/long on int/long condition. if (is_true_value_zero_constant) { // seleqz out_reg, false_reg, cond_reg @@ -4357,7 +4361,7 @@ static bool CanMoveConditionally(HSelect* select, LocationSummary* locations_to_ } } } else { - if (!Primitive::IsFloatingPointType(dst_type)) { + if (!DataType::IsFloatingPointType(dst_type)) { // Moving int/long on float/double condition. can_move_conditionally = true; if (is_true_value_zero_constant) { @@ -4403,7 +4407,7 @@ static bool CanMoveConditionally(HSelect* select, LocationSummary* locations_to_ locations_to_set->SetInAt(0, Location::ConstantLocation(cst_false_value)); } else { locations_to_set->SetInAt(0, - Primitive::IsFloatingPointType(dst_type) + DataType::IsFloatingPointType(dst_type) ? Location::RequiresFpuRegister() : Location::RequiresRegister()); } @@ -4411,7 +4415,7 @@ static bool CanMoveConditionally(HSelect* select, LocationSummary* locations_to_ locations_to_set->SetInAt(1, Location::ConstantLocation(cst_true_value)); } else { locations_to_set->SetInAt(1, - Primitive::IsFloatingPointType(dst_type) + DataType::IsFloatingPointType(dst_type) ? Location::RequiresFpuRegister() : Location::RequiresRegister()); } @@ -4420,7 +4424,7 @@ static bool CanMoveConditionally(HSelect* select, LocationSummary* locations_to_ } if (can_move_conditionally) { - locations_to_set->SetOut(Primitive::IsFloatingPointType(dst_type) + locations_to_set->SetOut(DataType::IsFloatingPointType(dst_type) ? Location::RequiresFpuRegister() : Location::RequiresRegister()); } else { @@ -4440,9 +4444,9 @@ void InstructionCodeGeneratorMIPS64::GenConditionalMove(HSelect* select) { HInstruction* cond = select->InputAt(/* condition_input_index */ 2); GpuRegister cond_reg = TMP; FpuRegister fcond_reg = FTMP; - Primitive::Type cond_type = Primitive::kPrimInt; + DataType::Type cond_type = DataType::Type::kInt32; bool cond_inverted = false; - Primitive::Type dst_type = select->GetType(); + DataType::Type dst_type = select->GetType(); if (IsBooleanValueOrMaterializedCondition(cond)) { cond_reg = locations->InAt(/* condition_input_index */ 2).AsRegister<GpuRegister>(); @@ -4458,14 +4462,14 @@ void InstructionCodeGeneratorMIPS64::GenConditionalMove(HSelect* select) { cond_locations, cond_reg); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: cond_inverted = MaterializeIntLongCompare(if_cond, /* is64bit */ true, cond_locations, cond_reg); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: cond_inverted = MaterializeFpCompare(if_cond, condition->IsGtBias(), cond_type, @@ -4484,7 +4488,7 @@ void InstructionCodeGeneratorMIPS64::GenConditionalMove(HSelect* select) { switch (dst_type) { default: - if (Primitive::IsFloatingPointType(cond_type)) { + if (DataType::IsFloatingPointType(cond_type)) { __ Mfc1(cond_reg, fcond_reg); } if (true_src.IsConstant()) { @@ -4511,8 +4515,8 @@ void InstructionCodeGeneratorMIPS64::GenConditionalMove(HSelect* select) { __ Or(dst.AsRegister<GpuRegister>(), AT, TMP); } break; - case Primitive::kPrimFloat: { - if (!Primitive::IsFloatingPointType(cond_type)) { + case DataType::Type::kFloat32: { + if (!DataType::IsFloatingPointType(cond_type)) { // sel*.fmt tests bit 0 of the condition register, account for that. __ Sltu(TMP, ZERO, cond_reg); __ Mtc1(TMP, fcond_reg); @@ -4546,8 +4550,8 @@ void InstructionCodeGeneratorMIPS64::GenConditionalMove(HSelect* select) { } break; } - case Primitive::kPrimDouble: { - if (!Primitive::IsFloatingPointType(cond_type)) { + case DataType::Type::kFloat64: { + if (!DataType::IsFloatingPointType(cond_type)) { // sel*.fmt tests bit 0 of the condition register, account for that. __ Sltu(TMP, ZERO, cond_reg); __ Mtc1(TMP, fcond_reg); @@ -4631,9 +4635,9 @@ void CodeGeneratorMIPS64::GenerateNop() { void LocationsBuilderMIPS64::HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info) { - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); bool object_field_get_with_read_barrier = - kEmitCompilerReadBarrier && (field_type == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (field_type == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary( instruction, object_field_get_with_read_barrier @@ -4643,7 +4647,7 @@ void LocationsBuilderMIPS64::HandleFieldGet(HInstruction* instruction, locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers. } locations->SetInAt(0, Location::RequiresRegister()); - if (Primitive::IsFloatingPointType(instruction->GetType())) { + if (DataType::IsFloatingPointType(instruction->GetType())) { locations->SetOut(Location::RequiresFpuRegister()); } else { // The output overlaps in the case of an object field get with @@ -4665,7 +4669,7 @@ void LocationsBuilderMIPS64::HandleFieldGet(HInstruction* instruction, void InstructionCodeGeneratorMIPS64::HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info) { - Primitive::Type type = field_info.GetFieldType(); + DataType::Type type = field_info.GetFieldType(); LocationSummary* locations = instruction->GetLocations(); Location obj_loc = locations->InAt(0); GpuRegister obj = obj_loc.AsRegister<GpuRegister>(); @@ -4676,37 +4680,37 @@ void InstructionCodeGeneratorMIPS64::HandleFieldGet(HInstruction* instruction, auto null_checker = GetImplicitNullChecker(instruction, codegen_); switch (type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: load_type = kLoadUnsignedByte; break; - case Primitive::kPrimByte: + case DataType::Type::kInt8: load_type = kLoadSignedByte; break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: load_type = kLoadSignedHalfword; break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: load_type = kLoadUnsignedHalfword; break; - case Primitive::kPrimInt: - case Primitive::kPrimFloat: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: load_type = kLoadWord; break; - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: load_type = kLoadDoubleword; break; - case Primitive::kPrimNot: + case DataType::Type::kReference: load_type = kLoadUnsignedWord; break; - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; UNREACHABLE(); } - if (!Primitive::IsFloatingPointType(type)) { + if (!DataType::IsFloatingPointType(type)) { DCHECK(dst_loc.IsRegister()); GpuRegister dst = dst_loc.AsRegister<GpuRegister>(); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // /* HeapReference<Object> */ dst = *(obj + offset) if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) { Location temp_loc = @@ -4743,7 +4747,7 @@ void InstructionCodeGeneratorMIPS64::HandleFieldGet(HInstruction* instruction, // Memory barriers, in the case of references, are handled in the // previous switch statement. - if (is_volatile && (type != Primitive::kPrimNot)) { + if (is_volatile && (type != DataType::Type::kReference)) { GenerateMemoryBarrier(MemBarrierKind::kLoadAny); } } @@ -4753,7 +4757,7 @@ void LocationsBuilderMIPS64::HandleFieldSet(HInstruction* instruction, LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); locations->SetInAt(0, Location::RequiresRegister()); - if (Primitive::IsFloatingPointType(instruction->InputAt(1)->GetType())) { + if (DataType::IsFloatingPointType(instruction->InputAt(1)->GetType())) { locations->SetInAt(1, FpuRegisterOrConstantForStore(instruction->InputAt(1))); } else { locations->SetInAt(1, RegisterOrZeroConstant(instruction->InputAt(1))); @@ -4763,7 +4767,7 @@ void LocationsBuilderMIPS64::HandleFieldSet(HInstruction* instruction, void InstructionCodeGeneratorMIPS64::HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info, bool value_can_be_null) { - Primitive::Type type = field_info.GetFieldType(); + DataType::Type type = field_info.GetFieldType(); LocationSummary* locations = instruction->GetLocations(); GpuRegister obj = locations->InAt(0).AsRegister<GpuRegister>(); Location value_location = locations->InAt(1); @@ -4774,24 +4778,24 @@ void InstructionCodeGeneratorMIPS64::HandleFieldSet(HInstruction* instruction, auto null_checker = GetImplicitNullChecker(instruction, codegen_); switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: store_type = kStoreByte; break; - case Primitive::kPrimShort: - case Primitive::kPrimChar: + case DataType::Type::kInt16: + case DataType::Type::kUint16: store_type = kStoreHalfword; break; - case Primitive::kPrimInt: - case Primitive::kPrimFloat: - case Primitive::kPrimNot: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: + case DataType::Type::kReference: store_type = kStoreWord; break; - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: store_type = kStoreDoubleword; break; - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; UNREACHABLE(); } @@ -4804,14 +4808,14 @@ void InstructionCodeGeneratorMIPS64::HandleFieldSet(HInstruction* instruction, int64_t value = CodeGenerator::GetInt64ValueOf(value_location.GetConstant()); __ StoreConstToOffset(store_type, value, obj, offset, TMP, null_checker); } else { - if (!Primitive::IsFloatingPointType(type)) { + if (!DataType::IsFloatingPointType(type)) { DCHECK(value_location.IsRegister()); GpuRegister src = value_location.AsRegister<GpuRegister>(); if (kPoisonHeapReferences && needs_write_barrier) { // Note that in the case where `value` is a null reference, // we do not enter this block, as a null reference does not // need poisoning. - DCHECK_EQ(type, Primitive::kPrimNot); + DCHECK_EQ(type, DataType::Type::kReference); __ PoisonHeapReference(TMP, src); __ StoreToOffset(store_type, TMP, obj, offset, null_checker); } else { @@ -6246,15 +6250,15 @@ void LocationsBuilderMIPS64::VisitMul(HMul* mul) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(mul, LocationSummary::kNoCall); switch (mul->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -6266,27 +6270,27 @@ void LocationsBuilderMIPS64::VisitMul(HMul* mul) { } void InstructionCodeGeneratorMIPS64::VisitMul(HMul* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GpuRegister dst = locations->Out().AsRegister<GpuRegister>(); GpuRegister lhs = locations->InAt(0).AsRegister<GpuRegister>(); GpuRegister rhs = locations->InAt(1).AsRegister<GpuRegister>(); - if (type == Primitive::kPrimInt) + if (type == DataType::Type::kInt32) __ MulR6(dst, lhs, rhs); else __ Dmul(dst, lhs, rhs); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { FpuRegister dst = locations->Out().AsFpuRegister<FpuRegister>(); FpuRegister lhs = locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister rhs = locations->InAt(1).AsFpuRegister<FpuRegister>(); - if (type == Primitive::kPrimFloat) + if (type == DataType::Type::kFloat32) __ MulS(dst, lhs, rhs); else __ MulD(dst, lhs, rhs); @@ -6301,14 +6305,14 @@ void LocationsBuilderMIPS64::VisitNeg(HNeg* neg) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); switch (neg->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); break; @@ -6319,25 +6323,25 @@ void LocationsBuilderMIPS64::VisitNeg(HNeg* neg) { } void InstructionCodeGeneratorMIPS64::VisitNeg(HNeg* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GpuRegister dst = locations->Out().AsRegister<GpuRegister>(); GpuRegister src = locations->InAt(0).AsRegister<GpuRegister>(); - if (type == Primitive::kPrimInt) + if (type == DataType::Type::kInt32) __ Subu(dst, ZERO, src); else __ Dsubu(dst, ZERO, src); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { FpuRegister dst = locations->Out().AsFpuRegister<FpuRegister>(); FpuRegister src = locations->InAt(0).AsFpuRegister<FpuRegister>(); - if (type == Primitive::kPrimFloat) + if (type == DataType::Type::kFloat32) __ NegS(dst, src); else __ NegD(dst, src); @@ -6352,7 +6356,7 @@ void LocationsBuilderMIPS64::VisitNewArray(HNewArray* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly); InvokeRuntimeCallingConvention calling_convention; - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference)); locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); } @@ -6376,7 +6380,7 @@ void LocationsBuilderMIPS64::VisitNewInstance(HNewInstance* instruction) { } else { locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); } - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference)); } void InstructionCodeGeneratorMIPS64::VisitNewInstance(HNewInstance* instruction) { @@ -6405,12 +6409,12 @@ void LocationsBuilderMIPS64::VisitNot(HNot* instruction) { } void InstructionCodeGeneratorMIPS64::VisitNot(HNot* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); LocationSummary* locations = instruction->GetLocations(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GpuRegister dst = locations->Out().AsRegister<GpuRegister>(); GpuRegister src = locations->InAt(0).AsRegister<GpuRegister>(); __ Nor(dst, src, ZERO); @@ -6519,22 +6523,22 @@ void InstructionCodeGeneratorMIPS64::VisitPhi(HPhi* instruction ATTRIBUTE_UNUSED } void LocationsBuilderMIPS64::VisitRem(HRem* rem) { - Primitive::Type type = rem->GetResultType(); + DataType::Type type = rem->GetResultType(); LocationSummary::CallKind call_kind = - Primitive::IsFloatingPointType(type) ? LocationSummary::kCallOnMainOnly - : LocationSummary::kNoCall; + DataType::IsFloatingPointType(type) ? LocationSummary::kCallOnMainOnly + : LocationSummary::kNoCall; LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(rem->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); locations->SetInAt(1, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(1))); @@ -6548,19 +6552,20 @@ void LocationsBuilderMIPS64::VisitRem(HRem* rem) { } void InstructionCodeGeneratorMIPS64::VisitRem(HRem* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: GenerateDivRemIntegral(instruction); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { - QuickEntrypointEnum entrypoint = (type == Primitive::kPrimFloat) ? kQuickFmodf : kQuickFmod; + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { + QuickEntrypointEnum entrypoint = + (type == DataType::Type::kFloat32) ? kQuickFmodf : kQuickFmod; codegen_->InvokeRuntime(entrypoint, instruction, instruction->GetDexPc()); - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { CheckEntrypointTypes<kQuickFmodf, float, float, float>(); } else { CheckEntrypointTypes<kQuickFmod, double, double, double>(); @@ -6591,7 +6596,7 @@ void InstructionCodeGeneratorMIPS64::VisitMemoryBarrier(HMemoryBarrier* memory_b void LocationsBuilderMIPS64::VisitReturn(HReturn* ret) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret); - Primitive::Type return_type = ret->InputAt(0)->GetType(); + DataType::Type return_type = ret->InputAt(0)->GetType(); locations->SetInAt(0, Mips64ReturnLocation(return_type)); } @@ -6760,24 +6765,24 @@ void InstructionCodeGeneratorMIPS64::VisitThrow(HThrow* instruction) { } void LocationsBuilderMIPS64::VisitTypeConversion(HTypeConversion* conversion) { - Primitive::Type input_type = conversion->GetInputType(); - Primitive::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); DCHECK_NE(input_type, result_type); - if ((input_type == Primitive::kPrimNot) || (input_type == Primitive::kPrimVoid) || - (result_type == Primitive::kPrimNot) || (result_type == Primitive::kPrimVoid)) { + if ((input_type == DataType::Type::kReference) || (input_type == DataType::Type::kVoid) || + (result_type == DataType::Type::kReference) || (result_type == DataType::Type::kVoid)) { LOG(FATAL) << "Unexpected type conversion from " << input_type << " to " << result_type; } LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(conversion); - if (Primitive::IsFloatingPointType(input_type)) { + if (DataType::IsFloatingPointType(input_type)) { locations->SetInAt(0, Location::RequiresFpuRegister()); } else { locations->SetInAt(0, Location::RequiresRegister()); } - if (Primitive::IsFloatingPointType(result_type)) { + if (DataType::IsFloatingPointType(result_type)) { locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); } else { locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -6786,21 +6791,21 @@ void LocationsBuilderMIPS64::VisitTypeConversion(HTypeConversion* conversion) { void InstructionCodeGeneratorMIPS64::VisitTypeConversion(HTypeConversion* conversion) { LocationSummary* locations = conversion->GetLocations(); - Primitive::Type result_type = conversion->GetResultType(); - Primitive::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); DCHECK_NE(input_type, result_type); - if (Primitive::IsIntegralType(result_type) && Primitive::IsIntegralType(input_type)) { + if (DataType::IsIntegralType(result_type) && DataType::IsIntegralType(input_type)) { GpuRegister dst = locations->Out().AsRegister<GpuRegister>(); GpuRegister src = locations->InAt(0).AsRegister<GpuRegister>(); switch (result_type) { - case Primitive::kPrimChar: + case DataType::Type::kUint16: __ Andi(dst, src, 0xFFFF); break; - case Primitive::kPrimByte: - if (input_type == Primitive::kPrimLong) { + case DataType::Type::kInt8: + if (input_type == DataType::Type::kInt64) { // Type conversion from long to types narrower than int is a result of code // transformations. To avoid unpredictable results for SEB and SEH, we first // need to sign-extend the low 32-bit value into bits 32 through 63. @@ -6810,8 +6815,8 @@ void InstructionCodeGeneratorMIPS64::VisitTypeConversion(HTypeConversion* conver __ Seb(dst, src); } break; - case Primitive::kPrimShort: - if (input_type == Primitive::kPrimLong) { + case DataType::Type::kInt16: + if (input_type == DataType::Type::kInt64) { // Type conversion from long to types narrower than int is a result of code // transformations. To avoid unpredictable results for SEB and SEH, we first // need to sign-extend the low 32-bit value into bits 32 through 63. @@ -6821,12 +6826,12 @@ void InstructionCodeGeneratorMIPS64::VisitTypeConversion(HTypeConversion* conver __ Seh(dst, src); } break; - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: // Sign-extend 32-bit int into bits 32 through 63 for int-to-long and long-to-int // conversions, except when the input and output registers are the same and we are not // converting longs to shorter types. In these cases, do nothing. - if ((input_type == Primitive::kPrimLong) || (dst != src)) { + if ((input_type == DataType::Type::kInt64) || (dst != src)) { __ Sll(dst, src, 0); } break; @@ -6835,49 +6840,49 @@ void InstructionCodeGeneratorMIPS64::VisitTypeConversion(HTypeConversion* conver LOG(FATAL) << "Unexpected type conversion from " << input_type << " to " << result_type; } - } else if (Primitive::IsFloatingPointType(result_type) && Primitive::IsIntegralType(input_type)) { + } else if (DataType::IsFloatingPointType(result_type) && DataType::IsIntegralType(input_type)) { FpuRegister dst = locations->Out().AsFpuRegister<FpuRegister>(); GpuRegister src = locations->InAt(0).AsRegister<GpuRegister>(); - if (input_type == Primitive::kPrimLong) { + if (input_type == DataType::Type::kInt64) { __ Dmtc1(src, FTMP); - if (result_type == Primitive::kPrimFloat) { + if (result_type == DataType::Type::kFloat32) { __ Cvtsl(dst, FTMP); } else { __ Cvtdl(dst, FTMP); } } else { __ Mtc1(src, FTMP); - if (result_type == Primitive::kPrimFloat) { + if (result_type == DataType::Type::kFloat32) { __ Cvtsw(dst, FTMP); } else { __ Cvtdw(dst, FTMP); } } - } else if (Primitive::IsIntegralType(result_type) && Primitive::IsFloatingPointType(input_type)) { - CHECK(result_type == Primitive::kPrimInt || result_type == Primitive::kPrimLong); + } else if (DataType::IsIntegralType(result_type) && DataType::IsFloatingPointType(input_type)) { + CHECK(result_type == DataType::Type::kInt32 || result_type == DataType::Type::kInt64); GpuRegister dst = locations->Out().AsRegister<GpuRegister>(); FpuRegister src = locations->InAt(0).AsFpuRegister<FpuRegister>(); - if (result_type == Primitive::kPrimLong) { - if (input_type == Primitive::kPrimFloat) { + if (result_type == DataType::Type::kInt64) { + if (input_type == DataType::Type::kFloat32) { __ TruncLS(FTMP, src); } else { __ TruncLD(FTMP, src); } __ Dmfc1(dst, FTMP); } else { - if (input_type == Primitive::kPrimFloat) { + if (input_type == DataType::Type::kFloat32) { __ TruncWS(FTMP, src); } else { __ TruncWD(FTMP, src); } __ Mfc1(dst, FTMP); } - } else if (Primitive::IsFloatingPointType(result_type) && - Primitive::IsFloatingPointType(input_type)) { + } else if (DataType::IsFloatingPointType(result_type) && + DataType::IsFloatingPointType(input_type)) { FpuRegister dst = locations->Out().AsFpuRegister<FpuRegister>(); FpuRegister src = locations->InAt(0).AsFpuRegister<FpuRegister>(); - if (result_type == Primitive::kPrimFloat) { + if (result_type == DataType::Type::kFloat32) { __ Cvtsd(dst, src); } else { __ Cvtds(dst, src); diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h index 3035621972..2a95b3775d 100644 --- a/compiler/optimizing/code_generator_mips64.h +++ b/compiler/optimizing/code_generator_mips64.h @@ -79,8 +79,8 @@ class InvokeDexCallingConventionVisitorMIPS64 : public InvokeDexCallingConventio InvokeDexCallingConventionVisitorMIPS64() {} virtual ~InvokeDexCallingConventionVisitorMIPS64() {} - Location GetNextLocation(Primitive::Type type) OVERRIDE; - Location GetReturnLocation(Primitive::Type type) const OVERRIDE; + Location GetNextLocation(DataType::Type type) OVERRIDE; + Location GetReturnLocation(DataType::Type type) const OVERRIDE; Location GetMethodLocation() const OVERRIDE; private: @@ -98,7 +98,7 @@ class InvokeRuntimeCallingConvention : public CallingConvention<GpuRegister, Fpu kRuntimeParameterFpuRegistersLength, kMips64PointerSize) {} - Location GetReturnLocation(Primitive::Type return_type); + Location GetReturnLocation(DataType::Type return_type); private: DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); @@ -114,16 +114,16 @@ class FieldAccessCallingConventionMIPS64 : public FieldAccessCallingConvention { Location GetFieldIndexLocation() const OVERRIDE { return Location::RegisterLocation(A0); } - Location GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { + Location GetReturnLocation(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return Location::RegisterLocation(V0); } - Location GetSetValueLocation(Primitive::Type type ATTRIBUTE_UNUSED, + Location GetSetValueLocation(DataType::Type type ATTRIBUTE_UNUSED, bool is_instance) const OVERRIDE { return is_instance ? Location::RegisterLocation(A2) : Location::RegisterLocation(A1); } - Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { + Location GetFpuLocation(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return Location::FpuRegisterLocation(F0); } @@ -306,19 +306,19 @@ class InstructionCodeGeneratorMIPS64 : public InstructionCodeGenerator { Mips64Label* label); void GenerateFpCompare(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* locations); // When the function returns `false` it means that the condition holds if `dst` is non-zero // and doesn't hold if `dst` is zero. If it returns `true`, the roles of zero and non-zero // `dst` are exchanged. bool MaterializeFpCompare(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* input_locations, FpuRegister dst); void GenerateFpCompareAndBranch(IfCondition cond, bool gt_bias, - Primitive::Type type, + DataType::Type type, LocationSummary* locations, Mips64Label* label); void HandleGoto(HInstruction* got, HBasicBlock* successor); @@ -374,7 +374,7 @@ class CodeGeneratorMIPS64 : public CodeGenerator { const Mips64Assembler& GetAssembler() const OVERRIDE { return assembler_; } // Emit linker patches. - void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; + void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) OVERRIDE; void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) OVERRIDE; // Fast path implementation of ReadBarrier::Barrier for a heap @@ -497,14 +497,14 @@ class CodeGeneratorMIPS64 : public CodeGenerator { void Finalize(CodeAllocator* allocator) OVERRIDE; // Code generation helpers. - void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; + void MoveLocation(Location dst, Location src, DataType::Type dst_type) OVERRIDE; void MoveConstant(Location destination, int32_t value) OVERRIDE; void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; - void SwapLocations(Location loc1, Location loc2, Primitive::Type type); + void SwapLocations(Location loc1, Location loc2, DataType::Type type); // Generate code to invoke a runtime entry point. void InvokeRuntime(QuickEntrypointEnum entrypoint, @@ -522,7 +522,7 @@ class CodeGeneratorMIPS64 : public CodeGenerator { ParallelMoveResolver* GetMoveResolver() OVERRIDE { return &move_resolver_; } - bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return false; } + bool NeedsTwoRegisters(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return false; } // Check if the desired_string_load_kind is supported. If it is, return it, // otherwise return a fall-back kind that should be used instead. @@ -546,7 +546,7 @@ class CodeGeneratorMIPS64 : public CodeGenerator { HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE; void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED, - Primitive::Type type ATTRIBUTE_UNUSED) OVERRIDE { + DataType::Type type ATTRIBUTE_UNUSED) OVERRIDE { UNIMPLEMENTED(FATAL) << "Not implemented on MIPS64"; } @@ -643,9 +643,9 @@ class CodeGeneratorMIPS64 : public CodeGenerator { const PcRelativePatchInfo* info_high, ArenaDeque<PcRelativePatchInfo>* patches); - template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> + template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> void EmitPcRelativeLinkerPatches(const ArenaDeque<PcRelativePatchInfo>& infos, - ArenaVector<LinkerPatch>* linker_patches); + ArenaVector<linker::LinkerPatch>* linker_patches); // Labels for each block that will be compiled. Mips64Label* block_labels_; // Indexed by block id. diff --git a/compiler/optimizing/code_generator_vector_arm64.cc b/compiler/optimizing/code_generator_vector_arm64.cc index 18a55c8b09..5d5623bbe7 100644 --- a/compiler/optimizing/code_generator_vector_arm64.cc +++ b/compiler/optimizing/code_generator_vector_arm64.cc @@ -41,17 +41,17 @@ void LocationsBuilderARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruc LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); HInstruction* input = instruction->InputAt(0); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, ARM64EncodableConstantOrRegister(input, instruction)); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: if (input->IsConstant() && Arm64CanEncodeConstantAsImmediate(input->AsConstant(), instruction)) { locations->SetInAt(0, Location::ConstantLocation(input->AsConstant())); @@ -72,8 +72,8 @@ void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* Location src_loc = locations->InAt(0); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (src_loc.IsConstant()) { __ Movi(dst.V16B(), Int64ConstantFrom(src_loc)); @@ -81,8 +81,8 @@ void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* __ Dup(dst.V16B(), InputRegisterAt(instruction, 0)); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (src_loc.IsConstant()) { __ Movi(dst.V8H(), Int64ConstantFrom(src_loc)); @@ -90,7 +90,7 @@ void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* __ Dup(dst.V8H(), InputRegisterAt(instruction, 0)); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (src_loc.IsConstant()) { __ Movi(dst.V4S(), Int64ConstantFrom(src_loc)); @@ -98,7 +98,7 @@ void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* __ Dup(dst.V4S(), InputRegisterAt(instruction, 0)); } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); if (src_loc.IsConstant()) { __ Movi(dst.V2D(), Int64ConstantFrom(src_loc)); @@ -106,7 +106,7 @@ void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* __ Dup(dst.V2D(), XRegisterFrom(src_loc)); } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (src_loc.IsConstant()) { __ Fmov(dst.V4S(), src_loc.GetConstant()->AsFloatConstant()->GetValue()); @@ -114,7 +114,7 @@ void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* __ Dup(dst.V4S(), VRegisterFrom(src_loc).V4S(), 0); } break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); if (src_loc.IsConstant()) { __ Fmov(dst.V2D(), src_loc.GetConstant()->AsDoubleConstant()->GetValue()); @@ -131,17 +131,17 @@ void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* void LocationsBuilderARM64::VisitVecExtractScalar(HVecExtractScalar* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); break; @@ -155,16 +155,16 @@ void InstructionCodeGeneratorARM64::VisitVecExtractScalar(HVecExtractScalar* ins LocationSummary* locations = instruction->GetLocations(); VRegister src = VRegisterFrom(locations->InAt(0)); switch (instruction->GetPackedType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Umov(OutputRegister(instruction), src.V4S(), 0); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Umov(OutputRegister(instruction), src.V2D(), 0); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 4u); DCHECK(locations->InAt(0).Equals(locations->Out())); // no code required @@ -179,19 +179,19 @@ void InstructionCodeGeneratorARM64::VisitVecExtractScalar(HVecExtractScalar* ins static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), instruction->IsVecNot() ? Location::kOutputOverlap : Location::kNoOutputOverlap); break; - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); break; @@ -210,7 +210,7 @@ void InstructionCodeGeneratorARM64::VisitVecReduce(HVecReduce* instruction) { VRegister src = VRegisterFrom(locations->InAt(0)); VRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); switch (instruction->GetKind()) { case HVecReduce::kSum: @@ -224,7 +224,7 @@ void InstructionCodeGeneratorARM64::VisitVecReduce(HVecReduce* instruction) { break; } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); switch (instruction->GetKind()) { case HVecReduce::kSum: @@ -249,9 +249,9 @@ void InstructionCodeGeneratorARM64::VisitVecCnv(HVecCnv* instruction) { LocationSummary* locations = instruction->GetLocations(); VRegister src = VRegisterFrom(locations->InAt(0)); VRegister dst = VRegisterFrom(locations->Out()); - Primitive::Type from = instruction->GetInputType(); - Primitive::Type to = instruction->GetResultType(); - if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) { + DataType::Type from = instruction->GetInputType(); + DataType::Type to = instruction->GetResultType(); + if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) { DCHECK_EQ(4u, instruction->GetVectorLength()); __ Scvtf(dst.V4S(), src.V4S()); } else { @@ -268,28 +268,28 @@ void InstructionCodeGeneratorARM64::VisitVecNeg(HVecNeg* instruction) { VRegister src = VRegisterFrom(locations->InAt(0)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ Neg(dst.V16B(), src.V16B()); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Neg(dst.V8H(), src.V8H()); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Neg(dst.V4S(), src.V4S()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Neg(dst.V2D(), src.V2D()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Fneg(dst.V4S(), src.V4S()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Fneg(dst.V2D(), src.V2D()); break; @@ -308,28 +308,28 @@ void InstructionCodeGeneratorARM64::VisitVecAbs(HVecAbs* instruction) { VRegister src = VRegisterFrom(locations->InAt(0)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ Abs(dst.V16B(), src.V16B()); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Abs(dst.V8H(), src.V8H()); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Abs(dst.V4S(), src.V4S()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Abs(dst.V2D(), src.V2D()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Fabs(dst.V4S(), src.V4S()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Fabs(dst.V2D(), src.V2D()); break; @@ -348,16 +348,16 @@ void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) { VRegister src = VRegisterFrom(locations->InAt(0)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: // special case boolean-not + case DataType::Type::kBool: // special case boolean-not DCHECK_EQ(16u, instruction->GetVectorLength()); __ Movi(dst.V16B(), 1); __ Eor(dst.V16B(), dst.V16B(), src.V16B()); break; - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: __ Not(dst.V16B(), src.V16B()); // lanes do not matter break; default: @@ -370,14 +370,14 @@ void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) { static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -398,28 +398,28 @@ void InstructionCodeGeneratorARM64::VisitVecAdd(HVecAdd* instruction) { VRegister rhs = VRegisterFrom(locations->InAt(1)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ Add(dst.V16B(), lhs.V16B(), rhs.V16B()); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Add(dst.V8H(), lhs.V8H(), rhs.V8H()); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Add(dst.V4S(), lhs.V4S(), rhs.V4S()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Add(dst.V2D(), lhs.V2D(), rhs.V2D()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Fadd(dst.V4S(), lhs.V4S(), rhs.V4S()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Fadd(dst.V2D(), lhs.V2D(), rhs.V2D()); break; @@ -439,7 +439,7 @@ void InstructionCodeGeneratorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instructi VRegister rhs = VRegisterFrom(locations->InAt(1)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { instruction->IsRounded() @@ -451,8 +451,8 @@ void InstructionCodeGeneratorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instructi : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B()); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { instruction->IsRounded() @@ -480,28 +480,28 @@ void InstructionCodeGeneratorARM64::VisitVecSub(HVecSub* instruction) { VRegister rhs = VRegisterFrom(locations->InAt(1)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ Sub(dst.V16B(), lhs.V16B(), rhs.V16B()); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Sub(dst.V8H(), lhs.V8H(), rhs.V8H()); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Sub(dst.V4S(), lhs.V4S(), rhs.V4S()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Sub(dst.V2D(), lhs.V2D(), rhs.V2D()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Fsub(dst.V2D(), lhs.V2D(), rhs.V2D()); break; @@ -521,24 +521,24 @@ void InstructionCodeGeneratorARM64::VisitVecMul(HVecMul* instruction) { VRegister rhs = VRegisterFrom(locations->InAt(1)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B()); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H()); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Fmul(dst.V2D(), lhs.V2D(), rhs.V2D()); break; @@ -558,11 +558,11 @@ void InstructionCodeGeneratorARM64::VisitVecDiv(HVecDiv* instruction) { VRegister rhs = VRegisterFrom(locations->InAt(1)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Fdiv(dst.V2D(), lhs.V2D(), rhs.V2D()); break; @@ -582,7 +582,7 @@ void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) { VRegister rhs = VRegisterFrom(locations->InAt(1)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B()); @@ -590,8 +590,8 @@ void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) { __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B()); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H()); @@ -599,7 +599,7 @@ void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) { __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H()); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Umin(dst.V4S(), lhs.V4S(), rhs.V4S()); @@ -607,12 +607,12 @@ void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) { __ Smin(dst.V4S(), lhs.V4S(), rhs.V4S()); } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ Fmin(dst.V4S(), lhs.V4S(), rhs.V4S()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ Fmin(dst.V2D(), lhs.V2D(), rhs.V2D()); @@ -633,7 +633,7 @@ void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) { VRegister rhs = VRegisterFrom(locations->InAt(1)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B()); @@ -641,8 +641,8 @@ void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) { __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B()); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H()); @@ -650,7 +650,7 @@ void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) { __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H()); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Umax(dst.V4S(), lhs.V4S(), rhs.V4S()); @@ -658,12 +658,12 @@ void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) { __ Smax(dst.V4S(), lhs.V4S(), rhs.V4S()); } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ Fmax(dst.V4S(), lhs.V4S(), rhs.V4S()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ Fmax(dst.V2D(), lhs.V2D(), rhs.V2D()); @@ -684,14 +684,14 @@ void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) { VRegister rhs = VRegisterFrom(locations->InAt(1)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ And(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter break; default: @@ -718,14 +718,14 @@ void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) { VRegister rhs = VRegisterFrom(locations->InAt(1)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter break; default: @@ -744,14 +744,14 @@ void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) { VRegister rhs = VRegisterFrom(locations->InAt(1)); VRegister dst = VRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter break; default: @@ -764,11 +764,11 @@ void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) { static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant())); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -789,20 +789,20 @@ void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) { VRegister dst = VRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ Shl(dst.V16B(), lhs.V16B(), value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Shl(dst.V8H(), lhs.V8H(), value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Shl(dst.V4S(), lhs.V4S(), value); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Shl(dst.V2D(), lhs.V2D(), value); break; @@ -822,20 +822,20 @@ void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) { VRegister dst = VRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ Sshr(dst.V16B(), lhs.V16B(), value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Sshr(dst.V8H(), lhs.V8H(), value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Sshr(dst.V4S(), lhs.V4S(), value); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Sshr(dst.V2D(), lhs.V2D(), value); break; @@ -855,20 +855,20 @@ void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) { VRegister dst = VRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ Ushr(dst.V16B(), lhs.V16B(), value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Ushr(dst.V8H(), lhs.V8H(), value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Ushr(dst.V4S(), lhs.V4S(), value); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Ushr(dst.V2D(), lhs.V2D(), value); break; @@ -887,18 +887,18 @@ void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) { bool is_zero = IsZeroBitPattern(input); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant()) : Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant()) : Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister()); @@ -925,21 +925,21 @@ void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instructi // Set required elements. switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ Mov(dst.V16B(), 0, InputRegisterAt(instruction, 0)); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Mov(dst.V8H(), 0, InputRegisterAt(instruction, 0)); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Mov(dst.V4S(), 0, InputRegisterAt(instruction, 0)); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Mov(dst.V2D(), 0, InputRegisterAt(instruction, 0)); break; @@ -949,20 +949,18 @@ void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instructi } } -void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { - LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr); - switch (instr->GetPackedType()) { - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - locations->SetInAt( - HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister()); - locations->SetInAt( - HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister()); - locations->SetInAt( - HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister()); - DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0); +// Helper to set up locations for vector accumulations. +static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { + LocationSummary* locations = new (arena) LocationSummary(instruction); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetInAt(1, Location::RequiresFpuRegister()); + locations->SetInAt(2, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); break; default: @@ -971,35 +969,42 @@ void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* i } } +void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); +} + // Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a // 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result. // However vector MultiplyAccumulate instruction is not affected. -void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { - LocationSummary* locations = instr->GetLocations(); - VRegister acc = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex)); - VRegister left = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex)); - VRegister right = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex)); - switch (instr->GetPackedType()) { - case Primitive::kPrimByte: - DCHECK_EQ(16u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { +void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + LocationSummary* locations = instruction->GetLocations(); + VRegister acc = VRegisterFrom(locations->InAt(0)); + VRegister left = VRegisterFrom(locations->InAt(1)); + VRegister right = VRegisterFrom(locations->InAt(2)); + + DCHECK(locations->InAt(0).Equals(locations->Out())); + + switch (instruction->GetPackedType()) { + case DataType::Type::kInt8: + DCHECK_EQ(16u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ Mla(acc.V16B(), left.V16B(), right.V16B()); } else { __ Mls(acc.V16B(), left.V16B(), right.V16B()); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: - DCHECK_EQ(8u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { + case DataType::Type::kUint16: + case DataType::Type::kInt16: + DCHECK_EQ(8u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ Mla(acc.V8H(), left.V8H(), right.V8H()); } else { __ Mls(acc.V8H(), left.V8H(), right.V8H()); } break; - case Primitive::kPrimInt: - DCHECK_EQ(4u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { + case DataType::Type::kInt32: + DCHECK_EQ(4u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ Mla(acc.V4S(), left.V4S(), right.V4S()); } else { __ Mls(acc.V4S(), left.V4S(), right.V4S()); @@ -1007,6 +1012,186 @@ void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccum break; default: LOG(FATAL) << "Unsupported SIMD type"; + UNREACHABLE(); + } +} + +void LocationsBuilderARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); + // Some conversions require temporary registers. + LocationSummary* locations = instruction->GetLocations(); + HVecOperation* a = instruction->InputAt(1)->AsVecOperation(); + HVecOperation* b = instruction->InputAt(2)->AsVecOperation(); + DCHECK_EQ(a->GetPackedType(), b->GetPackedType()); + switch (a->GetPackedType()) { + case DataType::Type::kInt8: + switch (instruction->GetPackedType()) { + case DataType::Type::kInt64: + locations->AddTemp(Location::RequiresFpuRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); + FALLTHROUGH_INTENDED; + case DataType::Type::kInt32: + locations->AddTemp(Location::RequiresFpuRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); + break; + default: + break; + } + break; + case DataType::Type::kUint16: + case DataType::Type::kInt16: + if (instruction->GetPackedType() == DataType::Type::kInt64) { + locations->AddTemp(Location::RequiresFpuRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); + } + break; + case DataType::Type::kInt32: + case DataType::Type::kInt64: + if (instruction->GetPackedType() == a->GetPackedType()) { + locations->AddTemp(Location::RequiresFpuRegister()); + } + break; + default: + break; + } +} + +void InstructionCodeGeneratorARM64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + LocationSummary* locations = instruction->GetLocations(); + VRegister acc = VRegisterFrom(locations->InAt(0)); + VRegister left = VRegisterFrom(locations->InAt(1)); + VRegister right = VRegisterFrom(locations->InAt(2)); + + DCHECK(locations->InAt(0).Equals(locations->Out())); + + // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S). + HVecOperation* a = instruction->InputAt(1)->AsVecOperation(); + HVecOperation* b = instruction->InputAt(2)->AsVecOperation(); + DCHECK_EQ(a->GetPackedType(), b->GetPackedType()); + switch (a->GetPackedType()) { + case DataType::Type::kInt8: + DCHECK_EQ(16u, a->GetVectorLength()); + switch (instruction->GetPackedType()) { + case DataType::Type::kUint16: + case DataType::Type::kInt16: + DCHECK_EQ(8u, instruction->GetVectorLength()); + __ Sabal(acc.V8H(), left.V8B(), right.V8B()); + __ Sabal2(acc.V8H(), left.V16B(), right.V16B()); + break; + case DataType::Type::kInt32: { + DCHECK_EQ(4u, instruction->GetVectorLength()); + VRegister tmp1 = VRegisterFrom(locations->GetTemp(0)); + VRegister tmp2 = VRegisterFrom(locations->GetTemp(1)); + __ Sxtl(tmp1.V8H(), left.V8B()); + __ Sxtl(tmp2.V8H(), right.V8B()); + __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H()); + __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H()); + __ Sxtl2(tmp1.V8H(), left.V16B()); + __ Sxtl2(tmp2.V8H(), right.V16B()); + __ Sabal(acc.V4S(), tmp1.V4H(), tmp2.V4H()); + __ Sabal2(acc.V4S(), tmp1.V8H(), tmp2.V8H()); + break; + } + case DataType::Type::kInt64: { + DCHECK_EQ(2u, instruction->GetVectorLength()); + VRegister tmp1 = VRegisterFrom(locations->GetTemp(0)); + VRegister tmp2 = VRegisterFrom(locations->GetTemp(1)); + VRegister tmp3 = VRegisterFrom(locations->GetTemp(2)); + VRegister tmp4 = VRegisterFrom(locations->GetTemp(3)); + __ Sxtl(tmp1.V8H(), left.V8B()); + __ Sxtl(tmp2.V8H(), right.V8B()); + __ Sxtl(tmp3.V4S(), tmp1.V4H()); + __ Sxtl(tmp4.V4S(), tmp2.V4H()); + __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S()); + __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S()); + __ Sxtl2(tmp3.V4S(), tmp1.V8H()); + __ Sxtl2(tmp4.V4S(), tmp2.V8H()); + __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S()); + __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S()); + __ Sxtl2(tmp1.V8H(), left.V16B()); + __ Sxtl2(tmp2.V8H(), right.V16B()); + __ Sxtl(tmp3.V4S(), tmp1.V4H()); + __ Sxtl(tmp4.V4S(), tmp2.V4H()); + __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S()); + __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S()); + __ Sxtl2(tmp3.V4S(), tmp1.V8H()); + __ Sxtl2(tmp4.V4S(), tmp2.V8H()); + __ Sabal(acc.V2D(), tmp3.V2S(), tmp4.V2S()); + __ Sabal2(acc.V2D(), tmp3.V4S(), tmp4.V4S()); + break; + } + default: + LOG(FATAL) << "Unsupported SIMD type"; + UNREACHABLE(); + } + break; + case DataType::Type::kUint16: + case DataType::Type::kInt16: + DCHECK_EQ(8u, a->GetVectorLength()); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt32: + DCHECK_EQ(4u, instruction->GetVectorLength()); + __ Sabal(acc.V4S(), left.V4H(), right.V4H()); + __ Sabal2(acc.V4S(), left.V8H(), right.V8H()); + break; + case DataType::Type::kInt64: { + DCHECK_EQ(2u, instruction->GetVectorLength()); + VRegister tmp1 = VRegisterFrom(locations->GetTemp(0)); + VRegister tmp2 = VRegisterFrom(locations->GetTemp(1)); + __ Sxtl(tmp1.V4S(), left.V4H()); + __ Sxtl(tmp2.V4S(), right.V4H()); + __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S()); + __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S()); + __ Sxtl2(tmp1.V4S(), left.V8H()); + __ Sxtl2(tmp2.V4S(), right.V8H()); + __ Sabal(acc.V2D(), tmp1.V2S(), tmp2.V2S()); + __ Sabal2(acc.V2D(), tmp1.V4S(), tmp2.V4S()); + break; + } + default: + LOG(FATAL) << "Unsupported SIMD type"; + UNREACHABLE(); + } + break; + case DataType::Type::kInt32: + DCHECK_EQ(4u, a->GetVectorLength()); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt32: { + DCHECK_EQ(4u, instruction->GetVectorLength()); + VRegister tmp = VRegisterFrom(locations->GetTemp(0)); + __ Sub(tmp.V4S(), left.V4S(), right.V4S()); + __ Abs(tmp.V4S(), tmp.V4S()); + __ Add(acc.V4S(), acc.V4S(), tmp.V4S()); + break; + } + case DataType::Type::kInt64: + DCHECK_EQ(2u, instruction->GetVectorLength()); + __ Sabal(acc.V2D(), left.V2S(), right.V2S()); + __ Sabal2(acc.V2D(), left.V4S(), right.V4S()); + break; + default: + LOG(FATAL) << "Unsupported SIMD type"; + UNREACHABLE(); + } + break; + case DataType::Type::kInt64: + DCHECK_EQ(2u, a->GetVectorLength()); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt64: { + DCHECK_EQ(2u, instruction->GetVectorLength()); + VRegister tmp = VRegisterFrom(locations->GetTemp(0)); + __ Sub(tmp.V2D(), left.V2D(), right.V2D()); + __ Abs(tmp.V2D(), tmp.V2D()); + __ Add(acc.V2D(), acc.V2D(), tmp.V2D()); + break; + } + default: + LOG(FATAL) << "Unsupported SIMD type"; + UNREACHABLE(); + } + break; + default: + LOG(FATAL) << "Unsupported SIMD type"; } } @@ -1016,14 +1201,14 @@ static void CreateVecMemLocations(ArenaAllocator* arena, bool is_load) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); if (is_load) { @@ -1080,13 +1265,13 @@ void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) { void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) { LocationSummary* locations = instruction->GetLocations(); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); VRegister reg = VRegisterFrom(locations->Out()); UseScratchRegisterScope temps(GetVIXLAssembler()); Register scratch; switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: + case DataType::Type::kUint16: DCHECK_EQ(8u, instruction->GetVectorLength()); // Special handling of compressed/uncompressed string load. if (mirror::kUseStringCompression && instruction->IsStringCharAt()) { @@ -1114,13 +1299,13 @@ void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) { return; } FALLTHROUGH_INTENDED; - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimFloat: - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ Ldr(reg, VecAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch)); @@ -1137,20 +1322,20 @@ void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) { void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) { LocationSummary* locations = instruction->GetLocations(); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); VRegister reg = VRegisterFrom(locations->InAt(2)); UseScratchRegisterScope temps(GetVIXLAssembler()); Register scratch; switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimFloat: - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ Str(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch)); diff --git a/compiler/optimizing/code_generator_vector_arm_vixl.cc b/compiler/optimizing/code_generator_vector_arm_vixl.cc index 7a11dff41e..333d108f2c 100644 --- a/compiler/optimizing/code_generator_vector_arm_vixl.cc +++ b/compiler/optimizing/code_generator_vector_arm_vixl.cc @@ -35,11 +35,11 @@ using helpers::RegisterFrom; void LocationsBuilderARMVIXL::VisitVecReplicateScalar(HVecReplicateScalar* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; @@ -53,17 +53,17 @@ void InstructionCodeGeneratorARMVIXL::VisitVecReplicateScalar(HVecReplicateScala LocationSummary* locations = instruction->GetLocations(); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Vdup(Untyped8, dst, InputRegisterAt(instruction, 0)); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Vdup(Untyped16, dst, InputRegisterAt(instruction, 0)); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Vdup(Untyped32, dst, InputRegisterAt(instruction, 0)); break; @@ -85,16 +85,16 @@ void InstructionCodeGeneratorARMVIXL::VisitVecExtractScalar(HVecExtractScalar* i static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), instruction->IsVecNot() ? Location::kOutputOverlap : Location::kNoOutputOverlap); break; - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); break; @@ -129,16 +129,16 @@ void InstructionCodeGeneratorARMVIXL::VisitVecNeg(HVecNeg* instruction) { vixl32::DRegister src = DRegisterFrom(locations->InAt(0)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Vneg(DataTypeValue::S8, dst, src); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Vneg(DataTypeValue::S16, dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Vneg(DataTypeValue::S32, dst, src); break; @@ -157,16 +157,16 @@ void InstructionCodeGeneratorARMVIXL::VisitVecAbs(HVecAbs* instruction) { vixl32::DRegister src = DRegisterFrom(locations->InAt(0)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Vabs(DataTypeValue::S8, dst, src); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Vabs(DataTypeValue::S16, dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Vabs(DataTypeValue::S32, dst, src); break; @@ -185,15 +185,15 @@ void InstructionCodeGeneratorARMVIXL::VisitVecNot(HVecNot* instruction) { vixl32::DRegister src = DRegisterFrom(locations->InAt(0)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: // special case boolean-not + case DataType::Type::kBool: // special case boolean-not DCHECK_EQ(8u, instruction->GetVectorLength()); __ Vmov(I8, dst, 1); __ Veor(dst, dst, src); break; - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: __ Vmvn(I8, dst, src); // lanes do not matter break; default: @@ -206,11 +206,11 @@ void InstructionCodeGeneratorARMVIXL::VisitVecNot(HVecNot* instruction) { static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -231,16 +231,16 @@ void InstructionCodeGeneratorARMVIXL::VisitVecAdd(HVecAdd* instruction) { vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Vadd(I8, dst, lhs, rhs); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Vadd(I16, dst, lhs, rhs); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Vadd(I32, dst, lhs, rhs); break; @@ -260,7 +260,7 @@ void InstructionCodeGeneratorARMVIXL::VisitVecHalvingAdd(HVecHalvingAdd* instruc vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { instruction->IsRounded() @@ -272,8 +272,8 @@ void InstructionCodeGeneratorARMVIXL::VisitVecHalvingAdd(HVecHalvingAdd* instruc : __ Vhadd(DataTypeValue::S8, dst, lhs, rhs); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { instruction->IsRounded() @@ -301,16 +301,16 @@ void InstructionCodeGeneratorARMVIXL::VisitVecSub(HVecSub* instruction) { vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Vsub(I8, dst, lhs, rhs); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Vsub(I16, dst, lhs, rhs); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Vsub(I32, dst, lhs, rhs); break; @@ -330,16 +330,16 @@ void InstructionCodeGeneratorARMVIXL::VisitVecMul(HVecMul* instruction) { vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Vmul(I8, dst, lhs, rhs); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Vmul(I16, dst, lhs, rhs); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Vmul(I32, dst, lhs, rhs); break; @@ -367,7 +367,7 @@ void InstructionCodeGeneratorARMVIXL::VisitVecMin(HVecMin* instruction) { vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Vmin(DataTypeValue::U8, dst, lhs, rhs); @@ -375,8 +375,8 @@ void InstructionCodeGeneratorARMVIXL::VisitVecMin(HVecMin* instruction) { __ Vmin(DataTypeValue::S8, dst, lhs, rhs); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Vmin(DataTypeValue::U16, dst, lhs, rhs); @@ -384,7 +384,7 @@ void InstructionCodeGeneratorARMVIXL::VisitVecMin(HVecMin* instruction) { __ Vmin(DataTypeValue::S16, dst, lhs, rhs); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Vmin(DataTypeValue::U32, dst, lhs, rhs); @@ -408,7 +408,7 @@ void InstructionCodeGeneratorARMVIXL::VisitVecMax(HVecMax* instruction) { vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Vmax(DataTypeValue::U8, dst, lhs, rhs); @@ -416,8 +416,8 @@ void InstructionCodeGeneratorARMVIXL::VisitVecMax(HVecMax* instruction) { __ Vmax(DataTypeValue::S8, dst, lhs, rhs); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Vmax(DataTypeValue::U16, dst, lhs, rhs); @@ -425,7 +425,7 @@ void InstructionCodeGeneratorARMVIXL::VisitVecMax(HVecMax* instruction) { __ Vmax(DataTypeValue::S16, dst, lhs, rhs); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Vmax(DataTypeValue::U32, dst, lhs, rhs); @@ -449,11 +449,11 @@ void InstructionCodeGeneratorARMVIXL::VisitVecAnd(HVecAnd* instruction) { vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: __ Vand(I8, dst, lhs, rhs); break; default: @@ -480,11 +480,11 @@ void InstructionCodeGeneratorARMVIXL::VisitVecOr(HVecOr* instruction) { vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: __ Vorr(I8, dst, lhs, rhs); break; default: @@ -503,11 +503,11 @@ void InstructionCodeGeneratorARMVIXL::VisitVecXor(HVecXor* instruction) { vixl32::DRegister rhs = DRegisterFrom(locations->InAt(1)); vixl32::DRegister dst = DRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: __ Veor(I8, dst, lhs, rhs); break; default: @@ -520,10 +520,10 @@ void InstructionCodeGeneratorARMVIXL::VisitVecXor(HVecXor* instruction) { static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant())); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -544,16 +544,16 @@ void InstructionCodeGeneratorARMVIXL::VisitVecShl(HVecShl* instruction) { vixl32::DRegister dst = DRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Vshl(I8, dst, lhs, value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Vshl(I16, dst, lhs, value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Vshl(I32, dst, lhs, value); break; @@ -573,16 +573,16 @@ void InstructionCodeGeneratorARMVIXL::VisitVecShr(HVecShr* instruction) { vixl32::DRegister dst = DRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Vshr(DataTypeValue::S8, dst, lhs, value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Vshr(DataTypeValue::S16, dst, lhs, value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Vshr(DataTypeValue::S32, dst, lhs, value); break; @@ -602,16 +602,16 @@ void InstructionCodeGeneratorARMVIXL::VisitVecUShr(HVecUShr* instruction) { vixl32::DRegister dst = DRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); __ Vshr(DataTypeValue::U8, dst, lhs, value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); __ Vshr(DataTypeValue::U16, dst, lhs, value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Vshr(DataTypeValue::U32, dst, lhs, value); break; @@ -629,12 +629,40 @@ void InstructionCodeGeneratorARMVIXL::VisitVecSetScalars(HVecSetScalars* instruc LOG(FATAL) << "No SIMD for " << instruction->GetId(); } -void LocationsBuilderARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { - LOG(FATAL) << "No SIMD for " << instr->GetId(); +// Helper to set up locations for vector accumulations. +static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { + LocationSummary* locations = new (arena) LocationSummary(instruction); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetInAt(1, Location::RequiresFpuRegister()); + locations->SetInAt(2, Location::RequiresFpuRegister()); + locations->SetOut(Location::SameAsFirstInput()); + break; + default: + LOG(FATAL) << "Unsupported SIMD type"; + UNREACHABLE(); + } } -void InstructionCodeGeneratorARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { - LOG(FATAL) << "No SIMD for " << instr->GetId(); +void LocationsBuilderARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); +} + +void InstructionCodeGeneratorARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + LOG(FATAL) << "No SIMD for " << instruction->GetId(); +} + +void LocationsBuilderARMVIXL::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); +} + +void InstructionCodeGeneratorARMVIXL::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + LOG(FATAL) << "No SIMD for " << instruction->GetId(); } // Return whether the vector memory access operation is guaranteed to be word-aligned (ARM word @@ -649,11 +677,11 @@ static void CreateVecMemLocations(ArenaAllocator* arena, bool is_load) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); if (is_load) { @@ -679,7 +707,7 @@ MemOperand InstructionCodeGeneratorARMVIXL::VecAddress( vixl32::Register base = InputRegisterAt(instruction, 0); Location index = locations->InAt(1); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); uint32_t offset = mirror::Array::DataOffset(size).Uint32Value(); size_t shift = ComponentSizeShiftWidth(size); @@ -705,7 +733,7 @@ AlignedMemOperand InstructionCodeGeneratorARMVIXL::VecAddressUnaligned( vixl32::Register base = InputRegisterAt(instruction, 0); Location index = locations->InAt(1); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); uint32_t offset = mirror::Array::DataOffset(size).Uint32Value(); size_t shift = ComponentSizeShiftWidth(size); @@ -732,11 +760,11 @@ void InstructionCodeGeneratorARMVIXL::VisitVecLoad(HVecLoad* instruction) { UseScratchRegisterScope temps(GetVIXLAssembler()); vixl32::Register scratch; - DCHECK(instruction->GetPackedType() != Primitive::kPrimChar || !instruction->IsStringCharAt()); + DCHECK(instruction->GetPackedType() != DataType::Type::kUint16 || !instruction->IsStringCharAt()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); if (IsWordAligned(instruction)) { __ Vldr(reg, VecAddress(instruction, &temps, &scratch)); @@ -746,8 +774,8 @@ void InstructionCodeGeneratorARMVIXL::VisitVecLoad(HVecLoad* instruction) { VecAddressUnaligned(instruction, &temps, &scratch)); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); if (IsWordAligned(instruction)) { __ Vldr(reg, VecAddress(instruction, &temps, &scratch)); @@ -757,7 +785,7 @@ void InstructionCodeGeneratorARMVIXL::VisitVecLoad(HVecLoad* instruction) { VecAddressUnaligned(instruction, &temps, &scratch)); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); if (IsWordAligned(instruction)) { __ Vldr(reg, VecAddress(instruction, &temps, &scratch)); @@ -782,8 +810,8 @@ void InstructionCodeGeneratorARMVIXL::VisitVecStore(HVecStore* instruction) { UseScratchRegisterScope temps(GetVIXLAssembler()); vixl32::Register scratch; switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(8u, instruction->GetVectorLength()); if (IsWordAligned(instruction)) { __ Vstr(reg, VecAddress(instruction, &temps, &scratch)); @@ -793,8 +821,8 @@ void InstructionCodeGeneratorARMVIXL::VisitVecStore(HVecStore* instruction) { VecAddressUnaligned(instruction, &temps, &scratch)); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(4u, instruction->GetVectorLength()); if (IsWordAligned(instruction)) { __ Vstr(reg, VecAddress(instruction, &temps, &scratch)); @@ -804,7 +832,7 @@ void InstructionCodeGeneratorARMVIXL::VisitVecStore(HVecStore* instruction) { VecAddressUnaligned(instruction, &temps, &scratch)); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(2u, instruction->GetVectorLength()); if (IsWordAligned(instruction)) { __ Vstr(reg, VecAddress(instruction, &temps, &scratch)); diff --git a/compiler/optimizing/code_generator_vector_mips.cc b/compiler/optimizing/code_generator_vector_mips.cc index c2fbf7f04b..c25f5acb7e 100644 --- a/compiler/optimizing/code_generator_vector_mips.cc +++ b/compiler/optimizing/code_generator_vector_mips.cc @@ -26,17 +26,17 @@ namespace mips { void LocationsBuilderMIPS::VisitVecReplicateScalar(HVecReplicateScalar* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); break; @@ -50,33 +50,33 @@ void InstructionCodeGeneratorMIPS::VisitVecReplicateScalar(HVecReplicateScalar* LocationSummary* locations = instruction->GetLocations(); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ FillB(dst, locations->InAt(0).AsRegister<Register>()); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ FillH(dst, locations->InAt(0).AsRegister<Register>()); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FillW(dst, locations->InAt(0).AsRegister<Register>()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ Mtc1(locations->InAt(0).AsRegisterPairLow<Register>(), FTMP); __ MoveToFpuHigh(locations->InAt(0).AsRegisterPairHigh<Register>(), FTMP); __ ReplicateFPToVectorRegister(dst, FTMP, /* is_double */ true); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ ReplicateFPToVectorRegister(dst, locations->InAt(0).AsFpuRegister<FRegister>(), /* is_double */ false); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ ReplicateFPToVectorRegister(dst, locations->InAt(0).AsFpuRegister<FRegister>(), @@ -100,19 +100,19 @@ void InstructionCodeGeneratorMIPS::VisitVecExtractScalar(HVecExtractScalar* inst static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), instruction->IsVecNot() ? Location::kOutputOverlap : Location::kNoOutputOverlap); break; - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), (instruction->IsVecNeg() || instruction->IsVecAbs()) @@ -141,9 +141,9 @@ void InstructionCodeGeneratorMIPS::VisitVecCnv(HVecCnv* instruction) { LocationSummary* locations = instruction->GetLocations(); VectorRegister src = VectorRegisterFrom(locations->InAt(0)); VectorRegister dst = VectorRegisterFrom(locations->Out()); - Primitive::Type from = instruction->GetInputType(); - Primitive::Type to = instruction->GetResultType(); - if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) { + DataType::Type from = instruction->GetInputType(); + DataType::Type to = instruction->GetResultType(); + if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) { DCHECK_EQ(4u, instruction->GetVectorLength()); __ Ffint_sW(dst, src); } else { @@ -160,33 +160,33 @@ void InstructionCodeGeneratorMIPS::VisitVecNeg(HVecNeg* instruction) { VectorRegister src = VectorRegisterFrom(locations->InAt(0)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ FillB(dst, ZERO); __ SubvB(dst, dst, src); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ FillH(dst, ZERO); __ SubvH(dst, dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FillW(dst, ZERO); __ SubvW(dst, dst, src); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FillW(dst, ZERO); __ SubvD(dst, dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FillW(dst, ZERO); __ FsubW(dst, dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FillW(dst, ZERO); __ FsubD(dst, dst, src); @@ -206,34 +206,34 @@ void InstructionCodeGeneratorMIPS::VisitVecAbs(HVecAbs* instruction) { VectorRegister src = VectorRegisterFrom(locations->InAt(0)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ FillB(dst, ZERO); // all zeroes __ Add_aB(dst, dst, src); // dst = abs(0) + abs(src) break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ FillH(dst, ZERO); // all zeroes __ Add_aH(dst, dst, src); // dst = abs(0) + abs(src) break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FillW(dst, ZERO); // all zeroes __ Add_aW(dst, dst, src); // dst = abs(0) + abs(src) break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FillW(dst, ZERO); // all zeroes __ Add_aD(dst, dst, src); // dst = abs(0) + abs(src) break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ LdiW(dst, -1); // all ones __ SrliW(dst, dst, 1); __ AndV(dst, dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ LdiD(dst, -1); // all ones __ SrliD(dst, dst, 1); @@ -254,18 +254,18 @@ void InstructionCodeGeneratorMIPS::VisitVecNot(HVecNot* instruction) { VectorRegister src = VectorRegisterFrom(locations->InAt(0)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: // special case boolean-not + case DataType::Type::kBool: // special case boolean-not DCHECK_EQ(16u, instruction->GetVectorLength()); __ LdiB(dst, 1); __ XorV(dst, dst, src); break; - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ NorV(dst, src, src); // lanes do not matter @@ -280,14 +280,14 @@ void InstructionCodeGeneratorMIPS::VisitVecNot(HVecNot* instruction) { static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -308,28 +308,28 @@ void InstructionCodeGeneratorMIPS::VisitVecAdd(HVecAdd* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ AddvB(dst, lhs, rhs); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ AddvH(dst, lhs, rhs); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ AddvW(dst, lhs, rhs); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ AddvD(dst, lhs, rhs); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FaddW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FaddD(dst, lhs, rhs); break; @@ -349,7 +349,7 @@ void InstructionCodeGeneratorMIPS::VisitVecHalvingAdd(HVecHalvingAdd* instructio VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { instruction->IsRounded() @@ -361,8 +361,8 @@ void InstructionCodeGeneratorMIPS::VisitVecHalvingAdd(HVecHalvingAdd* instructio : __ Ave_sB(dst, lhs, rhs); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { instruction->IsRounded() @@ -390,28 +390,28 @@ void InstructionCodeGeneratorMIPS::VisitVecSub(HVecSub* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ SubvB(dst, lhs, rhs); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ SubvH(dst, lhs, rhs); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ SubvW(dst, lhs, rhs); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ SubvD(dst, lhs, rhs); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FsubW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FsubD(dst, lhs, rhs); break; @@ -431,28 +431,28 @@ void InstructionCodeGeneratorMIPS::VisitVecMul(HVecMul* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ MulvB(dst, lhs, rhs); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ MulvH(dst, lhs, rhs); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ MulvW(dst, lhs, rhs); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ MulvD(dst, lhs, rhs); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FmulW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FmulD(dst, lhs, rhs); break; @@ -472,11 +472,11 @@ void InstructionCodeGeneratorMIPS::VisitVecDiv(HVecDiv* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FdivW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FdivD(dst, lhs, rhs); break; @@ -496,7 +496,7 @@ void InstructionCodeGeneratorMIPS::VisitVecMin(HVecMin* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Min_uB(dst, lhs, rhs); @@ -504,8 +504,8 @@ void InstructionCodeGeneratorMIPS::VisitVecMin(HVecMin* instruction) { __ Min_sB(dst, lhs, rhs); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Min_uH(dst, lhs, rhs); @@ -513,7 +513,7 @@ void InstructionCodeGeneratorMIPS::VisitVecMin(HVecMin* instruction) { __ Min_sH(dst, lhs, rhs); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Min_uW(dst, lhs, rhs); @@ -521,7 +521,7 @@ void InstructionCodeGeneratorMIPS::VisitVecMin(HVecMin* instruction) { __ Min_sW(dst, lhs, rhs); } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Min_uD(dst, lhs, rhs); @@ -531,12 +531,12 @@ void InstructionCodeGeneratorMIPS::VisitVecMin(HVecMin* instruction) { break; // When one of arguments is NaN, fmin.df returns other argument, but Java expects a NaN value. // TODO: Fix min(x, NaN) cases for float and double. - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ FminW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ FminD(dst, lhs, rhs); @@ -557,7 +557,7 @@ void InstructionCodeGeneratorMIPS::VisitVecMax(HVecMax* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Max_uB(dst, lhs, rhs); @@ -565,8 +565,8 @@ void InstructionCodeGeneratorMIPS::VisitVecMax(HVecMax* instruction) { __ Max_sB(dst, lhs, rhs); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Max_uH(dst, lhs, rhs); @@ -574,7 +574,7 @@ void InstructionCodeGeneratorMIPS::VisitVecMax(HVecMax* instruction) { __ Max_sH(dst, lhs, rhs); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Max_uW(dst, lhs, rhs); @@ -582,7 +582,7 @@ void InstructionCodeGeneratorMIPS::VisitVecMax(HVecMax* instruction) { __ Max_sW(dst, lhs, rhs); } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Max_uD(dst, lhs, rhs); @@ -592,12 +592,12 @@ void InstructionCodeGeneratorMIPS::VisitVecMax(HVecMax* instruction) { break; // When one of arguments is NaN, fmax.df returns other argument, but Java expects a NaN value. // TODO: Fix max(x, NaN) cases for float and double. - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ FmaxW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ FmaxD(dst, lhs, rhs); @@ -618,14 +618,14 @@ void InstructionCodeGeneratorMIPS::VisitVecAnd(HVecAnd* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ AndV(dst, lhs, rhs); // lanes do not matter @@ -654,14 +654,14 @@ void InstructionCodeGeneratorMIPS::VisitVecOr(HVecOr* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ OrV(dst, lhs, rhs); // lanes do not matter @@ -682,14 +682,14 @@ void InstructionCodeGeneratorMIPS::VisitVecXor(HVecXor* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ XorV(dst, lhs, rhs); // lanes do not matter @@ -704,11 +704,11 @@ void InstructionCodeGeneratorMIPS::VisitVecXor(HVecXor* instruction) { static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant())); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -729,20 +729,20 @@ void InstructionCodeGeneratorMIPS::VisitVecShl(HVecShl* instruction) { VectorRegister dst = VectorRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ SlliB(dst, lhs, value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ SlliH(dst, lhs, value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ SlliW(dst, lhs, value); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ SlliD(dst, lhs, value); break; @@ -762,20 +762,20 @@ void InstructionCodeGeneratorMIPS::VisitVecShr(HVecShr* instruction) { VectorRegister dst = VectorRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ SraiB(dst, lhs, value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ SraiH(dst, lhs, value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ SraiW(dst, lhs, value); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ SraiD(dst, lhs, value); break; @@ -795,20 +795,20 @@ void InstructionCodeGeneratorMIPS::VisitVecUShr(HVecUShr* instruction) { VectorRegister dst = VectorRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ SrliB(dst, lhs, value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ SrliH(dst, lhs, value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ SrliW(dst, lhs, value); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ SrliD(dst, lhs, value); break; @@ -826,21 +826,18 @@ void InstructionCodeGeneratorMIPS::VisitVecSetScalars(HVecSetScalars* instructio LOG(FATAL) << "No SIMD for " << instruction->GetId(); } -void LocationsBuilderMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { - LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr); - switch (instr->GetPackedType()) { - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - locations->SetInAt( - HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister()); - locations->SetInAt( - HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister()); - locations->SetInAt( - HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister()); - DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0); +// Helper to set up locations for vector accumulations. +static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { + LocationSummary* locations = new (arena) LocationSummary(instruction); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetInAt(1, Location::RequiresFpuRegister()); + locations->SetInAt(2, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); break; default: @@ -849,43 +846,44 @@ void LocationsBuilderMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* in } } -void InstructionCodeGeneratorMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { - LocationSummary* locations = instr->GetLocations(); - VectorRegister acc = - VectorRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex)); - VectorRegister left = - VectorRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex)); - VectorRegister right = - VectorRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex)); - switch (instr->GetPackedType()) { - case Primitive::kPrimByte: - DCHECK_EQ(16u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { +void LocationsBuilderMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); +} + +void InstructionCodeGeneratorMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + LocationSummary* locations = instruction->GetLocations(); + VectorRegister acc = VectorRegisterFrom(locations->InAt(0)); + VectorRegister left = VectorRegisterFrom(locations->InAt(1)); + VectorRegister right = VectorRegisterFrom(locations->InAt(2)); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt8: + DCHECK_EQ(16u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ MaddvB(acc, left, right); } else { __ MsubvB(acc, left, right); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: - DCHECK_EQ(8u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { + case DataType::Type::kUint16: + case DataType::Type::kInt16: + DCHECK_EQ(8u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ MaddvH(acc, left, right); } else { __ MsubvH(acc, left, right); } break; - case Primitive::kPrimInt: - DCHECK_EQ(4u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { + case DataType::Type::kInt32: + DCHECK_EQ(4u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ MaddvW(acc, left, right); } else { __ MsubvW(acc, left, right); } break; - case Primitive::kPrimLong: - DCHECK_EQ(2u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { + case DataType::Type::kInt64: + DCHECK_EQ(2u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ MaddvD(acc, left, right); } else { __ MsubvD(acc, left, right); @@ -897,20 +895,29 @@ void InstructionCodeGeneratorMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumu } } +void LocationsBuilderMIPS::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); +} + +void InstructionCodeGeneratorMIPS::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + LOG(FATAL) << "No SIMD for " << instruction->GetId(); + // TODO: implement this, location helper already filled out (shared with MulAcc). +} + // Helper to set up locations for vector memory operations. static void CreateVecMemLocations(ArenaAllocator* arena, HVecMemoryOperation* instruction, bool is_load) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); if (is_load) { @@ -963,18 +970,18 @@ void LocationsBuilderMIPS::VisitVecLoad(HVecLoad* instruction) { void InstructionCodeGeneratorMIPS::VisitVecLoad(HVecLoad* instruction) { LocationSummary* locations = instruction->GetLocations(); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); VectorRegister reg = VectorRegisterFrom(locations->Out()); Register base; int32_t offset = VecAddress(locations, size, &base); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ LdB(reg, base, offset); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: // Loading 8-bytes (needed if dealing with compressed strings in StringCharAt) from unaligned // memory address may cause a trap to the kernel if the CPU doesn't directly support unaligned // loads and stores. @@ -983,13 +990,13 @@ void InstructionCodeGeneratorMIPS::VisitVecLoad(HVecLoad* instruction) { DCHECK_EQ(8u, instruction->GetVectorLength()); __ LdH(reg, base, offset); break; - case Primitive::kPrimInt: - case Primitive::kPrimFloat: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ LdW(reg, base, offset); break; - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ LdD(reg, base, offset); break; @@ -1005,28 +1012,28 @@ void LocationsBuilderMIPS::VisitVecStore(HVecStore* instruction) { void InstructionCodeGeneratorMIPS::VisitVecStore(HVecStore* instruction) { LocationSummary* locations = instruction->GetLocations(); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); VectorRegister reg = VectorRegisterFrom(locations->InAt(2)); Register base; int32_t offset = VecAddress(locations, size, &base); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ StB(reg, base, offset); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ StH(reg, base, offset); break; - case Primitive::kPrimInt: - case Primitive::kPrimFloat: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ StW(reg, base, offset); break; - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ StD(reg, base, offset); break; diff --git a/compiler/optimizing/code_generator_vector_mips64.cc b/compiler/optimizing/code_generator_vector_mips64.cc index 9d3a777c13..f60f708976 100644 --- a/compiler/optimizing/code_generator_vector_mips64.cc +++ b/compiler/optimizing/code_generator_vector_mips64.cc @@ -31,17 +31,17 @@ VectorRegister VectorRegisterFrom(Location location) { void LocationsBuilderMIPS64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); break; @@ -55,31 +55,31 @@ void InstructionCodeGeneratorMIPS64::VisitVecReplicateScalar(HVecReplicateScalar LocationSummary* locations = instruction->GetLocations(); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ FillB(dst, locations->InAt(0).AsRegister<GpuRegister>()); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ FillH(dst, locations->InAt(0).AsRegister<GpuRegister>()); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FillW(dst, locations->InAt(0).AsRegister<GpuRegister>()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FillD(dst, locations->InAt(0).AsRegister<GpuRegister>()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ ReplicateFPToVectorRegister(dst, locations->InAt(0).AsFpuRegister<FpuRegister>(), /* is_double */ false); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ ReplicateFPToVectorRegister(dst, locations->InAt(0).AsFpuRegister<FpuRegister>(), @@ -103,19 +103,19 @@ void InstructionCodeGeneratorMIPS64::VisitVecExtractScalar(HVecExtractScalar* in static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), instruction->IsVecNot() ? Location::kOutputOverlap : Location::kNoOutputOverlap); break; - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), (instruction->IsVecNeg() || instruction->IsVecAbs()) @@ -144,9 +144,9 @@ void InstructionCodeGeneratorMIPS64::VisitVecCnv(HVecCnv* instruction) { LocationSummary* locations = instruction->GetLocations(); VectorRegister src = VectorRegisterFrom(locations->InAt(0)); VectorRegister dst = VectorRegisterFrom(locations->Out()); - Primitive::Type from = instruction->GetInputType(); - Primitive::Type to = instruction->GetResultType(); - if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) { + DataType::Type from = instruction->GetInputType(); + DataType::Type to = instruction->GetResultType(); + if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) { DCHECK_EQ(4u, instruction->GetVectorLength()); __ Ffint_sW(dst, src); } else { @@ -164,33 +164,33 @@ void InstructionCodeGeneratorMIPS64::VisitVecNeg(HVecNeg* instruction) { VectorRegister src = VectorRegisterFrom(locations->InAt(0)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ FillB(dst, ZERO); __ SubvB(dst, dst, src); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ FillH(dst, ZERO); __ SubvH(dst, dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FillW(dst, ZERO); __ SubvW(dst, dst, src); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FillD(dst, ZERO); __ SubvD(dst, dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FillW(dst, ZERO); __ FsubW(dst, dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FillD(dst, ZERO); __ FsubD(dst, dst, src); @@ -210,34 +210,34 @@ void InstructionCodeGeneratorMIPS64::VisitVecAbs(HVecAbs* instruction) { VectorRegister src = VectorRegisterFrom(locations->InAt(0)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ FillB(dst, ZERO); // all zeroes __ Add_aB(dst, dst, src); // dst = abs(0) + abs(src) break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ FillH(dst, ZERO); // all zeroes __ Add_aH(dst, dst, src); // dst = abs(0) + abs(src) break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FillW(dst, ZERO); // all zeroes __ Add_aW(dst, dst, src); // dst = abs(0) + abs(src) break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FillD(dst, ZERO); // all zeroes __ Add_aD(dst, dst, src); // dst = abs(0) + abs(src) break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ LdiW(dst, -1); // all ones __ SrliW(dst, dst, 1); __ AndV(dst, dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ LdiD(dst, -1); // all ones __ SrliD(dst, dst, 1); @@ -258,18 +258,18 @@ void InstructionCodeGeneratorMIPS64::VisitVecNot(HVecNot* instruction) { VectorRegister src = VectorRegisterFrom(locations->InAt(0)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: // special case boolean-not + case DataType::Type::kBool: // special case boolean-not DCHECK_EQ(16u, instruction->GetVectorLength()); __ LdiB(dst, 1); __ XorV(dst, dst, src); break; - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ NorV(dst, src, src); // lanes do not matter @@ -284,14 +284,14 @@ void InstructionCodeGeneratorMIPS64::VisitVecNot(HVecNot* instruction) { static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -312,28 +312,28 @@ void InstructionCodeGeneratorMIPS64::VisitVecAdd(HVecAdd* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ AddvB(dst, lhs, rhs); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ AddvH(dst, lhs, rhs); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ AddvW(dst, lhs, rhs); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ AddvD(dst, lhs, rhs); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FaddW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FaddD(dst, lhs, rhs); break; @@ -353,7 +353,7 @@ void InstructionCodeGeneratorMIPS64::VisitVecHalvingAdd(HVecHalvingAdd* instruct VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { instruction->IsRounded() @@ -365,8 +365,8 @@ void InstructionCodeGeneratorMIPS64::VisitVecHalvingAdd(HVecHalvingAdd* instruct : __ Ave_sB(dst, lhs, rhs); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { instruction->IsRounded() @@ -394,28 +394,28 @@ void InstructionCodeGeneratorMIPS64::VisitVecSub(HVecSub* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ SubvB(dst, lhs, rhs); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ SubvH(dst, lhs, rhs); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ SubvW(dst, lhs, rhs); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ SubvD(dst, lhs, rhs); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FsubW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FsubD(dst, lhs, rhs); break; @@ -435,28 +435,28 @@ void InstructionCodeGeneratorMIPS64::VisitVecMul(HVecMul* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ MulvB(dst, lhs, rhs); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ MulvH(dst, lhs, rhs); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ MulvW(dst, lhs, rhs); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ MulvD(dst, lhs, rhs); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FmulW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FmulD(dst, lhs, rhs); break; @@ -476,11 +476,11 @@ void InstructionCodeGeneratorMIPS64::VisitVecDiv(HVecDiv* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ FdivW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ FdivD(dst, lhs, rhs); break; @@ -500,7 +500,7 @@ void InstructionCodeGeneratorMIPS64::VisitVecMin(HVecMin* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Min_uB(dst, lhs, rhs); @@ -508,8 +508,8 @@ void InstructionCodeGeneratorMIPS64::VisitVecMin(HVecMin* instruction) { __ Min_sB(dst, lhs, rhs); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Min_uH(dst, lhs, rhs); @@ -517,7 +517,7 @@ void InstructionCodeGeneratorMIPS64::VisitVecMin(HVecMin* instruction) { __ Min_sH(dst, lhs, rhs); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Min_uW(dst, lhs, rhs); @@ -525,7 +525,7 @@ void InstructionCodeGeneratorMIPS64::VisitVecMin(HVecMin* instruction) { __ Min_sW(dst, lhs, rhs); } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Min_uD(dst, lhs, rhs); @@ -535,12 +535,12 @@ void InstructionCodeGeneratorMIPS64::VisitVecMin(HVecMin* instruction) { break; // When one of arguments is NaN, fmin.df returns other argument, but Java expects a NaN value. // TODO: Fix min(x, NaN) cases for float and double. - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ FminW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ FminD(dst, lhs, rhs); @@ -561,7 +561,7 @@ void InstructionCodeGeneratorMIPS64::VisitVecMax(HVecMax* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Max_uB(dst, lhs, rhs); @@ -569,8 +569,8 @@ void InstructionCodeGeneratorMIPS64::VisitVecMax(HVecMax* instruction) { __ Max_sB(dst, lhs, rhs); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Max_uH(dst, lhs, rhs); @@ -578,7 +578,7 @@ void InstructionCodeGeneratorMIPS64::VisitVecMax(HVecMax* instruction) { __ Max_sH(dst, lhs, rhs); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Max_uW(dst, lhs, rhs); @@ -586,7 +586,7 @@ void InstructionCodeGeneratorMIPS64::VisitVecMax(HVecMax* instruction) { __ Max_sW(dst, lhs, rhs); } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ Max_uD(dst, lhs, rhs); @@ -596,12 +596,12 @@ void InstructionCodeGeneratorMIPS64::VisitVecMax(HVecMax* instruction) { break; // When one of arguments is NaN, fmax.df returns other argument, but Java expects a NaN value. // TODO: Fix max(x, NaN) cases for float and double. - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ FmaxW(dst, lhs, rhs); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ FmaxD(dst, lhs, rhs); @@ -622,14 +622,14 @@ void InstructionCodeGeneratorMIPS64::VisitVecAnd(HVecAnd* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ AndV(dst, lhs, rhs); // lanes do not matter @@ -658,14 +658,14 @@ void InstructionCodeGeneratorMIPS64::VisitVecOr(HVecOr* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ OrV(dst, lhs, rhs); // lanes do not matter @@ -686,14 +686,14 @@ void InstructionCodeGeneratorMIPS64::VisitVecXor(HVecXor* instruction) { VectorRegister rhs = VectorRegisterFrom(locations->InAt(1)); VectorRegister dst = VectorRegisterFrom(locations->Out()); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ XorV(dst, lhs, rhs); // lanes do not matter @@ -708,11 +708,11 @@ void InstructionCodeGeneratorMIPS64::VisitVecXor(HVecXor* instruction) { static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant())); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -733,20 +733,20 @@ void InstructionCodeGeneratorMIPS64::VisitVecShl(HVecShl* instruction) { VectorRegister dst = VectorRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ SlliB(dst, lhs, value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ SlliH(dst, lhs, value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ SlliW(dst, lhs, value); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ SlliD(dst, lhs, value); break; @@ -766,20 +766,20 @@ void InstructionCodeGeneratorMIPS64::VisitVecShr(HVecShr* instruction) { VectorRegister dst = VectorRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ SraiB(dst, lhs, value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ SraiH(dst, lhs, value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ SraiW(dst, lhs, value); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ SraiD(dst, lhs, value); break; @@ -799,20 +799,20 @@ void InstructionCodeGeneratorMIPS64::VisitVecUShr(HVecUShr* instruction) { VectorRegister dst = VectorRegisterFrom(locations->Out()); int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ SrliB(dst, lhs, value); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ SrliH(dst, lhs, value); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ SrliW(dst, lhs, value); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ SrliD(dst, lhs, value); break; @@ -830,21 +830,18 @@ void InstructionCodeGeneratorMIPS64::VisitVecSetScalars(HVecSetScalars* instruct LOG(FATAL) << "No SIMD for " << instruction->GetId(); } -void LocationsBuilderMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { - LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr); - switch (instr->GetPackedType()) { - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - locations->SetInAt( - HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister()); - locations->SetInAt( - HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister()); - locations->SetInAt( - HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister()); - DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0); +// Helper to set up locations for vector accumulations. +static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { + LocationSummary* locations = new (arena) LocationSummary(instruction); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetInAt(1, Location::RequiresFpuRegister()); + locations->SetInAt(2, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); break; default: @@ -853,43 +850,44 @@ void LocationsBuilderMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* } } -void InstructionCodeGeneratorMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { - LocationSummary* locations = instr->GetLocations(); - VectorRegister acc = - VectorRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex)); - VectorRegister left = - VectorRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex)); - VectorRegister right = - VectorRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex)); - switch (instr->GetPackedType()) { - case Primitive::kPrimByte: - DCHECK_EQ(16u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { +void LocationsBuilderMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); +} + +void InstructionCodeGeneratorMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + LocationSummary* locations = instruction->GetLocations(); + VectorRegister acc = VectorRegisterFrom(locations->InAt(0)); + VectorRegister left = VectorRegisterFrom(locations->InAt(1)); + VectorRegister right = VectorRegisterFrom(locations->InAt(2)); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt8: + DCHECK_EQ(16u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ MaddvB(acc, left, right); } else { __ MsubvB(acc, left, right); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: - DCHECK_EQ(8u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { + case DataType::Type::kUint16: + case DataType::Type::kInt16: + DCHECK_EQ(8u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ MaddvH(acc, left, right); } else { __ MsubvH(acc, left, right); } break; - case Primitive::kPrimInt: - DCHECK_EQ(4u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { + case DataType::Type::kInt32: + DCHECK_EQ(4u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ MaddvW(acc, left, right); } else { __ MsubvW(acc, left, right); } break; - case Primitive::kPrimLong: - DCHECK_EQ(2u, instr->GetVectorLength()); - if (instr->GetOpKind() == HInstruction::kAdd) { + case DataType::Type::kInt64: + DCHECK_EQ(2u, instruction->GetVectorLength()); + if (instruction->GetOpKind() == HInstruction::kAdd) { __ MaddvD(acc, left, right); } else { __ MsubvD(acc, left, right); @@ -901,20 +899,29 @@ void InstructionCodeGeneratorMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccu } } +void LocationsBuilderMIPS64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); +} + +void InstructionCodeGeneratorMIPS64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + LOG(FATAL) << "No SIMD for " << instruction->GetId(); + // TODO: implement this, location helper already filled out (shared with MulAcc). +} + // Helper to set up locations for vector memory operations. static void CreateVecMemLocations(ArenaAllocator* arena, HVecMemoryOperation* instruction, bool is_load) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); if (is_load) { @@ -967,18 +974,18 @@ void LocationsBuilderMIPS64::VisitVecLoad(HVecLoad* instruction) { void InstructionCodeGeneratorMIPS64::VisitVecLoad(HVecLoad* instruction) { LocationSummary* locations = instruction->GetLocations(); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); VectorRegister reg = VectorRegisterFrom(locations->Out()); GpuRegister base; int32_t offset = VecAddress(locations, size, &base); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ LdB(reg, base, offset); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: // Loading 8-bytes (needed if dealing with compressed strings in StringCharAt) from unaligned // memory address may cause a trap to the kernel if the CPU doesn't directly support unaligned // loads and stores. @@ -987,13 +994,13 @@ void InstructionCodeGeneratorMIPS64::VisitVecLoad(HVecLoad* instruction) { DCHECK_EQ(8u, instruction->GetVectorLength()); __ LdH(reg, base, offset); break; - case Primitive::kPrimInt: - case Primitive::kPrimFloat: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ LdW(reg, base, offset); break; - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ LdD(reg, base, offset); break; @@ -1009,28 +1016,28 @@ void LocationsBuilderMIPS64::VisitVecStore(HVecStore* instruction) { void InstructionCodeGeneratorMIPS64::VisitVecStore(HVecStore* instruction) { LocationSummary* locations = instruction->GetLocations(); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); VectorRegister reg = VectorRegisterFrom(locations->InAt(2)); GpuRegister base; int32_t offset = VecAddress(locations, size, &base); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ StB(reg, base, offset); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ StH(reg, base, offset); break; - case Primitive::kPrimInt: - case Primitive::kPrimFloat: + case DataType::Type::kInt32: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ StW(reg, base, offset); break; - case Primitive::kPrimLong: - case Primitive::kPrimDouble: + case DataType::Type::kInt64: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ StD(reg, base, offset); break; diff --git a/compiler/optimizing/code_generator_vector_x86.cc b/compiler/optimizing/code_generator_vector_x86.cc index 37190f8363..6515dbe7b7 100644 --- a/compiler/optimizing/code_generator_vector_x86.cc +++ b/compiler/optimizing/code_generator_vector_x86.cc @@ -30,28 +30,27 @@ void LocationsBuilderX86::VisitVecReplicateScalar(HVecReplicateScalar* instructi HInstruction* input = instruction->InputAt(0); bool is_zero = IsZeroBitPattern(input); switch (instruction->GetPackedType()) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Long needs extra temporary to load from the register pair. if (!is_zero) { locations->AddTemp(Location::RequiresFpuRegister()); } FALLTHROUGH_INTENDED; - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant()) : Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant()) : Location::RequiresFpuRegister()); locations->SetOut(is_zero ? Location::RequiresFpuRegister() : Location::SameAsFirstInput()); - break; default: LOG(FATAL) << "Unsupported SIMD type"; @@ -70,27 +69,27 @@ void InstructionCodeGeneratorX86::VisitVecReplicateScalar(HVecReplicateScalar* i } switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegister<Register>()); __ punpcklbw(dst, dst); __ punpcklwd(dst, dst); __ pshufd(dst, dst, Immediate(0)); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegister<Register>()); __ punpcklwd(dst, dst); __ pshufd(dst, dst, Immediate(0)); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegister<Register>()); __ pshufd(dst, dst, Immediate(0)); break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); DCHECK_EQ(2u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>()); @@ -99,12 +98,12 @@ void InstructionCodeGeneratorX86::VisitVecReplicateScalar(HVecReplicateScalar* i __ punpcklqdq(dst, dst); break; } - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK(locations->InAt(0).Equals(locations->Out())); DCHECK_EQ(4u, instruction->GetVectorLength()); __ shufps(dst, dst, Immediate(0)); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK(locations->InAt(0).Equals(locations->Out())); DCHECK_EQ(2u, instruction->GetVectorLength()); __ shufpd(dst, dst, Immediate(0)); @@ -118,20 +117,20 @@ void InstructionCodeGeneratorX86::VisitVecReplicateScalar(HVecReplicateScalar* i void LocationsBuilderX86::VisitVecExtractScalar(HVecExtractScalar* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Long needs extra temporary to store into the register pair. locations->AddTemp(Location::RequiresFpuRegister()); FALLTHROUGH_INTENDED; - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); break; @@ -145,18 +144,18 @@ void InstructionCodeGeneratorX86::VisitVecExtractScalar(HVecExtractScalar* instr LocationSummary* locations = instruction->GetLocations(); XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: // TODO: up to here, and? + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: // TODO: up to here, and? LOG(FATAL) << "Unsupported SIMD type"; UNREACHABLE(); - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_LE(4u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ movd(locations->Out().AsRegister<Register>(), src); break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); DCHECK_EQ(2u, instruction->GetVectorLength()); __ movd(locations->Out().AsRegisterPairLow<Register>(), src); @@ -164,8 +163,8 @@ void InstructionCodeGeneratorX86::VisitVecExtractScalar(HVecExtractScalar* instr __ movd(locations->Out().AsRegisterPairHigh<Register>(), tmp); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 4u); DCHECK(locations->InAt(0).Equals(locations->Out())); // no code required @@ -180,14 +179,14 @@ void InstructionCodeGeneratorX86::VisitVecExtractScalar(HVecExtractScalar* instr static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; @@ -200,7 +199,7 @@ static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* in void LocationsBuilderX86::VisitVecReduce(HVecReduce* instruction) { CreateVecUnOpLocations(GetGraph()->GetArena(), instruction); // Long reduction or min/max require a temporary. - if (instruction->GetPackedType() == Primitive::kPrimLong || + if (instruction->GetPackedType() == DataType::Type::kInt64 || instruction->GetKind() == HVecReduce::kMin || instruction->GetKind() == HVecReduce::kMax) { instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister()); @@ -212,7 +211,7 @@ void InstructionCodeGeneratorX86::VisitVecReduce(HVecReduce* instruction) { XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); switch (instruction->GetKind()) { case HVecReduce::kSum: @@ -242,7 +241,7 @@ void InstructionCodeGeneratorX86::VisitVecReduce(HVecReduce* instruction) { } } break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { DCHECK_EQ(2u, instruction->GetVectorLength()); XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); switch (instruction->GetKind()) { @@ -272,9 +271,9 @@ void InstructionCodeGeneratorX86::VisitVecCnv(HVecCnv* instruction) { LocationSummary* locations = instruction->GetLocations(); XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); - Primitive::Type from = instruction->GetInputType(); - Primitive::Type to = instruction->GetResultType(); - if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) { + DataType::Type from = instruction->GetInputType(); + DataType::Type to = instruction->GetResultType(); + if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) { DCHECK_EQ(4u, instruction->GetVectorLength()); __ cvtdq2ps(dst, src); } else { @@ -291,33 +290,33 @@ void InstructionCodeGeneratorX86::VisitVecNeg(HVecNeg* instruction) { XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ pxor(dst, dst); __ psubb(dst, src); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ pxor(dst, dst); __ psubw(dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ pxor(dst, dst); __ psubd(dst, src); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ pxor(dst, dst); __ psubq(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ xorps(dst, dst); __ subps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ xorpd(dst, dst); __ subpd(dst, src); @@ -331,7 +330,7 @@ void InstructionCodeGeneratorX86::VisitVecNeg(HVecNeg* instruction) { void LocationsBuilderX86::VisitVecAbs(HVecAbs* instruction) { CreateVecUnOpLocations(GetGraph()->GetArena(), instruction); // Integral-abs requires a temporary for the comparison. - if (instruction->GetPackedType() == Primitive::kPrimInt) { + if (instruction->GetPackedType() == DataType::Type::kInt32) { instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister()); } } @@ -341,7 +340,7 @@ void InstructionCodeGeneratorX86::VisitVecAbs(HVecAbs* instruction) { XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { DCHECK_EQ(4u, instruction->GetVectorLength()); XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); __ movaps(dst, src); @@ -351,13 +350,13 @@ void InstructionCodeGeneratorX86::VisitVecAbs(HVecAbs* instruction) { __ psubd(dst, tmp); break; } - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ pcmpeqb(dst, dst); // all ones __ psrld(dst, Immediate(1)); __ andps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ pcmpeqb(dst, dst); // all ones __ psrlq(dst, Immediate(1)); @@ -372,7 +371,7 @@ void InstructionCodeGeneratorX86::VisitVecAbs(HVecAbs* instruction) { void LocationsBuilderX86::VisitVecNot(HVecNot* instruction) { CreateVecUnOpLocations(GetGraph()->GetArena(), instruction); // Boolean-not requires a temporary to construct the 16 x one. - if (instruction->GetPackedType() == Primitive::kPrimBoolean) { + if (instruction->GetPackedType() == DataType::Type::kBool) { instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister()); } } @@ -382,7 +381,7 @@ void InstructionCodeGeneratorX86::VisitVecNot(HVecNot* instruction) { XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: { // special case boolean-not + case DataType::Type::kBool: { // special case boolean-not DCHECK_EQ(16u, instruction->GetVectorLength()); XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); __ pxor(dst, dst); @@ -391,22 +390,22 @@ void InstructionCodeGeneratorX86::VisitVecNot(HVecNot* instruction) { __ pxor(dst, src); break; } - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ pcmpeqb(dst, dst); // all ones __ pxor(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ pcmpeqb(dst, dst); // all ones __ xorps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ pcmpeqb(dst, dst); // all ones __ xorpd(dst, src); @@ -421,14 +420,14 @@ void InstructionCodeGeneratorX86::VisitVecNot(HVecNot* instruction) { static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); @@ -449,28 +448,28 @@ void InstructionCodeGeneratorX86::VisitVecAdd(HVecAdd* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ paddb(dst, src); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ paddw(dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ paddd(dst, src); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ paddq(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ addps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ addpd(dst, src); break; @@ -494,12 +493,12 @@ void InstructionCodeGeneratorX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction DCHECK(instruction->IsUnsigned()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ pavgb(dst, src); return; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ pavgw(dst, src); return; @@ -519,28 +518,28 @@ void InstructionCodeGeneratorX86::VisitVecSub(HVecSub* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ psubb(dst, src); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ psubw(dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ psubd(dst, src); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ psubq(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ subps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ subpd(dst, src); break; @@ -560,20 +559,20 @@ void InstructionCodeGeneratorX86::VisitVecMul(HVecMul* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ pmullw(dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ pmulld(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ mulps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ mulpd(dst, src); break; @@ -593,11 +592,11 @@ void InstructionCodeGeneratorX86::VisitVecDiv(HVecDiv* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ divps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ divpd(dst, src); break; @@ -617,7 +616,7 @@ void InstructionCodeGeneratorX86::VisitVecMin(HVecMin* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pminub(dst, src); @@ -625,8 +624,8 @@ void InstructionCodeGeneratorX86::VisitVecMin(HVecMin* instruction) { __ pminsb(dst, src); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pminuw(dst, src); @@ -634,7 +633,7 @@ void InstructionCodeGeneratorX86::VisitVecMin(HVecMin* instruction) { __ pminsw(dst, src); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pminud(dst, src); @@ -643,12 +642,12 @@ void InstructionCodeGeneratorX86::VisitVecMin(HVecMin* instruction) { } break; // Next cases are sloppy wrt 0.0 vs -0.0. - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ minps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ minpd(dst, src); @@ -669,7 +668,7 @@ void InstructionCodeGeneratorX86::VisitVecMax(HVecMax* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pmaxub(dst, src); @@ -677,8 +676,8 @@ void InstructionCodeGeneratorX86::VisitVecMax(HVecMax* instruction) { __ pmaxsb(dst, src); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pmaxuw(dst, src); @@ -686,7 +685,7 @@ void InstructionCodeGeneratorX86::VisitVecMax(HVecMax* instruction) { __ pmaxsw(dst, src); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pmaxud(dst, src); @@ -695,12 +694,12 @@ void InstructionCodeGeneratorX86::VisitVecMax(HVecMax* instruction) { } break; // Next cases are sloppy wrt 0.0 vs -0.0. - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ maxps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ maxpd(dst, src); @@ -721,21 +720,21 @@ void InstructionCodeGeneratorX86::VisitVecAnd(HVecAnd* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ pand(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ andps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ andpd(dst, src); break; @@ -755,21 +754,21 @@ void InstructionCodeGeneratorX86::VisitVecAndNot(HVecAndNot* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ pandn(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ andnps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ andnpd(dst, src); break; @@ -789,21 +788,21 @@ void InstructionCodeGeneratorX86::VisitVecOr(HVecOr* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ por(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ orps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ orpd(dst, src); break; @@ -823,21 +822,21 @@ void InstructionCodeGeneratorX86::VisitVecXor(HVecXor* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ pxor(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ xorps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ xorpd(dst, src); break; @@ -851,10 +850,10 @@ void InstructionCodeGeneratorX86::VisitVecXor(HVecXor* instruction) { static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant())); locations->SetOut(Location::SameAsFirstInput()); @@ -875,16 +874,16 @@ void InstructionCodeGeneratorX86::VisitVecShl(HVecShl* instruction) { int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ psllw(dst, Immediate(static_cast<uint8_t>(value))); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ pslld(dst, Immediate(static_cast<uint8_t>(value))); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ psllq(dst, Immediate(static_cast<uint8_t>(value))); break; @@ -904,12 +903,12 @@ void InstructionCodeGeneratorX86::VisitVecShr(HVecShr* instruction) { int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ psraw(dst, Immediate(static_cast<uint8_t>(value))); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ psrad(dst, Immediate(static_cast<uint8_t>(value))); break; @@ -929,16 +928,16 @@ void InstructionCodeGeneratorX86::VisitVecUShr(HVecUShr* instruction) { int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ psrlw(dst, Immediate(static_cast<uint8_t>(value))); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ psrld(dst, Immediate(static_cast<uint8_t>(value))); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ psrlq(dst, Immediate(static_cast<uint8_t>(value))); break; @@ -957,23 +956,23 @@ void LocationsBuilderX86::VisitVecSetScalars(HVecSetScalars* instruction) { bool is_zero = IsZeroBitPattern(input); switch (instruction->GetPackedType()) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Long needs extra temporary to load from register pairs. if (!is_zero) { locations->AddTemp(Location::RequiresFpuRegister()); } FALLTHROUGH_INTENDED; - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant()) : Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant()) : Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister()); @@ -1000,17 +999,17 @@ void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction // Set required elements. switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: // TODO: up to here, and? + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: // TODO: up to here, and? LOG(FATAL) << "Unsupported SIMD type"; UNREACHABLE(); - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegister<Register>()); break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); DCHECK_EQ(2u, instruction->GetVectorLength()); __ xorps(tmp, tmp); @@ -1019,11 +1018,11 @@ void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction __ punpckldq(dst, tmp); break; } - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ movss(dst, locations->InAt(1).AsFpuRegister<XmmRegister>()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ movsd(dst, locations->InAt(1).AsFpuRegister<XmmRegister>()); break; @@ -1033,12 +1032,42 @@ void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction } } -void LocationsBuilderX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { - LOG(FATAL) << "No SIMD for " << instr->GetId(); +// Helper to set up locations for vector accumulations. +static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { + LocationSummary* locations = new (arena) LocationSummary(instruction); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetInAt(1, Location::RequiresFpuRegister()); + locations->SetInAt(2, Location::RequiresFpuRegister()); + locations->SetOut(Location::SameAsFirstInput()); + break; + default: + LOG(FATAL) << "Unsupported SIMD type"; + UNREACHABLE(); + } +} + +void LocationsBuilderX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); +} + +void InstructionCodeGeneratorX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + // TODO: pmaddwd? + LOG(FATAL) << "No SIMD for " << instruction->GetId(); +} + +void LocationsBuilderX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); } -void InstructionCodeGeneratorX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { - LOG(FATAL) << "No SIMD for " << instr->GetId(); +void InstructionCodeGeneratorX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + // TODO: psadbw for unsigned? + LOG(FATAL) << "No SIMD for " << instruction->GetId(); } // Helper to set up locations for vector memory operations. @@ -1047,14 +1076,14 @@ static void CreateVecMemLocations(ArenaAllocator* arena, bool is_load) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); if (is_load) { @@ -1097,12 +1126,12 @@ void LocationsBuilderX86::VisitVecLoad(HVecLoad* instruction) { void InstructionCodeGeneratorX86::VisitVecLoad(HVecLoad* instruction) { LocationSummary* locations = instruction->GetLocations(); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); Address address = VecAddress(locations, size, instruction->IsStringCharAt()); XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>(); bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: + case DataType::Type::kUint16: DCHECK_EQ(8u, instruction->GetVectorLength()); // Special handling of compressed/uncompressed string load. if (mirror::kUseStringCompression && instruction->IsStringCharAt()) { @@ -1126,20 +1155,20 @@ void InstructionCodeGeneratorX86::VisitVecLoad(HVecLoad* instruction) { return; } FALLTHROUGH_INTENDED; - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); is_aligned16 ? __ movaps(reg, address) : __ movups(reg, address); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); is_aligned16 ? __ movapd(reg, address) : __ movupd(reg, address); break; @@ -1155,26 +1184,26 @@ void LocationsBuilderX86::VisitVecStore(HVecStore* instruction) { void InstructionCodeGeneratorX86::VisitVecStore(HVecStore* instruction) { LocationSummary* locations = instruction->GetLocations(); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); Address address = VecAddress(locations, size, /*is_string_char_at*/ false); XmmRegister reg = locations->InAt(2).AsFpuRegister<XmmRegister>(); bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); is_aligned16 ? __ movdqa(address, reg) : __ movdqu(address, reg); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); is_aligned16 ? __ movaps(address, reg) : __ movups(address, reg); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); is_aligned16 ? __ movapd(address, reg) : __ movupd(address, reg); break; diff --git a/compiler/optimizing/code_generator_vector_x86_64.cc b/compiler/optimizing/code_generator_vector_x86_64.cc index edd0209f10..4241042574 100644 --- a/compiler/optimizing/code_generator_vector_x86_64.cc +++ b/compiler/optimizing/code_generator_vector_x86_64.cc @@ -30,18 +30,18 @@ void LocationsBuilderX86_64::VisitVecReplicateScalar(HVecReplicateScalar* instru HInstruction* input = instruction->InputAt(0); bool is_zero = IsZeroBitPattern(input); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant()) : Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant()) : Location::RequiresFpuRegister()); locations->SetOut(is_zero ? Location::RequiresFpuRegister() @@ -64,37 +64,37 @@ void InstructionCodeGeneratorX86_64::VisitVecReplicateScalar(HVecReplicateScalar } switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>(), /*64-bit*/ false); __ punpcklbw(dst, dst); __ punpcklwd(dst, dst); __ pshufd(dst, dst, Immediate(0)); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>(), /*64-bit*/ false); __ punpcklwd(dst, dst); __ pshufd(dst, dst, Immediate(0)); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>(), /*64-bit*/ false); __ pshufd(dst, dst, Immediate(0)); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>(), /*64-bit*/ true); __ punpcklqdq(dst, dst); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(locations->InAt(0).Equals(locations->Out())); __ shufps(dst, dst, Immediate(0)); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(locations->InAt(0).Equals(locations->Out())); __ shufpd(dst, dst, Immediate(0)); @@ -108,17 +108,17 @@ void InstructionCodeGeneratorX86_64::VisitVecReplicateScalar(HVecReplicateScalar void LocationsBuilderX86_64::VisitVecExtractScalar(HVecExtractScalar* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); break; @@ -132,22 +132,22 @@ void InstructionCodeGeneratorX86_64::VisitVecExtractScalar(HVecExtractScalar* in LocationSummary* locations = instruction->GetLocations(); XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: // TODO: up to here, and? + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: // TODO: up to here, and? LOG(FATAL) << "Unsupported SIMD type"; UNREACHABLE(); - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ movd(locations->Out().AsRegister<CpuRegister>(), src, /*64-bit*/ false); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ movd(locations->Out().AsRegister<CpuRegister>(), src, /*64-bit*/ true); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 4u); DCHECK(locations->InAt(0).Equals(locations->Out())); // no code required @@ -162,14 +162,14 @@ void InstructionCodeGeneratorX86_64::VisitVecExtractScalar(HVecExtractScalar* in static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; @@ -182,7 +182,7 @@ static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* in void LocationsBuilderX86_64::VisitVecReduce(HVecReduce* instruction) { CreateVecUnOpLocations(GetGraph()->GetArena(), instruction); // Long reduction or min/max require a temporary. - if (instruction->GetPackedType() == Primitive::kPrimLong || + if (instruction->GetPackedType() == DataType::Type::kInt64 || instruction->GetKind() == HVecReduce::kMin || instruction->GetKind() == HVecReduce::kMax) { instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister()); @@ -194,7 +194,7 @@ void InstructionCodeGeneratorX86_64::VisitVecReduce(HVecReduce* instruction) { XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); switch (instruction->GetKind()) { case HVecReduce::kSum: @@ -224,7 +224,7 @@ void InstructionCodeGeneratorX86_64::VisitVecReduce(HVecReduce* instruction) { } } break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { DCHECK_EQ(2u, instruction->GetVectorLength()); XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); switch (instruction->GetKind()) { @@ -254,9 +254,9 @@ void InstructionCodeGeneratorX86_64::VisitVecCnv(HVecCnv* instruction) { LocationSummary* locations = instruction->GetLocations(); XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); - Primitive::Type from = instruction->GetInputType(); - Primitive::Type to = instruction->GetResultType(); - if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) { + DataType::Type from = instruction->GetInputType(); + DataType::Type to = instruction->GetResultType(); + if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) { DCHECK_EQ(4u, instruction->GetVectorLength()); __ cvtdq2ps(dst, src); } else { @@ -273,33 +273,33 @@ void InstructionCodeGeneratorX86_64::VisitVecNeg(HVecNeg* instruction) { XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ pxor(dst, dst); __ psubb(dst, src); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ pxor(dst, dst); __ psubw(dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ pxor(dst, dst); __ psubd(dst, src); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ pxor(dst, dst); __ psubq(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ xorps(dst, dst); __ subps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ xorpd(dst, dst); __ subpd(dst, src); @@ -313,7 +313,7 @@ void InstructionCodeGeneratorX86_64::VisitVecNeg(HVecNeg* instruction) { void LocationsBuilderX86_64::VisitVecAbs(HVecAbs* instruction) { CreateVecUnOpLocations(GetGraph()->GetArena(), instruction); // Integral-abs requires a temporary for the comparison. - if (instruction->GetPackedType() == Primitive::kPrimInt) { + if (instruction->GetPackedType() == DataType::Type::kInt32) { instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister()); } } @@ -323,7 +323,7 @@ void InstructionCodeGeneratorX86_64::VisitVecAbs(HVecAbs* instruction) { XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { DCHECK_EQ(4u, instruction->GetVectorLength()); XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); __ movaps(dst, src); @@ -333,13 +333,13 @@ void InstructionCodeGeneratorX86_64::VisitVecAbs(HVecAbs* instruction) { __ psubd(dst, tmp); break; } - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ pcmpeqb(dst, dst); // all ones __ psrld(dst, Immediate(1)); __ andps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ pcmpeqb(dst, dst); // all ones __ psrlq(dst, Immediate(1)); @@ -354,7 +354,7 @@ void InstructionCodeGeneratorX86_64::VisitVecAbs(HVecAbs* instruction) { void LocationsBuilderX86_64::VisitVecNot(HVecNot* instruction) { CreateVecUnOpLocations(GetGraph()->GetArena(), instruction); // Boolean-not requires a temporary to construct the 16 x one. - if (instruction->GetPackedType() == Primitive::kPrimBoolean) { + if (instruction->GetPackedType() == DataType::Type::kBool) { instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister()); } } @@ -364,7 +364,7 @@ void InstructionCodeGeneratorX86_64::VisitVecNot(HVecNot* instruction) { XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: { // special case boolean-not + case DataType::Type::kBool: { // special case boolean-not DCHECK_EQ(16u, instruction->GetVectorLength()); XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); __ pxor(dst, dst); @@ -373,22 +373,22 @@ void InstructionCodeGeneratorX86_64::VisitVecNot(HVecNot* instruction) { __ pxor(dst, src); break; } - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ pcmpeqb(dst, dst); // all ones __ pxor(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ pcmpeqb(dst, dst); // all ones __ xorps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ pcmpeqb(dst, dst); // all ones __ xorpd(dst, src); @@ -403,14 +403,14 @@ void InstructionCodeGeneratorX86_64::VisitVecNot(HVecNot* instruction) { static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); @@ -431,28 +431,28 @@ void InstructionCodeGeneratorX86_64::VisitVecAdd(HVecAdd* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ paddb(dst, src); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ paddw(dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ paddd(dst, src); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ paddq(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ addps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ addpd(dst, src); break; @@ -476,12 +476,12 @@ void InstructionCodeGeneratorX86_64::VisitVecHalvingAdd(HVecHalvingAdd* instruct DCHECK(instruction->IsUnsigned()); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ pavgb(dst, src); return; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ pavgw(dst, src); return; @@ -501,28 +501,28 @@ void InstructionCodeGeneratorX86_64::VisitVecSub(HVecSub* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); __ psubb(dst, src); break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ psubw(dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ psubd(dst, src); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ psubq(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ subps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ subpd(dst, src); break; @@ -542,20 +542,20 @@ void InstructionCodeGeneratorX86_64::VisitVecMul(HVecMul* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ pmullw(dst, src); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ pmulld(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ mulps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ mulpd(dst, src); break; @@ -575,11 +575,11 @@ void InstructionCodeGeneratorX86_64::VisitVecDiv(HVecDiv* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ divps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ divpd(dst, src); break; @@ -599,7 +599,7 @@ void InstructionCodeGeneratorX86_64::VisitVecMin(HVecMin* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pminub(dst, src); @@ -607,8 +607,8 @@ void InstructionCodeGeneratorX86_64::VisitVecMin(HVecMin* instruction) { __ pminsb(dst, src); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pminuw(dst, src); @@ -616,7 +616,7 @@ void InstructionCodeGeneratorX86_64::VisitVecMin(HVecMin* instruction) { __ pminsw(dst, src); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pminud(dst, src); @@ -625,12 +625,12 @@ void InstructionCodeGeneratorX86_64::VisitVecMin(HVecMin* instruction) { } break; // Next cases are sloppy wrt 0.0 vs -0.0. - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ minps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ minpd(dst, src); @@ -651,7 +651,7 @@ void InstructionCodeGeneratorX86_64::VisitVecMax(HVecMax* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: DCHECK_EQ(16u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pmaxub(dst, src); @@ -659,8 +659,8 @@ void InstructionCodeGeneratorX86_64::VisitVecMax(HVecMax* instruction) { __ pmaxsb(dst, src); } break; - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pmaxuw(dst, src); @@ -668,7 +668,7 @@ void InstructionCodeGeneratorX86_64::VisitVecMax(HVecMax* instruction) { __ pmaxsw(dst, src); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); if (instruction->IsUnsigned()) { __ pmaxud(dst, src); @@ -677,12 +677,12 @@ void InstructionCodeGeneratorX86_64::VisitVecMax(HVecMax* instruction) { } break; // Next cases are sloppy wrt 0.0 vs -0.0. - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ maxps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); DCHECK(!instruction->IsUnsigned()); __ maxpd(dst, src); @@ -703,21 +703,21 @@ void InstructionCodeGeneratorX86_64::VisitVecAnd(HVecAnd* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ pand(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ andps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ andpd(dst, src); break; @@ -737,21 +737,21 @@ void InstructionCodeGeneratorX86_64::VisitVecAndNot(HVecAndNot* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ pandn(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ andnps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ andnpd(dst, src); break; @@ -771,21 +771,21 @@ void InstructionCodeGeneratorX86_64::VisitVecOr(HVecOr* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ por(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ orps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ orpd(dst, src); break; @@ -805,21 +805,21 @@ void InstructionCodeGeneratorX86_64::VisitVecXor(HVecXor* instruction) { XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); __ pxor(dst, src); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ xorps(dst, src); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ xorpd(dst, src); break; @@ -833,10 +833,10 @@ void InstructionCodeGeneratorX86_64::VisitVecXor(HVecXor* instruction) { static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant())); locations->SetOut(Location::SameAsFirstInput()); @@ -857,16 +857,16 @@ void InstructionCodeGeneratorX86_64::VisitVecShl(HVecShl* instruction) { int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ psllw(dst, Immediate(static_cast<int8_t>(value))); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ pslld(dst, Immediate(static_cast<int8_t>(value))); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ psllq(dst, Immediate(static_cast<int8_t>(value))); break; @@ -886,12 +886,12 @@ void InstructionCodeGeneratorX86_64::VisitVecShr(HVecShr* instruction) { int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ psraw(dst, Immediate(static_cast<int8_t>(value))); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ psrad(dst, Immediate(static_cast<int8_t>(value))); break; @@ -911,16 +911,16 @@ void InstructionCodeGeneratorX86_64::VisitVecUShr(HVecUShr* instruction) { int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>(); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: DCHECK_EQ(8u, instruction->GetVectorLength()); __ psrlw(dst, Immediate(static_cast<int8_t>(value))); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ psrld(dst, Immediate(static_cast<int8_t>(value))); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ psrlq(dst, Immediate(static_cast<int8_t>(value))); break; @@ -939,18 +939,18 @@ void LocationsBuilderX86_64::VisitVecSetScalars(HVecSetScalars* instruction) { bool is_zero = IsZeroBitPattern(input); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant()) : Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant()) : Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister()); @@ -977,25 +977,25 @@ void InstructionCodeGeneratorX86_64::VisitVecSetScalars(HVecSetScalars* instruct // Set required elements. switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: // TODO: up to here, and? + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: // TODO: up to here, and? LOG(FATAL) << "Unsupported SIMD type"; UNREACHABLE(); - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>()); // is 64-bit break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); __ movss(dst, locations->InAt(0).AsFpuRegister<XmmRegister>()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); __ movsd(dst, locations->InAt(0).AsFpuRegister<XmmRegister>()); break; @@ -1005,11 +1005,41 @@ void InstructionCodeGeneratorX86_64::VisitVecSetScalars(HVecSetScalars* instruct } } +// Helper to set up locations for vector accumulations. +static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) { + LocationSummary* locations = new (arena) LocationSummary(instruction); + switch (instruction->GetPackedType()) { + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetInAt(1, Location::RequiresFpuRegister()); + locations->SetInAt(2, Location::RequiresFpuRegister()); + locations->SetOut(Location::SameAsFirstInput()); + break; + default: + LOG(FATAL) << "Unsupported SIMD type"; + UNREACHABLE(); + } +} + void LocationsBuilderX86_64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { - LOG(FATAL) << "No SIMD for " << instruction->GetId(); + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); } void InstructionCodeGeneratorX86_64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) { + // TODO: pmaddwd? + LOG(FATAL) << "No SIMD for " << instruction->GetId(); +} + +void LocationsBuilderX86_64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + CreateVecAccumLocations(GetGraph()->GetArena(), instruction); +} + +void InstructionCodeGeneratorX86_64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) { + // TODO: psadbw for unsigned? LOG(FATAL) << "No SIMD for " << instruction->GetId(); } @@ -1019,14 +1049,14 @@ static void CreateVecMemLocations(ArenaAllocator* arena, bool is_load) { LocationSummary* locations = new (arena) LocationSummary(instruction); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); if (is_load) { @@ -1069,12 +1099,12 @@ void LocationsBuilderX86_64::VisitVecLoad(HVecLoad* instruction) { void InstructionCodeGeneratorX86_64::VisitVecLoad(HVecLoad* instruction) { LocationSummary* locations = instruction->GetLocations(); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); Address address = VecAddress(locations, size, instruction->IsStringCharAt()); XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>(); bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16); switch (instruction->GetPackedType()) { - case Primitive::kPrimChar: + case DataType::Type::kUint16: DCHECK_EQ(8u, instruction->GetVectorLength()); // Special handling of compressed/uncompressed string load. if (mirror::kUseStringCompression && instruction->IsStringCharAt()) { @@ -1098,20 +1128,20 @@ void InstructionCodeGeneratorX86_64::VisitVecLoad(HVecLoad* instruction) { return; } FALLTHROUGH_INTENDED; - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); is_aligned16 ? __ movaps(reg, address) : __ movups(reg, address); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); is_aligned16 ? __ movapd(reg, address) : __ movupd(reg, address); break; @@ -1127,26 +1157,26 @@ void LocationsBuilderX86_64::VisitVecStore(HVecStore* instruction) { void InstructionCodeGeneratorX86_64::VisitVecStore(HVecStore* instruction) { LocationSummary* locations = instruction->GetLocations(); - size_t size = Primitive::ComponentSize(instruction->GetPackedType()); + size_t size = DataType::Size(instruction->GetPackedType()); Address address = VecAddress(locations, size, /*is_string_char_at*/ false); XmmRegister reg = locations->InAt(2).AsFpuRegister<XmmRegister>(); bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16); switch (instruction->GetPackedType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); DCHECK_LE(instruction->GetVectorLength(), 16u); is_aligned16 ? __ movdqa(address, reg) : __ movdqu(address, reg); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: DCHECK_EQ(4u, instruction->GetVectorLength()); is_aligned16 ? __ movaps(address, reg) : __ movups(address, reg); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: DCHECK_EQ(2u, instruction->GetVectorLength()); is_aligned16 ? __ movapd(address, reg) : __ movupd(address, reg); break; diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 0b9130fa5a..70e270e74d 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -26,6 +26,7 @@ #include "heap_poisoning.h" #include "intrinsics.h" #include "intrinsics_x86.h" +#include "linker/linker_patch.h" #include "lock_word.h" #include "mirror/array-inl.h" #include "mirror/class-inl.h" @@ -160,10 +161,10 @@ class BoundsCheckSlowPathX86 : public SlowPathCode { x86_codegen->EmitParallelMoves( locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimInt, + DataType::Type::kInt32, length_loc, Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt); + DataType::Type::kInt32); QuickEntrypointEnum entrypoint = instruction_->AsBoundsCheck()->IsStringCharAt() ? kQuickThrowStringBounds : kQuickThrowArrayBounds; @@ -341,10 +342,10 @@ class TypeCheckSlowPathX86 : public SlowPathCode { InvokeRuntimeCallingConvention calling_convention; x86_codegen->EmitParallelMoves(locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, locations->InAt(1), Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot); + DataType::Type::kReference); if (instruction_->IsInstanceOf()) { x86_codegen->InvokeRuntime(kQuickInstanceofNonTrivial, instruction_, @@ -417,17 +418,17 @@ class ArraySetSlowPathX86 : public SlowPathCode { parallel_move.AddMove( locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove( locations->InAt(1), Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); parallel_move.AddMove( locations->InAt(2), Location::RegisterLocation(calling_convention.GetRegisterAt(2)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); @@ -813,16 +814,16 @@ class ReadBarrierForHeapReferenceSlowPathX86 : public SlowPathCode { HParallelMove parallel_move(codegen->GetGraph()->GetArena()); parallel_move.AddMove(ref_, Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove(obj_, Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); if (index.IsValid()) { parallel_move.AddMove(index, Location::RegisterLocation(calling_convention.GetRegisterAt(2)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); } else { @@ -1128,24 +1129,24 @@ void CodeGeneratorX86::Bind(HBasicBlock* block) { __ Bind(GetLabelOf(block)); } -Location InvokeDexCallingConventionVisitorX86::GetReturnLocation(Primitive::Type type) const { +Location InvokeDexCallingConventionVisitorX86::GetReturnLocation(DataType::Type type) const { switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: return Location::RegisterLocation(EAX); - case Primitive::kPrimLong: + case DataType::Type::kInt64: return Location::RegisterPairLocation(EAX, EDX); - case Primitive::kPrimVoid: + case DataType::Type::kVoid: return Location::NoLocation(); - case Primitive::kPrimDouble: - case Primitive::kPrimFloat: + case DataType::Type::kFloat64: + case DataType::Type::kFloat32: return Location::FpuRegisterLocation(XMM0); } @@ -1156,14 +1157,14 @@ Location InvokeDexCallingConventionVisitorX86::GetMethodLocation() const { return Location::RegisterLocation(kMethodRegisterArgument); } -Location InvokeDexCallingConventionVisitorX86::GetNextLocation(Primitive::Type type) { +Location InvokeDexCallingConventionVisitorX86::GetNextLocation(DataType::Type type) { switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: { uint32_t index = gp_index_++; stack_index_++; if (index < calling_convention.GetNumberOfRegisters()) { @@ -1173,7 +1174,7 @@ Location InvokeDexCallingConventionVisitorX86::GetNextLocation(Primitive::Type t } } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { uint32_t index = gp_index_; gp_index_ += 2; stack_index_ += 2; @@ -1186,7 +1187,7 @@ Location InvokeDexCallingConventionVisitorX86::GetNextLocation(Primitive::Type t } } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { uint32_t index = float_index_++; stack_index_++; if (index < calling_convention.GetNumberOfFpuRegisters()) { @@ -1196,7 +1197,7 @@ Location InvokeDexCallingConventionVisitorX86::GetNextLocation(Primitive::Type t } } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { uint32_t index = float_index_++; stack_index_ += 2; if (index < calling_convention.GetNumberOfFpuRegisters()) { @@ -1206,7 +1207,7 @@ Location InvokeDexCallingConventionVisitorX86::GetNextLocation(Primitive::Type t } } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unexpected parameter type " << type; break; } @@ -1262,10 +1263,10 @@ void CodeGeneratorX86::Move64(Location destination, Location source) { EmitParallelMoves( Location::RegisterLocation(source.AsRegisterPairHigh<Register>()), Location::RegisterLocation(destination.AsRegisterPairHigh<Register>()), - Primitive::kPrimInt, + DataType::Type::kInt32, Location::RegisterLocation(source.AsRegisterPairLow<Register>()), Location::RegisterLocation(destination.AsRegisterPairLow<Register>()), - Primitive::kPrimInt); + DataType::Type::kInt32); } else if (source.IsFpuRegister()) { XmmRegister src_reg = source.AsFpuRegister<XmmRegister>(); __ movd(destination.AsRegisterPairLow<Register>(), src_reg); @@ -1284,7 +1285,7 @@ void CodeGeneratorX86::Move64(Location destination, Location source) { } else if (source.IsDoubleStackSlot()) { __ movsd(destination.AsFpuRegister<XmmRegister>(), Address(ESP, source.GetStackIndex())); } else if (source.IsRegisterPair()) { - size_t elem_size = Primitive::ComponentSize(Primitive::kPrimInt); + size_t elem_size = DataType::Size(DataType::Type::kInt32); // Create stack space for 2 elements. __ subl(ESP, Immediate(2 * elem_size)); __ movl(Address(ESP, 0), source.AsRegisterPairLow<Register>()); @@ -1316,10 +1317,10 @@ void CodeGeneratorX86::Move64(Location destination, Location source) { EmitParallelMoves( Location::StackSlot(source.GetStackIndex()), Location::StackSlot(destination.GetStackIndex()), - Primitive::kPrimInt, + DataType::Type::kInt32, Location::StackSlot(source.GetHighStackIndex(kX86WordSize)), Location::StackSlot(destination.GetHighStackIndex(kX86WordSize)), - Primitive::kPrimInt); + DataType::Type::kInt32); } } } @@ -1329,11 +1330,11 @@ void CodeGeneratorX86::MoveConstant(Location location, int32_t value) { __ movl(location.AsRegister<Register>(), Immediate(value)); } -void CodeGeneratorX86::MoveLocation(Location dst, Location src, Primitive::Type dst_type) { +void CodeGeneratorX86::MoveLocation(Location dst, Location src, DataType::Type dst_type) { HParallelMove move(GetGraph()->GetArena()); - if (dst_type == Primitive::kPrimLong && !src.IsConstant() && !src.IsFpuRegister()) { - move.AddMove(src.ToLow(), dst.ToLow(), Primitive::kPrimInt, nullptr); - move.AddMove(src.ToHigh(), dst.ToHigh(), Primitive::kPrimInt, nullptr); + if (dst_type == DataType::Type::kInt64 && !src.IsConstant() && !src.IsFpuRegister()) { + move.AddMove(src.ToLow(), dst.ToLow(), DataType::Type::kInt32, nullptr); + move.AddMove(src.ToHigh(), dst.ToHigh(), DataType::Type::kInt32, nullptr); } else { move.AddMove(src, dst, dst_type, nullptr); } @@ -1556,16 +1557,16 @@ void InstructionCodeGeneratorX86::GenerateCompareTestAndBranch(HCondition* condi Location left = locations->InAt(0); Location right = locations->InAt(1); - Primitive::Type type = condition->InputAt(0)->GetType(); + DataType::Type type = condition->InputAt(0)->GetType(); switch (type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: GenerateLongComparesAndJumps(condition, true_target, false_target); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: GenerateFPCompare(left, right, condition, false); GenerateFPJumps(condition, true_target, false_target); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: GenerateFPCompare(left, right, condition, true); GenerateFPJumps(condition, true_target, false_target); break; @@ -1588,8 +1589,8 @@ static bool AreEflagsSetFrom(HInstruction* cond, HInstruction* branch) { // conditions if they are materialized due to the complex branching. return cond->IsCondition() && cond->GetNext() == branch && - cond->InputAt(0)->GetType() != Primitive::kPrimLong && - !Primitive::IsFloatingPointType(cond->InputAt(0)->GetType()); + cond->InputAt(0)->GetType() != DataType::Type::kInt64 && + !DataType::IsFloatingPointType(cond->InputAt(0)->GetType()); } template<class LabelType> @@ -1653,8 +1654,8 @@ void InstructionCodeGeneratorX86::GenerateTestAndBranch(HInstruction* instructio // If this is a long or FP comparison that has been folded into // the HCondition, generate the comparison directly. - Primitive::Type type = condition->InputAt(0)->GetType(); - if (type == Primitive::kPrimLong || Primitive::IsFloatingPointType(type)) { + DataType::Type type = condition->InputAt(0)->GetType(); + if (type == DataType::Type::kInt64 || DataType::IsFloatingPointType(type)) { GenerateCompareTestAndBranch(condition, true_target, false_target); return; } @@ -1727,7 +1728,7 @@ void InstructionCodeGeneratorX86::VisitShouldDeoptimizeFlag(HShouldDeoptimizeFla static bool SelectCanUseCMOV(HSelect* select) { // There are no conditional move instructions for XMMs. - if (Primitive::IsFloatingPointType(select->GetType())) { + if (DataType::IsFloatingPointType(select->GetType())) { return false; } @@ -1735,9 +1736,9 @@ static bool SelectCanUseCMOV(HSelect* select) { // In 32 bit mode, a long condition doesn't generate a single CC either. HInstruction* condition = select->GetCondition(); if (condition->IsCondition()) { - Primitive::Type compare_type = condition->InputAt(0)->GetType(); - if (compare_type == Primitive::kPrimLong || - Primitive::IsFloatingPointType(compare_type)) { + DataType::Type compare_type = condition->InputAt(0)->GetType(); + if (compare_type == DataType::Type::kInt64 || + DataType::IsFloatingPointType(compare_type)) { return false; } } @@ -1748,7 +1749,7 @@ static bool SelectCanUseCMOV(HSelect* select) { void LocationsBuilderX86::VisitSelect(HSelect* select) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(select); - if (Primitive::IsFloatingPointType(select->GetType())) { + if (DataType::IsFloatingPointType(select->GetType())) { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::Any()); } else { @@ -1796,8 +1797,8 @@ void InstructionCodeGeneratorX86::VisitSelect(HSelect* select) { } } else { // We can't handle FP or long here. - DCHECK_NE(condition->InputAt(0)->GetType(), Primitive::kPrimLong); - DCHECK(!Primitive::IsFloatingPointType(condition->InputAt(0)->GetType())); + DCHECK_NE(condition->InputAt(0)->GetType(), DataType::Type::kInt64); + DCHECK(!DataType::IsFloatingPointType(condition->InputAt(0)->GetType())); LocationSummary* cond_locations = condition->GetLocations(); codegen_->GenerateIntCompare(cond_locations->InAt(0), cond_locations->InAt(1)); cond = X86Condition(condition->GetCondition()); @@ -1811,7 +1812,7 @@ void InstructionCodeGeneratorX86::VisitSelect(HSelect* select) { // If the condition is true, overwrite the output, which already contains false. Location false_loc = locations->InAt(0); Location true_loc = locations->InAt(1); - if (select->GetType() == Primitive::kPrimLong) { + if (select->GetType() == DataType::Type::kInt64) { // 64 bit conditional move. Register false_high = false_loc.AsRegisterPairHigh<Register>(); Register false_low = false_loc.AsRegisterPairLow<Register>(); @@ -1857,7 +1858,7 @@ void LocationsBuilderX86::HandleCondition(HCondition* cond) { new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall); // Handle the long/FP comparisons made in instruction simplification. switch (cond->InputAt(0)->GetType()) { - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); if (!cond->IsEmittedAtUseSite()) { @@ -1865,8 +1866,8 @@ void LocationsBuilderX86::HandleCondition(HCondition* cond) { } break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); if (cond->InputAt(1)->IsX86LoadFromConstantTable()) { DCHECK(cond->InputAt(1)->IsEmittedAtUseSite()); @@ -1912,14 +1913,14 @@ void InstructionCodeGeneratorX86::HandleCondition(HCondition* cond) { __ setb(X86Condition(cond->GetCondition()), reg); return; } - case Primitive::kPrimLong: + case DataType::Type::kInt64: GenerateLongComparesAndJumps(cond, &true_label, &false_label); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: GenerateFPCompare(lhs, rhs, cond, false); GenerateFPJumps(cond, &true_label, &false_label); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: GenerateFPCompare(lhs, rhs, cond, true); GenerateFPJumps(cond, &true_label, &false_label); break; @@ -2098,22 +2099,22 @@ void LocationsBuilderX86::VisitReturn(HReturn* ret) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall); switch (ret->InputAt(0)->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: locations->SetInAt(0, Location::RegisterLocation(EAX)); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: locations->SetInAt( 0, Location::RegisterPairLocation(EAX, EDX)); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt( 0, Location::FpuRegisterLocation(XMM0)); break; @@ -2126,22 +2127,22 @@ void LocationsBuilderX86::VisitReturn(HReturn* ret) { void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) { if (kIsDebugBuild) { switch (ret->InputAt(0)->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: DCHECK_EQ(ret->GetLocations()->InAt(0).AsRegister<Register>(), EAX); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK_EQ(ret->GetLocations()->InAt(0).AsRegisterPairLow<Register>(), EAX); DCHECK_EQ(ret->GetLocations()->InAt(0).AsRegisterPairHigh<Register>(), EDX); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_EQ(ret->GetLocations()->InAt(0).AsFpuRegister<XmmRegister>(), XMM0); break; @@ -2297,20 +2298,20 @@ void LocationsBuilderX86::VisitNeg(HNeg* neg) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); switch (neg->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::SameAsFirstInput()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); locations->AddTemp(Location::RequiresRegister()); locations->AddTemp(Location::RequiresFpuRegister()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); locations->AddTemp(Location::RequiresFpuRegister()); @@ -2326,13 +2327,13 @@ void InstructionCodeGeneratorX86::VisitNeg(HNeg* neg) { Location out = locations->Out(); Location in = locations->InAt(0); switch (neg->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK(in.IsRegister()); DCHECK(in.Equals(out)); __ negl(out.AsRegister<Register>()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK(in.IsRegisterPair()); DCHECK(in.Equals(out)); __ negl(out.AsRegisterPairLow<Register>()); @@ -2345,7 +2346,7 @@ void InstructionCodeGeneratorX86::VisitNeg(HNeg* neg) { __ negl(out.AsRegisterPairHigh<Register>()); break; - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { DCHECK(in.Equals(out)); Register constant = locations->GetTemp(0).AsRegister<Register>(); XmmRegister mask = locations->GetTemp(1).AsFpuRegister<XmmRegister>(); @@ -2358,7 +2359,7 @@ void InstructionCodeGeneratorX86::VisitNeg(HNeg* neg) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { DCHECK(in.Equals(out)); XmmRegister mask = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); // Implement double negation with an exclusive or with value @@ -2377,7 +2378,7 @@ void InstructionCodeGeneratorX86::VisitNeg(HNeg* neg) { void LocationsBuilderX86::VisitX86FPNeg(HX86FPNeg* neg) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); - DCHECK(Primitive::IsFloatingPointType(neg->GetType())); + DCHECK(DataType::IsFloatingPointType(neg->GetType())); locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::RequiresRegister()); locations->SetOut(Location::SameAsFirstInput()); @@ -2391,7 +2392,7 @@ void InstructionCodeGeneratorX86::VisitX86FPNeg(HX86FPNeg* neg) { Register constant_area = locations->InAt(1).AsRegister<Register>(); XmmRegister mask = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); - if (neg->GetType() == Primitive::kPrimFloat) { + if (neg->GetType() == DataType::Type::kFloat32) { __ movss(mask, codegen_->LiteralInt32Address(INT32_C(0x80000000), neg->GetBaseMethodAddress(), constant_area)); @@ -2405,15 +2406,15 @@ void InstructionCodeGeneratorX86::VisitX86FPNeg(HX86FPNeg* neg) { } void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { - Primitive::Type result_type = conversion->GetResultType(); - Primitive::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); DCHECK_NE(result_type, input_type); // The float-to-long and double-to-long type conversions rely on a // call to the runtime. LocationSummary::CallKind call_kind = - ((input_type == Primitive::kPrimFloat || input_type == Primitive::kPrimDouble) - && result_type == Primitive::kPrimLong) + ((input_type == DataType::Type::kFloat32 || input_type == DataType::Type::kFloat64) + && result_type == DataType::Type::kInt64) ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall; LocationSummary* locations = @@ -2423,9 +2424,9 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { // our bit representation makes it safe. switch (result_type) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: switch (input_type) { - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { // Type conversion from long to byte is a result of code transformations. HInstruction* input = conversion->InputAt(0); Location input_location = input->IsConstant() @@ -2437,11 +2438,11 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap); break; } - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-byte' instruction. locations->SetInAt(0, Location::ByteRegisterOrConstant(ECX, conversion->InputAt(0))); // Make the output overlap to please the register allocator. This greatly simplifies @@ -2455,15 +2456,15 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to short is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-short' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -2475,22 +2476,22 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-int' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-int' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); locations->AddTemp(Location::RequiresFpuRegister()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-int' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); @@ -2503,21 +2504,21 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-long' instruction. locations->SetInAt(0, Location::RegisterLocation(EAX)); locations->SetOut(Location::RegisterPairLocation(EAX, EDX)); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { // Processing a Dex `float-to-long' or 'double-to-long' instruction. InvokeRuntimeCallingConvention calling_convention; XmmRegister parameter = calling_convention.GetFpuRegisterAt(0); @@ -2534,15 +2535,15 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to char is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: // Processing a Dex `int-to-char' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -2554,26 +2555,26 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-float' instruction. locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-float' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::Any()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-float' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -2585,26 +2586,26 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { }; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-double' instruction. locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-double' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::Any()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-double' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -2626,13 +2627,13 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio LocationSummary* locations = conversion->GetLocations(); Location out = locations->Out(); Location in = locations->InAt(0); - Primitive::Type result_type = conversion->GetResultType(); - Primitive::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); DCHECK_NE(result_type, input_type); switch (result_type) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to byte is a result of code transformations. if (in.IsRegisterPair()) { __ movsxb(out.AsRegister<Register>(), in.AsRegisterPairLow<ByteRegister>()); @@ -2642,11 +2643,11 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio __ movl(out.AsRegister<Register>(), Immediate(static_cast<int8_t>(value))); } break; - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-byte' instruction. if (in.IsRegister()) { __ movsxb(out.AsRegister<Register>(), in.AsRegister<ByteRegister>()); @@ -2663,9 +2664,9 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio } break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to short is a result of code transformations. if (in.IsRegisterPair()) { __ movsxw(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>()); @@ -2677,11 +2678,11 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio __ movl(out.AsRegister<Register>(), Immediate(static_cast<int16_t>(value))); } break; - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-short' instruction. if (in.IsRegister()) { __ movsxw(out.AsRegister<Register>(), in.AsRegister<Register>()); @@ -2700,9 +2701,9 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-int' instruction. if (in.IsRegisterPair()) { __ movl(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>()); @@ -2716,7 +2717,7 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio } break; - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { // Processing a Dex `float-to-int' instruction. XmmRegister input = in.AsFpuRegister<XmmRegister>(); Register output = out.AsRegister<Register>(); @@ -2741,7 +2742,7 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { // Processing a Dex `double-to-int' instruction. XmmRegister input = in.AsFpuRegister<XmmRegister>(); Register output = out.AsRegister<Register>(); @@ -2772,14 +2773,14 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-long' instruction. DCHECK_EQ(out.AsRegisterPairLow<Register>(), EAX); DCHECK_EQ(out.AsRegisterPairHigh<Register>(), EDX); @@ -2787,13 +2788,13 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio __ cdq(); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-long' instruction. codegen_->InvokeRuntime(kQuickF2l, conversion, conversion->GetDexPc()); CheckEntrypointTypes<kQuickF2l, int64_t, float>(); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-long' instruction. codegen_->InvokeRuntime(kQuickD2l, conversion, conversion->GetDexPc()); CheckEntrypointTypes<kQuickD2l, int64_t, double>(); @@ -2805,9 +2806,9 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio } break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to short is a result of code transformations. if (in.IsRegisterPair()) { __ movzxw(out.AsRegister<Register>(), in.AsRegisterPairLow<Register>()); @@ -2819,11 +2820,11 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio __ movl(out.AsRegister<Register>(), Immediate(static_cast<uint16_t>(value))); } break; - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: // Processing a Dex `Process a Dex `int-to-char'' instruction. if (in.IsRegister()) { __ movzxw(out.AsRegister<Register>(), in.AsRegister<Register>()); @@ -2842,19 +2843,19 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-float' instruction. __ cvtsi2ss(out.AsFpuRegister<XmmRegister>(), in.AsRegister<Register>()); break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { // Processing a Dex `long-to-float' instruction. size_t adjustment = 0; @@ -2862,7 +2863,7 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio // InstructionCodeGeneratorX86::PushOntoFPStack and/or X86Assembler::fstps below. // TODO: enhance register allocator to ask for stack temporaries. if (!in.IsDoubleStackSlot() || !out.IsStackSlot()) { - adjustment = Primitive::ComponentSize(Primitive::kPrimLong); + adjustment = DataType::Size(DataType::Type::kInt64); __ subl(ESP, Immediate(adjustment)); } @@ -2884,7 +2885,7 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio break; } - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-float' instruction. __ cvtsd2ss(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>()); break; @@ -2895,19 +2896,19 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio }; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-double' instruction. __ cvtsi2sd(out.AsFpuRegister<XmmRegister>(), in.AsRegister<Register>()); break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { // Processing a Dex `long-to-double' instruction. size_t adjustment = 0; @@ -2915,7 +2916,7 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio // InstructionCodeGeneratorX86::PushOntoFPStack and/or X86Assembler::fstpl below. // TODO: enhance register allocator to ask for stack temporaries. if (!in.IsDoubleStackSlot() || !out.IsDoubleStackSlot()) { - adjustment = Primitive::ComponentSize(Primitive::kPrimLong); + adjustment = DataType::Size(DataType::Type::kInt64); __ subl(ESP, Immediate(adjustment)); } @@ -2937,7 +2938,7 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio break; } - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-double' instruction. __ cvtss2sd(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>()); break; @@ -2958,22 +2959,22 @@ void LocationsBuilderX86::VisitAdd(HAdd* add) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall); switch (add->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(add->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::SameAsFirstInput()); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); if (add->InputAt(1)->IsX86LoadFromConstantTable()) { DCHECK(add->InputAt(1)->IsEmittedAtUseSite()); @@ -2999,7 +3000,7 @@ void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) { Location out = locations->Out(); switch (add->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { if (second.IsRegister()) { if (out.AsRegister<Register>() == first.AsRegister<Register>()) { __ addl(out.AsRegister<Register>(), second.AsRegister<Register>()); @@ -3023,7 +3024,7 @@ void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (second.IsRegisterPair()) { __ addl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>()); __ adcl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>()); @@ -3040,7 +3041,7 @@ void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (second.IsFpuRegister()) { __ addss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (add->InputAt(1)->IsX86LoadFromConstantTable()) { @@ -3058,7 +3059,7 @@ void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (second.IsFpuRegister()) { __ addsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (add->InputAt(1)->IsX86LoadFromConstantTable()) { @@ -3085,15 +3086,15 @@ void LocationsBuilderX86::VisitSub(HSub* sub) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub, LocationSummary::kNoCall); switch (sub->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::SameAsFirstInput()); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); if (sub->InputAt(1)->IsX86LoadFromConstantTable()) { DCHECK(sub->InputAt(1)->IsEmittedAtUseSite()); @@ -3117,7 +3118,7 @@ void InstructionCodeGeneratorX86::VisitSub(HSub* sub) { Location second = locations->InAt(1); DCHECK(first.Equals(locations->Out())); switch (sub->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { if (second.IsRegister()) { __ subl(first.AsRegister<Register>(), second.AsRegister<Register>()); } else if (second.IsConstant()) { @@ -3129,7 +3130,7 @@ void InstructionCodeGeneratorX86::VisitSub(HSub* sub) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (second.IsRegisterPair()) { __ subl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>()); __ sbbl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>()); @@ -3146,7 +3147,7 @@ void InstructionCodeGeneratorX86::VisitSub(HSub* sub) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (second.IsFpuRegister()) { __ subss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (sub->InputAt(1)->IsX86LoadFromConstantTable()) { @@ -3164,7 +3165,7 @@ void InstructionCodeGeneratorX86::VisitSub(HSub* sub) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (second.IsFpuRegister()) { __ subsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (sub->InputAt(1)->IsX86LoadFromConstantTable()) { @@ -3191,7 +3192,7 @@ void LocationsBuilderX86::VisitMul(HMul* mul) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(mul, LocationSummary::kNoCall); switch (mul->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); if (mul->InputAt(1)->IsIntConstant()) { @@ -3201,7 +3202,7 @@ void LocationsBuilderX86::VisitMul(HMul* mul) { locations->SetOut(Location::SameAsFirstInput()); } break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::SameAsFirstInput()); @@ -3210,8 +3211,8 @@ void LocationsBuilderX86::VisitMul(HMul* mul) { locations->AddTemp(Location::RegisterLocation(EDX)); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); if (mul->InputAt(1)->IsX86LoadFromConstantTable()) { DCHECK(mul->InputAt(1)->IsEmittedAtUseSite()); @@ -3236,7 +3237,7 @@ void InstructionCodeGeneratorX86::VisitMul(HMul* mul) { Location out = locations->Out(); switch (mul->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: // The constant may have ended up in a register, so test explicitly to avoid // problems where the output may not be the same as the first operand. if (mul->InputAt(1)->IsIntConstant()) { @@ -3252,7 +3253,7 @@ void InstructionCodeGeneratorX86::VisitMul(HMul* mul) { } break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Register in1_hi = first.AsRegisterPairHigh<Register>(); Register in1_lo = first.AsRegisterPairLow<Register>(); Register eax = locations->GetTemp(0).AsRegister<Register>(); @@ -3334,7 +3335,7 @@ void InstructionCodeGeneratorX86::VisitMul(HMul* mul) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { DCHECK(first.Equals(locations->Out())); if (second.IsFpuRegister()) { __ mulss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); @@ -3353,7 +3354,7 @@ void InstructionCodeGeneratorX86::VisitMul(HMul* mul) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { DCHECK(first.Equals(locations->Out())); if (second.IsFpuRegister()) { __ mulsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); @@ -3419,9 +3420,9 @@ void InstructionCodeGeneratorX86::PushOntoFPStack(Location source, } void InstructionCodeGeneratorX86::GenerateRemFP(HRem *rem) { - Primitive::Type type = rem->GetResultType(); - bool is_float = type == Primitive::kPrimFloat; - size_t elem_size = Primitive::ComponentSize(type); + DataType::Type type = rem->GetResultType(); + bool is_float = type == DataType::Type::kFloat32; + size_t elem_size = DataType::Size(type); LocationSummary* locations = rem->GetLocations(); Location first = locations->InAt(0); Location second = locations->InAt(1); @@ -3598,7 +3599,7 @@ void InstructionCodeGeneratorX86::GenerateDivRemIntegral(HBinaryOperation* instr bool is_div = instruction->IsDiv(); switch (instruction->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { DCHECK_EQ(EAX, first.AsRegister<Register>()); DCHECK_EQ(is_div ? EAX : EDX, out.AsRegister<Register>()); @@ -3637,7 +3638,7 @@ void InstructionCodeGeneratorX86::GenerateDivRemIntegral(HBinaryOperation* instr break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { InvokeRuntimeCallingConvention calling_convention; DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegisterPairLow<Register>()); DCHECK_EQ(calling_convention.GetRegisterAt(1), first.AsRegisterPairHigh<Register>()); @@ -3662,13 +3663,13 @@ void InstructionCodeGeneratorX86::GenerateDivRemIntegral(HBinaryOperation* instr } void LocationsBuilderX86::VisitDiv(HDiv* div) { - LocationSummary::CallKind call_kind = (div->GetResultType() == Primitive::kPrimLong) + LocationSummary::CallKind call_kind = (div->GetResultType() == DataType::Type::kInt64) ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall; LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, call_kind); switch (div->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RegisterLocation(EAX)); locations->SetInAt(1, Location::RegisterOrConstant(div->InputAt(1))); locations->SetOut(Location::SameAsFirstInput()); @@ -3682,7 +3683,7 @@ void LocationsBuilderX86::VisitDiv(HDiv* div) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::RegisterPairLocation( calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1))); @@ -3692,8 +3693,8 @@ void LocationsBuilderX86::VisitDiv(HDiv* div) { locations->SetOut(Location::RegisterPairLocation(EAX, EDX)); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); if (div->InputAt(1)->IsX86LoadFromConstantTable()) { DCHECK(div->InputAt(1)->IsEmittedAtUseSite()); @@ -3717,13 +3718,13 @@ void InstructionCodeGeneratorX86::VisitDiv(HDiv* div) { Location second = locations->InAt(1); switch (div->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GenerateDivRemIntegral(div); break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (second.IsFpuRegister()) { __ divss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (div->InputAt(1)->IsX86LoadFromConstantTable()) { @@ -3741,7 +3742,7 @@ void InstructionCodeGeneratorX86::VisitDiv(HDiv* div) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (second.IsFpuRegister()) { __ divsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (div->InputAt(1)->IsX86LoadFromConstantTable()) { @@ -3765,15 +3766,15 @@ void InstructionCodeGeneratorX86::VisitDiv(HDiv* div) { } void LocationsBuilderX86::VisitRem(HRem* rem) { - Primitive::Type type = rem->GetResultType(); + DataType::Type type = rem->GetResultType(); - LocationSummary::CallKind call_kind = (rem->GetResultType() == Primitive::kPrimLong) + LocationSummary::CallKind call_kind = (rem->GetResultType() == DataType::Type::kInt64) ? LocationSummary::kCallOnMainOnly : LocationSummary::kNoCall; LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RegisterLocation(EAX)); locations->SetInAt(1, Location::RegisterOrConstant(rem->InputAt(1))); locations->SetOut(Location::RegisterLocation(EDX)); @@ -3785,7 +3786,7 @@ void LocationsBuilderX86::VisitRem(HRem* rem) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::RegisterPairLocation( calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1))); @@ -3795,8 +3796,8 @@ void LocationsBuilderX86::VisitRem(HRem* rem) { locations->SetOut(Location::RegisterPairLocation(EAX, EDX)); break; } - case Primitive::kPrimDouble: - case Primitive::kPrimFloat: { + case DataType::Type::kFloat64: + case DataType::Type::kFloat32: { locations->SetInAt(0, Location::Any()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::RequiresFpuRegister()); @@ -3810,15 +3811,15 @@ void LocationsBuilderX86::VisitRem(HRem* rem) { } void InstructionCodeGeneratorX86::VisitRem(HRem* rem) { - Primitive::Type type = rem->GetResultType(); + DataType::Type type = rem->GetResultType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GenerateDivRemIntegral(rem); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { GenerateRemFP(rem); break; } @@ -3830,15 +3831,15 @@ void InstructionCodeGeneratorX86::VisitRem(HRem* rem) { void LocationsBuilderX86::VisitDivZeroCheck(HDivZeroCheck* instruction) { LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction); switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: { locations->SetInAt(0, Location::Any()); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0))); if (!instruction->IsConstant()) { locations->AddTemp(Location::RequiresRegister()); @@ -3858,11 +3859,11 @@ void InstructionCodeGeneratorX86::VisitDivZeroCheck(HDivZeroCheck* instruction) Location value = locations->InAt(0); switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: { if (value.IsRegister()) { __ testl(value.AsRegister<Register>(), value.AsRegister<Register>()); __ j(kEqual, slow_path->GetEntryLabel()); @@ -3877,7 +3878,7 @@ void InstructionCodeGeneratorX86::VisitDivZeroCheck(HDivZeroCheck* instruction) } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (value.IsRegisterPair()) { Register temp = locations->GetTemp(0).AsRegister<Register>(); __ movl(temp, value.AsRegisterPairLow<Register>()); @@ -3903,8 +3904,8 @@ void LocationsBuilderX86::HandleShift(HBinaryOperation* op) { new (GetGraph()->GetArena()) LocationSummary(op, LocationSummary::kNoCall); switch (op->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { // Can't have Location::Any() and output SameAsFirstInput() locations->SetInAt(0, Location::RequiresRegister()); // The shift count needs to be in CL or a constant. @@ -3926,7 +3927,7 @@ void InstructionCodeGeneratorX86::HandleShift(HBinaryOperation* op) { DCHECK(first.Equals(locations->Out())); switch (op->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { DCHECK(first.IsRegister()); Register first_reg = first.AsRegister<Register>(); if (second.IsRegister()) { @@ -3955,7 +3956,7 @@ void InstructionCodeGeneratorX86::HandleShift(HBinaryOperation* op) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (second.IsRegister()) { Register second_reg = second.AsRegister<Register>(); DCHECK_EQ(ECX, second_reg); @@ -3999,10 +4000,10 @@ void InstructionCodeGeneratorX86::GenerateShlLong(const Location& loc, int shift codegen_->EmitParallelMoves( loc.ToLow(), loc.ToHigh(), - Primitive::kPrimInt, + DataType::Type::kInt32, Location::ConstantLocation(GetGraph()->GetIntConstant(0)), loc.ToLow(), - Primitive::kPrimInt); + DataType::Type::kInt32); } else if (shift > 32) { // Low part becomes 0. High part is low part << (shift-32). __ movl(high, low); @@ -4066,10 +4067,10 @@ void InstructionCodeGeneratorX86::GenerateUShrLong(const Location& loc, int shif codegen_->EmitParallelMoves( loc.ToHigh(), loc.ToLow(), - Primitive::kPrimInt, + DataType::Type::kInt32, Location::ConstantLocation(GetGraph()->GetIntConstant(0)), loc.ToHigh(), - Primitive::kPrimInt); + DataType::Type::kInt32); } else if (shift > 32) { // Low part is high >> (shift - 32). High part becomes 0. __ movl(low, high); @@ -4098,11 +4099,11 @@ void LocationsBuilderX86::VisitRor(HRor* ror) { new (GetGraph()->GetArena()) LocationSummary(ror, LocationSummary::kNoCall); switch (ror->GetResultType()) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Add the temporary needed. locations->AddTemp(Location::RequiresRegister()); FALLTHROUGH_INTENDED; - case Primitive::kPrimInt: + case DataType::Type::kInt32: locations->SetInAt(0, Location::RequiresRegister()); // The shift count needs to be in CL (unless it is a constant). locations->SetInAt(1, Location::ByteRegisterOrConstant(ECX, ror->InputAt(1))); @@ -4119,7 +4120,7 @@ void InstructionCodeGeneratorX86::VisitRor(HRor* ror) { Location first = locations->InAt(0); Location second = locations->InAt(1); - if (ror->GetResultType() == Primitive::kPrimInt) { + if (ror->GetResultType() == DataType::Type::kInt32) { Register first_reg = first.AsRegister<Register>(); if (second.IsRegister()) { Register second_reg = second.AsRegister<Register>(); @@ -4131,7 +4132,7 @@ void InstructionCodeGeneratorX86::VisitRor(HRor* ror) { return; } - DCHECK_EQ(ror->GetResultType(), Primitive::kPrimLong); + DCHECK_EQ(ror->GetResultType(), DataType::Type::kInt64); Register first_reg_lo = first.AsRegisterPairLow<Register>(); Register first_reg_hi = first.AsRegisterPairHigh<Register>(); Register temp_reg = locations->GetTemp(0).AsRegister<Register>(); @@ -4314,11 +4315,11 @@ void InstructionCodeGeneratorX86::VisitNot(HNot* not_) { Location out = locations->Out(); DCHECK(in.Equals(out)); switch (not_->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ notl(out.AsRegister<Register>()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: __ notl(out.AsRegisterPairLow<Register>()); __ notl(out.AsRegisterPairHigh<Register>()); break; @@ -4347,19 +4348,19 @@ void LocationsBuilderX86::VisitCompare(HCompare* compare) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall); switch (compare->InputAt(0)->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); if (compare->InputAt(1)->IsX86LoadFromConstantTable()) { DCHECK(compare->InputAt(1)->IsEmittedAtUseSite()); @@ -4386,15 +4387,15 @@ void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) { Condition less_cond = kLess; switch (compare->InputAt(0)->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: { codegen_->GenerateIntCompare(left, right); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Register left_low = left.AsRegisterPairLow<Register>(); Register left_high = left.AsRegisterPairHigh<Register>(); int32_t val_low = 0; @@ -4430,13 +4431,13 @@ void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) { less_cond = kBelow; // for CF (unsigned). break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { GenerateFPCompare(left, right, compare, false); __ j(kUnordered, compare->IsGtBias() ? &greater : &less); less_cond = kBelow; // for CF (floats). break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { GenerateFPCompare(left, right, compare, true); __ j(kUnordered, compare->IsGtBias() ? &greater : &less); less_cond = kBelow; // for CF (floats). @@ -4675,10 +4676,10 @@ Label* CodeGeneratorX86::NewStringBssEntryPatch(HLoadString* load_string) { // for method patch needs to point to the embedded constant which occupies the last 4 bytes. constexpr uint32_t kLabelPositionToLiteralOffsetAdjustment = 4u; -template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> +template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> inline void CodeGeneratorX86::EmitPcRelativeLinkerPatches( const ArenaDeque<X86PcRelativePatchInfo>& infos, - ArenaVector<LinkerPatch>* linker_patches) { + ArenaVector<linker::LinkerPatch>* linker_patches) { for (const X86PcRelativePatchInfo& info : infos) { uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment; linker_patches->push_back(Factory( @@ -4686,7 +4687,7 @@ inline void CodeGeneratorX86::EmitPcRelativeLinkerPatches( } } -void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) { +void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) { DCHECK(linker_patches->empty()); size_t size = boot_image_method_patches_.size() + @@ -4697,24 +4698,25 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patche string_bss_entry_patches_.size(); linker_patches->reserve(size); if (GetCompilerOptions().IsBootImage()) { - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(boot_image_method_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeTypePatch>(boot_image_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeStringPatch>(string_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>( + boot_image_method_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>( + boot_image_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>( + string_patches_, linker_patches); } else { DCHECK(boot_image_method_patches_.empty()); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(boot_image_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(string_patches_, - linker_patches); - } - EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(string_bss_entry_patches_, - linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>( + boot_image_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>( + string_patches_, linker_patches); + } + EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( + method_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>( + type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>( + string_bss_entry_patches_, linker_patches); DCHECK_EQ(size, linker_patches->size()); } @@ -4742,7 +4744,7 @@ void LocationsBuilderX86::HandleFieldGet(HInstruction* instruction, const FieldI DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet()); bool object_field_get_with_read_barrier = - kEmitCompilerReadBarrier && (instruction->GetType() == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (instruction->GetType() == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, kEmitCompilerReadBarrier ? @@ -4753,7 +4755,7 @@ void LocationsBuilderX86::HandleFieldGet(HInstruction* instruction, const FieldI } locations->SetInAt(0, Location::RequiresRegister()); - if (Primitive::IsFloatingPointType(instruction->GetType())) { + if (DataType::IsFloatingPointType(instruction->GetType())) { locations->SetOut(Location::RequiresFpuRegister()); } else { // The output overlaps in case of long: we don't want the low move @@ -4763,12 +4765,12 @@ void LocationsBuilderX86::HandleFieldGet(HInstruction* instruction, const FieldI // the read barrier. locations->SetOut( Location::RequiresRegister(), - (object_field_get_with_read_barrier || instruction->GetType() == Primitive::kPrimLong) ? + (object_field_get_with_read_barrier || instruction->GetType() == DataType::Type::kInt64) ? Location::kOutputOverlap : Location::kNoOutputOverlap); } - if (field_info.IsVolatile() && (field_info.GetFieldType() == Primitive::kPrimLong)) { + if (field_info.IsVolatile() && (field_info.GetFieldType() == DataType::Type::kInt64)) { // Long values can be loaded atomically into an XMM using movsd. // So we use an XMM register as a temp to achieve atomicity (first // load the temp into the XMM and then copy the XMM into the @@ -4786,35 +4788,35 @@ void InstructionCodeGeneratorX86::HandleFieldGet(HInstruction* instruction, Register base = base_loc.AsRegister<Register>(); Location out = locations->Out(); bool is_volatile = field_info.IsVolatile(); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); uint32_t offset = field_info.GetFieldOffset().Uint32Value(); switch (field_type) { - case Primitive::kPrimBoolean: { + case DataType::Type::kBool: { __ movzxb(out.AsRegister<Register>(), Address(base, offset)); break; } - case Primitive::kPrimByte: { + case DataType::Type::kInt8: { __ movsxb(out.AsRegister<Register>(), Address(base, offset)); break; } - case Primitive::kPrimShort: { + case DataType::Type::kInt16: { __ movsxw(out.AsRegister<Register>(), Address(base, offset)); break; } - case Primitive::kPrimChar: { + case DataType::Type::kUint16: { __ movzxw(out.AsRegister<Register>(), Address(base, offset)); break; } - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ movl(out.AsRegister<Register>(), Address(base, offset)); break; - case Primitive::kPrimNot: { + case DataType::Type::kReference: { // /* HeapReference<Object> */ out = *(base + offset) if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) { // Note that a potential implicit null check is handled in this @@ -4838,7 +4840,7 @@ void InstructionCodeGeneratorX86::HandleFieldGet(HInstruction* instruction, break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (is_volatile) { XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); __ movsd(temp, Address(base, offset)); @@ -4855,22 +4857,22 @@ void InstructionCodeGeneratorX86::HandleFieldGet(HInstruction* instruction, break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { __ movss(out.AsFpuRegister<XmmRegister>(), Address(base, offset)); break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { __ movsd(out.AsFpuRegister<XmmRegister>(), Address(base, offset)); break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); } - if (field_type == Primitive::kPrimNot || field_type == Primitive::kPrimLong) { + if (field_type == DataType::Type::kReference || field_type == DataType::Type::kInt64) { // Potential implicit null checks, in the case of reference or // long fields, are handled in the previous switch statement. } else { @@ -4878,7 +4880,7 @@ void InstructionCodeGeneratorX86::HandleFieldGet(HInstruction* instruction, } if (is_volatile) { - if (field_type == Primitive::kPrimNot) { + if (field_type == DataType::Type::kReference) { // Memory barriers, in the case of references, are also handled // in the previous switch statement. } else { @@ -4894,23 +4896,23 @@ void LocationsBuilderX86::HandleFieldSet(HInstruction* instruction, const FieldI new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); locations->SetInAt(0, Location::RequiresRegister()); bool is_volatile = field_info.IsVolatile(); - Primitive::Type field_type = field_info.GetFieldType(); - bool is_byte_type = (field_type == Primitive::kPrimBoolean) - || (field_type == Primitive::kPrimByte); + DataType::Type field_type = field_info.GetFieldType(); + bool is_byte_type = (field_type == DataType::Type::kBool) + || (field_type == DataType::Type::kInt8); // The register allocator does not support multiple // inputs that die at entry with one in a specific register. if (is_byte_type) { // Ensure the value is in a byte register. locations->SetInAt(1, Location::RegisterLocation(EAX)); - } else if (Primitive::IsFloatingPointType(field_type)) { - if (is_volatile && field_type == Primitive::kPrimDouble) { + } else if (DataType::IsFloatingPointType(field_type)) { + if (is_volatile && field_type == DataType::Type::kFloat64) { // In order to satisfy the semantics of volatile, this must be a single instruction store. locations->SetInAt(1, Location::RequiresFpuRegister()); } else { locations->SetInAt(1, Location::FpuRegisterOrConstant(instruction->InputAt(1))); } - } else if (is_volatile && field_type == Primitive::kPrimLong) { + } else if (is_volatile && field_type == DataType::Type::kInt64) { // In order to satisfy the semantics of volatile, this must be a single instruction store. locations->SetInAt(1, Location::RequiresRegister()); @@ -4942,7 +4944,7 @@ void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction, Register base = locations->InAt(0).AsRegister<Register>(); Location value = locations->InAt(1); bool is_volatile = field_info.IsVolatile(); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); uint32_t offset = field_info.GetFieldOffset().Uint32Value(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1)); @@ -4954,14 +4956,14 @@ void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction, bool maybe_record_implicit_null_check_done = false; switch (field_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: { + case DataType::Type::kBool: + case DataType::Type::kInt8: { __ movb(Address(base, offset), value.AsRegister<ByteRegister>()); break; } - case Primitive::kPrimShort: - case Primitive::kPrimChar: { + case DataType::Type::kInt16: + case DataType::Type::kUint16: { if (value.IsConstant()) { __ movw(Address(base, offset), Immediate(CodeGenerator::GetInt16ValueOf(value.GetConstant()))); @@ -4971,13 +4973,13 @@ void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimInt: - case Primitive::kPrimNot: { + case DataType::Type::kInt32: + case DataType::Type::kReference: { if (kPoisonHeapReferences && needs_write_barrier) { // Note that in the case where `value` is a null reference, // we do not enter this block, as the reference does not // need poisoning. - DCHECK_EQ(field_type, Primitive::kPrimNot); + DCHECK_EQ(field_type, DataType::Type::kReference); Register temp = locations->GetTemp(0).AsRegister<Register>(); __ movl(temp, value.AsRegister<Register>()); __ PoisonHeapReference(temp); @@ -4992,7 +4994,7 @@ void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (is_volatile) { XmmRegister temp1 = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); XmmRegister temp2 = locations->GetTemp(1).AsFpuRegister<XmmRegister>(); @@ -5015,7 +5017,7 @@ void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (value.IsConstant()) { int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant()); __ movl(Address(base, offset), Immediate(v)); @@ -5025,7 +5027,7 @@ void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (value.IsConstant()) { int64_t v = CodeGenerator::GetInt64ValueOf(value.GetConstant()); __ movl(Address(base, offset), Immediate(Low32Bits(v))); @@ -5038,7 +5040,7 @@ void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); } @@ -5203,7 +5205,7 @@ void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) { void LocationsBuilderX86::VisitArrayGet(HArrayGet* instruction) { bool object_array_get_with_read_barrier = - kEmitCompilerReadBarrier && (instruction->GetType() == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (instruction->GetType() == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, object_array_get_with_read_barrier ? @@ -5214,7 +5216,7 @@ void LocationsBuilderX86::VisitArrayGet(HArrayGet* instruction) { } locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - if (Primitive::IsFloatingPointType(instruction->GetType())) { + if (DataType::IsFloatingPointType(instruction->GetType())) { locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); } else { // The output overlaps in case of long: we don't want the low move @@ -5224,9 +5226,9 @@ void LocationsBuilderX86::VisitArrayGet(HArrayGet* instruction) { // the read barrier. locations->SetOut( Location::RequiresRegister(), - (instruction->GetType() == Primitive::kPrimLong || object_array_get_with_read_barrier) ? - Location::kOutputOverlap : - Location::kNoOutputOverlap); + (instruction->GetType() == DataType::Type::kInt64 || object_array_get_with_read_barrier) + ? Location::kOutputOverlap + : Location::kNoOutputOverlap); } } @@ -5238,27 +5240,27 @@ void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) { Location out_loc = locations->Out(); uint32_t data_offset = CodeGenerator::GetArrayDataOffset(instruction); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); switch (type) { - case Primitive::kPrimBoolean: { + case DataType::Type::kBool: { Register out = out_loc.AsRegister<Register>(); __ movzxb(out, CodeGeneratorX86::ArrayAddress(obj, index, TIMES_1, data_offset)); break; } - case Primitive::kPrimByte: { + case DataType::Type::kInt8: { Register out = out_loc.AsRegister<Register>(); __ movsxb(out, CodeGeneratorX86::ArrayAddress(obj, index, TIMES_1, data_offset)); break; } - case Primitive::kPrimShort: { + case DataType::Type::kInt16: { Register out = out_loc.AsRegister<Register>(); __ movsxw(out, CodeGeneratorX86::ArrayAddress(obj, index, TIMES_2, data_offset)); break; } - case Primitive::kPrimChar: { + case DataType::Type::kUint16: { Register out = out_loc.AsRegister<Register>(); if (mirror::kUseStringCompression && instruction->IsStringCharAt()) { // Branch cases into compressed and uncompressed for each index's type. @@ -5282,13 +5284,13 @@ void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { Register out = out_loc.AsRegister<Register>(); __ movl(out, CodeGeneratorX86::ArrayAddress(obj, index, TIMES_4, data_offset)); break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { static_assert( sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t), "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes."); @@ -5318,7 +5320,7 @@ void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { DCHECK_NE(obj, out_loc.AsRegisterPairLow<Register>()); __ movl(out_loc.AsRegisterPairLow<Register>(), CodeGeneratorX86::ArrayAddress(obj, index, TIMES_8, data_offset)); @@ -5328,24 +5330,24 @@ void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { XmmRegister out = out_loc.AsFpuRegister<XmmRegister>(); __ movss(out, CodeGeneratorX86::ArrayAddress(obj, index, TIMES_4, data_offset)); break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { XmmRegister out = out_loc.AsFpuRegister<XmmRegister>(); __ movsd(out, CodeGeneratorX86::ArrayAddress(obj, index, TIMES_8, data_offset)); break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; UNREACHABLE(); } - if (type == Primitive::kPrimNot || type == Primitive::kPrimLong) { + if (type == DataType::Type::kReference || type == DataType::Type::kInt64) { // Potential implicit null checks, in the case of reference or // long arrays, are handled in the previous switch statement. } else { @@ -5354,7 +5356,7 @@ void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) { } void LocationsBuilderX86::VisitArraySet(HArraySet* instruction) { - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); @@ -5366,8 +5368,8 @@ void LocationsBuilderX86::VisitArraySet(HArraySet* instruction) { LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); - bool is_byte_type = (value_type == Primitive::kPrimBoolean) - || (value_type == Primitive::kPrimByte); + bool is_byte_type = (value_type == DataType::Type::kBool) + || (value_type == DataType::Type::kInt8); // We need the inputs to be different than the output in case of long operation. // In case of a byte operation, the register allocator does not support multiple // inputs that die at entry with one in a specific register. @@ -5376,7 +5378,7 @@ void LocationsBuilderX86::VisitArraySet(HArraySet* instruction) { if (is_byte_type) { // Ensure the value is in a byte register. locations->SetInAt(2, Location::ByteRegisterOrConstant(EAX, instruction->InputAt(2))); - } else if (Primitive::IsFloatingPointType(value_type)) { + } else if (DataType::IsFloatingPointType(value_type)) { locations->SetInAt(2, Location::FpuRegisterOrConstant(instruction->InputAt(2))); } else { locations->SetInAt(2, Location::RegisterOrConstant(instruction->InputAt(2))); @@ -5395,7 +5397,7 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) { Register array = array_loc.AsRegister<Register>(); Location index = locations->InAt(1); Location value = locations->InAt(2); - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value(); uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value(); @@ -5404,8 +5406,8 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) { CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); switch (value_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: { + case DataType::Type::kBool: + case DataType::Type::kInt8: { uint32_t offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value(); Address address = CodeGeneratorX86::ArrayAddress(array, index, TIMES_1, offset); if (value.IsRegister()) { @@ -5417,8 +5419,8 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimShort: - case Primitive::kPrimChar: { + case DataType::Type::kInt16: + case DataType::Type::kUint16: { uint32_t offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value(); Address address = CodeGeneratorX86::ArrayAddress(array, index, TIMES_2, offset); if (value.IsRegister()) { @@ -5430,7 +5432,7 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { uint32_t offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); Address address = CodeGeneratorX86::ArrayAddress(array, index, TIMES_4, offset); @@ -5526,7 +5528,7 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { uint32_t offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); Address address = CodeGeneratorX86::ArrayAddress(array, index, TIMES_4, offset); if (value.IsRegister()) { @@ -5540,7 +5542,7 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value(); if (value.IsRegisterPair()) { __ movl(CodeGeneratorX86::ArrayAddress(array, index, TIMES_8, data_offset), @@ -5560,7 +5562,7 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { uint32_t offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value(); Address address = CodeGeneratorX86::ArrayAddress(array, index, TIMES_4, offset); if (value.IsFpuRegister()) { @@ -5574,7 +5576,7 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { uint32_t offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value(); Address address = CodeGeneratorX86::ArrayAddress(array, index, TIMES_8, offset); if (value.IsFpuRegister()) { @@ -5591,7 +5593,7 @@ void InstructionCodeGeneratorX86::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); } @@ -5801,7 +5803,7 @@ void ParallelMoveResolverX86::EmitMove(size_t index) { __ movl(Address(ESP, destination.GetStackIndex()), source.AsRegister<Register>()); } } else if (source.IsRegisterPair()) { - size_t elem_size = Primitive::ComponentSize(Primitive::kPrimInt); + size_t elem_size = DataType::Size(DataType::Type::kInt32); // Create stack space for 2 elements. __ subl(ESP, Immediate(2 * elem_size)); __ movl(Address(ESP, 0), source.AsRegisterPairLow<Register>()); @@ -6955,8 +6957,8 @@ void LocationsBuilderX86::VisitXor(HXor* instruction) { HandleBitwiseOperation(i void LocationsBuilderX86::HandleBitwiseOperation(HBinaryOperation* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); - DCHECK(instruction->GetResultType() == Primitive::kPrimInt - || instruction->GetResultType() == Primitive::kPrimLong); + DCHECK(instruction->GetResultType() == DataType::Type::kInt32 + || instruction->GetResultType() == DataType::Type::kInt64); locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::SameAsFirstInput()); @@ -6980,7 +6982,7 @@ void InstructionCodeGeneratorX86::HandleBitwiseOperation(HBinaryOperation* instr Location second = locations->InAt(1); DCHECK(first.Equals(locations->Out())); - if (instruction->GetResultType() == Primitive::kPrimInt) { + if (instruction->GetResultType() == DataType::Type::kInt32) { if (second.IsRegister()) { if (instruction->IsAnd()) { __ andl(first.AsRegister<Register>(), second.AsRegister<Register>()); @@ -7013,7 +7015,7 @@ void InstructionCodeGeneratorX86::HandleBitwiseOperation(HBinaryOperation* instr } } } else { - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt64); if (second.IsRegisterPair()) { if (instruction->IsAnd()) { __ andl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>()); @@ -7555,12 +7557,12 @@ void LocationsBuilderX86::VisitX86LoadFromConstantTable( } switch (insn->GetType()) { - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: locations->SetOut(Location::RequiresRegister()); break; @@ -7580,19 +7582,19 @@ void InstructionCodeGeneratorX86::VisitX86LoadFromConstantTable(HX86LoadFromCons HConstant *value = insn->GetConstant(); switch (insn->GetType()) { - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: __ movss(out.AsFpuRegister<XmmRegister>(), codegen_->LiteralFloatAddress( value->AsFloatConstant()->GetValue(), insn->GetBaseMethodAddress(), const_area)); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: __ movsd(out.AsFpuRegister<XmmRegister>(), codegen_->LiteralDoubleAddress( value->AsDoubleConstant()->GetValue(), insn->GetBaseMethodAddress(), const_area)); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ movl(out.AsRegister<Register>(), codegen_->LiteralInt32Address( value->AsIntConstant()->GetValue(), insn->GetBaseMethodAddress(), const_area)); @@ -7785,13 +7787,13 @@ Address CodeGeneratorX86::LiteralCaseTable(HX86PackedSwitch* switch_instr, } // TODO: target as memory. -void CodeGeneratorX86::MoveFromReturnRegister(Location target, Primitive::Type type) { +void CodeGeneratorX86::MoveFromReturnRegister(Location target, DataType::Type type) { if (!target.IsValid()) { - DCHECK_EQ(type, Primitive::kPrimVoid); + DCHECK_EQ(type, DataType::Type::kVoid); return; } - DCHECK_NE(type, Primitive::kPrimVoid); + DCHECK_NE(type, DataType::Type::kVoid); Location return_loc = InvokeDexCallingConventionVisitorX86().GetReturnLocation(type); if (target.Equals(return_loc)) { @@ -7800,10 +7802,10 @@ void CodeGeneratorX86::MoveFromReturnRegister(Location target, Primitive::Type t // TODO: Consider pairs in the parallel move resolver, then this could be nicely merged // with the else branch. - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { HParallelMove parallel_move(GetGraph()->GetArena()); - parallel_move.AddMove(return_loc.ToLow(), target.ToLow(), Primitive::kPrimInt, nullptr); - parallel_move.AddMove(return_loc.ToHigh(), target.ToHigh(), Primitive::kPrimInt, nullptr); + parallel_move.AddMove(return_loc.ToLow(), target.ToLow(), DataType::Type::kInt32, nullptr); + parallel_move.AddMove(return_loc.ToHigh(), target.ToHigh(), DataType::Type::kInt32, nullptr); GetMoveResolver()->EmitNativeCode(¶llel_move); } else { // Let the parallel move resolver take care of all of this. diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index b32d57a774..fb61e75d73 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -83,8 +83,8 @@ class InvokeDexCallingConventionVisitorX86 : public InvokeDexCallingConventionVi InvokeDexCallingConventionVisitorX86() {} virtual ~InvokeDexCallingConventionVisitorX86() {} - Location GetNextLocation(Primitive::Type type) OVERRIDE; - Location GetReturnLocation(Primitive::Type type) const OVERRIDE; + Location GetNextLocation(DataType::Type type) OVERRIDE; + Location GetReturnLocation(DataType::Type type) const OVERRIDE; Location GetMethodLocation() const OVERRIDE; private: @@ -103,13 +103,13 @@ class FieldAccessCallingConventionX86 : public FieldAccessCallingConvention { Location GetFieldIndexLocation() const OVERRIDE { return Location::RegisterLocation(EAX); } - Location GetReturnLocation(Primitive::Type type) const OVERRIDE { - return Primitive::Is64BitType(type) + Location GetReturnLocation(DataType::Type type) const OVERRIDE { + return DataType::Is64BitType(type) ? Location::RegisterPairLocation(EAX, EDX) : Location::RegisterLocation(EAX); } - Location GetSetValueLocation(Primitive::Type type, bool is_instance) const OVERRIDE { - return Primitive::Is64BitType(type) + Location GetSetValueLocation(DataType::Type type, bool is_instance) const OVERRIDE { + return DataType::Is64BitType(type) ? (is_instance ? Location::RegisterPairLocation(EDX, EBX) : Location::RegisterPairLocation(ECX, EDX)) @@ -117,7 +117,7 @@ class FieldAccessCallingConventionX86 : public FieldAccessCallingConvention { ? Location::RegisterLocation(EDX) : Location::RegisterLocation(ECX)); } - Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { + Location GetFpuLocation(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return Location::FpuRegisterLocation(XMM0); } @@ -321,7 +321,7 @@ class CodeGeneratorX86 : public CodeGenerator { void GenerateFrameExit() OVERRIDE; void Bind(HBasicBlock* block) OVERRIDE; void MoveConstant(Location destination, int32_t value) OVERRIDE; - void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; + void MoveLocation(Location dst, Location src, DataType::Type dst_type) OVERRIDE; void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; @@ -428,10 +428,10 @@ class CodeGeneratorX86 : public CodeGenerator { dex::TypeIndex dex_index, Handle<mirror::Class> handle); - void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE; + void MoveFromReturnRegister(Location trg, DataType::Type type) OVERRIDE; // Emit linker patches. - void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; + void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) OVERRIDE; void PatchJitRootUse(uint8_t* code, const uint8_t* roots_data, @@ -456,8 +456,8 @@ class CodeGeneratorX86 : public CodeGenerator { block_labels_ = CommonInitializeLabels<Label>(); } - bool NeedsTwoRegisters(Primitive::Type type) const OVERRIDE { - return type == Primitive::kPrimLong; + bool NeedsTwoRegisters(DataType::Type type) const OVERRIDE { + return type == DataType::Type::kInt64; } bool ShouldSplitLongMoves() const OVERRIDE { return true; } @@ -617,9 +617,9 @@ class CodeGeneratorX86 : public CodeGenerator { HX86ComputeBaseMethodAddress* method_address; }; - template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> + template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> void EmitPcRelativeLinkerPatches(const ArenaDeque<X86PcRelativePatchInfo>& infos, - ArenaVector<LinkerPatch>* linker_patches); + ArenaVector<linker::LinkerPatch>* linker_patches); Register GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke, Register temp); diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 39a65806a4..42704e9fe1 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -25,6 +25,7 @@ #include "heap_poisoning.h" #include "intrinsics.h" #include "intrinsics_x86_64.h" +#include "linker/linker_patch.h" #include "lock_word.h" #include "mirror/array-inl.h" #include "mirror/class-inl.h" @@ -105,12 +106,12 @@ class DivZeroCheckSlowPathX86_64 : public SlowPathCode { class DivRemMinusOneSlowPathX86_64 : public SlowPathCode { public: - DivRemMinusOneSlowPathX86_64(HInstruction* at, Register reg, Primitive::Type type, bool is_div) + DivRemMinusOneSlowPathX86_64(HInstruction* at, Register reg, DataType::Type type, bool is_div) : SlowPathCode(at), cpu_reg_(CpuRegister(reg)), type_(type), is_div_(is_div) {} void EmitNativeCode(CodeGenerator* codegen) OVERRIDE { __ Bind(GetEntryLabel()); - if (type_ == Primitive::kPrimInt) { + if (type_ == DataType::Type::kInt32) { if (is_div_) { __ negl(cpu_reg_); } else { @@ -118,7 +119,7 @@ class DivRemMinusOneSlowPathX86_64 : public SlowPathCode { } } else { - DCHECK_EQ(Primitive::kPrimLong, type_); + DCHECK_EQ(DataType::Type::kInt64, type_); if (is_div_) { __ negq(cpu_reg_); } else { @@ -132,7 +133,7 @@ class DivRemMinusOneSlowPathX86_64 : public SlowPathCode { private: const CpuRegister cpu_reg_; - const Primitive::Type type_; + const DataType::Type type_; const bool is_div_; DISALLOW_COPY_AND_ASSIGN(DivRemMinusOneSlowPathX86_64); }; @@ -214,10 +215,10 @@ class BoundsCheckSlowPathX86_64 : public SlowPathCode { codegen->EmitParallelMoves( locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimInt, + DataType::Type::kInt32, length_loc, Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt); + DataType::Type::kInt32); QuickEntrypointEnum entrypoint = instruction_->AsBoundsCheck()->IsStringCharAt() ? kQuickThrowStringBounds : kQuickThrowArrayBounds; @@ -359,10 +360,10 @@ class TypeCheckSlowPathX86_64 : public SlowPathCode { InvokeRuntimeCallingConvention calling_convention; codegen->EmitParallelMoves(locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, locations->InAt(1), Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot); + DataType::Type::kReference); if (instruction_->IsInstanceOf()) { x86_64_codegen->InvokeRuntime(kQuickInstanceofNonTrivial, instruction_, dex_pc, this); CheckEntrypointTypes<kQuickInstanceofNonTrivial, size_t, mirror::Object*, mirror::Class*>(); @@ -430,17 +431,17 @@ class ArraySetSlowPathX86_64 : public SlowPathCode { parallel_move.AddMove( locations->InAt(0), Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove( locations->InAt(1), Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); parallel_move.AddMove( locations->InAt(2), Location::RegisterLocation(calling_convention.GetRegisterAt(2)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); @@ -833,16 +834,16 @@ class ReadBarrierForHeapReferenceSlowPathX86_64 : public SlowPathCode { HParallelMove parallel_move(codegen->GetGraph()->GetArena()); parallel_move.AddMove(ref_, Location::RegisterLocation(calling_convention.GetRegisterAt(0)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); parallel_move.AddMove(obj_, Location::RegisterLocation(calling_convention.GetRegisterAt(1)), - Primitive::kPrimNot, + DataType::Type::kReference, nullptr); if (index.IsValid()) { parallel_move.AddMove(index, Location::RegisterLocation(calling_convention.GetRegisterAt(2)), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); } else { @@ -1106,10 +1107,10 @@ Label* CodeGeneratorX86_64::NewStringBssEntryPatch(HLoadString* load_string) { // for method patch needs to point to the embedded constant which occupies the last 4 bytes. constexpr uint32_t kLabelPositionToLiteralOffsetAdjustment = 4u; -template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> +template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> inline void CodeGeneratorX86_64::EmitPcRelativeLinkerPatches( const ArenaDeque<PatchInfo<Label>>& infos, - ArenaVector<LinkerPatch>* linker_patches) { + ArenaVector<linker::LinkerPatch>* linker_patches) { for (const PatchInfo<Label>& info : infos) { uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment; linker_patches->push_back( @@ -1117,7 +1118,7 @@ inline void CodeGeneratorX86_64::EmitPcRelativeLinkerPatches( } } -void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) { +void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) { DCHECK(linker_patches->empty()); size_t size = boot_image_method_patches_.size() + @@ -1128,24 +1129,25 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_pat string_bss_entry_patches_.size(); linker_patches->reserve(size); if (GetCompilerOptions().IsBootImage()) { - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeMethodPatch>(boot_image_method_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeTypePatch>(boot_image_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::RelativeStringPatch>(string_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>( + boot_image_method_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>( + boot_image_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>( + string_patches_, linker_patches); } else { DCHECK(boot_image_method_patches_.empty()); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(boot_image_type_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(string_patches_, - linker_patches); - } - EmitPcRelativeLinkerPatches<LinkerPatch::MethodBssEntryPatch>(method_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::TypeBssEntryPatch>(type_bss_entry_patches_, - linker_patches); - EmitPcRelativeLinkerPatches<LinkerPatch::StringBssEntryPatch>(string_bss_entry_patches_, - linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>( + boot_image_type_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>( + string_patches_, linker_patches); + } + EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( + method_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>( + type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>( + string_bss_entry_patches_, linker_patches); DCHECK_EQ(size, linker_patches->size()); } @@ -1441,7 +1443,7 @@ void CodeGeneratorX86_64::MoveConstant(Location location, int32_t value) { } void CodeGeneratorX86_64::MoveLocation( - Location dst, Location src, Primitive::Type dst_type ATTRIBUTE_UNUSED) { + Location dst, Location src, DataType::Type dst_type ATTRIBUTE_UNUSED) { Move(dst, src); } @@ -1516,22 +1518,22 @@ void InstructionCodeGeneratorX86_64::GenerateCompareTest(HCondition* condition) Location left = locations->InAt(0); Location right = locations->InAt(1); - Primitive::Type type = condition->InputAt(0)->GetType(); + DataType::Type type = condition->InputAt(0)->GetType(); switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: { codegen_->GenerateIntCompare(left, right); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { codegen_->GenerateLongCompare(left, right); break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (right.IsFpuRegister()) { __ ucomiss(left.AsFpuRegister<XmmRegister>(), right.AsFpuRegister<XmmRegister>()); } else if (right.IsConstant()) { @@ -1545,7 +1547,7 @@ void InstructionCodeGeneratorX86_64::GenerateCompareTest(HCondition* condition) } break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (right.IsFpuRegister()) { __ ucomisd(left.AsFpuRegister<XmmRegister>(), right.AsFpuRegister<XmmRegister>()); } else if (right.IsConstant()) { @@ -1578,17 +1580,17 @@ void InstructionCodeGeneratorX86_64::GenerateCompareTestAndBranch(HCondition* co GenerateCompareTest(condition); // Now generate the correct jump(s). - Primitive::Type type = condition->InputAt(0)->GetType(); + DataType::Type type = condition->InputAt(0)->GetType(); switch (type) { - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { __ j(X86_64IntegerCondition(condition->GetCondition()), true_target); break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { GenerateFPJumps(condition, true_target, false_target); break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { GenerateFPJumps(condition, true_target, false_target); break; } @@ -1611,7 +1613,7 @@ static bool AreEflagsSetFrom(HInstruction* cond, HInstruction* branch) { // conditions if they are materialized due to the complex branching. return cond->IsCondition() && cond->GetNext() == branch && - !Primitive::IsFloatingPointType(cond->InputAt(0)->GetType()); + !DataType::IsFloatingPointType(cond->InputAt(0)->GetType()); } template<class LabelType> @@ -1675,8 +1677,8 @@ void InstructionCodeGeneratorX86_64::GenerateTestAndBranch(HInstruction* instruc // If this is a long or FP comparison that has been folded into // the HCondition, generate the comparison directly. - Primitive::Type type = condition->InputAt(0)->GetType(); - if (type == Primitive::kPrimLong || Primitive::IsFloatingPointType(type)) { + DataType::Type type = condition->InputAt(0)->GetType(); + if (type == DataType::Type::kInt64 || DataType::IsFloatingPointType(type)) { GenerateCompareTestAndBranch(condition, true_target, false_target); return; } @@ -1748,14 +1750,14 @@ void InstructionCodeGeneratorX86_64::VisitShouldDeoptimizeFlag(HShouldDeoptimize static bool SelectCanUseCMOV(HSelect* select) { // There are no conditional move instructions for XMMs. - if (Primitive::IsFloatingPointType(select->GetType())) { + if (DataType::IsFloatingPointType(select->GetType())) { return false; } // A FP condition doesn't generate the single CC that we need. HInstruction* condition = select->GetCondition(); if (condition->IsCondition() && - Primitive::IsFloatingPointType(condition->InputAt(0)->GetType())) { + DataType::IsFloatingPointType(condition->InputAt(0)->GetType())) { return false; } @@ -1765,7 +1767,7 @@ static bool SelectCanUseCMOV(HSelect* select) { void LocationsBuilderX86_64::VisitSelect(HSelect* select) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(select); - if (Primitive::IsFloatingPointType(select->GetType())) { + if (DataType::IsFloatingPointType(select->GetType())) { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::Any()); } else { @@ -1824,7 +1826,7 @@ void InstructionCodeGeneratorX86_64::VisitSelect(HSelect* select) { // If the condition is true, overwrite the output, which already contains false. // Generate the correct sized CMOV. - bool is_64_bit = Primitive::Is64BitType(select->GetType()); + bool is_64_bit = DataType::Is64BitType(select->GetType()); if (value_true_loc.IsRegister()) { __ cmov(cond, value_false, value_true_loc.AsRegister<CpuRegister>(), is_64_bit); } else { @@ -1860,12 +1862,12 @@ void LocationsBuilderX86_64::HandleCondition(HCondition* cond) { new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall); // Handle the long/FP comparisons made in instruction simplification. switch (cond->InputAt(0)->GetType()) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::Any()); break; @@ -1900,14 +1902,14 @@ void InstructionCodeGeneratorX86_64::HandleCondition(HCondition* cond) { codegen_->GenerateIntCompare(lhs, rhs); __ setcc(X86_64IntegerCondition(cond->GetCondition()), reg); return; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Clear output register: setcc only sets the low byte. __ xorl(reg, reg); codegen_->GenerateLongCompare(lhs, rhs); __ setcc(X86_64IntegerCondition(cond->GetCondition()), reg); return; - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { XmmRegister lhs_reg = lhs.AsFpuRegister<XmmRegister>(); if (rhs.IsConstant()) { float value = rhs.GetConstant()->AsFloatConstant()->GetValue(); @@ -1920,7 +1922,7 @@ void InstructionCodeGeneratorX86_64::HandleCondition(HCondition* cond) { GenerateFPJumps(cond, &true_label, &false_label); break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { XmmRegister lhs_reg = lhs.AsFpuRegister<XmmRegister>(); if (rhs.IsConstant()) { double value = rhs.GetConstant()->AsDoubleConstant()->GetValue(); @@ -2033,19 +2035,19 @@ void LocationsBuilderX86_64::VisitCompare(HCompare* compare) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall); switch (compare->InputAt(0)->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::RequiresRegister()); @@ -2063,23 +2065,23 @@ void InstructionCodeGeneratorX86_64::VisitCompare(HCompare* compare) { Location right = locations->InAt(1); NearLabel less, greater, done; - Primitive::Type type = compare->InputAt(0)->GetType(); + DataType::Type type = compare->InputAt(0)->GetType(); Condition less_cond = kLess; switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: { codegen_->GenerateIntCompare(left, right); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { codegen_->GenerateLongCompare(left, right); break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { XmmRegister left_reg = left.AsFpuRegister<XmmRegister>(); if (right.IsConstant()) { float value = right.GetConstant()->AsFloatConstant()->GetValue(); @@ -2093,7 +2095,7 @@ void InstructionCodeGeneratorX86_64::VisitCompare(HCompare* compare) { less_cond = kBelow; // ucomis{s,d} sets CF break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { XmmRegister left_reg = left.AsFpuRegister<XmmRegister>(); if (right.IsConstant()) { double value = right.GetConstant()->AsDoubleConstant()->GetValue(); @@ -2205,18 +2207,18 @@ void LocationsBuilderX86_64::VisitReturn(HReturn* ret) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret, LocationSummary::kNoCall); switch (ret->InputAt(0)->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RegisterLocation(RAX)); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::FpuRegisterLocation(XMM0)); break; @@ -2228,18 +2230,18 @@ void LocationsBuilderX86_64::VisitReturn(HReturn* ret) { void InstructionCodeGeneratorX86_64::VisitReturn(HReturn* ret) { if (kIsDebugBuild) { switch (ret->InputAt(0)->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: + case DataType::Type::kInt64: DCHECK_EQ(ret->GetLocations()->InAt(0).AsRegister<CpuRegister>().AsRegister(), RAX); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: DCHECK_EQ(ret->GetLocations()->InAt(0).AsFpuRegister<XmmRegister>().AsFloatRegister(), XMM0); break; @@ -2251,22 +2253,22 @@ void InstructionCodeGeneratorX86_64::VisitReturn(HReturn* ret) { codegen_->GenerateFrameExit(); } -Location InvokeDexCallingConventionVisitorX86_64::GetReturnLocation(Primitive::Type type) const { +Location InvokeDexCallingConventionVisitorX86_64::GetReturnLocation(DataType::Type type) const { switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: + case DataType::Type::kInt64: return Location::RegisterLocation(RAX); - case Primitive::kPrimVoid: + case DataType::Type::kVoid: return Location::NoLocation(); - case Primitive::kPrimDouble: - case Primitive::kPrimFloat: + case DataType::Type::kFloat64: + case DataType::Type::kFloat32: return Location::FpuRegisterLocation(XMM0); } @@ -2277,14 +2279,14 @@ Location InvokeDexCallingConventionVisitorX86_64::GetMethodLocation() const { return Location::RegisterLocation(kMethodRegisterArgument); } -Location InvokeDexCallingConventionVisitorX86_64::GetNextLocation(Primitive::Type type) { +Location InvokeDexCallingConventionVisitorX86_64::GetNextLocation(DataType::Type type) { switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kReference: { uint32_t index = gp_index_++; stack_index_++; if (index < calling_convention.GetNumberOfRegisters()) { @@ -2294,7 +2296,7 @@ Location InvokeDexCallingConventionVisitorX86_64::GetNextLocation(Primitive::Typ } } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { uint32_t index = gp_index_; stack_index_ += 2; if (index < calling_convention.GetNumberOfRegisters()) { @@ -2306,7 +2308,7 @@ Location InvokeDexCallingConventionVisitorX86_64::GetNextLocation(Primitive::Typ } } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { uint32_t index = float_index_++; stack_index_++; if (index < calling_convention.GetNumberOfFpuRegisters()) { @@ -2316,7 +2318,7 @@ Location InvokeDexCallingConventionVisitorX86_64::GetNextLocation(Primitive::Typ } } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { uint32_t index = float_index_++; stack_index_ += 2; if (index < calling_convention.GetNumberOfFpuRegisters()) { @@ -2326,7 +2328,7 @@ Location InvokeDexCallingConventionVisitorX86_64::GetNextLocation(Primitive::Typ } } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unexpected parameter type " << type; break; } @@ -2467,14 +2469,14 @@ void LocationsBuilderX86_64::VisitNeg(HNeg* neg) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); switch (neg->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::SameAsFirstInput()); break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::SameAsFirstInput()); locations->AddTemp(Location::RequiresFpuRegister()); @@ -2490,19 +2492,19 @@ void InstructionCodeGeneratorX86_64::VisitNeg(HNeg* neg) { Location out = locations->Out(); Location in = locations->InAt(0); switch (neg->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: DCHECK(in.IsRegister()); DCHECK(in.Equals(out)); __ negl(out.AsRegister<CpuRegister>()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: DCHECK(in.IsRegister()); DCHECK(in.Equals(out)); __ negq(out.AsRegister<CpuRegister>()); break; - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { DCHECK(in.Equals(out)); XmmRegister mask = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); // Implement float negation with an exclusive or with value @@ -2513,7 +2515,7 @@ void InstructionCodeGeneratorX86_64::VisitNeg(HNeg* neg) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { DCHECK(in.Equals(out)); XmmRegister mask = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); // Implement double negation with an exclusive or with value @@ -2532,23 +2534,23 @@ void InstructionCodeGeneratorX86_64::VisitNeg(HNeg* neg) { void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(conversion, LocationSummary::kNoCall); - Primitive::Type result_type = conversion->GetResultType(); - Primitive::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); DCHECK_NE(result_type, input_type); // The Java language does not allow treating boolean as an integral type but // our bit representation makes it safe. switch (result_type) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to byte is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-byte' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -2560,15 +2562,15 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to short is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-short' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -2580,21 +2582,21 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-int' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-int' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-int' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); @@ -2606,14 +2608,14 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-long' instruction. // TODO: We would benefit from a (to-be-implemented) // Location::RegisterOrStackSlot requirement for this input. @@ -2621,13 +2623,13 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { locations->SetOut(Location::RequiresRegister()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-long' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-long' instruction. locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetOut(Location::RequiresRegister()); @@ -2639,15 +2641,15 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to char is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: // Processing a Dex `int-to-char' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); @@ -2659,26 +2661,26 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-float' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-float' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-float' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -2690,26 +2692,26 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { }; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-double' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-double' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresFpuRegister()); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-double' instruction. locations->SetInAt(0, Location::Any()); locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); @@ -2731,19 +2733,19 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver LocationSummary* locations = conversion->GetLocations(); Location out = locations->Out(); Location in = locations->InAt(0); - Primitive::Type result_type = conversion->GetResultType(); - Primitive::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); DCHECK_NE(result_type, input_type); switch (result_type) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to byte is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-byte' instruction. if (in.IsRegister()) { __ movsxb(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>()); @@ -2762,15 +2764,15 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to short is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-short' instruction. if (in.IsRegister()) { __ movsxw(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>()); @@ -2789,9 +2791,9 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-int' instruction. if (in.IsRegister()) { __ movl(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>()); @@ -2806,7 +2808,7 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { // Processing a Dex `float-to-int' instruction. XmmRegister input = in.AsFpuRegister<XmmRegister>(); CpuRegister output = out.AsRegister<CpuRegister>(); @@ -2828,7 +2830,7 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { // Processing a Dex `double-to-int' instruction. XmmRegister input = in.AsFpuRegister<XmmRegister>(); CpuRegister output = out.AsRegister<CpuRegister>(); @@ -2856,21 +2858,21 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: switch (input_type) { DCHECK(out.IsRegister()); - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-long' instruction. DCHECK(in.IsRegister()); __ movsxd(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>()); break; - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { // Processing a Dex `float-to-long' instruction. XmmRegister input = in.AsFpuRegister<XmmRegister>(); CpuRegister output = out.AsRegister<CpuRegister>(); @@ -2892,7 +2894,7 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { // Processing a Dex `double-to-long' instruction. XmmRegister input = in.AsFpuRegister<XmmRegister>(); CpuRegister output = out.AsRegister<CpuRegister>(); @@ -2920,15 +2922,15 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Type conversion from long to char is a result of code transformations. - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: // Processing a Dex `int-to-char' instruction. if (in.IsRegister()) { __ movzxw(out.AsRegister<CpuRegister>(), in.AsRegister<CpuRegister>()); @@ -2947,14 +2949,14 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-float' instruction. if (in.IsRegister()) { __ cvtsi2ss(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), false); @@ -2968,7 +2970,7 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-float' instruction. if (in.IsRegister()) { __ cvtsi2ss(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), true); @@ -2982,7 +2984,7 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: // Processing a Dex `double-to-float' instruction. if (in.IsFpuRegister()) { __ cvtsd2ss(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>()); @@ -3002,14 +3004,14 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver }; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: switch (input_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: // Boolean input is a result of code transformations. - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimChar: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + case DataType::Type::kUint16: // Processing a Dex `int-to-double' instruction. if (in.IsRegister()) { __ cvtsi2sd(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), false); @@ -3023,7 +3025,7 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // Processing a Dex `long-to-double' instruction. if (in.IsRegister()) { __ cvtsi2sd(out.AsFpuRegister<XmmRegister>(), in.AsRegister<CpuRegister>(), true); @@ -3037,7 +3039,7 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: // Processing a Dex `float-to-double' instruction. if (in.IsFpuRegister()) { __ cvtss2sd(out.AsFpuRegister<XmmRegister>(), in.AsFpuRegister<XmmRegister>()); @@ -3067,14 +3069,14 @@ void LocationsBuilderX86_64::VisitAdd(HAdd* add) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall); switch (add->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(add->InputAt(1))); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); // We can use a leaq or addq if the constant can fit in an immediate. locations->SetInAt(1, Location::RegisterOrInt32Constant(add->InputAt(1))); @@ -3082,8 +3084,8 @@ void LocationsBuilderX86_64::VisitAdd(HAdd* add) { break; } - case Primitive::kPrimDouble: - case Primitive::kPrimFloat: { + case DataType::Type::kFloat64: + case DataType::Type::kFloat32: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::SameAsFirstInput()); @@ -3102,7 +3104,7 @@ void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) { Location out = locations->Out(); switch (add->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { if (second.IsRegister()) { if (out.AsRegister<Register>() == first.AsRegister<Register>()) { __ addl(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>()); @@ -3127,7 +3129,7 @@ void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (second.IsRegister()) { if (out.AsRegister<Register>() == first.AsRegister<Register>()) { __ addq(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>()); @@ -3152,7 +3154,7 @@ void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (second.IsFpuRegister()) { __ addss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (second.IsConstant()) { @@ -3167,7 +3169,7 @@ void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (second.IsFpuRegister()) { __ addsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (second.IsConstant()) { @@ -3191,20 +3193,20 @@ void LocationsBuilderX86_64::VisitSub(HSub* sub) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub, LocationSummary::kNoCall); switch (sub->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::SameAsFirstInput()); break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrInt32Constant(sub->InputAt(1))); locations->SetOut(Location::SameAsFirstInput()); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::SameAsFirstInput()); @@ -3221,7 +3223,7 @@ void InstructionCodeGeneratorX86_64::VisitSub(HSub* sub) { Location second = locations->InAt(1); DCHECK(first.Equals(locations->Out())); switch (sub->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { if (second.IsRegister()) { __ subl(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>()); } else if (second.IsConstant()) { @@ -3232,7 +3234,7 @@ void InstructionCodeGeneratorX86_64::VisitSub(HSub* sub) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (second.IsConstant()) { int64_t value = second.GetConstant()->AsLongConstant()->GetValue(); DCHECK(IsInt<32>(value)); @@ -3243,7 +3245,7 @@ void InstructionCodeGeneratorX86_64::VisitSub(HSub* sub) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (second.IsFpuRegister()) { __ subss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (second.IsConstant()) { @@ -3258,7 +3260,7 @@ void InstructionCodeGeneratorX86_64::VisitSub(HSub* sub) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (second.IsFpuRegister()) { __ subsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (second.IsConstant()) { @@ -3282,7 +3284,7 @@ void LocationsBuilderX86_64::VisitMul(HMul* mul) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(mul, LocationSummary::kNoCall); switch (mul->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); if (mul->InputAt(1)->IsIntConstant()) { @@ -3293,7 +3295,7 @@ void LocationsBuilderX86_64::VisitMul(HMul* mul) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); if (mul->InputAt(1)->IsLongConstant() && @@ -3305,8 +3307,8 @@ void LocationsBuilderX86_64::VisitMul(HMul* mul) { } break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::SameAsFirstInput()); @@ -3324,7 +3326,7 @@ void InstructionCodeGeneratorX86_64::VisitMul(HMul* mul) { Location second = locations->InAt(1); Location out = locations->Out(); switch (mul->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: // The constant may have ended up in a register, so test explicitly to avoid // problems where the output may not be the same as the first operand. if (mul->InputAt(1)->IsIntConstant()) { @@ -3340,7 +3342,7 @@ void InstructionCodeGeneratorX86_64::VisitMul(HMul* mul) { Address(CpuRegister(RSP), second.GetStackIndex())); } break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { // The constant may have ended up in a register, so test explicitly to avoid // problems where the output may not be the same as the first operand. if (mul->InputAt(1)->IsLongConstant()) { @@ -3365,7 +3367,7 @@ void InstructionCodeGeneratorX86_64::VisitMul(HMul* mul) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { DCHECK(first.Equals(out)); if (second.IsFpuRegister()) { __ mulss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); @@ -3381,7 +3383,7 @@ void InstructionCodeGeneratorX86_64::VisitMul(HMul* mul) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { DCHECK(first.Equals(out)); if (second.IsFpuRegister()) { __ mulsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); @@ -3425,9 +3427,9 @@ void InstructionCodeGeneratorX86_64::PushOntoFPStack(Location source, uint32_t t } void InstructionCodeGeneratorX86_64::GenerateRemFP(HRem *rem) { - Primitive::Type type = rem->GetResultType(); - bool is_float = type == Primitive::kPrimFloat; - size_t elem_size = Primitive::ComponentSize(type); + DataType::Type type = rem->GetResultType(); + bool is_float = type == DataType::Type::kFloat32; + size_t elem_size = DataType::Size(type); LocationSummary* locations = rem->GetLocations(); Location first = locations->InAt(0); Location second = locations->InAt(1); @@ -3491,7 +3493,7 @@ void InstructionCodeGeneratorX86_64::DivRemOneOrMinusOne(HBinaryOperation* instr DCHECK(imm == 1 || imm == -1); switch (instruction->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { if (instruction->IsRem()) { __ xorl(output_register, output_register); } else { @@ -3503,7 +3505,7 @@ void InstructionCodeGeneratorX86_64::DivRemOneOrMinusOne(HBinaryOperation* instr break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (instruction->IsRem()) { __ xorl(output_register, output_register); } else { @@ -3533,7 +3535,7 @@ void InstructionCodeGeneratorX86_64::DivByPowerOfTwo(HDiv* instruction) { CpuRegister tmp = locations->GetTemp(0).AsRegister<CpuRegister>(); - if (instruction->GetResultType() == Primitive::kPrimInt) { + if (instruction->GetResultType() == DataType::Type::kInt32) { __ leal(tmp, Address(numerator, abs_imm - 1)); __ testl(numerator, numerator); __ cmov(kGreaterEqual, tmp, numerator); @@ -3546,7 +3548,7 @@ void InstructionCodeGeneratorX86_64::DivByPowerOfTwo(HDiv* instruction) { __ movl(output_register, tmp); } else { - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt64); CpuRegister rdx = locations->GetTemp(0).AsRegister<CpuRegister>(); codegen_->Load64BitValue(rdx, abs_imm - 1); @@ -3589,7 +3591,7 @@ void InstructionCodeGeneratorX86_64::GenerateDivRemWithAnyConstant(HBinaryOperat int shift; // TODO: can these branches be written as one? - if (instruction->GetResultType() == Primitive::kPrimInt) { + if (instruction->GetResultType() == DataType::Type::kInt32) { int imm = second.GetConstant()->AsIntConstant()->GetValue(); CalculateMagicAndShiftForDivRem(imm, false /* is_long */, &magic, &shift); @@ -3624,7 +3626,7 @@ void InstructionCodeGeneratorX86_64::GenerateDivRemWithAnyConstant(HBinaryOperat } else { int64_t imm = second.GetConstant()->AsLongConstant()->GetValue(); - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt64); CpuRegister rax = eax; CpuRegister rdx = edx; @@ -3677,8 +3679,8 @@ void InstructionCodeGeneratorX86_64::GenerateDivRemWithAnyConstant(HBinaryOperat void InstructionCodeGeneratorX86_64::GenerateDivRemIntegral(HBinaryOperation* instruction) { DCHECK(instruction->IsDiv() || instruction->IsRem()); - Primitive::Type type = instruction->GetResultType(); - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DataType::Type type = instruction->GetResultType(); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); bool is_div = instruction->IsDiv(); LocationSummary* locations = instruction->GetLocations(); @@ -3712,7 +3714,7 @@ void InstructionCodeGeneratorX86_64::GenerateDivRemIntegral(HBinaryOperation* in // 0x80000000(00000000)/-1 triggers an arithmetic exception! // Dividing by -1 is actually negation and -0x800000000(00000000) = 0x80000000(00000000) // so it's safe to just use negl instead of more complex comparisons. - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { __ cmpl(second_reg, Immediate(-1)); __ j(kEqual, slow_path->GetEntryLabel()); // edx:eax <- sign-extended of eax @@ -3735,8 +3737,8 @@ void LocationsBuilderX86_64::VisitDiv(HDiv* div) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall); switch (div->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RegisterLocation(RAX)); locations->SetInAt(1, Location::RegisterOrConstant(div->InputAt(1))); locations->SetOut(Location::SameAsFirstInput()); @@ -3751,8 +3753,8 @@ void LocationsBuilderX86_64::VisitDiv(HDiv* div) { break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::RequiresFpuRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::SameAsFirstInput()); @@ -3770,15 +3772,15 @@ void InstructionCodeGeneratorX86_64::VisitDiv(HDiv* div) { Location second = locations->InAt(1); DCHECK(first.Equals(locations->Out())); - Primitive::Type type = div->GetResultType(); + DataType::Type type = div->GetResultType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GenerateDivRemIntegral(div); break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (second.IsFpuRegister()) { __ divss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (second.IsConstant()) { @@ -3793,7 +3795,7 @@ void InstructionCodeGeneratorX86_64::VisitDiv(HDiv* div) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (second.IsFpuRegister()) { __ divsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>()); } else if (second.IsConstant()) { @@ -3814,13 +3816,13 @@ void InstructionCodeGeneratorX86_64::VisitDiv(HDiv* div) { } void LocationsBuilderX86_64::VisitRem(HRem* rem) { - Primitive::Type type = rem->GetResultType(); + DataType::Type type = rem->GetResultType(); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, LocationSummary::kNoCall); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RegisterLocation(RAX)); locations->SetInAt(1, Location::RegisterOrConstant(rem->InputAt(1))); // Intel uses rdx:rax as the dividend and puts the remainder in rdx @@ -3834,8 +3836,8 @@ void LocationsBuilderX86_64::VisitRem(HRem* rem) { break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { locations->SetInAt(0, Location::Any()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::RequiresFpuRegister()); @@ -3849,15 +3851,15 @@ void LocationsBuilderX86_64::VisitRem(HRem* rem) { } void InstructionCodeGeneratorX86_64::VisitRem(HRem* rem) { - Primitive::Type type = rem->GetResultType(); + DataType::Type type = rem->GetResultType(); switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { GenerateDivRemIntegral(rem); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: { + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: { GenerateRemFP(rem); break; } @@ -3880,11 +3882,11 @@ void InstructionCodeGeneratorX86_64::VisitDivZeroCheck(HDivZeroCheck* instructio Location value = locations->InAt(0); switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: { if (value.IsRegister()) { __ testl(value.AsRegister<CpuRegister>(), value.AsRegister<CpuRegister>()); __ j(kEqual, slow_path->GetEntryLabel()); @@ -3899,7 +3901,7 @@ void InstructionCodeGeneratorX86_64::VisitDivZeroCheck(HDivZeroCheck* instructio } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (value.IsRegister()) { __ testq(value.AsRegister<CpuRegister>(), value.AsRegister<CpuRegister>()); __ j(kEqual, slow_path->GetEntryLabel()); @@ -3926,8 +3928,8 @@ void LocationsBuilderX86_64::HandleShift(HBinaryOperation* op) { new (GetGraph()->GetArena()) LocationSummary(op, LocationSummary::kNoCall); switch (op->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); // The shift count needs to be in CL. locations->SetInAt(1, Location::ByteRegisterOrConstant(RCX, op->InputAt(1))); @@ -3947,7 +3949,7 @@ void InstructionCodeGeneratorX86_64::HandleShift(HBinaryOperation* op) { Location second = locations->InAt(1); switch (op->GetResultType()) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { if (second.IsRegister()) { CpuRegister second_reg = second.AsRegister<CpuRegister>(); if (op->IsShl()) { @@ -3969,7 +3971,7 @@ void InstructionCodeGeneratorX86_64::HandleShift(HBinaryOperation* op) { } break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (second.IsRegister()) { CpuRegister second_reg = second.AsRegister<CpuRegister>(); if (op->IsShl()) { @@ -4002,8 +4004,8 @@ void LocationsBuilderX86_64::VisitRor(HRor* ror) { new (GetGraph()->GetArena()) LocationSummary(ror, LocationSummary::kNoCall); switch (ror->GetResultType()) { - case Primitive::kPrimInt: - case Primitive::kPrimLong: { + case DataType::Type::kInt32: + case DataType::Type::kInt64: { locations->SetInAt(0, Location::RequiresRegister()); // The shift count needs to be in CL (unless it is a constant). locations->SetInAt(1, Location::ByteRegisterOrConstant(RCX, ror->InputAt(1))); @@ -4022,7 +4024,7 @@ void InstructionCodeGeneratorX86_64::VisitRor(HRor* ror) { Location second = locations->InAt(1); switch (ror->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: if (second.IsRegister()) { CpuRegister second_reg = second.AsRegister<CpuRegister>(); __ rorl(first_reg, second_reg); @@ -4031,7 +4033,7 @@ void InstructionCodeGeneratorX86_64::VisitRor(HRor* ror) { __ rorl(first_reg, imm); } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (second.IsRegister()) { CpuRegister second_reg = second.AsRegister<CpuRegister>(); __ rorq(first_reg, second_reg); @@ -4184,11 +4186,11 @@ void InstructionCodeGeneratorX86_64::VisitNot(HNot* not_) { locations->Out().AsRegister<CpuRegister>().AsRegister()); Location out = locations->Out(); switch (not_->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ notl(out.AsRegister<CpuRegister>()); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: __ notq(out.AsRegister<CpuRegister>()); break; @@ -4253,7 +4255,7 @@ void LocationsBuilderX86_64::HandleFieldGet(HInstruction* instruction) { DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet()); bool object_field_get_with_read_barrier = - kEmitCompilerReadBarrier && (instruction->GetType() == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (instruction->GetType() == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, object_field_get_with_read_barrier ? @@ -4263,7 +4265,7 @@ void LocationsBuilderX86_64::HandleFieldGet(HInstruction* instruction) { locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers. } locations->SetInAt(0, Location::RequiresRegister()); - if (Primitive::IsFloatingPointType(instruction->GetType())) { + if (DataType::IsFloatingPointType(instruction->GetType())) { locations->SetOut(Location::RequiresFpuRegister()); } else { // The output overlaps for an object field get when read barriers @@ -4284,36 +4286,36 @@ void InstructionCodeGeneratorX86_64::HandleFieldGet(HInstruction* instruction, CpuRegister base = base_loc.AsRegister<CpuRegister>(); Location out = locations->Out(); bool is_volatile = field_info.IsVolatile(); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); uint32_t offset = field_info.GetFieldOffset().Uint32Value(); switch (field_type) { - case Primitive::kPrimBoolean: { + case DataType::Type::kBool: { __ movzxb(out.AsRegister<CpuRegister>(), Address(base, offset)); break; } - case Primitive::kPrimByte: { + case DataType::Type::kInt8: { __ movsxb(out.AsRegister<CpuRegister>(), Address(base, offset)); break; } - case Primitive::kPrimShort: { + case DataType::Type::kInt16: { __ movsxw(out.AsRegister<CpuRegister>(), Address(base, offset)); break; } - case Primitive::kPrimChar: { + case DataType::Type::kUint16: { __ movzxw(out.AsRegister<CpuRegister>(), Address(base, offset)); break; } - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { __ movl(out.AsRegister<CpuRegister>(), Address(base, offset)); break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { // /* HeapReference<Object> */ out = *(base + offset) if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) { // Note that a potential implicit null check is handled in this @@ -4337,27 +4339,27 @@ void InstructionCodeGeneratorX86_64::HandleFieldGet(HInstruction* instruction, break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { __ movq(out.AsRegister<CpuRegister>(), Address(base, offset)); break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { __ movss(out.AsFpuRegister<XmmRegister>(), Address(base, offset)); break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { __ movsd(out.AsFpuRegister<XmmRegister>(), Address(base, offset)); break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); } - if (field_type == Primitive::kPrimNot) { + if (field_type == DataType::Type::kReference) { // Potential implicit null checks, in the case of reference // fields, are handled in the previous switch statement. } else { @@ -4365,7 +4367,7 @@ void InstructionCodeGeneratorX86_64::HandleFieldGet(HInstruction* instruction, } if (is_volatile) { - if (field_type == Primitive::kPrimNot) { + if (field_type == DataType::Type::kReference) { // Memory barriers, in the case of references, are also handled // in the previous switch statement. } else { @@ -4380,13 +4382,13 @@ void LocationsBuilderX86_64::HandleFieldSet(HInstruction* instruction, LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); bool is_volatile = field_info.IsVolatile(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1)); locations->SetInAt(0, Location::RequiresRegister()); - if (Primitive::IsFloatingPointType(instruction->InputAt(1)->GetType())) { + if (DataType::IsFloatingPointType(instruction->InputAt(1)->GetType())) { if (is_volatile) { // In order to satisfy the semantics of volatile, this must be a single instruction store. locations->SetInAt(1, Location::FpuRegisterOrInt32Constant(instruction->InputAt(1))); @@ -4405,7 +4407,7 @@ void LocationsBuilderX86_64::HandleFieldSet(HInstruction* instruction, // Temporary registers for the write barrier. locations->AddTemp(Location::RequiresRegister()); // Possibly used for reference poisoning too. locations->AddTemp(Location::RequiresRegister()); - } else if (kPoisonHeapReferences && field_type == Primitive::kPrimNot) { + } else if (kPoisonHeapReferences && field_type == DataType::Type::kReference) { // Temporary register for the reference poisoning. locations->AddTemp(Location::RequiresRegister()); } @@ -4420,7 +4422,7 @@ void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction, CpuRegister base = locations->InAt(0).AsRegister<CpuRegister>(); Location value = locations->InAt(1); bool is_volatile = field_info.IsVolatile(); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); uint32_t offset = field_info.GetFieldOffset().Uint32Value(); if (is_volatile) { @@ -4430,8 +4432,8 @@ void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction, bool maybe_record_implicit_null_check_done = false; switch (field_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: { + case DataType::Type::kBool: + case DataType::Type::kInt8: { if (value.IsConstant()) { __ movb(Address(base, offset), Immediate(CodeGenerator::GetInt8ValueOf(value.GetConstant()))); @@ -4441,8 +4443,8 @@ void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimShort: - case Primitive::kPrimChar: { + case DataType::Type::kInt16: + case DataType::Type::kUint16: { if (value.IsConstant()) { __ movw(Address(base, offset), Immediate(CodeGenerator::GetInt16ValueOf(value.GetConstant()))); @@ -4452,17 +4454,17 @@ void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimInt: - case Primitive::kPrimNot: { + case DataType::Type::kInt32: + case DataType::Type::kReference: { if (value.IsConstant()) { int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant()); - // `field_type == Primitive::kPrimNot` implies `v == 0`. - DCHECK((field_type != Primitive::kPrimNot) || (v == 0)); + // `field_type == DataType::Type::kReference` implies `v == 0`. + DCHECK((field_type != DataType::Type::kReference) || (v == 0)); // Note: if heap poisoning is enabled, no need to poison // (negate) `v` if it is a reference, as it would be null. __ movl(Address(base, offset), Immediate(v)); } else { - if (kPoisonHeapReferences && field_type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && field_type == DataType::Type::kReference) { CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>(); __ movl(temp, value.AsRegister<CpuRegister>()); __ PoisonHeapReference(temp); @@ -4474,7 +4476,7 @@ void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (value.IsConstant()) { int64_t v = value.GetConstant()->AsLongConstant()->GetValue(); codegen_->MoveInt64ToAddress(Address(base, offset), @@ -4488,7 +4490,7 @@ void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (value.IsConstant()) { int32_t v = bit_cast<int32_t, float>(value.GetConstant()->AsFloatConstant()->GetValue()); @@ -4499,7 +4501,7 @@ void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (value.IsConstant()) { int64_t v = bit_cast<int64_t, double>(value.GetConstant()->AsDoubleConstant()->GetValue()); @@ -4514,7 +4516,7 @@ void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction, break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); } @@ -4679,7 +4681,7 @@ void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) { void LocationsBuilderX86_64::VisitArrayGet(HArrayGet* instruction) { bool object_array_get_with_read_barrier = - kEmitCompilerReadBarrier && (instruction->GetType() == Primitive::kPrimNot); + kEmitCompilerReadBarrier && (instruction->GetType() == DataType::Type::kReference); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, object_array_get_with_read_barrier ? @@ -4690,7 +4692,7 @@ void LocationsBuilderX86_64::VisitArrayGet(HArrayGet* instruction) { } locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - if (Primitive::IsFloatingPointType(instruction->GetType())) { + if (DataType::IsFloatingPointType(instruction->GetType())) { locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); } else { // The output overlaps for an object array get when read barriers @@ -4710,27 +4712,27 @@ void InstructionCodeGeneratorX86_64::VisitArrayGet(HArrayGet* instruction) { Location out_loc = locations->Out(); uint32_t data_offset = CodeGenerator::GetArrayDataOffset(instruction); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); switch (type) { - case Primitive::kPrimBoolean: { + case DataType::Type::kBool: { CpuRegister out = out_loc.AsRegister<CpuRegister>(); __ movzxb(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_1, data_offset)); break; } - case Primitive::kPrimByte: { + case DataType::Type::kInt8: { CpuRegister out = out_loc.AsRegister<CpuRegister>(); __ movsxb(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_1, data_offset)); break; } - case Primitive::kPrimShort: { + case DataType::Type::kInt16: { CpuRegister out = out_loc.AsRegister<CpuRegister>(); __ movsxw(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_2, data_offset)); break; } - case Primitive::kPrimChar: { + case DataType::Type::kUint16: { CpuRegister out = out_loc.AsRegister<CpuRegister>(); if (mirror::kUseStringCompression && instruction->IsStringCharAt()) { // Branch cases into compressed and uncompressed for each index's type. @@ -4752,13 +4754,13 @@ void InstructionCodeGeneratorX86_64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { CpuRegister out = out_loc.AsRegister<CpuRegister>(); __ movl(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_4, data_offset)); break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { static_assert( sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t), "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes."); @@ -4788,30 +4790,30 @@ void InstructionCodeGeneratorX86_64::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { CpuRegister out = out_loc.AsRegister<CpuRegister>(); __ movq(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_8, data_offset)); break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { XmmRegister out = out_loc.AsFpuRegister<XmmRegister>(); __ movss(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_4, data_offset)); break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { XmmRegister out = out_loc.AsFpuRegister<XmmRegister>(); __ movsd(out, CodeGeneratorX86_64::ArrayAddress(obj, index, TIMES_8, data_offset)); break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << type; UNREACHABLE(); } - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // Potential implicit null checks, in the case of reference // arrays, are handled in the previous switch statement. } else { @@ -4820,7 +4822,7 @@ void InstructionCodeGeneratorX86_64::VisitArrayGet(HArrayGet* instruction) { } void LocationsBuilderX86_64::VisitArraySet(HArraySet* instruction) { - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); @@ -4834,7 +4836,7 @@ void LocationsBuilderX86_64::VisitArraySet(HArraySet* instruction) { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - if (Primitive::IsFloatingPointType(value_type)) { + if (DataType::IsFloatingPointType(value_type)) { locations->SetInAt(2, Location::FpuRegisterOrConstant(instruction->InputAt(2))); } else { locations->SetInAt(2, Location::RegisterOrConstant(instruction->InputAt(2))); @@ -4853,7 +4855,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { CpuRegister array = array_loc.AsRegister<CpuRegister>(); Location index = locations->InAt(1); Location value = locations->InAt(2); - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); @@ -4862,8 +4864,8 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value(); switch (value_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: { + case DataType::Type::kBool: + case DataType::Type::kInt8: { uint32_t offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value(); Address address = CodeGeneratorX86_64::ArrayAddress(array, index, TIMES_1, offset); if (value.IsRegister()) { @@ -4875,8 +4877,8 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimShort: - case Primitive::kPrimChar: { + case DataType::Type::kInt16: + case DataType::Type::kUint16: { uint32_t offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value(); Address address = CodeGeneratorX86_64::ArrayAddress(array, index, TIMES_2, offset); if (value.IsRegister()) { @@ -4889,7 +4891,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { uint32_t offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); Address address = CodeGeneratorX86_64::ArrayAddress(array, index, TIMES_4, offset); @@ -4985,7 +4987,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { uint32_t offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); Address address = CodeGeneratorX86_64::ArrayAddress(array, index, TIMES_4, offset); if (value.IsRegister()) { @@ -4999,7 +5001,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { uint32_t offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value(); Address address = CodeGeneratorX86_64::ArrayAddress(array, index, TIMES_8, offset); if (value.IsRegister()) { @@ -5014,7 +5016,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { uint32_t offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value(); Address address = CodeGeneratorX86_64::ArrayAddress(array, index, TIMES_4, offset); if (value.IsFpuRegister()) { @@ -5028,7 +5030,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { uint32_t offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value(); Address address = CodeGeneratorX86_64::ArrayAddress(array, index, TIMES_8, offset); if (value.IsFpuRegister()) { @@ -5044,7 +5046,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); } @@ -6359,8 +6361,8 @@ void LocationsBuilderX86_64::VisitXor(HXor* instruction) { HandleBitwiseOperatio void LocationsBuilderX86_64::HandleBitwiseOperation(HBinaryOperation* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); - DCHECK(instruction->GetResultType() == Primitive::kPrimInt - || instruction->GetResultType() == Primitive::kPrimLong); + DCHECK(instruction->GetResultType() == DataType::Type::kInt32 + || instruction->GetResultType() == DataType::Type::kInt64); locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); locations->SetOut(Location::SameAsFirstInput()); @@ -6384,7 +6386,7 @@ void InstructionCodeGeneratorX86_64::HandleBitwiseOperation(HBinaryOperation* in Location second = locations->InAt(1); DCHECK(first.Equals(locations->Out())); - if (instruction->GetResultType() == Primitive::kPrimInt) { + if (instruction->GetResultType() == DataType::Type::kInt32) { if (second.IsRegister()) { if (instruction->IsAnd()) { __ andl(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>()); @@ -6416,7 +6418,7 @@ void InstructionCodeGeneratorX86_64::HandleBitwiseOperation(HBinaryOperation* in } } } else { - DCHECK_EQ(instruction->GetResultType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetResultType(), DataType::Type::kInt64); CpuRegister first_reg = first.AsRegister<CpuRegister>(); bool second_is_constant = false; int64_t value = 0; @@ -7094,13 +7096,13 @@ Address CodeGeneratorX86_64::LiteralInt64Address(int64_t v) { } // TODO: trg as memory. -void CodeGeneratorX86_64::MoveFromReturnRegister(Location trg, Primitive::Type type) { +void CodeGeneratorX86_64::MoveFromReturnRegister(Location trg, DataType::Type type) { if (!trg.IsValid()) { - DCHECK_EQ(type, Primitive::kPrimVoid); + DCHECK_EQ(type, DataType::Type::kVoid); return; } - DCHECK_NE(type, Primitive::kPrimVoid); + DCHECK_NE(type, DataType::Type::kVoid); Location return_loc = InvokeDexCallingConventionVisitorX86_64().GetReturnLocation(type); if (trg.Equals(return_loc)) { diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h index f5fa86bf23..6f67a45f25 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -89,16 +89,16 @@ class FieldAccessCallingConventionX86_64 : public FieldAccessCallingConvention { Location GetFieldIndexLocation() const OVERRIDE { return Location::RegisterLocation(RDI); } - Location GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { + Location GetReturnLocation(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return Location::RegisterLocation(RAX); } - Location GetSetValueLocation(Primitive::Type type ATTRIBUTE_UNUSED, bool is_instance) + Location GetSetValueLocation(DataType::Type type ATTRIBUTE_UNUSED, bool is_instance) const OVERRIDE { return is_instance ? Location::RegisterLocation(RDX) : Location::RegisterLocation(RSI); } - Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { + Location GetFpuLocation(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return Location::FpuRegisterLocation(XMM0); } @@ -112,8 +112,8 @@ class InvokeDexCallingConventionVisitorX86_64 : public InvokeDexCallingConventio InvokeDexCallingConventionVisitorX86_64() {} virtual ~InvokeDexCallingConventionVisitorX86_64() {} - Location GetNextLocation(Primitive::Type type) OVERRIDE; - Location GetReturnLocation(Primitive::Type type) const OVERRIDE; + Location GetNextLocation(DataType::Type type) OVERRIDE; + Location GetReturnLocation(DataType::Type type) const OVERRIDE; Location GetMethodLocation() const OVERRIDE; private: @@ -299,7 +299,7 @@ class CodeGeneratorX86_64 : public CodeGenerator { void GenerateFrameExit() OVERRIDE; void Bind(HBasicBlock* block) OVERRIDE; void MoveConstant(Location destination, int32_t value) OVERRIDE; - void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; + void MoveLocation(Location dst, Location src, DataType::Type dst_type) OVERRIDE; void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; @@ -384,7 +384,7 @@ class CodeGeneratorX86_64 : public CodeGenerator { block_labels_ = CommonInitializeLabels<Label>(); } - bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { + bool NeedsTwoRegisters(DataType::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return false; } @@ -422,9 +422,9 @@ class CodeGeneratorX86_64 : public CodeGenerator { dex::TypeIndex dex_index, Handle<mirror::Class> handle); - void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE; + void MoveFromReturnRegister(Location trg, DataType::Type type) OVERRIDE; - void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; + void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) OVERRIDE; void PatchJitRootUse(uint8_t* code, const uint8_t* roots_data, @@ -586,9 +586,9 @@ class CodeGeneratorX86_64 : public CodeGenerator { static constexpr int32_t kDummy32BitOffset = 256; private: - template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> + template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> static void EmitPcRelativeLinkerPatches(const ArenaDeque<PatchInfo<Label>>& infos, - ArenaVector<LinkerPatch>* linker_patches); + ArenaVector<linker::LinkerPatch>* linker_patches); // Labels for each block that will be compiled. Label* block_labels_; // Indexed by block id. diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index 0a8e97cf0d..896fcfa20d 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -91,7 +91,7 @@ static void TestCodeLong(const uint16_t* data, for (const CodegenTargetConfig& target_config : GetTargetConfigs()) { ArenaPool pool; ArenaAllocator arena(&pool); - HGraph* graph = CreateCFG(&arena, data, Primitive::kPrimLong); + HGraph* graph = CreateCFG(&arena, data, DataType::Type::kInt64); // Remove suspend checks, they cannot be executed in this context. RemoveSuspendChecks(graph); RunCode(target_config, graph, [](HGraph*) {}, has_result, expected); @@ -602,7 +602,7 @@ TEST_F(CodegenTest, ReturnDivInt2Addr) { static void TestComparison(IfCondition condition, int64_t i, int64_t j, - Primitive::Type type, + DataType::Type type, const CodegenTargetConfig target_config) { ArenaPool pool; ArenaAllocator allocator(&pool); @@ -626,11 +626,11 @@ static void TestComparison(IfCondition condition, HInstruction* op1; HInstruction* op2; - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { op1 = graph->GetIntConstant(i); op2 = graph->GetIntConstant(j); } else { - DCHECK_EQ(type, Primitive::kPrimLong); + DCHECK_EQ(type, DataType::Type::kInt64); op1 = graph->GetLongConstant(i); op2 = graph->GetLongConstant(j); } @@ -693,7 +693,8 @@ TEST_F(CodegenTest, ComparisonsInt) { for (int64_t i = -1; i <= 1; i++) { for (int64_t j = -1; j <= 1; j++) { for (int cond = kCondFirst; cond <= kCondLast; cond++) { - TestComparison(static_cast<IfCondition>(cond), i, j, Primitive::kPrimInt, target_config); + TestComparison( + static_cast<IfCondition>(cond), i, j, DataType::Type::kInt32, target_config); } } } @@ -705,7 +706,8 @@ TEST_F(CodegenTest, ComparisonsLong) { for (int64_t i = -1; i <= 1; i++) { for (int64_t j = -1; j <= 1; j++) { for (int cond = kCondFirst; cond <= kCondLast; cond++) { - TestComparison(static_cast<IfCondition>(cond), i, j, Primitive::kPrimLong, target_config); + TestComparison( + static_cast<IfCondition>(cond), i, j, DataType::Type::kInt64, target_config); } } } @@ -728,8 +730,8 @@ TEST_F(CodegenTest, ARMVIXLParallelMoveResolver) { // used as temps; however GPR scratch register is required for big stack offsets which don't fit // LDR encoding. So the following code is a regression test for that situation. HParallelMove* move = new (graph->GetArena()) HParallelMove(graph->GetArena()); - move->AddMove(Location::StackSlot(0), Location::StackSlot(8192), Primitive::kPrimInt, nullptr); - move->AddMove(Location::StackSlot(8192), Location::StackSlot(0), Primitive::kPrimInt, nullptr); + move->AddMove(Location::StackSlot(0), Location::StackSlot(8192), DataType::Type::kInt32, nullptr); + move->AddMove(Location::StackSlot(8192), Location::StackSlot(0), DataType::Type::kInt32, nullptr); codegen.GetMoveResolver()->EmitNativeCode(move); InternalCodeAllocator code_allocator; @@ -778,11 +780,11 @@ TEST_F(CodegenTest, ARM64ParallelMoveResolverB34760542) { HParallelMove* move = new (graph->GetArena()) HParallelMove(graph->GetArena()); move->AddMove(Location::DoubleStackSlot(0), Location::DoubleStackSlot(257), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); move->AddMove(Location::DoubleStackSlot(257), Location::DoubleStackSlot(0), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); codegen.GetMoveResolver()->EmitNativeCode(move); @@ -806,19 +808,19 @@ TEST_F(CodegenTest, ARM64ParallelMoveResolverSIMD) { HParallelMove* move = new (graph->GetArena()) HParallelMove(graph->GetArena()); move->AddMove(Location::SIMDStackSlot(0), Location::SIMDStackSlot(257), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); move->AddMove(Location::SIMDStackSlot(257), Location::SIMDStackSlot(0), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); move->AddMove(Location::FpuRegisterLocation(0), Location::FpuRegisterLocation(1), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); move->AddMove(Location::FpuRegisterLocation(1), Location::FpuRegisterLocation(0), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); codegen.GetMoveResolver()->EmitNativeCode(move); graph->SetHasSIMD(false); diff --git a/compiler/optimizing/common_arm.h b/compiler/optimizing/common_arm.h index e354654ee8..356ff9f41f 100644 --- a/compiler/optimizing/common_arm.h +++ b/compiler/optimizing/common_arm.h @@ -76,8 +76,8 @@ inline vixl::aarch32::Register RegisterFrom(Location location) { return vixl::aarch32::Register(location.reg()); } -inline vixl::aarch32::Register RegisterFrom(Location location, Primitive::Type type) { - DCHECK(type != Primitive::kPrimVoid && !Primitive::IsFloatingPointType(type)) << type; +inline vixl::aarch32::Register RegisterFrom(Location location, DataType::Type type) { + DCHECK(type != DataType::Type::kVoid && !DataType::IsFloatingPointType(type)) << type; return RegisterFrom(location); } @@ -94,20 +94,20 @@ inline vixl::aarch32::SRegister SRegisterFrom(Location location) { } inline vixl::aarch32::SRegister OutputSRegister(HInstruction* instr) { - Primitive::Type type = instr->GetType(); - DCHECK_EQ(type, Primitive::kPrimFloat) << type; + DataType::Type type = instr->GetType(); + DCHECK_EQ(type, DataType::Type::kFloat32) << type; return SRegisterFrom(instr->GetLocations()->Out()); } inline vixl::aarch32::DRegister OutputDRegister(HInstruction* instr) { - Primitive::Type type = instr->GetType(); - DCHECK_EQ(type, Primitive::kPrimDouble) << type; + DataType::Type type = instr->GetType(); + DCHECK_EQ(type, DataType::Type::kFloat64) << type; return DRegisterFrom(instr->GetLocations()->Out()); } inline vixl::aarch32::VRegister OutputVRegister(HInstruction* instr) { - Primitive::Type type = instr->GetType(); - if (type == Primitive::kPrimFloat) { + DataType::Type type = instr->GetType(); + if (type == DataType::Type::kFloat32) { return OutputSRegister(instr); } else { return OutputDRegister(instr); @@ -115,23 +115,23 @@ inline vixl::aarch32::VRegister OutputVRegister(HInstruction* instr) { } inline vixl::aarch32::SRegister InputSRegisterAt(HInstruction* instr, int input_index) { - Primitive::Type type = instr->InputAt(input_index)->GetType(); - DCHECK_EQ(type, Primitive::kPrimFloat) << type; + DataType::Type type = instr->InputAt(input_index)->GetType(); + DCHECK_EQ(type, DataType::Type::kFloat32) << type; return SRegisterFrom(instr->GetLocations()->InAt(input_index)); } inline vixl::aarch32::DRegister InputDRegisterAt(HInstruction* instr, int input_index) { - Primitive::Type type = instr->InputAt(input_index)->GetType(); - DCHECK_EQ(type, Primitive::kPrimDouble) << type; + DataType::Type type = instr->InputAt(input_index)->GetType(); + DCHECK_EQ(type, DataType::Type::kFloat64) << type; return DRegisterFrom(instr->GetLocations()->InAt(input_index)); } inline vixl::aarch32::VRegister InputVRegisterAt(HInstruction* instr, int input_index) { - Primitive::Type type = instr->InputAt(input_index)->GetType(); - if (type == Primitive::kPrimFloat) { + DataType::Type type = instr->InputAt(input_index)->GetType(); + if (type == DataType::Type::kFloat32) { return InputSRegisterAt(instr, input_index); } else { - DCHECK_EQ(type, Primitive::kPrimDouble); + DCHECK_EQ(type, DataType::Type::kFloat64); return InputDRegisterAt(instr, input_index); } } @@ -196,7 +196,7 @@ inline uint64_t Uint64ConstantFrom(HInstruction* instr) { return instr->AsConstant()->GetValueAsUint64(); } -inline vixl::aarch32::Operand OperandFrom(Location location, Primitive::Type type) { +inline vixl::aarch32::Operand OperandFrom(Location location, DataType::Type type) { if (location.IsRegister()) { return vixl::aarch32::Operand(RegisterFrom(location, type)); } else { diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h index e73fd7ddc8..102acb3423 100644 --- a/compiler/optimizing/common_arm64.h +++ b/compiler/optimizing/common_arm64.h @@ -73,9 +73,9 @@ inline vixl::aarch64::Register WRegisterFrom(Location location) { return vixl::aarch64::Register::GetWRegFromCode(VIXLRegCodeFromART(location.reg())); } -inline vixl::aarch64::Register RegisterFrom(Location location, Primitive::Type type) { - DCHECK(type != Primitive::kPrimVoid && !Primitive::IsFloatingPointType(type)) << type; - return type == Primitive::kPrimLong ? XRegisterFrom(location) : WRegisterFrom(location); +inline vixl::aarch64::Register RegisterFrom(Location location, DataType::Type type) { + DCHECK(type != DataType::Type::kVoid && !DataType::IsFloatingPointType(type)) << type; + return type == DataType::Type::kInt64 ? XRegisterFrom(location) : WRegisterFrom(location); } inline vixl::aarch64::Register OutputRegister(HInstruction* instr) { @@ -107,9 +107,9 @@ inline vixl::aarch64::FPRegister SRegisterFrom(Location location) { return vixl::aarch64::FPRegister::GetSRegFromCode(location.reg()); } -inline vixl::aarch64::FPRegister FPRegisterFrom(Location location, Primitive::Type type) { - DCHECK(Primitive::IsFloatingPointType(type)) << type; - return type == Primitive::kPrimDouble ? DRegisterFrom(location) : SRegisterFrom(location); +inline vixl::aarch64::FPRegister FPRegisterFrom(Location location, DataType::Type type) { + DCHECK(DataType::IsFloatingPointType(type)) << type; + return type == DataType::Type::kFloat64 ? DRegisterFrom(location) : SRegisterFrom(location); } inline vixl::aarch64::FPRegister OutputFPRegister(HInstruction* instr) { @@ -121,20 +121,20 @@ inline vixl::aarch64::FPRegister InputFPRegisterAt(HInstruction* instr, int inpu instr->InputAt(input_index)->GetType()); } -inline vixl::aarch64::CPURegister CPURegisterFrom(Location location, Primitive::Type type) { - return Primitive::IsFloatingPointType(type) +inline vixl::aarch64::CPURegister CPURegisterFrom(Location location, DataType::Type type) { + return DataType::IsFloatingPointType(type) ? vixl::aarch64::CPURegister(FPRegisterFrom(location, type)) : vixl::aarch64::CPURegister(RegisterFrom(location, type)); } inline vixl::aarch64::CPURegister OutputCPURegister(HInstruction* instr) { - return Primitive::IsFloatingPointType(instr->GetType()) + return DataType::IsFloatingPointType(instr->GetType()) ? static_cast<vixl::aarch64::CPURegister>(OutputFPRegister(instr)) : static_cast<vixl::aarch64::CPURegister>(OutputRegister(instr)); } inline vixl::aarch64::CPURegister InputCPURegisterAt(HInstruction* instr, int index) { - return Primitive::IsFloatingPointType(instr->InputAt(index)->GetType()) + return DataType::IsFloatingPointType(instr->InputAt(index)->GetType()) ? static_cast<vixl::aarch64::CPURegister>(InputFPRegisterAt(instr, index)) : static_cast<vixl::aarch64::CPURegister>(InputRegisterAt(instr, index)); } @@ -142,9 +142,9 @@ inline vixl::aarch64::CPURegister InputCPURegisterAt(HInstruction* instr, int in inline vixl::aarch64::CPURegister InputCPURegisterOrZeroRegAt(HInstruction* instr, int index) { HInstruction* input = instr->InputAt(index); - Primitive::Type input_type = input->GetType(); + DataType::Type input_type = input->GetType(); if (input->IsConstant() && input->AsConstant()->IsZeroBitPattern()) { - return (Primitive::ComponentSize(input_type) >= vixl::aarch64::kXRegSizeInBytes) + return (DataType::Size(input_type) >= vixl::aarch64::kXRegSizeInBytes) ? vixl::aarch64::Register(vixl::aarch64::xzr) : vixl::aarch64::Register(vixl::aarch64::wzr); } @@ -163,7 +163,7 @@ inline int64_t Int64ConstantFrom(Location location) { } } -inline vixl::aarch64::Operand OperandFrom(Location location, Primitive::Type type) { +inline vixl::aarch64::Operand OperandFrom(Location location, DataType::Type type) { if (location.IsRegister()) { return vixl::aarch64::Operand(RegisterFrom(location, type)); } else { @@ -202,7 +202,7 @@ inline vixl::aarch64::MemOperand HeapOperand(const vixl::aarch64::Register& base } inline vixl::aarch64::MemOperand HeapOperandFrom(Location location, Offset offset) { - return HeapOperand(RegisterFrom(location, Primitive::kPrimNot), offset); + return HeapOperand(RegisterFrom(location, DataType::Type::kReference), offset); } inline Location LocationFrom(const vixl::aarch64::Register& reg) { diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc index 5f39a49d68..bb586bf096 100644 --- a/compiler/optimizing/constant_folding.cc +++ b/compiler/optimizing/constant_folding.cc @@ -150,7 +150,7 @@ void InstructionWithAbsorbingInputSimplifier::VisitEqual(HEqual* instruction) { // EQUAL lhs, null // where lhs cannot be null with // CONSTANT false - instruction->ReplaceWith(GetGraph()->GetConstant(Primitive::kPrimBoolean, 0)); + instruction->ReplaceWith(GetGraph()->GetConstant(DataType::Type::kBool, 0)); instruction->GetBlock()->RemoveInstruction(instruction); } } @@ -162,7 +162,7 @@ void InstructionWithAbsorbingInputSimplifier::VisitNotEqual(HNotEqual* instructi // NOT_EQUAL lhs, null // where lhs cannot be null with // CONSTANT true - instruction->ReplaceWith(GetGraph()->GetConstant(Primitive::kPrimBoolean, 1)); + instruction->ReplaceWith(GetGraph()->GetConstant(DataType::Type::kBool, 1)); instruction->GetBlock()->RemoveInstruction(instruction); } } @@ -174,7 +174,7 @@ void InstructionWithAbsorbingInputSimplifier::VisitAbove(HAbove* instruction) { // ABOVE dst, 0, src // unsigned 0 > src is always false // with // CONSTANT false - instruction->ReplaceWith(GetGraph()->GetConstant(Primitive::kPrimBoolean, 0)); + instruction->ReplaceWith(GetGraph()->GetConstant(DataType::Type::kBool, 0)); instruction->GetBlock()->RemoveInstruction(instruction); } } @@ -186,7 +186,7 @@ void InstructionWithAbsorbingInputSimplifier::VisitAboveOrEqual(HAboveOrEqual* i // ABOVE_OR_EQUAL dst, src, 0 // unsigned src >= 0 is always true // with // CONSTANT true - instruction->ReplaceWith(GetGraph()->GetConstant(Primitive::kPrimBoolean, 1)); + instruction->ReplaceWith(GetGraph()->GetConstant(DataType::Type::kBool, 1)); instruction->GetBlock()->RemoveInstruction(instruction); } } @@ -198,7 +198,7 @@ void InstructionWithAbsorbingInputSimplifier::VisitBelow(HBelow* instruction) { // BELOW dst, src, 0 // unsigned src < 0 is always false // with // CONSTANT false - instruction->ReplaceWith(GetGraph()->GetConstant(Primitive::kPrimBoolean, 0)); + instruction->ReplaceWith(GetGraph()->GetConstant(DataType::Type::kBool, 0)); instruction->GetBlock()->RemoveInstruction(instruction); } } @@ -210,7 +210,7 @@ void InstructionWithAbsorbingInputSimplifier::VisitBelowOrEqual(HBelowOrEqual* i // BELOW_OR_EQUAL dst, 0, src // unsigned 0 <= src is always true // with // CONSTANT true - instruction->ReplaceWith(GetGraph()->GetConstant(Primitive::kPrimBoolean, 1)); + instruction->ReplaceWith(GetGraph()->GetConstant(DataType::Type::kBool, 1)); instruction->GetBlock()->RemoveInstruction(instruction); } } @@ -231,7 +231,7 @@ void InstructionWithAbsorbingInputSimplifier::VisitCompare(HCompare* instruction HConstant* input_cst = instruction->GetConstantRight(); if (input_cst != nullptr) { HInstruction* input_value = instruction->GetLeastConstantLeft(); - if (Primitive::IsFloatingPointType(input_value->GetType()) && + if (DataType::IsFloatingPointType(input_value->GetType()) && ((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->IsNaN()) || (input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->IsNaN()))) { // Replace code looking like @@ -240,7 +240,7 @@ void InstructionWithAbsorbingInputSimplifier::VisitCompare(HCompare* instruction // CONSTANT +1 (gt bias) // or // CONSTANT -1 (lt bias) - instruction->ReplaceWith(GetGraph()->GetConstant(Primitive::kPrimInt, + instruction->ReplaceWith(GetGraph()->GetConstant(DataType::Type::kInt32, (instruction->IsGtBias() ? 1 : -1))); instruction->GetBlock()->RemoveInstruction(instruction); } @@ -249,8 +249,8 @@ void InstructionWithAbsorbingInputSimplifier::VisitCompare(HCompare* instruction void InstructionWithAbsorbingInputSimplifier::VisitMul(HMul* instruction) { HConstant* input_cst = instruction->GetConstantRight(); - Primitive::Type type = instruction->GetType(); - if (Primitive::IsIntOrLongType(type) && + DataType::Type type = instruction->GetType(); + if (DataType::IsIntOrLongType(type) && (input_cst != nullptr) && input_cst->IsArithmeticZero()) { // Replace code looking like // MUL dst, src, 0 @@ -282,9 +282,9 @@ void InstructionWithAbsorbingInputSimplifier::VisitOr(HOr* instruction) { } void InstructionWithAbsorbingInputSimplifier::VisitRem(HRem* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); - if (!Primitive::IsIntegralType(type)) { + if (!DataType::IsIntegralType(type)) { return; } @@ -326,9 +326,9 @@ void InstructionWithAbsorbingInputSimplifier::VisitShr(HShr* instruction) { } void InstructionWithAbsorbingInputSimplifier::VisitSub(HSub* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); - if (!Primitive::IsIntegralType(type)) { + if (!DataType::IsIntegralType(type)) { return; } @@ -360,7 +360,7 @@ void InstructionWithAbsorbingInputSimplifier::VisitXor(HXor* instruction) { // XOR dst, src, src // with // CONSTANT 0 - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); HBasicBlock* block = instruction->GetBlock(); instruction->ReplaceWith(GetGraph()->GetConstant(type, 0)); block->RemoveInstruction(instruction); diff --git a/compiler/optimizing/constant_folding_test.cc b/compiler/optimizing/constant_folding_test.cc index 7ef28ed910..c85a2e3e70 100644 --- a/compiler/optimizing/constant_folding_test.cc +++ b/compiler/optimizing/constant_folding_test.cc @@ -43,7 +43,7 @@ class ConstantFoldingTest : public CommonCompilerTest { const std::string& expected_after_cf, const std::string& expected_after_dce, const std::function<void(HGraph*)>& check_after_cf, - Primitive::Type return_type = Primitive::kPrimInt) { + DataType::Type return_type = DataType::Type::kInt32) { graph_ = CreateCFG(&allocator_, data, return_type); TestCodeOnReadyGraph(expected_before, expected_after_cf, @@ -208,7 +208,7 @@ TEST_F(ConstantFoldingTest, LongConstantFoldingNegation) { expected_after_cf, expected_after_dce, check_after_cf, - Primitive::kPrimLong); + DataType::Type::kInt64); } /** @@ -483,7 +483,7 @@ TEST_F(ConstantFoldingTest, LongConstantFoldingOnAddition) { expected_after_cf, expected_after_dce, check_after_cf, - Primitive::kPrimLong); + DataType::Type::kInt64); } /** @@ -547,7 +547,7 @@ TEST_F(ConstantFoldingTest, LongConstantFoldingOnSubtraction) { expected_after_cf, expected_after_dce, check_after_cf, - Primitive::kPrimLong); + DataType::Type::kInt64); } /** @@ -756,7 +756,7 @@ TEST_F(ConstantFoldingTest, UnsignedComparisonsWithZero) { // Make various unsigned comparisons with zero against a parameter. HInstruction* parameter = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt, true); + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32, true); entry_block->AddInstruction(parameter); entry_block->AddInstruction(new (&allocator_) HGoto()); diff --git a/compiler/optimizing/data_type-inl.h b/compiler/optimizing/data_type-inl.h new file mode 100644 index 0000000000..fbc0c1215d --- /dev/null +++ b/compiler/optimizing/data_type-inl.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2017 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_OPTIMIZING_DATA_TYPE_INL_H_ +#define ART_COMPILER_OPTIMIZING_DATA_TYPE_INL_H_ + +#include "data_type.h" +#include "primitive.h" + +namespace art { + +// Note: Not declared in data_type.h to avoid pulling in "primitive.h". +constexpr DataType::Type DataTypeFromPrimitive(Primitive::Type type) { + switch (type) { + case Primitive::kPrimNot: return DataType::Type::kReference; + case Primitive::kPrimBoolean: return DataType::Type::kBool; + case Primitive::kPrimByte: return DataType::Type::kInt8; + case Primitive::kPrimChar: return DataType::Type::kUint16; + case Primitive::kPrimShort: return DataType::Type::kInt16; + case Primitive::kPrimInt: return DataType::Type::kInt32; + case Primitive::kPrimLong: return DataType::Type::kInt64; + case Primitive::kPrimFloat: return DataType::Type::kFloat32; + case Primitive::kPrimDouble: return DataType::Type::kFloat64; + case Primitive::kPrimVoid: return DataType::Type::kVoid; + } + LOG(FATAL) << "Unreachable"; + UNREACHABLE(); +} + +constexpr DataType::Type DataType::FromShorty(char type) { + return DataTypeFromPrimitive(Primitive::GetType(type)); +} + +constexpr char DataType::TypeId(DataType::Type type) { + // Type id for visualizer. + switch (type) { + case DataType::Type::kBool: return 'z'; + case DataType::Type::kInt8: return 'b'; + case DataType::Type::kUint16: return 'c'; + case DataType::Type::kInt16: return 's'; + case DataType::Type::kInt32: return 'i'; + case DataType::Type::kInt64: return 'j'; + case DataType::Type::kFloat32: return 'f'; + case DataType::Type::kFloat64: return 'd'; + case DataType::Type::kReference: return 'l'; + case DataType::Type::kVoid: return 'v'; + } + LOG(FATAL) << "Unreachable"; + UNREACHABLE(); +} + +} // namespace art + +#endif // ART_COMPILER_OPTIMIZING_DATA_TYPE_INL_H_ diff --git a/compiler/optimizing/data_type.cc b/compiler/optimizing/data_type.cc new file mode 100644 index 0000000000..689061722e --- /dev/null +++ b/compiler/optimizing/data_type.cc @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 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 "data_type.h" + +namespace art { + +static const char* kTypeNames[] = { + "Reference", + "Bool", + "Int8", + "Uint16", + "Int16", + "Int32", + "Int64", + "Float32", + "Float64", + "Void", +}; + +const char* DataType::PrettyDescriptor(Type type) { + static_assert(arraysize(kTypeNames) == static_cast<size_t>(Type::kLast) + 1, + "Missing element"); + uint32_t uint_type = static_cast<uint32_t>(type); + CHECK_LE(uint_type, static_cast<uint32_t>(Type::kLast)); + return kTypeNames[uint_type]; +} + +std::ostream& operator<<(std::ostream& os, DataType::Type type) { + uint32_t uint_type = static_cast<uint32_t>(type); + if (uint_type <= static_cast<uint32_t>(DataType::Type::kLast)) { + os << kTypeNames[uint_type]; + } else { + os << "Type[" << uint_type << "]"; + } + return os; +} + +} // namespace art diff --git a/compiler/optimizing/data_type.h b/compiler/optimizing/data_type.h new file mode 100644 index 0000000000..08f9263127 --- /dev/null +++ b/compiler/optimizing/data_type.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2017 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_OPTIMIZING_DATA_TYPE_H_ +#define ART_COMPILER_OPTIMIZING_DATA_TYPE_H_ + +#include <iosfwd> + +#include "base/logging.h" +#include "base/bit_utils.h" + +namespace art { + +class DataType { + public: + enum class Type : uint8_t { + kReference = 0, + kBool, + kInt8, + kUint16, + kInt16, + kInt32, + kInt64, + kFloat32, + kFloat64, + kVoid, + kLast = kVoid + }; + + static constexpr Type FromShorty(char type); + static constexpr char TypeId(DataType::Type type); + + static constexpr size_t SizeShift(Type type) { + switch (type) { + case Type::kVoid: + case Type::kBool: + case Type::kInt8: + return 0; + case Type::kUint16: + case Type::kInt16: + return 1; + case Type::kInt32: + case Type::kFloat32: + return 2; + case Type::kInt64: + case Type::kFloat64: + return 3; + case Type::kReference: + return WhichPowerOf2(kObjectReferenceSize); + default: + LOG(FATAL) << "Invalid type " << static_cast<int>(type); + return 0; + } + } + + static constexpr size_t Size(Type type) { + switch (type) { + case Type::kVoid: + return 0; + case Type::kBool: + case Type::kInt8: + return 1; + case Type::kUint16: + case Type::kInt16: + return 2; + case Type::kInt32: + case Type::kFloat32: + return 4; + case Type::kInt64: + case Type::kFloat64: + return 8; + case Type::kReference: + return kObjectReferenceSize; + default: + LOG(FATAL) << "Invalid type " << static_cast<int>(type); + return 0; + } + } + + static bool IsFloatingPointType(Type type) { + return type == Type::kFloat32 || type == Type::kFloat64; + } + + static bool IsIntegralType(Type type) { + // The Java language does not allow treating boolean as an integral type but + // our bit representation makes it safe. + switch (type) { + case Type::kBool: + case Type::kInt8: + case Type::kUint16: + case Type::kInt16: + case Type::kInt32: + case Type::kInt64: + return true; + default: + return false; + } + } + + static bool IsIntOrLongType(Type type) { + return type == Type::kInt32 || type == Type::kInt64; + } + + static bool Is64BitType(Type type) { + return type == Type::kInt64 || type == Type::kFloat64; + } + + // Return the general kind of `type`, fusing integer-like types as Type::kInt. + static Type Kind(Type type) { + switch (type) { + case Type::kBool: + case Type::kInt8: + case Type::kInt16: + case Type::kUint16: + case Type::kInt32: + return Type::kInt32; + default: + return type; + } + } + + static int64_t MinValueOfIntegralType(Type type) { + switch (type) { + case Type::kBool: + return std::numeric_limits<bool>::min(); + case Type::kInt8: + return std::numeric_limits<int8_t>::min(); + case Type::kUint16: + return std::numeric_limits<uint16_t>::min(); + case Type::kInt16: + return std::numeric_limits<int16_t>::min(); + case Type::kInt32: + return std::numeric_limits<int32_t>::min(); + case Type::kInt64: + return std::numeric_limits<int64_t>::min(); + default: + LOG(FATAL) << "non integral type"; + } + return 0; + } + + static int64_t MaxValueOfIntegralType(Type type) { + switch (type) { + case Type::kBool: + return std::numeric_limits<bool>::max(); + case Type::kInt8: + return std::numeric_limits<int8_t>::max(); + case Type::kUint16: + return std::numeric_limits<uint16_t>::max(); + case Type::kInt16: + return std::numeric_limits<int16_t>::max(); + case Type::kInt32: + return std::numeric_limits<int32_t>::max(); + case Type::kInt64: + return std::numeric_limits<int64_t>::max(); + default: + LOG(FATAL) << "non integral type"; + } + return 0; + } + + static const char* PrettyDescriptor(Type type); + + private: + static constexpr size_t kObjectReferenceSize = 4u; +}; +std::ostream& operator<<(std::ostream& os, DataType::Type data_type); + +} // namespace art + +#endif // ART_COMPILER_OPTIMIZING_DATA_TYPE_H_ diff --git a/compiler/optimizing/data_type_test.cc b/compiler/optimizing/data_type_test.cc new file mode 100644 index 0000000000..927291a54a --- /dev/null +++ b/compiler/optimizing/data_type_test.cc @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 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 <gtest/gtest.h> + +#include "data_type-inl.h" + +#include "primitive.h" + +namespace art { + +template <DataType::Type data_type, Primitive::Type primitive_type> +static void CheckConversion() { + static_assert(data_type == DataTypeFromPrimitive(primitive_type), "Conversion check."); + static_assert(DataType::Size(data_type) == Primitive::ComponentSize(primitive_type), + "Size check."); +} + +TEST(DataType, SizeAgainstPrimitive) { + CheckConversion<DataType::Type::kVoid, Primitive::kPrimVoid>(); + CheckConversion<DataType::Type::kBool, Primitive::kPrimBoolean>(); + CheckConversion<DataType::Type::kInt8, Primitive::kPrimByte>(); + CheckConversion<DataType::Type::kUint16, Primitive::kPrimChar>(); + CheckConversion<DataType::Type::kInt16, Primitive::kPrimShort>(); + CheckConversion<DataType::Type::kInt32, Primitive::kPrimInt>(); + CheckConversion<DataType::Type::kInt64, Primitive::kPrimLong>(); + CheckConversion<DataType::Type::kFloat32, Primitive::kPrimFloat>(); + CheckConversion<DataType::Type::kFloat64, Primitive::kPrimDouble>(); + CheckConversion<DataType::Type::kReference, Primitive::kPrimNot>(); +} + +TEST(DataType, Names) { +#define CHECK_NAME(type) EXPECT_STREQ(#type, DataType::PrettyDescriptor(DataType::Type::k##type)) + CHECK_NAME(Void); + CHECK_NAME(Bool); + CHECK_NAME(Int8); + CHECK_NAME(Uint16); + CHECK_NAME(Int16); + CHECK_NAME(Int32); + CHECK_NAME(Int64); + CHECK_NAME(Float32); + CHECK_NAME(Float64); + CHECK_NAME(Reference); +#undef CHECK_NAME +} + +} // namespace art diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc index 787296dc9d..9b094e989e 100644 --- a/compiler/optimizing/dead_code_elimination.cc +++ b/compiler/optimizing/dead_code_elimination.cc @@ -118,7 +118,7 @@ static bool HasEquality(IfCondition condition) { } static HConstant* Evaluate(HCondition* condition, HInstruction* left, HInstruction* right) { - if (left == right && !Primitive::IsFloatingPointType(left->GetType())) { + if (left == right && !DataType::IsFloatingPointType(left->GetType())) { return condition->GetBlock()->GetGraph()->GetIntConstant( HasEquality(condition->GetCondition()) ? 1 : 0); } diff --git a/compiler/optimizing/emit_swap_mips_test.cc b/compiler/optimizing/emit_swap_mips_test.cc index fa3c4dfba8..0e9c81dae3 100644 --- a/compiler/optimizing/emit_swap_mips_test.cc +++ b/compiler/optimizing/emit_swap_mips_test.cc @@ -118,12 +118,12 @@ TEST_F(EmitSwapMipsTest, TwoRegisters) { moves_->AddMove( Location::RegisterLocation(4), Location::RegisterLocation(5), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves_->AddMove( Location::RegisterLocation(5), Location::RegisterLocation(4), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); const char* expected = "or $t8, $a1, $zero\n" @@ -136,12 +136,12 @@ TEST_F(EmitSwapMipsTest, TwoRegisterPairs) { moves_->AddMove( Location::RegisterPairLocation(4, 5), Location::RegisterPairLocation(6, 7), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves_->AddMove( Location::RegisterPairLocation(6, 7), Location::RegisterPairLocation(4, 5), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); const char* expected = "or $t8, $a2, $zero\n" @@ -157,12 +157,12 @@ TEST_F(EmitSwapMipsTest, TwoFpuRegistersFloat) { moves_->AddMove( Location::FpuRegisterLocation(4), Location::FpuRegisterLocation(2), - Primitive::kPrimFloat, + DataType::Type::kFloat32, nullptr); moves_->AddMove( Location::FpuRegisterLocation(2), Location::FpuRegisterLocation(4), - Primitive::kPrimFloat, + DataType::Type::kFloat32, nullptr); const char* expected = "mov.s $f6, $f2\n" @@ -175,12 +175,12 @@ TEST_F(EmitSwapMipsTest, TwoFpuRegistersDouble) { moves_->AddMove( Location::FpuRegisterLocation(4), Location::FpuRegisterLocation(2), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); moves_->AddMove( Location::FpuRegisterLocation(2), Location::FpuRegisterLocation(4), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); const char* expected = "mov.d $f6, $f2\n" @@ -193,12 +193,12 @@ TEST_F(EmitSwapMipsTest, RegisterAndFpuRegister) { moves_->AddMove( Location::RegisterLocation(4), Location::FpuRegisterLocation(2), - Primitive::kPrimFloat, + DataType::Type::kFloat32, nullptr); moves_->AddMove( Location::FpuRegisterLocation(2), Location::RegisterLocation(4), - Primitive::kPrimFloat, + DataType::Type::kFloat32, nullptr); const char* expected = "or $t8, $a0, $zero\n" @@ -211,12 +211,12 @@ TEST_F(EmitSwapMipsTest, RegisterPairAndFpuRegister) { moves_->AddMove( Location::RegisterPairLocation(4, 5), Location::FpuRegisterLocation(4), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); moves_->AddMove( Location::FpuRegisterLocation(4), Location::RegisterPairLocation(4, 5), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); const char* expected = "mfc1 $t8, $f4\n" @@ -232,12 +232,12 @@ TEST_F(EmitSwapMipsTest, TwoStackSlots) { moves_->AddMove( Location::StackSlot(52), Location::StackSlot(48), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves_->AddMove( Location::StackSlot(48), Location::StackSlot(52), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); const char* expected = "addiu $sp, $sp, -4\n" @@ -255,12 +255,12 @@ TEST_F(EmitSwapMipsTest, TwoDoubleStackSlots) { moves_->AddMove( Location::DoubleStackSlot(56), Location::DoubleStackSlot(48), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves_->AddMove( Location::DoubleStackSlot(48), Location::DoubleStackSlot(56), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); const char* expected = "addiu $sp, $sp, -4\n" @@ -282,12 +282,12 @@ TEST_F(EmitSwapMipsTest, RegisterAndStackSlot) { moves_->AddMove( Location::RegisterLocation(4), Location::StackSlot(48), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves_->AddMove( Location::StackSlot(48), Location::RegisterLocation(4), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); const char* expected = "or $t8, $a0, $zero\n" @@ -300,12 +300,12 @@ TEST_F(EmitSwapMipsTest, RegisterPairAndDoubleStackSlot) { moves_->AddMove( Location::RegisterPairLocation(4, 5), Location::DoubleStackSlot(32), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves_->AddMove( Location::DoubleStackSlot(32), Location::RegisterPairLocation(4, 5), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); const char* expected = "or $t8, $a0, $zero\n" @@ -321,12 +321,12 @@ TEST_F(EmitSwapMipsTest, FpuRegisterAndStackSlot) { moves_->AddMove( Location::FpuRegisterLocation(4), Location::StackSlot(48), - Primitive::kPrimFloat, + DataType::Type::kFloat32, nullptr); moves_->AddMove( Location::StackSlot(48), Location::FpuRegisterLocation(4), - Primitive::kPrimFloat, + DataType::Type::kFloat32, nullptr); const char* expected = "mov.s $f6, $f4\n" @@ -339,12 +339,12 @@ TEST_F(EmitSwapMipsTest, FpuRegisterAndDoubleStackSlot) { moves_->AddMove( Location::FpuRegisterLocation(4), Location::DoubleStackSlot(48), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); moves_->AddMove( Location::DoubleStackSlot(48), Location::FpuRegisterLocation(4), - Primitive::kPrimDouble, + DataType::Type::kFloat64, nullptr); const char* expected = "mov.d $f6, $f4\n" diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index 327e11f7e7..1c7d1a0b69 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -456,7 +456,7 @@ void GraphChecker::VisitInstruction(HInstruction* instruction) { } // Ensure that reference type instructions have reference type info. - if (instruction->GetType() == Primitive::kPrimNot) { + if (instruction->GetType() == DataType::Type::kReference) { if (!instruction->GetReferenceTypeInfo().IsValid()) { AddError(StringPrintf("Reference type instruction %s:%d does not have " "valid reference type information.", @@ -674,7 +674,7 @@ void GraphChecker::HandleLoop(HBasicBlock* loop_header) { static bool IsSameSizeConstant(const HInstruction* insn1, const HInstruction* insn2) { return insn1->IsConstant() && insn2->IsConstant() - && Primitive::Is64BitType(insn1->GetType()) == Primitive::Is64BitType(insn2->GetType()); + && DataType::Is64BitType(insn1->GetType()) == DataType::Is64BitType(insn2->GetType()); } static bool IsConstantEquivalent(const HInstruction* insn1, @@ -721,20 +721,20 @@ void GraphChecker::VisitPhi(HPhi* phi) { // Ensure that the inputs have the same primitive kind as the phi. for (size_t i = 0; i < input_records.size(); ++i) { HInstruction* input = input_records[i].GetInstruction(); - if (Primitive::PrimitiveKind(input->GetType()) != Primitive::PrimitiveKind(phi->GetType())) { + if (DataType::Kind(input->GetType()) != DataType::Kind(phi->GetType())) { AddError(StringPrintf( "Input %d at index %zu of phi %d from block %d does not have the " "same kind as the phi: %s versus %s", input->GetId(), i, phi->GetId(), phi->GetBlock()->GetBlockId(), - Primitive::PrettyDescriptor(input->GetType()), - Primitive::PrettyDescriptor(phi->GetType()))); + DataType::PrettyDescriptor(input->GetType()), + DataType::PrettyDescriptor(phi->GetType()))); } } if (phi->GetType() != HPhi::ToPhiType(phi->GetType())) { AddError(StringPrintf("Phi %d in block %d does not have an expected phi type: %s", phi->GetId(), phi->GetBlock()->GetBlockId(), - Primitive::PrettyDescriptor(phi->GetType()))); + DataType::PrettyDescriptor(phi->GetType()))); } if (phi->IsCatchPhi()) { @@ -820,7 +820,7 @@ void GraphChecker::VisitPhi(HPhi* phi) { phi->GetId(), phi->GetRegNumber(), type_str.str().c_str())); - } else if (phi->GetType() == Primitive::kPrimNot) { + } else if (phi->GetType() == DataType::Type::kReference) { std::stringstream type_str; type_str << other_phi->GetType(); AddError(StringPrintf( @@ -859,7 +859,7 @@ void GraphChecker::HandleBooleanInput(HInstruction* instruction, size_t input_in static_cast<int>(input_index), value)); } - } else if (Primitive::PrimitiveKind(input->GetType()) != Primitive::kPrimInt) { + } else if (DataType::Kind(input->GetType()) != DataType::Type::kInt32) { // TODO: We need a data-flow analysis to determine if an input like Phi, // Select or a binary operation is actually Boolean. Allow for now. AddError(StringPrintf( @@ -867,7 +867,7 @@ void GraphChecker::HandleBooleanInput(HInstruction* instruction, size_t input_in instruction->DebugName(), instruction->GetId(), static_cast<int>(input_index), - Primitive::PrettyDescriptor(input->GetType()))); + DataType::PrettyDescriptor(input->GetType()))); } } @@ -904,27 +904,27 @@ void GraphChecker::VisitBooleanNot(HBooleanNot* instruction) { void GraphChecker::VisitCondition(HCondition* op) { VisitInstruction(op); - if (op->GetType() != Primitive::kPrimBoolean) { + if (op->GetType() != DataType::Type::kBool) { AddError(StringPrintf( "Condition %s %d has a non-Boolean result type: %s.", op->DebugName(), op->GetId(), - Primitive::PrettyDescriptor(op->GetType()))); + DataType::PrettyDescriptor(op->GetType()))); } HInstruction* lhs = op->InputAt(0); HInstruction* rhs = op->InputAt(1); - if (Primitive::PrimitiveKind(lhs->GetType()) != Primitive::PrimitiveKind(rhs->GetType())) { + if (DataType::Kind(lhs->GetType()) != DataType::Kind(rhs->GetType())) { AddError(StringPrintf( "Condition %s %d has inputs of different kinds: %s, and %s.", op->DebugName(), op->GetId(), - Primitive::PrettyDescriptor(lhs->GetType()), - Primitive::PrettyDescriptor(rhs->GetType()))); + DataType::PrettyDescriptor(lhs->GetType()), + DataType::PrettyDescriptor(rhs->GetType()))); } if (!op->IsEqual() && !op->IsNotEqual()) { - if ((lhs->GetType() == Primitive::kPrimNot)) { + if ((lhs->GetType() == DataType::Type::kReference)) { AddError(StringPrintf( "Condition %s %d uses an object as left-hand side input.", op->DebugName(), op->GetId())); - } else if (rhs->GetType() == Primitive::kPrimNot) { + } else if (rhs->GetType() == DataType::Type::kReference) { AddError(StringPrintf( "Condition %s %d uses an object as right-hand side input.", op->DebugName(), op->GetId())); @@ -934,72 +934,72 @@ void GraphChecker::VisitCondition(HCondition* op) { void GraphChecker::VisitNeg(HNeg* instruction) { VisitInstruction(instruction); - Primitive::Type input_type = instruction->InputAt(0)->GetType(); - Primitive::Type result_type = instruction->GetType(); - if (result_type != Primitive::PrimitiveKind(input_type)) { + DataType::Type input_type = instruction->InputAt(0)->GetType(); + DataType::Type result_type = instruction->GetType(); + if (result_type != DataType::Kind(input_type)) { AddError(StringPrintf("Binary operation %s %d has a result type different " "from its input kind: %s vs %s.", instruction->DebugName(), instruction->GetId(), - Primitive::PrettyDescriptor(result_type), - Primitive::PrettyDescriptor(input_type))); + DataType::PrettyDescriptor(result_type), + DataType::PrettyDescriptor(input_type))); } } void GraphChecker::VisitBinaryOperation(HBinaryOperation* op) { VisitInstruction(op); - Primitive::Type lhs_type = op->InputAt(0)->GetType(); - Primitive::Type rhs_type = op->InputAt(1)->GetType(); - Primitive::Type result_type = op->GetType(); + DataType::Type lhs_type = op->InputAt(0)->GetType(); + DataType::Type rhs_type = op->InputAt(1)->GetType(); + DataType::Type result_type = op->GetType(); // Type consistency between inputs. if (op->IsUShr() || op->IsShr() || op->IsShl() || op->IsRor()) { - if (Primitive::PrimitiveKind(rhs_type) != Primitive::kPrimInt) { + if (DataType::Kind(rhs_type) != DataType::Type::kInt32) { AddError(StringPrintf("Shift/rotate operation %s %d has a non-int kind second input: " "%s of type %s.", op->DebugName(), op->GetId(), op->InputAt(1)->DebugName(), - Primitive::PrettyDescriptor(rhs_type))); + DataType::PrettyDescriptor(rhs_type))); } } else { - if (Primitive::PrimitiveKind(lhs_type) != Primitive::PrimitiveKind(rhs_type)) { + if (DataType::Kind(lhs_type) != DataType::Kind(rhs_type)) { AddError(StringPrintf("Binary operation %s %d has inputs of different kinds: %s, and %s.", op->DebugName(), op->GetId(), - Primitive::PrettyDescriptor(lhs_type), - Primitive::PrettyDescriptor(rhs_type))); + DataType::PrettyDescriptor(lhs_type), + DataType::PrettyDescriptor(rhs_type))); } } // Type consistency between result and input(s). if (op->IsCompare()) { - if (result_type != Primitive::kPrimInt) { + if (result_type != DataType::Type::kInt32) { AddError(StringPrintf("Compare operation %d has a non-int result type: %s.", op->GetId(), - Primitive::PrettyDescriptor(result_type))); + DataType::PrettyDescriptor(result_type))); } } else if (op->IsUShr() || op->IsShr() || op->IsShl() || op->IsRor()) { // Only check the first input (value), as the second one (distance) // must invariably be of kind `int`. - if (result_type != Primitive::PrimitiveKind(lhs_type)) { + if (result_type != DataType::Kind(lhs_type)) { AddError(StringPrintf("Shift/rotate operation %s %d has a result type different " "from its left-hand side (value) input kind: %s vs %s.", op->DebugName(), op->GetId(), - Primitive::PrettyDescriptor(result_type), - Primitive::PrettyDescriptor(lhs_type))); + DataType::PrettyDescriptor(result_type), + DataType::PrettyDescriptor(lhs_type))); } } else { - if (Primitive::PrimitiveKind(result_type) != Primitive::PrimitiveKind(lhs_type)) { + if (DataType::Kind(result_type) != DataType::Kind(lhs_type)) { AddError(StringPrintf("Binary operation %s %d has a result kind different " "from its left-hand side input kind: %s vs %s.", op->DebugName(), op->GetId(), - Primitive::PrettyDescriptor(result_type), - Primitive::PrettyDescriptor(lhs_type))); + DataType::PrettyDescriptor(result_type), + DataType::PrettyDescriptor(lhs_type))); } - if (Primitive::PrimitiveKind(result_type) != Primitive::PrimitiveKind(rhs_type)) { + if (DataType::Kind(result_type) != DataType::Kind(rhs_type)) { AddError(StringPrintf("Binary operation %s %d has a result kind different " "from its right-hand side input kind: %s vs %s.", op->DebugName(), op->GetId(), - Primitive::PrettyDescriptor(result_type), - Primitive::PrettyDescriptor(rhs_type))); + DataType::PrettyDescriptor(result_type), + DataType::PrettyDescriptor(rhs_type))); } } } @@ -1028,16 +1028,16 @@ void GraphChecker::VisitBoundType(HBoundType* instruction) { void GraphChecker::VisitTypeConversion(HTypeConversion* instruction) { VisitInstruction(instruction); - Primitive::Type result_type = instruction->GetResultType(); - Primitive::Type input_type = instruction->GetInputType(); + DataType::Type result_type = instruction->GetResultType(); + DataType::Type input_type = instruction->GetInputType(); // Invariant: We should never generate a conversion to a Boolean value. - if (result_type == Primitive::kPrimBoolean) { + if (result_type == DataType::Type::kBool) { AddError(StringPrintf( "%s %d converts to a %s (from a %s).", instruction->DebugName(), instruction->GetId(), - Primitive::PrettyDescriptor(result_type), - Primitive::PrettyDescriptor(input_type))); + DataType::PrettyDescriptor(result_type), + DataType::PrettyDescriptor(input_type))); } } diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 3035e4657d..194f063d48 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -24,6 +24,7 @@ #include "bounds_check_elimination.h" #include "builder.h" #include "code_generator.h" +#include "data_type-inl.h" #include "dead_code_elimination.h" #include "disassembler.h" #include "inliner.h" @@ -243,25 +244,6 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { } } - char GetTypeId(Primitive::Type type) { - // Note that Primitive::Descriptor would not work for us - // because it does not handle reference types (that is kPrimNot). - switch (type) { - case Primitive::kPrimBoolean: return 'z'; - case Primitive::kPrimByte: return 'b'; - case Primitive::kPrimChar: return 'c'; - case Primitive::kPrimShort: return 's'; - case Primitive::kPrimInt: return 'i'; - case Primitive::kPrimLong: return 'j'; - case Primitive::kPrimFloat: return 'f'; - case Primitive::kPrimDouble: return 'd'; - case Primitive::kPrimNot: return 'l'; - case Primitive::kPrimVoid: return 'v'; - } - LOG(FATAL) << "Unreachable"; - return 'v'; - } - void PrintPredecessors(HBasicBlock* block) { AddIndent(); output_ << "predecessors"; @@ -583,7 +565,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { if (!inputs.empty()) { StringList input_list; for (const HInstruction* input : inputs) { - input_list.NewEntryStream() << GetTypeId(input->GetType()) << input->GetId(); + input_list.NewEntryStream() << DataType::TypeId(input->GetType()) << input->GetId(); } StartAttributeStream() << input_list; } @@ -597,7 +579,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { for (size_t i = 0, e = environment->Size(); i < e; ++i) { HInstruction* insn = environment->GetInstructionAt(i); if (insn != nullptr) { - vregs.NewEntryStream() << GetTypeId(insn->GetType()) << insn->GetId(); + vregs.NewEntryStream() << DataType::TypeId(insn->GetType()) << insn->GetId(); } else { vregs.NewEntryStream() << "_"; } @@ -654,7 +636,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { if ((IsPass(HGraphBuilder::kBuilderPassName) || IsPass(HInliner::kInlinerPassName)) - && (instruction->GetType() == Primitive::kPrimNot)) { + && (instruction->GetType() == DataType::Type::kReference)) { ReferenceTypeInfo info = instruction->IsLoadClass() ? instruction->AsLoadClass()->GetLoadedClassRTI() : instruction->GetReferenceTypeInfo(); @@ -698,7 +680,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { size_t num_uses = instruction->GetUses().SizeSlow(); AddIndent(); output_ << bci << " " << num_uses << " " - << GetTypeId(instruction->GetType()) << instruction->GetId() << " "; + << DataType::TypeId(instruction->GetType()) << instruction->GetId() << " "; PrintInstruction(instruction); output_ << " " << kEndInstructionMarker << "\n"; } @@ -821,7 +803,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) { AddIndent(); HInstruction* instruction = it.Current(); - output_ << instruction->GetId() << " " << GetTypeId(instruction->GetType()) + output_ << instruction->GetId() << " " << DataType::TypeId(instruction->GetType()) << instruction->GetId() << "[ "; for (const HInstruction* input : instruction->GetInputs()) { output_ << input->GetId() << " "; diff --git a/compiler/optimizing/gvn_test.cc b/compiler/optimizing/gvn_test.cc index e1ed7f656e..ac0dbee2c5 100644 --- a/compiler/optimizing/gvn_test.cc +++ b/compiler/optimizing/gvn_test.cc @@ -37,7 +37,7 @@ TEST_F(GVNTest, LocalFieldElimination) { HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimNot); + DataType::Type::kReference); entry->AddInstruction(parameter); HBasicBlock* block = new (&allocator) HBasicBlock(graph); @@ -46,7 +46,7 @@ TEST_F(GVNTest, LocalFieldElimination) { block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimNot, + DataType::Type::kReference, MemberOffset(42), false, kUnknownFieldIndex, @@ -55,7 +55,7 @@ TEST_F(GVNTest, LocalFieldElimination) { 0)); block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimNot, + DataType::Type::kReference, MemberOffset(42), false, kUnknownFieldIndex, @@ -65,7 +65,7 @@ TEST_F(GVNTest, LocalFieldElimination) { HInstruction* to_remove = block->GetLastInstruction(); block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimNot, + DataType::Type::kReference, MemberOffset(43), false, kUnknownFieldIndex, @@ -77,7 +77,7 @@ TEST_F(GVNTest, LocalFieldElimination) { block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter, parameter, nullptr, - Primitive::kPrimNot, + DataType::Type::kReference, MemberOffset(42), false, kUnknownFieldIndex, @@ -86,7 +86,7 @@ TEST_F(GVNTest, LocalFieldElimination) { 0)); block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimNot, + DataType::Type::kReference, MemberOffset(42), false, kUnknownFieldIndex, @@ -121,7 +121,7 @@ TEST_F(GVNTest, GlobalFieldElimination) { HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimNot); + DataType::Type::kReference); entry->AddInstruction(parameter); HBasicBlock* block = new (&allocator) HBasicBlock(graph); @@ -129,7 +129,7 @@ TEST_F(GVNTest, GlobalFieldElimination) { entry->AddSuccessor(block); block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimBoolean, + DataType::Type::kBool, MemberOffset(42), false, kUnknownFieldIndex, @@ -152,7 +152,7 @@ TEST_F(GVNTest, GlobalFieldElimination) { then->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimBoolean, + DataType::Type::kBool, MemberOffset(42), false, kUnknownFieldIndex, @@ -162,7 +162,7 @@ TEST_F(GVNTest, GlobalFieldElimination) { then->AddInstruction(new (&allocator) HGoto()); else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimBoolean, + DataType::Type::kBool, MemberOffset(42), false, kUnknownFieldIndex, @@ -172,7 +172,7 @@ TEST_F(GVNTest, GlobalFieldElimination) { else_->AddInstruction(new (&allocator) HGoto()); join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimBoolean, + DataType::Type::kBool, MemberOffset(42), false, kUnknownFieldIndex, @@ -204,7 +204,7 @@ TEST_F(GVNTest, LoopFieldElimination) { HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimNot); + DataType::Type::kReference); entry->AddInstruction(parameter); HBasicBlock* block = new (&allocator) HBasicBlock(graph); @@ -212,7 +212,7 @@ TEST_F(GVNTest, LoopFieldElimination) { entry->AddSuccessor(block); block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimBoolean, + DataType::Type::kBool, MemberOffset(42), false, kUnknownFieldIndex, @@ -235,7 +235,7 @@ TEST_F(GVNTest, LoopFieldElimination) { loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimBoolean, + DataType::Type::kBool, MemberOffset(42), false, kUnknownFieldIndex, @@ -250,7 +250,7 @@ TEST_F(GVNTest, LoopFieldElimination) { loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter, parameter, nullptr, - Primitive::kPrimBoolean, + DataType::Type::kBool, MemberOffset(42), false, kUnknownFieldIndex, @@ -260,7 +260,7 @@ TEST_F(GVNTest, LoopFieldElimination) { HInstruction* field_set = loop_body->GetLastInstruction(); loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimBoolean, + DataType::Type::kBool, MemberOffset(42), false, kUnknownFieldIndex, @@ -272,7 +272,7 @@ TEST_F(GVNTest, LoopFieldElimination) { exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimBoolean, + DataType::Type::kBool, MemberOffset(42), false, kUnknownFieldIndex, @@ -351,7 +351,7 @@ TEST_F(GVNTest, LoopSideEffects) { HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimBoolean); + DataType::Type::kBool); entry->AddInstruction(parameter); entry->AddInstruction(new (&allocator) HGoto()); outer_loop_header->AddInstruction(new (&allocator) HSuspendCheck()); @@ -374,7 +374,7 @@ TEST_F(GVNTest, LoopSideEffects) { entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter, parameter, nullptr, - Primitive::kPrimNot, + DataType::Type::kReference, MemberOffset(42), false, kUnknownFieldIndex, @@ -399,7 +399,7 @@ TEST_F(GVNTest, LoopSideEffects) { new (&allocator) HInstanceFieldSet(parameter, parameter, nullptr, - Primitive::kPrimNot, + DataType::Type::kReference, MemberOffset(42), false, kUnknownFieldIndex, @@ -425,7 +425,7 @@ TEST_F(GVNTest, LoopSideEffects) { new (&allocator) HInstanceFieldSet(parameter, parameter, nullptr, - Primitive::kPrimNot, + DataType::Type::kReference, MemberOffset(42), false, kUnknownFieldIndex, diff --git a/compiler/optimizing/induction_var_analysis.cc b/compiler/optimizing/induction_var_analysis.cc index 84b20f65e3..fe286ab88a 100644 --- a/compiler/optimizing/induction_var_analysis.cc +++ b/compiler/optimizing/induction_var_analysis.cc @@ -56,17 +56,17 @@ static void RotateEntryPhiFirst(HLoopInformation* loop, /** * Returns true if the from/to types denote a narrowing, integral conversion (precision loss). */ -static bool IsNarrowingIntegralConversion(Primitive::Type from, Primitive::Type to) { +static bool IsNarrowingIntegralConversion(DataType::Type from, DataType::Type to) { switch (from) { - case Primitive::kPrimLong: - return to == Primitive::kPrimByte || to == Primitive::kPrimShort - || to == Primitive::kPrimChar || to == Primitive::kPrimInt; - case Primitive::kPrimInt: - return to == Primitive::kPrimByte || to == Primitive::kPrimShort - || to == Primitive::kPrimChar; - case Primitive::kPrimChar: - case Primitive::kPrimShort: - return to == Primitive::kPrimByte; + case DataType::Type::kInt64: + return to == DataType::Type::kInt8 || to == DataType::Type::kInt16 + || to == DataType::Type::kUint16 || to == DataType::Type::kInt32; + case DataType::Type::kInt32: + return to == DataType::Type::kInt8 || to == DataType::Type::kInt16 + || to == DataType::Type::kUint16; + case DataType::Type::kUint16: + case DataType::Type::kInt16: + return to == DataType::Type::kInt8; default: return false; } @@ -75,13 +75,13 @@ static bool IsNarrowingIntegralConversion(Primitive::Type from, Primitive::Type /** * Returns result of implicit widening type conversion done in HIR. */ -static Primitive::Type ImplicitConversion(Primitive::Type type) { +static DataType::Type ImplicitConversion(DataType::Type type) { switch (type) { - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimByte: - case Primitive::kPrimBoolean: - return Primitive::kPrimInt; + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt8: + case DataType::Type::kBool: + return DataType::Type::kInt32; default: return type; } @@ -100,7 +100,7 @@ HInductionVarAnalysis::HInductionVarAnalysis(HGraph* graph) scc_(graph->GetArena()->Adapter(kArenaAllocInductionVarAnalysis)), cycle_(std::less<HInstruction*>(), graph->GetArena()->Adapter(kArenaAllocInductionVarAnalysis)), - type_(Primitive::kPrimVoid), + type_(DataType::Type::kVoid), induction_(std::less<HLoopInformation*>(), graph->GetArena()->Adapter(kArenaAllocInductionVarAnalysis)), cycles_(std::less<HPhi*>(), @@ -520,8 +520,8 @@ HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferMul(Inducti HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::TransferConversion( InductionInfo* a, - Primitive::Type from, - Primitive::Type to) { + DataType::Type from, + DataType::Type to) { if (a != nullptr) { // Allow narrowing conversion on linear induction in certain cases: // induction is already at narrow type, or can be made narrower. @@ -723,15 +723,15 @@ HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolveConversion( HLoopInformation* loop, HInstruction* entry_phi, HTypeConversion* conversion) { - Primitive::Type from = conversion->GetInputType(); - Primitive::Type to = conversion->GetResultType(); + DataType::Type from = conversion->GetInputType(); + DataType::Type to = conversion->GetResultType(); // A narrowing conversion is allowed as *last* operation of the cycle of a linear induction // with an initial value that fits the type, provided that the narrowest encountered type is // recorded with the induction to account for the precision loss. The narrower induction does // *not* transfer to any wider operations, however, since these may yield out-of-type values if (entry_phi->InputCount() == 2 && conversion == entry_phi->InputAt(1)) { - int64_t min = Primitive::MinValueOfIntegralType(to); - int64_t max = Primitive::MaxValueOfIntegralType(to); + int64_t min = DataType::MinValueOfIntegralType(to); + int64_t max = DataType::MaxValueOfIntegralType(to); int64_t value = 0; InductionInfo* initial = LookupInfo(loop, entry_phi->InputAt(0)); if (IsNarrowingIntegralConversion(from, to) && @@ -761,7 +761,7 @@ void HInductionVarAnalysis::VisitControl(HLoopInformation* loop) { HCondition* condition = if_expr->AsCondition(); InductionInfo* a = LookupInfo(loop, condition->InputAt(0)); InductionInfo* b = LookupInfo(loop, condition->InputAt(1)); - Primitive::Type type = ImplicitConversion(condition->InputAt(0)->GetType()); + DataType::Type type = ImplicitConversion(condition->InputAt(0)->GetType()); // Determine if the loop control uses a known sequence on an if-exit (X outside) or on // an if-iterate (X inside), expressed as if-iterate when passed into VisitCondition(). if (a == nullptr || b == nullptr) { @@ -778,7 +778,7 @@ void HInductionVarAnalysis::VisitControl(HLoopInformation* loop) { void HInductionVarAnalysis::VisitCondition(HLoopInformation* loop, InductionInfo* a, InductionInfo* b, - Primitive::Type type, + DataType::Type type, IfCondition cmp) { if (a->induction_class == kInvariant && b->induction_class == kLinear) { // Swap condition if induction is at right-hand-side (e.g. U > i is same as i < U). @@ -809,7 +809,7 @@ void HInductionVarAnalysis::VisitCondition(HLoopInformation* loop, } // Only accept integral condition. A mismatch between the type of condition and the induction // is only allowed if the, necessarily narrower, induction range fits the narrower control. - if (type != Primitive::kPrimInt && type != Primitive::kPrimLong) { + if (type != DataType::Type::kInt32 && type != DataType::Type::kInt64) { return; // not integral } else if (type != a->type && !FitsNarrowerControl(lower_expr, upper_expr, stride_value, a->type, cmp)) { @@ -830,7 +830,7 @@ void HInductionVarAnalysis::VisitTripCount(HLoopInformation* loop, InductionInfo* upper_expr, InductionInfo* stride_expr, int64_t stride_value, - Primitive::Type type, + DataType::Type type, IfCondition cmp) { // Any loop of the general form: // @@ -931,10 +931,10 @@ bool HInductionVarAnalysis::IsTaken(InductionInfo* lower_expr, bool HInductionVarAnalysis::IsFinite(InductionInfo* upper_expr, int64_t stride_value, - Primitive::Type type, + DataType::Type type, IfCondition cmp) { - int64_t min = Primitive::MinValueOfIntegralType(type); - int64_t max = Primitive::MaxValueOfIntegralType(type); + int64_t min = DataType::MinValueOfIntegralType(type); + int64_t max = DataType::MaxValueOfIntegralType(type); // Some rules under which it is certain at compile-time that the loop is finite. int64_t value; switch (cmp) { @@ -957,10 +957,10 @@ bool HInductionVarAnalysis::IsFinite(InductionInfo* upper_expr, bool HInductionVarAnalysis::FitsNarrowerControl(InductionInfo* lower_expr, InductionInfo* upper_expr, int64_t stride_value, - Primitive::Type type, + DataType::Type type, IfCondition cmp) { - int64_t min = Primitive::MinValueOfIntegralType(type); - int64_t max = Primitive::MaxValueOfIntegralType(type); + int64_t min = DataType::MinValueOfIntegralType(type); + int64_t max = DataType::MaxValueOfIntegralType(type); // Inclusive test need one extra. if (stride_value != 1 && stride_value != -1) { return false; // non-unit stride @@ -1008,13 +1008,13 @@ HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::LookupInfo(HLoopInf } HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::CreateConstant(int64_t value, - Primitive::Type type) { + DataType::Type type) { HInstruction* constant; switch (type) { - case Primitive::kPrimDouble: constant = graph_->GetDoubleConstant(value); break; - case Primitive::kPrimFloat: constant = graph_->GetFloatConstant(value); break; - case Primitive::kPrimLong: constant = graph_->GetLongConstant(value); break; - default: constant = graph_->GetIntConstant(value); break; + case DataType::Type::kFloat64: constant = graph_->GetDoubleConstant(value); break; + case DataType::Type::kFloat32: constant = graph_->GetFloatConstant(value); break; + case DataType::Type::kInt64: constant = graph_->GetLongConstant(value); break; + default: constant = graph_->GetIntConstant(value); break; } return CreateInvariantFetch(constant); } @@ -1100,11 +1100,11 @@ HInstruction* HInductionVarAnalysis::GetShiftConstant(HLoopInformation* loop, InductionInfo* b = LookupInfo(loop, instruction->InputAt(1)); int64_t value = -1; if (IsExact(b, &value)) { - Primitive::Type type = instruction->InputAt(0)->GetType(); - if (type == Primitive::kPrimInt && 0 <= value && value < 31) { + DataType::Type type = instruction->InputAt(0)->GetType(); + if (type == DataType::Type::kInt32 && 0 <= value && value < 31) { return graph_->GetIntConstant(1 << value); } - if (type == Primitive::kPrimLong && 0 <= value && value < 63) { + if (type == DataType::Type::kInt64 && 0 <= value && value < 63) { return graph_->GetLongConstant(1L << value); } } @@ -1142,11 +1142,11 @@ bool HInductionVarAnalysis::IsAtLeast(InductionInfo* info, int64_t* value) { bool HInductionVarAnalysis::IsNarrowingLinear(InductionInfo* info) { return info != nullptr && info->induction_class == kLinear && - (info->type == Primitive::kPrimByte || - info->type == Primitive::kPrimShort || - info->type == Primitive::kPrimChar || - (info->type == Primitive::kPrimInt && (info->op_a->type == Primitive::kPrimLong || - info->op_b->type == Primitive::kPrimLong))); + (info->type == DataType::Type::kInt8 || + info->type == DataType::Type::kInt16 || + info->type == DataType::Type::kUint16 || + (info->type == DataType::Type::kInt32 && (info->op_a->type == DataType::Type::kInt64 || + info->op_b->type == DataType::Type::kInt64))); } bool HInductionVarAnalysis::InductionEqual(InductionInfo* info1, @@ -1207,12 +1207,12 @@ std::string HInductionVarAnalysis::InductionToString(InductionInfo* info) { DCHECK(info->operation == kNop); return "(" + InductionToString(info->op_a) + " * i + " + InductionToString(info->op_b) + "):" + - Primitive::PrettyDescriptor(info->type); + DataType::PrettyDescriptor(info->type); } else if (info->induction_class == kPolynomial) { DCHECK(info->operation == kNop); return "poly(sum_lt(" + InductionToString(info->op_a) + ") + " + InductionToString(info->op_b) + "):" + - Primitive::PrettyDescriptor(info->type); + DataType::PrettyDescriptor(info->type); } else if (info->induction_class == kGeometric) { DCHECK(info->operation == kMul || info->operation == kDiv); DCHECK(info->fetch != nullptr); @@ -1220,17 +1220,17 @@ std::string HInductionVarAnalysis::InductionToString(InductionInfo* info) { FetchToString(info->fetch) + (info->operation == kMul ? " ^ i + " : " ^ -i + ") + InductionToString(info->op_b) + "):" + - Primitive::PrettyDescriptor(info->type); + DataType::PrettyDescriptor(info->type); } else if (info->induction_class == kWrapAround) { DCHECK(info->operation == kNop); return "wrap(" + InductionToString(info->op_a) + ", " + InductionToString(info->op_b) + "):" + - Primitive::PrettyDescriptor(info->type); + DataType::PrettyDescriptor(info->type); } else if (info->induction_class == kPeriodic) { DCHECK(info->operation == kNop); return "periodic(" + InductionToString(info->op_a) + ", " + InductionToString(info->op_b) + "):" + - Primitive::PrettyDescriptor(info->type); + DataType::PrettyDescriptor(info->type); } } } diff --git a/compiler/optimizing/induction_var_analysis.h b/compiler/optimizing/induction_var_analysis.h index 39b39cdf55..421b3ab9d0 100644 --- a/compiler/optimizing/induction_var_analysis.h +++ b/compiler/optimizing/induction_var_analysis.h @@ -103,7 +103,7 @@ class HInductionVarAnalysis : public HOptimization { InductionInfo* a, InductionInfo* b, HInstruction* f, - Primitive::Type t) + DataType::Type t) : induction_class(ic), operation(op), op_a(a), @@ -115,7 +115,7 @@ class HInductionVarAnalysis : public HOptimization { InductionInfo* op_a; InductionInfo* op_b; HInstruction* fetch; - Primitive::Type type; // precision of operation + DataType::Type type; // precision of operation }; bool IsVisitedNode(HInstruction* instruction) const { @@ -136,7 +136,7 @@ class HInductionVarAnalysis : public HOptimization { InductionInfo* CreateTripCount(InductionOp op, InductionInfo* a, InductionInfo* b, - Primitive::Type type) { + DataType::Type type) { DCHECK(a != nullptr && b != nullptr); return new (graph_->GetArena()) InductionInfo(kInvariant, op, a, b, nullptr, type); } @@ -146,7 +146,7 @@ class HInductionVarAnalysis : public HOptimization { InductionInfo* a, InductionInfo* b, HInstruction* f, - Primitive::Type type) { + DataType::Type type) { DCHECK(a != nullptr && b != nullptr); return new (graph_->GetArena()) InductionInfo(ic, op, a, b, f, type); } @@ -167,7 +167,7 @@ class HInductionVarAnalysis : public HOptimization { InductionInfo* TransferAddSub(InductionInfo* a, InductionInfo* b, InductionOp op); InductionInfo* TransferNeg(InductionInfo* a); InductionInfo* TransferMul(InductionInfo* a, InductionInfo* b); - InductionInfo* TransferConversion(InductionInfo* a, Primitive::Type from, Primitive::Type to); + InductionInfo* TransferConversion(InductionInfo* a, DataType::Type from, DataType::Type to); // Solvers. InductionInfo* SolvePhi(HInstruction* phi, size_t input_index, size_t adjust_input_size); @@ -200,30 +200,30 @@ class HInductionVarAnalysis : public HOptimization { void VisitCondition(HLoopInformation* loop, InductionInfo* a, InductionInfo* b, - Primitive::Type type, + DataType::Type type, IfCondition cmp); void VisitTripCount(HLoopInformation* loop, InductionInfo* lower_expr, InductionInfo* upper_expr, InductionInfo* stride, int64_t stride_value, - Primitive::Type type, + DataType::Type type, IfCondition cmp); bool IsTaken(InductionInfo* lower_expr, InductionInfo* upper_expr, IfCondition cmp); bool IsFinite(InductionInfo* upper_expr, int64_t stride_value, - Primitive::Type type, + DataType::Type type, IfCondition cmp); bool FitsNarrowerControl(InductionInfo* lower_expr, InductionInfo* upper_expr, int64_t stride_value, - Primitive::Type type, + DataType::Type type, IfCondition cmp); // Assign and lookup. void AssignInfo(HLoopInformation* loop, HInstruction* instruction, InductionInfo* info); InductionInfo* LookupInfo(HLoopInformation* loop, HInstruction* instruction); - InductionInfo* CreateConstant(int64_t value, Primitive::Type type); + InductionInfo* CreateConstant(int64_t value, DataType::Type type); InductionInfo* CreateSimplifiedInvariant(InductionOp op, InductionInfo* a, InductionInfo* b); HInstruction* GetShiftConstant(HLoopInformation* loop, HInstruction* instruction, @@ -250,7 +250,7 @@ class HInductionVarAnalysis : public HOptimization { ArenaSafeMap<HInstruction*, NodeInfo> map_; ArenaVector<HInstruction*> scc_; ArenaSafeMap<HInstruction*, InductionInfo*> cycle_; - Primitive::Type type_; + DataType::Type type_; /** * Maintains the results of the analysis as a mapping from loops to a mapping from instructions diff --git a/compiler/optimizing/induction_var_analysis_test.cc b/compiler/optimizing/induction_var_analysis_test.cc index 9516ccb385..53c8044a0b 100644 --- a/compiler/optimizing/induction_var_analysis_test.cc +++ b/compiler/optimizing/induction_var_analysis_test.cc @@ -94,7 +94,7 @@ class InductionVarAnalysisTest : public CommonCompilerTest { // Provide entry and exit instructions. parameter_ = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot, true); + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference, true); entry_->AddInstruction(parameter_); constant0_ = graph_->GetIntConstant(0); constant1_ = graph_->GetIntConstant(1); @@ -108,13 +108,13 @@ class InductionVarAnalysisTest : public CommonCompilerTest { // Provide loop instructions. for (int d = 0; d < n; d++) { - basic_[d] = new (&allocator_) HPhi(&allocator_, d, 0, Primitive::kPrimInt); + basic_[d] = new (&allocator_) HPhi(&allocator_, d, 0, DataType::Type::kInt32); loop_preheader_[d]->AddInstruction(new (&allocator_) HGoto()); loop_header_[d]->AddPhi(basic_[d]); HInstruction* compare = new (&allocator_) HLessThan(basic_[d], constant100_); loop_header_[d]->AddInstruction(compare); loop_header_[d]->AddInstruction(new (&allocator_) HIf(compare)); - increment_[d] = new (&allocator_) HAdd(Primitive::kPrimInt, basic_[d], constant1_); + increment_[d] = new (&allocator_) HAdd(DataType::Type::kInt32, basic_[d], constant1_); loop_body_[d]->AddInstruction(increment_[d]); loop_body_[d]->AddInstruction(new (&allocator_) HGoto()); @@ -141,7 +141,7 @@ class InductionVarAnalysisTest : public CommonCompilerTest { *ifT = ifTrue; *ifF = ifFalse; - HPhi* select_phi = new (&allocator_) HPhi(&allocator_, -1, 0, Primitive::kPrimInt); + HPhi* select_phi = new (&allocator_) HPhi(&allocator_, -1, 0, DataType::Type::kInt32); loop_body_[d]->AddPhi(select_phi); return select_phi; } @@ -154,7 +154,7 @@ class InductionVarAnalysisTest : public CommonCompilerTest { // Inserts a phi to loop header at depth d and returns it. HPhi* InsertLoopPhi(int vreg, int d) { - HPhi* phi = new (&allocator_) HPhi(&allocator_, vreg, 0, Primitive::kPrimInt); + HPhi* phi = new (&allocator_) HPhi(&allocator_, vreg, 0, DataType::Type::kInt32); loop_header_[d]->AddPhi(phi); return phi; } @@ -165,7 +165,7 @@ class InductionVarAnalysisTest : public CommonCompilerTest { // ArraySet is given a float value in order to avoid SsaBuilder typing // it from the array's non-existent reference type info. return InsertInstruction(new (&allocator_) HArraySet( - parameter_, subscript, float_constant0_, Primitive::kPrimFloat, 0), d); + parameter_, subscript, float_constant0_, DataType::Type::kFloat32, 0), d); } // Returns induction information of instruction in loop at depth d. @@ -265,8 +265,8 @@ TEST_F(InductionVarAnalysisTest, FindBasicInduction) { HInstruction* store = InsertArrayStore(basic_[0], 0); PerformInductionVarAnalysis(); - EXPECT_STREQ("((1) * i + (0)):PrimInt", GetInductionInfo(store->InputAt(1), 0).c_str()); - EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(increment_[0], 0).c_str()); + EXPECT_STREQ("((1) * i + (0)):Int32", GetInductionInfo(store->InputAt(1), 0).c_str()); + EXPECT_STREQ("((1) * i + (1)):Int32", GetInductionInfo(increment_[0], 0).c_str()); // Offset matters! EXPECT_FALSE(HaveSameInduction(store->InputAt(1), increment_[0])); @@ -286,22 +286,22 @@ TEST_F(InductionVarAnalysisTest, FindDerivedInduction) { // } BuildLoopNest(1); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, constant100_, basic_[0]), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, constant100_, basic_[0]), 0); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, constant100_, basic_[0]), 0); + new (&allocator_) HSub(DataType::Type::kInt32, constant100_, basic_[0]), 0); HInstruction* mul = InsertInstruction( - new (&allocator_) HMul(Primitive::kPrimInt, constant100_, basic_[0]), 0); + new (&allocator_) HMul(DataType::Type::kInt32, constant100_, basic_[0]), 0); HInstruction* shl = InsertInstruction( - new (&allocator_) HShl(Primitive::kPrimInt, basic_[0], constant1_), 0); + new (&allocator_) HShl(DataType::Type::kInt32, basic_[0], constant1_), 0); HInstruction* neg = InsertInstruction( - new (&allocator_) HNeg(Primitive::kPrimInt, basic_[0]), 0); + new (&allocator_) HNeg(DataType::Type::kInt32, basic_[0]), 0); PerformInductionVarAnalysis(); - EXPECT_STREQ("((1) * i + (100)):PrimInt", GetInductionInfo(add, 0).c_str()); - EXPECT_STREQ("(( - (1)) * i + (100)):PrimInt", GetInductionInfo(sub, 0).c_str()); - EXPECT_STREQ("((100) * i + (0)):PrimInt", GetInductionInfo(mul, 0).c_str()); - EXPECT_STREQ("((2) * i + (0)):PrimInt", GetInductionInfo(shl, 0).c_str()); - EXPECT_STREQ("(( - (1)) * i + (0)):PrimInt", GetInductionInfo(neg, 0).c_str()); + EXPECT_STREQ("((1) * i + (100)):Int32", GetInductionInfo(add, 0).c_str()); + EXPECT_STREQ("(( - (1)) * i + (100)):Int32", GetInductionInfo(sub, 0).c_str()); + EXPECT_STREQ("((100) * i + (0)):Int32", GetInductionInfo(mul, 0).c_str()); + EXPECT_STREQ("((2) * i + (0)):Int32", GetInductionInfo(shl, 0).c_str()); + EXPECT_STREQ("(( - (1)) * i + (0)):Int32", GetInductionInfo(neg, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindChainInduction) { @@ -318,19 +318,19 @@ TEST_F(InductionVarAnalysisTest, FindChainInduction) { k_header->AddInput(constant0_); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant100_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, constant100_), 0); HInstruction* store1 = InsertArrayStore(add, 0); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, add, constant1_), 0); + new (&allocator_) HSub(DataType::Type::kInt32, add, constant1_), 0); HInstruction* store2 = InsertArrayStore(sub, 0); k_header->AddInput(sub); PerformInductionVarAnalysis(); - EXPECT_STREQ("(((100) - (1)) * i + (0)):PrimInt", + EXPECT_STREQ("(((100) - (1)) * i + (0)):Int32", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("(((100) - (1)) * i + (100)):PrimInt", + EXPECT_STREQ("(((100) - (1)) * i + (100)):Int32", GetInductionInfo(store1->InputAt(1), 0).c_str()); - EXPECT_STREQ("(((100) - (1)) * i + ((100) - (1))):PrimInt", + EXPECT_STREQ("(((100) - (1)) * i + ((100) - (1))):Int32", GetInductionInfo(store2->InputAt(1), 0).c_str()); } @@ -351,11 +351,11 @@ TEST_F(InductionVarAnalysisTest, FindTwoWayBasicInduction) { HPhi* k_body = BuildIf(0, &ifTrue, &ifFalse); // True-branch. - HInstruction* inc1 = new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant1_); + HInstruction* inc1 = new (&allocator_) HAdd(DataType::Type::kInt32, k_header, constant1_); ifTrue->AddInstruction(inc1); k_body->AddInput(inc1); // False-branch. - HInstruction* inc2 = new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant1_); + HInstruction* inc2 = new (&allocator_) HAdd(DataType::Type::kInt32, k_header, constant1_); ifFalse->AddInstruction(inc2); k_body->AddInput(inc2); // Merge over a phi. @@ -363,8 +363,8 @@ TEST_F(InductionVarAnalysisTest, FindTwoWayBasicInduction) { k_header->AddInput(k_body); PerformInductionVarAnalysis(); - EXPECT_STREQ("((1) * i + (0)):PrimInt", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(store->InputAt(1), 0).c_str()); + EXPECT_STREQ("((1) * i + (0)):Int32", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("((1) * i + (1)):Int32", GetInductionInfo(store->InputAt(1), 0).c_str()); // Both increments get same induction. EXPECT_TRUE(HaveSameInduction(store->InputAt(1), inc1)); @@ -384,18 +384,18 @@ TEST_F(InductionVarAnalysisTest, FindTwoWayDerivedInduction) { HPhi* k = BuildIf(0, &ifTrue, &ifFalse); // True-branch. - HInstruction* inc1 = new (&allocator_) HAdd(Primitive::kPrimInt, basic_[0], constant1_); + HInstruction* inc1 = new (&allocator_) HAdd(DataType::Type::kInt32, basic_[0], constant1_); ifTrue->AddInstruction(inc1); k->AddInput(inc1); // False-branch. - HInstruction* inc2 = new (&allocator_) HAdd(Primitive::kPrimInt, basic_[0], constant1_); + HInstruction* inc2 = new (&allocator_) HAdd(DataType::Type::kInt32, basic_[0], constant1_); ifFalse->AddInstruction(inc2); k->AddInput(inc2); // Merge over a phi. HInstruction* store = InsertArrayStore(k, 0); PerformInductionVarAnalysis(); - EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(store->InputAt(1), 0).c_str()); + EXPECT_STREQ("((1) * i + (1)):Int32", GetInductionInfo(store->InputAt(1), 0).c_str()); // Both increments get same induction. EXPECT_TRUE(HaveSameInduction(store->InputAt(1), inc1)); @@ -412,17 +412,17 @@ TEST_F(InductionVarAnalysisTest, AddLinear) { BuildLoopNest(1); HInstruction* add1 = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, basic_[0], basic_[0]), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, basic_[0], basic_[0]), 0); HInstruction* add2 = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, constant7_, basic_[0]), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, constant7_, basic_[0]), 0); HInstruction* add3 = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, add1, add2), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, add1, add2), 0); PerformInductionVarAnalysis(); - EXPECT_STREQ("((1) * i + (0)):PrimInt", GetInductionInfo(basic_[0], 0).c_str()); - EXPECT_STREQ("(((1) + (1)) * i + (0)):PrimInt", GetInductionInfo(add1, 0).c_str()); - EXPECT_STREQ("((1) * i + (7)):PrimInt", GetInductionInfo(add2, 0).c_str()); - EXPECT_STREQ("((((1) + (1)) + (1)) * i + (7)):PrimInt", GetInductionInfo(add3, 0).c_str()); + EXPECT_STREQ("((1) * i + (0)):Int32", GetInductionInfo(basic_[0], 0).c_str()); + EXPECT_STREQ("(((1) + (1)) * i + (0)):Int32", GetInductionInfo(add1, 0).c_str()); + EXPECT_STREQ("((1) * i + (7)):Int32", GetInductionInfo(add2, 0).c_str()); + EXPECT_STREQ("((((1) + (1)) + (1)) * i + (7)):Int32", GetInductionInfo(add3, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindPolynomialInduction) { @@ -438,18 +438,18 @@ TEST_F(InductionVarAnalysisTest, FindPolynomialInduction) { k_header->AddInput(constant1_); HInstruction* mul = InsertInstruction( - new (&allocator_) HMul(Primitive::kPrimInt, basic_[0], constant2_), 0); + new (&allocator_) HMul(DataType::Type::kInt32, basic_[0], constant2_), 0); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, constant100_, mul), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, constant100_, mul), 0); HInstruction* pol = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, add, k_header), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, add, k_header), 0); k_header->AddInput(pol); PerformInductionVarAnalysis(); // Note, only the phi in the cycle and the base linear induction are classified. - EXPECT_STREQ("poly(sum_lt(((2) * i + (100)):PrimInt) + (1)):PrimInt", + EXPECT_STREQ("poly(sum_lt(((2) * i + (100)):Int32) + (1)):Int32", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("((2) * i + (100)):PrimInt", GetInductionInfo(add, 0).c_str()); + EXPECT_STREQ("((2) * i + (100)):Int32", GetInductionInfo(add, 0).c_str()); EXPECT_STREQ("", GetInductionInfo(pol, 0).c_str()); } @@ -469,32 +469,32 @@ TEST_F(InductionVarAnalysisTest, FindPolynomialInductionAndDerived) { k_header->AddInput(constant1_); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant100_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, constant100_), 0); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HSub(DataType::Type::kInt32, k_header, constant1_), 0); HInstruction* neg = InsertInstruction( - new (&allocator_) HNeg(Primitive::kPrimInt, sub), 0); + new (&allocator_) HNeg(DataType::Type::kInt32, sub), 0); HInstruction* mul = InsertInstruction( - new (&allocator_) HMul(Primitive::kPrimInt, k_header, constant2_), 0); + new (&allocator_) HMul(DataType::Type::kInt32, k_header, constant2_), 0); HInstruction* shl = InsertInstruction( - new (&allocator_) HShl(Primitive::kPrimInt, k_header, constant2_), 0); + new (&allocator_) HShl(DataType::Type::kInt32, k_header, constant2_), 0); HInstruction* pol = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, basic_[0]), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, basic_[0]), 0); k_header->AddInput(pol); PerformInductionVarAnalysis(); // Note, only the phi in the cycle and derived are classified. - EXPECT_STREQ("poly(sum_lt(((1) * i + (0)):PrimInt) + (1)):PrimInt", + EXPECT_STREQ("poly(sum_lt(((1) * i + (0)):Int32) + (1)):Int32", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("poly(sum_lt(((1) * i + (0)):PrimInt) + ((1) + (100))):PrimInt", + EXPECT_STREQ("poly(sum_lt(((1) * i + (0)):Int32) + ((1) + (100))):Int32", GetInductionInfo(add, 0).c_str()); - EXPECT_STREQ("poly(sum_lt(((1) * i + (0)):PrimInt) + ((1) - (1))):PrimInt", + EXPECT_STREQ("poly(sum_lt(((1) * i + (0)):Int32) + ((1) - (1))):Int32", GetInductionInfo(sub, 0).c_str()); - EXPECT_STREQ("poly(sum_lt((( - (1)) * i + (0)):PrimInt) + ((1) - (1))):PrimInt", + EXPECT_STREQ("poly(sum_lt((( - (1)) * i + (0)):Int32) + ((1) - (1))):Int32", GetInductionInfo(neg, 0).c_str()); - EXPECT_STREQ("poly(sum_lt(((2) * i + (0)):PrimInt) + (2)):PrimInt", + EXPECT_STREQ("poly(sum_lt(((2) * i + (0)):Int32) + (2)):Int32", GetInductionInfo(mul, 0).c_str()); - EXPECT_STREQ("poly(sum_lt(((4) * i + (0)):PrimInt) + (4)):PrimInt", + EXPECT_STREQ("poly(sum_lt(((4) * i + (0)):Int32) + (4)):Int32", GetInductionInfo(shl, 0).c_str()); EXPECT_STREQ("", GetInductionInfo(pol, 0).c_str()); } @@ -512,21 +512,21 @@ TEST_F(InductionVarAnalysisTest, AddPolynomial) { k_header->AddInput(constant7_); HInstruction* add1 = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, k_header), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, k_header), 0); HInstruction* add2 = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, add1, k_header), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, add1, k_header), 0); HInstruction* add3 = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, basic_[0]), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, basic_[0]), 0); k_header->AddInput(add3); PerformInductionVarAnalysis(); // Note, only the phi in the cycle and added-derived are classified. - EXPECT_STREQ("poly(sum_lt(((1) * i + (0)):PrimInt) + (7)):PrimInt", + EXPECT_STREQ("poly(sum_lt(((1) * i + (0)):Int32) + (7)):Int32", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("poly(sum_lt((((1) + (1)) * i + (0)):PrimInt) + ((7) + (7))):PrimInt", + EXPECT_STREQ("poly(sum_lt((((1) + (1)) * i + (0)):Int32) + ((7) + (7))):Int32", GetInductionInfo(add1, 0).c_str()); EXPECT_STREQ( - "poly(sum_lt(((((1) + (1)) + (1)) * i + (0)):PrimInt) + (((7) + (7)) + (7))):PrimInt", + "poly(sum_lt(((((1) + (1)) + (1)) * i + (0)):Int32) + (((7) + (7)) + (7))):Int32", GetInductionInfo(add2, 0).c_str()); EXPECT_STREQ("", GetInductionInfo(add3, 0).c_str()); } @@ -542,12 +542,12 @@ TEST_F(InductionVarAnalysisTest, FindGeometricMulInduction) { k_header->AddInput(constant1_); HInstruction* mul = InsertInstruction( - new (&allocator_) HMul(Primitive::kPrimInt, k_header, constant100_), 0); + new (&allocator_) HMul(DataType::Type::kInt32, k_header, constant100_), 0); k_header->AddInput(mul); PerformInductionVarAnalysis(); - EXPECT_STREQ("geo((1) * 100 ^ i + (0)):PrimInt", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("geo((100) * 100 ^ i + (0)):PrimInt", GetInductionInfo(mul, 0).c_str()); + EXPECT_STREQ("geo((1) * 100 ^ i + (0)):Int32", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("geo((100) * 100 ^ i + (0)):Int32", GetInductionInfo(mul, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindGeometricShlInductionAndDerived) { @@ -567,31 +567,31 @@ TEST_F(InductionVarAnalysisTest, FindGeometricShlInductionAndDerived) { k_header->AddInput(constant1_); HInstruction* add1 = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, constant1_), 0); HInstruction* shl1 = InsertInstruction( - new (&allocator_) HShl(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HShl(DataType::Type::kInt32, k_header, constant1_), 0); HInstruction* add2 = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, shl1, constant100_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, shl1, constant100_), 0); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, shl1, constant1_), 0); + new (&allocator_) HSub(DataType::Type::kInt32, shl1, constant1_), 0); HInstruction* neg = InsertInstruction( - new (&allocator_) HNeg(Primitive::kPrimInt, sub), 0); + new (&allocator_) HNeg(DataType::Type::kInt32, sub), 0); HInstruction* mul = InsertInstruction( - new (&allocator_) HMul(Primitive::kPrimInt, shl1, constant2_), 0); + new (&allocator_) HMul(DataType::Type::kInt32, shl1, constant2_), 0); HInstruction* shl2 = InsertInstruction( - new (&allocator_) HShl(Primitive::kPrimInt, shl1, constant2_), 0); + new (&allocator_) HShl(DataType::Type::kInt32, shl1, constant2_), 0); k_header->AddInput(shl1); PerformInductionVarAnalysis(); - EXPECT_STREQ("geo((1) * 2 ^ i + (0)):PrimInt", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("geo((1) * 2 ^ i + (1)):PrimInt", GetInductionInfo(add1, 0).c_str()); - EXPECT_STREQ("geo((2) * 2 ^ i + (0)):PrimInt", GetInductionInfo(shl1, 0).c_str()); - EXPECT_STREQ("geo((2) * 2 ^ i + (100)):PrimInt", GetInductionInfo(add2, 0).c_str()); - EXPECT_STREQ("geo((2) * 2 ^ i + ((0) - (1))):PrimInt", GetInductionInfo(sub, 0).c_str()); - EXPECT_STREQ("geo(( - (2)) * 2 ^ i + ( - ((0) - (1)))):PrimInt", + EXPECT_STREQ("geo((1) * 2 ^ i + (0)):Int32", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("geo((1) * 2 ^ i + (1)):Int32", GetInductionInfo(add1, 0).c_str()); + EXPECT_STREQ("geo((2) * 2 ^ i + (0)):Int32", GetInductionInfo(shl1, 0).c_str()); + EXPECT_STREQ("geo((2) * 2 ^ i + (100)):Int32", GetInductionInfo(add2, 0).c_str()); + EXPECT_STREQ("geo((2) * 2 ^ i + ((0) - (1))):Int32", GetInductionInfo(sub, 0).c_str()); + EXPECT_STREQ("geo(( - (2)) * 2 ^ i + ( - ((0) - (1)))):Int32", GetInductionInfo(neg, 0).c_str()); - EXPECT_STREQ("geo(((2) * (2)) * 2 ^ i + (0)):PrimInt", GetInductionInfo(mul, 0).c_str()); - EXPECT_STREQ("geo(((2) * (4)) * 2 ^ i + (0)):PrimInt", GetInductionInfo(shl2, 0).c_str()); + EXPECT_STREQ("geo(((2) * (2)) * 2 ^ i + (0)):Int32", GetInductionInfo(mul, 0).c_str()); + EXPECT_STREQ("geo(((2) * (4)) * 2 ^ i + (0)):Int32", GetInductionInfo(shl2, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindGeometricDivInductionAndDerived) { @@ -610,24 +610,24 @@ TEST_F(InductionVarAnalysisTest, FindGeometricDivInductionAndDerived) { k_header->AddInput(constant1_); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant100_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, constant100_), 0); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HSub(DataType::Type::kInt32, k_header, constant1_), 0); HInstruction* neg = InsertInstruction( - new (&allocator_) HNeg(Primitive::kPrimInt, sub), 0); + new (&allocator_) HNeg(DataType::Type::kInt32, sub), 0); HInstruction* mul = InsertInstruction( - new (&allocator_) HMul(Primitive::kPrimInt, k_header, constant2_), 0); + new (&allocator_) HMul(DataType::Type::kInt32, k_header, constant2_), 0); HInstruction* shl = InsertInstruction( - new (&allocator_) HShl(Primitive::kPrimInt, k_header, constant2_), 0); + new (&allocator_) HShl(DataType::Type::kInt32, k_header, constant2_), 0); HInstruction* div = InsertInstruction( - new (&allocator_) HDiv(Primitive::kPrimInt, k_header, constant100_, kNoDexPc), 0); + new (&allocator_) HDiv(DataType::Type::kInt32, k_header, constant100_, kNoDexPc), 0); k_header->AddInput(div); PerformInductionVarAnalysis(); // Note, only the phi in the cycle and direct additive derived are classified. - EXPECT_STREQ("geo((1) * 100 ^ -i + (0)):PrimInt", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("geo((1) * 100 ^ -i + (100)):PrimInt", GetInductionInfo(add, 0).c_str()); - EXPECT_STREQ("geo((1) * 100 ^ -i + ((0) - (1))):PrimInt", GetInductionInfo(sub, 0).c_str()); + EXPECT_STREQ("geo((1) * 100 ^ -i + (0)):Int32", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("geo((1) * 100 ^ -i + (100)):Int32", GetInductionInfo(add, 0).c_str()); + EXPECT_STREQ("geo((1) * 100 ^ -i + ((0) - (1))):Int32", GetInductionInfo(sub, 0).c_str()); EXPECT_STREQ("", GetInductionInfo(neg, 0).c_str()); EXPECT_STREQ("", GetInductionInfo(mul, 0).c_str()); EXPECT_STREQ("", GetInductionInfo(shl, 0).c_str()); @@ -645,12 +645,12 @@ TEST_F(InductionVarAnalysisTest, FindGeometricShrInduction) { k_header->AddInput(constant100_); HInstruction* shr = InsertInstruction( - new (&allocator_) HShr(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HShr(DataType::Type::kInt32, k_header, constant1_), 0); k_header->AddInput(shr); PerformInductionVarAnalysis(); // Note, only the phi in the cycle is classified. - EXPECT_STREQ("geo((100) * 2 ^ -i + (0)):PrimInt", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("geo((100) * 2 ^ -i + (0)):Int32", GetInductionInfo(k_header, 0).c_str()); EXPECT_STREQ("", GetInductionInfo(shr, 0).c_str()); } @@ -665,7 +665,7 @@ TEST_F(InductionVarAnalysisTest, FindNotGeometricShrInduction) { k_header->AddInput(constantm1_); HInstruction* shr = InsertInstruction( - new (&allocator_) HShr(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HShr(DataType::Type::kInt32, k_header, constant1_), 0); k_header->AddInput(shr); PerformInductionVarAnalysis(); @@ -689,27 +689,32 @@ TEST_F(InductionVarAnalysisTest, FindRemWrapAroundInductionAndDerived) { k_header->AddInput(constant100_); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant100_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, constant100_), 0); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HSub(DataType::Type::kInt32, k_header, constant1_), 0); HInstruction* neg = InsertInstruction( - new (&allocator_) HNeg(Primitive::kPrimInt, sub), 0); + new (&allocator_) HNeg(DataType::Type::kInt32, sub), 0); HInstruction* mul = InsertInstruction( - new (&allocator_) HMul(Primitive::kPrimInt, k_header, constant2_), 0); + new (&allocator_) HMul(DataType::Type::kInt32, k_header, constant2_), 0); HInstruction* shl = InsertInstruction( - new (&allocator_) HShl(Primitive::kPrimInt, k_header, constant2_), 0); + new (&allocator_) HShl(DataType::Type::kInt32, k_header, constant2_), 0); HInstruction* rem = InsertInstruction( - new (&allocator_) HRem(Primitive::kPrimInt, k_header, constant7_, kNoDexPc), 0); + new (&allocator_) HRem(DataType::Type::kInt32, k_header, constant7_, kNoDexPc), 0); k_header->AddInput(rem); PerformInductionVarAnalysis(); // Note, only the phi in the cycle and derived are classified. - EXPECT_STREQ("wrap((100), ((100) % (7))):PrimInt", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("wrap(((100) + (100)), (((100) % (7)) + (100))):PrimInt", GetInductionInfo(add, 0).c_str()); - EXPECT_STREQ("wrap(((100) - (1)), (((100) % (7)) - (1))):PrimInt", GetInductionInfo(sub, 0).c_str()); - EXPECT_STREQ("wrap(( - ((100) - (1))), ( - (((100) % (7)) - (1)))):PrimInt", GetInductionInfo(neg, 0).c_str()); - EXPECT_STREQ("wrap(((100) * (2)), (((100) % (7)) * (2))):PrimInt", GetInductionInfo(mul, 0).c_str()); - EXPECT_STREQ("wrap(((100) * (4)), (((100) % (7)) * (4))):PrimInt", GetInductionInfo(shl, 0).c_str()); + EXPECT_STREQ("wrap((100), ((100) % (7))):Int32", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("wrap(((100) + (100)), (((100) % (7)) + (100))):Int32", + GetInductionInfo(add, 0).c_str()); + EXPECT_STREQ("wrap(((100) - (1)), (((100) % (7)) - (1))):Int32", + GetInductionInfo(sub, 0).c_str()); + EXPECT_STREQ("wrap(( - ((100) - (1))), ( - (((100) % (7)) - (1)))):Int32", + GetInductionInfo(neg, 0).c_str()); + EXPECT_STREQ("wrap(((100) * (2)), (((100) % (7)) * (2))):Int32", + GetInductionInfo(mul, 0).c_str()); + EXPECT_STREQ("wrap(((100) * (4)), (((100) % (7)) * (4))):Int32", + GetInductionInfo(shl, 0).c_str()); EXPECT_STREQ("", GetInductionInfo(rem, 0).c_str()); } @@ -726,15 +731,15 @@ TEST_F(InductionVarAnalysisTest, FindFirstOrderWrapAroundInduction) { HInstruction* store = InsertArrayStore(k_header, 0); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, constant100_, basic_[0]), 0); + new (&allocator_) HSub(DataType::Type::kInt32, constant100_, basic_[0]), 0); k_header->AddInput(sub); PerformInductionVarAnalysis(); - EXPECT_STREQ("wrap((0), (( - (1)) * i + (100)):PrimInt):PrimInt", + EXPECT_STREQ("wrap((0), (( - (1)) * i + (100)):Int32):Int32", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("wrap((0), (( - (1)) * i + (100)):PrimInt):PrimInt", + EXPECT_STREQ("wrap((0), (( - (1)) * i + (100)):Int32):Int32", GetInductionInfo(store->InputAt(1), 0).c_str()); - EXPECT_STREQ("(( - (1)) * i + (100)):PrimInt", GetInductionInfo(sub, 0).c_str()); + EXPECT_STREQ("(( - (1)) * i + (100)):Int32", GetInductionInfo(sub, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindSecondOrderWrapAroundInduction) { @@ -755,11 +760,11 @@ TEST_F(InductionVarAnalysisTest, FindSecondOrderWrapAroundInduction) { HInstruction* store = InsertArrayStore(k_header, 0); k_header->AddInput(t); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, constant100_, basic_[0], 0), 0); + new (&allocator_) HSub(DataType::Type::kInt32, constant100_, basic_[0], 0), 0); t->AddInput(sub); PerformInductionVarAnalysis(); - EXPECT_STREQ("wrap((0), wrap((100), (( - (1)) * i + (100)):PrimInt):PrimInt):PrimInt", + EXPECT_STREQ("wrap((0), wrap((100), (( - (1)) * i + (100)):Int32):Int32):Int32", GetInductionInfo(store->InputAt(1), 0).c_str()); } @@ -780,34 +785,34 @@ TEST_F(InductionVarAnalysisTest, FindWrapAroundDerivedInduction) { k_header->AddInput(constant0_); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant100_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, constant100_), 0); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, k_header, constant100_), 0); + new (&allocator_) HSub(DataType::Type::kInt32, k_header, constant100_), 0); HInstruction* mul = InsertInstruction( - new (&allocator_) HMul(Primitive::kPrimInt, k_header, constant100_), 0); + new (&allocator_) HMul(DataType::Type::kInt32, k_header, constant100_), 0); HInstruction* shl1 = InsertInstruction( - new (&allocator_) HShl(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HShl(DataType::Type::kInt32, k_header, constant1_), 0); HInstruction* neg1 = InsertInstruction( - new (&allocator_) HNeg(Primitive::kPrimInt, k_header), 0); + new (&allocator_) HNeg(DataType::Type::kInt32, k_header), 0); HInstruction* shl2 = InsertInstruction( - new (&allocator_) HShl(Primitive::kPrimInt, basic_[0], constant1_), 0); + new (&allocator_) HShl(DataType::Type::kInt32, basic_[0], constant1_), 0); HInstruction* neg2 = InsertInstruction( - new (&allocator_) HNeg(Primitive::kPrimInt, shl2), 0); + new (&allocator_) HNeg(DataType::Type::kInt32, shl2), 0); k_header->AddInput(shl2); PerformInductionVarAnalysis(); - EXPECT_STREQ("wrap((100), ((2) * i + (100)):PrimInt):PrimInt", + EXPECT_STREQ("wrap((100), ((2) * i + (100)):Int32):Int32", GetInductionInfo(add, 0).c_str()); - EXPECT_STREQ("wrap(((0) - (100)), ((2) * i + ((0) - (100))):PrimInt):PrimInt", + EXPECT_STREQ("wrap(((0) - (100)), ((2) * i + ((0) - (100))):Int32):Int32", GetInductionInfo(sub, 0).c_str()); - EXPECT_STREQ("wrap((0), (((2) * (100)) * i + (0)):PrimInt):PrimInt", + EXPECT_STREQ("wrap((0), (((2) * (100)) * i + (0)):Int32):Int32", GetInductionInfo(mul, 0).c_str()); - EXPECT_STREQ("wrap((0), (((2) * (2)) * i + (0)):PrimInt):PrimInt", + EXPECT_STREQ("wrap((0), (((2) * (2)) * i + (0)):Int32):Int32", GetInductionInfo(shl1, 0).c_str()); - EXPECT_STREQ("wrap((0), (( - (2)) * i + (0)):PrimInt):PrimInt", + EXPECT_STREQ("wrap((0), (( - (2)) * i + (0)):Int32):Int32", GetInductionInfo(neg1, 0).c_str()); - EXPECT_STREQ("((2) * i + (0)):PrimInt", GetInductionInfo(shl2, 0).c_str()); - EXPECT_STREQ("(( - (2)) * i + (0)):PrimInt", GetInductionInfo(neg2, 0).c_str()); + EXPECT_STREQ("((2) * i + (0)):Int32", GetInductionInfo(shl2, 0).c_str()); + EXPECT_STREQ("(( - (2)) * i + (0)):Int32", GetInductionInfo(neg2, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindPeriodicInduction) { @@ -834,8 +839,8 @@ TEST_F(InductionVarAnalysisTest, FindPeriodicInduction) { t->AddInput(k_header); PerformInductionVarAnalysis(); - EXPECT_STREQ("periodic((0), (100)):PrimInt", GetInductionInfo(store1->InputAt(1), 0).c_str()); - EXPECT_STREQ("periodic((100), (0)):PrimInt", GetInductionInfo(store2->InputAt(1), 0).c_str()); + EXPECT_STREQ("periodic((0), (100)):Int32", GetInductionInfo(store1->InputAt(1), 0).c_str()); + EXPECT_STREQ("periodic((100), (0)):Int32", GetInductionInfo(store2->InputAt(1), 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindIdiomaticPeriodicInduction) { @@ -851,12 +856,12 @@ TEST_F(InductionVarAnalysisTest, FindIdiomaticPeriodicInduction) { HInstruction* store = InsertArrayStore(k_header, 0); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, constant1_, k_header), 0); + new (&allocator_) HSub(DataType::Type::kInt32, constant1_, k_header), 0); k_header->AddInput(sub); PerformInductionVarAnalysis(); - EXPECT_STREQ("periodic((0), (1)):PrimInt", GetInductionInfo(store->InputAt(1), 0).c_str()); - EXPECT_STREQ("periodic((1), (0)):PrimInt", GetInductionInfo(sub, 0).c_str()); + EXPECT_STREQ("periodic((0), (1)):Int32", GetInductionInfo(store->InputAt(1), 0).c_str()); + EXPECT_STREQ("periodic((1), (0)):Int32", GetInductionInfo(sub, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindXorPeriodicInduction) { @@ -872,12 +877,12 @@ TEST_F(InductionVarAnalysisTest, FindXorPeriodicInduction) { HInstruction* store = InsertArrayStore(k_header, 0); HInstruction* x = InsertInstruction( - new (&allocator_) HXor(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HXor(DataType::Type::kInt32, k_header, constant1_), 0); k_header->AddInput(x); PerformInductionVarAnalysis(); - EXPECT_STREQ("periodic((0), (1)):PrimInt", GetInductionInfo(store->InputAt(1), 0).c_str()); - EXPECT_STREQ("periodic((1), (0)):PrimInt", GetInductionInfo(x, 0).c_str()); + EXPECT_STREQ("periodic((0), (1)):Int32", GetInductionInfo(store->InputAt(1), 0).c_str()); + EXPECT_STREQ("periodic((1), (0)):Int32", GetInductionInfo(x, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindXorConstantLeftPeriodicInduction) { @@ -891,12 +896,12 @@ TEST_F(InductionVarAnalysisTest, FindXorConstantLeftPeriodicInduction) { k_header->AddInput(constant1_); HInstruction* x = InsertInstruction( - new (&allocator_) HXor(Primitive::kPrimInt, constant1_, k_header), 0); + new (&allocator_) HXor(DataType::Type::kInt32, constant1_, k_header), 0); k_header->AddInput(x); PerformInductionVarAnalysis(); - EXPECT_STREQ("periodic((1), ((1) ^ (1))):PrimInt", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("periodic(((1) ^ (1)), (1)):PrimInt", GetInductionInfo(x, 0).c_str()); + EXPECT_STREQ("periodic((1), ((1) ^ (1))):Int32", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("periodic(((1) ^ (1)), (1)):Int32", GetInductionInfo(x, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindXor100PeriodicInduction) { @@ -910,12 +915,12 @@ TEST_F(InductionVarAnalysisTest, FindXor100PeriodicInduction) { k_header->AddInput(constant1_); HInstruction* x = InsertInstruction( - new (&allocator_) HXor(Primitive::kPrimInt, k_header, constant100_), 0); + new (&allocator_) HXor(DataType::Type::kInt32, k_header, constant100_), 0); k_header->AddInput(x); PerformInductionVarAnalysis(); - EXPECT_STREQ("periodic((1), ((1) ^ (100))):PrimInt", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("periodic(((1) ^ (100)), (1)):PrimInt", GetInductionInfo(x, 0).c_str()); + EXPECT_STREQ("periodic((1), ((1) ^ (100))):Int32", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("periodic(((1) ^ (100)), (1)):Int32", GetInductionInfo(x, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindBooleanEqPeriodicInduction) { @@ -932,8 +937,8 @@ TEST_F(InductionVarAnalysisTest, FindBooleanEqPeriodicInduction) { k_header->AddInput(x); PerformInductionVarAnalysis(); - EXPECT_STREQ("periodic((0), (1)):PrimBoolean", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("periodic((1), (0)):PrimBoolean", GetInductionInfo(x, 0).c_str()); + EXPECT_STREQ("periodic((0), (1)):Bool", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("periodic((1), (0)):Bool", GetInductionInfo(x, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindBooleanEqConstantLeftPeriodicInduction) { @@ -950,8 +955,8 @@ TEST_F(InductionVarAnalysisTest, FindBooleanEqConstantLeftPeriodicInduction) { k_header->AddInput(x); PerformInductionVarAnalysis(); - EXPECT_STREQ("periodic((0), (1)):PrimBoolean", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("periodic((1), (0)):PrimBoolean", GetInductionInfo(x, 0).c_str()); + EXPECT_STREQ("periodic((0), (1)):Bool", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("periodic((1), (0)):Bool", GetInductionInfo(x, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindBooleanNePeriodicInduction) { @@ -968,8 +973,8 @@ TEST_F(InductionVarAnalysisTest, FindBooleanNePeriodicInduction) { k_header->AddInput(x); PerformInductionVarAnalysis(); - EXPECT_STREQ("periodic((0), (1)):PrimBoolean", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("periodic((1), (0)):PrimBoolean", GetInductionInfo(x, 0).c_str()); + EXPECT_STREQ("periodic((0), (1)):Bool", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("periodic((1), (0)):Bool", GetInductionInfo(x, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindBooleanNeConstantLeftPeriodicInduction) { @@ -986,8 +991,8 @@ TEST_F(InductionVarAnalysisTest, FindBooleanNeConstantLeftPeriodicInduction) { k_header->AddInput(x); PerformInductionVarAnalysis(); - EXPECT_STREQ("periodic((0), (1)):PrimBoolean", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("periodic((1), (0)):PrimBoolean", GetInductionInfo(x, 0).c_str()); + EXPECT_STREQ("periodic((0), (1)):Bool", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("periodic((1), (0)):Bool", GetInductionInfo(x, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindDerivedPeriodicInduction) { @@ -1007,30 +1012,30 @@ TEST_F(InductionVarAnalysisTest, FindDerivedPeriodicInduction) { k_header->AddInput(constant0_); HInstruction* neg1 = InsertInstruction( - new (&allocator_) HNeg(Primitive::kPrimInt, k_header), 0); + new (&allocator_) HNeg(DataType::Type::kInt32, k_header), 0); HInstruction* idiom = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, constant1_, k_header), 0); + new (&allocator_) HSub(DataType::Type::kInt32, constant1_, k_header), 0); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, idiom, constant100_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, idiom, constant100_), 0); HInstruction* sub = InsertInstruction( - new (&allocator_) HSub(Primitive::kPrimInt, idiom, constant100_), 0); + new (&allocator_) HSub(DataType::Type::kInt32, idiom, constant100_), 0); HInstruction* mul = InsertInstruction( - new (&allocator_) HMul(Primitive::kPrimInt, idiom, constant100_), 0); + new (&allocator_) HMul(DataType::Type::kInt32, idiom, constant100_), 0); HInstruction* shl = InsertInstruction( - new (&allocator_) HShl(Primitive::kPrimInt, idiom, constant1_), 0); + new (&allocator_) HShl(DataType::Type::kInt32, idiom, constant1_), 0); HInstruction* neg2 = InsertInstruction( - new (&allocator_) HNeg(Primitive::kPrimInt, idiom), 0); + new (&allocator_) HNeg(DataType::Type::kInt32, idiom), 0); k_header->AddInput(idiom); PerformInductionVarAnalysis(); - EXPECT_STREQ("periodic((0), (1)):PrimInt", GetInductionInfo(k_header, 0).c_str()); - EXPECT_STREQ("periodic((0), ( - (1))):PrimInt", GetInductionInfo(neg1, 0).c_str()); - EXPECT_STREQ("periodic((1), (0)):PrimInt", GetInductionInfo(idiom, 0).c_str()); - EXPECT_STREQ("periodic(((1) + (100)), (100)):PrimInt", GetInductionInfo(add, 0).c_str()); - EXPECT_STREQ("periodic(((1) - (100)), ((0) - (100))):PrimInt", GetInductionInfo(sub, 0).c_str()); - EXPECT_STREQ("periodic((100), (0)):PrimInt", GetInductionInfo(mul, 0).c_str()); - EXPECT_STREQ("periodic((2), (0)):PrimInt", GetInductionInfo(shl, 0).c_str()); - EXPECT_STREQ("periodic(( - (1)), (0)):PrimInt", GetInductionInfo(neg2, 0).c_str()); + EXPECT_STREQ("periodic((0), (1)):Int32", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("periodic((0), ( - (1))):Int32", GetInductionInfo(neg1, 0).c_str()); + EXPECT_STREQ("periodic((1), (0)):Int32", GetInductionInfo(idiom, 0).c_str()); + EXPECT_STREQ("periodic(((1) + (100)), (100)):Int32", GetInductionInfo(add, 0).c_str()); + EXPECT_STREQ("periodic(((1) - (100)), ((0) - (100))):Int32", GetInductionInfo(sub, 0).c_str()); + EXPECT_STREQ("periodic((100), (0)):Int32", GetInductionInfo(mul, 0).c_str()); + EXPECT_STREQ("periodic((2), (0)):Int32", GetInductionInfo(shl, 0).c_str()); + EXPECT_STREQ("periodic(( - (1)), (0)):Int32", GetInductionInfo(neg2, 0).c_str()); } TEST_F(InductionVarAnalysisTest, FindDeepLoopInduction) { @@ -1052,7 +1057,7 @@ TEST_F(InductionVarAnalysisTest, FindDeepLoopInduction) { } HInstruction* inc = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, constant1_, k_header[9]), 9); + new (&allocator_) HAdd(DataType::Type::kInt32, constant1_, k_header[9]), 9); HInstruction* store = InsertArrayStore(inc, 9); for (int d = 0; d < 10; d++) { @@ -1063,7 +1068,7 @@ TEST_F(InductionVarAnalysisTest, FindDeepLoopInduction) { // Avoid exact phi number, since that depends on the SSA building phase. std::regex r("\\(\\(1\\) \\* i \\+ " - "\\(\\(1\\) \\+ \\(\\d+:Phi\\)\\)\\):PrimInt"); + "\\(\\(1\\) \\+ \\(\\d+:Phi\\)\\)\\):Int32"); for (int d = 0; d < 10; d++) { if (d == 9) { @@ -1071,7 +1076,7 @@ TEST_F(InductionVarAnalysisTest, FindDeepLoopInduction) { } else { EXPECT_STREQ("", GetInductionInfo(store->InputAt(1), d).c_str()); } - EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(increment_[d], d).c_str()); + EXPECT_STREQ("((1) * i + (1)):Int32", GetInductionInfo(increment_[d], d).c_str()); // Trip-count. EXPECT_STREQ("((100) (TC-loop) ((0) < (100)))", GetTripCount(d).c_str()); } @@ -1086,15 +1091,15 @@ TEST_F(InductionVarAnalysisTest, ByteInductionIntLoopControl) { // } BuildLoopNest(1); HInstruction* conv = InsertInstruction( - new (&allocator_) HTypeConversion(Primitive::kPrimByte, basic_[0], kNoDexPc), 0); + new (&allocator_) HTypeConversion(DataType::Type::kInt8, basic_[0], kNoDexPc), 0); HInstruction* store1 = InsertArrayStore(conv, 0); HInstruction* store2 = InsertArrayStore(basic_[0], 0); PerformInductionVarAnalysis(); // Regular int induction (i) is transferred over conversion into byte induction (k). - EXPECT_STREQ("((1) * i + (0)):PrimByte", GetInductionInfo(store1->InputAt(1), 0).c_str()); - EXPECT_STREQ("((1) * i + (0)):PrimInt", GetInductionInfo(store2->InputAt(1), 0).c_str()); - EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(increment_[0], 0).c_str()); + EXPECT_STREQ("((1) * i + (0)):Int8", GetInductionInfo(store1->InputAt(1), 0).c_str()); + EXPECT_STREQ("((1) * i + (0)):Int32", GetInductionInfo(store2->InputAt(1), 0).c_str()); + EXPECT_STREQ("((1) * i + (1)):Int32", GetInductionInfo(increment_[0], 0).c_str()); // Narrowing detected. EXPECT_TRUE(IsNarrowingLinear(store1->InputAt(1))); @@ -1117,17 +1122,17 @@ TEST_F(InductionVarAnalysisTest, ByteInductionDerivedIntLoopControl) { // } BuildLoopNest(1); HInstruction* conv = InsertInstruction( - new (&allocator_) HTypeConversion(Primitive::kPrimByte, basic_[0], kNoDexPc), 0); + new (&allocator_) HTypeConversion(DataType::Type::kInt8, basic_[0], kNoDexPc), 0); HInstruction* store1 = InsertArrayStore(conv, 0); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, conv, constant1_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, conv, constant1_), 0); HInstruction* store2 = InsertArrayStore(add, 0); PerformInductionVarAnalysis(); // Byte induction (k) is detected, but it does not transfer over the addition, // since this may yield out-of-type values. - EXPECT_STREQ("((1) * i + (0)):PrimByte", GetInductionInfo(store1->InputAt(1), 0).c_str()); + EXPECT_STREQ("((1) * i + (0)):Int8", GetInductionInfo(store1->InputAt(1), 0).c_str()); EXPECT_STREQ("", GetInductionInfo(store2->InputAt(1), 0).c_str()); // Narrowing detected. @@ -1147,15 +1152,15 @@ TEST_F(InductionVarAnalysisTest, ByteInduction) { k_header->AddInput(graph_->GetIntConstant(-128)); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, constant1_), 0); HInstruction* conv = InsertInstruction( - new (&allocator_) HTypeConversion(Primitive::kPrimByte, add, kNoDexPc), 0); + new (&allocator_) HTypeConversion(DataType::Type::kInt8, add, kNoDexPc), 0); k_header->AddInput(conv); PerformInductionVarAnalysis(); // Byte induction (k) is detected, but it does not transfer over the addition, // since this may yield out-of-type values. - EXPECT_STREQ("((1) * i + (-128)):PrimByte", GetInductionInfo(k_header, 0).c_str()); + EXPECT_STREQ("((1) * i + (-128)):Int8", GetInductionInfo(k_header, 0).c_str()); EXPECT_STREQ("", GetInductionInfo(add, 0).c_str()); // Narrowing detected. @@ -1175,9 +1180,9 @@ TEST_F(InductionVarAnalysisTest, NoByteInduction1) { k_header->AddInput(graph_->GetIntConstant(-129)); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant1_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, k_header, constant1_), 0); HInstruction* conv = InsertInstruction( - new (&allocator_) HTypeConversion(Primitive::kPrimByte, add, kNoDexPc), 0); + new (&allocator_) HTypeConversion(DataType::Type::kInt8, add, kNoDexPc), 0); k_header->AddInput(conv); PerformInductionVarAnalysis(); @@ -1197,9 +1202,9 @@ TEST_F(InductionVarAnalysisTest, NoByteInduction2) { k_header->AddInput(constant0_); HInstruction* conv = InsertInstruction( - new (&allocator_) HTypeConversion(Primitive::kPrimByte, k_header, kNoDexPc), 0); + new (&allocator_) HTypeConversion(DataType::Type::kInt8, k_header, kNoDexPc), 0); HInstruction* add = InsertInstruction( - new (&allocator_) HAdd(Primitive::kPrimInt, conv, constant1_), 0); + new (&allocator_) HAdd(DataType::Type::kInt32, conv, constant1_), 0); k_header->AddInput(add); PerformInductionVarAnalysis(); @@ -1216,13 +1221,13 @@ TEST_F(InductionVarAnalysisTest, ByteLoopControl1) { HInstruction* ifs = loop_header_[0]->GetLastInstruction()->GetPrevious(); ifs->ReplaceInput(graph_->GetIntConstant(127), 1); HInstruction* conv = - new (&allocator_) HTypeConversion(Primitive::kPrimByte, increment_[0], kNoDexPc); + new (&allocator_) HTypeConversion(DataType::Type::kInt8, increment_[0], kNoDexPc); loop_body_[0]->InsertInstructionBefore(conv, increment_[0]->GetNext()); basic_[0]->ReplaceInput(conv, 1); PerformInductionVarAnalysis(); // Recorded at the phi, but not transferred to increment. - EXPECT_STREQ("((1) * i + (-128)):PrimByte", GetInductionInfo(basic_[0], 0).c_str()); + EXPECT_STREQ("((1) * i + (-128)):Int8", GetInductionInfo(basic_[0], 0).c_str()); EXPECT_STREQ("", GetInductionInfo(increment_[0], 0).c_str()); // Narrowing detected. @@ -1242,13 +1247,13 @@ TEST_F(InductionVarAnalysisTest, ByteLoopControl2) { HInstruction* ifs = loop_header_[0]->GetLastInstruction()->GetPrevious(); ifs->ReplaceInput(graph_->GetIntConstant(128), 1); HInstruction* conv = - new (&allocator_) HTypeConversion(Primitive::kPrimByte, increment_[0], kNoDexPc); + new (&allocator_) HTypeConversion(DataType::Type::kInt8, increment_[0], kNoDexPc); loop_body_[0]->InsertInstructionBefore(conv, increment_[0]->GetNext()); basic_[0]->ReplaceInput(conv, 1); PerformInductionVarAnalysis(); // Recorded at the phi, but not transferred to increment. - EXPECT_STREQ("((1) * i + (-128)):PrimByte", GetInductionInfo(basic_[0], 0).c_str()); + EXPECT_STREQ("((1) * i + (-128)):Int8", GetInductionInfo(basic_[0], 0).c_str()); EXPECT_STREQ("", GetInductionInfo(increment_[0], 0).c_str()); // Narrowing detected. @@ -1268,13 +1273,13 @@ TEST_F(InductionVarAnalysisTest, ShortLoopControl1) { HInstruction* ifs = loop_header_[0]->GetLastInstruction()->GetPrevious(); ifs->ReplaceInput(graph_->GetIntConstant(32767), 1); HInstruction* conv = - new (&allocator_) HTypeConversion(Primitive::kPrimShort, increment_[0], kNoDexPc); + new (&allocator_) HTypeConversion(DataType::Type::kInt16, increment_[0], kNoDexPc); loop_body_[0]->InsertInstructionBefore(conv, increment_[0]->GetNext()); basic_[0]->ReplaceInput(conv, 1); PerformInductionVarAnalysis(); // Recorded at the phi, but not transferred to increment. - EXPECT_STREQ("((1) * i + (-32768)):PrimShort", GetInductionInfo(basic_[0], 0).c_str()); + EXPECT_STREQ("((1) * i + (-32768)):Int16", GetInductionInfo(basic_[0], 0).c_str()); EXPECT_STREQ("", GetInductionInfo(increment_[0], 0).c_str()); // Narrowing detected. @@ -1294,13 +1299,13 @@ TEST_F(InductionVarAnalysisTest, ShortLoopControl2) { HInstruction* ifs = loop_header_[0]->GetLastInstruction()->GetPrevious(); ifs->ReplaceInput(graph_->GetIntConstant(32768), 1); HInstruction* conv = - new (&allocator_) HTypeConversion(Primitive::kPrimShort, increment_[0], kNoDexPc); + new (&allocator_) HTypeConversion(DataType::Type::kInt16, increment_[0], kNoDexPc); loop_body_[0]->InsertInstructionBefore(conv, increment_[0]->GetNext()); basic_[0]->ReplaceInput(conv, 1); PerformInductionVarAnalysis(); // Recorded at the phi, but not transferred to increment. - EXPECT_STREQ("((1) * i + (-32768)):PrimShort", GetInductionInfo(basic_[0], 0).c_str()); + EXPECT_STREQ("((1) * i + (-32768)):Int16", GetInductionInfo(basic_[0], 0).c_str()); EXPECT_STREQ("", GetInductionInfo(increment_[0], 0).c_str()); // Narrowing detected. @@ -1319,13 +1324,13 @@ TEST_F(InductionVarAnalysisTest, CharLoopControl1) { HInstruction* ifs = loop_header_[0]->GetLastInstruction()->GetPrevious(); ifs->ReplaceInput(graph_->GetIntConstant(65535), 1); HInstruction* conv = - new (&allocator_) HTypeConversion(Primitive::kPrimChar, increment_[0], kNoDexPc); + new (&allocator_) HTypeConversion(DataType::Type::kUint16, increment_[0], kNoDexPc); loop_body_[0]->InsertInstructionBefore(conv, increment_[0]->GetNext()); basic_[0]->ReplaceInput(conv, 1); PerformInductionVarAnalysis(); // Recorded at the phi, but not transferred to increment. - EXPECT_STREQ("((1) * i + (0)):PrimChar", GetInductionInfo(basic_[0], 0).c_str()); + EXPECT_STREQ("((1) * i + (0)):Uint16", GetInductionInfo(basic_[0], 0).c_str()); EXPECT_STREQ("", GetInductionInfo(increment_[0], 0).c_str()); // Narrowing detected. @@ -1344,13 +1349,13 @@ TEST_F(InductionVarAnalysisTest, CharLoopControl2) { HInstruction* ifs = loop_header_[0]->GetLastInstruction()->GetPrevious(); ifs->ReplaceInput(graph_->GetIntConstant(65536), 1); HInstruction* conv = - new (&allocator_) HTypeConversion(Primitive::kPrimChar, increment_[0], kNoDexPc); + new (&allocator_) HTypeConversion(DataType::Type::kUint16, increment_[0], kNoDexPc); loop_body_[0]->InsertInstructionBefore(conv, increment_[0]->GetNext()); basic_[0]->ReplaceInput(conv, 1); PerformInductionVarAnalysis(); // Recorded at the phi, but not transferred to increment. - EXPECT_STREQ("((1) * i + (0)):PrimChar", GetInductionInfo(basic_[0], 0).c_str()); + EXPECT_STREQ("((1) * i + (0)):Uint16", GetInductionInfo(basic_[0], 0).c_str()); EXPECT_STREQ("", GetInductionInfo(increment_[0], 0).c_str()); // Narrowing detected. diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc index 191d3d128c..92b584cc3b 100644 --- a/compiler/optimizing/induction_var_range.cc +++ b/compiler/optimizing/induction_var_range.cc @@ -157,15 +157,15 @@ static bool IsConstantValue(InductionVarRange::Value v) { } /** Corrects a value for type to account for arithmetic wrap-around in lower precision. */ -static InductionVarRange::Value CorrectForType(InductionVarRange::Value v, Primitive::Type type) { +static InductionVarRange::Value CorrectForType(InductionVarRange::Value v, DataType::Type type) { switch (type) { - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimByte: { + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt8: { // Constants within range only. // TODO: maybe some room for improvement, like allowing widening conversions - int32_t min = Primitive::MinValueOfIntegralType(type); - int32_t max = Primitive::MaxValueOfIntegralType(type); + int32_t min = DataType::MinValueOfIntegralType(type); + int32_t max = DataType::MaxValueOfIntegralType(type); return (IsConstantValue(v) && min <= v.b_constant && v.b_constant <= max) ? v : InductionVarRange::Value(); @@ -216,10 +216,10 @@ bool InductionVarRange::GetInductionRange(HInstruction* context, // bounds check elimination, will have truncated higher precision induction // at their use point already). switch (info->type) { - case Primitive::kPrimInt: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimByte: + case DataType::Type::kInt32: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt8: break; default: return false; @@ -689,8 +689,8 @@ InductionVarRange::Value InductionVarRange::GetFetch(HInstruction* instruction, } else if (instruction->IsTypeConversion()) { // Since analysis is 32-bit (or narrower), chase beyond widening along the path. // For example, this discovers the length in: for (long i = 0; i < a.length; i++); - if (instruction->AsTypeConversion()->GetInputType() == Primitive::kPrimInt && - instruction->AsTypeConversion()->GetResultType() == Primitive::kPrimLong) { + if (instruction->AsTypeConversion()->GetInputType() == DataType::Type::kInt32 && + instruction->AsTypeConversion()->GetResultType() == DataType::Type::kInt64) { return GetFetch(instruction->InputAt(0), trip, in_body, is_min); } } @@ -1051,9 +1051,9 @@ bool InductionVarRange::GenerateLastValuePolynomial(HInductionVarAnalysis::Induc HInstruction* c = nullptr; if (GenerateCode(info->op_b, nullptr, graph, block, graph ? &c : nullptr, false, false)) { if (graph != nullptr) { - Primitive::Type type = info->type; + DataType::Type type = info->type; int64_t sum = a * ((m * (m - 1)) / 2) + b * m; - if (type != Primitive::kPrimLong) { + if (type != DataType::Type::kInt64) { sum = static_cast<int32_t>(sum); // okay to truncate } *result = @@ -1081,16 +1081,16 @@ bool InductionVarRange::GenerateLastValueGeometric(HInductionVarAnalysis::Induct if (GenerateCode(info->op_a, nullptr, graph, block, &opa, false, false) && GenerateCode(info->op_b, nullptr, graph, block, &opb, false, false)) { if (graph != nullptr) { - Primitive::Type type = info->type; + DataType::Type type = info->type; // Compute f ^ m for known maximum index value m. bool overflow = false; int64_t fpow = IntPow(f, m, &overflow); if (info->operation == HInductionVarAnalysis::kDiv) { // For division, any overflow truncates to zero. - if (overflow || (type != Primitive::kPrimLong && !CanLongValueFitIntoInt(fpow))) { + if (overflow || (type != DataType::Type::kInt64 && !CanLongValueFitIntoInt(fpow))) { fpow = 0; } - } else if (type != Primitive::kPrimLong) { + } else if (type != DataType::Type::kInt64) { // For multiplication, okay to truncate to required precision. DCHECK(info->operation == HInductionVarAnalysis::kMul); fpow = static_cast<int32_t>(fpow); @@ -1161,7 +1161,7 @@ bool InductionVarRange::GenerateLastValuePeriodic(HInductionVarAnalysis::Inducti } // Don't rely on FP arithmetic to be precise, unless the full period // consist of pre-computed expressions only. - if (info->type == Primitive::kPrimFloat || info->type == Primitive::kPrimDouble) { + if (info->type == DataType::Type::kFloat32 || info->type == DataType::Type::kFloat64) { if (!all_invariants) { return false; } @@ -1187,7 +1187,7 @@ bool InductionVarRange::GenerateLastValuePeriodic(HInductionVarAnalysis::Inducti GenerateCode(trip->op_a, nullptr, graph, block, graph ? &t : nullptr, false, false)) { // During actual code generation (graph != nullptr), generate is_even ? x : y. if (graph != nullptr) { - Primitive::Type type = trip->type; + DataType::Type type = trip->type; HInstruction* msk = Insert(block, new (graph->GetArena()) HAnd(type, t, graph->GetConstant(type, 1))); HInstruction* is_even = @@ -1224,7 +1224,7 @@ bool InductionVarRange::GenerateCode(HInductionVarAnalysis::InductionInfo* info, return true; } // Handle current operation. - Primitive::Type type = info->type; + DataType::Type type = info->type; HInstruction* opa = nullptr; HInstruction* opb = nullptr; switch (info->induction_class) { diff --git a/compiler/optimizing/induction_var_range_test.cc b/compiler/optimizing/induction_var_range_test.cc index 9437014407..1c8426954b 100644 --- a/compiler/optimizing/induction_var_range_test.cc +++ b/compiler/optimizing/induction_var_range_test.cc @@ -71,12 +71,12 @@ class InductionVarRangeTest : public CommonCompilerTest { x_ = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimInt); + DataType::Type::kInt32); entry_block_->AddInstruction(x_); y_ = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimInt); + DataType::Type::kInt32); entry_block_->AddInstruction(y_); // Set arbitrary range analysis hint while testing private methods. SetHint(x_); @@ -101,7 +101,7 @@ class InductionVarRangeTest : public CommonCompilerTest { return_block->AddSuccessor(exit_block_); // Instructions. loop_preheader_->AddInstruction(new (&allocator_) HGoto()); - HPhi* phi = new (&allocator_) HPhi(&allocator_, 0, 0, Primitive::kPrimInt); + HPhi* phi = new (&allocator_) HPhi(&allocator_, 0, 0, DataType::Type::kInt32); loop_header_->AddPhi(phi); phi->AddInput(graph_->GetIntConstant(lower)); // i = l if (stride > 0) { @@ -111,7 +111,8 @@ class InductionVarRangeTest : public CommonCompilerTest { } loop_header_->AddInstruction(condition_); loop_header_->AddInstruction(new (&allocator_) HIf(condition_)); - increment_ = new (&allocator_) HAdd(Primitive::kPrimInt, phi, graph_->GetIntConstant(stride)); + increment_ = + new (&allocator_) HAdd(DataType::Type::kInt32, phi, graph_->GetIntConstant(stride)); loop_body_->AddInstruction(increment_); // i += s phi->AddInput(increment_); loop_body_->AddInstruction(new (&allocator_) HGoto()); @@ -173,7 +174,7 @@ class InductionVarRangeTest : public CommonCompilerTest { return iva_->CreateTripCount(op, CreateConst(tc), CreateInvariant('<', CreateConst(0), CreateConst(tc)), - Primitive::kPrimInt); + DataType::Type::kInt32); } /** Constructs a linear a * i + b induction. */ @@ -183,7 +184,7 @@ class InductionVarRangeTest : public CommonCompilerTest { CreateConst(a), CreateConst(b), nullptr, - Primitive::kPrimInt); + DataType::Type::kInt32); } /** Constructs a polynomial sum(a * i + b) + c induction. */ @@ -193,7 +194,7 @@ class InductionVarRangeTest : public CommonCompilerTest { CreateLinear(a, b), CreateConst(c), nullptr, - Primitive::kPrimInt); + DataType::Type::kInt32); } /** Constructs a geometric a * f^i + b induction. */ @@ -204,7 +205,7 @@ class InductionVarRangeTest : public CommonCompilerTest { CreateConst(a), CreateConst(b), graph_->GetIntConstant(f), - Primitive::kPrimInt); + DataType::Type::kInt32); } /** Constructs a range [lo, hi] using a periodic induction. */ @@ -214,7 +215,7 @@ class InductionVarRangeTest : public CommonCompilerTest { CreateConst(lo), CreateConst(hi), nullptr, - Primitive::kPrimInt); + DataType::Type::kInt32); } /** Constructs a wrap-around induction consisting of a constant, followed by info. */ @@ -226,7 +227,7 @@ class InductionVarRangeTest : public CommonCompilerTest { CreateConst(initial), info, nullptr, - Primitive::kPrimInt); + DataType::Type::kInt32); } /** Constructs a wrap-around induction consisting of a constant, followed by a range. */ @@ -725,13 +726,13 @@ TEST_F(InductionVarRangeTest, ArrayLengthAndHints) { TEST_F(InductionVarRangeTest, AddOrSubAndConstant) { HInstruction* add = new (&allocator_) - HAdd(Primitive::kPrimInt, x_, graph_->GetIntConstant(-1)); + HAdd(DataType::Type::kInt32, x_, graph_->GetIntConstant(-1)); HInstruction* alt = new (&allocator_) - HAdd(Primitive::kPrimInt, graph_->GetIntConstant(-1), x_); + HAdd(DataType::Type::kInt32, graph_->GetIntConstant(-1), x_); HInstruction* sub = new (&allocator_) - HSub(Primitive::kPrimInt, x_, graph_->GetIntConstant(1)); + HSub(DataType::Type::kInt32, x_, graph_->GetIntConstant(1)); HInstruction* rev = new (&allocator_) - HSub(Primitive::kPrimInt, graph_->GetIntConstant(1), x_); + HSub(DataType::Type::kInt32, graph_->GetIntConstant(1), x_); entry_block_->AddInstruction(add); entry_block_->AddInstruction(alt); entry_block_->AddInstruction(sub); diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 793e781bae..90e3d2ade7 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -21,6 +21,7 @@ #include "builder.h" #include "class_linker.h" #include "constant_folding.h" +#include "data_type-inl.h" #include "dead_code_elimination.h" #include "dex/inline_method_analyser.h" #include "dex/verification_results.h" @@ -707,7 +708,7 @@ HInstanceFieldGet* HInliner::BuildGetReceiverClass(ClassLinker* class_linker, HInstanceFieldGet* result = new (graph_->GetArena()) HInstanceFieldGet( receiver, field, - Primitive::kPrimNot, + DataType::Type::kReference, field->GetOffset(), field->IsVolatile(), field->GetDexFieldIndex(), @@ -1143,9 +1144,9 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget( HInstanceFieldGet* receiver_class = BuildGetReceiverClass( class_linker, receiver, invoke_instruction->GetDexPc()); - Primitive::Type type = Is64BitInstructionSet(graph_->GetInstructionSet()) - ? Primitive::kPrimLong - : Primitive::kPrimInt; + DataType::Type type = Is64BitInstructionSet(graph_->GetInstructionSet()) + ? DataType::Type::kInt64 + : DataType::Type::kInt32; HClassTableGet* class_table_get = new (graph_->GetArena()) HClassTableGet( receiver_class, type, @@ -1155,7 +1156,7 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget( invoke_instruction->GetDexPc()); HConstant* constant; - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { constant = graph_->GetLongConstant( reinterpret_cast<intptr_t>(actual_method), invoke_instruction->GetDexPc()); } else { @@ -1253,7 +1254,7 @@ bool HInliner::TryInlineAndReplace(HInvoke* invoke_instruction, } invoke_instruction->GetBlock()->InsertInstructionBefore(new_invoke, invoke_instruction); new_invoke->CopyEnvironmentFrom(invoke_instruction->GetEnvironment()); - if (invoke_instruction->GetType() == Primitive::kPrimNot) { + if (invoke_instruction->GetType() == DataType::Type::kReference) { new_invoke->SetReferenceTypeInfo(invoke_instruction->GetReferenceTypeInfo()); } return_replacement = new_invoke; @@ -1403,7 +1404,7 @@ static HInstruction* GetInvokeInputForArgVRegIndex(HInvoke* invoke_instruction, size_t input_index = 0; for (size_t i = 0; i < arg_vreg_index; ++i, ++input_index) { DCHECK_LT(input_index, invoke_instruction->GetNumberOfArguments()); - if (Primitive::Is64BitType(invoke_instruction->InputAt(input_index)->GetType())) { + if (DataType::Is64BitType(invoke_instruction->InputAt(input_index)->GetType())) { ++i; DCHECK_NE(i, arg_vreg_index); } @@ -1423,7 +1424,7 @@ bool HInliner::TryPatternSubstitution(HInvoke* invoke_instruction, switch (inline_method.opcode) { case kInlineOpNop: - DCHECK_EQ(invoke_instruction->GetType(), Primitive::kPrimVoid); + DCHECK_EQ(invoke_instruction->GetType(), DataType::Type::kVoid); *return_replacement = nullptr; break; case kInlineOpReturnArg: @@ -1541,7 +1542,7 @@ HInstanceFieldGet* HInliner::CreateInstanceFieldGet(uint32_t field_index, HInstanceFieldGet* iget = new (graph_->GetArena()) HInstanceFieldGet( obj, resolved_field, - resolved_field->GetTypeAsPrimitiveType(), + DataType::FromShorty(resolved_field->GetTypeDescriptor()[0]), resolved_field->GetOffset(), resolved_field->IsVolatile(), field_index, @@ -1550,7 +1551,7 @@ HInstanceFieldGet* HInliner::CreateInstanceFieldGet(uint32_t field_index, // Read barrier generates a runtime call in slow path and we need a valid // dex pc for the associated stack map. 0 is bogus but valid. Bug: 26854537. /* dex_pc */ 0); - if (iget->GetType() == Primitive::kPrimNot) { + if (iget->GetType() == DataType::Type::kReference) { // Use the same dex_cache that we used for field lookup as the hint_dex_cache. Handle<mirror::DexCache> dex_cache = handles_->NewHandle(referrer->GetDexCache()); ReferenceTypePropagation rtp(graph_, @@ -1582,7 +1583,7 @@ HInstanceFieldSet* HInliner::CreateInstanceFieldSet(uint32_t field_index, obj, value, resolved_field, - resolved_field->GetTypeAsPrimitiveType(), + DataType::FromShorty(resolved_field->GetTypeDescriptor()[0]), resolved_field->GetOffset(), resolved_field->IsVolatile(), field_index, @@ -1667,8 +1668,6 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, HGraphBuilder builder(callee_graph, &dex_compilation_unit, &outer_compilation_unit_, - resolved_method->GetDexFile(), - *code_item, compiler_driver_, codegen_, inline_stats_, @@ -1711,7 +1710,7 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, } else if (argument->IsDoubleConstant()) { current->ReplaceWith( callee_graph->GetDoubleConstant(argument->AsDoubleConstant()->GetValue())); - } else if (argument->GetType() == Primitive::kPrimNot) { + } else if (argument->GetType() == DataType::Type::kReference) { if (!resolved_method->IsStatic() && parameter_index == 0 && receiver_type.IsValid()) { run_rtp = true; current->SetReferenceTypeInfo(receiver_type); @@ -1975,7 +1974,7 @@ bool HInliner::ArgumentTypesMoreSpecific(HInvoke* invoke_instruction, ArtMethod* param_idx < e; ++param_idx, ++input_idx) { HInstruction* input = invoke_instruction->InputAt(input_idx); - if (input->GetType() == Primitive::kPrimNot) { + if (input->GetType() == DataType::Type::kReference) { ObjPtr<mirror::Class> param_cls = resolved_method->LookupResolvedClassFromTypeIndex( param_list->GetTypeItem(param_idx).type_idx_); if (IsReferenceTypeRefinement(GetClassRTI(param_cls), @@ -1993,7 +1992,7 @@ bool HInliner::ReturnTypeMoreSpecific(HInvoke* invoke_instruction, HInstruction* return_replacement) { // Check the integrity of reference types and run another type propagation if needed. if (return_replacement != nullptr) { - if (return_replacement->GetType() == Primitive::kPrimNot) { + if (return_replacement->GetType() == DataType::Type::kReference) { // Test if the return type is a refinement of the declared return type. if (IsReferenceTypeRefinement(invoke_instruction->GetReferenceTypeInfo(), /* declared_can_be_null */ true, @@ -2019,7 +2018,7 @@ bool HInliner::ReturnTypeMoreSpecific(HInvoke* invoke_instruction, void HInliner::FixUpReturnReferenceType(ArtMethod* resolved_method, HInstruction* return_replacement) { if (return_replacement != nullptr) { - if (return_replacement->GetType() == Primitive::kPrimNot) { + if (return_replacement->GetType() == DataType::Type::kReference) { if (!return_replacement->GetReferenceTypeInfo().IsValid()) { // Make sure that we have a valid type for the return. We may get an invalid one when // we inline invokes with multiple branches and create a Phi for the result. diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 6532ec123d..6ad8036870 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -19,6 +19,7 @@ #include "art_method-inl.h" #include "bytecode_utils.h" #include "class_linker.h" +#include "data_type-inl.h" #include "dex_instruction-inl.h" #include "driver/compiler_options.h" #include "imtable-inl.h" @@ -221,7 +222,7 @@ void HInstructionBuilder::InitializeInstruction(HInstruction* instruction) { } HInstruction* HInstructionBuilder::LoadNullCheckedLocal(uint32_t register_index, uint32_t dex_pc) { - HInstruction* ref = LoadLocal(register_index, Primitive::kPrimNot); + HInstruction* ref = LoadLocal(register_index, DataType::Type::kReference); if (!ref->CanBeNull()) { return ref; } @@ -367,17 +368,16 @@ void HInstructionBuilder::FindNativeDebugInfoLocations(ArenaBitVector* locations }; dex_file_->DecodeDebugPositionInfo(&code_item_, Callback::Position, locations); // Instruction-specific tweaks. - const Instruction* const begin = Instruction::At(code_item_.insns_); - const Instruction* const end = begin->RelativeAt(code_item_.insns_size_in_code_units_); - for (const Instruction* inst = begin; inst < end; inst = inst->Next()) { - switch (inst->Opcode()) { + IterationRange<DexInstructionIterator> instructions = code_item_.Instructions(); + for (const Instruction& inst : instructions) { + switch (inst.Opcode()) { case Instruction::MOVE_EXCEPTION: { // Stop in native debugger after the exception has been moved. // The compiler also expects the move at the start of basic block so // we do not want to interfere by inserting native-debug-info before it. - locations->ClearBit(inst->GetDexPc(code_item_.insns_)); - const Instruction* next = inst->Next(); - if (next < end) { + locations->ClearBit(inst.GetDexPc(code_item_.insns_)); + const Instruction* next = inst.Next(); + if (DexInstructionIterator(next) != instructions.end()) { locations->SetBit(next->GetDexPc(code_item_.insns_)); } break; @@ -388,15 +388,15 @@ void HInstructionBuilder::FindNativeDebugInfoLocations(ArenaBitVector* locations } } -HInstruction* HInstructionBuilder::LoadLocal(uint32_t reg_number, Primitive::Type type) const { +HInstruction* HInstructionBuilder::LoadLocal(uint32_t reg_number, DataType::Type type) const { HInstruction* value = (*current_locals_)[reg_number]; DCHECK(value != nullptr); // If the operation requests a specific type, we make sure its input is of that type. if (type != value->GetType()) { - if (Primitive::IsFloatingPointType(type)) { + if (DataType::IsFloatingPointType(type)) { value = ssa_builder_->GetFloatOrDoubleEquivalent(value, type); - } else if (type == Primitive::kPrimNot) { + } else if (type == DataType::Type::kReference) { value = ssa_builder_->GetReferenceTypeEquivalent(value); } DCHECK(value != nullptr); @@ -406,8 +406,8 @@ HInstruction* HInstructionBuilder::LoadLocal(uint32_t reg_number, Primitive::Typ } void HInstructionBuilder::UpdateLocal(uint32_t reg_number, HInstruction* stored_value) { - Primitive::Type stored_type = stored_value->GetType(); - DCHECK_NE(stored_type, Primitive::kPrimVoid); + DataType::Type stored_type = stored_value->GetType(); + DCHECK_NE(stored_type, DataType::Type::kVoid); // Storing into vreg `reg_number` may implicitly invalidate the surrounding // registers. Consider the following cases: @@ -420,7 +420,7 @@ void HInstructionBuilder::UpdateLocal(uint32_t reg_number, HInstruction* stored_ if (reg_number != 0) { HInstruction* local_low = (*current_locals_)[reg_number - 1]; - if (local_low != nullptr && Primitive::Is64BitType(local_low->GetType())) { + if (local_low != nullptr && DataType::Is64BitType(local_low->GetType())) { // The vreg we are storing into was previously the high vreg of a pair. // We need to invalidate its low vreg. DCHECK((*current_locals_)[reg_number] == nullptr); @@ -429,7 +429,7 @@ void HInstructionBuilder::UpdateLocal(uint32_t reg_number, HInstruction* stored_ } (*current_locals_)[reg_number] = stored_value; - if (Primitive::Is64BitType(stored_type)) { + if (DataType::Is64BitType(stored_type)) { // We are storing a pair. Invalidate the instruction in the high vreg. (*current_locals_)[reg_number + 1] = nullptr; } @@ -455,7 +455,7 @@ void HInstructionBuilder::InitializeParameters() { HParameterValue* parameter = new (arena_) HParameterValue(*dex_file_, referrer_method_id.class_idx_, parameter_index++, - Primitive::kPrimNot, + DataType::Type::kReference, /* is_this */ true); AppendInstruction(parameter); UpdateLocal(locals_index++, parameter); @@ -472,14 +472,14 @@ void HInstructionBuilder::InitializeParameters() { *dex_file_, arg_types->GetTypeItem(shorty_pos - 1).type_idx_, parameter_index++, - Primitive::GetType(shorty[shorty_pos]), + DataType::FromShorty(shorty[shorty_pos]), /* is_this */ false); ++shorty_pos; AppendInstruction(parameter); // Store the parameter value in the local that the dex code will use // to reference that parameter. UpdateLocal(locals_index++, parameter); - if (Primitive::Is64BitType(parameter->GetType())) { + if (DataType::Is64BitType(parameter->GetType())) { i++; locals_index++; parameter_index++; @@ -489,8 +489,8 @@ void HInstructionBuilder::InitializeParameters() { template<typename T> void HInstructionBuilder::If_22t(const Instruction& instruction, uint32_t dex_pc) { - HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt); - HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); + HInstruction* first = LoadLocal(instruction.VRegA(), DataType::Type::kInt32); + HInstruction* second = LoadLocal(instruction.VRegB(), DataType::Type::kInt32); T* comparison = new (arena_) T(first, second, dex_pc); AppendInstruction(comparison); AppendInstruction(new (arena_) HIf(comparison, dex_pc)); @@ -499,7 +499,7 @@ void HInstructionBuilder::If_22t(const Instruction& instruction, uint32_t dex_pc template<typename T> void HInstructionBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc) { - HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt); + HInstruction* value = LoadLocal(instruction.VRegA(), DataType::Type::kInt32); T* comparison = new (arena_) T(value, graph_->GetIntConstant(0, dex_pc), dex_pc); AppendInstruction(comparison); AppendInstruction(new (arena_) HIf(comparison, dex_pc)); @@ -508,7 +508,7 @@ void HInstructionBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc template<typename T> void HInstructionBuilder::Unop_12x(const Instruction& instruction, - Primitive::Type type, + DataType::Type type, uint32_t dex_pc) { HInstruction* first = LoadLocal(instruction.VRegB(), type); AppendInstruction(new (arena_) T(type, first, dex_pc)); @@ -516,8 +516,8 @@ void HInstructionBuilder::Unop_12x(const Instruction& instruction, } void HInstructionBuilder::Conversion_12x(const Instruction& instruction, - Primitive::Type input_type, - Primitive::Type result_type, + DataType::Type input_type, + DataType::Type result_type, uint32_t dex_pc) { HInstruction* first = LoadLocal(instruction.VRegB(), input_type); AppendInstruction(new (arena_) HTypeConversion(result_type, first, dex_pc)); @@ -526,7 +526,7 @@ void HInstructionBuilder::Conversion_12x(const Instruction& instruction, template<typename T> void HInstructionBuilder::Binop_23x(const Instruction& instruction, - Primitive::Type type, + DataType::Type type, uint32_t dex_pc) { HInstruction* first = LoadLocal(instruction.VRegB(), type); HInstruction* second = LoadLocal(instruction.VRegC(), type); @@ -536,16 +536,16 @@ void HInstructionBuilder::Binop_23x(const Instruction& instruction, template<typename T> void HInstructionBuilder::Binop_23x_shift(const Instruction& instruction, - Primitive::Type type, + DataType::Type type, uint32_t dex_pc) { HInstruction* first = LoadLocal(instruction.VRegB(), type); - HInstruction* second = LoadLocal(instruction.VRegC(), Primitive::kPrimInt); + HInstruction* second = LoadLocal(instruction.VRegC(), DataType::Type::kInt32); AppendInstruction(new (arena_) T(type, first, second, dex_pc)); UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); } void HInstructionBuilder::Binop_23x_cmp(const Instruction& instruction, - Primitive::Type type, + DataType::Type type, ComparisonBias bias, uint32_t dex_pc) { HInstruction* first = LoadLocal(instruction.VRegB(), type); @@ -556,17 +556,17 @@ void HInstructionBuilder::Binop_23x_cmp(const Instruction& instruction, template<typename T> void HInstructionBuilder::Binop_12x_shift(const Instruction& instruction, - Primitive::Type type, + DataType::Type type, uint32_t dex_pc) { HInstruction* first = LoadLocal(instruction.VRegA(), type); - HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); + HInstruction* second = LoadLocal(instruction.VRegB(), DataType::Type::kInt32); AppendInstruction(new (arena_) T(type, first, second, dex_pc)); UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); } template<typename T> void HInstructionBuilder::Binop_12x(const Instruction& instruction, - Primitive::Type type, + DataType::Type type, uint32_t dex_pc) { HInstruction* first = LoadLocal(instruction.VRegA(), type); HInstruction* second = LoadLocal(instruction.VRegB(), type); @@ -576,23 +576,23 @@ void HInstructionBuilder::Binop_12x(const Instruction& instruction, template<typename T> void HInstructionBuilder::Binop_22s(const Instruction& instruction, bool reverse, uint32_t dex_pc) { - HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); + HInstruction* first = LoadLocal(instruction.VRegB(), DataType::Type::kInt32); HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22s(), dex_pc); if (reverse) { std::swap(first, second); } - AppendInstruction(new (arena_) T(Primitive::kPrimInt, first, second, dex_pc)); + AppendInstruction(new (arena_) T(DataType::Type::kInt32, first, second, dex_pc)); UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); } template<typename T> void HInstructionBuilder::Binop_22b(const Instruction& instruction, bool reverse, uint32_t dex_pc) { - HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); + HInstruction* first = LoadLocal(instruction.VRegB(), DataType::Type::kInt32); HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22b(), dex_pc); if (reverse) { std::swap(first, second); } - AppendInstruction(new (arena_) T(Primitive::kPrimInt, first, second, dex_pc)); + AppendInstruction(new (arena_) T(DataType::Type::kInt32, first, second, dex_pc)); UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); } @@ -624,7 +624,7 @@ static bool IsFallthroughInstruction(const Instruction& instruction, } void HInstructionBuilder::BuildSwitch(const Instruction& instruction, uint32_t dex_pc) { - HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt); + HInstruction* value = LoadLocal(instruction.VRegA(), DataType::Type::kInt32); DexSwitchTable table(instruction, dex_pc); if (table.GetNumEntries() == 0) { @@ -651,9 +651,9 @@ void HInstructionBuilder::BuildSwitch(const Instruction& instruction, uint32_t d } void HInstructionBuilder::BuildReturn(const Instruction& instruction, - Primitive::Type type, + DataType::Type type, uint32_t dex_pc) { - if (type == Primitive::kPrimVoid) { + if (type == DataType::Type::kVoid) { // Only <init> (which is a return-void) could possibly have a constructor fence. // This may insert additional redundant constructor fences from the super constructors. // TODO: remove redundant constructor fences (b/36656456). @@ -802,7 +802,7 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction, uint32_t register_index) { InvokeType invoke_type = GetInvokeTypeFromOpCode(instruction.Opcode()); const char* descriptor = dex_file_->GetMethodShorty(method_idx); - Primitive::Type return_type = Primitive::GetType(descriptor[0]); + DataType::Type return_type = DataType::FromShorty(descriptor[0]); // Remove the return type from the 'proto'. size_t number_of_arguments = strlen(descriptor) - 1; @@ -844,7 +844,7 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction, HInvoke* invoke = new (arena_) HInvokeStaticOrDirect( arena_, number_of_arguments - 1, - Primitive::kPrimNot /*return_type */, + DataType::Type::kReference /*return_type */, dex_pc, method_idx, nullptr, @@ -938,7 +938,7 @@ bool HInstructionBuilder::BuildInvokePolymorphic(const Instruction& instruction uint32_t register_index) { const char* descriptor = dex_file_->GetShorty(proto_idx); DCHECK_EQ(1 + ArtMethod::NumArgRegisters(descriptor), number_of_vreg_arguments); - Primitive::Type return_type = Primitive::GetType(descriptor[0]); + DataType::Type return_type = DataType::FromShorty(descriptor[0]); size_t number_of_arguments = strlen(descriptor); HInvoke* invoke = new (arena_) HInvokePolymorphic(arena_, number_of_arguments, @@ -1113,8 +1113,8 @@ bool HInstructionBuilder::SetupInvokeArguments(HInvoke* invoke, // it hasn't been properly checked. (i < number_of_vreg_arguments) && (*argument_index < invoke->GetNumberOfArguments()); i++, (*argument_index)++) { - Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]); - bool is_wide = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble); + DataType::Type type = DataType::FromShorty(descriptor[descriptor_index++]); + bool is_wide = (type == DataType::Type::kInt64) || (type == DataType::Type::kFloat64); if (!is_range && is_wide && ((i + 1 == number_of_vreg_arguments) || (args[i] + 1 != args[i + 1]))) { @@ -1169,7 +1169,7 @@ bool HInstructionBuilder::HandleInvoke(HInvoke* invoke, if (invoke->GetInvokeType() != InvokeType::kStatic) { // Instance call. uint32_t obj_reg = is_range ? register_index : args[0]; HInstruction* arg = is_unresolved - ? LoadLocal(obj_reg, Primitive::kPrimNot) + ? LoadLocal(obj_reg, DataType::Type::kReference) : LoadNullCheckedLocal(obj_reg, invoke->GetDexPc()); invoke->SetArgumentAt(0, arg); start_index = 1; @@ -1229,7 +1229,7 @@ bool HInstructionBuilder::HandleStringInit(HInvoke* invoke, // This is a StringFactory call, not an actual String constructor. Its result // replaces the empty String pre-allocated by NewInstance. uint32_t orig_this_reg = is_range ? register_index : args[0]; - HInstruction* arg_this = LoadLocal(orig_this_reg, Primitive::kPrimNot); + HInstruction* arg_this = LoadLocal(orig_this_reg, DataType::Type::kReference); // Replacing the NewInstance might render it redundant. Keep a list of these // to be visited once it is clear whether it is has remaining uses. @@ -1251,10 +1251,10 @@ bool HInstructionBuilder::HandleStringInit(HInvoke* invoke, return true; } -static Primitive::Type GetFieldAccessType(const DexFile& dex_file, uint16_t field_index) { +static DataType::Type GetFieldAccessType(const DexFile& dex_file, uint16_t field_index) { const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); const char* type = dex_file.GetFieldTypeDescriptor(field_id); - return Primitive::GetType(type[0]); + return DataType::FromShorty(type[0]); } bool HInstructionBuilder::BuildInstanceFieldAccess(const Instruction& instruction, @@ -1280,12 +1280,10 @@ bool HInstructionBuilder::BuildInstanceFieldAccess(const Instruction& instructio // is unresolved. In that case, we rely on the runtime to perform various // checks first, followed by a null check. HInstruction* object = (resolved_field == nullptr) - ? LoadLocal(obj_reg, Primitive::kPrimNot) + ? LoadLocal(obj_reg, DataType::Type::kReference) : LoadNullCheckedLocal(obj_reg, dex_pc); - Primitive::Type field_type = (resolved_field == nullptr) - ? GetFieldAccessType(*dex_file_, field_index) - : resolved_field->GetTypeAsPrimitiveType(); + DataType::Type field_type = GetFieldAccessType(*dex_file_, field_index); if (is_put) { HInstruction* value = LoadLocal(source_or_dest_reg, field_type); HInstruction* field_set = nullptr; @@ -1377,7 +1375,7 @@ bool HInstructionBuilder::IsOutermostCompilingClass(dex::TypeIndex type_index) c void HInstructionBuilder::BuildUnresolvedStaticFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put, - Primitive::Type field_type) { + DataType::Type field_type) { uint32_t source_or_dest_reg = instruction.VRegA_21c(); uint16_t field_index = instruction.VRegB_21c(); @@ -1452,12 +1450,12 @@ bool HInstructionBuilder::BuildStaticFieldAccess(const Instruction& instruction, if (resolved_field == nullptr) { MaybeRecordStat(compilation_stats_, MethodCompilationStat::kUnresolvedField); - Primitive::Type field_type = GetFieldAccessType(*dex_file_, field_index); + DataType::Type field_type = GetFieldAccessType(*dex_file_, field_index); BuildUnresolvedStaticFieldAccess(instruction, dex_pc, is_put, field_type); return true; } - Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType(); + DataType::Type field_type = GetFieldAccessType(*dex_file_, field_index); Handle<mirror::Class> klass = handles_->NewHandle(resolved_field->GetDeclaringClass()); HLoadClass* constant = BuildLoadClass(klass->GetDexTypeIndex(), @@ -1515,15 +1513,15 @@ void HInstructionBuilder::BuildCheckedDivRem(uint16_t out_vreg, uint16_t first_vreg, int64_t second_vreg_or_constant, uint32_t dex_pc, - Primitive::Type type, + DataType::Type type, bool second_is_constant, bool isDiv) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); HInstruction* first = LoadLocal(first_vreg, type); HInstruction* second = nullptr; if (second_is_constant) { - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { second = graph_->GetIntConstant(second_vreg_or_constant, dex_pc); } else { second = graph_->GetLongConstant(second_vreg_or_constant, dex_pc); @@ -1533,8 +1531,8 @@ void HInstructionBuilder::BuildCheckedDivRem(uint16_t out_vreg, } if (!second_is_constant - || (type == Primitive::kPrimInt && second->AsIntConstant()->GetValue() == 0) - || (type == Primitive::kPrimLong && second->AsLongConstant()->GetValue() == 0)) { + || (type == DataType::Type::kInt32 && second->AsIntConstant()->GetValue() == 0) + || (type == DataType::Type::kInt64 && second->AsLongConstant()->GetValue() == 0)) { second = new (arena_) HDivZeroCheck(second, dex_pc); AppendInstruction(second); } @@ -1550,7 +1548,7 @@ void HInstructionBuilder::BuildCheckedDivRem(uint16_t out_vreg, void HInstructionBuilder::BuildArrayAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put, - Primitive::Type anticipated_type) { + DataType::Type anticipated_type) { uint8_t source_or_dest_reg = instruction.VRegA_23x(); uint8_t array_reg = instruction.VRegB_23x(); uint8_t index_reg = instruction.VRegC_23x(); @@ -1558,7 +1556,7 @@ void HInstructionBuilder::BuildArrayAccess(const Instruction& instruction, HInstruction* object = LoadNullCheckedLocal(array_reg, dex_pc); HInstruction* length = new (arena_) HArrayLength(object, dex_pc); AppendInstruction(length); - HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt); + HInstruction* index = LoadLocal(index_reg, DataType::Type::kInt32); index = new (arena_) HBoundsCheck(index, length, dex_pc); AppendInstruction(index); if (is_put) { @@ -1594,7 +1592,7 @@ HNewArray* HInstructionBuilder::BuildFilledNewArray(uint32_t dex_pc, || primitive == 'L' || primitive == '[') << descriptor; bool is_reference_array = (primitive == 'L') || (primitive == '['); - Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt; + DataType::Type type = is_reference_array ? DataType::Type::kReference : DataType::Type::kInt32; for (size_t i = 0; i < number_of_vreg_arguments; ++i) { HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type); @@ -1612,7 +1610,7 @@ template <typename T> void HInstructionBuilder::BuildFillArrayData(HInstruction* object, const T* data, uint32_t element_count, - Primitive::Type anticipated_type, + DataType::Type anticipated_type, uint32_t dex_pc) { for (uint32_t i = 0; i < element_count; ++i) { HInstruction* index = graph_->GetIntConstant(i, dex_pc); @@ -1650,21 +1648,21 @@ void HInstructionBuilder::BuildFillArrayData(const Instruction& instruction, uin BuildFillArrayData(array, reinterpret_cast<const int8_t*>(data), element_count, - Primitive::kPrimByte, + DataType::Type::kInt8, dex_pc); break; case 2: BuildFillArrayData(array, reinterpret_cast<const int16_t*>(data), element_count, - Primitive::kPrimShort, + DataType::Type::kInt16, dex_pc); break; case 4: BuildFillArrayData(array, reinterpret_cast<const int32_t*>(data), element_count, - Primitive::kPrimInt, + DataType::Type::kInt32, dex_pc); break; case 8: @@ -1686,7 +1684,7 @@ void HInstructionBuilder::BuildFillWideArrayData(HInstruction* object, for (uint32_t i = 0; i < element_count; ++i) { HInstruction* index = graph_->GetIntConstant(i, dex_pc); HInstruction* value = graph_->GetLongConstant(data[i], dex_pc); - HArraySet* aset = new (arena_) HArraySet(object, index, value, Primitive::kPrimLong, dex_pc); + HArraySet* aset = new (arena_) HArraySet(object, index, value, DataType::Type::kInt64, dex_pc); ssa_builder_->MaybeAddAmbiguousArraySet(aset); AppendInstruction(aset); } @@ -1783,7 +1781,7 @@ void HInstructionBuilder::BuildTypeCheck(const Instruction& instruction, uint8_t reference, dex::TypeIndex type_index, uint32_t dex_pc) { - HInstruction* object = LoadLocal(reference, Primitive::kPrimNot); + HInstruction* object = LoadLocal(reference, DataType::Type::kReference); HLoadClass* cls = BuildLoadClass(type_index, dex_pc); ScopedObjectAccess soa(Thread::Current()); @@ -1889,7 +1887,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, case Instruction::MOVE: case Instruction::MOVE_FROM16: case Instruction::MOVE_16: { - HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); + HInstruction* value = LoadLocal(instruction.VRegB(), DataType::Type::kInt32); UpdateLocal(instruction.VRegA(), value); break; } @@ -1898,7 +1896,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, case Instruction::MOVE_WIDE: case Instruction::MOVE_WIDE_FROM16: case Instruction::MOVE_WIDE_16: { - HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong); + HInstruction* value = LoadLocal(instruction.VRegB(), DataType::Type::kInt64); UpdateLocal(instruction.VRegA(), value); break; } @@ -1916,9 +1914,10 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, if (value->IsIntConstant()) { DCHECK_EQ(value->AsIntConstant()->GetValue(), 0); } else if (value->IsPhi()) { - DCHECK(value->GetType() == Primitive::kPrimInt || value->GetType() == Primitive::kPrimNot); + DCHECK(value->GetType() == DataType::Type::kInt32 || + value->GetType() == DataType::Type::kReference); } else { - value = LoadLocal(reg_number, Primitive::kPrimNot); + value = LoadLocal(reg_number, DataType::Type::kReference); } UpdateLocal(instruction.VRegA(), value); break; @@ -1926,7 +1925,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, case Instruction::RETURN_VOID_NO_BARRIER: case Instruction::RETURN_VOID: { - BuildReturn(instruction, Primitive::kPrimVoid, dex_pc); + BuildReturn(instruction, DataType::Type::kVoid, dex_pc); break; } @@ -2045,435 +2044,435 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, } case Instruction::NEG_INT: { - Unop_12x<HNeg>(instruction, Primitive::kPrimInt, dex_pc); + Unop_12x<HNeg>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::NEG_LONG: { - Unop_12x<HNeg>(instruction, Primitive::kPrimLong, dex_pc); + Unop_12x<HNeg>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::NEG_FLOAT: { - Unop_12x<HNeg>(instruction, Primitive::kPrimFloat, dex_pc); + Unop_12x<HNeg>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::NEG_DOUBLE: { - Unop_12x<HNeg>(instruction, Primitive::kPrimDouble, dex_pc); + Unop_12x<HNeg>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::NOT_INT: { - Unop_12x<HNot>(instruction, Primitive::kPrimInt, dex_pc); + Unop_12x<HNot>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::NOT_LONG: { - Unop_12x<HNot>(instruction, Primitive::kPrimLong, dex_pc); + Unop_12x<HNot>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::INT_TO_LONG: { - Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimLong, dex_pc); + Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kInt64, dex_pc); break; } case Instruction::INT_TO_FLOAT: { - Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimFloat, dex_pc); + Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kFloat32, dex_pc); break; } case Instruction::INT_TO_DOUBLE: { - Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimDouble, dex_pc); + Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kFloat64, dex_pc); break; } case Instruction::LONG_TO_INT: { - Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimInt, dex_pc); + Conversion_12x(instruction, DataType::Type::kInt64, DataType::Type::kInt32, dex_pc); break; } case Instruction::LONG_TO_FLOAT: { - Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimFloat, dex_pc); + Conversion_12x(instruction, DataType::Type::kInt64, DataType::Type::kFloat32, dex_pc); break; } case Instruction::LONG_TO_DOUBLE: { - Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimDouble, dex_pc); + Conversion_12x(instruction, DataType::Type::kInt64, DataType::Type::kFloat64, dex_pc); break; } case Instruction::FLOAT_TO_INT: { - Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimInt, dex_pc); + Conversion_12x(instruction, DataType::Type::kFloat32, DataType::Type::kInt32, dex_pc); break; } case Instruction::FLOAT_TO_LONG: { - Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimLong, dex_pc); + Conversion_12x(instruction, DataType::Type::kFloat32, DataType::Type::kInt64, dex_pc); break; } case Instruction::FLOAT_TO_DOUBLE: { - Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimDouble, dex_pc); + Conversion_12x(instruction, DataType::Type::kFloat32, DataType::Type::kFloat64, dex_pc); break; } case Instruction::DOUBLE_TO_INT: { - Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimInt, dex_pc); + Conversion_12x(instruction, DataType::Type::kFloat64, DataType::Type::kInt32, dex_pc); break; } case Instruction::DOUBLE_TO_LONG: { - Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimLong, dex_pc); + Conversion_12x(instruction, DataType::Type::kFloat64, DataType::Type::kInt64, dex_pc); break; } case Instruction::DOUBLE_TO_FLOAT: { - Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimFloat, dex_pc); + Conversion_12x(instruction, DataType::Type::kFloat64, DataType::Type::kFloat32, dex_pc); break; } case Instruction::INT_TO_BYTE: { - Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimByte, dex_pc); + Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kInt8, dex_pc); break; } case Instruction::INT_TO_SHORT: { - Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimShort, dex_pc); + Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kInt16, dex_pc); break; } case Instruction::INT_TO_CHAR: { - Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimChar, dex_pc); + Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kUint16, dex_pc); break; } case Instruction::ADD_INT: { - Binop_23x<HAdd>(instruction, Primitive::kPrimInt, dex_pc); + Binop_23x<HAdd>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::ADD_LONG: { - Binop_23x<HAdd>(instruction, Primitive::kPrimLong, dex_pc); + Binop_23x<HAdd>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::ADD_DOUBLE: { - Binop_23x<HAdd>(instruction, Primitive::kPrimDouble, dex_pc); + Binop_23x<HAdd>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::ADD_FLOAT: { - Binop_23x<HAdd>(instruction, Primitive::kPrimFloat, dex_pc); + Binop_23x<HAdd>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::SUB_INT: { - Binop_23x<HSub>(instruction, Primitive::kPrimInt, dex_pc); + Binop_23x<HSub>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::SUB_LONG: { - Binop_23x<HSub>(instruction, Primitive::kPrimLong, dex_pc); + Binop_23x<HSub>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::SUB_FLOAT: { - Binop_23x<HSub>(instruction, Primitive::kPrimFloat, dex_pc); + Binop_23x<HSub>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::SUB_DOUBLE: { - Binop_23x<HSub>(instruction, Primitive::kPrimDouble, dex_pc); + Binop_23x<HSub>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::ADD_INT_2ADDR: { - Binop_12x<HAdd>(instruction, Primitive::kPrimInt, dex_pc); + Binop_12x<HAdd>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::MUL_INT: { - Binop_23x<HMul>(instruction, Primitive::kPrimInt, dex_pc); + Binop_23x<HMul>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::MUL_LONG: { - Binop_23x<HMul>(instruction, Primitive::kPrimLong, dex_pc); + Binop_23x<HMul>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::MUL_FLOAT: { - Binop_23x<HMul>(instruction, Primitive::kPrimFloat, dex_pc); + Binop_23x<HMul>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::MUL_DOUBLE: { - Binop_23x<HMul>(instruction, Primitive::kPrimDouble, dex_pc); + Binop_23x<HMul>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::DIV_INT: { BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), - dex_pc, Primitive::kPrimInt, false, true); + dex_pc, DataType::Type::kInt32, false, true); break; } case Instruction::DIV_LONG: { BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), - dex_pc, Primitive::kPrimLong, false, true); + dex_pc, DataType::Type::kInt64, false, true); break; } case Instruction::DIV_FLOAT: { - Binop_23x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc); + Binop_23x<HDiv>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::DIV_DOUBLE: { - Binop_23x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc); + Binop_23x<HDiv>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::REM_INT: { BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), - dex_pc, Primitive::kPrimInt, false, false); + dex_pc, DataType::Type::kInt32, false, false); break; } case Instruction::REM_LONG: { BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), - dex_pc, Primitive::kPrimLong, false, false); + dex_pc, DataType::Type::kInt64, false, false); break; } case Instruction::REM_FLOAT: { - Binop_23x<HRem>(instruction, Primitive::kPrimFloat, dex_pc); + Binop_23x<HRem>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::REM_DOUBLE: { - Binop_23x<HRem>(instruction, Primitive::kPrimDouble, dex_pc); + Binop_23x<HRem>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::AND_INT: { - Binop_23x<HAnd>(instruction, Primitive::kPrimInt, dex_pc); + Binop_23x<HAnd>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::AND_LONG: { - Binop_23x<HAnd>(instruction, Primitive::kPrimLong, dex_pc); + Binop_23x<HAnd>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::SHL_INT: { - Binop_23x_shift<HShl>(instruction, Primitive::kPrimInt, dex_pc); + Binop_23x_shift<HShl>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::SHL_LONG: { - Binop_23x_shift<HShl>(instruction, Primitive::kPrimLong, dex_pc); + Binop_23x_shift<HShl>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::SHR_INT: { - Binop_23x_shift<HShr>(instruction, Primitive::kPrimInt, dex_pc); + Binop_23x_shift<HShr>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::SHR_LONG: { - Binop_23x_shift<HShr>(instruction, Primitive::kPrimLong, dex_pc); + Binop_23x_shift<HShr>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::USHR_INT: { - Binop_23x_shift<HUShr>(instruction, Primitive::kPrimInt, dex_pc); + Binop_23x_shift<HUShr>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::USHR_LONG: { - Binop_23x_shift<HUShr>(instruction, Primitive::kPrimLong, dex_pc); + Binop_23x_shift<HUShr>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::OR_INT: { - Binop_23x<HOr>(instruction, Primitive::kPrimInt, dex_pc); + Binop_23x<HOr>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::OR_LONG: { - Binop_23x<HOr>(instruction, Primitive::kPrimLong, dex_pc); + Binop_23x<HOr>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::XOR_INT: { - Binop_23x<HXor>(instruction, Primitive::kPrimInt, dex_pc); + Binop_23x<HXor>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::XOR_LONG: { - Binop_23x<HXor>(instruction, Primitive::kPrimLong, dex_pc); + Binop_23x<HXor>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::ADD_LONG_2ADDR: { - Binop_12x<HAdd>(instruction, Primitive::kPrimLong, dex_pc); + Binop_12x<HAdd>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::ADD_DOUBLE_2ADDR: { - Binop_12x<HAdd>(instruction, Primitive::kPrimDouble, dex_pc); + Binop_12x<HAdd>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::ADD_FLOAT_2ADDR: { - Binop_12x<HAdd>(instruction, Primitive::kPrimFloat, dex_pc); + Binop_12x<HAdd>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::SUB_INT_2ADDR: { - Binop_12x<HSub>(instruction, Primitive::kPrimInt, dex_pc); + Binop_12x<HSub>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::SUB_LONG_2ADDR: { - Binop_12x<HSub>(instruction, Primitive::kPrimLong, dex_pc); + Binop_12x<HSub>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::SUB_FLOAT_2ADDR: { - Binop_12x<HSub>(instruction, Primitive::kPrimFloat, dex_pc); + Binop_12x<HSub>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::SUB_DOUBLE_2ADDR: { - Binop_12x<HSub>(instruction, Primitive::kPrimDouble, dex_pc); + Binop_12x<HSub>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::MUL_INT_2ADDR: { - Binop_12x<HMul>(instruction, Primitive::kPrimInt, dex_pc); + Binop_12x<HMul>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::MUL_LONG_2ADDR: { - Binop_12x<HMul>(instruction, Primitive::kPrimLong, dex_pc); + Binop_12x<HMul>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::MUL_FLOAT_2ADDR: { - Binop_12x<HMul>(instruction, Primitive::kPrimFloat, dex_pc); + Binop_12x<HMul>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::MUL_DOUBLE_2ADDR: { - Binop_12x<HMul>(instruction, Primitive::kPrimDouble, dex_pc); + Binop_12x<HMul>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::DIV_INT_2ADDR: { BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(), - dex_pc, Primitive::kPrimInt, false, true); + dex_pc, DataType::Type::kInt32, false, true); break; } case Instruction::DIV_LONG_2ADDR: { BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(), - dex_pc, Primitive::kPrimLong, false, true); + dex_pc, DataType::Type::kInt64, false, true); break; } case Instruction::REM_INT_2ADDR: { BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(), - dex_pc, Primitive::kPrimInt, false, false); + dex_pc, DataType::Type::kInt32, false, false); break; } case Instruction::REM_LONG_2ADDR: { BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(), - dex_pc, Primitive::kPrimLong, false, false); + dex_pc, DataType::Type::kInt64, false, false); break; } case Instruction::REM_FLOAT_2ADDR: { - Binop_12x<HRem>(instruction, Primitive::kPrimFloat, dex_pc); + Binop_12x<HRem>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::REM_DOUBLE_2ADDR: { - Binop_12x<HRem>(instruction, Primitive::kPrimDouble, dex_pc); + Binop_12x<HRem>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::SHL_INT_2ADDR: { - Binop_12x_shift<HShl>(instruction, Primitive::kPrimInt, dex_pc); + Binop_12x_shift<HShl>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::SHL_LONG_2ADDR: { - Binop_12x_shift<HShl>(instruction, Primitive::kPrimLong, dex_pc); + Binop_12x_shift<HShl>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::SHR_INT_2ADDR: { - Binop_12x_shift<HShr>(instruction, Primitive::kPrimInt, dex_pc); + Binop_12x_shift<HShr>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::SHR_LONG_2ADDR: { - Binop_12x_shift<HShr>(instruction, Primitive::kPrimLong, dex_pc); + Binop_12x_shift<HShr>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::USHR_INT_2ADDR: { - Binop_12x_shift<HUShr>(instruction, Primitive::kPrimInt, dex_pc); + Binop_12x_shift<HUShr>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::USHR_LONG_2ADDR: { - Binop_12x_shift<HUShr>(instruction, Primitive::kPrimLong, dex_pc); + Binop_12x_shift<HUShr>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::DIV_FLOAT_2ADDR: { - Binop_12x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc); + Binop_12x<HDiv>(instruction, DataType::Type::kFloat32, dex_pc); break; } case Instruction::DIV_DOUBLE_2ADDR: { - Binop_12x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc); + Binop_12x<HDiv>(instruction, DataType::Type::kFloat64, dex_pc); break; } case Instruction::AND_INT_2ADDR: { - Binop_12x<HAnd>(instruction, Primitive::kPrimInt, dex_pc); + Binop_12x<HAnd>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::AND_LONG_2ADDR: { - Binop_12x<HAnd>(instruction, Primitive::kPrimLong, dex_pc); + Binop_12x<HAnd>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::OR_INT_2ADDR: { - Binop_12x<HOr>(instruction, Primitive::kPrimInt, dex_pc); + Binop_12x<HOr>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::OR_LONG_2ADDR: { - Binop_12x<HOr>(instruction, Primitive::kPrimLong, dex_pc); + Binop_12x<HOr>(instruction, DataType::Type::kInt64, dex_pc); break; } case Instruction::XOR_INT_2ADDR: { - Binop_12x<HXor>(instruction, Primitive::kPrimInt, dex_pc); + Binop_12x<HXor>(instruction, DataType::Type::kInt32, dex_pc); break; } case Instruction::XOR_LONG_2ADDR: { - Binop_12x<HXor>(instruction, Primitive::kPrimLong, dex_pc); + Binop_12x<HXor>(instruction, DataType::Type::kInt64, dex_pc); break; } @@ -2540,14 +2539,14 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, case Instruction::DIV_INT_LIT16: case Instruction::DIV_INT_LIT8: { BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), - dex_pc, Primitive::kPrimInt, true, true); + dex_pc, DataType::Type::kInt32, true, true); break; } case Instruction::REM_INT_LIT16: case Instruction::REM_INT_LIT8: { BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(), - dex_pc, Primitive::kPrimInt, true, false); + dex_pc, DataType::Type::kInt32, true, false); break; } @@ -2578,7 +2577,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, case Instruction::NEW_ARRAY: { dex::TypeIndex type_index(instruction.VRegC_22c()); - HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt); + HInstruction* length = LoadLocal(instruction.VRegB_22c(), DataType::Type::kInt32); HLoadClass* cls = BuildLoadClass(type_index, dex_pc); HNewArray* new_array = new (arena_) HNewArray(cls, length, dex_pc); @@ -2632,27 +2631,27 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, } case Instruction::CMP_LONG: { - Binop_23x_cmp(instruction, Primitive::kPrimLong, ComparisonBias::kNoBias, dex_pc); + Binop_23x_cmp(instruction, DataType::Type::kInt64, ComparisonBias::kNoBias, dex_pc); break; } case Instruction::CMPG_FLOAT: { - Binop_23x_cmp(instruction, Primitive::kPrimFloat, ComparisonBias::kGtBias, dex_pc); + Binop_23x_cmp(instruction, DataType::Type::kFloat32, ComparisonBias::kGtBias, dex_pc); break; } case Instruction::CMPG_DOUBLE: { - Binop_23x_cmp(instruction, Primitive::kPrimDouble, ComparisonBias::kGtBias, dex_pc); + Binop_23x_cmp(instruction, DataType::Type::kFloat64, ComparisonBias::kGtBias, dex_pc); break; } case Instruction::CMPL_FLOAT: { - Binop_23x_cmp(instruction, Primitive::kPrimFloat, ComparisonBias::kLtBias, dex_pc); + Binop_23x_cmp(instruction, DataType::Type::kFloat32, ComparisonBias::kLtBias, dex_pc); break; } case Instruction::CMPL_DOUBLE: { - Binop_23x_cmp(instruction, Primitive::kPrimDouble, ComparisonBias::kLtBias, dex_pc); + Binop_23x_cmp(instruction, DataType::Type::kFloat64, ComparisonBias::kLtBias, dex_pc); break; } @@ -2735,13 +2734,13 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, break; \ } - ARRAY_XX(, Primitive::kPrimInt); - ARRAY_XX(_WIDE, Primitive::kPrimLong); - ARRAY_XX(_OBJECT, Primitive::kPrimNot); - ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean); - ARRAY_XX(_BYTE, Primitive::kPrimByte); - ARRAY_XX(_CHAR, Primitive::kPrimChar); - ARRAY_XX(_SHORT, Primitive::kPrimShort); + ARRAY_XX(, DataType::Type::kInt32); + ARRAY_XX(_WIDE, DataType::Type::kInt64); + ARRAY_XX(_OBJECT, DataType::Type::kReference); + ARRAY_XX(_BOOLEAN, DataType::Type::kBool); + ARRAY_XX(_BYTE, DataType::Type::kInt8); + ARRAY_XX(_CHAR, DataType::Type::kUint16); + ARRAY_XX(_SHORT, DataType::Type::kInt16); case Instruction::ARRAY_LENGTH: { HInstruction* object = LoadNullCheckedLocal(instruction.VRegB_12x(), dex_pc); @@ -2781,7 +2780,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, } case Instruction::THROW: { - HInstruction* exception = LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot); + HInstruction* exception = LoadLocal(instruction.VRegA_11x(), DataType::Type::kReference); AppendInstruction(new (arena_) HThrow(exception, dex_pc)); // We finished building this block. Set the current block to null to avoid // adding dead instructions to it. @@ -2806,7 +2805,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, case Instruction::MONITOR_ENTER: { AppendInstruction(new (arena_) HMonitorOperation( - LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot), + LoadLocal(instruction.VRegA_11x(), DataType::Type::kReference), HMonitorOperation::OperationKind::kEnter, dex_pc)); break; @@ -2814,7 +2813,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, case Instruction::MONITOR_EXIT: { AppendInstruction(new (arena_) HMonitorOperation( - LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot), + LoadLocal(instruction.VRegA_11x(), DataType::Type::kReference), HMonitorOperation::OperationKind::kExit, dex_pc)); break; diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h index b7fa39404b..a684bf40e6 100644 --- a/compiler/optimizing/instruction_builder.h +++ b/compiler/optimizing/instruction_builder.h @@ -42,7 +42,7 @@ class HInstructionBuilder : public ValueObject { SsaBuilder* ssa_builder, const DexFile* dex_file, const DexFile::CodeItem& code_item, - Primitive::Type return_type, + DataType::Type return_type, DexCompilationUnit* dex_compilation_unit, const DexCompilationUnit* const outer_compilation_unit, CompilerDriver* driver, @@ -96,7 +96,7 @@ class HInstructionBuilder : public ValueObject { ArenaVector<HInstruction*>* GetLocalsForWithAllocation( HBasicBlock* block, ArenaVector<HInstruction*>* locals, const size_t vregs); HInstruction* ValueOfLocalAt(HBasicBlock* block, size_t local); - HInstruction* LoadLocal(uint32_t register_index, Primitive::Type type) const; + HInstruction* LoadLocal(uint32_t register_index, DataType::Type type) const; HInstruction* LoadNullCheckedLocal(uint32_t register_index, uint32_t dex_pc); void UpdateLocal(uint32_t register_index, HInstruction* instruction); @@ -112,24 +112,24 @@ class HInstructionBuilder : public ValueObject { REQUIRES_SHARED(Locks::mutator_lock_); template<typename T> - void Unop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc); + void Unop_12x(const Instruction& instruction, DataType::Type type, uint32_t dex_pc); template<typename T> - void Binop_23x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc); + void Binop_23x(const Instruction& instruction, DataType::Type type, uint32_t dex_pc); template<typename T> - void Binop_23x_shift(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc); + void Binop_23x_shift(const Instruction& instruction, DataType::Type type, uint32_t dex_pc); void Binop_23x_cmp(const Instruction& instruction, - Primitive::Type type, + DataType::Type type, ComparisonBias bias, uint32_t dex_pc); template<typename T> - void Binop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc); + void Binop_12x(const Instruction& instruction, DataType::Type type, uint32_t dex_pc); template<typename T> - void Binop_12x_shift(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc); + void Binop_12x_shift(const Instruction& instruction, DataType::Type type, uint32_t dex_pc); template<typename T> void Binop_22b(const Instruction& instruction, bool reverse, uint32_t dex_pc); @@ -141,19 +141,19 @@ class HInstructionBuilder : public ValueObject { template<typename T> void If_22t(const Instruction& instruction, uint32_t dex_pc); void Conversion_12x(const Instruction& instruction, - Primitive::Type input_type, - Primitive::Type result_type, + DataType::Type input_type, + DataType::Type result_type, uint32_t dex_pc); void BuildCheckedDivRem(uint16_t out_reg, uint16_t first_reg, int64_t second_reg_or_constant, uint32_t dex_pc, - Primitive::Type type, + DataType::Type type, bool second_is_lit, bool is_div); - void BuildReturn(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc); + void BuildReturn(const Instruction& instruction, DataType::Type type, uint32_t dex_pc); // Builds an instance field access node and returns whether the instruction is supported. bool BuildInstanceFieldAccess(const Instruction& instruction, @@ -164,14 +164,14 @@ class HInstructionBuilder : public ValueObject { void BuildUnresolvedStaticFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put, - Primitive::Type field_type); + DataType::Type field_type); // Builds a static field access node and returns whether the instruction is supported. bool BuildStaticFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put); void BuildArrayAccess(const Instruction& instruction, uint32_t dex_pc, bool is_get, - Primitive::Type anticipated_type); + DataType::Type anticipated_type); // Builds an invocation node and returns whether the instruction is supported. bool BuildInvoke(const Instruction& instruction, @@ -210,7 +210,7 @@ class HInstructionBuilder : public ValueObject { void BuildFillArrayData(HInstruction* object, const T* data, uint32_t element_count, - Primitive::Type anticipated_type, + DataType::Type anticipated_type, uint32_t dex_pc); // Fills the given object with data as specified in the fill-array-data @@ -321,7 +321,7 @@ class HInstructionBuilder : public ValueObject { const DexFile::CodeItem& code_item_; // The return type of the method being compiled. - const Primitive::Type return_type_; + const DataType::Type return_type_; HBasicBlockBuilder* block_builder_; SsaBuilder* ssa_builder_; diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 337177fa80..1a2494a992 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -18,6 +18,7 @@ #include "art_method-inl.h" #include "class_linker-inl.h" +#include "data_type-inl.h" #include "escape.h" #include "intrinsics.h" #include "mirror/class-inl.h" @@ -103,10 +104,10 @@ class InstructionSimplifierVisitor : public HGraphDelegateVisitor { bool CanEnsureNotNullAt(HInstruction* instr, HInstruction* at) const; - void SimplifyRotate(HInvoke* invoke, bool is_left, Primitive::Type type); + void SimplifyRotate(HInvoke* invoke, bool is_left, DataType::Type type); void SimplifySystemArrayCopy(HInvoke* invoke); void SimplifyStringEquals(HInvoke* invoke); - void SimplifyCompare(HInvoke* invoke, bool is_signum, Primitive::Type type); + void SimplifyCompare(HInvoke* invoke, bool is_signum, DataType::Type type); void SimplifyIsNaN(HInvoke* invoke); void SimplifyFP2Int(HInvoke* invoke); void SimplifyStringCharAt(HInvoke* invoke); @@ -178,7 +179,7 @@ bool InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop(HBinaryOperation // Note that we cannot optimize `(-a) + (-b)` to `-(a + b)` for floating-point. // When `a` is `-0.0` and `b` is `0.0`, the former expression yields `0.0`, // while the later yields `-0.0`. - if (!Primitive::IsIntegralType(binop->GetType())) { + if (!DataType::IsIntegralType(binop->GetType())) { return false; } binop->ReplaceInput(left_neg->GetInput(), 0); @@ -194,7 +195,7 @@ bool InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop(HBinaryOperation bool InstructionSimplifierVisitor::TryDeMorganNegationFactoring(HBinaryOperation* op) { DCHECK(op->IsAnd() || op->IsOr()) << op->DebugName(); - Primitive::Type type = op->GetType(); + DataType::Type type = op->GetType(); HInstruction* left = op->GetLeft(); HInstruction* right = op->GetRight(); @@ -246,24 +247,24 @@ bool InstructionSimplifierVisitor::TryDeMorganNegationFactoring(HBinaryOperation } bool InstructionSimplifierVisitor::TryCombineVecMultiplyAccumulate(HVecMul* mul) { - Primitive::Type type = mul->GetPackedType(); + DataType::Type type = mul->GetPackedType(); InstructionSet isa = codegen_->GetInstructionSet(); switch (isa) { case kArm64: - if (!(type == Primitive::kPrimByte || - type == Primitive::kPrimChar || - type == Primitive::kPrimShort || - type == Primitive::kPrimInt)) { + if (!(type == DataType::Type::kInt8 || + type == DataType::Type::kUint16 || + type == DataType::Type::kInt16 || + type == DataType::Type::kInt32)) { return false; } break; case kMips: case kMips64: - if (!(type == Primitive::kPrimByte || - type == Primitive::kPrimChar || - type == Primitive::kPrimShort || - type == Primitive::kPrimInt || - type == Primitive::kPrimLong)) { + if (!(type == DataType::Type::kInt8 || + type == DataType::Type::kUint16 || + type == DataType::Type::kInt16 || + type == DataType::Type::kInt32 || + type == DataType::Type::kInt64)) { return false; } break; @@ -328,7 +329,7 @@ void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) { HInstruction* shift_amount = instruction->GetRight(); HInstruction* value = instruction->GetLeft(); - int64_t implicit_mask = (value->GetType() == Primitive::kPrimLong) + int64_t implicit_mask = (value->GetType() == DataType::Type::kInt64) ? kMaxLongShiftDistance : kMaxIntShiftDistance; @@ -351,7 +352,7 @@ void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) { // SHL dst, value, cst & implicit_mask // (as defined by shift semantics). This ensures other // optimizations do not need to special case for such situations. - DCHECK_EQ(shift_amount->GetType(), Primitive::kPrimInt); + DCHECK_EQ(shift_amount->GetType(), DataType::Type::kInt32); instruction->ReplaceInput(GetGraph()->GetIntConstant(masked_cst), /* index */ 1); RecordSimplification(); return; @@ -412,7 +413,7 @@ bool InstructionSimplifierVisitor::TryReplaceWithRotate(HBinaryOperation* op) { if ((left->IsUShr() && right->IsShl()) || (left->IsShl() && right->IsUShr())) { HUShr* ushr = left->IsUShr() ? left->AsUShr() : right->AsUShr(); HShl* shl = left->IsShl() ? left->AsShl() : right->AsShl(); - DCHECK(Primitive::IsIntOrLongType(ushr->GetType())); + DCHECK(DataType::IsIntOrLongType(ushr->GetType())); if (ushr->GetType() == shl->GetType() && ushr->GetLeft() == shl->GetLeft()) { if (ushr->GetRight()->IsConstant() && shl->GetRight()->IsConstant()) { @@ -445,7 +446,7 @@ bool InstructionSimplifierVisitor::TryReplaceWithRotateConstantPattern(HBinaryOp HUShr* ushr, HShl* shl) { DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()); - size_t reg_bits = Primitive::ComponentSize(ushr->GetType()) * kBitsPerByte; + size_t reg_bits = DataType::Size(ushr->GetType()) * kBitsPerByte; size_t rdist = Int64FromConstant(ushr->GetRight()->AsConstant()); size_t ldist = Int64FromConstant(shl->GetRight()->AsConstant()); if (((ldist + rdist) & (reg_bits - 1)) == 0) { @@ -506,7 +507,7 @@ bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterSubPattern(HBinar HShl* shl) { DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()); DCHECK(ushr->GetRight()->IsSub() || shl->GetRight()->IsSub()); - size_t reg_bits = Primitive::ComponentSize(ushr->GetType()) * kBitsPerByte; + size_t reg_bits = DataType::Size(ushr->GetType()) * kBitsPerByte; HInstruction* shl_shift = shl->GetRight(); HInstruction* ushr_shift = ushr->GetRight(); if ((shl_shift->IsSub() && IsSubRegBitsMinusOther(shl_shift->AsSub(), reg_bits, ushr_shift)) || @@ -664,14 +665,14 @@ void InstructionSimplifierVisitor::VisitInstanceOf(HInstanceOf* instruction) { } void InstructionSimplifierVisitor::VisitInstanceFieldSet(HInstanceFieldSet* instruction) { - if ((instruction->GetValue()->GetType() == Primitive::kPrimNot) + if ((instruction->GetValue()->GetType() == DataType::Type::kReference) && CanEnsureNotNullAt(instruction->GetValue(), instruction)) { instruction->ClearValueCanBeNull(); } } void InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruction) { - if ((instruction->GetValue()->GetType() == Primitive::kPrimNot) + if ((instruction->GetValue()->GetType() == DataType::Type::kReference) && CanEnsureNotNullAt(instruction->GetValue(), instruction)) { instruction->ClearValueCanBeNull(); } @@ -708,7 +709,7 @@ static HCondition* GetOppositeConditionSwapOps(ArenaAllocator* arena, HInstructi } static bool CmpHasBoolType(HInstruction* input, HInstruction* cmp) { - if (input->GetType() == Primitive::kPrimBoolean) { + if (input->GetType() == DataType::Type::kBool) { return true; // input has direct boolean type } else if (cmp->GetUses().HasExactlyOneElement()) { // Comparison also has boolean type if both its input and the instruction @@ -801,7 +802,7 @@ void InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) { } else if (input->IsCondition() && // Don't change FP compares. The definition of compares involving // NaNs forces the compares to be done as written by the user. - !Primitive::IsFloatingPointType(input->InputAt(0)->GetType())) { + !DataType::IsFloatingPointType(input->InputAt(0)->GetType())) { // Replace condition with its opposite. replace_with = GetGraph()->InsertOppositeCondition(input->AsCondition(), bool_not); } @@ -815,8 +816,8 @@ void InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) { // Constructs a new ABS(x) node in the HIR. static HInstruction* NewIntegralAbs(ArenaAllocator* arena, HInstruction* x, HInstruction* cursor) { - Primitive::Type type = x->GetType(); - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DataType::Type type = x->GetType(); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); // Construct a fake intrinsic with as much context as is needed to allocate one. // The intrinsic will always be lowered into code later anyway. // TODO: b/65164101 : moving towards a real HAbs node makes more sense. @@ -837,8 +838,8 @@ static HInstruction* NewIntegralAbs(ArenaAllocator* arena, HInstruction* x, HIns MethodReference(nullptr, dex::kDexNoIndex), HInvokeStaticOrDirect::ClinitCheckRequirement::kNone); invoke->SetArgumentAt(0, x); - invoke->SetIntrinsic(type == Primitive::kPrimInt ? Intrinsics::kMathAbsInt - : Intrinsics::kMathAbsLong, + invoke->SetIntrinsic(type == DataType::Type::kInt32 ? Intrinsics::kMathAbsInt + : Intrinsics::kMathAbsLong, kNoEnvironmentOrCache, kNoSideEffects, kNoThrow); @@ -848,20 +849,20 @@ static HInstruction* NewIntegralAbs(ArenaAllocator* arena, HInstruction* x, HIns // Returns true if operands a and b consists of widening type conversions // (either explicit or implicit) to the given to_type. -static bool AreLowerPrecisionArgs(Primitive::Type to_type, HInstruction* a, HInstruction* b) { +static bool AreLowerPrecisionArgs(DataType::Type to_type, HInstruction* a, HInstruction* b) { if (a->IsTypeConversion() && a->GetType() == to_type) { a = a->InputAt(0); } if (b->IsTypeConversion() && b->GetType() == to_type) { b = b->InputAt(0); } - Primitive::Type type1 = a->GetType(); - Primitive::Type type2 = b->GetType(); - return (type1 == Primitive::kPrimByte && type2 == Primitive::kPrimByte) || - (type1 == Primitive::kPrimShort && type2 == Primitive::kPrimShort) || - (type1 == Primitive::kPrimChar && type2 == Primitive::kPrimChar) || - (type1 == Primitive::kPrimInt && type2 == Primitive::kPrimInt && - to_type == Primitive::kPrimLong); + DataType::Type type1 = a->GetType(); + DataType::Type type2 = b->GetType(); + return (type1 == DataType::Type::kInt8 && type2 == DataType::Type::kInt8) || + (type1 == DataType::Type::kInt16 && type2 == DataType::Type::kInt16) || + (type1 == DataType::Type::kUint16 && type2 == DataType::Type::kUint16) || + (type1 == DataType::Type::kInt32 && type2 == DataType::Type::kInt32 && + to_type == DataType::Type::kInt64); } void InstructionSimplifierVisitor::VisitSelect(HSelect* select) { @@ -904,11 +905,12 @@ void InstructionSimplifierVisitor::VisitSelect(HSelect* select) { IfCondition cmp = condition->AsCondition()->GetCondition(); HInstruction* a = condition->InputAt(0); HInstruction* b = condition->InputAt(1); - Primitive::Type t_type = true_value->GetType(); - Primitive::Type f_type = false_value->GetType(); + DataType::Type t_type = true_value->GetType(); + DataType::Type f_type = false_value->GetType(); // Here we have a <cmp> b ? true_value : false_value. // Test if both values are same-typed int or long. - if (t_type == f_type && (t_type == Primitive::kPrimInt || t_type == Primitive::kPrimLong)) { + if (t_type == f_type && + (t_type == DataType::Type::kInt32 || t_type == DataType::Type::kInt64)) { // Try to replace typical integral ABS constructs. if (true_value->IsNeg()) { HInstruction* negated = true_value->InputAt(0); @@ -974,7 +976,9 @@ void InstructionSimplifierVisitor::VisitArrayLength(HArrayLength* instruction) { void InstructionSimplifierVisitor::VisitArraySet(HArraySet* instruction) { HInstruction* value = instruction->GetValue(); - if (value->GetType() != Primitive::kPrimNot) return; + if (value->GetType() != DataType::Type::kReference) { + return; + } if (CanEnsureNotNullAt(value, instruction)) { instruction->ClearValueCanBeNull(); @@ -1014,39 +1018,39 @@ void InstructionSimplifierVisitor::VisitArraySet(HArraySet* instruction) { } } -static bool IsTypeConversionImplicit(Primitive::Type input_type, Primitive::Type result_type) { +static bool IsTypeConversionImplicit(DataType::Type input_type, DataType::Type result_type) { // Invariant: We should never generate a conversion to a Boolean value. - DCHECK_NE(Primitive::kPrimBoolean, result_type); + DCHECK_NE(DataType::Type::kBool, result_type); // Besides conversion to the same type, widening integral conversions are implicit, // excluding conversions to long and the byte->char conversion where we need to // clear the high 16 bits of the 32-bit sign-extended representation of byte. return result_type == input_type || - (result_type == Primitive::kPrimInt && (input_type == Primitive::kPrimBoolean || - input_type == Primitive::kPrimByte || - input_type == Primitive::kPrimShort || - input_type == Primitive::kPrimChar)) || - (result_type == Primitive::kPrimChar && input_type == Primitive::kPrimBoolean) || - (result_type == Primitive::kPrimShort && (input_type == Primitive::kPrimBoolean || - input_type == Primitive::kPrimByte)) || - (result_type == Primitive::kPrimByte && input_type == Primitive::kPrimBoolean); + (result_type == DataType::Type::kInt32 && (input_type == DataType::Type::kBool || + input_type == DataType::Type::kInt8 || + input_type == DataType::Type::kInt16 || + input_type == DataType::Type::kUint16)) || + (result_type == DataType::Type::kUint16 && input_type == DataType::Type::kBool) || + (result_type == DataType::Type::kInt16 && (input_type == DataType::Type::kBool || + input_type == DataType::Type::kInt8)) || + (result_type == DataType::Type::kInt8 && input_type == DataType::Type::kBool); } -static bool IsTypeConversionLossless(Primitive::Type input_type, Primitive::Type result_type) { +static bool IsTypeConversionLossless(DataType::Type input_type, DataType::Type result_type) { // The conversion to a larger type is loss-less with the exception of two cases, - // - conversion to char, the only unsigned type, where we may lose some bits, and + // - conversion to Uint16, the only unsigned type, where we may lose some bits, and // - conversion from float to long, the only FP to integral conversion with smaller FP type. // For integral to FP conversions this holds because the FP mantissa is large enough. DCHECK_NE(input_type, result_type); - return Primitive::ComponentSize(result_type) > Primitive::ComponentSize(input_type) && - result_type != Primitive::kPrimChar && - !(result_type == Primitive::kPrimLong && input_type == Primitive::kPrimFloat); + return DataType::Size(result_type) > DataType::Size(input_type) && + result_type != DataType::Type::kUint16 && + !(result_type == DataType::Type::kInt64 && input_type == DataType::Type::kFloat32); } void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruction) { HInstruction* input = instruction->GetInput(); - Primitive::Type input_type = input->GetType(); - Primitive::Type result_type = instruction->GetResultType(); + DataType::Type input_type = input->GetType(); + DataType::Type result_type = instruction->GetResultType(); if (IsTypeConversionImplicit(input_type, result_type)) { // Remove the implicit conversion; this includes conversion to the same type. instruction->ReplaceWith(input); @@ -1058,7 +1062,7 @@ void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruct if (input->IsTypeConversion()) { HTypeConversion* input_conversion = input->AsTypeConversion(); HInstruction* original_input = input_conversion->GetInput(); - Primitive::Type original_type = original_input->GetType(); + DataType::Type original_type = original_input->GetType(); // When the first conversion is lossless, a direct conversion from the original type // to the final type yields the same result, even for a lossy second conversion, for @@ -1069,10 +1073,10 @@ void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruct // doesn't need, i.e. the final type is no wider than the intermediate. If so, direct // conversion yields the same result, for example long->int->short or int->char->short. bool integral_conversions_with_non_widening_second = - Primitive::IsIntegralType(input_type) && - Primitive::IsIntegralType(original_type) && - Primitive::IsIntegralType(result_type) && - Primitive::ComponentSize(result_type) <= Primitive::ComponentSize(input_type); + DataType::IsIntegralType(input_type) && + DataType::IsIntegralType(original_type) && + DataType::IsIntegralType(result_type) && + DataType::Size(result_type) <= DataType::Size(input_type); if (is_first_conversion_lossless || integral_conversions_with_non_widening_second) { // If the merged conversion is implicit, do the simplification unconditionally. @@ -1094,15 +1098,15 @@ void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruct return; } } - } else if (input->IsAnd() && Primitive::IsIntegralType(result_type)) { - DCHECK(Primitive::IsIntegralType(input_type)); + } else if (input->IsAnd() && DataType::IsIntegralType(result_type)) { + DCHECK(DataType::IsIntegralType(input_type)); HAnd* input_and = input->AsAnd(); HConstant* constant = input_and->GetConstantRight(); if (constant != nullptr) { int64_t value = Int64FromConstant(constant); DCHECK_NE(value, -1); // "& -1" would have been optimized away in VisitAnd(). size_t trailing_ones = CTZ(~static_cast<uint64_t>(value)); - if (trailing_ones >= kBitsPerByte * Primitive::ComponentSize(result_type)) { + if (trailing_ones >= kBitsPerByte * DataType::Size(result_type)) { // The `HAnd` is useless, for example in `(byte) (x & 0xff)`, get rid of it. HInstruction* original_input = input_and->GetLeastConstantLeft(); if (IsTypeConversionImplicit(original_input->GetType(), result_type)) { @@ -1124,7 +1128,7 @@ void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruct void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) { HConstant* input_cst = instruction->GetConstantRight(); HInstruction* input_other = instruction->GetLeastConstantLeft(); - bool integral_type = Primitive::IsIntegralType(instruction->GetType()); + bool integral_type = DataType::IsIntegralType(instruction->GetType()); if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) { // Replace code looking like // ADD dst, src, 0 @@ -1226,7 +1230,7 @@ void InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) { // can be non-zero after UShr. Transform Shr+And to UShr if the And-mask // precisely clears the shifted-in sign bits. if ((input_other->IsUShr() || input_other->IsShr()) && input_other->InputAt(1)->IsConstant()) { - size_t reg_bits = (instruction->GetResultType() == Primitive::kPrimLong) ? 64 : 32; + size_t reg_bits = (instruction->GetResultType() == DataType::Type::kInt64) ? 64 : 32; size_t shift = Int64FromConstant(input_other->InputAt(1)->AsConstant()) & (reg_bits - 1); size_t num_tail_bits_set = CTZ(value + 1); if ((num_tail_bits_set >= reg_bits - shift) && input_other->IsUShr()) { @@ -1447,7 +1451,7 @@ static constexpr bool CanDivideByReciprocalMultiplyDouble(int64_t divisor) { void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) { HConstant* input_cst = instruction->GetConstantRight(); HInstruction* input_other = instruction->GetLeastConstantLeft(); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); if ((input_cst != nullptr) && input_cst->IsOne()) { // Replace code looking like @@ -1471,19 +1475,19 @@ void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) { return; } - if ((input_cst != nullptr) && Primitive::IsFloatingPointType(type)) { + if ((input_cst != nullptr) && DataType::IsFloatingPointType(type)) { // Try replacing code looking like // DIV dst, src, constant // with // MUL dst, src, 1 / constant HConstant* reciprocal = nullptr; - if (type == Primitive::Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { double value = input_cst->AsDoubleConstant()->GetValue(); if (CanDivideByReciprocalMultiplyDouble(bit_cast<int64_t, double>(value))) { reciprocal = GetGraph()->GetDoubleConstant(1.0 / value); } } else { - DCHECK_EQ(type, Primitive::kPrimFloat); + DCHECK_EQ(type, DataType::Type::kFloat32); float value = input_cst->AsFloatConstant()->GetValue(); if (CanDivideByReciprocalMultiplyFloat(bit_cast<int32_t, float>(value))) { reciprocal = GetGraph()->GetFloatConstant(1.0f / value); @@ -1502,7 +1506,7 @@ void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) { void InstructionSimplifierVisitor::VisitMul(HMul* instruction) { HConstant* input_cst = instruction->GetConstantRight(); HInstruction* input_other = instruction->GetLeastConstantLeft(); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); HBasicBlock* block = instruction->GetBlock(); ArenaAllocator* allocator = GetGraph()->GetArena(); @@ -1522,7 +1526,7 @@ void InstructionSimplifierVisitor::VisitMul(HMul* instruction) { } if (input_cst->IsMinusOne() && - (Primitive::IsFloatingPointType(type) || Primitive::IsIntOrLongType(type))) { + (DataType::IsFloatingPointType(type) || DataType::IsIntOrLongType(type))) { // Replace code looking like // MUL dst, src, -1 // with @@ -1533,7 +1537,7 @@ void InstructionSimplifierVisitor::VisitMul(HMul* instruction) { return; } - if (Primitive::IsFloatingPointType(type) && + if (DataType::IsFloatingPointType(type) && ((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->GetValue() == 2.0f) || (input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->GetValue() == 2.0))) { // Replace code looking like @@ -1547,7 +1551,7 @@ void InstructionSimplifierVisitor::VisitMul(HMul* instruction) { return; } - if (Primitive::IsIntOrLongType(type)) { + if (DataType::IsIntOrLongType(type)) { int64_t factor = Int64FromConstant(input_cst); // Even though constant propagation also takes care of the zero case, other // optimizations can lead to having a zero multiplication. @@ -1630,7 +1634,7 @@ void InstructionSimplifierVisitor::VisitNeg(HNeg* instruction) { } if (input->IsSub() && input->HasOnlyOneNonEnvironmentUse() && - !Primitive::IsFloatingPointType(input->GetType())) { + !DataType::IsFloatingPointType(input->GetType())) { // Replace code looking like // SUB tmp, a, b // NEG dst, tmp @@ -1726,8 +1730,8 @@ void InstructionSimplifierVisitor::VisitSub(HSub* instruction) { HConstant* input_cst = instruction->GetConstantRight(); HInstruction* input_other = instruction->GetLeastConstantLeft(); - Primitive::Type type = instruction->GetType(); - if (Primitive::IsFloatingPointType(type)) { + DataType::Type type = instruction->GetType(); + if (DataType::IsFloatingPointType(type)) { return; } @@ -1818,7 +1822,7 @@ void InstructionSimplifierVisitor::VisitSub(HSub* instruction) { // SUB instruction is not needed in this case, we may use // one of inputs of ADD instead. // It is applicable to integral types only. - DCHECK(Primitive::IsIntegralType(type)); + DCHECK(DataType::IsIntegralType(type)); if (left->InputAt(1) == right) { instruction->ReplaceWith(left->InputAt(0)); RecordSimplification(); @@ -1853,7 +1857,7 @@ void InstructionSimplifierVisitor::VisitXor(HXor* instruction) { } if ((input_cst != nullptr) && input_cst->IsOne() - && input_other->GetType() == Primitive::kPrimBoolean) { + && input_other->GetType() == DataType::Type::kBool) { // Replace code looking like // XOR dst, src, 1 // with @@ -1930,7 +1934,7 @@ void InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) { void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke, bool is_left, - Primitive::Type type) { + DataType::Type type) { DCHECK(invoke->IsInvokeStaticOrDirect()); DCHECK_EQ(invoke->GetInvokeType(), InvokeType::kStatic); HInstruction* value = invoke->InputAt(0); @@ -1940,7 +1944,7 @@ void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke, // Unconditionally set the type of the negated distance to `int`, // as shift and rotate operations expect a 32-bit (or narrower) // value for their distance input. - distance = new (GetGraph()->GetArena()) HNeg(Primitive::kPrimInt, distance); + distance = new (GetGraph()->GetArena()) HNeg(DataType::Type::kInt32, distance); invoke->GetBlock()->InsertInstructionBefore(distance, invoke); } HRor* ror = new (GetGraph()->GetArena()) HRor(type, value, distance); @@ -1993,8 +1997,8 @@ void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) { ScopedObjectAccess soa(Thread::Current()); - Primitive::Type source_component_type = Primitive::kPrimVoid; - Primitive::Type destination_component_type = Primitive::kPrimVoid; + DataType::Type source_component_type = DataType::Type::kVoid; + DataType::Type destination_component_type = DataType::Type::kVoid; ReferenceTypeInfo destination_rti = destination->GetReferenceTypeInfo(); if (destination_rti.IsValid()) { if (destination_rti.IsObjectArray()) { @@ -2004,8 +2008,8 @@ void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) optimizations.SetDestinationIsTypedObjectArray(); } if (destination_rti.IsPrimitiveArrayClass()) { - destination_component_type = - destination_rti.GetTypeHandle()->GetComponentType()->GetPrimitiveType(); + destination_component_type = DataTypeFromPrimitive( + destination_rti.GetTypeHandle()->GetComponentType()->GetPrimitiveType()); optimizations.SetDestinationIsPrimitiveArray(); } else if (destination_rti.IsNonPrimitiveArrayClass()) { optimizations.SetDestinationIsNonPrimitiveArray(); @@ -2018,13 +2022,14 @@ void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) } if (source_rti.IsPrimitiveArrayClass()) { optimizations.SetSourceIsPrimitiveArray(); - source_component_type = source_rti.GetTypeHandle()->GetComponentType()->GetPrimitiveType(); + source_component_type = DataTypeFromPrimitive( + source_rti.GetTypeHandle()->GetComponentType()->GetPrimitiveType()); } else if (source_rti.IsNonPrimitiveArrayClass()) { optimizations.SetSourceIsNonPrimitiveArray(); } } // For primitive arrays, use their optimized ArtMethod implementations. - if ((source_component_type != Primitive::kPrimVoid) && + if ((source_component_type != DataType::Type::kVoid) && (source_component_type == destination_component_type)) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); PointerSize image_size = class_linker->GetImagePointerSize(); @@ -2032,28 +2037,28 @@ void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) mirror::Class* system = invoke->GetResolvedMethod()->GetDeclaringClass(); ArtMethod* method = nullptr; switch (source_component_type) { - case Primitive::kPrimBoolean: + case DataType::Type::kBool: method = system->FindClassMethod("arraycopy", "([ZI[ZII)V", image_size); break; - case Primitive::kPrimByte: + case DataType::Type::kInt8: method = system->FindClassMethod("arraycopy", "([BI[BII)V", image_size); break; - case Primitive::kPrimChar: + case DataType::Type::kUint16: method = system->FindClassMethod("arraycopy", "([CI[CII)V", image_size); break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: method = system->FindClassMethod("arraycopy", "([SI[SII)V", image_size); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: method = system->FindClassMethod("arraycopy", "([II[III)V", image_size); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: method = system->FindClassMethod("arraycopy", "([FI[FII)V", image_size); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: method = system->FindClassMethod("arraycopy", "([JI[JII)V", image_size); break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: method = system->FindClassMethod("arraycopy", "([DI[DII)V", image_size); break; default: @@ -2074,14 +2079,14 @@ void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) void InstructionSimplifierVisitor::SimplifyCompare(HInvoke* invoke, bool is_signum, - Primitive::Type type) { + DataType::Type type) { DCHECK(invoke->IsInvokeStaticOrDirect()); uint32_t dex_pc = invoke->GetDexPc(); HInstruction* left = invoke->InputAt(0); HInstruction* right; if (!is_signum) { right = invoke->InputAt(1); - } else if (type == Primitive::kPrimLong) { + } else if (type == DataType::Type::kInt64) { right = GetGraph()->GetLongConstant(0); } else { right = GetGraph()->GetIntConstant(0); @@ -2105,17 +2110,17 @@ void InstructionSimplifierVisitor::SimplifyFP2Int(HInvoke* invoke) { DCHECK(invoke->IsInvokeStaticOrDirect()); uint32_t dex_pc = invoke->GetDexPc(); HInstruction* x = invoke->InputAt(0); - Primitive::Type type = x->GetType(); + DataType::Type type = x->GetType(); // Set proper bit pattern for NaN and replace intrinsic with raw version. HInstruction* nan; - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { nan = GetGraph()->GetLongConstant(0x7ff8000000000000L); invoke->SetIntrinsic(Intrinsics::kDoubleDoubleToRawLongBits, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow); } else { - DCHECK_EQ(type, Primitive::kPrimFloat); + DCHECK_EQ(type, DataType::Type::kFloat32); nan = GetGraph()->GetIntConstant(0x7fc00000); invoke->SetIntrinsic(Intrinsics::kFloatFloatToRawIntBits, kNeedsEnvironmentOrCache, @@ -2145,7 +2150,7 @@ void InstructionSimplifierVisitor::SimplifyStringCharAt(HInvoke* invoke) { index, length, dex_pc, invoke->GetDexMethodIndex()); invoke->GetBlock()->InsertInstructionBefore(bounds_check, invoke); HArrayGet* array_get = new (arena) HArrayGet( - str, bounds_check, Primitive::kPrimChar, dex_pc, /* is_string_char_at */ true); + str, bounds_check, DataType::Type::kUint16, dex_pc, /* is_string_char_at */ true); invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, array_get); bounds_check->CopyEnvironmentFrom(invoke->GetEnvironment()); GetGraph()->SetHasBoundsChecks(true); @@ -2248,28 +2253,28 @@ void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) { SimplifySystemArrayCopy(instruction); break; case Intrinsics::kIntegerRotateRight: - SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimInt); + SimplifyRotate(instruction, /* is_left */ false, DataType::Type::kInt32); break; case Intrinsics::kLongRotateRight: - SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimLong); + SimplifyRotate(instruction, /* is_left */ false, DataType::Type::kInt64); break; case Intrinsics::kIntegerRotateLeft: - SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimInt); + SimplifyRotate(instruction, /* is_left */ true, DataType::Type::kInt32); break; case Intrinsics::kLongRotateLeft: - SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimLong); + SimplifyRotate(instruction, /* is_left */ true, DataType::Type::kInt64); break; case Intrinsics::kIntegerCompare: - SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimInt); + SimplifyCompare(instruction, /* is_signum */ false, DataType::Type::kInt32); break; case Intrinsics::kLongCompare: - SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimLong); + SimplifyCompare(instruction, /* is_signum */ false, DataType::Type::kInt64); break; case Intrinsics::kIntegerSignum: - SimplifyCompare(instruction, /* is_signum */ true, Primitive::kPrimInt); + SimplifyCompare(instruction, /* is_signum */ true, DataType::Type::kInt32); break; case Intrinsics::kLongSignum: - SimplifyCompare(instruction, /* is_signum */ true, Primitive::kPrimLong); + SimplifyCompare(instruction, /* is_signum */ true, DataType::Type::kInt64); break; case Intrinsics::kFloatIsNaN: case Intrinsics::kDoubleIsNaN: @@ -2337,7 +2342,7 @@ bool InstructionSimplifierVisitor::TryHandleAssociativeAndCommutativeOperation( HBinaryOperation* instruction) { DCHECK(instruction->IsCommutative()); - if (!Primitive::IsIntegralType(instruction->GetType())) { + if (!DataType::IsIntegralType(instruction->GetType())) { return false; } @@ -2387,12 +2392,12 @@ static HBinaryOperation* AsAddOrSub(HInstruction* binop) { } // Helper function that performs addition statically, considering the result type. -static int64_t ComputeAddition(Primitive::Type type, int64_t x, int64_t y) { +static int64_t ComputeAddition(DataType::Type type, int64_t x, int64_t y) { // Use the Compute() method for consistency with TryStaticEvaluation(). - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { return HAdd::Compute<int32_t>(x, y); } else { - DCHECK_EQ(type, Primitive::kPrimLong); + DCHECK_EQ(type, DataType::Type::kInt64); return HAdd::Compute<int64_t>(x, y); } } @@ -2414,8 +2419,8 @@ bool InstructionSimplifierVisitor::TrySubtractionChainSimplification( HBinaryOperation* instruction) { DCHECK(instruction->IsAdd() || instruction->IsSub()) << instruction->DebugName(); - Primitive::Type type = instruction->GetType(); - if (!Primitive::IsIntegralType(type)) { + DataType::Type type = instruction->GetType(); + if (!DataType::IsIntegralType(type)) { return false; } diff --git a/compiler/optimizing/instruction_simplifier_arm.cc b/compiler/optimizing/instruction_simplifier_arm.cc index a32d0ce42b..efd7cb47fe 100644 --- a/compiler/optimizing/instruction_simplifier_arm.cc +++ b/compiler/optimizing/instruction_simplifier_arm.cc @@ -38,8 +38,8 @@ bool InstructionSimplifierArmVisitor::TryMergeIntoShifterOperand(HInstruction* u DCHECK(CanFitInShifterOperand(bitfield_op)); DCHECK(!bitfield_op->HasEnvironmentUses()); - Primitive::Type type = use->GetType(); - if (type != Primitive::kPrimInt && type != Primitive::kPrimLong) { + DataType::Type type = use->GetType(); + if (type != DataType::Type::kInt32 && type != DataType::Type::kInt64) { return false; } @@ -70,17 +70,17 @@ bool InstructionSimplifierArmVisitor::TryMergeIntoShifterOperand(HInstruction* u int shift_amount = 0; HDataProcWithShifterOp::GetOpInfoFromInstruction(bitfield_op, &op_kind, &shift_amount); - shift_amount &= use->GetType() == Primitive::kPrimInt + shift_amount &= use->GetType() == DataType::Type::kInt32 ? kMaxIntShiftDistance : kMaxLongShiftDistance; if (HDataProcWithShifterOp::IsExtensionOp(op_kind)) { - if (!use->IsAdd() && (!use->IsSub() || use->GetType() != Primitive::kPrimLong)) { + if (!use->IsAdd() && (!use->IsSub() || use->GetType() != DataType::Type::kInt64)) { return false; } // Shift by 1 is a special case that results in the same number and type of instructions // as this simplification, but potentially shorter code. - } else if (type == Primitive::kPrimLong && shift_amount == 1) { + } else if (type == DataType::Type::kInt64 && shift_amount == 1) { return false; } @@ -143,7 +143,7 @@ void InstructionSimplifierArmVisitor::VisitAnd(HAnd* instruction) { void InstructionSimplifierArmVisitor::VisitArrayGet(HArrayGet* instruction) { size_t data_offset = CodeGenerator::GetArrayDataOffset(instruction); - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); // TODO: Implement reading (length + compression) for String compression feature from // negative offset (count_offset - data_offset). Thumb2Assembler (now removed) did @@ -153,9 +153,9 @@ void InstructionSimplifierArmVisitor::VisitArrayGet(HArrayGet* instruction) { return; } - if (type == Primitive::kPrimLong - || type == Primitive::kPrimFloat - || type == Primitive::kPrimDouble) { + if (type == DataType::Type::kInt64 + || type == DataType::Type::kFloat32 + || type == DataType::Type::kFloat64) { // T32 doesn't support ShiftedRegOffset mem address mode for these types // to enable optimization. return; @@ -170,13 +170,13 @@ void InstructionSimplifierArmVisitor::VisitArrayGet(HArrayGet* instruction) { } void InstructionSimplifierArmVisitor::VisitArraySet(HArraySet* instruction) { - size_t access_size = Primitive::ComponentSize(instruction->GetComponentType()); + size_t access_size = DataType::Size(instruction->GetComponentType()); size_t data_offset = mirror::Array::DataOffset(access_size).Uint32Value(); - Primitive::Type type = instruction->GetComponentType(); + DataType::Type type = instruction->GetComponentType(); - if (type == Primitive::kPrimLong - || type == Primitive::kPrimFloat - || type == Primitive::kPrimDouble) { + if (type == DataType::Type::kInt64 + || type == DataType::Type::kFloat32 + || type == DataType::Type::kFloat64) { // T32 doesn't support ShiftedRegOffset mem address mode for these types // to enable optimization. return; @@ -215,15 +215,15 @@ void InstructionSimplifierArmVisitor::VisitShr(HShr* instruction) { } void InstructionSimplifierArmVisitor::VisitTypeConversion(HTypeConversion* instruction) { - Primitive::Type result_type = instruction->GetResultType(); - Primitive::Type input_type = instruction->GetInputType(); + DataType::Type result_type = instruction->GetResultType(); + DataType::Type input_type = instruction->GetInputType(); if (input_type == result_type) { // We let the arch-independent code handle this. return; } - if (Primitive::IsIntegralType(result_type) && Primitive::IsIntegralType(input_type)) { + if (DataType::IsIntegralType(result_type) && DataType::IsIntegralType(input_type)) { TryMergeIntoUsersShifterOperand(instruction); } } diff --git a/compiler/optimizing/instruction_simplifier_arm64.cc b/compiler/optimizing/instruction_simplifier_arm64.cc index 7c9bfb11b2..1c3b79dc03 100644 --- a/compiler/optimizing/instruction_simplifier_arm64.cc +++ b/compiler/optimizing/instruction_simplifier_arm64.cc @@ -38,8 +38,8 @@ bool InstructionSimplifierArm64Visitor::TryMergeIntoShifterOperand(HInstruction* DCHECK(CanFitInShifterOperand(bitfield_op)); DCHECK(!bitfield_op->HasEnvironmentUses()); - Primitive::Type type = use->GetType(); - if (type != Primitive::kPrimInt && type != Primitive::kPrimLong) { + DataType::Type type = use->GetType(); + if (type != DataType::Type::kInt32 && type != DataType::Type::kInt64) { return false; } @@ -150,7 +150,7 @@ void InstructionSimplifierArm64Visitor::VisitArrayGet(HArrayGet* instruction) { } void InstructionSimplifierArm64Visitor::VisitArraySet(HArraySet* instruction) { - size_t access_size = Primitive::ComponentSize(instruction->GetComponentType()); + size_t access_size = DataType::Size(instruction->GetComponentType()); size_t data_offset = mirror::Array::DataOffset(access_size).Uint32Value(); if (TryExtractArrayAccessAddress(instruction, instruction->GetArray(), @@ -185,15 +185,15 @@ void InstructionSimplifierArm64Visitor::VisitShr(HShr* instruction) { } void InstructionSimplifierArm64Visitor::VisitTypeConversion(HTypeConversion* instruction) { - Primitive::Type result_type = instruction->GetResultType(); - Primitive::Type input_type = instruction->GetInputType(); + DataType::Type result_type = instruction->GetResultType(); + DataType::Type input_type = instruction->GetInputType(); if (input_type == result_type) { // We let the arch-independent code handle this. return; } - if (Primitive::IsIntegralType(result_type) && Primitive::IsIntegralType(input_type)) { + if (DataType::IsIntegralType(result_type) && DataType::IsIntegralType(input_type)) { TryMergeIntoUsersShifterOperand(instruction); } } diff --git a/compiler/optimizing/instruction_simplifier_shared.cc b/compiler/optimizing/instruction_simplifier_shared.cc index 7a759b9118..73d866fbea 100644 --- a/compiler/optimizing/instruction_simplifier_shared.cc +++ b/compiler/optimizing/instruction_simplifier_shared.cc @@ -25,7 +25,7 @@ namespace { bool TrySimpleMultiplyAccumulatePatterns(HMul* mul, HBinaryOperation* input_binop, HInstruction* input_other) { - DCHECK(Primitive::IsIntOrLongType(mul->GetType())); + DCHECK(DataType::IsIntOrLongType(mul->GetType())); DCHECK(input_binop->IsAdd() || input_binop->IsSub()); DCHECK_NE(input_binop, input_other); if (!input_binop->HasOnlyOneNonEnvironmentUse()) { @@ -88,16 +88,16 @@ bool TrySimpleMultiplyAccumulatePatterns(HMul* mul, } // namespace bool TryCombineMultiplyAccumulate(HMul* mul, InstructionSet isa) { - Primitive::Type type = mul->GetType(); + DataType::Type type = mul->GetType(); switch (isa) { case kArm: case kThumb2: - if (type != Primitive::kPrimInt) { + if (type != DataType::Type::kInt32) { return false; } break; case kArm64: - if (!Primitive::IsIntOrLongType(type)) { + if (!DataType::IsIntOrLongType(type)) { return false; } break; @@ -240,13 +240,13 @@ bool TryExtractArrayAccessAddress(HInstruction* access, return false; } if (access->IsArraySet() && - access->AsArraySet()->GetValue()->GetType() == Primitive::kPrimNot) { + access->AsArraySet()->GetValue()->GetType() == DataType::Type::kReference) { // The access may require a runtime call or the original array pointer. return false; } if (kEmitCompilerReadBarrier && access->IsArrayGet() && - access->GetType() == Primitive::kPrimNot) { + access->GetType() == DataType::Type::kReference) { // For object arrays, the read barrier instrumentation requires // the original array pointer. // TODO: This can be relaxed for Baker CC. @@ -290,10 +290,10 @@ bool TryExtractVecArrayAccessAddress(HVecMemoryOperation* access, HInstruction* HGraph* graph = access->GetBlock()->GetGraph(); ArenaAllocator* arena = graph->GetArena(); - Primitive::Type packed_type = access->GetPackedType(); + DataType::Type packed_type = access->GetPackedType(); uint32_t data_offset = mirror::Array::DataOffset( - Primitive::ComponentSize(packed_type)).Uint32Value(); - size_t component_shift = Primitive::ComponentSizeShift(packed_type); + DataType::Size(packed_type)).Uint32Value(); + size_t component_shift = DataType::SizeShift(packed_type); bool is_extracting_beneficial = false; // It is beneficial to extract index intermediate address only if there are at least 2 users. @@ -301,10 +301,10 @@ bool TryExtractVecArrayAccessAddress(HVecMemoryOperation* access, HInstruction* HInstruction* user = use.GetUser(); if (user->IsVecMemoryOperation() && user != access) { HVecMemoryOperation* another_access = user->AsVecMemoryOperation(); - Primitive::Type another_packed_type = another_access->GetPackedType(); + DataType::Type another_packed_type = another_access->GetPackedType(); uint32_t another_data_offset = mirror::Array::DataOffset( - Primitive::ComponentSize(another_packed_type)).Uint32Value(); - size_t another_component_shift = Primitive::ComponentSizeShift(another_packed_type); + DataType::Size(another_packed_type)).Uint32Value(); + size_t another_component_shift = DataType::SizeShift(another_packed_type); if (another_data_offset == data_offset && another_component_shift == component_shift) { is_extracting_beneficial = true; break; diff --git a/compiler/optimizing/instruction_simplifier_shared.h b/compiler/optimizing/instruction_simplifier_shared.h index 31e23833b1..b016a8769e 100644 --- a/compiler/optimizing/instruction_simplifier_shared.h +++ b/compiler/optimizing/instruction_simplifier_shared.h @@ -26,10 +26,10 @@ namespace helpers { inline bool CanFitInShifterOperand(HInstruction* instruction) { if (instruction->IsTypeConversion()) { HTypeConversion* conversion = instruction->AsTypeConversion(); - Primitive::Type result_type = conversion->GetResultType(); - Primitive::Type input_type = conversion->GetInputType(); + DataType::Type result_type = conversion->GetResultType(); + DataType::Type input_type = conversion->GetInputType(); // We don't expect to see the same type as input and result. - return Primitive::IsIntegralType(result_type) && Primitive::IsIntegralType(input_type) && + return DataType::IsIntegralType(result_type) && DataType::IsIntegralType(input_type) && (result_type != input_type); } else { return (instruction->IsShl() && instruction->AsShl()->InputAt(1)->IsIntConstant()) || diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 96efe7f3b1..75a1ce7e6f 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -76,16 +76,16 @@ ArenaAllocator* IntrinsicCodeGeneratorARM64::GetAllocator() { #define __ codegen->GetVIXLAssembler()-> static void MoveFromReturnRegister(Location trg, - Primitive::Type type, + DataType::Type type, CodeGeneratorARM64* codegen) { if (!trg.IsValid()) { - DCHECK(type == Primitive::kPrimVoid); + DCHECK(type == DataType::Type::kVoid); return; } - DCHECK_NE(type, Primitive::kPrimVoid); + DCHECK_NE(type, DataType::Type::kVoid); - if (Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) { + if (DataType::IsIntegralType(type) || type == DataType::Type::kReference) { Register trg_reg = RegisterFrom(trg, type); Register res_reg = RegisterFrom(ARM64ReturnLocation(type), type); __ Mov(trg_reg, res_reg, kDiscardForSameWReg); @@ -173,7 +173,7 @@ class ReadBarrierSystemArrayCopySlowPathARM64 : public SlowPathCodeARM64 { DCHECK(instruction_->GetLocations()->Intrinsified()); DCHECK_EQ(instruction_->AsInvoke()->GetIntrinsic(), Intrinsics::kSystemArrayCopy); - const int32_t element_size = Primitive::ComponentSize(Primitive::kPrimNot); + const int32_t element_size = DataType::Size(DataType::Type::kReference); Register src_curr_addr = XRegisterFrom(locations->GetTemp(0)); Register dst_curr_addr = XRegisterFrom(locations->GetTemp(1)); @@ -303,18 +303,18 @@ static void CreateIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { } static void GenReverseBytes(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, MacroAssembler* masm) { Location in = locations->InAt(0); Location out = locations->Out(); switch (type) { - case Primitive::kPrimShort: + case DataType::Type::kInt16: __ Rev16(WRegisterFrom(out), WRegisterFrom(in)); __ Sxth(WRegisterFrom(out), WRegisterFrom(out)); break; - case Primitive::kPrimInt: - case Primitive::kPrimLong: + case DataType::Type::kInt32: + case DataType::Type::kInt64: __ Rev(RegisterFrom(out, type), RegisterFrom(in, type)); break; default: @@ -328,7 +328,7 @@ void IntrinsicLocationsBuilderARM64::VisitIntegerReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitIntegerReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimInt, GetVIXLAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt32, GetVIXLAssembler()); } void IntrinsicLocationsBuilderARM64::VisitLongReverseBytes(HInvoke* invoke) { @@ -336,7 +336,7 @@ void IntrinsicLocationsBuilderARM64::VisitLongReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitLongReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimLong, GetVIXLAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt64, GetVIXLAssembler()); } void IntrinsicLocationsBuilderARM64::VisitShortReverseBytes(HInvoke* invoke) { @@ -344,7 +344,7 @@ void IntrinsicLocationsBuilderARM64::VisitShortReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitShortReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimShort, GetVIXLAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt16, GetVIXLAssembler()); } static void CreateIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { @@ -357,9 +357,9 @@ static void CreateIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { } static void GenNumberOfLeadingZeros(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, MacroAssembler* masm) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); Location in = locations->InAt(0); Location out = locations->Out(); @@ -372,7 +372,7 @@ void IntrinsicLocationsBuilderARM64::VisitIntegerNumberOfLeadingZeros(HInvoke* i } void IntrinsicCodeGeneratorARM64::VisitIntegerNumberOfLeadingZeros(HInvoke* invoke) { - GenNumberOfLeadingZeros(invoke->GetLocations(), Primitive::kPrimInt, GetVIXLAssembler()); + GenNumberOfLeadingZeros(invoke->GetLocations(), DataType::Type::kInt32, GetVIXLAssembler()); } void IntrinsicLocationsBuilderARM64::VisitLongNumberOfLeadingZeros(HInvoke* invoke) { @@ -380,13 +380,13 @@ void IntrinsicLocationsBuilderARM64::VisitLongNumberOfLeadingZeros(HInvoke* invo } void IntrinsicCodeGeneratorARM64::VisitLongNumberOfLeadingZeros(HInvoke* invoke) { - GenNumberOfLeadingZeros(invoke->GetLocations(), Primitive::kPrimLong, GetVIXLAssembler()); + GenNumberOfLeadingZeros(invoke->GetLocations(), DataType::Type::kInt64, GetVIXLAssembler()); } static void GenNumberOfTrailingZeros(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, MacroAssembler* masm) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); Location in = locations->InAt(0); Location out = locations->Out(); @@ -400,7 +400,7 @@ void IntrinsicLocationsBuilderARM64::VisitIntegerNumberOfTrailingZeros(HInvoke* } void IntrinsicCodeGeneratorARM64::VisitIntegerNumberOfTrailingZeros(HInvoke* invoke) { - GenNumberOfTrailingZeros(invoke->GetLocations(), Primitive::kPrimInt, GetVIXLAssembler()); + GenNumberOfTrailingZeros(invoke->GetLocations(), DataType::Type::kInt32, GetVIXLAssembler()); } void IntrinsicLocationsBuilderARM64::VisitLongNumberOfTrailingZeros(HInvoke* invoke) { @@ -408,13 +408,13 @@ void IntrinsicLocationsBuilderARM64::VisitLongNumberOfTrailingZeros(HInvoke* inv } void IntrinsicCodeGeneratorARM64::VisitLongNumberOfTrailingZeros(HInvoke* invoke) { - GenNumberOfTrailingZeros(invoke->GetLocations(), Primitive::kPrimLong, GetVIXLAssembler()); + GenNumberOfTrailingZeros(invoke->GetLocations(), DataType::Type::kInt64, GetVIXLAssembler()); } static void GenReverse(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, MacroAssembler* masm) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); Location in = locations->InAt(0); Location out = locations->Out(); @@ -427,7 +427,7 @@ void IntrinsicLocationsBuilderARM64::VisitIntegerReverse(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitIntegerReverse(HInvoke* invoke) { - GenReverse(invoke->GetLocations(), Primitive::kPrimInt, GetVIXLAssembler()); + GenReverse(invoke->GetLocations(), DataType::Type::kInt32, GetVIXLAssembler()); } void IntrinsicLocationsBuilderARM64::VisitLongReverse(HInvoke* invoke) { @@ -435,19 +435,19 @@ void IntrinsicLocationsBuilderARM64::VisitLongReverse(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitLongReverse(HInvoke* invoke) { - GenReverse(invoke->GetLocations(), Primitive::kPrimLong, GetVIXLAssembler()); + GenReverse(invoke->GetLocations(), DataType::Type::kInt64, GetVIXLAssembler()); } -static void GenBitCount(HInvoke* instr, Primitive::Type type, MacroAssembler* masm) { - DCHECK(Primitive::IsIntOrLongType(type)) << type; - DCHECK_EQ(instr->GetType(), Primitive::kPrimInt); - DCHECK_EQ(Primitive::PrimitiveKind(instr->InputAt(0)->GetType()), type); +static void GenBitCount(HInvoke* instr, DataType::Type type, MacroAssembler* masm) { + DCHECK(DataType::IsIntOrLongType(type)) << type; + DCHECK_EQ(instr->GetType(), DataType::Type::kInt32); + DCHECK_EQ(DataType::Kind(instr->InputAt(0)->GetType()), type); UseScratchRegisterScope temps(masm); Register src = InputRegisterAt(instr, 0); Register dst = RegisterFrom(instr->GetLocations()->Out(), type); - FPRegister fpr = (type == Primitive::kPrimLong) ? temps.AcquireD() : temps.AcquireS(); + FPRegister fpr = (type == DataType::Type::kInt64) ? temps.AcquireD() : temps.AcquireS(); __ Fmov(fpr, src); __ Cnt(fpr.V8B(), fpr.V8B()); @@ -460,7 +460,7 @@ void IntrinsicLocationsBuilderARM64::VisitLongBitCount(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitLongBitCount(HInvoke* invoke) { - GenBitCount(invoke, Primitive::kPrimLong, GetVIXLAssembler()); + GenBitCount(invoke, DataType::Type::kInt64, GetVIXLAssembler()); } void IntrinsicLocationsBuilderARM64::VisitIntegerBitCount(HInvoke* invoke) { @@ -468,19 +468,19 @@ void IntrinsicLocationsBuilderARM64::VisitIntegerBitCount(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitIntegerBitCount(HInvoke* invoke) { - GenBitCount(invoke, Primitive::kPrimInt, GetVIXLAssembler()); + GenBitCount(invoke, DataType::Type::kInt32, GetVIXLAssembler()); } -static void GenHighestOneBit(HInvoke* invoke, Primitive::Type type, MacroAssembler* masm) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); +static void GenHighestOneBit(HInvoke* invoke, DataType::Type type, MacroAssembler* masm) { + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); UseScratchRegisterScope temps(masm); Register src = InputRegisterAt(invoke, 0); Register dst = RegisterFrom(invoke->GetLocations()->Out(), type); - Register temp = (type == Primitive::kPrimLong) ? temps.AcquireX() : temps.AcquireW(); - size_t high_bit = (type == Primitive::kPrimLong) ? 63u : 31u; - size_t clz_high_bit = (type == Primitive::kPrimLong) ? 6u : 5u; + Register temp = (type == DataType::Type::kInt64) ? temps.AcquireX() : temps.AcquireW(); + size_t high_bit = (type == DataType::Type::kInt64) ? 63u : 31u; + size_t clz_high_bit = (type == DataType::Type::kInt64) ? 6u : 5u; __ Clz(temp, src); __ Mov(dst, UINT64_C(1) << high_bit); // MOV (bitmask immediate) @@ -493,7 +493,7 @@ void IntrinsicLocationsBuilderARM64::VisitIntegerHighestOneBit(HInvoke* invoke) } void IntrinsicCodeGeneratorARM64::VisitIntegerHighestOneBit(HInvoke* invoke) { - GenHighestOneBit(invoke, Primitive::kPrimInt, GetVIXLAssembler()); + GenHighestOneBit(invoke, DataType::Type::kInt32, GetVIXLAssembler()); } void IntrinsicLocationsBuilderARM64::VisitLongHighestOneBit(HInvoke* invoke) { @@ -501,17 +501,17 @@ void IntrinsicLocationsBuilderARM64::VisitLongHighestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitLongHighestOneBit(HInvoke* invoke) { - GenHighestOneBit(invoke, Primitive::kPrimLong, GetVIXLAssembler()); + GenHighestOneBit(invoke, DataType::Type::kInt64, GetVIXLAssembler()); } -static void GenLowestOneBit(HInvoke* invoke, Primitive::Type type, MacroAssembler* masm) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); +static void GenLowestOneBit(HInvoke* invoke, DataType::Type type, MacroAssembler* masm) { + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); UseScratchRegisterScope temps(masm); Register src = InputRegisterAt(invoke, 0); Register dst = RegisterFrom(invoke->GetLocations()->Out(), type); - Register temp = (type == Primitive::kPrimLong) ? temps.AcquireX() : temps.AcquireW(); + Register temp = (type == DataType::Type::kInt64) ? temps.AcquireX() : temps.AcquireW(); __ Neg(temp, src); __ And(dst, temp, src); @@ -522,7 +522,7 @@ void IntrinsicLocationsBuilderARM64::VisitIntegerLowestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitIntegerLowestOneBit(HInvoke* invoke) { - GenLowestOneBit(invoke, Primitive::kPrimInt, GetVIXLAssembler()); + GenLowestOneBit(invoke, DataType::Type::kInt32, GetVIXLAssembler()); } void IntrinsicLocationsBuilderARM64::VisitLongLowestOneBit(HInvoke* invoke) { @@ -530,7 +530,7 @@ void IntrinsicLocationsBuilderARM64::VisitLongLowestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitLongLowestOneBit(HInvoke* invoke) { - GenLowestOneBit(invoke, Primitive::kPrimLong, GetVIXLAssembler()); + GenLowestOneBit(invoke, DataType::Type::kInt64, GetVIXLAssembler()); } static void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { @@ -902,18 +902,18 @@ void IntrinsicLocationsBuilderARM64::VisitThreadCurrentThread(HInvoke* invoke) { } void IntrinsicCodeGeneratorARM64::VisitThreadCurrentThread(HInvoke* invoke) { - codegen_->Load(Primitive::kPrimNot, WRegisterFrom(invoke->GetLocations()->Out()), + codegen_->Load(DataType::Type::kReference, WRegisterFrom(invoke->GetLocations()->Out()), MemOperand(tr, Thread::PeerOffset<kArm64PointerSize>().Int32Value())); } static void GenUnsafeGet(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, bool is_volatile, CodeGeneratorARM64* codegen) { LocationSummary* locations = invoke->GetLocations(); - DCHECK((type == Primitive::kPrimInt) || - (type == Primitive::kPrimLong) || - (type == Primitive::kPrimNot)); + DCHECK((type == DataType::Type::kInt32) || + (type == DataType::Type::kInt64) || + (type == DataType::Type::kReference)); Location base_loc = locations->InAt(1); Register base = WRegisterFrom(base_loc); // Object pointer. Location offset_loc = locations->InAt(2); @@ -921,7 +921,7 @@ static void GenUnsafeGet(HInvoke* invoke, Location trg_loc = locations->Out(); Register trg = RegisterFrom(trg_loc, type); - if (type == Primitive::kPrimNot && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { + if (type == DataType::Type::kReference && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { // UnsafeGetObject/UnsafeGetObjectVolatile with Baker's read barrier case. Register temp = WRegisterFrom(locations->GetTemp(0)); codegen->GenerateReferenceLoadWithBakerReadBarrier(invoke, @@ -942,7 +942,7 @@ static void GenUnsafeGet(HInvoke* invoke, codegen->Load(type, trg, mem_op); } - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { DCHECK(trg.IsW()); codegen->MaybeGenerateReadBarrierSlow(invoke, trg_loc, trg_loc, base_loc, 0u, offset_loc); } @@ -991,22 +991,22 @@ void IntrinsicLocationsBuilderARM64::VisitUnsafeGetObjectVolatile(HInvoke* invok } void IntrinsicCodeGeneratorARM64::VisitUnsafeGet(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafeGetVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafeGetLong(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafeGetLongVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafeGetObject(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ true, codegen_); } static void CreateIntIntIntIntToVoid(ArenaAllocator* arena, HInvoke* invoke) { @@ -1048,7 +1048,7 @@ void IntrinsicLocationsBuilderARM64::VisitUnsafePutLongVolatile(HInvoke* invoke) } static void GenUnsafePut(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, bool is_volatile, bool is_ordered, CodeGeneratorARM64* codegen) { @@ -1066,7 +1066,7 @@ static void GenUnsafePut(HInvoke* invoke, // freeing the temporary registers so they can be used in `MarkGCCard`. UseScratchRegisterScope temps(masm); - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { DCHECK(value.IsW()); Register temp = temps.AcquireW(); __ Mov(temp.W(), value.W()); @@ -1081,7 +1081,7 @@ static void GenUnsafePut(HInvoke* invoke, } } - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { bool value_can_be_null = true; // TODO: Worth finding out this information? codegen->MarkGCCard(base, value, value_can_be_null); } @@ -1089,63 +1089,63 @@ static void GenUnsafePut(HInvoke* invoke, void IntrinsicCodeGeneratorARM64::VisitUnsafePut(HInvoke* invoke) { GenUnsafePut(invoke, - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ false, /* is_ordered */ false, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafePutOrdered(HInvoke* invoke) { GenUnsafePut(invoke, - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ false, /* is_ordered */ true, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafePutVolatile(HInvoke* invoke) { GenUnsafePut(invoke, - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ true, /* is_ordered */ false, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafePutObject(HInvoke* invoke) { GenUnsafePut(invoke, - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ false, /* is_ordered */ false, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafePutObjectOrdered(HInvoke* invoke) { GenUnsafePut(invoke, - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ false, /* is_ordered */ true, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafePutObjectVolatile(HInvoke* invoke) { GenUnsafePut(invoke, - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ true, /* is_ordered */ false, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafePutLong(HInvoke* invoke) { GenUnsafePut(invoke, - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ false, /* is_ordered */ false, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafePutLongOrdered(HInvoke* invoke) { GenUnsafePut(invoke, - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ false, /* is_ordered */ true, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafePutLongVolatile(HInvoke* invoke) { GenUnsafePut(invoke, - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ true, /* is_ordered */ false, codegen_); @@ -1153,7 +1153,7 @@ void IntrinsicCodeGeneratorARM64::VisitUnsafePutLongVolatile(HInvoke* invoke) { static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, HInvoke* invoke, - Primitive::Type type) { + DataType::Type type) { bool can_call = kEmitCompilerReadBarrier && kUseBakerReadBarrier && (invoke->GetIntrinsic() == Intrinsics::kUnsafeCASObject); @@ -1172,17 +1172,17 @@ static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, // operations to potentially clobber the output. Likewise when // emitting a (Baker) read barrier, which may call. Location::OutputOverlap overlaps = - ((kPoisonHeapReferences && type == Primitive::kPrimNot) || can_call) + ((kPoisonHeapReferences && type == DataType::Type::kReference) || can_call) ? Location::kOutputOverlap : Location::kNoOutputOverlap; locations->SetOut(Location::RequiresRegister(), overlaps); - if (type == Primitive::kPrimNot && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { + if (type == DataType::Type::kReference && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { // Temporary register for (Baker) read barrier. locations->AddTemp(Location::RequiresRegister()); } } -static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorARM64* codegen) { +static void GenCas(HInvoke* invoke, DataType::Type type, CodeGeneratorARM64* codegen) { MacroAssembler* masm = codegen->GetVIXLAssembler(); LocationSummary* locations = invoke->GetLocations(); @@ -1196,7 +1196,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorARM64* co Register value = RegisterFrom(locations->InAt(4), type); // Value. // This needs to be before the temp registers, as MarkGCCard also uses VIXL temps. - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // Mark card for object assuming new value is stored. bool value_can_be_null = true; // TODO: Worth finding out this information? codegen->MarkGCCard(base, value, value_can_be_null); @@ -1228,7 +1228,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorARM64* co __ Add(tmp_ptr, base.X(), Operand(offset)); - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { codegen->GetAssembler()->PoisonHeapReference(expected); if (value.Is(expected)) { // Do not poison `value`, as it is the same register as @@ -1253,7 +1253,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorARM64* co __ Bind(&exit_loop); __ Cset(out, eq); - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { codegen->GetAssembler()->UnpoisonHeapReference(expected); if (value.Is(expected)) { // Do not unpoison `value`, as it is the same register as @@ -1265,10 +1265,10 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorARM64* co } void IntrinsicLocationsBuilderARM64::VisitUnsafeCASInt(HInvoke* invoke) { - CreateIntIntIntIntIntToInt(arena_, invoke, Primitive::kPrimInt); + CreateIntIntIntIntIntToInt(arena_, invoke, DataType::Type::kInt32); } void IntrinsicLocationsBuilderARM64::VisitUnsafeCASLong(HInvoke* invoke) { - CreateIntIntIntIntIntToInt(arena_, invoke, Primitive::kPrimLong); + CreateIntIntIntIntIntToInt(arena_, invoke, DataType::Type::kInt64); } void IntrinsicLocationsBuilderARM64::VisitUnsafeCASObject(HInvoke* invoke) { // The only read barrier implementation supporting the @@ -1277,21 +1277,21 @@ void IntrinsicLocationsBuilderARM64::VisitUnsafeCASObject(HInvoke* invoke) { return; } - CreateIntIntIntIntIntToInt(arena_, invoke, Primitive::kPrimNot); + CreateIntIntIntIntIntToInt(arena_, invoke, DataType::Type::kReference); } void IntrinsicCodeGeneratorARM64::VisitUnsafeCASInt(HInvoke* invoke) { - GenCas(invoke, Primitive::kPrimInt, codegen_); + GenCas(invoke, DataType::Type::kInt32, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafeCASLong(HInvoke* invoke) { - GenCas(invoke, Primitive::kPrimLong, codegen_); + GenCas(invoke, DataType::Type::kInt64, codegen_); } void IntrinsicCodeGeneratorARM64::VisitUnsafeCASObject(HInvoke* invoke) { // The only read barrier implementation supporting the // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); - GenCas(invoke, Primitive::kPrimNot, codegen_); + GenCas(invoke, DataType::Type::kReference, codegen_); } void IntrinsicLocationsBuilderARM64::VisitStringCompareTo(HInvoke* invoke) { @@ -1397,7 +1397,7 @@ void IntrinsicCodeGeneratorARM64::VisitStringCompareTo(HInvoke* invoke) { DCHECK_ALIGNED(value_offset, 8); static_assert(IsAligned<8>(kObjectAlignment), "String of odd length is not zero padded"); - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); // Promote temp2 to an X reg, ready for LDR. @@ -1457,7 +1457,7 @@ void IntrinsicCodeGeneratorARM64::VisitStringCompareTo(HInvoke* invoke) { __ Bind(&different_compression); // Comparison for different compression style. - const size_t c_char_size = Primitive::ComponentSize(Primitive::kPrimByte); + const size_t c_char_size = DataType::Size(DataType::Type::kInt8); DCHECK_EQ(c_char_size, 1u); temp1 = temp1.W(); temp2 = temp2.W(); @@ -1731,7 +1731,7 @@ static void GenerateVisitStringIndexOf(HInvoke* invoke, __ Bind(slow_path->GetExitLabel()); return; } - } else if (code_point->GetType() != Primitive::kPrimChar) { + } else if (code_point->GetType() != DataType::Type::kUint16) { Register char_reg = WRegisterFrom(locations->InAt(1)); __ Tst(char_reg, 0xFFFF0000); slow_path = new (allocator) IntrinsicSlowPathARM64(invoke); @@ -1762,7 +1762,7 @@ void IntrinsicLocationsBuilderARM64::VisitStringIndexOf(HInvoke* invoke) { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, LocationFrom(calling_convention.GetRegisterAt(1))); - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimInt)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kInt32)); // Need to send start_index=0. locations->AddTemp(LocationFrom(calling_convention.GetRegisterAt(2))); @@ -1783,7 +1783,7 @@ void IntrinsicLocationsBuilderARM64::VisitStringIndexOfAfter(HInvoke* invoke) { locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, LocationFrom(calling_convention.GetRegisterAt(1))); locations->SetInAt(2, LocationFrom(calling_convention.GetRegisterAt(2))); - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimInt)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kInt32)); } void IntrinsicCodeGeneratorARM64::VisitStringIndexOfAfter(HInvoke* invoke) { @@ -1800,7 +1800,7 @@ void IntrinsicLocationsBuilderARM64::VisitStringNewStringFromBytes(HInvoke* invo locations->SetInAt(1, LocationFrom(calling_convention.GetRegisterAt(1))); locations->SetInAt(2, LocationFrom(calling_convention.GetRegisterAt(2))); locations->SetInAt(3, LocationFrom(calling_convention.GetRegisterAt(3))); - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference)); } void IntrinsicCodeGeneratorARM64::VisitStringNewStringFromBytes(HInvoke* invoke) { @@ -1826,7 +1826,7 @@ void IntrinsicLocationsBuilderARM64::VisitStringNewStringFromChars(HInvoke* invo locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, LocationFrom(calling_convention.GetRegisterAt(1))); locations->SetInAt(2, LocationFrom(calling_convention.GetRegisterAt(2))); - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference)); } void IntrinsicCodeGeneratorARM64::VisitStringNewStringFromChars(HInvoke* invoke) { @@ -1846,7 +1846,7 @@ void IntrinsicLocationsBuilderARM64::VisitStringNewStringFromString(HInvoke* inv kIntrinsified); InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0))); - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference)); } void IntrinsicCodeGeneratorARM64::VisitStringNewStringFromString(HInvoke* invoke) { @@ -1866,8 +1866,8 @@ void IntrinsicCodeGeneratorARM64::VisitStringNewStringFromString(HInvoke* invoke static void CreateFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) { DCHECK_EQ(invoke->GetNumberOfArguments(), 1U); - DCHECK(Primitive::IsFloatingPointType(invoke->InputAt(0)->GetType())); - DCHECK(Primitive::IsFloatingPointType(invoke->GetType())); + DCHECK(DataType::IsFloatingPointType(invoke->InputAt(0)->GetType())); + DCHECK(DataType::IsFloatingPointType(invoke->GetType())); LocationSummary* const locations = new (arena) LocationSummary(invoke, LocationSummary::kCallOnMainOnly, @@ -1880,9 +1880,9 @@ static void CreateFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) { static void CreateFPFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) { DCHECK_EQ(invoke->GetNumberOfArguments(), 2U); - DCHECK(Primitive::IsFloatingPointType(invoke->InputAt(0)->GetType())); - DCHECK(Primitive::IsFloatingPointType(invoke->InputAt(1)->GetType())); - DCHECK(Primitive::IsFloatingPointType(invoke->GetType())); + DCHECK(DataType::IsFloatingPointType(invoke->InputAt(0)->GetType())); + DCHECK(DataType::IsFloatingPointType(invoke->InputAt(1)->GetType())); + DCHECK(DataType::IsFloatingPointType(invoke->GetType())); LocationSummary* const locations = new (arena) LocationSummary(invoke, LocationSummary::kCallOnMainOnly, @@ -2056,7 +2056,7 @@ void IntrinsicCodeGeneratorARM64::VisitStringGetCharsNoCheck(HInvoke* invoke) { LocationSummary* locations = invoke->GetLocations(); // Check assumption that sizeof(Char) is 2 (used in scaling below). - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); // Location of data in char array buffer. @@ -2135,7 +2135,7 @@ void IntrinsicCodeGeneratorARM64::VisitStringGetCharsNoCheck(HInvoke* invoke) { __ B(&done); if (mirror::kUseStringCompression) { - const size_t c_char_size = Primitive::ComponentSize(Primitive::kPrimByte); + const size_t c_char_size = DataType::Size(DataType::Type::kInt8); DCHECK_EQ(c_char_size, 1u); __ Bind(&compressed_string_preloop); __ Add(src_ptr, src_ptr, Operand(srcBegin)); @@ -2219,7 +2219,7 @@ static void CheckSystemArrayCopyPosition(MacroAssembler* masm, if (!length_is_input_length) { // Check that length(input) >= length. __ Ldr(temp, MemOperand(input, length_offset)); - __ Cmp(temp, OperandFrom(length, Primitive::kPrimInt)); + __ Cmp(temp, OperandFrom(length, DataType::Type::kInt32)); __ B(slow_path->GetEntryLabel(), lt); } } else { @@ -2229,7 +2229,7 @@ static void CheckSystemArrayCopyPosition(MacroAssembler* masm, __ B(slow_path->GetEntryLabel(), lt); // Check that (length(input) - pos) >= length. - __ Cmp(temp, OperandFrom(length, Primitive::kPrimInt)); + __ Cmp(temp, OperandFrom(length, DataType::Type::kInt32)); __ B(slow_path->GetEntryLabel(), lt); } } else if (length_is_input_length) { @@ -2244,7 +2244,7 @@ static void CheckSystemArrayCopyPosition(MacroAssembler* masm, __ Ldr(temp, MemOperand(input, length_offset)); __ Subs(temp, temp, pos_reg); // Ccmp if length(input) >= pos, else definitely bail to slow path (N!=V == lt). - __ Ccmp(temp, OperandFrom(length, Primitive::kPrimInt), NFlag, ge); + __ Ccmp(temp, OperandFrom(length, DataType::Type::kInt32), NFlag, ge); __ B(slow_path->GetEntryLabel(), lt); } } @@ -2253,7 +2253,7 @@ static void CheckSystemArrayCopyPosition(MacroAssembler* masm, // source address for System.arraycopy* intrinsics in `src_base`, // `dst_base` and `src_end` respectively. static void GenSystemArrayCopyAddresses(MacroAssembler* masm, - Primitive::Type type, + DataType::Type type, const Register& src, const Location& src_pos, const Register& dst, @@ -2263,10 +2263,10 @@ static void GenSystemArrayCopyAddresses(MacroAssembler* masm, const Register& dst_base, const Register& src_end) { // This routine is used by the SystemArrayCopy and the SystemArrayCopyChar intrinsics. - DCHECK(type == Primitive::kPrimNot || type == Primitive::kPrimChar) + DCHECK(type == DataType::Type::kReference || type == DataType::Type::kUint16) << "Unexpected element type: " << type; - const int32_t element_size = Primitive::ComponentSize(type); - const int32_t element_size_shift = Primitive::ComponentSizeShift(type); + const int32_t element_size = DataType::Size(type); + const int32_t element_size_shift = DataType::SizeShift(type); const uint32_t data_offset = mirror::Array::DataOffset(element_size).Uint32Value(); if (src_pos.IsConstant()) { @@ -2353,7 +2353,7 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopyChar(HInvoke* invoke) { src_stop_addr = src_stop_addr.X(); GenSystemArrayCopyAddresses(masm, - Primitive::kPrimChar, + DataType::Type::kUint16, src, src_pos, dst, @@ -2364,7 +2364,7 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopyChar(HInvoke* invoke) { src_stop_addr); // Iterate over the arrays and do a raw copy of the chars. - const int32_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const int32_t char_size = DataType::Size(DataType::Type::kUint16); UseScratchRegisterScope temps(masm); Register tmp = temps.AcquireW(); vixl::aarch64::Label loop, done; @@ -2781,8 +2781,8 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopy(HInvoke* invoke) { Register dst_curr_addr = temp2.X(); Register src_stop_addr = temp3.X(); vixl::aarch64::Label done; - const Primitive::Type type = Primitive::kPrimNot; - const int32_t element_size = Primitive::ComponentSize(type); + const DataType::Type type = DataType::Type::kReference; + const int32_t element_size = DataType::Size(type); if (length.IsRegister()) { // Don't enter the copy loop if the length is null. @@ -2957,7 +2957,7 @@ void IntrinsicLocationsBuilderARM64::VisitIntegerValueOf(HInvoke* invoke) { IntrinsicVisitor::ComputeIntegerValueOfLocations( invoke, codegen_, - calling_convention.GetReturnLocation(Primitive::kPrimNot), + calling_convention.GetReturnLocation(DataType::Type::kReference), Location::RegisterLocation(calling_convention.GetRegisterAt(0).GetCode())); } @@ -2966,7 +2966,7 @@ void IntrinsicCodeGeneratorARM64::VisitIntegerValueOf(HInvoke* invoke) { LocationSummary* locations = invoke->GetLocations(); MacroAssembler* masm = GetVIXLAssembler(); - Register out = RegisterFrom(locations->Out(), Primitive::kPrimNot); + Register out = RegisterFrom(locations->Out(), DataType::Type::kReference); UseScratchRegisterScope temps(masm); Register temp = temps.AcquireW(); InvokeRuntimeCallingConvention calling_convention; @@ -2996,7 +2996,7 @@ void IntrinsicCodeGeneratorARM64::VisitIntegerValueOf(HInvoke* invoke) { codegen_->GenerateMemoryBarrier(MemBarrierKind::kStoreStore); } } else { - Register in = RegisterFrom(locations->InAt(0), Primitive::kPrimInt); + Register in = RegisterFrom(locations->InAt(0), DataType::Type::kInt32); // Check bounds of our cache. __ Add(out.W(), in.W(), -info.low); __ Cmp(out.W(), info.high - info.low + 1); @@ -3007,8 +3007,8 @@ void IntrinsicCodeGeneratorARM64::VisitIntegerValueOf(HInvoke* invoke) { uint32_t address = dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(info.cache)); __ Ldr(temp.W(), codegen_->DeduplicateBootImageAddressLiteral(data_offset + address)); MemOperand source = HeapOperand( - temp, out.X(), LSL, Primitive::ComponentSizeShift(Primitive::kPrimNot)); - codegen_->Load(Primitive::kPrimNot, out, source); + temp, out.X(), LSL, DataType::SizeShift(DataType::Type::kReference)); + codegen_->Load(DataType::Type::kReference, out, source); codegen_->GetAssembler()->MaybeUnpoisonHeapReference(out); __ B(&done); __ Bind(&allocate); @@ -3034,7 +3034,7 @@ void IntrinsicLocationsBuilderARM64::VisitThreadInterrupted(HInvoke* invoke) { void IntrinsicCodeGeneratorARM64::VisitThreadInterrupted(HInvoke* invoke) { MacroAssembler* masm = GetVIXLAssembler(); - Register out = RegisterFrom(invoke->GetLocations()->Out(), Primitive::kPrimInt); + Register out = RegisterFrom(invoke->GetLocations()->Out(), DataType::Type::kInt32); UseScratchRegisterScope temps(masm); Register temp = temps.AcquireX(); diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc index e2494f0ce8..7ce576c307 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.cc +++ b/compiler/optimizing/intrinsics_arm_vixl.cc @@ -126,16 +126,16 @@ class IntrinsicSlowPathARMVIXL : public SlowPathCodeARMVIXL { // Compute base address for the System.arraycopy intrinsic in `base`. static void GenSystemArrayCopyBaseAddress(ArmVIXLAssembler* assembler, - Primitive::Type type, + DataType::Type type, const vixl32::Register& array, const Location& pos, const vixl32::Register& base) { // This routine is only used by the SystemArrayCopy intrinsic at the - // moment. We can allow Primitive::kPrimNot as `type` to implement + // moment. We can allow DataType::Type::kReference as `type` to implement // the SystemArrayCopyChar intrinsic. - DCHECK_EQ(type, Primitive::kPrimNot); - const int32_t element_size = Primitive::ComponentSize(type); - const uint32_t element_size_shift = Primitive::ComponentSizeShift(type); + DCHECK_EQ(type, DataType::Type::kReference); + const int32_t element_size = DataType::Size(type); + const uint32_t element_size_shift = DataType::SizeShift(type); const uint32_t data_offset = mirror::Array::DataOffset(element_size).Uint32Value(); if (pos.IsConstant()) { @@ -149,16 +149,16 @@ static void GenSystemArrayCopyBaseAddress(ArmVIXLAssembler* assembler, // Compute end address for the System.arraycopy intrinsic in `end`. static void GenSystemArrayCopyEndAddress(ArmVIXLAssembler* assembler, - Primitive::Type type, + DataType::Type type, const Location& copy_length, const vixl32::Register& base, const vixl32::Register& end) { // This routine is only used by the SystemArrayCopy intrinsic at the - // moment. We can allow Primitive::kPrimNot as `type` to implement + // moment. We can allow DataType::Type::kReference as `type` to implement // the SystemArrayCopyChar intrinsic. - DCHECK_EQ(type, Primitive::kPrimNot); - const int32_t element_size = Primitive::ComponentSize(type); - const uint32_t element_size_shift = Primitive::ComponentSizeShift(type); + DCHECK_EQ(type, DataType::Type::kReference); + const int32_t element_size = DataType::Size(type); + const uint32_t element_size_shift = DataType::SizeShift(type); if (copy_length.IsConstant()) { int32_t constant = Int32ConstantFrom(copy_length); @@ -188,8 +188,8 @@ class ReadBarrierSystemArrayCopySlowPathARMVIXL : public SlowPathCodeARMVIXL { DCHECK(instruction_->GetLocations()->Intrinsified()); DCHECK_EQ(instruction_->AsInvoke()->GetIntrinsic(), Intrinsics::kSystemArrayCopy); - Primitive::Type type = Primitive::kPrimNot; - const int32_t element_size = Primitive::ComponentSize(type); + DataType::Type type = DataType::Type::kReference; + const int32_t element_size = DataType::Size(type); vixl32::Register dest = InputRegisterAt(instruction_, 2); Location dest_pos = locations->InAt(3); @@ -349,16 +349,16 @@ static void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { } static void GenNumberOfLeadingZeros(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, CodeGeneratorARMVIXL* codegen) { ArmVIXLAssembler* assembler = codegen->GetAssembler(); LocationSummary* locations = invoke->GetLocations(); Location in = locations->InAt(0); vixl32::Register out = RegisterFrom(locations->Out()); - DCHECK((type == Primitive::kPrimInt) || (type == Primitive::kPrimLong)); + DCHECK((type == DataType::Type::kInt32) || (type == DataType::Type::kInt64)); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { vixl32::Register in_reg_lo = LowRegisterFrom(in); vixl32::Register in_reg_hi = HighRegisterFrom(in); vixl32::Label end; @@ -380,7 +380,7 @@ void IntrinsicLocationsBuilderARMVIXL::VisitIntegerNumberOfLeadingZeros(HInvoke* } void IntrinsicCodeGeneratorARMVIXL::VisitIntegerNumberOfLeadingZeros(HInvoke* invoke) { - GenNumberOfLeadingZeros(invoke, Primitive::kPrimInt, codegen_); + GenNumberOfLeadingZeros(invoke, DataType::Type::kInt32, codegen_); } void IntrinsicLocationsBuilderARMVIXL::VisitLongNumberOfLeadingZeros(HInvoke* invoke) { @@ -388,19 +388,19 @@ void IntrinsicLocationsBuilderARMVIXL::VisitLongNumberOfLeadingZeros(HInvoke* in } void IntrinsicCodeGeneratorARMVIXL::VisitLongNumberOfLeadingZeros(HInvoke* invoke) { - GenNumberOfLeadingZeros(invoke, Primitive::kPrimLong, codegen_); + GenNumberOfLeadingZeros(invoke, DataType::Type::kInt64, codegen_); } static void GenNumberOfTrailingZeros(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, CodeGeneratorARMVIXL* codegen) { - DCHECK((type == Primitive::kPrimInt) || (type == Primitive::kPrimLong)); + DCHECK((type == DataType::Type::kInt32) || (type == DataType::Type::kInt64)); ArmVIXLAssembler* assembler = codegen->GetAssembler(); LocationSummary* locations = invoke->GetLocations(); vixl32::Register out = RegisterFrom(locations->Out()); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { vixl32::Register in_reg_lo = LowRegisterFrom(locations->InAt(0)); vixl32::Register in_reg_hi = HighRegisterFrom(locations->InAt(0)); vixl32::Label end; @@ -426,7 +426,7 @@ void IntrinsicLocationsBuilderARMVIXL::VisitIntegerNumberOfTrailingZeros(HInvoke } void IntrinsicCodeGeneratorARMVIXL::VisitIntegerNumberOfTrailingZeros(HInvoke* invoke) { - GenNumberOfTrailingZeros(invoke, Primitive::kPrimInt, codegen_); + GenNumberOfTrailingZeros(invoke, DataType::Type::kInt32, codegen_); } void IntrinsicLocationsBuilderARMVIXL::VisitLongNumberOfTrailingZeros(HInvoke* invoke) { @@ -434,7 +434,7 @@ void IntrinsicLocationsBuilderARMVIXL::VisitLongNumberOfTrailingZeros(HInvoke* i } void IntrinsicCodeGeneratorARMVIXL::VisitLongNumberOfTrailingZeros(HInvoke* invoke) { - GenNumberOfTrailingZeros(invoke, Primitive::kPrimLong, codegen_); + GenNumberOfTrailingZeros(invoke, DataType::Type::kInt64, codegen_); } static void MathAbsFP(HInvoke* invoke, ArmVIXLAssembler* assembler) { @@ -963,7 +963,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitThreadCurrentThread(HInvoke* invoke) { } static void GenUnsafeGet(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, bool is_volatile, CodeGeneratorARMVIXL* codegen) { LocationSummary* locations = invoke->GetLocations(); @@ -975,7 +975,7 @@ static void GenUnsafeGet(HInvoke* invoke, Location trg_loc = locations->Out(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { vixl32::Register trg = RegisterFrom(trg_loc); __ Ldr(trg, MemOperand(base, offset)); if (is_volatile) { @@ -984,7 +984,7 @@ static void GenUnsafeGet(HInvoke* invoke, break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { vixl32::Register trg = RegisterFrom(trg_loc); if (kEmitCompilerReadBarrier) { if (kUseBakerReadBarrier) { @@ -1011,7 +1011,7 @@ static void GenUnsafeGet(HInvoke* invoke, break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { vixl32::Register trg_lo = LowRegisterFrom(trg_loc); vixl32::Register trg_hi = HighRegisterFrom(trg_loc); if (is_volatile && !codegen->GetInstructionSetFeatures().HasAtomicLdrdAndStrd()) { @@ -1036,7 +1036,7 @@ static void GenUnsafeGet(HInvoke* invoke, static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke, - Primitive::Type type) { + DataType::Type type) { bool can_call = kEmitCompilerReadBarrier && (invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObject || invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObjectVolatile); @@ -1053,7 +1053,7 @@ static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, locations->SetInAt(2, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), (can_call ? Location::kOutputOverlap : Location::kNoOutputOverlap)); - if (type == Primitive::kPrimNot && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { + if (type == DataType::Type::kReference && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { // We need a temporary register for the read barrier marking slow // path in CodeGeneratorARMVIXL::GenerateReferenceLoadWithBakerReadBarrier. locations->AddTemp(Location::RequiresRegister()); @@ -1061,46 +1061,46 @@ static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGet(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimInt); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt32); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimInt); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt32); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetLong(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimLong); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt64); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetLongVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimLong); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt64); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetObject(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimNot); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kReference); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimNot); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kReference); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGet(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetLong(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetLongVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetObject(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ true, codegen_); } static void CreateIntIntIntIntToVoid(ArenaAllocator* arena, const ArmInstructionSetFeatures& features, - Primitive::Type type, + DataType::Type type, bool is_volatile, HInvoke* invoke) { LocationSummary* locations = new (arena) LocationSummary(invoke, @@ -1111,13 +1111,13 @@ static void CreateIntIntIntIntToVoid(ArenaAllocator* arena, locations->SetInAt(2, Location::RequiresRegister()); locations->SetInAt(3, Location::RequiresRegister()); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { // Potentially need temps for ldrexd-strexd loop. if (is_volatile && !features.HasAtomicLdrdAndStrd()) { locations->AddTemp(Location::RequiresRegister()); // Temp_lo. locations->AddTemp(Location::RequiresRegister()); // Temp_hi. } - } else if (type == Primitive::kPrimNot) { + } else if (type == DataType::Type::kReference) { // Temps for card-marking. locations->AddTemp(Location::RequiresRegister()); // Temp. locations->AddTemp(Location::RequiresRegister()); // Card. @@ -1125,38 +1125,44 @@ static void CreateIntIntIntIntToVoid(ArenaAllocator* arena, } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePut(HInvoke* invoke) { - CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimInt, /* is_volatile */ false, invoke); + CreateIntIntIntIntToVoid( + arena_, features_, DataType::Type::kInt32, /* is_volatile */ false, invoke); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutOrdered(HInvoke* invoke) { - CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimInt, /* is_volatile */ false, invoke); + CreateIntIntIntIntToVoid( + arena_, features_, DataType::Type::kInt32, /* is_volatile */ false, invoke); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutVolatile(HInvoke* invoke) { - CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimInt, /* is_volatile */ true, invoke); + CreateIntIntIntIntToVoid( + arena_, features_, DataType::Type::kInt32, /* is_volatile */ true, invoke); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutObject(HInvoke* invoke) { - CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimNot, /* is_volatile */ false, invoke); + CreateIntIntIntIntToVoid( + arena_, features_, DataType::Type::kReference, /* is_volatile */ false, invoke); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutObjectOrdered(HInvoke* invoke) { - CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimNot, /* is_volatile */ false, invoke); + CreateIntIntIntIntToVoid( + arena_, features_, DataType::Type::kReference, /* is_volatile */ false, invoke); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutObjectVolatile(HInvoke* invoke) { - CreateIntIntIntIntToVoid(arena_, features_, Primitive::kPrimNot, /* is_volatile */ true, invoke); + CreateIntIntIntIntToVoid( + arena_, features_, DataType::Type::kReference, /* is_volatile */ true, invoke); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutLong(HInvoke* invoke) { CreateIntIntIntIntToVoid( - arena_, features_, Primitive::kPrimLong, /* is_volatile */ false, invoke); + arena_, features_, DataType::Type::kInt64, /* is_volatile */ false, invoke); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutLongOrdered(HInvoke* invoke) { CreateIntIntIntIntToVoid( - arena_, features_, Primitive::kPrimLong, /* is_volatile */ false, invoke); + arena_, features_, DataType::Type::kInt64, /* is_volatile */ false, invoke); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutLongVolatile(HInvoke* invoke) { CreateIntIntIntIntToVoid( - arena_, features_, Primitive::kPrimLong, /* is_volatile */ true, invoke); + arena_, features_, DataType::Type::kInt64, /* is_volatile */ true, invoke); } static void GenUnsafePut(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, bool is_volatile, bool is_ordered, CodeGeneratorARMVIXL* codegen) { @@ -1170,7 +1176,7 @@ static void GenUnsafePut(LocationSummary* locations, __ Dmb(vixl32::ISH); } - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { vixl32::Register value_lo = LowRegisterFrom(locations->InAt(3)); vixl32::Register value_hi = HighRegisterFrom(locations->InAt(3)); value = value_lo; @@ -1193,7 +1199,7 @@ static void GenUnsafePut(LocationSummary* locations, } else { value = RegisterFrom(locations->InAt(3)); vixl32::Register source = value; - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { vixl32::Register temp = RegisterFrom(locations->GetTemp(0)); __ Mov(temp, value); assembler->PoisonHeapReference(temp); @@ -1206,7 +1212,7 @@ static void GenUnsafePut(LocationSummary* locations, __ Dmb(vixl32::ISH); } - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { vixl32::Register temp = RegisterFrom(locations->GetTemp(0)); vixl32::Register card = RegisterFrom(locations->GetTemp(1)); bool value_can_be_null = true; // TODO: Worth finding out this information? @@ -1216,63 +1222,63 @@ static void GenUnsafePut(LocationSummary* locations, void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePut(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ false, /* is_ordered */ false, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutOrdered(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ false, /* is_ordered */ true, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutVolatile(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ true, /* is_ordered */ false, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutObject(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ false, /* is_ordered */ false, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutObjectOrdered(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ false, /* is_ordered */ true, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutObjectVolatile(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ true, /* is_ordered */ false, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutLong(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ false, /* is_ordered */ false, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutLongOrdered(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ false, /* is_ordered */ true, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutLongVolatile(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ true, /* is_ordered */ false, codegen_); @@ -1280,7 +1286,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutLongVolatile(HInvoke* invoke) static void CreateIntIntIntIntIntToIntPlusTemps(ArenaAllocator* arena, HInvoke* invoke, - Primitive::Type type) { + DataType::Type type) { bool can_call = kEmitCompilerReadBarrier && kUseBakerReadBarrier && (invoke->GetIntrinsic() == Intrinsics::kUnsafeCASObject); @@ -1299,7 +1305,7 @@ static void CreateIntIntIntIntIntToIntPlusTemps(ArenaAllocator* arena, // operations to potentially clobber the output. Likewise when // emitting a (Baker) read barrier, which may call. Location::OutputOverlap overlaps = - ((kPoisonHeapReferences && type == Primitive::kPrimNot) || can_call) + ((kPoisonHeapReferences && type == DataType::Type::kReference) || can_call) ? Location::kOutputOverlap : Location::kNoOutputOverlap; locations->SetOut(Location::RequiresRegister(), overlaps); @@ -1311,8 +1317,8 @@ static void CreateIntIntIntIntIntToIntPlusTemps(ArenaAllocator* arena, locations->AddTemp(Location::RequiresRegister()); // Temp 1. } -static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorARMVIXL* codegen) { - DCHECK_NE(type, Primitive::kPrimLong); +static void GenCas(HInvoke* invoke, DataType::Type type, CodeGeneratorARMVIXL* codegen) { + DCHECK_NE(type, DataType::Type::kInt64); ArmVIXLAssembler* assembler = codegen->GetAssembler(); LocationSummary* locations = invoke->GetLocations(); @@ -1330,7 +1336,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorARMVIXL* vixl32::Register tmp_ptr = RegisterFrom(tmp_ptr_loc); // Pointer to actual memory. vixl32::Register tmp = RegisterFrom(locations->GetTemp(1)); // Value in memory. - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // The only read barrier implementation supporting the // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); @@ -1362,7 +1368,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorARMVIXL* __ Add(tmp_ptr, base, offset); - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { codegen->GetAssembler()->PoisonHeapReference(expected); if (value.Is(expected)) { // Do not poison `value`, as it is the same register as @@ -1409,7 +1415,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorARMVIXL* __ mov(cc, out, 0); } - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { codegen->GetAssembler()->UnpoisonHeapReference(expected); if (value.Is(expected)) { // Do not unpoison `value`, as it is the same register as @@ -1421,7 +1427,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorARMVIXL* } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeCASInt(HInvoke* invoke) { - CreateIntIntIntIntIntToIntPlusTemps(arena_, invoke, Primitive::kPrimInt); + CreateIntIntIntIntIntToIntPlusTemps(arena_, invoke, DataType::Type::kInt32); } void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeCASObject(HInvoke* invoke) { // The only read barrier implementation supporting the @@ -1430,17 +1436,17 @@ void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeCASObject(HInvoke* invoke) { return; } - CreateIntIntIntIntIntToIntPlusTemps(arena_, invoke, Primitive::kPrimNot); + CreateIntIntIntIntIntToIntPlusTemps(arena_, invoke, DataType::Type::kReference); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeCASInt(HInvoke* invoke) { - GenCas(invoke, Primitive::kPrimInt, codegen_); + GenCas(invoke, DataType::Type::kInt32, codegen_); } void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeCASObject(HInvoke* invoke) { // The only read barrier implementation supporting the // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); - GenCas(invoke, Primitive::kPrimNot, codegen_); + GenCas(invoke, DataType::Type::kReference, codegen_); } void IntrinsicLocationsBuilderARMVIXL::VisitStringCompareTo(HInvoke* invoke) { @@ -1558,7 +1564,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) { static_assert(IsAligned<8>(kObjectAlignment), "String data must be 8-byte aligned for unrolled CompareTo loop."); - const unsigned char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const unsigned char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); UseScratchRegisterScope temps(assembler->GetVIXLAssembler()); @@ -1645,7 +1651,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) { __ Bind(&different_compression); // Comparison for different compression style. - const size_t c_char_size = Primitive::ComponentSize(Primitive::kPrimByte); + const size_t c_char_size = DataType::Size(DataType::Type::kInt8); DCHECK_EQ(c_char_size, 1u); // We want to free up the temp3, currently holding `str.count`, for comparison. @@ -1943,7 +1949,7 @@ static void GenerateVisitStringIndexOf(HInvoke* invoke, __ Bind(slow_path->GetExitLabel()); return; } - } else if (code_point->GetType() != Primitive::kPrimChar) { + } else if (code_point->GetType() != DataType::Type::kUint16) { vixl32::Register char_reg = InputRegisterAt(invoke, 1); // 0xffff is not modified immediate but 0x10000 is, so use `>= 0x10000` instead of `> 0xffff`. __ Cmp(char_reg, static_cast<uint32_t>(std::numeric_limits<uint16_t>::max()) + 1); @@ -2450,8 +2456,8 @@ void IntrinsicCodeGeneratorARMVIXL::VisitSystemArrayCopy(HInvoke* invoke) { // Null constant length: not need to emit the loop code at all. } else { vixl32::Label done; - const Primitive::Type type = Primitive::kPrimNot; - const int32_t element_size = Primitive::ComponentSize(type); + const DataType::Type type = DataType::Type::kReference; + const int32_t element_size = DataType::Size(type); if (length.IsRegister()) { // Don't enter the copy loop if the length is null. @@ -2576,8 +2582,8 @@ static void CreateFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) { } DCHECK_EQ(invoke->GetNumberOfArguments(), 1U); - DCHECK_EQ(invoke->InputAt(0)->GetType(), Primitive::kPrimDouble); - DCHECK_EQ(invoke->GetType(), Primitive::kPrimDouble); + DCHECK_EQ(invoke->InputAt(0)->GetType(), DataType::Type::kFloat64); + DCHECK_EQ(invoke->GetType(), DataType::Type::kFloat64); LocationSummary* const locations = new (arena) LocationSummary(invoke, LocationSummary::kCallOnMainOnly, @@ -2602,9 +2608,9 @@ static void CreateFPFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) } DCHECK_EQ(invoke->GetNumberOfArguments(), 2U); - DCHECK_EQ(invoke->InputAt(0)->GetType(), Primitive::kPrimDouble); - DCHECK_EQ(invoke->InputAt(1)->GetType(), Primitive::kPrimDouble); - DCHECK_EQ(invoke->GetType(), Primitive::kPrimDouble); + DCHECK_EQ(invoke->InputAt(0)->GetType(), DataType::Type::kFloat64); + DCHECK_EQ(invoke->InputAt(1)->GetType(), DataType::Type::kFloat64); + DCHECK_EQ(invoke->GetType(), DataType::Type::kFloat64); LocationSummary* const locations = new (arena) LocationSummary(invoke, LocationSummary::kCallOnMainOnly, @@ -2859,12 +2865,12 @@ void IntrinsicCodeGeneratorARMVIXL::VisitShortReverseBytes(HInvoke* invoke) { __ Revsh(OutputRegister(invoke), InputRegisterAt(invoke, 0)); } -static void GenBitCount(HInvoke* instr, Primitive::Type type, ArmVIXLAssembler* assembler) { - DCHECK(Primitive::IsIntOrLongType(type)) << type; - DCHECK_EQ(instr->GetType(), Primitive::kPrimInt); - DCHECK_EQ(Primitive::PrimitiveKind(instr->InputAt(0)->GetType()), type); +static void GenBitCount(HInvoke* instr, DataType::Type type, ArmVIXLAssembler* assembler) { + DCHECK(DataType::IsIntOrLongType(type)) << type; + DCHECK_EQ(instr->GetType(), DataType::Type::kInt32); + DCHECK_EQ(DataType::Kind(instr->InputAt(0)->GetType()), type); - bool is_long = type == Primitive::kPrimLong; + bool is_long = type == DataType::Type::kInt64; LocationSummary* locations = instr->GetLocations(); Location in = locations->InAt(0); vixl32::Register src_0 = is_long ? LowRegisterFrom(in) : RegisterFrom(in); @@ -2893,7 +2899,7 @@ void IntrinsicLocationsBuilderARMVIXL::VisitIntegerBitCount(HInvoke* invoke) { } void IntrinsicCodeGeneratorARMVIXL::VisitIntegerBitCount(HInvoke* invoke) { - GenBitCount(invoke, Primitive::kPrimInt, GetAssembler()); + GenBitCount(invoke, DataType::Type::kInt32, GetAssembler()); } void IntrinsicLocationsBuilderARMVIXL::VisitLongBitCount(HInvoke* invoke) { @@ -2901,19 +2907,19 @@ void IntrinsicLocationsBuilderARMVIXL::VisitLongBitCount(HInvoke* invoke) { } void IntrinsicCodeGeneratorARMVIXL::VisitLongBitCount(HInvoke* invoke) { - GenBitCount(invoke, Primitive::kPrimLong, GetAssembler()); + GenBitCount(invoke, DataType::Type::kInt64, GetAssembler()); } static void GenHighestOneBit(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, CodeGeneratorARMVIXL* codegen) { - DCHECK(Primitive::IsIntOrLongType(type)); + DCHECK(DataType::IsIntOrLongType(type)); ArmVIXLAssembler* assembler = codegen->GetAssembler(); UseScratchRegisterScope temps(assembler->GetVIXLAssembler()); const vixl32::Register temp = temps.Acquire(); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { LocationSummary* locations = invoke->GetLocations(); Location in = locations->InAt(0); Location out = locations->Out(); @@ -2959,7 +2965,7 @@ void IntrinsicLocationsBuilderARMVIXL::VisitIntegerHighestOneBit(HInvoke* invoke } void IntrinsicCodeGeneratorARMVIXL::VisitIntegerHighestOneBit(HInvoke* invoke) { - GenHighestOneBit(invoke, Primitive::kPrimInt, codegen_); + GenHighestOneBit(invoke, DataType::Type::kInt32, codegen_); } void IntrinsicLocationsBuilderARMVIXL::VisitLongHighestOneBit(HInvoke* invoke) { @@ -2967,19 +2973,19 @@ void IntrinsicLocationsBuilderARMVIXL::VisitLongHighestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorARMVIXL::VisitLongHighestOneBit(HInvoke* invoke) { - GenHighestOneBit(invoke, Primitive::kPrimLong, codegen_); + GenHighestOneBit(invoke, DataType::Type::kInt64, codegen_); } static void GenLowestOneBit(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, CodeGeneratorARMVIXL* codegen) { - DCHECK(Primitive::IsIntOrLongType(type)); + DCHECK(DataType::IsIntOrLongType(type)); ArmVIXLAssembler* assembler = codegen->GetAssembler(); UseScratchRegisterScope temps(assembler->GetVIXLAssembler()); const vixl32::Register temp = temps.Acquire(); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { LocationSummary* locations = invoke->GetLocations(); Location in = locations->InAt(0); Location out = locations->Out(); @@ -3024,7 +3030,7 @@ void IntrinsicLocationsBuilderARMVIXL::VisitIntegerLowestOneBit(HInvoke* invoke) } void IntrinsicCodeGeneratorARMVIXL::VisitIntegerLowestOneBit(HInvoke* invoke) { - GenLowestOneBit(invoke, Primitive::kPrimInt, codegen_); + GenLowestOneBit(invoke, DataType::Type::kInt32, codegen_); } void IntrinsicLocationsBuilderARMVIXL::VisitLongLowestOneBit(HInvoke* invoke) { @@ -3032,7 +3038,7 @@ void IntrinsicLocationsBuilderARMVIXL::VisitLongLowestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorARMVIXL::VisitLongLowestOneBit(HInvoke* invoke) { - GenLowestOneBit(invoke, Primitive::kPrimLong, codegen_); + GenLowestOneBit(invoke, DataType::Type::kInt64, codegen_); } void IntrinsicLocationsBuilderARMVIXL::VisitStringGetCharsNoCheck(HInvoke* invoke) { @@ -3056,7 +3062,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringGetCharsNoCheck(HInvoke* invoke) LocationSummary* locations = invoke->GetLocations(); // Check assumption that sizeof(Char) is 2 (used in scaling below). - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); // Location of data in char array buffer. @@ -3144,7 +3150,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringGetCharsNoCheck(HInvoke* invoke) if (mirror::kUseStringCompression) { __ B(final_label); - const size_t c_char_size = Primitive::ComponentSize(Primitive::kPrimByte); + const size_t c_char_size = DataType::Size(DataType::Type::kInt8); DCHECK_EQ(c_char_size, 1u); // Copy loop for compressed src, copying 1 character (8-bit) to (16-bit) at a time. __ Bind(&compressed_string_preloop); @@ -3285,7 +3291,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitIntegerValueOf(HInvoke* invoke) { uint32_t data_offset = mirror::Array::DataOffset(kHeapReferenceSize).Uint32Value(); uint32_t address = dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(info.cache)); __ Ldr(temp, codegen_->DeduplicateBootImageAddressLiteral(data_offset + address)); - codegen_->LoadFromShiftedRegOffset(Primitive::kPrimNot, locations->Out(), temp, out); + codegen_->LoadFromShiftedRegOffset(DataType::Type::kReference, locations->Out(), temp, out); assembler->MaybeUnpoisonHeapReference(out); __ B(&done); __ Bind(&allocate); diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index fe5579c8be..8847256532 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -61,16 +61,16 @@ inline bool IntrinsicCodeGeneratorMIPS::Is32BitFPU() const { #define __ codegen->GetAssembler()-> static void MoveFromReturnRegister(Location trg, - Primitive::Type type, + DataType::Type type, CodeGeneratorMIPS* codegen) { if (!trg.IsValid()) { - DCHECK_EQ(type, Primitive::kPrimVoid); + DCHECK_EQ(type, DataType::Type::kVoid); return; } - DCHECK_NE(type, Primitive::kPrimVoid); + DCHECK_NE(type, DataType::Type::kVoid); - if (Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) { + if (DataType::IsIntegralType(type) || type == DataType::Type::kReference) { Register trg_reg = trg.AsRegister<Register>(); if (trg_reg != V0) { __ Move(V0, trg_reg); @@ -78,7 +78,7 @@ static void MoveFromReturnRegister(Location trg, } else { FRegister trg_reg = trg.AsFpuRegister<FRegister>(); if (trg_reg != F0) { - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ MovS(F0, trg_reg); } else { __ MovD(F0, trg_reg); @@ -247,17 +247,17 @@ static void CreateIntToIntLocations(ArenaAllocator* arena, } static void GenReverse(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, bool isR2OrNewer, bool isR6, bool reverseBits, MipsAssembler* assembler) { - DCHECK(type == Primitive::kPrimShort || - type == Primitive::kPrimInt || - type == Primitive::kPrimLong); - DCHECK(type != Primitive::kPrimShort || !reverseBits); + DCHECK(type == DataType::Type::kInt16 || + type == DataType::Type::kInt32 || + type == DataType::Type::kInt64); + DCHECK(type != DataType::Type::kInt16 || !reverseBits); - if (type == Primitive::kPrimShort) { + if (type == DataType::Type::kInt16) { Register in = locations->InAt(0).AsRegister<Register>(); Register out = locations->Out().AsRegister<Register>(); @@ -271,7 +271,7 @@ static void GenReverse(LocationSummary* locations, __ Srl(out, out, 24); __ Or(out, out, TMP); } - } else if (type == Primitive::kPrimInt) { + } else if (type == DataType::Type::kInt32) { Register in = locations->InAt(0).AsRegister<Register>(); Register out = locations->Out().AsRegister<Register>(); @@ -316,7 +316,7 @@ static void GenReverse(LocationSummary* locations, __ Or(out, TMP, out); } } - } else if (type == Primitive::kPrimLong) { + } else if (type == DataType::Type::kInt64) { Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); Register out_lo = locations->Out().AsRegisterPairLow<Register>(); @@ -407,7 +407,7 @@ void IntrinsicLocationsBuilderMIPS::VisitIntegerReverseBytes(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitIntegerReverseBytes(HInvoke* invoke) { GenReverse(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, IsR2OrNewer(), IsR6(), /* reverseBits */ false, @@ -421,7 +421,7 @@ void IntrinsicLocationsBuilderMIPS::VisitLongReverseBytes(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitLongReverseBytes(HInvoke* invoke) { GenReverse(invoke->GetLocations(), - Primitive::kPrimLong, + DataType::Type::kInt64, IsR2OrNewer(), IsR6(), /* reverseBits */ false, @@ -435,7 +435,7 @@ void IntrinsicLocationsBuilderMIPS::VisitShortReverseBytes(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitShortReverseBytes(HInvoke* invoke) { GenReverse(invoke->GetLocations(), - Primitive::kPrimShort, + DataType::Type::kInt16, IsR2OrNewer(), IsR6(), /* reverseBits */ false, @@ -584,7 +584,7 @@ void IntrinsicLocationsBuilderMIPS::VisitIntegerReverse(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitIntegerReverse(HInvoke* invoke) { GenReverse(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, IsR2OrNewer(), IsR6(), /* reverseBits */ true, @@ -598,7 +598,7 @@ void IntrinsicLocationsBuilderMIPS::VisitLongReverse(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitLongReverse(HInvoke* invoke) { GenReverse(invoke->GetLocations(), - Primitive::kPrimLong, + DataType::Type::kInt64, IsR2OrNewer(), IsR6(), /* reverseBits */ true, @@ -614,7 +614,7 @@ static void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { } static void GenBitCount(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, bool isR6, MipsAssembler* assembler) { Register out = locations->Out().AsRegister<Register>(); @@ -641,7 +641,7 @@ static void GenBitCount(LocationSummary* locations, // instructions compared to a loop-based algorithm which required 47 // instructions. - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { Register in = locations->InAt(0).AsRegister<Register>(); __ Srl(TMP, in, 1); @@ -665,7 +665,7 @@ static void GenBitCount(LocationSummary* locations, } __ Srl(out, out, 24); } else { - DCHECK_EQ(type, Primitive::kPrimLong); + DCHECK_EQ(type, DataType::Type::kInt64); Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); Register tmp_hi = locations->GetTemp(0).AsRegister<Register>(); @@ -729,7 +729,7 @@ void IntrinsicLocationsBuilderMIPS::VisitIntegerBitCount(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitIntegerBitCount(HInvoke* invoke) { - GenBitCount(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler()); + GenBitCount(invoke->GetLocations(), DataType::Type::kInt32, IsR6(), GetAssembler()); } // int java.lang.Long.bitCount(int) @@ -744,7 +744,7 @@ void IntrinsicLocationsBuilderMIPS::VisitLongBitCount(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitLongBitCount(HInvoke* invoke) { - GenBitCount(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler()); + GenBitCount(invoke->GetLocations(), DataType::Type::kInt64, IsR6(), GetAssembler()); } static void MathAbsFP(LocationSummary* locations, @@ -865,7 +865,7 @@ void IntrinsicCodeGeneratorMIPS::VisitMathAbsLong(HInvoke* invoke) { static void GenMinMaxFP(LocationSummary* locations, bool is_min, - Primitive::Type type, + DataType::Type type, bool is_R6, MipsAssembler* assembler) { FRegister out = locations->Out().AsFpuRegister<FRegister>(); @@ -884,7 +884,7 @@ static void GenMinMaxFP(LocationSummary* locations, // returned. This is why there is extra logic preceding the use of // the MIPS min.fmt/max.fmt instructions. If either a, or b holds a // NaN, return the NaN, otherwise return the min/max. - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ CmpUnD(FTMP, a, b); __ Bc1eqz(FTMP, &noNaNs); @@ -907,7 +907,7 @@ static void GenMinMaxFP(LocationSummary* locations, __ MaxD(out, a, b); } } else { - DCHECK_EQ(type, Primitive::kPrimFloat); + DCHECK_EQ(type, DataType::Type::kFloat32); __ CmpUnS(FTMP, a, b); __ Bc1eqz(FTMP, &noNaNs); @@ -938,16 +938,16 @@ static void GenMinMaxFP(LocationSummary* locations, MipsLabel select; MipsLabel done; - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ CunD(a, b); } else { - DCHECK_EQ(type, Primitive::kPrimFloat); + DCHECK_EQ(type, DataType::Type::kFloat32); __ CunS(a, b); } __ Bc1f(&ordered); // a or b (or both) is a NaN. Return one, which is a NaN. - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ CeqD(b, b); } else { __ CeqS(b, b); @@ -959,7 +959,7 @@ static void GenMinMaxFP(LocationSummary* locations, // Neither is a NaN. // a == b? (-0.0 compares equal with +0.0) // If equal, handle zeroes, else compare further. - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ CeqD(a, b); } else { __ CeqS(a, b); @@ -967,7 +967,7 @@ static void GenMinMaxFP(LocationSummary* locations, __ Bc1f(&compare); // a == b either bit for bit or one is -0.0 and the other is +0.0. - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ MoveFromFpuHigh(TMP, a); __ MoveFromFpuHigh(AT, b); } else { @@ -983,7 +983,7 @@ static void GenMinMaxFP(LocationSummary* locations, __ And(TMP, TMP, AT); } - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ Mfc1(AT, a); __ Mtc1(AT, out); __ MoveToFpuHigh(TMP, out); @@ -994,7 +994,7 @@ static void GenMinMaxFP(LocationSummary* locations, __ Bind(&compare); - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { if (is_min) { // return (a <= b) ? a : b; __ ColeD(a, b); @@ -1014,7 +1014,7 @@ static void GenMinMaxFP(LocationSummary* locations, __ Bind(&select); - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ MovtD(out, a); __ MovfD(out, b); } else { @@ -1043,7 +1043,7 @@ void IntrinsicLocationsBuilderMIPS::VisitMathMinDoubleDouble(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitMathMinDoubleDouble(HInvoke* invoke) { GenMinMaxFP(invoke->GetLocations(), /* is_min */ true, - Primitive::kPrimDouble, + DataType::Type::kFloat64, IsR6(), GetAssembler()); } @@ -1056,7 +1056,7 @@ void IntrinsicLocationsBuilderMIPS::VisitMathMinFloatFloat(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitMathMinFloatFloat(HInvoke* invoke) { GenMinMaxFP(invoke->GetLocations(), /* is_min */ true, - Primitive::kPrimFloat, + DataType::Type::kFloat32, IsR6(), GetAssembler()); } @@ -1069,7 +1069,7 @@ void IntrinsicLocationsBuilderMIPS::VisitMathMaxDoubleDouble(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitMathMaxDoubleDouble(HInvoke* invoke) { GenMinMaxFP(invoke->GetLocations(), /* is_min */ false, - Primitive::kPrimDouble, + DataType::Type::kFloat64, IsR6(), GetAssembler()); } @@ -1082,7 +1082,7 @@ void IntrinsicLocationsBuilderMIPS::VisitMathMaxFloatFloat(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitMathMaxFloatFloat(HInvoke* invoke) { GenMinMaxFP(invoke->GetLocations(), /* is_min */ false, - Primitive::kPrimFloat, + DataType::Type::kFloat32, IsR6(), GetAssembler()); } @@ -1098,7 +1098,7 @@ static void CreateIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { static void GenMinMax(LocationSummary* locations, bool is_min, - Primitive::Type type, + DataType::Type type, bool is_R6, MipsAssembler* assembler) { if (is_R6) { @@ -1125,7 +1125,7 @@ static void GenMinMax(LocationSummary* locations, // as the output register; the else clause also handles the case // where the output register is distinct from both the first, and the // second input registers. - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { Register a_lo = locations->InAt(0).AsRegisterPairLow<Register>(); Register a_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); Register b_lo = locations->InAt(1).AsRegisterPairLow<Register>(); @@ -1168,7 +1168,7 @@ static void GenMinMax(LocationSummary* locations, __ Or(out_hi, out_hi, AT); } } else { - DCHECK_EQ(type, Primitive::kPrimInt); + DCHECK_EQ(type, DataType::Type::kInt32); Register a = locations->InAt(0).AsRegister<Register>(); Register b = locations->InAt(1).AsRegister<Register>(); Register out = locations->Out().AsRegister<Register>(); @@ -1190,7 +1190,7 @@ static void GenMinMax(LocationSummary* locations, } } } else { - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { Register a_lo = locations->InAt(0).AsRegisterPairLow<Register>(); Register a_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); Register b_lo = locations->InAt(1).AsRegisterPairLow<Register>(); @@ -1234,7 +1234,7 @@ static void GenMinMax(LocationSummary* locations, } } } else { - DCHECK_EQ(type, Primitive::kPrimInt); + DCHECK_EQ(type, DataType::Type::kInt32); Register a = locations->InAt(0).AsRegister<Register>(); Register b = locations->InAt(1).AsRegister<Register>(); Register out = locations->Out().AsRegister<Register>(); @@ -1273,7 +1273,7 @@ void IntrinsicLocationsBuilderMIPS::VisitMathMinIntInt(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitMathMinIntInt(HInvoke* invoke) { GenMinMax(invoke->GetLocations(), /* is_min */ true, - Primitive::kPrimInt, + DataType::Type::kInt32, IsR6(), GetAssembler()); } @@ -1286,7 +1286,7 @@ void IntrinsicLocationsBuilderMIPS::VisitMathMinLongLong(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitMathMinLongLong(HInvoke* invoke) { GenMinMax(invoke->GetLocations(), /* is_min */ true, - Primitive::kPrimLong, + DataType::Type::kInt64, IsR6(), GetAssembler()); } @@ -1299,7 +1299,7 @@ void IntrinsicLocationsBuilderMIPS::VisitMathMaxIntInt(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitMathMaxIntInt(HInvoke* invoke) { GenMinMax(invoke->GetLocations(), /* is_min */ false, - Primitive::kPrimInt, + DataType::Type::kInt32, IsR6(), GetAssembler()); } @@ -1312,7 +1312,7 @@ void IntrinsicLocationsBuilderMIPS::VisitMathMaxLongLong(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitMathMaxLongLong(HInvoke* invoke) { GenMinMax(invoke->GetLocations(), /* is_min */ false, - Primitive::kPrimLong, + DataType::Type::kInt64, IsR6(), GetAssembler()); } @@ -1519,7 +1519,7 @@ void IntrinsicCodeGeneratorMIPS::VisitThreadCurrentThread(HInvoke* invoke) { static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke, - Primitive::Type type) { + DataType::Type type) { bool can_call = kEmitCompilerReadBarrier && (invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObject || invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObjectVolatile); @@ -1536,7 +1536,7 @@ static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, locations->SetInAt(2, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), (can_call ? Location::kOutputOverlap : Location::kNoOutputOverlap)); - if (type == Primitive::kPrimNot && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { + if (type == DataType::Type::kReference && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { // We need a temporary register for the read barrier marking slow // path in InstructionCodeGeneratorMIPS::GenerateReferenceLoadWithBakerReadBarrier. locations->AddTemp(Location::RequiresRegister()); @@ -1546,14 +1546,14 @@ static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, // Note that the caller must supply a properly aligned memory address. // If they do not, the behavior is undefined (atomicity not guaranteed, exception may occur). static void GenUnsafeGet(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, bool is_volatile, bool is_R6, CodeGeneratorMIPS* codegen) { LocationSummary* locations = invoke->GetLocations(); - DCHECK((type == Primitive::kPrimInt) || - (type == Primitive::kPrimLong) || - (type == Primitive::kPrimNot)) << type; + DCHECK((type == DataType::Type::kInt32) || + (type == DataType::Type::kInt64) || + (type == DataType::Type::kReference)) << type; MipsAssembler* assembler = codegen->GetAssembler(); // Target register. Location trg_loc = locations->Out(); @@ -1566,12 +1566,12 @@ static void GenUnsafeGet(HInvoke* invoke, Location offset_loc = locations->InAt(2); Register offset_lo = offset_loc.AsRegisterPairLow<Register>(); - if (!(kEmitCompilerReadBarrier && kUseBakerReadBarrier && (type == Primitive::kPrimNot))) { + if (!(kEmitCompilerReadBarrier && kUseBakerReadBarrier && (type == DataType::Type::kReference))) { __ Addu(TMP, base, offset_lo); } switch (type) { - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Register trg_lo = trg_loc.AsRegisterPairLow<Register>(); Register trg_hi = trg_loc.AsRegisterPairHigh<Register>(); CHECK(!is_volatile); // TODO: support atomic 8-byte volatile loads. @@ -1587,7 +1587,7 @@ static void GenUnsafeGet(HInvoke* invoke, break; } - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { Register trg = trg_loc.AsRegister<Register>(); if (is_R6) { __ Lw(trg, TMP, 0); @@ -1601,7 +1601,7 @@ static void GenUnsafeGet(HInvoke* invoke, break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { Register trg = trg_loc.AsRegister<Register>(); if (kEmitCompilerReadBarrier) { if (kUseBakerReadBarrier) { @@ -1657,47 +1657,47 @@ static void GenUnsafeGet(HInvoke* invoke, // int sun.misc.Unsafe.getInt(Object o, long offset) void IntrinsicLocationsBuilderMIPS::VisitUnsafeGet(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimInt); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt32); } void IntrinsicCodeGeneratorMIPS::VisitUnsafeGet(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ false, IsR6(), codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ false, IsR6(), codegen_); } // int sun.misc.Unsafe.getIntVolatile(Object o, long offset) void IntrinsicLocationsBuilderMIPS::VisitUnsafeGetVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimInt); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt32); } void IntrinsicCodeGeneratorMIPS::VisitUnsafeGetVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ true, IsR6(), codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ true, IsR6(), codegen_); } // long sun.misc.Unsafe.getLong(Object o, long offset) void IntrinsicLocationsBuilderMIPS::VisitUnsafeGetLong(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimLong); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt64); } void IntrinsicCodeGeneratorMIPS::VisitUnsafeGetLong(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ false, IsR6(), codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ false, IsR6(), codegen_); } // Object sun.misc.Unsafe.getObject(Object o, long offset) void IntrinsicLocationsBuilderMIPS::VisitUnsafeGetObject(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimNot); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kReference); } void IntrinsicCodeGeneratorMIPS::VisitUnsafeGetObject(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ false, IsR6(), codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ false, IsR6(), codegen_); } // Object sun.misc.Unsafe.getObjectVolatile(Object o, long offset) void IntrinsicLocationsBuilderMIPS::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimNot); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kReference); } void IntrinsicCodeGeneratorMIPS::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ true, IsR6(), codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ true, IsR6(), codegen_); } static void CreateIntIntIntIntToVoidLocations(ArenaAllocator* arena, HInvoke* invoke) { @@ -1713,14 +1713,14 @@ static void CreateIntIntIntIntToVoidLocations(ArenaAllocator* arena, HInvoke* in // Note that the caller must supply a properly aligned memory address. // If they do not, the behavior is undefined (atomicity not guaranteed, exception may occur). static void GenUnsafePut(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, bool is_volatile, bool is_ordered, bool is_R6, CodeGeneratorMIPS* codegen) { - DCHECK((type == Primitive::kPrimInt) || - (type == Primitive::kPrimLong) || - (type == Primitive::kPrimNot)) << type; + DCHECK((type == DataType::Type::kInt32) || + (type == DataType::Type::kInt64) || + (type == DataType::Type::kReference)) << type; MipsAssembler* assembler = codegen->GetAssembler(); // Object pointer. Register base = locations->InAt(1).AsRegister<Register>(); @@ -1733,10 +1733,10 @@ static void GenUnsafePut(LocationSummary* locations, if (is_volatile || is_ordered) { __ Sync(0); } - if ((type == Primitive::kPrimInt) || (type == Primitive::kPrimNot)) { + if ((type == DataType::Type::kInt32) || (type == DataType::Type::kReference)) { Register value = locations->InAt(3).AsRegister<Register>(); - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { __ PoisonHeapReference(AT, value); value = AT; } @@ -1766,7 +1766,7 @@ static void GenUnsafePut(LocationSummary* locations, __ Sync(0); } - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { bool value_can_be_null = true; // TODO: Worth finding out this information? codegen->MarkGCCard(base, locations->InAt(3).AsRegister<Register>(), value_can_be_null); } @@ -1779,7 +1779,7 @@ void IntrinsicLocationsBuilderMIPS::VisitUnsafePut(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitUnsafePut(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ false, /* is_ordered */ false, IsR6(), @@ -1793,7 +1793,7 @@ void IntrinsicLocationsBuilderMIPS::VisitUnsafePutOrdered(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitUnsafePutOrdered(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ false, /* is_ordered */ true, IsR6(), @@ -1807,7 +1807,7 @@ void IntrinsicLocationsBuilderMIPS::VisitUnsafePutVolatile(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitUnsafePutVolatile(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ true, /* is_ordered */ false, IsR6(), @@ -1821,7 +1821,7 @@ void IntrinsicLocationsBuilderMIPS::VisitUnsafePutObject(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitUnsafePutObject(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ false, /* is_ordered */ false, IsR6(), @@ -1835,7 +1835,7 @@ void IntrinsicLocationsBuilderMIPS::VisitUnsafePutObjectOrdered(HInvoke* invoke) void IntrinsicCodeGeneratorMIPS::VisitUnsafePutObjectOrdered(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ false, /* is_ordered */ true, IsR6(), @@ -1849,7 +1849,7 @@ void IntrinsicLocationsBuilderMIPS::VisitUnsafePutObjectVolatile(HInvoke* invoke void IntrinsicCodeGeneratorMIPS::VisitUnsafePutObjectVolatile(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ true, /* is_ordered */ false, IsR6(), @@ -1863,7 +1863,7 @@ void IntrinsicLocationsBuilderMIPS::VisitUnsafePutLong(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitUnsafePutLong(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ false, /* is_ordered */ false, IsR6(), @@ -1877,7 +1877,7 @@ void IntrinsicLocationsBuilderMIPS::VisitUnsafePutLongOrdered(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS::VisitUnsafePutLongOrdered(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ false, /* is_ordered */ true, IsR6(), @@ -1908,7 +1908,7 @@ static void CreateIntIntIntIntIntToIntPlusTemps(ArenaAllocator* arena, HInvoke* // Note that the caller must supply a properly aligned memory address. // If they do not, the behavior is undefined (atomicity not guaranteed, exception may occur). -static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS* codegen) { +static void GenCas(HInvoke* invoke, DataType::Type type, CodeGeneratorMIPS* codegen) { MipsAssembler* assembler = codegen->GetAssembler(); LocationSummary* locations = invoke->GetLocations(); bool isR6 = codegen->GetInstructionSetFeatures().IsR6(); @@ -1924,7 +1924,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS* cod DCHECK_NE(offset_lo, out); DCHECK_NE(expected, out); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // The only read barrier implementation supporting the // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); @@ -1954,7 +1954,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS* cod MipsLabel loop_head, exit_loop; __ Addu(TMP, base, offset_lo); - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { __ PoisonHeapReference(expected); // Do not poison `value`, if it is the same register as // `expected`, which has just been poisoned. @@ -1970,7 +1970,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS* cod __ Sync(0); __ Bind(&loop_head); - if ((type == Primitive::kPrimInt) || (type == Primitive::kPrimNot)) { + if ((type == DataType::Type::kInt32) || (type == DataType::Type::kReference)) { if (isR6) { __ LlR6(out, TMP); } else { @@ -1988,11 +1988,11 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS* cod // in the case that the store fails. Whether the // store succeeds, or fails, it will load the // correct Boolean value into the 'out' register. - // This test isn't really necessary. We only support Primitive::kPrimInt, - // Primitive::kPrimNot, and we already verified that we're working on one + // This test isn't really necessary. We only support DataType::Type::kInt, + // DataType::Type::kReference, and we already verified that we're working on one // of those two types. It's left here in case the code needs to support // other types in the future. - if ((type == Primitive::kPrimInt) || (type == Primitive::kPrimNot)) { + if ((type == DataType::Type::kInt32) || (type == DataType::Type::kReference)) { if (isR6) { __ ScR6(out, TMP); } else { @@ -2004,7 +2004,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS* cod __ Bind(&exit_loop); __ Sync(0); - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { __ UnpoisonHeapReference(expected); // Do not unpoison `value`, if it is the same register as // `expected`, which has just been unpoisoned. @@ -2020,7 +2020,7 @@ void IntrinsicLocationsBuilderMIPS::VisitUnsafeCASInt(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitUnsafeCASInt(HInvoke* invoke) { - GenCas(invoke, Primitive::kPrimInt, codegen_); + GenCas(invoke, DataType::Type::kInt32, codegen_); } // boolean sun.misc.Unsafe.compareAndSwapObject(Object o, long offset, Object expected, Object x) @@ -2039,7 +2039,7 @@ void IntrinsicCodeGeneratorMIPS::VisitUnsafeCASObject(HInvoke* invoke) { // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); - GenCas(invoke, Primitive::kPrimNot, codegen_); + GenCas(invoke, DataType::Type::kReference, codegen_); } // int java.lang.String.compareTo(String anotherString) @@ -2050,7 +2050,7 @@ void IntrinsicLocationsBuilderMIPS::VisitStringCompareTo(HInvoke* invoke) { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); } @@ -2218,7 +2218,7 @@ static void GenerateStringIndexOf(HInvoke* invoke, __ Bind(slow_path->GetExitLabel()); return; } - } else if (code_point->GetType() != Primitive::kPrimChar) { + } else if (code_point->GetType() != DataType::Type::kUint16) { Register char_reg = locations->InAt(1).AsRegister<Register>(); // The "bltu" conditional branch tests to see if the character value // fits in a valid 16-bit (MIPS halfword) value. If it doesn't then @@ -2256,7 +2256,7 @@ void IntrinsicLocationsBuilderMIPS::VisitStringIndexOf(HInvoke* invoke) { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); // Need a temp for slow-path codepoint compare, and need to send start-index=0. @@ -2282,7 +2282,7 @@ void IntrinsicLocationsBuilderMIPS::VisitStringIndexOfAfter(HInvoke* invoke) { locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); // Need a temp for slow-path codepoint compare. @@ -2307,7 +2307,7 @@ void IntrinsicLocationsBuilderMIPS::VisitStringNewStringFromBytes(HInvoke* invok locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); locations->SetInAt(3, Location::RegisterLocation(calling_convention.GetRegisterAt(3))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); } @@ -2332,7 +2332,7 @@ void IntrinsicLocationsBuilderMIPS::VisitStringNewStringFromChars(HInvoke* invok locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); } @@ -2353,7 +2353,7 @@ void IntrinsicLocationsBuilderMIPS::VisitStringNewStringFromString(HInvoke* invo kIntrinsified); InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<Register>())); } @@ -2370,16 +2370,16 @@ void IntrinsicCodeGeneratorMIPS::VisitStringNewStringFromString(HInvoke* invoke) } static void GenIsInfinite(LocationSummary* locations, - const Primitive::Type type, + const DataType::Type type, const bool isR6, MipsAssembler* assembler) { FRegister in = locations->InAt(0).AsFpuRegister<FRegister>(); Register out = locations->Out().AsRegister<Register>(); - DCHECK(type == Primitive::kPrimFloat || type == Primitive::kPrimDouble); + DCHECK(type == DataType::Type::kFloat32 || type == DataType::Type::kFloat64); if (isR6) { - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ ClassD(FTMP, in); } else { __ ClassS(FTMP, in); @@ -2389,7 +2389,7 @@ static void GenIsInfinite(LocationSummary* locations, __ Sltu(out, ZERO, out); } else { // If one, or more, of the exponent bits is zero, then the number can't be infinite. - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ MoveFromFpuHigh(TMP, in); __ LoadConst32(AT, High32Bits(kPositiveInfinityDouble)); } else { @@ -2400,7 +2400,7 @@ static void GenIsInfinite(LocationSummary* locations, __ Sll(TMP, TMP, 1); - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ Mfc1(AT, in); __ Or(TMP, TMP, AT); } @@ -2415,7 +2415,7 @@ void IntrinsicLocationsBuilderMIPS::VisitFloatIsInfinite(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitFloatIsInfinite(HInvoke* invoke) { - GenIsInfinite(invoke->GetLocations(), Primitive::kPrimFloat, IsR6(), GetAssembler()); + GenIsInfinite(invoke->GetLocations(), DataType::Type::kFloat32, IsR6(), GetAssembler()); } // boolean java.lang.Double.isInfinite(double) @@ -2424,16 +2424,16 @@ void IntrinsicLocationsBuilderMIPS::VisitDoubleIsInfinite(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitDoubleIsInfinite(HInvoke* invoke) { - GenIsInfinite(invoke->GetLocations(), Primitive::kPrimDouble, IsR6(), GetAssembler()); + GenIsInfinite(invoke->GetLocations(), DataType::Type::kFloat64, IsR6(), GetAssembler()); } static void GenHighestOneBit(LocationSummary* locations, - const Primitive::Type type, + const DataType::Type type, bool isR6, MipsAssembler* assembler) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); Register out_lo = locations->Out().AsRegisterPairLow<Register>(); @@ -2480,7 +2480,7 @@ void IntrinsicLocationsBuilderMIPS::VisitIntegerHighestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitIntegerHighestOneBit(HInvoke* invoke) { - GenHighestOneBit(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler()); + GenHighestOneBit(invoke->GetLocations(), DataType::Type::kInt32, IsR6(), GetAssembler()); } // long java.lang.Long.highestOneBit(long) @@ -2489,16 +2489,16 @@ void IntrinsicLocationsBuilderMIPS::VisitLongHighestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitLongHighestOneBit(HInvoke* invoke) { - GenHighestOneBit(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler()); + GenHighestOneBit(invoke->GetLocations(), DataType::Type::kInt64, IsR6(), GetAssembler()); } static void GenLowestOneBit(LocationSummary* locations, - const Primitive::Type type, + const DataType::Type type, bool isR6, MipsAssembler* assembler) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); Register out_lo = locations->Out().AsRegisterPairLow<Register>(); @@ -2528,7 +2528,7 @@ void IntrinsicLocationsBuilderMIPS::VisitIntegerLowestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitIntegerLowestOneBit(HInvoke* invoke) { - GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler()); + GenLowestOneBit(invoke->GetLocations(), DataType::Type::kInt32, IsR6(), GetAssembler()); } // long java.lang.Long.lowestOneBit(long) @@ -2537,7 +2537,7 @@ void IntrinsicLocationsBuilderMIPS::VisitLongLowestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitLongLowestOneBit(HInvoke* invoke) { - GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler()); + GenLowestOneBit(invoke->GetLocations(), DataType::Type::kInt64, IsR6(), GetAssembler()); } // int java.lang.Math.round(float) @@ -2686,9 +2686,9 @@ void IntrinsicCodeGeneratorMIPS::VisitStringGetCharsNoCheck(HInvoke* invoke) { LocationSummary* locations = invoke->GetLocations(); // Check assumption that sizeof(Char) is 2 (used in scaling below). - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); - const size_t char_shift = Primitive::ComponentSizeShift(Primitive::kPrimChar); + const size_t char_shift = DataType::SizeShift(DataType::Type::kUint16); Register srcObj = locations->InAt(0).AsRegister<Register>(); Register srcBegin = locations->InAt(1).AsRegister<Register>(); @@ -2764,7 +2764,7 @@ static void CreateFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimDouble)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kFloat64)); } static void CreateFPFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) { @@ -2775,7 +2775,7 @@ static void CreateFPFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); locations->SetInAt(1, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(1))); - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimDouble)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kFloat64)); } static void GenFPToFPCall(HInvoke* invoke, CodeGeneratorMIPS* codegen, QuickEntrypointEnum entry) { @@ -3112,10 +3112,10 @@ void IntrinsicCodeGeneratorMIPS::VisitSystemArrayCopyChar(HInvoke* invoke) { // Okay, everything checks out. Finally time to do the copy. // Check assumption that sizeof(Char) is 2 (used in scaling below). - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); - const size_t char_shift = Primitive::ComponentSizeShift(Primitive::kPrimChar); + const size_t char_shift = DataType::SizeShift(DataType::Type::kUint16); const uint32_t data_offset = mirror::Array::DataOffset(char_size).Uint32Value(); @@ -3154,7 +3154,7 @@ void IntrinsicLocationsBuilderMIPS::VisitIntegerValueOf(HInvoke* invoke) { IntrinsicVisitor::ComputeIntegerValueOfLocations( invoke, codegen_, - calling_convention.GetReturnLocation(Primitive::kPrimNot), + calling_convention.GetReturnLocation(DataType::Type::kReference), Location::RegisterLocation(calling_convention.GetRegisterAt(0))); } diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc index 80448f1389..d0234d8271 100644 --- a/compiler/optimizing/intrinsics_mips64.cc +++ b/compiler/optimizing/intrinsics_mips64.cc @@ -49,16 +49,16 @@ ArenaAllocator* IntrinsicCodeGeneratorMIPS64::GetAllocator() { #define __ codegen->GetAssembler()-> static void MoveFromReturnRegister(Location trg, - Primitive::Type type, + DataType::Type type, CodeGeneratorMIPS64* codegen) { if (!trg.IsValid()) { - DCHECK_EQ(type, Primitive::kPrimVoid); + DCHECK_EQ(type, DataType::Type::kVoid); return; } - DCHECK_NE(type, Primitive::kPrimVoid); + DCHECK_NE(type, DataType::Type::kVoid); - if (Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) { + if (DataType::IsIntegralType(type) || type == DataType::Type::kReference) { GpuRegister trg_reg = trg.AsRegister<GpuRegister>(); if (trg_reg != V0) { __ Move(V0, trg_reg); @@ -66,7 +66,7 @@ static void MoveFromReturnRegister(Location trg, } else { FpuRegister trg_reg = trg.AsFpuRegister<FpuRegister>(); if (trg_reg != F0) { - if (type == Primitive::kPrimFloat) { + if (type == DataType::Type::kFloat32) { __ MovS(F0, trg_reg); } else { __ MovD(F0, trg_reg); @@ -224,21 +224,21 @@ static void CreateIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { } static void GenReverseBytes(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, Mips64Assembler* assembler) { GpuRegister in = locations->InAt(0).AsRegister<GpuRegister>(); GpuRegister out = locations->Out().AsRegister<GpuRegister>(); switch (type) { - case Primitive::kPrimShort: + case DataType::Type::kInt16: __ Dsbh(out, in); __ Seh(out, out); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ Rotr(out, in, 16); __ Wsbh(out, out); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: __ Dsbh(out, in); __ Dshd(out, out); break; @@ -254,7 +254,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitIntegerReverseBytes(HInvoke* invoke) } void IntrinsicCodeGeneratorMIPS64::VisitIntegerReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } // long java.lang.Long.reverseBytes(long) @@ -263,7 +263,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitLongReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitLongReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt64, GetAssembler()); } // short java.lang.Short.reverseBytes(short) @@ -272,7 +272,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitShortReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitShortReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimShort, GetAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt16, GetAssembler()); } static void GenNumberOfLeadingZeroes(LocationSummary* locations, @@ -344,14 +344,14 @@ void IntrinsicCodeGeneratorMIPS64::VisitLongNumberOfTrailingZeros(HInvoke* invok } static void GenReverse(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, Mips64Assembler* assembler) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); GpuRegister in = locations->InAt(0).AsRegister<GpuRegister>(); GpuRegister out = locations->Out().AsRegister<GpuRegister>(); - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { __ Rotr(out, in, 16); __ Wsbh(out, out); __ Bitswap(out, out); @@ -368,7 +368,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitIntegerReverse(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitIntegerReverse(HInvoke* invoke) { - GenReverse(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenReverse(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } // long java.lang.Long.reverse(long) @@ -377,7 +377,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitLongReverse(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitLongReverse(HInvoke* invoke) { - GenReverse(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); + GenReverse(invoke->GetLocations(), DataType::Type::kInt64, GetAssembler()); } static void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { @@ -389,12 +389,12 @@ static void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { } static void GenBitCount(LocationSummary* locations, - const Primitive::Type type, + const DataType::Type type, Mips64Assembler* assembler) { GpuRegister out = locations->Out().AsRegister<GpuRegister>(); GpuRegister in = locations->InAt(0).AsRegister<GpuRegister>(); - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel // @@ -419,7 +419,7 @@ static void GenBitCount(LocationSummary* locations, // number of instructions executed even when a large number of bits // are set. - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { __ Srl(TMP, in, 1); __ LoadConst32(AT, 0x55555555); __ And(TMP, TMP, AT); @@ -436,7 +436,7 @@ static void GenBitCount(LocationSummary* locations, __ LoadConst32(TMP, 0x01010101); __ MulR6(out, out, TMP); __ Srl(out, out, 24); - } else if (type == Primitive::kPrimLong) { + } else if (type == DataType::Type::kInt64) { __ Dsrl(TMP, in, 1); __ LoadConst64(AT, 0x5555555555555555L); __ And(TMP, TMP, AT); @@ -462,7 +462,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitIntegerBitCount(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitIntegerBitCount(HInvoke* invoke) { - GenBitCount(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenBitCount(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } // int java.lang.Long.bitCount(long) @@ -471,7 +471,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitLongBitCount(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitLongBitCount(HInvoke* invoke) { - GenBitCount(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); + GenBitCount(invoke->GetLocations(), DataType::Type::kInt64, GetAssembler()); } static void MathAbsFP(LocationSummary* locations, bool is64bit, Mips64Assembler* assembler) { @@ -546,7 +546,7 @@ void IntrinsicCodeGeneratorMIPS64::VisitMathAbsLong(HInvoke* invoke) { static void GenMinMaxFP(LocationSummary* locations, bool is_min, - Primitive::Type type, + DataType::Type type, Mips64Assembler* assembler) { FpuRegister a = locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister b = locations->InAt(1).AsFpuRegister<FpuRegister>(); @@ -563,7 +563,7 @@ static void GenMinMaxFP(LocationSummary* locations, // returned. This is why there is extra logic preceding the use of // the MIPS min.fmt/max.fmt instructions. If either a, or b holds a // NaN, return the NaN, otherwise return the min/max. - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ CmpUnD(FTMP, a, b); __ Bc1eqz(FTMP, &noNaNs); @@ -586,7 +586,7 @@ static void GenMinMaxFP(LocationSummary* locations, __ MaxD(out, a, b); } } else { - DCHECK_EQ(type, Primitive::kPrimFloat); + DCHECK_EQ(type, DataType::Type::kFloat32); __ CmpUnS(FTMP, a, b); __ Bc1eqz(FTMP, &noNaNs); @@ -628,7 +628,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitMathMinDoubleDouble(HInvoke* invoke) } void IntrinsicCodeGeneratorMIPS64::VisitMathMinDoubleDouble(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ true, Primitive::kPrimDouble, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), /* is_min */ true, DataType::Type::kFloat64, GetAssembler()); } // float java.lang.Math.min(float, float) @@ -637,7 +637,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitMathMinFloatFloat(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitMathMinFloatFloat(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ true, Primitive::kPrimFloat, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), /* is_min */ true, DataType::Type::kFloat32, GetAssembler()); } // double java.lang.Math.max(double, double) @@ -646,7 +646,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitMathMaxDoubleDouble(HInvoke* invoke) } void IntrinsicCodeGeneratorMIPS64::VisitMathMaxDoubleDouble(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ false, Primitive::kPrimDouble, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), /* is_min */ false, DataType::Type::kFloat64, GetAssembler()); } // float java.lang.Math.max(float, float) @@ -655,7 +655,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitMathMaxFloatFloat(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitMathMaxFloatFloat(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ false, Primitive::kPrimFloat, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), /* is_min */ false, DataType::Type::kFloat32, GetAssembler()); } static void GenMinMax(LocationSummary* locations, @@ -885,12 +885,12 @@ void IntrinsicCodeGeneratorMIPS64::VisitMathCeil(HInvoke* invoke) { GenRoundingMode(invoke->GetLocations(), kCeil, GetAssembler()); } -static void GenRound(LocationSummary* locations, Mips64Assembler* assembler, Primitive::Type type) { +static void GenRound(LocationSummary* locations, Mips64Assembler* assembler, DataType::Type type) { FpuRegister in = locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister half = locations->GetTemp(0).AsFpuRegister<FpuRegister>(); GpuRegister out = locations->Out().AsRegister<GpuRegister>(); - DCHECK(type == Primitive::kPrimFloat || type == Primitive::kPrimDouble); + DCHECK(type == DataType::Type::kFloat32 || type == DataType::Type::kFloat64); Mips64Label done; @@ -903,7 +903,7 @@ static void GenRound(LocationSummary* locations, Mips64Assembler* assembler, Pri // return out; // out = floor(in); - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ FloorLD(FTMP, in); __ Dmfc1(out, FTMP); } else { @@ -912,7 +912,7 @@ static void GenRound(LocationSummary* locations, Mips64Assembler* assembler, Pri } // if (out != MAX_VALUE && out != MIN_VALUE) - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ Daddiu(TMP, out, 1); __ Dati(TMP, 0x8000); // TMP = out + 0x8000 0000 0000 0001 // or out - 0x7FFF FFFF FFFF FFFF. @@ -933,7 +933,7 @@ static void GenRound(LocationSummary* locations, Mips64Assembler* assembler, Pri } // TMP = (0.5 <= (in - out)) ? -1 : 0; - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ Cvtdl(FTMP, FTMP); // Convert output of floor.l.d back to "double". __ LoadConst64(AT, bit_cast<int64_t, double>(0.5)); __ SubD(FTMP, in, FTMP); @@ -950,7 +950,7 @@ static void GenRound(LocationSummary* locations, Mips64Assembler* assembler, Pri } // Return out -= TMP. - if (type == Primitive::kPrimDouble) { + if (type == DataType::Type::kFloat64) { __ Dsubu(out, out, TMP); } else { __ Subu(out, out, TMP); @@ -970,7 +970,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitMathRoundFloat(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitMathRoundFloat(HInvoke* invoke) { - GenRound(invoke->GetLocations(), GetAssembler(), Primitive::kPrimFloat); + GenRound(invoke->GetLocations(), GetAssembler(), DataType::Type::kFloat32); } // long java.lang.Math.round(double) @@ -984,7 +984,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitMathRoundDouble(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitMathRoundDouble(HInvoke* invoke) { - GenRound(invoke->GetLocations(), GetAssembler(), Primitive::kPrimDouble); + GenRound(invoke->GetLocations(), GetAssembler(), DataType::Type::kFloat64); } // byte libcore.io.Memory.peekByte(long address) @@ -1119,7 +1119,7 @@ void IntrinsicCodeGeneratorMIPS64::VisitThreadCurrentThread(HInvoke* invoke) { static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke, - Primitive::Type type) { + DataType::Type type) { bool can_call = kEmitCompilerReadBarrier && (invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObject || invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObjectVolatile); @@ -1136,7 +1136,7 @@ static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, locations->SetInAt(2, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister(), (can_call ? Location::kOutputOverlap : Location::kNoOutputOverlap)); - if (type == Primitive::kPrimNot && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { + if (type == DataType::Type::kReference && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { // We need a temporary register for the read barrier marking slow // path in InstructionCodeGeneratorMIPS64::GenerateReferenceLoadWithBakerReadBarrier. locations->AddTemp(Location::RequiresRegister()); @@ -1146,13 +1146,13 @@ static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, // Note that the caller must supply a properly aligned memory address. // If they do not, the behavior is undefined (atomicity not guaranteed, exception may occur). static void GenUnsafeGet(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, bool is_volatile, CodeGeneratorMIPS64* codegen) { LocationSummary* locations = invoke->GetLocations(); - DCHECK((type == Primitive::kPrimInt) || - (type == Primitive::kPrimLong) || - (type == Primitive::kPrimNot)) << type; + DCHECK((type == DataType::Type::kInt32) || + (type == DataType::Type::kInt64) || + (type == DataType::Type::kReference)) << type; Mips64Assembler* assembler = codegen->GetAssembler(); // Target register. Location trg_loc = locations->Out(); @@ -1164,26 +1164,26 @@ static void GenUnsafeGet(HInvoke* invoke, Location offset_loc = locations->InAt(2); GpuRegister offset = offset_loc.AsRegister<GpuRegister>(); - if (!(kEmitCompilerReadBarrier && kUseBakerReadBarrier && (type == Primitive::kPrimNot))) { + if (!(kEmitCompilerReadBarrier && kUseBakerReadBarrier && (type == DataType::Type::kReference))) { __ Daddu(TMP, base, offset); } switch (type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: __ Ld(trg, TMP, 0); if (is_volatile) { __ Sync(0); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ Lw(trg, TMP, 0); if (is_volatile) { __ Sync(0); } break; - case Primitive::kPrimNot: + case DataType::Type::kReference: if (kEmitCompilerReadBarrier) { if (kUseBakerReadBarrier) { Location temp = locations->GetTemp(0); @@ -1227,56 +1227,56 @@ static void GenUnsafeGet(HInvoke* invoke, // int sun.misc.Unsafe.getInt(Object o, long offset) void IntrinsicLocationsBuilderMIPS64::VisitUnsafeGet(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimInt); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt32); } void IntrinsicCodeGeneratorMIPS64::VisitUnsafeGet(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ false, codegen_); } // int sun.misc.Unsafe.getIntVolatile(Object o, long offset) void IntrinsicLocationsBuilderMIPS64::VisitUnsafeGetVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimInt); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt32); } void IntrinsicCodeGeneratorMIPS64::VisitUnsafeGetVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ true, codegen_); } // long sun.misc.Unsafe.getLong(Object o, long offset) void IntrinsicLocationsBuilderMIPS64::VisitUnsafeGetLong(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimLong); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt64); } void IntrinsicCodeGeneratorMIPS64::VisitUnsafeGetLong(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ false, codegen_); } // long sun.misc.Unsafe.getLongVolatile(Object o, long offset) void IntrinsicLocationsBuilderMIPS64::VisitUnsafeGetLongVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimLong); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt64); } void IntrinsicCodeGeneratorMIPS64::VisitUnsafeGetLongVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ true, codegen_); } // Object sun.misc.Unsafe.getObject(Object o, long offset) void IntrinsicLocationsBuilderMIPS64::VisitUnsafeGetObject(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimNot); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kReference); } void IntrinsicCodeGeneratorMIPS64::VisitUnsafeGetObject(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ false, codegen_); } // Object sun.misc.Unsafe.getObjectVolatile(Object o, long offset) void IntrinsicLocationsBuilderMIPS64::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimNot); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kReference); } void IntrinsicCodeGeneratorMIPS64::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ true, codegen_); } static void CreateIntIntIntIntToVoid(ArenaAllocator* arena, HInvoke* invoke) { @@ -1292,13 +1292,13 @@ static void CreateIntIntIntIntToVoid(ArenaAllocator* arena, HInvoke* invoke) { // Note that the caller must supply a properly aligned memory address. // If they do not, the behavior is undefined (atomicity not guaranteed, exception may occur). static void GenUnsafePut(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, bool is_volatile, bool is_ordered, CodeGeneratorMIPS64* codegen) { - DCHECK((type == Primitive::kPrimInt) || - (type == Primitive::kPrimLong) || - (type == Primitive::kPrimNot)); + DCHECK((type == DataType::Type::kInt32) || + (type == DataType::Type::kInt64) || + (type == DataType::Type::kReference)); Mips64Assembler* assembler = codegen->GetAssembler(); // Object pointer. GpuRegister base = locations->InAt(1).AsRegister<GpuRegister>(); @@ -1311,9 +1311,9 @@ static void GenUnsafePut(LocationSummary* locations, __ Sync(0); } switch (type) { - case Primitive::kPrimInt: - case Primitive::kPrimNot: - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + case DataType::Type::kInt32: + case DataType::Type::kReference: + if (kPoisonHeapReferences && type == DataType::Type::kReference) { __ PoisonHeapReference(AT, value); __ Sw(AT, TMP, 0); } else { @@ -1321,7 +1321,7 @@ static void GenUnsafePut(LocationSummary* locations, } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: __ Sd(value, TMP, 0); break; @@ -1333,7 +1333,7 @@ static void GenUnsafePut(LocationSummary* locations, __ Sync(0); } - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { bool value_can_be_null = true; // TODO: Worth finding out this information? codegen->MarkGCCard(base, value, value_can_be_null); } @@ -1346,7 +1346,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafePut(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS64::VisitUnsafePut(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ false, /* is_ordered */ false, codegen_); @@ -1359,7 +1359,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafePutOrdered(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS64::VisitUnsafePutOrdered(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ false, /* is_ordered */ true, codegen_); @@ -1372,7 +1372,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafePutVolatile(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS64::VisitUnsafePutVolatile(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimInt, + DataType::Type::kInt32, /* is_volatile */ true, /* is_ordered */ false, codegen_); @@ -1385,7 +1385,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafePutObject(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS64::VisitUnsafePutObject(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ false, /* is_ordered */ false, codegen_); @@ -1398,7 +1398,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafePutObjectOrdered(HInvoke* invok void IntrinsicCodeGeneratorMIPS64::VisitUnsafePutObjectOrdered(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ false, /* is_ordered */ true, codegen_); @@ -1411,7 +1411,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafePutObjectVolatile(HInvoke* invo void IntrinsicCodeGeneratorMIPS64::VisitUnsafePutObjectVolatile(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimNot, + DataType::Type::kReference, /* is_volatile */ true, /* is_ordered */ false, codegen_); @@ -1424,7 +1424,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafePutLong(HInvoke* invoke) { void IntrinsicCodeGeneratorMIPS64::VisitUnsafePutLong(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ false, /* is_ordered */ false, codegen_); @@ -1437,7 +1437,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafePutLongOrdered(HInvoke* invoke) void IntrinsicCodeGeneratorMIPS64::VisitUnsafePutLongOrdered(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ false, /* is_ordered */ true, codegen_); @@ -1450,7 +1450,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafePutLongVolatile(HInvoke* invoke void IntrinsicCodeGeneratorMIPS64::VisitUnsafePutLongVolatile(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), - Primitive::kPrimLong, + DataType::Type::kInt64, /* is_volatile */ true, /* is_ordered */ false, codegen_); @@ -1480,7 +1480,7 @@ static void CreateIntIntIntIntIntToIntPlusTemps(ArenaAllocator* arena, HInvoke* // Note that the caller must supply a properly aligned memory address. // If they do not, the behavior is undefined (atomicity not guaranteed, exception may occur). -static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS64* codegen) { +static void GenCas(HInvoke* invoke, DataType::Type type, CodeGeneratorMIPS64* codegen) { Mips64Assembler* assembler = codegen->GetAssembler(); LocationSummary* locations = invoke->GetLocations(); GpuRegister base = locations->InAt(1).AsRegister<GpuRegister>(); @@ -1495,7 +1495,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS64* c DCHECK_NE(offset, out); DCHECK_NE(expected, out); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // The only read barrier implementation supporting the // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); @@ -1525,7 +1525,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS64* c Mips64Label loop_head, exit_loop; __ Daddu(TMP, base, offset); - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { __ PoisonHeapReference(expected); // Do not poison `value`, if it is the same register as // `expected`, which has just been poisoned. @@ -1541,13 +1541,13 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS64* c __ Sync(0); __ Bind(&loop_head); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { __ Lld(out, TMP); } else { // Note: We will need a read barrier here, when read barrier // support is added to the MIPS64 back end. __ Ll(out, TMP); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // The LL instruction sign-extends the 32-bit value, but // 32-bit references must be zero-extended. Zero-extend `out`. __ Dext(out, out, 0, 32); @@ -1561,7 +1561,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS64* c // in the case that the store fails. Whether the // store succeeds, or fails, it will load the // correct Boolean value into the 'out' register. - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { __ Scd(out, TMP); } else { __ Sc(out, TMP); @@ -1571,7 +1571,7 @@ static void GenCas(HInvoke* invoke, Primitive::Type type, CodeGeneratorMIPS64* c __ Bind(&exit_loop); __ Sync(0); - if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + if (kPoisonHeapReferences && type == DataType::Type::kReference) { __ UnpoisonHeapReference(expected); // Do not unpoison `value`, if it is the same register as // `expected`, which has just been unpoisoned. @@ -1587,7 +1587,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafeCASInt(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitUnsafeCASInt(HInvoke* invoke) { - GenCas(invoke, Primitive::kPrimInt, codegen_); + GenCas(invoke, DataType::Type::kInt32, codegen_); } // boolean sun.misc.Unsafe.compareAndSwapLong(Object o, long offset, long expected, long x) @@ -1596,7 +1596,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitUnsafeCASLong(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitUnsafeCASLong(HInvoke* invoke) { - GenCas(invoke, Primitive::kPrimLong, codegen_); + GenCas(invoke, DataType::Type::kInt64, codegen_); } // boolean sun.misc.Unsafe.compareAndSwapObject(Object o, long offset, Object expected, Object x) @@ -1615,7 +1615,7 @@ void IntrinsicCodeGeneratorMIPS64::VisitUnsafeCASObject(HInvoke* invoke) { // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); - GenCas(invoke, Primitive::kPrimNot, codegen_); + GenCas(invoke, DataType::Type::kReference, codegen_); } // int java.lang.String.compareTo(String anotherString) @@ -1626,7 +1626,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitStringCompareTo(HInvoke* invoke) { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<GpuRegister>())); } @@ -1790,7 +1790,7 @@ static void GenerateStringIndexOf(HInvoke* invoke, __ Bind(slow_path->GetExitLabel()); return; } - } else if (code_point->GetType() != Primitive::kPrimChar) { + } else if (code_point->GetType() != DataType::Type::kUint16) { GpuRegister char_reg = locations->InAt(1).AsRegister<GpuRegister>(); __ LoadConst32(tmp_reg, std::numeric_limits<uint16_t>::max()); slow_path = new (allocator) IntrinsicSlowPathMIPS64(invoke); @@ -1822,7 +1822,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitStringIndexOf(HInvoke* invoke) { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<GpuRegister>())); // Need a temp for slow-path codepoint compare, and need to send start-index=0. @@ -1844,7 +1844,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitStringIndexOfAfter(HInvoke* invoke) { locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<GpuRegister>())); } @@ -1863,7 +1863,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitStringNewStringFromBytes(HInvoke* inv locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); locations->SetInAt(3, Location::RegisterLocation(calling_convention.GetRegisterAt(3))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<GpuRegister>())); } @@ -1890,7 +1890,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitStringNewStringFromChars(HInvoke* inv locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<GpuRegister>())); } @@ -1912,7 +1912,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitStringNewStringFromString(HInvoke* in kIntrinsified); InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); - Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + Location outLocation = calling_convention.GetReturnLocation(DataType::Type::kInt32); locations->SetOut(Location::RegisterLocation(outLocation.AsRegister<GpuRegister>())); } @@ -1985,9 +1985,9 @@ void IntrinsicCodeGeneratorMIPS64::VisitStringGetCharsNoCheck(HInvoke* invoke) { LocationSummary* locations = invoke->GetLocations(); // Check assumption that sizeof(Char) is 2 (used in scaling below). - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); - const size_t char_shift = Primitive::ComponentSizeShift(Primitive::kPrimChar); + const size_t char_shift = DataType::SizeShift(DataType::Type::kUint16); GpuRegister srcObj = locations->InAt(0).AsRegister<GpuRegister>(); GpuRegister srcBegin = locations->InAt(1).AsRegister<GpuRegister>(); @@ -2213,10 +2213,10 @@ void IntrinsicCodeGeneratorMIPS64::VisitSystemArrayCopyChar(HInvoke* invoke) { // Okay, everything checks out. Finally time to do the copy. // Check assumption that sizeof(Char) is 2 (used in scaling below). - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); - const size_t char_shift = Primitive::ComponentSizeShift(Primitive::kPrimChar); + const size_t char_shift = DataType::SizeShift(DataType::Type::kUint16); const uint32_t data_offset = mirror::Array::DataOffset(char_size).Uint32Value(); @@ -2250,14 +2250,14 @@ void IntrinsicCodeGeneratorMIPS64::VisitSystemArrayCopyChar(HInvoke* invoke) { } static void GenHighestOneBit(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, Mips64Assembler* assembler) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong) << PrettyDescriptor(type); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64) << type; GpuRegister in = locations->InAt(0).AsRegister<GpuRegister>(); GpuRegister out = locations->Out().AsRegister<GpuRegister>(); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { __ Dclz(TMP, in); __ LoadConst64(AT, INT64_C(0x8000000000000000)); __ Dsrlv(AT, AT, TMP); @@ -2281,7 +2281,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitIntegerHighestOneBit(HInvoke* invoke) } void IntrinsicCodeGeneratorMIPS64::VisitIntegerHighestOneBit(HInvoke* invoke) { - GenHighestOneBit(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenHighestOneBit(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } // long java.lang.Long.highestOneBit(long) @@ -2290,18 +2290,18 @@ void IntrinsicLocationsBuilderMIPS64::VisitLongHighestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitLongHighestOneBit(HInvoke* invoke) { - GenHighestOneBit(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); + GenHighestOneBit(invoke->GetLocations(), DataType::Type::kInt64, GetAssembler()); } static void GenLowestOneBit(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, Mips64Assembler* assembler) { - DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong) << PrettyDescriptor(type); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64) << type; GpuRegister in = locations->InAt(0).AsRegister<GpuRegister>(); GpuRegister out = locations->Out().AsRegister<GpuRegister>(); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { __ Dsubu(TMP, ZERO, in); } else { __ Subu(TMP, ZERO, in); @@ -2315,7 +2315,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitIntegerLowestOneBit(HInvoke* invoke) } void IntrinsicCodeGeneratorMIPS64::VisitIntegerLowestOneBit(HInvoke* invoke) { - GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenLowestOneBit(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } // long java.lang.Long.lowestOneBit(long) @@ -2324,7 +2324,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitLongLowestOneBit(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS64::VisitLongLowestOneBit(HInvoke* invoke) { - GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); + GenLowestOneBit(invoke->GetLocations(), DataType::Type::kInt64, GetAssembler()); } static void CreateFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) { @@ -2334,7 +2334,7 @@ static void CreateFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) { InvokeRuntimeCallingConvention calling_convention; locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimDouble)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kFloat64)); } static void CreateFPFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) { @@ -2345,7 +2345,7 @@ static void CreateFPFPToFPCallLocations(ArenaAllocator* arena, HInvoke* invoke) locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); locations->SetInAt(1, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(1))); - locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimDouble)); + locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kFloat64)); } static void GenFPToFPCall(HInvoke* invoke, @@ -2533,7 +2533,7 @@ void IntrinsicLocationsBuilderMIPS64::VisitIntegerValueOf(HInvoke* invoke) { IntrinsicVisitor::ComputeIntegerValueOfLocations( invoke, codegen_, - calling_convention.GetReturnLocation(Primitive::kPrimNot), + calling_convention.GetReturnLocation(DataType::Type::kReference), Location::RegisterLocation(calling_convention.GetRegisterAt(0))); } diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index abd9014438..a5916228a8 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -97,7 +97,7 @@ class ReadBarrierSystemArrayCopySlowPathX86 : public SlowPathCode { DCHECK(instruction_->GetLocations()->Intrinsified()); DCHECK_EQ(instruction_->AsInvoke()->GetIntrinsic(), Intrinsics::kSystemArrayCopy); - int32_t element_size = Primitive::ComponentSize(Primitive::kPrimNot); + int32_t element_size = DataType::Size(DataType::Type::kReference); uint32_t offset = mirror::Array::DataOffset(element_size).Uint32Value(); Register src = locations->InAt(0).AsRegister<Register>(); @@ -282,17 +282,17 @@ static void CreateLongToLongLocations(ArenaAllocator* arena, HInvoke* invoke) { } static void GenReverseBytes(LocationSummary* locations, - Primitive::Type size, + DataType::Type size, X86Assembler* assembler) { Register out = locations->Out().AsRegister<Register>(); switch (size) { - case Primitive::kPrimShort: + case DataType::Type::kInt16: // TODO: Can be done with an xchg of 8b registers. This is straight from Quick. __ bswapl(out); __ sarl(out, Immediate(16)); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ bswapl(out); break; default: @@ -306,7 +306,7 @@ void IntrinsicLocationsBuilderX86::VisitIntegerReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitIntegerReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } void IntrinsicLocationsBuilderX86::VisitLongReverseBytes(HInvoke* invoke) { @@ -335,7 +335,7 @@ void IntrinsicLocationsBuilderX86::VisitShortReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitShortReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimShort, GetAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt16, GetAssembler()); } @@ -1307,7 +1307,7 @@ void IntrinsicCodeGeneratorX86::VisitSystemArrayCopyChar(HInvoke* invoke) { // Okay, everything checks out. Finally time to do the copy. // Check assumption that sizeof(Char) is 2 (used in scaling below). - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); const uint32_t data_offset = mirror::Array::DataOffset(char_size).Uint32Value(); @@ -1540,7 +1540,7 @@ static void GenerateStringIndexOf(HInvoke* invoke, __ Bind(slow_path->GetExitLabel()); return; } - } else if (code_point->GetType() != Primitive::kPrimChar) { + } else if (code_point->GetType() != DataType::Type::kUint16) { __ cmpl(search_value, Immediate(std::numeric_limits<uint16_t>::max())); slow_path = new (allocator) IntrinsicSlowPathX86(invoke); codegen->AddSlowPath(slow_path); @@ -1766,7 +1766,7 @@ void IntrinsicCodeGeneratorX86::VisitStringGetCharsNoCheck(HInvoke* invoke) { X86Assembler* assembler = GetAssembler(); LocationSummary* locations = invoke->GetLocations(); - size_t char_component_size = Primitive::ComponentSize(Primitive::kPrimChar); + size_t char_component_size = DataType::Size(DataType::Type::kUint16); // Location of data in char array buffer. const uint32_t data_offset = mirror::Array::DataOffset(char_component_size).Uint32Value(); // Location of char array data in string. @@ -1782,7 +1782,7 @@ void IntrinsicCodeGeneratorX86::VisitStringGetCharsNoCheck(HInvoke* invoke) { Register dstBegin = locations->InAt(4).AsRegister<Register>(); // Check assumption that sizeof(Char) is 2 (used in scaling below). - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); // Compute the number of chars (words) to move. @@ -1802,7 +1802,7 @@ void IntrinsicCodeGeneratorX86::VisitStringGetCharsNoCheck(HInvoke* invoke) { if (mirror::kUseStringCompression) { // Location of count in string const uint32_t count_offset = mirror::String::CountOffset().Uint32Value(); - const size_t c_char_size = Primitive::ComponentSize(Primitive::kPrimByte); + const size_t c_char_size = DataType::Size(DataType::Type::kInt8); DCHECK_EQ(c_char_size, 1u); __ pushl(EAX); __ cfi().AdjustCFAOffset(stack_adjust); @@ -1849,22 +1849,22 @@ void IntrinsicCodeGeneratorX86::VisitStringGetCharsNoCheck(HInvoke* invoke) { __ cfi().AdjustCFAOffset(-stack_adjust); } -static void GenPeek(LocationSummary* locations, Primitive::Type size, X86Assembler* assembler) { +static void GenPeek(LocationSummary* locations, DataType::Type size, X86Assembler* assembler) { Register address = locations->InAt(0).AsRegisterPairLow<Register>(); Location out_loc = locations->Out(); // x86 allows unaligned access. We do not have to check the input or use specific instructions // to avoid a SIGBUS. switch (size) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: __ movsxb(out_loc.AsRegister<Register>(), Address(address, 0)); break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: __ movsxw(out_loc.AsRegister<Register>(), Address(address, 0)); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ movl(out_loc.AsRegister<Register>(), Address(address, 0)); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: __ movl(out_loc.AsRegisterPairLow<Register>(), Address(address, 0)); __ movl(out_loc.AsRegisterPairHigh<Register>(), Address(address, 4)); break; @@ -1879,7 +1879,7 @@ void IntrinsicLocationsBuilderX86::VisitMemoryPeekByte(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMemoryPeekByte(HInvoke* invoke) { - GenPeek(invoke->GetLocations(), Primitive::kPrimByte, GetAssembler()); + GenPeek(invoke->GetLocations(), DataType::Type::kInt8, GetAssembler()); } void IntrinsicLocationsBuilderX86::VisitMemoryPeekIntNative(HInvoke* invoke) { @@ -1887,7 +1887,7 @@ void IntrinsicLocationsBuilderX86::VisitMemoryPeekIntNative(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMemoryPeekIntNative(HInvoke* invoke) { - GenPeek(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenPeek(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } void IntrinsicLocationsBuilderX86::VisitMemoryPeekLongNative(HInvoke* invoke) { @@ -1895,7 +1895,7 @@ void IntrinsicLocationsBuilderX86::VisitMemoryPeekLongNative(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMemoryPeekLongNative(HInvoke* invoke) { - GenPeek(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); + GenPeek(invoke->GetLocations(), DataType::Type::kInt64, GetAssembler()); } void IntrinsicLocationsBuilderX86::VisitMemoryPeekShortNative(HInvoke* invoke) { @@ -1903,30 +1903,30 @@ void IntrinsicLocationsBuilderX86::VisitMemoryPeekShortNative(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMemoryPeekShortNative(HInvoke* invoke) { - GenPeek(invoke->GetLocations(), Primitive::kPrimShort, GetAssembler()); + GenPeek(invoke->GetLocations(), DataType::Type::kInt16, GetAssembler()); } -static void CreateLongIntToVoidLocations(ArenaAllocator* arena, Primitive::Type size, +static void CreateLongIntToVoidLocations(ArenaAllocator* arena, DataType::Type size, HInvoke* invoke) { LocationSummary* locations = new (arena) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); HInstruction* value = invoke->InputAt(1); - if (size == Primitive::kPrimByte) { + if (size == DataType::Type::kInt8) { locations->SetInAt(1, Location::ByteRegisterOrConstant(EDX, value)); } else { locations->SetInAt(1, Location::RegisterOrConstant(value)); } } -static void GenPoke(LocationSummary* locations, Primitive::Type size, X86Assembler* assembler) { +static void GenPoke(LocationSummary* locations, DataType::Type size, X86Assembler* assembler) { Register address = locations->InAt(0).AsRegisterPairLow<Register>(); Location value_loc = locations->InAt(1); // x86 allows unaligned access. We do not have to check the input or use specific instructions // to avoid a SIGBUS. switch (size) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: if (value_loc.IsConstant()) { __ movb(Address(address, 0), Immediate(value_loc.GetConstant()->AsIntConstant()->GetValue())); @@ -1934,7 +1934,7 @@ static void GenPoke(LocationSummary* locations, Primitive::Type size, X86Assembl __ movb(Address(address, 0), value_loc.AsRegister<ByteRegister>()); } break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: if (value_loc.IsConstant()) { __ movw(Address(address, 0), Immediate(value_loc.GetConstant()->AsIntConstant()->GetValue())); @@ -1942,7 +1942,7 @@ static void GenPoke(LocationSummary* locations, Primitive::Type size, X86Assembl __ movw(Address(address, 0), value_loc.AsRegister<Register>()); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: if (value_loc.IsConstant()) { __ movl(Address(address, 0), Immediate(value_loc.GetConstant()->AsIntConstant()->GetValue())); @@ -1950,7 +1950,7 @@ static void GenPoke(LocationSummary* locations, Primitive::Type size, X86Assembl __ movl(Address(address, 0), value_loc.AsRegister<Register>()); } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (value_loc.IsConstant()) { int64_t value = value_loc.GetConstant()->AsLongConstant()->GetValue(); __ movl(Address(address, 0), Immediate(Low32Bits(value))); @@ -1967,35 +1967,35 @@ static void GenPoke(LocationSummary* locations, Primitive::Type size, X86Assembl } void IntrinsicLocationsBuilderX86::VisitMemoryPokeByte(HInvoke* invoke) { - CreateLongIntToVoidLocations(arena_, Primitive::kPrimByte, invoke); + CreateLongIntToVoidLocations(arena_, DataType::Type::kInt8, invoke); } void IntrinsicCodeGeneratorX86::VisitMemoryPokeByte(HInvoke* invoke) { - GenPoke(invoke->GetLocations(), Primitive::kPrimByte, GetAssembler()); + GenPoke(invoke->GetLocations(), DataType::Type::kInt8, GetAssembler()); } void IntrinsicLocationsBuilderX86::VisitMemoryPokeIntNative(HInvoke* invoke) { - CreateLongIntToVoidLocations(arena_, Primitive::kPrimInt, invoke); + CreateLongIntToVoidLocations(arena_, DataType::Type::kInt32, invoke); } void IntrinsicCodeGeneratorX86::VisitMemoryPokeIntNative(HInvoke* invoke) { - GenPoke(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenPoke(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } void IntrinsicLocationsBuilderX86::VisitMemoryPokeLongNative(HInvoke* invoke) { - CreateLongIntToVoidLocations(arena_, Primitive::kPrimLong, invoke); + CreateLongIntToVoidLocations(arena_, DataType::Type::kInt64, invoke); } void IntrinsicCodeGeneratorX86::VisitMemoryPokeLongNative(HInvoke* invoke) { - GenPoke(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); + GenPoke(invoke->GetLocations(), DataType::Type::kInt64, GetAssembler()); } void IntrinsicLocationsBuilderX86::VisitMemoryPokeShortNative(HInvoke* invoke) { - CreateLongIntToVoidLocations(arena_, Primitive::kPrimShort, invoke); + CreateLongIntToVoidLocations(arena_, DataType::Type::kInt16, invoke); } void IntrinsicCodeGeneratorX86::VisitMemoryPokeShortNative(HInvoke* invoke) { - GenPoke(invoke->GetLocations(), Primitive::kPrimShort, GetAssembler()); + GenPoke(invoke->GetLocations(), DataType::Type::kInt16, GetAssembler()); } void IntrinsicLocationsBuilderX86::VisitThreadCurrentThread(HInvoke* invoke) { @@ -2011,7 +2011,7 @@ void IntrinsicCodeGeneratorX86::VisitThreadCurrentThread(HInvoke* invoke) { } static void GenUnsafeGet(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, bool is_volatile, CodeGeneratorX86* codegen) { X86Assembler* assembler = down_cast<X86Assembler*>(codegen->GetAssembler()); @@ -2023,13 +2023,13 @@ static void GenUnsafeGet(HInvoke* invoke, Location output_loc = locations->Out(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { Register output = output_loc.AsRegister<Register>(); __ movl(output, Address(base, offset, ScaleFactor::TIMES_1, 0)); break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { Register output = output_loc.AsRegister<Register>(); if (kEmitCompilerReadBarrier) { if (kUseBakerReadBarrier) { @@ -2048,7 +2048,7 @@ static void GenUnsafeGet(HInvoke* invoke, break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { Register output_lo = output_loc.AsRegisterPairLow<Register>(); Register output_hi = output_loc.AsRegisterPairHigh<Register>(); if (is_volatile) { @@ -2073,7 +2073,7 @@ static void GenUnsafeGet(HInvoke* invoke, static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke, - Primitive::Type type, + DataType::Type type, bool is_volatile) { bool can_call = kEmitCompilerReadBarrier && (invoke->GetIntrinsic() == Intrinsics::kUnsafeGetObject || @@ -2089,7 +2089,7 @@ static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, locations->SetInAt(0, Location::NoLocation()); // Unused receiver. locations->SetInAt(1, Location::RequiresRegister()); locations->SetInAt(2, Location::RequiresRegister()); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { if (is_volatile) { // Need to use XMM to read volatile. locations->AddTemp(Location::RequiresFpuRegister()); @@ -2104,47 +2104,48 @@ static void CreateIntIntIntToIntLocations(ArenaAllocator* arena, } void IntrinsicLocationsBuilderX86::VisitUnsafeGet(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimInt, /* is_volatile */ false); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt32, /* is_volatile */ false); } void IntrinsicLocationsBuilderX86::VisitUnsafeGetVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimInt, /* is_volatile */ true); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt32, /* is_volatile */ true); } void IntrinsicLocationsBuilderX86::VisitUnsafeGetLong(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimLong, /* is_volatile */ false); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt64, /* is_volatile */ false); } void IntrinsicLocationsBuilderX86::VisitUnsafeGetLongVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimLong, /* is_volatile */ true); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kInt64, /* is_volatile */ true); } void IntrinsicLocationsBuilderX86::VisitUnsafeGetObject(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimNot, /* is_volatile */ false); + CreateIntIntIntToIntLocations( + arena_, invoke, DataType::Type::kReference, /* is_volatile */ false); } void IntrinsicLocationsBuilderX86::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { - CreateIntIntIntToIntLocations(arena_, invoke, Primitive::kPrimNot, /* is_volatile */ true); + CreateIntIntIntToIntLocations(arena_, invoke, DataType::Type::kReference, /* is_volatile */ true); } void IntrinsicCodeGeneratorX86::VisitUnsafeGet(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafeGetVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafeGetLong(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafeGetLongVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafeGetObject(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ true, codegen_); } static void CreateIntIntIntIntToVoidPlusTempsLocations(ArenaAllocator* arena, - Primitive::Type type, + DataType::Type type, HInvoke* invoke, bool is_volatile) { LocationSummary* locations = new (arena) LocationSummary(invoke, @@ -2154,12 +2155,12 @@ static void CreateIntIntIntIntToVoidPlusTempsLocations(ArenaAllocator* arena, locations->SetInAt(1, Location::RequiresRegister()); locations->SetInAt(2, Location::RequiresRegister()); locations->SetInAt(3, Location::RequiresRegister()); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // Need temp registers for card-marking. locations->AddTemp(Location::RequiresRegister()); // Possibly used for reference poisoning too. // Ensure the value is in a byte register. locations->AddTemp(Location::RegisterLocation(ECX)); - } else if (type == Primitive::kPrimLong && is_volatile) { + } else if (type == DataType::Type::kInt64 && is_volatile) { locations->AddTemp(Location::RequiresFpuRegister()); locations->AddTemp(Location::RequiresFpuRegister()); } @@ -2167,45 +2168,45 @@ static void CreateIntIntIntIntToVoidPlusTempsLocations(ArenaAllocator* arena, void IntrinsicLocationsBuilderX86::VisitUnsafePut(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations( - arena_, Primitive::kPrimInt, invoke, /* is_volatile */ false); + arena_, DataType::Type::kInt32, invoke, /* is_volatile */ false); } void IntrinsicLocationsBuilderX86::VisitUnsafePutOrdered(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations( - arena_, Primitive::kPrimInt, invoke, /* is_volatile */ false); + arena_, DataType::Type::kInt32, invoke, /* is_volatile */ false); } void IntrinsicLocationsBuilderX86::VisitUnsafePutVolatile(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations( - arena_, Primitive::kPrimInt, invoke, /* is_volatile */ true); + arena_, DataType::Type::kInt32, invoke, /* is_volatile */ true); } void IntrinsicLocationsBuilderX86::VisitUnsafePutObject(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations( - arena_, Primitive::kPrimNot, invoke, /* is_volatile */ false); + arena_, DataType::Type::kReference, invoke, /* is_volatile */ false); } void IntrinsicLocationsBuilderX86::VisitUnsafePutObjectOrdered(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations( - arena_, Primitive::kPrimNot, invoke, /* is_volatile */ false); + arena_, DataType::Type::kReference, invoke, /* is_volatile */ false); } void IntrinsicLocationsBuilderX86::VisitUnsafePutObjectVolatile(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations( - arena_, Primitive::kPrimNot, invoke, /* is_volatile */ true); + arena_, DataType::Type::kReference, invoke, /* is_volatile */ true); } void IntrinsicLocationsBuilderX86::VisitUnsafePutLong(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations( - arena_, Primitive::kPrimLong, invoke, /* is_volatile */ false); + arena_, DataType::Type::kInt64, invoke, /* is_volatile */ false); } void IntrinsicLocationsBuilderX86::VisitUnsafePutLongOrdered(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations( - arena_, Primitive::kPrimLong, invoke, /* is_volatile */ false); + arena_, DataType::Type::kInt64, invoke, /* is_volatile */ false); } void IntrinsicLocationsBuilderX86::VisitUnsafePutLongVolatile(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations( - arena_, Primitive::kPrimLong, invoke, /* is_volatile */ true); + arena_, DataType::Type::kInt64, invoke, /* is_volatile */ true); } // We don't care for ordered: it requires an AnyStore barrier, which is already given by the x86 // memory model. static void GenUnsafePut(LocationSummary* locations, - Primitive::Type type, + DataType::Type type, bool is_volatile, CodeGeneratorX86* codegen) { X86Assembler* assembler = down_cast<X86Assembler*>(codegen->GetAssembler()); @@ -2213,7 +2214,7 @@ static void GenUnsafePut(LocationSummary* locations, Register offset = locations->InAt(2).AsRegisterPairLow<Register>(); Location value_loc = locations->InAt(3); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { Register value_lo = value_loc.AsRegisterPairLow<Register>(); Register value_hi = value_loc.AsRegisterPairHigh<Register>(); if (is_volatile) { @@ -2227,7 +2228,7 @@ static void GenUnsafePut(LocationSummary* locations, __ movl(Address(base, offset, ScaleFactor::TIMES_1, 0), value_lo); __ movl(Address(base, offset, ScaleFactor::TIMES_1, 4), value_hi); } - } else if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + } else if (kPoisonHeapReferences && type == DataType::Type::kReference) { Register temp = locations->GetTemp(0).AsRegister<Register>(); __ movl(temp, value_loc.AsRegister<Register>()); __ PoisonHeapReference(temp); @@ -2240,7 +2241,7 @@ static void GenUnsafePut(LocationSummary* locations, codegen->MemoryFence(); } - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { bool value_can_be_null = true; // TODO: Worth finding out this information? codegen->MarkGCCard(locations->GetTemp(0).AsRegister<Register>(), locations->GetTemp(1).AsRegister<Register>(), @@ -2251,35 +2252,38 @@ static void GenUnsafePut(LocationSummary* locations, } void IntrinsicCodeGeneratorX86::VisitUnsafePut(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimInt, /* is_volatile */ false, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafePutOrdered(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimInt, /* is_volatile */ false, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafePutVolatile(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimInt, /* is_volatile */ true, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafePutObject(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimNot, /* is_volatile */ false, codegen_); + GenUnsafePut( + invoke->GetLocations(), DataType::Type::kReference, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafePutObjectOrdered(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimNot, /* is_volatile */ false, codegen_); + GenUnsafePut( + invoke->GetLocations(), DataType::Type::kReference, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafePutObjectVolatile(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimNot, /* is_volatile */ true, codegen_); + GenUnsafePut( + invoke->GetLocations(), DataType::Type::kReference, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafePutLong(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimLong, /* is_volatile */ false, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt64, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafePutLongOrdered(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimLong, /* is_volatile */ false, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt64, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafePutLongVolatile(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimLong, /* is_volatile */ true, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt64, /* is_volatile */ true, codegen_); } static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, - Primitive::Type type, + DataType::Type type, HInvoke* invoke) { bool can_call = kEmitCompilerReadBarrier && kUseBakerReadBarrier && @@ -2296,7 +2300,7 @@ static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, locations->SetInAt(2, Location::RequiresRegister()); // Expected value must be in EAX or EDX:EAX. // For long, new value must be in ECX:EBX. - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { locations->SetInAt(3, Location::RegisterPairLocation(EAX, EDX)); locations->SetInAt(4, Location::RegisterPairLocation(EBX, ECX)); } else { @@ -2306,7 +2310,7 @@ static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, // Force a byte register for the output. locations->SetOut(Location::RegisterLocation(EAX)); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // Need temporary registers for card-marking, and possibly for // (Baker) read barrier. locations->AddTemp(Location::RequiresRegister()); // Possibly used for reference poisoning too. @@ -2316,11 +2320,11 @@ static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, } void IntrinsicLocationsBuilderX86::VisitUnsafeCASInt(HInvoke* invoke) { - CreateIntIntIntIntIntToInt(arena_, Primitive::kPrimInt, invoke); + CreateIntIntIntIntIntToInt(arena_, DataType::Type::kInt32, invoke); } void IntrinsicLocationsBuilderX86::VisitUnsafeCASLong(HInvoke* invoke) { - CreateIntIntIntIntIntToInt(arena_, Primitive::kPrimLong, invoke); + CreateIntIntIntIntIntToInt(arena_, DataType::Type::kInt64, invoke); } void IntrinsicLocationsBuilderX86::VisitUnsafeCASObject(HInvoke* invoke) { @@ -2330,10 +2334,10 @@ void IntrinsicLocationsBuilderX86::VisitUnsafeCASObject(HInvoke* invoke) { return; } - CreateIntIntIntIntIntToInt(arena_, Primitive::kPrimNot, invoke); + CreateIntIntIntIntIntToInt(arena_, DataType::Type::kReference, invoke); } -static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86* codegen) { +static void GenCAS(DataType::Type type, HInvoke* invoke, CodeGeneratorX86* codegen) { X86Assembler* assembler = down_cast<X86Assembler*>(codegen->GetAssembler()); LocationSummary* locations = invoke->GetLocations(); @@ -2345,7 +2349,7 @@ static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86* code // The address of the field within the holding object. Address field_addr(base, offset, ScaleFactor::TIMES_1, 0); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // The only read barrier implementation supporting the // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); @@ -2426,12 +2430,12 @@ static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86* code // `expected`, as it is the same as register `out` (EAX). } } else { - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { // Ensure the expected value is in EAX (required by the CMPXCHG // instruction). DCHECK_EQ(locations->InAt(3).AsRegister<Register>(), EAX); __ LockCmpxchgl(field_addr, locations->InAt(4).AsRegister<Register>()); - } else if (type == Primitive::kPrimLong) { + } else if (type == DataType::Type::kInt64) { // Ensure the expected value is in EAX:EDX and that the new // value is in EBX:ECX (required by the CMPXCHG8B instruction). DCHECK_EQ(locations->InAt(3).AsRegisterPairLow<Register>(), EAX); @@ -2453,11 +2457,11 @@ static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86* code } void IntrinsicCodeGeneratorX86::VisitUnsafeCASInt(HInvoke* invoke) { - GenCAS(Primitive::kPrimInt, invoke, codegen_); + GenCAS(DataType::Type::kInt32, invoke, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafeCASLong(HInvoke* invoke) { - GenCAS(Primitive::kPrimLong, invoke, codegen_); + GenCAS(DataType::Type::kInt64, invoke, codegen_); } void IntrinsicCodeGeneratorX86::VisitUnsafeCASObject(HInvoke* invoke) { @@ -2465,7 +2469,7 @@ void IntrinsicCodeGeneratorX86::VisitUnsafeCASObject(HInvoke* invoke) { // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); - GenCAS(Primitive::kPrimNot, invoke, codegen_); + GenCAS(DataType::Type::kReference, invoke, codegen_); } void IntrinsicLocationsBuilderX86::VisitIntegerReverse(HInvoke* invoke) { @@ -2824,16 +2828,16 @@ static bool IsSameInput(HInstruction* instruction, size_t input0, size_t input1) // Compute base address for the System.arraycopy intrinsic in `base`. static void GenSystemArrayCopyBaseAddress(X86Assembler* assembler, - Primitive::Type type, + DataType::Type type, const Register& array, const Location& pos, const Register& base) { // This routine is only used by the SystemArrayCopy intrinsic at the - // moment. We can allow Primitive::kPrimNot as `type` to implement + // moment. We can allow DataType::Type::kReference as `type` to implement // the SystemArrayCopyChar intrinsic. - DCHECK_EQ(type, Primitive::kPrimNot); - const int32_t element_size = Primitive::ComponentSize(type); - const ScaleFactor scale_factor = static_cast<ScaleFactor>(Primitive::ComponentSizeShift(type)); + DCHECK_EQ(type, DataType::Type::kReference); + const int32_t element_size = DataType::Size(type); + const ScaleFactor scale_factor = static_cast<ScaleFactor>(DataType::SizeShift(type)); const uint32_t data_offset = mirror::Array::DataOffset(element_size).Uint32Value(); if (pos.IsConstant()) { @@ -2846,16 +2850,16 @@ static void GenSystemArrayCopyBaseAddress(X86Assembler* assembler, // Compute end source address for the System.arraycopy intrinsic in `end`. static void GenSystemArrayCopyEndAddress(X86Assembler* assembler, - Primitive::Type type, + DataType::Type type, const Location& copy_length, const Register& base, const Register& end) { // This routine is only used by the SystemArrayCopy intrinsic at the - // moment. We can allow Primitive::kPrimNot as `type` to implement + // moment. We can allow DataType::Type::kReference as `type` to implement // the SystemArrayCopyChar intrinsic. - DCHECK_EQ(type, Primitive::kPrimNot); - const int32_t element_size = Primitive::ComponentSize(type); - const ScaleFactor scale_factor = static_cast<ScaleFactor>(Primitive::ComponentSizeShift(type)); + DCHECK_EQ(type, DataType::Type::kReference); + const int32_t element_size = DataType::Size(type); + const ScaleFactor scale_factor = static_cast<ScaleFactor>(DataType::SizeShift(type)); if (copy_length.IsConstant()) { int32_t constant = copy_length.GetConstant()->AsIntConstant()->GetValue(); @@ -3169,8 +3173,8 @@ void IntrinsicCodeGeneratorX86::VisitSystemArrayCopy(HInvoke* invoke) { __ j(kNotEqual, intrinsic_slow_path->GetEntryLabel()); } - const Primitive::Type type = Primitive::kPrimNot; - const int32_t element_size = Primitive::ComponentSize(type); + const DataType::Type type = DataType::Type::kReference; + const int32_t element_size = DataType::Size(type); // Compute the base source address in `temp1`. GenSystemArrayCopyBaseAddress(GetAssembler(), type, src, src_pos, temp1); diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index 7798c0d99e..a2545ee3d8 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -90,7 +90,7 @@ class ReadBarrierSystemArrayCopySlowPathX86_64 : public SlowPathCode { DCHECK(instruction_->GetLocations()->Intrinsified()); DCHECK_EQ(instruction_->AsInvoke()->GetIntrinsic(), Intrinsics::kSystemArrayCopy); - int32_t element_size = Primitive::ComponentSize(Primitive::kPrimNot); + int32_t element_size = DataType::Size(DataType::Type::kReference); CpuRegister src_curr_addr = locations->GetTemp(0).AsRegister<CpuRegister>(); CpuRegister dst_curr_addr = locations->GetTemp(1).AsRegister<CpuRegister>(); @@ -193,20 +193,20 @@ static void CreateIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { } static void GenReverseBytes(LocationSummary* locations, - Primitive::Type size, + DataType::Type size, X86_64Assembler* assembler) { CpuRegister out = locations->Out().AsRegister<CpuRegister>(); switch (size) { - case Primitive::kPrimShort: + case DataType::Type::kInt16: // TODO: Can be done with an xchg of 8b registers. This is straight from Quick. __ bswapl(out); __ sarl(out, Immediate(16)); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ bswapl(out); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: __ bswapq(out); break; default: @@ -220,7 +220,7 @@ void IntrinsicLocationsBuilderX86_64::VisitIntegerReverseBytes(HInvoke* invoke) } void IntrinsicCodeGeneratorX86_64::VisitIntegerReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } void IntrinsicLocationsBuilderX86_64::VisitLongReverseBytes(HInvoke* invoke) { @@ -228,7 +228,7 @@ void IntrinsicLocationsBuilderX86_64::VisitLongReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86_64::VisitLongReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt64, GetAssembler()); } void IntrinsicLocationsBuilderX86_64::VisitShortReverseBytes(HInvoke* invoke) { @@ -236,7 +236,7 @@ void IntrinsicLocationsBuilderX86_64::VisitShortReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86_64::VisitShortReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), Primitive::kPrimShort, GetAssembler()); + GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt16, GetAssembler()); } @@ -1084,7 +1084,7 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopyChar(HInvoke* invoke) { // Okay, everything checks out. Finally time to do the copy. // Check assumption that sizeof(Char) is 2 (used in scaling below). - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); const uint32_t data_offset = mirror::Array::DataOffset(char_size).Uint32Value(); @@ -1125,7 +1125,7 @@ void IntrinsicLocationsBuilderX86_64::VisitSystemArrayCopy(HInvoke* invoke) { // source address for the System.arraycopy intrinsic in `src_base`, // `dst_base` and `src_end` respectively. static void GenSystemArrayCopyAddresses(X86_64Assembler* assembler, - Primitive::Type type, + DataType::Type type, const CpuRegister& src, const Location& src_pos, const CpuRegister& dst, @@ -1135,9 +1135,9 @@ static void GenSystemArrayCopyAddresses(X86_64Assembler* assembler, const CpuRegister& dst_base, const CpuRegister& src_end) { // This routine is only used by the SystemArrayCopy intrinsic. - DCHECK_EQ(type, Primitive::kPrimNot); - const int32_t element_size = Primitive::ComponentSize(type); - const ScaleFactor scale_factor = static_cast<ScaleFactor>(Primitive::ComponentSizeShift(type)); + DCHECK_EQ(type, DataType::Type::kReference); + const int32_t element_size = DataType::Size(type); + const ScaleFactor scale_factor = static_cast<ScaleFactor>(DataType::SizeShift(type)); const uint32_t data_offset = mirror::Array::DataOffset(element_size).Uint32Value(); if (src_pos.IsConstant()) { @@ -1410,8 +1410,8 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { __ j(kNotEqual, intrinsic_slow_path->GetEntryLabel()); } - const Primitive::Type type = Primitive::kPrimNot; - const int32_t element_size = Primitive::ComponentSize(type); + const DataType::Type type = DataType::Type::kReference; + const int32_t element_size = DataType::Size(type); // Compute base source address, base destination address, and end // source address in `temp1`, `temp2` and `temp3` respectively. @@ -1705,7 +1705,7 @@ static void GenerateStringIndexOf(HInvoke* invoke, __ Bind(slow_path->GetExitLabel()); return; } - } else if (code_point->GetType() != Primitive::kPrimChar) { + } else if (code_point->GetType() != DataType::Type::kUint16) { __ cmpl(search_value, Immediate(std::numeric_limits<uint16_t>::max())); slow_path = new (allocator) IntrinsicSlowPathX86_64(invoke); codegen->AddSlowPath(slow_path); @@ -1922,7 +1922,7 @@ void IntrinsicCodeGeneratorX86_64::VisitStringGetCharsNoCheck(HInvoke* invoke) { X86_64Assembler* assembler = GetAssembler(); LocationSummary* locations = invoke->GetLocations(); - size_t char_component_size = Primitive::ComponentSize(Primitive::kPrimChar); + size_t char_component_size = DataType::Size(DataType::Type::kUint16); // Location of data in char array buffer. const uint32_t data_offset = mirror::Array::DataOffset(char_component_size).Uint32Value(); // Location of char array data in string. @@ -1938,7 +1938,7 @@ void IntrinsicCodeGeneratorX86_64::VisitStringGetCharsNoCheck(HInvoke* invoke) { CpuRegister dstBegin = locations->InAt(4).AsRegister<CpuRegister>(); // Check assumption that sizeof(Char) is 2 (used in scaling below). - const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + const size_t char_size = DataType::Size(DataType::Type::kUint16); DCHECK_EQ(char_size, 2u); NearLabel done; @@ -1952,7 +1952,7 @@ void IntrinsicCodeGeneratorX86_64::VisitStringGetCharsNoCheck(HInvoke* invoke) { } if (mirror::kUseStringCompression) { NearLabel copy_uncompressed, copy_loop; - const size_t c_char_size = Primitive::ComponentSize(Primitive::kPrimByte); + const size_t c_char_size = DataType::Size(DataType::Type::kInt8); DCHECK_EQ(c_char_size, 1u); // Location of count in string. const uint32_t count_offset = mirror::String::CountOffset().Uint32Value(); @@ -1993,22 +1993,22 @@ void IntrinsicCodeGeneratorX86_64::VisitStringGetCharsNoCheck(HInvoke* invoke) { __ Bind(&done); } -static void GenPeek(LocationSummary* locations, Primitive::Type size, X86_64Assembler* assembler) { +static void GenPeek(LocationSummary* locations, DataType::Type size, X86_64Assembler* assembler) { CpuRegister address = locations->InAt(0).AsRegister<CpuRegister>(); CpuRegister out = locations->Out().AsRegister<CpuRegister>(); // == address, here for clarity. // x86 allows unaligned access. We do not have to check the input or use specific instructions // to avoid a SIGBUS. switch (size) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: __ movsxb(out, Address(address, 0)); break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: __ movsxw(out, Address(address, 0)); break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ movl(out, Address(address, 0)); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: __ movq(out, Address(address, 0)); break; default: @@ -2022,7 +2022,7 @@ void IntrinsicLocationsBuilderX86_64::VisitMemoryPeekByte(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86_64::VisitMemoryPeekByte(HInvoke* invoke) { - GenPeek(invoke->GetLocations(), Primitive::kPrimByte, GetAssembler()); + GenPeek(invoke->GetLocations(), DataType::Type::kInt8, GetAssembler()); } void IntrinsicLocationsBuilderX86_64::VisitMemoryPeekIntNative(HInvoke* invoke) { @@ -2030,7 +2030,7 @@ void IntrinsicLocationsBuilderX86_64::VisitMemoryPeekIntNative(HInvoke* invoke) } void IntrinsicCodeGeneratorX86_64::VisitMemoryPeekIntNative(HInvoke* invoke) { - GenPeek(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenPeek(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } void IntrinsicLocationsBuilderX86_64::VisitMemoryPeekLongNative(HInvoke* invoke) { @@ -2038,7 +2038,7 @@ void IntrinsicLocationsBuilderX86_64::VisitMemoryPeekLongNative(HInvoke* invoke) } void IntrinsicCodeGeneratorX86_64::VisitMemoryPeekLongNative(HInvoke* invoke) { - GenPeek(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); + GenPeek(invoke->GetLocations(), DataType::Type::kInt64, GetAssembler()); } void IntrinsicLocationsBuilderX86_64::VisitMemoryPeekShortNative(HInvoke* invoke) { @@ -2046,7 +2046,7 @@ void IntrinsicLocationsBuilderX86_64::VisitMemoryPeekShortNative(HInvoke* invoke } void IntrinsicCodeGeneratorX86_64::VisitMemoryPeekShortNative(HInvoke* invoke) { - GenPeek(invoke->GetLocations(), Primitive::kPrimShort, GetAssembler()); + GenPeek(invoke->GetLocations(), DataType::Type::kInt16, GetAssembler()); } static void CreateIntIntToVoidLocations(ArenaAllocator* arena, HInvoke* invoke) { @@ -2057,13 +2057,13 @@ static void CreateIntIntToVoidLocations(ArenaAllocator* arena, HInvoke* invoke) locations->SetInAt(1, Location::RegisterOrInt32Constant(invoke->InputAt(1))); } -static void GenPoke(LocationSummary* locations, Primitive::Type size, X86_64Assembler* assembler) { +static void GenPoke(LocationSummary* locations, DataType::Type size, X86_64Assembler* assembler) { CpuRegister address = locations->InAt(0).AsRegister<CpuRegister>(); Location value = locations->InAt(1); // x86 allows unaligned access. We do not have to check the input or use specific instructions // to avoid a SIGBUS. switch (size) { - case Primitive::kPrimByte: + case DataType::Type::kInt8: if (value.IsConstant()) { __ movb(Address(address, 0), Immediate(CodeGenerator::GetInt32ValueOf(value.GetConstant()))); @@ -2071,7 +2071,7 @@ static void GenPoke(LocationSummary* locations, Primitive::Type size, X86_64Asse __ movb(Address(address, 0), value.AsRegister<CpuRegister>()); } break; - case Primitive::kPrimShort: + case DataType::Type::kInt16: if (value.IsConstant()) { __ movw(Address(address, 0), Immediate(CodeGenerator::GetInt32ValueOf(value.GetConstant()))); @@ -2079,7 +2079,7 @@ static void GenPoke(LocationSummary* locations, Primitive::Type size, X86_64Asse __ movw(Address(address, 0), value.AsRegister<CpuRegister>()); } break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: if (value.IsConstant()) { __ movl(Address(address, 0), Immediate(CodeGenerator::GetInt32ValueOf(value.GetConstant()))); @@ -2087,7 +2087,7 @@ static void GenPoke(LocationSummary* locations, Primitive::Type size, X86_64Asse __ movl(Address(address, 0), value.AsRegister<CpuRegister>()); } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (value.IsConstant()) { int64_t v = value.GetConstant()->AsLongConstant()->GetValue(); DCHECK(IsInt<32>(v)); @@ -2108,7 +2108,7 @@ void IntrinsicLocationsBuilderX86_64::VisitMemoryPokeByte(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86_64::VisitMemoryPokeByte(HInvoke* invoke) { - GenPoke(invoke->GetLocations(), Primitive::kPrimByte, GetAssembler()); + GenPoke(invoke->GetLocations(), DataType::Type::kInt8, GetAssembler()); } void IntrinsicLocationsBuilderX86_64::VisitMemoryPokeIntNative(HInvoke* invoke) { @@ -2116,7 +2116,7 @@ void IntrinsicLocationsBuilderX86_64::VisitMemoryPokeIntNative(HInvoke* invoke) } void IntrinsicCodeGeneratorX86_64::VisitMemoryPokeIntNative(HInvoke* invoke) { - GenPoke(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); + GenPoke(invoke->GetLocations(), DataType::Type::kInt32, GetAssembler()); } void IntrinsicLocationsBuilderX86_64::VisitMemoryPokeLongNative(HInvoke* invoke) { @@ -2124,7 +2124,7 @@ void IntrinsicLocationsBuilderX86_64::VisitMemoryPokeLongNative(HInvoke* invoke) } void IntrinsicCodeGeneratorX86_64::VisitMemoryPokeLongNative(HInvoke* invoke) { - GenPoke(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); + GenPoke(invoke->GetLocations(), DataType::Type::kInt64, GetAssembler()); } void IntrinsicLocationsBuilderX86_64::VisitMemoryPokeShortNative(HInvoke* invoke) { @@ -2132,7 +2132,7 @@ void IntrinsicLocationsBuilderX86_64::VisitMemoryPokeShortNative(HInvoke* invoke } void IntrinsicCodeGeneratorX86_64::VisitMemoryPokeShortNative(HInvoke* invoke) { - GenPoke(invoke->GetLocations(), Primitive::kPrimShort, GetAssembler()); + GenPoke(invoke->GetLocations(), DataType::Type::kInt16, GetAssembler()); } void IntrinsicLocationsBuilderX86_64::VisitThreadCurrentThread(HInvoke* invoke) { @@ -2149,7 +2149,7 @@ void IntrinsicCodeGeneratorX86_64::VisitThreadCurrentThread(HInvoke* invoke) { } static void GenUnsafeGet(HInvoke* invoke, - Primitive::Type type, + DataType::Type type, bool is_volatile ATTRIBUTE_UNUSED, CodeGeneratorX86_64* codegen) { X86_64Assembler* assembler = down_cast<X86_64Assembler*>(codegen->GetAssembler()); @@ -2162,11 +2162,11 @@ static void GenUnsafeGet(HInvoke* invoke, CpuRegister output = output_loc.AsRegister<CpuRegister>(); switch (type) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: __ movl(output, Address(base, offset, ScaleFactor::TIMES_1, 0)); break; - case Primitive::kPrimNot: { + case DataType::Type::kReference: { if (kEmitCompilerReadBarrier) { if (kUseBakerReadBarrier) { Address src(base, offset, ScaleFactor::TIMES_1, 0); @@ -2184,7 +2184,7 @@ static void GenUnsafeGet(HInvoke* invoke, break; } - case Primitive::kPrimLong: + case DataType::Type::kInt64: __ movq(output, Address(base, offset, ScaleFactor::TIMES_1, 0)); break; @@ -2234,27 +2234,27 @@ void IntrinsicLocationsBuilderX86_64::VisitUnsafeGetObjectVolatile(HInvoke* invo void IntrinsicCodeGeneratorX86_64::VisitUnsafeGet(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafeGetVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimInt, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt32, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafeGetLong(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafeGetLongVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimLong, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kInt64, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafeGetObject(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ false, codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { - GenUnsafeGet(invoke, Primitive::kPrimNot, /* is_volatile */ true, codegen_); + GenUnsafeGet(invoke, DataType::Type::kReference, /* is_volatile */ true, codegen_); } static void CreateIntIntIntIntToVoidPlusTempsLocations(ArenaAllocator* arena, - Primitive::Type type, + DataType::Type type, HInvoke* invoke) { LocationSummary* locations = new (arena) LocationSummary(invoke, LocationSummary::kNoCall, @@ -2263,7 +2263,7 @@ static void CreateIntIntIntIntToVoidPlusTempsLocations(ArenaAllocator* arena, locations->SetInAt(1, Location::RequiresRegister()); locations->SetInAt(2, Location::RequiresRegister()); locations->SetInAt(3, Location::RequiresRegister()); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // Need temp registers for card-marking. locations->AddTemp(Location::RequiresRegister()); // Possibly used for reference poisoning too. locations->AddTemp(Location::RequiresRegister()); @@ -2271,45 +2271,45 @@ static void CreateIntIntIntIntToVoidPlusTempsLocations(ArenaAllocator* arena, } void IntrinsicLocationsBuilderX86_64::VisitUnsafePut(HInvoke* invoke) { - CreateIntIntIntIntToVoidPlusTempsLocations(arena_, Primitive::kPrimInt, invoke); + CreateIntIntIntIntToVoidPlusTempsLocations(arena_, DataType::Type::kInt32, invoke); } void IntrinsicLocationsBuilderX86_64::VisitUnsafePutOrdered(HInvoke* invoke) { - CreateIntIntIntIntToVoidPlusTempsLocations(arena_, Primitive::kPrimInt, invoke); + CreateIntIntIntIntToVoidPlusTempsLocations(arena_, DataType::Type::kInt32, invoke); } void IntrinsicLocationsBuilderX86_64::VisitUnsafePutVolatile(HInvoke* invoke) { - CreateIntIntIntIntToVoidPlusTempsLocations(arena_, Primitive::kPrimInt, invoke); + CreateIntIntIntIntToVoidPlusTempsLocations(arena_, DataType::Type::kInt32, invoke); } void IntrinsicLocationsBuilderX86_64::VisitUnsafePutObject(HInvoke* invoke) { - CreateIntIntIntIntToVoidPlusTempsLocations(arena_, Primitive::kPrimNot, invoke); + CreateIntIntIntIntToVoidPlusTempsLocations(arena_, DataType::Type::kReference, invoke); } void IntrinsicLocationsBuilderX86_64::VisitUnsafePutObjectOrdered(HInvoke* invoke) { - CreateIntIntIntIntToVoidPlusTempsLocations(arena_, Primitive::kPrimNot, invoke); + CreateIntIntIntIntToVoidPlusTempsLocations(arena_, DataType::Type::kReference, invoke); } void IntrinsicLocationsBuilderX86_64::VisitUnsafePutObjectVolatile(HInvoke* invoke) { - CreateIntIntIntIntToVoidPlusTempsLocations(arena_, Primitive::kPrimNot, invoke); + CreateIntIntIntIntToVoidPlusTempsLocations(arena_, DataType::Type::kReference, invoke); } void IntrinsicLocationsBuilderX86_64::VisitUnsafePutLong(HInvoke* invoke) { - CreateIntIntIntIntToVoidPlusTempsLocations(arena_, Primitive::kPrimLong, invoke); + CreateIntIntIntIntToVoidPlusTempsLocations(arena_, DataType::Type::kInt64, invoke); } void IntrinsicLocationsBuilderX86_64::VisitUnsafePutLongOrdered(HInvoke* invoke) { - CreateIntIntIntIntToVoidPlusTempsLocations(arena_, Primitive::kPrimLong, invoke); + CreateIntIntIntIntToVoidPlusTempsLocations(arena_, DataType::Type::kInt64, invoke); } void IntrinsicLocationsBuilderX86_64::VisitUnsafePutLongVolatile(HInvoke* invoke) { - CreateIntIntIntIntToVoidPlusTempsLocations(arena_, Primitive::kPrimLong, invoke); + CreateIntIntIntIntToVoidPlusTempsLocations(arena_, DataType::Type::kInt64, invoke); } // We don't care for ordered: it requires an AnyStore barrier, which is already given by the x86 // memory model. -static void GenUnsafePut(LocationSummary* locations, Primitive::Type type, bool is_volatile, +static void GenUnsafePut(LocationSummary* locations, DataType::Type type, bool is_volatile, CodeGeneratorX86_64* codegen) { X86_64Assembler* assembler = down_cast<X86_64Assembler*>(codegen->GetAssembler()); CpuRegister base = locations->InAt(1).AsRegister<CpuRegister>(); CpuRegister offset = locations->InAt(2).AsRegister<CpuRegister>(); CpuRegister value = locations->InAt(3).AsRegister<CpuRegister>(); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { __ movq(Address(base, offset, ScaleFactor::TIMES_1, 0), value); - } else if (kPoisonHeapReferences && type == Primitive::kPrimNot) { + } else if (kPoisonHeapReferences && type == DataType::Type::kReference) { CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>(); __ movl(temp, value); __ PoisonHeapReference(temp); @@ -2322,7 +2322,7 @@ static void GenUnsafePut(LocationSummary* locations, Primitive::Type type, bool codegen->MemoryFence(); } - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { bool value_can_be_null = true; // TODO: Worth finding out this information? codegen->MarkGCCard(locations->GetTemp(0).AsRegister<CpuRegister>(), locations->GetTemp(1).AsRegister<CpuRegister>(), @@ -2333,35 +2333,38 @@ static void GenUnsafePut(LocationSummary* locations, Primitive::Type type, bool } void IntrinsicCodeGeneratorX86_64::VisitUnsafePut(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimInt, /* is_volatile */ false, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafePutOrdered(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimInt, /* is_volatile */ false, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafePutVolatile(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimInt, /* is_volatile */ true, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafePutObject(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimNot, /* is_volatile */ false, codegen_); + GenUnsafePut( + invoke->GetLocations(), DataType::Type::kReference, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafePutObjectOrdered(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimNot, /* is_volatile */ false, codegen_); + GenUnsafePut( + invoke->GetLocations(), DataType::Type::kReference, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafePutObjectVolatile(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimNot, /* is_volatile */ true, codegen_); + GenUnsafePut( + invoke->GetLocations(), DataType::Type::kReference, /* is_volatile */ true, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafePutLong(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimLong, /* is_volatile */ false, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt64, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafePutLongOrdered(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimLong, /* is_volatile */ false, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt64, /* is_volatile */ false, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafePutLongVolatile(HInvoke* invoke) { - GenUnsafePut(invoke->GetLocations(), Primitive::kPrimLong, /* is_volatile */ true, codegen_); + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt64, /* is_volatile */ true, codegen_); } static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, - Primitive::Type type, + DataType::Type type, HInvoke* invoke) { bool can_call = kEmitCompilerReadBarrier && kUseBakerReadBarrier && @@ -2379,7 +2382,7 @@ static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, locations->SetInAt(4, Location::RequiresRegister()); locations->SetOut(Location::RequiresRegister()); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // Need temporary registers for card-marking, and possibly for // (Baker) read barrier. locations->AddTemp(Location::RequiresRegister()); // Possibly used for reference poisoning too. @@ -2388,11 +2391,11 @@ static void CreateIntIntIntIntIntToInt(ArenaAllocator* arena, } void IntrinsicLocationsBuilderX86_64::VisitUnsafeCASInt(HInvoke* invoke) { - CreateIntIntIntIntIntToInt(arena_, Primitive::kPrimInt, invoke); + CreateIntIntIntIntIntToInt(arena_, DataType::Type::kInt32, invoke); } void IntrinsicLocationsBuilderX86_64::VisitUnsafeCASLong(HInvoke* invoke) { - CreateIntIntIntIntIntToInt(arena_, Primitive::kPrimLong, invoke); + CreateIntIntIntIntIntToInt(arena_, DataType::Type::kInt64, invoke); } void IntrinsicLocationsBuilderX86_64::VisitUnsafeCASObject(HInvoke* invoke) { @@ -2402,10 +2405,10 @@ void IntrinsicLocationsBuilderX86_64::VisitUnsafeCASObject(HInvoke* invoke) { return; } - CreateIntIntIntIntIntToInt(arena_, Primitive::kPrimNot, invoke); + CreateIntIntIntIntIntToInt(arena_, DataType::Type::kReference, invoke); } -static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86_64* codegen) { +static void GenCAS(DataType::Type type, HInvoke* invoke, CodeGeneratorX86_64* codegen) { X86_64Assembler* assembler = down_cast<X86_64Assembler*>(codegen->GetAssembler()); LocationSummary* locations = invoke->GetLocations(); @@ -2418,7 +2421,7 @@ static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86_64* c Location out_loc = locations->Out(); CpuRegister out = out_loc.AsRegister<CpuRegister>(); - if (type == Primitive::kPrimNot) { + if (type == DataType::Type::kReference) { // The only read barrier implementation supporting the // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); @@ -2500,9 +2503,9 @@ static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86_64* c __ UnpoisonHeapReference(expected); } } else { - if (type == Primitive::kPrimInt) { + if (type == DataType::Type::kInt32) { __ LockCmpxchgl(Address(base, offset, TIMES_1, 0), value); - } else if (type == Primitive::kPrimLong) { + } else if (type == DataType::Type::kInt64) { __ LockCmpxchgq(Address(base, offset, TIMES_1, 0), value); } else { LOG(FATAL) << "Unexpected CAS type " << type; @@ -2518,11 +2521,11 @@ static void GenCAS(Primitive::Type type, HInvoke* invoke, CodeGeneratorX86_64* c } void IntrinsicCodeGeneratorX86_64::VisitUnsafeCASInt(HInvoke* invoke) { - GenCAS(Primitive::kPrimInt, invoke, codegen_); + GenCAS(DataType::Type::kInt32, invoke, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafeCASLong(HInvoke* invoke) { - GenCAS(Primitive::kPrimLong, invoke, codegen_); + GenCAS(DataType::Type::kInt64, invoke, codegen_); } void IntrinsicCodeGeneratorX86_64::VisitUnsafeCASObject(HInvoke* invoke) { @@ -2530,7 +2533,7 @@ void IntrinsicCodeGeneratorX86_64::VisitUnsafeCASObject(HInvoke* invoke) { // UnsafeCASObject intrinsic is the Baker-style read barriers. DCHECK(!kEmitCompilerReadBarrier || kUseBakerReadBarrier); - GenCAS(Primitive::kPrimNot, invoke, codegen_); + GenCAS(DataType::Type::kReference, invoke, codegen_); } void IntrinsicLocationsBuilderX86_64::VisitIntegerReverse(HInvoke* invoke) { diff --git a/compiler/optimizing/licm_test.cc b/compiler/optimizing/licm_test.cc index 8967d7cef2..0617e60cfe 100644 --- a/compiler/optimizing/licm_test.cc +++ b/compiler/optimizing/licm_test.cc @@ -78,7 +78,7 @@ class LICMTest : public CommonCompilerTest { parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimNot); + DataType::Type::kReference); entry_->AddInstruction(parameter_); int_constant_ = graph_->GetIntConstant(42); float_constant_ = graph_->GetFloatConstant(42.0f); @@ -125,7 +125,7 @@ TEST_F(LICMTest, FieldHoisting) { // Populate the loop with instructions: set/get field with different types. HInstruction* get_field = new (&allocator_) HInstanceFieldGet(parameter_, nullptr, - Primitive::kPrimLong, + DataType::Type::kInt64, MemberOffset(10), false, kUnknownFieldIndex, @@ -134,7 +134,7 @@ TEST_F(LICMTest, FieldHoisting) { 0); loop_body_->InsertInstructionBefore(get_field, loop_body_->GetLastInstruction()); HInstruction* set_field = new (&allocator_) HInstanceFieldSet( - parameter_, int_constant_, nullptr, Primitive::kPrimInt, MemberOffset(20), + parameter_, int_constant_, nullptr, DataType::Type::kInt32, MemberOffset(20), false, kUnknownFieldIndex, kUnknownClassDefIndex, graph_->GetDexFile(), 0); loop_body_->InsertInstructionBefore(set_field, loop_body_->GetLastInstruction()); @@ -152,7 +152,7 @@ TEST_F(LICMTest, NoFieldHoisting) { ScopedNullHandle<mirror::DexCache> dex_cache; HInstruction* get_field = new (&allocator_) HInstanceFieldGet(parameter_, nullptr, - Primitive::kPrimLong, + DataType::Type::kInt64, MemberOffset(10), false, kUnknownFieldIndex, @@ -163,7 +163,7 @@ TEST_F(LICMTest, NoFieldHoisting) { HInstruction* set_field = new (&allocator_) HInstanceFieldSet(parameter_, get_field, nullptr, - Primitive::kPrimLong, + DataType::Type::kInt64, MemberOffset(10), false, kUnknownFieldIndex, @@ -184,10 +184,10 @@ TEST_F(LICMTest, ArrayHoisting) { // Populate the loop with instructions: set/get array with different types. HInstruction* get_array = new (&allocator_) HArrayGet( - parameter_, int_constant_, Primitive::kPrimInt, 0); + parameter_, int_constant_, DataType::Type::kInt32, 0); loop_body_->InsertInstructionBefore(get_array, loop_body_->GetLastInstruction()); HInstruction* set_array = new (&allocator_) HArraySet( - parameter_, int_constant_, float_constant_, Primitive::kPrimFloat, 0); + parameter_, int_constant_, float_constant_, DataType::Type::kFloat32, 0); loop_body_->InsertInstructionBefore(set_array, loop_body_->GetLastInstruction()); EXPECT_EQ(get_array->GetBlock(), loop_body_); @@ -202,10 +202,10 @@ TEST_F(LICMTest, NoArrayHoisting) { // Populate the loop with instructions: set/get array with same types. HInstruction* get_array = new (&allocator_) HArrayGet( - parameter_, int_constant_, Primitive::kPrimFloat, 0); + parameter_, int_constant_, DataType::Type::kFloat32, 0); loop_body_->InsertInstructionBefore(get_array, loop_body_->GetLastInstruction()); HInstruction* set_array = new (&allocator_) HArraySet( - parameter_, get_array, float_constant_, Primitive::kPrimFloat, 0); + parameter_, get_array, float_constant_, DataType::Type::kFloat32, 0); loop_body_->InsertInstructionBefore(set_array, loop_body_->GetLastInstruction()); EXPECT_EQ(get_array->GetBlock(), loop_body_); diff --git a/compiler/optimizing/load_store_analysis.h b/compiler/optimizing/load_store_analysis.h index 02bc254729..d46b904c9e 100644 --- a/compiler/optimizing/load_store_analysis.h +++ b/compiler/optimizing/load_store_analysis.h @@ -369,7 +369,7 @@ class HeapLocationCollector : public HGraphVisitor { } void CreateReferenceInfoForReferenceType(HInstruction* instruction) { - if (instruction->GetType() != Primitive::kPrimNot) { + if (instruction->GetType() != DataType::Type::kReference) { return; } DCHECK(FindReferenceInfoOf(instruction) == nullptr); diff --git a/compiler/optimizing/load_store_analysis_test.cc b/compiler/optimizing/load_store_analysis_test.cc index 81344b52f6..0df2f27e82 100644 --- a/compiler/optimizing/load_store_analysis_test.cc +++ b/compiler/optimizing/load_store_analysis_test.cc @@ -49,16 +49,17 @@ TEST_F(LoadStoreAnalysisTest, ArrayHeapLocations) { // array_set1 ArraySet [array, c1, c3] // array_set2 ArraySet [array, index, c3] HInstruction* array = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); HInstruction* index = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(1), 1, Primitive::kPrimInt); + graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kInt32); HInstruction* c1 = graph_->GetIntConstant(1); HInstruction* c2 = graph_->GetIntConstant(2); HInstruction* c3 = graph_->GetIntConstant(3); - HInstruction* array_get1 = new (&allocator_) HArrayGet(array, c1, Primitive::kPrimInt, 0); - HInstruction* array_get2 = new (&allocator_) HArrayGet(array, c2, Primitive::kPrimInt, 0); - HInstruction* array_set1 = new (&allocator_) HArraySet(array, c1, c3, Primitive::kPrimInt, 0); - HInstruction* array_set2 = new (&allocator_) HArraySet(array, index, c3, Primitive::kPrimInt, 0); + HInstruction* array_get1 = new (&allocator_) HArrayGet(array, c1, DataType::Type::kInt32, 0); + HInstruction* array_get2 = new (&allocator_) HArrayGet(array, c2, DataType::Type::kInt32, 0); + HInstruction* array_set1 = new (&allocator_) HArraySet(array, c1, c3, DataType::Type::kInt32, 0); + HInstruction* array_set2 = + new (&allocator_) HArraySet(array, index, c3, DataType::Type::kInt32, 0); entry->AddInstruction(array); entry->AddInstruction(index); entry->AddInstruction(array_get1); @@ -121,11 +122,11 @@ TEST_F(LoadStoreAnalysisTest, FieldHeapLocations) { HInstruction* object = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimNot); + DataType::Type::kReference); HInstanceFieldSet* set_field10 = new (&allocator_) HInstanceFieldSet(object, c1, nullptr, - Primitive::kPrimInt, + DataType::Type::kInt32, MemberOffset(10), false, kUnknownFieldIndex, @@ -134,7 +135,7 @@ TEST_F(LoadStoreAnalysisTest, FieldHeapLocations) { 0); HInstanceFieldGet* get_field10 = new (&allocator_) HInstanceFieldGet(object, nullptr, - Primitive::kPrimInt, + DataType::Type::kInt32, MemberOffset(10), false, kUnknownFieldIndex, @@ -143,7 +144,7 @@ TEST_F(LoadStoreAnalysisTest, FieldHeapLocations) { 0); HInstanceFieldGet* get_field20 = new (&allocator_) HInstanceFieldGet(object, nullptr, - Primitive::kPrimInt, + DataType::Type::kInt32, MemberOffset(20), false, kUnknownFieldIndex, @@ -191,26 +192,28 @@ TEST_F(LoadStoreAnalysisTest, ArrayIndexAliasingTest) { graph_->BuildDominatorTree(); HInstruction* array = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); HInstruction* index = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(1), 1, Primitive::kPrimInt); + graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kInt32); HInstruction* c0 = graph_->GetIntConstant(0); HInstruction* c1 = graph_->GetIntConstant(1); HInstruction* c_neg1 = graph_->GetIntConstant(-1); - HInstruction* add0 = new (&allocator_) HAdd(Primitive::kPrimInt, index, c0); - HInstruction* add1 = new (&allocator_) HAdd(Primitive::kPrimInt, index, c1); - HInstruction* sub0 = new (&allocator_) HSub(Primitive::kPrimInt, index, c0); - HInstruction* sub1 = new (&allocator_) HSub(Primitive::kPrimInt, index, c1); - HInstruction* sub_neg1 = new (&allocator_) HSub(Primitive::kPrimInt, index, c_neg1); - HInstruction* rev_sub1 = new (&allocator_) HSub(Primitive::kPrimInt, c1, index); - HInstruction* arr_set1 = new (&allocator_) HArraySet(array, c0, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set2 = new (&allocator_) HArraySet(array, c1, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set3 = new (&allocator_) HArraySet(array, add0, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set4 = new (&allocator_) HArraySet(array, add1, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set5 = new (&allocator_) HArraySet(array, sub0, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set6 = new (&allocator_) HArraySet(array, sub1, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set7 = new (&allocator_) HArraySet(array, rev_sub1, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set8 = new (&allocator_) HArraySet(array, sub_neg1, c0, Primitive::kPrimInt, 0); + HInstruction* add0 = new (&allocator_) HAdd(DataType::Type::kInt32, index, c0); + HInstruction* add1 = new (&allocator_) HAdd(DataType::Type::kInt32, index, c1); + HInstruction* sub0 = new (&allocator_) HSub(DataType::Type::kInt32, index, c0); + HInstruction* sub1 = new (&allocator_) HSub(DataType::Type::kInt32, index, c1); + HInstruction* sub_neg1 = new (&allocator_) HSub(DataType::Type::kInt32, index, c_neg1); + HInstruction* rev_sub1 = new (&allocator_) HSub(DataType::Type::kInt32, c1, index); + HInstruction* arr_set1 = new (&allocator_) HArraySet(array, c0, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set2 = new (&allocator_) HArraySet(array, c1, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set3 = new (&allocator_) HArraySet(array, add0, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set4 = new (&allocator_) HArraySet(array, add1, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set5 = new (&allocator_) HArraySet(array, sub0, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set6 = new (&allocator_) HArraySet(array, sub1, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set7 = + new (&allocator_) HArraySet(array, rev_sub1, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set8 = + new (&allocator_) HArraySet(array, sub_neg1, c0, DataType::Type::kInt32, 0); entry->AddInstruction(array); entry->AddInstruction(index); @@ -275,9 +278,9 @@ TEST_F(LoadStoreAnalysisTest, ArrayIndexCalculationOverflowTest) { graph_->BuildDominatorTree(); HInstruction* array = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); HInstruction* index = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(1), 1, Primitive::kPrimInt); + graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kInt32); HInstruction* c0 = graph_->GetIntConstant(0); HInstruction* c_0x80000000 = graph_->GetIntConstant(0x80000000); @@ -287,34 +290,41 @@ TEST_F(LoadStoreAnalysisTest, ArrayIndexCalculationOverflowTest) { HInstruction* c_0x80000001 = graph_->GetIntConstant(0x80000001); // `index+0x80000000` and `index-0x80000000` array indices MAY alias. - HInstruction* add_0x80000000 = new (&allocator_) HAdd(Primitive::kPrimInt, index, c_0x80000000); - HInstruction* sub_0x80000000 = new (&allocator_) HSub(Primitive::kPrimInt, index, c_0x80000000); + HInstruction* add_0x80000000 = new (&allocator_) HAdd( + DataType::Type::kInt32, index, c_0x80000000); + HInstruction* sub_0x80000000 = new (&allocator_) HSub( + DataType::Type::kInt32, index, c_0x80000000); HInstruction* arr_set_1 = new (&allocator_) HArraySet( - array, add_0x80000000, c0, Primitive::kPrimInt, 0); + array, add_0x80000000, c0, DataType::Type::kInt32, 0); HInstruction* arr_set_2 = new (&allocator_) HArraySet( - array, sub_0x80000000, c0, Primitive::kPrimInt, 0); + array, sub_0x80000000, c0, DataType::Type::kInt32, 0); // `index+0x10` and `index-0xFFFFFFF0` array indices MAY alias. - HInstruction* add_0x10 = new (&allocator_) HAdd(Primitive::kPrimInt, index, c_0x10); - HInstruction* sub_0xFFFFFFF0 = new (&allocator_) HSub(Primitive::kPrimInt, index, c_0xFFFFFFF0); + HInstruction* add_0x10 = new (&allocator_) HAdd(DataType::Type::kInt32, index, c_0x10); + HInstruction* sub_0xFFFFFFF0 = new (&allocator_) HSub( + DataType::Type::kInt32, index, c_0xFFFFFFF0); HInstruction* arr_set_3 = new (&allocator_) HArraySet( - array, add_0x10, c0, Primitive::kPrimInt, 0); + array, add_0x10, c0, DataType::Type::kInt32, 0); HInstruction* arr_set_4 = new (&allocator_) HArraySet( - array, sub_0xFFFFFFF0, c0, Primitive::kPrimInt, 0); + array, sub_0xFFFFFFF0, c0, DataType::Type::kInt32, 0); // `index+0x7FFFFFFF` and `index-0x80000001` array indices MAY alias. - HInstruction* add_0x7FFFFFFF = new (&allocator_) HAdd(Primitive::kPrimInt, index, c_0x7FFFFFFF); - HInstruction* sub_0x80000001 = new (&allocator_) HSub(Primitive::kPrimInt, index, c_0x80000001); + HInstruction* add_0x7FFFFFFF = new (&allocator_) HAdd( + DataType::Type::kInt32, index, c_0x7FFFFFFF); + HInstruction* sub_0x80000001 = new (&allocator_) HSub( + DataType::Type::kInt32, index, c_0x80000001); HInstruction* arr_set_5 = new (&allocator_) HArraySet( - array, add_0x7FFFFFFF, c0, Primitive::kPrimInt, 0); + array, add_0x7FFFFFFF, c0, DataType::Type::kInt32, 0); HInstruction* arr_set_6 = new (&allocator_) HArraySet( - array, sub_0x80000001, c0, Primitive::kPrimInt, 0); + array, sub_0x80000001, c0, DataType::Type::kInt32, 0); // `index+0` and `index-0` array indices MAY alias. - HInstruction* add_0 = new (&allocator_) HAdd(Primitive::kPrimInt, index, c0); - HInstruction* sub_0 = new (&allocator_) HSub(Primitive::kPrimInt, index, c0); - HInstruction* arr_set_7 = new (&allocator_) HArraySet(array, add_0, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set_8 = new (&allocator_) HArraySet(array, sub_0, c0, Primitive::kPrimInt, 0); + HInstruction* add_0 = new (&allocator_) HAdd(DataType::Type::kInt32, index, c0); + HInstruction* sub_0 = new (&allocator_) HSub(DataType::Type::kInt32, index, c0); + HInstruction* arr_set_7 = new (&allocator_) HArraySet( + array, add_0, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set_8 = new (&allocator_) HArraySet( + array, sub_0, c0, DataType::Type::kInt32, 0); entry->AddInstruction(array); entry->AddInstruction(index); diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc index 8a9acf108c..bd14f2b142 100644 --- a/compiler/optimizing/load_store_elimination.cc +++ b/compiler/optimizing/load_store_elimination.cc @@ -271,21 +271,21 @@ class LSEVisitor : public HGraphVisitor { } } - HInstruction* GetDefaultValue(Primitive::Type type) { + HInstruction* GetDefaultValue(DataType::Type type) { switch (type) { - case Primitive::kPrimNot: + case DataType::Type::kReference: return GetGraph()->GetNullConstant(); - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: return GetGraph()->GetIntConstant(0); - case Primitive::kPrimLong: + case DataType::Type::kInt64: return GetGraph()->GetLongConstant(0); - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: return GetGraph()->GetFloatConstant(0); - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: return GetGraph()->GetDoubleConstant(0); default: UNREACHABLE(); @@ -328,8 +328,7 @@ class LSEVisitor : public HGraphVisitor { // This acts like GVN but with better aliasing analysis. heap_values[idx] = instruction; } else { - if (Primitive::PrimitiveKind(heap_value->GetType()) - != Primitive::PrimitiveKind(instruction->GetType())) { + if (DataType::Kind(heap_value->GetType()) != DataType::Kind(instruction->GetType())) { // The only situation where the same heap location has different type is when // we do an array get on an instruction that originates from the null constant // (the null could be behind a field access, an array access, a null check or diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc index baa045390b..7e37018229 100644 --- a/compiler/optimizing/loop_optimization.cc +++ b/compiler/optimizing/loop_optimization.cc @@ -71,31 +71,44 @@ static bool IsEarlyExit(HLoopInformation* loop_info) { return false; } -// Detect a sign extension from the given type. Returns the promoted operand on success. +// Forward declaration. +static bool IsZeroExtensionAndGet(HInstruction* instruction, + DataType::Type type, + /*out*/ HInstruction** operand, + bool to64 = false); + +// Detect a sign extension in instruction from the given type. The to64 parameter +// denotes if result is long, and thus sign extension from int can be included. +// Returns the promoted operand on success. static bool IsSignExtensionAndGet(HInstruction* instruction, - Primitive::Type type, - /*out*/ HInstruction** operand) { + DataType::Type type, + /*out*/ HInstruction** operand, + bool to64 = false) { // Accept any already wider constant that would be handled properly by sign // extension when represented in the *width* of the given narrower data type // (the fact that char normally zero extends does not matter here). int64_t value = 0; if (IsInt64AndGet(instruction, /*out*/ &value)) { switch (type) { - case Primitive::kPrimByte: - if (std::numeric_limits<int8_t>::min() <= value && - std::numeric_limits<int8_t>::max() >= value) { + case DataType::Type::kInt8: + if (IsInt<8>(value)) { *operand = instruction; return true; } return false; - case Primitive::kPrimChar: - case Primitive::kPrimShort: - if (std::numeric_limits<int16_t>::min() <= value && - std::numeric_limits<int16_t>::max() <= value) { + case DataType::Type::kUint16: + case DataType::Type::kInt16: + if (IsInt<16>(value)) { *operand = instruction; return true; } return false; + case DataType::Type::kInt32: + if (IsInt<32>(value)) { + *operand = instruction; + return to64; + } + return false; default: return false; } @@ -106,44 +119,66 @@ static bool IsSignExtensionAndGet(HInstruction* instruction, instruction->IsStaticFieldGet() || instruction->IsInstanceFieldGet())) { switch (type) { - case Primitive::kPrimByte: - case Primitive::kPrimShort: + case DataType::Type::kInt8: + case DataType::Type::kInt16: *operand = instruction; return true; + case DataType::Type::kInt32: + *operand = instruction; + return to64; + default: + return false; + } + } + // Explicit type conversions. + if (instruction->IsTypeConversion()) { + DataType::Type from = instruction->InputAt(0)->GetType(); + switch (instruction->GetType()) { + case DataType::Type::kInt64: + return IsSignExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, /*to64*/ true); + case DataType::Type::kInt16: + return type == DataType::Type::kUint16 && + from == DataType::Type::kUint16 && + IsZeroExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, to64); default: return false; } } - // TODO: perhaps explicit conversions later too? - // (this may return something different from instruction) return false; } -// Detect a zero extension from the given type. Returns the promoted operand on success. +// Detect a zero extension in instruction from the given type. The to64 parameter +// denotes if result is long, and thus zero extension from int can be included. +// Returns the promoted operand on success. static bool IsZeroExtensionAndGet(HInstruction* instruction, - Primitive::Type type, - /*out*/ HInstruction** operand) { + DataType::Type type, + /*out*/ HInstruction** operand, + bool to64) { // Accept any already wider constant that would be handled properly by zero // extension when represented in the *width* of the given narrower data type - // (the fact that byte/short normally sign extend does not matter here). + // (the fact that byte/short/int normally sign extend does not matter here). int64_t value = 0; if (IsInt64AndGet(instruction, /*out*/ &value)) { switch (type) { - case Primitive::kPrimByte: - if (std::numeric_limits<uint8_t>::min() <= value && - std::numeric_limits<uint8_t>::max() >= value) { + case DataType::Type::kInt8: + if (IsUint<8>(value)) { *operand = instruction; return true; } return false; - case Primitive::kPrimChar: - case Primitive::kPrimShort: - if (std::numeric_limits<uint16_t>::min() <= value && - std::numeric_limits<uint16_t>::max() <= value) { + case DataType::Type::kUint16: + case DataType::Type::kInt16: + if (IsUint<16>(value)) { *operand = instruction; return true; } return false; + case DataType::Type::kInt32: + if (IsUint<32>(value)) { + *operand = instruction; + return to64; + } + return false; default: return false; } @@ -153,7 +188,7 @@ static bool IsZeroExtensionAndGet(HInstruction* instruction, if (instruction->GetType() == type && (instruction->IsArrayGet() || instruction->IsStaticFieldGet() || instruction->IsInstanceFieldGet())) { - if (type == Primitive::kPrimChar) { + if (type == DataType::Type::kUint16) { *operand = instruction; return true; } @@ -170,14 +205,31 @@ static bool IsZeroExtensionAndGet(HInstruction* instruction, (IsInt64AndGet(b, /*out*/ &mask) && (IsSignExtensionAndGet(a, type, /*out*/ operand) || IsZeroExtensionAndGet(a, type, /*out*/ operand)))) { switch ((*operand)->GetType()) { - case Primitive::kPrimByte: return mask == std::numeric_limits<uint8_t>::max(); - case Primitive::kPrimChar: - case Primitive::kPrimShort: return mask == std::numeric_limits<uint16_t>::max(); + case DataType::Type::kInt8: + return mask == std::numeric_limits<uint8_t>::max(); + case DataType::Type::kUint16: + case DataType::Type::kInt16: + return mask == std::numeric_limits<uint16_t>::max(); + case DataType::Type::kInt32: + return mask == std::numeric_limits<uint32_t>::max() && to64; default: return false; } } } - // TODO: perhaps explicit conversions later too? + // Explicit type conversions. + if (instruction->IsTypeConversion()) { + DataType::Type from = instruction->InputAt(0)->GetType(); + switch (instruction->GetType()) { + case DataType::Type::kInt64: + return IsZeroExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, /*to64*/ true); + case DataType::Type::kUint16: + return type == DataType::Type::kInt16 && + from == DataType::Type::kInt16 && + IsSignExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, to64); + default: + return false; + } + } return false; } @@ -185,7 +237,7 @@ static bool IsZeroExtensionAndGet(HInstruction* instruction, // Returns true on success and sets is_unsigned accordingly. static bool IsNarrowerOperands(HInstruction* a, HInstruction* b, - Primitive::Type type, + DataType::Type type, /*out*/ HInstruction** r, /*out*/ HInstruction** s, /*out*/ bool* is_unsigned) { @@ -201,7 +253,7 @@ static bool IsNarrowerOperands(HInstruction* a, // As above, single operand. static bool IsNarrowerOperand(HInstruction* a, - Primitive::Type type, + DataType::Type type, /*out*/ HInstruction** r, /*out*/ bool* is_unsigned) { if (IsSignExtensionAndGet(a, type, r)) { @@ -214,6 +266,55 @@ static bool IsNarrowerOperand(HInstruction* a, return false; } +// Compute relative vector length based on type difference. +static size_t GetOtherVL(DataType::Type other_type, DataType::Type vector_type, size_t vl) { + switch (other_type) { + case DataType::Type::kBool: + case DataType::Type::kInt8: + switch (vector_type) { + case DataType::Type::kBool: + case DataType::Type::kInt8: return vl; + default: break; + } + return vl; + case DataType::Type::kUint16: + case DataType::Type::kInt16: + switch (vector_type) { + case DataType::Type::kBool: + case DataType::Type::kInt8: return vl >> 1; + case DataType::Type::kUint16: + case DataType::Type::kInt16: return vl; + default: break; + } + break; + case DataType::Type::kInt32: + switch (vector_type) { + case DataType::Type::kBool: + case DataType::Type::kInt8: return vl >> 2; + case DataType::Type::kUint16: + case DataType::Type::kInt16: return vl >> 1; + case DataType::Type::kInt32: return vl; + default: break; + } + break; + case DataType::Type::kInt64: + switch (vector_type) { + case DataType::Type::kBool: + case DataType::Type::kInt8: return vl >> 3; + case DataType::Type::kUint16: + case DataType::Type::kInt16: return vl >> 2; + case DataType::Type::kInt32: return vl >> 1; + case DataType::Type::kInt64: return vl; + default: break; + } + break; + default: + break; + } + LOG(FATAL) << "Unsupported idiom conversion"; + UNREACHABLE(); +} + // Detect up to two instructions a and b, and an acccumulated constant c. static bool IsAddConstHelper(HInstruction* instruction, /*out*/ HInstruction** a, @@ -260,16 +361,16 @@ static bool IsAddConst(HInstruction* instruction, } // Detect reductions of the following forms, -// under assumption phi has only *one* use: // x = x_phi + .. // x = x_phi - .. // x = max(x_phi, ..) // x = min(x_phi, ..) static bool HasReductionFormat(HInstruction* reduction, HInstruction* phi) { if (reduction->IsAdd()) { - return reduction->InputAt(0) == phi || reduction->InputAt(1) == phi; + return (reduction->InputAt(0) == phi && reduction->InputAt(1) != phi) || + (reduction->InputAt(0) != phi && reduction->InputAt(1) == phi); } else if (reduction->IsSub()) { - return reduction->InputAt(0) == phi; + return (reduction->InputAt(0) == phi && reduction->InputAt(1) != phi); } else if (reduction->IsInvokeStaticOrDirect()) { switch (reduction->AsInvokeStaticOrDirect()->GetIntrinsic()) { case Intrinsics::kMathMinIntInt: @@ -280,7 +381,8 @@ static bool HasReductionFormat(HInstruction* reduction, HInstruction* phi) { case Intrinsics::kMathMaxLongLong: case Intrinsics::kMathMaxFloatFloat: case Intrinsics::kMathMaxDoubleDouble: - return reduction->InputAt(0) == phi || reduction->InputAt(1) == phi; + return (reduction->InputAt(0) == phi && reduction->InputAt(1) != phi) || + (reduction->InputAt(0) != phi && reduction->InputAt(1) == phi); default: return false; } @@ -288,9 +390,9 @@ static bool HasReductionFormat(HInstruction* reduction, HInstruction* phi) { return false; } -// Translates operation to reduction kind. -static HVecReduce::ReductionKind GetReductionKind(HInstruction* reduction) { - if (reduction->IsVecAdd() || reduction->IsVecSub()) { +// Translates vector operation to reduction kind. +static HVecReduce::ReductionKind GetReductionKind(HVecOperation* reduction) { + if (reduction->IsVecAdd() || reduction->IsVecSub() || reduction->IsVecSADAccumulate()) { return HVecReduce::kSum; } else if (reduction->IsVecMin()) { return HVecReduce::kMin; @@ -720,7 +822,6 @@ void HLoopOptimization::Vectorize(LoopNode* node, HBasicBlock* block, HBasicBlock* exit, int64_t trip_count) { - Primitive::Type induc_type = Primitive::kPrimInt; HBasicBlock* header = node->loop_info->GetHeader(); HBasicBlock* preheader = node->loop_info->GetPreHeader(); @@ -739,6 +840,11 @@ void HLoopOptimization::Vectorize(LoopNode* node, vector_header_ = header; vector_body_ = block; + // Loop induction type. + DataType::Type induc_type = main_phi->GetType(); + DCHECK(induc_type == DataType::Type::kInt32 || induc_type == DataType::Type::kInt64) + << induc_type; + // Generate dynamic loop peeling trip count, if needed, under the assumption // that the Android runtime guarantees at least "component size" alignment: // ptc = (ALIGN - (&a[initial] % ALIGN)) / type-size @@ -767,10 +873,10 @@ void HLoopOptimization::Vectorize(LoopNode* node, HInstruction* rem = Insert( preheader, new (global_allocator_) HAnd(induc_type, diff, - graph_->GetIntConstant(chunk - 1))); + graph_->GetConstant(induc_type, chunk - 1))); vtc = Insert(preheader, new (global_allocator_) HSub(induc_type, stc, rem)); } - vector_index_ = graph_->GetIntConstant(0); + vector_index_ = graph_->GetConstant(induc_type, 0); // Generate runtime disambiguation test: // vtc = a != b ? vtc : 0; @@ -779,7 +885,8 @@ void HLoopOptimization::Vectorize(LoopNode* node, preheader, new (global_allocator_) HNotEqual(vector_runtime_test_a_, vector_runtime_test_b_)); vtc = Insert(preheader, - new (global_allocator_) HSelect(rt, vtc, graph_->GetIntConstant(0), kNoDexPc)); + new (global_allocator_) + HSelect(rt, vtc, graph_->GetConstant(induc_type, 0), kNoDexPc)); needs_cleanup = true; } @@ -793,7 +900,7 @@ void HLoopOptimization::Vectorize(LoopNode* node, graph_->TransformLoopForVectorization(vector_header_, vector_body_, exit), vector_index_, ptc, - graph_->GetIntConstant(1), + graph_->GetConstant(induc_type, 1), kNoUnrollingFactor); } @@ -806,7 +913,7 @@ void HLoopOptimization::Vectorize(LoopNode* node, graph_->TransformLoopForVectorization(vector_header_, vector_body_, exit), vector_index_, vtc, - graph_->GetIntConstant(vector_length_), // increment per unroll + graph_->GetConstant(induc_type, vector_length_), // increment per unroll unroll); HLoopInformation* vloop = vector_header_->GetLoopInformation(); @@ -820,14 +927,20 @@ void HLoopOptimization::Vectorize(LoopNode* node, graph_->TransformLoopForVectorization(vector_header_, vector_body_, exit), vector_index_, stc, - graph_->GetIntConstant(1), + graph_->GetConstant(induc_type, 1), kNoUnrollingFactor); } // Link reductions to their final uses. for (auto i = reductions_->begin(); i != reductions_->end(); ++i) { if (i->first->IsPhi()) { - i->first->ReplaceWith(ReduceAndExtractIfNeeded(i->second)); + HInstruction* phi = i->first; + HInstruction* repl = ReduceAndExtractIfNeeded(i->second); + // Deal with regular uses. + for (const HUseListNode<HInstruction*>& use : phi->GetUses()) { + induction_range_.Replace(use.GetUser(), phi, repl); // update induction use + } + phi->ReplaceWith(repl); } } @@ -853,7 +966,7 @@ void HLoopOptimization::GenerateNewLoop(LoopNode* node, HInstruction* step, uint32_t unroll) { DCHECK(unroll == 1 || vector_mode_ == kVector); - Primitive::Type induc_type = Primitive::kPrimInt; + DataType::Type induc_type = lo->GetType(); // Prepare new loop. vector_preheader_ = new_preheader, vector_header_ = vector_preheader_->GetSingleSuccessor(); @@ -917,7 +1030,7 @@ bool HLoopOptimization::VectorizeDef(LoopNode* node, // (4) vectorizable right-hand-side value. uint64_t restrictions = kNone; if (instruction->IsArraySet()) { - Primitive::Type type = instruction->AsArraySet()->GetComponentType(); + DataType::Type type = instruction->AsArraySet()->GetComponentType(); HInstruction* base = instruction->InputAt(0); HInstruction* index = instruction->InputAt(1); HInstruction* value = instruction->InputAt(2); @@ -941,9 +1054,11 @@ bool HLoopOptimization::VectorizeDef(LoopNode* node, // (2) vectorizable right-hand-side value. auto redit = reductions_->find(instruction); if (redit != reductions_->end()) { - Primitive::Type type = instruction->GetType(); - if (TrySetVectorType(type, &restrictions) && - VectorizeUse(node, instruction, generate_code, type, restrictions)) { + DataType::Type type = instruction->GetType(); + // Recognize SAD idiom or direct reduction. + if (VectorizeSADIdiom(node, instruction, generate_code, type, restrictions) || + (TrySetVectorType(type, &restrictions) && + VectorizeUse(node, instruction, generate_code, type, restrictions))) { if (generate_code) { HInstruction* new_red = vector_map_->Get(instruction); vector_permanent_map_->Put(new_red, vector_map_->Get(redit->second)); @@ -966,7 +1081,7 @@ bool HLoopOptimization::VectorizeDef(LoopNode* node, bool HLoopOptimization::VectorizeUse(LoopNode* node, HInstruction* instruction, bool generate_code, - Primitive::Type type, + DataType::Type type, uint64_t restrictions) { // Accept anything for which code has already been generated. if (generate_code) { @@ -1027,16 +1142,22 @@ bool HLoopOptimization::VectorizeUse(LoopNode* node, // Accept particular type conversions. HTypeConversion* conversion = instruction->AsTypeConversion(); HInstruction* opa = conversion->InputAt(0); - Primitive::Type from = conversion->GetInputType(); - Primitive::Type to = conversion->GetResultType(); - if ((to == Primitive::kPrimByte || - to == Primitive::kPrimChar || - to == Primitive::kPrimShort) && from == Primitive::kPrimInt) { - // Accept a "narrowing" type conversion from a "wider" computation for - // (1) conversion into final required type, - // (2) vectorizable operand, - // (3) "wider" operations cannot bring in higher order bits. - if (to == type && VectorizeUse(node, opa, generate_code, type, restrictions | kNoHiBits)) { + DataType::Type from = conversion->GetInputType(); + DataType::Type to = conversion->GetResultType(); + if (DataType::IsIntegralType(from) && DataType::IsIntegralType(to)) { + size_t size_vec = DataType::Size(type); + size_t size_from = DataType::Size(from); + size_t size_to = DataType::Size(to); + // Accept an integral conversion + // (1a) narrowing into vector type, "wider" operations cannot bring in higher order bits, or + // (1b) widening from at least vector type, and + // (2) vectorizable operand. + if ((size_to < size_from && + size_to == size_vec && + VectorizeUse(node, opa, generate_code, type, restrictions | kNoHiBits)) || + (size_to >= size_from && + size_from >= size_vec && + VectorizeUse(node, opa, generate_code, type, restrictions))) { if (generate_code) { if (vector_mode_ == kVector) { vector_map_->Put(instruction, vector_map_->Get(opa)); // operand pass-through @@ -1046,7 +1167,7 @@ bool HLoopOptimization::VectorizeUse(LoopNode* node, } return true; } - } else if (to == Primitive::kPrimFloat && from == Primitive::kPrimInt) { + } else if (to == DataType::Type::kFloat32 && from == DataType::Type::kInt32) { DCHECK_EQ(to, type); // Accept int to float conversion for // (1) supported int, @@ -1088,7 +1209,7 @@ bool HLoopOptimization::VectorizeUse(LoopNode* node, return true; } } else if (instruction->IsShl() || instruction->IsShr() || instruction->IsUShr()) { - // Recognize vectorization idioms. + // Recognize halving add idiom. if (VectorizeHalvingAddIdiom(node, instruction, generate_code, type, restrictions)) { return true; } @@ -1121,7 +1242,7 @@ bool HLoopOptimization::VectorizeUse(LoopNode* node, if (VectorizeUse(node, r, generate_code, type, restrictions) && IsInt64AndGet(opb, /*out*/ &distance)) { // Restrict shift distance to packed data type width. - int64_t max_distance = Primitive::ComponentSize(type) * 8; + int64_t max_distance = DataType::Size(type) * 8; if (0 <= distance && distance < max_distance) { if (generate_code) { GenerateVecOp(instruction, vector_map_->Get(r), opb, type); @@ -1181,7 +1302,8 @@ bool HLoopOptimization::VectorizeUse(LoopNode* node, return false; // reject, unless all operands are same-extension narrower } // Accept MIN/MAX(x, y) for vectorizable operands. - DCHECK(r != nullptr && s != nullptr); + DCHECK(r != nullptr); + DCHECK(s != nullptr); if (generate_code && vector_mode_ != kVector) { // de-idiom r = opa; s = opb; @@ -1203,7 +1325,7 @@ bool HLoopOptimization::VectorizeUse(LoopNode* node, return false; } -bool HLoopOptimization::TrySetVectorType(Primitive::Type type, uint64_t* restrictions) { +bool HLoopOptimization::TrySetVectorType(DataType::Type type, uint64_t* restrictions) { const InstructionSetFeatures* features = compiler_driver_->GetInstructionSetFeatures(); switch (compiler_driver_->GetInstructionSet()) { case kArm: @@ -1211,15 +1333,15 @@ bool HLoopOptimization::TrySetVectorType(Primitive::Type type, uint64_t* restric // Allow vectorization for all ARM devices, because Android assumes that // ARM 32-bit always supports advanced SIMD (64-bit SIMD). switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: *restrictions |= kNoDiv | kNoReduction; return TrySetVectorLength(8); - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kUint16: + case DataType::Type::kInt16: *restrictions |= kNoDiv | kNoStringCharAt | kNoReduction; return TrySetVectorLength(4); - case Primitive::kPrimInt: + case DataType::Type::kInt32: *restrictions |= kNoDiv | kNoReduction; return TrySetVectorLength(2); default: @@ -1230,24 +1352,24 @@ bool HLoopOptimization::TrySetVectorType(Primitive::Type type, uint64_t* restric // Allow vectorization for all ARM devices, because Android assumes that // ARMv8 AArch64 always supports advanced SIMD (128-bit SIMD). switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - *restrictions |= kNoDiv | kNoReduction; + case DataType::Type::kBool: + case DataType::Type::kInt8: + *restrictions |= kNoDiv; return TrySetVectorLength(16); - case Primitive::kPrimChar: - case Primitive::kPrimShort: - *restrictions |= kNoDiv | kNoReduction; + case DataType::Type::kUint16: + case DataType::Type::kInt16: + *restrictions |= kNoDiv; return TrySetVectorLength(8); - case Primitive::kPrimInt: + case DataType::Type::kInt32: *restrictions |= kNoDiv; return TrySetVectorLength(4); - case Primitive::kPrimLong: + case DataType::Type::kInt64: *restrictions |= kNoDiv | kNoMul | kNoMinMax; return TrySetVectorLength(2); - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: *restrictions |= kNoReduction; return TrySetVectorLength(4); - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: *restrictions |= kNoReduction; return TrySetVectorLength(2); default: @@ -1258,25 +1380,25 @@ bool HLoopOptimization::TrySetVectorType(Primitive::Type type, uint64_t* restric // Allow vectorization for SSE4.1-enabled X86 devices only (128-bit SIMD). if (features->AsX86InstructionSetFeatures()->HasSSE4_1()) { switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: + case DataType::Type::kBool: + case DataType::Type::kInt8: *restrictions |= - kNoMul | kNoDiv | kNoShift | kNoAbs | kNoSignedHAdd | kNoUnroundedHAdd | kNoReduction; + kNoMul | kNoDiv | kNoShift | kNoAbs | kNoSignedHAdd | kNoUnroundedHAdd | kNoSAD; return TrySetVectorLength(16); - case Primitive::kPrimChar: - case Primitive::kPrimShort: - *restrictions |= kNoDiv | kNoAbs | kNoSignedHAdd | kNoUnroundedHAdd | kNoReduction; + case DataType::Type::kUint16: + case DataType::Type::kInt16: + *restrictions |= kNoDiv | kNoAbs | kNoSignedHAdd | kNoUnroundedHAdd | kNoSAD; return TrySetVectorLength(8); - case Primitive::kPrimInt: - *restrictions |= kNoDiv; + case DataType::Type::kInt32: + *restrictions |= kNoDiv | kNoSAD; return TrySetVectorLength(4); - case Primitive::kPrimLong: - *restrictions |= kNoMul | kNoDiv | kNoShr | kNoAbs | kNoMinMax; + case DataType::Type::kInt64: + *restrictions |= kNoMul | kNoDiv | kNoShr | kNoAbs | kNoMinMax | kNoSAD; return TrySetVectorLength(2); - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: *restrictions |= kNoMinMax | kNoReduction; // minmax: -0.0 vs +0.0 return TrySetVectorLength(4); - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: *restrictions |= kNoMinMax | kNoReduction; // minmax: -0.0 vs +0.0 return TrySetVectorLength(2); default: @@ -1287,24 +1409,24 @@ bool HLoopOptimization::TrySetVectorType(Primitive::Type type, uint64_t* restric case kMips: if (features->AsMipsInstructionSetFeatures()->HasMsa()) { switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - *restrictions |= kNoDiv | kNoReduction; + case DataType::Type::kBool: + case DataType::Type::kInt8: + *restrictions |= kNoDiv | kNoReduction | kNoSAD; return TrySetVectorLength(16); - case Primitive::kPrimChar: - case Primitive::kPrimShort: - *restrictions |= kNoDiv | kNoStringCharAt | kNoReduction; + case DataType::Type::kUint16: + case DataType::Type::kInt16: + *restrictions |= kNoDiv | kNoStringCharAt | kNoReduction | kNoSAD; return TrySetVectorLength(8); - case Primitive::kPrimInt: - *restrictions |= kNoDiv | kNoReduction; + case DataType::Type::kInt32: + *restrictions |= kNoDiv | kNoReduction | kNoSAD; return TrySetVectorLength(4); - case Primitive::kPrimLong: - *restrictions |= kNoDiv | kNoReduction; + case DataType::Type::kInt64: + *restrictions |= kNoDiv | kNoReduction | kNoSAD; return TrySetVectorLength(2); - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: *restrictions |= kNoMinMax | kNoReduction; // min/max(x, NaN) return TrySetVectorLength(4); - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: *restrictions |= kNoMinMax | kNoReduction; // min/max(x, NaN) return TrySetVectorLength(2); default: @@ -1315,24 +1437,24 @@ bool HLoopOptimization::TrySetVectorType(Primitive::Type type, uint64_t* restric case kMips64: if (features->AsMips64InstructionSetFeatures()->HasMsa()) { switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - *restrictions |= kNoDiv | kNoReduction; + case DataType::Type::kBool: + case DataType::Type::kInt8: + *restrictions |= kNoDiv | kNoReduction | kNoSAD; return TrySetVectorLength(16); - case Primitive::kPrimChar: - case Primitive::kPrimShort: - *restrictions |= kNoDiv | kNoStringCharAt | kNoReduction; + case DataType::Type::kUint16: + case DataType::Type::kInt16: + *restrictions |= kNoDiv | kNoStringCharAt | kNoReduction | kNoSAD; return TrySetVectorLength(8); - case Primitive::kPrimInt: - *restrictions |= kNoDiv | kNoReduction; + case DataType::Type::kInt32: + *restrictions |= kNoDiv | kNoReduction | kNoSAD; return TrySetVectorLength(4); - case Primitive::kPrimLong: - *restrictions |= kNoDiv | kNoReduction; + case DataType::Type::kInt64: + *restrictions |= kNoDiv | kNoReduction | kNoSAD; return TrySetVectorLength(2); - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: *restrictions |= kNoMinMax | kNoReduction; // min/max(x, NaN) return TrySetVectorLength(4); - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: *restrictions |= kNoMinMax | kNoReduction; // min/max(x, NaN) return TrySetVectorLength(2); default: @@ -1357,7 +1479,7 @@ bool HLoopOptimization::TrySetVectorLength(uint32_t length) { return vector_length_ == length; } -void HLoopOptimization::GenerateVecInv(HInstruction* org, Primitive::Type type) { +void HLoopOptimization::GenerateVecInv(HInstruction* org, DataType::Type type) { if (vector_map_->find(org) == vector_map_->end()) { // In scalar code, just use a self pass-through for scalar invariants // (viz. expression remains itself). @@ -1371,8 +1493,16 @@ void HLoopOptimization::GenerateVecInv(HInstruction* org, Primitive::Type type) if (it != vector_permanent_map_->end()) { vector = it->second; // reuse during unrolling } else { - vector = new (global_allocator_) HVecReplicateScalar( - global_allocator_, org, type, vector_length_); + // Generates ReplicateScalar( (optional_type_conv) org ). + HInstruction* input = org; + DataType::Type input_type = input->GetType(); + if (type != input_type && (type == DataType::Type::kInt64 || + input_type == DataType::Type::kInt64)) { + input = Insert(vector_preheader_, + new (global_allocator_) HTypeConversion(type, input, kNoDexPc)); + } + vector = new (global_allocator_) + HVecReplicateScalar(global_allocator_, input, type, vector_length_); vector_permanent_map_->Put(org, Insert(vector_preheader_, vector)); } vector_map_->Put(org, vector); @@ -1384,7 +1514,7 @@ void HLoopOptimization::GenerateVecSub(HInstruction* org, HInstruction* offset) HInstruction* subscript = vector_index_; int64_t value = 0; if (!IsInt64AndGet(offset, &value) || value != 0) { - subscript = new (global_allocator_) HAdd(Primitive::kPrimInt, subscript, offset); + subscript = new (global_allocator_) HAdd(DataType::Type::kInt32, subscript, offset); if (org->IsPhi()) { Insert(vector_body_, subscript); // lacks layout placeholder } @@ -1397,7 +1527,7 @@ void HLoopOptimization::GenerateVecMem(HInstruction* org, HInstruction* opa, HInstruction* opb, HInstruction* offset, - Primitive::Type type) { + DataType::Type type) { HInstruction* vector = nullptr; if (vector_mode_ == kVector) { // Vector store or load. @@ -1465,10 +1595,15 @@ void HLoopOptimization::GenerateVecReductionPhiInputs(HPhi* phi, HInstruction* r // Prepare the new initialization. if (vector_mode_ == kVector) { // Generate a [initial, 0, .., 0] vector. - new_init = Insert( - vector_preheader_, - new (global_allocator_) HVecSetScalars( - global_allocator_, &new_init, phi->GetType(), vector_length_, 1)); + HVecOperation* red_vector = new_red->AsVecOperation(); + size_t vector_length = red_vector->GetVectorLength(); + DataType::Type type = red_vector->GetPackedType(); + new_init = Insert(vector_preheader_, + new (global_allocator_) HVecSetScalars(global_allocator_, + &new_init, + type, + vector_length, + 1)); } else { new_init = ReduceAndExtractIfNeeded(new_init); } @@ -1484,18 +1619,20 @@ HInstruction* HLoopOptimization::ReduceAndExtractIfNeeded(HInstruction* instruct if (instruction->IsPhi()) { HInstruction* input = instruction->InputAt(1); if (input->IsVecOperation()) { - Primitive::Type type = input->AsVecOperation()->GetPackedType(); + HVecOperation* input_vector = input->AsVecOperation(); + size_t vector_length = input_vector->GetVectorLength(); + DataType::Type type = input_vector->GetPackedType(); + HVecReduce::ReductionKind kind = GetReductionKind(input_vector); HBasicBlock* exit = instruction->GetBlock()->GetSuccessors()[0]; // Generate a vector reduction and scalar extract // x = REDUCE( [x_1, .., x_n] ) // y = x_1 // along the exit of the defining loop. - HVecReduce::ReductionKind kind = GetReductionKind(input); HInstruction* reduce = new (global_allocator_) HVecReduce( - global_allocator_, instruction, type, vector_length_, kind); + global_allocator_, instruction, type, vector_length, kind); exit->InsertInstructionBefore(reduce, exit->GetFirstInstruction()); instruction = new (global_allocator_) HVecExtractScalar( - global_allocator_, reduce, type, vector_length_, 0); + global_allocator_, reduce, type, vector_length, 0); exit->InsertInstructionAfter(instruction, reduce); } } @@ -1514,29 +1651,21 @@ HInstruction* HLoopOptimization::ReduceAndExtractIfNeeded(HInstruction* instruct void HLoopOptimization::GenerateVecOp(HInstruction* org, HInstruction* opa, HInstruction* opb, - Primitive::Type type, + DataType::Type type, bool is_unsigned) { - if (vector_mode_ == kSequential) { - // Non-converting scalar code follows implicit integral promotion. - if (!org->IsTypeConversion() && (type == Primitive::kPrimBoolean || - type == Primitive::kPrimByte || - type == Primitive::kPrimChar || - type == Primitive::kPrimShort)) { - type = Primitive::kPrimInt; - } - } HInstruction* vector = nullptr; + DataType::Type org_type = org->GetType(); switch (org->GetKind()) { case HInstruction::kNeg: DCHECK(opb == nullptr); GENERATE_VEC( new (global_allocator_) HVecNeg(global_allocator_, opa, type, vector_length_), - new (global_allocator_) HNeg(type, opa)); + new (global_allocator_) HNeg(org_type, opa)); case HInstruction::kNot: DCHECK(opb == nullptr); GENERATE_VEC( new (global_allocator_) HVecNot(global_allocator_, opa, type, vector_length_), - new (global_allocator_) HNot(type, opa)); + new (global_allocator_) HNot(org_type, opa)); case HInstruction::kBooleanNot: DCHECK(opb == nullptr); GENERATE_VEC( @@ -1546,47 +1675,47 @@ void HLoopOptimization::GenerateVecOp(HInstruction* org, DCHECK(opb == nullptr); GENERATE_VEC( new (global_allocator_) HVecCnv(global_allocator_, opa, type, vector_length_), - new (global_allocator_) HTypeConversion(type, opa, kNoDexPc)); + new (global_allocator_) HTypeConversion(org_type, opa, kNoDexPc)); case HInstruction::kAdd: GENERATE_VEC( new (global_allocator_) HVecAdd(global_allocator_, opa, opb, type, vector_length_), - new (global_allocator_) HAdd(type, opa, opb)); + new (global_allocator_) HAdd(org_type, opa, opb)); case HInstruction::kSub: GENERATE_VEC( new (global_allocator_) HVecSub(global_allocator_, opa, opb, type, vector_length_), - new (global_allocator_) HSub(type, opa, opb)); + new (global_allocator_) HSub(org_type, opa, opb)); case HInstruction::kMul: GENERATE_VEC( new (global_allocator_) HVecMul(global_allocator_, opa, opb, type, vector_length_), - new (global_allocator_) HMul(type, opa, opb)); + new (global_allocator_) HMul(org_type, opa, opb)); case HInstruction::kDiv: GENERATE_VEC( new (global_allocator_) HVecDiv(global_allocator_, opa, opb, type, vector_length_), - new (global_allocator_) HDiv(type, opa, opb, kNoDexPc)); + new (global_allocator_) HDiv(org_type, opa, opb, kNoDexPc)); case HInstruction::kAnd: GENERATE_VEC( new (global_allocator_) HVecAnd(global_allocator_, opa, opb, type, vector_length_), - new (global_allocator_) HAnd(type, opa, opb)); + new (global_allocator_) HAnd(org_type, opa, opb)); case HInstruction::kOr: GENERATE_VEC( new (global_allocator_) HVecOr(global_allocator_, opa, opb, type, vector_length_), - new (global_allocator_) HOr(type, opa, opb)); + new (global_allocator_) HOr(org_type, opa, opb)); case HInstruction::kXor: GENERATE_VEC( new (global_allocator_) HVecXor(global_allocator_, opa, opb, type, vector_length_), - new (global_allocator_) HXor(type, opa, opb)); + new (global_allocator_) HXor(org_type, opa, opb)); case HInstruction::kShl: GENERATE_VEC( new (global_allocator_) HVecShl(global_allocator_, opa, opb, type, vector_length_), - new (global_allocator_) HShl(type, opa, opb)); + new (global_allocator_) HShl(org_type, opa, opb)); case HInstruction::kShr: GENERATE_VEC( new (global_allocator_) HVecShr(global_allocator_, opa, opb, type, vector_length_), - new (global_allocator_) HShr(type, opa, opb)); + new (global_allocator_) HShr(org_type, opa, opb)); case HInstruction::kUShr: GENERATE_VEC( new (global_allocator_) HVecUShr(global_allocator_, opa, opb, type, vector_length_), - new (global_allocator_) HUShr(type, opa, opb)); + new (global_allocator_) HUShr(org_type, opa, opb)); case HInstruction::kInvokeStaticOrDirect: { HInvokeStaticOrDirect* invoke = org->AsInvokeStaticOrDirect(); if (vector_mode_ == kVector) { @@ -1667,8 +1796,8 @@ void HLoopOptimization::GenerateVecOp(HInstruction* org, // // Method recognizes the following idioms: -// rounding halving add (a + b + 1) >> 1 for unsigned/signed operands a, b -// regular halving add (a + b) >> 1 for unsigned/signed operands a, b +// rounding halving add (a + b + 1) >> 1 for unsigned/signed operands a, b +// truncated halving add (a + b) >> 1 for unsigned/signed operands a, b // Provided that the operands are promoted to a wider form to do the arithmetic and // then cast back to narrower form, the idioms can be mapped into efficient SIMD // implementation that operates directly in narrower form (plus one extra bit). @@ -1677,7 +1806,7 @@ void HLoopOptimization::GenerateVecOp(HInstruction* org, bool HLoopOptimization::VectorizeHalvingAddIdiom(LoopNode* node, HInstruction* instruction, bool generate_code, - Primitive::Type type, + DataType::Type type, uint64_t restrictions) { // Test for top level arithmetic shift right x >> 1 or logical shift right x >>> 1 // (note whether the sign bit in wider precision is shifted in has no effect @@ -1712,7 +1841,8 @@ bool HLoopOptimization::VectorizeHalvingAddIdiom(LoopNode* node, } // Accept recognized halving add for vectorizable operands. Vectorized code uses the // shorthand idiomatic operation. Sequential code uses the original scalar expressions. - DCHECK(r != nullptr && s != nullptr); + DCHECK(r != nullptr); + DCHECK(s != nullptr); if (generate_code && vector_mode_ != kVector) { // de-idiom r = instruction->InputAt(0); s = instruction->InputAt(1); @@ -1741,6 +1871,96 @@ bool HLoopOptimization::VectorizeHalvingAddIdiom(LoopNode* node, return false; } +// Method recognizes the following idiom: +// q += ABS(a - b) for signed operands a, b +// Provided that the operands have the same type or are promoted to a wider form. +// Since this may involve a vector length change, the idiom is handled by going directly +// to a sad-accumulate node (rather than relying combining finer grained nodes later). +// TODO: unsigned SAD too? +bool HLoopOptimization::VectorizeSADIdiom(LoopNode* node, + HInstruction* instruction, + bool generate_code, + DataType::Type reduction_type, + uint64_t restrictions) { + // Filter integral "q += ABS(a - b);" reduction, where ABS and SUB + // are done in the same precision (either int or long). + if (!instruction->IsAdd() || + (reduction_type != DataType::Type::kInt32 && reduction_type != DataType::Type::kInt64)) { + return false; + } + HInstruction* q = instruction->InputAt(0); + HInstruction* v = instruction->InputAt(1); + HInstruction* a = nullptr; + HInstruction* b = nullptr; + if (v->IsInvokeStaticOrDirect() && + (v->AsInvokeStaticOrDirect()->GetIntrinsic() == Intrinsics::kMathAbsInt || + v->AsInvokeStaticOrDirect()->GetIntrinsic() == Intrinsics::kMathAbsLong)) { + HInstruction* x = v->InputAt(0); + if (x->IsSub() && x->GetType() == reduction_type) { + a = x->InputAt(0); + b = x->InputAt(1); + } + } + if (a == nullptr || b == nullptr) { + return false; + } + // Accept same-type or consistent sign extension for narrower-type on operands a and b. + // The same-type or narrower operands are called r (a or lower) and s (b or lower). + HInstruction* r = a; + HInstruction* s = b; + bool is_unsigned = false; + DataType::Type sub_type = a->GetType(); + if (a->IsTypeConversion()) { + HInstruction* hunt = a; + while (hunt->IsTypeConversion()) { + hunt = hunt->InputAt(0); + } + sub_type = hunt->GetType(); + } else if (b->IsTypeConversion()) { + HInstruction* hunt = a; + while (hunt->IsTypeConversion()) { + hunt = hunt->InputAt(0); + } + sub_type = hunt->GetType(); + } + if (reduction_type != sub_type && + (!IsNarrowerOperands(a, b, sub_type, &r, &s, &is_unsigned) || is_unsigned)) { + return false; + } + // Try same/narrower type and deal with vector restrictions. + if (!TrySetVectorType(sub_type, &restrictions) || HasVectorRestrictions(restrictions, kNoSAD)) { + return false; + } + // Accept SAD idiom for vectorizable operands. Vectorized code uses the shorthand + // idiomatic operation. Sequential code uses the original scalar expressions. + DCHECK(r != nullptr); + DCHECK(s != nullptr); + if (generate_code && vector_mode_ != kVector) { // de-idiom + r = s = v->InputAt(0); + } + if (VectorizeUse(node, q, generate_code, sub_type, restrictions) && + VectorizeUse(node, r, generate_code, sub_type, restrictions) && + VectorizeUse(node, s, generate_code, sub_type, restrictions)) { + if (generate_code) { + if (vector_mode_ == kVector) { + vector_map_->Put(instruction, new (global_allocator_) HVecSADAccumulate( + global_allocator_, + vector_map_->Get(q), + vector_map_->Get(r), + vector_map_->Get(s), + reduction_type, + GetOtherVL(reduction_type, sub_type, vector_length_))); + MaybeRecordStat(stats_, MethodCompilationStat::kLoopVectorizedIdiom); + } else { + GenerateVecOp(v, vector_map_->Get(r), nullptr, reduction_type); + GenerateVecOp(instruction, vector_map_->Get(q), vector_map_->Get(v), reduction_type); + } + } + return true; + } + return false; +} + // // Vectorization heuristics. // diff --git a/compiler/optimizing/loop_optimization.h b/compiler/optimizing/loop_optimization.h index f34751815b..6e6e3873f9 100644 --- a/compiler/optimizing/loop_optimization.h +++ b/compiler/optimizing/loop_optimization.h @@ -75,6 +75,7 @@ class HLoopOptimization : public HOptimization { kNoMinMax = 1 << 8, // no min/max kNoStringCharAt = 1 << 9, // no StringCharAt kNoReduction = 1 << 10, // no reduction + kNoSAD = 1 << 11, // no sum of absolute differences (SAD) }; /* @@ -90,7 +91,7 @@ class HLoopOptimization : public HOptimization { * Representation of a unit-stride array reference. */ struct ArrayReference { - ArrayReference(HInstruction* b, HInstruction* o, Primitive::Type t, bool l) + ArrayReference(HInstruction* b, HInstruction* o, DataType::Type t, bool l) : base(b), offset(o), type(t), lhs(l) { } bool operator<(const ArrayReference& other) const { return @@ -102,7 +103,7 @@ class HLoopOptimization : public HOptimization { } HInstruction* base; // base address HInstruction* offset; // offset + i - Primitive::Type type; // component type + DataType::Type type; // component type bool lhs; // def/use }; @@ -146,32 +147,37 @@ class HLoopOptimization : public HOptimization { bool VectorizeUse(LoopNode* node, HInstruction* instruction, bool generate_code, - Primitive::Type type, + DataType::Type type, uint64_t restrictions); - bool TrySetVectorType(Primitive::Type type, /*out*/ uint64_t* restrictions); + bool TrySetVectorType(DataType::Type type, /*out*/ uint64_t* restrictions); bool TrySetVectorLength(uint32_t length); - void GenerateVecInv(HInstruction* org, Primitive::Type type); + void GenerateVecInv(HInstruction* org, DataType::Type type); void GenerateVecSub(HInstruction* org, HInstruction* offset); void GenerateVecMem(HInstruction* org, HInstruction* opa, HInstruction* opb, HInstruction* offset, - Primitive::Type type); + DataType::Type type); void GenerateVecReductionPhi(HPhi* phi); void GenerateVecReductionPhiInputs(HPhi* phi, HInstruction* reduction); HInstruction* ReduceAndExtractIfNeeded(HInstruction* instruction); void GenerateVecOp(HInstruction* org, HInstruction* opa, HInstruction* opb, - Primitive::Type type, + DataType::Type type, bool is_unsigned = false); // Vectorization idioms. bool VectorizeHalvingAddIdiom(LoopNode* node, HInstruction* instruction, bool generate_code, - Primitive::Type type, + DataType::Type type, uint64_t restrictions); + bool VectorizeSADIdiom(LoopNode* node, + HInstruction* instruction, + bool generate_code, + DataType::Type type, + uint64_t restrictions); // Vectorization heuristics. bool IsVectorizationProfitable(int64_t trip_count); diff --git a/compiler/optimizing/loop_optimization_test.cc b/compiler/optimizing/loop_optimization_test.cc index 1c5603d00f..95718ae388 100644 --- a/compiler/optimizing/loop_optimization_test.cc +++ b/compiler/optimizing/loop_optimization_test.cc @@ -51,7 +51,7 @@ class LoopOptimizationTest : public CommonCompilerTest { parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimInt); + DataType::Type::kInt32); entry_block_->AddInstruction(parameter_); return_block_->AddInstruction(new (&allocator_) HReturnVoid()); exit_block_->AddInstruction(new (&allocator_) HExit()); @@ -216,8 +216,8 @@ TEST_F(LoopOptimizationTest, SimplifyLoop) { header->AddInstruction(new (&allocator_) HIf(parameter_)); body->AddInstruction(new (&allocator_) HGoto()); - HPhi* phi = new (&allocator_) HPhi(&allocator_, 0, 0, Primitive::kPrimInt); - HInstruction* add = new (&allocator_) HAdd(Primitive::kPrimInt, phi, parameter_); + HPhi* phi = new (&allocator_) HPhi(&allocator_, 0, 0, DataType::Type::kInt32); + HInstruction* add = new (&allocator_) HAdd(DataType::Type::kInt32, phi, parameter_); header->AddPhi(phi); body->AddInstruction(add); diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 9cff6b005b..41ea998a8c 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -564,7 +564,7 @@ HCurrentMethod* HGraph::GetCurrentMethod() { // id and/or any invariants the graph is assuming when adding new instructions. if ((cached_current_method_ == nullptr) || (cached_current_method_->GetBlock() == nullptr)) { cached_current_method_ = new (arena_) HCurrentMethod( - Is64BitInstructionSet(instruction_set_) ? Primitive::kPrimLong : Primitive::kPrimInt, + Is64BitInstructionSet(instruction_set_) ? DataType::Type::kInt64 : DataType::Type::kInt32, entry_block_->GetDexPc()); if (entry_block_->GetFirstInstruction() == nullptr) { entry_block_->AddInstruction(cached_current_method_); @@ -585,19 +585,19 @@ std::string HGraph::PrettyMethod(bool with_signature) const { return dex_file_.PrettyMethod(method_idx_, with_signature); } -HConstant* HGraph::GetConstant(Primitive::Type type, int64_t value, uint32_t dex_pc) { +HConstant* HGraph::GetConstant(DataType::Type type, int64_t value, uint32_t dex_pc) { switch (type) { - case Primitive::Type::kPrimBoolean: + case DataType::Type::kBool: DCHECK(IsUint<1>(value)); FALLTHROUGH_INTENDED; - case Primitive::Type::kPrimByte: - case Primitive::Type::kPrimChar: - case Primitive::Type::kPrimShort: - case Primitive::Type::kPrimInt: - DCHECK(IsInt(Primitive::ComponentSize(type) * kBitsPerByte, value)); + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: + DCHECK(IsInt(DataType::Size(type) * kBitsPerByte, value)); return GetIntConstant(static_cast<int32_t>(value), dex_pc); - case Primitive::Type::kPrimLong: + case DataType::Type::kInt64: return GetLongConstant(value, dex_pc); default: @@ -838,9 +838,9 @@ void HBasicBlock::ReplaceAndRemoveInstructionWith(HInstruction* initial, // We can only replace a control flow instruction with another control flow instruction. DCHECK(replacement->IsControlFlow()); DCHECK_EQ(replacement->GetId(), -1); - DCHECK_EQ(replacement->GetType(), Primitive::kPrimVoid); + DCHECK_EQ(replacement->GetType(), DataType::Type::kVoid); DCHECK_EQ(initial->GetBlock(), this); - DCHECK_EQ(initial->GetType(), Primitive::kPrimVoid); + DCHECK_EQ(initial->GetType(), DataType::Type::kVoid); DCHECK(initial->GetUses().empty()); DCHECK(initial->GetEnvUses().empty()); replacement->SetBlock(this); @@ -1219,7 +1219,7 @@ void HVariableInputSizeInstruction::RemoveAllInputs() { size_t HConstructorFence::RemoveConstructorFences(HInstruction* instruction) { DCHECK(instruction->GetBlock() != nullptr); // Removing constructor fences only makes sense for instructions with an object return type. - DCHECK_EQ(Primitive::kPrimNot, instruction->GetType()); + DCHECK_EQ(DataType::Type::kReference, instruction->GetType()); // Return how many instructions were removed for statistic purposes. size_t remove_count = 0; @@ -1382,11 +1382,11 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { if (GetInput()->IsIntConstant()) { int32_t value = GetInput()->AsIntConstant()->GetValue(); switch (GetResultType()) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc()); - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: return graph->GetFloatConstant(static_cast<float>(value), GetDexPc()); - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc()); default: return nullptr; @@ -1394,11 +1394,11 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { } else if (GetInput()->IsLongConstant()) { int64_t value = GetInput()->AsLongConstant()->GetValue(); switch (GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc()); - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: return graph->GetFloatConstant(static_cast<float>(value), GetDexPc()); - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc()); default: return nullptr; @@ -1406,7 +1406,7 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { } else if (GetInput()->IsFloatConstant()) { float value = GetInput()->AsFloatConstant()->GetValue(); switch (GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: if (std::isnan(value)) return graph->GetIntConstant(0, GetDexPc()); if (value >= kPrimIntMax) @@ -1414,7 +1414,7 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { if (value <= kPrimIntMin) return graph->GetIntConstant(kPrimIntMin, GetDexPc()); return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc()); - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (std::isnan(value)) return graph->GetLongConstant(0, GetDexPc()); if (value >= kPrimLongMax) @@ -1422,7 +1422,7 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { if (value <= kPrimLongMin) return graph->GetLongConstant(kPrimLongMin, GetDexPc()); return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc()); - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc()); default: return nullptr; @@ -1430,7 +1430,7 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { } else if (GetInput()->IsDoubleConstant()) { double value = GetInput()->AsDoubleConstant()->GetValue(); switch (GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: if (std::isnan(value)) return graph->GetIntConstant(0, GetDexPc()); if (value >= kPrimIntMax) @@ -1438,7 +1438,7 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { if (value <= kPrimLongMin) return graph->GetIntConstant(kPrimIntMin, GetDexPc()); return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc()); - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (std::isnan(value)) return graph->GetLongConstant(0, GetDexPc()); if (value >= kPrimLongMax) @@ -1446,7 +1446,7 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { if (value <= kPrimLongMin) return graph->GetLongConstant(kPrimLongMin, GetDexPc()); return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc()); - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: return graph->GetFloatConstant(static_cast<float>(value), GetDexPc()); default: return nullptr; @@ -2604,7 +2604,7 @@ static void CheckAgainstUpperBound(ReferenceTypeInfo rti, ReferenceTypeInfo uppe void HInstruction::SetReferenceTypeInfo(ReferenceTypeInfo rti) { if (kIsDebugBuild) { - DCHECK_EQ(GetType(), Primitive::kPrimNot); + DCHECK_EQ(GetType(), DataType::Type::kReference); ScopedObjectAccess soa(Thread::Current()); DCHECK(rti.IsValid()) << "Invalid RTI for " << DebugName(); if (IsBoundType()) { @@ -2893,7 +2893,7 @@ HInstruction* HGraph::InsertOppositeCondition(HInstruction* cond, HInstruction* ArenaAllocator* allocator = GetArena(); if (cond->IsCondition() && - !Primitive::IsFloatingPointType(cond->InputAt(0)->GetType())) { + !DataType::IsFloatingPointType(cond->InputAt(0)->GetType())) { // Can't reverse floating point conditions. We have to use HBooleanNot in that case. HInstruction* lhs = cond->InputAt(0); HInstruction* rhs = cond->InputAt(1); diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index a6d0da1c96..c49cee3284 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -28,6 +28,7 @@ #include "base/iteration_range.h" #include "base/stl_util.h" #include "base/transform_array_ref.h" +#include "data_type.h" #include "deoptimization_kind.h" #include "dex_file.h" #include "dex_file_types.h" @@ -40,7 +41,6 @@ #include "method_reference.h" #include "mirror/class.h" #include "offsets.h" -#include "primitive.h" #include "utils/intrusive_forward_list.h" namespace art { @@ -511,7 +511,7 @@ class HGraph : public ArenaObject<kArenaAllocGraph> { // Returns a constant of the given type and value. If it does not exist // already, it is created and inserted into the graph. This method is only for // integral types. - HConstant* GetConstant(Primitive::Type type, int64_t value, uint32_t dex_pc = kNoDexPc); + HConstant* GetConstant(DataType::Type type, int64_t value, uint32_t dex_pc = kNoDexPc); // TODO: This is problematic for the consistency of reference type propagation // because it can be created anytime after the pass and thus it will be left @@ -1396,6 +1396,7 @@ class HLoopInformationOutwardIterator : public ValueObject { M(VecUShr, VecBinaryOperation) \ M(VecSetScalars, VecOperation) \ M(VecMultiplyAccumulate, VecOperation) \ + M(VecSADAccumulate, VecOperation) \ M(VecLoad, VecMemoryOperation) \ M(VecStore, VecMemoryOperation) \ @@ -1566,7 +1567,7 @@ using HConstInputsRef = TransformArrayRef<const HUserRecord<HInstruction*>, HInp * The internal representation uses 38-bit and is described in the table below. * The first line indicates the side effect, and for field/array accesses the * second line indicates the type of the access (in the order of the - * Primitive::Type enum). + * DataType::Type enum). * The two numbered lines below indicate the bit position in the bitfield (read * vertically). * @@ -1615,23 +1616,23 @@ class SideEffects : public ValueObject { return SideEffects(kAllReads); } - static SideEffects FieldWriteOfType(Primitive::Type type, bool is_volatile) { + static SideEffects FieldWriteOfType(DataType::Type type, bool is_volatile) { return is_volatile ? AllWritesAndReads() : SideEffects(TypeFlag(type, kFieldWriteOffset)); } - static SideEffects ArrayWriteOfType(Primitive::Type type) { + static SideEffects ArrayWriteOfType(DataType::Type type) { return SideEffects(TypeFlag(type, kArrayWriteOffset)); } - static SideEffects FieldReadOfType(Primitive::Type type, bool is_volatile) { + static SideEffects FieldReadOfType(DataType::Type type, bool is_volatile) { return is_volatile ? AllWritesAndReads() : SideEffects(TypeFlag(type, kFieldReadOffset)); } - static SideEffects ArrayReadOfType(Primitive::Type type) { + static SideEffects ArrayReadOfType(DataType::Type type) { return SideEffects(TypeFlag(type, kArrayReadOffset)); } @@ -1760,13 +1761,13 @@ class SideEffects : public ValueObject { ((1ULL << (kLastBitForReads + 1 - kFieldReadOffset)) - 1) << kFieldReadOffset; // Translates type to bit flag. - static uint64_t TypeFlag(Primitive::Type type, int offset) { - CHECK_NE(type, Primitive::kPrimVoid); + static uint64_t TypeFlag(DataType::Type type, int offset) { + CHECK_NE(type, DataType::Type::kVoid); const uint64_t one = 1; - const int shift = type; // 0-based consecutive enum + const int shift = static_cast<int>(type); // 0-based consecutive enum DCHECK_LE(kFieldWriteOffset, shift); DCHECK_LT(shift, kArrayWriteOffset); - return one << (type + offset); + return one << (shift + offset); } // Private constructor on direct flags value. @@ -1955,7 +1956,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { virtual void Accept(HGraphVisitor* visitor) = 0; virtual const char* DebugName() const = 0; - virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; } + virtual DataType::Type GetType() const { return DataType::Type::kVoid; } virtual bool NeedsEnvironment() const { return false; } @@ -1976,7 +1977,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { // simplifies the null check elimination. // TODO: Consider merging can_be_null into ReferenceTypeInfo. virtual bool CanBeNull() const { - DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types"; + DCHECK_EQ(GetType(), DataType::Type::kReference) << "CanBeNull only applies to reference types"; return true; } @@ -1985,13 +1986,13 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { } virtual bool IsActualObject() const { - return GetType() == Primitive::kPrimNot; + return GetType() == DataType::Type::kReference; } void SetReferenceTypeInfo(ReferenceTypeInfo rti); ReferenceTypeInfo GetReferenceTypeInfo() const { - DCHECK_EQ(GetType(), Primitive::kPrimNot); + DCHECK_EQ(GetType(), DataType::Type::kReference); return ReferenceTypeInfo::CreateUnchecked(reference_type_handle_, GetPackedFlag<kFlagReferenceTypeIsExact>()); } @@ -2504,24 +2505,24 @@ class HTemplateInstruction<0>: public HInstruction { template<intptr_t N> class HExpression : public HTemplateInstruction<N> { public: - HExpression<N>(Primitive::Type type, SideEffects side_effects, uint32_t dex_pc) + HExpression<N>(DataType::Type type, SideEffects side_effects, uint32_t dex_pc) : HTemplateInstruction<N>(side_effects, dex_pc) { this->template SetPackedField<TypeField>(type); } virtual ~HExpression() {} - Primitive::Type GetType() const OVERRIDE { + DataType::Type GetType() const OVERRIDE { return TypeField::Decode(this->GetPackedFields()); } protected: static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits; static constexpr size_t kFieldTypeSize = - MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast)); + MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast)); static constexpr size_t kNumberOfExpressionPackedBits = kFieldType + kFieldTypeSize; static_assert(kNumberOfExpressionPackedBits <= HInstruction::kMaxNumberOfPackedBits, "Too many packed fields."); - using TypeField = BitField<Primitive::Type, kFieldType, kFieldTypeSize>; + using TypeField = BitField<DataType::Type, kFieldType, kFieldTypeSize>; }; // Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow @@ -2561,7 +2562,7 @@ class HPhi FINAL : public HVariableInputSizeInstruction { HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, - Primitive::Type type, + DataType::Type type, uint32_t dex_pc = kNoDexPc) : HVariableInputSizeInstruction( SideEffects::None(), @@ -2571,7 +2572,7 @@ class HPhi FINAL : public HVariableInputSizeInstruction { kArenaAllocPhiInputs), reg_number_(reg_number) { SetPackedField<TypeField>(ToPhiType(type)); - DCHECK_NE(GetType(), Primitive::kPrimVoid); + DCHECK_NE(GetType(), DataType::Type::kVoid); // Phis are constructed live and marked dead if conflicting or unused. // Individual steps of SsaBuilder should assume that if a phi has been // marked dead, it can be ignored and will be removed by SsaPhiElimination. @@ -2580,21 +2581,21 @@ class HPhi FINAL : public HVariableInputSizeInstruction { } // Returns a type equivalent to the given `type`, but that a `HPhi` can hold. - static Primitive::Type ToPhiType(Primitive::Type type) { - return Primitive::PrimitiveKind(type); + static DataType::Type ToPhiType(DataType::Type type) { + return DataType::Kind(type); } bool IsCatchPhi() const { return GetBlock()->IsCatchBlock(); } - Primitive::Type GetType() const OVERRIDE { return GetPackedField<TypeField>(); } - void SetType(Primitive::Type new_type) { + DataType::Type GetType() const OVERRIDE { return GetPackedField<TypeField>(); } + void SetType(DataType::Type new_type) { // Make sure that only valid type changes occur. The following are allowed: // (1) int -> float/ref (primitive type propagation), // (2) long -> double (primitive type propagation). DCHECK(GetType() == new_type || - (GetType() == Primitive::kPrimInt && new_type == Primitive::kPrimFloat) || - (GetType() == Primitive::kPrimInt && new_type == Primitive::kPrimNot) || - (GetType() == Primitive::kPrimLong && new_type == Primitive::kPrimDouble)); + (GetType() == DataType::Type::kInt32 && new_type == DataType::Type::kFloat32) || + (GetType() == DataType::Type::kInt32 && new_type == DataType::Type::kReference) || + (GetType() == DataType::Type::kInt64 && new_type == DataType::Type::kFloat64)); SetPackedField<TypeField>(new_type); } @@ -2644,12 +2645,12 @@ class HPhi FINAL : public HVariableInputSizeInstruction { private: static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits; static constexpr size_t kFieldTypeSize = - MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast)); + MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast)); static constexpr size_t kFlagIsLive = kFieldType + kFieldTypeSize; static constexpr size_t kFlagCanBeNull = kFlagIsLive + 1; static constexpr size_t kNumberOfPhiPackedBits = kFlagCanBeNull + 1; static_assert(kNumberOfPhiPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields."); - using TypeField = BitField<Primitive::Type, kFieldType, kFieldTypeSize>; + using TypeField = BitField<DataType::Type, kFieldType, kFieldTypeSize>; const uint32_t reg_number_; @@ -2690,7 +2691,7 @@ class HGoto FINAL : public HTemplateInstruction<0> { class HConstant : public HExpression<0> { public: - explicit HConstant(Primitive::Type type, uint32_t dex_pc = kNoDexPc) + explicit HConstant(DataType::Type type, uint32_t dex_pc = kNoDexPc) : HExpression(type, SideEffects::None(), dex_pc) {} bool CanBeMoved() const OVERRIDE { return true; } @@ -2728,7 +2729,8 @@ class HNullConstant FINAL : public HConstant { DECLARE_INSTRUCTION(NullConstant); private: - explicit HNullConstant(uint32_t dex_pc = kNoDexPc) : HConstant(Primitive::kPrimNot, dex_pc) {} + explicit HNullConstant(uint32_t dex_pc = kNoDexPc) + : HConstant(DataType::Type::kReference, dex_pc) {} friend class HGraph; DISALLOW_COPY_AND_ASSIGN(HNullConstant); @@ -2765,9 +2767,9 @@ class HIntConstant FINAL : public HConstant { private: explicit HIntConstant(int32_t value, uint32_t dex_pc = kNoDexPc) - : HConstant(Primitive::kPrimInt, dex_pc), value_(value) {} + : HConstant(DataType::Type::kInt32, dex_pc), value_(value) {} explicit HIntConstant(bool value, uint32_t dex_pc = kNoDexPc) - : HConstant(Primitive::kPrimInt, dex_pc), value_(value ? 1 : 0) {} + : HConstant(DataType::Type::kInt32, dex_pc), value_(value ? 1 : 0) {} const int32_t value_; @@ -2799,7 +2801,7 @@ class HLongConstant FINAL : public HConstant { private: explicit HLongConstant(int64_t value, uint32_t dex_pc = kNoDexPc) - : HConstant(Primitive::kPrimLong, dex_pc), value_(value) {} + : HConstant(DataType::Type::kInt64, dex_pc), value_(value) {} const int64_t value_; @@ -2848,9 +2850,9 @@ class HFloatConstant FINAL : public HConstant { private: explicit HFloatConstant(float value, uint32_t dex_pc = kNoDexPc) - : HConstant(Primitive::kPrimFloat, dex_pc), value_(value) {} + : HConstant(DataType::Type::kFloat32, dex_pc), value_(value) {} explicit HFloatConstant(int32_t value, uint32_t dex_pc = kNoDexPc) - : HConstant(Primitive::kPrimFloat, dex_pc), value_(bit_cast<float, int32_t>(value)) {} + : HConstant(DataType::Type::kFloat32, dex_pc), value_(bit_cast<float, int32_t>(value)) {} const float value_; @@ -2899,9 +2901,9 @@ class HDoubleConstant FINAL : public HConstant { private: explicit HDoubleConstant(double value, uint32_t dex_pc = kNoDexPc) - : HConstant(Primitive::kPrimDouble, dex_pc), value_(value) {} + : HConstant(DataType::Type::kFloat64, dex_pc), value_(value) {} explicit HDoubleConstant(int64_t value, uint32_t dex_pc = kNoDexPc) - : HConstant(Primitive::kPrimDouble, dex_pc), value_(bit_cast<double, int64_t>(value)) {} + : HConstant(DataType::Type::kFloat64, dex_pc), value_(bit_cast<double, int64_t>(value)) {} const double value_; @@ -3050,8 +3052,8 @@ class HDeoptimize FINAL : public HVariableInputSizeInstruction { DeoptimizationKind GetDeoptimizationKind() const { return GetPackedField<DeoptimizeKindField>(); } - Primitive::Type GetType() const OVERRIDE { - return GuardsAnInput() ? GuardedInput()->GetType() : Primitive::kPrimVoid; + DataType::Type GetType() const OVERRIDE { + return GuardsAnInput() ? GuardedInput()->GetType() : DataType::Type::kVoid; } bool GuardsAnInput() const { @@ -3097,7 +3099,7 @@ class HShouldDeoptimizeFlag FINAL : public HVariableInputSizeInstruction { : HVariableInputSizeInstruction(SideEffects::None(), dex_pc, arena, 0, kArenaAllocCHA) { } - Primitive::Type GetType() const OVERRIDE { return Primitive::kPrimInt; } + DataType::Type GetType() const OVERRIDE { return DataType::Type::kInt32; } // We do all CHA guard elimination/motion in a single pass, after which there is no // further guard elimination/motion since a guard might have been used for justification @@ -3116,7 +3118,7 @@ class HShouldDeoptimizeFlag FINAL : public HVariableInputSizeInstruction { // instructions that work with the dex cache. class HCurrentMethod FINAL : public HExpression<0> { public: - explicit HCurrentMethod(Primitive::Type type, uint32_t dex_pc = kNoDexPc) + explicit HCurrentMethod(DataType::Type type, uint32_t dex_pc = kNoDexPc) : HExpression(type, SideEffects::None(), dex_pc) {} DECLARE_INSTRUCTION(CurrentMethod); @@ -3135,7 +3137,7 @@ class HClassTableGet FINAL : public HExpression<1> { kLast = kIMTable }; HClassTableGet(HInstruction* cls, - Primitive::Type type, + DataType::Type type, TableKind kind, size_t index, uint32_t dex_pc) @@ -3207,13 +3209,13 @@ class HPackedSwitch FINAL : public HTemplateInstruction<1> { class HUnaryOperation : public HExpression<1> { public: - HUnaryOperation(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc) + HUnaryOperation(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc) : HExpression(result_type, SideEffects::None(), dex_pc) { SetRawInputAt(0, input); } HInstruction* GetInput() const { return InputAt(0); } - Primitive::Type GetResultType() const { return GetType(); } + DataType::Type GetResultType() const { return GetType(); } bool CanBeMoved() const OVERRIDE { return true; } bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { @@ -3239,7 +3241,7 @@ class HUnaryOperation : public HExpression<1> { class HBinaryOperation : public HExpression<2> { public: - HBinaryOperation(Primitive::Type result_type, + HBinaryOperation(DataType::Type result_type, HInstruction* left, HInstruction* right, SideEffects side_effects = SideEffects::None(), @@ -3251,7 +3253,7 @@ class HBinaryOperation : public HExpression<2> { HInstruction* GetLeft() const { return InputAt(0); } HInstruction* GetRight() const { return InputAt(1); } - Primitive::Type GetResultType() const { return GetType(); } + DataType::Type GetResultType() const { return GetType(); } virtual bool IsCommutative() const { return false; } @@ -3341,7 +3343,7 @@ std::ostream& operator<<(std::ostream& os, const ComparisonBias& rhs); class HCondition : public HBinaryOperation { public: HCondition(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc) - : HBinaryOperation(Primitive::kPrimBoolean, first, second, SideEffects::None(), dex_pc) { + : HBinaryOperation(DataType::Type::kBool, first, second, SideEffects::None(), dex_pc) { SetPackedField<ComparisonBiasField>(ComparisonBias::kNoBias); } @@ -3366,7 +3368,7 @@ class HCondition : public HBinaryOperation { } bool IsFPConditionTrueIfNaN() const { - DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType(); + DCHECK(DataType::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType(); IfCondition if_cond = GetCondition(); if (if_cond == kCondNE) { return true; @@ -3377,7 +3379,7 @@ class HCondition : public HBinaryOperation { } bool IsFPConditionFalseIfNaN() const { - DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType(); + DCHECK(DataType::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType(); IfCondition if_cond = GetCondition(); if (if_cond == kCondEQ) { return true; @@ -3403,7 +3405,7 @@ class HCondition : public HBinaryOperation { template <typename T> int32_t CompareFP(T x, T y) const { - DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType(); + DCHECK(DataType::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType(); DCHECK_NE(GetBias(), ComparisonBias::kNoBias); // Handle the bias. return std::isunordered(x, y) ? (IsGtBias() ? 1 : -1) : Compare(x, y); @@ -3820,20 +3822,20 @@ class HCompare FINAL : public HBinaryOperation { public: // Note that `comparison_type` is the type of comparison performed // between the comparison's inputs, not the type of the instantiated - // HCompare instruction (which is always Primitive::kPrimInt). - HCompare(Primitive::Type comparison_type, + // HCompare instruction (which is always DataType::Type::kInt). + HCompare(DataType::Type comparison_type, HInstruction* first, HInstruction* second, ComparisonBias bias, uint32_t dex_pc) - : HBinaryOperation(Primitive::kPrimInt, + : HBinaryOperation(DataType::Type::kInt32, first, second, SideEffectsForArchRuntimeCalls(comparison_type), dex_pc) { SetPackedField<ComparisonBiasField>(bias); - DCHECK_EQ(comparison_type, Primitive::PrimitiveKind(first->GetType())); - DCHECK_EQ(comparison_type, Primitive::PrimitiveKind(second->GetType())); + DCHECK_EQ(comparison_type, DataType::Kind(first->GetType())); + DCHECK_EQ(comparison_type, DataType::Kind(second->GetType())); } template <typename T> @@ -3841,7 +3843,7 @@ class HCompare FINAL : public HBinaryOperation { template <typename T> int32_t ComputeFP(T x, T y) const { - DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType(); + DCHECK(DataType::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType(); DCHECK_NE(GetBias(), ComparisonBias::kNoBias); // Handle the bias. return std::isunordered(x, y) ? (IsGtBias() ? 1 : -1) : Compute(x, y); @@ -3874,11 +3876,11 @@ class HCompare FINAL : public HBinaryOperation { // Does this compare instruction have a "gt bias" (vs an "lt bias")? // Only meaningful for floating-point comparisons. bool IsGtBias() const { - DCHECK(Primitive::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType(); + DCHECK(DataType::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType(); return GetBias() == ComparisonBias::kGtBias; } - static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type type ATTRIBUTE_UNUSED) { + static SideEffects SideEffectsForArchRuntimeCalls(DataType::Type type ATTRIBUTE_UNUSED) { // Comparisons do not require a runtime call in any back end. return SideEffects::None(); } @@ -3913,7 +3915,7 @@ class HNewInstance FINAL : public HExpression<1> { const DexFile& dex_file, bool finalizable, QuickEntrypointEnum entrypoint) - : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc), + : HExpression(DataType::Type::kReference, SideEffects::CanTriggerGC(), dex_pc), type_index_(type_index), dex_file_(dex_file), entrypoint_(entrypoint) { @@ -4001,7 +4003,7 @@ class HInvoke : public HVariableInputSizeInstruction { // inputs at the end of their list of inputs. uint32_t GetNumberOfArguments() const { return number_of_arguments_; } - Primitive::Type GetType() const OVERRIDE { return GetPackedField<ReturnTypeField>(); } + DataType::Type GetType() const OVERRIDE { return GetPackedField<ReturnTypeField>(); } uint32_t GetDexMethodIndex() const { return dex_method_index_; } @@ -4054,17 +4056,17 @@ class HInvoke : public HVariableInputSizeInstruction { static constexpr size_t kFieldReturnType = kFieldInvokeType + kFieldInvokeTypeSize; static constexpr size_t kFieldReturnTypeSize = - MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast)); + MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast)); static constexpr size_t kFlagCanThrow = kFieldReturnType + kFieldReturnTypeSize; static constexpr size_t kNumberOfInvokePackedBits = kFlagCanThrow + 1; static_assert(kNumberOfInvokePackedBits <= kMaxNumberOfPackedBits, "Too many packed fields."); using InvokeTypeField = BitField<InvokeType, kFieldInvokeType, kFieldInvokeTypeSize>; - using ReturnTypeField = BitField<Primitive::Type, kFieldReturnType, kFieldReturnTypeSize>; + using ReturnTypeField = BitField<DataType::Type, kFieldReturnType, kFieldReturnTypeSize>; HInvoke(ArenaAllocator* arena, uint32_t number_of_arguments, uint32_t number_of_other_inputs, - Primitive::Type return_type, + DataType::Type return_type, uint32_t dex_pc, uint32_t dex_method_index, ArtMethod* resolved_method, @@ -4101,7 +4103,7 @@ class HInvokeUnresolved FINAL : public HInvoke { public: HInvokeUnresolved(ArenaAllocator* arena, uint32_t number_of_arguments, - Primitive::Type return_type, + DataType::Type return_type, uint32_t dex_pc, uint32_t dex_method_index, InvokeType invoke_type) @@ -4125,7 +4127,7 @@ class HInvokePolymorphic FINAL : public HInvoke { public: HInvokePolymorphic(ArenaAllocator* arena, uint32_t number_of_arguments, - Primitive::Type return_type, + DataType::Type return_type, uint32_t dex_pc, uint32_t dex_method_index) : HInvoke(arena, @@ -4202,7 +4204,7 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { HInvokeStaticOrDirect(ArenaAllocator* arena, uint32_t number_of_arguments, - Primitive::Type return_type, + DataType::Type return_type, uint32_t dex_pc, uint32_t method_index, ArtMethod* resolved_method, @@ -4280,7 +4282,7 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { } bool CanBeNull() const OVERRIDE { - return GetPackedField<ReturnTypeField>() == Primitive::kPrimNot && !IsStringInit(); + return GetPackedField<ReturnTypeField>() == DataType::Type::kReference && !IsStringInit(); } // Get the index of the special input, if any. @@ -4397,7 +4399,7 @@ class HInvokeVirtual FINAL : public HInvoke { public: HInvokeVirtual(ArenaAllocator* arena, uint32_t number_of_arguments, - Primitive::Type return_type, + DataType::Type return_type, uint32_t dex_pc, uint32_t dex_method_index, ArtMethod* resolved_method, @@ -4445,7 +4447,7 @@ class HInvokeInterface FINAL : public HInvoke { public: HInvokeInterface(ArenaAllocator* arena, uint32_t number_of_arguments, - Primitive::Type return_type, + DataType::Type return_type, uint32_t dex_pc, uint32_t dex_method_index, ArtMethod* resolved_method, @@ -4484,9 +4486,9 @@ class HInvokeInterface FINAL : public HInvoke { class HNeg FINAL : public HUnaryOperation { public: - HNeg(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc) + HNeg(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc) : HUnaryOperation(result_type, input, dex_pc) { - DCHECK_EQ(result_type, Primitive::PrimitiveKind(input->GetType())); + DCHECK_EQ(result_type, DataType::Kind(input->GetType())); } template <typename T> static T Compute(T x) { return -x; } @@ -4513,7 +4515,7 @@ class HNeg FINAL : public HUnaryOperation { class HNewArray FINAL : public HExpression<2> { public: HNewArray(HInstruction* cls, HInstruction* length, uint32_t dex_pc) - : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc) { + : HExpression(DataType::Type::kReference, SideEffects::CanTriggerGC(), dex_pc) { SetRawInputAt(0, cls); SetRawInputAt(1, length); } @@ -4543,7 +4545,7 @@ class HNewArray FINAL : public HExpression<2> { class HAdd FINAL : public HBinaryOperation { public: - HAdd(Primitive::Type result_type, + HAdd(DataType::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc = kNoDexPc) @@ -4578,7 +4580,7 @@ class HAdd FINAL : public HBinaryOperation { class HSub FINAL : public HBinaryOperation { public: - HSub(Primitive::Type result_type, + HSub(DataType::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc = kNoDexPc) @@ -4611,7 +4613,7 @@ class HSub FINAL : public HBinaryOperation { class HMul FINAL : public HBinaryOperation { public: - HMul(Primitive::Type result_type, + HMul(DataType::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc = kNoDexPc) @@ -4646,7 +4648,7 @@ class HMul FINAL : public HBinaryOperation { class HDiv FINAL : public HBinaryOperation { public: - HDiv(Primitive::Type result_type, + HDiv(DataType::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc) @@ -4654,7 +4656,7 @@ class HDiv FINAL : public HBinaryOperation { template <typename T> T ComputeIntegral(T x, T y) const { - DCHECK(!Primitive::IsFloatingPointType(GetType())) << GetType(); + DCHECK(!DataType::IsFloatingPointType(GetType())) << GetType(); // Our graph structure ensures we never have 0 for `y` during // constant folding. DCHECK_NE(y, 0); @@ -4664,7 +4666,7 @@ class HDiv FINAL : public HBinaryOperation { template <typename T> T ComputeFP(T x, T y) const { - DCHECK(Primitive::IsFloatingPointType(GetType())) << GetType(); + DCHECK(DataType::IsFloatingPointType(GetType())) << GetType(); return x / y; } @@ -4693,7 +4695,7 @@ class HDiv FINAL : public HBinaryOperation { class HRem FINAL : public HBinaryOperation { public: - HRem(Primitive::Type result_type, + HRem(DataType::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc) @@ -4701,7 +4703,7 @@ class HRem FINAL : public HBinaryOperation { template <typename T> T ComputeIntegral(T x, T y) const { - DCHECK(!Primitive::IsFloatingPointType(GetType())) << GetType(); + DCHECK(!DataType::IsFloatingPointType(GetType())) << GetType(); // Our graph structure ensures we never have 0 for `y` during // constant folding. DCHECK_NE(y, 0); @@ -4711,7 +4713,7 @@ class HRem FINAL : public HBinaryOperation { template <typename T> T ComputeFP(T x, T y) const { - DCHECK(Primitive::IsFloatingPointType(GetType())) << GetType(); + DCHECK(DataType::IsFloatingPointType(GetType())) << GetType(); return std::fmod(x, y); } @@ -4747,7 +4749,7 @@ class HDivZeroCheck FINAL : public HExpression<1> { SetRawInputAt(0, value); } - Primitive::Type GetType() const OVERRIDE { return InputAt(0)->GetType(); } + DataType::Type GetType() const OVERRIDE { return InputAt(0)->GetType(); } bool CanBeMoved() const OVERRIDE { return true; } @@ -4766,13 +4768,13 @@ class HDivZeroCheck FINAL : public HExpression<1> { class HShl FINAL : public HBinaryOperation { public: - HShl(Primitive::Type result_type, + HShl(DataType::Type result_type, HInstruction* value, HInstruction* distance, uint32_t dex_pc = kNoDexPc) : HBinaryOperation(result_type, value, distance, SideEffects::None(), dex_pc) { - DCHECK_EQ(result_type, Primitive::PrimitiveKind(value->GetType())); - DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(distance->GetType())); + DCHECK_EQ(result_type, DataType::Kind(value->GetType())); + DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType())); } template <typename T> @@ -4812,13 +4814,13 @@ class HShl FINAL : public HBinaryOperation { class HShr FINAL : public HBinaryOperation { public: - HShr(Primitive::Type result_type, + HShr(DataType::Type result_type, HInstruction* value, HInstruction* distance, uint32_t dex_pc = kNoDexPc) : HBinaryOperation(result_type, value, distance, SideEffects::None(), dex_pc) { - DCHECK_EQ(result_type, Primitive::PrimitiveKind(value->GetType())); - DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(distance->GetType())); + DCHECK_EQ(result_type, DataType::Kind(value->GetType())); + DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType())); } template <typename T> @@ -4858,13 +4860,13 @@ class HShr FINAL : public HBinaryOperation { class HUShr FINAL : public HBinaryOperation { public: - HUShr(Primitive::Type result_type, + HUShr(DataType::Type result_type, HInstruction* value, HInstruction* distance, uint32_t dex_pc = kNoDexPc) : HBinaryOperation(result_type, value, distance, SideEffects::None(), dex_pc) { - DCHECK_EQ(result_type, Primitive::PrimitiveKind(value->GetType())); - DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(distance->GetType())); + DCHECK_EQ(result_type, DataType::Kind(value->GetType())); + DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType())); } template <typename T> @@ -4906,7 +4908,7 @@ class HUShr FINAL : public HBinaryOperation { class HAnd FINAL : public HBinaryOperation { public: - HAnd(Primitive::Type result_type, + HAnd(DataType::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc = kNoDexPc) @@ -4943,7 +4945,7 @@ class HAnd FINAL : public HBinaryOperation { class HOr FINAL : public HBinaryOperation { public: - HOr(Primitive::Type result_type, + HOr(DataType::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc = kNoDexPc) @@ -4980,7 +4982,7 @@ class HOr FINAL : public HBinaryOperation { class HXor FINAL : public HBinaryOperation { public: - HXor(Primitive::Type result_type, + HXor(DataType::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc = kNoDexPc) @@ -5017,10 +5019,10 @@ class HXor FINAL : public HBinaryOperation { class HRor FINAL : public HBinaryOperation { public: - HRor(Primitive::Type result_type, HInstruction* value, HInstruction* distance) + HRor(DataType::Type result_type, HInstruction* value, HInstruction* distance) : HBinaryOperation(result_type, value, distance) { - DCHECK_EQ(result_type, Primitive::PrimitiveKind(value->GetType())); - DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(distance->GetType())); + DCHECK_EQ(result_type, DataType::Kind(value->GetType())); + DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType())); } template <typename T> @@ -5073,7 +5075,7 @@ class HParameterValue FINAL : public HExpression<0> { HParameterValue(const DexFile& dex_file, dex::TypeIndex type_index, uint8_t index, - Primitive::Type parameter_type, + DataType::Type parameter_type, bool is_this = false) : HExpression(parameter_type, SideEffects::None(), kNoDexPc), dex_file_(dex_file), @@ -5112,7 +5114,7 @@ class HParameterValue FINAL : public HExpression<0> { class HNot FINAL : public HUnaryOperation { public: - HNot(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc) + HNot(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc) : HUnaryOperation(result_type, input, dex_pc) {} bool CanBeMoved() const OVERRIDE { return true; } @@ -5146,7 +5148,7 @@ class HNot FINAL : public HUnaryOperation { class HBooleanNot FINAL : public HUnaryOperation { public: explicit HBooleanNot(HInstruction* input, uint32_t dex_pc = kNoDexPc) - : HUnaryOperation(Primitive::Type::kPrimBoolean, input, dex_pc) {} + : HUnaryOperation(DataType::Type::kBool, input, dex_pc) {} bool CanBeMoved() const OVERRIDE { return true; } bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { @@ -5183,16 +5185,16 @@ class HBooleanNot FINAL : public HUnaryOperation { class HTypeConversion FINAL : public HExpression<1> { public: // Instantiate a type conversion of `input` to `result_type`. - HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc) + HTypeConversion(DataType::Type result_type, HInstruction* input, uint32_t dex_pc) : HExpression(result_type, SideEffects::None(), dex_pc) { SetRawInputAt(0, input); // Invariant: We should never generate a conversion to a Boolean value. - DCHECK_NE(Primitive::kPrimBoolean, result_type); + DCHECK_NE(DataType::Type::kBool, result_type); } HInstruction* GetInput() const { return InputAt(0); } - Primitive::Type GetInputType() const { return GetInput()->GetType(); } - Primitive::Type GetResultType() const { return GetType(); } + DataType::Type GetInputType() const { return GetInput()->GetType(); } + DataType::Type GetResultType() const { return GetType(); } bool CanBeMoved() const OVERRIDE { return true; } bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { @@ -5244,7 +5246,7 @@ class FieldInfo : public ValueObject { public: FieldInfo(ArtField* field, MemberOffset field_offset, - Primitive::Type field_type, + DataType::Type field_type, bool is_volatile, uint32_t index, uint16_t declaring_class_def_index, @@ -5259,7 +5261,7 @@ class FieldInfo : public ValueObject { ArtField* GetField() const { return field_; } MemberOffset GetFieldOffset() const { return field_offset_; } - Primitive::Type GetFieldType() const { return field_type_; } + DataType::Type GetFieldType() const { return field_type_; } uint32_t GetFieldIndex() const { return index_; } uint16_t GetDeclaringClassDefIndex() const { return declaring_class_def_index_;} const DexFile& GetDexFile() const { return dex_file_; } @@ -5268,7 +5270,7 @@ class FieldInfo : public ValueObject { private: ArtField* const field_; const MemberOffset field_offset_; - const Primitive::Type field_type_; + const DataType::Type field_type_; const bool is_volatile_; const uint32_t index_; const uint16_t declaring_class_def_index_; @@ -5279,7 +5281,7 @@ class HInstanceFieldGet FINAL : public HExpression<1> { public: HInstanceFieldGet(HInstruction* value, ArtField* field, - Primitive::Type field_type, + DataType::Type field_type, MemberOffset field_offset, bool is_volatile, uint32_t field_idx, @@ -5314,7 +5316,7 @@ class HInstanceFieldGet FINAL : public HExpression<1> { const FieldInfo& GetFieldInfo() const { return field_info_; } MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } - Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } + DataType::Type GetFieldType() const { return field_info_.GetFieldType(); } bool IsVolatile() const { return field_info_.IsVolatile(); } DECLARE_INSTRUCTION(InstanceFieldGet); @@ -5330,7 +5332,7 @@ class HInstanceFieldSet FINAL : public HTemplateInstruction<2> { HInstanceFieldSet(HInstruction* object, HInstruction* value, ArtField* field, - Primitive::Type field_type, + DataType::Type field_type, MemberOffset field_offset, bool is_volatile, uint32_t field_idx, @@ -5356,7 +5358,7 @@ class HInstanceFieldSet FINAL : public HTemplateInstruction<2> { const FieldInfo& GetFieldInfo() const { return field_info_; } MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } - Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } + DataType::Type GetFieldType() const { return field_info_.GetFieldType(); } bool IsVolatile() const { return field_info_.IsVolatile(); } HInstruction* GetValue() const { return InputAt(1); } bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); } @@ -5379,7 +5381,7 @@ class HArrayGet FINAL : public HExpression<2> { public: HArrayGet(HInstruction* array, HInstruction* index, - Primitive::Type type, + DataType::Type type, uint32_t dex_pc, bool is_string_char_at = false) : HExpression(type, SideEffects::ArrayReadOfType(type), dex_pc) { @@ -5413,11 +5415,11 @@ class HArrayGet FINAL : public HExpression<2> { DCHECK_EQ(GetBlock(), other->GetBlock()); DCHECK_EQ(GetArray(), other->GetArray()); DCHECK_EQ(GetIndex(), other->GetIndex()); - if (Primitive::IsIntOrLongType(GetType())) { - DCHECK(Primitive::IsFloatingPointType(other->GetType())) << other->GetType(); + if (DataType::IsIntOrLongType(GetType())) { + DCHECK(DataType::IsFloatingPointType(other->GetType())) << other->GetType(); } else { - DCHECK(Primitive::IsFloatingPointType(GetType())) << GetType(); - DCHECK(Primitive::IsIntOrLongType(other->GetType())) << other->GetType(); + DCHECK(DataType::IsFloatingPointType(GetType())) << GetType(); + DCHECK(DataType::IsIntOrLongType(other->GetType())) << other->GetType(); } } return result; @@ -5449,11 +5451,11 @@ class HArraySet FINAL : public HTemplateInstruction<3> { HArraySet(HInstruction* array, HInstruction* index, HInstruction* value, - Primitive::Type expected_component_type, + DataType::Type expected_component_type, uint32_t dex_pc) : HTemplateInstruction(SideEffects::None(), dex_pc) { SetPackedField<ExpectedComponentTypeField>(expected_component_type); - SetPackedFlag<kFlagNeedsTypeCheck>(value->GetType() == Primitive::kPrimNot); + SetPackedFlag<kFlagNeedsTypeCheck>(value->GetType() == DataType::Type::kReference); SetPackedFlag<kFlagValueCanBeNull>(true); SetPackedFlag<kFlagStaticTypeOfArrayIsObjectArray>(false); SetRawInputAt(0, array); @@ -5498,29 +5500,30 @@ class HArraySet FINAL : public HTemplateInstruction<3> { HInstruction* GetIndex() const { return InputAt(1); } HInstruction* GetValue() const { return InputAt(2); } - Primitive::Type GetComponentType() const { + DataType::Type GetComponentType() const { // The Dex format does not type floating point index operations. Since the // `expected_component_type_` is set during building and can therefore not // be correct, we also check what is the value type. If it is a floating // point type, we must use that type. - Primitive::Type value_type = GetValue()->GetType(); - return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble)) + DataType::Type value_type = GetValue()->GetType(); + return ((value_type == DataType::Type::kFloat32) || (value_type == DataType::Type::kFloat64)) ? value_type : GetRawExpectedComponentType(); } - Primitive::Type GetRawExpectedComponentType() const { + DataType::Type GetRawExpectedComponentType() const { return GetPackedField<ExpectedComponentTypeField>(); } void ComputeSideEffects() { - Primitive::Type type = GetComponentType(); + DataType::Type type = GetComponentType(); SetSideEffects(SideEffects::ArrayWriteOfType(type).Union( SideEffectsForArchRuntimeCalls(type))); } - static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type value_type) { - return (value_type == Primitive::kPrimNot) ? SideEffects::CanTriggerGC() : SideEffects::None(); + static SideEffects SideEffectsForArchRuntimeCalls(DataType::Type value_type) { + return (value_type == DataType::Type::kReference) ? SideEffects::CanTriggerGC() + : SideEffects::None(); } DECLARE_INSTRUCTION(ArraySet); @@ -5528,7 +5531,7 @@ class HArraySet FINAL : public HTemplateInstruction<3> { private: static constexpr size_t kFieldExpectedComponentType = kNumberOfGenericPackedBits; static constexpr size_t kFieldExpectedComponentTypeSize = - MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast)); + MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast)); static constexpr size_t kFlagNeedsTypeCheck = kFieldExpectedComponentType + kFieldExpectedComponentTypeSize; static constexpr size_t kFlagValueCanBeNull = kFlagNeedsTypeCheck + 1; @@ -5539,7 +5542,7 @@ class HArraySet FINAL : public HTemplateInstruction<3> { kFlagStaticTypeOfArrayIsObjectArray + 1; static_assert(kNumberOfArraySetPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields."); using ExpectedComponentTypeField = - BitField<Primitive::Type, kFieldExpectedComponentType, kFieldExpectedComponentTypeSize>; + BitField<DataType::Type, kFieldExpectedComponentType, kFieldExpectedComponentTypeSize>; DISALLOW_COPY_AND_ASSIGN(HArraySet); }; @@ -5547,7 +5550,7 @@ class HArraySet FINAL : public HTemplateInstruction<3> { class HArrayLength FINAL : public HExpression<1> { public: HArrayLength(HInstruction* array, uint32_t dex_pc, bool is_string_length = false) - : HExpression(Primitive::kPrimInt, SideEffects::None(), dex_pc) { + : HExpression(DataType::Type::kInt32, SideEffects::None(), dex_pc) { SetPackedFlag<kFlagIsStringLength>(is_string_length); // Note that arrays do not change length, so the instruction does not // depend on any write. @@ -5589,7 +5592,7 @@ class HBoundsCheck FINAL : public HExpression<2> { uint32_t dex_pc, bool string_char_at = false) : HExpression(index->GetType(), SideEffects::CanTriggerGC(), dex_pc) { - DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(index->GetType())); + DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(index->GetType())); SetPackedFlag<kFlagIsStringCharAt>(string_char_at); SetRawInputAt(0, index); SetRawInputAt(1, length); @@ -5799,8 +5802,8 @@ class HLoadClass FINAL : public HInstruction { &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u); } - Primitive::Type GetType() const OVERRIDE { - return Primitive::kPrimNot; + DataType::Type GetType() const OVERRIDE { + return DataType::Type::kReference; } Handle<mirror::Class> GetClass() const { @@ -5967,8 +5970,8 @@ class HLoadString FINAL : public HInstruction { &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u); } - Primitive::Type GetType() const OVERRIDE { - return Primitive::kPrimNot; + DataType::Type GetType() const OVERRIDE { + return DataType::Type::kReference; } DECLARE_INSTRUCTION(LoadString); @@ -6019,7 +6022,7 @@ class HClinitCheck FINAL : public HExpression<1> { public: HClinitCheck(HLoadClass* constant, uint32_t dex_pc) : HExpression( - Primitive::kPrimNot, + DataType::Type::kReference, SideEffects::AllChanges(), // Assume write/read on all fields/arrays. dex_pc) { SetRawInputAt(0, constant); @@ -6052,7 +6055,7 @@ class HStaticFieldGet FINAL : public HExpression<1> { public: HStaticFieldGet(HInstruction* cls, ArtField* field, - Primitive::Type field_type, + DataType::Type field_type, MemberOffset field_offset, bool is_volatile, uint32_t field_idx, @@ -6084,7 +6087,7 @@ class HStaticFieldGet FINAL : public HExpression<1> { const FieldInfo& GetFieldInfo() const { return field_info_; } MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } - Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } + DataType::Type GetFieldType() const { return field_info_.GetFieldType(); } bool IsVolatile() const { return field_info_.IsVolatile(); } DECLARE_INSTRUCTION(StaticFieldGet); @@ -6100,7 +6103,7 @@ class HStaticFieldSet FINAL : public HTemplateInstruction<2> { HStaticFieldSet(HInstruction* cls, HInstruction* value, ArtField* field, - Primitive::Type field_type, + DataType::Type field_type, MemberOffset field_offset, bool is_volatile, uint32_t field_idx, @@ -6122,7 +6125,7 @@ class HStaticFieldSet FINAL : public HTemplateInstruction<2> { const FieldInfo& GetFieldInfo() const { return field_info_; } MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } - Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } + DataType::Type GetFieldType() const { return field_info_.GetFieldType(); } bool IsVolatile() const { return field_info_.IsVolatile(); } HInstruction* GetValue() const { return InputAt(1); } @@ -6145,7 +6148,7 @@ class HStaticFieldSet FINAL : public HTemplateInstruction<2> { class HUnresolvedInstanceFieldGet FINAL : public HExpression<1> { public: HUnresolvedInstanceFieldGet(HInstruction* obj, - Primitive::Type field_type, + DataType::Type field_type, uint32_t field_index, uint32_t dex_pc) : HExpression(field_type, SideEffects::AllExceptGCDependency(), dex_pc), @@ -6156,7 +6159,7 @@ class HUnresolvedInstanceFieldGet FINAL : public HExpression<1> { bool NeedsEnvironment() const OVERRIDE { return true; } bool CanThrow() const OVERRIDE { return true; } - Primitive::Type GetFieldType() const { return GetType(); } + DataType::Type GetFieldType() const { return GetType(); } uint32_t GetFieldIndex() const { return field_index_; } DECLARE_INSTRUCTION(UnresolvedInstanceFieldGet); @@ -6171,13 +6174,13 @@ class HUnresolvedInstanceFieldSet FINAL : public HTemplateInstruction<2> { public: HUnresolvedInstanceFieldSet(HInstruction* obj, HInstruction* value, - Primitive::Type field_type, + DataType::Type field_type, uint32_t field_index, uint32_t dex_pc) : HTemplateInstruction(SideEffects::AllExceptGCDependency(), dex_pc), field_index_(field_index) { SetPackedField<FieldTypeField>(field_type); - DCHECK_EQ(Primitive::PrimitiveKind(field_type), Primitive::PrimitiveKind(value->GetType())); + DCHECK_EQ(DataType::Kind(field_type), DataType::Kind(value->GetType())); SetRawInputAt(0, obj); SetRawInputAt(1, value); } @@ -6185,7 +6188,7 @@ class HUnresolvedInstanceFieldSet FINAL : public HTemplateInstruction<2> { bool NeedsEnvironment() const OVERRIDE { return true; } bool CanThrow() const OVERRIDE { return true; } - Primitive::Type GetFieldType() const { return GetPackedField<FieldTypeField>(); } + DataType::Type GetFieldType() const { return GetPackedField<FieldTypeField>(); } uint32_t GetFieldIndex() const { return field_index_; } DECLARE_INSTRUCTION(UnresolvedInstanceFieldSet); @@ -6193,12 +6196,12 @@ class HUnresolvedInstanceFieldSet FINAL : public HTemplateInstruction<2> { private: static constexpr size_t kFieldFieldType = HInstruction::kNumberOfGenericPackedBits; static constexpr size_t kFieldFieldTypeSize = - MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast)); + MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast)); static constexpr size_t kNumberOfUnresolvedStaticFieldSetPackedBits = kFieldFieldType + kFieldFieldTypeSize; static_assert(kNumberOfUnresolvedStaticFieldSetPackedBits <= HInstruction::kMaxNumberOfPackedBits, "Too many packed fields."); - using FieldTypeField = BitField<Primitive::Type, kFieldFieldType, kFieldFieldTypeSize>; + using FieldTypeField = BitField<DataType::Type, kFieldFieldType, kFieldFieldTypeSize>; const uint32_t field_index_; @@ -6207,7 +6210,7 @@ class HUnresolvedInstanceFieldSet FINAL : public HTemplateInstruction<2> { class HUnresolvedStaticFieldGet FINAL : public HExpression<0> { public: - HUnresolvedStaticFieldGet(Primitive::Type field_type, + HUnresolvedStaticFieldGet(DataType::Type field_type, uint32_t field_index, uint32_t dex_pc) : HExpression(field_type, SideEffects::AllExceptGCDependency(), dex_pc), @@ -6217,7 +6220,7 @@ class HUnresolvedStaticFieldGet FINAL : public HExpression<0> { bool NeedsEnvironment() const OVERRIDE { return true; } bool CanThrow() const OVERRIDE { return true; } - Primitive::Type GetFieldType() const { return GetType(); } + DataType::Type GetFieldType() const { return GetType(); } uint32_t GetFieldIndex() const { return field_index_; } DECLARE_INSTRUCTION(UnresolvedStaticFieldGet); @@ -6231,20 +6234,20 @@ class HUnresolvedStaticFieldGet FINAL : public HExpression<0> { class HUnresolvedStaticFieldSet FINAL : public HTemplateInstruction<1> { public: HUnresolvedStaticFieldSet(HInstruction* value, - Primitive::Type field_type, + DataType::Type field_type, uint32_t field_index, uint32_t dex_pc) : HTemplateInstruction(SideEffects::AllExceptGCDependency(), dex_pc), field_index_(field_index) { SetPackedField<FieldTypeField>(field_type); - DCHECK_EQ(Primitive::PrimitiveKind(field_type), Primitive::PrimitiveKind(value->GetType())); + DCHECK_EQ(DataType::Kind(field_type), DataType::Kind(value->GetType())); SetRawInputAt(0, value); } bool NeedsEnvironment() const OVERRIDE { return true; } bool CanThrow() const OVERRIDE { return true; } - Primitive::Type GetFieldType() const { return GetPackedField<FieldTypeField>(); } + DataType::Type GetFieldType() const { return GetPackedField<FieldTypeField>(); } uint32_t GetFieldIndex() const { return field_index_; } DECLARE_INSTRUCTION(UnresolvedStaticFieldSet); @@ -6252,12 +6255,12 @@ class HUnresolvedStaticFieldSet FINAL : public HTemplateInstruction<1> { private: static constexpr size_t kFieldFieldType = HInstruction::kNumberOfGenericPackedBits; static constexpr size_t kFieldFieldTypeSize = - MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast)); + MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast)); static constexpr size_t kNumberOfUnresolvedStaticFieldSetPackedBits = kFieldFieldType + kFieldFieldTypeSize; static_assert(kNumberOfUnresolvedStaticFieldSetPackedBits <= HInstruction::kMaxNumberOfPackedBits, "Too many packed fields."); - using FieldTypeField = BitField<Primitive::Type, kFieldFieldType, kFieldFieldTypeSize>; + using FieldTypeField = BitField<DataType::Type, kFieldFieldType, kFieldFieldTypeSize>; const uint32_t field_index_; @@ -6268,7 +6271,7 @@ class HUnresolvedStaticFieldSet FINAL : public HTemplateInstruction<1> { class HLoadException FINAL : public HExpression<0> { public: explicit HLoadException(uint32_t dex_pc = kNoDexPc) - : HExpression(Primitive::kPrimNot, SideEffects::None(), dex_pc) {} + : HExpression(DataType::Type::kReference, SideEffects::None(), dex_pc) {} bool CanBeNull() const OVERRIDE { return false; } @@ -6334,7 +6337,7 @@ class HInstanceOf FINAL : public HExpression<2> { HLoadClass* constant, TypeCheckKind check_kind, uint32_t dex_pc) - : HExpression(Primitive::kPrimBoolean, + : HExpression(DataType::Type::kBool, SideEffectsForArchRuntimeCalls(check_kind), dex_pc) { SetPackedField<TypeCheckKindField>(check_kind); @@ -6385,11 +6388,11 @@ class HInstanceOf FINAL : public HExpression<2> { class HBoundType FINAL : public HExpression<1> { public: explicit HBoundType(HInstruction* input, uint32_t dex_pc = kNoDexPc) - : HExpression(Primitive::kPrimNot, SideEffects::None(), dex_pc), + : HExpression(DataType::Type::kReference, SideEffects::None(), dex_pc), upper_bound_(ReferenceTypeInfo::CreateInvalid()) { SetPackedFlag<kFlagUpperCanBeNull>(true); SetPackedFlag<kFlagCanBeNull>(true); - DCHECK_EQ(input->GetType(), Primitive::kPrimNot); + DCHECK_EQ(input->GetType(), DataType::Type::kReference); SetRawInputAt(0, input); } @@ -6760,7 +6763,7 @@ class MoveOperands : public ArenaObject<kArenaAllocMoveOperands> { public: MoveOperands(Location source, Location destination, - Primitive::Type type, + DataType::Type type, HInstruction* instruction) : source_(source), destination_(destination), type_(type), instruction_(instruction) {} @@ -6810,10 +6813,10 @@ class MoveOperands : public ArenaObject<kArenaAllocMoveOperands> { return source_.IsInvalid(); } - Primitive::Type GetType() const { return type_; } + DataType::Type GetType() const { return type_; } bool Is64BitMove() const { - return Primitive::Is64BitType(type_); + return DataType::Is64BitType(type_); } HInstruction* GetInstruction() const { return instruction_; } @@ -6822,7 +6825,7 @@ class MoveOperands : public ArenaObject<kArenaAllocMoveOperands> { Location source_; Location destination_; // The type this move is for. - Primitive::Type type_; + DataType::Type type_; // The instruction this move is assocatied with. Null when this move is // for moving an input in the expected locations of user (including a phi user). // This is only used in debug mode, to ensure we do not connect interval siblings @@ -6844,7 +6847,7 @@ class HParallelMove FINAL : public HTemplateInstruction<0> { void AddMove(Location source, Location destination, - Primitive::Type type, + DataType::Type type, HInstruction* instruction) { DCHECK(source.IsValid()); DCHECK(destination.IsValid()); diff --git a/compiler/optimizing/nodes_mips.h b/compiler/optimizing/nodes_mips.h index 8e439d9621..80e652eaa7 100644 --- a/compiler/optimizing/nodes_mips.h +++ b/compiler/optimizing/nodes_mips.h @@ -24,7 +24,7 @@ class HMipsComputeBaseMethodAddress : public HExpression<0> { public: // Treat the value as an int32_t, but it is really a 32 bit native pointer. HMipsComputeBaseMethodAddress() - : HExpression(Primitive::kPrimInt, SideEffects::None(), kNoDexPc) {} + : HExpression(DataType::Type::kInt32, SideEffects::None(), kNoDexPc) {} bool CanBeMoved() const OVERRIDE { return true; } diff --git a/compiler/optimizing/nodes_shared.cc b/compiler/optimizing/nodes_shared.cc index f6d33f015f..f982523634 100644 --- a/compiler/optimizing/nodes_shared.cc +++ b/compiler/optimizing/nodes_shared.cc @@ -42,20 +42,20 @@ void HDataProcWithShifterOp::GetOpInfoFromInstruction(HInstruction* instruction, *shift_amount = instruction->AsUShr()->GetRight()->AsIntConstant()->GetValue(); } else { DCHECK(instruction->IsTypeConversion()); - Primitive::Type result_type = instruction->AsTypeConversion()->GetResultType(); - Primitive::Type input_type = instruction->AsTypeConversion()->GetInputType(); - int result_size = Primitive::ComponentSize(result_type); - int input_size = Primitive::ComponentSize(input_type); + DataType::Type result_type = instruction->AsTypeConversion()->GetResultType(); + DataType::Type input_type = instruction->AsTypeConversion()->GetInputType(); + int result_size = DataType::Size(result_type); + int input_size = DataType::Size(input_type); int min_size = std::min(result_size, input_size); - if (result_type == Primitive::kPrimInt && input_type == Primitive::kPrimLong) { + if (result_type == DataType::Type::kInt32 && input_type == DataType::Type::kInt64) { // There is actually nothing to do. On ARM the high register from the // pair will be ignored. On ARM64 the register will be used as a W // register, discarding the top bits. This is represented by the // default encoding 'LSL 0'. *op_kind = kLSL; *shift_amount = 0; - } else if (result_type == Primitive::kPrimChar || - (input_type == Primitive::kPrimChar && input_size < result_size)) { + } else if (result_type == DataType::Type::kUint16 || + (input_type == DataType::Type::kUint16 && input_size < result_size)) { *op_kind = kUXTH; } else { switch (min_size) { diff --git a/compiler/optimizing/nodes_shared.h b/compiler/optimizing/nodes_shared.h index 075a816f3f..14cbf85c3f 100644 --- a/compiler/optimizing/nodes_shared.h +++ b/compiler/optimizing/nodes_shared.h @@ -26,7 +26,7 @@ namespace art { class HMultiplyAccumulate FINAL : public HExpression<3> { public: - HMultiplyAccumulate(Primitive::Type type, + HMultiplyAccumulate(DataType::Type type, InstructionKind op, HInstruction* accumulator, HInstruction* mul_left, @@ -60,11 +60,11 @@ class HMultiplyAccumulate FINAL : public HExpression<3> { class HBitwiseNegatedRight FINAL : public HBinaryOperation { public: - HBitwiseNegatedRight(Primitive::Type result_type, - InstructionKind op, - HInstruction* left, - HInstruction* right, - uint32_t dex_pc = kNoDexPc) + HBitwiseNegatedRight(DataType::Type result_type, + InstructionKind op, + HInstruction* left, + HInstruction* right, + uint32_t dex_pc = kNoDexPc) : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc), op_kind_(op) { DCHECK(op == HInstruction::kAnd || op == HInstruction::kOr || op == HInstruction::kXor) << op; @@ -122,14 +122,14 @@ class HBitwiseNegatedRight FINAL : public HBinaryOperation { // This instruction computes an intermediate address pointing in the 'middle' of an object. The // result pointer cannot be handled by GC, so extra care is taken to make sure that this value is // never used across anything that can trigger GC. -// The result of this instruction is not a pointer in the sense of `Primitive::kPrimNot`. So we -// represent it by the type `Primitive::kPrimInt`. +// The result of this instruction is not a pointer in the sense of `DataType::Type::kreference`. +// So we represent it by the type `DataType::Type::kInt`. class HIntermediateAddress FINAL : public HExpression<2> { public: HIntermediateAddress(HInstruction* base_address, HInstruction* offset, uint32_t dex_pc) - : HExpression(Primitive::kPrimInt, SideEffects::DependsOnGC(), dex_pc) { - DCHECK_EQ(Primitive::ComponentSize(Primitive::kPrimInt), - Primitive::ComponentSize(Primitive::kPrimNot)) + : HExpression(DataType::Type::kInt32, SideEffects::DependsOnGC(), dex_pc) { + DCHECK_EQ(DataType::Size(DataType::Type::kInt32), + DataType::Size(DataType::Type::kReference)) << "kPrimInt and kPrimNot have different sizes."; SetRawInputAt(0, base_address); SetRawInputAt(1, offset); @@ -171,7 +171,7 @@ class HIntermediateAddressIndex FINAL : public HExpression<3> { public: HIntermediateAddressIndex( HInstruction* index, HInstruction* offset, HInstruction* shift, uint32_t dex_pc) - : HExpression(Primitive::kPrimInt, SideEffects::None(), dex_pc) { + : HExpression(DataType::Type::kInt32, SideEffects::None(), dex_pc) { SetRawInputAt(0, index); SetRawInputAt(1, offset); SetRawInputAt(2, shift); @@ -222,7 +222,7 @@ class HDataProcWithShifterOp FINAL : public HExpression<2> { uint32_t dex_pc = kNoDexPc) : HExpression(instr->GetType(), SideEffects::None(), dex_pc), instr_kind_(instr->GetKind()), op_kind_(op), - shift_amount_(shift & (instr->GetType() == Primitive::kPrimInt + shift_amount_(shift & (instr->GetType() == DataType::Type::kInt32 ? kMaxIntShiftDistance : kMaxLongShiftDistance)) { DCHECK(!instr->HasSideEffects()); diff --git a/compiler/optimizing/nodes_test.cc b/compiler/optimizing/nodes_test.cc index f3a78a064e..ada6177bfb 100644 --- a/compiler/optimizing/nodes_test.cc +++ b/compiler/optimizing/nodes_test.cc @@ -36,7 +36,7 @@ TEST(Node, RemoveInstruction) { graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter = new (&allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); entry->AddInstruction(parameter); entry->AddInstruction(new (&allocator) HGoto()); @@ -79,9 +79,9 @@ TEST(Node, InsertInstruction) { graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter1 = new (&allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); HInstruction* parameter2 = new (&allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); entry->AddInstruction(parameter1); entry->AddInstruction(parameter2); entry->AddInstruction(new (&allocator) HExit()); @@ -107,7 +107,7 @@ TEST(Node, AddInstruction) { graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter = new (&allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); entry->AddInstruction(parameter); ASSERT_FALSE(parameter->HasUses()); @@ -128,7 +128,7 @@ TEST(Node, ParentEnvironment) { graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter1 = new (&allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); HInstruction* with_environment = new (&allocator) HNullCheck(parameter1, 0); entry->AddInstruction(parameter1); entry->AddInstruction(with_environment); diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h index 886d75e5c7..0aac260839 100644 --- a/compiler/optimizing/nodes_vector.h +++ b/compiler/optimizing/nodes_vector.h @@ -65,10 +65,10 @@ class HVecOperation : public HVariableInputSizeInstruction { public: // A SIMD operation looks like a FPU location. // TODO: we could introduce SIMD types in HIR. - static constexpr Primitive::Type kSIMDType = Primitive::kPrimDouble; + static constexpr DataType::Type kSIMDType = DataType::Type::kFloat64; HVecOperation(ArenaAllocator* arena, - Primitive::Type packed_type, + DataType::Type packed_type, SideEffects side_effects, size_t number_of_inputs, size_t vector_length, @@ -90,16 +90,16 @@ class HVecOperation : public HVariableInputSizeInstruction { // Returns the number of bytes in a full vector. size_t GetVectorNumberOfBytes() const { - return vector_length_ * Primitive::ComponentSize(GetPackedType()); + return vector_length_ * DataType::Size(GetPackedType()); } // Returns the type of the vector operation. - Primitive::Type GetType() const OVERRIDE { + DataType::Type GetType() const OVERRIDE { return kSIMDType; } // Returns the true component type packed in a vector. - Primitive::Type GetPackedType() const { + DataType::Type GetPackedType() const { return GetPackedField<TypeField>(); } @@ -122,10 +122,10 @@ class HVecOperation : public HVariableInputSizeInstruction { // Additional packed bits. static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits; static constexpr size_t kFieldTypeSize = - MinimumBitsToStore(static_cast<size_t>(Primitive::kPrimLast)); + MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast)); static constexpr size_t kNumberOfVectorOpPackedBits = kFieldType + kFieldTypeSize; static_assert(kNumberOfVectorOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields."); - using TypeField = BitField<Primitive::Type, kFieldType, kFieldTypeSize>; + using TypeField = BitField<DataType::Type, kFieldType, kFieldTypeSize>; private: const size_t vector_length_; @@ -138,7 +138,7 @@ class HVecUnaryOperation : public HVecOperation { public: HVecUnaryOperation(ArenaAllocator* arena, HInstruction* input, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) : HVecOperation(arena, @@ -164,7 +164,7 @@ class HVecBinaryOperation : public HVecOperation { HVecBinaryOperation(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc) : HVecOperation(arena, @@ -192,13 +192,13 @@ class HVecBinaryOperation : public HVecOperation { class HVecMemoryOperation : public HVecOperation { public: HVecMemoryOperation(ArenaAllocator* arena, - Primitive::Type packed_type, + DataType::Type packed_type, SideEffects side_effects, size_t number_of_inputs, size_t vector_length, uint32_t dex_pc) : HVecOperation(arena, packed_type, side_effects, number_of_inputs, vector_length, dex_pc), - alignment_(Primitive::ComponentSize(packed_type), 0) { + alignment_(DataType::Size(packed_type), 0) { DCHECK_GE(number_of_inputs, 2u); } @@ -224,21 +224,21 @@ class HVecMemoryOperation : public HVecOperation { }; // Packed type consistency checker ("same vector length" integral types may mix freely). -inline static bool HasConsistentPackedTypes(HInstruction* input, Primitive::Type type) { +inline static bool HasConsistentPackedTypes(HInstruction* input, DataType::Type type) { if (input->IsPhi()) { return input->GetType() == HVecOperation::kSIMDType; // carries SIMD } DCHECK(input->IsVecOperation()); - Primitive::Type input_type = input->AsVecOperation()->GetPackedType(); + DataType::Type input_type = input->AsVecOperation()->GetPackedType(); switch (input_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - return type == Primitive::kPrimBoolean || - type == Primitive::kPrimByte; - case Primitive::kPrimChar: - case Primitive::kPrimShort: - return type == Primitive::kPrimChar || - type == Primitive::kPrimShort; + case DataType::Type::kBool: + case DataType::Type::kInt8: + return type == DataType::Type::kBool || + type == DataType::Type::kInt8; + case DataType::Type::kUint16: + case DataType::Type::kInt16: + return type == DataType::Type::kUint16 || + type == DataType::Type::kInt16; default: return type == input_type; } @@ -254,7 +254,7 @@ class HVecReplicateScalar FINAL : public HVecUnaryOperation { public: HVecReplicateScalar(ArenaAllocator* arena, HInstruction* scalar, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) { @@ -279,7 +279,7 @@ class HVecExtractScalar FINAL : public HVecUnaryOperation { public: HVecExtractScalar(ArenaAllocator* arena, HInstruction* input, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, size_t index, uint32_t dex_pc = kNoDexPc) @@ -290,7 +290,7 @@ class HVecExtractScalar FINAL : public HVecUnaryOperation { } // Yields a single component in the vector. - Primitive::Type GetType() const OVERRIDE { + DataType::Type GetType() const OVERRIDE { return GetPackedType(); } @@ -317,7 +317,7 @@ class HVecReduce FINAL : public HVecUnaryOperation { HVecReduce(ArenaAllocator* arena, HInstruction* input, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, ReductionKind kind, uint32_t dex_pc = kNoDexPc) @@ -350,7 +350,7 @@ class HVecCnv FINAL : public HVecUnaryOperation { public: HVecCnv(ArenaAllocator* arena, HInstruction* input, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { @@ -358,8 +358,8 @@ class HVecCnv FINAL : public HVecUnaryOperation { DCHECK_NE(GetInputType(), GetResultType()); // actual convert } - Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); } - Primitive::Type GetResultType() const { return GetPackedType(); } + DataType::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); } + DataType::Type GetResultType() const { return GetPackedType(); } bool CanBeMoved() const OVERRIDE { return true; } @@ -375,7 +375,7 @@ class HVecNeg FINAL : public HVecUnaryOperation { public: HVecNeg(ArenaAllocator* arena, HInstruction* input, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { @@ -396,7 +396,7 @@ class HVecAbs FINAL : public HVecUnaryOperation { public: HVecAbs(ArenaAllocator* arena, HInstruction* input, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { @@ -418,7 +418,7 @@ class HVecNot FINAL : public HVecUnaryOperation { public: HVecNot(ArenaAllocator* arena, HInstruction* input, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { @@ -444,7 +444,7 @@ class HVecAdd FINAL : public HVecBinaryOperation { HVecAdd(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -461,15 +461,15 @@ class HVecAdd FINAL : public HVecBinaryOperation { }; // Performs halving add on every component in the two vectors, viz. -// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ] -// or [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ] +// rounded [ x1, .. , xn ] hradd [ y1, .. , yn ] = [ (x1 + y1 + 1) >> 1, .. , (xn + yn + 1) >> 1 ] +// truncated [ x1, .. , xn ] hadd [ y1, .. , yn ] = [ (x1 + y1) >> 1, .. , (xn + yn ) >> 1 ] // for signed operands x, y (sign extension) or unsigned operands x, y (zero extension). class HVecHalvingAdd FINAL : public HVecBinaryOperation { public: HVecHalvingAdd(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, bool is_unsigned, bool is_rounded, @@ -513,7 +513,7 @@ class HVecSub FINAL : public HVecBinaryOperation { HVecSub(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -536,7 +536,7 @@ class HVecMul FINAL : public HVecBinaryOperation { HVecMul(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -559,7 +559,7 @@ class HVecDiv FINAL : public HVecBinaryOperation { HVecDiv(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -582,7 +582,7 @@ class HVecMin FINAL : public HVecBinaryOperation { HVecMin(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, bool is_unsigned, uint32_t dex_pc = kNoDexPc) @@ -620,7 +620,7 @@ class HVecMax FINAL : public HVecBinaryOperation { HVecMax(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, bool is_unsigned, uint32_t dex_pc = kNoDexPc) @@ -658,7 +658,7 @@ class HVecAnd FINAL : public HVecBinaryOperation { HVecAnd(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -680,7 +680,7 @@ class HVecAndNot FINAL : public HVecBinaryOperation { HVecAndNot(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -702,7 +702,7 @@ class HVecOr FINAL : public HVecBinaryOperation { HVecOr(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -724,7 +724,7 @@ class HVecXor FINAL : public HVecBinaryOperation { HVecXor(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -746,7 +746,7 @@ class HVecShl FINAL : public HVecBinaryOperation { HVecShl(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -768,7 +768,7 @@ class HVecShr FINAL : public HVecBinaryOperation { HVecShr(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -790,7 +790,7 @@ class HVecUShr FINAL : public HVecBinaryOperation { HVecUShr(ArenaAllocator* arena, HInstruction* left, HInstruction* right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { @@ -810,13 +810,13 @@ class HVecUShr FINAL : public HVecBinaryOperation { // // Assigns the given scalar elements to a vector, -// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ] if n == m, -// set( array(x1, .., xm) ) = [ x1, .. , xm, 0, .., 0 ] if m < n. +// viz. set( array(x1, .. , xn) ) = [ x1, .. , xn ] if n == m, +// set( array(x1, .. , xm) ) = [ x1, .. , xm, 0, .. , 0 ] if m < n. class HVecSetScalars FINAL : public HVecOperation { public: HVecSetScalars(ArenaAllocator* arena, - HInstruction** scalars, // array - Primitive::Type packed_type, + HInstruction* scalars[], + DataType::Type packed_type, size_t vector_length, size_t number_of_scalars, uint32_t dex_pc = kNoDexPc) @@ -827,7 +827,7 @@ class HVecSetScalars FINAL : public HVecOperation { vector_length, dex_pc) { for (size_t i = 0; i < number_of_scalars; i++) { - DCHECK(!scalars[i]->IsVecOperation()); + DCHECK(!scalars[i]->IsVecOperation() || scalars[i]->IsVecExtractScalar()); SetRawInputAt(0, scalars[i]); } } @@ -842,9 +842,8 @@ class HVecSetScalars FINAL : public HVecOperation { DISALLOW_COPY_AND_ASSIGN(HVecSetScalars); }; -// Multiplies every component in the two vectors, adds the result vector to the accumulator vector. -// viz. [ acc1, .., accn ] + [ x1, .. , xn ] * [ y1, .. , yn ] = -// [ acc1 + x1 * y1, .. , accn + xn * yn ]. +// Multiplies every component in the two vectors, adds the result vector to the accumulator vector, +// viz. [ a1, .. , an ] + [ x1, .. , xn ] * [ y1, .. , yn ] = [ a1 + x1 * y1, .. , an + xn * yn ]. class HVecMultiplyAccumulate FINAL : public HVecOperation { public: HVecMultiplyAccumulate(ArenaAllocator* arena, @@ -852,7 +851,7 @@ class HVecMultiplyAccumulate FINAL : public HVecOperation { HInstruction* accumulator, HInstruction* mul_left, HInstruction* mul_right, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecOperation(arena, @@ -866,15 +865,11 @@ class HVecMultiplyAccumulate FINAL : public HVecOperation { DCHECK(HasConsistentPackedTypes(accumulator, packed_type)); DCHECK(HasConsistentPackedTypes(mul_left, packed_type)); DCHECK(HasConsistentPackedTypes(mul_right, packed_type)); - SetRawInputAt(kInputAccumulatorIndex, accumulator); - SetRawInputAt(kInputMulLeftIndex, mul_left); - SetRawInputAt(kInputMulRightIndex, mul_right); + SetRawInputAt(0, accumulator); + SetRawInputAt(1, mul_left); + SetRawInputAt(2, mul_right); } - static constexpr int kInputAccumulatorIndex = 0; - static constexpr int kInputMulLeftIndex = 1; - static constexpr int kInputMulRightIndex = 2; - bool CanBeMoved() const OVERRIDE { return true; } bool InstructionDataEquals(const HInstruction* other) const OVERRIDE { @@ -894,6 +889,42 @@ class HVecMultiplyAccumulate FINAL : public HVecOperation { DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate); }; +// Takes the absolute difference of two vectors, and adds the results to +// same-precision or wider-precision components in the accumulator, +// viz. SAD([ a1, .. , am ], [ x1, .. , xn ], [ y1, .. , yn ] = +// [ a1 + sum abs(xi-yi), .. , am + sum abs(xj-yj) ], +// for m <= n and non-overlapping sums. +class HVecSADAccumulate FINAL : public HVecOperation { + public: + HVecSADAccumulate(ArenaAllocator* arena, + HInstruction* accumulator, + HInstruction* sad_left, + HInstruction* sad_right, + DataType::Type packed_type, + size_t vector_length, + uint32_t dex_pc = kNoDexPc) + : HVecOperation(arena, + packed_type, + SideEffects::None(), + /* number_of_inputs */ 3, + vector_length, + dex_pc) { + DCHECK(HasConsistentPackedTypes(accumulator, packed_type)); + DCHECK(sad_left->IsVecOperation()); + DCHECK(sad_right->IsVecOperation()); + DCHECK_EQ(sad_left->AsVecOperation()->GetPackedType(), + sad_right->AsVecOperation()->GetPackedType()); + SetRawInputAt(0, accumulator); + SetRawInputAt(1, sad_left); + SetRawInputAt(2, sad_right); + } + + DECLARE_INSTRUCTION(VecSADAccumulate); + + private: + DISALLOW_COPY_AND_ASSIGN(HVecSADAccumulate); +}; + // Loads a vector from memory, viz. load(mem, 1) // yield the vector [ mem(1), .. , mem(n) ]. class HVecLoad FINAL : public HVecMemoryOperation { @@ -901,7 +932,7 @@ class HVecLoad FINAL : public HVecMemoryOperation { HVecLoad(ArenaAllocator* arena, HInstruction* base, HInstruction* index, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, bool is_string_char_at, uint32_t dex_pc = kNoDexPc) @@ -945,7 +976,7 @@ class HVecStore FINAL : public HVecMemoryOperation { HInstruction* base, HInstruction* index, HInstruction* value, - Primitive::Type packed_type, + DataType::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) : HVecMemoryOperation(arena, diff --git a/compiler/optimizing/nodes_vector_test.cc b/compiler/optimizing/nodes_vector_test.cc index 5a56a2c210..3acdb20b32 100644 --- a/compiler/optimizing/nodes_vector_test.cc +++ b/compiler/optimizing/nodes_vector_test.cc @@ -45,7 +45,7 @@ class NodesVectorTest : public CommonCompilerTest { parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimInt); + DataType::Type::kInt32); entry_block_->AddInstruction(parameter_); } @@ -119,15 +119,15 @@ TEST(NodesVector, AlignmentString) { TEST_F(NodesVectorTest, VectorOperationProperties) { HVecOperation* v0 = new (&allocator_) - HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4); + HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 4); HVecOperation* v1 = new (&allocator_) - HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4); + HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 4); HVecOperation* v2 = new (&allocator_) - HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 2); + HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 2); HVecOperation* v3 = new (&allocator_) - HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimShort, 4); + HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt16, 4); HVecOperation* v4 = new (&allocator_) - HVecStore(&allocator_, parameter_, parameter_, v0, Primitive::kPrimInt, 4); + HVecStore(&allocator_, parameter_, parameter_, v0, DataType::Type::kInt32, 4); EXPECT_TRUE(v0->Equals(v0)); EXPECT_TRUE(v1->Equals(v1)); @@ -149,17 +149,17 @@ TEST_F(NodesVectorTest, VectorOperationProperties) { EXPECT_EQ(4u, v3->GetVectorLength()); EXPECT_EQ(4u, v4->GetVectorLength()); - EXPECT_EQ(Primitive::kPrimDouble, v0->GetType()); - EXPECT_EQ(Primitive::kPrimDouble, v1->GetType()); - EXPECT_EQ(Primitive::kPrimDouble, v2->GetType()); - EXPECT_EQ(Primitive::kPrimDouble, v3->GetType()); - EXPECT_EQ(Primitive::kPrimDouble, v4->GetType()); + EXPECT_EQ(DataType::Type::kFloat64, v0->GetType()); + EXPECT_EQ(DataType::Type::kFloat64, v1->GetType()); + EXPECT_EQ(DataType::Type::kFloat64, v2->GetType()); + EXPECT_EQ(DataType::Type::kFloat64, v3->GetType()); + EXPECT_EQ(DataType::Type::kFloat64, v4->GetType()); - EXPECT_EQ(Primitive::kPrimInt, v0->GetPackedType()); - EXPECT_EQ(Primitive::kPrimInt, v1->GetPackedType()); - EXPECT_EQ(Primitive::kPrimInt, v2->GetPackedType()); - EXPECT_EQ(Primitive::kPrimShort, v3->GetPackedType()); - EXPECT_EQ(Primitive::kPrimInt, v4->GetPackedType()); + EXPECT_EQ(DataType::Type::kInt32, v0->GetPackedType()); + EXPECT_EQ(DataType::Type::kInt32, v1->GetPackedType()); + EXPECT_EQ(DataType::Type::kInt32, v2->GetPackedType()); + EXPECT_EQ(DataType::Type::kInt16, v3->GetPackedType()); + EXPECT_EQ(DataType::Type::kInt32, v4->GetPackedType()); EXPECT_EQ(16u, v0->GetVectorNumberOfBytes()); EXPECT_EQ(16u, v1->GetVectorNumberOfBytes()); @@ -175,12 +175,12 @@ TEST_F(NodesVectorTest, VectorOperationProperties) { } TEST_F(NodesVectorTest, VectorAlignmentAndStringCharAtMatterOnLoad) { - HVecLoad* v0 = new (&allocator_) - HVecLoad(&allocator_, parameter_, parameter_, Primitive::kPrimInt, 4, /*is_string_char_at*/ false); - HVecLoad* v1 = new (&allocator_) - HVecLoad(&allocator_, parameter_, parameter_, Primitive::kPrimInt, 4, /*is_string_char_at*/ false); - HVecLoad* v2 = new (&allocator_) - HVecLoad(&allocator_, parameter_, parameter_, Primitive::kPrimInt, 4, /*is_string_char_at*/ true); + HVecLoad* v0 = new (&allocator_) HVecLoad( + &allocator_, parameter_, parameter_, DataType::Type::kInt32, 4, /*is_string_char_at*/ false); + HVecLoad* v1 = new (&allocator_) HVecLoad( + &allocator_, parameter_, parameter_, DataType::Type::kInt32, 4, /*is_string_char_at*/ false); + HVecLoad* v2 = new (&allocator_) HVecLoad( + &allocator_, parameter_, parameter_, DataType::Type::kInt32, 4, /*is_string_char_at*/ true); EXPECT_TRUE(v0->CanBeMoved()); EXPECT_TRUE(v1->CanBeMoved()); @@ -210,14 +210,14 @@ TEST_F(NodesVectorTest, VectorAlignmentAndStringCharAtMatterOnLoad) { TEST_F(NodesVectorTest, VectorSignMattersOnMin) { HVecOperation* v0 = new (&allocator_) - HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4); + HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 4); HVecMin* v1 = new (&allocator_) - HVecMin(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true); + HVecMin(&allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ true); HVecMin* v2 = new (&allocator_) - HVecMin(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false); + HVecMin(&allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ false); HVecMin* v3 = new (&allocator_) - HVecMin(&allocator_, v0, v0, Primitive::kPrimInt, 2, /*is_unsigned*/ true); + HVecMin(&allocator_, v0, v0, DataType::Type::kInt32, 2, /*is_unsigned*/ true); EXPECT_FALSE(v0->CanBeMoved()); EXPECT_TRUE(v1->CanBeMoved()); @@ -238,14 +238,14 @@ TEST_F(NodesVectorTest, VectorSignMattersOnMin) { TEST_F(NodesVectorTest, VectorSignMattersOnMax) { HVecOperation* v0 = new (&allocator_) - HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4); + HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 4); HVecMax* v1 = new (&allocator_) - HVecMax(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true); + HVecMax(&allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ true); HVecMax* v2 = new (&allocator_) - HVecMax(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false); + HVecMax(&allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ false); HVecMax* v3 = new (&allocator_) - HVecMax(&allocator_, v0, v0, Primitive::kPrimInt, 2, /*is_unsigned*/ true); + HVecMax(&allocator_, v0, v0, DataType::Type::kInt32, 2, /*is_unsigned*/ true); EXPECT_FALSE(v0->CanBeMoved()); EXPECT_TRUE(v1->CanBeMoved()); @@ -266,18 +266,18 @@ TEST_F(NodesVectorTest, VectorSignMattersOnMax) { TEST_F(NodesVectorTest, VectorAttributesMatterOnHalvingAdd) { HVecOperation* v0 = new (&allocator_) - HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4); + HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 4); HVecHalvingAdd* v1 = new (&allocator_) HVecHalvingAdd( - &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true, /*is_rounded*/ true); + &allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ true, /*is_rounded*/ true); HVecHalvingAdd* v2 = new (&allocator_) HVecHalvingAdd( - &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true, /*is_rounded*/ false); + &allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ true, /*is_rounded*/ false); HVecHalvingAdd* v3 = new (&allocator_) HVecHalvingAdd( - &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false, /*is_rounded*/ true); + &allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ false, /*is_rounded*/ true); HVecHalvingAdd* v4 = new (&allocator_) HVecHalvingAdd( - &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false, /*is_rounded*/ false); + &allocator_, v0, v0, DataType::Type::kInt32, 4, /*is_unsigned*/ false, /*is_rounded*/ false); HVecHalvingAdd* v5 = new (&allocator_) HVecHalvingAdd( - &allocator_, v0, v0, Primitive::kPrimInt, 2, /*is_unsigned*/ true, /*is_rounded*/ true); + &allocator_, v0, v0, DataType::Type::kInt32, 2, /*is_unsigned*/ true, /*is_rounded*/ true); EXPECT_FALSE(v0->CanBeMoved()); EXPECT_TRUE(v1->CanBeMoved()); @@ -306,14 +306,14 @@ TEST_F(NodesVectorTest, VectorAttributesMatterOnHalvingAdd) { TEST_F(NodesVectorTest, VectorOperationMattersOnMultiplyAccumulate) { HVecOperation* v0 = new (&allocator_) - HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4); + HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 4); - HVecMultiplyAccumulate* v1 = new (&allocator_) - HVecMultiplyAccumulate(&allocator_, HInstruction::kAdd, v0, v0, v0, Primitive::kPrimInt, 4); - HVecMultiplyAccumulate* v2 = new (&allocator_) - HVecMultiplyAccumulate(&allocator_, HInstruction::kSub, v0, v0, v0, Primitive::kPrimInt, 4); - HVecMultiplyAccumulate* v3 = new (&allocator_) - HVecMultiplyAccumulate(&allocator_, HInstruction::kAdd, v0, v0, v0, Primitive::kPrimInt, 2); + HVecMultiplyAccumulate* v1 = new (&allocator_) HVecMultiplyAccumulate( + &allocator_, HInstruction::kAdd, v0, v0, v0, DataType::Type::kInt32, 4); + HVecMultiplyAccumulate* v2 = new (&allocator_) HVecMultiplyAccumulate( + &allocator_, HInstruction::kSub, v0, v0, v0, DataType::Type::kInt32, 4); + HVecMultiplyAccumulate* v3 = new (&allocator_) HVecMultiplyAccumulate( + &allocator_, HInstruction::kAdd, v0, v0, v0, DataType::Type::kInt32, 2); EXPECT_FALSE(v0->CanBeMoved()); EXPECT_TRUE(v1->CanBeMoved()); @@ -334,14 +334,14 @@ TEST_F(NodesVectorTest, VectorOperationMattersOnMultiplyAccumulate) { TEST_F(NodesVectorTest, VectorKindMattersOnReduce) { HVecOperation* v0 = new (&allocator_) - HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4); + HVecReplicateScalar(&allocator_, parameter_, DataType::Type::kInt32, 4); HVecReduce* v1 = new (&allocator_) HVecReduce( - &allocator_, v0, Primitive::kPrimInt, 4, HVecReduce::kSum); + &allocator_, v0, DataType::Type::kInt32, 4, HVecReduce::kSum); HVecReduce* v2 = new (&allocator_) HVecReduce( - &allocator_, v0, Primitive::kPrimInt, 4, HVecReduce::kMin); + &allocator_, v0, DataType::Type::kInt32, 4, HVecReduce::kMin); HVecReduce* v3 = new (&allocator_) HVecReduce( - &allocator_, v0, Primitive::kPrimInt, 4, HVecReduce::kMax); + &allocator_, v0, DataType::Type::kInt32, 4, HVecReduce::kMax); EXPECT_FALSE(v0->CanBeMoved()); EXPECT_TRUE(v1->CanBeMoved()); diff --git a/compiler/optimizing/nodes_x86.h b/compiler/optimizing/nodes_x86.h index 75893c3129..22e92eab31 100644 --- a/compiler/optimizing/nodes_x86.h +++ b/compiler/optimizing/nodes_x86.h @@ -24,7 +24,7 @@ class HX86ComputeBaseMethodAddress FINAL : public HExpression<0> { public: // Treat the value as an int32_t, but it is really a 32 bit native pointer. HX86ComputeBaseMethodAddress() - : HExpression(Primitive::kPrimInt, SideEffects::None(), kNoDexPc) {} + : HExpression(DataType::Type::kInt32, SideEffects::None(), kNoDexPc) {} bool CanBeMoved() const OVERRIDE { return true; } @@ -61,12 +61,12 @@ class HX86LoadFromConstantTable FINAL : public HExpression<2> { // Version of HNeg with access to the constant table for FP types. class HX86FPNeg FINAL : public HExpression<2> { public: - HX86FPNeg(Primitive::Type result_type, + HX86FPNeg(DataType::Type result_type, HInstruction* input, HX86ComputeBaseMethodAddress* method_base, uint32_t dex_pc) : HExpression(result_type, SideEffects::None(), dex_pc) { - DCHECK(Primitive::IsFloatingPointType(result_type)); + DCHECK(DataType::IsFloatingPointType(result_type)); SetRawInputAt(0, input); SetRawInputAt(1, method_base); } diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 8dd2762a75..10b3fe1731 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -77,6 +77,7 @@ #include "jit/jit_logger.h" #include "jni/quick/jni_compiler.h" #include "licm.h" +#include "linker/linker_patch.h" #include "load_store_analysis.h" #include "load_store_elimination.h" #include "loop_optimization.h" @@ -670,13 +671,29 @@ void OptimizingCompiler::RunArchOptimizations(InstructionSet instruction_set, case kMips: { mips::PcRelativeFixups* pc_relative_fixups = new (arena) mips::PcRelativeFixups(graph, codegen, stats); + SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph); + GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects, "GVN$after_arch"); HOptimization* mips_optimizations[] = { + side_effects, + gvn, pc_relative_fixups, }; RunOptimizations(mips_optimizations, arraysize(mips_optimizations), pass_observer); break; } #endif +#ifdef ART_ENABLE_CODEGEN_mips64 + case kMips64: { + SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph); + GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects, "GVN$after_arch"); + HOptimization* mips64_optimizations[] = { + side_effects, + gvn, + }; + RunOptimizations(mips64_optimizations, arraysize(mips64_optimizations), pass_observer); + break; + } +#endif #ifdef ART_ENABLE_CODEGEN_x86 case kX86: { x86::PcRelativeFixups* pc_relative_fixups = @@ -833,13 +850,13 @@ void OptimizingCompiler::RunOptimizations(HGraph* graph, RunArchOptimizations(driver->GetInstructionSet(), graph, codegen, pass_observer); } -static ArenaVector<LinkerPatch> EmitAndSortLinkerPatches(CodeGenerator* codegen) { - ArenaVector<LinkerPatch> linker_patches(codegen->GetGraph()->GetArena()->Adapter()); +static ArenaVector<linker::LinkerPatch> EmitAndSortLinkerPatches(CodeGenerator* codegen) { + ArenaVector<linker::LinkerPatch> linker_patches(codegen->GetGraph()->GetArena()->Adapter()); codegen->EmitLinkerPatches(&linker_patches); // Sort patches by literal offset. Required for .oat_patches encoding. std::sort(linker_patches.begin(), linker_patches.end(), - [](const LinkerPatch& lhs, const LinkerPatch& rhs) { + [](const linker::LinkerPatch& lhs, const linker::LinkerPatch& rhs) { return lhs.LiteralOffset() < rhs.LiteralOffset(); }); @@ -851,7 +868,7 @@ CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* arena, CodeGenerator* codegen, CompilerDriver* compiler_driver, const DexFile::CodeItem* code_item) const { - ArenaVector<LinkerPatch> linker_patches = EmitAndSortLinkerPatches(codegen); + ArenaVector<linker::LinkerPatch> linker_patches = EmitAndSortLinkerPatches(codegen); ArenaVector<uint8_t> stack_map(arena->Adapter(kArenaAllocStackMaps)); ArenaVector<uint8_t> method_info(arena->Adapter(kArenaAllocStackMaps)); size_t stack_map_size = 0; @@ -876,7 +893,7 @@ CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* arena, ArrayRef<const uint8_t>(method_info), ArrayRef<const uint8_t>(stack_map), ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()), - ArrayRef<const LinkerPatch>(linker_patches)); + ArrayRef<const linker::LinkerPatch>(linker_patches)); return compiled_method; } @@ -989,8 +1006,6 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena, HGraphBuilder builder(graph, &dex_compilation_unit, &dex_compilation_unit, - &dex_file, - *code_item, compiler_driver, codegen.get(), compilation_stats_.get(), diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h index 08493fa177..33f1a4affe 100644 --- a/compiler/optimizing/optimizing_unit_test.h +++ b/compiler/optimizing/optimizing_unit_test.h @@ -50,7 +50,8 @@ LiveInterval* BuildInterval(const size_t ranges[][2], ArenaAllocator* allocator, int reg = -1, HInstruction* defined_by = nullptr) { - LiveInterval* interval = LiveInterval::MakeInterval(allocator, Primitive::kPrimInt, defined_by); + LiveInterval* interval = + LiveInterval::MakeInterval(allocator, DataType::Type::kInt32, defined_by); if (defined_by != nullptr) { defined_by->SetLiveInterval(interval); } @@ -88,7 +89,7 @@ inline HGraph* CreateGraph(ArenaAllocator* allocator) { // Create a control-flow graph from Dex instructions. inline HGraph* CreateCFG(ArenaAllocator* allocator, const uint16_t* data, - Primitive::Type return_type = Primitive::kPrimInt) { + DataType::Type return_type = DataType::Type::kInt32) { const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); HGraph* graph = CreateGraph(allocator); diff --git a/compiler/optimizing/parallel_move_resolver.cc b/compiler/optimizing/parallel_move_resolver.cc index be470ccb7d..2036b4a370 100644 --- a/compiler/optimizing/parallel_move_resolver.cc +++ b/compiler/optimizing/parallel_move_resolver.cc @@ -457,7 +457,7 @@ void ParallelMoveResolverNoSwap::PerformMove(size_t index) { DCHECK_NE(kind, Location::kConstant); Location scratch = AllocateScratchLocationFor(kind); // We only care about the move size. - Primitive::Type type = move->Is64BitMove() ? Primitive::kPrimLong : Primitive::kPrimInt; + DataType::Type type = move->Is64BitMove() ? DataType::Type::kInt64 : DataType::Type::kInt32; // Perform (C -> scratch) move->SetDestination(scratch); EmitMove(index); @@ -521,7 +521,8 @@ void ParallelMoveResolverNoSwap::UpdateMoveSource(Location from, Location to) { } void ParallelMoveResolverNoSwap::AddPendingMove(Location source, - Location destination, Primitive::Type type) { + Location destination, + DataType::Type type) { pending_moves_.push_back(new (allocator_) MoveOperands(source, destination, type, nullptr)); } diff --git a/compiler/optimizing/parallel_move_resolver.h b/compiler/optimizing/parallel_move_resolver.h index 4278861690..e6e069f96e 100644 --- a/compiler/optimizing/parallel_move_resolver.h +++ b/compiler/optimizing/parallel_move_resolver.h @@ -19,8 +19,8 @@ #include "base/arena_containers.h" #include "base/value_object.h" +#include "data_type.h" #include "locations.h" -#include "primitive.h" namespace art { @@ -177,7 +177,7 @@ class ParallelMoveResolverNoSwap : public ParallelMoveResolver { void UpdateMoveSource(Location from, Location to); - void AddPendingMove(Location source, Location destination, Primitive::Type type); + void AddPendingMove(Location source, Location destination, DataType::Type type); void DeletePendingMove(MoveOperands* move); diff --git a/compiler/optimizing/parallel_move_test.cc b/compiler/optimizing/parallel_move_test.cc index 50620f0e7b..cb87cabe1c 100644 --- a/compiler/optimizing/parallel_move_test.cc +++ b/compiler/optimizing/parallel_move_test.cc @@ -158,7 +158,7 @@ static HParallelMove* BuildParallelMove(ArenaAllocator* allocator, moves->AddMove( Location::RegisterLocation(operands[i][0]), Location::RegisterLocation(operands[i][1]), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); } return moves; @@ -264,12 +264,12 @@ TYPED_TEST(ParallelMoveTest, ConstantLast) { moves->AddMove( Location::ConstantLocation(new (&allocator) HIntConstant(0)), Location::RegisterLocation(0), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterLocation(1), Location::RegisterLocation(2), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); resolver.EmitNativeCode(moves); ASSERT_STREQ("(1 -> 2) (C -> 0)", resolver.GetMessage().c_str()); @@ -285,12 +285,12 @@ TYPED_TEST(ParallelMoveTest, Pairs) { moves->AddMove( Location::RegisterLocation(2), Location::RegisterLocation(4), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); resolver.EmitNativeCode(moves); ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str()); @@ -302,12 +302,12 @@ TYPED_TEST(ParallelMoveTest, Pairs) { moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::RegisterLocation(2), Location::RegisterLocation(4), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); resolver.EmitNativeCode(moves); ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str()); @@ -319,12 +319,12 @@ TYPED_TEST(ParallelMoveTest, Pairs) { moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::RegisterLocation(2), Location::RegisterLocation(0), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -339,17 +339,17 @@ TYPED_TEST(ParallelMoveTest, Pairs) { moves->AddMove( Location::RegisterLocation(2), Location::RegisterLocation(7), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterLocation(7), Location::RegisterLocation(1), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -365,17 +365,17 @@ TYPED_TEST(ParallelMoveTest, Pairs) { moves->AddMove( Location::RegisterLocation(2), Location::RegisterLocation(7), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::RegisterLocation(7), Location::RegisterLocation(1), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -391,17 +391,17 @@ TYPED_TEST(ParallelMoveTest, Pairs) { moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::RegisterLocation(2), Location::RegisterLocation(7), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterLocation(7), Location::RegisterLocation(1), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -416,12 +416,12 @@ TYPED_TEST(ParallelMoveTest, Pairs) { moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::RegisterPairLocation(2, 3), Location::RegisterPairLocation(0, 1), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -436,12 +436,12 @@ TYPED_TEST(ParallelMoveTest, Pairs) { moves->AddMove( Location::RegisterPairLocation(2, 3), Location::RegisterPairLocation(0, 1), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -473,17 +473,17 @@ TYPED_TEST(ParallelMoveTest, MultiCycles) { moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::RegisterLocation(2), Location::RegisterLocation(0), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterLocation(3), Location::RegisterLocation(1), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -499,17 +499,17 @@ TYPED_TEST(ParallelMoveTest, MultiCycles) { moves->AddMove( Location::RegisterLocation(2), Location::RegisterLocation(0), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterLocation(3), Location::RegisterLocation(1), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -527,17 +527,17 @@ TYPED_TEST(ParallelMoveTest, MultiCycles) { moves->AddMove( Location::RegisterLocation(10), Location::RegisterLocation(5), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterPairLocation(4, 5), Location::DoubleStackSlot(32), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::DoubleStackSlot(32), Location::RegisterPairLocation(10, 11), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -560,17 +560,17 @@ TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves) { moves->AddMove( Location::RegisterLocation(0), Location::RegisterLocation(1), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::RegisterLocation(1), Location::StackSlot(48), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::StackSlot(48), Location::RegisterLocation(0), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -587,17 +587,17 @@ TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves) { moves->AddMove( Location::RegisterPairLocation(0, 1), Location::RegisterPairLocation(2, 3), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::RegisterPairLocation(2, 3), Location::DoubleStackSlot(32), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::DoubleStackSlot(32), Location::RegisterPairLocation(0, 1), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { @@ -619,17 +619,17 @@ TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves2) { moves->AddMove( Location::RegisterLocation(0), Location::RegisterLocation(3), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); moves->AddMove( Location::RegisterPairLocation(2, 3), Location::RegisterPairLocation(0, 1), - Primitive::kPrimLong, + DataType::Type::kInt64, nullptr); moves->AddMove( Location::RegisterLocation(7), Location::RegisterLocation(2), - Primitive::kPrimInt, + DataType::Type::kInt32, nullptr); resolver.EmitNativeCode(moves); if (TestFixture::has_swap) { diff --git a/compiler/optimizing/pc_relative_fixups_x86.cc b/compiler/optimizing/pc_relative_fixups_x86.cc index 9877e10474..a114e78eb4 100644 --- a/compiler/optimizing/pc_relative_fixups_x86.cc +++ b/compiler/optimizing/pc_relative_fixups_x86.cc @@ -63,7 +63,7 @@ class PCRelativeHandlerVisitor : public HGraphVisitor { void VisitReturn(HReturn* ret) OVERRIDE { HConstant* value = ret->InputAt(0)->AsConstant(); - if ((value != nullptr && Primitive::IsFloatingPointType(value->GetType()))) { + if ((value != nullptr && DataType::IsFloatingPointType(value->GetType()))) { ReplaceInput(ret, value, 0, true); } } @@ -102,7 +102,7 @@ class PCRelativeHandlerVisitor : public HGraphVisitor { void BinaryFP(HBinaryOperation* bin) { HConstant* rhs = bin->InputAt(1)->AsConstant(); - if (rhs != nullptr && Primitive::IsFloatingPointType(rhs->GetType())) { + if (rhs != nullptr && DataType::IsFloatingPointType(rhs->GetType())) { ReplaceInput(bin, rhs, 1, false); } } @@ -132,7 +132,7 @@ class PCRelativeHandlerVisitor : public HGraphVisitor { } void VisitNeg(HNeg* neg) OVERRIDE { - if (Primitive::IsFloatingPointType(neg->GetType())) { + if (DataType::IsFloatingPointType(neg->GetType())) { // We need to replace the HNeg with a HX86FPNeg in order to address the constant area. HX86ComputeBaseMethodAddress* method_address = GetPCRelativeBasePointer(neg); HGraph* graph = GetGraph(); @@ -225,7 +225,7 @@ class PCRelativeHandlerVisitor : public HGraphVisitor { HInputsRef inputs = invoke->GetInputs(); for (size_t i = 0; i < inputs.size(); i++) { HConstant* input = inputs[i]->AsConstant(); - if (input != nullptr && Primitive::IsFloatingPointType(input->GetType())) { + if (input != nullptr && DataType::IsFloatingPointType(input->GetType())) { ReplaceInput(invoke, input, i, true); } } diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc index 2c856cd3d9..b52de367d1 100644 --- a/compiler/optimizing/prepare_for_register_allocation.cc +++ b/compiler/optimizing/prepare_for_register_allocation.cc @@ -77,7 +77,7 @@ void PrepareForRegisterAllocation::VisitArraySet(HArraySet* instruction) { // BoundType (as value input of this ArraySet) with a NullConstant. // If so, this ArraySet no longer needs a type check. if (value->IsNullConstant()) { - DCHECK_EQ(value->GetType(), Primitive::kPrimNot); + DCHECK_EQ(value->GetType(), DataType::Type::kReference); if (instruction->NeedsTypeCheck()) { instruction->ClearNeedsTypeCheck(); } diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 93613a5542..f5064c3057 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -133,7 +133,7 @@ void ReferenceTypePropagation::ValidateTypes() { for (HBasicBlock* block : graph_->GetReversePostOrder()) { for (HInstructionIterator iti(block->GetInstructions()); !iti.Done(); iti.Advance()) { HInstruction* instr = iti.Current(); - if (instr->GetType() == Primitive::kPrimNot) { + if (instr->GetType() == DataType::Type::kReference) { DCHECK(instr->GetReferenceTypeInfo().IsValid()) << "Invalid RTI for instruction: " << instr->DebugName(); if (instr->IsBoundType()) { @@ -555,7 +555,7 @@ void ReferenceTypePropagation::RTPVisitor::UpdateReferenceTypeInfo(HInstruction* dex::TypeIndex type_idx, const DexFile& dex_file, bool is_exact) { - DCHECK_EQ(instr->GetType(), Primitive::kPrimNot); + DCHECK_EQ(instr->GetType(), DataType::Type::kReference); ScopedObjectAccess soa(Thread::Current()); ObjPtr<mirror::DexCache> dex_cache = FindDexCacheWithHint(soa.Self(), dex_file, hint_dex_cache_); @@ -576,7 +576,7 @@ void ReferenceTypePropagation::RTPVisitor::VisitNewArray(HNewArray* instr) { void ReferenceTypePropagation::RTPVisitor::VisitParameterValue(HParameterValue* instr) { // We check if the existing type is valid: the inliner may have set it. - if (instr->GetType() == Primitive::kPrimNot && !instr->GetReferenceTypeInfo().IsValid()) { + if (instr->GetType() == DataType::Type::kReference && !instr->GetReferenceTypeInfo().IsValid()) { UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile(), @@ -586,7 +586,7 @@ void ReferenceTypePropagation::RTPVisitor::VisitParameterValue(HParameterValue* void ReferenceTypePropagation::RTPVisitor::UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info) { - if (instr->GetType() != Primitive::kPrimNot) { + if (instr->GetType() != DataType::Type::kReference) { return; } @@ -612,7 +612,7 @@ void ReferenceTypePropagation::RTPVisitor::VisitStaticFieldGet(HStaticFieldGet* void ReferenceTypePropagation::RTPVisitor::VisitUnresolvedInstanceFieldGet( HUnresolvedInstanceFieldGet* instr) { // TODO: Use descriptor to get the actual type. - if (instr->GetFieldType() == Primitive::kPrimNot) { + if (instr->GetFieldType() == DataType::Type::kReference) { instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti()); } } @@ -620,7 +620,7 @@ void ReferenceTypePropagation::RTPVisitor::VisitUnresolvedInstanceFieldGet( void ReferenceTypePropagation::RTPVisitor::VisitUnresolvedStaticFieldGet( HUnresolvedStaticFieldGet* instr) { // TODO: Use descriptor to get the actual type. - if (instr->GetFieldType() == Primitive::kPrimNot) { + if (instr->GetFieldType() == DataType::Type::kReference) { instr->SetReferenceTypeInfo(instr->GetBlock()->GetGraph()->GetInexactObjectRti()); } } @@ -729,7 +729,7 @@ void ReferenceTypePropagation::RTPVisitor::VisitCheckCast(HCheckCast* check_cast } void ReferenceTypePropagation::VisitPhi(HPhi* phi) { - if (phi->IsDead() || phi->GetType() != Primitive::kPrimNot) { + if (phi->IsDead() || phi->GetType() != DataType::Type::kReference) { return; } @@ -813,7 +813,7 @@ ReferenceTypeInfo ReferenceTypePropagation::MergeTypes(const ReferenceTypeInfo& } void ReferenceTypePropagation::UpdateArrayGet(HArrayGet* instr, HandleCache* handle_cache) { - DCHECK_EQ(Primitive::kPrimNot, instr->GetType()); + DCHECK_EQ(DataType::Type::kReference, instr->GetType()); ReferenceTypeInfo parent_rti = instr->InputAt(0)->GetReferenceTypeInfo(); if (!parent_rti.IsValid()) { @@ -857,7 +857,7 @@ bool ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr) { } void ReferenceTypePropagation::RTPVisitor::VisitInvoke(HInvoke* instr) { - if (instr->GetType() != Primitive::kPrimNot) { + if (instr->GetType() != DataType::Type::kReference) { return; } @@ -868,7 +868,7 @@ void ReferenceTypePropagation::RTPVisitor::VisitInvoke(HInvoke* instr) { } void ReferenceTypePropagation::RTPVisitor::VisitArrayGet(HArrayGet* instr) { - if (instr->GetType() != Primitive::kPrimNot) { + if (instr->GetType() != DataType::Type::kReference) { return; } @@ -989,7 +989,7 @@ void ReferenceTypePropagation::ProcessWorklist() { } void ReferenceTypePropagation::AddToWorklist(HInstruction* instruction) { - DCHECK_EQ(instruction->GetType(), Primitive::kPrimNot) + DCHECK_EQ(instruction->GetType(), DataType::Type::kReference) << instruction->DebugName() << ":" << instruction->GetType(); worklist_.push_back(instruction); } @@ -1000,7 +1000,7 @@ void ReferenceTypePropagation::AddDependentInstructionsToWorklist(HInstruction* if ((user->IsPhi() && user->AsPhi()->IsLive()) || user->IsBoundType() || user->IsNullCheck() - || (user->IsArrayGet() && (user->GetType() == Primitive::kPrimNot))) { + || (user->IsArrayGet() && (user->GetType() == DataType::Type::kReference))) { AddToWorklist(user); } } diff --git a/compiler/optimizing/register_allocation_resolver.cc b/compiler/optimizing/register_allocation_resolver.cc index ce3a4966aa..f0057c3095 100644 --- a/compiler/optimizing/register_allocation_resolver.cc +++ b/compiler/optimizing/register_allocation_resolver.cc @@ -100,24 +100,24 @@ void RegisterAllocationResolver::Resolve(ArrayRef<HInstruction* const> safepoint // [art method ]. size_t slot = current->GetSpillSlot(); switch (current->GetType()) { - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: slot += long_spill_slots; FALLTHROUGH_INTENDED; - case Primitive::kPrimLong: + case DataType::Type::kInt64: slot += float_spill_slots; FALLTHROUGH_INTENDED; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: slot += int_spill_slots; FALLTHROUGH_INTENDED; - case Primitive::kPrimNot: - case Primitive::kPrimInt: - case Primitive::kPrimChar: - case Primitive::kPrimByte: - case Primitive::kPrimBoolean: - case Primitive::kPrimShort: + case DataType::Type::kReference: + case DataType::Type::kInt32: + case DataType::Type::kUint16: + case DataType::Type::kInt8: + case DataType::Type::kBool: + case DataType::Type::kInt16: slot += reserved_out_slots; break; - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unexpected type for interval " << current->GetType(); } current->SetSpillSlot(slot * kVRegSize); @@ -205,12 +205,12 @@ void RegisterAllocationResolver::Resolve(ArrayRef<HInstruction* const> safepoint size_t temp_index = liveness_.GetTempIndex(temp); LocationSummary* locations = at->GetLocations(); switch (temp->GetType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: locations->SetTempAt(temp_index, Location::RegisterLocation(temp->GetRegister())); break; - case Primitive::kPrimDouble: - if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) { + case DataType::Type::kFloat64: + if (codegen_->NeedsTwoRegisters(DataType::Type::kFloat64)) { Location location = Location::FpuRegisterPairLocation( temp->GetRegister(), temp->GetHighInterval()->GetRegister()); locations->SetTempAt(temp_index, location); @@ -383,7 +383,7 @@ void RegisterAllocationResolver::ConnectSiblings(LiveInterval* interval) { safepoint_position = safepoint_position->GetNext()) { DCHECK(current->CoversSlow(safepoint_position->GetPosition())); - if (current->GetType() == Primitive::kPrimNot) { + if (current->GetType() == DataType::Type::kReference) { DCHECK(interval->GetDefinedBy()->IsActualObject()) << interval->GetDefinedBy()->DebugName() << '(' << interval->GetDefinedBy()->GetId() << ')' @@ -507,13 +507,13 @@ void RegisterAllocationResolver::AddMove(HParallelMove* move, Location source, Location destination, HInstruction* instruction, - Primitive::Type type) const { - if (type == Primitive::kPrimLong + DataType::Type type) const { + if (type == DataType::Type::kInt64 && codegen_->ShouldSplitLongMoves() // The parallel move resolver knows how to deal with long constants. && !source.IsConstant()) { - move->AddMove(source.ToLow(), destination.ToLow(), Primitive::kPrimInt, instruction); - move->AddMove(source.ToHigh(), destination.ToHigh(), Primitive::kPrimInt, nullptr); + move->AddMove(source.ToLow(), destination.ToLow(), DataType::Type::kInt32, instruction); + move->AddMove(source.ToHigh(), destination.ToHigh(), DataType::Type::kInt32, nullptr); } else { move->AddMove(source, destination, type, instruction); } diff --git a/compiler/optimizing/register_allocation_resolver.h b/compiler/optimizing/register_allocation_resolver.h index d48b1a0bb9..4a148e0abf 100644 --- a/compiler/optimizing/register_allocation_resolver.h +++ b/compiler/optimizing/register_allocation_resolver.h @@ -20,7 +20,7 @@ #include "base/arena_containers.h" #include "base/array_ref.h" #include "base/value_object.h" -#include "primitive.h" +#include "data_type.h" namespace art { @@ -88,7 +88,7 @@ class RegisterAllocationResolver : ValueObject { Location source, Location destination, HInstruction* instruction, - Primitive::Type type) const; + DataType::Type type) const; ArenaAllocator* const allocator_; CodeGenerator* const codegen_; diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h index 7e1fff8e2b..4375d6851a 100644 --- a/compiler/optimizing/register_allocator.h +++ b/compiler/optimizing/register_allocator.h @@ -21,7 +21,6 @@ #include "base/arena_containers.h" #include "base/arena_object.h" #include "base/macros.h" -#include "primitive.h" namespace art { diff --git a/compiler/optimizing/register_allocator_graph_color.cc b/compiler/optimizing/register_allocator_graph_color.cc index 5e22772844..4ff7315045 100644 --- a/compiler/optimizing/register_allocator_graph_color.cc +++ b/compiler/optimizing/register_allocator_graph_color.cc @@ -540,7 +540,7 @@ class ColoringIteration { }; static bool IsCoreInterval(LiveInterval* interval) { - return !Primitive::IsFloatingPointType(interval->GetType()); + return !DataType::IsFloatingPointType(interval->GetType()); } static size_t ComputeReservedArtMethodSlots(const CodeGenerator& codegen) { @@ -573,7 +573,7 @@ RegisterAllocatorGraphColor::RegisterAllocatorGraphColor(ArenaAllocator* allocat // This includes globally blocked registers, such as the stack pointer. physical_core_nodes_.resize(codegen_->GetNumberOfCoreRegisters(), nullptr); for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) { - LiveInterval* interval = LiveInterval::MakeFixedInterval(allocator_, i, Primitive::kPrimInt); + LiveInterval* interval = LiveInterval::MakeFixedInterval(allocator_, i, DataType::Type::kInt32); physical_core_nodes_[i] = new (allocator_) InterferenceNode(allocator_, interval, liveness); physical_core_nodes_[i]->stage = NodeStage::kPrecolored; @@ -585,7 +585,8 @@ RegisterAllocatorGraphColor::RegisterAllocatorGraphColor(ArenaAllocator* allocat // Initialize physical floating point register live intervals and blocked registers. physical_fp_nodes_.resize(codegen_->GetNumberOfFloatingPointRegisters(), nullptr); for (size_t i = 0; i < codegen_->GetNumberOfFloatingPointRegisters(); ++i) { - LiveInterval* interval = LiveInterval::MakeFixedInterval(allocator_, i, Primitive::kPrimFloat); + LiveInterval* interval = + LiveInterval::MakeFixedInterval(allocator_, i, DataType::Type::kFloat32); physical_fp_nodes_[i] = new (allocator_) InterferenceNode(allocator_, interval, liveness); physical_fp_nodes_[i]->stage = NodeStage::kPrecolored; @@ -936,7 +937,7 @@ void RegisterAllocatorGraphColor::CheckForTempLiveIntervals(HInstruction* instru switch (temp.GetPolicy()) { case Location::kRequiresRegister: { LiveInterval* interval = - LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimInt); + LiveInterval::MakeTempInterval(allocator_, DataType::Type::kInt32); interval->AddTempUse(instruction, i); core_intervals_.push_back(interval); temp_intervals_.push_back(interval); @@ -945,11 +946,11 @@ void RegisterAllocatorGraphColor::CheckForTempLiveIntervals(HInstruction* instru case Location::kRequiresFpuRegister: { LiveInterval* interval = - LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimDouble); + LiveInterval::MakeTempInterval(allocator_, DataType::Type::kFloat64); interval->AddTempUse(instruction, i); fp_intervals_.push_back(interval); temp_intervals_.push_back(interval); - if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) { + if (codegen_->NeedsTwoRegisters(DataType::Type::kFloat64)) { interval->AddHighInterval(/*is_temp*/ true); temp_intervals_.push_back(interval->GetHighInterval()); } @@ -1927,24 +1928,24 @@ void RegisterAllocatorGraphColor::AllocateSpillSlots(const ArenaVector<Interfere // We need to find a spill slot for this interval. Place it in the correct // worklist to be processed later. switch (node->GetInterval()->GetType()) { - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: double_intervals.push_back(parent); break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: long_intervals.push_back(parent); break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: float_intervals.push_back(parent); break; - case Primitive::kPrimNot: - case Primitive::kPrimInt: - case Primitive::kPrimChar: - case Primitive::kPrimByte: - case Primitive::kPrimBoolean: - case Primitive::kPrimShort: + case DataType::Type::kReference: + case DataType::Type::kInt32: + case DataType::Type::kUint16: + case DataType::Type::kInt8: + case DataType::Type::kBool: + case DataType::Type::kInt16: int_intervals.push_back(parent); break; - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unexpected type for interval " << node->GetInterval()->GetType(); UNREACHABLE(); } diff --git a/compiler/optimizing/register_allocator_graph_color.h b/compiler/optimizing/register_allocator_graph_color.h index 548687f784..3f6d674905 100644 --- a/compiler/optimizing/register_allocator_graph_color.h +++ b/compiler/optimizing/register_allocator_graph_color.h @@ -21,7 +21,6 @@ #include "base/arena_containers.h" #include "base/arena_object.h" #include "base/macros.h" -#include "primitive.h" #include "register_allocator.h" namespace art { diff --git a/compiler/optimizing/register_allocator_linear_scan.cc b/compiler/optimizing/register_allocator_linear_scan.cc index ab8d540359..2012cd5847 100644 --- a/compiler/optimizing/register_allocator_linear_scan.cc +++ b/compiler/optimizing/register_allocator_linear_scan.cc @@ -83,8 +83,8 @@ RegisterAllocatorLinearScan::RegisterAllocatorLinearScan(ArenaAllocator* allocat static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) { if (interval == nullptr) return false; - bool is_core_register = (interval->GetType() != Primitive::kPrimDouble) - && (interval->GetType() != Primitive::kPrimFloat); + bool is_core_register = (interval->GetType() != DataType::Type::kFloat64) + && (interval->GetType() != DataType::Type::kFloat32); return processing_core_registers == is_core_register; } @@ -132,9 +132,9 @@ void RegisterAllocatorLinearScan::BlockRegister(Location location, size_t start, LiveInterval* interval = location.IsRegister() ? physical_core_register_intervals_[reg] : physical_fp_register_intervals_[reg]; - Primitive::Type type = location.IsRegister() - ? Primitive::kPrimInt - : Primitive::kPrimFloat; + DataType::Type type = location.IsRegister() + ? DataType::Type::kInt32 + : DataType::Type::kFloat32; if (interval == nullptr) { interval = LiveInterval::MakeFixedInterval(allocator_, reg, type); if (location.IsRegister()) { @@ -237,7 +237,7 @@ void RegisterAllocatorLinearScan::ProcessInstruction(HInstruction* instruction) switch (temp.GetPolicy()) { case Location::kRequiresRegister: { LiveInterval* interval = - LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimInt); + LiveInterval::MakeTempInterval(allocator_, DataType::Type::kInt32); temp_intervals_.push_back(interval); interval->AddTempUse(instruction, i); unhandled_core_intervals_.push_back(interval); @@ -246,10 +246,10 @@ void RegisterAllocatorLinearScan::ProcessInstruction(HInstruction* instruction) case Location::kRequiresFpuRegister: { LiveInterval* interval = - LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimDouble); + LiveInterval::MakeTempInterval(allocator_, DataType::Type::kFloat64); temp_intervals_.push_back(interval); interval->AddTempUse(instruction, i); - if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) { + if (codegen_->NeedsTwoRegisters(DataType::Type::kFloat64)) { interval->AddHighInterval(/* is_temp */ true); LiveInterval* high = interval->GetHighInterval(); temp_intervals_.push_back(high); @@ -266,8 +266,8 @@ void RegisterAllocatorLinearScan::ProcessInstruction(HInstruction* instruction) } } - bool core_register = (instruction->GetType() != Primitive::kPrimDouble) - && (instruction->GetType() != Primitive::kPrimFloat); + bool core_register = (instruction->GetType() != DataType::Type::kFloat64) + && (instruction->GetType() != DataType::Type::kFloat32); if (locations->NeedsSafepoint()) { if (codegen_->IsLeafMethod()) { @@ -1104,24 +1104,24 @@ void RegisterAllocatorLinearScan::AllocateSpillSlotFor(LiveInterval* interval) { ArenaVector<size_t>* spill_slots = nullptr; switch (interval->GetType()) { - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: spill_slots = &double_spill_slots_; break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: spill_slots = &long_spill_slots_; break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: spill_slots = &float_spill_slots_; break; - case Primitive::kPrimNot: - case Primitive::kPrimInt: - case Primitive::kPrimChar: - case Primitive::kPrimByte: - case Primitive::kPrimBoolean: - case Primitive::kPrimShort: + case DataType::Type::kReference: + case DataType::Type::kInt32: + case DataType::Type::kUint16: + case DataType::Type::kInt8: + case DataType::Type::kBool: + case DataType::Type::kInt16: spill_slots = &int_spill_slots_; break; - case Primitive::kPrimVoid: + case DataType::Type::kVoid: LOG(FATAL) << "Unexpected type for interval " << interval->GetType(); } diff --git a/compiler/optimizing/register_allocator_linear_scan.h b/compiler/optimizing/register_allocator_linear_scan.h index b3834f45e4..9c650a44d2 100644 --- a/compiler/optimizing/register_allocator_linear_scan.h +++ b/compiler/optimizing/register_allocator_linear_scan.h @@ -20,7 +20,6 @@ #include "arch/instruction_set.h" #include "base/arena_containers.h" #include "base/macros.h" -#include "primitive.h" #include "register_allocator.h" namespace art { diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc index bcdd7f9cd8..59987e26b6 100644 --- a/compiler/optimizing/register_allocator_test.cc +++ b/compiler/optimizing/register_allocator_test.cc @@ -461,15 +461,15 @@ TEST_F(RegisterAllocatorTest, FreeUntil) { // Add three temps holding the same register, and starting at different positions. // Put the one that should be picked in the middle of the inactive list to ensure // we do not depend on an order. - LiveInterval* interval = LiveInterval::MakeFixedInterval(&allocator, 0, Primitive::kPrimInt); + LiveInterval* interval = LiveInterval::MakeFixedInterval(&allocator, 0, DataType::Type::kInt32); interval->AddRange(40, 50); register_allocator.inactive_.push_back(interval); - interval = LiveInterval::MakeFixedInterval(&allocator, 0, Primitive::kPrimInt); + interval = LiveInterval::MakeFixedInterval(&allocator, 0, DataType::Type::kInt32); interval->AddRange(20, 30); register_allocator.inactive_.push_back(interval); - interval = LiveInterval::MakeFixedInterval(&allocator, 0, Primitive::kPrimInt); + interval = LiveInterval::MakeFixedInterval(&allocator, 0, DataType::Type::kInt32); interval->AddRange(60, 70); register_allocator.inactive_.push_back(interval); @@ -496,7 +496,7 @@ static HGraph* BuildIfElseWithPhi(ArenaAllocator* allocator, graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter = new (allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); entry->AddInstruction(parameter); HBasicBlock* block = new (allocator) HBasicBlock(graph); @@ -505,7 +505,7 @@ static HGraph* BuildIfElseWithPhi(ArenaAllocator* allocator, HInstruction* test = new (allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimBoolean, + DataType::Type::kBool, MemberOffset(22), false, kUnknownFieldIndex, @@ -528,11 +528,11 @@ static HGraph* BuildIfElseWithPhi(ArenaAllocator* allocator, then->AddInstruction(new (allocator) HGoto()); else_->AddInstruction(new (allocator) HGoto()); - *phi = new (allocator) HPhi(allocator, 0, 0, Primitive::kPrimInt); + *phi = new (allocator) HPhi(allocator, 0, 0, DataType::Type::kInt32); join->AddPhi(*phi); *input1 = new (allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimInt, + DataType::Type::kInt32, MemberOffset(42), false, kUnknownFieldIndex, @@ -541,7 +541,7 @@ static HGraph* BuildIfElseWithPhi(ArenaAllocator* allocator, 0); *input2 = new (allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimInt, + DataType::Type::kInt32, MemberOffset(42), false, kUnknownFieldIndex, @@ -658,7 +658,7 @@ static HGraph* BuildFieldReturn(ArenaAllocator* allocator, graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter = new (allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); entry->AddInstruction(parameter); HBasicBlock* block = new (allocator) HBasicBlock(graph); @@ -667,7 +667,7 @@ static HGraph* BuildFieldReturn(ArenaAllocator* allocator, *field = new (allocator) HInstanceFieldGet(parameter, nullptr, - Primitive::kPrimInt, + DataType::Type::kInt32, MemberOffset(42), false, kUnknownFieldIndex, @@ -742,7 +742,7 @@ static HGraph* BuildTwoSubs(ArenaAllocator* allocator, graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter = new (allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); entry->AddInstruction(parameter); HInstruction* constant1 = graph->GetIntConstant(1); @@ -752,9 +752,9 @@ static HGraph* BuildTwoSubs(ArenaAllocator* allocator, graph->AddBlock(block); entry->AddSuccessor(block); - *first_sub = new (allocator) HSub(Primitive::kPrimInt, parameter, constant1); + *first_sub = new (allocator) HSub(DataType::Type::kInt32, parameter, constant1); block->AddInstruction(*first_sub); - *second_sub = new (allocator) HSub(Primitive::kPrimInt, *first_sub, constant2); + *second_sub = new (allocator) HSub(DataType::Type::kInt32, *first_sub, constant2); block->AddInstruction(*second_sub); block->AddInstruction(new (allocator) HExit()); @@ -821,9 +821,9 @@ static HGraph* BuildDiv(ArenaAllocator* allocator, graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* first = new (allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); HInstruction* second = new (allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); entry->AddInstruction(first); entry->AddInstruction(second); @@ -831,7 +831,8 @@ static HGraph* BuildDiv(ArenaAllocator* allocator, graph->AddBlock(block); entry->AddSuccessor(block); - *div = new (allocator) HDiv(Primitive::kPrimInt, first, second, 0); // don't care about dex_pc. + *div = + new (allocator) HDiv(DataType::Type::kInt32, first, second, 0); // don't care about dex_pc. block->AddInstruction(*div); block->AddInstruction(new (allocator) HExit()); @@ -883,13 +884,13 @@ TEST_F(RegisterAllocatorTest, SpillInactive) { graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* one = new (&allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); HInstruction* two = new (&allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); HInstruction* three = new (&allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); HInstruction* four = new (&allocator) HParameterValue( - graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); + graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); entry->AddInstruction(one); entry->AddInstruction(two); entry->AddInstruction(three); @@ -902,7 +903,7 @@ TEST_F(RegisterAllocatorTest, SpillInactive) { // We create a synthesized user requesting a register, to avoid just spilling the // intervals. - HPhi* user = new (&allocator) HPhi(&allocator, 0, 1, Primitive::kPrimInt); + HPhi* user = new (&allocator) HPhi(&allocator, 0, 1, DataType::Type::kInt32); user->AddInput(one); user->SetBlock(block); LocationSummary* locations = new (&allocator) LocationSummary(user, LocationSummary::kNoCall); diff --git a/compiler/optimizing/scheduler.cc b/compiler/optimizing/scheduler.cc index 38cd51bef6..5212e866cf 100644 --- a/compiler/optimizing/scheduler.cc +++ b/compiler/optimizing/scheduler.cc @@ -16,9 +16,11 @@ #include <string> -#include "prepare_for_register_allocation.h" #include "scheduler.h" +#include "data_type-inl.h" +#include "prepare_for_register_allocation.h" + #ifdef ART_ENABLE_CODEGEN_arm64 #include "scheduler_arm64.h" #endif @@ -399,17 +401,7 @@ bool SchedulingGraph::HasImmediateOtherDependency(const HInstruction* instructio } static const std::string InstructionTypeId(const HInstruction* instruction) { - std::string id; - Primitive::Type type = instruction->GetType(); - if (type == Primitive::kPrimNot) { - id.append("l"); - } else { - id.append(Primitive::Descriptor(instruction->GetType())); - } - // Use lower-case to be closer to the `HGraphVisualizer` output. - id[0] = std::tolower(id[0]); - id.append(std::to_string(instruction->GetId())); - return id; + return DataType::TypeId(instruction->GetType()) + std::to_string(instruction->GetId()); } // Ideally we would reuse the graph visualizer code, but it is not available diff --git a/compiler/optimizing/scheduler_arm.cc b/compiler/optimizing/scheduler_arm.cc index 66756a5fc7..110db47eb5 100644 --- a/compiler/optimizing/scheduler_arm.cc +++ b/compiler/optimizing/scheduler_arm.cc @@ -31,15 +31,15 @@ using helpers::Uint64ConstantFrom; void SchedulingLatencyVisitorARM::HandleBinaryOperationLantencies(HBinaryOperation* instr) { switch (instr->GetResultType()) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: // HAdd and HSub long operations translate to ADDS+ADC or SUBS+SBC pairs, // so a bubble (kArmNopLatency) is added to represent the internal carry flag // dependency inside these pairs. last_visited_internal_latency_ = kArmIntegerOpLatency + kArmNopLatency; last_visited_latency_ = kArmIntegerOpLatency; break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: last_visited_latency_ = kArmFloatingPointOpLatency; break; default: @@ -58,12 +58,12 @@ void SchedulingLatencyVisitorARM::VisitSub(HSub* instr) { void SchedulingLatencyVisitorARM::VisitMul(HMul* instr) { switch (instr->GetResultType()) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: last_visited_internal_latency_ = 3 * kArmMulIntegerLatency; last_visited_latency_ = kArmIntegerOpLatency; break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: last_visited_latency_ = kArmMulFloatingPointLatency; break; default: @@ -74,12 +74,12 @@ void SchedulingLatencyVisitorARM::VisitMul(HMul* instr) { void SchedulingLatencyVisitorARM::HandleBitwiseOperationLantencies(HBinaryOperation* instr) { switch (instr->GetResultType()) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: last_visited_internal_latency_ = kArmIntegerOpLatency; last_visited_latency_ = kArmIntegerOpLatency; break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: last_visited_latency_ = kArmFloatingPointOpLatency; break; default: @@ -102,10 +102,10 @@ void SchedulingLatencyVisitorARM::VisitXor(HXor* instr) { void SchedulingLatencyVisitorARM::VisitRor(HRor* instr) { switch (instr->GetResultType()) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: last_visited_latency_ = kArmIntegerOpLatency; break; - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { // HandleLongRotate HInstruction* rhs = instr->GetRight(); if (rhs->IsConstant()) { @@ -130,16 +130,16 @@ void SchedulingLatencyVisitorARM::VisitRor(HRor* instr) { } void SchedulingLatencyVisitorARM::HandleShiftLatencies(HBinaryOperation* instr) { - Primitive::Type type = instr->GetResultType(); + DataType::Type type = instr->GetResultType(); HInstruction* rhs = instr->GetRight(); switch (type) { - case Primitive::kPrimInt: + case DataType::Type::kInt32: if (!rhs->IsConstant()) { last_visited_internal_latency_ = kArmIntegerOpLatency; } last_visited_latency_ = kArmIntegerOpLatency; break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (!rhs->IsConstant()) { last_visited_internal_latency_ = 8 * kArmIntegerOpLatency; } else { @@ -204,7 +204,7 @@ void SchedulingLatencyVisitorARM::HandleGenerateConditionWithZero(IfCondition co } void SchedulingLatencyVisitorARM::HandleGenerateLongTestConstant(HCondition* condition) { - DCHECK_EQ(condition->GetLeft()->GetType(), Primitive::kPrimLong); + DCHECK_EQ(condition->GetLeft()->GetType(), DataType::Type::kInt64); IfCondition cond = condition->GetCondition(); @@ -270,7 +270,7 @@ void SchedulingLatencyVisitorARM::HandleGenerateLongTestConstant(HCondition* con } void SchedulingLatencyVisitorARM::HandleGenerateLongTest(HCondition* condition) { - DCHECK_EQ(condition->GetLeft()->GetType(), Primitive::kPrimLong); + DCHECK_EQ(condition->GetLeft()->GetType(), DataType::Type::kInt64); IfCondition cond = condition->GetCondition(); @@ -301,13 +301,13 @@ void SchedulingLatencyVisitorARM::HandleGenerateLongTest(HCondition* condition) // The GenerateTest series of function all counted as internal latency. void SchedulingLatencyVisitorARM::HandleGenerateTest(HCondition* condition) { - const Primitive::Type type = condition->GetLeft()->GetType(); + const DataType::Type type = condition->GetLeft()->GetType(); - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { condition->InputAt(1)->IsConstant() ? HandleGenerateLongTestConstant(condition) : HandleGenerateLongTest(condition); - } else if (Primitive::IsFloatingPointType(type)) { + } else if (DataType::IsFloatingPointType(type)) { // GenerateVcmp + Vmrs last_visited_internal_latency_ += 2 * kArmFloatingPointOpLatency; } else { @@ -317,7 +317,7 @@ void SchedulingLatencyVisitorARM::HandleGenerateTest(HCondition* condition) { } bool SchedulingLatencyVisitorARM::CanGenerateTest(HCondition* condition) { - if (condition->GetLeft()->GetType() == Primitive::kPrimLong) { + if (condition->GetLeft()->GetType() == DataType::Type::kInt64) { HInstruction* right = condition->InputAt(1); if (right->IsConstant()) { @@ -353,7 +353,7 @@ void SchedulingLatencyVisitorARM::HandleGenerateConditionGeneric(HCondition* con } void SchedulingLatencyVisitorARM::HandleGenerateEqualLong(HCondition* cond) { - DCHECK_EQ(cond->GetLeft()->GetType(), Primitive::kPrimLong); + DCHECK_EQ(cond->GetLeft()->GetType(), DataType::Type::kInt64); IfCondition condition = cond->GetCondition(); @@ -374,7 +374,7 @@ void SchedulingLatencyVisitorARM::HandleGenerateLongComparesAndJumps() { } void SchedulingLatencyVisitorARM::HandleGenerateConditionLong(HCondition* cond) { - DCHECK_EQ(cond->GetLeft()->GetType(), Primitive::kPrimLong); + DCHECK_EQ(cond->GetLeft()->GetType(), DataType::Type::kInt64); IfCondition condition = cond->GetCondition(); HInstruction* right = cond->InputAt(1); @@ -424,11 +424,11 @@ void SchedulingLatencyVisitorARM::HandleGenerateConditionLong(HCondition* cond) } void SchedulingLatencyVisitorARM::HandleGenerateConditionIntegralOrNonPrimitive(HCondition* cond) { - const Primitive::Type type = cond->GetLeft()->GetType(); + const DataType::Type type = cond->GetLeft()->GetType(); - DCHECK(Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) << type; + DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type; - if (type == Primitive::kPrimLong) { + if (type == DataType::Type::kInt64) { HandleGenerateConditionLong(cond); return; } @@ -482,19 +482,19 @@ void SchedulingLatencyVisitorARM::HandleCondition(HCondition* cond) { return; } - const Primitive::Type type = cond->GetLeft()->GetType(); + const DataType::Type type = cond->GetLeft()->GetType(); - if (Primitive::IsFloatingPointType(type)) { + if (DataType::IsFloatingPointType(type)) { HandleGenerateConditionGeneric(cond); return; } - DCHECK(Primitive::IsIntegralType(type) || type == Primitive::kPrimNot) << type; + DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type; const IfCondition condition = cond->GetCondition(); - if (type == Primitive::kPrimBoolean && - cond->GetRight()->GetType() == Primitive::kPrimBoolean && + if (type == DataType::Type::kBool && + cond->GetRight()->GetType() == DataType::Type::kBool && (condition == kCondEQ || condition == kCondNE)) { if (condition == kCondEQ) { last_visited_internal_latency_ = kArmIntegerOpLatency; @@ -511,20 +511,20 @@ void SchedulingLatencyVisitorARM::VisitCondition(HCondition* instr) { } void SchedulingLatencyVisitorARM::VisitCompare(HCompare* instr) { - Primitive::Type type = instr->InputAt(0)->GetType(); + DataType::Type type = instr->InputAt(0)->GetType(); switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: last_visited_internal_latency_ = 2 * kArmIntegerOpLatency; break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: last_visited_internal_latency_ = 2 * kArmIntegerOpLatency + 3 * kArmBranchLatency; break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: last_visited_internal_latency_ = kArmIntegerOpLatency + 2 * kArmFloatingPointOpLatency; break; default: @@ -535,7 +535,7 @@ void SchedulingLatencyVisitorARM::VisitCompare(HCompare* instr) { } void SchedulingLatencyVisitorARM::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) { - if (instruction->GetResultType() == Primitive::kPrimInt) { + if (instruction->GetResultType() == DataType::Type::kInt32) { last_visited_latency_ = kArmIntegerOpLatency; } else { last_visited_internal_latency_ = kArmIntegerOpLatency; @@ -566,7 +566,7 @@ void SchedulingLatencyVisitorARM::HandleGenerateDataProc(HDataProcWithShifterOp* } void SchedulingLatencyVisitorARM::HandleGenerateLongDataProc(HDataProcWithShifterOp* instruction) { - DCHECK_EQ(instruction->GetType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64); DCHECK(HDataProcWithShifterOp::IsShiftOp(instruction->GetOpKind())); const uint32_t shift_value = instruction->GetShiftAmount(); @@ -595,10 +595,10 @@ void SchedulingLatencyVisitorARM::HandleGenerateLongDataProc(HDataProcWithShifte void SchedulingLatencyVisitorARM::VisitDataProcWithShifterOp(HDataProcWithShifterOp* instruction) { const HDataProcWithShifterOp::OpKind op_kind = instruction->GetOpKind(); - if (instruction->GetType() == Primitive::kPrimInt) { + if (instruction->GetType() == DataType::Type::kInt32) { HandleGenerateDataProcInstruction(); } else { - DCHECK_EQ(instruction->GetType(), Primitive::kPrimLong); + DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64); if (HDataProcWithShifterOp::IsExtensionOp(op_kind)) { HandleGenerateDataProc(instruction); } else { @@ -624,7 +624,7 @@ void SchedulingLatencyVisitorARM::VisitMultiplyAccumulate(HMultiplyAccumulate* A } void SchedulingLatencyVisitorARM::VisitArrayGet(HArrayGet* instruction) { - Primitive::Type type = instruction->GetType(); + DataType::Type type = instruction->GetType(); const bool maybe_compressed_char_at = mirror::kUseStringCompression && instruction->IsStringCharAt(); HInstruction* array_instr = instruction->GetArray(); @@ -632,11 +632,11 @@ void SchedulingLatencyVisitorARM::VisitArrayGet(HArrayGet* instruction) { HInstruction* index = instruction->InputAt(1); switch (type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: { if (maybe_compressed_char_at) { last_visited_internal_latency_ += kArmMemoryLoadLatency; } @@ -664,7 +664,7 @@ void SchedulingLatencyVisitorARM::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) { last_visited_latency_ = kArmLoadWithBakerReadBarrierLatency; } else { @@ -681,7 +681,7 @@ void SchedulingLatencyVisitorARM::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (index->IsConstant()) { last_visited_latency_ = kArmMemoryLoadLatency; } else { @@ -691,7 +691,7 @@ void SchedulingLatencyVisitorARM::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (index->IsConstant()) { last_visited_latency_ = kArmMemoryLoadLatency; } else { @@ -701,7 +701,7 @@ void SchedulingLatencyVisitorARM::VisitArrayGet(HArrayGet* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (index->IsConstant()) { last_visited_latency_ = kArmMemoryLoadLatency; } else { @@ -727,16 +727,16 @@ void SchedulingLatencyVisitorARM::VisitArrayLength(HArrayLength* instruction) { void SchedulingLatencyVisitorARM::VisitArraySet(HArraySet* instruction) { HInstruction* index = instruction->InputAt(1); - Primitive::Type value_type = instruction->GetComponentType(); + DataType::Type value_type = instruction->GetComponentType(); HInstruction* array_instr = instruction->GetArray(); bool has_intermediate_address = array_instr->IsIntermediateAddress(); switch (value_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: { + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: { if (index->IsConstant()) { last_visited_latency_ = kArmMemoryStoreLatency; } else { @@ -749,7 +749,7 @@ void SchedulingLatencyVisitorARM::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimNot: { + case DataType::Type::kReference: { if (instruction->InputAt(2)->IsNullConstant()) { if (index->IsConstant()) { last_visited_latency_ = kArmMemoryStoreLatency; @@ -765,7 +765,7 @@ void SchedulingLatencyVisitorARM::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimLong: { + case DataType::Type::kInt64: { if (index->IsConstant()) { last_visited_latency_ = kArmMemoryLoadLatency; } else { @@ -775,7 +775,7 @@ void SchedulingLatencyVisitorARM::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimFloat: { + case DataType::Type::kFloat32: { if (index->IsConstant()) { last_visited_latency_ = kArmMemoryLoadLatency; } else { @@ -785,7 +785,7 @@ void SchedulingLatencyVisitorARM::VisitArraySet(HArraySet* instruction) { break; } - case Primitive::kPrimDouble: { + case DataType::Type::kFloat64: { if (index->IsConstant()) { last_visited_latency_ = kArmMemoryLoadLatency; } else { @@ -823,9 +823,9 @@ void SchedulingLatencyVisitorARM::HandleDivRemConstantIntegralLatencies(int32_t } void SchedulingLatencyVisitorARM::VisitDiv(HDiv* instruction) { - Primitive::Type type = instruction->GetResultType(); + DataType::Type type = instruction->GetResultType(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { HInstruction* rhs = instruction->GetRight(); if (rhs->IsConstant()) { int32_t imm = Int32ConstantFrom(rhs->AsConstant()); @@ -835,10 +835,10 @@ void SchedulingLatencyVisitorARM::VisitDiv(HDiv* instruction) { } break; } - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: last_visited_latency_ = kArmDivFloatLatency; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: last_visited_latency_ = kArmDivDoubleLatency; break; default: @@ -886,9 +886,9 @@ void SchedulingLatencyVisitorARM::VisitNewInstance(HNewInstance* instruction) { } void SchedulingLatencyVisitorARM::VisitRem(HRem* instruction) { - Primitive::Type type = instruction->GetResultType(); + DataType::Type type = instruction->GetResultType(); switch (type) { - case Primitive::kPrimInt: { + case DataType::Type::kInt32: { HInstruction* rhs = instruction->GetRight(); if (rhs->IsConstant()) { int32_t imm = Int32ConstantFrom(rhs->AsConstant()); @@ -911,19 +911,19 @@ void SchedulingLatencyVisitorARM::HandleFieldGetLatencies(HInstruction* instruct DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet()); DCHECK(codegen_ != nullptr); bool is_volatile = field_info.IsVolatile(); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd(); switch (field_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: + case DataType::Type::kInt32: last_visited_latency_ = kArmMemoryLoadLatency; break; - case Primitive::kPrimNot: + case DataType::Type::kReference: if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) { last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency; last_visited_latency_ = kArmMemoryLoadLatency; @@ -932,7 +932,7 @@ void SchedulingLatencyVisitorARM::HandleFieldGetLatencies(HInstruction* instruct } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (is_volatile && !atomic_ldrd_strd) { last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency; last_visited_latency_ = kArmMemoryLoadLatency; @@ -941,11 +941,11 @@ void SchedulingLatencyVisitorARM::HandleFieldGetLatencies(HInstruction* instruct } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: last_visited_latency_ = kArmMemoryLoadLatency; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: if (is_volatile && !atomic_ldrd_strd) { last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency + kArmMemoryLoadLatency; @@ -970,16 +970,16 @@ void SchedulingLatencyVisitorARM::HandleFieldSetLatencies(HInstruction* instruct DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet()); DCHECK(codegen_ != nullptr); bool is_volatile = field_info.IsVolatile(); - Primitive::Type field_type = field_info.GetFieldType(); + DataType::Type field_type = field_info.GetFieldType(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1)); bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd(); switch (field_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimShort: - case Primitive::kPrimChar: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kInt16: + case DataType::Type::kUint16: if (is_volatile) { last_visited_internal_latency_ = kArmMemoryBarrierLatency + kArmMemoryStoreLatency; last_visited_latency_ = kArmMemoryBarrierLatency; @@ -988,15 +988,15 @@ void SchedulingLatencyVisitorARM::HandleFieldSetLatencies(HInstruction* instruct } break; - case Primitive::kPrimInt: - case Primitive::kPrimNot: + case DataType::Type::kInt32: + case DataType::Type::kReference: if (kPoisonHeapReferences && needs_write_barrier) { last_visited_internal_latency_ += kArmIntegerOpLatency * 2; } last_visited_latency_ = kArmMemoryStoreLatency; break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: if (is_volatile && !atomic_ldrd_strd) { last_visited_internal_latency_ = kArmIntegerOpLatency + kArmMemoryLoadLatency + kArmMemoryStoreLatency; @@ -1006,11 +1006,11 @@ void SchedulingLatencyVisitorARM::HandleFieldSetLatencies(HInstruction* instruct } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: last_visited_latency_ = kArmMemoryStoreLatency; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: if (is_volatile && !atomic_ldrd_strd) { last_visited_internal_latency_ = kArmIntegerOpLatency + kArmIntegerOpLatency + kArmMemoryLoadLatency + kArmMemoryStoreLatency; @@ -1043,23 +1043,23 @@ void SchedulingLatencyVisitorARM::VisitSuspendCheck(HSuspendCheck* instruction) } void SchedulingLatencyVisitorARM::VisitTypeConversion(HTypeConversion* instr) { - Primitive::Type result_type = instr->GetResultType(); - Primitive::Type input_type = instr->GetInputType(); + DataType::Type result_type = instr->GetResultType(); + DataType::Type input_type = instr->GetInputType(); switch (result_type) { - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: last_visited_latency_ = kArmIntegerOpLatency; // SBFX or UBFX break; - case Primitive::kPrimInt: + case DataType::Type::kInt32: switch (input_type) { - case Primitive::kPrimLong: + case DataType::Type::kInt64: last_visited_latency_ = kArmIntegerOpLatency; // MOV break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency; last_visited_latency_ = kArmFloatingPointOpLatency; break; @@ -1069,19 +1069,19 @@ void SchedulingLatencyVisitorARM::VisitTypeConversion(HTypeConversion* instr) { } break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: switch (input_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: // MOV and extension last_visited_internal_latency_ = kArmIntegerOpLatency; last_visited_latency_ = kArmIntegerOpLatency; break; - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: + case DataType::Type::kFloat32: + case DataType::Type::kFloat64: // invokes runtime last_visited_internal_latency_ = kArmCallInternalLatency; break; @@ -1092,21 +1092,21 @@ void SchedulingLatencyVisitorARM::VisitTypeConversion(HTypeConversion* instr) { } break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: switch (input_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency; last_visited_latency_ = kArmFloatingPointOpLatency; break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: // invokes runtime last_visited_internal_latency_ = kArmCallInternalLatency; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: last_visited_latency_ = kArmFloatingPointOpLatency; break; default: @@ -1115,21 +1115,21 @@ void SchedulingLatencyVisitorARM::VisitTypeConversion(HTypeConversion* instr) { } break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: switch (input_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: + case DataType::Type::kBool: + case DataType::Type::kInt8: + case DataType::Type::kUint16: + case DataType::Type::kInt16: + case DataType::Type::kInt32: last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency; last_visited_latency_ = kArmFloatingPointOpLatency; break; - case Primitive::kPrimLong: + case DataType::Type::kInt64: last_visited_internal_latency_ = 5 * kArmFloatingPointOpLatency; last_visited_latency_ = kArmFloatingPointOpLatency; break; - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: last_visited_latency_ = kArmFloatingPointOpLatency; break; default: diff --git a/compiler/optimizing/scheduler_arm64.cc b/compiler/optimizing/scheduler_arm64.cc index 1d9d28ab24..7bcf4e75a9 100644 --- a/compiler/optimizing/scheduler_arm64.cc +++ b/compiler/optimizing/scheduler_arm64.cc @@ -24,7 +24,7 @@ namespace art { namespace arm64 { void SchedulingLatencyVisitorARM64::VisitBinaryOperation(HBinaryOperation* instr) { - last_visited_latency_ = Primitive::IsFloatingPointType(instr->GetResultType()) + last_visited_latency_ = DataType::IsFloatingPointType(instr->GetResultType()) ? kArm64FloatingPointOpLatency : kArm64IntegerOpLatency; } @@ -80,12 +80,12 @@ void SchedulingLatencyVisitorARM64::VisitBoundsCheck(HBoundsCheck* ATTRIBUTE_UNU } void SchedulingLatencyVisitorARM64::VisitDiv(HDiv* instr) { - Primitive::Type type = instr->GetResultType(); + DataType::Type type = instr->GetResultType(); switch (type) { - case Primitive::kPrimFloat: + case DataType::Type::kFloat32: last_visited_latency_ = kArm64DivFloatLatency; break; - case Primitive::kPrimDouble: + case DataType::Type::kFloat64: last_visited_latency_ = kArm64DivDoubleLatency; break; default: @@ -133,7 +133,7 @@ void SchedulingLatencyVisitorARM64::VisitLoadString(HLoadString* ATTRIBUTE_UNUSE } void SchedulingLatencyVisitorARM64::VisitMul(HMul* instr) { - last_visited_latency_ = Primitive::IsFloatingPointType(instr->GetResultType()) + last_visited_latency_ = DataType::IsFloatingPointType(instr->GetResultType()) ? kArm64MulFloatingPointLatency : kArm64MulIntegerLatency; } @@ -153,7 +153,7 @@ void SchedulingLatencyVisitorARM64::VisitNewInstance(HNewInstance* instruction) } void SchedulingLatencyVisitorARM64::VisitRem(HRem* instruction) { - if (Primitive::IsFloatingPointType(instruction->GetResultType())) { + if (DataType::IsFloatingPointType(instruction->GetResultType())) { last_visited_internal_latency_ = kArm64CallInternalLatency; last_visited_latency_ = kArm64CallLatency; } else { @@ -194,8 +194,8 @@ void SchedulingLatencyVisitorARM64::VisitSuspendCheck(HSuspendCheck* instruction } void SchedulingLatencyVisitorARM64::VisitTypeConversion(HTypeConversion* instr) { - if (Primitive::IsFloatingPointType(instr->GetResultType()) || - Primitive::IsFloatingPointType(instr->GetInputType())) { + if (DataType::IsFloatingPointType(instr->GetResultType()) || + DataType::IsFloatingPointType(instr->GetInputType())) { last_visited_latency_ = kArm64TypeConversionFloatingPointIntegerLatency; } else { last_visited_latency_ = kArm64IntegerOpLatency; @@ -203,7 +203,7 @@ void SchedulingLatencyVisitorARM64::VisitTypeConversion(HTypeConversion* instr) } void SchedulingLatencyVisitorARM64::HandleSimpleArithmeticSIMD(HVecOperation *instr) { - if (Primitive::IsFloatingPointType(instr->GetPackedType())) { + if (DataType::IsFloatingPointType(instr->GetPackedType())) { last_visited_latency_ = kArm64SIMDFloatingPointOpLatency; } else { last_visited_latency_ = kArm64SIMDIntegerOpLatency; @@ -236,7 +236,7 @@ void SchedulingLatencyVisitorARM64::VisitVecAbs(HVecAbs* instr) { } void SchedulingLatencyVisitorARM64::VisitVecNot(HVecNot* instr) { - if (instr->GetPackedType() == Primitive::kPrimBoolean) { + if (instr->GetPackedType() == DataType::Type::kBool) { last_visited_internal_latency_ = kArm64SIMDIntegerOpLatency; } last_visited_latency_ = kArm64SIMDIntegerOpLatency; @@ -255,7 +255,7 @@ void SchedulingLatencyVisitorARM64::VisitVecSub(HVecSub* instr) { } void SchedulingLatencyVisitorARM64::VisitVecMul(HVecMul* instr) { - if (Primitive::IsFloatingPointType(instr->GetPackedType())) { + if (DataType::IsFloatingPointType(instr->GetPackedType())) { last_visited_latency_ = kArm64SIMDMulFloatingPointLatency; } else { last_visited_latency_ = kArm64SIMDMulIntegerLatency; @@ -263,10 +263,10 @@ void SchedulingLatencyVisitorARM64::VisitVecMul(HVecMul* instr) { } void SchedulingLatencyVisitorARM64::VisitVecDiv(HVecDiv* instr) { - if (instr->GetPackedType() == Primitive::kPrimFloat) { + if (instr->GetPackedType() == DataType::Type::kFloat32) { last_visited_latency_ = kArm64SIMDDivFloatLatency; } else { - DCHECK(instr->GetPackedType() == Primitive::kPrimDouble); + DCHECK(instr->GetPackedType() == DataType::Type::kFloat64); last_visited_latency_ = kArm64SIMDDivDoubleLatency; } } @@ -327,9 +327,9 @@ void SchedulingLatencyVisitorARM64::HandleVecAddress( void SchedulingLatencyVisitorARM64::VisitVecLoad(HVecLoad* instr) { last_visited_internal_latency_ = 0; - size_t size = Primitive::ComponentSize(instr->GetPackedType()); + size_t size = DataType::Size(instr->GetPackedType()); - if (instr->GetPackedType() == Primitive::kPrimChar + if (instr->GetPackedType() == DataType::Type::kUint16 && mirror::kUseStringCompression && instr->IsStringCharAt()) { // Set latencies for the uncompressed case. @@ -344,7 +344,7 @@ void SchedulingLatencyVisitorARM64::VisitVecLoad(HVecLoad* instr) { void SchedulingLatencyVisitorARM64::VisitVecStore(HVecStore* instr) { last_visited_internal_latency_ = 0; - size_t size = Primitive::ComponentSize(instr->GetPackedType()); + size_t size = DataType::Size(instr->GetPackedType()); HandleVecAddress(instr, size); last_visited_latency_ = kArm64SIMDMemoryStoreLatency; } diff --git a/compiler/optimizing/scheduler_test.cc b/compiler/optimizing/scheduler_test.cc index cdb6666f83..0e6e0c5a3d 100644 --- a/compiler/optimizing/scheduler_test.cc +++ b/compiler/optimizing/scheduler_test.cc @@ -103,18 +103,20 @@ class SchedulerTest : public CommonCompilerTest { HInstruction* array = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimNot); + DataType::Type::kReference); HInstruction* c1 = graph_->GetIntConstant(1); HInstruction* c2 = graph_->GetIntConstant(10); - HInstruction* add1 = new (&allocator_) HAdd(Primitive::kPrimInt, c1, c2); - HInstruction* add2 = new (&allocator_) HAdd(Primitive::kPrimInt, add1, c2); - HInstruction* mul = new (&allocator_) HMul(Primitive::kPrimInt, add1, add2); + HInstruction* add1 = new (&allocator_) HAdd(DataType::Type::kInt32, c1, c2); + HInstruction* add2 = new (&allocator_) HAdd(DataType::Type::kInt32, add1, c2); + HInstruction* mul = new (&allocator_) HMul(DataType::Type::kInt32, add1, add2); HInstruction* div_check = new (&allocator_) HDivZeroCheck(add2, 0); - HInstruction* div = new (&allocator_) HDiv(Primitive::kPrimInt, add1, div_check, 0); - HInstruction* array_get1 = new (&allocator_) HArrayGet(array, add1, Primitive::kPrimInt, 0); - HInstruction* array_set1 = new (&allocator_) HArraySet(array, add1, add2, Primitive::kPrimInt, 0); - HInstruction* array_get2 = new (&allocator_) HArrayGet(array, add1, Primitive::kPrimInt, 0); - HInstruction* array_set2 = new (&allocator_) HArraySet(array, add1, add2, Primitive::kPrimInt, 0); + HInstruction* div = new (&allocator_) HDiv(DataType::Type::kInt32, add1, div_check, 0); + HInstruction* array_get1 = new (&allocator_) HArrayGet(array, add1, DataType::Type::kInt32, 0); + HInstruction* array_set1 = + new (&allocator_) HArraySet(array, add1, add2, DataType::Type::kInt32, 0); + HInstruction* array_get2 = new (&allocator_) HArrayGet(array, add1, DataType::Type::kInt32, 0); + HInstruction* array_set2 = + new (&allocator_) HArraySet(array, add1, add2, DataType::Type::kInt32, 0); DCHECK(div_check->CanThrow()); @@ -204,37 +206,41 @@ class SchedulerTest : public CommonCompilerTest { HInstruction* arr = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimNot); + DataType::Type::kReference); HInstruction* i = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, - Primitive::kPrimInt); + DataType::Type::kInt32); HInstruction* j = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, - Primitive::kPrimInt); + DataType::Type::kInt32); HInstruction* object = new (&allocator_) HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, - Primitive::kPrimNot); + DataType::Type::kReference); HInstruction* c0 = graph_->GetIntConstant(0); HInstruction* c1 = graph_->GetIntConstant(1); - HInstruction* add0 = new (&allocator_) HAdd(Primitive::kPrimInt, i, c0); - HInstruction* add1 = new (&allocator_) HAdd(Primitive::kPrimInt, i, c1); - HInstruction* sub0 = new (&allocator_) HSub(Primitive::kPrimInt, i, c0); - HInstruction* sub1 = new (&allocator_) HSub(Primitive::kPrimInt, i, c1); - HInstruction* arr_set_0 = new (&allocator_) HArraySet(arr, c0, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set_1 = new (&allocator_) HArraySet(arr, c1, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set_i = new (&allocator_) HArraySet(arr, i, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set_add0 = new (&allocator_) HArraySet(arr, add0, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set_add1 = new (&allocator_) HArraySet(arr, add1, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set_sub0 = new (&allocator_) HArraySet(arr, sub0, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set_sub1 = new (&allocator_) HArraySet(arr, sub1, c0, Primitive::kPrimInt, 0); - HInstruction* arr_set_j = new (&allocator_) HArraySet(arr, j, c0, Primitive::kPrimInt, 0); + HInstruction* add0 = new (&allocator_) HAdd(DataType::Type::kInt32, i, c0); + HInstruction* add1 = new (&allocator_) HAdd(DataType::Type::kInt32, i, c1); + HInstruction* sub0 = new (&allocator_) HSub(DataType::Type::kInt32, i, c0); + HInstruction* sub1 = new (&allocator_) HSub(DataType::Type::kInt32, i, c1); + HInstruction* arr_set_0 = new (&allocator_) HArraySet(arr, c0, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set_1 = new (&allocator_) HArraySet(arr, c1, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set_i = new (&allocator_) HArraySet(arr, i, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set_add0 = + new (&allocator_) HArraySet(arr, add0, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set_add1 = + new (&allocator_) HArraySet(arr, add1, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set_sub0 = + new (&allocator_) HArraySet(arr, sub0, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set_sub1 = + new (&allocator_) HArraySet(arr, sub1, c0, DataType::Type::kInt32, 0); + HInstruction* arr_set_j = new (&allocator_) HArraySet(arr, j, c0, DataType::Type::kInt32, 0); HInstanceFieldSet* set_field10 = new (&allocator_) HInstanceFieldSet(object, c1, nullptr, - Primitive::kPrimInt, + DataType::Type::kInt32, MemberOffset(10), false, kUnknownFieldIndex, diff --git a/compiler/optimizing/select_generator.cc b/compiler/optimizing/select_generator.cc index e220d32344..827b5913af 100644 --- a/compiler/optimizing/select_generator.cc +++ b/compiler/optimizing/select_generator.cc @@ -140,11 +140,11 @@ void HSelectGenerator::Run() { false_value, if_instruction->GetDexPc()); if (both_successors_return) { - if (true_value->GetType() == Primitive::kPrimNot) { - DCHECK(false_value->GetType() == Primitive::kPrimNot); + if (true_value->GetType() == DataType::Type::kReference) { + DCHECK(false_value->GetType() == DataType::Type::kReference); ReferenceTypePropagation::FixUpInstructionType(select, handle_scope_); } - } else if (phi->GetType() == Primitive::kPrimNot) { + } else if (phi->GetType() == DataType::Type::kReference) { select->SetReferenceTypeInfo(phi->GetReferenceTypeInfo()); } block->InsertInstructionBefore(select, if_instruction); diff --git a/compiler/optimizing/side_effects_test.cc b/compiler/optimizing/side_effects_test.cc index b01bc1ca0d..ac5eb15228 100644 --- a/compiler/optimizing/side_effects_test.cc +++ b/compiler/optimizing/side_effects_test.cc @@ -14,9 +14,10 @@ * limitations under the License. */ -#include "gtest/gtest.h" +#include <gtest/gtest.h> + +#include "data_type.h" #include "nodes.h" -#include "primitive.h" namespace art { @@ -89,18 +90,18 @@ TEST(SideEffectsTest, None) { } TEST(SideEffectsTest, DependencesAndNoDependences) { - // Apply test to each individual primitive type. - for (Primitive::Type type = Primitive::kPrimNot; - type < Primitive::kPrimVoid; - type = Primitive::Type(type + 1)) { - // Same primitive type and access type: proper write/read dep. + // Apply test to each individual data type. + for (DataType::Type type = DataType::Type::kReference; + type < DataType::Type::kVoid; + type = static_cast<DataType::Type>(static_cast<uint8_t>(type) + 1u)) { + // Same data type and access type: proper write/read dep. testWriteAndReadDependence( SideEffects::FieldWriteOfType(type, false), SideEffects::FieldReadOfType(type, false)); testWriteAndReadDependence( SideEffects::ArrayWriteOfType(type), SideEffects::ArrayReadOfType(type)); - // Same primitive type but different access type: no write/read dep. + // Same data type but different access type: no write/read dep. testNoWriteAndReadDependence( SideEffects::FieldWriteOfType(type, false), SideEffects::ArrayReadOfType(type)); @@ -111,31 +112,31 @@ TEST(SideEffectsTest, DependencesAndNoDependences) { } TEST(SideEffectsTest, NoDependences) { - // Different primitive type, same access type: no write/read dep. + // Different data type, same access type: no write/read dep. testNoWriteAndReadDependence( - SideEffects::FieldWriteOfType(Primitive::kPrimInt, false), - SideEffects::FieldReadOfType(Primitive::kPrimDouble, false)); + SideEffects::FieldWriteOfType(DataType::Type::kInt32, false), + SideEffects::FieldReadOfType(DataType::Type::kFloat64, false)); testNoWriteAndReadDependence( - SideEffects::ArrayWriteOfType(Primitive::kPrimInt), - SideEffects::ArrayReadOfType(Primitive::kPrimDouble)); + SideEffects::ArrayWriteOfType(DataType::Type::kInt32), + SideEffects::ArrayReadOfType(DataType::Type::kFloat64)); // Everything different: no write/read dep. testNoWriteAndReadDependence( - SideEffects::FieldWriteOfType(Primitive::kPrimInt, false), - SideEffects::ArrayReadOfType(Primitive::kPrimDouble)); + SideEffects::FieldWriteOfType(DataType::Type::kInt32, false), + SideEffects::ArrayReadOfType(DataType::Type::kFloat64)); testNoWriteAndReadDependence( - SideEffects::ArrayWriteOfType(Primitive::kPrimInt), - SideEffects::FieldReadOfType(Primitive::kPrimDouble, false)); + SideEffects::ArrayWriteOfType(DataType::Type::kInt32), + SideEffects::FieldReadOfType(DataType::Type::kFloat64, false)); } TEST(SideEffectsTest, VolatileDependences) { SideEffects volatile_write = - SideEffects::FieldWriteOfType(Primitive::kPrimInt, /* is_volatile */ true); + SideEffects::FieldWriteOfType(DataType::Type::kInt32, /* is_volatile */ true); SideEffects any_write = - SideEffects::FieldWriteOfType(Primitive::kPrimInt, /* is_volatile */ false); + SideEffects::FieldWriteOfType(DataType::Type::kInt32, /* is_volatile */ false); SideEffects volatile_read = - SideEffects::FieldReadOfType(Primitive::kPrimByte, /* is_volatile */ true); + SideEffects::FieldReadOfType(DataType::Type::kInt8, /* is_volatile */ true); SideEffects any_read = - SideEffects::FieldReadOfType(Primitive::kPrimByte, /* is_volatile */ false); + SideEffects::FieldReadOfType(DataType::Type::kInt8, /* is_volatile */ false); EXPECT_FALSE(volatile_write.MayDependOn(any_read)); EXPECT_TRUE(any_read.MayDependOn(volatile_write)); @@ -151,26 +152,26 @@ TEST(SideEffectsTest, VolatileDependences) { TEST(SideEffectsTest, SameWidthTypesNoAlias) { // Type I/F. testNoWriteAndReadDependence( - SideEffects::FieldWriteOfType(Primitive::kPrimInt, /* is_volatile */ false), - SideEffects::FieldReadOfType(Primitive::kPrimFloat, /* is_volatile */ false)); + SideEffects::FieldWriteOfType(DataType::Type::kInt32, /* is_volatile */ false), + SideEffects::FieldReadOfType(DataType::Type::kFloat32, /* is_volatile */ false)); testNoWriteAndReadDependence( - SideEffects::ArrayWriteOfType(Primitive::kPrimInt), - SideEffects::ArrayReadOfType(Primitive::kPrimFloat)); + SideEffects::ArrayWriteOfType(DataType::Type::kInt32), + SideEffects::ArrayReadOfType(DataType::Type::kFloat32)); // Type L/D. testNoWriteAndReadDependence( - SideEffects::FieldWriteOfType(Primitive::kPrimLong, /* is_volatile */ false), - SideEffects::FieldReadOfType(Primitive::kPrimDouble, /* is_volatile */ false)); + SideEffects::FieldWriteOfType(DataType::Type::kInt64, /* is_volatile */ false), + SideEffects::FieldReadOfType(DataType::Type::kFloat64, /* is_volatile */ false)); testNoWriteAndReadDependence( - SideEffects::ArrayWriteOfType(Primitive::kPrimLong), - SideEffects::ArrayReadOfType(Primitive::kPrimDouble)); + SideEffects::ArrayWriteOfType(DataType::Type::kInt64), + SideEffects::ArrayReadOfType(DataType::Type::kFloat64)); } TEST(SideEffectsTest, AllWritesAndReads) { SideEffects s = SideEffects::None(); // Keep taking the union of different writes and reads. - for (Primitive::Type type = Primitive::kPrimNot; - type < Primitive::kPrimVoid; - type = Primitive::Type(type + 1)) { + for (DataType::Type type = DataType::Type::kReference; + type < DataType::Type::kVoid; + type = static_cast<DataType::Type>(static_cast<uint8_t>(type) + 1u)) { s = s.Union(SideEffects::FieldWriteOfType(type, /* is_volatile */ false)); s = s.Union(SideEffects::ArrayWriteOfType(type)); s = s.Union(SideEffects::FieldReadOfType(type, /* is_volatile */ false)); @@ -214,41 +215,41 @@ TEST(SideEffectsTest, BitStrings) { SideEffects::AllReads().ToString().c_str()); EXPECT_STREQ( "||||||L|", - SideEffects::FieldWriteOfType(Primitive::kPrimNot, false).ToString().c_str()); + SideEffects::FieldWriteOfType(DataType::Type::kReference, false).ToString().c_str()); EXPECT_STREQ( "||DFJISCBZL|DFJISCBZL||DFJISCBZL|DFJISCBZL|", - SideEffects::FieldWriteOfType(Primitive::kPrimNot, true).ToString().c_str()); + SideEffects::FieldWriteOfType(DataType::Type::kReference, true).ToString().c_str()); EXPECT_STREQ( "|||||Z||", - SideEffects::ArrayWriteOfType(Primitive::kPrimBoolean).ToString().c_str()); + SideEffects::ArrayWriteOfType(DataType::Type::kBool).ToString().c_str()); EXPECT_STREQ( "|||||C||", - SideEffects::ArrayWriteOfType(Primitive::kPrimChar).ToString().c_str()); + SideEffects::ArrayWriteOfType(DataType::Type::kUint16).ToString().c_str()); EXPECT_STREQ( "|||||S||", - SideEffects::ArrayWriteOfType(Primitive::kPrimShort).ToString().c_str()); + SideEffects::ArrayWriteOfType(DataType::Type::kInt16).ToString().c_str()); EXPECT_STREQ( "|||B||||", - SideEffects::FieldReadOfType(Primitive::kPrimByte, false).ToString().c_str()); + SideEffects::FieldReadOfType(DataType::Type::kInt8, false).ToString().c_str()); EXPECT_STREQ( "||D|||||", - SideEffects::ArrayReadOfType(Primitive::kPrimDouble).ToString().c_str()); + SideEffects::ArrayReadOfType(DataType::Type::kFloat64).ToString().c_str()); EXPECT_STREQ( "||J|||||", - SideEffects::ArrayReadOfType(Primitive::kPrimLong).ToString().c_str()); + SideEffects::ArrayReadOfType(DataType::Type::kInt64).ToString().c_str()); EXPECT_STREQ( "||F|||||", - SideEffects::ArrayReadOfType(Primitive::kPrimFloat).ToString().c_str()); + SideEffects::ArrayReadOfType(DataType::Type::kFloat32).ToString().c_str()); EXPECT_STREQ( "||I|||||", - SideEffects::ArrayReadOfType(Primitive::kPrimInt).ToString().c_str()); + SideEffects::ArrayReadOfType(DataType::Type::kInt32).ToString().c_str()); SideEffects s = SideEffects::None(); - s = s.Union(SideEffects::FieldWriteOfType(Primitive::kPrimChar, /* is_volatile */ false)); - s = s.Union(SideEffects::FieldWriteOfType(Primitive::kPrimLong, /* is_volatile */ false)); - s = s.Union(SideEffects::ArrayWriteOfType(Primitive::kPrimShort)); - s = s.Union(SideEffects::FieldReadOfType(Primitive::kPrimInt, /* is_volatile */ false)); - s = s.Union(SideEffects::ArrayReadOfType(Primitive::kPrimFloat)); - s = s.Union(SideEffects::ArrayReadOfType(Primitive::kPrimDouble)); + s = s.Union(SideEffects::FieldWriteOfType(DataType::Type::kUint16, /* is_volatile */ false)); + s = s.Union(SideEffects::FieldWriteOfType(DataType::Type::kInt64, /* is_volatile */ false)); + s = s.Union(SideEffects::ArrayWriteOfType(DataType::Type::kInt16)); + s = s.Union(SideEffects::FieldReadOfType(DataType::Type::kInt32, /* is_volatile */ false)); + s = s.Union(SideEffects::ArrayReadOfType(DataType::Type::kFloat32)); + s = s.Union(SideEffects::ArrayReadOfType(DataType::Type::kFloat64)); EXPECT_STREQ("||DF|I||S|JC|", s.ToString().c_str()); } diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc index 50ab11bc23..77b7a228dc 100644 --- a/compiler/optimizing/ssa_builder.cc +++ b/compiler/optimizing/ssa_builder.cc @@ -17,6 +17,7 @@ #include "ssa_builder.h" #include "bytecode_utils.h" +#include "data_type-inl.h" #include "mirror/class-inl.h" #include "nodes.h" #include "reference_type_propagation.h" @@ -37,10 +38,11 @@ void SsaBuilder::FixNullConstantType() { HInstruction* right = equality_instr->InputAt(1); HInstruction* int_operand = nullptr; - if ((left->GetType() == Primitive::kPrimNot) && (right->GetType() == Primitive::kPrimInt)) { + if ((left->GetType() == DataType::Type::kReference) && + (right->GetType() == DataType::Type::kInt32)) { int_operand = right; - } else if ((right->GetType() == Primitive::kPrimNot) - && (left->GetType() == Primitive::kPrimInt)) { + } else if ((right->GetType() == DataType::Type::kReference) && + (left->GetType() == DataType::Type::kInt32)) { int_operand = left; } else { continue; @@ -122,7 +124,7 @@ static void AddDependentInstructionsToWorklist(HInstruction* instruction, // Find a candidate primitive type for `phi` by merging the type of its inputs. // Return false if conflict is identified. static bool TypePhiFromInputs(HPhi* phi) { - Primitive::Type common_type = phi->GetType(); + DataType::Type common_type = phi->GetType(); for (HInstruction* input : phi->GetInputs()) { if (input->IsPhi() && input->AsPhi()->IsDead()) { @@ -131,26 +133,29 @@ static bool TypePhiFromInputs(HPhi* phi) { return false; } - Primitive::Type input_type = HPhi::ToPhiType(input->GetType()); + DataType::Type input_type = HPhi::ToPhiType(input->GetType()); if (common_type == input_type) { // No change in type. - } else if (Primitive::Is64BitType(common_type) != Primitive::Is64BitType(input_type)) { + } else if (DataType::Is64BitType(common_type) != DataType::Is64BitType(input_type)) { // Types are of different sizes, e.g. int vs. long. Must be a conflict. return false; - } else if (Primitive::IsIntegralType(common_type)) { + } else if (DataType::IsIntegralType(common_type)) { // Previous inputs were integral, this one is not but is of the same size. // This does not imply conflict since some bytecode instruction types are // ambiguous. TypeInputsOfPhi will either type them or detect a conflict. - DCHECK(Primitive::IsFloatingPointType(input_type) || input_type == Primitive::kPrimNot); + DCHECK(DataType::IsFloatingPointType(input_type) || + input_type == DataType::Type::kReference); common_type = input_type; - } else if (Primitive::IsIntegralType(input_type)) { + } else if (DataType::IsIntegralType(input_type)) { // Input is integral, common type is not. Same as in the previous case, if // there is a conflict, it will be detected during TypeInputsOfPhi. - DCHECK(Primitive::IsFloatingPointType(common_type) || common_type == Primitive::kPrimNot); + DCHECK(DataType::IsFloatingPointType(common_type) || + common_type == DataType::Type::kReference); } else { // Combining float and reference types. Clearly a conflict. - DCHECK((common_type == Primitive::kPrimFloat && input_type == Primitive::kPrimNot) || - (common_type == Primitive::kPrimNot && input_type == Primitive::kPrimFloat)); + DCHECK( + (common_type == DataType::Type::kFloat32 && input_type == DataType::Type::kReference) || + (common_type == DataType::Type::kReference && input_type == DataType::Type::kFloat32)); return false; } } @@ -163,8 +168,8 @@ static bool TypePhiFromInputs(HPhi* phi) { // Replace inputs of `phi` to match its type. Return false if conflict is identified. bool SsaBuilder::TypeInputsOfPhi(HPhi* phi, ArenaVector<HPhi*>* worklist) { - Primitive::Type common_type = phi->GetType(); - if (Primitive::IsIntegralType(common_type)) { + DataType::Type common_type = phi->GetType(); + if (DataType::IsIntegralType(common_type)) { // We do not need to retype ambiguous inputs because they are always constructed // with the integral type candidate. if (kIsDebugBuild) { @@ -175,14 +180,15 @@ bool SsaBuilder::TypeInputsOfPhi(HPhi* phi, ArenaVector<HPhi*>* worklist) { // Inputs did not need to be replaced, hence no conflict. Report success. return true; } else { - DCHECK(common_type == Primitive::kPrimNot || Primitive::IsFloatingPointType(common_type)); + DCHECK(common_type == DataType::Type::kReference || + DataType::IsFloatingPointType(common_type)); HInputsRef inputs = phi->GetInputs(); for (size_t i = 0; i < inputs.size(); ++i) { HInstruction* input = inputs[i]; if (input->GetType() != common_type) { // Input type does not match phi's type. Try to retype the input or // generate a suitably typed equivalent. - HInstruction* equivalent = (common_type == Primitive::kPrimNot) + HInstruction* equivalent = (common_type == DataType::Type::kReference) ? GetReferenceTypeEquivalent(input) : GetFloatOrDoubleEquivalent(input, common_type); if (equivalent == nullptr) { @@ -209,7 +215,7 @@ bool SsaBuilder::TypeInputsOfPhi(HPhi* phi, ArenaVector<HPhi*>* worklist) { // it was changed by the algorithm or not. bool SsaBuilder::UpdatePrimitiveType(HPhi* phi, ArenaVector<HPhi*>* worklist) { DCHECK(phi->IsLive()); - Primitive::Type original_type = phi->GetType(); + DataType::Type original_type = phi->GetType(); // Try to type the phi in two stages: // (1) find a candidate type for the phi by merging types of all its inputs, @@ -270,8 +276,8 @@ void SsaBuilder::ProcessPrimitiveTypePropagationWorklist(ArenaVector<HPhi*>* wor } static HArrayGet* FindFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget) { - Primitive::Type type = aget->GetType(); - DCHECK(Primitive::IsIntOrLongType(type)); + DataType::Type type = aget->GetType(); + DCHECK(DataType::IsIntOrLongType(type)); HInstruction* next = aget->GetNext(); if (next != nullptr && next->IsArrayGet()) { HArrayGet* next_aget = next->AsArrayGet(); @@ -283,24 +289,25 @@ static HArrayGet* FindFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget) { } static HArrayGet* CreateFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget) { - Primitive::Type type = aget->GetType(); - DCHECK(Primitive::IsIntOrLongType(type)); + DataType::Type type = aget->GetType(); + DCHECK(DataType::IsIntOrLongType(type)); DCHECK(FindFloatOrDoubleEquivalentOfArrayGet(aget) == nullptr); HArrayGet* equivalent = new (aget->GetBlock()->GetGraph()->GetArena()) HArrayGet( aget->GetArray(), aget->GetIndex(), - type == Primitive::kPrimInt ? Primitive::kPrimFloat : Primitive::kPrimDouble, + type == DataType::Type::kInt32 ? DataType::Type::kFloat32 : DataType::Type::kFloat64, aget->GetDexPc()); aget->GetBlock()->InsertInstructionAfter(equivalent, aget); return equivalent; } -static Primitive::Type GetPrimitiveArrayComponentType(HInstruction* array) +static DataType::Type GetPrimitiveArrayComponentType(HInstruction* array) REQUIRES_SHARED(Locks::mutator_lock_) { ReferenceTypeInfo array_type = array->GetReferenceTypeInfo(); DCHECK(array_type.IsPrimitiveArrayClass()); - return array_type.GetTypeHandle()->GetComponentType()->GetPrimitiveType(); + return DataTypeFromPrimitive( + array_type.GetTypeHandle()->GetComponentType()->GetPrimitiveType()); } bool SsaBuilder::FixAmbiguousArrayOps() { @@ -325,10 +332,10 @@ bool SsaBuilder::FixAmbiguousArrayOps() { } HArrayGet* aget_float = FindFloatOrDoubleEquivalentOfArrayGet(aget_int); - Primitive::Type array_type = GetPrimitiveArrayComponentType(array); - DCHECK_EQ(Primitive::Is64BitType(aget_int->GetType()), Primitive::Is64BitType(array_type)); + DataType::Type array_type = GetPrimitiveArrayComponentType(array); + DCHECK_EQ(DataType::Is64BitType(aget_int->GetType()), DataType::Is64BitType(array_type)); - if (Primitive::IsIntOrLongType(array_type)) { + if (DataType::IsIntOrLongType(array_type)) { if (aget_float != nullptr) { // There is a float/double equivalent. We must replace it and re-run // primitive type propagation on all dependent instructions. @@ -337,7 +344,7 @@ bool SsaBuilder::FixAmbiguousArrayOps() { AddDependentInstructionsToWorklist(aget_int, &worklist); } } else { - DCHECK(Primitive::IsFloatingPointType(array_type)); + DCHECK(DataType::IsFloatingPointType(array_type)); if (aget_float == nullptr) { // This is a float/double ArrayGet but there were no typed uses which // would create the typed equivalent. Create it now. @@ -365,13 +372,13 @@ bool SsaBuilder::FixAmbiguousArrayOps() { } HInstruction* value = aset->GetValue(); - Primitive::Type value_type = value->GetType(); - Primitive::Type array_type = GetPrimitiveArrayComponentType(array); - DCHECK_EQ(Primitive::Is64BitType(value_type), Primitive::Is64BitType(array_type)); + DataType::Type value_type = value->GetType(); + DataType::Type array_type = GetPrimitiveArrayComponentType(array); + DCHECK_EQ(DataType::Is64BitType(value_type), DataType::Is64BitType(array_type)); - if (Primitive::IsFloatingPointType(array_type)) { - if (!Primitive::IsFloatingPointType(value_type)) { - DCHECK(Primitive::IsIntegralType(value_type)); + if (DataType::IsFloatingPointType(array_type)) { + if (!DataType::IsFloatingPointType(value_type)) { + DCHECK(DataType::IsIntegralType(value_type)); // Array elements are floating-point but the value has not been replaced // with its floating-point equivalent. The replacement must always // succeed in code validated by the verifier. @@ -390,8 +397,8 @@ bool SsaBuilder::FixAmbiguousArrayOps() { } else { // Array elements are integral and the value assigned to it initially // was integral too. Nothing to do. - DCHECK(Primitive::IsIntegralType(array_type)); - DCHECK(Primitive::IsIntegralType(value_type)); + DCHECK(DataType::IsIntegralType(array_type)); + DCHECK(DataType::IsIntegralType(value_type)); } } } @@ -599,7 +606,7 @@ HDoubleConstant* SsaBuilder::GetDoubleEquivalent(HLongConstant* constant) { * floating point registers and core registers), we need to create a copy of the * phi with a floating point / reference type. */ -HPhi* SsaBuilder::GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, Primitive::Type type) { +HPhi* SsaBuilder::GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, DataType::Type type) { DCHECK(phi->IsLive()) << "Cannot get equivalent of a dead phi since it would create a live one."; // We place the floating point /reference phi next to this phi. @@ -637,9 +644,9 @@ HPhi* SsaBuilder::GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, Primitive: } HArrayGet* SsaBuilder::GetFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget) { - DCHECK(Primitive::IsIntegralType(aget->GetType())); + DCHECK(DataType::IsIntegralType(aget->GetType())); - if (!Primitive::IsIntOrLongType(aget->GetType())) { + if (!DataType::IsIntOrLongType(aget->GetType())) { // Cannot type boolean, char, byte, short to float/double. return nullptr; } @@ -650,7 +657,7 @@ HArrayGet* SsaBuilder::GetFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget) { // int/long. Requesting a float/double equivalent should lead to a conflict. if (kIsDebugBuild) { ScopedObjectAccess soa(Thread::Current()); - DCHECK(Primitive::IsIntOrLongType(GetPrimitiveArrayComponentType(aget->GetArray()))); + DCHECK(DataType::IsIntOrLongType(GetPrimitiveArrayComponentType(aget->GetArray()))); } return nullptr; } else { @@ -661,7 +668,7 @@ HArrayGet* SsaBuilder::GetFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget) { } } -HInstruction* SsaBuilder::GetFloatOrDoubleEquivalent(HInstruction* value, Primitive::Type type) { +HInstruction* SsaBuilder::GetFloatOrDoubleEquivalent(HInstruction* value, DataType::Type type) { if (value->IsArrayGet()) { return GetFloatOrDoubleEquivalentOfArrayGet(value->AsArrayGet()); } else if (value->IsLongConstant()) { @@ -679,7 +686,7 @@ HInstruction* SsaBuilder::GetReferenceTypeEquivalent(HInstruction* value) { if (value->IsIntConstant() && value->AsIntConstant()->GetValue() == 0) { return graph_->GetNullConstant(); } else if (value->IsPhi()) { - return GetFloatDoubleOrReferenceEquivalentOfPhi(value->AsPhi(), Primitive::kPrimNot); + return GetFloatDoubleOrReferenceEquivalentOfPhi(value->AsPhi(), DataType::Type::kReference); } else { return nullptr; } diff --git a/compiler/optimizing/ssa_builder.h b/compiler/optimizing/ssa_builder.h index 978f113ec4..1819ee568e 100644 --- a/compiler/optimizing/ssa_builder.h +++ b/compiler/optimizing/ssa_builder.h @@ -64,20 +64,20 @@ class SsaBuilder : public ValueObject { GraphAnalysisResult BuildSsa(); - HInstruction* GetFloatOrDoubleEquivalent(HInstruction* instruction, Primitive::Type type); + HInstruction* GetFloatOrDoubleEquivalent(HInstruction* instruction, DataType::Type type); HInstruction* GetReferenceTypeEquivalent(HInstruction* instruction); void MaybeAddAmbiguousArrayGet(HArrayGet* aget) { - Primitive::Type type = aget->GetType(); - DCHECK(!Primitive::IsFloatingPointType(type)); - if (Primitive::IsIntOrLongType(type)) { + DataType::Type type = aget->GetType(); + DCHECK(!DataType::IsFloatingPointType(type)); + if (DataType::IsIntOrLongType(type)) { ambiguous_agets_.push_back(aget); } } void MaybeAddAmbiguousArraySet(HArraySet* aset) { - Primitive::Type type = aset->GetValue()->GetType(); - if (Primitive::IsIntOrLongType(type)) { + DataType::Type type = aset->GetValue()->GetType(); + if (DataType::IsIntOrLongType(type)) { ambiguous_asets_.push_back(aset); } } @@ -111,7 +111,7 @@ class SsaBuilder : public ValueObject { HFloatConstant* GetFloatEquivalent(HIntConstant* constant); HDoubleConstant* GetDoubleEquivalent(HLongConstant* constant); - HPhi* GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, Primitive::Type type); + HPhi* GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, DataType::Type type); HArrayGet* GetFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget); void RemoveRedundantUninitializedStrings(); diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc index 185303bc8c..f1f1be25d7 100644 --- a/compiler/optimizing/ssa_liveness_analysis.cc +++ b/compiler/optimizing/ssa_liveness_analysis.cc @@ -474,11 +474,13 @@ size_t LiveInterval::NumberOfSpillSlotsNeeded() const { // For a SIMD operation, compute the number of needed spill slots. // TODO: do through vector type? HInstruction* definition = GetParent()->GetDefinedBy(); - if (definition != nullptr && definition->IsVecOperation()) { + if (definition != nullptr && + definition->IsVecOperation() && + !definition->IsVecExtractScalar()) { return definition->AsVecOperation()->GetVectorNumberOfBytes() / kVRegSize; } // Return number of needed spill slots based on type. - return (type_ == Primitive::kPrimLong || type_ == Primitive::kPrimDouble) ? 2 : 1; + return (type_ == DataType::Type::kInt64 || type_ == DataType::Type::kFloat64) ? 2 : 1; } Location LiveInterval::ToLocation() const { diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h index a6681575a2..ec4ab31d61 100644 --- a/compiler/optimizing/ssa_liveness_analysis.h +++ b/compiler/optimizing/ssa_liveness_analysis.h @@ -262,16 +262,16 @@ class SafepointPosition : public ArenaObject<kArenaAllocSsaLiveness> { class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> { public: static LiveInterval* MakeInterval(ArenaAllocator* allocator, - Primitive::Type type, + DataType::Type type, HInstruction* instruction = nullptr) { return new (allocator) LiveInterval(allocator, type, instruction); } - static LiveInterval* MakeFixedInterval(ArenaAllocator* allocator, int reg, Primitive::Type type) { + static LiveInterval* MakeFixedInterval(ArenaAllocator* allocator, int reg, DataType::Type type) { return new (allocator) LiveInterval(allocator, type, nullptr, true, reg, false); } - static LiveInterval* MakeTempInterval(ArenaAllocator* allocator, Primitive::Type type) { + static LiveInterval* MakeTempInterval(ArenaAllocator* allocator, DataType::Type type) { return new (allocator) LiveInterval(allocator, type, nullptr, false, kNoRegister, true); } @@ -608,7 +608,7 @@ class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> { return parent_->env_uses_; } - Primitive::Type GetType() const { + DataType::Type GetType() const { return type_; } @@ -783,7 +783,7 @@ class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> { size_t NumberOfSpillSlotsNeeded() const; bool IsFloatingPoint() const { - return type_ == Primitive::kPrimFloat || type_ == Primitive::kPrimDouble; + return type_ == DataType::Type::kFloat32 || type_ == DataType::Type::kFloat64; } // Converts the location of the interval to a `Location` object. @@ -970,7 +970,7 @@ class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> { private: LiveInterval(ArenaAllocator* allocator, - Primitive::Type type, + DataType::Type type, HInstruction* defined_by = nullptr, bool is_fixed = false, int reg = kNoRegister, @@ -1102,7 +1102,7 @@ class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> { EnvUsePositionList env_uses_; // The instruction type this interval corresponds to. - const Primitive::Type type_; + const DataType::Type type_; // Live interval that is the result of a split. LiveInterval* next_sibling_; @@ -1262,7 +1262,7 @@ class SsaLivenessAnalysis : public ValueObject { // the exception handler to its location at the top of the catch block. if (env_holder->CanThrowIntoCatchBlock()) return true; if (instruction->GetBlock()->GetGraph()->IsDebuggable()) return true; - return instruction->GetType() == Primitive::kPrimNot; + return instruction->GetType() == DataType::Type::kReference; } void CheckNoLiveInIrreducibleLoop(const HBasicBlock& block) const { diff --git a/compiler/optimizing/ssa_liveness_analysis_test.cc b/compiler/optimizing/ssa_liveness_analysis_test.cc index b46060a24a..e89bf6d801 100644 --- a/compiler/optimizing/ssa_liveness_analysis_test.cc +++ b/compiler/optimizing/ssa_liveness_analysis_test.cc @@ -70,7 +70,7 @@ class SsaLivenessAnalysisTest : public testing::Test { TEST_F(SsaLivenessAnalysisTest, TestReturnArg) { HInstruction* arg = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt); + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32); entry_->AddInstruction(arg); HBasicBlock* block = CreateSuccessor(entry_); @@ -90,15 +90,15 @@ TEST_F(SsaLivenessAnalysisTest, TestReturnArg) { TEST_F(SsaLivenessAnalysisTest, TestAput) { HInstruction* array = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); HInstruction* index = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(1), 1, Primitive::kPrimInt); + graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kInt32); HInstruction* value = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(2), 2, Primitive::kPrimInt); + graph_->GetDexFile(), dex::TypeIndex(2), 2, DataType::Type::kInt32); HInstruction* extra_arg1 = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(3), 3, Primitive::kPrimInt); + graph_->GetDexFile(), dex::TypeIndex(3), 3, DataType::Type::kInt32); HInstruction* extra_arg2 = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(4), 4, Primitive::kPrimNot); + graph_->GetDexFile(), dex::TypeIndex(4), 4, DataType::Type::kReference); ArenaVector<HInstruction*> args({ array, index, value, extra_arg1, extra_arg2 }, allocator_.Adapter()); for (HInstruction* insn : args) { @@ -127,7 +127,7 @@ TEST_F(SsaLivenessAnalysisTest, TestAput) { bounds_check_env->CopyFrom(args); bounds_check->SetRawEnvironment(bounds_check_env); HInstruction* array_set = - new (&allocator_) HArraySet(array, index, value, Primitive::kPrimInt, /* dex_pc */ 0); + new (&allocator_) HArraySet(array, index, value, DataType::Type::kInt32, /* dex_pc */ 0); block->AddInstruction(array_set); graph_->BuildDominatorTree(); @@ -160,15 +160,15 @@ TEST_F(SsaLivenessAnalysisTest, TestAput) { TEST_F(SsaLivenessAnalysisTest, TestDeoptimize) { HInstruction* array = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot); + graph_->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); HInstruction* index = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(1), 1, Primitive::kPrimInt); + graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kInt32); HInstruction* value = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(2), 2, Primitive::kPrimInt); + graph_->GetDexFile(), dex::TypeIndex(2), 2, DataType::Type::kInt32); HInstruction* extra_arg1 = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(3), 3, Primitive::kPrimInt); + graph_->GetDexFile(), dex::TypeIndex(3), 3, DataType::Type::kInt32); HInstruction* extra_arg2 = new (&allocator_) HParameterValue( - graph_->GetDexFile(), dex::TypeIndex(4), 4, Primitive::kPrimNot); + graph_->GetDexFile(), dex::TypeIndex(4), 4, DataType::Type::kReference); ArenaVector<HInstruction*> args({ array, index, value, extra_arg1, extra_arg2 }, allocator_.Adapter()); for (HInstruction* insn : args) { @@ -201,7 +201,7 @@ TEST_F(SsaLivenessAnalysisTest, TestDeoptimize) { deoptimize_env->CopyFrom(args); deoptimize->SetRawEnvironment(deoptimize_env); HInstruction* array_set = - new (&allocator_) HArraySet(array, index, value, Primitive::kPrimInt, /* dex_pc */ 0); + new (&allocator_) HArraySet(array, index, value, DataType::Type::kInt32, /* dex_pc */ 0); block->AddInstruction(array_set); graph_->BuildDominatorTree(); diff --git a/compiler/optimizing/ssa_test.cc b/compiler/optimizing/ssa_test.cc index f69f417efc..ac998dbcab 100644 --- a/compiler/optimizing/ssa_test.cc +++ b/compiler/optimizing/ssa_test.cc @@ -89,7 +89,7 @@ static void TestCode(const uint16_t* data, const char* expected) { // Test that phis had their type set. for (HBasicBlock* block : graph->GetBlocks()) { for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) { - ASSERT_NE(it.Current()->GetType(), Primitive::kPrimVoid); + ASSERT_NE(it.Current()->GetType(), DataType::Type::kVoid); } } diff --git a/compiler/optimizing/x86_memory_gen.cc b/compiler/optimizing/x86_memory_gen.cc index 4e256832a2..0271850f29 100644 --- a/compiler/optimizing/x86_memory_gen.cc +++ b/compiler/optimizing/x86_memory_gen.cc @@ -41,7 +41,7 @@ class MemoryOperandVisitor : public HGraphVisitor { } HInstruction* array = array_len->InputAt(0); - DCHECK_EQ(array->GetType(), Primitive::kPrimNot); + DCHECK_EQ(array->GetType(), DataType::Type::kReference); // Don't apply this optimization when the array is nullptr. if (array->IsConstant() || (array->IsNullCheck() && array->InputAt(0)->IsConstant())) { diff --git a/compiler/utils/assembler_test.h b/compiler/utils/assembler_test.h index 12954a4c32..227954e21b 100644 --- a/compiler/utils/assembler_test.h +++ b/compiler/utils/assembler_test.h @@ -114,6 +114,24 @@ class AssemblerTest : public testing::Test { fmt); } + std::string Repeatww(void (Ass::*f)(Reg, Reg), const std::string& fmt) { + return RepeatTemplatedRegisters<Reg, Reg>(f, + GetRegisters(), + GetRegisters(), + &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>, + &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>, + fmt); + } + + std::string Repeatbb(void (Ass::*f)(Reg, Reg), const std::string& fmt) { + return RepeatTemplatedRegisters<Reg, Reg>(f, + GetRegisters(), + GetRegisters(), + &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>, + &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>, + fmt); + } + std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), const std::string& fmt) { return RepeatTemplatedRegisters<Reg, Reg, Reg>(f, GetRegisters(), @@ -147,10 +165,18 @@ class AssemblerTest : public testing::Test { return RepeatRegisterImm<RegisterView::kUsePrimaryName>(f, imm_bytes, fmt); } - std::string Repeatri(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) { + std::string RepeatrI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) { return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt); } + std::string RepeatwI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) { + return RepeatRegisterImm<RegisterView::kUseTertiaryName>(f, imm_bytes, fmt); + } + + std::string RepeatbI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) { + return RepeatRegisterImm<RegisterView::kUseQuaternaryName>(f, imm_bytes, fmt); + } + template <typename Reg1, typename Reg2, typename ImmType> std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, ImmType), int imm_bits, @@ -909,6 +935,63 @@ class AssemblerTest : public testing::Test { fmt); } + // Repeats over secondary registers and addresses provided by fixture. + std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) { + return RepeatrA(f, GetAddresses(), fmt); + } + + // Variant that takes explicit vector of addresss + // (to test restricted addressing modes set). + std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), + const std::vector<Addr>& a, + const std::string& fmt) { + return RepeatTemplatedRegMem<Reg, Addr>( + f, + GetRegisters(), + a, + &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, + &AssemblerTest::GetAddrName, + fmt); + } + + // Repeats over tertiary registers and addresses provided by fixture. + std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) { + return RepeatwA(f, GetAddresses(), fmt); + } + + // Variant that takes explicit vector of addresss + // (to test restricted addressing modes set). + std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), + const std::vector<Addr>& a, + const std::string& fmt) { + return RepeatTemplatedRegMem<Reg, Addr>( + f, + GetRegisters(), + a, + &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>, + &AssemblerTest::GetAddrName, + fmt); + } + + // Repeats over quaternary registers and addresses provided by fixture. + std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) { + return RepeatbA(f, GetAddresses(), fmt); + } + + // Variant that takes explicit vector of addresss + // (to test restricted addressing modes set). + std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), + const std::vector<Addr>& a, + const std::string& fmt) { + return RepeatTemplatedRegMem<Reg, Addr>( + f, + GetRegisters(), + a, + &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>, + &AssemblerTest::GetAddrName, + fmt); + } + // Repeats over fp-registers and addresses provided by fixture. std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) { return RepeatFA(f, GetAddresses(), fmt); @@ -947,6 +1030,63 @@ class AssemblerTest : public testing::Test { fmt); } + // Repeats over addresses and secondary registers provided by fixture. + std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) { + return RepeatAr(f, GetAddresses(), fmt); + } + + // Variant that takes explicit vector of addresss + // (to test restricted addressing modes set). + std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), + const std::vector<Addr>& a, + const std::string& fmt) { + return RepeatTemplatedMemReg<Addr, Reg>( + f, + a, + GetRegisters(), + &AssemblerTest::GetAddrName, + &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, + fmt); + } + + // Repeats over addresses and tertiary registers provided by fixture. + std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) { + return RepeatAw(f, GetAddresses(), fmt); + } + + // Variant that takes explicit vector of addresss + // (to test restricted addressing modes set). + std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), + const std::vector<Addr>& a, + const std::string& fmt) { + return RepeatTemplatedMemReg<Addr, Reg>( + f, + a, + GetRegisters(), + &AssemblerTest::GetAddrName, + &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>, + fmt); + } + + // Repeats over addresses and quaternary registers provided by fixture. + std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) { + return RepeatAb(f, GetAddresses(), fmt); + } + + // Variant that takes explicit vector of addresss + // (to test restricted addressing modes set). + std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), + const std::vector<Addr>& a, + const std::string& fmt) { + return RepeatTemplatedMemReg<Addr, Reg>( + f, + a, + GetRegisters(), + &AssemblerTest::GetAddrName, + &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>, + fmt); + } + // Repeats over addresses and fp-registers provided by fixture. std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) { return RepeatAF(f, GetAddresses(), fmt); diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc index 3162a32994..9fcede5e97 100644 --- a/compiler/utils/x86/assembler_x86.cc +++ b/compiler/utils/x86/assembler_x86.cc @@ -35,25 +35,25 @@ std::ostream& operator<<(std::ostream& os, const X87Register& reg) { std::ostream& operator<<(std::ostream& os, const Address& addr) { switch (addr.mod()) { case 0: - if (addr.rm() == ESP && addr.index() != ESP) { - return os << "(%" << addr.base() << ",%" - << addr.index() << "," << (1 << addr.scale()) << ")"; + if (addr.rm() != ESP || addr.index() == ESP) { + return os << "(%" << addr.rm() << ")"; + } else if (addr.base() == EBP) { + return os << static_cast<int>(addr.disp32()) << "(,%" << addr.index() + << "," << (1 << addr.scale()) << ")"; } - return os << "(%" << addr.rm() << ")"; + return os << "(%" << addr.base() << ",%" << addr.index() << "," << (1 << addr.scale()) << ")"; case 1: - if (addr.rm() == ESP && addr.index() != ESP) { - return os << static_cast<int>(addr.disp8()) - << "(%" << addr.base() << ",%" - << addr.index() << "," << (1 << addr.scale()) << ")"; + if (addr.rm() != ESP || addr.index() == ESP) { + return os << static_cast<int>(addr.disp8()) << "(%" << addr.rm() << ")"; } - return os << static_cast<int>(addr.disp8()) << "(%" << addr.rm() << ")"; + return os << static_cast<int>(addr.disp8()) << "(%" << addr.base() << ",%" + << addr.index() << "," << (1 << addr.scale()) << ")"; case 2: - if (addr.rm() == ESP && addr.index() != ESP) { - return os << static_cast<int>(addr.disp32()) - << "(%" << addr.base() << ",%" - << addr.index() << "," << (1 << addr.scale()) << ")"; + if (addr.rm() != ESP || addr.index() == ESP) { + return os << static_cast<int>(addr.disp32()) << "(%" << addr.rm() << ")"; } - return os << static_cast<int>(addr.disp32()) << "(%" << addr.rm() << ")"; + return os << static_cast<int>(addr.disp32()) << "(%" << addr.base() << ",%" + << addr.index() << "," << (1 << addr.scale()) << ")"; default: return os << "<address?>"; } diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc index c28ed3b815..cccde37548 100644 --- a/compiler/utils/x86/assembler_x86_test.cc +++ b/compiler/utils/x86/assembler_x86_test.cc @@ -148,21 +148,14 @@ class AssemblerX86Test : public AssemblerTest<x86::X86Assembler, }; // -// Test repeat drivers used in the tests. +// Test some repeat drivers used in the tests. // TEST_F(AssemblerX86Test, RepeatRR) { - EXPECT_EQ("%eax %eax\n%eax %ebx\n%eax %ecx\n%eax %edx\n%eax %ebp\n%eax %esp\n%eax %esi\n" - "%eax %edi\n%ebx %eax\n%ebx %ebx\n%ebx %ecx\n%ebx %edx\n%ebx %ebp\n%ebx %esp\n" - "%ebx %esi\n%ebx %edi\n%ecx %eax\n%ecx %ebx\n%ecx %ecx\n%ecx %edx\n%ecx %ebp\n" - "%ecx %esp\n%ecx %esi\n%ecx %edi\n%edx %eax\n%edx %ebx\n%edx %ecx\n%edx %edx\n" - "%edx %ebp\n%edx %esp\n%edx %esi\n%edx %edi\n%ebp %eax\n%ebp %ebx\n%ebp %ecx\n" - "%ebp %edx\n%ebp %ebp\n%ebp %esp\n%ebp %esi\n%ebp %edi\n%esp %eax\n%esp %ebx\n" - "%esp %ecx\n%esp %edx\n%esp %ebp\n%esp %esp\n%esp %esi\n%esp %edi\n%esi %eax\n" - "%esi %ebx\n%esi %ecx\n%esi %edx\n%esi %ebp\n%esi %esp\n%esi %esi\n%esi %edi\n" - "%edi %eax\n%edi %ebx\n%edi %ecx\n%edi %edx\n%edi %ebp\n%edi %esp\n%edi %esi\n" - "%edi %edi\n", - RepeatRR(/*f*/ nullptr, "%{reg1} %{reg2}")); + EXPECT_NE(RepeatRR(/*f*/ nullptr, "%{reg1} %{reg2}") + .find("%eax %eax\n%eax %ebx\n%eax %ecx\n%eax %edx\n%eax %ebp\n%eax %esp\n%eax %esi\n" + "%eax %edi\n%ebx %eax\n%ebx %ebx\n%ebx %ecx\n%ebx %edx\n%ebx %ebp\n%ebx %esp\n"), + std::string::npos); } TEST_F(AssemblerX86Test, RepeatRI) { @@ -173,18 +166,10 @@ TEST_F(AssemblerX86Test, RepeatRI) { } TEST_F(AssemblerX86Test, RepeatFF) { - EXPECT_EQ("%XMM0 %XMM0\n%XMM0 %XMM1\n%XMM0 %XMM2\n%XMM0 %XMM3\n%XMM0 %XMM4\n%XMM0 %XMM5\n" - "%XMM0 %XMM6\n%XMM0 %XMM7\n%XMM1 %XMM0\n%XMM1 %XMM1\n%XMM1 %XMM2\n%XMM1 %XMM3\n" - "%XMM1 %XMM4\n%XMM1 %XMM5\n%XMM1 %XMM6\n%XMM1 %XMM7\n%XMM2 %XMM0\n%XMM2 %XMM1\n" - "%XMM2 %XMM2\n%XMM2 %XMM3\n%XMM2 %XMM4\n%XMM2 %XMM5\n%XMM2 %XMM6\n%XMM2 %XMM7\n" - "%XMM3 %XMM0\n%XMM3 %XMM1\n%XMM3 %XMM2\n%XMM3 %XMM3\n%XMM3 %XMM4\n%XMM3 %XMM5\n" - "%XMM3 %XMM6\n%XMM3 %XMM7\n%XMM4 %XMM0\n%XMM4 %XMM1\n%XMM4 %XMM2\n%XMM4 %XMM3\n" - "%XMM4 %XMM4\n%XMM4 %XMM5\n%XMM4 %XMM6\n%XMM4 %XMM7\n%XMM5 %XMM0\n%XMM5 %XMM1\n" - "%XMM5 %XMM2\n%XMM5 %XMM3\n%XMM5 %XMM4\n%XMM5 %XMM5\n%XMM5 %XMM6\n%XMM5 %XMM7\n" - "%XMM6 %XMM0\n%XMM6 %XMM1\n%XMM6 %XMM2\n%XMM6 %XMM3\n%XMM6 %XMM4\n%XMM6 %XMM5\n" - "%XMM6 %XMM6\n%XMM6 %XMM7\n%XMM7 %XMM0\n%XMM7 %XMM1\n%XMM7 %XMM2\n%XMM7 %XMM3\n" - "%XMM7 %XMM4\n%XMM7 %XMM5\n%XMM7 %XMM6\n%XMM7 %XMM7\n", - RepeatFF(/*f*/ nullptr, "%{reg1} %{reg2}")); + EXPECT_NE(RepeatFF(/*f*/ nullptr, "%{reg1} %{reg2}") + .find("%XMM0 %XMM0\n%XMM0 %XMM1\n%XMM0 %XMM2\n%XMM0 %XMM3\n%XMM0 %XMM4\n%XMM0 %XMM5\n" + "%XMM0 %XMM6\n%XMM0 %XMM7\n%XMM1 %XMM0\n%XMM1 %XMM1\n%XMM1 %XMM2\n%XMM1 %XMM3\n"), + std::string::npos); } TEST_F(AssemblerX86Test, RepeatFFI) { @@ -235,6 +220,36 @@ TEST_F(AssemblerX86Test, RepeatAF) { // Actual x86 instruction assembler tests. // +TEST_F(AssemblerX86Test, PoplAllAddresses) { + // Make sure all addressing modes combinations are tested at least once. + std::vector<x86::Address> all_addresses; + for (x86::Register* base : GetRegisters()) { + // Base only. + all_addresses.push_back(x86::Address(*base, -1)); + all_addresses.push_back(x86::Address(*base, 0)); + all_addresses.push_back(x86::Address(*base, 1)); + all_addresses.push_back(x86::Address(*base, 123456789)); + for (x86::Register* index : GetRegisters()) { + if (*index == x86::ESP) { + // Index cannot be ESP. + continue; + } else if (*base == *index) { + // Index only. + all_addresses.push_back(x86::Address(*index, x86::TIMES_1, -1)); + all_addresses.push_back(x86::Address(*index, x86::TIMES_2, 0)); + all_addresses.push_back(x86::Address(*index, x86::TIMES_4, 1)); + all_addresses.push_back(x86::Address(*index, x86::TIMES_8, 123456789)); + } + // Base and index. + all_addresses.push_back(x86::Address(*base, *index, x86::TIMES_1, -1)); + all_addresses.push_back(x86::Address(*base, *index, x86::TIMES_2, 0)); + all_addresses.push_back(x86::Address(*base, *index, x86::TIMES_4, 1)); + all_addresses.push_back(x86::Address(*base, *index, x86::TIMES_8, 123456789)); + } + } + DriverStr(RepeatA(&x86::X86Assembler::popl, all_addresses, "popl {mem}"), "popq"); +} + TEST_F(AssemblerX86Test, Movl) { DriverStr(RepeatRR(&x86::X86Assembler::movl, "movl %{reg2}, %{reg1}"), "movl"); } @@ -370,7 +385,7 @@ TEST_F(AssemblerX86Test, RorlReg) { } TEST_F(AssemblerX86Test, RorlImm) { - DriverStr(RepeatRI(&x86::X86Assembler::rorl, 1U, "rorl ${imm}, %{reg}"), "rorli"); + DriverStr(RepeatRI(&x86::X86Assembler::rorl, /*imm_bytes*/ 1U, "rorl ${imm}, %{reg}"), "rorli"); } // Roll only allows CL as the shift count. @@ -390,7 +405,7 @@ TEST_F(AssemblerX86Test, RollReg) { } TEST_F(AssemblerX86Test, RollImm) { - DriverStr(RepeatRI(&x86::X86Assembler::roll, 1U, "roll ${imm}, %{reg}"), "rolli"); + DriverStr(RepeatRI(&x86::X86Assembler::roll, /*imm_bytes*/ 1U, "roll ${imm}, %{reg}"), "rolli"); } TEST_F(AssemblerX86Test, Cvtdq2ps) { @@ -418,12 +433,12 @@ TEST_F(AssemblerX86Test, UComisdAddr) { } TEST_F(AssemblerX86Test, RoundSS) { - DriverStr(RepeatFFI(&x86::X86Assembler::roundss, 1U, + DriverStr(RepeatFFI(&x86::X86Assembler::roundss, /*imm_bytes*/ 1U, "roundss ${imm}, %{reg2}, %{reg1}"), "roundss"); } TEST_F(AssemblerX86Test, RoundSD) { - DriverStr(RepeatFFI(&x86::X86Assembler::roundsd, 1U, + DriverStr(RepeatFFI(&x86::X86Assembler::roundsd, /*imm_bytes*/ 1U, "roundsd ${imm}, %{reg2}, %{reg1}"), "roundsd"); } @@ -896,7 +911,15 @@ TEST_F(AssemblerX86Test, NearLabel) { } TEST_F(AssemblerX86Test, Cmpb) { - DriverStr(RepeatAI(&x86::X86Assembler::cmpb, /*imm_bytes*/ 1U, "cmpb ${imm}, {mem}"), "cmpb"); + DriverStr(RepeatAI(&x86::X86Assembler::cmpb, + /*imm_bytes*/ 1U, + "cmpb ${imm}, {mem}"), "cmpb"); +} + +TEST_F(AssemblerX86Test, Cmpw) { + DriverStr(RepeatAI(&x86::X86Assembler::cmpw, + /*imm_bytes*/ 1U, + "cmpw ${imm}, {mem}"), "cmpw"); // TODO: only imm8? } } // namespace art diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc index 3bff67d2f2..51f61ca756 100644 --- a/compiler/utils/x86_64/assembler_x86_64.cc +++ b/compiler/utils/x86_64/assembler_x86_64.cc @@ -36,6 +36,34 @@ std::ostream& operator<<(std::ostream& os, const X87Register& reg) { return os << "ST" << static_cast<int>(reg); } +std::ostream& operator<<(std::ostream& os, const Address& addr) { + switch (addr.mod()) { + case 0: + if (addr.rm() != RSP || addr.cpu_index().AsRegister() == RSP) { + return os << "(%" << addr.cpu_rm() << ")"; + } else if (addr.base() == RBP) { + return os << static_cast<int>(addr.disp32()) << "(,%" << addr.cpu_index() + << "," << (1 << addr.scale()) << ")"; + } + return os << "(%" << addr.cpu_base() << ",%" + << addr.cpu_index() << "," << (1 << addr.scale()) << ")"; + case 1: + if (addr.rm() != RSP || addr.cpu_index().AsRegister() == RSP) { + return os << static_cast<int>(addr.disp8()) << "(%" << addr.cpu_rm() << ")"; + } + return os << static_cast<int>(addr.disp8()) << "(%" << addr.cpu_base() << ",%" + << addr.cpu_index() << "," << (1 << addr.scale()) << ")"; + case 2: + if (addr.rm() != RSP || addr.cpu_index().AsRegister() == RSP) { + return os << static_cast<int>(addr.disp32()) << "(%" << addr.cpu_rm() << ")"; + } + return os << static_cast<int>(addr.disp32()) << "(%" << addr.cpu_base() << ",%" + << addr.cpu_index() << "," << (1 << addr.scale()) << ")"; + default: + return os << "<address?>"; + } +} + void X86_64Assembler::call(CpuRegister reg) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitOptionalRex32(reg); diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h index fc0839b5a8..11304443e0 100644 --- a/compiler/utils/x86_64/assembler_x86_64.h +++ b/compiler/utils/x86_64/assembler_x86_64.h @@ -80,6 +80,21 @@ class Operand : public ValueObject { return static_cast<Register>(encoding_at(1) & 7); } + CpuRegister cpu_rm() const { + int ext = (rex_ & 1) != 0 ? x86_64::R8 : x86_64::RAX; + return static_cast<CpuRegister>(rm() + ext); + } + + CpuRegister cpu_index() const { + int ext = (rex_ & 2) != 0 ? x86_64::R8 : x86_64::RAX; + return static_cast<CpuRegister>(index() + ext); + } + + CpuRegister cpu_base() const { + int ext = (rex_ & 1) != 0 ? x86_64::R8 : x86_64::RAX; + return static_cast<CpuRegister>(base() + ext); + } + uint8_t rex() const { return rex_; } @@ -268,6 +283,7 @@ class Address : public Operand { Address() {} }; +std::ostream& operator<<(std::ostream& os, const Address& addr); /** * Class to handle constant area values. diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc index 3e6110d4d0..aff8871025 100644 --- a/compiler/utils/x86_64/assembler_x86_64_test.cc +++ b/compiler/utils/x86_64/assembler_x86_64_test.cc @@ -153,6 +153,55 @@ class AssemblerX86_64Test : public AssemblerTest<x86_64::X86_64Assembler, } void SetUpHelpers() OVERRIDE { + if (addresses_singleton_.size() == 0) { + // One addressing mode to test the repeat drivers. + addresses_singleton_.push_back( + x86_64::Address(x86_64::CpuRegister(x86_64::RAX), + x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_1, -1)); + } + + if (addresses_.size() == 0) { + // Several addressing modes. + addresses_.push_back( + x86_64::Address(x86_64::CpuRegister(x86_64::RDI), + x86_64::CpuRegister(x86_64::RAX), x86_64::TIMES_1, 15)); + addresses_.push_back( + x86_64::Address(x86_64::CpuRegister(x86_64::RDI), + x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_2, 16)); + addresses_.push_back( + x86_64::Address(x86_64::CpuRegister(x86_64::RDI), + x86_64::CpuRegister(x86_64::RCX), x86_64::TIMES_4, 17)); + addresses_.push_back( + x86_64::Address(x86_64::CpuRegister(x86_64::RDI), + x86_64::CpuRegister(x86_64::RDX), x86_64::TIMES_8, 18)); + addresses_.push_back(x86_64::Address(x86_64::CpuRegister(x86_64::RAX), -1)); + addresses_.push_back(x86_64::Address(x86_64::CpuRegister(x86_64::RBX), 0)); + addresses_.push_back(x86_64::Address(x86_64::CpuRegister(x86_64::RSI), 1)); + addresses_.push_back(x86_64::Address(x86_64::CpuRegister(x86_64::RDI), 987654321)); + // Several addressing modes with the special ESP. + addresses_.push_back( + x86_64::Address(x86_64::CpuRegister(x86_64::RSP), + x86_64::CpuRegister(x86_64::RAX), x86_64::TIMES_1, 15)); + addresses_.push_back( + x86_64::Address(x86_64::CpuRegister(x86_64::RSP), + x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_2, 16)); + addresses_.push_back( + x86_64::Address(x86_64::CpuRegister(x86_64::RSP), + x86_64::CpuRegister(x86_64::RCX), x86_64::TIMES_4, 17)); + addresses_.push_back( + x86_64::Address(x86_64::CpuRegister(x86_64::RSP), + x86_64::CpuRegister(x86_64::RDX), x86_64::TIMES_8, 18)); + addresses_.push_back(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), -1)); + addresses_.push_back(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 0)); + addresses_.push_back(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 1)); + addresses_.push_back(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 987654321)); + // Several addressing modes with the higher registers. + addresses_.push_back( + x86_64::Address(x86_64::CpuRegister(x86_64::R8), + x86_64::CpuRegister(x86_64::R15), x86_64::TIMES_2, -1)); + addresses_.push_back(x86_64::Address(x86_64::CpuRegister(x86_64::R15), 123456789)); + } + if (registers_.size() == 0) { registers_.push_back(new x86_64::CpuRegister(x86_64::RAX)); registers_.push_back(new x86_64::CpuRegister(x86_64::RBX)); @@ -248,8 +297,7 @@ class AssemblerX86_64Test : public AssemblerTest<x86_64::X86_64Assembler, } std::vector<x86_64::Address> GetAddresses() { - UNIMPLEMENTED(FATAL) << "Feature not implemented yet"; - UNREACHABLE(); + return addresses_; } std::vector<x86_64::CpuRegister*> GetRegisters() OVERRIDE { @@ -279,29 +327,31 @@ class AssemblerX86_64Test : public AssemblerTest<x86_64::X86_64Assembler, return quaternary_register_names_[reg]; } + std::vector<x86_64::Address> addresses_singleton_; + private: + std::vector<x86_64::Address> addresses_; std::vector<x86_64::CpuRegister*> registers_; std::map<x86_64::CpuRegister, std::string, X86_64CpuRegisterCompare> secondary_register_names_; std::map<x86_64::CpuRegister, std::string, X86_64CpuRegisterCompare> tertiary_register_names_; std::map<x86_64::CpuRegister, std::string, X86_64CpuRegisterCompare> quaternary_register_names_; - std::vector<x86_64::XmmRegister*> fp_registers_; }; // -// Test repeat drivers used in the tests. +// Test some repeat drivers used in the tests. // TEST_F(AssemblerX86_64Test, RepeatI4) { - EXPECT_EQ("%0\n%-1\n%18\n%4660\n%-4660\n%305419896\n%-305419896\n", - RepeatI(/*f*/ nullptr, /*imm_bytes*/ 4U, "%{imm}")); + EXPECT_EQ("$0\n$-1\n$18\n$4660\n$-4660\n$305419896\n$-305419896\n", + RepeatI(/*f*/ nullptr, /*imm_bytes*/ 4U, "${imm}")); } TEST_F(AssemblerX86_64Test, RepeatI8) { - EXPECT_EQ("%0\n%-1\n%18\n%4660\n%-4660\n%305419896\n%-305419896\n" - "%20015998343868\n%-20015998343868\n%1311768467463790320\n" - "%-1311768467463790320\n", - RepeatI(/*f*/ nullptr, /*imm_bytes*/ 8U, "%{imm}")); + EXPECT_EQ("$0\n$-1\n$18\n$4660\n$-4660\n$305419896\n$-305419896\n" + "$20015998343868\n$-20015998343868\n$1311768467463790320\n" + "$-1311768467463790320\n", + RepeatI(/*f*/ nullptr, /*imm_bytes*/ 8U, "${imm}")); } TEST_F(AssemblerX86_64Test, Repeatr) { @@ -310,10 +360,10 @@ TEST_F(AssemblerX86_64Test, Repeatr) { Repeatr(/*f*/ nullptr, "%{reg}")); } -TEST_F(AssemblerX86_64Test, Repeatri) { - EXPECT_NE(Repeatri(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg} %{imm}"). - find("%eax %0\n%eax %-1\n%eax %18\n%ebx %0\n%ebx %-1\n%ebx %18\n" - "%ecx %0\n%ecx %-1\n%ecx %18\n%edx %0\n%edx %-1\n%edx %18\n"), +TEST_F(AssemblerX86_64Test, RepeatrI) { + EXPECT_NE(RepeatrI(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg} ${imm}"). + find("%eax $0\n%eax $-1\n%eax $18\n%ebx $0\n%ebx $-1\n%ebx $18\n" + "%ecx $0\n%ecx $-1\n%ecx $18\n%edx $0\n%edx $-1\n%edx $18\n"), std::string::npos); } @@ -334,10 +384,7 @@ TEST_F(AssemblerX86_64Test, Repeatrb) { TEST_F(AssemblerX86_64Test, RepeatrF) { EXPECT_NE(RepeatrF(/*f*/ nullptr, "%{reg1} %{reg2}") .find("%eax %xmm0\n%eax %xmm1\n%eax %xmm2\n%eax %xmm3\n" - "%eax %xmm4\n%eax %xmm5\n%eax %xmm6\n%eax %xmm7\n" - "%eax %xmm8\n%eax %xmm9\n%eax %xmm10\n%eax %xmm11\n" - "%eax %xmm12\n%eax %xmm13\n%eax %xmm14\n%eax %xmm15\n" - "%ebx %xmm0\n%ebx %xmm1\n%ebx %xmm2\n%ebx %xmm3\n%ebx %xmm4\n"), + "%eax %xmm4\n%eax %xmm5\n%eax %xmm6\n%eax %xmm7\n"), std::string::npos); } @@ -348,59 +395,103 @@ TEST_F(AssemblerX86_64Test, RepeatR) { } TEST_F(AssemblerX86_64Test, RepeatRI) { - EXPECT_EQ("%rax %0\n%rax %-1\n%rax %18\n%rbx %0\n%rbx %-1\n%rbx %18\n" - "%rcx %0\n%rcx %-1\n%rcx %18\n%rdx %0\n%rdx %-1\n%rdx %18\n" - "%rbp %0\n%rbp %-1\n%rbp %18\n%rsp %0\n%rsp %-1\n%rsp %18\n" - "%rsi %0\n%rsi %-1\n%rsi %18\n%rdi %0\n%rdi %-1\n%rdi %18\n" - "%r8 %0\n%r8 %-1\n%r8 %18\n%r9 %0\n%r9 %-1\n%r9 %18\n" - "%r10 %0\n%r10 %-1\n%r10 %18\n%r11 %0\n%r11 %-1\n%r11 %18\n" - "%r12 %0\n%r12 %-1\n%r12 %18\n%r13 %0\n%r13 %-1\n%r13 %18\n" - "%r14 %0\n%r14 %-1\n%r14 %18\n%r15 %0\n%r15 %-1\n%r15 %18\n", - RepeatRI(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg} %{imm}")); + EXPECT_NE(RepeatRI(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg} ${imm}") + .find("%rax $0\n%rax $-1\n%rax $18\n%rbx $0\n%rbx $-1\n%rbx $18\n" + "%rcx $0\n%rcx $-1\n%rcx $18\n%rdx $0\n%rdx $-1\n%rdx $18\n"), + std::string::npos); } TEST_F(AssemblerX86_64Test, RepeatRr) { EXPECT_NE(RepeatRr(/*f*/ nullptr, "%{reg1} %{reg2}") .find("%rax %eax\n%rax %ebx\n%rax %ecx\n%rax %edx\n%rax %ebp\n" - "%rax %esp\n%rax %esi\n%rax %edi\n%rax %r8d\n%rax %r9d\n" - "%rax %r10d\n%rax %r11d\n%rax %r12d\n%rax %r13d\n%rax %r14d\n" - "%rax %r15d\n%rbx %eax\n%rbx %ebx\n%rbx %ecx\n%rbx %edx\n"), + "%rax %esp\n%rax %esi\n%rax %edi\n%rax %r8d\n%rax %r9d\n"), std::string::npos); } TEST_F(AssemblerX86_64Test, RepeatRR) { EXPECT_NE(RepeatRR(/*f*/ nullptr, "%{reg1} %{reg2}") .find("%rax %rax\n%rax %rbx\n%rax %rcx\n%rax %rdx\n%rax %rbp\n" - "%rax %rsp\n%rax %rsi\n%rax %rdi\n%rax %r8\n%rax %r9\n" - "%rax %r10\n%rax %r11\n%rax %r12\n%rax %r13\n%rax %r14\n" - "%rax %r15\n%rbx %rax\n%rbx %rbx\n%rbx %rcx\n%rbx %rdx\n"), + "%rax %rsp\n%rax %rsi\n%rax %rdi\n%rax %r8\n%rax %r9\n"), std::string::npos); } TEST_F(AssemblerX86_64Test, RepeatRF) { EXPECT_NE(RepeatRF(/*f*/ nullptr, "%{reg1} %{reg2}") .find("%rax %xmm0\n%rax %xmm1\n%rax %xmm2\n%rax %xmm3\n%rax %xmm4\n" - "%rax %xmm5\n%rax %xmm6\n%rax %xmm7\n%rax %xmm8\n%rax %xmm9\n" - "%rax %xmm10\n%rax %xmm11\n%rax %xmm12\n%rax %xmm13\n%rax %xmm14\n" - "%rax %xmm15\n%rbx %xmm0\n%rbx %xmm1\n%rbx %xmm2\n%rbx %xmm3\n"), + "%rax %xmm5\n%rax %xmm6\n%rax %xmm7\n%rax %xmm8\n%rax %xmm9\n"), std::string::npos); } TEST_F(AssemblerX86_64Test, RepeatFF) { EXPECT_NE(RepeatFF(/*f*/ nullptr, "%{reg1} %{reg2}") .find("%xmm0 %xmm0\n%xmm0 %xmm1\n%xmm0 %xmm2\n%xmm0 %xmm3\n%xmm0 %xmm4\n" - "%xmm0 %xmm5\n%xmm0 %xmm6\n%xmm0 %xmm7\n%xmm0 %xmm8\n%xmm0 %xmm9\n" - "%xmm0 %xmm10\n%xmm0 %xmm11\n%xmm0 %xmm12\n%xmm0 %xmm13\n%xmm0 %xmm14\n" - "%xmm0 %xmm15\n%xmm1 %xmm0\n%xmm1 %xmm1\n%xmm1 %xmm2\n%xmm1 %xmm3\n"), + "%xmm0 %xmm5\n%xmm0 %xmm6\n%xmm0 %xmm7\n%xmm0 %xmm8\n%xmm0 %xmm9\n"), std::string::npos); } TEST_F(AssemblerX86_64Test, RepeatFFI) { - EXPECT_NE(RepeatFFI(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg1} %{reg2} %{imm}") - .find("%xmm0 %xmm0 %0\n%xmm0 %xmm0 %-1\n%xmm0 %xmm0 %18\n" - "%xmm0 %xmm1 %0\n%xmm0 %xmm1 %-1\n%xmm0 %xmm1 %18\n" - "%xmm0 %xmm2 %0\n%xmm0 %xmm2 %-1\n%xmm0 %xmm2 %18\n" - "%xmm0 %xmm3 %0\n%xmm0 %xmm3 %-1\n%xmm0 %xmm3 %18\n"), + EXPECT_NE(RepeatFFI(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg1} %{reg2} ${imm}") + .find("%xmm0 %xmm0 $0\n%xmm0 %xmm0 $-1\n%xmm0 %xmm0 $18\n" + "%xmm0 %xmm1 $0\n%xmm0 %xmm1 $-1\n%xmm0 %xmm1 $18\n"), + std::string::npos); +} + +TEST_F(AssemblerX86_64Test, RepeatA) { + EXPECT_EQ("-1(%rax,%rbx,1)\n", RepeatA(/*f*/ nullptr, addresses_singleton_, "{mem}")); +} + +TEST_F(AssemblerX86_64Test, RepeatAFull) { + EXPECT_EQ("15(%rdi,%rax,1)\n16(%rdi,%rbx,2)\n17(%rdi,%rcx,4)\n18(%rdi,%rdx,8)\n" + "-1(%rax)\n(%rbx)\n1(%rsi)\n987654321(%rdi)\n15(%rsp,%rax,1)\n" + "16(%rsp,%rbx,2)\n17(%rsp,%rcx,4)\n18(%rsp,%rdx,8)\n-1(%rsp)\n" + "(%rsp)\n1(%rsp)\n987654321(%rsp)\n-1(%r8,%r15,2)\n123456789(%r15)\n", + RepeatA(/*f*/ nullptr, "{mem}")); +} + +TEST_F(AssemblerX86_64Test, RepeatAI) { + EXPECT_EQ("-1(%rax,%rbx,1) $0\n-1(%rax,%rbx,1) $-1\n-1(%rax,%rbx,1) $18\n", + RepeatAI(/*f*/ nullptr, /*imm_bytes*/ 1U, addresses_singleton_, "{mem} ${imm}")); +} + +TEST_F(AssemblerX86_64Test, RepeatRA) { + EXPECT_NE(RepeatRA(/*f*/ nullptr, addresses_singleton_, "%{reg} {mem}") + .find("%rax -1(%rax,%rbx,1)\n%rbx -1(%rax,%rbx,1)\n%rcx -1(%rax,%rbx,1)\n" + "%rdx -1(%rax,%rbx,1)\n%rbp -1(%rax,%rbx,1)\n%rsp -1(%rax,%rbx,1)\n"), + std::string::npos); +} + +TEST_F(AssemblerX86_64Test, RepeatrA) { + EXPECT_NE(RepeatrA(/*f*/ nullptr, addresses_singleton_, "%{reg} {mem}") + .find("%eax -1(%rax,%rbx,1)\n%ebx -1(%rax,%rbx,1)\n%ecx -1(%rax,%rbx,1)\n" + "%edx -1(%rax,%rbx,1)\n%ebp -1(%rax,%rbx,1)\n%esp -1(%rax,%rbx,1)\n"), + std::string::npos); +} + +TEST_F(AssemblerX86_64Test, RepeatAR) { + EXPECT_NE(RepeatAR(/*f*/ nullptr, addresses_singleton_, "{mem} %{reg}") + .find("-1(%rax,%rbx,1) %rax\n-1(%rax,%rbx,1) %rbx\n-1(%rax,%rbx,1) %rcx\n" + "-1(%rax,%rbx,1) %rdx\n-1(%rax,%rbx,1) %rbp\n-1(%rax,%rbx,1) %rsp\n"), + std::string::npos); +} + +TEST_F(AssemblerX86_64Test, RepeatAr) { + EXPECT_NE(RepeatAr(/*f*/ nullptr, addresses_singleton_, "{mem} %{reg}") + .find("-1(%rax,%rbx,1) %eax\n-1(%rax,%rbx,1) %ebx\n-1(%rax,%rbx,1) %ecx\n" + "-1(%rax,%rbx,1) %edx\n-1(%rax,%rbx,1) %ebp\n-1(%rax,%rbx,1) %esp\n"), + std::string::npos); +} + +TEST_F(AssemblerX86_64Test, RepeatFA) { + EXPECT_NE(RepeatFA(/*f*/ nullptr, addresses_singleton_, "%{reg} {mem}"). + find("%xmm0 -1(%rax,%rbx,1)\n%xmm1 -1(%rax,%rbx,1)\n%xmm2 -1(%rax,%rbx,1)\n" + "%xmm3 -1(%rax,%rbx,1)\n%xmm4 -1(%rax,%rbx,1)\n%xmm5 -1(%rax,%rbx,1)\n"), + std::string::npos); +} + +TEST_F(AssemblerX86_64Test, RepeatAF) { + EXPECT_NE(RepeatAF(/*f*/ nullptr, addresses_singleton_, "{mem} %{reg}") + .find("-1(%rax,%rbx,1) %xmm0\n-1(%rax,%rbx,1) %xmm1\n-1(%rax,%rbx,1) %xmm2\n" + "-1(%rax,%rbx,1) %xmm3\n-1(%rax,%rbx,1) %xmm4\n-1(%rax,%rbx,1) %xmm5\n"), std::string::npos); } @@ -412,12 +503,43 @@ TEST_F(AssemblerX86_64Test, Toolchain) { EXPECT_TRUE(CheckTools()); } +TEST_F(AssemblerX86_64Test, PopqAllAddresses) { + // Make sure all addressing modes combinations are tested at least once. + std::vector<x86_64::Address> all_addresses; + for (x86_64::CpuRegister* base : GetRegisters()) { + // Base only. + all_addresses.push_back(x86_64::Address(*base, -1)); + all_addresses.push_back(x86_64::Address(*base, 0)); + all_addresses.push_back(x86_64::Address(*base, 1)); + all_addresses.push_back(x86_64::Address(*base, 123456789)); + for (x86_64::CpuRegister* index : GetRegisters()) { + if (index->AsRegister() == x86_64::RSP) { + // Index cannot be RSP. + continue; + } else if (base->AsRegister() == index->AsRegister()) { + // Index only. + all_addresses.push_back(x86_64::Address(*index, x86_64::TIMES_1, -1)); + all_addresses.push_back(x86_64::Address(*index, x86_64::TIMES_2, 0)); + all_addresses.push_back(x86_64::Address(*index, x86_64::TIMES_4, 1)); + all_addresses.push_back(x86_64::Address(*index, x86_64::TIMES_8, 123456789)); + } + // Base and index. + all_addresses.push_back(x86_64::Address(*base, *index, x86_64::TIMES_1, -1)); + all_addresses.push_back(x86_64::Address(*base, *index, x86_64::TIMES_2, 0)); + all_addresses.push_back(x86_64::Address(*base, *index, x86_64::TIMES_4, 1)); + all_addresses.push_back(x86_64::Address(*base, *index, x86_64::TIMES_8, 123456789)); + } + } + DriverStr(RepeatA(&x86_64::X86_64Assembler::popq, all_addresses, "popq {mem}"), "popq"); +} + TEST_F(AssemblerX86_64Test, PushqRegs) { DriverStr(RepeatR(&x86_64::X86_64Assembler::pushq, "pushq %{reg}"), "pushq"); } TEST_F(AssemblerX86_64Test, PushqImm) { - DriverStr(RepeatI(&x86_64::X86_64Assembler::pushq, 4U, "pushq ${imm}"), "pushqi"); + DriverStr(RepeatI(&x86_64::X86_64Assembler::pushq, /*imm_bytes*/ 4U, + "pushq ${imm}"), "pushqi"); } TEST_F(AssemblerX86_64Test, MovqRegs) { @@ -425,7 +547,8 @@ TEST_F(AssemblerX86_64Test, MovqRegs) { } TEST_F(AssemblerX86_64Test, MovqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::movq, 8U, "movq ${imm}, %{reg}"), "movqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::movq, /*imm_bytes*/ 8U, + "movq ${imm}, %{reg}"), "movqi"); } TEST_F(AssemblerX86_64Test, MovlRegs) { @@ -433,7 +556,8 @@ TEST_F(AssemblerX86_64Test, MovlRegs) { } TEST_F(AssemblerX86_64Test, MovlImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::movl, 4U, "mov ${imm}, %{reg}"), "movli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::movl, /*imm_bytes*/ 4U, + "mov ${imm}, %{reg}"), "movli"); } TEST_F(AssemblerX86_64Test, AddqRegs) { @@ -441,7 +565,8 @@ TEST_F(AssemblerX86_64Test, AddqRegs) { } TEST_F(AssemblerX86_64Test, AddqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::addq, 4U, "addq ${imm}, %{reg}"), "addqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::addq, /*imm_bytes*/ 4U, + "addq ${imm}, %{reg}"), "addqi"); } TEST_F(AssemblerX86_64Test, AddlRegs) { @@ -449,7 +574,8 @@ TEST_F(AssemblerX86_64Test, AddlRegs) { } TEST_F(AssemblerX86_64Test, AddlImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::addl, 4U, "add ${imm}, %{reg}"), "addli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::addl, /*imm_bytes*/ 4U, + "add ${imm}, %{reg}"), "addli"); } TEST_F(AssemblerX86_64Test, ImulqReg1) { @@ -461,7 +587,8 @@ TEST_F(AssemblerX86_64Test, ImulqRegs) { } TEST_F(AssemblerX86_64Test, ImulqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::imulq, 4U, "imulq ${imm}, %{reg}, %{reg}"), + DriverStr(RepeatRI(&x86_64::X86_64Assembler::imulq, /*imm_bytes*/ 4U, + "imulq ${imm}, %{reg}, %{reg}"), "imulqi"); } @@ -470,7 +597,8 @@ TEST_F(AssemblerX86_64Test, ImullRegs) { } TEST_F(AssemblerX86_64Test, ImullImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::imull, 4U, "imull ${imm}, %{reg}, %{reg}"), + DriverStr(RepeatrI(&x86_64::X86_64Assembler::imull, /*imm_bytes*/ 4U, + "imull ${imm}, %{reg}, %{reg}"), "imulli"); } @@ -483,7 +611,8 @@ TEST_F(AssemblerX86_64Test, SubqRegs) { } TEST_F(AssemblerX86_64Test, SubqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::subq, 4U, "subq ${imm}, %{reg}"), "subqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::subq, /*imm_bytes*/ 4U, + "subq ${imm}, %{reg}"), "subqi"); } TEST_F(AssemblerX86_64Test, SublRegs) { @@ -491,21 +620,19 @@ TEST_F(AssemblerX86_64Test, SublRegs) { } TEST_F(AssemblerX86_64Test, SublImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::subl, 4U, "sub ${imm}, %{reg}"), "subli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::subl, /*imm_bytes*/ 4U, + "sub ${imm}, %{reg}"), "subli"); } // Shll only allows CL as the shift count. std::string shll_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; - std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); - x86_64::CpuRegister shifter(x86_64::RCX); for (auto reg : registers) { assembler->shll(*reg, shifter); str << "shll %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n"; } - return str.str(); } @@ -514,21 +641,19 @@ TEST_F(AssemblerX86_64Test, ShllReg) { } TEST_F(AssemblerX86_64Test, ShllImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::shll, 1U, "shll ${imm}, %{reg}"), "shlli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::shll, /*imm_bytes*/ 1U, + "shll ${imm}, %{reg}"), "shlli"); } // Shlq only allows CL as the shift count. std::string shlq_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; - std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); - x86_64::CpuRegister shifter(x86_64::RCX); for (auto reg : registers) { assembler->shlq(*reg, shifter); str << "shlq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; } - return str.str(); } @@ -537,21 +662,19 @@ TEST_F(AssemblerX86_64Test, ShlqReg) { } TEST_F(AssemblerX86_64Test, ShlqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::shlq, 1U, "shlq ${imm}, %{reg}"), "shlqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::shlq, /*imm_bytes*/ 1U, + "shlq ${imm}, %{reg}"), "shlqi"); } // Shrl only allows CL as the shift count. std::string shrl_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; - std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); - x86_64::CpuRegister shifter(x86_64::RCX); for (auto reg : registers) { assembler->shrl(*reg, shifter); str << "shrl %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n"; } - return str.str(); } @@ -560,21 +683,18 @@ TEST_F(AssemblerX86_64Test, ShrlReg) { } TEST_F(AssemblerX86_64Test, ShrlImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::shrl, 1U, "shrl ${imm}, %{reg}"), "shrli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::shrl, /*imm_bytes*/ 1U, "shrl ${imm}, %{reg}"), "shrli"); } // Shrq only allows CL as the shift count. std::string shrq_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; - std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); - x86_64::CpuRegister shifter(x86_64::RCX); for (auto reg : registers) { assembler->shrq(*reg, shifter); str << "shrq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; } - return str.str(); } @@ -583,21 +703,18 @@ TEST_F(AssemblerX86_64Test, ShrqReg) { } TEST_F(AssemblerX86_64Test, ShrqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::shrq, 1U, "shrq ${imm}, %{reg}"), "shrqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::shrq, /*imm_bytes*/ 1U, "shrq ${imm}, %{reg}"), "shrqi"); } // Sarl only allows CL as the shift count. std::string sarl_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; - std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); - x86_64::CpuRegister shifter(x86_64::RCX); for (auto reg : registers) { assembler->sarl(*reg, shifter); str << "sarl %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n"; } - return str.str(); } @@ -606,21 +723,18 @@ TEST_F(AssemblerX86_64Test, SarlReg) { } TEST_F(AssemblerX86_64Test, SarlImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::sarl, 1U, "sarl ${imm}, %{reg}"), "sarli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::sarl, /*imm_bytes*/ 1U, "sarl ${imm}, %{reg}"), "sarli"); } // Sarq only allows CL as the shift count. std::string sarq_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; - std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); - x86_64::CpuRegister shifter(x86_64::RCX); for (auto reg : registers) { assembler->sarq(*reg, shifter); str << "sarq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; } - return str.str(); } @@ -629,21 +743,18 @@ TEST_F(AssemblerX86_64Test, SarqReg) { } TEST_F(AssemblerX86_64Test, SarqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::sarq, 1U, "sarq ${imm}, %{reg}"), "sarqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::sarq, /*imm_bytes*/ 1U, "sarq ${imm}, %{reg}"), "sarqi"); } // Rorl only allows CL as the shift count. std::string rorl_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; - std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); - x86_64::CpuRegister shifter(x86_64::RCX); for (auto reg : registers) { assembler->rorl(*reg, shifter); str << "rorl %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n"; } - return str.str(); } @@ -652,21 +763,18 @@ TEST_F(AssemblerX86_64Test, RorlReg) { } TEST_F(AssemblerX86_64Test, RorlImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::rorl, 1U, "rorl ${imm}, %{reg}"), "rorli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::rorl, /*imm_bytes*/ 1U, "rorl ${imm}, %{reg}"), "rorli"); } // Roll only allows CL as the shift count. std::string roll_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; - std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); - x86_64::CpuRegister shifter(x86_64::RCX); for (auto reg : registers) { assembler->roll(*reg, shifter); str << "roll %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n"; } - return str.str(); } @@ -675,21 +783,18 @@ TEST_F(AssemblerX86_64Test, RollReg) { } TEST_F(AssemblerX86_64Test, RollImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::roll, 1U, "roll ${imm}, %{reg}"), "rolli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::roll, /*imm_bytes*/ 1U, "roll ${imm}, %{reg}"), "rolli"); } // Rorq only allows CL as the shift count. std::string rorq_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; - std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); - x86_64::CpuRegister shifter(x86_64::RCX); for (auto reg : registers) { assembler->rorq(*reg, shifter); str << "rorq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; } - return str.str(); } @@ -698,21 +803,18 @@ TEST_F(AssemblerX86_64Test, RorqReg) { } TEST_F(AssemblerX86_64Test, RorqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::rorq, 1U, "rorq ${imm}, %{reg}"), "rorqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::rorq, /*imm_bytes*/ 1U, "rorq ${imm}, %{reg}"), "rorqi"); } // Rolq only allows CL as the shift count. std::string rolq_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { std::ostringstream str; - std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); - x86_64::CpuRegister shifter(x86_64::RCX); for (auto reg : registers) { assembler->rolq(*reg, shifter); str << "rolq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; } - return str.str(); } @@ -721,7 +823,7 @@ TEST_F(AssemblerX86_64Test, RolqReg) { } TEST_F(AssemblerX86_64Test, RolqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::rolq, 1U, "rolq ${imm}, %{reg}"), "rolqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::rolq, /*imm_bytes*/ 1U, "rolq ${imm}, %{reg}"), "rolqi"); } TEST_F(AssemblerX86_64Test, CmpqRegs) { @@ -729,8 +831,9 @@ TEST_F(AssemblerX86_64Test, CmpqRegs) { } TEST_F(AssemblerX86_64Test, CmpqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::cmpq, 4U /* cmpq only supports 32b imm */, - "cmpq ${imm}, %{reg}"), "cmpqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::cmpq, + /*imm_bytes*/ 4U, + "cmpq ${imm}, %{reg}"), "cmpqi"); // only imm32 } TEST_F(AssemblerX86_64Test, CmplRegs) { @@ -738,7 +841,7 @@ TEST_F(AssemblerX86_64Test, CmplRegs) { } TEST_F(AssemblerX86_64Test, CmplImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::cmpl, 4U, "cmpl ${imm}, %{reg}"), "cmpli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::cmpl, /*imm_bytes*/ 4U, "cmpl ${imm}, %{reg}"), "cmpli"); } TEST_F(AssemblerX86_64Test, Testl) { @@ -768,8 +871,9 @@ TEST_F(AssemblerX86_64Test, AndqRegs) { } TEST_F(AssemblerX86_64Test, AndqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::andq, 4U /* andq only supports 32b imm */, - "andq ${imm}, %{reg}"), "andqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::andq, + /*imm_bytes*/ 4U, + "andq ${imm}, %{reg}"), "andqi"); // only imm32 } TEST_F(AssemblerX86_64Test, AndlRegs) { @@ -777,7 +881,9 @@ TEST_F(AssemblerX86_64Test, AndlRegs) { } TEST_F(AssemblerX86_64Test, AndlImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::andl, 4U, "andl ${imm}, %{reg}"), "andli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::andl, + /*imm_bytes*/ 4U, + "andl ${imm}, %{reg}"), "andli"); } TEST_F(AssemblerX86_64Test, OrqRegs) { @@ -789,7 +895,8 @@ TEST_F(AssemblerX86_64Test, OrlRegs) { } TEST_F(AssemblerX86_64Test, OrlImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::orl, 4U, "orl ${imm}, %{reg}"), "orli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::orl, + /*imm_bytes*/ 4U, "orl ${imm}, %{reg}"), "orli"); } TEST_F(AssemblerX86_64Test, XorqRegs) { @@ -797,7 +904,8 @@ TEST_F(AssemblerX86_64Test, XorqRegs) { } TEST_F(AssemblerX86_64Test, XorqImm) { - DriverStr(RepeatRI(&x86_64::X86_64Assembler::xorq, 4U, "xorq ${imm}, %{reg}"), "xorqi"); + DriverStr(RepeatRI(&x86_64::X86_64Assembler::xorq, + /*imm_bytes*/ 4U, "xorq ${imm}, %{reg}"), "xorqi"); } TEST_F(AssemblerX86_64Test, XorlRegs) { @@ -805,7 +913,8 @@ TEST_F(AssemblerX86_64Test, XorlRegs) { } TEST_F(AssemblerX86_64Test, XorlImm) { - DriverStr(Repeatri(&x86_64::X86_64Assembler::xorl, 4U, "xor ${imm}, %{reg}"), "xorli"); + DriverStr(RepeatrI(&x86_64::X86_64Assembler::xorl, + /*imm_bytes*/ 4U, "xor ${imm}, %{reg}"), "xorli"); } TEST_F(AssemblerX86_64Test, Xchgq) { @@ -813,167 +922,87 @@ TEST_F(AssemblerX86_64Test, Xchgq) { } TEST_F(AssemblerX86_64Test, Xchgl) { - // Test is disabled because GCC generates 0x87 0xC0 for xchgl eax, eax. All other cases are the - // same. Anyone know why it doesn't emit a simple 0x90? It does so for xchgq rax, rax... + // TODO: Test is disabled because GCC generates 0x87 0xC0 for xchgl eax, eax. All other cases + // are the same. Anyone know why it doesn't emit a simple 0x90? It does so for xchgq rax, rax... // DriverStr(Repeatrr(&x86_64::X86_64Assembler::xchgl, "xchgl %{reg2}, %{reg1}"), "xchgl"); } TEST_F(AssemblerX86_64Test, LockCmpxchgl) { - GetAssembler()->LockCmpxchgl(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), - x86_64::CpuRegister(x86_64::RSI)); - GetAssembler()->LockCmpxchgl(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), - x86_64::CpuRegister(x86_64::RSI)); - GetAssembler()->LockCmpxchgl(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), - x86_64::CpuRegister(x86_64::R8)); - GetAssembler()->LockCmpxchgl(x86_64::Address( - x86_64::CpuRegister(x86_64::R13), 0), x86_64::CpuRegister(x86_64::RSI)); - GetAssembler()->LockCmpxchgl(x86_64::Address( - x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0), - x86_64::CpuRegister(x86_64::RSI)); - const char* expected = - "lock cmpxchgl %ESI, 0xc(%RDI,%RBX,4)\n" - "lock cmpxchgl %ESI, 0xc(%RDI,%R9,4)\n" - "lock cmpxchgl %R8d, 0xc(%RDI,%R9,4)\n" - "lock cmpxchgl %ESI, (%R13)\n" - "lock cmpxchgl %ESI, (%R13,%R9,1)\n"; - - DriverStr(expected, "lock_cmpxchgl"); + DriverStr(RepeatAr(&x86_64::X86_64Assembler::LockCmpxchgl, + "lock cmpxchgl %{reg}, {mem}"), "lock_cmpxchgl"); } TEST_F(AssemblerX86_64Test, LockCmpxchgq) { - GetAssembler()->LockCmpxchgq(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), - x86_64::CpuRegister(x86_64::RSI)); - GetAssembler()->LockCmpxchgq(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), - x86_64::CpuRegister(x86_64::RSI)); - GetAssembler()->LockCmpxchgq(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), - x86_64::CpuRegister(x86_64::R8)); - GetAssembler()->LockCmpxchgq(x86_64::Address( - x86_64::CpuRegister(x86_64::R13), 0), x86_64::CpuRegister(x86_64::RSI)); - GetAssembler()->LockCmpxchgq(x86_64::Address( - x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0), - x86_64::CpuRegister(x86_64::RSI)); - const char* expected = - "lock cmpxchg %RSI, 0xc(%RDI,%RBX,4)\n" - "lock cmpxchg %RSI, 0xc(%RDI,%R9,4)\n" - "lock cmpxchg %R8, 0xc(%RDI,%R9,4)\n" - "lock cmpxchg %RSI, (%R13)\n" - "lock cmpxchg %RSI, (%R13,%R9,1)\n"; - - DriverStr(expected, "lock_cmpxchg"); -} - -TEST_F(AssemblerX86_64Test, Movl) { - GetAssembler()->movl(x86_64::CpuRegister(x86_64::RAX), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->movl(x86_64::CpuRegister(x86_64::RAX), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - GetAssembler()->movl(x86_64::CpuRegister(x86_64::R8), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - GetAssembler()->movl(x86_64::CpuRegister(x86_64::RAX), x86_64::Address( - x86_64::CpuRegister(x86_64::R13), 0)); - GetAssembler()->movl(x86_64::CpuRegister(x86_64::RAX), x86_64::Address( - x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0)); - const char* expected = - "movl 0xc(%RDI,%RBX,4), %EAX\n" - "movl 0xc(%RDI,%R9,4), %EAX\n" - "movl 0xc(%RDI,%R9,4), %R8d\n" - "movl (%R13), %EAX\n" - "movl (%R13,%R9,1), %EAX\n"; - - DriverStr(expected, "movl"); -} - -TEST_F(AssemblerX86_64Test, Movw) { - GetAssembler()->movw(x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0), - x86_64::CpuRegister(x86_64::R9)); - GetAssembler()->movw(x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0), - x86_64::Immediate(0)); - GetAssembler()->movw(x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0), - x86_64::Immediate(0)); - GetAssembler()->movw(x86_64::Address(x86_64::CpuRegister(x86_64::R14), 0), - x86_64::Immediate(0)); - const char* expected = - "movw %R9w, 0(%RAX)\n" - "movw $0, 0(%RAX)\n" - "movw $0, 0(%R9)\n" - "movw $0, 0(%R14)\n"; - DriverStr(expected, "movw"); + DriverStr(RepeatAR(&x86_64::X86_64Assembler::LockCmpxchgq, + "lock cmpxchg %{reg}, {mem}"), "lock_cmpxchg"); +} + +TEST_F(AssemblerX86_64Test, MovqStore) { + DriverStr(RepeatAR(&x86_64::X86_64Assembler::movq, "movq %{reg}, {mem}"), "movq_s"); +} + +TEST_F(AssemblerX86_64Test, MovqLoad) { + DriverStr(RepeatRA(&x86_64::X86_64Assembler::movq, "movq {mem}, %{reg}"), "movq_l"); +} + +TEST_F(AssemblerX86_64Test, MovlStore) { + DriverStr(RepeatAr(&x86_64::X86_64Assembler::movl, "movl %{reg}, {mem}"), "movl_s"); +} + +TEST_F(AssemblerX86_64Test, MovlLoad) { + DriverStr(RepeatrA(&x86_64::X86_64Assembler::movl, "movl {mem}, %{reg}"), "movl_l"); +} + +TEST_F(AssemblerX86_64Test, MovwStore) { + DriverStr(RepeatAw(&x86_64::X86_64Assembler::movw, "movw %{reg}, {mem}"), "movw_s"); +} + +TEST_F(AssemblerX86_64Test, MovbStore) { + DriverStr(RepeatAb(&x86_64::X86_64Assembler::movb, "movb %{reg}, {mem}"), "movb_s"); } TEST_F(AssemblerX86_64Test, Cmpw) { - GetAssembler()->cmpw(x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0), - x86_64::Immediate(0)); - GetAssembler()->cmpw(x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0), - x86_64::Immediate(0)); - GetAssembler()->cmpw(x86_64::Address(x86_64::CpuRegister(x86_64::R14), 0), - x86_64::Immediate(0)); - const char* expected = - "cmpw $0, 0(%RAX)\n" - "cmpw $0, 0(%R9)\n" - "cmpw $0, 0(%R14)\n"; - DriverStr(expected, "cmpw"); + DriverStr(RepeatAI(&x86_64::X86_64Assembler::cmpw, + /*imm_bytes*/ 1U, + "cmpw ${imm}, {mem}"), "cmpw"); // TODO: only imm8? } TEST_F(AssemblerX86_64Test, MovqAddrImm) { - GetAssembler()->movq(x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0), - x86_64::Immediate(-5)); - const char* expected = "movq $-5, 0(%RAX)\n"; - DriverStr(expected, "movq"); + DriverStr(RepeatAI(&x86_64::X86_64Assembler::movq, + /*imm_bytes*/ 4U, + "movq ${imm}, {mem}"), "movq"); // only imm32 } -TEST_F(AssemblerX86_64Test, Movntl) { - GetAssembler()->movntl(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX)); - GetAssembler()->movntl(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX)); - GetAssembler()->movntl(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX)); - GetAssembler()->movntl(x86_64::Address(x86_64::CpuRegister(x86_64::R13), 0), x86_64::CpuRegister(x86_64::RAX)); - GetAssembler()->movntl(x86_64::Address( - x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0), x86_64::CpuRegister(x86_64::R9)); - const char* expected = - "movntil %EAX, 0xc(%RDI,%RBX,4)\n" - "movntil %EAX, 0xc(%RDI,%R9,4)\n" - "movntil %EAX, 0xc(%RDI,%R9,4)\n" - "movntil %EAX, (%R13)\n" - "movntil %R9d, (%R13,%R9,1)\n"; +TEST_F(AssemblerX86_64Test, MovlAddrImm) { + DriverStr(RepeatAI(&x86_64::X86_64Assembler::movl, + /*imm_bytes*/ 4U, "movl ${imm}, {mem}"), "movl"); +} - DriverStr(expected, "movntl"); +TEST_F(AssemblerX86_64Test, MovwAddrImm) { + DriverStr(RepeatAI(&x86_64::X86_64Assembler::movw, + /*imm_bytes*/ 2U, "movw ${imm}, {mem}"), "movw"); } -TEST_F(AssemblerX86_64Test, Movntq) { - GetAssembler()->movntq(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX)); - GetAssembler()->movntq(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX)); - GetAssembler()->movntq(x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX)); - GetAssembler()->movntq(x86_64::Address(x86_64::CpuRegister(x86_64::R13), 0), x86_64::CpuRegister(x86_64::RAX)); - GetAssembler()->movntq(x86_64::Address( - x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0), x86_64::CpuRegister(x86_64::R9)); - const char* expected = - "movntiq %RAX, 0xc(%RDI,%RBX,4)\n" - "movntiq %RAX, 0xc(%RDI,%R9,4)\n" - "movntiq %RAX, 0xc(%RDI,%R9,4)\n" - "movntiq %RAX, (%R13)\n" - "movntiq %R9, (%R13,%R9,1)\n"; +TEST_F(AssemblerX86_64Test, MovbAddrImm) { + DriverStr(RepeatAI(&x86_64::X86_64Assembler::movb, + /*imm_bytes*/ 1U, "movb ${imm}, {mem}"), "movb"); +} - DriverStr(expected, "movntq"); +TEST_F(AssemblerX86_64Test, Movntl) { + DriverStr(RepeatAr(&x86_64::X86_64Assembler::movntl, "movntil %{reg}, {mem}"), "movntl"); +} + +TEST_F(AssemblerX86_64Test, Movntq) { + DriverStr(RepeatAR(&x86_64::X86_64Assembler::movntq, "movntiq %{reg}, {mem}"), "movntq"); } TEST_F(AssemblerX86_64Test, Cvtsi2ssAddr) { GetAssembler()->cvtsi2ss(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0), - false); + /*is64bit*/ false); GetAssembler()->cvtsi2ss(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0), - true); + /*is64bit*/ true); const char* expected = "cvtsi2ss 0(%RAX), %xmm0\n" "cvtsi2ssq 0(%RAX), %xmm0\n"; DriverStr(expected, "cvtsi2ss"); @@ -982,111 +1011,69 @@ TEST_F(AssemblerX86_64Test, Cvtsi2ssAddr) { TEST_F(AssemblerX86_64Test, Cvtsi2sdAddr) { GetAssembler()->cvtsi2sd(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0), - false); + /*is64bit*/ false); GetAssembler()->cvtsi2sd(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0), - true); + /*is64bit*/ true); const char* expected = "cvtsi2sd 0(%RAX), %xmm0\n" "cvtsi2sdq 0(%RAX), %xmm0\n"; DriverStr(expected, "cvtsi2sd"); } TEST_F(AssemblerX86_64Test, CmpqAddr) { - GetAssembler()->cmpq(x86_64::CpuRegister(x86_64::R12), - x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0)); - const char* expected = "cmpq 0(%R9), %R12\n"; - DriverStr(expected, "cmpq"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::cmpq, "cmpq {mem}, %{reg}"), "cmpq"); } TEST_F(AssemblerX86_64Test, MovsxdAddr) { - GetAssembler()->movsxd(x86_64::CpuRegister(x86_64::R12), - x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0)); - const char* expected = "movslq 0(%R9), %R12\n"; - DriverStr(expected, "movsxd"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::movsxd, "movslq {mem}, %{reg}"), "movsxd"); } TEST_F(AssemblerX86_64Test, TestqAddr) { - GetAssembler()->testq(x86_64::CpuRegister(x86_64::R12), - x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0)); - const char* expected = "testq 0(%R9), %R12\n"; - DriverStr(expected, "testq"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::testq, "testq {mem}, %{reg}"), "testq"); } TEST_F(AssemblerX86_64Test, AddqAddr) { - GetAssembler()->addq(x86_64::CpuRegister(x86_64::R12), - x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0)); - const char* expected = "addq 0(%R9), %R12\n"; - DriverStr(expected, "addq"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::addq, "addq {mem}, %{reg}"), "addq"); } TEST_F(AssemblerX86_64Test, SubqAddr) { - GetAssembler()->subq(x86_64::CpuRegister(x86_64::R12), - x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0)); - const char* expected = "subq 0(%R9), %R12\n"; - DriverStr(expected, "subq"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::subq, "subq {mem}, %{reg}"), "subq"); } TEST_F(AssemblerX86_64Test, Cvtss2sdAddr) { - GetAssembler()->cvtss2sd(x86_64::XmmRegister(x86_64::XMM0), - x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0)); - const char* expected = "cvtss2sd 0(%RAX), %xmm0\n"; - DriverStr(expected, "cvtss2sd"); + DriverStr(RepeatFA(&x86_64::X86_64Assembler::cvtss2sd, "cvtss2sd {mem}, %{reg}"), "cvtss2sd"); } TEST_F(AssemblerX86_64Test, Cvtsd2ssAddr) { - GetAssembler()->cvtsd2ss(x86_64::XmmRegister(x86_64::XMM0), - x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0)); - const char* expected = "cvtsd2ss 0(%RAX), %xmm0\n"; - DriverStr(expected, "cvtsd2ss"); + DriverStr(RepeatFA(&x86_64::X86_64Assembler::cvtsd2ss, "cvtsd2ss {mem}, %{reg}"), "cvtsd2ss"); } TEST_F(AssemblerX86_64Test, ComissAddr) { - GetAssembler()->comiss(x86_64::XmmRegister(x86_64::XMM14), - x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0)); - const char* expected = "comiss 0(%RAX), %xmm14\n"; - DriverStr(expected, "comiss"); + DriverStr(RepeatFA(&x86_64::X86_64Assembler::comiss, "comiss {mem}, %{reg}"), "comiss"); } TEST_F(AssemblerX86_64Test, ComisdAddr) { - GetAssembler()->comisd(x86_64::XmmRegister(x86_64::XMM0), - x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0)); - const char* expected = "comisd 0(%R9), %xmm0\n"; - DriverStr(expected, "comisd"); + DriverStr(RepeatFA(&x86_64::X86_64Assembler::comisd, "comisd {mem}, %{reg}"), "comisd"); } TEST_F(AssemblerX86_64Test, UComissAddr) { - GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM0), - x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0)); - const char* expected = "ucomiss 0(%RAX), %xmm0\n"; - DriverStr(expected, "ucomiss"); + DriverStr(RepeatFA(&x86_64::X86_64Assembler::ucomiss, "ucomiss {mem}, %{reg}"), "ucomiss"); } TEST_F(AssemblerX86_64Test, UComisdAddr) { - GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM0), - x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0)); - const char* expected = "ucomisd 0(%RAX), %xmm0\n"; - DriverStr(expected, "ucomisd"); + DriverStr(RepeatFA(&x86_64::X86_64Assembler::ucomisd, "ucomisd {mem}, %{reg}"), "ucomisd"); } TEST_F(AssemblerX86_64Test, Andq) { - GetAssembler()->andq(x86_64::CpuRegister(x86_64::R9), - x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0)); - const char* expected = "andq 0(%RAX), %r9\n"; - DriverStr(expected, "andq"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::andq, "andq {mem}, %{reg}"), "andq"); } TEST_F(AssemblerX86_64Test, Orq) { - GetAssembler()->orq(x86_64::CpuRegister(x86_64::R9), - x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0)); - const char* expected = "orq 0(%RAX), %r9\n"; - DriverStr(expected, "orq"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::orq, "orq {mem}, %{reg}"), "orq"); } TEST_F(AssemblerX86_64Test, Xorq) { - GetAssembler()->xorq(x86_64::CpuRegister(x86_64::R9), - x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0)); - const char* expected = "xorq 0(%RAX), %r9\n"; - DriverStr(expected, "xorq"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::xorq, "xorq {mem}, %{reg}"), "xorq"); } TEST_F(AssemblerX86_64Test, RepneScasb) { @@ -1115,22 +1102,20 @@ TEST_F(AssemblerX86_64Test, Movaps) { DriverStr(RepeatFF(&x86_64::X86_64Assembler::movaps, "movaps %{reg2}, %{reg1}"), "movaps"); } -TEST_F(AssemblerX86_64Test, MovapsAddr) { - GetAssembler()->movaps(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4)); - GetAssembler()->movaps(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1)); - const char* expected = - "movaps 0x4(%RSP), %xmm0\n" - "movaps %xmm1, 0x2(%RSP)\n"; - DriverStr(expected, "movaps_address"); +TEST_F(AssemblerX86_64Test, MovapsStore) { + DriverStr(RepeatAF(&x86_64::X86_64Assembler::movaps, "movaps %{reg}, {mem}"), "movaps_s"); } -TEST_F(AssemblerX86_64Test, MovupsAddr) { - GetAssembler()->movups(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4)); - GetAssembler()->movups(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1)); - const char* expected = - "movups 0x4(%RSP), %xmm0\n" - "movups %xmm1, 0x2(%RSP)\n"; - DriverStr(expected, "movups_address"); +TEST_F(AssemblerX86_64Test, MovapsLoad) { + DriverStr(RepeatFA(&x86_64::X86_64Assembler::movaps, "movaps {mem}, %{reg}"), "movaps_l"); +} + +TEST_F(AssemblerX86_64Test, MovupsStore) { + DriverStr(RepeatAF(&x86_64::X86_64Assembler::movups, "movups %{reg}, {mem}"), "movups_s"); +} + +TEST_F(AssemblerX86_64Test, MovupsLoad) { + DriverStr(RepeatFA(&x86_64::X86_64Assembler::movups, "movups {mem}, %{reg}"), "movups_l"); } TEST_F(AssemblerX86_64Test, Movss) { @@ -1141,22 +1126,20 @@ TEST_F(AssemblerX86_64Test, Movapd) { DriverStr(RepeatFF(&x86_64::X86_64Assembler::movapd, "movapd %{reg2}, %{reg1}"), "movapd"); } -TEST_F(AssemblerX86_64Test, MovapdAddr) { - GetAssembler()->movapd(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4)); - GetAssembler()->movapd(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1)); - const char* expected = - "movapd 0x4(%RSP), %xmm0\n" - "movapd %xmm1, 0x2(%RSP)\n"; - DriverStr(expected, "movapd_address"); +TEST_F(AssemblerX86_64Test, MovapdStore) { + DriverStr(RepeatAF(&x86_64::X86_64Assembler::movapd, "movapd %{reg}, {mem}"), "movapd_s"); } -TEST_F(AssemblerX86_64Test, MovupdAddr) { - GetAssembler()->movupd(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4)); - GetAssembler()->movupd(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1)); - const char* expected = - "movupd 0x4(%RSP), %xmm0\n" - "movupd %xmm1, 0x2(%RSP)\n"; - DriverStr(expected, "movupd_address"); +TEST_F(AssemblerX86_64Test, MovapdLoad) { + DriverStr(RepeatFA(&x86_64::X86_64Assembler::movapd, "movapd {mem}, %{reg}"), "movapd_l"); +} + +TEST_F(AssemblerX86_64Test, MovupdStore) { + DriverStr(RepeatAF(&x86_64::X86_64Assembler::movupd, "movupd %{reg}, {mem}"), "movupd_s"); +} + +TEST_F(AssemblerX86_64Test, MovupdLoad) { + DriverStr(RepeatFA(&x86_64::X86_64Assembler::movupd, "movupd {mem}, %{reg}"), "movupd_l"); } TEST_F(AssemblerX86_64Test, Movsd) { @@ -1164,25 +1147,23 @@ TEST_F(AssemblerX86_64Test, Movsd) { } TEST_F(AssemblerX86_64Test, Movdqa) { - DriverStr(RepeatFF(&x86_64::X86_64Assembler::movdqa, "movdqa %{reg2}, %{reg1}"), "movapd"); + DriverStr(RepeatFF(&x86_64::X86_64Assembler::movdqa, "movdqa %{reg2}, %{reg1}"), "movdqa"); } -TEST_F(AssemblerX86_64Test, MovdqaAddr) { - GetAssembler()->movdqa(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4)); - GetAssembler()->movdqa(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1)); - const char* expected = - "movdqa 0x4(%RSP), %xmm0\n" - "movdqa %xmm1, 0x2(%RSP)\n"; - DriverStr(expected, "movdqa_address"); +TEST_F(AssemblerX86_64Test, MovdqaStore) { + DriverStr(RepeatAF(&x86_64::X86_64Assembler::movdqa, "movdqa %{reg}, {mem}"), "movdqa_s"); } -TEST_F(AssemblerX86_64Test, MovdquAddr) { - GetAssembler()->movdqu(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4)); - GetAssembler()->movdqu(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1)); - const char* expected = - "movdqu 0x4(%RSP), %xmm0\n" - "movdqu %xmm1, 0x2(%RSP)\n"; - DriverStr(expected, "movdqu_address"); +TEST_F(AssemblerX86_64Test, MovdqaLoad) { + DriverStr(RepeatFA(&x86_64::X86_64Assembler::movdqa, "movdqa {mem}, %{reg}"), "movdqa_l"); +} + +TEST_F(AssemblerX86_64Test, MovdquStore) { + DriverStr(RepeatAF(&x86_64::X86_64Assembler::movdqu, "movdqu %{reg}, {mem}"), "movdqu_s"); +} + +TEST_F(AssemblerX86_64Test, MovdquLoad) { + DriverStr(RepeatFA(&x86_64::X86_64Assembler::movdqu, "movdqu {mem}, %{reg}"), "movdqu_l"); } TEST_F(AssemblerX86_64Test, Movd1) { @@ -1364,11 +1345,13 @@ TEST_F(AssemblerX86_64Test, Sqrtsd) { } TEST_F(AssemblerX86_64Test, Roundss) { - DriverStr(RepeatFFI(&x86_64::X86_64Assembler::roundss, 1, "roundss ${imm}, %{reg2}, %{reg1}"), "roundss"); + DriverStr(RepeatFFI(&x86_64::X86_64Assembler::roundss, /*imm_bytes*/ 1U, + "roundss ${imm}, %{reg2}, %{reg1}"), "roundss"); } TEST_F(AssemblerX86_64Test, Roundsd) { - DriverStr(RepeatFFI(&x86_64::X86_64Assembler::roundsd, 1, "roundsd ${imm}, %{reg2}, %{reg1}"), "roundsd"); + DriverStr(RepeatFFI(&x86_64::X86_64Assembler::roundsd, /*imm_bytes*/ 1U, + "roundsd ${imm}, %{reg2}, %{reg1}"), "roundsd"); } TEST_F(AssemblerX86_64Test, Xorps) { @@ -1564,47 +1547,58 @@ TEST_F(AssemblerX86_64Test, PCmpgtq) { } TEST_F(AssemblerX86_64Test, Shufps) { - DriverStr(RepeatFFI(&x86_64::X86_64Assembler::shufps, 1, "shufps ${imm}, %{reg2}, %{reg1}"), "shufps"); + DriverStr(RepeatFFI(&x86_64::X86_64Assembler::shufps, /*imm_bytes*/ 1U, + "shufps ${imm}, %{reg2}, %{reg1}"), "shufps"); } TEST_F(AssemblerX86_64Test, Shufpd) { - DriverStr(RepeatFFI(&x86_64::X86_64Assembler::shufpd, 1, "shufpd ${imm}, %{reg2}, %{reg1}"), "shufpd"); + DriverStr(RepeatFFI(&x86_64::X86_64Assembler::shufpd, /*imm_bytes*/ 1U, + "shufpd ${imm}, %{reg2}, %{reg1}"), "shufpd"); } TEST_F(AssemblerX86_64Test, PShufd) { - DriverStr(RepeatFFI(&x86_64::X86_64Assembler::pshufd, 1, "pshufd ${imm}, %{reg2}, %{reg1}"), "pshufd"); + DriverStr(RepeatFFI(&x86_64::X86_64Assembler::pshufd, /*imm_bytes*/ 1U, + "pshufd ${imm}, %{reg2}, %{reg1}"), "pshufd"); } TEST_F(AssemblerX86_64Test, Punpcklbw) { - DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpcklbw, "punpcklbw %{reg2}, %{reg1}"), "punpcklbw"); + DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpcklbw, + "punpcklbw %{reg2}, %{reg1}"), "punpcklbw"); } TEST_F(AssemblerX86_64Test, Punpcklwd) { - DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpcklwd, "punpcklwd %{reg2}, %{reg1}"), "punpcklwd"); + DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpcklwd, + "punpcklwd %{reg2}, %{reg1}"), "punpcklwd"); } TEST_F(AssemblerX86_64Test, Punpckldq) { - DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckldq, "punpckldq %{reg2}, %{reg1}"), "punpckldq"); + DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckldq, + "punpckldq %{reg2}, %{reg1}"), "punpckldq"); } TEST_F(AssemblerX86_64Test, Punpcklqdq) { - DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpcklqdq, "punpcklqdq %{reg2}, %{reg1}"), "punpcklqdq"); + DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpcklqdq, + "punpcklqdq %{reg2}, %{reg1}"), "punpcklqdq"); } TEST_F(AssemblerX86_64Test, Punpckhbw) { - DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckhbw, "punpckhbw %{reg2}, %{reg1}"), "punpckhbw"); + DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckhbw, + "punpckhbw %{reg2}, %{reg1}"), "punpckhbw"); } TEST_F(AssemblerX86_64Test, Punpckhwd) { - DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckhwd, "punpckhwd %{reg2}, %{reg1}"), "punpckhwd"); + DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckhwd, + "punpckhwd %{reg2}, %{reg1}"), "punpckhwd"); } TEST_F(AssemblerX86_64Test, Punpckhdq) { - DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckhdq, "punpckhdq %{reg2}, %{reg1}"), "punpckhdq"); + DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckhdq, + "punpckhdq %{reg2}, %{reg1}"), "punpckhdq"); } TEST_F(AssemblerX86_64Test, Punpckhqdq) { - DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckhqdq, "punpckhqdq %{reg2}, %{reg1}"), "punpckhqdq"); + DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckhqdq, + "punpckhqdq %{reg2}, %{reg1}"), "punpckhqdq"); } TEST_F(AssemblerX86_64Test, Psllw) { @@ -1653,63 +1647,21 @@ TEST_F(AssemblerX86_64Test, Psrld) { GetAssembler()->psrld(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1)); GetAssembler()->psrld(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2)); DriverStr("psrld $1, %xmm0\n" - "psrld $2, %xmm15\n", "pslldi"); + "psrld $2, %xmm15\n", "psrldi"); } TEST_F(AssemblerX86_64Test, Psrlq) { GetAssembler()->psrlq(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1)); GetAssembler()->psrlq(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2)); DriverStr("psrlq $1, %xmm0\n" - "psrlq $2, %xmm15\n", "pslrqi"); + "psrlq $2, %xmm15\n", "psrlqi"); } TEST_F(AssemblerX86_64Test, Psrldq) { GetAssembler()->psrldq(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1)); GetAssembler()->psrldq(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2)); DriverStr("psrldq $1, %xmm0\n" - "psrldq $2, %xmm15\n", "pslrdqi"); -} - -TEST_F(AssemblerX86_64Test, UcomissAddress) { - GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM1), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM2), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM3), x86_64::Address( - x86_64::CpuRegister(x86_64::R13), 0)); - GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM4), x86_64::Address( - x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0)); - const char* expected = - "ucomiss 0xc(%RDI,%RBX,4), %xmm0\n" - "ucomiss 0xc(%RDI,%R9,4), %xmm1\n" - "ucomiss 0xc(%RDI,%R9,4), %xmm2\n" - "ucomiss (%R13), %xmm3\n" - "ucomiss (%R13,%R9,1), %xmm4\n"; - - DriverStr(expected, "ucomiss_address"); -} - -TEST_F(AssemblerX86_64Test, UcomisdAddress) { - GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM1), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM2), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM3), x86_64::Address( - x86_64::CpuRegister(x86_64::R13), 0)); - GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM4), x86_64::Address( - x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0)); - const char* expected = - "ucomisd 0xc(%RDI,%RBX,4), %xmm0\n" - "ucomisd 0xc(%RDI,%R9,4), %xmm1\n" - "ucomisd 0xc(%RDI,%R9,4), %xmm2\n" - "ucomisd (%R13), %xmm3\n" - "ucomisd (%R13,%R9,1), %xmm4\n"; - - DriverStr(expected, "ucomisd_address"); + "psrldq $2, %xmm15\n", "psrldqi"); } std::string x87_fn(AssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED, @@ -1735,22 +1687,28 @@ TEST_F(AssemblerX86_64Test, X87) { DriverFn(&x87_fn, "x87"); } -TEST_F(AssemblerX86_64Test, FPUIntegerLoad) { - GetAssembler()->filds(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4)); - GetAssembler()->fildl(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 12)); - const char* expected = - "fildl 0x4(%RSP)\n" - "fildll 0xc(%RSP)\n"; - DriverStr(expected, "FPUIntegerLoad"); +TEST_F(AssemblerX86_64Test, FPUIntegerLoads) { + DriverStr(RepeatA(&x86_64::X86_64Assembler::filds, + addresses_singleton_, // no ext addressing + "fildl {mem}"), "filds"); } -TEST_F(AssemblerX86_64Test, FPUIntegerStore) { - GetAssembler()->fistps(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 16)); - GetAssembler()->fistpl(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 24)); - const char* expected = - "fistpl 0x10(%RSP)\n" - "fistpll 0x18(%RSP)\n"; - DriverStr(expected, "FPUIntegerStore"); +TEST_F(AssemblerX86_64Test, FPUIntegerLoadl) { + DriverStr(RepeatA(&x86_64::X86_64Assembler::fildl, + addresses_singleton_, // no ext addressing + "fildll {mem}"), "fildl"); +} + +TEST_F(AssemblerX86_64Test, FPUIntegerStores) { + DriverStr(RepeatA(&x86_64::X86_64Assembler::fistps, + addresses_singleton_, // no ext addressing + "fistpl {mem}"), "fistps"); +} + +TEST_F(AssemblerX86_64Test, FPUIntegerStorel) { + DriverStr(RepeatA(&x86_64::X86_64Assembler::fistpl, + addresses_singleton_, // no ext addressing + "fistpll {mem}"), "fistpl"); } TEST_F(AssemblerX86_64Test, Call) { @@ -1762,13 +1720,15 @@ TEST_F(AssemblerX86_64Test, Jmp) { } TEST_F(AssemblerX86_64Test, Enter) { - DriverStr(RepeatI(&x86_64::X86_64Assembler::enter, 2U /* 16b immediate */, "enter ${imm}, $0", - true /* Only non-negative number */), "enter"); + DriverStr(RepeatI(&x86_64::X86_64Assembler::enter, + /*imm_bytes*/ 2U, + "enter ${imm}, $0", /*non-negative*/ true), "enter"); } TEST_F(AssemblerX86_64Test, RetImm) { - DriverStr(RepeatI(&x86_64::X86_64Assembler::ret, 2U /* 16b immediate */, "ret ${imm}", - true /* Only non-negative number */), "reti"); + DriverStr(RepeatI(&x86_64::X86_64Assembler::ret, + /*imm_bytes*/ 2U, + "ret ${imm}", /*non-negative*/ true), "ret"); } std::string ret_and_leave_fn(AssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED, @@ -1801,18 +1761,7 @@ TEST_F(AssemblerX86_64Test, Bsfl) { } TEST_F(AssemblerX86_64Test, BsflAddress) { - GetAssembler()->bsfl(x86_64::CpuRegister(x86_64::R10), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->bsfl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->bsfl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - const char* expected = - "bsfl 0xc(%RDI,%RBX,4), %R10d\n" - "bsfl 0xc(%R10,%RBX,4), %edi\n" - "bsfl 0xc(%RDI,%R9,4), %edi\n"; - - DriverStr(expected, "bsfl_address"); + DriverStr(RepeatrA(&x86_64::X86_64Assembler::bsfl, "bsfl {mem}, %{reg}"), "bsfl_address"); } TEST_F(AssemblerX86_64Test, Bsfq) { @@ -1820,18 +1769,7 @@ TEST_F(AssemblerX86_64Test, Bsfq) { } TEST_F(AssemblerX86_64Test, BsfqAddress) { - GetAssembler()->bsfq(x86_64::CpuRegister(x86_64::R10), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->bsfq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->bsfq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - const char* expected = - "bsfq 0xc(%RDI,%RBX,4), %R10\n" - "bsfq 0xc(%R10,%RBX,4), %RDI\n" - "bsfq 0xc(%RDI,%R9,4), %RDI\n"; - - DriverStr(expected, "bsfq_address"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::bsfq, "bsfq {mem}, %{reg}"), "bsfq_address"); } TEST_F(AssemblerX86_64Test, Bsrl) { @@ -1839,18 +1777,7 @@ TEST_F(AssemblerX86_64Test, Bsrl) { } TEST_F(AssemblerX86_64Test, BsrlAddress) { - GetAssembler()->bsrl(x86_64::CpuRegister(x86_64::R10), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->bsrl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->bsrl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - const char* expected = - "bsrl 0xc(%RDI,%RBX,4), %R10d\n" - "bsrl 0xc(%R10,%RBX,4), %edi\n" - "bsrl 0xc(%RDI,%R9,4), %edi\n"; - - DriverStr(expected, "bsrl_address"); + DriverStr(RepeatrA(&x86_64::X86_64Assembler::bsrl, "bsrl {mem}, %{reg}"), "bsrl_address"); } TEST_F(AssemblerX86_64Test, Bsrq) { @@ -1858,18 +1785,7 @@ TEST_F(AssemblerX86_64Test, Bsrq) { } TEST_F(AssemblerX86_64Test, BsrqAddress) { - GetAssembler()->bsrq(x86_64::CpuRegister(x86_64::R10), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->bsrq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->bsrq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - const char* expected = - "bsrq 0xc(%RDI,%RBX,4), %R10\n" - "bsrq 0xc(%R10,%RBX,4), %RDI\n" - "bsrq 0xc(%RDI,%R9,4), %RDI\n"; - - DriverStr(expected, "bsrq_address"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::bsrq, "bsrq {mem}, %{reg}"), "bsrq_address"); } TEST_F(AssemblerX86_64Test, Popcntl) { @@ -1877,18 +1793,7 @@ TEST_F(AssemblerX86_64Test, Popcntl) { } TEST_F(AssemblerX86_64Test, PopcntlAddress) { - GetAssembler()->popcntl(x86_64::CpuRegister(x86_64::R10), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->popcntl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->popcntl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - const char* expected = - "popcntl 0xc(%RDI,%RBX,4), %R10d\n" - "popcntl 0xc(%R10,%RBX,4), %edi\n" - "popcntl 0xc(%RDI,%R9,4), %edi\n"; - - DriverStr(expected, "popcntl_address"); + DriverStr(RepeatrA(&x86_64::X86_64Assembler::popcntl, "popcntl {mem}, %{reg}"), "popcntl_address"); } TEST_F(AssemblerX86_64Test, Popcntq) { @@ -1896,18 +1801,7 @@ TEST_F(AssemblerX86_64Test, Popcntq) { } TEST_F(AssemblerX86_64Test, PopcntqAddress) { - GetAssembler()->popcntq(x86_64::CpuRegister(x86_64::R10), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->popcntq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); - GetAssembler()->popcntq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( - x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); - const char* expected = - "popcntq 0xc(%RDI,%RBX,4), %R10\n" - "popcntq 0xc(%R10,%RBX,4), %RDI\n" - "popcntq 0xc(%RDI,%R9,4), %RDI\n"; - - DriverStr(expected, "popcntq_address"); + DriverStr(RepeatRA(&x86_64::X86_64Assembler::popcntq, "popcntq {mem}, %{reg}"), "popcntq_address"); } TEST_F(AssemblerX86_64Test, CmovlAddress) { @@ -1921,7 +1815,6 @@ TEST_F(AssemblerX86_64Test, CmovlAddress) { "cmovzl 0xc(%RDI,%RBX,4), %R10d\n" "cmovnzl 0xc(%R10,%RBX,4), %edi\n" "cmovzl 0xc(%RDI,%R9,4), %edi\n"; - DriverStr(expected, "cmovl_address"); } @@ -1936,7 +1829,6 @@ TEST_F(AssemblerX86_64Test, CmovqAddress) { "cmovzq 0xc(%RDI,%RBX,4), %R10\n" "cmovnzq 0xc(%R10,%RBX,4), %rdi\n" "cmovzq 0xc(%RDI,%R9,4), %rdi\n"; - DriverStr(expected, "cmovq_address"); } @@ -2050,52 +1942,21 @@ TEST_F(AssemblerX86_64Test, Repecmpsq) { } TEST_F(AssemblerX86_64Test, Cmpb) { - GetAssembler()->cmpb(x86_64::Address(x86_64::CpuRegister(x86_64::RDI), 128), - x86_64::Immediate(0)); - const char* expected = "cmpb $0, 128(%RDI)\n"; - DriverStr(expected, "cmpb"); + DriverStr(RepeatAI(&x86_64::X86_64Assembler::cmpb, + /*imm_bytes*/ 1U, + "cmpb ${imm}, {mem}"), "cmpb"); } TEST_F(AssemblerX86_64Test, TestbAddressImmediate) { - GetAssembler()->testb( - x86_64::Address(x86_64::CpuRegister(x86_64::RDI), - x86_64::CpuRegister(x86_64::RBX), - x86_64::TIMES_4, - 12), - x86_64::Immediate(1)); - GetAssembler()->testb( - x86_64::Address(x86_64::CpuRegister(x86_64::RSP), FrameOffset(7)), - x86_64::Immediate(-128)); - GetAssembler()->testb( - x86_64::Address(x86_64::CpuRegister(x86_64::RBX), MemberOffset(130)), - x86_64::Immediate(127)); - const char* expected = - "testb $1, 0xc(%RDI,%RBX,4)\n" - "testb $-128, 0x7(%RSP)\n" - "testb $127, 0x82(%RBX)\n"; - - DriverStr(expected, "TestbAddressImmediate"); + DriverStr(RepeatAI(&x86_64::X86_64Assembler::testb, + /*imm_bytes*/ 1U, + "testb ${imm}, {mem}"), "testbi"); } TEST_F(AssemblerX86_64Test, TestlAddressImmediate) { - GetAssembler()->testl( - x86_64::Address(x86_64::CpuRegister(x86_64::RDI), - x86_64::CpuRegister(x86_64::RBX), - x86_64::TIMES_4, - 12), - x86_64::Immediate(1)); - GetAssembler()->testl( - x86_64::Address(x86_64::CpuRegister(x86_64::RSP), FrameOffset(7)), - x86_64::Immediate(-100000)); - GetAssembler()->testl( - x86_64::Address(x86_64::CpuRegister(x86_64::RBX), MemberOffset(130)), - x86_64::Immediate(77777777)); - const char* expected = - "testl $1, 0xc(%RDI,%RBX,4)\n" - "testl $-100000, 0x7(%RSP)\n" - "testl $77777777, 0x82(%RBX)\n"; - - DriverStr(expected, "TestlAddressImmediate"); + DriverStr(RepeatAI(&x86_64::X86_64Assembler::testl, + /*imm_bytes*/ 4U, + "testl ${imm}, {mem}"), "testli"); } class JNIMacroAssemblerX86_64Test : public JNIMacroAssemblerTest<x86_64::X86_64JNIMacroAssembler> { @@ -2150,15 +2011,15 @@ std::string buildframe_test_fn(JNIMacroAssemblerX86_64Test::Base* assembler_test // Construct assembly text counterpart. std::ostringstream str; - // 1) Push the spill_regs. + // (1) Push the spill_regs. str << "pushq %rsi\n"; str << "pushq %r10\n"; - // 2) Move down the stack pointer. + // (2) Move down the stack pointer. ssize_t displacement = static_cast<ssize_t>(frame_size) - (spill_regs.size() * 8 + 8); str << "subq $" << displacement << ", %rsp\n"; - // 3) Store method reference. + // (3) Store method reference. str << "movq %rdi, (%rsp)\n"; - // 4) Entry spills. + // (4) Entry spills. str << "movq %rax, " << frame_size + 0 << "(%rsp)\n"; str << "movq %rbx, " << frame_size + 8 << "(%rsp)\n"; str << "movsd %xmm1, " << frame_size + 16 << "(%rsp)\n"; @@ -2186,10 +2047,10 @@ std::string removeframe_test_fn(JNIMacroAssemblerX86_64Test::Base* assembler_tes // Construct assembly text counterpart. std::ostringstream str; - // 1) Move up the stack pointer. + // (1) Move up the stack pointer. ssize_t displacement = static_cast<ssize_t>(frame_size) - spill_regs.size() * 8 - 8; str << "addq $" << displacement << ", %rsp\n"; - // 2) Pop spill regs. + // (2) Pop spill regs. str << "popq %r10\n"; str << "popq %rsi\n"; str << "ret\n"; diff --git a/dalvikvm/Android.bp b/dalvikvm/Android.bp index 09bbbda6a7..0405fe1003 100644 --- a/dalvikvm/Android.bp +++ b/dalvikvm/Android.bp @@ -30,15 +30,8 @@ art_cc_binary { ], whole_static_libs: ["libsigchain"], target: { - host: { - host_ldlibs: [ - "-ldl", - "-lpthread", - ], - }, android: { shared_libs: [ - "libdl", "liblog", ], ldflags: ["-Wl,--export-dynamic"], diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp index bdb8ff1fb1..c9125df8f4 100644 --- a/dex2oat/Android.bp +++ b/dex2oat/Android.bp @@ -18,7 +18,6 @@ art_cc_defaults { name: "libart-dex2oat-defaults", defaults: ["art_defaults"], host_supported: true, - clang: true, srcs: [ "linker/elf_writer.cc", "linker/elf_writer_quick.cc", @@ -27,10 +26,6 @@ art_cc_defaults { "linker/oat_writer.cc", ], target: { - host: { - // For compiler driver TLS. - host_ldlibs: ["-lpthread"], - }, android: { // For atrace. shared_libs: ["libcutils"], @@ -70,7 +65,7 @@ art_cc_static_library { defaults: ["libart-dex2oat-defaults"], shared_libs: [ "libart-compiler", - "libart" + "libart", ], } @@ -82,7 +77,7 @@ art_cc_static_library { ], shared_libs: [ "libartd-compiler", - "libartd" + "libartd", ], } @@ -126,7 +121,7 @@ art_cc_binary { ], static_libs: [ "libart-dex2oat", - ] + ], } art_cc_binary { @@ -145,7 +140,7 @@ art_cc_binary { ], static_libs: [ "libartd-dex2oat", - ] + ], } art_cc_binary { @@ -231,5 +226,5 @@ art_cc_test { ], static_libs: [ "libartd-dex2oat", - ] + ], } diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 21d38956e3..7b4653107f 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -712,6 +712,10 @@ class Dex2Oat FINAL { } } + bool VerifyProfileData() { + return profile_compilation_info_->VerifyProfileData(dex_files_); + } + void ParseInstructionSetVariant(const StringPiece& option, ParserOptions* parser_options) { DCHECK(option.starts_with("--instruction-set-variant=")); StringPiece str = option.substr(strlen("--instruction-set-variant=")).data(); @@ -1353,7 +1357,7 @@ class Dex2Oat FINAL { DCHECK(!oat_filenames_.empty()); for (const char* oat_filename : oat_filenames_) { std::unique_ptr<File> oat_file(OS::CreateEmptyFile(oat_filename)); - if (oat_file.get() == nullptr) { + if (oat_file == nullptr) { PLOG(ERROR) << "Failed to create oat file: " << oat_filename; return false; } @@ -1383,7 +1387,7 @@ class Dex2Oat FINAL { vdex_files_.push_back(std::move(vdex_file)); } else { std::unique_ptr<File> vdex_file(OS::CreateEmptyFile(vdex_filename.c_str())); - if (vdex_file.get() == nullptr) { + if (vdex_file == nullptr) { PLOG(ERROR) << "Failed to open vdex file: " << vdex_filename; return false; } @@ -1397,13 +1401,15 @@ class Dex2Oat FINAL { } } else { std::unique_ptr<File> oat_file(new File(oat_fd_, oat_location_, /* check_usage */ true)); - if (oat_file.get() == nullptr) { + if (oat_file == nullptr) { PLOG(ERROR) << "Failed to create oat file: " << oat_location_; return false; } oat_file->DisableAutoClose(); if (oat_file->SetLength(0) != 0) { PLOG(WARNING) << "Truncating oat file " << oat_location_ << " failed."; + oat_file->Erase(); + return false; } oat_files_.push_back(std::move(oat_file)); @@ -1432,7 +1438,7 @@ class Dex2Oat FINAL { DCHECK_NE(output_vdex_fd_, -1); std::string vdex_location = ReplaceFileExtension(oat_location_, "vdex"); std::unique_ptr<File> vdex_file(new File(output_vdex_fd_, vdex_location, /* check_usage */ true)); - if (vdex_file.get() == nullptr) { + if (vdex_file == nullptr) { PLOG(ERROR) << "Failed to create vdex file: " << vdex_location; return false; } @@ -1442,6 +1448,7 @@ class Dex2Oat FINAL { } else { if (vdex_file->SetLength(0) != 0) { PLOG(ERROR) << "Truncating vdex file " << vdex_location << " failed."; + vdex_file->Erase(); return false; } } @@ -2305,6 +2312,10 @@ class Dex2Oat FINAL { return DoProfileGuidedOptimizations(); } + bool DoOatLayoutOptimizations() const { + return DoProfileGuidedOptimizations(); + } + bool DoEagerUnquickeningOfVdex() const { // DexLayout can invalidate the vdex metadata, so we need to unquicken // the vdex file eagerly, before passing it to dexlayout. @@ -2517,9 +2528,11 @@ class Dex2Oat FINAL { compiler_options_.get(), oat_file.get())); elf_writers_.back()->Start(); - const bool do_dexlayout = DoDexLayoutOptimizations(); + const bool do_oat_writer_layout = DoDexLayoutOptimizations() || DoOatLayoutOptimizations(); oat_writers_.emplace_back(new linker::OatWriter( - IsBootImage(), timings_, do_dexlayout ? profile_compilation_info_.get() : nullptr)); + IsBootImage(), + timings_, + do_oat_writer_layout ? profile_compilation_info_.get() : nullptr)); } } @@ -3103,6 +3116,19 @@ static dex2oat::ReturnCode Dex2oat(int argc, char** argv) { return setup_code; } + // TODO: Due to the cyclic dependencies, profile loading and verifying are + // being done separately. Refactor and place the two next to each other. + // If verification fails, we don't abort the compilation and instead log an + // error. + // TODO(b/62602192, b/65260586): We should consider aborting compilation when + // the profile verification fails. + // Note: If dex2oat fails, installd will remove the oat files causing the app + // to fallback to apk with possible in-memory extraction. We want to avoid + // that, and thus we're lenient towards profile corruptions. + if (dex2oat->UseProfile()) { + dex2oat->VerifyProfileData(); + } + // Helps debugging on device. Can be used to determine which dalvikvm instance invoked a dex2oat // instance. Used by tools/bisection_search/bisection_search.py. VLOG(compiler) << "Running dex2oat (parent PID = " << getppid() << ")"; diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h index 71f1fa607e..492c76bc54 100644 --- a/dex2oat/linker/image_test.h +++ b/dex2oat/linker/image_test.h @@ -302,8 +302,8 @@ inline void CompilationHelper::Compile(CompilerDriver* driver, } for (size_t i = 0, size = oat_files.size(); i != size; ++i) { - linker::MultiOatRelativePatcher patcher(driver->GetInstructionSet(), - driver->GetInstructionSetFeatures()); + MultiOatRelativePatcher patcher(driver->GetInstructionSet(), + driver->GetInstructionSetFeatures()); OatWriter* const oat_writer = oat_writers[i].get(); ElfWriter* const elf_writer = elf_writers[i].get(); std::vector<const DexFile*> cur_dex_files(1u, class_path[i]); diff --git a/dex2oat/linker/multi_oat_relative_patcher_test.cc b/dex2oat/linker/multi_oat_relative_patcher_test.cc index 1b2d43e4c5..ca9c5f1e84 100644 --- a/dex2oat/linker/multi_oat_relative_patcher_test.cc +++ b/dex2oat/linker/multi_oat_relative_patcher_test.cc @@ -19,6 +19,7 @@ #include "compiled_method.h" #include "debug/method_debug_info.h" #include "gtest/gtest.h" +#include "linker/linker_patch.h" #include "linker/vector_output_stream.h" namespace art { diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index 51c2a037a0..a80dbf6bda 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -16,6 +16,7 @@ #include "oat_writer.h" +#include <algorithm> #include <unistd.h> #include <zlib.h> @@ -29,7 +30,7 @@ #include "base/unix_file/fd_file.h" #include "class_linker.h" #include "class_table-inl.h" -#include "compiled_method.h" +#include "compiled_method-inl.h" #include "debug/method_debug_info.h" #include "dex/verification_results.h" #include "dex_file-inl.h" @@ -43,6 +44,7 @@ #include "image_writer.h" #include "linker/buffered_output_stream.h" #include "linker/file_output_stream.h" +#include "linker/linker_patch.h" #include "linker/method_bss_mapping_encoder.h" #include "linker/multi_oat_relative_patcher.h" #include "linker/output_stream.h" @@ -68,6 +70,18 @@ namespace { // anonymous namespace // If we write dex layout info in the oat file. static constexpr bool kWriteDexLayoutInfo = true; +// Force the OAT method layout to be sorted-by-name instead of +// the default (class_def_idx, method_idx). +// +// Otherwise if profiles are used, that will act as +// the primary sort order. +// +// A bit easier to use for development since oatdump can easily +// show that things are being re-ordered when two methods aren't adjacent. +static constexpr bool kOatWriterForceOatCodeLayout = false; + +static constexpr bool kOatWriterDebugOatCodeLayout = false; + typedef DexFile::Header __attribute__((aligned(1))) UnalignedDexFileHeader; const UnalignedDexFileHeader* AsUnalignedDexFileHeader(const uint8_t* raw_data) { @@ -866,158 +880,433 @@ class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor { size_t compiled_methods_with_code_; }; -class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { +// CompiledMethod + metadata required to do ordered method layout. +// +// See also OrderedMethodVisitor. +struct OatWriter::OrderedMethodData { + ProfileCompilationInfo::MethodHotness method_hotness; + OatClass* oat_class; + CompiledMethod* compiled_method; + MethodReference method_reference; + size_t method_offsets_index; + + size_t class_def_index; + uint32_t access_flags; + const DexFile::CodeItem* code_item; + + // A value of -1 denotes missing debug info + static constexpr size_t kDebugInfoIdxInvalid = static_cast<size_t>(-1); + // Index into writer_->method_info_ + size_t debug_info_idx; + + bool HasDebugInfo() const { + return debug_info_idx != kDebugInfoIdxInvalid; + } + + // Bin each method according to the profile flags. + // + // Groups by e.g. + // -- not hot at all + // -- hot + // -- hot and startup + // -- hot and post-startup + // -- hot and startup and poststartup + // -- startup + // -- startup and post-startup + // -- post-startup + // + // (See MethodHotness enum definition for up-to-date binning order.) + bool operator<(const OrderedMethodData& other) const { + if (kOatWriterForceOatCodeLayout) { + // Development flag: Override default behavior by sorting by name. + + std::string name = method_reference.PrettyMethod(); + std::string other_name = other.method_reference.PrettyMethod(); + return name < other_name; + } + + // Use the profile's method hotness to determine sort order. + if (GetMethodHotnessOrder() < other.GetMethodHotnessOrder()) { + return true; + } + + // Default: retain the original order. + return false; + } + + private: + // Used to determine relative order for OAT code layout when determining + // binning. + size_t GetMethodHotnessOrder() const { + bool hotness[] = { + method_hotness.IsHot(), + method_hotness.IsStartup(), + method_hotness.IsPostStartup() + }; + + + // Note: Bin-to-bin order does not matter. If the kernel does or does not read-ahead + // any memory, it only goes into the buffer cache and does not grow the PSS until the first + // time that memory is referenced in the process. + + size_t hotness_bits = 0; + for (size_t i = 0; i < arraysize(hotness); ++i) { + if (hotness[i]) { + hotness_bits |= (1 << i); + } + } + + if (kIsDebugBuild) { + // Check for bins that are always-empty given a real profile. + if (method_hotness.IsHot() && + !method_hotness.IsStartup() && !method_hotness.IsPostStartup()) { + std::string name = method_reference.PrettyMethod(); + LOG(WARNING) << "Method " << name << " had a Hot method that wasn't marked " + << "either start-up or post-startup. Possible corrupted profile?"; + // This is not fatal, so only warn. + } + } + + return hotness_bits; + } +}; + +// Given a queue of CompiledMethod in some total order, +// visit each one in that order. +class OatWriter::OrderedMethodVisitor { public: - InitCodeMethodVisitor(OatWriter* writer, size_t offset) - : InitCodeMethodVisitor(writer, offset, writer->GetCompilerDriver()->GetCompilerOptions()) {} + explicit OrderedMethodVisitor(OrderedMethodList ordered_methods) + : ordered_methods_(std::move(ordered_methods)) { + } - bool EndClass() OVERRIDE { - OatDexMethodVisitor::EndClass(); - if (oat_class_index_ == writer_->oat_classes_.size()) { - offset_ = relative_patcher_->ReserveSpaceEnd(offset_); - if (generate_debug_info_) { - std::vector<debug::MethodDebugInfo> thunk_infos = - relative_patcher_->GenerateThunkDebugInfo(executable_offset_); - writer_->method_info_.insert(writer_->method_info_.end(), - std::make_move_iterator(thunk_infos.begin()), - std::make_move_iterator(thunk_infos.end())); + virtual ~OrderedMethodVisitor() {} + + // Invoke VisitMethod in the order of `ordered_methods`, then invoke VisitComplete. + bool Visit() REQUIRES_SHARED(Locks::mutator_lock_) { + if (!VisitStart()) { + return false; + } + + for (const OrderedMethodData& method_data : ordered_methods_) { + if (!VisitMethod(method_data)) { + return false; } } + + return VisitComplete(); + } + + // Invoked once at the beginning, prior to visiting anything else. + // + // Return false to abort further visiting. + virtual bool VisitStart() { return true; } + + // Invoked repeatedly in the order specified by `ordered_methods`. + // + // Return false to short-circuit and to stop visiting further methods. + virtual bool VisitMethod(const OrderedMethodData& method_data) + REQUIRES_SHARED(Locks::mutator_lock_) = 0; + + // Invoked once at the end, after every other method has been successfully visited. + // + // Return false to indicate the overall `Visit` has failed. + virtual bool VisitComplete() = 0; + + OrderedMethodList ReleaseOrderedMethods() { + return std::move(ordered_methods_); + } + + private: + // List of compiled methods, sorted by the order defined in OrderedMethodData. + // Methods can be inserted more than once in case of duplicated methods. + OrderedMethodList ordered_methods_; +}; + +// Visit every compiled method in order to determine its order within the OAT file. +// Methods from the same class do not need to be adjacent in the OAT code. +class OatWriter::LayoutCodeMethodVisitor : public OatDexMethodVisitor { + public: + LayoutCodeMethodVisitor(OatWriter* writer, size_t offset) + : OatDexMethodVisitor(writer, offset) { + } + + bool EndClass() OVERRIDE { + OatDexMethodVisitor::EndClass(); return true; } - bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE - REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitMethod(size_t class_def_method_index, + const ClassDataItemIterator& it) + OVERRIDE + REQUIRES_SHARED(Locks::mutator_lock_) { + Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); + OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); if (HasCompiledCode(compiled_method)) { - // Derived from CompiledMethod. - uint32_t quick_code_offset = 0; - - ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode(); - uint32_t code_size = quick_code.size() * sizeof(uint8_t); - uint32_t thumb_offset = compiled_method->CodeDelta(); + size_t debug_info_idx = OrderedMethodData::kDebugInfoIdxInvalid; + + { + const CompilerOptions& compiler_options = writer_->compiler_driver_->GetCompilerOptions(); + ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode(); + uint32_t code_size = quick_code.size() * sizeof(uint8_t); + + // Debug method info must be pushed in the original order + // (i.e. all methods from the same class must be adjacent in the debug info sections) + // ElfCompilationUnitWriter::Write requires this. + if (compiler_options.GenerateAnyDebugInfo() && code_size != 0) { + debug::MethodDebugInfo info = debug::MethodDebugInfo(); + writer_->method_info_.push_back(info); + + // The debug info is filled in LayoutReserveOffsetCodeMethodVisitor + // once we know the offsets. + // + // Store the index into writer_->method_info_ since future push-backs + // could reallocate and change the underlying data address. + debug_info_idx = writer_->method_info_.size() - 1; + } + } - // Deduplicate code arrays if we are not producing debuggable code. - bool deduped = true; MethodReference method_ref(dex_file_, it.GetMemberIndex()); - if (debuggable_) { - quick_code_offset = relative_patcher_->GetOffset(method_ref); - if (quick_code_offset != 0u) { - // Duplicate methods, we want the same code for both of them so that the oat writer puts - // the same code in both ArtMethods so that we do not get different oat code at runtime. - } else { - quick_code_offset = NewQuickCodeOffset(compiled_method, it, thumb_offset); - deduped = false; - } + + // Lookup method hotness from profile, if available. + // Otherwise assume a default of none-hotness. + ProfileCompilationInfo::MethodHotness method_hotness = + writer_->profile_compilation_info_ != nullptr + ? writer_->profile_compilation_info_->GetMethodHotness(method_ref) + : ProfileCompilationInfo::MethodHotness(); + + // Handle duplicate methods by pushing them repeatedly. + OrderedMethodData method_data = { + method_hotness, + oat_class, + compiled_method, + method_ref, + method_offsets_index_, + class_def_index_, + it.GetMethodAccessFlags(), + it.GetMethodCodeItem(), + debug_info_idx + }; + ordered_methods_.push_back(method_data); + + method_offsets_index_++; + } + + return true; + } + + OrderedMethodList ReleaseOrderedMethods() { + if (kOatWriterForceOatCodeLayout || writer_->profile_compilation_info_ != nullptr) { + // Sort by the method ordering criteria (in OrderedMethodData). + // Since most methods will have the same ordering criteria, + // we preserve the original insertion order within the same sort order. + std::stable_sort(ordered_methods_.begin(), ordered_methods_.end()); + } else { + // The profile-less behavior is as if every method had 0 hotness + // associated with it. + // + // Since sorting all methods with hotness=0 should give back the same + // order as before, don't do anything. + DCHECK(std::is_sorted(ordered_methods_.begin(), ordered_methods_.end())); + } + + return std::move(ordered_methods_); + } + + private: + // List of compiled methods, later to be sorted by order defined in OrderedMethodData. + // Methods can be inserted more than once in case of duplicated methods. + OrderedMethodList ordered_methods_; +}; + +// Given a method order, reserve the offsets for each CompiledMethod in the OAT file. +class OatWriter::LayoutReserveOffsetCodeMethodVisitor : public OrderedMethodVisitor { + public: + LayoutReserveOffsetCodeMethodVisitor(OatWriter* writer, + size_t offset, + OrderedMethodList ordered_methods) + : LayoutReserveOffsetCodeMethodVisitor(writer, + offset, + writer->GetCompilerDriver()->GetCompilerOptions(), + std::move(ordered_methods)) { + } + + virtual bool VisitComplete() OVERRIDE { + offset_ = writer_->relative_patcher_->ReserveSpaceEnd(offset_); + if (generate_debug_info_) { + std::vector<debug::MethodDebugInfo> thunk_infos = + relative_patcher_->GenerateThunkDebugInfo(executable_offset_); + writer_->method_info_.insert(writer_->method_info_.end(), + std::make_move_iterator(thunk_infos.begin()), + std::make_move_iterator(thunk_infos.end())); + } + return true; + } + + virtual bool VisitMethod(const OrderedMethodData& method_data) + OVERRIDE + REQUIRES_SHARED(Locks::mutator_lock_) { + OatClass* oat_class = method_data.oat_class; + CompiledMethod* compiled_method = method_data.compiled_method; + const MethodReference& method_ref = method_data.method_reference; + uint16_t method_offsets_index_ = method_data.method_offsets_index; + size_t class_def_index = method_data.class_def_index; + uint32_t access_flags = method_data.access_flags; + const DexFile::CodeItem* code_item = method_data.code_item; + bool has_debug_info = method_data.HasDebugInfo(); + size_t debug_info_idx = method_data.debug_info_idx; + + DCHECK(HasCompiledCode(compiled_method)) << method_ref.PrettyMethod(); + + // Derived from CompiledMethod. + uint32_t quick_code_offset = 0; + + ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode(); + uint32_t code_size = quick_code.size() * sizeof(uint8_t); + uint32_t thumb_offset = compiled_method->CodeDelta(); + + // Deduplicate code arrays if we are not producing debuggable code. + bool deduped = true; + if (debuggable_) { + quick_code_offset = relative_patcher_->GetOffset(method_ref); + if (quick_code_offset != 0u) { + // Duplicate methods, we want the same code for both of them so that the oat writer puts + // the same code in both ArtMethods so that we do not get different oat code at runtime. } else { - quick_code_offset = dedupe_map_.GetOrCreate( - compiled_method, - [this, &deduped, compiled_method, &it, thumb_offset]() { - deduped = false; - return NewQuickCodeOffset(compiled_method, it, thumb_offset); - }); + quick_code_offset = NewQuickCodeOffset(compiled_method, method_ref, thumb_offset); + deduped = false; } if (code_size != 0) { if (relative_patcher_->GetOffset(method_ref) != 0u) { // TODO: Should this be a hard failure? LOG(WARNING) << "Multiple definitions of " - << method_ref.PrettyMethod() + << method_ref.dex_file->PrettyMethod(method_ref.index) << " offsets " << relative_patcher_->GetOffset(method_ref) << " " << quick_code_offset; } else { relative_patcher_->SetOffset(method_ref, quick_code_offset); } } - - // Update quick method header. - DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size()); - OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_]; - uint32_t vmap_table_offset = method_header->GetVmapTableOffset(); - uint32_t method_info_offset = method_header->GetMethodInfoOffset(); - // The code offset was 0 when the mapping/vmap table offset was set, so it's set - // to 0-offset and we need to adjust it by code_offset. - uint32_t code_offset = quick_code_offset - thumb_offset; - if (!compiled_method->GetQuickCode().empty()) { - // If the code is compiled, we write the offset of the stack map relative - // to the code, - if (vmap_table_offset != 0u) { - vmap_table_offset += code_offset; - DCHECK_LT(vmap_table_offset, code_offset); - } - if (method_info_offset != 0u) { - method_info_offset += code_offset; - DCHECK_LT(method_info_offset, code_offset); - } + } else { + quick_code_offset = dedupe_map_.GetOrCreate( + compiled_method, + [this, &deduped, compiled_method, &method_ref, thumb_offset]() { + deduped = false; + return NewQuickCodeOffset(compiled_method, method_ref, thumb_offset); + }); + } + + if (code_size != 0) { + if (relative_patcher_->GetOffset(method_ref) != 0u) { + // TODO: Should this be a hard failure? + LOG(WARNING) << "Multiple definitions of " + << method_ref.dex_file->PrettyMethod(method_ref.index) + << " offsets " << relative_patcher_->GetOffset(method_ref) + << " " << quick_code_offset; } else { - CHECK(!kIsVdexEnabled); - // We write the offset of the quickening info relative to the code. + relative_patcher_->SetOffset(method_ref, quick_code_offset); + } + } + + // Update quick method header. + DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size()); + OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_]; + uint32_t vmap_table_offset = method_header->GetVmapTableOffset(); + uint32_t method_info_offset = method_header->GetMethodInfoOffset(); + // The code offset was 0 when the mapping/vmap table offset was set, so it's set + // to 0-offset and we need to adjust it by code_offset. + uint32_t code_offset = quick_code_offset - thumb_offset; + if (!compiled_method->GetQuickCode().empty()) { + // If the code is compiled, we write the offset of the stack map relative + // to the code, + if (vmap_table_offset != 0u) { vmap_table_offset += code_offset; DCHECK_LT(vmap_table_offset, code_offset); } - uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); - uint32_t core_spill_mask = compiled_method->GetCoreSpillMask(); - uint32_t fp_spill_mask = compiled_method->GetFpSpillMask(); - *method_header = OatQuickMethodHeader(vmap_table_offset, - method_info_offset, - frame_size_in_bytes, - core_spill_mask, - fp_spill_mask, - code_size); - - if (!deduped) { - // Update offsets. (Checksum is updated when writing.) - offset_ += sizeof(*method_header); // Method header is prepended before code. - offset_ += code_size; - // Record absolute patch locations. - if (!compiled_method->GetPatches().empty()) { - uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset(); - for (const LinkerPatch& patch : compiled_method->GetPatches()) { - if (!patch.IsPcRelative()) { - writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset()); - } + if (method_info_offset != 0u) { + method_info_offset += code_offset; + DCHECK_LT(method_info_offset, code_offset); + } + } else { + CHECK(!kIsVdexEnabled); + // We write the offset of the quickening info relative to the code. + vmap_table_offset += code_offset; + DCHECK_LT(vmap_table_offset, code_offset); + } + uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); + uint32_t core_spill_mask = compiled_method->GetCoreSpillMask(); + uint32_t fp_spill_mask = compiled_method->GetFpSpillMask(); + *method_header = OatQuickMethodHeader(vmap_table_offset, + method_info_offset, + frame_size_in_bytes, + core_spill_mask, + fp_spill_mask, + code_size); + + if (!deduped) { + // Update offsets. (Checksum is updated when writing.) + offset_ += sizeof(*method_header); // Method header is prepended before code. + offset_ += code_size; + // Record absolute patch locations. + if (!compiled_method->GetPatches().empty()) { + uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset(); + for (const LinkerPatch& patch : compiled_method->GetPatches()) { + if (!patch.IsPcRelative()) { + writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset()); } } } + } - // Exclude quickened dex methods (code_size == 0) since they have no native code. - if (generate_debug_info_ && code_size != 0) { - bool has_code_info = method_header->IsOptimized(); - // Record debug information for this function if we are doing that. - debug::MethodDebugInfo info = {}; - DCHECK(info.trampoline_name.empty()); - info.dex_file = dex_file_; - info.class_def_index = class_def_index_; - info.dex_method_index = it.GetMemberIndex(); - info.access_flags = it.GetMethodAccessFlags(); - info.code_item = it.GetMethodCodeItem(); - info.isa = compiled_method->GetInstructionSet(); - info.deduped = deduped; - info.is_native_debuggable = native_debuggable_; - info.is_optimized = method_header->IsOptimized(); - info.is_code_address_text_relative = true; - info.code_address = code_offset - executable_offset_; - info.code_size = code_size; - info.frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); - info.code_info = has_code_info ? compiled_method->GetVmapTable().data() : nullptr; - info.cfi = compiled_method->GetCFIInfo(); - writer_->method_info_.push_back(info); - } - - DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); - OatMethodOffsets* offsets = &oat_class->method_offsets_[method_offsets_index_]; - offsets->code_offset_ = quick_code_offset; - ++method_offsets_index_; + // Exclude quickened dex methods (code_size == 0) since they have no native code. + if (generate_debug_info_ && code_size != 0) { + DCHECK(has_debug_info); + + bool has_code_info = method_header->IsOptimized(); + // Record debug information for this function if we are doing that. + debug::MethodDebugInfo& info = writer_->method_info_[debug_info_idx]; + DCHECK(info.trampoline_name.empty()); + info.dex_file = method_ref.dex_file; + info.class_def_index = class_def_index; + info.dex_method_index = method_ref.index; + info.access_flags = access_flags; + info.code_item = code_item; + info.isa = compiled_method->GetInstructionSet(); + info.deduped = deduped; + info.is_native_debuggable = native_debuggable_; + info.is_optimized = method_header->IsOptimized(); + info.is_code_address_text_relative = true; + info.code_address = code_offset - executable_offset_; + info.code_size = code_size; + info.frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); + info.code_info = has_code_info ? compiled_method->GetVmapTable().data() : nullptr; + info.cfi = compiled_method->GetCFIInfo(); + } else { + DCHECK(!has_debug_info); } + DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); + OatMethodOffsets* offsets = &oat_class->method_offsets_[method_offsets_index_]; + offsets->code_offset_ = quick_code_offset; + return true; } + size_t GetOffset() const { + return offset_; + } + private: - InitCodeMethodVisitor(OatWriter* writer, size_t offset, const CompilerOptions& compiler_options) - : OatDexMethodVisitor(writer, offset), + LayoutReserveOffsetCodeMethodVisitor(OatWriter* writer, + size_t offset, + const CompilerOptions& compiler_options, + OrderedMethodList ordered_methods) + : OrderedMethodVisitor(std::move(ordered_methods)), + writer_(writer), + offset_(offset), relative_patcher_(writer->relative_patcher_), executable_offset_(writer->oat_header_->GetExecutableOffset()), debuggable_(compiler_options.GetDebuggable()), @@ -1048,22 +1337,26 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { }; uint32_t NewQuickCodeOffset(CompiledMethod* compiled_method, - const ClassDataItemIterator& it, + const MethodReference& method_ref, uint32_t thumb_offset) { - offset_ = relative_patcher_->ReserveSpace( - offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex())); + offset_ = relative_patcher_->ReserveSpace(offset_, compiled_method, method_ref); offset_ += CodeAlignmentSize(offset_, *compiled_method); DCHECK_ALIGNED_PARAM(offset_ + sizeof(OatQuickMethodHeader), GetInstructionSetAlignment(compiled_method->GetInstructionSet())); return offset_ + sizeof(OatQuickMethodHeader) + thumb_offset; } + OatWriter* writer_; + + // Offset of the code of the compiled methods. + size_t offset_; + // Deduplication is already done on a pointer basis by the compiler driver, // so we can simply compare the pointers to find out if things are duplicated. SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_; // Cache writer_'s members and compiler options. - linker::MultiOatRelativePatcher* relative_patcher_; + MultiOatRelativePatcher* relative_patcher_; uint32_t executable_offset_; const bool debuggable_; const bool native_debuggable_; @@ -1295,19 +1588,24 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor { std::vector<std::pair<ArtMethod*, ArtMethod*>> methods_to_process_; }; -class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { +class OatWriter::WriteCodeMethodVisitor : public OrderedMethodVisitor { public: - WriteCodeMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset, - size_t relative_offset) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) - : OatDexMethodVisitor(writer, relative_offset), + WriteCodeMethodVisitor(OatWriter* writer, + OutputStream* out, + const size_t file_offset, + size_t relative_offset, + OrderedMethodList ordered_methods) + : OrderedMethodVisitor(std::move(ordered_methods)), + writer_(writer), + offset_(relative_offset), + dex_file_(nullptr), pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())), class_loader_(writer->HasImage() ? writer->image_writer_->GetClassLoader() : nullptr), out_(out), file_offset_(file_offset), - soa_(Thread::Current()), - no_thread_suspension_("OatWriter patching"), class_linker_(Runtime::Current()->GetClassLinker()), - dex_cache_(nullptr) { + dex_cache_(nullptr), + no_thread_suspension_("OatWriter patching") { patched_code_.reserve(16 * KB); if (writer_->HasBootImage()) { // If we're creating the image, the address space must be ready so that we can apply patches. @@ -1315,12 +1613,17 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { } } - ~WriteCodeMethodVisitor() UNLOCK_FUNCTION(Locks::mutator_lock_) { + virtual bool VisitStart() OVERRIDE { + return true; } - bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE + void UpdateDexFileAndDexCache(const DexFile* dex_file) REQUIRES_SHARED(Locks::mutator_lock_) { - OatDexMethodVisitor::StartClass(dex_file, class_def_index); + dex_file_ = dex_file; + + // Ordered method visiting is only for compiled methods. + DCHECK(writer_->MayHaveCompiledMethods()); + if (writer_->GetCompilerDriver()->GetCompilerOptions().IsAotCompilationEnabled()) { // Only need to set the dex cache if we have compilation. Other modes might have unloaded it. if (dex_cache_ == nullptr || dex_cache_->GetDexFile() != dex_file) { @@ -1328,198 +1631,212 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { DCHECK(dex_cache_ != nullptr); } } - return true; } - bool EndClass() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { - bool result = OatDexMethodVisitor::EndClass(); - if (oat_class_index_ == writer_->oat_classes_.size()) { - DCHECK(result); // OatDexMethodVisitor::EndClass() never fails. - offset_ = writer_->relative_patcher_->WriteThunks(out_, offset_); - if (UNLIKELY(offset_ == 0u)) { - PLOG(ERROR) << "Failed to write final relative call thunks"; - result = false; - } + virtual bool VisitComplete() { + offset_ = writer_->relative_patcher_->WriteThunks(out_, offset_); + if (UNLIKELY(offset_ == 0u)) { + PLOG(ERROR) << "Failed to write final relative call thunks"; + return false; } - return result; + return true; } - bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE + virtual bool VisitMethod(const OrderedMethodData& method_data) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { - OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; - const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); + const MethodReference& method_ref = method_data.method_reference; + UpdateDexFileAndDexCache(method_ref.dex_file); + + OatClass* oat_class = method_data.oat_class; + CompiledMethod* compiled_method = method_data.compiled_method; + uint16_t method_offsets_index = method_data.method_offsets_index; // No thread suspension since dex_cache_ that may get invalidated if that occurs. ScopedAssertNoThreadSuspension tsc(__FUNCTION__); - if (HasCompiledCode(compiled_method)) { - size_t file_offset = file_offset_; - OutputStream* out = out_; + DCHECK(HasCompiledCode(compiled_method)) << method_ref.PrettyMethod(); - ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode(); - uint32_t code_size = quick_code.size() * sizeof(uint8_t); + // TODO: cleanup DCHECK_OFFSET_ to accept file_offset as parameter. + size_t file_offset = file_offset_; // Used by DCHECK_OFFSET_ macro. + OutputStream* out = out_; - // Deduplicate code arrays. - const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_]; - if (method_offsets.code_offset_ > offset_) { - offset_ = writer_->relative_patcher_->WriteThunks(out, offset_); - if (offset_ == 0u) { - ReportWriteFailure("relative call thunk", it); - return false; - } - uint32_t alignment_size = CodeAlignmentSize(offset_, *compiled_method); - if (alignment_size != 0) { - if (!writer_->WriteCodeAlignment(out, alignment_size)) { - ReportWriteFailure("code alignment padding", it); - return false; - } - offset_ += alignment_size; - DCHECK_OFFSET_(); - } - DCHECK_ALIGNED_PARAM(offset_ + sizeof(OatQuickMethodHeader), - GetInstructionSetAlignment(compiled_method->GetInstructionSet())); - DCHECK_EQ(method_offsets.code_offset_, - offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta()) - << dex_file_->PrettyMethod(it.GetMemberIndex()); - const OatQuickMethodHeader& method_header = - oat_class->method_headers_[method_offsets_index_]; - if (!out->WriteFully(&method_header, sizeof(method_header))) { - ReportWriteFailure("method header", it); + ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode(); + uint32_t code_size = quick_code.size() * sizeof(uint8_t); + + // Deduplicate code arrays. + const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index]; + if (method_offsets.code_offset_ > offset_) { + offset_ = writer_->relative_patcher_->WriteThunks(out, offset_); + if (offset_ == 0u) { + ReportWriteFailure("relative call thunk", method_ref); + return false; + } + uint32_t alignment_size = CodeAlignmentSize(offset_, *compiled_method); + if (alignment_size != 0) { + if (!writer_->WriteCodeAlignment(out, alignment_size)) { + ReportWriteFailure("code alignment padding", method_ref); return false; } - writer_->size_method_header_ += sizeof(method_header); - offset_ += sizeof(method_header); + offset_ += alignment_size; DCHECK_OFFSET_(); + } + DCHECK_ALIGNED_PARAM(offset_ + sizeof(OatQuickMethodHeader), + GetInstructionSetAlignment(compiled_method->GetInstructionSet())); + DCHECK_EQ(method_offsets.code_offset_, + offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta()) + << dex_file_->PrettyMethod(method_ref.index); + const OatQuickMethodHeader& method_header = + oat_class->method_headers_[method_offsets_index]; + if (!out->WriteFully(&method_header, sizeof(method_header))) { + ReportWriteFailure("method header", method_ref); + return false; + } + writer_->size_method_header_ += sizeof(method_header); + offset_ += sizeof(method_header); + DCHECK_OFFSET_(); - if (!compiled_method->GetPatches().empty()) { - patched_code_.assign(quick_code.begin(), quick_code.end()); - quick_code = ArrayRef<const uint8_t>(patched_code_); - for (const LinkerPatch& patch : compiled_method->GetPatches()) { - uint32_t literal_offset = patch.LiteralOffset(); - switch (patch.GetType()) { - case LinkerPatch::Type::kMethodBssEntry: { - uint32_t target_offset = - writer_->bss_start_ + writer_->bss_method_entries_.Get(patch.TargetMethod()); - writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, - patch, - offset_ + literal_offset, - target_offset); - break; - } - case LinkerPatch::Type::kCallRelative: { - // NOTE: Relative calls across oat files are not supported. - uint32_t target_offset = GetTargetOffset(patch); - writer_->relative_patcher_->PatchCall(&patched_code_, - literal_offset, - offset_ + literal_offset, - target_offset); - break; - } - case LinkerPatch::Type::kStringRelative: { - uint32_t target_offset = GetTargetObjectOffset(GetTargetString(patch)); - writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, - patch, - offset_ + literal_offset, - target_offset); - break; - } - case LinkerPatch::Type::kStringInternTable: { - uint32_t target_offset = GetInternTableEntryOffset(patch); - writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, - patch, - offset_ + literal_offset, - target_offset); - break; - } - case LinkerPatch::Type::kStringBssEntry: { - StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex()); - uint32_t target_offset = - writer_->bss_start_ + writer_->bss_string_entries_.Get(ref); - writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, - patch, - offset_ + literal_offset, - target_offset); - break; - } - case LinkerPatch::Type::kTypeRelative: { - uint32_t target_offset = GetTargetObjectOffset(GetTargetType(patch)); - writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, - patch, - offset_ + literal_offset, - target_offset); - break; - } - case LinkerPatch::Type::kTypeClassTable: { - uint32_t target_offset = GetClassTableEntryOffset(patch); - writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, - patch, - offset_ + literal_offset, - target_offset); - break; - } - case LinkerPatch::Type::kTypeBssEntry: { - TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex()); - uint32_t target_offset = writer_->bss_start_ + writer_->bss_type_entries_.Get(ref); - writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, - patch, - offset_ + literal_offset, - target_offset); - break; - } - case LinkerPatch::Type::kCall: { - uint32_t target_offset = GetTargetOffset(patch); - PatchCodeAddress(&patched_code_, literal_offset, target_offset); - break; - } - case LinkerPatch::Type::kMethodRelative: { - uint32_t target_offset = GetTargetMethodOffset(GetTargetMethod(patch)); - writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, - patch, - offset_ + literal_offset, - target_offset); - break; - } - case LinkerPatch::Type::kBakerReadBarrierBranch: { - writer_->relative_patcher_->PatchBakerReadBarrierBranch(&patched_code_, - patch, - offset_ + literal_offset); - break; - } - default: { - DCHECK(false) << "Unexpected linker patch type: " << patch.GetType(); - break; - } + if (!compiled_method->GetPatches().empty()) { + patched_code_.assign(quick_code.begin(), quick_code.end()); + quick_code = ArrayRef<const uint8_t>(patched_code_); + for (const LinkerPatch& patch : compiled_method->GetPatches()) { + uint32_t literal_offset = patch.LiteralOffset(); + switch (patch.GetType()) { + case LinkerPatch::Type::kMethodBssEntry: { + uint32_t target_offset = + writer_->bss_start_ + writer_->bss_method_entries_.Get(patch.TargetMethod()); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } + case LinkerPatch::Type::kCallRelative: { + // NOTE: Relative calls across oat files are not supported. + uint32_t target_offset = GetTargetOffset(patch); + writer_->relative_patcher_->PatchCall(&patched_code_, + literal_offset, + offset_ + literal_offset, + target_offset); + break; + } + case LinkerPatch::Type::kStringRelative: { + uint32_t target_offset = GetTargetObjectOffset(GetTargetString(patch)); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } + case LinkerPatch::Type::kStringInternTable: { + uint32_t target_offset = GetInternTableEntryOffset(patch); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } + case LinkerPatch::Type::kStringBssEntry: { + StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex()); + uint32_t target_offset = + writer_->bss_start_ + writer_->bss_string_entries_.Get(ref); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } + case LinkerPatch::Type::kTypeRelative: { + uint32_t target_offset = GetTargetObjectOffset(GetTargetType(patch)); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } + case LinkerPatch::Type::kTypeClassTable: { + uint32_t target_offset = GetClassTableEntryOffset(patch); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } + case LinkerPatch::Type::kTypeBssEntry: { + TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex()); + uint32_t target_offset = writer_->bss_start_ + writer_->bss_type_entries_.Get(ref); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } + case LinkerPatch::Type::kCall: { + uint32_t target_offset = GetTargetOffset(patch); + PatchCodeAddress(&patched_code_, literal_offset, target_offset); + break; + } + case LinkerPatch::Type::kMethodRelative: { + uint32_t target_offset = GetTargetMethodOffset(GetTargetMethod(patch)); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } + case LinkerPatch::Type::kBakerReadBarrierBranch: { + writer_->relative_patcher_->PatchBakerReadBarrierBranch(&patched_code_, + patch, + offset_ + literal_offset); + break; + } + default: { + DCHECK(false) << "Unexpected linker patch type: " << patch.GetType(); + break; } } } + } - if (!out->WriteFully(quick_code.data(), code_size)) { - ReportWriteFailure("method code", it); - return false; - } - writer_->size_code_ += code_size; - offset_ += code_size; + if (!out->WriteFully(quick_code.data(), code_size)) { + ReportWriteFailure("method code", method_ref); + return false; } - DCHECK_OFFSET_(); - ++method_offsets_index_; + writer_->size_code_ += code_size; + offset_ += code_size; } + DCHECK_OFFSET_(); return true; } + size_t GetOffset() const { + return offset_; + } + private: + OatWriter* const writer_; + + // Updated in VisitMethod as methods are written out. + size_t offset_; + + // Potentially varies with every different VisitMethod. + // Used to determine which DexCache to use when finding ArtMethods. + const DexFile* dex_file_; + + // Pointer size we are compiling to. const PointerSize pointer_size_; + // The image writer's classloader, if there is one, else null. ObjPtr<mirror::ClassLoader> class_loader_; + // Stream to output file, where the OAT code will be written to. OutputStream* const out_; const size_t file_offset_; - const ScopedObjectAccess soa_; - const ScopedAssertNoThreadSuspension no_thread_suspension_; ClassLinker* const class_linker_; ObjPtr<mirror::DexCache> dex_cache_; std::vector<uint8_t> patched_code_; + const ScopedAssertNoThreadSuspension no_thread_suspension_; - void ReportWriteFailure(const char* what, const ClassDataItemIterator& it) { + void ReportWriteFailure(const char* what, const MethodReference& method_ref) { PLOG(ERROR) << "Failed to write " << what << " for " - << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to " << out_->GetLocation(); + << method_ref.PrettyMethod() << " to " << out_->GetLocation(); } ArtMethod* GetTargetMethod(const LinkerPatch& patch) @@ -1528,7 +1845,8 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { ObjPtr<mirror::DexCache> dex_cache = (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache( Thread::Current(), *ref.dex_file); - ArtMethod* method = class_linker_->LookupResolvedMethod(ref.index, dex_cache, class_loader_); + ArtMethod* method = + class_linker_->LookupResolvedMethod(ref.index, dex_cache, class_loader_); CHECK(method != nullptr); return method; } @@ -1920,7 +2238,7 @@ size_t OatWriter::InitMethodBssMappings(size_t offset) { DCHECK_ALIGNED(offset, 4u); oat_dex_files_[i].method_bss_mapping_offset_ = offset; - linker::MethodBssMappingEncoder encoder( + MethodBssMappingEncoder encoder( GetInstructionSetPointerSize(oat_header_->GetInstructionSet())); size_t number_of_entries = 0u; bool first_index = true; @@ -2001,12 +2319,50 @@ size_t OatWriter::InitOatCode(size_t offset) { size_t OatWriter::InitOatCodeDexFiles(size_t offset) { if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) { + if (kOatWriterDebugOatCodeLayout) { + LOG(INFO) << "InitOatCodeDexFiles: OatWriter(" + << this << "), " + << "compilation is disabled"; + } + return offset; } - InitCodeMethodVisitor code_visitor(this, offset); - bool success = VisitDexMethods(&code_visitor); - DCHECK(success); - offset = code_visitor.GetOffset(); + bool success = false; + + { + ScopedObjectAccess soa(Thread::Current()); + + LayoutCodeMethodVisitor layout_code_visitor(this, offset); + success = VisitDexMethods(&layout_code_visitor); + DCHECK(success); + + LayoutReserveOffsetCodeMethodVisitor layout_reserve_code_visitor( + this, + offset, + layout_code_visitor.ReleaseOrderedMethods()); + success = layout_reserve_code_visitor.Visit(); + DCHECK(success); + offset = layout_reserve_code_visitor.GetOffset(); + + // Save the method order because the WriteCodeMethodVisitor will need this + // order again. + DCHECK(ordered_methods_ == nullptr); + ordered_methods_.reset( + new OrderedMethodList( + layout_reserve_code_visitor.ReleaseOrderedMethods())); + + if (kOatWriterDebugOatCodeLayout) { + LOG(INFO) << "IniatOatCodeDexFiles: method order: "; + for (const OrderedMethodData& ordered_method : *ordered_methods_) { + std::string pretty_name = ordered_method.method_reference.PrettyMethod(); + LOG(INFO) << pretty_name + << "@ offset " + << relative_patcher_->GetOffset(ordered_method.method_reference) + << " X hotness " + << reinterpret_cast<void*>(ordered_method.method_hotness.GetFlags()); + } + } + } if (HasImage()) { InitImageMethodVisitor image_visitor(this, offset, dex_files_); @@ -2593,7 +2949,7 @@ size_t OatWriter::WriteMethodBssMappings(OutputStream* out, "MethodBssMapping alignment check."); DCHECK_ALIGNED(relative_offset, sizeof(uint32_t)); - linker::MethodBssMappingEncoder encoder( + MethodBssMappingEncoder encoder( GetInstructionSetPointerSize(oat_header_->GetInstructionSet())); // Allocate a sufficiently large MethodBssMapping. size_t number_of_method_indexes = method_indexes.NumSetBits(); @@ -2688,18 +3044,30 @@ size_t OatWriter::WriteCode(OutputStream* out, size_t file_offset, size_t relati size_t OatWriter::WriteCodeDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset) { - #define VISIT(VisitorType) \ - do { \ - VisitorType visitor(this, out, file_offset, relative_offset); \ - if (UNLIKELY(!VisitDexMethods(&visitor))) { \ - return 0; \ - } \ - relative_offset = visitor.GetOffset(); \ - } while (false) - - VISIT(WriteCodeMethodVisitor); - - #undef VISIT + if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) { + // As with InitOatCodeDexFiles, also skip the writer if + // compilation was disabled. + if (kOatWriterDebugOatCodeLayout) { + LOG(INFO) << "WriteCodeDexFiles: OatWriter(" + << this << "), " + << "compilation is disabled"; + } + + return relative_offset; + } + ScopedObjectAccess soa(Thread::Current()); + DCHECK(ordered_methods_ != nullptr); + std::unique_ptr<OrderedMethodList> ordered_methods_ptr = + std::move(ordered_methods_); + WriteCodeMethodVisitor visitor(this, + out, + file_offset, + relative_offset, + std::move(*ordered_methods_ptr)); + if (UNLIKELY(!visitor.Visit())) { + return 0; + } + relative_offset = visitor.GetOffset(); size_code_alignment_ += relative_patcher_->CodeAlignmentSize(); size_relative_call_thunks_ += relative_patcher_->RelativeCallThunksSize(); diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h index a93dd23493..c742fd4441 100644 --- a/dex2oat/linker/oat_writer.h +++ b/dex2oat/linker/oat_writer.h @@ -20,6 +20,7 @@ #include <stdint.h> #include <cstddef> #include <memory> +#include <vector> #include "base/array_ref.h" #include "base/dchecked_vector.h" @@ -254,6 +255,10 @@ class OatWriter { class OatDexMethodVisitor; class InitBssLayoutMethodVisitor; class InitOatClassesMethodVisitor; + class LayoutCodeMethodVisitor; + class LayoutReserveOffsetCodeMethodVisitor; + struct OrderedMethodData; + class OrderedMethodVisitor; class InitCodeMethodVisitor; class InitMapMethodVisitor; class InitMethodInfoVisitor; @@ -486,6 +491,13 @@ class OatWriter { // Profile info used to generate new layout of files. ProfileCompilationInfo* profile_compilation_info_; + using OrderedMethodList = std::vector<OrderedMethodData>; + + // List of compiled methods, sorted by the order defined in OrderedMethodData. + // Methods can be inserted more than once in case of duplicated methods. + // This pointer is only non-null after InitOatCodeDexFiles succeeds. + std::unique_ptr<OrderedMethodList> ordered_methods_; + DISALLOW_COPY_AND_ASSIGN(OatWriter); }; diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc index 33d1491933..d89d9f07b2 100644 --- a/dex2oat/linker/oat_writer_test.cc +++ b/dex2oat/linker/oat_writer_test.cc @@ -23,7 +23,7 @@ #include "base/unix_file/fd_file.h" #include "class_linker.h" #include "common_compiler_test.h" -#include "compiled_method.h" +#include "compiled_method-inl.h" #include "compiler.h" #include "debug/method_debug_info.h" #include "dex/quick_compiler_callbacks.h" diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp index 588a3ae3ca..29c9e92189 100644 --- a/dexlayout/Android.bp +++ b/dexlayout/Android.bp @@ -74,9 +74,9 @@ art_cc_binary { android: { shared_libs: [ "libpagemap", - ] + ], }, - } + }, } art_cc_test { diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc index 5913832f96..0c944cee2c 100644 --- a/dexlayout/dex_ir.cc +++ b/dexlayout/dex_ir.cc @@ -185,21 +185,14 @@ static bool GetIdsFromByteCode(Collections& collections, std::vector<MethodId*>* method_ids, std::vector<FieldId*>* field_ids) { bool has_id = false; - // Iterate over all instructions. - const uint16_t* insns = code->Insns(); - for (uint32_t insn_idx = 0; insn_idx < code->InsnsSize();) { - const Instruction* instruction = Instruction::At(&insns[insn_idx]); - const uint32_t insn_width = instruction->SizeInCodeUnits(); - if (insn_width == 0) { - break; - } + for (const Instruction& instruction : code->Instructions()) { + CHECK_GT(instruction.SizeInCodeUnits(), 0u); has_id |= GetIdFromInstruction(collections, - instruction, + &instruction, type_ids, string_ids, method_ids, field_ids); - insn_idx += insn_width; } // for return has_id; } diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h index 362c08b918..5dcc87dd2e 100644 --- a/dexlayout/dex_ir.h +++ b/dexlayout/dex_ir.h @@ -947,6 +947,11 @@ class CodeItem : public Item { void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } + IterationRange<DexInstructionIterator> Instructions() const { + return MakeIterationRange(DexInstructionIterator(Insns()), + DexInstructionIterator(Insns() + InsnsSize())); + } + private: uint16_t registers_size_; uint16_t ins_size_; diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index 92a1366778..095c960bc0 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -1079,16 +1079,15 @@ void DexLayout::DumpBytecodes(uint32_t idx, const dex_ir::CodeItem* code, uint32 code_offset, code_offset, dot.c_str(), name, type_descriptor.c_str()); // Iterate over all instructions. - const uint16_t* insns = code->Insns(); - for (uint32_t insn_idx = 0; insn_idx < code->InsnsSize();) { - const Instruction* instruction = Instruction::At(&insns[insn_idx]); - const uint32_t insn_width = instruction->SizeInCodeUnits(); + IterationRange<DexInstructionIterator> instructions = code->Instructions(); + for (auto inst = instructions.begin(); inst != instructions.end(); ++inst) { + const uint32_t dex_pc = inst.GetDexPC(instructions.begin()); + const uint32_t insn_width = inst->SizeInCodeUnits(); if (insn_width == 0) { - fprintf(stderr, "GLITCH: zero-width instruction at idx=0x%04x\n", insn_idx); + fprintf(stderr, "GLITCH: zero-width instruction at idx=0x%04x\n", dex_pc); break; } - DumpInstruction(code, code_offset, insn_idx, insn_width, instruction); - insn_idx += insn_width; + DumpInstruction(code, code_offset, dex_pc, insn_width, &*inst); } // for } diff --git a/dexoptanalyzer/Android.bp b/dexoptanalyzer/Android.bp index 715c209d7f..33366ad371 100644 --- a/dexoptanalyzer/Android.bp +++ b/dexoptanalyzer/Android.bp @@ -58,7 +58,7 @@ art_cc_test { "art_gtest_defaults", ], shared_libs: [ - "libbacktrace" + "libbacktrace", ], srcs: ["dexoptanalyzer_test.cc"], } diff --git a/disassembler/Android.bp b/disassembler/Android.bp index 086b8c7990..88493091e6 100644 --- a/disassembler/Android.bp +++ b/disassembler/Android.bp @@ -18,7 +18,6 @@ art_cc_defaults { name: "libart-disassembler-defaults", defaults: ["art_defaults"], host_supported: true, - clang: true, srcs: [ "disassembler.cc", "disassembler_arm.cc", diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 36bd4bcc24..bcf007b87a 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -36,6 +36,7 @@ #include "base/unix_file/fd_file.h" #include "class_linker-inl.h" #include "class_linker.h" +#include "compiled_method.h" #include "debug/elf_debug_writer.h" #include "debug/method_debug_info.h" #include "dex_file-inl.h" @@ -904,26 +905,23 @@ class OatDumper { if (code_item == nullptr) { return; } - const size_t code_item_size = code_item->insns_size_in_code_units_; - const uint16_t* code_ptr = code_item->insns_; - const uint16_t* code_end = code_item->insns_ + code_item_size; + const uint16_t* code_ptr = code_item->insns_; // If we inserted a new dex code item pointer, add to total code bytes. if (dex_code_item_ptrs_.insert(code_ptr).second) { - dex_code_bytes_ += code_item_size * sizeof(code_ptr[0]); + dex_code_bytes_ += code_item->insns_size_in_code_units_ * sizeof(code_ptr[0]); } - while (code_ptr < code_end) { - const Instruction* inst = Instruction::At(code_ptr); - switch (inst->Opcode()) { + for (const Instruction& inst : code_item->Instructions()) { + switch (inst.Opcode()) { case Instruction::CONST_STRING: { - const dex::StringIndex string_index(inst->VRegB_21c()); + const dex::StringIndex string_index(inst.VRegB_21c()); unique_string_ids_from_code_.insert(StringReference(&dex_file, string_index)); ++num_string_ids_from_code_; break; } case Instruction::CONST_STRING_JUMBO: { - const dex::StringIndex string_index(inst->VRegB_31c()); + const dex::StringIndex string_index(inst.VRegB_31c()); unique_string_ids_from_code_.insert(StringReference(&dex_file, string_index)); ++num_string_ids_from_code_; break; @@ -931,8 +929,6 @@ class OatDumper { default: break; } - - code_ptr += inst->SizeInCodeUnits(); } } @@ -1519,12 +1515,11 @@ class OatDumper { void DumpDexCode(std::ostream& os, const DexFile& dex_file, const DexFile::CodeItem* code_item) { if (code_item != nullptr) { - size_t i = 0; - while (i < code_item->insns_size_in_code_units_) { - const Instruction* instruction = Instruction::At(&code_item->insns_[i]); - os << StringPrintf("0x%04zx: ", i) << instruction->DumpHexLE(5) - << StringPrintf("\t| %s\n", instruction->DumpString(&dex_file).c_str()); - i += instruction->SizeInCodeUnits(); + IterationRange<DexInstructionIterator> instructions = code_item->Instructions(); + for (auto it = instructions.begin(); it != instructions.end(); ++it) { + const size_t dex_pc = it.GetDexPC(instructions.begin()); + os << StringPrintf("0x%04zx: ", dex_pc) << it->DumpHexLE(5) + << StringPrintf("\t| %s\n", it->DumpString(&dex_file).c_str()); } } } diff --git a/openjdkjvm/Android.bp b/openjdkjvm/Android.bp index 071b4348f8..761df02553 100644 --- a/openjdkjvm/Android.bp +++ b/openjdkjvm/Android.bp @@ -20,7 +20,7 @@ cc_defaults { srcs: ["OpenjdkJvm.cc"], shared_libs: [ "libbase", - "libnativehelper" + "libnativehelper", ], } diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp index b6b1b56a26..84a90d65fd 100644 --- a/openjdkjvmti/Android.bp +++ b/openjdkjvmti/Android.bp @@ -23,31 +23,33 @@ cc_defaults { name: "libopenjdkjvmti_defaults", defaults: ["art_defaults"], host_supported: true, - srcs: ["events.cc", - "fixed_up_dex_file.cc", - "object_tagging.cc", - "OpenjdkJvmTi.cc", - "ti_allocator.cc", - "ti_breakpoint.cc", - "ti_class.cc", - "ti_class_definition.cc", - "ti_class_loader.cc", - "ti_dump.cc", - "ti_field.cc", - "ti_heap.cc", - "ti_jni.cc", - "ti_method.cc", - "ti_monitor.cc", - "ti_object.cc", - "ti_phase.cc", - "ti_properties.cc", - "ti_search.cc", - "ti_stack.cc", - "ti_redefine.cc", - "ti_thread.cc", - "ti_threadgroup.cc", - "ti_timers.cc", - "transform.cc"], + srcs: [ + "events.cc", + "fixed_up_dex_file.cc", + "object_tagging.cc", + "OpenjdkJvmTi.cc", + "ti_allocator.cc", + "ti_breakpoint.cc", + "ti_class.cc", + "ti_class_definition.cc", + "ti_class_loader.cc", + "ti_dump.cc", + "ti_field.cc", + "ti_heap.cc", + "ti_jni.cc", + "ti_method.cc", + "ti_monitor.cc", + "ti_object.cc", + "ti_phase.cc", + "ti_properties.cc", + "ti_search.cc", + "ti_stack.cc", + "ti_redefine.cc", + "ti_thread.cc", + "ti_threadgroup.cc", + "ti_timers.cc", + "transform.cc", + ], header_libs: ["libopenjdkjvmti_headers"], shared_libs: [ "libbase", diff --git a/openjdkjvmti/OpenjdkJvmTi.cc b/openjdkjvmti/OpenjdkJvmTi.cc index 4339b2bdef..bac57f9bc6 100644 --- a/openjdkjvmti/OpenjdkJvmTi.cc +++ b/openjdkjvmti/OpenjdkJvmTi.cc @@ -1034,14 +1034,13 @@ class JvmtiFunctions { ENSURE_VALID_ENV(env); art::Thread* art_thread = nullptr; if (event_thread != nullptr) { - // TODO: Need non-aborting call here, to return JVMTI_ERROR_INVALID_THREAD. + // TODO The locking around this call is less then what we really want. art::ScopedObjectAccess soa(art::Thread::Current()); art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); - art_thread = art::Thread::FromManagedThread(soa, event_thread); - - if (art_thread == nullptr || // The thread hasn't been started or is already dead. - art_thread->IsStillStarting()) { - // TODO: We may want to let the EventHandler know, so it could clean up masks, potentially. + jvmtiError err = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(event_thread, soa, &art_thread, &err)) { + return err; + } else if (art_thread->IsStillStarting()) { return ERR(THREAD_NOT_ALIVE); } } diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc index 62603aa187..7f841fc62d 100644 --- a/openjdkjvmti/ti_method.cc +++ b/openjdkjvmti/ti_method.cc @@ -761,12 +761,10 @@ jvmtiError MethodUtil::GetLocalVariableGeneric(jvmtiEnv* env ATTRIBUTE_UNUSED, art::jit::ScopedJitSuspend suspend_jit; art::ScopedObjectAccess soa(self); art::MutexLock mu(self, *art::Locks::thread_list_lock_); - art::Thread* target = ThreadUtil::GetNativeThread(thread, soa); - if (target == nullptr && thread == nullptr) { - return ERR(INVALID_THREAD); - } - if (target == nullptr) { - return ERR(THREAD_NOT_ALIVE); + art::Thread* target = nullptr; + jvmtiError err = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { + return err; } GetLocalVariableClosure c(self, depth, slot, type, val); if (!target->RequestSynchronousCheckpoint(&c)) { @@ -890,12 +888,10 @@ jvmtiError MethodUtil::SetLocalVariableGeneric(jvmtiEnv* env ATTRIBUTE_UNUSED, art::jit::ScopedJitSuspend suspend_jit; art::ScopedObjectAccess soa(self); art::MutexLock mu(self, *art::Locks::thread_list_lock_); - art::Thread* target = ThreadUtil::GetNativeThread(thread, soa); - if (target == nullptr && thread == nullptr) { - return ERR(INVALID_THREAD); - } - if (target == nullptr) { - return ERR(THREAD_NOT_ALIVE); + art::Thread* target = nullptr; + jvmtiError err = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { + return err; } SetLocalVariableClosure c(self, depth, slot, type, val); if (!target->RequestSynchronousCheckpoint(&c)) { @@ -923,12 +919,6 @@ class GetLocalInstanceClosure : public art::Closure { result_ = ERR(NO_MORE_FRAMES); return; } - art::ArtMethod* method = visitor.GetMethod(); - if (!visitor.IsShadowFrame() && !method->IsNative() && !method->IsProxyMethod()) { - // TODO We really should support get/set for non-shadow frames. - result_ = ERR(OPAQUE_FRAME); - return; - } result_ = OK; art::ObjPtr<art::mirror::Object> obj = visitor.GetThisObject(); *val_ = obj.IsNull() ? nullptr : caller_->GetJniEnv()->AddLocalReference<jobject>(obj); @@ -955,12 +945,10 @@ jvmtiError MethodUtil::GetLocalInstance(jvmtiEnv* env ATTRIBUTE_UNUSED, art::Thread* self = art::Thread::Current(); art::ScopedObjectAccess soa(self); art::MutexLock mu(self, *art::Locks::thread_list_lock_); - art::Thread* target = ThreadUtil::GetNativeThread(thread, soa); - if (target == nullptr && thread == nullptr) { - return ERR(INVALID_THREAD); - } - if (target == nullptr) { - return ERR(THREAD_NOT_ALIVE); + art::Thread* target = nullptr; + jvmtiError err = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { + return err; } GetLocalInstanceClosure c(self, depth, data); if (!target->RequestSynchronousCheckpoint(&c)) { diff --git a/openjdkjvmti/ti_monitor.cc b/openjdkjvmti/ti_monitor.cc index f92d81ef17..5a38f46901 100644 --- a/openjdkjvmti/ti_monitor.cc +++ b/openjdkjvmti/ti_monitor.cc @@ -335,12 +335,10 @@ jvmtiError MonitorUtil::GetCurrentContendedMonitor(jvmtiEnv* env ATTRIBUTE_UNUSE art::Thread* self = art::Thread::Current(); art::ScopedObjectAccess soa(self); art::MutexLock mu(self, *art::Locks::thread_list_lock_); - art::Thread* target = ThreadUtil::GetNativeThread(thread, soa); - if (target == nullptr && thread == nullptr) { - return ERR(INVALID_THREAD); - } - if (target == nullptr) { - return ERR(THREAD_NOT_ALIVE); + art::Thread* target = nullptr; + jvmtiError err = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { + return err; } struct GetContendedMonitorClosure : public art::Closure { public: @@ -395,7 +393,9 @@ jvmtiError MonitorUtil::GetCurrentContendedMonitor(jvmtiEnv* env ATTRIBUTE_UNUSE jobject* out_; }; GetContendedMonitorClosure closure(self, monitor); - target->RequestSynchronousCheckpoint(&closure); + if (!target->RequestSynchronousCheckpoint(&closure)) { + return ERR(THREAD_NOT_ALIVE); + } return OK; } diff --git a/openjdkjvmti/ti_stack.cc b/openjdkjvmti/ti_stack.cc index 699f6952c4..d4cc42ae70 100644 --- a/openjdkjvmti/ti_stack.cc +++ b/openjdkjvmti/ti_stack.cc @@ -211,34 +211,6 @@ struct GetStackTraceDirectClosure : public art::Closure { size_t index = 0; }; -static jvmtiError GetThread(JNIEnv* env, - art::ScopedObjectAccessAlreadyRunnable& soa, - jthread java_thread, - art::Thread** thread) - REQUIRES_SHARED(art::Locks::mutator_lock_) // Needed for FromManagedThread. - REQUIRES(art::Locks::thread_list_lock_) { // Needed for FromManagedThread. - if (java_thread == nullptr) { - *thread = art::Thread::Current(); - if (*thread == nullptr) { - // GetStackTrace can only be run during the live phase, so the current thread should be - // attached and thus available. Getting a null for current means we're starting up or - // dying. - return ERR(WRONG_PHASE); - } - } else { - if (!env->IsInstanceOf(java_thread, art::WellKnownClasses::java_lang_Thread)) { - return ERR(INVALID_THREAD); - } - - // TODO: Need non-aborting call here, to return JVMTI_ERROR_INVALID_THREAD. - *thread = art::Thread::FromManagedThread(soa, java_thread); - if (*thread == nullptr) { - return ERR(THREAD_NOT_ALIVE); - } - } - return ERR(NONE); -} - jvmtiError StackUtil::GetStackTrace(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED, jthread java_thread, jint start_depth, @@ -251,19 +223,14 @@ jvmtiError StackUtil::GetStackTrace(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED, art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); art::Thread* thread; - jvmtiError thread_error = GetThread(art::Thread::Current()->GetJniEnv(), - soa, - java_thread, - &thread); - if (thread_error != ERR(NONE)) { + jvmtiError thread_error = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(java_thread, soa, &thread, &thread_error)) { return thread_error; } DCHECK(thread != nullptr); art::ThreadState state = thread->GetState(); - if (state == art::ThreadState::kStarting || - state == art::ThreadState::kTerminated || - thread->IsStillStarting()) { + if (state == art::ThreadState::kStarting || thread->IsStillStarting()) { return ERR(THREAD_NOT_ALIVE); } @@ -714,22 +681,25 @@ jvmtiError StackUtil::GetFrameCount(jvmtiEnv* env ATTRIBUTE_UNUSED, art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); art::Thread* thread; - jvmtiError thread_error = GetThread(art::Thread::Current()->GetJniEnv(), - soa, - java_thread, - &thread); - - if (thread_error != ERR(NONE)) { + jvmtiError thread_error = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(java_thread, soa, &thread, &thread_error)) { return thread_error; } + DCHECK(thread != nullptr); + art::ThreadState state = thread->GetState(); + if (state == art::ThreadState::kStarting || thread->IsStillStarting()) { + return ERR(THREAD_NOT_ALIVE); + } if (count_ptr == nullptr) { return ERR(NULL_POINTER); } GetFrameCountClosure closure; - thread->RequestSynchronousCheckpoint(&closure); + if (!thread->RequestSynchronousCheckpoint(&closure)) { + return ERR(THREAD_NOT_ALIVE); + } *count_ptr = closure.count; return ERR(NONE); @@ -793,15 +763,17 @@ jvmtiError StackUtil::GetFrameLocation(jvmtiEnv* env ATTRIBUTE_UNUSED, art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); art::Thread* thread; - jvmtiError thread_error = GetThread(art::Thread::Current()->GetJniEnv(), - soa, - java_thread, - &thread); - if (thread_error != ERR(NONE)) { + jvmtiError thread_error = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(java_thread, soa, &thread, &thread_error)) { return thread_error; } DCHECK(thread != nullptr); + art::ThreadState state = thread->GetState(); + if (state == art::ThreadState::kStarting || thread->IsStillStarting()) { + return ERR(THREAD_NOT_ALIVE); + } + if (depth < 0) { return ERR(ILLEGAL_ARGUMENT); } @@ -920,12 +892,10 @@ static jvmtiError GetOwnedMonitorInfoCommon(jthread thread, Fn handle_results) { bool called_method = false; { art::MutexLock mu(self, *art::Locks::thread_list_lock_); - art::Thread* target = ThreadUtil::GetNativeThread(thread, soa); - if (target == nullptr && thread == nullptr) { - return ERR(INVALID_THREAD); - } - if (target == nullptr) { - return ERR(THREAD_NOT_ALIVE); + art::Thread* target = nullptr; + jvmtiError err = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { + return err; } if (target != self) { called_method = true; @@ -1014,10 +984,11 @@ jvmtiError StackUtil::NotifyFramePop(jvmtiEnv* env, jthread thread, jint depth) // have the 'suspend_lock' locked here. art::ScopedObjectAccess soa(self); art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_); - target = ThreadUtil::GetNativeThread(thread, soa); - if (target == nullptr) { - return ERR(THREAD_NOT_ALIVE); - } else if (target != self) { + jvmtiError err = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { + return err; + } + if (target != self) { // TODO This is part of the spec but we could easily avoid needing to do it. We would just put // all the logic into a sync-checkpoint. art::MutexLock tscl_mu(self, *art::Locks::thread_suspend_count_lock_); diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc index d437e52d0f..907b5158c6 100644 --- a/openjdkjvmti/ti_thread.cc +++ b/openjdkjvmti/ti_thread.cc @@ -161,13 +161,34 @@ jvmtiError ThreadUtil::GetCurrentThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread* } // Get the native thread. The spec says a null object denotes the current thread. -art::Thread* ThreadUtil::GetNativeThread(jthread thread, - const art::ScopedObjectAccessAlreadyRunnable& soa) { +bool ThreadUtil::GetNativeThread(jthread thread, + const art::ScopedObjectAccessAlreadyRunnable& soa, + /*out*/ art::Thread** thr, + /*out*/ jvmtiError* err) { if (thread == nullptr) { - return art::Thread::Current(); + *thr = art::Thread::Current(); + return true; + } else if (!soa.Env()->IsInstanceOf(thread, art::WellKnownClasses::java_lang_Thread)) { + *err = ERR(INVALID_THREAD); + return false; + } else { + *thr = art::Thread::FromManagedThread(soa, thread); + return true; } +} - return art::Thread::FromManagedThread(soa, thread); +bool ThreadUtil::GetAliveNativeThread(jthread thread, + const art::ScopedObjectAccessAlreadyRunnable& soa, + /*out*/ art::Thread** thr, + /*out*/ jvmtiError* err) { + if (!GetNativeThread(thread, soa, thr, err)) { + return false; + } else if (*thr == nullptr || (*thr)->GetState() == art::ThreadState::kTerminated) { + *err = ERR(THREAD_NOT_ALIVE); + return false; + } else { + return true; + } } jvmtiError ThreadUtil::GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr) { @@ -182,9 +203,10 @@ jvmtiError ThreadUtil::GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadI art::ScopedObjectAccess soa(self); art::MutexLock mu(self, *art::Locks::thread_list_lock_); - art::Thread* target = GetNativeThread(thread, soa); - if (target == nullptr && thread == nullptr) { - return ERR(INVALID_THREAD); + art::Thread* target; + jvmtiError err = ERR(INTERNAL); + if (!GetNativeThread(thread, soa, &target, &err)) { + return err; } JvmtiUniquePtr<char[]> name_uptr; @@ -297,25 +319,18 @@ struct InternalThreadState { }; // Return the thread's (or current thread, if null) thread state. -static InternalThreadState GetNativeThreadState(jthread thread, - const art::ScopedObjectAccessAlreadyRunnable& soa) +static InternalThreadState GetNativeThreadState(art::Thread* target) REQUIRES_SHARED(art::Locks::mutator_lock_) REQUIRES(art::Locks::thread_list_lock_, art::Locks::user_code_suspension_lock_) { - art::Thread* self = nullptr; - if (thread == nullptr) { - self = art::Thread::Current(); - } else { - self = art::Thread::FromManagedThread(soa, thread); - } InternalThreadState thread_state = {}; - art::MutexLock tscl_mu(soa.Self(), *art::Locks::thread_suspend_count_lock_); - thread_state.native_thread = self; - if (self == nullptr || self->IsStillStarting()) { + art::MutexLock tscl_mu(art::Thread::Current(), *art::Locks::thread_suspend_count_lock_); + thread_state.native_thread = target; + if (target == nullptr || target->IsStillStarting()) { thread_state.art_state = art::ThreadState::kStarting; thread_state.thread_user_code_suspend_count = 0; } else { - thread_state.art_state = self->GetState(); - thread_state.thread_user_code_suspend_count = self->GetUserCodeSuspendCount(); + thread_state.art_state = target->GetState(); + thread_state.thread_user_code_suspend_count = target->GetUserCodeSuspendCount(); } return thread_state; } @@ -456,7 +471,12 @@ jvmtiError ThreadUtil::GetThreadState(jvmtiEnv* env ATTRIBUTE_UNUSED, } art::ScopedObjectAccess soa(self); art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_); - state = GetNativeThreadState(thread, soa); + jvmtiError err = ERR(INTERNAL); + art::Thread* target = nullptr; + if (!GetNativeThread(thread, soa, &target, &err)) { + return err; + } + state = GetNativeThreadState(target); if (state.art_state == art::ThreadState::kStarting) { break; } @@ -484,13 +504,18 @@ jvmtiError ThreadUtil::GetThreadState(jvmtiEnv* env ATTRIBUTE_UNUSED, } art::ScopedObjectAccess soa(self); + art::StackHandleScope<1> hs(self); // Need to read the Java "started" field to know whether this is starting or terminated. - art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread); - art::ObjPtr<art::mirror::Class> klass = peer->GetClass(); - art::ArtField* started_field = klass->FindDeclaredInstanceField("started", "Z"); + art::Handle<art::mirror::Object> peer(hs.NewHandle(soa.Decode<art::mirror::Object>(thread))); + art::ObjPtr<art::mirror::Class> thread_klass = + soa.Decode<art::mirror::Class>(art::WellKnownClasses::java_lang_Thread); + if (!thread_klass->IsAssignableFrom(peer->GetClass())) { + return ERR(INVALID_THREAD); + } + art::ArtField* started_field = thread_klass->FindDeclaredInstanceField("started", "Z"); CHECK(started_field != nullptr); - bool started = started_field->GetBoolean(peer) != 0; + bool started = started_field->GetBoolean(peer.Get()) != 0; constexpr jint kStartedState = JVMTI_JAVA_LANG_THREAD_STATE_NEW; constexpr jint kTerminatedState = JVMTI_THREAD_STATE_TERMINATED | JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED; @@ -573,12 +598,10 @@ jvmtiError ThreadUtil::SetThreadLocalStorage(jvmtiEnv* env, jthread thread, cons art::Thread* self = art::Thread::Current(); art::ScopedObjectAccess soa(self); art::MutexLock mu(self, *art::Locks::thread_list_lock_); - art::Thread* target = GetNativeThread(thread, soa); - if (target == nullptr && thread == nullptr) { - return ERR(INVALID_THREAD); - } - if (target == nullptr) { - return ERR(THREAD_NOT_ALIVE); + art::Thread* target = nullptr; + jvmtiError err = ERR(INTERNAL); + if (!GetAliveNativeThread(thread, soa, &target, &err)) { + return err; } JvmtiGlobalTLSData* global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS()); @@ -602,12 +625,10 @@ jvmtiError ThreadUtil::GetThreadLocalStorage(jvmtiEnv* env, art::Thread* self = art::Thread::Current(); art::ScopedObjectAccess soa(self); art::MutexLock mu(self, *art::Locks::thread_list_lock_); - art::Thread* target = GetNativeThread(thread, soa); - if (target == nullptr && thread == nullptr) { - return ERR(INVALID_THREAD); - } - if (target == nullptr) { - return ERR(THREAD_NOT_ALIVE); + art::Thread* target = nullptr; + jvmtiError err = ERR(INTERNAL); + if (!GetAliveNativeThread(thread, soa, &target, &err)) { + return err; } JvmtiGlobalTLSData* global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS()); @@ -726,9 +747,13 @@ jvmtiError ThreadUtil::SuspendOther(art::Thread* self, { art::ScopedObjectAccess soa(self); art::MutexLock thread_list_mu(self, *art::Locks::thread_list_lock_); - art::Thread* target = GetNativeThread(target_jthread, soa); + art::Thread* target = nullptr; + jvmtiError err = ERR(INTERNAL); + if (!GetAliveNativeThread(target_jthread, soa, &target, &err)) { + return err; + } art::ThreadState state = target->GetState(); - if (state == art::ThreadState::kTerminated || state == art::ThreadState::kStarting) { + if (state == art::ThreadState::kStarting || target->IsStillStarting()) { return ERR(THREAD_NOT_ALIVE); } else { art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_); @@ -784,9 +809,10 @@ jvmtiError ThreadUtil::SuspendThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread thr { art::ScopedObjectAccess soa(self); art::MutexLock mu(self, *art::Locks::thread_list_lock_); - art::Thread* target = GetNativeThread(thread, soa); - if (target == nullptr) { - return ERR(INVALID_THREAD); + art::Thread* target = nullptr; + jvmtiError err = ERR(INTERNAL); + if (!GetAliveNativeThread(thread, soa, &target, &err)) { + return err; } else if (target == self) { target_is_self = true; } @@ -820,16 +846,14 @@ jvmtiError ThreadUtil::ResumeThread(jvmtiEnv* env ATTRIBUTE_UNUSED, // have the 'suspend_lock' locked here. art::ScopedObjectAccess soa(self); art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_); - target = GetNativeThread(thread, soa); - if (target == nullptr) { - return ERR(INVALID_THREAD); + jvmtiError err = ERR(INTERNAL); + if (!GetAliveNativeThread(thread, soa, &target, &err)) { + return err; } else if (target == self) { // We would have paused until we aren't suspended anymore due to the ScopedObjectAccess so // we can just return THREAD_NOT_SUSPENDED. Unfortunately we cannot do any real DCHECKs // about current state since it's all concurrent. return ERR(THREAD_NOT_SUSPENDED); - } else if (target->GetState() == art::ThreadState::kTerminated) { - return ERR(THREAD_NOT_ALIVE); } // The JVMTI spec requires us to return THREAD_NOT_SUSPENDED if it is alive but we really // cannot tell why resume failed. @@ -854,6 +878,22 @@ jvmtiError ThreadUtil::ResumeThread(jvmtiEnv* env ATTRIBUTE_UNUSED, } while (true); } +static bool IsCurrentThread(jthread thr) { + if (thr == nullptr) { + return true; + } + art::Thread* self = art::Thread::Current(); + art::ScopedObjectAccess soa(self); + art::MutexLock mu(self, *art::Locks::thread_list_lock_); + art::Thread* target = nullptr; + jvmtiError err_unused = ERR(INTERNAL); + if (ThreadUtil::GetNativeThread(thr, soa, &target, &err_unused)) { + return target == self; + } else { + return false; + } +} + // Suspends all the threads in the list at the same time. Getting this behavior is a little tricky // since we can have threads in the list multiple times. This generally doesn't matter unless the // current thread is present multiple times. In that case we need to suspend only once and either @@ -873,17 +913,12 @@ jvmtiError ThreadUtil::SuspendThreadList(jvmtiEnv* env, // running thread. These indexes we need to handle specially since we need to only actually // suspend a single time. std::vector<jint> current_thread_indexes; - art::Thread* self = art::Thread::Current(); for (jint i = 0; i < request_count; i++) { - { - art::ScopedObjectAccess soa(self); - art::MutexLock mu(self, *art::Locks::thread_list_lock_); - if (threads[i] == nullptr || GetNativeThread(threads[i], soa) == self) { - current_thread_indexes.push_back(i); - continue; - } + if (IsCurrentThread(threads[i])) { + current_thread_indexes.push_back(i); + } else { + results[i] = env->SuspendThread(threads[i]); } - results[i] = env->SuspendThread(threads[i]); } if (!current_thread_indexes.empty()) { jint first_current_thread_index = current_thread_indexes[0]; diff --git a/openjdkjvmti/ti_thread.h b/openjdkjvmti/ti_thread.h index 57b194362f..ceebff67ec 100644 --- a/openjdkjvmti/ti_thread.h +++ b/openjdkjvmti/ti_thread.h @@ -93,8 +93,24 @@ class ThreadUtil { const jthread* threads, jvmtiError* results); - static art::Thread* GetNativeThread(jthread thread, - const art::ScopedObjectAccessAlreadyRunnable& soa) + // Returns true if we decoded the thread and it is alive, false otherwise with an appropriate + // error placed into 'err'. A thread is alive if it has had it's 'start' function called and has + // (or at least could have) executed managed code and has not yet returned past it's first managed + // frame. This means that the thread returned might have IsStillStarting() return true. Code that + // does not consider that alive should check manually. + static bool GetAliveNativeThread(jthread thread, + const art::ScopedObjectAccessAlreadyRunnable& soa, + /*out*/ art::Thread** thr, + /*out*/ jvmtiError* err) + REQUIRES_SHARED(art::Locks::mutator_lock_) + REQUIRES(art::Locks::thread_list_lock_); + + // Returns true if we decoded the thread, false otherwise with an appropriate error placed into + // 'err' + static bool GetNativeThread(jthread thread, + const art::ScopedObjectAccessAlreadyRunnable& soa, + /*out*/ art::Thread** thr, + /*out*/ jvmtiError* err) REQUIRES_SHARED(art::Locks::mutator_lock_) REQUIRES(art::Locks::thread_list_lock_); diff --git a/runtime/Android.bp b/runtime/Android.bp index db9707f290..a3a45e1984 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -356,10 +356,9 @@ cc_defaults { "thread_android.cc", ], shared_libs: [ - "libdl", // For android::FileMap used by libziparchive. "libutils", - "libtombstoned_client" + "libtombstoned_client", ], static_libs: [ // ZipArchive support, the order matters here to get all symbols. @@ -398,7 +397,6 @@ cc_defaults { generated_headers: ["cpp-define-generator-asm-support"], // export our headers so the libart-gtest targets can use it as well. export_generated_headers: ["cpp-define-generator-asm-support"], - clang: true, include_dirs: [ "art/sigchainlib", "art", @@ -493,8 +491,8 @@ art_cc_library { art_cc_library { name: "libartd", defaults: [ - "art_debug_defaults", - "libart_defaults", + "art_debug_defaults", + "libart_defaults", ], } @@ -503,12 +501,12 @@ art_cc_library { defaults: ["libart-gtest-defaults"], srcs: [ "common_runtime_test.cc", - "dexopt_test.cc" + "dexopt_test.cc", ], shared_libs: [ "libartd", "libbase", - "libbacktrace" + "libbacktrace", ], } @@ -555,7 +553,6 @@ art_cc_test { "dex_file_test.cc", "dex_file_verifier_test.cc", "dex_instruction_test.cc", - "dex_method_iterator_test.cc", "entrypoints/math_entrypoints_test.cc", "entrypoints/quick/quick_trampoline_entrypoints_test.cc", "entrypoints_order_test.cc", @@ -614,7 +611,7 @@ art_cc_test { "libbacktrace", ], header_libs: [ - "art_cmdlineparser_headers", // For parsed_options_test. + "art_cmdlineparser_headers", // For parsed_options_test. ], } @@ -636,7 +633,7 @@ art_cc_test { } cc_library_headers { - name: "libart_runtime_headers", - host_supported: true, - export_include_dirs: ["."], + name: "libart_runtime_headers", + host_supported: true, + export_include_dirs: ["."], } diff --git a/runtime/art_method.cc b/runtime/art_method.cc index ece853f016..d4297df76f 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -777,26 +777,16 @@ std::string ArtMethod::PrettyMethod(ArtMethod* m, bool with_signature) { } std::string ArtMethod::PrettyMethod(bool with_signature) { - ArtMethod* m = this; - if (!m->IsRuntimeMethod()) { - m = m->GetInterfaceMethodIfProxy(Runtime::Current()->GetClassLinker()->GetImagePointerSize()); - } - std::string result(PrettyDescriptor(m->GetDeclaringClassDescriptor())); - result += '.'; - result += m->GetName(); - if (UNLIKELY(m->IsFastNative())) { - result += "!"; - } - if (with_signature) { - const Signature signature = m->GetSignature(); - std::string sig_as_string(signature.ToString()); - if (signature == Signature::NoSignature()) { - return result + sig_as_string; - } - result = PrettyReturnType(sig_as_string.c_str()) + " " + result + - PrettyArguments(sig_as_string.c_str()); - } - return result; + if (UNLIKELY(IsRuntimeMethod())) { + std::string result = GetDeclaringClassDescriptor(); + result += '.'; + result += GetName(); + // Do not add "<no signature>" even if `with_signature` is true. + return result; + } + ArtMethod* m = + GetInterfaceMethodIfProxy(Runtime::Current()->GetClassLinker()->GetImagePointerSize()); + return m->GetDexFile()->PrettyMethod(m->GetDexMethodIndex(), with_signature); } std::string ArtMethod::JniShortName() { diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc index b2e5251e73..b8d6931a83 100644 --- a/runtime/base/timing_logger.cc +++ b/runtime/base/timing_logger.cc @@ -128,8 +128,11 @@ void CumulativeLogger::DumpHistogram(std::ostream &os) const { os << "Done Dumping histograms\n"; } -TimingLogger::TimingLogger(const char* name, bool precise, bool verbose) - : name_(name), precise_(precise), verbose_(verbose) { +TimingLogger::TimingLogger(const char* name, + bool precise, + bool verbose, + TimingLogger::TimingKind kind) + : name_(name), precise_(precise), verbose_(verbose), kind_(kind) { } void TimingLogger::Reset() { @@ -138,12 +141,12 @@ void TimingLogger::Reset() { void TimingLogger::StartTiming(const char* label) { DCHECK(label != nullptr); - timings_.push_back(Timing(NanoTime(), label)); + timings_.push_back(Timing(kind_, label)); ATRACE_BEGIN(label); } void TimingLogger::EndTiming() { - timings_.push_back(Timing(NanoTime(), nullptr)); + timings_.push_back(Timing(kind_, nullptr)); ATRACE_END(); } diff --git a/runtime/base/timing_logger.h b/runtime/base/timing_logger.h index a5344dbd31..a8a6701822 100644 --- a/runtime/base/timing_logger.h +++ b/runtime/base/timing_logger.h @@ -20,6 +20,7 @@ #include "base/histogram.h" #include "base/macros.h" #include "base/mutex.h" +#include "base/time_utils.h" #include <set> #include <string> @@ -79,9 +80,23 @@ class TimingLogger { public: static constexpr size_t kIndexNotFound = static_cast<size_t>(-1); + // Kind of timing we are going to do. We collect time at the nano second. + enum class TimingKind { + kMonotonic, + kThreadCpu, + }; + class Timing { public: - Timing(uint64_t time, const char* name) : time_(time), name_(name) { + Timing(TimingKind kind, const char* name) : name_(name) { + switch (kind) { + case TimingKind::kMonotonic: + time_ = NanoTime(); + break; + case TimingKind::kThreadCpu: + time_ = ThreadCpuNanoTime(); + break; + } } bool IsStartTiming() const { return !IsEndTiming(); @@ -131,7 +146,10 @@ class TimingLogger { friend class TimingLogger; }; - TimingLogger(const char* name, bool precise, bool verbose); + TimingLogger(const char* name, + bool precise, + bool verbose, + TimingKind kind = TimingKind::kMonotonic); ~TimingLogger(); // Verify that all open timings have related closed timings. void Verify(); @@ -187,6 +205,8 @@ class TimingLogger { const bool precise_; // Verbose logging. const bool verbose_; + // The kind of timing we want. + const TimingKind kind_; // Timing points that are either start or end points. For each starting point ret[i] = location // of end split associated with i. If it is and end split ret[i] = i. std::vector<Timing> timings_; diff --git a/runtime/base/timing_logger_test.cc b/runtime/base/timing_logger_test.cc index 35a73d0a76..770d2c0edd 100644 --- a/runtime/base/timing_logger_test.cc +++ b/runtime/base/timing_logger_test.cc @@ -158,4 +158,21 @@ TEST_F(TimingLoggerTest, ScopedAndExplicit) { EXPECT_LE(timings[idx_innerinnersplit1].GetTime(), timings[idx_innerinnersplit2].GetTime()); } +TEST_F(TimingLoggerTest, ThreadCpuAndMonotonic) { + TimingLogger mon_logger("Scoped", true, false, TimingLogger::TimingKind::kMonotonic); + TimingLogger cpu_logger("Scoped", true, false, TimingLogger::TimingKind::kThreadCpu); + mon_logger.StartTiming("MON"); + cpu_logger.StartTiming("CPU"); + + sleep(2); + + cpu_logger.EndTiming(); + mon_logger.EndTiming(); + uint64_t mon_timing = mon_logger.GetTimings()[1].GetTime() - mon_logger.GetTimings()[0].GetTime(); + uint64_t cpu_timing = cpu_logger.GetTimings()[1].GetTime() - cpu_logger.GetTimings()[0].GetTime(); + EXPECT_LT(cpu_timing, MsToNs(1000u)); + EXPECT_GT(mon_timing, MsToNs(1000u)); + EXPECT_LT(cpu_timing, mon_timing); +} + } // namespace art diff --git a/runtime/base/unix_file/fd_file.cc b/runtime/base/unix_file/fd_file.cc index eb8ced00a8..6d1de0087f 100644 --- a/runtime/base/unix_file/fd_file.cc +++ b/runtime/base/unix_file/fd_file.cc @@ -70,7 +70,7 @@ void FdFile::Destroy() { if (guard_state_ < GuardState::kClosed) { LOG(ERROR) << "File " << file_path_ << " wasn't explicitly closed before destruction."; } - CHECK_GE(guard_state_, GuardState::kClosed); + DCHECK_GE(guard_state_, GuardState::kClosed); } if (auto_close_ && fd_ != -1) { if (Close() != 0) { @@ -135,7 +135,7 @@ bool FdFile::Open(const std::string& path, int flags) { bool FdFile::Open(const std::string& path, int flags, mode_t mode) { static_assert(O_RDONLY == 0, "Readonly flag has unexpected value."); - CHECK_EQ(fd_, -1) << path; + DCHECK_EQ(fd_, -1) << path; read_only_mode_ = ((flags & O_ACCMODE) == O_RDONLY); fd_ = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)); if (fd_ == -1) { @@ -158,7 +158,7 @@ int FdFile::Close() { // Test here, so the file is closed and not leaked. if (kCheckSafeUsage) { - CHECK_GE(guard_state_, GuardState::kFlushed) << "File " << file_path_ + DCHECK_GE(guard_state_, GuardState::kFlushed) << "File " << file_path_ << " has not been flushed before closing."; moveUp(GuardState::kClosed, nullptr); } diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index 3bd45966e4..2282da048f 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -220,7 +220,7 @@ bool ClassLoaderContext::OpenDexFiles(InstructionSet isa, const std::string& cla // If we can't get the realpath of the location there might be something wrong with the // classpath (maybe the file was deleted). // Do not continue in this case and return false. - PLOG(ERROR) << "Could not get the realpath of dex location " << raw_location; + PLOG(WARNING) << "Could not get the realpath of dex location " << raw_location; return false; } diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc index f70846bce0..be157a3f4c 100644 --- a/runtime/dex_file.cc +++ b/runtime/dex_file.cc @@ -1302,17 +1302,27 @@ std::string DexFile::PrettyMethod(uint32_t method_idx, bool with_signature) cons return StringPrintf("<<invalid-method-idx-%d>>", method_idx); } const DexFile::MethodId& method_id = GetMethodId(method_idx); - std::string result(PrettyDescriptor(GetMethodDeclaringClassDescriptor(method_id))); + std::string result; + const DexFile::ProtoId* proto_id = with_signature ? &GetProtoId(method_id.proto_idx_) : nullptr; + if (with_signature) { + AppendPrettyDescriptor(StringByTypeIdx(proto_id->return_type_idx_), &result); + result += ' '; + } + AppendPrettyDescriptor(GetMethodDeclaringClassDescriptor(method_id), &result); result += '.'; result += GetMethodName(method_id); if (with_signature) { - const Signature signature = GetMethodSignature(method_id); - std::string sig_as_string(signature.ToString()); - if (signature == Signature::NoSignature()) { - return result + sig_as_string; + result += '('; + const DexFile::TypeList* params = GetProtoParameters(*proto_id); + if (params != nullptr) { + const char* separator = ""; + for (uint32_t i = 0u, size = params->Size(); i != size; ++i) { + result += separator; + separator = ", "; + AppendPrettyDescriptor(StringByTypeIdx(params->GetTypeItem(i).type_idx_), &result); + } } - result = PrettyReturnType(sig_as_string.c_str()) + " " + result + - PrettyArguments(sig_as_string.c_str()); + result += ')'; } return result; } @@ -1327,7 +1337,7 @@ std::string DexFile::PrettyField(uint32_t field_idx, bool with_type) const { result += GetFieldTypeDescriptor(field_id); result += ' '; } - result += PrettyDescriptor(GetFieldDeclaringClassDescriptor(field_id)); + AppendPrettyDescriptor(GetFieldDeclaringClassDescriptor(field_id), &result); result += '.'; result += GetFieldName(field_id); return result; diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 480742775b..ac91d52a45 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -21,9 +21,11 @@ #include <string> #include <vector> +#include "base/iteration_range.h" #include "base/logging.h" #include "base/value_object.h" #include "dex_file_types.h" +#include "dex_instruction_iterator.h" #include "globals.h" #include "jni.h" #include "modifiers.h" @@ -293,6 +295,15 @@ class DexFile { // Raw code_item. struct CodeItem { + IterationRange<DexInstructionIterator> Instructions() const { + return { DexInstructionIterator(insns_), + DexInstructionIterator(insns_ + insns_size_in_code_units_)}; + } + + const Instruction& InstructionAt(uint32_t dex_pc) const { + return *Instruction::At(insns_ + dex_pc); + } + uint16_t registers_size_; // the number of registers used by this code // (locals + parameters) uint16_t ins_size_; // the number of words of incoming arguments to the method diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc index 1a73062068..a7bf59eb29 100644 --- a/runtime/dex_file_test.cc +++ b/runtime/dex_file_test.cc @@ -423,28 +423,83 @@ TEST_F(DexFileTest, GetMethodSignature) { ASSERT_EQ("()V", signature); } - // Check both virtual methods. - ASSERT_EQ(2U, it.NumVirtualMethods()); - { + // Check all virtual methods. + struct Result { + const char* name; + const char* signature; + const char* pretty_method; + }; + static const Result results[] = { + { + "m1", + "(IDJLjava/lang/Object;)Ljava/lang/Float;", + "java.lang.Float GetMethodSignature.m1(int, double, long, java.lang.Object)" + }, + { // NOLINT [whitespace/braces] [4] + "m2", + "(ZSC)LGetMethodSignature;", + "GetMethodSignature GetMethodSignature.m2(boolean, short, char)" + }, + { // NOLINT [whitespace/braces] [4] + "m3", + "()V", + "void GetMethodSignature.m3()" + }, + { // NOLINT [whitespace/braces] [4] + "m4", + "(I)V", + "void GetMethodSignature.m4(int)" + }, + { // NOLINT [whitespace/braces] [4] + "m5", + "(II)V", + "void GetMethodSignature.m5(int, int)" + }, + { // NOLINT [whitespace/braces] [4] + "m6", + "(II[[I)V", + "void GetMethodSignature.m6(int, int, int[][])" + }, + { // NOLINT [whitespace/braces] [4] + "m7", + "(II[[ILjava/lang/Object;)V", + "void GetMethodSignature.m7(int, int, int[][], java.lang.Object)" + }, + { // NOLINT [whitespace/braces] [4] + "m8", + "(II[[ILjava/lang/Object;[[Ljava/lang/Object;)V", + "void GetMethodSignature.m8(int, int, int[][], java.lang.Object, java.lang.Object[][])" + }, + { // NOLINT [whitespace/braces] [4] + "m9", + "()I", + "int GetMethodSignature.m9()" + }, + { // NOLINT [whitespace/braces] [4] + "mA", + "()[[I", + "int[][] GetMethodSignature.mA()" + }, + { // NOLINT [whitespace/braces] [4] + "mB", + "()[[Ljava/lang/Object;", + "java.lang.Object[][] GetMethodSignature.mB()" + }, + }; + ASSERT_EQ(arraysize(results), it.NumVirtualMethods()); + for (const Result& r : results) { it.Next(); const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex()); const char* name = raw->StringDataByIdx(method_id.name_idx_); - ASSERT_STREQ("m1", name); + ASSERT_STREQ(r.name, name); std::string signature(raw->GetMethodSignature(method_id).ToString()); - ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", signature); - } + ASSERT_EQ(r.signature, signature); - { - it.Next(); - const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex()); - - const char* name = raw->StringDataByIdx(method_id.name_idx_); - ASSERT_STREQ("m2", name); - - std::string signature(raw->GetMethodSignature(method_id).ToString()); - ASSERT_EQ("(ZSC)LGetMethodSignature;", signature); + std::string plain_method = std::string("GetMethodSignature.") + r.name; + ASSERT_EQ(plain_method, raw->PrettyMethod(it.GetMemberIndex(), /* with_signature */ false)); + ASSERT_EQ(r.pretty_method, raw->PrettyMethod(it.GetMemberIndex(), /* with_signature */ true)); } } diff --git a/runtime/dex_instruction_iterator.h b/runtime/dex_instruction_iterator.h new file mode 100644 index 0000000000..6585875df4 --- /dev/null +++ b/runtime/dex_instruction_iterator.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2017 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_DEX_INSTRUCTION_ITERATOR_H_ +#define ART_RUNTIME_DEX_INSTRUCTION_ITERATOR_H_ + +#include <iterator> + +#include "dex_instruction.h" +#include "base/logging.h" + +namespace art { + +class DexInstructionIterator : public std::iterator<std::forward_iterator_tag, Instruction> { + public: + using Type = std::iterator<std::forward_iterator_tag, Instruction>::value_type; + using difference_type = typename std::iterator<std::forward_iterator_tag, Type>::difference_type; + + DexInstructionIterator() = default; + DexInstructionIterator(const DexInstructionIterator&) = default; + DexInstructionIterator(DexInstructionIterator&&) = default; + DexInstructionIterator& operator=(const DexInstructionIterator&) = default; + DexInstructionIterator& operator=(DexInstructionIterator&&) = default; + + explicit DexInstructionIterator(const Type* inst) : inst_(inst) {} + explicit DexInstructionIterator(const uint16_t* inst) : inst_(Type::At(inst)) {} + + ALWAYS_INLINE bool operator==(const DexInstructionIterator& other) const { + return inst_ == other.inst_ || inst_ == nullptr || other.inst_ == nullptr; + } + + // Value after modification. + DexInstructionIterator& operator++() { + inst_ = inst_->Next(); + return *this; + } + + // Value before modification. + DexInstructionIterator operator++(int) { + DexInstructionIterator temp = *this; + ++*this; + return temp; + } + + const Type& operator*() const { + return *inst_; + } + + const Type* operator->() const { + return &**this; + } + + // Return the dex pc for an iterator compared to the code item begin. + uint32_t GetDexPC(const DexInstructionIterator& code_item_begin) { + return reinterpret_cast<const uint16_t*>(inst_) - + reinterpret_cast<const uint16_t*>(code_item_begin.inst_); + } + + const Type* Inst() const { + return inst_; + } + + private: + const Type* inst_ = nullptr; +}; + +static inline bool operator!=(const DexInstructionIterator& lhs, + const DexInstructionIterator& rhs) { + return !(lhs == rhs); +} + +static inline bool operator<(const DexInstructionIterator& lhs, + const DexInstructionIterator& rhs) { + return lhs.Inst() < rhs.Inst(); +} + +static inline bool operator>(const DexInstructionIterator& lhs, + const DexInstructionIterator& rhs) { + return rhs < lhs; +} + +static inline bool operator<=(const DexInstructionIterator& lhs, + const DexInstructionIterator& rhs) { + return !(rhs < lhs); +} + +static inline bool operator>=(const DexInstructionIterator& lhs, + const DexInstructionIterator& rhs) { + return !(lhs < rhs); +} + +} // namespace art + +#endif // ART_RUNTIME_DEX_INSTRUCTION_ITERATOR_H_ diff --git a/runtime/dex_instruction_test.cc b/runtime/dex_instruction_test.cc index 3f7ac57cef..48ed027882 100644 --- a/runtime/dex_instruction_test.cc +++ b/runtime/dex_instruction_test.cc @@ -15,6 +15,7 @@ */ #include "dex_instruction-inl.h" +#include "dex_instruction_iterator.h" #include "gtest/gtest.h" namespace art { @@ -73,7 +74,7 @@ TEST(Instruction, PropertiesOf45cc) { Build45cc(4u /* num_vregs */, 16u /* method_idx */, 32u /* proto_idx */, 0xcafe /* arg_regs */, instruction); - const Instruction* ins = Instruction::At(instruction); + DexInstructionIterator ins(instruction); ASSERT_EQ(4u, ins->SizeInCodeUnits()); ASSERT_TRUE(ins->HasVRegA()); @@ -108,7 +109,7 @@ TEST(Instruction, PropertiesOf4rcc) { Build4rcc(4u /* num_vregs */, 16u /* method_idx */, 32u /* proto_idx */, 0xcafe /* arg_regs */, instruction); - const Instruction* ins = Instruction::At(instruction); + DexInstructionIterator ins(instruction); ASSERT_EQ(4u, ins->SizeInCodeUnits()); ASSERT_TRUE(ins->HasVRegA()); @@ -154,7 +155,7 @@ static std::string DumpInst35c(Instruction::Code code, std::vector<uint16_t> args) { uint16_t inst[6] = {}; Build35c(inst, code, method_idx, args); - return Instruction::At(inst)->DumpString(nullptr); + return DexInstructionIterator(inst)->DumpString(nullptr); } TEST(Instruction, DumpString) { diff --git a/runtime/dex_method_iterator.h b/runtime/dex_method_iterator.h deleted file mode 100644 index a44bc16287..0000000000 --- a/runtime/dex_method_iterator.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2011 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_DEX_METHOD_ITERATOR_H_ -#define ART_RUNTIME_DEX_METHOD_ITERATOR_H_ - -#include <vector> - -#include "dex_file-inl.h" - -namespace art { - -class DexMethodIterator { - public: - explicit DexMethodIterator(const std::vector<const DexFile*>& dex_files) - : dex_files_(dex_files), - found_next_(false), - dex_file_index_(0), - class_def_index_(0), - class_def_(nullptr), - class_data_(nullptr), - direct_method_(false) { - CHECK_NE(0U, dex_files_.size()); - } - - bool HasNext() { - if (found_next_) { - return true; - } - while (true) { - // End of DexFiles, we are done. - if (dex_file_index_ == dex_files_.size()) { - return false; - } - if (class_def_index_ == GetDexFileInternal().NumClassDefs()) { - // End of this DexFile, advance and retry. - class_def_index_ = 0; - dex_file_index_++; - continue; - } - if (class_def_ == nullptr) { - class_def_ = &GetDexFileInternal().GetClassDef(class_def_index_); - } - if (class_data_ == nullptr) { - class_data_ = GetDexFileInternal().GetClassData(*class_def_); - if (class_data_ == nullptr) { - // empty class, such as a marker interface - // End of this class, advance and retry. - class_def_ = nullptr; - class_def_index_++; - continue; - } - } - if (it_.get() == nullptr) { - it_.reset(new ClassDataItemIterator(GetDexFileInternal(), class_data_)); - GetIterator().SkipAllFields(); - direct_method_ = true; - } - if (direct_method_ && GetIterator().HasNextDirectMethod()) { - // Found method - found_next_ = true; - return true; - } - direct_method_ = false; - if (GetIterator().HasNextVirtualMethod()) { - // Found method - found_next_ = true; - return true; - } - // End of this class, advance and retry. - DCHECK(!GetIterator().HasNext()); - it_.reset(nullptr); - class_data_ = nullptr; - class_def_ = nullptr; - class_def_index_++; - } - } - - void Next() { - found_next_ = false; - if (it_.get() != nullptr) { - // Advance to next method if we currently are looking at a class. - GetIterator().Next(); - } - } - - const DexFile& GetDexFile() { - CHECK(HasNext()); - return GetDexFileInternal(); - } - - uint32_t GetMemberIndex() { - CHECK(HasNext()); - return GetIterator().GetMemberIndex(); - } - - InvokeType GetInvokeType() { - CHECK(HasNext()); - CHECK(class_def_ != nullptr); - return GetIterator().GetMethodInvokeType(*class_def_); - } - - private: - ClassDataItemIterator& GetIterator() const { - CHECK(it_.get() != nullptr); - return *it_.get(); - } - - const DexFile& GetDexFileInternal() const { - CHECK_LT(dex_file_index_, dex_files_.size()); - const DexFile* dex_file = dex_files_[dex_file_index_]; - CHECK(dex_file != nullptr); - return *dex_file; - } - - const std::vector<const DexFile*>& dex_files_; - - bool found_next_; - - uint32_t dex_file_index_; - uint32_t class_def_index_; - const DexFile::ClassDef* class_def_; - const uint8_t* class_data_; - std::unique_ptr<ClassDataItemIterator> it_; - bool direct_method_; -}; - -} // namespace art - -#endif // ART_RUNTIME_DEX_METHOD_ITERATOR_H_ diff --git a/runtime/dex_method_iterator_test.cc b/runtime/dex_method_iterator_test.cc deleted file mode 100644 index e83829bb46..0000000000 --- a/runtime/dex_method_iterator_test.cc +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2011 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 "dex_method_iterator.h" - -#include "base/stl_util.h" -#include "common_runtime_test.h" -#include "oat_file.h" -#include "scoped_thread_state_change-inl.h" -#include "thread-current-inl.h" - -namespace art { - -class DexMethodIteratorTest : public CommonRuntimeTest { -}; - -TEST_F(DexMethodIteratorTest, Basic) { - ScopedObjectAccess soa(Thread::Current()); - std::vector<const DexFile*> dex_files; - CHECK_NE(boot_class_path_.size(), 0U); - for (size_t i = 0; i < boot_class_path_.size(); ++i) { - dex_files.push_back(boot_class_path_[i]); - } - DexMethodIterator it(dex_files); - while (it.HasNext()) { - const DexFile& dex_file = it.GetDexFile(); - InvokeType invoke_type = it.GetInvokeType(); - uint32_t method_idx = it.GetMemberIndex(); - if ((false)) { - LOG(INFO) << invoke_type << " " << dex_file.PrettyMethod(method_idx); - } - it.Next(); - } -} - -} // namespace art diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 211381ccbe..eef277398c 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -1119,7 +1119,7 @@ extern "C" const void* artQuickResolutionTrampoline( const DexFile::CodeItem* code; code = caller->GetCodeItem(); CHECK_LT(dex_pc, code->insns_size_in_code_units_); - const Instruction* instr = Instruction::At(&code->insns_[dex_pc]); + const Instruction* instr = &code->InstructionAt(dex_pc); Instruction::Code instr_code = instr->Opcode(); bool is_range; switch (instr_code) { @@ -2484,7 +2484,7 @@ extern "C" TwoWordReturn artInvokeInterfaceTrampoline(ArtMethod* interface_metho uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp); const DexFile::CodeItem* code_item = caller_method->GetCodeItem(); DCHECK_LT(dex_pc, code_item->insns_size_in_code_units_); - const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]); + const Instruction* instr = &code_item->InstructionAt(dex_pc); Instruction::Code instr_code = instr->Opcode(); DCHECK(instr_code == Instruction::INVOKE_INTERFACE || instr_code == Instruction::INVOKE_INTERFACE_RANGE) @@ -2600,7 +2600,7 @@ extern "C" uintptr_t artInvokePolymorphic( ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp); uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp); const DexFile::CodeItem* code = caller_method->GetCodeItem(); - const Instruction* inst = Instruction::At(&code->insns_[dex_pc]); + const Instruction* inst = &code->InstructionAt(dex_pc); DCHECK(inst->Opcode() == Instruction::INVOKE_POLYMORPHIC || inst->Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE); const DexFile* dex_file = caller_method->GetDexFile(); diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc index cff3ea7ecd..2dd4db3895 100644 --- a/runtime/indirect_reference_table.cc +++ b/runtime/indirect_reference_table.cc @@ -237,7 +237,8 @@ bool IndirectReferenceTable::Resize(size_t new_size, std::string* error_msg) { } IndirectRef IndirectReferenceTable::Add(IRTSegmentState previous_state, - ObjPtr<mirror::Object> obj) { + ObjPtr<mirror::Object> obj, + std::string* error_msg) { if (kDebugIRT) { LOG(INFO) << "+++ Add: previous_state=" << previous_state.top_index << " top_index=" << segment_state_.top_index @@ -253,28 +254,34 @@ IndirectRef IndirectReferenceTable::Add(IRTSegmentState previous_state, if (top_index == max_entries_) { if (resizable_ == ResizableCapacity::kNo) { - LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow " - << "(max=" << max_entries_ << ")\n" - << MutatorLockedDumpable<IndirectReferenceTable>(*this); - UNREACHABLE(); + std::ostringstream oss; + oss << "JNI ERROR (app bug): " << kind_ << " table overflow " + << "(max=" << max_entries_ << ")" + << MutatorLockedDumpable<IndirectReferenceTable>(*this); + *error_msg = oss.str(); + return nullptr; } // Try to double space. if (std::numeric_limits<size_t>::max() / 2 < max_entries_) { - LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow " - << "(max=" << max_entries_ << ")" << std::endl - << MutatorLockedDumpable<IndirectReferenceTable>(*this) - << " Resizing failed: exceeds size_t"; - UNREACHABLE(); + std::ostringstream oss; + oss << "JNI ERROR (app bug): " << kind_ << " table overflow " + << "(max=" << max_entries_ << ")" << std::endl + << MutatorLockedDumpable<IndirectReferenceTable>(*this) + << " Resizing failed: exceeds size_t"; + *error_msg = oss.str(); + return nullptr; } - std::string error_msg; - if (!Resize(max_entries_ * 2, &error_msg)) { - LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow " - << "(max=" << max_entries_ << ")" << std::endl - << MutatorLockedDumpable<IndirectReferenceTable>(*this) - << " Resizing failed: " << error_msg; - UNREACHABLE(); + std::string inner_error_msg; + if (!Resize(max_entries_ * 2, &inner_error_msg)) { + std::ostringstream oss; + oss << "JNI ERROR (app bug): " << kind_ << " table overflow " + << "(max=" << max_entries_ << ")" << std::endl + << MutatorLockedDumpable<IndirectReferenceTable>(*this) + << " Resizing failed: " << inner_error_msg; + *error_msg = oss.str(); + return nullptr; } } diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h index 6d52d959cb..bf287b1ac9 100644 --- a/runtime/indirect_reference_table.h +++ b/runtime/indirect_reference_table.h @@ -244,8 +244,10 @@ class IndirectReferenceTable { bool IsValid() const; // Add a new entry. "obj" must be a valid non-null object reference. This function will - // abort if the table is full (max entries reached, or expansion failed). - IndirectRef Add(IRTSegmentState previous_state, ObjPtr<mirror::Object> obj) + // return null if an error happened (with an appropriate error message set). + IndirectRef Add(IRTSegmentState previous_state, + ObjPtr<mirror::Object> obj, + std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_); // Given an IndirectRef in the table, return the Object it refers to. diff --git a/runtime/indirect_reference_table_test.cc b/runtime/indirect_reference_table_test.cc index 6aefe239a9..92785090f5 100644 --- a/runtime/indirect_reference_table_test.cc +++ b/runtime/indirect_reference_table_test.cc @@ -80,13 +80,13 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { EXPECT_FALSE(irt.Remove(cookie, iref0)) << "unexpectedly successful removal"; // Add three, check, remove in the order in which they were added. - iref0 = irt.Add(cookie, obj0.Get()); + iref0 = irt.Add(cookie, obj0.Get(), &error_msg); EXPECT_TRUE(iref0 != nullptr); CheckDump(&irt, 1, 1); - IndirectRef iref1 = irt.Add(cookie, obj1.Get()); + IndirectRef iref1 = irt.Add(cookie, obj1.Get(), &error_msg); EXPECT_TRUE(iref1 != nullptr); CheckDump(&irt, 2, 2); - IndirectRef iref2 = irt.Add(cookie, obj2.Get()); + IndirectRef iref2 = irt.Add(cookie, obj2.Get(), &error_msg); EXPECT_TRUE(iref2 != nullptr); CheckDump(&irt, 3, 3); @@ -108,11 +108,11 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { EXPECT_TRUE(irt.Get(iref0) == nullptr); // Add three, remove in the opposite order. - iref0 = irt.Add(cookie, obj0.Get()); + iref0 = irt.Add(cookie, obj0.Get(), &error_msg); EXPECT_TRUE(iref0 != nullptr); - iref1 = irt.Add(cookie, obj1.Get()); + iref1 = irt.Add(cookie, obj1.Get(), &error_msg); EXPECT_TRUE(iref1 != nullptr); - iref2 = irt.Add(cookie, obj2.Get()); + iref2 = irt.Add(cookie, obj2.Get(), &error_msg); EXPECT_TRUE(iref2 != nullptr); CheckDump(&irt, 3, 3); @@ -128,11 +128,11 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { // Add three, remove middle / middle / bottom / top. (Second attempt // to remove middle should fail.) - iref0 = irt.Add(cookie, obj0.Get()); + iref0 = irt.Add(cookie, obj0.Get(), &error_msg); EXPECT_TRUE(iref0 != nullptr); - iref1 = irt.Add(cookie, obj1.Get()); + iref1 = irt.Add(cookie, obj1.Get(), &error_msg); EXPECT_TRUE(iref1 != nullptr); - iref2 = irt.Add(cookie, obj2.Get()); + iref2 = irt.Add(cookie, obj2.Get(), &error_msg); EXPECT_TRUE(iref2 != nullptr); CheckDump(&irt, 3, 3); @@ -157,20 +157,20 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { // Add four entries. Remove #1, add new entry, verify that table size // is still 4 (i.e. holes are getting filled). Remove #1 and #3, verify // that we delete one and don't hole-compact the other. - iref0 = irt.Add(cookie, obj0.Get()); + iref0 = irt.Add(cookie, obj0.Get(), &error_msg); EXPECT_TRUE(iref0 != nullptr); - iref1 = irt.Add(cookie, obj1.Get()); + iref1 = irt.Add(cookie, obj1.Get(), &error_msg); EXPECT_TRUE(iref1 != nullptr); - iref2 = irt.Add(cookie, obj2.Get()); + iref2 = irt.Add(cookie, obj2.Get(), &error_msg); EXPECT_TRUE(iref2 != nullptr); - IndirectRef iref3 = irt.Add(cookie, obj3.Get()); + IndirectRef iref3 = irt.Add(cookie, obj3.Get(), &error_msg); EXPECT_TRUE(iref3 != nullptr); CheckDump(&irt, 4, 4); ASSERT_TRUE(irt.Remove(cookie, iref1)); CheckDump(&irt, 3, 3); - iref1 = irt.Add(cookie, obj1.Get()); + iref1 = irt.Add(cookie, obj1.Get(), &error_msg); EXPECT_TRUE(iref1 != nullptr); ASSERT_EQ(4U, irt.Capacity()) << "hole not filled"; @@ -193,12 +193,12 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { // Add an entry, remove it, add a new entry, and try to use the original // iref. They have the same slot number but are for different objects. // With the extended checks in place, this should fail. - iref0 = irt.Add(cookie, obj0.Get()); + iref0 = irt.Add(cookie, obj0.Get(), &error_msg); EXPECT_TRUE(iref0 != nullptr); CheckDump(&irt, 1, 1); ASSERT_TRUE(irt.Remove(cookie, iref0)); CheckDump(&irt, 0, 0); - iref1 = irt.Add(cookie, obj1.Get()); + iref1 = irt.Add(cookie, obj1.Get(), &error_msg); EXPECT_TRUE(iref1 != nullptr); CheckDump(&irt, 1, 1); ASSERT_FALSE(irt.Remove(cookie, iref0)) << "mismatched del succeeded"; @@ -209,12 +209,12 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { // Same as above, but with the same object. A more rigorous checker // (e.g. with slot serialization) will catch this. - iref0 = irt.Add(cookie, obj0.Get()); + iref0 = irt.Add(cookie, obj0.Get(), &error_msg); EXPECT_TRUE(iref0 != nullptr); CheckDump(&irt, 1, 1); ASSERT_TRUE(irt.Remove(cookie, iref0)); CheckDump(&irt, 0, 0); - iref1 = irt.Add(cookie, obj0.Get()); + iref1 = irt.Add(cookie, obj0.Get(), &error_msg); EXPECT_TRUE(iref1 != nullptr); CheckDump(&irt, 1, 1); if (iref0 != iref1) { @@ -229,7 +229,7 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { ASSERT_TRUE(irt.Get(nullptr) == nullptr); // Stale lookup. - iref0 = irt.Add(cookie, obj0.Get()); + iref0 = irt.Add(cookie, obj0.Get(), &error_msg); EXPECT_TRUE(iref0 != nullptr); CheckDump(&irt, 1, 1); ASSERT_TRUE(irt.Remove(cookie, iref0)); @@ -241,12 +241,12 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { static const size_t kTableInitial = kTableMax / 2; IndirectRef manyRefs[kTableInitial]; for (size_t i = 0; i < kTableInitial; i++) { - manyRefs[i] = irt.Add(cookie, obj0.Get()); + manyRefs[i] = irt.Add(cookie, obj0.Get(), &error_msg); ASSERT_TRUE(manyRefs[i] != nullptr) << "Failed adding " << i; CheckDump(&irt, i + 1, 1); } // ...this one causes overflow. - iref0 = irt.Add(cookie, obj0.Get()); + iref0 = irt.Add(cookie, obj0.Get(), &error_msg); ASSERT_TRUE(iref0 != nullptr); ASSERT_EQ(kTableInitial + 1, irt.Capacity()); CheckDump(&irt, kTableInitial + 1, 1); @@ -306,16 +306,16 @@ TEST_F(IndirectReferenceTableTest, Holes) { CheckDump(&irt, 0, 0); - IndirectRef iref0 = irt.Add(cookie0, obj0.Get()); - IndirectRef iref1 = irt.Add(cookie0, obj1.Get()); - IndirectRef iref2 = irt.Add(cookie0, obj2.Get()); + IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg); + IndirectRef iref1 = irt.Add(cookie0, obj1.Get(), &error_msg); + IndirectRef iref2 = irt.Add(cookie0, obj2.Get(), &error_msg); EXPECT_TRUE(irt.Remove(cookie0, iref1)); // New segment. const IRTSegmentState cookie1 = irt.GetSegmentState(); - IndirectRef iref3 = irt.Add(cookie1, obj3.Get()); + IndirectRef iref3 = irt.Add(cookie1, obj3.Get(), &error_msg); // Must not have filled the previous hole. EXPECT_EQ(irt.Capacity(), 4u); @@ -337,21 +337,21 @@ TEST_F(IndirectReferenceTableTest, Holes) { CheckDump(&irt, 0, 0); - IndirectRef iref0 = irt.Add(cookie0, obj0.Get()); + IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg); // New segment. const IRTSegmentState cookie1 = irt.GetSegmentState(); - IndirectRef iref1 = irt.Add(cookie1, obj1.Get()); - IndirectRef iref2 = irt.Add(cookie1, obj2.Get()); - IndirectRef iref3 = irt.Add(cookie1, obj3.Get()); + IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg); + IndirectRef iref2 = irt.Add(cookie1, obj2.Get(), &error_msg); + IndirectRef iref3 = irt.Add(cookie1, obj3.Get(), &error_msg); EXPECT_TRUE(irt.Remove(cookie1, iref2)); // Pop segment. irt.SetSegmentState(cookie1); - IndirectRef iref4 = irt.Add(cookie1, obj4.Get()); + IndirectRef iref4 = irt.Add(cookie1, obj4.Get(), &error_msg); EXPECT_EQ(irt.Capacity(), 2u); EXPECT_TRUE(irt.Get(iref2) == nullptr); @@ -373,25 +373,25 @@ TEST_F(IndirectReferenceTableTest, Holes) { CheckDump(&irt, 0, 0); - IndirectRef iref0 = irt.Add(cookie0, obj0.Get()); + IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg); // New segment. const IRTSegmentState cookie1 = irt.GetSegmentState(); - IndirectRef iref1 = irt.Add(cookie1, obj1.Get()); - IndirectRef iref2 = irt.Add(cookie1, obj2.Get()); + IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg); + IndirectRef iref2 = irt.Add(cookie1, obj2.Get(), &error_msg); EXPECT_TRUE(irt.Remove(cookie1, iref1)); // New segment. const IRTSegmentState cookie2 = irt.GetSegmentState(); - IndirectRef iref3 = irt.Add(cookie2, obj3.Get()); + IndirectRef iref3 = irt.Add(cookie2, obj3.Get(), &error_msg); // Pop segment. irt.SetSegmentState(cookie2); - IndirectRef iref4 = irt.Add(cookie1, obj4.Get()); + IndirectRef iref4 = irt.Add(cookie1, obj4.Get(), &error_msg); EXPECT_EQ(irt.Capacity(), 3u); EXPECT_TRUE(irt.Get(iref1) == nullptr); @@ -412,20 +412,20 @@ TEST_F(IndirectReferenceTableTest, Holes) { CheckDump(&irt, 0, 0); - IndirectRef iref0 = irt.Add(cookie0, obj0.Get()); + IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg); // New segment. const IRTSegmentState cookie1 = irt.GetSegmentState(); - IndirectRef iref1 = irt.Add(cookie1, obj1.Get()); + IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg); EXPECT_TRUE(irt.Remove(cookie1, iref1)); // Emptied segment, push new one. const IRTSegmentState cookie2 = irt.GetSegmentState(); - IndirectRef iref2 = irt.Add(cookie1, obj1.Get()); - IndirectRef iref3 = irt.Add(cookie1, obj2.Get()); - IndirectRef iref4 = irt.Add(cookie1, obj3.Get()); + IndirectRef iref2 = irt.Add(cookie1, obj1.Get(), &error_msg); + IndirectRef iref3 = irt.Add(cookie1, obj2.Get(), &error_msg); + IndirectRef iref4 = irt.Add(cookie1, obj3.Get(), &error_msg); EXPECT_TRUE(irt.Remove(cookie1, iref3)); @@ -433,7 +433,7 @@ TEST_F(IndirectReferenceTableTest, Holes) { UNUSED(cookie2); irt.SetSegmentState(cookie1); - IndirectRef iref5 = irt.Add(cookie1, obj4.Get()); + IndirectRef iref5 = irt.Add(cookie1, obj4.Get(), &error_msg); EXPECT_EQ(irt.Capacity(), 2u); EXPECT_TRUE(irt.Get(iref3) == nullptr); @@ -455,14 +455,14 @@ TEST_F(IndirectReferenceTableTest, Holes) { CheckDump(&irt, 0, 0); - IndirectRef iref0 = irt.Add(cookie0, obj0.Get()); + IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg); // New segment. const IRTSegmentState cookie1 = irt.GetSegmentState(); - IndirectRef iref1 = irt.Add(cookie1, obj1.Get()); - IndirectRef iref2 = irt.Add(cookie1, obj1.Get()); - IndirectRef iref3 = irt.Add(cookie1, obj2.Get()); + IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg); + IndirectRef iref2 = irt.Add(cookie1, obj1.Get(), &error_msg); + IndirectRef iref3 = irt.Add(cookie1, obj2.Get(), &error_msg); EXPECT_TRUE(irt.Remove(cookie1, iref2)); @@ -473,7 +473,7 @@ TEST_F(IndirectReferenceTableTest, Holes) { const IRTSegmentState cookie1_second = irt.GetSegmentState(); UNUSED(cookie1_second); - IndirectRef iref4 = irt.Add(cookie1, obj3.Get()); + IndirectRef iref4 = irt.Add(cookie1, obj3.Get(), &error_msg); EXPECT_EQ(irt.Capacity(), 2u); EXPECT_TRUE(irt.Get(iref3) == nullptr); @@ -504,7 +504,7 @@ TEST_F(IndirectReferenceTableTest, Resize) { const IRTSegmentState cookie = kIRTFirstSegment; for (size_t i = 0; i != kTableMax + 1; ++i) { - irt.Add(cookie, obj0.Get()); + irt.Add(cookie, obj0.Get(), &error_msg); } EXPECT_EQ(irt.Capacity(), kTableMax + 1); diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc index 71ab01e0fc..fb378251ad 100644 --- a/runtime/interpreter/unstarted_runtime_test.cc +++ b/runtime/interpreter/unstarted_runtime_test.cc @@ -393,7 +393,7 @@ TEST_F(UnstartedRuntimeTest, StringInit) { // create instruction data for invoke-direct {v0, v1} of method with fake index uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 }; - const Instruction* inst = Instruction::At(inst_data); + DexInstructionIterator inst(inst_data); JValue result; ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, method, 0); @@ -403,7 +403,7 @@ TEST_F(UnstartedRuntimeTest, StringInit) { shadow_frame->SetVRegReference(0, reference_empty_string); shadow_frame->SetVRegReference(1, string_arg); - interpreter::DoCall<false, false>(method, self, *shadow_frame, inst, inst_data[0], &result); + interpreter::DoCall<false, false>(method, self, *shadow_frame, &*inst, inst_data[0], &result); mirror::String* string_result = reinterpret_cast<mirror::String*>(result.GetL()); EXPECT_EQ(string_arg->GetLength(), string_result->GetLength()); @@ -1027,12 +1027,12 @@ TEST_F(UnstartedRuntimeTest, FloatConversion) { // create instruction data for invoke-direct {v0, v1} of method with fake index uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 }; - const Instruction* inst = Instruction::At(inst_data); + DexInstructionIterator inst(inst_data); JValue result; ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, method, 0); shadow_frame->SetVRegDouble(0, 1.23); - interpreter::DoCall<false, false>(method, self, *shadow_frame, inst, inst_data[0], &result); + interpreter::DoCall<false, false>(method, self, *shadow_frame, &*inst, inst_data[0], &result); ObjPtr<mirror::String> string_result = reinterpret_cast<mirror::String*>(result.GetL()); ASSERT_TRUE(string_result != nullptr); @@ -1187,12 +1187,12 @@ class UnstartedClassForNameTest : public UnstartedRuntimeTest { // create instruction data for invoke-direct {v0} of method with fake index uint16_t inst_data[3] = { 0x1070, 0x0000, 0x0010 }; - const Instruction* inst = Instruction::At(inst_data); + DexInstructionIterator inst(inst_data); interpreter::DoCall<false, false>(boot_cp_init, self, *shadow_frame, - inst, + &*inst, inst_data[0], &result); CHECK(!self->IsExceptionPending()); diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index 1593577625..5a1605323e 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -35,6 +35,7 @@ #include "mirror/class_loader.h" #include "nativebridge/native_bridge.h" #include "nativehelper/ScopedLocalRef.h" +#include "nativehelper/ScopedUtfChars.h" #include "nativeloader/native_loader.h" #include "object_callbacks.h" #include "parsed_options.h" @@ -588,7 +589,12 @@ jobject JavaVMExt::AddGlobalRef(Thread* self, ObjPtr<mirror::Object> obj) { return nullptr; } WriterMutexLock mu(self, *Locks::jni_globals_lock_); - IndirectRef ref = globals_.Add(kIRTFirstSegment, obj); + std::string error_msg; + IndirectRef ref = globals_.Add(kIRTFirstSegment, obj, &error_msg); + if (UNLIKELY(ref == nullptr)) { + LOG(FATAL) << error_msg; + UNREACHABLE(); + } return reinterpret_cast<jobject>(ref); } @@ -606,7 +612,12 @@ jweak JavaVMExt::AddWeakGlobalRef(Thread* self, ObjPtr<mirror::Object> obj) { self->CheckEmptyCheckpointFromWeakRefAccess(Locks::jni_weak_globals_lock_); weak_globals_add_condition_.WaitHoldingLocks(self); } - IndirectRef ref = weak_globals_.Add(kIRTFirstSegment, obj); + std::string error_msg; + IndirectRef ref = weak_globals_.Add(kIRTFirstSegment, obj, &error_msg); + if (UNLIKELY(ref == nullptr)) { + LOG(FATAL) << error_msg; + UNREACHABLE(); + } return reinterpret_cast<jweak>(ref); } @@ -833,9 +844,42 @@ bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, // The library will be associated with class_loader. The JNI // spec says we can't load the same library into more than one // class loader. + // + // This isn't very common. So spend some time to get a readable message. + auto call_to_string = [&](jobject obj) -> std::string { + if (obj == nullptr) { + return "null"; + } + // Handle jweaks. Ignore double local-ref. + ScopedLocalRef<jobject> local_ref(env, env->NewLocalRef(obj)); + if (local_ref != nullptr) { + ScopedLocalRef<jclass> local_class(env, env->GetObjectClass(local_ref.get())); + jmethodID to_string = env->GetMethodID(local_class.get(), + "toString", + "()Ljava/lang/String;"); + DCHECK(to_string != nullptr); + ScopedLocalRef<jobject> local_string(env, + env->CallObjectMethod(local_ref.get(), to_string)); + if (local_string != nullptr) { + ScopedUtfChars utf(env, reinterpret_cast<jstring>(local_string.get())); + if (utf.c_str() != nullptr) { + return utf.c_str(); + } + } + env->ExceptionClear(); + return "(Error calling toString)"; + } + return "null"; + }; + std::string old_class_loader = call_to_string(library->GetClassLoader()); + std::string new_class_loader = call_to_string(class_loader); StringAppendF(error_msg, "Shared library \"%s\" already opened by " - "ClassLoader %p; can't open in ClassLoader %p", - path.c_str(), library->GetClassLoader(), class_loader); + "ClassLoader %p(%s); can't open in ClassLoader %p(%s)", + path.c_str(), + library->GetClassLoader(), + old_class_loader.c_str(), + class_loader, + new_class_loader.c_str()); LOG(WARNING) << *error_msg; return false; } diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc index 12fa49ea79..1ed7889998 100644 --- a/runtime/jit/profile_compilation_info.cc +++ b/runtime/jit/profile_compilation_info.cc @@ -1053,6 +1053,98 @@ bool ProfileCompilationInfo::Load(int fd, bool merge_classes) { } } +bool ProfileCompilationInfo::VerifyProfileData(const std::vector<const DexFile*>& dex_files) { + std::unordered_map<std::string, const DexFile*> key_to_dex_file; + for (const DexFile* dex_file : dex_files) { + key_to_dex_file.emplace(GetProfileDexFileKey(dex_file->GetLocation()), dex_file); + } + for (const DexFileData* dex_data : info_) { + const auto it = key_to_dex_file.find(dex_data->profile_key); + if (it == key_to_dex_file.end()) { + // It is okay if profile contains data for additional dex files. + continue; + } + const DexFile* dex_file = it->second; + const std::string& dex_location = dex_file->GetLocation(); + if (!ChecksumMatch(dex_data->checksum, dex_file->GetLocationChecksum())) { + LOG(ERROR) << "Dex checksum mismatch while verifying profile " + << "dex location " << dex_location << " (checksum=" + << dex_file->GetLocationChecksum() << ", profile checksum=" + << dex_data->checksum; + return false; + } + + if (dex_data->num_method_ids != dex_file->NumMethodIds()) { + LOG(ERROR) << "Number of method ids in dex file and profile don't match." + << "dex location " << dex_location << " NumMethodId in DexFile" + << dex_file->NumMethodIds() << ", NumMethodId in profile" + << dex_data->num_method_ids; + return false; + } + + // Verify method_encoding. + for (const auto& method_it : dex_data->method_map) { + size_t method_id = (size_t)(method_it.first); + if (method_id >= dex_file->NumMethodIds()) { + LOG(ERROR) << "Invalid method id in profile file. dex location=" + << dex_location << " method_id=" << method_id << " NumMethodIds=" + << dex_file->NumMethodIds(); + return false; + } + + // Verify class indices of inline caches. + const InlineCacheMap &inline_cache_map = method_it.second; + for (const auto& inline_cache_it : inline_cache_map) { + const DexPcData dex_pc_data = inline_cache_it.second; + if (dex_pc_data.is_missing_types || dex_pc_data.is_megamorphic) { + // No class indices to verify. + continue; + } + + const ClassSet &classes = dex_pc_data.classes; + SafeMap<uint8_t, std::vector<dex::TypeIndex>> dex_to_classes_map; + // Group the classes by dex. We expect that most of the classes will come from + // the same dex, so this will be more efficient than encoding the dex index + // for each class reference. + GroupClassesByDex(classes, &dex_to_classes_map); + for (const auto &dex_it : dex_to_classes_map) { + uint8_t dex_profile_index = dex_it.first; + const auto dex_file_inline_cache_it = key_to_dex_file.find( + info_[dex_profile_index]->profile_key); + if (dex_file_inline_cache_it == key_to_dex_file.end()) { + // It is okay if profile contains data for additional dex files. + continue; + } + const DexFile *dex_file_for_inline_cache_check = dex_file_inline_cache_it->second; + const std::vector<dex::TypeIndex> &dex_classes = dex_it.second; + for (size_t i = 0; i < dex_classes.size(); i++) { + if (dex_classes[i].index_ >= dex_file_for_inline_cache_check->NumTypeIds()) { + LOG(ERROR) << "Invalid inline cache in profile file. dex location=" + << dex_location << " method_id=" << method_id + << " dex_profile_index=" + << static_cast<uint16_t >(dex_profile_index) << " type_index=" + << dex_classes[i].index_ + << " NumTypeIds=" + << dex_file_for_inline_cache_check->NumTypeIds(); + return false; + } + } + } + } + } + // Verify class_ids. + for (const auto& class_id : dex_data->class_set) { + if (class_id.index_ >= dex_file->NumTypeIds()) { + LOG(ERROR) << "Invalid class id in profile file. dex_file location " + << dex_location << " class_id=" << class_id.index_ << " NumClassIds=" + << dex_file->NumClassDefs(); + return false; + } + } + } + return true; +} + // TODO(calin): fail fast if the dex checksums don't match. ProfileCompilationInfo::ProfileLoadSatus ProfileCompilationInfo::LoadInternal( int fd, std::string* error, bool merge_classes) { diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h index 009554c7ca..09de29e394 100644 --- a/runtime/jit/profile_compilation_info.h +++ b/runtime/jit/profile_compilation_info.h @@ -305,6 +305,15 @@ class ProfileCompilationInfo { // If merge_classes is set to false, classes will not be merged/loaded. bool Load(int fd, bool merge_classes = true); + // Verify integrity of the profile file with the provided dex files. + // If there exists a DexData object which maps to a dex_file, then it verifies that: + // - The checksums of the DexData and dex_file are equals. + // - No method id exceeds NumMethodIds corresponding to the dex_file. + // - No class id exceeds NumTypeIds corresponding to the dex_file. + // - For every inline_caches, class_ids does not exceed NumTypeIds corresponding to + // the dex_file they are in. + bool VerifyProfileData(const std::vector<const DexFile *> &dex_files); + // Load profile information from the given file // If the current profile is non-empty the load will fail. // If clear_if_invalid is true and the file is invalid the method clears the diff --git a/runtime/jit/profiling_info.cc b/runtime/jit/profiling_info.cc index 1bd095a88e..ad013244c3 100644 --- a/runtime/jit/profiling_info.cc +++ b/runtime/jit/profiling_info.cc @@ -43,15 +43,12 @@ bool ProfilingInfo::Create(Thread* self, ArtMethod* method, bool retry_allocatio // instructions we are interested in profiling. DCHECK(!method->IsNative()); - const DexFile::CodeItem& code_item = *method->GetCodeItem(); - const uint16_t* code_ptr = code_item.insns_; - const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_; - - uint32_t dex_pc = 0; std::vector<uint32_t> entries; - while (code_ptr < code_end) { - const Instruction& instruction = *Instruction::At(code_ptr); - switch (instruction.Opcode()) { + + IterationRange<DexInstructionIterator> instructions = method->GetCodeItem()->Instructions(); + for (auto inst = instructions.begin(); inst != instructions.end(); ++inst) { + const uint32_t dex_pc = inst.GetDexPC(instructions.begin()); + switch (inst->Opcode()) { case Instruction::INVOKE_VIRTUAL: case Instruction::INVOKE_VIRTUAL_RANGE: case Instruction::INVOKE_VIRTUAL_QUICK: @@ -64,8 +61,6 @@ bool ProfilingInfo::Create(Thread* self, ArtMethod* method, bool retry_allocatio default: break; } - dex_pc += instruction.SizeInCodeUnits(); - code_ptr += instruction.SizeInCodeUnits(); } // We always create a `ProfilingInfo` object, even if there is no instruction we are diff --git a/runtime/jni_env_ext-inl.h b/runtime/jni_env_ext-inl.h index 25893b7eda..d66df081c6 100644 --- a/runtime/jni_env_ext-inl.h +++ b/runtime/jni_env_ext-inl.h @@ -25,7 +25,13 @@ namespace art { template<typename T> inline T JNIEnvExt::AddLocalReference(ObjPtr<mirror::Object> obj) { - IndirectRef ref = locals.Add(local_ref_cookie, obj); + std::string error_msg; + IndirectRef ref = locals.Add(local_ref_cookie, obj, &error_msg); + if (UNLIKELY(ref == nullptr)) { + // This is really unexpected if we allow resizing local IRTs... + LOG(FATAL) << error_msg; + UNREACHABLE(); + } // TODO: fix this to understand PushLocalFrame, so we can turn it on. if (false) { diff --git a/runtime/jni_env_ext.cc b/runtime/jni_env_ext.cc index 3ff94f995d..8352657f28 100644 --- a/runtime/jni_env_ext.cc +++ b/runtime/jni_env_ext.cc @@ -99,7 +99,14 @@ jobject JNIEnvExt::NewLocalRef(mirror::Object* obj) { if (obj == nullptr) { return nullptr; } - return reinterpret_cast<jobject>(locals.Add(local_ref_cookie, obj)); + std::string error_msg; + jobject ref = reinterpret_cast<jobject>(locals.Add(local_ref_cookie, obj, &error_msg)); + if (UNLIKELY(ref == nullptr)) { + // This is really unexpected if we allow resizing local IRTs... + LOG(FATAL) << error_msg; + UNREACHABLE(); + } + return ref; } void JNIEnvExt::DeleteLocalRef(jobject obj) { diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 77a5b559e3..78f6b25649 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -128,7 +128,8 @@ inline ArraySlice<ArtMethod> Class::GetDirectMethodsSlice(PointerSize pointer_si } inline ArraySlice<ArtMethod> Class::GetDirectMethodsSliceUnchecked(PointerSize pointer_size) { - return GetMethodsSliceRangeUnchecked(pointer_size, + return GetMethodsSliceRangeUnchecked(GetMethodsPtr(), + pointer_size, GetDirectMethodsStartOffset(), GetVirtualMethodsStartOffset()); } @@ -140,7 +141,8 @@ inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSlice(PointerSize pointer_ } inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSliceUnchecked(PointerSize pointer_size) { - return GetMethodsSliceRangeUnchecked(pointer_size, + return GetMethodsSliceRangeUnchecked(GetMethodsPtr(), + pointer_size, GetDirectMethodsStartOffset(), GetCopiedMethodsStartOffset()); } @@ -152,7 +154,8 @@ inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSlice(PointerSize p inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSliceUnchecked( PointerSize pointer_size) { - return GetMethodsSliceRangeUnchecked(pointer_size, + return GetMethodsSliceRangeUnchecked(GetMethodsPtr(), + pointer_size, GetVirtualMethodsStartOffset(), GetCopiedMethodsStartOffset()); } @@ -164,9 +167,11 @@ inline ArraySlice<ArtMethod> Class::GetVirtualMethodsSlice(PointerSize pointer_s } inline ArraySlice<ArtMethod> Class::GetVirtualMethodsSliceUnchecked(PointerSize pointer_size) { - return GetMethodsSliceRangeUnchecked(pointer_size, + LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); + return GetMethodsSliceRangeUnchecked(methods, + pointer_size, GetVirtualMethodsStartOffset(), - NumMethods()); + NumMethods(methods)); } template<VerifyObjectFlags kVerifyFlags> @@ -176,7 +181,11 @@ inline ArraySlice<ArtMethod> Class::GetCopiedMethodsSlice(PointerSize pointer_si } inline ArraySlice<ArtMethod> Class::GetCopiedMethodsSliceUnchecked(PointerSize pointer_size) { - return GetMethodsSliceRangeUnchecked(pointer_size, GetCopiedMethodsStartOffset(), NumMethods()); + LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); + return GetMethodsSliceRangeUnchecked(methods, + pointer_size, + GetCopiedMethodsStartOffset(), + NumMethods(methods)); } inline LengthPrefixedArray<ArtMethod>* Class::GetMethodsPtr() { @@ -187,19 +196,21 @@ inline LengthPrefixedArray<ArtMethod>* Class::GetMethodsPtr() { template<VerifyObjectFlags kVerifyFlags> inline ArraySlice<ArtMethod> Class::GetMethodsSlice(PointerSize pointer_size) { DCHECK(IsLoaded() || IsErroneous()); - return GetMethodsSliceRangeUnchecked(pointer_size, 0, NumMethods()); + LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); + return GetMethodsSliceRangeUnchecked(methods, pointer_size, 0, NumMethods(methods)); } -inline ArraySlice<ArtMethod> Class::GetMethodsSliceRangeUnchecked(PointerSize pointer_size, - uint32_t start_offset, - uint32_t end_offset) { +inline ArraySlice<ArtMethod> Class::GetMethodsSliceRangeUnchecked( + LengthPrefixedArray<ArtMethod>* methods, + PointerSize pointer_size, + uint32_t start_offset, + uint32_t end_offset) { DCHECK_LE(start_offset, end_offset); - DCHECK_LE(end_offset, NumMethods()); + DCHECK_LE(end_offset, NumMethods(methods)); uint32_t size = end_offset - start_offset; if (size == 0u) { return ArraySlice<ArtMethod>(); } - LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); DCHECK(methods != nullptr); DCHECK_LE(end_offset, methods->size()); size_t method_size = ArtMethod::Size(pointer_size); @@ -211,7 +222,10 @@ inline ArraySlice<ArtMethod> Class::GetMethodsSliceRangeUnchecked(PointerSize po } inline uint32_t Class::NumMethods() { - LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); + return NumMethods(GetMethodsPtr()); +} + +inline uint32_t Class::NumMethods(LengthPrefixedArray<ArtMethod>* methods) { return (methods == nullptr) ? 0 : methods->size(); } @@ -969,7 +983,8 @@ inline ArraySlice<ArtMethod> Class::GetCopiedMethods(PointerSize pointer_size) { inline ArraySlice<ArtMethod> Class::GetMethods(PointerSize pointer_size) { CheckPointerSize(pointer_size); - return GetMethodsSliceRangeUnchecked(pointer_size, 0u, NumMethods()); + LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); + return GetMethodsSliceRangeUnchecked(methods, pointer_size, 0u, NumMethods(methods)); } inline IterationRange<StrideIterator<ArtField>> Class::GetIFields() { diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index c44b6160ad..148273be98 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -773,6 +773,8 @@ class MANAGED Class FINAL : public Object { ALWAYS_INLINE uint32_t NumDeclaredVirtualMethods() REQUIRES_SHARED(Locks::mutator_lock_); ALWAYS_INLINE uint32_t NumMethods() REQUIRES_SHARED(Locks::mutator_lock_); + static ALWAYS_INLINE uint32_t NumMethods(LengthPrefixedArray<ArtMethod>* methods) + REQUIRES_SHARED(Locks::mutator_lock_); template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> ArtMethod* GetVirtualMethod(size_t i, PointerSize pointer_size) @@ -1294,9 +1296,11 @@ class MANAGED Class FINAL : public Object { ALWAYS_INLINE void SetMethodsPtrInternal(LengthPrefixedArray<ArtMethod>* new_methods) REQUIRES_SHARED(Locks::mutator_lock_); - ALWAYS_INLINE ArraySlice<ArtMethod> GetMethodsSliceRangeUnchecked(PointerSize pointer_size, - uint32_t start_offset, - uint32_t end_offset) + ALWAYS_INLINE static ArraySlice<ArtMethod> GetMethodsSliceRangeUnchecked( + LengthPrefixedArray<ArtMethod>* methods, + PointerSize pointer_size, + uint32_t start_offset, + uint32_t end_offset) REQUIRES_SHARED(Locks::mutator_lock_); template <bool throw_on_failure> diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 83a8e096e4..f3a0725f79 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -645,6 +645,30 @@ static bool PrepareOdexDirectories(const std::string& dex_location, return true; } +class Dex2oatFileWrapper { + public: + explicit Dex2oatFileWrapper(File* file) + : file_(file), + unlink_file_at_destruction_(true) { + } + + ~Dex2oatFileWrapper() { + if (unlink_file_at_destruction_ && (file_ != nullptr)) { + file_->Erase(/*unlink*/ true); + } + } + + File* GetFile() { return file_.get(); } + + void DisableUnlinkAtDestruction() { + unlink_file_at_destruction_ = false; + }; + + private: + std::unique_ptr<File> file_; + bool unlink_file_at_destruction_; +}; + OatFileAssistant::ResultOfAttemptToUpdate OatFileAssistant::GenerateOatFileNoChecks( OatFileAssistant::OatFileInfo& info, CompilerFilter::Filter filter, @@ -690,8 +714,9 @@ OatFileAssistant::ResultOfAttemptToUpdate OatFileAssistant::GenerateOatFileNoChe (dex_path_stat.st_mode & S_IRGRP) | (dex_path_stat.st_mode & S_IROTH); - std::unique_ptr<File> vdex_file(OS::CreateEmptyFile(vdex_file_name.c_str())); - if (vdex_file.get() == nullptr) { + Dex2oatFileWrapper vdex_file_wrapper(OS::CreateEmptyFile(vdex_file_name.c_str())); + File* vdex_file = vdex_file_wrapper.GetFile(); + if (vdex_file == nullptr) { *error_msg = "Generation of oat file " + oat_file_name + " not attempted because the vdex file " + vdex_file_name + " could not be opened."; @@ -705,8 +730,9 @@ OatFileAssistant::ResultOfAttemptToUpdate OatFileAssistant::GenerateOatFileNoChe return kUpdateNotAttempted; } - std::unique_ptr<File> oat_file(OS::CreateEmptyFile(oat_file_name.c_str())); - if (oat_file.get() == nullptr) { + Dex2oatFileWrapper oat_file_wrapper(OS::CreateEmptyFile(oat_file_name.c_str())); + File* oat_file = oat_file_wrapper.GetFile(); + if (oat_file == nullptr) { *error_msg = "Generation of oat file " + oat_file_name + " not attempted because the oat file could not be created."; return kUpdateNotAttempted; @@ -715,7 +741,6 @@ OatFileAssistant::ResultOfAttemptToUpdate OatFileAssistant::GenerateOatFileNoChe if (fchmod(oat_file->Fd(), file_mode) != 0) { *error_msg = "Generation of oat file " + oat_file_name + " not attempted because the oat file could not be made world readable."; - oat_file->Erase(); return kUpdateNotAttempted; } @@ -731,29 +756,25 @@ OatFileAssistant::ResultOfAttemptToUpdate OatFileAssistant::GenerateOatFileNoChe args.push_back("--class-loader-context=" + dex2oat_context); if (!Dex2Oat(args, error_msg)) { - // Manually delete the oat and vdex files. This ensures there is no garbage - // left over if the process unexpectedly died. - vdex_file->Erase(); - unlink(vdex_file_name.c_str()); - oat_file->Erase(); - unlink(oat_file_name.c_str()); return kUpdateFailed; } if (vdex_file->FlushCloseOrErase() != 0) { *error_msg = "Unable to close vdex file " + vdex_file_name; - unlink(vdex_file_name.c_str()); return kUpdateFailed; } if (oat_file->FlushCloseOrErase() != 0) { *error_msg = "Unable to close oat file " + oat_file_name; - unlink(oat_file_name.c_str()); return kUpdateFailed; } // Mark that the odex file has changed and we should try to reload. info.Reset(); + // We have compiled successfully. Disable the auto-unlink. + vdex_file_wrapper.DisableUnlinkAtDestruction(); + oat_file_wrapper.DisableUnlinkAtDestruction(); + return kUpdateSucceeded; } diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc index 05b63d285a..7cabae55e4 100644 --- a/runtime/oat_file_manager.cc +++ b/runtime/oat_file_manager.cc @@ -54,7 +54,8 @@ static constexpr bool kEnableAppImage = true; static bool OatFileIsOnSystem(const std::unique_ptr<const OatFile>& oat_file) { UniqueCPtr<const char[]> path(realpath(oat_file->GetLocation().c_str(), nullptr)); - return path != nullptr && android::base::StartsWith(oat_file->GetLocation(), GetAndroidRoot()); + return path != nullptr && android::base::StartsWith(oat_file->GetLocation(), + GetAndroidRoot().c_str()); } const OatFile* OatFileManager::RegisterOatFile(std::unique_ptr<const OatFile> oat_file) { diff --git a/runtime/primitive.cc b/runtime/primitive.cc index 1ec345a359..6f3571c78c 100644 --- a/runtime/primitive.cc +++ b/runtime/primitive.cc @@ -60,9 +60,9 @@ const char* Primitive::BoxedDescriptor(Primitive::Type type) { return kBoxedDescriptors[type]; } -std::ostream& operator<<(std::ostream& os, const Primitive::Type& type) { - int32_t int_type = static_cast<int32_t>(type); - if (type >= Primitive::kPrimNot && type <= Primitive::kPrimVoid) { +std::ostream& operator<<(std::ostream& os, Primitive::Type type) { + uint32_t int_type = static_cast<uint32_t>(type); + if (type <= Primitive::kPrimLast) { os << kTypeNames[int_type]; } else { os << "Type[" << int_type << "]"; diff --git a/runtime/primitive.h b/runtime/primitive.h index a0edaee6fe..a429914d5c 100644 --- a/runtime/primitive.h +++ b/runtime/primitive.h @@ -49,7 +49,7 @@ class Primitive { kPrimLast = kPrimVoid }; - static Type GetType(char type) { + static constexpr Type GetType(char type) { switch (type) { case 'B': return kPrimByte; @@ -74,7 +74,7 @@ class Primitive { } } - static size_t ComponentSizeShift(Type type) { + static constexpr size_t ComponentSizeShift(Type type) { switch (type) { case kPrimVoid: case kPrimBoolean: @@ -86,13 +86,12 @@ class Primitive { case kPrimLong: case kPrimDouble: return 3; case kPrimNot: return ComponentSizeShiftWidth(kObjectReferenceSize); - default: - LOG(FATAL) << "Invalid type " << static_cast<int>(type); - return 0; } + LOG(FATAL) << "Invalid type " << static_cast<int>(type); + UNREACHABLE(); } - static size_t ComponentSize(Type type) { + static constexpr size_t ComponentSize(Type type) { switch (type) { case kPrimVoid: return 0; case kPrimBoolean: @@ -104,10 +103,9 @@ class Primitive { case kPrimLong: case kPrimDouble: return 8; case kPrimNot: return kObjectReferenceSize; - default: - LOG(FATAL) << "Invalid type " << static_cast<int>(type); - return 0; } + LOG(FATAL) << "Invalid type " << static_cast<int>(type); + UNREACHABLE(); } static const char* Descriptor(Type type) { @@ -141,26 +139,6 @@ class Primitive { // Returns the descriptor corresponding to the boxed type of |type|. static const char* BoxedDescriptor(Type type); - static bool IsFloatingPointType(Type type) { - return type == kPrimFloat || type == kPrimDouble; - } - - static bool IsIntegralType(Type type) { - // The Java language does not allow treating boolean as an integral type but - // our bit representation makes it safe. - switch (type) { - case kPrimBoolean: - case kPrimByte: - case kPrimChar: - case kPrimShort: - case kPrimInt: - case kPrimLong: - return true; - default: - return false; - } - } - // Return true if |type| is an numeric type. static constexpr bool IsNumericType(Type type) { switch (type) { @@ -175,6 +153,8 @@ class Primitive { case Primitive::Type::kPrimDouble: return true; case Primitive::Type::kPrimVoid: return false; } + LOG(FATAL) << "Invalid type " << static_cast<int>(type); + UNREACHABLE(); } // Returns true if it is possible to widen type |from| to type |to|. Both |from| and @@ -190,73 +170,15 @@ class Primitive { return IsNumericType(from) && IsNumericType(to) && from <= to; } - static bool IsIntOrLongType(Type type) { - return type == kPrimInt || type == kPrimLong; - } - static bool Is64BitType(Type type) { return type == kPrimLong || type == kPrimDouble; } - // Return the general kind of `type`, fusing integer-like types as kPrimInt. - static Type PrimitiveKind(Type type) { - switch (type) { - case kPrimBoolean: - case kPrimByte: - case kPrimShort: - case kPrimChar: - case kPrimInt: - return kPrimInt; - default: - return type; - } - } - - static int64_t MinValueOfIntegralType(Type type) { - switch (type) { - case kPrimBoolean: - return std::numeric_limits<bool>::min(); - case kPrimByte: - return std::numeric_limits<int8_t>::min(); - case kPrimChar: - return std::numeric_limits<uint16_t>::min(); - case kPrimShort: - return std::numeric_limits<int16_t>::min(); - case kPrimInt: - return std::numeric_limits<int32_t>::min(); - case kPrimLong: - return std::numeric_limits<int64_t>::min(); - default: - LOG(FATAL) << "non integral type"; - } - return 0; - } - - static int64_t MaxValueOfIntegralType(Type type) { - switch (type) { - case kPrimBoolean: - return std::numeric_limits<bool>::max(); - case kPrimByte: - return std::numeric_limits<int8_t>::max(); - case kPrimChar: - return std::numeric_limits<uint16_t>::max(); - case kPrimShort: - return std::numeric_limits<int16_t>::max(); - case kPrimInt: - return std::numeric_limits<int32_t>::max(); - case kPrimLong: - return std::numeric_limits<int64_t>::max(); - default: - LOG(FATAL) << "non integral type"; - } - return 0; - } - private: DISALLOW_IMPLICIT_CONSTRUCTORS(Primitive); }; -std::ostream& operator<<(std::ostream& os, const Primitive::Type& state); +std::ostream& operator<<(std::ostream& os, Primitive::Type state); } // namespace art diff --git a/runtime/utils.cc b/runtime/utils.cc index 3fe18c7933..b72dec62bd 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -25,6 +25,21 @@ #include <sys/wait.h> #include <unistd.h> +// We need dladdr. +#ifndef __APPLE__ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#define DEFINED_GNU_SOURCE +#endif +#include <dlfcn.h> +#include <libgen.h> +#ifdef DEFINED_GNU_SOURCE +#undef _GNU_SOURCE +#undef DEFINED_GNU_SOURCE +#endif +#endif + + #include <memory> #include "android-base/stringprintf.h" @@ -148,7 +163,7 @@ bool PrintFileToLog(const std::string& file_name, LogSeverity level) { } } -std::string PrettyDescriptor(const char* descriptor) { +void AppendPrettyDescriptor(const char* descriptor, std::string* result) { // Count the number of '['s to get the dimensionality. const char* c = descriptor; size_t dim = 0; @@ -166,74 +181,41 @@ std::string PrettyDescriptor(const char* descriptor) { // To make life easier, we make primitives look like unqualified // reference types. switch (*c) { - case 'B': c = "byte;"; break; - case 'C': c = "char;"; break; - case 'D': c = "double;"; break; - case 'F': c = "float;"; break; - case 'I': c = "int;"; break; - case 'J': c = "long;"; break; - case 'S': c = "short;"; break; - case 'Z': c = "boolean;"; break; - case 'V': c = "void;"; break; // Used when decoding return types. - default: return descriptor; + case 'B': c = "byte;"; break; + case 'C': c = "char;"; break; + case 'D': c = "double;"; break; + case 'F': c = "float;"; break; + case 'I': c = "int;"; break; + case 'J': c = "long;"; break; + case 'S': c = "short;"; break; + case 'Z': c = "boolean;"; break; + case 'V': c = "void;"; break; // Used when decoding return types. + default: result->append(descriptor); return; } } // At this point, 'c' is a string of the form "fully/qualified/Type;" // or "primitive;". Rewrite the type with '.' instead of '/': - std::string result; const char* p = c; while (*p != ';') { char ch = *p++; if (ch == '/') { ch = '.'; } - result.push_back(ch); + result->push_back(ch); } // ...and replace the semicolon with 'dim' "[]" pairs: for (size_t i = 0; i < dim; ++i) { - result += "[]"; + result->append("[]"); } - return result; } -std::string PrettyArguments(const char* signature) { +std::string PrettyDescriptor(const char* descriptor) { std::string result; - result += '('; - CHECK_EQ(*signature, '('); - ++signature; // Skip the '('. - while (*signature != ')') { - size_t argument_length = 0; - while (signature[argument_length] == '[') { - ++argument_length; - } - if (signature[argument_length] == 'L') { - argument_length = (strchr(signature, ';') - signature + 1); - } else { - ++argument_length; - } - { - std::string argument_descriptor(signature, argument_length); - result += PrettyDescriptor(argument_descriptor.c_str()); - } - if (signature[argument_length] != ')') { - result += ", "; - } - signature += argument_length; - } - CHECK_EQ(*signature, ')'); - ++signature; // Skip the ')'. - result += ')'; + AppendPrettyDescriptor(descriptor, &result); return result; } -std::string PrettyReturnType(const char* signature) { - const char* return_type = strchr(signature, ')'); - CHECK(return_type != nullptr); - ++return_type; // Skip ')'. - return PrettyDescriptor(return_type); -} - std::string PrettyJavaAccessFlags(uint32_t access_flags) { std::string result; if ((access_flags & kAccPublic) != 0) { @@ -735,6 +717,54 @@ void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) *task_cpu = strtoull(fields[36].c_str(), nullptr, 10); } +std::string GetAndroidRootSafe(std::string* error_msg) { + // Prefer ANDROID_ROOT if it's set. + const char* android_dir = getenv("ANDROID_ROOT"); + if (android_dir != nullptr) { + if (!OS::DirectoryExists(android_dir)) { + *error_msg = StringPrintf("Failed to find ANDROID_ROOT directory %s", android_dir); + return ""; + } + return android_dir; + } + + // Check where libart is from, and derive from there. Only do this for non-Mac. +#ifndef __APPLE__ + { + Dl_info info; + if (dladdr(reinterpret_cast<const void*>(&GetAndroidRootSafe), /* out */ &info) != 0) { + // Make a duplicate of the fname so dirname can modify it. + UniqueCPtr<char> fname(strdup(info.dli_fname)); + + char* dir1 = dirname(fname.get()); // This is the lib directory. + char* dir2 = dirname(dir1); // This is the "system" directory. + if (OS::DirectoryExists(dir2)) { + std::string tmp = dir2; // Make a copy here so that fname can be released. + return tmp; + } + } + } +#endif + + // Try "/system". + if (!OS::DirectoryExists("/system")) { + *error_msg = "Failed to find ANDROID_ROOT directory /system"; + return ""; + } + return "/system"; +} + +std::string GetAndroidRoot() { + std::string error_msg; + std::string ret = GetAndroidRootSafe(&error_msg); + if (ret.empty()) { + LOG(FATAL) << error_msg; + UNREACHABLE(); + } + return ret; +} + + static const char* GetAndroidDirSafe(const char* env_var, const char* default_dir, std::string* error_msg) { @@ -754,7 +784,7 @@ static const char* GetAndroidDirSafe(const char* env_var, return android_dir; } -const char* GetAndroidDir(const char* env_var, const char* default_dir) { +static const char* GetAndroidDir(const char* env_var, const char* default_dir) { std::string error_msg; const char* dir = GetAndroidDirSafe(env_var, default_dir, &error_msg); if (dir != nullptr) { @@ -765,14 +795,6 @@ const char* GetAndroidDir(const char* env_var, const char* default_dir) { } } -const char* GetAndroidRoot() { - return GetAndroidDir("ANDROID_ROOT", "/system"); -} - -const char* GetAndroidRootSafe(std::string* error_msg) { - return GetAndroidDirSafe("ANDROID_ROOT", "/system", error_msg); -} - const char* GetAndroidData() { return GetAndroidDir("ANDROID_DATA", "/data"); } @@ -782,11 +804,11 @@ const char* GetAndroidDataSafe(std::string* error_msg) { } std::string GetDefaultBootImageLocation(std::string* error_msg) { - const char* android_root = GetAndroidRootSafe(error_msg); - if (android_root == nullptr) { + std::string android_root = GetAndroidRootSafe(error_msg); + if (android_root.empty()) { return ""; } - return StringPrintf("%s/framework/boot.art", android_root); + return StringPrintf("%s/framework/boot.art", android_root.c_str()); } void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache, diff --git a/runtime/utils.h b/runtime/utils.h index 739681d446..4cb06c1afa 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -81,13 +81,10 @@ std::string PrintableString(const char* utf8); // Returns a human-readable equivalent of 'descriptor'. So "I" would be "int", // "[[I" would be "int[][]", "[Ljava/lang/String;" would be // "java.lang.String[]", and so forth. +void AppendPrettyDescriptor(const char* descriptor, std::string* result); std::string PrettyDescriptor(const char* descriptor); std::string PrettyDescriptor(Primitive::Type type); -// Utilities for printing the types for method signatures. -std::string PrettyArguments(const char* signature); -std::string PrettyReturnType(const char* signature); - // Returns a human-readable version of the Java part of the access flags, e.g., "private static " // (note the trailing whitespace). std::string PrettyJavaAccessFlags(uint32_t access_flags); @@ -142,9 +139,9 @@ void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) void SetThreadName(const char* thread_name); // Find $ANDROID_ROOT, /system, or abort. -const char* GetAndroidRoot(); -// Find $ANDROID_ROOT, /system, or return null. -const char* GetAndroidRootSafe(std::string* error_msg); +std::string GetAndroidRoot(); +// Find $ANDROID_ROOT, /system, or return an empty string. +std::string GetAndroidRootSafe(std::string* error_msg); // Find $ANDROID_DATA, /data, or abort. const char* GetAndroidData(); diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc index ee8eb363f1..e846c983af 100644 --- a/runtime/utils_test.cc +++ b/runtime/utils_test.cc @@ -16,9 +16,11 @@ #include "utils.h" +#include <libgen.h> #include <stdlib.h> #include "base/enums.h" +#include "base/stl_util.h" #include "class_linker-inl.h" #include "common_runtime_test.h" #include "exec_utils.h" @@ -91,23 +93,6 @@ TEST_F(UtilsTest, PrettyDescriptor_PrimitiveScalars) { EXPECT_EQ("short", PrettyDescriptor("S")); } -TEST_F(UtilsTest, PrettyArguments) { - EXPECT_EQ("()", PrettyArguments("()V")); - EXPECT_EQ("(int)", PrettyArguments("(I)V")); - EXPECT_EQ("(int, int)", PrettyArguments("(II)V")); - EXPECT_EQ("(int, int, int[][])", PrettyArguments("(II[[I)V")); - EXPECT_EQ("(int, int, int[][], java.lang.Poop)", PrettyArguments("(II[[ILjava/lang/Poop;)V")); - EXPECT_EQ("(int, int, int[][], java.lang.Poop, java.lang.Poop[][])", PrettyArguments("(II[[ILjava/lang/Poop;[[Ljava/lang/Poop;)V")); -} - -TEST_F(UtilsTest, PrettyReturnType) { - EXPECT_EQ("void", PrettyReturnType("()V")); - EXPECT_EQ("int", PrettyReturnType("()I")); - EXPECT_EQ("int[][]", PrettyReturnType("()[[I")); - EXPECT_EQ("java.lang.Poop", PrettyReturnType("()Ljava/lang/Poop;")); - EXPECT_EQ("java.lang.Poop[][]", PrettyReturnType("()[[Ljava/lang/Poop;")); -} - TEST_F(UtilsTest, PrettyTypeOf) { ScopedObjectAccess soa(Thread::Current()); EXPECT_EQ("null", mirror::Object::PrettyTypeOf(nullptr)); @@ -430,4 +415,40 @@ TEST_F(UtilsTest, BoundsCheckedCast) { EXPECT_EQ(BoundsCheckedCast<const uint64_t*>(buffer + 57, buffer, buffer_end), nullptr); } +TEST_F(UtilsTest, GetAndroidRootSafe) { + std::string error_msg; + + // We don't expect null returns for most cases, so don't check and let std::string crash. + + // CommonRuntimeTest sets ANDROID_ROOT, so expect this to be the same. + std::string android_root = GetAndroidRootSafe(&error_msg); + std::string android_root_env = getenv("ANDROID_ROOT"); + EXPECT_EQ(android_root, android_root_env); + + // Set ANDROID_ROOT to something else (but the directory must exist). So use dirname. + char* root_dup = strdup(android_root_env.c_str()); + char* dir = dirname(root_dup); + ASSERT_EQ(0, setenv("ANDROID_ROOT", dir, 1 /* overwrite */)); + std::string android_root2 = GetAndroidRootSafe(&error_msg); + EXPECT_STREQ(dir, android_root2.c_str()); + free(root_dup); + + // Set a bogus value for ANDROID_ROOT. This should be an error. + ASSERT_EQ(0, setenv("ANDROID_ROOT", "/this/is/obviously/bogus", 1 /* overwrite */)); + EXPECT_TRUE(GetAndroidRootSafe(&error_msg) == nullptr); + + // Unset ANDROID_ROOT and see that it still returns something (as libart code is running). + ASSERT_EQ(0, unsetenv("ANDROID_ROOT")); + std::string android_root3 = GetAndroidRootSafe(&error_msg); + // This should be the same as the other root (modulo realpath), otherwise the test setup is + // broken. + UniqueCPtr<char> real_root(realpath(android_root.c_str(), nullptr)); + UniqueCPtr<char> real_root3(realpath(android_root3.c_str(), nullptr)); + EXPECT_STREQ(real_root.get(), real_root3.get()); + + + // Reset ANDROID_ROOT, as other things may depend on it. + ASSERT_EQ(0, setenv("ANDROID_ROOT", android_root_env.c_str(), 1 /* overwrite */)); +} + } // namespace art diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index e4ad55dda1..b789ac6b8d 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -616,18 +616,11 @@ void MethodVerifier::FindLocksAtDexPc(ArtMethod* m, uint32_t dex_pc, } static bool HasMonitorEnterInstructions(const DexFile::CodeItem* const code_item) { - const Instruction* inst = Instruction::At(code_item->insns_); - - uint32_t insns_size = code_item->insns_size_in_code_units_; - for (uint32_t dex_pc = 0; dex_pc < insns_size;) { - if (inst->Opcode() == Instruction::MONITOR_ENTER) { + for (const Instruction& inst : code_item->Instructions()) { + if (inst.Opcode() == Instruction::MONITOR_ENTER) { return true; } - - dex_pc += inst->SizeInCodeUnits(); - inst = inst->Next(); } - return false; } @@ -683,7 +676,7 @@ ArtField* MethodVerifier::FindAccessedFieldAtDexPc(uint32_t dex_pc) { if (register_line == nullptr) { return nullptr; } - const Instruction* inst = Instruction::At(code_item_->insns_ + dex_pc); + const Instruction* inst = &code_item_->InstructionAt(dex_pc); return GetQuickFieldAccess(inst, register_line); } @@ -723,7 +716,7 @@ ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(uint32_t dex_pc) { if (register_line == nullptr) { return nullptr; } - const Instruction* inst = Instruction::At(code_item_->insns_ + dex_pc); + const Instruction* inst = &code_item_->InstructionAt(dex_pc); const bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK); return GetQuickInvokedMethod(inst, register_line, is_range, false); } @@ -929,9 +922,8 @@ std::ostream& MethodVerifier::Fail(VerifyError error) { // Note: this can fail before we touch any instruction, for the signature of a method. So // add a check. if (work_insn_idx_ < dex::kDexNoIndex) { - const uint16_t* insns = code_item_->insns_ + work_insn_idx_; - const Instruction* inst = Instruction::At(insns); - int opcode_flags = Instruction::FlagsOf(inst->Opcode()); + const Instruction& inst = code_item_->InstructionAt(work_insn_idx_); + int opcode_flags = Instruction::FlagsOf(inst.Opcode()); if ((opcode_flags & Instruction::kThrow) == 0 && CurrentInsnFlags()->IsInTry()) { saved_line_->CopyFromLine(work_line_.get()); @@ -990,14 +982,12 @@ void MethodVerifier::AppendToLastFailMessage(const std::string& append) { } bool MethodVerifier::ComputeWidthsAndCountOps() { - const uint16_t* insns = code_item_->insns_; - size_t insns_size = code_item_->insns_size_in_code_units_; - const Instruction* inst = Instruction::At(insns); size_t new_instance_count = 0; size_t monitor_enter_count = 0; - size_t dex_pc = 0; - while (dex_pc < insns_size) { + IterationRange<DexInstructionIterator> instructions = code_item_->Instructions(); + DexInstructionIterator inst = instructions.begin(); + for ( ; inst < instructions.end(); ++inst) { Instruction::Code opcode = inst->Opcode(); switch (opcode) { case Instruction::APUT_OBJECT: @@ -1019,15 +1009,14 @@ bool MethodVerifier::ComputeWidthsAndCountOps() { default: break; } - size_t inst_size = inst->SizeInCodeUnits(); - GetInstructionFlags(dex_pc).SetIsOpcode(); - dex_pc += inst_size; - inst = inst->RelativeAt(inst_size); + GetInstructionFlags(inst.GetDexPC(instructions.begin())).SetIsOpcode(); } - if (dex_pc != insns_size) { + if (inst != instructions.end()) { + const size_t insns_size = code_item_->insns_size_in_code_units_; Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "code did not end where expected (" - << dex_pc << " vs. " << insns_size << ")"; + << inst.GetDexPC(instructions.begin()) << " vs. " + << insns_size << ")"; return false; } @@ -1105,15 +1094,13 @@ bool MethodVerifier::ScanTryCatchBlocks() { template <bool kAllowRuntimeOnlyInstructions> bool MethodVerifier::VerifyInstructions() { - const Instruction* inst = Instruction::At(code_item_->insns_); - /* Flag the start of the method as a branch target, and a GC point due to stack overflow errors */ GetInstructionFlags(0).SetBranchTarget(); GetInstructionFlags(0).SetCompileTimeInfoPoint(); - - uint32_t insns_size = code_item_->insns_size_in_code_units_; - for (uint32_t dex_pc = 0; dex_pc < insns_size;) { - if (!VerifyInstruction<kAllowRuntimeOnlyInstructions>(inst, dex_pc)) { + IterationRange<DexInstructionIterator> instructions = code_item_->Instructions(); + for (auto inst = instructions.begin(); inst != instructions.end(); ++inst) { + const uint32_t dex_pc = inst.GetDexPC(instructions.begin()); + if (!VerifyInstruction<kAllowRuntimeOnlyInstructions>(&*inst, dex_pc)) { DCHECK_NE(failures_.size(), 0U); return false; } @@ -1134,8 +1121,6 @@ bool MethodVerifier::VerifyInstructions() { } else if (inst->IsReturn()) { GetInstructionFlags(dex_pc).SetCompileTimeInfoPointAndReturn(); } - dex_pc += inst->SizeInCodeUnits(); - inst = inst->Next(); } return true; } @@ -1671,9 +1656,10 @@ void MethodVerifier::Dump(VariableIndentationOutputStream* vios) { } vios->Stream() << "Dumping instructions and register lines:\n"; ScopedIndentation indent1(vios); - const Instruction* inst = Instruction::At(code_item_->insns_); - for (size_t dex_pc = 0; dex_pc < code_item_->insns_size_in_code_units_; - dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) { + + IterationRange<DexInstructionIterator> instructions = code_item_->Instructions(); + for (auto inst = instructions.begin(); inst != instructions.end(); ++inst) { + const size_t dex_pc = inst.GetDexPC(instructions.begin()); RegisterLine* reg_line = reg_table_.GetLine(dex_pc); if (reg_line != nullptr) { vios->Stream() << reg_line->Dump(this) << "\n"; @@ -1938,9 +1924,10 @@ bool MethodVerifier::CodeFlowVerifyMethod() { * we are almost certainly going to have some dead code. */ int dead_start = -1; - uint32_t insn_idx = 0; - for (; insn_idx < insns_size; - insn_idx += Instruction::At(code_item_->insns_ + insn_idx)->SizeInCodeUnits()) { + + IterationRange<DexInstructionIterator> instructions = code_item_->Instructions(); + for (auto inst = instructions.begin(); inst != instructions.end(); ++inst) { + const uint32_t insn_idx = inst.GetDexPC(instructions.begin()); /* * Switch-statement data doesn't get "visited" by scanner. It * may or may not be preceded by a padding NOP (for alignment). @@ -1956,8 +1943,9 @@ bool MethodVerifier::CodeFlowVerifyMethod() { } if (!GetInstructionFlags(insn_idx).IsVisited()) { - if (dead_start < 0) + if (dead_start < 0) { dead_start = insn_idx; + } } else if (dead_start >= 0) { LogVerifyInfo() << "dead code " << reinterpret_cast<void*>(dead_start) << "-" << reinterpret_cast<void*>(insn_idx - 1); @@ -1965,8 +1953,9 @@ bool MethodVerifier::CodeFlowVerifyMethod() { } } if (dead_start >= 0) { - LogVerifyInfo() << "dead code " << reinterpret_cast<void*>(dead_start) - << "-" << reinterpret_cast<void*>(insn_idx - 1); + LogVerifyInfo() + << "dead code " << reinterpret_cast<void*>(dead_start) + << "-" << reinterpret_cast<void*>(instructions.end().GetDexPC(instructions.begin())); } // To dump the state of the verify after a method, do something like: // if (dex_file_->PrettyMethod(dex_method_idx_) == @@ -2340,17 +2329,17 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { while (0 != prev_idx && !GetInstructionFlags(prev_idx).IsOpcode()) { prev_idx--; } - const Instruction* prev_inst = Instruction::At(code_item_->insns_ + prev_idx); - switch (prev_inst->Opcode()) { + const Instruction& prev_inst = code_item_->InstructionAt(prev_idx); + switch (prev_inst.Opcode()) { case Instruction::MOVE_OBJECT: case Instruction::MOVE_OBJECT_16: case Instruction::MOVE_OBJECT_FROM16: - if (prev_inst->VRegB() == inst->VRegA_11x()) { + if (prev_inst.VRegB() == inst->VRegA_11x()) { // Redo the copy. This won't change the register types, but update the lock status // for the aliased register. work_line_->CopyRegister1(this, - prev_inst->VRegA(), - prev_inst->VRegB(), + prev_inst.VRegA(), + prev_inst.VRegB(), kTypeCategoryRef); } break; @@ -2648,7 +2637,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { break; } - const Instruction* instance_of_inst = Instruction::At(code_item_->insns_ + instance_of_idx); + const Instruction* instance_of_inst = &code_item_->InstructionAt(instance_of_idx); /* Check for peep-hole pattern of: * ...; @@ -2710,7 +2699,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { work_insn_idx_)) { break; } - const Instruction* move_inst = Instruction::At(code_item_->insns_ + move_idx); + const Instruction* move_inst = &code_item_->InstructionAt(move_idx); switch (move_inst->Opcode()) { case Instruction::MOVE_OBJECT: if (move_inst->VRegA_12x() == instance_of_inst->VRegB_22c()) { @@ -3648,7 +3637,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { * and this change should not be used in those cases. */ if ((opcode_flags & Instruction::kContinue) != 0) { - DCHECK_EQ(Instruction::At(code_item_->insns_ + work_insn_idx_), inst); + DCHECK_EQ(&code_item_->InstructionAt(work_insn_idx_), inst); uint32_t next_insn_idx = work_insn_idx_ + inst->SizeInCodeUnits(); if (next_insn_idx >= code_item_->insns_size_in_code_units_) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Execution can walk off end of code area"; diff --git a/sigchainlib/Android.bp b/sigchainlib/Android.bp index 0c64b7df9f..7aab726be7 100644 --- a/sigchainlib/Android.bp +++ b/sigchainlib/Android.bp @@ -25,9 +25,6 @@ cc_library { srcs: ["sigchain.cc"], }, target: { - host: { - host_ldlibs: ["-ldl"], - }, android: { shared_libs: ["liblog"], }, @@ -49,9 +46,6 @@ cc_library_static { defaults: ["art_defaults"], srcs: ["sigchain_dummy.cc"], target: { - host: { - host_ldlibs: ["-ldl"], - }, android: { shared_libs: ["liblog"], }, diff --git a/simulator/Android.bp b/simulator/Android.bp index a39928985a..74b5a900b4 100644 --- a/simulator/Android.bp +++ b/simulator/Android.bp @@ -73,7 +73,7 @@ cc_defaults { ], header_libs: ["libart_simulator_headers"], - export_include_dirs: ["."], // TODO: Consider a proper separation. + export_include_dirs: ["."], // TODO: Consider a proper separation. } art_cc_library { diff --git a/test/004-JniTest/expected.txt b/test/004-JniTest/expected.txt index 7e85ab1041..1d05160883 100644 --- a/test/004-JniTest/expected.txt +++ b/test/004-JniTest/expected.txt @@ -60,3 +60,4 @@ hi-default δλ hi-default δλ Clinit Lookup: ClassWithoutClinit: <NSME Exception> Clinit Lookup: ClassWithClinit: Main$ClassWithClinit()(Class: class java.lang.reflect.Constructor) +Got UnsatisfiedLinkError for duplicate loadLibrary diff --git a/test/004-JniTest/src-ex/A.java b/test/004-JniTest/src-ex/A.java new file mode 100644 index 0000000000..8fe0e0afe6 --- /dev/null +++ b/test/004-JniTest/src-ex/A.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2017 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. + */ + +public class A { + public static void run(String lib) { + System.loadLibrary(lib); + } +}
\ No newline at end of file diff --git a/test/004-JniTest/src/Main.java b/test/004-JniTest/src/Main.java index fe5f4e3dc6..871107c56b 100644 --- a/test/004-JniTest/src/Main.java +++ b/test/004-JniTest/src/Main.java @@ -14,9 +14,12 @@ * limitations under the License. */ +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.util.regex.Pattern; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; @@ -58,6 +61,8 @@ public class Main { testCriticalNativeMethods(); testClinitMethodLookup(); + + testDoubleLoad(args[0]); } private static native boolean registerNativesJniTest(); @@ -346,6 +351,57 @@ public class Main { private static class ClassWithClinit { static {} } + + private static void testDoubleLoad(String library) { + // Test that nothing observably happens on loading "library" again. + System.loadLibrary(library); + + // Now load code in a separate classloader and try to let it load. + ClassLoader loader = createClassLoader(); + try { + Class<?> aClass = loader.loadClass("A"); + Method runMethod = aClass.getDeclaredMethod("run", String.class); + runMethod.invoke(null, library); + } catch (InvocationTargetException ite) { + if (ite.getCause() instanceof UnsatisfiedLinkError) { + if (!(loader instanceof java.net.URLClassLoader)) { + String msg = ite.getCause().getMessage(); + String pattern = "^Shared library .*libarttest.* already opened by ClassLoader.*" + + "004-JniTest.jar.*; can't open in ClassLoader.*004-JniTest-ex.jar.*"; + if (!Pattern.matches(pattern, msg)) { + throw new RuntimeException("Could not find pattern in message", ite.getCause()); + } + } + System.out.println("Got UnsatisfiedLinkError for duplicate loadLibrary"); + } else { + throw new RuntimeException(ite); + } + } catch (Throwable t) { + // Anything else just let die. + throw new RuntimeException(t); + } + } + + private static ClassLoader createClassLoader() { + String location = System.getenv("DEX_LOCATION"); + try { + Class<?> class_loader_class = Class.forName("dalvik.system.PathClassLoader"); + Constructor<?> ctor = class_loader_class.getConstructor(String.class, ClassLoader.class); + + return (ClassLoader)ctor.newInstance(location + "/004-JniTest-ex.jar", + Main.class.getClassLoader()); + } catch (ClassNotFoundException e) { + // Running on RI. Use URLClassLoader. + try { + return new java.net.URLClassLoader( + new java.net.URL[] { new java.net.URL("file://" + location + "/classes-ex/") }); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } } @FunctionalInterface diff --git a/test/063-process-manager/src/Main.java b/test/063-process-manager/src/Main.java index 1005b77107..2cfc0d7fc2 100644 --- a/test/063-process-manager/src/Main.java +++ b/test/063-process-manager/src/Main.java @@ -10,7 +10,7 @@ public class Main { ProcessBuilder pb = new ProcessBuilder("sleep", "0"); Process proc = pb.start(); proc.waitFor(); - Thread.sleep(500); // Consider checking for (and waiting on) the reaper state here. + waitForReaperTimedWaiting(true /* reaperMustExist */); } for (int i = 1; i <= 2; i++) { @@ -32,6 +32,11 @@ public class Main { System.out.println("child died"); } + private static boolean isReaperThread(Thread t) { + String name = t.getName(); + return name.indexOf("process reaper") >= 0; + } + static private void checkManager() { Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces(); boolean found = false; @@ -39,8 +44,7 @@ public class Main { for (Map.Entry<Thread, StackTraceElement[]> entry : traces.entrySet()) { Thread t = entry.getKey(); - String name = t.getName(); - if (name.indexOf("process reaper") >= 0) { + if (isReaperThread(t)) { Thread.State state = t.getState(); System.out.println("process manager: " + state); if (state != Thread.State.RUNNABLE && state != Thread.State.TIMED_WAITING) { @@ -56,4 +60,34 @@ public class Main { System.out.println("process manager: nonexistent"); } } + + private static void waitForReaperTimedWaiting(boolean reaperMustExist) { + for (;;) { + Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces(); + + boolean ok = true; + boolean found = false; + + for (Thread t : traces.keySet()) { + if (isReaperThread(t)) { + found = true; + Thread.State state = t.getState(); + if (state != Thread.State.TIMED_WAITING) { + ok = false; + break; + } + } + } + + if (ok && (!reaperMustExist || found)) { + return; + } + + try { + Thread.sleep(100); + } catch (Exception e) { + // Ignore. + } + } + } } diff --git a/test/088-monitor-verification/src/Main.java b/test/088-monitor-verification/src/Main.java index f5cbc2ae7a..3f7bb56e8f 100644 --- a/test/088-monitor-verification/src/Main.java +++ b/test/088-monitor-verification/src/Main.java @@ -25,7 +25,7 @@ public class Main { /** * Drives tests. */ - public static void main(String[] args) { + public static void main(String[] args) throws Exception { System.loadLibrary(args[0]); if (!hasOatFile() || runtimeIsSoftFail() || isInterpreted()) { // Some tests ensure that the verifier was able to guarantee balanced locking by @@ -40,6 +40,7 @@ public class Main { ensureJitCompiled(Main.class, "notExcessiveNesting"); ensureJitCompiled(Main.class, "notNested"); ensureJitCompiled(TwoPath.class, "twoPath"); + ensureJitCompiled(Class.forName("OK"), "runBalancedJoin"); Main m = new Main(); diff --git a/test/1930-monitor-info/src/art/Monitors.java b/test/1930-monitor-info/src/art/Monitors.java index b28a3ee035..7fe2b60c1e 100644 --- a/test/1930-monitor-info/src/art/Monitors.java +++ b/test/1930-monitor-info/src/art/Monitors.java @@ -36,12 +36,40 @@ public class Monitors { public static class NamedLock { public final String name; + private volatile int calledNotify; public NamedLock(String name) { this.name = name; + calledNotify = 0; } + public String toString() { return String.format("NamedLock[%s]", name); } + + public final void DoWait() throws Exception { + final int v = calledNotify; + while (v == calledNotify) { + wait(); + } + } + + public final void DoWait(long t) throws Exception { + final int v = calledNotify; + final long target = System.currentTimeMillis() + (t / 2); + while (v == calledNotify && (t < 0 || System.currentTimeMillis() < target)) { + wait(t); + } + } + + public final void DoNotifyAll() throws Exception { + calledNotify++; + notifyAll(); + } + + public final void DoNotify() throws Exception { + calledNotify++; + notify(); + } } public static final class MonitorUsage { @@ -91,7 +119,7 @@ public class Monitors { public static class LockController { private static enum Action { HOLD, RELEASE, NOTIFY, NOTIFY_ALL, WAIT, TIMED_WAIT } - public final Object lock; + public final NamedLock lock; public final long timeout; private final AtomicStampedReference<Action> action; private volatile Thread runner = null; @@ -100,10 +128,10 @@ public class Monitors { private static final AtomicInteger cnt = new AtomicInteger(0); private volatile Throwable exe; - public LockController(Object lock) { + public LockController(NamedLock lock) { this(lock, 10 * 1000); } - public LockController(Object lock, long timeout) { + public LockController(NamedLock lock, long timeout) { this.lock = lock; this.timeout = timeout; this.action = new AtomicStampedReference(Action.HOLD, 0); @@ -177,16 +205,16 @@ public class Monitors { Thread.yield(); break; case NOTIFY: - lock.notify(); + lock.DoNotify(); break; case NOTIFY_ALL: - lock.notifyAll(); + lock.DoNotifyAll(); break; case TIMED_WAIT: - lock.wait(timeout); + lock.DoWait(timeout); break; case WAIT: - lock.wait(); + lock.DoWait(); break; default: throw new Error("Unknown action " + action); diff --git a/test/1930-monitor-info/src/art/Test1930.java b/test/1930-monitor-info/src/art/Test1930.java index a7fa1c78cb..ee03d73760 100644 --- a/test/1930-monitor-info/src/art/Test1930.java +++ b/test/1930-monitor-info/src/art/Test1930.java @@ -96,7 +96,7 @@ public class Test1930 { printMonitorUsage(lk); sem.release(); try { - lk.wait(); + lk.DoWait(); } catch (Exception e) { throw new Error("Error waiting!", e); } @@ -107,7 +107,7 @@ public class Test1930 { sem.acquire(); synchronized (lk) { printMonitorUsage(lk); - lk.notifyAll(); + lk.DoNotifyAll(); } t.join(); printMonitorUsage(lk); diff --git a/test/1931-monitor-events/src/art/Monitors.java b/test/1931-monitor-events/src/art/Monitors.java index b28a3ee035..7fe2b60c1e 100644 --- a/test/1931-monitor-events/src/art/Monitors.java +++ b/test/1931-monitor-events/src/art/Monitors.java @@ -36,12 +36,40 @@ public class Monitors { public static class NamedLock { public final String name; + private volatile int calledNotify; public NamedLock(String name) { this.name = name; + calledNotify = 0; } + public String toString() { return String.format("NamedLock[%s]", name); } + + public final void DoWait() throws Exception { + final int v = calledNotify; + while (v == calledNotify) { + wait(); + } + } + + public final void DoWait(long t) throws Exception { + final int v = calledNotify; + final long target = System.currentTimeMillis() + (t / 2); + while (v == calledNotify && (t < 0 || System.currentTimeMillis() < target)) { + wait(t); + } + } + + public final void DoNotifyAll() throws Exception { + calledNotify++; + notifyAll(); + } + + public final void DoNotify() throws Exception { + calledNotify++; + notify(); + } } public static final class MonitorUsage { @@ -91,7 +119,7 @@ public class Monitors { public static class LockController { private static enum Action { HOLD, RELEASE, NOTIFY, NOTIFY_ALL, WAIT, TIMED_WAIT } - public final Object lock; + public final NamedLock lock; public final long timeout; private final AtomicStampedReference<Action> action; private volatile Thread runner = null; @@ -100,10 +128,10 @@ public class Monitors { private static final AtomicInteger cnt = new AtomicInteger(0); private volatile Throwable exe; - public LockController(Object lock) { + public LockController(NamedLock lock) { this(lock, 10 * 1000); } - public LockController(Object lock, long timeout) { + public LockController(NamedLock lock, long timeout) { this.lock = lock; this.timeout = timeout; this.action = new AtomicStampedReference(Action.HOLD, 0); @@ -177,16 +205,16 @@ public class Monitors { Thread.yield(); break; case NOTIFY: - lock.notify(); + lock.DoNotify(); break; case NOTIFY_ALL: - lock.notifyAll(); + lock.DoNotifyAll(); break; case TIMED_WAIT: - lock.wait(timeout); + lock.DoWait(timeout); break; case WAIT: - lock.wait(); + lock.DoWait(); break; default: throw new Error("Unknown action " + action); diff --git a/test/1932-monitor-events-misc/src/art/Monitors.java b/test/1932-monitor-events-misc/src/art/Monitors.java index b28a3ee035..7fe2b60c1e 100644 --- a/test/1932-monitor-events-misc/src/art/Monitors.java +++ b/test/1932-monitor-events-misc/src/art/Monitors.java @@ -36,12 +36,40 @@ public class Monitors { public static class NamedLock { public final String name; + private volatile int calledNotify; public NamedLock(String name) { this.name = name; + calledNotify = 0; } + public String toString() { return String.format("NamedLock[%s]", name); } + + public final void DoWait() throws Exception { + final int v = calledNotify; + while (v == calledNotify) { + wait(); + } + } + + public final void DoWait(long t) throws Exception { + final int v = calledNotify; + final long target = System.currentTimeMillis() + (t / 2); + while (v == calledNotify && (t < 0 || System.currentTimeMillis() < target)) { + wait(t); + } + } + + public final void DoNotifyAll() throws Exception { + calledNotify++; + notifyAll(); + } + + public final void DoNotify() throws Exception { + calledNotify++; + notify(); + } } public static final class MonitorUsage { @@ -91,7 +119,7 @@ public class Monitors { public static class LockController { private static enum Action { HOLD, RELEASE, NOTIFY, NOTIFY_ALL, WAIT, TIMED_WAIT } - public final Object lock; + public final NamedLock lock; public final long timeout; private final AtomicStampedReference<Action> action; private volatile Thread runner = null; @@ -100,10 +128,10 @@ public class Monitors { private static final AtomicInteger cnt = new AtomicInteger(0); private volatile Throwable exe; - public LockController(Object lock) { + public LockController(NamedLock lock) { this(lock, 10 * 1000); } - public LockController(Object lock, long timeout) { + public LockController(NamedLock lock, long timeout) { this.lock = lock; this.timeout = timeout; this.action = new AtomicStampedReference(Action.HOLD, 0); @@ -177,16 +205,16 @@ public class Monitors { Thread.yield(); break; case NOTIFY: - lock.notify(); + lock.DoNotify(); break; case NOTIFY_ALL: - lock.notifyAll(); + lock.DoNotifyAll(); break; case TIMED_WAIT: - lock.wait(timeout); + lock.DoWait(timeout); break; case WAIT: - lock.wait(); + lock.DoWait(); break; default: throw new Error("Unknown action " + action); diff --git a/test/1933-monitor-current-contended/src/art/Monitors.java b/test/1933-monitor-current-contended/src/art/Monitors.java index b28a3ee035..7fe2b60c1e 100644 --- a/test/1933-monitor-current-contended/src/art/Monitors.java +++ b/test/1933-monitor-current-contended/src/art/Monitors.java @@ -36,12 +36,40 @@ public class Monitors { public static class NamedLock { public final String name; + private volatile int calledNotify; public NamedLock(String name) { this.name = name; + calledNotify = 0; } + public String toString() { return String.format("NamedLock[%s]", name); } + + public final void DoWait() throws Exception { + final int v = calledNotify; + while (v == calledNotify) { + wait(); + } + } + + public final void DoWait(long t) throws Exception { + final int v = calledNotify; + final long target = System.currentTimeMillis() + (t / 2); + while (v == calledNotify && (t < 0 || System.currentTimeMillis() < target)) { + wait(t); + } + } + + public final void DoNotifyAll() throws Exception { + calledNotify++; + notifyAll(); + } + + public final void DoNotify() throws Exception { + calledNotify++; + notify(); + } } public static final class MonitorUsage { @@ -91,7 +119,7 @@ public class Monitors { public static class LockController { private static enum Action { HOLD, RELEASE, NOTIFY, NOTIFY_ALL, WAIT, TIMED_WAIT } - public final Object lock; + public final NamedLock lock; public final long timeout; private final AtomicStampedReference<Action> action; private volatile Thread runner = null; @@ -100,10 +128,10 @@ public class Monitors { private static final AtomicInteger cnt = new AtomicInteger(0); private volatile Throwable exe; - public LockController(Object lock) { + public LockController(NamedLock lock) { this(lock, 10 * 1000); } - public LockController(Object lock, long timeout) { + public LockController(NamedLock lock, long timeout) { this.lock = lock; this.timeout = timeout; this.action = new AtomicStampedReference(Action.HOLD, 0); @@ -177,16 +205,16 @@ public class Monitors { Thread.yield(); break; case NOTIFY: - lock.notify(); + lock.DoNotify(); break; case NOTIFY_ALL: - lock.notifyAll(); + lock.DoNotifyAll(); break; case TIMED_WAIT: - lock.wait(timeout); + lock.DoWait(timeout); break; case WAIT: - lock.wait(); + lock.DoWait(); break; default: throw new Error("Unknown action " + action); diff --git a/test/1933-monitor-current-contended/src/art/Test1933.java b/test/1933-monitor-current-contended/src/art/Test1933.java index e21c395196..194a043c63 100644 --- a/test/1933-monitor-current-contended/src/art/Test1933.java +++ b/test/1933-monitor-current-contended/src/art/Test1933.java @@ -34,9 +34,13 @@ public class Test1933 { controller1.waitForLockToBeHeld(); controller1.DoWait(); controller1.waitForNotifySleep(); - System.out.println("c1 is contending for monitor: " + controller1.getWorkerContendedMonitor()); + // Spurious wakeups can hurt us here. Just retry until we get the result we expect. The test + // will timeout eventually. + Object mon = controller1.getWorkerContendedMonitor(); + for (; mon == null; mon = controller1.getWorkerContendedMonitor()) { Thread.yield(); } + System.out.println("c1 is contending for monitor: " + mon); synchronized (lk) { - lk.notifyAll(); + lk.DoNotifyAll(); } controller1.DoUnlock(); } diff --git a/test/442-checker-constant-folding/smali/TestCmp.smali b/test/442-checker-constant-folding/smali/TestCmp.smali index df631bc202..f55c837b17 100644 --- a/test/442-checker-constant-folding/smali/TestCmp.smali +++ b/test/442-checker-constant-folding/smali/TestCmp.smali @@ -330,3 +330,141 @@ cmpl-double v0, v1, v3 return v0 .end method + + +## CHECK-START: int TestCmp.IntAddition2() constant_folding (before) +## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 +## CHECK-DAG: <<Const2:i\d+>> IntConstant 2 +## CHECK-DAG: <<Const5:i\d+>> IntConstant 5 +## CHECK-DAG: <<Const6:i\d+>> IntConstant 6 +## CHECK-DAG: <<Add1:i\d+>> Add [<<Const1>>,<<Const2>>] +## CHECK-DAG: <<Add2:i\d+>> Add [<<Const5>>,<<Const6>>] +## CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Add2>>] +## CHECK-DAG: Return [<<Add3>>] + +## CHECK-START: int TestCmp.IntAddition2() constant_folding (after) +## CHECK-DAG: <<Const14:i\d+>> IntConstant 14 +## CHECK-DAG: Return [<<Const14>>] + +## CHECK-START: int TestCmp.IntAddition2() constant_folding (after) +## CHECK-NOT: Add +.method public static IntAddition2()I + # A more direct translation from Java. + + # int a, b, c; + .registers 3 + + # a = 1; + const/4 v0, 1 + # b = 2; + const/4 v1, 2 + + # a += b; + add-int/2addr v0, v1 + + # b = 5; + const/4 v1, 5 + # c = 6; + const/4 v2, 6 + + # b += c; + add-int/2addr v1, v2 + # c = a + b; + add-int v2, v0, v1 + + # return c; + return v2 +.end method + + +## CHECK-START: int TestCmp.IntAddition2AddAndMove() constant_folding (before) +## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 +## CHECK-DAG: <<Const2:i\d+>> IntConstant 2 +## CHECK-DAG: <<Const5:i\d+>> IntConstant 5 +## CHECK-DAG: <<Const6:i\d+>> IntConstant 6 +## CHECK-DAG: <<Add1:i\d+>> Add [<<Const1>>,<<Const2>>] +## CHECK-DAG: <<Add2:i\d+>> Add [<<Const5>>,<<Const6>>] +## CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Add2>>] +## CHECK-DAG: Return [<<Add3>>] + +## CHECK-START: int TestCmp.IntAddition2AddAndMove() constant_folding (after) +## CHECK-DAG: <<Const14:i\d+>> IntConstant 14 +## CHECK-DAG: Return [<<Const14>>] + +## CHECK-START: int TestCmp.IntAddition2AddAndMove() constant_folding (after) +## CHECK-NOT: Add + +# D8 uses 3 registers for += when local variable info is presented. +.method public static IntAddition2AddAndMove()I + .registers 4 + + # a = 1; + const/4 v0, 1 + # b = 2; + const/4 v1, 2 + + # a += b; + add-int v2, v0, v1 + move v0, v2 + + # b = 5; + const/4 v2, 5 + move v1, v2 + + # c = 6; + const/4 v2, 6 + + # b += c; + add-int v3, v1, v2 + move v1, v3 + + # c = a + b; + add-int v3, v0, v1 + move v2, v3 + + # return c; + return v2 +.end method + + +## CHECK-START: int TestCmp.JumpsAndConditionals(boolean) constant_folding (before) +## CHECK-DAG: <<Const2:i\d+>> IntConstant 2 +## CHECK-DAG: <<Const5:i\d+>> IntConstant 5 +## CHECK-DAG: <<Add:i\d+>> Add [<<Const5>>,<<Const2>>] +## CHECK-DAG: <<Sub:i\d+>> Sub [<<Const5>>,<<Const2>>] +## CHECK-DAG: <<Phi:i\d+>> Phi [<<Add>>,<<Sub>>] +## CHECK-DAG: Return [<<Phi>>] + +## CHECK-START: int TestCmp.JumpsAndConditionals(boolean) constant_folding (after) +## CHECK-DAG: <<Const3:i\d+>> IntConstant 3 +## CHECK-DAG: <<Const7:i\d+>> IntConstant 7 +## CHECK-DAG: <<Phi:i\d+>> Phi [<<Const7>>,<<Const3>>] +## CHECK-DAG: Return [<<Phi>>] + +## CHECK-START: int TestCmp.JumpsAndConditionals(boolean) constant_folding (after) +## CHECK-NOT: Add +## CHECK-NOT: Sub +.method public static JumpsAndConditionals(Z)I + # int a, b, c; + # a = 5; + # b = 2; + # if (cond) + # c = a + b; + # else + # c = a - b; + # return c; + .registers 4 + + const/4 v0, 5 + const/4 v1, 2 + + if-eqz p0, :cond_7 + add-int v2, v0, v1 + + :goto_6 + return v2 + + :cond_7 + sub-int v2, v0, v1 + goto :goto_6 +.end method diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java index eba5137f6f..95c19eaabc 100644 --- a/test/442-checker-constant-folding/src/Main.java +++ b/test/442-checker-constant-folding/src/Main.java @@ -113,6 +113,19 @@ public class Main { return (Integer)m.invoke(null); } + public static int smaliIntAddition2() throws Exception { + Method m = Class.forName("TestCmp").getMethod("IntAddition2"); + return (Integer)m.invoke(null); + } + public static int smaliIntAddition2AddAndMove() throws Exception { + Method m = Class.forName("TestCmp").getMethod("IntAddition2AddAndMove"); + return (Integer)m.invoke(null); + } + public static int smaliJumpsAndConditionals(boolean cond) throws Exception { + Method m = Class.forName("TestCmp").getMethod("JumpsAndConditionals", boolean.class); + return (Integer)m.invoke(null, cond); + } + /** * Exercise constant folding on negation. @@ -225,11 +238,8 @@ public class Main { /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5 /// CHECK-DAG: <<Const6:i\d+>> IntConstant 6 - /// CHECK-DAG: <<Const11:i\d+>> IntConstant 11 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Const1>>,<<Const2>>] /// CHECK-DAG: Add [<<Const5>>,<<Const6>>] - /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Const11>>] - /// CHECK-DAG: Return [<<Add3>>] /// CHECK-START: int Main.IntAddition2() constant_folding (after) /// CHECK-DAG: <<Const14:i\d+>> IntConstant 14 @@ -1520,6 +1530,8 @@ public class Main { assertIntEquals(3, IntAddition1()); assertIntEquals(14, IntAddition2()); + assertIntEquals(14, smaliIntAddition2()); + assertIntEquals(14, smaliIntAddition2AddAndMove()); assertLongEquals(3L, LongAddition()); assertFloatEquals(3F, FloatAddition()); assertDoubleEquals(3D, DoubleAddition()); @@ -1567,6 +1579,8 @@ public class Main { assertIntEquals(7, JumpsAndConditionals(true)); assertIntEquals(3, JumpsAndConditionals(false)); + assertIntEquals(7, smaliJumpsAndConditionals(true)); + assertIntEquals(3, smaliJumpsAndConditionals(false)); int arbitrary = 123456; // Value chosen arbitrarily. diff --git a/test/529-checker-unresolved/src/Main.java b/test/529-checker-unresolved/src/Main.java index c2683acb30..255ce7859b 100644 --- a/test/529-checker-unresolved/src/Main.java +++ b/test/529-checker-unresolved/src/Main.java @@ -45,21 +45,21 @@ public class Main extends UnresolvedSuperClass { } /// CHECK-START: void Main.callUnresolvedStaticFieldAccess() register (before) - /// CHECK: UnresolvedStaticFieldSet field_type:PrimByte - /// CHECK: UnresolvedStaticFieldSet field_type:PrimChar - /// CHECK: UnresolvedStaticFieldSet field_type:PrimInt - /// CHECK: UnresolvedStaticFieldSet field_type:PrimLong - /// CHECK: UnresolvedStaticFieldSet field_type:PrimFloat - /// CHECK: UnresolvedStaticFieldSet field_type:PrimDouble - /// CHECK: UnresolvedStaticFieldSet field_type:PrimNot - - /// CHECK: UnresolvedStaticFieldGet field_type:PrimByte - /// CHECK: UnresolvedStaticFieldGet field_type:PrimChar - /// CHECK: UnresolvedStaticFieldGet field_type:PrimInt - /// CHECK: UnresolvedStaticFieldGet field_type:PrimLong - /// CHECK: UnresolvedStaticFieldGet field_type:PrimFloat - /// CHECK: UnresolvedStaticFieldGet field_type:PrimDouble - /// CHECK: UnresolvedStaticFieldGet field_type:PrimNot + /// CHECK: UnresolvedStaticFieldSet field_type:Int8 + /// CHECK: UnresolvedStaticFieldSet field_type:Uint16 + /// CHECK: UnresolvedStaticFieldSet field_type:Int32 + /// CHECK: UnresolvedStaticFieldSet field_type:Int64 + /// CHECK: UnresolvedStaticFieldSet field_type:Float32 + /// CHECK: UnresolvedStaticFieldSet field_type:Float64 + /// CHECK: UnresolvedStaticFieldSet field_type:Reference + + /// CHECK: UnresolvedStaticFieldGet field_type:Int8 + /// CHECK: UnresolvedStaticFieldGet field_type:Uint16 + /// CHECK: UnresolvedStaticFieldGet field_type:Int32 + /// CHECK: UnresolvedStaticFieldGet field_type:Int64 + /// CHECK: UnresolvedStaticFieldGet field_type:Float32 + /// CHECK: UnresolvedStaticFieldGet field_type:Float64 + /// CHECK: UnresolvedStaticFieldGet field_type:Reference static public void callUnresolvedStaticFieldAccess() { Object o = new Object(); UnresolvedClass.staticByte = (byte)1; @@ -90,21 +90,21 @@ public class Main extends UnresolvedSuperClass { } /// CHECK-START: void Main.callUnresolvedInstanceFieldAccess(UnresolvedClass) register (before) - /// CHECK: UnresolvedInstanceFieldSet field_type:PrimByte - /// CHECK: UnresolvedInstanceFieldSet field_type:PrimChar - /// CHECK: UnresolvedInstanceFieldSet field_type:PrimInt - /// CHECK: UnresolvedInstanceFieldSet field_type:PrimLong - /// CHECK: UnresolvedInstanceFieldSet field_type:PrimFloat - /// CHECK: UnresolvedInstanceFieldSet field_type:PrimDouble - /// CHECK: UnresolvedInstanceFieldSet field_type:PrimNot - - /// CHECK: UnresolvedInstanceFieldGet field_type:PrimByte - /// CHECK: UnresolvedInstanceFieldGet field_type:PrimChar - /// CHECK: UnresolvedInstanceFieldGet field_type:PrimInt - /// CHECK: UnresolvedInstanceFieldGet field_type:PrimLong - /// CHECK: UnresolvedInstanceFieldGet field_type:PrimFloat - /// CHECK: UnresolvedInstanceFieldGet field_type:PrimDouble - /// CHECK: UnresolvedInstanceFieldGet field_type:PrimNot + /// CHECK: UnresolvedInstanceFieldSet field_type:Int8 + /// CHECK: UnresolvedInstanceFieldSet field_type:Uint16 + /// CHECK: UnresolvedInstanceFieldSet field_type:Int32 + /// CHECK: UnresolvedInstanceFieldSet field_type:Int64 + /// CHECK: UnresolvedInstanceFieldSet field_type:Float32 + /// CHECK: UnresolvedInstanceFieldSet field_type:Float64 + /// CHECK: UnresolvedInstanceFieldSet field_type:Reference + + /// CHECK: UnresolvedInstanceFieldGet field_type:Int8 + /// CHECK: UnresolvedInstanceFieldGet field_type:Uint16 + /// CHECK: UnresolvedInstanceFieldGet field_type:Int32 + /// CHECK: UnresolvedInstanceFieldGet field_type:Int64 + /// CHECK: UnresolvedInstanceFieldGet field_type:Float32 + /// CHECK: UnresolvedInstanceFieldGet field_type:Float64 + /// CHECK: UnresolvedInstanceFieldGet field_type:Reference static public void callUnresolvedInstanceFieldAccess(UnresolvedClass c) { Object o = new Object(); c.instanceByte = (byte)1; diff --git a/test/552-checker-sharpening/src/Main.java b/test/552-checker-sharpening/src/Main.java index 1f1920ca15..55873eabf0 100644 --- a/test/552-checker-sharpening/src/Main.java +++ b/test/552-checker-sharpening/src/Main.java @@ -63,16 +63,12 @@ public class Main { /// CHECK-START-X86_64: int Main.testSimple(int) sharpening (after) /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry - /// CHECK-START-MIPS: int Main.testSimple(int) pc_relative_fixups_mips (after) - /// CHECK: MipsComputeBaseMethodAddress - /// CHECK-NOT: MipsComputeBaseMethodAddress - /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (after) /// CHECK: X86ComputeBaseMethodAddress /// CHECK-NOT: X86ComputeBaseMethodAddress public static int testSimple(int x) { - // This call should use PC-relative dex cache array load to retrieve the target method. + // This call should use PC-relative .bss array load to retrieve the target method. return $noinline$foo(x); } @@ -104,14 +100,6 @@ public class Main { /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry - /// CHECK-START-MIPS: int Main.testDiamond(boolean, int) pc_relative_fixups_mips (after) - /// CHECK: MipsComputeBaseMethodAddress - /// CHECK-NOT: MipsComputeBaseMethodAddress - - /// CHECK-START-MIPS: int Main.testDiamond(boolean, int) pc_relative_fixups_mips (after) - /// CHECK: MipsComputeBaseMethodAddress - /// CHECK-NEXT: If - /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after) /// CHECK: X86ComputeBaseMethodAddress /// CHECK-NOT: X86ComputeBaseMethodAddress @@ -122,7 +110,7 @@ public class Main { public static int testDiamond(boolean negate, int x) { // These calls should use PC-relative loads to retrieve the target method. - // PC-relative bases used by MIPS and X86 should be pulled before the If. + // PC-relative bases used by MIPS32R2 and X86 should be pulled before the If. if (negate) { return $noinline$foo(-x); } else { @@ -130,24 +118,6 @@ public class Main { } } - /// CHECK-START-MIPS: int Main.testLoop(int[], int) pc_relative_fixups_mips (before) - /// CHECK-NOT: MipsComputeBaseMethodAddress - - /// CHECK-START-MIPS: int Main.testLoop(int[], int) pc_relative_fixups_mips (after) - /// CHECK: MipsComputeBaseMethodAddress - /// CHECK-NOT: MipsComputeBaseMethodAddress - - /// CHECK-START-MIPS: int Main.testLoop(int[], int) pc_relative_fixups_mips (after) - /// CHECK: InvokeStaticOrDirect - /// CHECK-NOT: InvokeStaticOrDirect - - /// CHECK-START-MIPS: int Main.testLoop(int[], int) pc_relative_fixups_mips (after) - /// CHECK: ArrayLength - /// CHECK-NEXT: MipsComputeBaseMethodAddress - /// CHECK-NEXT: Goto - /// CHECK: begin_block - /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry - /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (before) /// CHECK-NOT: X86ComputeBaseMethodAddress @@ -167,23 +137,13 @@ public class Main { /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry public static int testLoop(int[] array, int x) { - // PC-relative bases used by MIPS and X86 should be pulled before the loop. + // PC-relative bases used by MIPS32R2 and X86 should be pulled before the loop. for (int i : array) { x += $noinline$foo(i); } return x; } - /// CHECK-START-MIPS: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_mips (before) - /// CHECK-NOT: MipsComputeBaseMethodAddress - - /// CHECK-START-MIPS: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_mips (after) - /// CHECK: If - /// CHECK: begin_block - /// CHECK: ArrayLength - /// CHECK-NEXT: MipsComputeBaseMethodAddress - /// CHECK-NEXT: Goto - /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (before) /// CHECK-NOT: X86ComputeBaseMethodAddress @@ -195,7 +155,7 @@ public class Main { /// CHECK-NEXT: Goto public static int testLoopWithDiamond(int[] array, boolean negate, int x) { - // PC-relative bases used by MIPS and X86 should be pulled before the loop + // PC-relative bases used by MIPS32R2 and X86 should be pulled before the loop // but not outside the if. if (array != null) { for (int i : array) { diff --git a/test/566-polymorphic-inlining/run b/test/566-polymorphic-inlining/run new file mode 100644 index 0000000000..2919f46d82 --- /dev/null +++ b/test/566-polymorphic-inlining/run @@ -0,0 +1,20 @@ +#!/bin/bash +# +# Copyright 2017 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. + +# -Xjitinitialsize:32M to prevent profiling info creation failure. +exec ${RUN} \ + --runtime-option -Xjitinitialsize:32M \ + "${@}" diff --git a/test/597-deopt-invoke-stub/src/Main.java b/test/597-deopt-invoke-stub/src/Main.java index 075178361b..8c6f0697e5 100644 --- a/test/597-deopt-invoke-stub/src/Main.java +++ b/test/597-deopt-invoke-stub/src/Main.java @@ -16,8 +16,8 @@ public class Main implements Runnable { static final int numberOfThreads = 2; - volatile static boolean sExitFlag = false; - volatile static boolean sEntered = false; + static boolean sExitFlag = false; + static boolean sEntered = false; int threadIndex; private static native void deoptimizeAll(); @@ -46,8 +46,17 @@ public class Main implements Runnable { private static int $noinline$bar() { // Should be entered via interpreter bridge. assertIsInterpreted(); - sEntered = true; - while (!sExitFlag) {} + synchronized (Main.class) { + sEntered = true; + Main.class.notify(); + while (!sExitFlag) { + try { + Main.class.wait(); + } catch (InterruptedException e) { + throw new Error("Unexpected exception."); + } + } + } assertIsInterpreted(); return 0x1234; } @@ -62,11 +71,20 @@ public class Main implements Runnable { public void run() { if (threadIndex == 0) { - while (!sEntered) { - Thread.yield(); + synchronized (Main.class) { + while (!sEntered) { + try { + Main.class.wait(); + } catch (InterruptedException e) { + throw new Error("Unexpected exception."); + } + } } deoptimizeAll(); - sExitFlag = true; + synchronized (Main.class) { + sExitFlag = true; + Main.class.notify(); + } } else { ensureJitCompiled(Main.class, "$noinline$foo"); $noinline$foo(); diff --git a/test/651-checker-byte-simd-minmax/src/Main.java b/test/651-checker-byte-simd-minmax/src/Main.java index e018b56dd5..9643b90d15 100644 --- a/test/651-checker-byte-simd-minmax/src/Main.java +++ b/test/651-checker-byte-simd-minmax/src/Main.java @@ -165,6 +165,28 @@ public class Main { } } + /// CHECK-START: void Main.doitMin100(byte[], byte[]) loop_optimization (before) + /// CHECK-DAG: <<I100:i\d+>> IntConstant 100 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:b\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Min:i\d+>> InvokeStaticOrDirect [<<Get>>,<<I100>>] intrinsic:MathMinIntInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Min>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.doitMin100(byte[], byte[]) loop_optimization (after) + /// CHECK-DAG: <<I100:i\d+>> IntConstant 100 loop:none + /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I100>>] loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get>>,<<Repl>>] unsigned:false loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Min>>] loop:<<Loop>> outer_loop:none + private static void doitMin100(byte[] x, byte[] y) { + int min = Math.min(x.length, y.length); + for (int i = 0; i < min; i++) { + x[i] = (byte) Math.min(y[i], 100); + } + } + public static void main(String[] args) { // Initialize cross-values for all possible values. int total = 256 * 256; @@ -202,6 +224,11 @@ public class Main { byte expected = (byte) Math.max(y[i] & 0xff, z[i] & 0xff); expectEquals(expected, x[i]); } + doitMin100(x, y); + for (int i = 0; i < total; i++) { + byte expected = (byte) Math.min(y[i], 100); + expectEquals(expected, x[i]); + } System.out.println("passed"); } diff --git a/test/651-checker-char-simd-minmax/src/Main.java b/test/651-checker-char-simd-minmax/src/Main.java index 57cad9b34a..8a0262cfcd 100644 --- a/test/651-checker-char-simd-minmax/src/Main.java +++ b/test/651-checker-char-simd-minmax/src/Main.java @@ -89,6 +89,28 @@ public class Main { } } + /// CHECK-START: void Main.doitMin100(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<I100:i\d+>> IntConstant 100 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Min:i\d+>> InvokeStaticOrDirect [<<Get>>,<<I100>>] intrinsic:MathMinIntInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<Min>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.doitMin100(char[], char[]) loop_optimization (after) + /// CHECK-DAG: <<I100:i\d+>> IntConstant 100 loop:none + /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I100>>] loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get>>,<<Repl>>] unsigned:true loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Min>>] loop:<<Loop>> outer_loop:none + private static void doitMin100(char[] x, char[] y) { + int min = Math.min(x.length, y.length); + for (int i = 0; i < min; i++) { + x[i] = (char) Math.min(y[i], 100); + } + } + public static void main(String[] args) { char[] interesting = { 0x0000, 0x0001, 0x007f, 0x0080, 0x0081, 0x00ff, @@ -124,6 +146,11 @@ public class Main { char expected = (char) Math.max(y[i], z[i]); expectEquals(expected, x[i]); } + doitMin100(x, y); + for (int i = 0; i < total; i++) { + char expected = (char) Math.min(y[i], 100); + expectEquals(expected, x[i]); + } System.out.println("passed"); } diff --git a/test/651-checker-short-simd-minmax/src/Main.java b/test/651-checker-short-simd-minmax/src/Main.java index 4f2a7a4440..ffbf73bd62 100644 --- a/test/651-checker-short-simd-minmax/src/Main.java +++ b/test/651-checker-short-simd-minmax/src/Main.java @@ -165,6 +165,28 @@ public class Main { } } + /// CHECK-START: void Main.doitMin100(short[], short[]) loop_optimization (before) + /// CHECK-DAG: <<I100:i\d+>> IntConstant 100 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Min:i\d+>> InvokeStaticOrDirect [<<Get>>,<<I100>>] intrinsic:MathMinIntInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Min>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.doitMin100(short[], short[]) loop_optimization (after) + /// CHECK-DAG: <<I100:i\d+>> IntConstant 100 loop:none + /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I100>>] loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get>>,<<Repl>>] unsigned:false loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Min>>] loop:<<Loop>> outer_loop:none + private static void doitMin100(short[] x, short[] y) { + int min = Math.min(x.length, y.length); + for (int i = 0; i < min; i++) { + x[i] = (short) Math.min(y[i], 100); + } + } + public static void main(String[] args) { short[] interesting = { (short) 0x0000, (short) 0x0001, (short) 0x007f, @@ -216,6 +238,11 @@ public class Main { short expected = (short) Math.max(y[i] & 0xffff, z[i] & 0xffff); expectEquals(expected, x[i]); } + doitMin100(x, y); + for (int i = 0; i < total; i++) { + short expected = (short) Math.min(y[i], 100); + expectEquals(expected, x[i]); + } System.out.println("passed"); } diff --git a/test/656-checker-simd-opt/src/Main.java b/test/656-checker-simd-opt/src/Main.java index 091633ff34..39a126f5d3 100644 --- a/test/656-checker-simd-opt/src/Main.java +++ b/test/656-checker-simd-opt/src/Main.java @@ -92,7 +92,91 @@ public class Main { } } - public static void main(String[] args) { + /// CHECK-START: long Main.longInductionReduction(long[]) loop_optimization (before) + /// CHECK-DAG: <<L0:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<L1:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<I0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Get:j\d+>> ArrayGet [{{l\d+}},<<I0>>] loop:none + /// CHECK-DAG: <<Phi1:j\d+>> Phi [<<L0>>,<<Add1:j\d+>>] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<L1>>,<<Add2:j\d+>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Add2>> Add [<<Phi2>>,<<Get>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Add1>> Add [<<Phi1>>,<<L1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.longInductionReduction(long[]) loop_optimization (after) + /// CHECK-DAG: <<L0:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<L1:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<L2:j\d+>> LongConstant 2 loop:none + /// CHECK-DAG: <<I0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Get:j\d+>> ArrayGet [{{l\d+}},<<I0>>] loop:none + /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<Get>>] loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<L1>>] loop:none + /// CHECK-DAG: <<Phi1:j\d+>> Phi [<<L0>>,{{j\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecAdd [<<Phi2>>,<<Rep>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<L2>>] loop:<<Loop>> outer_loop:none + static long longInductionReduction(long[] y) { + long x = 1; + for (long i = 0; i < 10; i++) { + x += y[0]; + } + return x; + } + + /// CHECK-START: void Main.intVectorLongInvariant(int[], long[]) loop_optimization (before) + /// CHECK-DAG: <<I0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Get:j\d+>> ArrayGet [{{l\d+}},<<I0>>] loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi [<<I0>>,<<Add:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Cnv:i\d+>> TypeConversion [<<Get>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Add>> Add [<<Phi>>,<<I1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.intVectorLongInvariant(int[], long[]) loop_optimization (after) + /// CHECK-DAG: <<I0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<I4:i\d+>> IntConstant 4 loop:none + /// CHECK-DAG: <<Get:j\d+>> ArrayGet [{{l\d+}},<<I0>>] loop:none + /// CHECK-DAG: <<Cnv:i\d+>> TypeConversion [<<Get>>] loop:none + /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<Cnv>>] loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi [<<I0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Rep>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi>>,<<I4>>] loop:<<Loop>> outer_loop:none + static void intVectorLongInvariant(int[] x, long[] y) { + for (int i = 0; i < 100; i++) { + x[i] = (int) y[0]; + } + } + + /// CHECK-START: void Main.longCanBeDoneWithInt(int[], int[]) loop_optimization (before) + /// CHECK-DAG: <<I0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<L1:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi [<<I0>>,<<Add:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Get:i\d+>> ArrayGet [{{l\d+}},<<Phi>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<AddL:j\d+>> Add [<<Cnv1>>,<<L1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:i\d+>> TypeConversion [<<AddL>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Add>> Add [<<Phi>>,<<I1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: void Main.longCanBeDoneWithInt(int[], int[]) loop_optimization (after) + /// CHECK-DAG: <<I0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<I4:i\d+>> IntConstant 4 loop:none + /// CHECK-DAG: <<L1:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Cnv:i\d+>> TypeConversion [<<L1>>] loop:none + /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<Cnv>>] loop:none + /// CHECK-DAG: <<Phi:i\d+>> Phi [<<I0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Add:d\d+>> VecAdd [<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Add>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi>>,<<I4>>] loop:<<Loop>> outer_loop:none + static void longCanBeDoneWithInt(int[] x, int[] y) { + for (int i = 0; i < 100; i++) { + x[i] = (int) (y[i] + 1L); + } + } + + static void testUnroll() { float[] x = new float[100]; float[] y = new float[100]; for (int i = 0; i < 100; i++) { @@ -104,51 +188,89 @@ public class Main { expectEquals(5.0f, x[i]); expectEquals(2.0f, y[i]); } - { - int[] a = new int[100]; - int[] b = new int[100]; - for (int i = 0; i < 100; i++) { - a[i] = 0; - b[i] = i; - } - stencil(a, b, 100); - for (int i = 1; i < 99; i++) { - int e = i + i + i; - expectEquals(e, a[i]); - expectEquals(i, b[i]); - } - } - { - int[] a = new int[100]; - int[] b = new int[100]; - for (int i = 0; i < 100; i++) { - a[i] = 0; - b[i] = i; - } - stencilSubInt(a, b, 100); - for (int i = 1; i < 99; i++) { - int e = i + i + i; - expectEquals(e, a[i]); - expectEquals(i, b[i]); - } - } - { - int[] a = new int[100]; - int[] b = new int[100]; - for (int i = 0; i < 100; i++) { - a[i] = 0; - b[i] = i; - } - stencilAddInt(a, b, 100); - for (int i = 1; i < 99; i++) { - int e = i + i + i; - expectEquals(e, a[i]); - expectEquals(i, b[i]); - } + } + + static void testStencil1() { + int[] a = new int[100]; + int[] b = new int[100]; + for (int i = 0; i < 100; i++) { + a[i] = 0; + b[i] = i; + } + stencil(a, b, 100); + for (int i = 1; i < 99; i++) { + int e = i + i + i; + expectEquals(e, a[i]); + expectEquals(i, b[i]); + } + } + + static void testStencil2() { + int[] a = new int[100]; + int[] b = new int[100]; + for (int i = 0; i < 100; i++) { + a[i] = 0; + b[i] = i; + } + stencilSubInt(a, b, 100); + for (int i = 1; i < 99; i++) { + int e = i + i + i; + expectEquals(e, a[i]); + expectEquals(i, b[i]); } + } + + static void testStencil3() { + int[] a = new int[100]; + int[] b = new int[100]; + for (int i = 0; i < 100; i++) { + a[i] = 0; + b[i] = i; + } + stencilAddInt(a, b, 100); + for (int i = 1; i < 99; i++) { + int e = i + i + i; + expectEquals(e, a[i]); + expectEquals(i, b[i]); + } + } + + static void testTypes() { + int[] a = new int[100]; + int[] b = new int[100]; + long[] l = { 3 }; + expectEquals(31, longInductionReduction(l)); + intVectorLongInvariant(a, l); + for (int i = 0; i < 100; i++) { + expectEquals(3, a[i]); + } + longCanBeDoneWithInt(b, a); + for (int i = 0; i < 100; i++) { + expectEquals(4, b[i]); + } + } + + public static void main(String[] args) { + testUnroll(); + testStencil1(); + testStencil2(); + testStencil3(); + testTypes(); System.out.println("passed"); } + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + private static void expectEquals(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + private static void expectEquals(float expected, float result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); diff --git a/test/660-checker-simd-sad-byte/expected.txt b/test/660-checker-simd-sad-byte/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/660-checker-simd-sad-byte/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/660-checker-simd-sad-byte/info.txt b/test/660-checker-simd-sad-byte/info.txt new file mode 100644 index 0000000000..b56c119129 --- /dev/null +++ b/test/660-checker-simd-sad-byte/info.txt @@ -0,0 +1 @@ +Functional tests on SAD vectorization. diff --git a/test/660-checker-simd-sad-byte/src/Main.java b/test/660-checker-simd-sad-byte/src/Main.java new file mode 100644 index 0000000000..72d1c24dbe --- /dev/null +++ b/test/660-checker-simd-sad-byte/src/Main.java @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * Tests for SAD (sum of absolute differences). + */ +public class Main { + + // TODO: lower precision still coming, b/64091002 + + private static byte sadByte2Byte(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + byte sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(b1[i] - b2[i]); + } + return sad; + } + + private static byte sadByte2ByteAlt(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + byte sad = 0; + for (int i = 0; i < min_length; i++) { + byte s = b1[i]; + byte p = b2[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + private static byte sadByte2ByteAlt2(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + byte sad = 0; + for (int i = 0; i < min_length; i++) { + byte s = b1[i]; + byte p = b2[i]; + int x = s - p; + if (x < 0) x = -x; + sad += x; + } + return sad; + } + + private static short sadByte2Short(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + short sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(b1[i] - b2[i]); + } + return sad; + } + + private static short sadByte2ShortAlt(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + short sad = 0; + for (int i = 0; i < min_length; i++) { + byte s = b1[i]; + byte p = b2[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + private static short sadByte2ShortAlt2(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + short sad = 0; + for (int i = 0; i < min_length; i++) { + byte s = b1[i]; + byte p = b2[i]; + int x = s - p; + if (x < 0) x = -x; + sad += x; + } + return sad; + } + + /// CHECK-START: int Main.sadByte2Int(byte[], byte[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadByte2Int(byte[], byte[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons16:i\d+>> IntConstant 16 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons16>>] loop:<<Loop>> outer_loop:none + private static int sadByte2Int(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(b1[i] - b2[i]); + } + return sad; + } + + /// CHECK-START: int Main.sadByte2IntAlt(byte[], byte[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadByte2IntAlt(byte[], byte[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons16:i\d+>> IntConstant 16 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons16>>] loop:<<Loop>> outer_loop:none + private static int sadByte2IntAlt(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + byte s = b1[i]; + byte p = b2[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + /// CHECK-START: int Main.sadByte2IntAlt2(byte[], byte[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadByte2IntAlt2(byte[], byte[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons16:i\d+>> IntConstant 16 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons16>>] loop:<<Loop>> outer_loop:none + private static int sadByte2IntAlt2(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + byte s = b1[i]; + byte p = b2[i]; + int x = s - p; + if (x < 0) x = -x; + sad += x; + } + return sad; + } + + /// CHECK-START: long Main.sadByte2Long(byte[], byte[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadByte2Long(byte[], byte[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons16:i\d+>> IntConstant 16 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons16>>] loop:<<Loop>> outer_loop:none + private static long sadByte2Long(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + long sad = 0; + for (int i = 0; i < min_length; i++) { + long x = b1[i]; + long y = b2[i]; + sad += Math.abs(x - y); + } + return sad; + } + + /// CHECK-START: long Main.sadByte2LongAt1(byte[], byte[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadByte2LongAt1(byte[], byte[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons16:i\d+>> IntConstant 16 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons16>>] loop:<<Loop>> outer_loop:none + private static long sadByte2LongAt1(byte[] b1, byte[] b2) { + int min_length = Math.min(b1.length, b2.length); + long sad = 1; // starts at 1 + for (int i = 0; i < min_length; i++) { + long x = b1[i]; + long y = b2[i]; + sad += Math.abs(x - y); + } + return sad; + } + + public static void main(String[] args) { + // Cross-test the two most extreme values individually. + byte[] b1 = { 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + byte[] b2 = { 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + expectEquals(-1, sadByte2Byte(b1, b2)); + expectEquals(-1, sadByte2Byte(b2, b1)); + expectEquals(-1, sadByte2ByteAlt(b1, b2)); + expectEquals(-1, sadByte2ByteAlt(b2, b1)); + expectEquals(-1, sadByte2ByteAlt2(b1, b2)); + expectEquals(-1, sadByte2ByteAlt2(b2, b1)); + expectEquals(255, sadByte2Short(b1, b2)); + expectEquals(255, sadByte2Short(b2, b1)); + expectEquals(255, sadByte2ShortAlt(b1, b2)); + expectEquals(255, sadByte2ShortAlt(b2, b1)); + expectEquals(255, sadByte2ShortAlt2(b1, b2)); + expectEquals(255, sadByte2ShortAlt2(b2, b1)); + expectEquals(255, sadByte2Int(b1, b2)); + expectEquals(255, sadByte2Int(b2, b1)); + expectEquals(255, sadByte2IntAlt(b1, b2)); + expectEquals(255, sadByte2IntAlt(b2, b1)); + expectEquals(255, sadByte2IntAlt2(b1, b2)); + expectEquals(255, sadByte2IntAlt2(b2, b1)); + expectEquals(255, sadByte2Long(b1, b2)); + expectEquals(255L, sadByte2Long(b2, b1)); + expectEquals(256L, sadByte2LongAt1(b1, b2)); + expectEquals(256L, sadByte2LongAt1(b2, b1)); + + // Use cross-values to test all cases. + // One for scalar cleanup. + int n = 256; + int m = n * n + 1; + int k = 0; + b1 = new byte[m]; + b2 = new byte[m]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + b1[k] = (byte) i; + b2[k] = (byte) j; + k++; + } + } + b1[k] = 10; + b2[k] = 2; + expectEquals(8, sadByte2Byte(b1, b2)); + expectEquals(8, sadByte2ByteAlt(b1, b2)); + expectEquals(8, sadByte2ByteAlt2(b1, b2)); + expectEquals(21768, sadByte2Short(b1, b2)); + expectEquals(21768, sadByte2ShortAlt(b1, b2)); + expectEquals(21768, sadByte2ShortAlt2(b1, b2)); + expectEquals(5592328, sadByte2Int(b1, b2)); + expectEquals(5592328, sadByte2IntAlt(b1, b2)); + expectEquals(5592328, sadByte2IntAlt2(b1, b2)); + expectEquals(5592328L, sadByte2Long(b1, b2)); + expectEquals(5592329L, sadByte2LongAt1(b1, b2)); + + System.out.println("passed"); + } + + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + private static void expectEquals(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/660-checker-simd-sad-char/expected.txt b/test/660-checker-simd-sad-char/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/660-checker-simd-sad-char/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/660-checker-simd-sad-char/info.txt b/test/660-checker-simd-sad-char/info.txt new file mode 100644 index 0000000000..b56c119129 --- /dev/null +++ b/test/660-checker-simd-sad-char/info.txt @@ -0,0 +1 @@ +Functional tests on SAD vectorization. diff --git a/test/660-checker-simd-sad-char/src/Main.java b/test/660-checker-simd-sad-char/src/Main.java new file mode 100644 index 0000000000..2535d49b9c --- /dev/null +++ b/test/660-checker-simd-sad-char/src/Main.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * Tests for SAD (sum of absolute differences). + */ +public class Main { + + // TODO: lower precision still coming, b/64091002 + + // TODO: consider unsigned SAD too, b/64091002 + + private static char sadChar2Char(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + char sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(s1[i] - s2[i]); + } + return sad; + } + + private static char sadChar2CharAlt(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + char sad = 0; + for (int i = 0; i < min_length; i++) { + char s = s1[i]; + char p = s2[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + private static char sadChar2CharAlt2(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + char sad = 0; + for (int i = 0; i < min_length; i++) { + char s = s1[i]; + char p = s2[i]; + int x = s - p; + if (x < 0) x = -x; + sad += x; + } + return sad; + } + + /// CHECK-START: int Main.sadChar2Int(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadChar2Int(char[], char[]) loop_optimization (after) + /// CHECK-NOT: VecSADAccumulate + private static int sadChar2Int(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(s1[i] - s2[i]); + } + return sad; + } + + /// CHECK-START: int Main.sadChar2IntAlt(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadChar2IntAlt(char[], char[]) loop_optimization (after) + /// CHECK-NOT: VecSADAccumulate + private static int sadChar2IntAlt(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + char s = s1[i]; + char p = s2[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + /// CHECK-START: int Main.sadChar2IntAlt2(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadChar2IntAlt2(char[], char[]) loop_optimization (after) + /// CHECK-NOT: VecSADAccumulate + private static int sadChar2IntAlt2(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + char s = s1[i]; + char p = s2[i]; + int x = s - p; + if (x < 0) x = -x; + sad += x; + } + return sad; + } + + /// CHECK-START: long Main.sadChar2Long(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadChar2Long(char[], char[]) loop_optimization (after) + /// CHECK-NOT: VecSADAccumulate + private static long sadChar2Long(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + long sad = 0; + for (int i = 0; i < min_length; i++) { + long x = s1[i]; + long y = s2[i]; + sad += Math.abs(x - y); + } + return sad; + } + + /// CHECK-START: long Main.sadChar2LongAt1(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadChar2LongAt1(char[], char[]) loop_optimization (after) + /// CHECK-NOT: VecSADAccumulate + private static long sadChar2LongAt1(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + long sad = 1; // starts at 1 + for (int i = 0; i < min_length; i++) { + long x = s1[i]; + long y = s2[i]; + sad += Math.abs(x - y); + } + return sad; + } + + public static void main(String[] args) { + // Cross-test the two most extreme values individually. + char[] s1 = { 0, 0x8000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + char[] s2 = { 0, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + expectEquals(1, sadChar2Char(s1, s2)); + expectEquals(1, sadChar2Char(s2, s1)); + expectEquals(1, sadChar2CharAlt(s1, s2)); + expectEquals(1, sadChar2CharAlt(s2, s1)); + expectEquals(1, sadChar2CharAlt2(s1, s2)); + expectEquals(1, sadChar2CharAlt2(s2, s1)); + expectEquals(1, sadChar2Int(s1, s2)); + expectEquals(1, sadChar2Int(s2, s1)); + expectEquals(1, sadChar2IntAlt(s1, s2)); + expectEquals(1, sadChar2IntAlt(s2, s1)); + expectEquals(1, sadChar2IntAlt2(s1, s2)); + expectEquals(1, sadChar2IntAlt2(s2, s1)); + expectEquals(1L, sadChar2Long(s1, s2)); + expectEquals(1L, sadChar2Long(s2, s1)); + expectEquals(2L, sadChar2LongAt1(s1, s2)); + expectEquals(2L, sadChar2LongAt1(s2, s1)); + + // Use cross-values to test all cases. + char[] interesting = { + (char) 0x0000, + (char) 0x0001, + (char) 0x0002, + (char) 0x1234, + (char) 0x8000, + (char) 0x8001, + (char) 0x7fff, + (char) 0xffff + }; + int n = interesting.length; + int m = n * n + 1; + s1 = new char[m]; + s2 = new char[m]; + int k = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + s1[k] = interesting[i]; + s2[k] = interesting[j]; + k++; + } + } + s1[k] = 10; + s2[k] = 2; + expectEquals(56196, sadChar2Char(s1, s2)); + expectEquals(56196, sadChar2CharAlt(s1, s2)); + expectEquals(56196, sadChar2CharAlt2(s1, s2)); + expectEquals(1497988, sadChar2Int(s1, s2)); + expectEquals(1497988, sadChar2IntAlt(s1, s2)); + expectEquals(1497988, sadChar2IntAlt2(s1, s2)); + expectEquals(1497988L, sadChar2Long(s1, s2)); + expectEquals(1497989L, sadChar2LongAt1(s1, s2)); + + System.out.println("passed"); + } + + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + private static void expectEquals(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/660-checker-simd-sad-int/expected.txt b/test/660-checker-simd-sad-int/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/660-checker-simd-sad-int/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/660-checker-simd-sad-int/info.txt b/test/660-checker-simd-sad-int/info.txt new file mode 100644 index 0000000000..b56c119129 --- /dev/null +++ b/test/660-checker-simd-sad-int/info.txt @@ -0,0 +1 @@ +Functional tests on SAD vectorization. diff --git a/test/660-checker-simd-sad-int/src/Main.java b/test/660-checker-simd-sad-int/src/Main.java new file mode 100644 index 0000000000..0daeeddc69 --- /dev/null +++ b/test/660-checker-simd-sad-int/src/Main.java @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * Tests for SAD (sum of absolute differences). + */ +public class Main { + + /// CHECK-START: int Main.sadInt2Int(int[], int[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadInt2Int(int[], int[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons4:i\d+>> IntConstant 4 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons4>>] loop:<<Loop>> outer_loop:none + private static int sadInt2Int(int[] x, int[] y) { + int min_length = Math.min(x.length, y.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(x[i] - y[i]); + } + return sad; + } + + /// CHECK-START: int Main.sadInt2IntAlt(int[], int[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub1:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub2:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Select:i\d+>> Select [<<Sub2>>,<<Sub1>>,{{z\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Select>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + // No ABS? No SAD! + // + /// CHECK-START-ARM64: int Main.sadInt2IntAlt(int[], int[]) loop_optimization (after) + /// CHECK-NOT: VecSADAccumulate + private static int sadInt2IntAlt(int[] x, int[] y) { + int min_length = Math.min(x.length, y.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + int s = x[i]; + int p = y[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + /// CHECK-START: int Main.sadInt2IntAlt2(int[], int[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadInt2IntAlt2(int[], int[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons4:i\d+>> IntConstant 4 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons4>>] loop:<<Loop>> outer_loop:none + private static int sadInt2IntAlt2(int[] x, int[] y) { + int min_length = Math.min(x.length, y.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + int s = x[i]; + int p = y[i]; + int m = s - p; + if (m < 0) m = -m; + sad += m; + } + return sad; + } + + /// CHECK-START: long Main.sadInt2Long(int[], int[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadInt2Long(int[], int[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons4:i\d+>> IntConstant 4 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons4>>] loop:<<Loop>> outer_loop:none + private static long sadInt2Long(int[] x, int[] y) { + int min_length = Math.min(x.length, y.length); + long sad = 0; + for (int i = 0; i < min_length; i++) { + long s = x[i]; + long p = y[i]; + sad += Math.abs(s - p); + } + return sad; + } + + /// CHECK-START: long Main.sadInt2LongAt1(int[], int[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadInt2LongAt1(int[], int[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons4:i\d+>> IntConstant 4 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons4>>] loop:<<Loop>> outer_loop:none + private static long sadInt2LongAt1(int[] x, int[] y) { + int min_length = Math.min(x.length, y.length); + long sad = 1; // starts at 1 + for (int i = 0; i < min_length; i++) { + long s = x[i]; + long p = y[i]; + sad += Math.abs(s - p); + } + return sad; + } + + public static void main(String[] args) { + // Cross-test the two most extreme values individually. + int[] x = { 0, Integer.MAX_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int[] y = { 0, Integer.MIN_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + expectEquals(1, sadInt2Int(x, y)); + expectEquals(1, sadInt2Int(y, x)); + expectEquals(-1, sadInt2IntAlt(x, y)); + expectEquals(-1, sadInt2IntAlt(y, x)); + expectEquals(1, sadInt2IntAlt2(x, y)); + expectEquals(1, sadInt2IntAlt2(y, x)); + expectEquals(4294967295L, sadInt2Long(x, y)); + expectEquals(4294967295L, sadInt2Long(y, x)); + expectEquals(4294967296L, sadInt2LongAt1(x, y)); + expectEquals(4294967296L, sadInt2LongAt1(y, x)); + + // Use cross-values for the interesting values. + int[] interesting = { + 0x00000000, 0x00000001, 0x00007fff, 0x00008000, 0x00008001, 0x0000ffff, + 0x00010000, 0x00010001, 0x00017fff, 0x00018000, 0x00018001, 0x0001ffff, + 0x7fff0000, 0x7fff0001, 0x7fff7fff, 0x7fff8000, 0x7fff8001, 0x7fffffff, + 0x80000000, 0x80000001, 0x80007fff, 0x80008000, 0x80008001, 0x8000ffff, + 0x80010000, 0x80010001, 0x80017fff, 0x80018000, 0x80018001, 0x8001ffff, + 0xffff0000, 0xffff0001, 0xffff7fff, 0xffff8000, 0xffff8001, 0xffffffff + }; + int n = interesting.length; + int m = n * n + 1; + x = new int[m]; + y = new int[m]; + int k = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + x[k] = interesting[i]; + y[k] = interesting[j]; + k++; + } + } + x[k] = 10; + y[k] = 2; + expectEquals(8, sadInt2Int(x, y)); + expectEquals(-13762600, sadInt2IntAlt(x, y)); + expectEquals(8, sadInt2IntAlt2(x, y)); + expectEquals(2010030931928L, sadInt2Long(x, y)); + expectEquals(2010030931929L, sadInt2LongAt1(x, y)); + + System.out.println("passed"); + } + + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + private static void expectEquals(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/660-checker-simd-sad-long/expected.txt b/test/660-checker-simd-sad-long/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/660-checker-simd-sad-long/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/660-checker-simd-sad-long/info.txt b/test/660-checker-simd-sad-long/info.txt new file mode 100644 index 0000000000..b56c119129 --- /dev/null +++ b/test/660-checker-simd-sad-long/info.txt @@ -0,0 +1 @@ +Functional tests on SAD vectorization. diff --git a/test/660-checker-simd-sad-long/src/Main.java b/test/660-checker-simd-sad-long/src/Main.java new file mode 100644 index 0000000000..06f62bd031 --- /dev/null +++ b/test/660-checker-simd-sad-long/src/Main.java @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * Tests for SAD (sum of absolute differences). + */ +public class Main { + + /// CHECK-START: long Main.sadLong2Long(long[], long[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadLong2Long(long[], long[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons2:i\d+>> IntConstant 2 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons2>>] loop:<<Loop>> outer_loop:none + private static long sadLong2Long(long[] x, long[] y) { + int min_length = Math.min(x.length, y.length); + long sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(x[i] - y[i]); + } + return sad; + } + + /// CHECK-START: long Main.sadLong2LongAlt(long[], long[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub1:j\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub2:j\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Select:j\d+>> Select [<<Sub2>>,<<Sub1>>,{{z\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Select>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + // No ABS? No SAD! + // + /// CHECK-START: long Main.sadLong2LongAlt(long[], long[]) loop_optimization (after) + /// CHECK-NOT: VecSADAccumulate + private static long sadLong2LongAlt(long[] x, long[] y) { + int min_length = Math.min(x.length, y.length); + long sad = 0; + for (int i = 0; i < min_length; i++) { + long s = x[i]; + long p = y[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + /// CHECK-START: long Main.sadLong2LongAlt2(long[], long[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadLong2LongAlt2(long[], long[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons2:i\d+>> IntConstant 2 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons2>>] loop:<<Loop>> outer_loop:none + private static long sadLong2LongAlt2(long[] x, long[] y) { + int min_length = Math.min(x.length, y.length); + long sad = 0; + for (int i = 0; i < min_length; i++) { + long s = x[i]; + long p = y[i]; + long m = s - p; + if (m < 0) m = -m; + sad += m; + } + return sad; + } + + /// CHECK-START: long Main.sadLong2LongAt1(long[], long[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:j\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadLong2LongAt1(long[], long[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons2:i\d+>> IntConstant 2 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons2>>] loop:<<Loop>> outer_loop:none + private static long sadLong2LongAt1(long[] x, long[] y) { + int min_length = Math.min(x.length, y.length); + long sad = 1; // starts at 1 + for (int i = 0; i < min_length; i++) { + sad += Math.abs(x[i] - y[i]); + } + return sad; + } + + public static void main(String[] args) { + // Cross-test the two most extreme values individually. + long[] x = { 0, Long.MIN_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + long[] y = { 0, Long.MAX_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + expectEquals(1L, sadLong2Long(x, y)); + expectEquals(1L, sadLong2Long(y, x)); + expectEquals(-1L, sadLong2LongAlt(x, y)); + expectEquals(-1L, sadLong2LongAlt(y, x)); + expectEquals(1L, sadLong2LongAlt2(x, y)); + expectEquals(1L, sadLong2LongAlt2(y, x)); + expectEquals(2L, sadLong2LongAt1(x, y)); + expectEquals(2L, sadLong2LongAt1(y, x)); + + // Use cross-values for the interesting values. + long[] interesting = { + 0x0000000000000000L, 0x0000000000000001L, 0x000000007fffffffL, + 0x0000000080000000L, 0x0000000080000001L, 0x00000000ffffffffL, + 0x0000000100000000L, 0x0000000100000001L, 0x000000017fffffffL, + 0x0000000180000000L, 0x0000000180000001L, 0x00000001ffffffffL, + 0x7fffffff00000000L, 0x7fffffff00000001L, 0x7fffffff7fffffffL, + 0x7fffffff80000000L, 0x7fffffff80000001L, 0x7fffffffffffffffL, + 0x8000000000000000L, 0x8000000000000001L, 0x800000007fffffffL, + 0x8000000080000000L, 0x8000000080000001L, 0x80000000ffffffffL, + 0x8000000100000000L, 0x8000000100000001L, 0x800000017fffffffL, + 0x8000000180000000L, 0x8000000180000001L, 0x80000001ffffffffL, + 0xffffffff00000000L, 0xffffffff00000001L, 0xffffffff7fffffffL, + 0xffffffff80000000L, 0xffffffff80000001L, 0xffffffffffffffffL + }; + int n = interesting.length; + int m = n * n + 1; + x = new long[m]; + y = new long[m]; + int k = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + x[k] = interesting[i]; + y[k] = interesting[j]; + k++; + } + } + x[k] = 10; + y[k] = 2; + expectEquals(8L, sadLong2Long(x, y)); + expectEquals(-901943132200L, sadLong2LongAlt(x, y)); + expectEquals(8L, sadLong2LongAlt2(x, y)); + expectEquals(9L, sadLong2LongAt1(x, y)); + + System.out.println("passed"); + } + + private static void expectEquals(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/660-checker-simd-sad-short/expected.txt b/test/660-checker-simd-sad-short/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/660-checker-simd-sad-short/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/660-checker-simd-sad-short/info.txt b/test/660-checker-simd-sad-short/info.txt new file mode 100644 index 0000000000..b56c119129 --- /dev/null +++ b/test/660-checker-simd-sad-short/info.txt @@ -0,0 +1 @@ +Functional tests on SAD vectorization. diff --git a/test/660-checker-simd-sad-short/src/Main.java b/test/660-checker-simd-sad-short/src/Main.java new file mode 100644 index 0000000000..d94308e24d --- /dev/null +++ b/test/660-checker-simd-sad-short/src/Main.java @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * Tests for SAD (sum of absolute differences). + */ +public class Main { + + // TODO: lower precision still coming, b/64091002 + + private static short sadShort2Short(short[] s1, short[] s2) { + int min_length = Math.min(s1.length, s2.length); + short sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(s1[i] - s2[i]); + } + return sad; + } + + private static short sadShort2ShortAlt(short[] s1, short[] s2) { + int min_length = Math.min(s1.length, s2.length); + short sad = 0; + for (int i = 0; i < min_length; i++) { + short s = s1[i]; + short p = s2[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + private static short sadShort2ShortAlt2(short[] s1, short[] s2) { + int min_length = Math.min(s1.length, s2.length); + short sad = 0; + for (int i = 0; i < min_length; i++) { + short s = s1[i]; + short p = s2[i]; + int x = s - p; + if (x < 0) x = -x; + sad += x; + } + return sad; + } + + /// CHECK-START: int Main.sadShort2Int(short[], short[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadShort2Int(short[], short[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none + private static int sadShort2Int(short[] s1, short[] s2) { + int min_length = Math.min(s1.length, s2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(s1[i] - s2[i]); + } + return sad; + } + + /// CHECK-START: int Main.sadShort2IntAlt(short[], short[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadShort2IntAlt(short[], short[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none + private static int sadShort2IntAlt(short[] s1, short[] s2) { + int min_length = Math.min(s1.length, s2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + short s = s1[i]; + short p = s2[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + /// CHECK-START: int Main.sadShort2IntAlt2(short[], short[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadShort2IntAlt2(short[], short[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none + private static int sadShort2IntAlt2(short[] s1, short[] s2) { + int min_length = Math.min(s1.length, s2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + short s = s1[i]; + short p = s2[i]; + int x = s - p; + if (x < 0) x = -x; + sad += x; + } + return sad; + } + + /// CHECK-START: long Main.sadShort2Long(short[], short[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadShort2Long(short[], short[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none + private static long sadShort2Long(short[] s1, short[] s2) { + int min_length = Math.min(s1.length, s2.length); + long sad = 0; + for (int i = 0; i < min_length; i++) { + long x = s1[i]; + long y = s2[i]; + sad += Math.abs(x - y); + } + return sad; + } + + /// CHECK-START: long Main.sadShort2LongAt1(short[], short[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:j\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:j\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadShort2LongAt1(short[], short[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none + private static long sadShort2LongAt1(short[] s1, short[] s2) { + int min_length = Math.min(s1.length, s2.length); + long sad = 1; // starts at 1 + for (int i = 0; i < min_length; i++) { + long x = s1[i]; + long y = s2[i]; + sad += Math.abs(x - y); + } + return sad; + } + + public static void main(String[] args) { + // Cross-test the two most extreme values individually. + short[] s1 = { 0, -32768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + short[] s2 = { 0, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + expectEquals(-1, sadShort2Short(s1, s2)); + expectEquals(-1, sadShort2Short(s2, s1)); + expectEquals(-1, sadShort2ShortAlt(s1, s2)); + expectEquals(-1, sadShort2ShortAlt(s2, s1)); + expectEquals(-1, sadShort2ShortAlt2(s1, s2)); + expectEquals(-1, sadShort2ShortAlt2(s2, s1)); + expectEquals(65535, sadShort2Int(s1, s2)); + expectEquals(65535, sadShort2Int(s2, s1)); + expectEquals(65535, sadShort2IntAlt(s1, s2)); + expectEquals(65535, sadShort2IntAlt(s2, s1)); + expectEquals(65535, sadShort2IntAlt2(s1, s2)); + expectEquals(65535, sadShort2IntAlt2(s2, s1)); + expectEquals(65535L, sadShort2Long(s1, s2)); + expectEquals(65535L, sadShort2Long(s2, s1)); + expectEquals(65536L, sadShort2LongAt1(s1, s2)); + expectEquals(65536L, sadShort2LongAt1(s2, s1)); + + // Use cross-values to test all cases. + short[] interesting = { + (short) 0x0000, + (short) 0x0001, + (short) 0x0002, + (short) 0x1234, + (short) 0x8000, + (short) 0x8001, + (short) 0x7fff, + (short) 0xffff + }; + int n = interesting.length; + int m = n * n + 1; + s1 = new short[m]; + s2 = new short[m]; + int k = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + s1[k] = interesting[i]; + s2[k] = interesting[j]; + k++; + } + } + s1[k] = 10; + s2[k] = 2; + expectEquals(-18932, sadShort2Short(s1, s2)); + expectEquals(-18932, sadShort2ShortAlt(s1, s2)); + expectEquals(-18932, sadShort2ShortAlt2(s1, s2)); + expectEquals(1291788, sadShort2Int(s1, s2)); + expectEquals(1291788, sadShort2IntAlt(s1, s2)); + expectEquals(1291788, sadShort2IntAlt2(s1, s2)); + expectEquals(1291788L, sadShort2Long(s1, s2)); + expectEquals(1291789L, sadShort2LongAt1(s1, s2)); + + System.out.println("passed"); + } + + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + private static void expectEquals(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/660-checker-simd-sad-short2/expected.txt b/test/660-checker-simd-sad-short2/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/660-checker-simd-sad-short2/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/660-checker-simd-sad-short2/info.txt b/test/660-checker-simd-sad-short2/info.txt new file mode 100644 index 0000000000..b56c119129 --- /dev/null +++ b/test/660-checker-simd-sad-short2/info.txt @@ -0,0 +1 @@ +Functional tests on SAD vectorization. diff --git a/test/660-checker-simd-sad-short2/src/Main.java b/test/660-checker-simd-sad-short2/src/Main.java new file mode 100644 index 0000000000..7acc490536 --- /dev/null +++ b/test/660-checker-simd-sad-short2/src/Main.java @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * Tests for SAD (sum of absolute differences). + * + * Special case, char array that is first casted to short, forcing sign extension. + */ +public class Main { + + // TODO: lower precision still coming, b/64091002 + + private static short sadCastedChar2Short(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + short sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(((short) s1[i]) - ((short) s2[i])); + } + return sad; + } + + private static short sadCastedChar2ShortAlt(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + short sad = 0; + for (int i = 0; i < min_length; i++) { + short s = (short) s1[i]; + short p = (short) s2[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + private static short sadCastedChar2ShortAlt2(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + short sad = 0; + for (int i = 0; i < min_length; i++) { + short s = (short) s1[i]; + short p = (short) s2[i]; + int x = s - p; + if (x < 0) x = -x; + sad += x; + } + return sad; + } + + /// CHECK-START: int Main.sadCastedChar2Int(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:s\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadCastedChar2Int(char[], char[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none + private static int sadCastedChar2Int(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + sad += Math.abs(((short) s1[i]) - ((short) s2[i])); + } + return sad; + } + + /// CHECK-START: int Main.sadCastedChar2IntAlt(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:s\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Cnv2>>,<<Cnv1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadCastedChar2IntAlt(char[], char[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none + private static int sadCastedChar2IntAlt(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + short s = (short) s1[i]; + short p = (short) s2[i]; + sad += s >= p ? s - p : p - s; + } + return sad; + } + + /// CHECK-START: int Main.sadCastedChar2IntAlt2(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:s\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: int Main.sadCastedChar2IntAlt2(char[], char[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none + private static int sadCastedChar2IntAlt2(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + int sad = 0; + for (int i = 0; i < min_length; i++) { + short s = (short) s1[i]; + short p = (short) s2[i]; + int x = s - p; + if (x < 0) x = -x; + sad += x; + } + return sad; + } + + /// CHECK-START: long Main.sadCastedChar2Long(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:s\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv3:j\d+>> TypeConversion [<<Cnv1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv4:j\d+>> TypeConversion [<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv3>>,<<Cnv4>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadCastedChar2Long(char[], char[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none + private static long sadCastedChar2Long(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + long sad = 0; + for (int i = 0; i < min_length; i++) { + long x = (short) s1[i]; + long y = (short) s2[i]; + sad += Math.abs(x - y); + } + return sad; + } + + /// CHECK-START: long Main.sadCastedChar2LongAt1(char[], char[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv2:s\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv3:j\d+>> TypeConversion [<<Cnv1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Cnv4:j\d+>> TypeConversion [<<Cnv2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv3>>,<<Cnv4>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none + // + /// CHECK-START-ARM64: long Main.sadCastedChar2LongAt1(char[], char[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none + /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none + private static long sadCastedChar2LongAt1(char[] s1, char[] s2) { + int min_length = Math.min(s1.length, s2.length); + long sad = 1; // starts at 1 + for (int i = 0; i < min_length; i++) { + long x = (short) s1[i]; + long y = (short) s2[i]; + sad += Math.abs(x - y); + } + return sad; + } + + public static void main(String[] args) { + // Cross-test the two most extreme values individually. + char[] s1 = { 0, 0x8000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + char[] s2 = { 0, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + expectEquals(-1, sadCastedChar2Short(s1, s2)); + expectEquals(-1, sadCastedChar2Short(s2, s1)); + expectEquals(-1, sadCastedChar2ShortAlt(s1, s2)); + expectEquals(-1, sadCastedChar2ShortAlt(s2, s1)); + expectEquals(-1, sadCastedChar2ShortAlt2(s1, s2)); + expectEquals(-1, sadCastedChar2ShortAlt2(s2, s1)); + expectEquals(65535, sadCastedChar2Int(s1, s2)); + expectEquals(65535, sadCastedChar2Int(s2, s1)); + expectEquals(65535, sadCastedChar2IntAlt(s1, s2)); + expectEquals(65535, sadCastedChar2IntAlt(s2, s1)); + expectEquals(65535, sadCastedChar2IntAlt2(s1, s2)); + expectEquals(65535, sadCastedChar2IntAlt2(s2, s1)); + expectEquals(65535L, sadCastedChar2Long(s1, s2)); + expectEquals(65535L, sadCastedChar2Long(s2, s1)); + expectEquals(65536L, sadCastedChar2LongAt1(s1, s2)); + expectEquals(65536L, sadCastedChar2LongAt1(s2, s1)); + + // Use cross-values to test all cases. + char[] interesting = { + (char) 0x0000, + (char) 0x0001, + (char) 0x0002, + (char) 0x1234, + (char) 0x8000, + (char) 0x8001, + (char) 0x7fff, + (char) 0xffff + }; + int n = interesting.length; + int m = n * n + 1; + s1 = new char[m]; + s2 = new char[m]; + int k = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + s1[k] = interesting[i]; + s2[k] = interesting[j]; + k++; + } + } + s1[k] = 10; + s2[k] = 2; + expectEquals(-18932, sadCastedChar2Short(s1, s2)); + expectEquals(-18932, sadCastedChar2ShortAlt(s1, s2)); + expectEquals(-18932, sadCastedChar2ShortAlt2(s1, s2)); + expectEquals(1291788, sadCastedChar2Int(s1, s2)); + expectEquals(1291788, sadCastedChar2IntAlt(s1, s2)); + expectEquals(1291788, sadCastedChar2IntAlt2(s1, s2)); + expectEquals(1291788L, sadCastedChar2Long(s1, s2)); + expectEquals(1291789L, sadCastedChar2LongAt1(s1, s2)); + + System.out.println("passed"); + } + + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + private static void expectEquals(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/661-checker-simd-reduc/src/Main.java b/test/661-checker-simd-reduc/src/Main.java index 71eb3cde9c..bcfa968584 100644 --- a/test/661-checker-simd-reduc/src/Main.java +++ b/test/661-checker-simd-reduc/src/Main.java @@ -80,6 +80,101 @@ public class Main { return sum; } + /// CHECK-START: int Main.reductionIntChain() loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons1>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi2>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Get1>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Cons1>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi4:i\d+>> Phi [<<Phi1>>,{{i\d+}}] loop:<<Loop2>> outer_loop:none + /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi3>>] loop:<<Loop2>> outer_loop:none + /// CHECK-DAG: Add [<<Phi4>>,<<Get2>>] loop:<<Loop2>> outer_loop:none + /// CHECK-DAG: Add [<<Phi3>>,<<Cons1>>] loop:<<Loop2>> outer_loop:none + /// CHECK-DAG: Return [<<Phi4>>] loop:none + // + /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" + // + /// CHECK-START-ARM64: int Main.reductionIntChain() loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Cons4:i\d+>> IntConstant 4 loop:none + /// CHECK-DAG: <<Set1:d\d+>> VecSetScalars [<<Cons1>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set1>>,{{d\d+}}] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: VecAdd [<<Phi2>>,<<Load1>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons4>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: <<Red1:d\d+>> VecReduce [<<Phi2>>] loop:none + /// CHECK-DAG: <<Extr1:i\d+>> VecExtractScalar [<<Red1>>] loop:none + /// CHECK-DAG: <<Set2:d\d+>> VecSetScalars [<<Extr1>>] loop:none + /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi4:d\d+>> Phi [<<Set2>>,{{d\d+}}] loop:<<Loop2>> outer_loop:none + /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi3>>] loop:<<Loop2>> outer_loop:none + /// CHECK-DAG: VecAdd [<<Phi4>>,<<Load2>>] loop:<<Loop2>> outer_loop:none + /// CHECK-DAG: Add [<<Phi3>>,<<Cons4>>] loop:<<Loop2>> outer_loop:none + /// CHECK-DAG: <<Red2:d\d+>> VecReduce [<<Phi4>>] loop:none + /// CHECK-DAG: <<Extr2:i\d+>> VecExtractScalar [<<Red2>>] loop:none + /// CHECK-DAG: Return [<<Extr2>>] loop:none + // + /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" + // + // NOTE: pattern is robust with respect to vector loop unrolling. + private static int reductionIntChain() { + int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + int r = 1; + for (int i = 0; i < 16; i++) { + r += x[i]; + } + for (int i = 0; i < 16; i++) { + r += x[i]; + } + return r; + } + + /// CHECK-START: int Main.reductionIntToLoop(int[]) loop_optimization (before) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: <<Get:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: Add [<<Phi2>>,<<Get>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Phi2>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi4:i\d+>> Phi [<<Phi2>>,{{i\d+}}] loop:<<Loop2>> outer_loop:none + // + /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" + // + /// CHECK-START-ARM64: int Main.reductionIntToLoop(int[]) loop_optimization (after) + /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none + /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none + /// CHECK-DAG: <<Cons4:i\d+>> IntConstant 4 loop:none + /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none + /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: VecAdd [<<Phi2>>,<<Load1>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: Add [<<Phi1>>,<<Cons4>>] loop:<<Loop1>> outer_loop:none + /// CHECK-DAG: <<Red:d\d+>> VecReduce [<<Phi2>>] loop:none + /// CHECK-DAG: <<Extr:i\d+>> VecExtractScalar [<<Red>>] loop:none + /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Extr>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:none + /// CHECK-DAG: <<Phi4:i\d+>> Phi [<<Extr>>,{{i\d+}}] loop:<<Loop2>> outer_loop:none + // + /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" + // + private static int reductionIntToLoop(int[] x) { + int r = 0; + for (int i = 0; i < 4; i++) { + r += x[i]; + } + for (int i = r; i < 16; i++) { + r += i; + } + return r; + } + /// CHECK-START: long Main.reductionLong(long[]) loop_optimization (before) /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none /// CHECK-DAG: <<Long0:j\d+>> LongConstant 0 loop:none @@ -468,10 +563,28 @@ public class Main { } // Test various reductions in loops. + int[] x0 = { 0, 0, 0, 0 }; + int[] x1 = { 0, 0, 0, 1 }; + int[] x2 = { 1, 1, 1, 1 }; expectEquals(-74, reductionByte(xb)); expectEquals(-27466, reductionShort(xs)); expectEquals(38070, reductionChar(xc)); expectEquals(365750, reductionInt(xi)); + expectEquals(273, reductionIntChain()); + expectEquals(120, reductionIntToLoop(x0)); + expectEquals(121, reductionIntToLoop(x1)); + expectEquals(118, reductionIntToLoop(x2)); + expectEquals(-1205, reductionIntToLoop(xi)); + expectEquals(365750L, reductionLong(xl)); + expectEquals(-75, reductionByteM1(xb)); + expectEquals(-27467, reductionShortM1(xs)); + expectEquals(38069, reductionCharM1(xc)); + expectEquals(365749, reductionIntM1(xi)); + expectEquals(365749L, reductionLongM1(xl)); + expectEquals(74, reductionMinusByte(xb)); + expectEquals(27466, reductionMinusShort(xs)); + expectEquals(27466, reductionMinusChar(xc)); + expectEquals(-365750, reductionMinusInt(xi)); expectEquals(365750L, reductionLong(xl)); expectEquals(-75, reductionByteM1(xb)); expectEquals(-27467, reductionShortM1(xs)); diff --git a/test/661-oat-writer-layout/expected.no-compiled-code.txt b/test/661-oat-writer-layout/expected.no-compiled-code.txt new file mode 100644 index 0000000000..4ed7577915 --- /dev/null +++ b/test/661-oat-writer-layout/expected.no-compiled-code.txt @@ -0,0 +1 @@ +No OAT class diff --git a/test/661-oat-writer-layout/expected.txt b/test/661-oat-writer-layout/expected.txt new file mode 100644 index 0000000000..db28e4f76d --- /dev/null +++ b/test/661-oat-writer-layout/expected.txt @@ -0,0 +1,73 @@ +JNI_OnLoad called +A::m_a$$$ +A::m_b$$$ +A::m_c$$$ +B::m_a$$$ +B::m_b$$$ +B::m_c$$$ +C::m_a$$$ +C::m_b$$$ +C::m_c$$$ +A::m_a$Hot$$ +A::m_b$Hot$$ +A::m_c$Hot$$ +B::m_a$Hot$$ +B::m_b$Hot$$ +B::m_c$Hot$$ +C::m_a$Hot$$ +C::m_b$Hot$$ +C::m_c$Hot$$ +A::m_a$$Startup$ +A::m_b$$Startup$ +A::m_c$$Startup$ +B::m_a$$Startup$ +B::m_b$$Startup$ +B::m_c$$Startup$ +C::m_a$$Startup$ +C::m_b$$Startup$ +C::m_c$$Startup$ +A::m_a$Hot$Startup$ +A::m_b$Hot$Startup$ +A::m_c$Hot$Startup$ +B::m_a$Hot$Startup$ +B::m_b$Hot$Startup$ +B::m_c$Hot$Startup$ +C::m_a$Hot$Startup$ +C::m_b$Hot$Startup$ +C::m_c$Hot$Startup$ +A::m_a$$$Poststartup +A::m_b$$$Poststartup +A::m_c$$$Poststartup +B::m_a$$$Poststartup +B::m_b$$$Poststartup +B::m_c$$$Poststartup +C::m_a$$$Poststartup +C::m_b$$$Poststartup +C::m_c$$$Poststartup +A::m_a$Hot$$Poststartup +A::m_b$Hot$$Poststartup +A::m_c$Hot$$Poststartup +B::m_a$Hot$$Poststartup +B::m_b$Hot$$Poststartup +B::m_c$Hot$$Poststartup +C::m_a$Hot$$Poststartup +C::m_b$Hot$$Poststartup +C::m_c$Hot$$Poststartup +A::m_a$$Startup$Poststartup +A::m_b$$Startup$Poststartup +A::m_c$$Startup$Poststartup +B::m_a$$Startup$Poststartup +B::m_b$$Startup$Poststartup +B::m_c$$Startup$Poststartup +C::m_a$$Startup$Poststartup +C::m_b$$Startup$Poststartup +C::m_c$$Startup$Poststartup +A::m_a$Hot$Startup$Poststartup +A::m_b$Hot$Startup$Poststartup +A::m_c$Hot$Startup$Poststartup +B::m_a$Hot$Startup$Poststartup +B::m_b$Hot$Startup$Poststartup +B::m_c$Hot$Startup$Poststartup +C::m_a$Hot$Startup$Poststartup +C::m_b$Hot$Startup$Poststartup +C::m_c$Hot$Startup$Poststartup diff --git a/test/661-oat-writer-layout/info.txt b/test/661-oat-writer-layout/info.txt new file mode 100644 index 0000000000..897b85c4ad --- /dev/null +++ b/test/661-oat-writer-layout/info.txt @@ -0,0 +1,4 @@ +Tests Oat Writer is correctly changing the layout of OatMethod code addresses. + +Whenever we pass in a profile to dex2oat, we expect that it sorts the methods by the +MethodHotness bitmask (and sub-sorts by class_def_idx, then method_id). diff --git a/test/661-oat-writer-layout/oat_writer_layout.cc b/test/661-oat-writer-layout/oat_writer_layout.cc new file mode 100644 index 0000000000..61996b22e7 --- /dev/null +++ b/test/661-oat-writer-layout/oat_writer_layout.cc @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2017 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 "jni.h" + +#include "art_method.h" +#include "class_linker.h" +#include "mirror/class-inl.h" +#include "mirror/dex_cache.h" +#include "mirror/executable.h" +#include "mirror/object-inl.h" +#include "obj_ptr.h" +#include "oat_file.h" +#include "runtime.h" +#include "scoped_thread_state_change-inl.h" +#include "thread.h" + +namespace art { +namespace { + +extern "C" JNIEXPORT jlong JNICALL Java_Main_getOatMethodQuickCode(JNIEnv* env, + jclass, + jobject method) { + CHECK(method != nullptr); + ScopedObjectAccess soa(env); + ObjPtr<mirror::Executable> exec = soa.Decode<mirror::Executable>(method); + ArtMethod* art_method = exec->GetArtMethod(); + + const void* quick_code = + art_method->GetOatMethodQuickCode(Runtime::Current()->GetClassLinker()->GetImagePointerSize()); + + return static_cast<jlong>(reinterpret_cast<uintptr_t>(quick_code)); +} + +extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasOatCompiledCode(JNIEnv* env, + jclass, + jclass kls) { + CHECK(kls != nullptr); + ScopedObjectAccess soa(env); + Thread* self = Thread::Current(); + + ObjPtr<mirror::Class> klass_ptr = self->DecodeJObject(kls)->AsClass(); + + bool found = false; + OatFile::OatClass oat_class = OatFile::FindOatClass(*klass_ptr->GetDexCache()->GetDexFile(), + klass_ptr->GetDexClassDefIndex(), + /* out */ &found); + + if (!found) { + return false; + } + + OatClassType type = oat_class.GetType(); + switch (type) { + case kOatClassAllCompiled: + case kOatClassSomeCompiled: + return true; + + case kOatClassNoneCompiled: + case kOatClassMax: + return false; + } + + LOG(FATAL) << "unhandled switch statement"; + UNREACHABLE(); +} + +} // namespace +} // namespace art diff --git a/test/661-oat-writer-layout/parse_oatdump_offsets.sh b/test/661-oat-writer-layout/parse_oatdump_offsets.sh new file mode 100755 index 0000000000..ab9b9a9350 --- /dev/null +++ b/test/661-oat-writer-layout/parse_oatdump_offsets.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# +# Copyright (C) 2017 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. + +# +# Quick and dirty helper tool to print the sorted oat code offsets from oatdump. +# +# Usage: +# +# oatdump --oat-file=661-oat-writer-layout.odex | $ANDROID_BUILD_TOP/art/test/661-oat-writer-layout/parse_oatdump_offsets.sh +# + +found_method="" +tmp_file="$(mktemp)" +while read -r line; do + + if [[ $line == *dex_method_idx=* ]]; then + found_method=$line + fi + + if [[ $line == *"code_offset: "* ]]; then + echo $line $found_method >> "$tmp_file" + fi +done + +sort "$tmp_file" diff --git a/test/661-oat-writer-layout/profile b/test/661-oat-writer-layout/profile new file mode 100644 index 0000000000..54064843ce --- /dev/null +++ b/test/661-oat-writer-layout/profile @@ -0,0 +1,63 @@ +HLA;->m_a$Hot$$()V +SLA;->m_a$$Startup$()V +HSLA;->m_a$Hot$Startup$()V +PLA;->m_a$$$Poststartup()V +HPLA;->m_a$Hot$$Poststartup()V +SPLA;->m_a$$Startup$Poststartup()V +HSPLA;->m_a$Hot$Startup$Poststartup()V +HLA;->m_b$Hot$$()V +SLA;->m_b$$Startup$()V +HSLA;->m_b$Hot$Startup$()V +PLA;->m_b$$$Poststartup()V +HPLA;->m_b$Hot$$Poststartup()V +SPLA;->m_b$$Startup$Poststartup()V +HSPLA;->m_b$Hot$Startup$Poststartup()V +HLA;->m_c$Hot$$()V +SLA;->m_c$$Startup$()V +HSLA;->m_c$Hot$Startup$()V +PLA;->m_c$$$Poststartup()V +HPLA;->m_c$Hot$$Poststartup()V +SPLA;->m_c$$Startup$Poststartup()V +HSPLA;->m_c$Hot$Startup$Poststartup()V +HLB;->m_a$Hot$$()V +SLB;->m_a$$Startup$()V +HSLB;->m_a$Hot$Startup$()V +PLB;->m_a$$$Poststartup()V +HPLB;->m_a$Hot$$Poststartup()V +SPLB;->m_a$$Startup$Poststartup()V +HSPLB;->m_a$Hot$Startup$Poststartup()V +HLB;->m_b$Hot$$()V +SLB;->m_b$$Startup$()V +HSLB;->m_b$Hot$Startup$()V +PLB;->m_b$$$Poststartup()V +HPLB;->m_b$Hot$$Poststartup()V +SPLB;->m_b$$Startup$Poststartup()V +HSPLB;->m_b$Hot$Startup$Poststartup()V +HLB;->m_c$Hot$$()V +SLB;->m_c$$Startup$()V +HSLB;->m_c$Hot$Startup$()V +PLB;->m_c$$$Poststartup()V +HPLB;->m_c$Hot$$Poststartup()V +SPLB;->m_c$$Startup$Poststartup()V +HSPLB;->m_c$Hot$Startup$Poststartup()V +HLC;->m_a$Hot$$()V +SLC;->m_a$$Startup$()V +HSLC;->m_a$Hot$Startup$()V +PLC;->m_a$$$Poststartup()V +HPLC;->m_a$Hot$$Poststartup()V +SPLC;->m_a$$Startup$Poststartup()V +HSPLC;->m_a$Hot$Startup$Poststartup()V +HLC;->m_b$Hot$$()V +SLC;->m_b$$Startup$()V +HSLC;->m_b$Hot$Startup$()V +PLC;->m_b$$$Poststartup()V +HPLC;->m_b$Hot$$Poststartup()V +SPLC;->m_b$$Startup$Poststartup()V +HSPLC;->m_b$Hot$Startup$Poststartup()V +HLC;->m_c$Hot$$()V +SLC;->m_c$$Startup$()V +HSLC;->m_c$Hot$Startup$()V +PLC;->m_c$$$Poststartup()V +HPLC;->m_c$Hot$$Poststartup()V +SPLC;->m_c$$Startup$Poststartup()V +HSPLC;->m_c$Hot$Startup$Poststartup()V diff --git a/test/661-oat-writer-layout/run b/test/661-oat-writer-layout/run new file mode 100644 index 0000000000..f93d7b7ceb --- /dev/null +++ b/test/661-oat-writer-layout/run @@ -0,0 +1,20 @@ +#!/bin/bash +# +# Copyright (C) 2017 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. + +# Always use the 'profile'. +# Note that this test only works with --compiler-filter=speed +# -- we accomplish this by blacklisting other compiler variants. +"${RUN}" "$@" --profile diff --git a/test/661-oat-writer-layout/src/Generated.java b/test/661-oat-writer-layout/src/Generated.java new file mode 100644 index 0000000000..09f4e88621 --- /dev/null +++ b/test/661-oat-writer-layout/src/Generated.java @@ -0,0 +1,109 @@ +// Copyright (C) 2017 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. + +// +// Lists several combinations of Classes X Methods X Hotness: +// +// Class A-C: +// - Ensure method hotness overrides sorting by class_def_idx +// +// Method m_a : m_c +// - Ensure method hotness overrides sorting by method_id +// +// Method m_a$Hot$Enum$Bits +// - $X$Y$Z is an encoding of MethodHotness flags ($[Hot]$[Startup]$[Poststartup]) +// - The method name encoding matches the `profile` hotness. +// - Check all variations of the bits to make sure it sorts by hotness correctly. +// + +class A { + // Note that every method has unique dex code (by using a unique string literal). + // This is to prevent dex/oat code deduping. Deduped methods do not get distinct bins. + void m_a$$$() { System.out.println("Don't dedupe me! A::m_a$$$"); } + void m_a$Hot$$() { System.out.println("Don't dedupe me! A::m_a$Hot$$"); } + void m_a$$Startup$() { System.out.println("Don't dedupe me! A::m_a$$Startup$"); } + void m_a$Hot$Startup$() { System.out.println("Don't dedupe me! A::m_a$Hot$Startup$"); } + void m_a$$$Poststartup() { System.out.println("Don't dedupe me! A::m_a$$$Poststartup"); } + void m_a$Hot$$Poststartup() { System.out.println("Don't dedupe me! A::m_a$Hot$$Poststartup"); } + void m_a$$Startup$Poststartup() { System.out.println("Don't dedupe me! A::m_a$$Startup$Poststartup"); } + void m_a$Hot$Startup$Poststartup() { System.out.println("Don't dedupe me! A::m_a$Hot$Startup$Poststartup"); } + void m_b$$$() { System.out.println("Don't dedupe me! A::m_b$$$"); } + void m_b$Hot$$() { System.out.println("Don't dedupe me! A::m_b$Hot$$"); } + void m_b$$Startup$() { System.out.println("Don't dedupe me! A::m_b$$Startup$"); } + void m_b$Hot$Startup$() { System.out.println("Don't dedupe me! A::m_b$Hot$Startup$"); } + void m_b$$$Poststartup() { System.out.println("Don't dedupe me! A::m_b$$$Poststartup"); } + void m_b$Hot$$Poststartup() { System.out.println("Don't dedupe me! A::m_b$Hot$$Poststartup"); } + void m_b$$Startup$Poststartup() { System.out.println("Don't dedupe me! A::m_b$$Startup$Poststartup"); } + void m_b$Hot$Startup$Poststartup() { System.out.println("Don't dedupe me! A::m_b$Hot$Startup$Poststartup"); } + void m_c$$$() { System.out.println("Don't dedupe me! A::m_c$$$"); } + void m_c$Hot$$() { System.out.println("Don't dedupe me! A::m_c$Hot$$"); } + void m_c$$Startup$() { System.out.println("Don't dedupe me! A::m_c$$Startup$"); } + void m_c$Hot$Startup$() { System.out.println("Don't dedupe me! A::m_c$Hot$Startup$"); } + void m_c$$$Poststartup() { System.out.println("Don't dedupe me! A::m_c$$$Poststartup"); } + void m_c$Hot$$Poststartup() { System.out.println("Don't dedupe me! A::m_c$Hot$$Poststartup"); } + void m_c$$Startup$Poststartup() { System.out.println("Don't dedupe me! A::m_c$$Startup$Poststartup"); } + void m_c$Hot$Startup$Poststartup() { System.out.println("Don't dedupe me! A::m_c$Hot$Startup$Poststartup"); } +} +class B { + void m_a$$$() { System.out.println("Don't dedupe me! B::m_a$$$"); } + void m_a$Hot$$() { System.out.println("Don't dedupe me! B::m_a$Hot$$"); } + void m_a$$Startup$() { System.out.println("Don't dedupe me! B::m_a$$Startup$"); } + void m_a$Hot$Startup$() { System.out.println("Don't dedupe me! B::m_a$Hot$Startup$"); } + void m_a$$$Poststartup() { System.out.println("Don't dedupe me! B::m_a$$$Poststartup"); } + void m_a$Hot$$Poststartup() { System.out.println("Don't dedupe me! B::m_a$Hot$$Poststartup"); } + void m_a$$Startup$Poststartup() { System.out.println("Don't dedupe me! B::m_a$$Startup$Poststartup"); } + void m_a$Hot$Startup$Poststartup() { System.out.println("Don't dedupe me! B::m_a$Hot$Startup$Poststartup"); } + void m_b$$$() { System.out.println("Don't dedupe me! B::m_b$$$"); } + void m_b$Hot$$() { System.out.println("Don't dedupe me! B::m_b$Hot$$"); } + void m_b$$Startup$() { System.out.println("Don't dedupe me! B::m_b$$Startup$"); } + void m_b$Hot$Startup$() { System.out.println("Don't dedupe me! B::m_b$Hot$Startup$"); } + void m_b$$$Poststartup() { System.out.println("Don't dedupe me! B::m_b$$$Poststartup"); } + void m_b$Hot$$Poststartup() { System.out.println("Don't dedupe me! B::m_b$Hot$$Poststartup"); } + void m_b$$Startup$Poststartup() { System.out.println("Don't dedupe me! B::m_b$$Startup$Poststartup"); } + void m_b$Hot$Startup$Poststartup() { System.out.println("Don't dedupe me! B::m_b$Hot$Startup$Poststartup"); } + void m_c$$$() { System.out.println("Don't dedupe me! B::m_c$$$"); } + void m_c$Hot$$() { System.out.println("Don't dedupe me! B::m_c$Hot$$"); } + void m_c$$Startup$() { System.out.println("Don't dedupe me! B::m_c$$Startup$"); } + void m_c$Hot$Startup$() { System.out.println("Don't dedupe me! B::m_c$Hot$Startup$"); } + void m_c$$$Poststartup() { System.out.println("Don't dedupe me! B::m_c$$$Poststartup"); } + void m_c$Hot$$Poststartup() { System.out.println("Don't dedupe me! B::m_c$Hot$$Poststartup"); } + void m_c$$Startup$Poststartup() { System.out.println("Don't dedupe me! B::m_c$$Startup$Poststartup"); } + void m_c$Hot$Startup$Poststartup() { System.out.println("Don't dedupe me! B::m_c$Hot$Startup$Poststartup"); } +} +class C { + void m_a$$$() { System.out.println("Don't dedupe me! C::m_a$$$"); } + void m_a$Hot$$() { System.out.println("Don't dedupe me! C::m_a$Hot$$"); } + void m_a$$Startup$() { System.out.println("Don't dedupe me! C::m_a$$Startup$"); } + void m_a$Hot$Startup$() { System.out.println("Don't dedupe me! C::m_a$Hot$Startup$"); } + void m_a$$$Poststartup() { System.out.println("Don't dedupe me! C::m_a$$$Poststartup"); } + void m_a$Hot$$Poststartup() { System.out.println("Don't dedupe me! C::m_a$Hot$$Poststartup"); } + void m_a$$Startup$Poststartup() { System.out.println("Don't dedupe me! C::m_a$$Startup$Poststartup"); } + void m_a$Hot$Startup$Poststartup() { System.out.println("Don't dedupe me! C::m_a$Hot$Startup$Poststartup"); } + void m_b$$$() { System.out.println("Don't dedupe me! C::m_b$$$"); } + void m_b$Hot$$() { System.out.println("Don't dedupe me! C::m_b$Hot$$"); } + void m_b$$Startup$() { System.out.println("Don't dedupe me! C::m_b$$Startup$"); } + void m_b$Hot$Startup$() { System.out.println("Don't dedupe me! C::m_b$Hot$Startup$"); } + void m_b$$$Poststartup() { System.out.println("Don't dedupe me! C::m_b$$$Poststartup"); } + void m_b$Hot$$Poststartup() { System.out.println("Don't dedupe me! C::m_b$Hot$$Poststartup"); } + void m_b$$Startup$Poststartup() { System.out.println("Don't dedupe me! C::m_b$$Startup$Poststartup"); } + void m_b$Hot$Startup$Poststartup() { System.out.println("Don't dedupe me! C::m_b$Hot$Startup$Poststartup"); } + void m_c$$$() { System.out.println("Don't dedupe me! C::m_c$$$"); } + void m_c$Hot$$() { System.out.println("Don't dedupe me! C::m_c$Hot$$"); } + void m_c$$Startup$() { System.out.println("Don't dedupe me! C::m_c$$Startup$"); } + void m_c$Hot$Startup$() { System.out.println("Don't dedupe me! C::m_c$Hot$Startup$"); } + void m_c$$$Poststartup() { System.out.println("Don't dedupe me! C::m_c$$$Poststartup"); } + void m_c$Hot$$Poststartup() { System.out.println("Don't dedupe me! C::m_c$Hot$$Poststartup"); } + void m_c$$Startup$Poststartup() { System.out.println("Don't dedupe me! C::m_c$$Startup$Poststartup"); } + void m_c$Hot$Startup$Poststartup() { System.out.println("Don't dedupe me! C::m_c$Hot$Startup$Poststartup"); } +} diff --git a/test/661-oat-writer-layout/src/Main.java b/test/661-oat-writer-layout/src/Main.java new file mode 100644 index 0000000000..940798dc69 --- /dev/null +++ b/test/661-oat-writer-layout/src/Main.java @@ -0,0 +1,80 @@ +// Copyright (C) 2017 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. +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; + +public class Main { + + static class OatMethodAndOffset implements Comparable<OatMethodAndOffset> { + Method method; + long codeOffset; + + public OatMethodAndOffset(Method method, long codeOffset) { + this.method = method; + this.codeOffset = codeOffset; + } + + // e.g. "Foo::Bar()" + public String methodReferenceString() { + return method.getDeclaringClass().getName() + "::" + method.getName(); + } + + @Override + public int compareTo(OatMethodAndOffset other) { + return Long.compareUnsigned(codeOffset, other.codeOffset); + } + } + + // Print the list of methods in Generated.class, sorted by their OAT code address. + public static void main(String[] args) { + System.loadLibrary(args[0]); + + // Make sure to check "Test.class" because Main.class still has JNI which could be compiled + // even if the rest of the classes are not. + if (!hasOatCompiledCode(Test.class)) { + System.out.println("No OAT class"); + return; + } + + // We only care about explicitly defined methods from Generated.java. + Method[] interesting_methods; + try { + interesting_methods = Test.getTestMethods(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + return; + } + + // Get the list of oat code methods for each Java method. + ArrayList<OatMethodAndOffset> offsets_list = new ArrayList<OatMethodAndOffset>(); + for (Method m : interesting_methods) { + offsets_list.add(new OatMethodAndOffset(m, getOatMethodQuickCode(m))); + } + + // Sort by the offset address. + Collections.sort(offsets_list); + + // Print each method as a method reference string. + for (OatMethodAndOffset m : offsets_list) { + System.out.println(m.methodReferenceString()); + } + } + + // Does Main.class have an OatClass with actually compiled code? + private static native boolean hasOatCompiledCode(Class kls); + // Get the OatMethod's pointer to code. We get 'real' memory address, not relative offset, + // but it's still good since we never compare multiple OAT files here. + private static native long getOatMethodQuickCode(Method method); +} diff --git a/test/661-oat-writer-layout/src/Test.java b/test/661-oat-writer-layout/src/Test.java new file mode 100644 index 0000000000..db67b482a2 --- /dev/null +++ b/test/661-oat-writer-layout/src/Test.java @@ -0,0 +1,98 @@ +// Copyright (C) 2017 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. + +import java.lang.reflect.Method; + +public class Test { + // Returns list of all methods in Generated.java + // This is to avoid having to introspect classes with extra code + // (for example, we ignore <init> methods). + public static Method[] getTestMethods() throws NoSuchMethodException, SecurityException { + Method[] all_methods = new Method[72]; + all_methods[0] = A.class.getDeclaredMethod("m_a$$$"); + all_methods[1] = A.class.getDeclaredMethod("m_a$Hot$$"); + all_methods[2] = A.class.getDeclaredMethod("m_a$$Startup$"); + all_methods[3] = A.class.getDeclaredMethod("m_a$Hot$Startup$"); + all_methods[4] = A.class.getDeclaredMethod("m_a$$$Poststartup"); + all_methods[5] = A.class.getDeclaredMethod("m_a$Hot$$Poststartup"); + all_methods[6] = A.class.getDeclaredMethod("m_a$$Startup$Poststartup"); + all_methods[7] = A.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup"); + all_methods[8] = A.class.getDeclaredMethod("m_b$$$"); + all_methods[9] = A.class.getDeclaredMethod("m_b$Hot$$"); + all_methods[10] = A.class.getDeclaredMethod("m_b$$Startup$"); + all_methods[11] = A.class.getDeclaredMethod("m_b$Hot$Startup$"); + all_methods[12] = A.class.getDeclaredMethod("m_b$$$Poststartup"); + all_methods[13] = A.class.getDeclaredMethod("m_b$Hot$$Poststartup"); + all_methods[14] = A.class.getDeclaredMethod("m_b$$Startup$Poststartup"); + all_methods[15] = A.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup"); + all_methods[16] = A.class.getDeclaredMethod("m_c$$$"); + all_methods[17] = A.class.getDeclaredMethod("m_c$Hot$$"); + all_methods[18] = A.class.getDeclaredMethod("m_c$$Startup$"); + all_methods[19] = A.class.getDeclaredMethod("m_c$Hot$Startup$"); + all_methods[20] = A.class.getDeclaredMethod("m_c$$$Poststartup"); + all_methods[21] = A.class.getDeclaredMethod("m_c$Hot$$Poststartup"); + all_methods[22] = A.class.getDeclaredMethod("m_c$$Startup$Poststartup"); + all_methods[23] = A.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup"); + all_methods[24] = B.class.getDeclaredMethod("m_a$$$"); + all_methods[25] = B.class.getDeclaredMethod("m_a$Hot$$"); + all_methods[26] = B.class.getDeclaredMethod("m_a$$Startup$"); + all_methods[27] = B.class.getDeclaredMethod("m_a$Hot$Startup$"); + all_methods[28] = B.class.getDeclaredMethod("m_a$$$Poststartup"); + all_methods[29] = B.class.getDeclaredMethod("m_a$Hot$$Poststartup"); + all_methods[30] = B.class.getDeclaredMethod("m_a$$Startup$Poststartup"); + all_methods[31] = B.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup"); + all_methods[32] = B.class.getDeclaredMethod("m_b$$$"); + all_methods[33] = B.class.getDeclaredMethod("m_b$Hot$$"); + all_methods[34] = B.class.getDeclaredMethod("m_b$$Startup$"); + all_methods[35] = B.class.getDeclaredMethod("m_b$Hot$Startup$"); + all_methods[36] = B.class.getDeclaredMethod("m_b$$$Poststartup"); + all_methods[37] = B.class.getDeclaredMethod("m_b$Hot$$Poststartup"); + all_methods[38] = B.class.getDeclaredMethod("m_b$$Startup$Poststartup"); + all_methods[39] = B.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup"); + all_methods[40] = B.class.getDeclaredMethod("m_c$$$"); + all_methods[41] = B.class.getDeclaredMethod("m_c$Hot$$"); + all_methods[42] = B.class.getDeclaredMethod("m_c$$Startup$"); + all_methods[43] = B.class.getDeclaredMethod("m_c$Hot$Startup$"); + all_methods[44] = B.class.getDeclaredMethod("m_c$$$Poststartup"); + all_methods[45] = B.class.getDeclaredMethod("m_c$Hot$$Poststartup"); + all_methods[46] = B.class.getDeclaredMethod("m_c$$Startup$Poststartup"); + all_methods[47] = B.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup"); + all_methods[48] = C.class.getDeclaredMethod("m_a$$$"); + all_methods[49] = C.class.getDeclaredMethod("m_a$Hot$$"); + all_methods[50] = C.class.getDeclaredMethod("m_a$$Startup$"); + all_methods[51] = C.class.getDeclaredMethod("m_a$Hot$Startup$"); + all_methods[52] = C.class.getDeclaredMethod("m_a$$$Poststartup"); + all_methods[53] = C.class.getDeclaredMethod("m_a$Hot$$Poststartup"); + all_methods[54] = C.class.getDeclaredMethod("m_a$$Startup$Poststartup"); + all_methods[55] = C.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup"); + all_methods[56] = C.class.getDeclaredMethod("m_b$$$"); + all_methods[57] = C.class.getDeclaredMethod("m_b$Hot$$"); + all_methods[58] = C.class.getDeclaredMethod("m_b$$Startup$"); + all_methods[59] = C.class.getDeclaredMethod("m_b$Hot$Startup$"); + all_methods[60] = C.class.getDeclaredMethod("m_b$$$Poststartup"); + all_methods[61] = C.class.getDeclaredMethod("m_b$Hot$$Poststartup"); + all_methods[62] = C.class.getDeclaredMethod("m_b$$Startup$Poststartup"); + all_methods[63] = C.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup"); + all_methods[64] = C.class.getDeclaredMethod("m_c$$$"); + all_methods[65] = C.class.getDeclaredMethod("m_c$Hot$$"); + all_methods[66] = C.class.getDeclaredMethod("m_c$$Startup$"); + all_methods[67] = C.class.getDeclaredMethod("m_c$Hot$Startup$"); + all_methods[68] = C.class.getDeclaredMethod("m_c$$$Poststartup"); + all_methods[69] = C.class.getDeclaredMethod("m_c$Hot$$Poststartup"); + all_methods[70] = C.class.getDeclaredMethod("m_c$$Startup$Poststartup"); + all_methods[71] = C.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup"); + return all_methods; + } +} + diff --git a/test/707-checker-invalid-profile/check b/test/707-checker-invalid-profile/check new file mode 100755 index 0000000000..976afc4ad5 --- /dev/null +++ b/test/707-checker-invalid-profile/check @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Copyright (C) 2017 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. + +# When profile verification fails, dex2oat logs an error. The following +# command strips out the error message. +grep -v -f $1 $2 > $1 + +./default-check "$@" diff --git a/test/707-checker-invalid-profile/expected.txt b/test/707-checker-invalid-profile/expected.txt index e69de29bb2..4d84c96443 100644 --- a/test/707-checker-invalid-profile/expected.txt +++ b/test/707-checker-invalid-profile/expected.txt @@ -0,0 +1 @@ +Invalid inline cache in profile file. diff --git a/test/911-get-stack-trace/src/art/PrintThread.java b/test/911-get-stack-trace/src/art/PrintThread.java index fee5ba00ab..d8b3cbc57e 100644 --- a/test/911-get-stack-trace/src/art/PrintThread.java +++ b/test/911-get-stack-trace/src/art/PrintThread.java @@ -42,7 +42,7 @@ public class PrintThread { // may not exist depending on the environment. public final static String IGNORE_THREAD_NAME_REGEX = "Binder:|RenderThread|hwuiTask|Jit thread pool worker|Instr:|JDWP|Profile Saver|main|" + - "queued-work-looper"; + "queued-work-looper|InstrumentationConnectionThread"; public final static Matcher IGNORE_THREADS = Pattern.compile(IGNORE_THREAD_NAME_REGEX).matcher(""); diff --git a/test/912-classes/expected.txt b/test/912-classes/expected.txt index 9dcc5f9c90..7ad5d608b7 100644 --- a/test/912-classes/expected.txt +++ b/test/912-classes/expected.txt @@ -56,7 +56,7 @@ boot <- (B) <- (A, List) boot <- 1+2 (A,B) [class A, class B, class java.lang.Object] -[37, 0] +[35, 0] B, false Load: LB; on ClassEvents diff --git a/test/912-classes/src-art/art/Test912.java b/test/912-classes/src-art/art/Test912.java index 2e41c2646d..ddfadf3626 100644 --- a/test/912-classes/src-art/art/Test912.java +++ b/test/912-classes/src-art/art/Test912.java @@ -19,8 +19,10 @@ package art; import java.lang.ref.Reference; import java.lang.reflect.Constructor; import java.lang.reflect.Proxy; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.Comparator; public class Test912 { @@ -214,8 +216,34 @@ public class Test912 { } } - private static void testClassVersion() { - System.out.println(Arrays.toString(getClassVersion(Main.class))); + /** + * base64 encoded class/dex file for + * class Transform { + * public void sayHi() { + * System.out.println("Goodbye"); + * } + * } + */ + private static final byte[] DEX_BYTES = Base64.getDecoder().decode( + "ZGV4CjAzNQCLXSBQ5FiS3f16krSYZFF8xYZtFVp0GRXMAgAAcAAAAHhWNBIAAAAAAAAAACwCAAAO" + + "AAAAcAAAAAYAAACoAAAAAgAAAMAAAAABAAAA2AAAAAQAAADgAAAAAQAAAAABAACsAQAAIAEAAGIB" + + "AABqAQAAcwEAAIABAACXAQAAqwEAAL8BAADTAQAA4wEAAOYBAADqAQAA/gEAAAMCAAAMAgAAAgAA" + + "AAMAAAAEAAAABQAAAAYAAAAIAAAACAAAAAUAAAAAAAAACQAAAAUAAABcAQAABAABAAsAAAAAAAAA" + + "AAAAAAAAAAANAAAAAQABAAwAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAHAAAAAAAAAB4CAAAA" + + "AAAAAQABAAEAAAATAgAABAAAAHAQAwAAAA4AAwABAAIAAAAYAgAACQAAAGIAAAAbAQEAAABuIAIA" + + "EAAOAAAAAQAAAAMABjxpbml0PgAHR29vZGJ5ZQALTFRyYW5zZm9ybTsAFUxqYXZhL2lvL1ByaW50" + + "U3RyZWFtOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xh" + + "bmcvU3lzdGVtOwAOVHJhbnNmb3JtLmphdmEAAVYAAlZMABJlbWl0dGVyOiBqYWNrLTMuMzYAA291" + + "dAAHcHJpbnRsbgAFc2F5SGkAEQAHDgATAAcOhQAAAAEBAICABKACAQG4Ag0AAAAAAAAAAQAAAAAA" + + "AAABAAAADgAAAHAAAAACAAAABgAAAKgAAAADAAAAAgAAAMAAAAAEAAAAAQAAANgAAAAFAAAABAAA" + + "AOAAAAAGAAAAAQAAAAABAAABIAAAAgAAACABAAABEAAAAQAAAFwBAAACIAAADgAAAGIBAAADIAAA" + + "AgAAABMCAAAAIAAAAQAAAB4CAAAAEAAAAQAAACwCAAA="); + private static void testClassVersion() throws Exception { + Class<?> class_loader_class = Class.forName("dalvik.system.InMemoryDexClassLoader"); + Constructor<?> ctor = class_loader_class.getConstructor(ByteBuffer.class, ClassLoader.class); + Class target = ((ClassLoader)ctor.newInstance( + ByteBuffer.wrap(DEX_BYTES), Test912.class.getClassLoader())).loadClass("Transform"); + System.out.println(Arrays.toString(getClassVersion(target))); } private static void testClassEvents() throws Exception { diff --git a/test/924-threads/expected.txt b/test/924-threads/expected.txt index 1eb2e1bd52..e52955992b 100644 --- a/test/924-threads/expected.txt +++ b/test/924-threads/expected.txt @@ -26,6 +26,15 @@ java.lang.ThreadGroup[name=main,maxpri=10] class dalvik.system.PathClassLoader 5 5 +Thread type is class java.lang.Thread +0 = NEW +191 = ALIVE|WAITING_INDEFINITELY|WAITING|IN_OBJECT_WAIT +1a1 = ALIVE|WAITING_WITH_TIMEOUT|WAITING|IN_OBJECT_WAIT +401 = ALIVE|BLOCKED_ON_MONITOR_ENTER +e1 = ALIVE|WAITING_WITH_TIMEOUT|SLEEPING|WAITING +5 = ALIVE|RUNNABLE +2 = TERMINATED +Thread type is class art.Test924$ExtThread 0 = NEW 191 = ALIVE|WAITING_INDEFINITELY|WAITING|IN_OBJECT_WAIT 1a1 = ALIVE|WAITING_WITH_TIMEOUT|WAITING|IN_OBJECT_WAIT diff --git a/test/924-threads/src/art/Test924.java b/test/924-threads/src/art/Test924.java index b73eb30888..1ff2c3f644 100644 --- a/test/924-threads/src/art/Test924.java +++ b/test/924-threads/src/art/Test924.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.concurrent.CountDownLatch; +import java.util.function.Function; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -76,7 +77,9 @@ public class Test924 { }; printThreadInfo(t4); - doStateTests(); + doCurrentThreadStateTests(); + doStateTests(Thread::new); + doStateTests(ExtThread::new); doAllThreadsTests(); @@ -85,14 +88,20 @@ public class Test924 { doTestEvents(); } + private static final class ExtThread extends Thread { + public ExtThread(Runnable r) { super(r); } + } + private static class Holder { volatile boolean flag = false; } - private static void doStateTests() throws Exception { + private static void doCurrentThreadStateTests() throws Exception { System.out.println(Integer.toHexString(getThreadState(null))); System.out.println(Integer.toHexString(getThreadState(Thread.currentThread()))); + } + private static void doStateTests(Function<Runnable, Thread> mkThread) throws Exception { final CountDownLatch cdl1 = new CountDownLatch(1); final CountDownLatch cdl2 = new CountDownLatch(1); final CountDownLatch cdl3_1 = new CountDownLatch(1); @@ -133,7 +142,8 @@ public class Test924 { } }; - Thread t = new Thread(r); + Thread t = mkThread.apply(r); + System.out.println("Thread type is " + t.getClass()); printThreadState(t); t.start(); diff --git a/test/961-default-iface-resolution-gen/run b/test/961-default-iface-resolution-gen/run new file mode 100755 index 0000000000..fdcd2a8e9a --- /dev/null +++ b/test/961-default-iface-resolution-gen/run @@ -0,0 +1,18 @@ +#!/bin/bash +# +# Copyright (C) 2017 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. + +# Run with a 2 minute default dex2oat timeout and a 2.5 minute hard dex2oat timeout. +./default-run "$@" --dex2oat-timeout 120 --dex2oat-rt-timeout 180 diff --git a/test/980-redefine-object/check b/test/980-redefine-object/check index 07b21b3176..6f1e7097ab 100755 --- a/test/980-redefine-object/check +++ b/test/980-redefine-object/check @@ -17,4 +17,7 @@ # The number of paused background threads (and therefore InterruptedExceptions) # can change so we will just delete their lines from the log. -sed "/Object allocated of type 'java\.lang\.InterruptedException'/d" "$2" | diff --strip-trailing-cr -q "$1" - >/dev/null +cat "$2" \ + | sed "/Object allocated of type 'java\.lang\.InterruptedException'/d" \ + | sed "/Object allocated of type 'java\.lang\.Long'/d" \ + | diff --strip-trailing-cr -q "$1" - >/dev/null diff --git a/test/Android.bp b/test/Android.bp index d56c0b50c2..d2eccb06bd 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -86,10 +86,6 @@ art_cc_defaults { "libziparchive", "libz-host", ], - host_ldlibs: [ - "-ldl", - "-lpthread", - ], cflags: [ // gtest issue "-Wno-used-but-marked-unused", @@ -107,7 +103,6 @@ art_cc_defaults { ], shared_libs: [ "liblog", - "libdl", "libz", ], cflags: [ @@ -169,26 +164,15 @@ art_cc_library { whole_static_libs: [ "libart-compiler-gtest", "libart-runtime-gtest", - "libgtest" + "libgtest", ], shared_libs: [ "libartd", "libartd-compiler", "libbase", - "libbacktrace" + "libbacktrace", ], target: { - android: { - shared_libs: [ - "libdl", - ], - }, - host: { - host_ldlibs: [ - "-ldl", - "-lpthread", - ], - }, darwin: { enabled: false, }, @@ -206,17 +190,6 @@ cc_defaults { "libbase", "libnativehelper", ], - target: { - android: { - shared_libs: ["libdl"], - }, - host: { - host_ldlibs: [ - "-ldl", - "-lpthread", - ], - }, - }, } art_cc_test_library { @@ -237,7 +210,7 @@ art_cc_test_library { } art_cc_defaults { - name: "libtiagent-base-defaults", + name: "libtiagent-base-defaults", defaults: ["libartagent-defaults"], srcs: [ // These are the ART-independent parts. @@ -302,7 +275,7 @@ art_cc_defaults { "1926-missed-frame-pop/frame_pop_missed.cc", "1927-exception-event/exception_event.cc", "1930-monitor-info/monitor.cc", - "1932-monitor-events-misc/monitor_misc.cc" + "1932-monitor-events-misc/monitor_misc.cc", ], shared_libs: [ "libbase", @@ -359,7 +332,7 @@ art_cc_defaults { art_cc_test_library { name: "libtistress", - defaults: [ "libtistress-defaults"], + defaults: ["libtistress-defaults"], shared_libs: ["libart"], } @@ -420,25 +393,15 @@ cc_defaults { "642-fp-callees/fp_callees.cc", "647-jni-get-field-id/get_field_id.cc", "656-annotation-lookup-generic-jni/test.cc", - "664-aget-verifier/aget-verifier.cc", - "708-jit-cache-churn/jit.cc" + "661-oat-writer-layout/oat_writer_layout.cc", + "664-aget-verifier/aget-verifier.cc", + "708-jit-cache-churn/jit.cc", ], shared_libs: [ "libbacktrace", "libbase", "libnativehelper", ], - target: { - android: { - shared_libs: ["libdl"], - }, - host: { - host_ldlibs: [ - "-ldl", - "-lpthread", - ], - }, - }, } art_cc_test_library { @@ -466,18 +429,4 @@ art_cc_test_library { ], header_libs: ["libnativebridge-dummy-headers"], srcs: ["115-native-bridge/nativebridge.cc"], - target: { - android: { - shared_libs: ["libdl"], - }, - host: { - host_ldlibs: [ - "-ldl", - "-lpthread", - ], - }, - linux: { - host_ldlibs: ["-lrt"], - }, - }, } diff --git a/test/GetMethodSignature/GetMethodSignature.java b/test/GetMethodSignature/GetMethodSignature.java index c2ba948d60..d2f96bbb96 100644 --- a/test/GetMethodSignature/GetMethodSignature.java +++ b/test/GetMethodSignature/GetMethodSignature.java @@ -17,4 +17,13 @@ class GetMethodSignature { Float m1(int a, double b, long c, Object d) { return null; } GetMethodSignature m2(boolean x, short y, char z) { return null; } + void m3() { } + void m4(int i) { } + void m5(int i, int j) { } + void m6(int i, int j, int[][] array1) { } + void m7(int i, int j, int[][] array1, Object o) { } + void m8(int i, int j, int[][] array1, Object o, Object[][] array2) { } + int m9() { return 0; } + int[][] mA() { return null; } + Object[][] mB() { return null; } } diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar index c16c487dd1..d37e6bc4f3 100755 --- a/test/etc/run-test-jar +++ b/test/etc/run-test-jar @@ -70,6 +70,10 @@ JVMTI_REDEFINE_STRESS="n" VDEX_FILTER="" PROFILE="n" RANDOM_PROFILE="n" +# The normal dex2oat timeout. +DEX2OAT_TIMEOUT="60" +# The *hard* timeout where we really start trying to kill the dex2oat. +DEX2OAT_RT_TIMEOUT="90" # if "y", set -Xstacktracedir and inform the test of its location. When # this is set, stack trace dumps (from signal 3) will be written to a file @@ -87,6 +91,22 @@ while true; do if [ "x$1" = "x--quiet" ]; then QUIET="y" shift + elif [ "x$1" = "x--dex2oat-rt-timeout" ]; then + shift + if [ "x$1" = "x" ]; then + echo "$0 missing argument to --dex2oat-rt-timeout" 1>&2 + exit 1 + fi + DEX2OAT_RT_TIMEOUT="$1" + shift + elif [ "x$1" = "x--dex2oat-timeout" ]; then + shift + if [ "x$1" = "x" ]; then + echo "$0 missing argument to --dex2oat-timeout" 1>&2 + exit 1 + fi + DEX2OAT_TIMEOUT="$1" + shift elif [ "x$1" = "x--jvmti" ]; then IS_JVMTI_TEST="y" shift @@ -646,10 +666,11 @@ if [ "$PREBUILD" = "y" ]; then # Note: as we don't know how decent targets are (e.g., emulator), only do this on the host for # now. We should try to improve this. # The current value is rather arbitrary. run-tests should compile quickly. + # Watchdog timeout is in milliseconds so add 3 '0's to the dex2oat timeout. if [ "$HOST" != "n" ]; then # Use SIGRTMIN+2 to try to dump threads. # Use -k 1m to SIGKILL it a minute later if it hasn't ended. - dex2oat_cmdline="timeout -k 1m -s SIGRTMIN+2 90s ${dex2oat_cmdline} --watchdog-timeout=60000" + dex2oat_cmdline="timeout -k ${DEX2OAT_TIMEOUT}s -s SIGRTMIN+2 ${DEX2OAT_RT_TIMEOUT}s ${dex2oat_cmdline} --watchdog-timeout=${DEX2OAT_TIMEOUT}000" fi if [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then vdex_cmdline="${dex2oat_cmdline} ${VDEX_FILTER} --input-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex --output-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex" diff --git a/test/knownfailures.json b/test/knownfailures.json index 252d13ae29..df24c7d749 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -366,167 +366,20 @@ "variant": "speed-profile" }, { - "tests": [ - "004-checker-UnsafeTest18", - "127-checker-secondarydex", - "441-checker-inliner", - "442-checker-constant-folding", - "444-checker-nce", - "445-checker-licm", - "446-checker-inliner2", - "447-checker-inliner3", - "449-checker-bce", - "450-checker-types", - "455-checker-gvn", - "458-checker-instruct-simplification", - "462-checker-inlining-dex-files", - "463-checker-boolean-simplifier", - "464-checker-inline-sharpen-calls", - "465-checker-clinit-gvn", - "468-checker-bool-simplif-regression", - "473-checker-inliner-constants", - "474-checker-boolean-input", - "476-checker-ctor-memory-barrier", - "477-checker-bound-type", - "478-checker-clinit-check-pruning", - "478-checker-inline-noreturn", - "478-checker-inliner-nested-loop", - "480-checker-dead-blocks", - "482-checker-loop-back-edge-use", - "484-checker-register-hints", - "485-checker-dce-loop-update", - "485-checker-dce-switch", - "486-checker-must-do-null-check", - "487-checker-inline-calls", - "488-checker-inline-recursive-calls", - "490-checker-inline", - "492-checker-inline-invoke-interface", - "493-checker-inline-invoke-interface", - "494-checker-instanceof-tests", - "495-checker-checkcast-tests", - "496-checker-inlining-class-loader", - "508-checker-disassembly", - "510-checker-try-catch", - "517-checker-builder-fallthrough", - "521-checker-array-set-null", - "522-checker-regression-monitor-exit", - "523-checker-can-throw-regression", - "525-checker-arrays-fields1", - "525-checker-arrays-fields2", - "526-checker-caller-callee-regs", - "527-checker-array-access-split", - "529-checker-unresolved", - "530-checker-loops1", - "530-checker-loops2", - "530-checker-loops3", - "530-checker-loops4", - "530-checker-loops5", - "530-checker-lse", - "530-checker-lse2", - "530-checker-regression-reftyp-final", - "532-checker-nonnull-arrayset", - "534-checker-bce-deoptimization", - "536-checker-intrinsic-optimization", - "536-checker-needs-access-check", - "537-checker-arraycopy", - "537-checker-debuggable", - "537-checker-inline-and-unverified", - "537-checker-jump-over-jump", - "538-checker-embed-constants", - "540-checker-rtp-bug", - "543-checker-dce-trycatch", - "548-checker-inlining-and-dce", - "549-checker-types-merge", - "550-checker-multiply-accumulate", - "550-checker-regression-wide-store", - "551-checker-clinit", - "551-checker-shifter-operand", - "552-checker-primitive-typeprop", - "552-checker-sharpening", - "554-checker-rtp-checkcast", - "557-checker-instruct-simplifier-ror", - "557-checker-ref-equivalent", - "559-checker-irreducible-loop", - "559-checker-rtp-ifnotnull", - "562-checker-no-intermediate", - "563-checker-fakestring", - "563-checker-invoke-super", - "564-checker-bitcount", - "564-checker-inline-loop", - "564-checker-irreducible-loop", - "564-checker-negbitwise", - "565-checker-condition-liveness", - "565-checker-doublenegbitwise", - "565-checker-irreducible-loop", - "565-checker-rotate", - "566-checker-codegen-select", - "566-checker-signum", - "567-checker-compare", - "568-checker-onebit", - "569-checker-pattern-replacement", - "570-checker-osr", - "570-checker-select", - "572-checker-array-get-regression", - "573-checker-checkcast-regression", - "575-checker-isnan", - "575-checker-string-init-alias", - "577-checker-fp2int", - "580-checker-round", - "580-checker-string-fact-intrinsics", - "582-checker-bce-length", - "583-checker-zero", - "584-checker-div-bool", - "586-checker-null-array-get", - "588-checker-irreducib-lifetime-hole", - "590-checker-arr-set-null-regression", - "591-checker-regression-dead-loop", - "592-checker-regression-bool-input", - "593-checker-boolean-2-integral-conv", - "593-checker-long-2-float-regression", - "593-checker-shift-and-simplifier", - "594-checker-array-alias", - "594-checker-irreducible-linorder", - "596-checker-dead-phi", - "598-checker-irreducible-dominance", - "599-checker-irreducible-loop", - "603-checker-instanceof", - "608-checker-unresolved-lse", - "609-checker-inline-interface", - "609-checker-x86-bounds-check", - "611-checker-simplify-if", - "614-checker-dump-constant-location", - "615-checker-arm64-store-zero", - "618-checker-induction", - "619-checker-current-method", - "620-checker-bce-intrinsics", - "622-checker-bce-regressions", - "623-checker-loop-regressions", - "624-checker-stringops", - "625-checker-licm-regressions", - "626-checker-arm64-scratch-register", - "627-checker-unroll", - "631-checker-fp-abs", - "631-checker-get-class", - "632-checker-char-at-bounds", - "633-checker-rtp-getclass", - "635-checker-arm64-volatile-load-cc", - "637-checker-throw-inline", - "638-checker-inline-caches", - "639-checker-code-sinking", - "640-checker-boolean-simd", - "640-checker-byte-simd", - "640-checker-char-simd", - "640-checker-double-simd", - "640-checker-float-simd", - "640-checker-integer-valueof", - "640-checker-int-simd", - "640-checker-long-simd", - "640-checker-short-simd", - "641-checker-arraycopy", - "643-checker-bogus-ic", - "645-checker-abs-simd", - "663-checker-select-generator", - "706-checker-scheduler"], + "test_patterns": ["616-cha.*"], + "description": ["cha tests rely on knowing more about the state of the JIT then is possible with jvmti-stress"], + "variant": "jvmti-stress & jit | redefine-stress & jit" + }, + { + "tests": [ "663-odd-dex-size", + "663-odd-dex-size2", + "663-odd-dex-size3", + "663-odd-dex-size4" ], + "description": ["All the odd-dex-size tests cause slicer to emit warnings."], + "variant": "jvmti-stress | redefine-stress" + }, + { + "test_patterns": ["[0-9]*-checker-.*"], "description": ["Checker tests are not compatible with jvmti."], "variant": "jvmti-stress | redefine-stress | trace-stress | field-stress | step-stress" }, @@ -539,20 +392,34 @@ "variant": "jvmti-stress | redefine-stress | trace-stress | step-stress" }, { + "tests": ["082-inline-execute"], + "description": ["speed-profile seems to cause the agent to be given an invalid dex file" ], + "bug": "b/65452964", + "variant": "redefine-stress & speed-profile | jvmti-stress & speed-profile" + }, + { + "tests": ["701-easy-div-rem", + "303-verification-stress"], + "description": ["speed-profile leads to dex files that slicer emits warnings about"], + "variant": "redefine-stress & speed-profile | jvmti-stress & speed-profile" + }, + { "tests": [ "950-redefine-intrinsic", "951-threaded-obsolete", "952-invoke-custom", + "952-invoke-custom-kinds", "953-invoke-polymorphic-compiler", "954-invoke-polymorphic-verifier", "955-methodhandles-smali", "956-methodhandles", "957-methodhandle-transforms", "958-methodhandle-stackframe", - "959-invoke-polymorphic-accessors" + "959-invoke-polymorphic-accessors", + "990-method-handle-and-mr" ], "description": [ - "Tests that use dex version 38 which is not yet supported by", + "Tests that use invoke-polymorphic/invoke-custom which is not yet supported by", "dexter/slicer." ], "bug": "b/37272822", @@ -620,6 +487,13 @@ "variant": "jvmti-stress | redefine-stress" }, { + "tests": [ "1911-get-local-var-table" ], + "description": [ + "Test that relies on knowing the exact layout of a dex file" + ], + "variant": "jvmti-stress | redefine-stress" + }, + { "tests": [ "536-checker-needs-access-check", "537-checker-inline-and-unverified", @@ -729,9 +603,9 @@ }, { "tests": "660-clinit", - "variant": "no-image | no-dex2oat | no-prebuild", - "description": ["Tests <clinit> for app images, which --no-image, --no-prebuild and", - "--no-dex2oat do not create"] + "variant": "no-image | no-dex2oat | no-prebuild | jvmti-stress | redefine-stress", + "description": ["Tests <clinit> for app images, which --no-image, --no-prebuild, ", + "--no-dex2oat, and --redefine-stress do not create"] }, { "tests": ["961-default-iface-resolution-gen", @@ -744,5 +618,10 @@ "tests": "664-aget-verifier", "description": ["Aget on potentially null array fails verification."], "bug": "b/64683522" + }, + { + "tests": "661-oat-writer-layout", + "variant": "interp-ac | interpreter | jit | no-dex2oat | no-prebuild | no-image | trace", + "description": ["Test is designed to only check --compiler-filter=speed"] } ] diff --git a/test/testrunner/env.py b/test/testrunner/env.py index d45d009ba4..cc19afc403 100644 --- a/test/testrunner/env.py +++ b/test/testrunner/env.py @@ -115,82 +115,9 @@ ART_HOST_TEST_DIR = tempfile.mkdtemp(prefix = 'test-art-') # Keep going after encountering a test failure? ART_TEST_KEEP_GOING = _getEnvBoolean('ART_TEST_KEEP_GOING', True) -# Do you want all tests, even those that are time consuming? -ART_TEST_FULL = _getEnvBoolean('ART_TEST_FULL', False) - -# Do you want interpreter tests run? -ART_TEST_INTERPRETER = _getEnvBoolean('ART_TEST_INTERPRETER', ART_TEST_FULL) -ART_TEST_INTERPRETER_ACCESS_CHECKS = _getEnvBoolean('ART_TEST_INTERPRETER_ACCESS_CHECKS', - ART_TEST_FULL) - -# Do you want JIT tests run? -ART_TEST_JIT = _getEnvBoolean('ART_TEST_JIT', ART_TEST_FULL) - -# Do you want optimizing compiler tests run? -ART_TEST_OPTIMIZING = _getEnvBoolean('ART_TEST_OPTIMIZING', ART_TEST_FULL) - -# Do you want to test the optimizing compiler with graph coloring register allocation? -ART_TEST_OPTIMIZING_GRAPH_COLOR = _getEnvBoolean('ART_TEST_OPTIMIZING_GRAPH_COLOR', ART_TEST_FULL) - -# Do you want to do run-tests with profiles? -ART_TEST_SPEED_PROFILE = _getEnvBoolean('ART_TEST_SPEED_PROFILE', ART_TEST_FULL) - -# Do we want to test PIC-compiled tests ("apps")? -ART_TEST_PIC_TEST = _getEnvBoolean('ART_TEST_PIC_TEST', ART_TEST_FULL) -# Do you want tracing tests run? -ART_TEST_TRACE = _getEnvBoolean('ART_TEST_TRACE', ART_TEST_FULL) - -# Do you want tracing tests (streaming mode) run? -ART_TEST_TRACE_STREAM = _getEnvBoolean('ART_TEST_TRACE_STREAM', ART_TEST_FULL) - -# Do you want tests with GC verification enabled run? -ART_TEST_GC_VERIFY = _getEnvBoolean('ART_TEST_GC_VERIFY', ART_TEST_FULL) - -# Do you want tests with the GC stress mode enabled run? -ART_TEST_GC_STRESS = _getEnvBoolean('ART_TEST_GC_STRESS', ART_TEST_FULL) - -# Do you want tests with the JNI forcecopy mode enabled run? -ART_TEST_JNI_FORCECOPY = _getEnvBoolean('ART_TEST_JNI_FORCECOPY', ART_TEST_FULL) - -# Do you want run-tests with relocation disabled run? -ART_TEST_RUN_TEST_RELOCATE = _getEnvBoolean('ART_TEST_RUN_TEST_RELOCATE', ART_TEST_FULL) - -# Do you want run-tests with prebuilding? -ART_TEST_RUN_TEST_PREBUILD = _getEnvBoolean('ART_TEST_RUN_TEST_PREBUILD', ART_TEST_FULL) - -# Do you want run-tests with no prebuilding enabled run? -ART_TEST_RUN_TEST_NO_PREBUILD = _getEnvBoolean('ART_TEST_RUN_TEST_NO_PREBUILD', ART_TEST_FULL) - -# Do you want run-tests with a pregenerated core.art? -ART_TEST_RUN_TEST_IMAGE = _getEnvBoolean('ART_TEST_RUN_TEST_IMAGE', ART_TEST_FULL) - -# Do you want run-tests without a pregenerated core.art? -ART_TEST_RUN_TEST_NO_IMAGE = _getEnvBoolean('ART_TEST_RUN_TEST_NO_IMAGE', ART_TEST_FULL) - -# Do you want run-tests with relocation enabled but patchoat failing? -ART_TEST_RUN_TEST_RELOCATE_NO_PATCHOAT = _getEnvBoolean('ART_TEST_RUN_TEST_RELOCATE_NO_PATCHOAT', - ART_TEST_FULL) - -# Do you want run-tests without a dex2oat? -ART_TEST_RUN_TEST_NO_DEX2OAT = _getEnvBoolean('ART_TEST_RUN_TEST_NO_DEX2OAT', ART_TEST_FULL) - -# Do you want run-tests with libartd.so? -ART_TEST_RUN_TEST_DEBUG = _getEnvBoolean('ART_TEST_RUN_TEST_DEBUG', ART_TEST_FULL) - -# Do you want run-tests with libart.so? -ART_TEST_RUN_TEST_NDEBUG = _getEnvBoolean('ART_TEST_RUN_TEST_NDEBUG', ART_TEST_FULL) - # Do you want failed tests to have their artifacts cleaned up? ART_TEST_RUN_TEST_ALWAYS_CLEAN = _getEnvBoolean('ART_TEST_RUN_TEST_ALWAYS_CLEAN', True) -# Do you want run-tests with the --debuggable flag -ART_TEST_RUN_TEST_DEBUGGABLE = _getEnvBoolean('ART_TEST_RUN_TEST_DEBUGGABLE', ART_TEST_FULL) - -# Do you want to test multi-part boot-image functionality? -ART_TEST_RUN_TEST_MULTI_IMAGE = _getEnvBoolean('ART_TEST_RUN_TEST_MULTI_IMAGE', ART_TEST_FULL) - -ART_TEST_DEBUG_GC = _getEnvBoolean('ART_TEST_DEBUG_GC', False) - ART_TEST_BISECTION = _getEnvBoolean('ART_TEST_BISECTION', False) DEX2OAT_HOST_INSTRUCTION_SET_FEATURES = _env.get('DEX2OAT_HOST_INSTRUCTION_SET_FEATURES') @@ -217,8 +144,6 @@ TARGET_ARCH = _get_build_var('TARGET_ARCH') # Note: ART_2ND_PHONY_TEST_HOST_SUFFIX is 2ND_ART_PHONY_HOST_TARGET_SUFFIX in .mk files # Python does not let us have variable names starting with a digit, so it has differ. -ART_TEST_RUN_TEST_JVMTI_STRESS = _getEnvBoolean('ART_TEST_RUN_TEST_JVMTI_STRESS', ART_TEST_FULL) - if TARGET_2ND_ARCH: if "64" in TARGET_ARCH: ART_PHONY_TEST_TARGET_SUFFIX = "64" diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py index f425097b57..2a772ffa1f 100755 --- a/test/testrunner/testrunner.py +++ b/test/testrunner/testrunner.py @@ -45,6 +45,7 @@ In the end, the script will print the failed and skipped tests if any. """ import argparse +import collections import fnmatch import itertools import json @@ -60,21 +61,6 @@ import time import env from target_config import target_config -TARGET_TYPES = set() -RUN_TYPES = set() -PREBUILD_TYPES = set() -COMPILER_TYPES = set() -RELOCATE_TYPES = set() -TRACE_TYPES = set() -GC_TYPES = set() -JNI_TYPES = set() -IMAGE_TYPES = set() -PICTEST_TYPES = set() -DEBUGGABLE_TYPES = set() -ADDRESS_SIZES = set() -OPTIMIZING_COMPILER_TYPES = set() -JVMTI_TYPES = set() -ADDRESS_SIZES_TARGET = {'host': set(), 'target': set()} # timeout for individual tests. # TODO: make it adjustable per tests and for buildbots timeout = 3000 # 50 minutes @@ -128,6 +114,12 @@ gdb = False gdb_arg = '' stop_testrunner = False dex2oat_jobs = -1 # -1 corresponds to default threads for dex2oat +run_all_configs = False + +# Dict to store user requested test variants. +# key: variant_type. +# value: set of variants user wants to run of type <key>. +_user_input_variants = collections.defaultdict(set) def gather_test_info(): """The method gathers test information about the test to be run which includes @@ -151,7 +143,7 @@ def gather_test_info(): VARIANT_TYPE_DICT['jvmti'] = {'no-jvmti', 'jvmti-stress', 'redefine-stress', 'trace-stress', 'field-stress', 'step-stress'} VARIANT_TYPE_DICT['compiler'] = {'interp-ac', 'interpreter', 'jit', 'optimizing', - 'regalloc_gc', 'speed-profile'} + 'regalloc_gc', 'speed-profile'} for v_type in VARIANT_TYPE_DICT: TOTAL_VARIANTS_SET = TOTAL_VARIANTS_SET.union(VARIANT_TYPE_DICT.get(v_type)) @@ -173,106 +165,75 @@ def setup_test_env(): # Bisection search writes to standard output. env.ART_TEST_QUIET = False - if not TARGET_TYPES: - TARGET_TYPES.add('host') - TARGET_TYPES.add('target') - - if env.ART_TEST_RUN_TEST_NO_PREBUILD: - PREBUILD_TYPES.add('no-prebuild') - if env.ART_TEST_RUN_TEST_NO_DEX2OAT: - PREBUILD_TYPES.add('no-dex2oat') - if env.ART_TEST_RUN_TEST_PREBUILD or not PREBUILD_TYPES: # Default - PREBUILD_TYPES.add('prebuild') - - if env.ART_TEST_INTERPRETER_ACCESS_CHECKS: - COMPILER_TYPES.add('interp-ac') - if env.ART_TEST_INTERPRETER: - COMPILER_TYPES.add('interpreter') - if env.ART_TEST_JIT: - COMPILER_TYPES.add('jit') - if env.ART_TEST_OPTIMIZING_GRAPH_COLOR: - COMPILER_TYPES.add('regalloc_gc') - OPTIMIZING_COMPILER_TYPES.add('regalloc_gc') - if env.ART_TEST_OPTIMIZING: - COMPILER_TYPES.add('optimizing') - OPTIMIZING_COMPILER_TYPES.add('optimizing') - if env.ART_TEST_SPEED_PROFILE: - COMPILER_TYPES.add('speed-profile') + global _user_input_variants + global run_all_configs + if run_all_configs: + target_types = _user_input_variants['target'] + _user_input_variants = VARIANT_TYPE_DICT + _user_input_variants['target'] = target_types + + if not _user_input_variants['target']: + _user_input_variants['target'].add('host') + _user_input_variants['target'].add('target') + + if not _user_input_variants['prebuild']: # Default + _user_input_variants['prebuild'].add('prebuild') # By default only run without jvmti - if not JVMTI_TYPES: - JVMTI_TYPES.add('no-jvmti') + if not _user_input_variants['jvmti']: + _user_input_variants['jvmti'].add('no-jvmti') # By default we run all 'compiler' variants. - if not COMPILER_TYPES: - COMPILER_TYPES.add('optimizing') - COMPILER_TYPES.add('jit') - COMPILER_TYPES.add('interpreter') - COMPILER_TYPES.add('interp-ac') - COMPILER_TYPES.add('speed-profile') - OPTIMIZING_COMPILER_TYPES.add('optimizing') - - if env.ART_TEST_RUN_TEST_RELOCATE: - RELOCATE_TYPES.add('relocate') - if env.ART_TEST_RUN_TEST_RELOCATE_NO_PATCHOAT: - RELOCATE_TYPES.add('relocate-npatchoat') - if not RELOCATE_TYPES: # Default - RELOCATE_TYPES.add('no-relocate') - - if env.ART_TEST_TRACE: - TRACE_TYPES.add('trace') - if env.ART_TEST_TRACE_STREAM: - TRACE_TYPES.add('stream') - if not TRACE_TYPES: # Default - TRACE_TYPES.add('ntrace') - - if env.ART_TEST_GC_STRESS: - GC_TYPES.add('gcstress') - if env.ART_TEST_GC_VERIFY: - GC_TYPES.add('gcverify') - if not GC_TYPES: # Default - GC_TYPES.add('cms') - - if env.ART_TEST_JNI_FORCECOPY: - JNI_TYPES.add('forcecopy') - if not JNI_TYPES: # Default - JNI_TYPES.add('checkjni') - - if env.ART_TEST_RUN_TEST_NO_IMAGE: - IMAGE_TYPES.add('no-image') - if env.ART_TEST_RUN_TEST_MULTI_IMAGE: - IMAGE_TYPES.add('multipicimage') - if env.ART_TEST_RUN_TEST_IMAGE or not IMAGE_TYPES: # Default - IMAGE_TYPES.add('picimage') - - if env.ART_TEST_PIC_TEST: - PICTEST_TYPES.add('pictest') - if not PICTEST_TYPES: # Default - PICTEST_TYPES.add('npictest') - - if env.ART_TEST_RUN_TEST_NDEBUG: - RUN_TYPES.add('ndebug') - if env.ART_TEST_RUN_TEST_DEBUG or not RUN_TYPES: # Default - RUN_TYPES.add('debug') - - if env.ART_TEST_RUN_TEST_DEBUGGABLE: - DEBUGGABLE_TYPES.add('debuggable') - if not DEBUGGABLE_TYPES: # Default - DEBUGGABLE_TYPES.add('ndebuggable') - - if not ADDRESS_SIZES: - ADDRESS_SIZES_TARGET['target'].add(env.ART_PHONY_TEST_TARGET_SUFFIX) - ADDRESS_SIZES_TARGET['host'].add(env.ART_PHONY_TEST_HOST_SUFFIX) + if not _user_input_variants['compiler']: + _user_input_variants['compiler'].add('optimizing') + _user_input_variants['compiler'].add('jit') + _user_input_variants['compiler'].add('interpreter') + _user_input_variants['compiler'].add('interp-ac') + _user_input_variants['compiler'].add('speed-profile') + + if not _user_input_variants['relocate']: # Default + _user_input_variants['relocate'].add('no-relocate') + + if not _user_input_variants['trace']: # Default + _user_input_variants['trace'].add('ntrace') + + if not _user_input_variants['gc']: # Default + _user_input_variants['gc'].add('cms') + + if not _user_input_variants['jni']: # Default + _user_input_variants['jni'].add('checkjni') + + if not _user_input_variants['image']: # Default + _user_input_variants['image'].add('picimage') + + + if not _user_input_variants['pictest']: # Default + _user_input_variants['pictest'].add('npictest') + + if not _user_input_variants['debuggable']: # Default + _user_input_variants['debuggable'].add('ndebuggable') + + if not _user_input_variants['run']: # Default + _user_input_variants['run'].add('debug') + + _user_input_variants['address_sizes_target'] = collections.defaultdict(set) + if not _user_input_variants['address_sizes']: + _user_input_variants['address_sizes_target']['target'].add( + env.ART_PHONY_TEST_TARGET_SUFFIX) + _user_input_variants['address_sizes_target']['host'].add( + env.ART_PHONY_TEST_HOST_SUFFIX) if env.ART_TEST_RUN_TEST_2ND_ARCH: - ADDRESS_SIZES_TARGET['host'].add(env.ART_2ND_PHONY_TEST_HOST_SUFFIX) - ADDRESS_SIZES_TARGET['target'].add(env.ART_2ND_PHONY_TEST_TARGET_SUFFIX) + _user_input_variants['address_sizes_target']['host'].add( + env.ART_2ND_PHONY_TEST_HOST_SUFFIX) + _user_input_variants['address_sizes_target']['target'].add( + env.ART_2ND_PHONY_TEST_TARGET_SUFFIX) else: - ADDRESS_SIZES_TARGET['host'] = ADDRESS_SIZES_TARGET['host'].union(ADDRESS_SIZES) - ADDRESS_SIZES_TARGET['target'] = ADDRESS_SIZES_TARGET['target'].union(ADDRESS_SIZES) + _user_input_variants['address_sizes_target']['host'] = _user_input_variants['address_sizes'] + _user_input_variants['address_sizes_target']['target'] = _user_input_variants['address_sizes'] global n_thread if n_thread is -1: - if 'target' in TARGET_TYPES: + if 'target' in _user_input_variants['target']: n_thread = get_default_threads('target') else: n_thread = get_default_threads('host') @@ -308,20 +269,12 @@ def run_tests(tests): options_all = '' global total_test_count total_test_count = len(tests) - total_test_count *= len(RUN_TYPES) - total_test_count *= len(PREBUILD_TYPES) - total_test_count *= len(RELOCATE_TYPES) - total_test_count *= len(TRACE_TYPES) - total_test_count *= len(GC_TYPES) - total_test_count *= len(JNI_TYPES) - total_test_count *= len(IMAGE_TYPES) - total_test_count *= len(PICTEST_TYPES) - total_test_count *= len(DEBUGGABLE_TYPES) - total_test_count *= len(COMPILER_TYPES) - total_test_count *= len(JVMTI_TYPES) + for variant_type in VARIANT_TYPE_DICT: + if not (variant_type == 'target' or 'address_sizes' in variant_type): + total_test_count *= len(_user_input_variants[variant_type]) target_address_combinations = 0 - for target in TARGET_TYPES: - for address_size in ADDRESS_SIZES_TARGET[target]: + for target in _user_input_variants['target']: + for address_size in _user_input_variants['address_sizes_target'][target]: target_address_combinations += 1 total_test_count *= target_address_combinations @@ -345,14 +298,16 @@ def run_tests(tests): if dex2oat_jobs != -1: options_all += ' --dex2oat-jobs ' + str(dex2oat_jobs) - config = itertools.product(tests, TARGET_TYPES, RUN_TYPES, PREBUILD_TYPES, - COMPILER_TYPES, RELOCATE_TYPES, TRACE_TYPES, - GC_TYPES, JNI_TYPES, IMAGE_TYPES, PICTEST_TYPES, - DEBUGGABLE_TYPES, JVMTI_TYPES) + config = itertools.product(tests, _user_input_variants['target'], _user_input_variants['run'], + _user_input_variants['prebuild'], _user_input_variants['compiler'], + _user_input_variants['relocate'], _user_input_variants['trace'], + _user_input_variants['gc'], _user_input_variants['jni'], + _user_input_variants['image'], _user_input_variants['pictest'], + _user_input_variants['debuggable'], _user_input_variants['jvmti']) for test, target, run, prebuild, compiler, relocate, trace, gc, \ jni, image, pictest, debuggable, jvmti in config: - for address_size in ADDRESS_SIZES_TARGET[target]: + for address_size in _user_input_variants['address_sizes_target'][target]: if stop_testrunner: # When ART_TEST_KEEP_GOING is set to false, then as soon as a test # fails, stop_testrunner is set to True. When this happens, the method @@ -577,11 +532,10 @@ def print_test_info(test_name, result, failed_test_info=""): total_test_count) if result == 'FAIL' or result == 'TIMEOUT': - info += ('%s %s %s\n%s\n') % ( + info += ('%s %s %s\n') % ( progress_info, test_name, - COLOR_ERROR + result + COLOR_NORMAL, - failed_test_info) + COLOR_ERROR + result + COLOR_NORMAL) else: result_text = '' if result == 'PASS': @@ -617,6 +571,7 @@ def print_test_info(test_name, result, failed_test_info=""): def verify_knownfailure_entry(entry): supported_field = { 'tests' : (list, str), + 'test_patterns' : (list,), 'description' : (list, str), 'bug' : (str,), 'variant' : (str,), @@ -650,6 +605,11 @@ def get_disabled_test_info(): tests = failure.get('tests', []) if isinstance(tests, str): tests = [tests] + patterns = failure.get("test_patterns", []) + if (not isinstance(patterns, list)): + raise ValueError("test_patters is not a list in %s" % failure) + + tests += [f for f in RUN_TEST_SET if any(re.match(pat, f) is not None for pat in patterns)] variants = parse_variants(failure.get('variant')) env_vars = failure.get('env_vars') @@ -804,19 +764,19 @@ def parse_test_name(test_name): regex += '(' + '|'.join(VARIANT_TYPE_DICT['address_sizes']) + ')$' match = re.match(regex, test_name) if match: - TARGET_TYPES.add(match.group(1)) - RUN_TYPES.add(match.group(2)) - PREBUILD_TYPES.add(match.group(3)) - COMPILER_TYPES.add(match.group(4)) - RELOCATE_TYPES.add(match.group(5)) - TRACE_TYPES.add(match.group(6)) - GC_TYPES.add(match.group(7)) - JNI_TYPES.add(match.group(8)) - IMAGE_TYPES.add(match.group(9)) - PICTEST_TYPES.add(match.group(10)) - DEBUGGABLE_TYPES.add(match.group(11)) - JVMTI_TYPES.add(match.group(12)) - ADDRESS_SIZES.add(match.group(14)) + _user_input_variants['target'].add(match.group(1)) + _user_input_variants['run'].add(match.group(2)) + _user_input_variants['prebuild'].add(match.group(3)) + _user_input_variants['compiler'].add(match.group(4)) + _user_input_variants['relocate'].add(match.group(5)) + _user_input_variants['trace'].add(match.group(6)) + _user_input_variants['gc'].add(match.group(7)) + _user_input_variants['jni'].add(match.group(8)) + _user_input_variants['image'].add(match.group(9)) + _user_input_variants['pictest'].add(match.group(10)) + _user_input_variants['debuggable'].add(match.group(11)) + _user_input_variants['jvmti'].add(match.group(12)) + _user_input_variants['address_sizes'].add(match.group(14)) return {match.group(13)} raise ValueError(test_name + " is not a valid test") @@ -865,6 +825,7 @@ def parse_option(): global gdb_arg global timeout global dex2oat_jobs + global run_all_configs parser = argparse.ArgumentParser(description="Runs all or a subset of the ART test suite.") parser.add_argument('-t', '--test', dest='test', help='name of the test') @@ -872,10 +833,7 @@ def parse_option(): parser.add_argument('--timeout', default=timeout, type=int, dest='timeout') for variant in TOTAL_VARIANTS_SET: flag = '--' + variant - flag_dest = variant.replace('-', '_') - if variant == '32' or variant == '64': - flag_dest = 'n' + flag_dest - parser.add_argument(flag, action='store_true', dest=flag_dest) + parser.add_argument(flag, action='store_true', dest=variant) parser.add_argument('--verbose', '-v', action='store_true', dest='verbose') parser.add_argument('--dry-run', action='store_true', dest='dry_run') parser.add_argument("--skip", action="append", dest="skips", default=[], @@ -894,6 +852,8 @@ def parse_option(): parser.add_argument('--gdb-arg', dest='gdb_arg') parser.add_argument('--dex2oat-jobs', type=int, dest='dex2oat_jobs', help='Number of dex2oat jobs') + parser.add_argument('-a', '--all', action='store_true', dest='run_all', + help="Run all the possible configurations for the input test set") options = vars(parser.parse_args()) if options['build_target']: @@ -904,82 +864,12 @@ def parse_option(): env.EXTRA_DISABLED_TESTS.update(set(options['skips'])) if options['test']: test = parse_test_name(options['test']) - if options['pictest']: - PICTEST_TYPES.add('pictest') - if options['ndebug']: - RUN_TYPES.add('ndebug') - if options['interp_ac']: - COMPILER_TYPES.add('interp-ac') - if options['picimage']: - IMAGE_TYPES.add('picimage') - if options['n64']: - ADDRESS_SIZES.add('64') - if options['interpreter']: - COMPILER_TYPES.add('interpreter') - if options['jni']: - JNI_TYPES.add('jni') - if options['relocate_npatchoat']: - RELOCATE_TYPES.add('relocate-npatchoat') - if options['no_prebuild']: - PREBUILD_TYPES.add('no-prebuild') - if options['npictest']: - PICTEST_TYPES.add('npictest') - if options['no_dex2oat']: - PREBUILD_TYPES.add('no-dex2oat') - if options['jit']: - COMPILER_TYPES.add('jit') - if options['relocate']: - RELOCATE_TYPES.add('relocate') - if options['ndebuggable']: - DEBUGGABLE_TYPES.add('ndebuggable') - if options['no_image']: - IMAGE_TYPES.add('no-image') - if options['optimizing']: - COMPILER_TYPES.add('optimizing') - if options['speed_profile']: - COMPILER_TYPES.add('speed-profile') - if options['trace']: - TRACE_TYPES.add('trace') - if options['gcstress']: - GC_TYPES.add('gcstress') - if options['no_relocate']: - RELOCATE_TYPES.add('no-relocate') - if options['target']: - TARGET_TYPES.add('target') - if options['forcecopy']: - JNI_TYPES.add('forcecopy') - if options['n32']: - ADDRESS_SIZES.add('32') - if options['host']: - TARGET_TYPES.add('host') - if options['gcverify']: - GC_TYPES.add('gcverify') - if options['debuggable']: - DEBUGGABLE_TYPES.add('debuggable') - if options['prebuild']: - PREBUILD_TYPES.add('prebuild') - if options['debug']: - RUN_TYPES.add('debug') - if options['checkjni']: - JNI_TYPES.add('checkjni') - if options['ntrace']: - TRACE_TYPES.add('ntrace') - if options['cms']: - GC_TYPES.add('cms') - if options['multipicimage']: - IMAGE_TYPES.add('multipicimage') - if options['jvmti_stress']: - JVMTI_TYPES.add('jvmti-stress') - if options['redefine_stress']: - JVMTI_TYPES.add('redefine-stress') - if options['field_stress']: - JVMTI_TYPES.add('field-stress') - if options['step_stress']: - JVMTI_TYPES.add('step-stress') - if options['trace_stress']: - JVMTI_TYPES.add('trace-stress') - if options['no_jvmti']: - JVMTI_TYPES.add('no-jvmti') + + for variant_type in VARIANT_TYPE_DICT: + for variant in VARIANT_TYPE_DICT[variant_type]: + if options.get(variant): + _user_input_variants[variant_type].add(variant) + if options['verbose']: verbose = True if options['n_thread']: @@ -996,6 +886,8 @@ def parse_option(): timeout = options['timeout'] if options['dex2oat_jobs']: dex2oat_jobs = options['dex2oat_jobs'] + if options['run_all']: + run_all_configs = True return test @@ -1005,9 +897,9 @@ def main(): setup_test_env() if build: build_targets = '' - if 'host' in TARGET_TYPES: + if 'host' in _user_input_variants['target']: build_targets += 'test-art-host-run-test-dependencies' - if 'target' in TARGET_TYPES: + if 'target' in _user_input_variants['target']: build_targets += 'test-art-target-run-test-dependencies' build_command = 'make' build_command += ' -j' diff --git a/tools/ahat/Android.mk b/tools/ahat/Android.mk index 2ce61cf048..cf31e2e5bd 100644 --- a/tools/ahat/Android.mk +++ b/tools/ahat/Android.mk @@ -22,10 +22,7 @@ include art/build/Android.common_path.mk include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_JAR_MANIFEST := src/manifest.txt -LOCAL_JAVA_RESOURCE_FILES := \ - $(LOCAL_PATH)/src/style.css - -LOCAL_STATIC_JAVA_LIBRARIES := perflib-prebuilt guavalib trove-prebuilt +LOCAL_JAVA_RESOURCE_FILES := $(LOCAL_PATH)/src/style.css LOCAL_IS_HOST_MODULE := true LOCAL_MODULE_TAGS := optional LOCAL_MODULE := ahat @@ -43,17 +40,11 @@ LOCAL_MODULE := ahat LOCAL_SRC_FILES := ahat include $(BUILD_PREBUILT) -# --- ahat-tests.jar -------------- -include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(call all-java-files-under, test) -LOCAL_JAR_MANIFEST := test/manifest.txt -LOCAL_STATIC_JAVA_LIBRARIES := ahat junit-host -LOCAL_IS_HOST_MODULE := true -LOCAL_MODULE_TAGS := tests -LOCAL_MODULE := ahat-tests -include $(BUILD_HOST_JAVA_LIBRARY) -AHAT_TEST_JAR := $(LOCAL_BUILT_MODULE) - +# The ahat tests rely on running ART to generate a heap dump for test, but ART +# doesn't run on darwin. Only build and run the tests for linux. +# There are also issues with running under instrumentation. +ifeq ($(HOST_OS),linux) +ifneq ($(EMMA_INSTRUMENT),true) # --- ahat-test-dump.jar -------------- include $(CLEAR_VARS) LOCAL_MODULE := ahat-test-dump @@ -69,7 +60,13 @@ include $(BUILD_JAVA_LIBRARY) AHAT_TEST_DUMP_JAR := $(LOCAL_BUILT_MODULE) AHAT_TEST_DUMP_HPROF := $(intermediates.COMMON)/test-dump.hprof AHAT_TEST_DUMP_BASE_HPROF := $(intermediates.COMMON)/test-dump-base.hprof -AHAT_TEST_DUMP_PROGUARD_MAP := $(proguard_dictionary) +AHAT_TEST_DUMP_PROGUARD_MAP := $(intermediates.COMMON)/test-dump.map + +# Generate the proguard map in the desired location by copying it from +# wherever the build system generates it by default. +$(AHAT_TEST_DUMP_PROGUARD_MAP): PRIVATE_AHAT_SOURCE_PROGUARD_MAP := $(proguard_dictionary) +$(AHAT_TEST_DUMP_PROGUARD_MAP): $(proguard_dictionary) + cp $(PRIVATE_AHAT_SOURCE_PROGUARD_MAP) $@ # Run ahat-test-dump.jar to generate test-dump.hprof and test-dump-base.hprof AHAT_TEST_DUMP_DEPENDENCIES := \ @@ -80,23 +77,38 @@ AHAT_TEST_DUMP_DEPENDENCIES := \ $(AHAT_TEST_DUMP_HPROF): PRIVATE_AHAT_TEST_ART := $(HOST_OUT_EXECUTABLES)/art $(AHAT_TEST_DUMP_HPROF): PRIVATE_AHAT_TEST_DUMP_JAR := $(AHAT_TEST_DUMP_JAR) -$(AHAT_TEST_DUMP_HPROF): PRIVATE_AHAT_TEST_DUMP_DEPENDENCIES := $(AHAT_TEST_DUMP_DEPENDENCIES) $(AHAT_TEST_DUMP_HPROF): $(AHAT_TEST_DUMP_JAR) $(AHAT_TEST_DUMP_DEPENDENCIES) $(PRIVATE_AHAT_TEST_ART) -cp $(PRIVATE_AHAT_TEST_DUMP_JAR) Main $@ $(AHAT_TEST_DUMP_BASE_HPROF): PRIVATE_AHAT_TEST_ART := $(HOST_OUT_EXECUTABLES)/art $(AHAT_TEST_DUMP_BASE_HPROF): PRIVATE_AHAT_TEST_DUMP_JAR := $(AHAT_TEST_DUMP_JAR) -$(AHAT_TEST_DUMP_BASE_HPROF): PRIVATE_AHAT_TEST_DUMP_DEPENDENCIES := $(AHAT_TEST_DUMP_DEPENDENCIES) $(AHAT_TEST_DUMP_BASE_HPROF): $(AHAT_TEST_DUMP_JAR) $(AHAT_TEST_DUMP_DEPENDENCIES) $(PRIVATE_AHAT_TEST_ART) -cp $(PRIVATE_AHAT_TEST_DUMP_JAR) Main $@ --base +# --- ahat-tests.jar -------------- +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(call all-java-files-under, test) +LOCAL_JAR_MANIFEST := test/manifest.txt +LOCAL_JAVA_RESOURCE_FILES := \ + $(AHAT_TEST_DUMP_HPROF) \ + $(AHAT_TEST_DUMP_BASE_HPROF) \ + $(AHAT_TEST_DUMP_PROGUARD_MAP) \ + $(LOCAL_PATH)/test-dump/L.hprof \ + $(LOCAL_PATH)/test-dump/O.hprof \ + $(LOCAL_PATH)/test-dump/RI.hprof +LOCAL_STATIC_JAVA_LIBRARIES := ahat junit-host +LOCAL_IS_HOST_MODULE := true +LOCAL_MODULE_TAGS := tests +LOCAL_MODULE := ahat-tests +include $(BUILD_HOST_JAVA_LIBRARY) +AHAT_TEST_JAR := $(LOCAL_BUILT_MODULE) + .PHONY: ahat-test -ahat-test: PRIVATE_AHAT_TEST_DUMP_HPROF := $(AHAT_TEST_DUMP_HPROF) -ahat-test: PRIVATE_AHAT_TEST_DUMP_BASE_HPROF := $(AHAT_TEST_DUMP_BASE_HPROF) ahat-test: PRIVATE_AHAT_TEST_JAR := $(AHAT_TEST_JAR) -ahat-test: PRIVATE_AHAT_PROGUARD_MAP := $(AHAT_TEST_DUMP_PROGUARD_MAP) -ahat-test: $(AHAT_TEST_JAR) $(AHAT_TEST_DUMP_HPROF) $(AHAT_TEST_DUMP_BASE_HPROF) - java -enableassertions -Dahat.test.dump.hprof=$(PRIVATE_AHAT_TEST_DUMP_HPROF) -Dahat.test.dump.base.hprof=$(PRIVATE_AHAT_TEST_DUMP_BASE_HPROF) -Dahat.test.dump.map=$(PRIVATE_AHAT_PROGUARD_MAP) -jar $(PRIVATE_AHAT_TEST_JAR) +ahat-test: $(AHAT_TEST_JAR) + java -enableassertions -jar $(PRIVATE_AHAT_TEST_JAR) +endif # EMMA_INSTRUMENT +endif # linux # Clean up local variables. AHAT_TEST_JAR := diff --git a/tools/ahat/README.txt b/tools/ahat/README.txt index 4471c0a7ec..ed40cb7030 100644 --- a/tools/ahat/README.txt +++ b/tools/ahat/README.txt @@ -55,25 +55,6 @@ Things to Test: Reported Issues: * Request to be able to sort tables by size. -Perflib Requests: - * Class objects should have java.lang.Class as their class object, not null. - * ArrayInstance should have asString() to get the string, without requiring a - length function. - * Document that getHeapIndex returns -1 for no such heap. - * Look up totalRetainedSize for a heap by Heap object, not by a separate heap - index. - * What's the difference between getId and getUniqueId? - * I see objects with duplicate references. - * A way to get overall retained size by heap. - * A method Instance.isReachable() - -Things to move to perflib: - * Extracting the string from a String Instance. - * Extracting bitmap data from bitmap instances. - * Adding up allocations by stack frame. - * Computing, for each instance, the other instances it dominates. - * Instance.isRoot and Instance.getRootTypes. - Release History: 1.4 Pending diff --git a/tools/ahat/src/DocString.java b/tools/ahat/src/DocString.java index 7970bf8de4..76e9e80d46 100644 --- a/tools/ahat/src/DocString.java +++ b/tools/ahat/src/DocString.java @@ -16,7 +16,6 @@ package com.android.ahat; -import com.google.common.html.HtmlEscapers; import java.net.URI; import java.net.URISyntaxException; @@ -67,7 +66,7 @@ class DocString { * Returns this object. */ public DocString append(String text) { - mStringBuilder.append(HtmlEscapers.htmlEscaper().escape(text)); + mStringBuilder.append(HtmlEscaper.escape(text)); return this; } @@ -185,7 +184,7 @@ class DocString { public DocString appendImage(URI uri, String alt) { mStringBuilder.append("<img alt=\""); - mStringBuilder.append(HtmlEscapers.htmlEscaper().escape(alt)); + mStringBuilder.append(HtmlEscaper.escape(alt)); mStringBuilder.append("\" src=\""); mStringBuilder.append(uri.toASCIIString()); mStringBuilder.append("\" />"); @@ -194,7 +193,7 @@ class DocString { public DocString appendThumbnail(URI uri, String alt) { mStringBuilder.append("<img height=\"16\" alt=\""); - mStringBuilder.append(HtmlEscapers.htmlEscaper().escape(alt)); + mStringBuilder.append(HtmlEscaper.escape(alt)); mStringBuilder.append("\" src=\""); mStringBuilder.append(uri.toASCIIString()); mStringBuilder.append("\" />"); diff --git a/tools/ahat/src/HtmlEscaper.java b/tools/ahat/src/HtmlEscaper.java new file mode 100644 index 0000000000..75a68277d3 --- /dev/null +++ b/tools/ahat/src/HtmlEscaper.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 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. + */ + +package com.android.ahat; + +public class HtmlEscaper { + /** + * Escape html characters in the input string. + */ + public static String escape(String text) { + String specials = "&<>\'\""; + String[] replacements = new String[]{"&", "<", ">", "'", """}; + StringBuilder sb = null; + int low = 0; + for (int i = 0; i < text.length(); ++i) { + int s = specials.indexOf(text.charAt(i)); + if (s != -1) { + if (sb == null) { + sb = new StringBuilder(); + } + sb.append(text.substring(low, i)); + sb.append(replacements[s]); + low = i + 1; + } + } + if (sb == null) { + return text; + } + + sb.append(text.substring(low)); + return sb.toString(); + } +} + + diff --git a/tools/ahat/src/Main.java b/tools/ahat/src/Main.java index 7cda035576..623a865785 100644 --- a/tools/ahat/src/Main.java +++ b/tools/ahat/src/Main.java @@ -18,7 +18,8 @@ package com.android.ahat; import com.android.ahat.heapdump.AhatSnapshot; import com.android.ahat.heapdump.Diff; -import com.android.tools.perflib.heap.ProguardMap; +import com.android.ahat.heapdump.Parser; +import com.android.ahat.proguard.ProguardMap; import com.sun.net.httpserver.HttpServer; import java.io.File; import java.io.IOException; @@ -46,7 +47,7 @@ public class Main { out.println(""); } - public static void main(String[] args) throws IOException { + public static void main(String[] args) throws Exception { int port = 7100; for (String arg : args) { if (arg.equals("--help")) { @@ -110,11 +111,11 @@ public class Main { HttpServer server = HttpServer.create(addr, 0); System.out.println("Processing hprof file..."); - AhatSnapshot ahat = AhatSnapshot.fromHprof(hprof, map); + AhatSnapshot ahat = Parser.parseHeapDump(hprof, map); if (hprofbase != null) { System.out.println("Processing baseline hprof file..."); - AhatSnapshot base = AhatSnapshot.fromHprof(hprofbase, mapbase); + AhatSnapshot base = Parser.parseHeapDump(hprofbase, mapbase); System.out.println("Diffing hprof files..."); Diff.snapshots(ahat, base); diff --git a/tools/ahat/src/ObjectHandler.java b/tools/ahat/src/ObjectHandler.java index f4926aa83b..79f8b76c92 100644 --- a/tools/ahat/src/ObjectHandler.java +++ b/tools/ahat/src/ObjectHandler.java @@ -25,6 +25,7 @@ import com.android.ahat.heapdump.DiffFields; import com.android.ahat.heapdump.DiffedFieldValue; import com.android.ahat.heapdump.FieldValue; import com.android.ahat.heapdump.PathElement; +import com.android.ahat.heapdump.RootType; import com.android.ahat.heapdump.Site; import com.android.ahat.heapdump.Value; import java.io.IOException; @@ -74,13 +75,13 @@ class ObjectHandler implements AhatHandler { doc.description(DocString.text("Heap"), DocString.text(inst.getHeap().getName())); - Collection<String> rootTypes = inst.getRootTypes(); + Collection<RootType> rootTypes = inst.getRootTypes(); if (rootTypes != null) { DocString types = new DocString(); String comma = ""; - for (String type : rootTypes) { + for (RootType type : rootTypes) { types.append(comma); - types.append(type); + types.append(type.toString()); comma = ", "; } doc.description(DocString.text("Root Types"), types); @@ -175,21 +176,21 @@ class ObjectHandler implements AhatHandler { was.append(Summarizer.summarize(previous)); switch (field.status) { case ADDED: - doc.row(DocString.text(field.type), + doc.row(DocString.text(field.type.name), DocString.text(field.name), Summarizer.summarize(field.current), DocString.added("new")); break; case MATCHED: - doc.row(DocString.text(field.type), + doc.row(DocString.text(field.type.name), DocString.text(field.name), Summarizer.summarize(field.current), Objects.equals(field.current, previous) ? new DocString() : was); break; case DELETED: - doc.row(DocString.text(field.type), + doc.row(DocString.text(field.type.name), DocString.text(field.name), DocString.removed("del"), was); diff --git a/tools/ahat/src/StaticHandler.java b/tools/ahat/src/StaticHandler.java index b2805d624d..4a68f1c12f 100644 --- a/tools/ahat/src/StaticHandler.java +++ b/tools/ahat/src/StaticHandler.java @@ -16,7 +16,6 @@ package com.android.ahat; -import com.google.common.io.ByteStreams; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import java.io.IOException; @@ -49,7 +48,12 @@ class StaticHandler implements HttpHandler { exchange.getResponseHeaders().add("Content-Type", mContentType); exchange.sendResponseHeaders(200, 0); OutputStream os = exchange.getResponseBody(); - ByteStreams.copy(is, os); + int read; + byte[] buf = new byte[4096]; + while ((read = is.read(buf)) >= 0) { + os.write(buf, 0, read); + } + is.close(); os.close(); } } diff --git a/tools/ahat/src/heapdump/AhatArrayInstance.java b/tools/ahat/src/heapdump/AhatArrayInstance.java index 8d23276fde..50a4805bed 100644 --- a/tools/ahat/src/heapdump/AhatArrayInstance.java +++ b/tools/ahat/src/heapdump/AhatArrayInstance.java @@ -16,20 +16,20 @@ package com.android.ahat.heapdump; -import com.android.tools.perflib.heap.ArrayInstance; -import com.android.tools.perflib.heap.Instance; import java.nio.charset.StandardCharsets; import java.util.AbstractList; import java.util.Collections; import java.util.List; public class AhatArrayInstance extends AhatInstance { - // To save space, we store byte, character, and object arrays directly as - // byte, character, and AhatInstance arrays respectively. This is especially - // important for large byte arrays, such as bitmaps. All other array types - // are stored as an array of objects, though we could potentially save space - // by specializing those too. mValues is a list view of the underlying - // array. + // To save space, we store arrays as primitive arrays or AhatInstance arrays + // and provide a wrapper over the arrays to expose a list of Values. + // This is especially important for large byte arrays, such as bitmaps. + // We keep a separate pointer to the underlying array in the case of byte or + // char arrays because they are sometimes useful to have. + // TODO: Have different subtypes of AhatArrayInstance to avoid the overhead + // of these extra pointers and cost in getReferences when the array type is + // not relevant? private List<Value> mValues; private byte[] mByteArray; // null if not a byte array. private char[] mCharArray; // null if not a char array. @@ -38,72 +38,151 @@ public class AhatArrayInstance extends AhatInstance { super(id); } - @Override void initialize(AhatSnapshot snapshot, Instance inst, Site site) { - super.initialize(snapshot, inst, site); + /** + * Initialize the array elements for a primitive boolean array. + */ + void initialize(final boolean[] bools) { + mValues = new AbstractList<Value>() { + @Override public int size() { + return bools.length; + } - ArrayInstance array = (ArrayInstance)inst; - switch (array.getArrayType()) { - case OBJECT: - Object[] objects = array.getValues(); - final AhatInstance[] insts = new AhatInstance[objects.length]; - for (int i = 0; i < objects.length; i++) { - if (objects[i] != null) { - Instance ref = (Instance)objects[i]; - insts[i] = snapshot.findInstance(ref.getId()); - } - } - mValues = new AbstractList<Value>() { - @Override public int size() { - return insts.length; - } + @Override public Value get(int index) { + return Value.pack(bools[index]); + } + }; + } - @Override public Value get(int index) { - return Value.pack(insts[index]); - } - }; - break; - - case CHAR: - final char[] chars = array.asCharArray(0, array.getLength()); - mCharArray = chars; - mValues = new AbstractList<Value>() { - @Override public int size() { - return chars.length; - } + /** + * Initialize the array elements for a primitive char array. + */ + void initialize(final char[] chars) { + mCharArray = chars; + mValues = new AbstractList<Value>() { + @Override public int size() { + return chars.length; + } - @Override public Value get(int index) { - return Value.pack(chars[index]); - } - }; - break; - - case BYTE: - final byte[] bytes = array.asRawByteArray(0, array.getLength()); - mByteArray = bytes; - mValues = new AbstractList<Value>() { - @Override public int size() { - return bytes.length; - } + @Override public Value get(int index) { + return Value.pack(chars[index]); + } + }; + } - @Override public Value get(int index) { - return Value.pack(bytes[index]); - } - }; - break; + /** + * Initialize the array elements for a primitive float array. + */ + void initialize(final float[] floats) { + mValues = new AbstractList<Value>() { + @Override public int size() { + return floats.length; + } - default: - final Object[] values = array.getValues(); - mValues = new AbstractList<Value>() { - @Override public int size() { - return values.length; - } + @Override public Value get(int index) { + return Value.pack(floats[index]); + } + }; + } - @Override public Value get(int index) { - return Value.pack(values[index]); - } - }; - break; + /** + * Initialize the array elements for a primitive double array. + */ + void initialize(final double[] doubles) { + mValues = new AbstractList<Value>() { + @Override public int size() { + return doubles.length; + } + + @Override public Value get(int index) { + return Value.pack(doubles[index]); + } + }; + } + + /** + * Initialize the array elements for a primitive byte array. + */ + void initialize(final byte[] bytes) { + mByteArray = bytes; + mValues = new AbstractList<Value>() { + @Override public int size() { + return bytes.length; + } + + @Override public Value get(int index) { + return Value.pack(bytes[index]); + } + }; + } + + /** + * Initialize the array elements for a primitive short array. + */ + void initialize(final short[] shorts) { + mValues = new AbstractList<Value>() { + @Override public int size() { + return shorts.length; + } + + @Override public Value get(int index) { + return Value.pack(shorts[index]); + } + }; + } + + /** + * Initialize the array elements for a primitive int array. + */ + void initialize(final int[] ints) { + mValues = new AbstractList<Value>() { + @Override public int size() { + return ints.length; + } + + @Override public Value get(int index) { + return Value.pack(ints[index]); + } + }; + } + + /** + * Initialize the array elements for a primitive long array. + */ + void initialize(final long[] longs) { + mValues = new AbstractList<Value>() { + @Override public int size() { + return longs.length; + } + + @Override public Value get(int index) { + return Value.pack(longs[index]); + } + }; + } + + /** + * Initialize the array elements for an instance array. + */ + void initialize(final AhatInstance[] insts) { + mValues = new AbstractList<Value>() { + @Override public int size() { + return insts.length; + } + + @Override public Value get(int index) { + return Value.pack(insts[index]); + } + }; + } + + @Override + protected long getExtraJavaSize() { + int length = getLength(); + if (length == 0) { + return 0; } + + return Value.getType(mValues.get(0)).size * getLength(); } /** diff --git a/tools/ahat/src/heapdump/AhatClassInstance.java b/tools/ahat/src/heapdump/AhatClassInstance.java index f7d8431a7b..94efa5049f 100644 --- a/tools/ahat/src/heapdump/AhatClassInstance.java +++ b/tools/ahat/src/heapdump/AhatClassInstance.java @@ -16,11 +16,8 @@ package com.android.ahat.heapdump; -import com.android.tools.perflib.heap.ClassInstance; -import com.android.tools.perflib.heap.Instance; import java.awt.image.BufferedImage; import java.util.Iterator; -import java.util.List; import java.util.NoSuchElementException; public class AhatClassInstance extends AhatInstance { @@ -34,15 +31,13 @@ public class AhatClassInstance extends AhatInstance { super(id); } - @Override void initialize(AhatSnapshot snapshot, Instance inst, Site site) { - super.initialize(snapshot, inst, site); + void initialize(Value[] fields) { + mFields = fields; + } - ClassInstance classInst = (ClassInstance)inst; - List<ClassInstance.FieldValue> fieldValues = classInst.getValues(); - mFields = new Value[fieldValues.size()]; - for (int i = 0; i < mFields.length; i++) { - mFields[i] = snapshot.getValue(fieldValues.get(i).getValue()); - } + @Override + protected long getExtraJavaSize() { + return 0; } @Override public Value getField(String fieldName) { @@ -123,7 +118,7 @@ public class AhatClassInstance extends AhatInstance { } Value value = getField("value"); - if (!value.isAhatInstance()) { + if (value == null || !value.isAhatInstance()) { return null; } @@ -248,6 +243,49 @@ public class AhatClassInstance extends AhatInstance { return bitmap; } + @Override + public RegisteredNativeAllocation asRegisteredNativeAllocation() { + if (!isInstanceOfClass("sun.misc.Cleaner")) { + return null; + } + + Value vthunk = getField("thunk"); + if (vthunk == null || !vthunk.isAhatInstance()) { + return null; + } + + AhatClassInstance thunk = vthunk.asAhatInstance().asClassInstance(); + if (thunk == null + || !thunk.isInstanceOfClass("libcore.util.NativeAllocationRegistry$CleanerThunk")) { + return null; + } + + Value vregistry = thunk.getField("this$0"); + if (vregistry == null || !vregistry.isAhatInstance()) { + return null; + } + + AhatClassInstance registry = vregistry.asAhatInstance().asClassInstance(); + if (registry == null || !registry.isInstanceOfClass("libcore.util.NativeAllocationRegistry")) { + return null; + } + + Value size = registry.getField("size"); + if (!size.isLong()) { + return null; + } + + Value referent = getField("referent"); + if (referent == null || !referent.isAhatInstance()) { + return null; + } + + RegisteredNativeAllocation rna = new RegisteredNativeAllocation(); + rna.referent = referent.asAhatInstance(); + rna.size = size.asLong(); + return rna; + } + private static class InstanceFieldIterator implements Iterable<FieldValue>, Iterator<FieldValue> { // The complete list of instance field values to iterate over, including diff --git a/tools/ahat/src/heapdump/AhatClassObj.java b/tools/ahat/src/heapdump/AhatClassObj.java index 08c70974c6..be0f71306e 100644 --- a/tools/ahat/src/heapdump/AhatClassObj.java +++ b/tools/ahat/src/heapdump/AhatClassObj.java @@ -16,13 +16,9 @@ package com.android.ahat.heapdump; -import com.android.tools.perflib.heap.ClassObj; -import com.android.tools.perflib.heap.Instance; import java.util.AbstractList; import java.util.Arrays; -import java.util.Collection; import java.util.List; -import java.util.Map; public class AhatClassObj extends AhatInstance { private String mClassName; @@ -30,43 +26,32 @@ public class AhatClassObj extends AhatInstance { private AhatInstance mClassLoader; private FieldValue[] mStaticFieldValues; private Field[] mInstanceFields; + private long mStaticFieldsSize; + private long mInstanceSize; - public AhatClassObj(long id) { + public AhatClassObj(long id, String className) { super(id); + mClassName = className; } - @Override void initialize(AhatSnapshot snapshot, Instance inst, Site site) { - super.initialize(snapshot, inst, site); - - ClassObj classObj = (ClassObj)inst; - mClassName = classObj.getClassName(); - - ClassObj superClassObj = classObj.getSuperClassObj(); - if (superClassObj != null) { - mSuperClassObj = snapshot.findClassObj(superClassObj.getId()); - } - - Instance loader = classObj.getClassLoader(); - if (loader != null) { - mClassLoader = snapshot.findInstance(loader.getId()); - } - - Collection<Map.Entry<com.android.tools.perflib.heap.Field, Object>> fieldValues - = classObj.getStaticFieldValues().entrySet(); - mStaticFieldValues = new FieldValue[fieldValues.size()]; - int index = 0; - for (Map.Entry<com.android.tools.perflib.heap.Field, Object> field : fieldValues) { - String name = field.getKey().getName(); - String type = field.getKey().getType().toString(); - Value value = snapshot.getValue(field.getValue()); - mStaticFieldValues[index++] = new FieldValue(name, type, value); - } - - com.android.tools.perflib.heap.Field[] fields = classObj.getFields(); - mInstanceFields = new Field[fields.length]; - for (int i = 0; i < fields.length; i++) { - mInstanceFields[i] = new Field(fields[i].getName(), fields[i].getType().toString()); - } + void initialize(AhatClassObj superClass, + long instanceSize, + Field[] instanceFields, + long staticFieldsSize) { + mSuperClassObj = superClass; + mInstanceSize = instanceSize; + mInstanceFields = instanceFields; + mStaticFieldsSize = staticFieldsSize; + } + + void initialize(AhatInstance classLoader, FieldValue[] staticFields) { + mClassLoader = classLoader; + mStaticFieldValues = staticFields; + } + + @Override + protected long getExtraJavaSize() { + return mStaticFieldsSize; } /** @@ -91,6 +76,14 @@ public class AhatClassObj extends AhatInstance { } /** + * Returns the size of instances of this object, as reported in the heap + * dump. + */ + public long getInstanceSize() { + return mInstanceSize; + } + + /** * Returns the static field values for this class object. */ public List<FieldValue> getStaticFieldValues() { diff --git a/tools/ahat/src/heapdump/AhatInstance.java b/tools/ahat/src/heapdump/AhatInstance.java index 0e7855801d..c04448728f 100644 --- a/tools/ahat/src/heapdump/AhatInstance.java +++ b/tools/ahat/src/heapdump/AhatInstance.java @@ -17,8 +17,6 @@ package com.android.ahat.heapdump; import com.android.ahat.dominators.DominatorsComputation; -import com.android.tools.perflib.heap.ClassObj; -import com.android.tools.perflib.heap.Instance; import java.awt.image.BufferedImage; import java.util.ArrayDeque; import java.util.ArrayList; @@ -34,14 +32,15 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, private final long mId; // Fields initialized in initialize(). - private Size mSize; private AhatHeap mHeap; private AhatClassObj mClassObj; private Site mSite; - // If this instance is a root, mRootTypes contains a set of the root types. - // If this instance is not a root, mRootTypes is null. - private List<String> mRootTypes; + // Bit vector of the root types of this object. + private int mRootTypes; + + // Field initialized via addRegisterednativeSize. + private long mRegisteredNativeSize = 0; // Fields initialized in computeReverseReferences(). private AhatInstance mNextInstanceToGcRoot; @@ -55,33 +54,29 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, private AhatInstance mImmediateDominator; private List<AhatInstance> mDominated = new ArrayList<AhatInstance>(); private Size[] mRetainedSizes; - private Object mDominatorsComputationState; // The baseline instance for purposes of diff. private AhatInstance mBaseline; + // temporary user data associated with this instance. This is used for a + // couple different purposes: + // 1. During parsing of instances, to store temporary field data. + // 2. During dominators computation, to store the dominators computation state. + private Object mTemporaryUserData; + public AhatInstance(long id) { mId = id; mBaseline = this; } /** - * Initializes this AhatInstance based on the given perflib instance. - * The AhatSnapshot should be used to look up AhatInstances and AhatHeaps. - * There is no guarantee that the AhatInstances returned by - * snapshot.findInstance have been initialized yet. + * Initialize this AhatInstance based on the the given info. */ - void initialize(AhatSnapshot snapshot, Instance inst, Site site) { - site.addInstance(this); - mSize = new Size(inst.getSize(), 0); - mHeap = snapshot.getHeap(inst.getHeap().getName()); - - ClassObj clsObj = inst.getClassObj(); - if (clsObj != null) { - mClassObj = snapshot.findClassObj(clsObj.getId()); - } - + void initialize(AhatHeap heap, Site site, AhatClassObj classObj) { + mHeap = heap; mSite = site; + site.addInstance(this); + mClassObj = classObj; } /** @@ -95,10 +90,20 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, * Returns the shallow number of bytes this object takes up. */ public Size getSize() { - return mSize; + return new Size(mClassObj.getInstanceSize() + getExtraJavaSize(), mRegisteredNativeSize); } /** + * Returns the number of bytes taken up by this object on the Java heap + * beyond the standard instance size as recorded by the class of this + * instance. + * + * For example, class objects will have extra size for static fields and + * array objects will have extra size for the array elements. + */ + protected abstract long getExtraJavaSize(); + + /** * Returns the number of bytes belonging to the given heap that this instance * retains. */ @@ -127,7 +132,7 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, * Increment the number of registered native bytes tied to this object. */ void addRegisteredNativeSize(long size) { - mSize = mSize.plusRegisteredNativeSize(size); + mRegisteredNativeSize += size; } /** @@ -154,27 +159,32 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, * Returns true if this instance is marked as a root instance. */ public boolean isRoot() { - return mRootTypes != null; + return mRootTypes != 0; } /** * Marks this instance as being a root of the given type. */ - void addRootType(String type) { - if (mRootTypes == null) { - mRootTypes = new ArrayList<String>(); - mRootTypes.add(type); - } else if (!mRootTypes.contains(type)) { - mRootTypes.add(type); - } + void addRootType(RootType type) { + mRootTypes |= type.mask; } /** - * Returns a list of string descriptions of the root types of this object. + * Returns a list of the root types of this object. * Returns null if this object is not a root. */ - public Collection<String> getRootTypes() { - return mRootTypes; + public Collection<RootType> getRootTypes() { + if (!isRoot()) { + return null; + } + + List<RootType> types = new ArrayList<RootType>(); + for (RootType type : RootType.values()) { + if ((mRootTypes & type.mask) != 0) { + types.add(type); + } + } + return types; } /** @@ -363,6 +373,19 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, return null; } + public static class RegisteredNativeAllocation { + public AhatInstance referent; + public long size; + }; + + /** + * Return the registered native allocation that this instance represents, if + * any. This is relevant for instances of sun.misc.Cleaner. + */ + public RegisteredNativeAllocation asRegisteredNativeAllocation() { + return null; + } + /** * Returns a sample path from a GC root to this instance. * This instance is included as the last element of the path with an empty @@ -433,6 +456,14 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, return new AhatPlaceHolderInstance(this); } + public void setTemporaryUserData(Object state) { + mTemporaryUserData = state; + } + + public Object getTemporaryUserData() { + return mTemporaryUserData; + } + /** * Initialize the reverse reference fields of this instance and all other * instances reachable from it. Initializes the following fields: @@ -498,7 +529,7 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } if (!(inst instanceof SuperRoot)) { inst.mRetainedSizes[inst.mHeap.getIndex()] = - inst.mRetainedSizes[inst.mHeap.getIndex()].plus(inst.mSize); + inst.mRetainedSizes[inst.mHeap.getIndex()].plus(inst.getSize()); } deque.push(inst); for (AhatInstance dominated : inst.mDominated) { @@ -516,12 +547,12 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, @Override public void setDominatorsComputationState(Object state) { - mDominatorsComputationState = state; + setTemporaryUserData(state); } @Override public Object getDominatorsComputationState() { - return mDominatorsComputationState; + return getTemporaryUserData(); } @Override diff --git a/tools/ahat/src/heapdump/AhatPlaceHolderClassObj.java b/tools/ahat/src/heapdump/AhatPlaceHolderClassObj.java index 8b4c6796aa..07f5b50012 100644 --- a/tools/ahat/src/heapdump/AhatPlaceHolderClassObj.java +++ b/tools/ahat/src/heapdump/AhatPlaceHolderClassObj.java @@ -24,11 +24,15 @@ package com.android.ahat.heapdump; */ public class AhatPlaceHolderClassObj extends AhatClassObj { AhatPlaceHolderClassObj(AhatClassObj baseline) { - super(-1); + super(-1, baseline.getClassName()); setBaseline(baseline); baseline.setBaseline(this); } + @Override public Size getSize() { + return Size.ZERO; + } + @Override public Size getRetainedSize(AhatHeap heap) { return Size.ZERO; } diff --git a/tools/ahat/src/heapdump/AhatPlaceHolderInstance.java b/tools/ahat/src/heapdump/AhatPlaceHolderInstance.java index 9abc952072..884940370d 100644 --- a/tools/ahat/src/heapdump/AhatPlaceHolderInstance.java +++ b/tools/ahat/src/heapdump/AhatPlaceHolderInstance.java @@ -36,6 +36,10 @@ public class AhatPlaceHolderInstance extends AhatInstance { return Size.ZERO; } + @Override protected long getExtraJavaSize() { + return 0; + } + @Override public Size getRetainedSize(AhatHeap heap) { return Size.ZERO; } diff --git a/tools/ahat/src/heapdump/AhatSnapshot.java b/tools/ahat/src/heapdump/AhatSnapshot.java index 1b2cf3c59f..945966cec7 100644 --- a/tools/ahat/src/heapdump/AhatSnapshot.java +++ b/tools/ahat/src/heapdump/AhatSnapshot.java @@ -17,158 +17,43 @@ package com.android.ahat.heapdump; import com.android.ahat.dominators.DominatorsComputation; -import com.android.tools.perflib.captures.DataBuffer; -import com.android.tools.perflib.captures.MemoryMappedFileBuffer; -import com.android.tools.perflib.heap.ArrayInstance; -import com.android.tools.perflib.heap.ClassInstance; -import com.android.tools.perflib.heap.ClassObj; -import com.android.tools.perflib.heap.Heap; -import com.android.tools.perflib.heap.Instance; -import com.android.tools.perflib.heap.ProguardMap; -import com.android.tools.perflib.heap.RootObj; -import com.android.tools.perflib.heap.Snapshot; -import com.android.tools.perflib.heap.StackFrame; -import com.android.tools.perflib.heap.StackTrace; -import gnu.trove.TObjectProcedure; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; import java.util.List; -import java.util.Map; public class AhatSnapshot implements Diffable<AhatSnapshot> { - private final Site mRootSite = new Site("ROOT"); + private final Site mRootSite; - // Collection of objects whose immediate dominator is the SENTINEL_ROOT. - private final List<AhatInstance> mRooted; + private final SuperRoot mSuperRoot; - // List of all ahat instances stored in increasing order by id. - private final List<AhatInstance> mInstances = new ArrayList<AhatInstance>(); + // List of all ahat instances. + private final Instances<AhatInstance> mInstances; - private final List<AhatHeap> mHeaps = new ArrayList<AhatHeap>(); + private List<AhatHeap> mHeaps; private AhatSnapshot mBaseline = this; - /** - * Create an AhatSnapshot from an hprof file. - */ - public static AhatSnapshot fromHprof(File hprof, ProguardMap map) throws IOException { - return fromDataBuffer(new MemoryMappedFileBuffer(hprof), map); - } - - /** - * Create an AhatSnapshot from an in-memory data buffer. - */ - public static AhatSnapshot fromDataBuffer(DataBuffer buffer, ProguardMap map) throws IOException { - AhatSnapshot snapshot = new AhatSnapshot(buffer, map); - - // Request a GC now to clean up memory used by perflib. This helps to - // avoid a noticable pause when visiting the first interesting page in - // ahat. - System.gc(); - - return snapshot; - } - - /** - * Constructs an AhatSnapshot for the given hprof binary data. - */ - private AhatSnapshot(DataBuffer buffer, ProguardMap map) throws IOException { - Snapshot snapshot = Snapshot.createSnapshot(buffer, map); - - // Properly label the class of class objects in the perflib snapshot. - final ClassObj javaLangClass = snapshot.findClass("java.lang.Class"); - if (javaLangClass != null) { - for (Heap heap : snapshot.getHeaps()) { - Collection<ClassObj> classes = heap.getClasses(); - for (ClassObj clsObj : classes) { - if (clsObj.getClassObj() == null) { - clsObj.setClassId(javaLangClass.getId()); - } - } - } - } - - // Create mappings from id to ahat instance and heaps. - Collection<Heap> heaps = snapshot.getHeaps(); - for (Heap heap : heaps) { - // Note: mHeaps will not be in index order if snapshot.getHeaps does not - // return heaps in index order. That's fine, because we don't rely on - // mHeaps being in index order. - mHeaps.add(new AhatHeap(heap.getName(), snapshot.getHeapIndex(heap))); - TObjectProcedure<Instance> doCreate = new TObjectProcedure<Instance>() { - @Override - public boolean execute(Instance inst) { - long id = inst.getId(); - if (inst instanceof ClassInstance) { - mInstances.add(new AhatClassInstance(id)); - } else if (inst instanceof ArrayInstance) { - mInstances.add(new AhatArrayInstance(id)); - } else if (inst instanceof ClassObj) { - AhatClassObj classObj = new AhatClassObj(id); - mInstances.add(classObj); - } - return true; - } - }; - for (Instance instance : heap.getClasses()) { - doCreate.execute(instance); - } - heap.forEachInstance(doCreate); - } - - // Sort the instances by id so we can use binary search to lookup - // instances by id. - mInstances.sort(new Comparator<AhatInstance>() { - @Override - public int compare(AhatInstance a, AhatInstance b) { - return Long.compare(a.getId(), b.getId()); - } - }); - - Map<Instance, Long> registeredNative = Perflib.getRegisteredNativeAllocations(snapshot); - - // Initialize ahat snapshot and instances based on the perflib snapshot - // and instances. - for (AhatInstance ahat : mInstances) { - Instance inst = snapshot.findInstance(ahat.getId()); - - StackFrame[] frames = null; - StackTrace stack = inst.getStack(); - if (stack != null) { - frames = stack.getFrames(); - } - ahat.initialize(this, inst, mRootSite.getSite(frames)); - - Long registeredNativeSize = registeredNative.get(inst); - if (registeredNativeSize != null) { - ahat.addRegisteredNativeSize(registeredNativeSize); + AhatSnapshot(SuperRoot root, + Instances<AhatInstance> instances, + List<AhatHeap> heaps, + Site rootSite) { + mSuperRoot = root; + mInstances = instances; + mHeaps = heaps; + mRootSite = rootSite; + + // Update registered native allocation size. + for (AhatInstance cleaner : mInstances) { + AhatInstance.RegisteredNativeAllocation nra = cleaner.asRegisteredNativeAllocation(); + if (nra != null) { + nra.referent.addRegisteredNativeSize(nra.size); } } - // Record the roots and their types. - SuperRoot superRoot = new SuperRoot(); - for (RootObj root : snapshot.getGCRoots()) { - Instance inst = root.getReferredInstance(); - if (inst != null) { - AhatInstance ahat = findInstance(inst.getId()); - if (!ahat.isRoot()) { - superRoot.addRoot(ahat); - } - ahat.addRootType(root.getRootType().toString()); - } - } - snapshot.dispose(); - - AhatInstance.computeReverseReferences(superRoot); - DominatorsComputation.computeDominators(superRoot); - AhatInstance.computeRetainedSize(superRoot, mHeaps.size()); + AhatInstance.computeReverseReferences(mSuperRoot); + DominatorsComputation.computeDominators(mSuperRoot); + AhatInstance.computeRetainedSize(mSuperRoot, mHeaps.size()); - mRooted = superRoot.getDominated(); for (AhatHeap heap : mHeaps) { - heap.addToSize(superRoot.getRetainedSize(heap)); + heap.addToSize(mSuperRoot.getRetainedSize(heap)); } mRootSite.prepareForUse(0, mHeaps.size()); @@ -179,22 +64,7 @@ public class AhatSnapshot implements Diffable<AhatSnapshot> { * Returns null if no instance with the given id is found. */ public AhatInstance findInstance(long id) { - // Binary search over the sorted instances. - int start = 0; - int end = mInstances.size(); - while (start < end) { - int mid = start + ((end - start) / 2); - AhatInstance midInst = mInstances.get(mid); - long midId = midInst.getId(); - if (id == midId) { - return midInst; - } else if (id < midId) { - end = mid; - } else { - start = mid + 1; - } - } - return null; + return mInstances.get(id); } /** @@ -235,7 +105,7 @@ public class AhatSnapshot implements Diffable<AhatSnapshot> { * SENTINEL_ROOT. */ public List<AhatInstance> getRooted() { - return mRooted; + return mSuperRoot.getDominated(); } /** @@ -252,14 +122,6 @@ public class AhatSnapshot implements Diffable<AhatSnapshot> { return site == null ? mRootSite : site; } - // Return the Value for the given perflib value object. - Value getValue(Object value) { - if (value instanceof Instance) { - value = findInstance(((Instance)value).getId()); - } - return Value.pack(value); - } - public void setBaseline(AhatSnapshot baseline) { mBaseline = baseline; } diff --git a/tools/ahat/src/heapdump/DiffedFieldValue.java b/tools/ahat/src/heapdump/DiffedFieldValue.java index e2dcf3e8f0..3cd273ed98 100644 --- a/tools/ahat/src/heapdump/DiffedFieldValue.java +++ b/tools/ahat/src/heapdump/DiffedFieldValue.java @@ -23,7 +23,7 @@ import java.util.Objects; */ public class DiffedFieldValue { public final String name; - public final String type; + public final Type type; public final Value current; public final Value baseline; @@ -60,7 +60,7 @@ public class DiffedFieldValue { return new DiffedFieldValue(baseline.name, baseline.type, null, baseline.value, Status.DELETED); } - private DiffedFieldValue(String name, String type, Value current, Value baseline, Status status) { + private DiffedFieldValue(String name, Type type, Value current, Value baseline, Status status) { this.name = name; this.type = type; this.current = current; diff --git a/tools/ahat/src/heapdump/Field.java b/tools/ahat/src/heapdump/Field.java index 01f87c726e..dff401796a 100644 --- a/tools/ahat/src/heapdump/Field.java +++ b/tools/ahat/src/heapdump/Field.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2017 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. @@ -18,9 +18,9 @@ package com.android.ahat.heapdump; public class Field { public final String name; - public final String type; + public final Type type; - public Field(String name, String type) { + public Field(String name, Type type) { this.name = name; this.type = type; } diff --git a/tools/ahat/src/heapdump/FieldValue.java b/tools/ahat/src/heapdump/FieldValue.java index 6d725953b3..20e6da7271 100644 --- a/tools/ahat/src/heapdump/FieldValue.java +++ b/tools/ahat/src/heapdump/FieldValue.java @@ -18,10 +18,10 @@ package com.android.ahat.heapdump; public class FieldValue { public final String name; - public final String type; + public final Type type; public final Value value; - public FieldValue(String name, String type, Value value) { + public FieldValue(String name, Type type, Value value) { this.name = name; this.type = type; this.value = value; diff --git a/tools/ahat/src/heapdump/HprofFormatException.java b/tools/ahat/src/heapdump/HprofFormatException.java new file mode 100644 index 0000000000..55e8958c43 --- /dev/null +++ b/tools/ahat/src/heapdump/HprofFormatException.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2017 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. + */ + +package com.android.ahat.heapdump; + +public class HprofFormatException extends Exception { + public HprofFormatException(String msg) { + super(msg); + } +} diff --git a/tools/ahat/src/heapdump/Instances.java b/tools/ahat/src/heapdump/Instances.java new file mode 100644 index 0000000000..085144650f --- /dev/null +++ b/tools/ahat/src/heapdump/Instances.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2017 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. + */ + +package com.android.ahat.heapdump; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +/** + * A collection of instances that can be searched for by id. + */ +class Instances<T extends AhatInstance> implements Iterable<T> { + + private final List<T> mInstances; + + /** + * Create a collection of instances that can be looked up by id. + * Note: this takes ownership of the given list of instances. + */ + public Instances(List<T> instances) { + mInstances = instances; + + // Sort the instances by id so we can use binary search to lookup + // instances by id. + instances.sort(new Comparator<AhatInstance>() { + @Override + public int compare(AhatInstance a, AhatInstance b) { + return Long.compare(a.getId(), b.getId()); + } + }); + } + + /** + * Look up an instance by id. + * Returns null if no instance with the given id is found. + */ + public T get(long id) { + // Binary search over the sorted instances. + int start = 0; + int end = mInstances.size(); + while (start < end) { + int mid = start + ((end - start) / 2); + T midInst = mInstances.get(mid); + long midId = midInst.getId(); + if (id == midId) { + return midInst; + } else if (id < midId) { + end = mid; + } else { + start = mid + 1; + } + } + return null; + } + + @Override + public Iterator<T> iterator() { + return mInstances.iterator(); + } +} + diff --git a/tools/ahat/src/heapdump/Parser.java b/tools/ahat/src/heapdump/Parser.java new file mode 100644 index 0000000000..3d5f95f6ae --- /dev/null +++ b/tools/ahat/src/heapdump/Parser.java @@ -0,0 +1,942 @@ +/* + * Copyright (C) 2017 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. + */ + +package com.android.ahat.heapdump; + +import com.android.ahat.proguard.ProguardMap; +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.StandardCharsets; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class Parser { + private static final int ID_SIZE = 4; + + /** + * Parse the given heap dump using the given proguard map for deobfuscation. + * We make the following assumptions about valid heap dumps: + * Class serial numbers, stack frames, and stack traces + * individually satisfy the following: + * - all elements are defined before they are referenced. + * - ids are densely packed in some range [a, b] where a is not + * necessarily 0. + * - there are not more than 2^31 elements defined. + * All classes are defined via a LOAD CLASS record before the first heap + * dump segment. + * The ID size used in the heap dump is 4 bytes. + */ + public static AhatSnapshot parseHeapDump(File hprof, ProguardMap map) + throws IOException, HprofFormatException { + return parseHeapDump(new HprofBuffer(hprof), map); + } + + /** + * Parse a heap dump from a byte buffer. + */ + public static AhatSnapshot parseHeapDump(ByteBuffer hprof, ProguardMap map) + throws IOException, HprofFormatException { + return parseHeapDump(new HprofBuffer(hprof), map); + } + + private static AhatSnapshot parseHeapDump(HprofBuffer hprof, ProguardMap map) + throws IOException, HprofFormatException { + // Read, and mostly ignore, the hprof header info. + { + StringBuilder format = new StringBuilder(); + int b; + while ((b = hprof.getU1()) != 0) { + format.append((char)b); + } + + int idSize = hprof.getU4(); + if (idSize != ID_SIZE) { + throw new HprofFormatException("Id size " + idSize + " not supported."); + } + int hightime = hprof.getU4(); + int lowtime = hprof.getU4(); + } + + // First pass: Read through all the heap dump records. Construct the + // AhatInstances, initialize them as much as possible and save any + // additional temporary data we need to complete their initialization in + // the fixup pass. + Site rootSite = new Site("ROOT"); + List<AhatInstance> instances = new ArrayList<AhatInstance>(); + List<RootData> roots = new ArrayList<RootData>(); + HeapList heaps = new HeapList(); + { + // Note: Strings do not satisfy the DenseMap requirements on heap dumps + // from Android K. + UnDenseMap<String> strings = new UnDenseMap<String>("String"); + DenseMap<ProguardMap.Frame> frames = new DenseMap<ProguardMap.Frame>("Stack Frame"); + DenseMap<Site> sites = new DenseMap<Site>("Stack Trace"); + DenseMap<String> classNamesBySerial = new DenseMap<String>("Class Serial Number"); + AhatClassObj javaLangClass = null; + AhatClassObj[] primArrayClasses = new AhatClassObj[Type.values().length]; + ArrayList<AhatClassObj> classes = new ArrayList<AhatClassObj>(); + Instances<AhatClassObj> classById = null; + + while (hprof.hasRemaining()) { + int tag = hprof.getU1(); + int time = hprof.getU4(); + int recordLength = hprof.getU4(); + switch (tag) { + case 0x01: { // STRING + long id = hprof.getId(); + byte[] bytes = new byte[recordLength - ID_SIZE]; + hprof.getBytes(bytes); + String str = new String(bytes, StandardCharsets.UTF_8); + strings.put(id, str); + break; + } + + case 0x02: { // LOAD CLASS + int classSerialNumber = hprof.getU4(); + long objectId = hprof.getId(); + int stackSerialNumber = hprof.getU4(); + long classNameStringId = hprof.getId(); + String obfClassName = strings.get(classNameStringId); + String clrClassName = map.getClassName(obfClassName); + AhatClassObj classObj = new AhatClassObj(objectId, clrClassName); + classNamesBySerial.put(classSerialNumber, clrClassName); + classes.add(classObj); + + // Check whether this class is one of the special classes we are + // interested in, and if so, save it for later use. + if ("java.lang.Class".equals(clrClassName)) { + javaLangClass = classObj; + } + + for (Type type : Type.values()) { + if (clrClassName.equals(type.name + "[]")) { + primArrayClasses[type.ordinal()] = classObj; + } + } + break; + } + + case 0x04: { // STACK FRAME + long frameId = hprof.getId(); + long methodNameStringId = hprof.getId(); + long methodSignatureStringId = hprof.getId(); + long methodFileNameStringId = hprof.getId(); + int classSerialNumber = hprof.getU4(); + int lineNumber = hprof.getU4(); + + ProguardMap.Frame frame = map.getFrame( + classNamesBySerial.get(classSerialNumber), + strings.get(methodNameStringId), + strings.get(methodSignatureStringId), + strings.get(methodFileNameStringId), + lineNumber); + frames.put(frameId, frame); + break; + } + + case 0x05: { // STACK TRACE + int stackSerialNumber = hprof.getU4(); + int threadSerialNumber = hprof.getU4(); + int numFrames = hprof.getU4(); + ProguardMap.Frame[] trace = new ProguardMap.Frame[numFrames]; + for (int i = 0; i < numFrames; i++) { + long frameId = hprof.getId(); + trace[i] = frames.get(frameId); + } + sites.put(stackSerialNumber, rootSite.getSite(trace)); + break; + } + + case 0x1C: { // HEAP DUMP SEGMENT + if (classById == null) { + classById = new Instances<AhatClassObj>(classes); + } + int subtag; + while (!isEndOfHeapDumpSegment(subtag = hprof.getU1())) { + switch (subtag) { + case 0x01: { // ROOT JNI GLOBAL + long objectId = hprof.getId(); + long refId = hprof.getId(); + roots.add(new RootData(objectId, RootType.JNI_GLOBAL)); + break; + } + + case 0x02: { // ROOT JNI LOCAL + long objectId = hprof.getId(); + int threadSerialNumber = hprof.getU4(); + int frameNumber = hprof.getU4(); + roots.add(new RootData(objectId, RootType.JNI_LOCAL)); + break; + } + + case 0x03: { // ROOT JAVA FRAME + long objectId = hprof.getId(); + int threadSerialNumber = hprof.getU4(); + int frameNumber = hprof.getU4(); + roots.add(new RootData(objectId, RootType.JAVA_FRAME)); + break; + } + + case 0x04: { // ROOT NATIVE STACK + long objectId = hprof.getId(); + int threadSerialNumber = hprof.getU4(); + roots.add(new RootData(objectId, RootType.NATIVE_STACK)); + break; + } + + case 0x05: { // ROOT STICKY CLASS + long objectId = hprof.getId(); + roots.add(new RootData(objectId, RootType.STICKY_CLASS)); + break; + } + + case 0x06: { // ROOT THREAD BLOCK + long objectId = hprof.getId(); + int threadSerialNumber = hprof.getU4(); + roots.add(new RootData(objectId, RootType.THREAD_BLOCK)); + break; + } + + case 0x07: { // ROOT MONITOR USED + long objectId = hprof.getId(); + roots.add(new RootData(objectId, RootType.MONITOR)); + break; + } + + case 0x08: { // ROOT THREAD OBJECT + long objectId = hprof.getId(); + int threadSerialNumber = hprof.getU4(); + int stackSerialNumber = hprof.getU4(); + roots.add(new RootData(objectId, RootType.THREAD)); + break; + } + + case 0x20: { // CLASS DUMP + ClassObjData data = new ClassObjData(); + long objectId = hprof.getId(); + int stackSerialNumber = hprof.getU4(); + long superClassId = hprof.getId(); + data.classLoaderId = hprof.getId(); + long signersId = hprof.getId(); + long protectionId = hprof.getId(); + long reserved1 = hprof.getId(); + long reserved2 = hprof.getId(); + int instanceSize = hprof.getU4(); + int constantPoolSize = hprof.getU2(); + for (int i = 0; i < constantPoolSize; ++i) { + int index = hprof.getU2(); + Type type = hprof.getType(); + hprof.skip(type.size); + } + int numStaticFields = hprof.getU2(); + data.staticFields = new FieldValue[numStaticFields]; + AhatClassObj obj = classById.get(objectId); + String clrClassName = obj.getName(); + long staticFieldsSize = 0; + for (int i = 0; i < numStaticFields; ++i) { + String obfName = strings.get(hprof.getId()); + String clrName = map.getFieldName(clrClassName, obfName); + Type type = hprof.getType(); + Value value = hprof.getDeferredValue(type); + staticFieldsSize += type.size; + data.staticFields[i] = new FieldValue(clrName, type, value); + } + AhatClassObj superClass = classById.get(superClassId); + int numInstanceFields = hprof.getU2(); + Field[] ifields = new Field[numInstanceFields]; + for (int i = 0; i < numInstanceFields; ++i) { + String name = map.getFieldName(obj.getName(), strings.get(hprof.getId())); + ifields[i] = new Field(name, hprof.getType()); + } + Site site = sites.get(stackSerialNumber); + + if (javaLangClass == null) { + throw new HprofFormatException("No class definition found for java.lang.Class"); + } + obj.initialize(heaps.getCurrentHeap(), site, javaLangClass); + obj.initialize(superClass, instanceSize, ifields, staticFieldsSize); + obj.setTemporaryUserData(data); + break; + } + + case 0x21: { // INSTANCE DUMP + long objectId = hprof.getId(); + int stackSerialNumber = hprof.getU4(); + long classId = hprof.getId(); + int numBytes = hprof.getU4(); + ClassInstData data = new ClassInstData(hprof.tell()); + hprof.skip(numBytes); + + Site site = sites.get(stackSerialNumber); + AhatClassObj classObj = classById.get(classId); + AhatClassInstance obj = new AhatClassInstance(objectId); + obj.initialize(heaps.getCurrentHeap(), site, classObj); + obj.setTemporaryUserData(data); + instances.add(obj); + break; + } + + case 0x22: { // OBJECT ARRAY DUMP + long objectId = hprof.getId(); + int stackSerialNumber = hprof.getU4(); + int length = hprof.getU4(); + long classId = hprof.getId(); + ObjArrayData data = new ObjArrayData(length, hprof.tell()); + hprof.skip(length * ID_SIZE); + + Site site = sites.get(stackSerialNumber); + AhatClassObj classObj = classById.get(classId); + AhatArrayInstance obj = new AhatArrayInstance(objectId); + obj.initialize(heaps.getCurrentHeap(), site, classObj); + obj.setTemporaryUserData(data); + instances.add(obj); + break; + } + + case 0x23: { // PRIMITIVE ARRAY DUMP + long objectId = hprof.getId(); + int stackSerialNumber = hprof.getU4(); + int length = hprof.getU4(); + Type type = hprof.getPrimitiveType(); + Site site = sites.get(stackSerialNumber); + + AhatClassObj classObj = primArrayClasses[type.ordinal()]; + if (classObj == null) { + throw new HprofFormatException( + "No class definition found for " + type.name + "[]"); + } + + AhatArrayInstance obj = new AhatArrayInstance(objectId); + obj.initialize(heaps.getCurrentHeap(), site, classObj); + instances.add(obj); + switch (type) { + case BOOLEAN: { + boolean[] data = new boolean[length]; + for (int i = 0; i < length; ++i) { + data[i] = hprof.getBool(); + } + obj.initialize(data); + break; + } + + case CHAR: { + char[] data = new char[length]; + for (int i = 0; i < length; ++i) { + data[i] = hprof.getChar(); + } + obj.initialize(data); + break; + } + + case FLOAT: { + float[] data = new float[length]; + for (int i = 0; i < length; ++i) { + data[i] = hprof.getFloat(); + } + obj.initialize(data); + break; + } + + case DOUBLE: { + double[] data = new double[length]; + for (int i = 0; i < length; ++i) { + data[i] = hprof.getDouble(); + } + obj.initialize(data); + break; + } + + case BYTE: { + byte[] data = new byte[length]; + hprof.getBytes(data); + obj.initialize(data); + break; + } + + case SHORT: { + short[] data = new short[length]; + for (int i = 0; i < length; ++i) { + data[i] = hprof.getShort(); + } + obj.initialize(data); + break; + } + + case INT: { + int[] data = new int[length]; + for (int i = 0; i < length; ++i) { + data[i] = hprof.getInt(); + } + obj.initialize(data); + break; + } + + case LONG: { + long[] data = new long[length]; + for (int i = 0; i < length; ++i) { + data[i] = hprof.getLong(); + } + obj.initialize(data); + break; + } + } + break; + } + + case 0x89: { // ROOT INTERNED STRING (ANDROID) + long objectId = hprof.getId(); + roots.add(new RootData(objectId, RootType.INTERNED_STRING)); + break; + } + + case 0x8b: { // ROOT DEBUGGER (ANDROID) + long objectId = hprof.getId(); + roots.add(new RootData(objectId, RootType.DEBUGGER)); + break; + } + + case 0x8d: { // ROOT VM INTERNAL (ANDROID) + long objectId = hprof.getId(); + roots.add(new RootData(objectId, RootType.VM_INTERNAL)); + break; + } + + case 0x8e: { // ROOT JNI MONITOR (ANDROID) + long objectId = hprof.getId(); + int threadSerialNumber = hprof.getU4(); + int frameNumber = hprof.getU4(); + roots.add(new RootData(objectId, RootType.JNI_MONITOR)); + break; + } + + case 0xfe: { // HEAP DUMP INFO (ANDROID) + int type = hprof.getU4(); + long stringId = hprof.getId(); + heaps.setCurrentHeap(strings.get(stringId)); + break; + } + + case 0xff: { // ROOT UNKNOWN + long objectId = hprof.getId(); + roots.add(new RootData(objectId, RootType.UNKNOWN)); + break; + } + + default: + throw new HprofFormatException( + String.format("Unsupported heap dump sub tag 0x%02x", subtag)); + } + } + + // Reset the file pointer back because we read the first byte into + // the next record. + hprof.skip(-1); + break; + } + + default: + // Ignore any other tags that we either don't know about or don't + // care about. + hprof.skip(recordLength); + break; + } + } + + instances.addAll(classes); + } + + // Sort roots and instances by id in preparation for the fixup pass. + Instances<AhatInstance> mInstances = new Instances<AhatInstance>(instances); + roots.sort(new Comparator<RootData>() { + @Override + public int compare(RootData a, RootData b) { + return Long.compare(a.id, b.id); + } + }); + roots.add(null); + + // Fixup pass: Label the root instances and fix up references to instances + // that we couldn't previously resolve. + SuperRoot superRoot = new SuperRoot(); + { + Iterator<RootData> ri = roots.iterator(); + RootData root = ri.next(); + for (AhatInstance inst : mInstances) { + long id = inst.getId(); + + // Skip past any roots that don't have associated instances. + // It's not clear why there would be a root without an associated + // instance dump, but it does happen in practice, for example when + // taking heap dumps using the RI. + while (root != null && root.id < id) { + root = ri.next(); + } + + // Check if this instance is a root, and if so, update its root types. + if (root != null && root.id == id) { + superRoot.addRoot(inst); + while (root != null && root.id == id) { + inst.addRootType(root.type); + root = ri.next(); + } + } + + // Fixup the instance based on its type using the temporary data we + // saved during the first pass over the heap dump. + if (inst instanceof AhatClassInstance) { + ClassInstData data = (ClassInstData)inst.getTemporaryUserData(); + inst.setTemporaryUserData(null); + + // Compute the size of the fields array in advance to avoid + // extra allocations and copies that would come from using an array + // list to collect the field values. + int numFields = 0; + for (AhatClassObj cls = inst.getClassObj(); cls != null; cls = cls.getSuperClassObj()) { + numFields += cls.getInstanceFields().length; + } + + Value[] fields = new Value[numFields]; + int i = 0; + hprof.seek(data.position); + for (AhatClassObj cls = inst.getClassObj(); cls != null; cls = cls.getSuperClassObj()) { + for (Field field : cls.getInstanceFields()) { + fields[i++] = hprof.getValue(field.type, mInstances); + } + } + ((AhatClassInstance)inst).initialize(fields); + } else if (inst instanceof AhatClassObj) { + ClassObjData data = (ClassObjData)inst.getTemporaryUserData(); + inst.setTemporaryUserData(null); + AhatInstance loader = mInstances.get(data.classLoaderId); + for (int i = 0; i < data.staticFields.length; ++i) { + FieldValue field = data.staticFields[i]; + if (field.value instanceof DeferredInstanceValue) { + DeferredInstanceValue deferred = (DeferredInstanceValue)field.value; + data.staticFields[i] = new FieldValue( + field.name, field.type, Value.pack(mInstances.get(deferred.getId()))); + } + } + ((AhatClassObj)inst).initialize(loader, data.staticFields); + } else if (inst instanceof AhatArrayInstance && inst.getTemporaryUserData() != null) { + // TODO: Have specialized object array instance and check for that + // rather than checking for the presence of user data? + ObjArrayData data = (ObjArrayData)inst.getTemporaryUserData(); + inst.setTemporaryUserData(null); + AhatInstance[] array = new AhatInstance[data.length]; + hprof.seek(data.position); + for (int i = 0; i < data.length; i++) { + array[i] = mInstances.get(hprof.getId()); + } + ((AhatArrayInstance)inst).initialize(array); + } + } + } + + hprof = null; + roots = null; + return new AhatSnapshot(superRoot, mInstances, heaps.heaps, rootSite); + } + + private static boolean isEndOfHeapDumpSegment(int subtag) { + return subtag == 0x1C || subtag == 0x2C; + } + + private static class RootData { + public long id; + public RootType type; + + public RootData(long id, RootType type) { + this.id = id; + this.type = type; + } + } + + private static class ClassInstData { + // The byte position in the hprof file where instance field data starts. + public int position; + + public ClassInstData(int position) { + this.position = position; + } + } + + private static class ObjArrayData { + public int length; // Number of array elements. + public int position; // Position in hprof file containing element data. + + public ObjArrayData(int length, int position) { + this.length = length; + this.position = position; + } + } + + private static class ClassObjData { + public long classLoaderId; + public FieldValue[] staticFields; // Contains DeferredInstanceValues. + } + + /** + * Dummy value representing a reference to an instance that has not yet been + * resolved. + * When first initializing class static fields, we don't yet know what kinds + * of objects Object references refer to. We use DeferredInstanceValue as + * a dummy kind of value to store the id of an object. In the fixup pass we + * resolve all the DeferredInstanceValues into their proper InstanceValues. + */ + private static class DeferredInstanceValue extends Value { + private long mId; + + public DeferredInstanceValue(long id) { + mId = id; + } + + public long getId() { + return mId; + } + + @Override + protected Type getType() { + return Type.OBJECT; + } + + @Override + public String toString() { + return String.format("0x%08x", mId); + } + + @Override public boolean equals(Object other) { + if (other instanceof DeferredInstanceValue) { + DeferredInstanceValue value = (DeferredInstanceValue)other; + return mId == value.mId; + } + return false; + } + } + + /** + * A convenient abstraction for lazily building up the list of heaps seen in + * the heap dump. + */ + private static class HeapList { + public List<AhatHeap> heaps = new ArrayList<AhatHeap>(); + private AhatHeap current; + + public AhatHeap getCurrentHeap() { + if (current == null) { + setCurrentHeap("default"); + } + return current; + } + + public void setCurrentHeap(String name) { + for (AhatHeap heap : heaps) { + if (name.equals(heap.getName())) { + current = heap; + return; + } + } + + current = new AhatHeap(name, heaps.size()); + heaps.add(current); + } + } + + /** + * A mapping from id to elements, where certain conditions are + * satisfied. The conditions are: + * - all elements are defined before they are referenced. + * - ids are densely packed in some range [a, b] where a is not + * necessarily 0. + * - there are not more than 2^31 elements defined. + */ + private static class DenseMap<T> { + private String mElementType; + + // mValues behaves like a circular buffer. + // mKeyAt0 is the key corresponding to index 0 of mValues. Values with + // smaller keys will wrap around to the end of the mValues buffer. The + // buffer is expanded when it is no longer big enough to hold all the keys + // from mMinKey to mMaxKey. + private Object[] mValues; + private long mKeyAt0; + private long mMaxKey; + private long mMinKey; + + /** + * Constructs a DenseMap. + * @param elementType Human readable name describing the type of + * elements for error message if the required + * conditions are found not to hold. + */ + public DenseMap(String elementType) { + mElementType = elementType; + } + + public void put(long key, T value) { + if (mValues == null) { + mValues = new Object[8]; + mValues[0] = value; + mKeyAt0 = key; + mMaxKey = key; + mMinKey = key; + return; + } + + long max = Math.max(mMaxKey, key); + long min = Math.min(mMinKey, key); + int count = (int)(max + 1 - min); + if (count > mValues.length) { + Object[] values = new Object[2 * count]; + + // Copy over the values into the newly allocated larger buffer. It is + // convenient to move the value with mMinKey to index 0 when we make + // the copy. + for (int i = 0; i < mValues.length; ++i) { + values[i] = mValues[indexOf(i + mMinKey)]; + } + mValues = values; + mKeyAt0 = mMinKey; + } + mMinKey = min; + mMaxKey = max; + mValues[indexOf(key)] = value; + } + + /** + * Returns the value for the given key. + * @throws HprofFormatException if there is no value with the key in the + * given map. + */ + public T get(long key) throws HprofFormatException { + T value = null; + if (mValues != null && key >= mMinKey && key <= mMaxKey) { + value = (T)mValues[indexOf(key)]; + } + + if (value == null) { + throw new HprofFormatException(String.format( + "%s with id 0x%x referenced before definition", mElementType, key)); + } + return value; + } + + private int indexOf(long key) { + return ((int)(key - mKeyAt0) + mValues.length) % mValues.length; + } + } + + /** + * A mapping from id to elements, where we don't have nice conditions to + * work with. + */ + private static class UnDenseMap<T> { + private String mElementType; + private Map<Long, T> mValues = new HashMap<Long, T>(); + + /** + * Constructs an UnDenseMap. + * @param elementType Human readable name describing the type of + * elements for error message if the required + * conditions are found not to hold. + */ + public UnDenseMap(String elementType) { + mElementType = elementType; + } + + public void put(long key, T value) { + mValues.put(key, value); + } + + /** + * Returns the value for the given key. + * @throws HprofFormatException if there is no value with the key in the + * given map. + */ + public T get(long key) throws HprofFormatException { + T value = mValues.get(key); + if (value == null) { + throw new HprofFormatException(String.format( + "%s with id 0x%x referenced before definition", mElementType, key)); + } + return value; + } + } + + /** + * Wrapper around a ByteBuffer that presents a uniform interface for + * accessing data from an hprof file. + */ + private static class HprofBuffer { + private ByteBuffer mBuffer; + + public HprofBuffer(File path) throws IOException { + FileChannel channel = FileChannel.open(path.toPath(), StandardOpenOption.READ); + mBuffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); + channel.close(); + } + + public HprofBuffer(ByteBuffer buffer) { + mBuffer = buffer; + } + + public boolean hasRemaining() { + return mBuffer.hasRemaining(); + } + + /** + * Return the current absolution position in the file. + */ + public int tell() { + return mBuffer.position(); + } + + /** + * Seek to the given absolution position in the file. + */ + public void seek(int position) { + mBuffer.position(position); + } + + /** + * Skip ahead in the file by the given delta bytes. Delta may be negative + * to skip backwards in the file. + */ + public void skip(int delta) { + seek(tell() + delta); + } + + public int getU1() { + return mBuffer.get() & 0xFF; + } + + public int getU2() { + return mBuffer.getShort() & 0xFFFF; + } + + public int getU4() { + return mBuffer.getInt(); + } + + public long getId() { + return mBuffer.getInt(); + } + + public boolean getBool() { + return mBuffer.get() != 0; + } + + public char getChar() { + return mBuffer.getChar(); + } + + public float getFloat() { + return mBuffer.getFloat(); + } + + public double getDouble() { + return mBuffer.getDouble(); + } + + public byte getByte() { + return mBuffer.get(); + } + + public void getBytes(byte[] bytes) { + mBuffer.get(bytes); + } + + public short getShort() { + return mBuffer.getShort(); + } + + public int getInt() { + return mBuffer.getInt(); + } + + public long getLong() { + return mBuffer.getLong(); + } + + private static Type[] TYPES = new Type[] { + null, null, Type.OBJECT, null, + Type.BOOLEAN, Type.CHAR, Type.FLOAT, Type.DOUBLE, + Type.BYTE, Type.SHORT, Type.INT, Type.LONG + }; + + public Type getType() throws HprofFormatException { + int id = getU1(); + Type type = id < TYPES.length ? TYPES[id] : null; + if (type == null) { + throw new HprofFormatException("Invalid basic type id: " + id); + } + return type; + } + + public Type getPrimitiveType() throws HprofFormatException { + Type type = getType(); + if (type == Type.OBJECT) { + throw new HprofFormatException("Expected primitive type, but found type 'Object'"); + } + return type; + } + + /** + * Get a value from the hprof file, using the given instances map to + * convert instance ids to their corresponding AhatInstance objects. + */ + public Value getValue(Type type, Instances instances) { + switch (type) { + case OBJECT: return Value.pack(instances.get(getId())); + case BOOLEAN: return Value.pack(getBool()); + case CHAR: return Value.pack(getChar()); + case FLOAT: return Value.pack(getFloat()); + case DOUBLE: return Value.pack(getDouble()); + case BYTE: return Value.pack(getByte()); + case SHORT: return Value.pack(getShort()); + case INT: return Value.pack(getInt()); + case LONG: return Value.pack(getLong()); + default: throw new AssertionError("unsupported enum member"); + } + } + + /** + * Get a value from the hprof file. AhatInstance values are returned as + * DefferredInstanceValues rather than their corresponding AhatInstance + * objects. + */ + public Value getDeferredValue(Type type) { + switch (type) { + case OBJECT: return new DeferredInstanceValue(getId()); + case BOOLEAN: return Value.pack(getBool()); + case CHAR: return Value.pack(getChar()); + case FLOAT: return Value.pack(getFloat()); + case DOUBLE: return Value.pack(getDouble()); + case BYTE: return Value.pack(getByte()); + case SHORT: return Value.pack(getShort()); + case INT: return Value.pack(getInt()); + case LONG: return Value.pack(getLong()); + default: throw new AssertionError("unsupported enum member"); + } + } + } +} diff --git a/tools/ahat/src/heapdump/Perflib.java b/tools/ahat/src/heapdump/Perflib.java deleted file mode 100644 index d0264a3b39..0000000000 --- a/tools/ahat/src/heapdump/Perflib.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -package com.android.ahat.heapdump; - -import com.android.tools.perflib.heap.ClassInstance; -import com.android.tools.perflib.heap.ClassObj; -import com.android.tools.perflib.heap.Instance; -import com.android.tools.perflib.heap.Snapshot; -import java.util.HashMap; -import java.util.Map; - -/** - * Collection of utilities that may be suitable to have in perflib instead of - * ahat. - */ -public class Perflib { - /** - * Return a collection of instances in the given snapshot that are tied to - * registered native allocations and their corresponding registered native - * sizes. - */ - public static Map<Instance, Long> getRegisteredNativeAllocations(Snapshot snapshot) { - Map<Instance, Long> allocs = new HashMap<Instance, Long>(); - ClassObj cleanerClass = snapshot.findClass("sun.misc.Cleaner"); - if (cleanerClass != null) { - for (Instance cleanerInst : cleanerClass.getInstancesList()) { - ClassInstance cleaner = (ClassInstance)cleanerInst; - Object referent = getField(cleaner, "referent"); - if (referent instanceof Instance) { - Instance inst = (Instance)referent; - Object thunkValue = getField(cleaner, "thunk"); - if (thunkValue instanceof ClassInstance) { - ClassInstance thunk = (ClassInstance)thunkValue; - ClassObj thunkClass = thunk.getClassObj(); - String cleanerThunkClassName = "libcore.util.NativeAllocationRegistry$CleanerThunk"; - if (thunkClass != null && cleanerThunkClassName.equals(thunkClass.getClassName())) { - for (ClassInstance.FieldValue thunkField : thunk.getValues()) { - if (thunkField.getValue() instanceof ClassInstance) { - ClassInstance registry = (ClassInstance)thunkField.getValue(); - ClassObj registryClass = registry.getClassObj(); - String registryClassName = "libcore.util.NativeAllocationRegistry"; - if (registryClass != null - && registryClassName.equals(registryClass.getClassName())) { - Object sizeValue = getField(registry, "size"); - if (sizeValue instanceof Long) { - long size = (Long)sizeValue; - if (size > 0) { - Long old = allocs.get(inst); - allocs.put(inst, old == null ? size : old + size); - } - } - break; - } - } - } - } - } - } - } - } - return allocs; - } - - /** - * Helper function to read a single field from a perflib class instance. - * Returns null if field not found. Note there is no way to distinguish - * between field not found an a field value of null. - */ - private static Object getField(ClassInstance cls, String name) { - for (ClassInstance.FieldValue field : cls.getValues()) { - if (name.equals(field.getField().getName())) { - return field.getValue(); - } - } - return null; - } -} diff --git a/tools/ahat/src/heapdump/RootType.java b/tools/ahat/src/heapdump/RootType.java new file mode 100644 index 0000000000..7165b83722 --- /dev/null +++ b/tools/ahat/src/heapdump/RootType.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 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. + */ + +package com.android.ahat.heapdump; + +public enum RootType { + JNI_GLOBAL (1 << 0), + JNI_LOCAL (1 << 1), + JAVA_FRAME (1 << 2), + NATIVE_STACK (1 << 3), + STICKY_CLASS (1 << 4), + THREAD_BLOCK (1 << 5), + MONITOR (1 << 6), + THREAD (1 << 7), + INTERNED_STRING (1 << 8), + DEBUGGER (1 << 9), + VM_INTERNAL (1 << 10), + UNKNOWN (1 << 11), + JNI_MONITOR (1 << 12); + + public final int mask; + + RootType(int mask) { + this.mask = mask; + } +} diff --git a/tools/ahat/src/heapdump/Site.java b/tools/ahat/src/heapdump/Site.java index 82931f0056..821493f1be 100644 --- a/tools/ahat/src/heapdump/Site.java +++ b/tools/ahat/src/heapdump/Site.java @@ -16,7 +16,7 @@ package com.android.ahat.heapdump; -import com.android.tools.perflib.heap.StackFrame; +import com.android.ahat.proguard.ProguardMap; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -127,27 +127,27 @@ public class Site implements Diffable<Site> { * inner-most frame. May be null, in which case this site is * returned. */ - Site getSite(StackFrame frames[]) { + Site getSite(ProguardMap.Frame[] frames) { return frames == null ? this : getSite(this, frames); } - private static Site getSite(Site site, StackFrame frames[]) { + private static Site getSite(Site site, ProguardMap.Frame[] frames) { for (int s = frames.length - 1; s >= 0; --s) { - StackFrame frame = frames[s]; + ProguardMap.Frame frame = frames[s]; Site child = null; for (int i = 0; i < site.mChildren.size(); i++) { Site curr = site.mChildren.get(i); - if (curr.mLineNumber == frame.getLineNumber() - && curr.mMethodName.equals(frame.getMethodName()) - && curr.mSignature.equals(frame.getSignature()) - && curr.mFilename.equals(frame.getFilename())) { + if (curr.mLineNumber == frame.line + && curr.mMethodName.equals(frame.method) + && curr.mSignature.equals(frame.signature) + && curr.mFilename.equals(frame.filename)) { child = curr; break; } } if (child == null) { - child = new Site(site, frame.getMethodName(), frame.getSignature(), - frame.getFilename(), frame.getLineNumber()); + child = new Site(site, frame.method, frame.signature, + frame.filename, frame.line); site.mChildren.add(child); } site = child; diff --git a/tools/ahat/src/heapdump/SuperRoot.java b/tools/ahat/src/heapdump/SuperRoot.java index d377113862..a2adbd2808 100644 --- a/tools/ahat/src/heapdump/SuperRoot.java +++ b/tools/ahat/src/heapdump/SuperRoot.java @@ -34,6 +34,11 @@ public class SuperRoot extends AhatInstance implements DominatorsComputation.Nod } @Override + protected long getExtraJavaSize() { + return 0; + } + + @Override public String toString() { return "SUPER_ROOT"; } diff --git a/tools/ahat/src/heapdump/Type.java b/tools/ahat/src/heapdump/Type.java new file mode 100644 index 0000000000..726bc47cf2 --- /dev/null +++ b/tools/ahat/src/heapdump/Type.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2017 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. + */ + +package com.android.ahat.heapdump; + +public enum Type { + OBJECT("Object", 4), + BOOLEAN("boolean", 1), + CHAR("char", 2), + FLOAT("float", 4), + DOUBLE("double", 8), + BYTE("byte", 1), + SHORT("short", 2), + INT("int", 4), + LONG("long", 8); + + public final String name; + public final int size; + + Type(String name, int size) { + this.name = name; + this.size = size; + } + + @Override + public String toString() { + return name; + } +} diff --git a/tools/ahat/src/heapdump/Value.java b/tools/ahat/src/heapdump/Value.java index 7f86c01efb..01fd25057d 100644 --- a/tools/ahat/src/heapdump/Value.java +++ b/tools/ahat/src/heapdump/Value.java @@ -25,37 +25,6 @@ public abstract class Value { return value == null ? null : new InstanceValue(value); } - /** - * Constructs a value from a generic Java Object. - * The Object must either be a boxed Java primitive type or a subclass of - * AhatInstance. The object must not be null. - */ - public static Value pack(Object object) { - if (object == null) { - return null; - } else if (object instanceof AhatInstance) { - return Value.pack((AhatInstance)object); - } else if (object instanceof Boolean) { - return Value.pack(((Boolean)object).booleanValue()); - } else if (object instanceof Character) { - return Value.pack(((Character)object).charValue()); - } else if (object instanceof Float) { - return Value.pack(((Float)object).floatValue()); - } else if (object instanceof Double) { - return Value.pack(((Double)object).doubleValue()); - } else if (object instanceof Byte) { - return Value.pack(((Byte)object).byteValue()); - } else if (object instanceof Short) { - return Value.pack(((Short)object).shortValue()); - } else if (object instanceof Integer) { - return Value.pack(((Integer)object).intValue()); - } else if (object instanceof Long) { - return Value.pack(((Long)object).longValue()); - } - throw new IllegalArgumentException( - "AhatInstance or primitive type required, but got: " + object.toString()); - } - public static Value pack(boolean value) { return new BooleanValue(value); } @@ -89,6 +58,18 @@ public abstract class Value { } /** + * Return the type of the given value. + */ + public static Type getType(Value value) { + return value == null ? Type.OBJECT : value.getType(); + } + + /** + * Return the type of the given value. + */ + protected abstract Type getType(); + + /** * Returns true if the Value is an AhatInstance, as opposed to a Java * primitive value. */ @@ -172,6 +153,11 @@ public abstract class Value { } @Override + protected Type getType() { + return Type.BOOLEAN; + } + + @Override public String toString() { return Boolean.toString(mBool); } @@ -198,6 +184,11 @@ public abstract class Value { } @Override + protected Type getType() { + return Type.BYTE; + } + + @Override public String toString() { return Byte.toString(mByte); } @@ -224,6 +215,11 @@ public abstract class Value { } @Override + protected Type getType() { + return Type.CHAR; + } + + @Override public String toString() { return Character.toString(mChar); } @@ -245,6 +241,11 @@ public abstract class Value { } @Override + protected Type getType() { + return Type.DOUBLE; + } + + @Override public String toString() { return Double.toString(mDouble); } @@ -266,6 +267,11 @@ public abstract class Value { } @Override + protected Type getType() { + return Type.FLOAT; + } + + @Override public String toString() { return Float.toString(mFloat); } @@ -298,6 +304,11 @@ public abstract class Value { } @Override + protected Type getType() { + return Type.OBJECT; + } + + @Override public String toString() { return mInstance.toString(); } @@ -334,6 +345,11 @@ public abstract class Value { } @Override + protected Type getType() { + return Type.INT; + } + + @Override public String toString() { return Integer.toString(mInt); } @@ -365,6 +381,11 @@ public abstract class Value { } @Override + protected Type getType() { + return Type.LONG; + } + + @Override public String toString() { return Long.toString(mLong); } @@ -386,6 +407,11 @@ public abstract class Value { } @Override + protected Type getType() { + return Type.SHORT; + } + + @Override public String toString() { return Short.toString(mShort); } diff --git a/tools/ahat/src/proguard/ProguardMap.java b/tools/ahat/src/proguard/ProguardMap.java new file mode 100644 index 0000000000..50c110aad4 --- /dev/null +++ b/tools/ahat/src/proguard/ProguardMap.java @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2016 Google Inc. + * + * 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. + */ + +package com.android.ahat.proguard; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; + +// Class used to deobfuscate classes, fields, and stack frames. +public class ProguardMap { + + private static final String ARRAY_SYMBOL = "[]"; + + private static class FrameData { + public FrameData(String clearMethodName, int lineDelta) { + this.clearMethodName = clearMethodName; + this.lineDelta = lineDelta; + } + + public final String clearMethodName; + public final int lineDelta; // lineDelta = obfuscatedLine - clearLine + } + + private static class ClassData { + private final String mClearName; + + // Mapping from obfuscated field name to clear field name. + private final Map<String, String> mFields = new HashMap<String, String>(); + + // obfuscatedMethodName + clearSignature -> FrameData + private final Map<String, FrameData> mFrames = new HashMap<String, FrameData>(); + + // Constructs a ClassData object for a class with the given clear name. + public ClassData(String clearName) { + mClearName = clearName; + } + + // Returns the clear name of the class. + public String getClearName() { + return mClearName; + } + + public void addField(String obfuscatedName, String clearName) { + mFields.put(obfuscatedName, clearName); + } + + // Get the clear name for the field in this class with the given + // obfuscated name. Returns the original obfuscated name if a clear + // name for the field could not be determined. + // TODO: Do we need to take into account the type of the field to + // propery determine the clear name? + public String getField(String obfuscatedName) { + String clearField = mFields.get(obfuscatedName); + return clearField == null ? obfuscatedName : clearField; + } + + // TODO: Does this properly interpret the meaning of line numbers? Is + // it possible to have multiple frame entries for the same method + // name and signature that differ only by line ranges? + public void addFrame(String obfuscatedMethodName, String clearMethodName, + String clearSignature, int obfuscatedLine, int clearLine) { + String key = obfuscatedMethodName + clearSignature; + mFrames.put(key, new FrameData(clearMethodName, obfuscatedLine - clearLine)); + } + + public Frame getFrame(String clearClassName, String obfuscatedMethodName, + String clearSignature, String obfuscatedFilename, int obfuscatedLine) { + String key = obfuscatedMethodName + clearSignature; + FrameData frame = mFrames.get(key); + if (frame == null) { + return new Frame(obfuscatedMethodName, clearSignature, + obfuscatedFilename, obfuscatedLine); + } + return new Frame(frame.clearMethodName, clearSignature, + getFileName(clearClassName, frame.clearMethodName), + obfuscatedLine - frame.lineDelta); + } + } + + private Map<String, ClassData> mClassesFromClearName = new HashMap<String, ClassData>(); + private Map<String, ClassData> mClassesFromObfuscatedName = new HashMap<String, ClassData>(); + + public static class Frame { + public Frame(String method, String signature, String filename, int line) { + this.method = method; + this.signature = signature; + this.filename = filename; + this.line = line; + } + + public final String method; + public final String signature; + public final String filename; + public final int line; + } + + private static void parseException(String msg) throws ParseException { + throw new ParseException(msg, 0); + } + + // Read in proguard mapping information from the given file. + public void readFromFile(File mapFile) + throws FileNotFoundException, IOException, ParseException { + readFromReader(new FileReader(mapFile)); + } + + // Read in proguard mapping information from the given Reader. + public void readFromReader(Reader mapReader) throws IOException, ParseException { + BufferedReader reader = new BufferedReader(mapReader); + String line = reader.readLine(); + while (line != null) { + // Class lines are of the form: + // 'clear.class.name -> obfuscated_class_name:' + int sep = line.indexOf(" -> "); + if (sep == -1 || sep + 5 >= line.length()) { + parseException("Error parsing class line: '" + line + "'"); + } + String clearClassName = line.substring(0, sep); + String obfuscatedClassName = line.substring(sep + 4, line.length() - 1); + + ClassData classData = new ClassData(clearClassName); + mClassesFromClearName.put(clearClassName, classData); + mClassesFromObfuscatedName.put(obfuscatedClassName, classData); + + // After the class line comes zero or more field/method lines of the form: + // ' type clearName -> obfuscatedName' + line = reader.readLine(); + while (line != null && line.startsWith(" ")) { + String trimmed = line.trim(); + int ws = trimmed.indexOf(' '); + sep = trimmed.indexOf(" -> "); + if (ws == -1 || sep == -1) { + parseException("Error parse field/method line: '" + line + "'"); + } + + String type = trimmed.substring(0, ws); + String clearName = trimmed.substring(ws + 1, sep); + String obfuscatedName = trimmed.substring(sep + 4, trimmed.length()); + + // If the clearName contains '(', then this is for a method instead of a + // field. + if (clearName.indexOf('(') == -1) { + classData.addField(obfuscatedName, clearName); + } else { + // For methods, the type is of the form: [#:[#:]]<returnType> + int obfuscatedLine = 0; + int colon = type.indexOf(':'); + if (colon != -1) { + obfuscatedLine = Integer.parseInt(type.substring(0, colon)); + type = type.substring(colon + 1); + } + colon = type.indexOf(':'); + if (colon != -1) { + type = type.substring(colon + 1); + } + + // For methods, the clearName is of the form: <clearName><sig>[:#[:#]] + int op = clearName.indexOf('('); + int cp = clearName.indexOf(')'); + if (op == -1 || cp == -1) { + parseException("Error parse method line: '" + line + "'"); + } + + String sig = clearName.substring(op, cp + 1); + + int clearLine = obfuscatedLine; + colon = clearName.lastIndexOf(':'); + if (colon != -1) { + clearLine = Integer.parseInt(clearName.substring(colon + 1)); + clearName = clearName.substring(0, colon); + } + + colon = clearName.lastIndexOf(':'); + if (colon != -1) { + clearLine = Integer.parseInt(clearName.substring(colon + 1)); + clearName = clearName.substring(0, colon); + } + + clearName = clearName.substring(0, op); + + String clearSig = fromProguardSignature(sig + type); + classData.addFrame(obfuscatedName, clearName, clearSig, + obfuscatedLine, clearLine); + } + + line = reader.readLine(); + } + } + reader.close(); + } + + // Returns the deobfuscated version of the given class name. If no + // deobfuscated version is known, the original string is returned. + public String getClassName(String obfuscatedClassName) { + // Class names for arrays may have trailing [] that need to be + // stripped before doing the lookup. + String baseName = obfuscatedClassName; + String arraySuffix = ""; + while (baseName.endsWith(ARRAY_SYMBOL)) { + arraySuffix += ARRAY_SYMBOL; + baseName = baseName.substring(0, baseName.length() - ARRAY_SYMBOL.length()); + } + + ClassData classData = mClassesFromObfuscatedName.get(baseName); + String clearBaseName = classData == null ? baseName : classData.getClearName(); + return clearBaseName + arraySuffix; + } + + // Returns the deobfuscated version of the given field name for the given + // (clear) class name. If no deobfuscated version is known, the original + // string is returned. + public String getFieldName(String clearClass, String obfuscatedField) { + ClassData classData = mClassesFromClearName.get(clearClass); + if (classData == null) { + return obfuscatedField; + } + return classData.getField(obfuscatedField); + } + + // Returns the deobfuscated frame for the given obfuscated frame and (clear) + // class name. As much of the frame is deobfuscated as can be. + public Frame getFrame(String clearClassName, String obfuscatedMethodName, + String obfuscatedSignature, String obfuscatedFilename, int obfuscatedLine) { + String clearSignature = getSignature(obfuscatedSignature); + ClassData classData = mClassesFromClearName.get(clearClassName); + if (classData == null) { + return new Frame(obfuscatedMethodName, clearSignature, + obfuscatedFilename, obfuscatedLine); + } + return classData.getFrame(clearClassName, obfuscatedMethodName, clearSignature, + obfuscatedFilename, obfuscatedLine); + } + + // Converts a proguard-formatted method signature into a Java formatted + // method signature. + private static String fromProguardSignature(String sig) throws ParseException { + if (sig.startsWith("(")) { + int end = sig.indexOf(')'); + if (end == -1) { + parseException("Error parsing signature: " + sig); + } + + StringBuilder converted = new StringBuilder(); + converted.append('('); + if (end > 1) { + for (String arg : sig.substring(1, end).split(",")) { + converted.append(fromProguardSignature(arg)); + } + } + converted.append(')'); + converted.append(fromProguardSignature(sig.substring(end + 1))); + return converted.toString(); + } else if (sig.endsWith(ARRAY_SYMBOL)) { + return "[" + fromProguardSignature(sig.substring(0, sig.length() - 2)); + } else if (sig.equals("boolean")) { + return "Z"; + } else if (sig.equals("byte")) { + return "B"; + } else if (sig.equals("char")) { + return "C"; + } else if (sig.equals("short")) { + return "S"; + } else if (sig.equals("int")) { + return "I"; + } else if (sig.equals("long")) { + return "J"; + } else if (sig.equals("float")) { + return "F"; + } else if (sig.equals("double")) { + return "D"; + } else if (sig.equals("void")) { + return "V"; + } else { + return "L" + sig.replace('.', '/') + ";"; + } + } + + // Return a clear signature for the given obfuscated signature. + private String getSignature(String obfuscatedSig) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < obfuscatedSig.length(); i++) { + if (obfuscatedSig.charAt(i) == 'L') { + int e = obfuscatedSig.indexOf(';', i); + builder.append('L'); + String cls = obfuscatedSig.substring(i + 1, e).replace('/', '.'); + builder.append(getClassName(cls).replace('.', '/')); + builder.append(';'); + i = e; + } else { + builder.append(obfuscatedSig.charAt(i)); + } + } + return builder.toString(); + } + + // Return a file name for the given clear class name and method. + private static String getFileName(String clearClass, String method) { + int dot = method.lastIndexOf('.'); + if (dot != -1) { + clearClass = method.substring(0, dot); + } + + String filename = clearClass; + dot = filename.lastIndexOf('.'); + if (dot != -1) { + filename = filename.substring(dot + 1); + } + + int dollar = filename.indexOf('$'); + if (dollar != -1) { + filename = filename.substring(0, dollar); + } + return filename + ".java"; + } +} diff --git a/tools/ahat/test-dump/L.hprof b/tools/ahat/test-dump/L.hprof Binary files differnew file mode 100644 index 0000000000..cf82557d6d --- /dev/null +++ b/tools/ahat/test-dump/L.hprof diff --git a/tools/ahat/test-dump/O.hprof b/tools/ahat/test-dump/O.hprof Binary files differnew file mode 100644 index 0000000000..d474c6c6b4 --- /dev/null +++ b/tools/ahat/test-dump/O.hprof diff --git a/tools/ahat/test-dump/README.txt b/tools/ahat/test-dump/README.txt new file mode 100644 index 0000000000..344271c2f4 --- /dev/null +++ b/tools/ahat/test-dump/README.txt @@ -0,0 +1,5 @@ + +Main.java - A program used to generate a heap dump used for tests. +L.hprof - A version of the test dump generated on Android L. +O.hprof - A version of the test dump generated on Android O. +RI.hprof - A version of the test dump generated on the reference implementation. diff --git a/tools/ahat/test-dump/RI.hprof b/tools/ahat/test-dump/RI.hprof Binary files differnew file mode 100644 index 0000000000..9482542a7f --- /dev/null +++ b/tools/ahat/test-dump/RI.hprof diff --git a/tools/ahat/test/DiffFieldsTest.java b/tools/ahat/test/DiffFieldsTest.java index 7dc519d60b..19399757a6 100644 --- a/tools/ahat/test/DiffFieldsTest.java +++ b/tools/ahat/test/DiffFieldsTest.java @@ -19,6 +19,7 @@ package com.android.ahat; import com.android.ahat.heapdump.DiffFields; import com.android.ahat.heapdump.DiffedFieldValue; import com.android.ahat.heapdump.FieldValue; +import com.android.ahat.heapdump.Type; import com.android.ahat.heapdump.Value; import java.util.ArrayList; import java.util.List; @@ -28,14 +29,25 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; public class DiffFieldsTest { + // Give more convenient abstract names for different types. + private static final Type t0 = Type.OBJECT; + private static final Type t1 = Type.BOOLEAN; + private static final Type t2 = Type.CHAR; + private static final Type t3 = Type.FLOAT; + private static final Type t4 = Type.DOUBLE; + private static final Type t5 = Type.BYTE; + private static final Type t6 = Type.SHORT; + private static final Type t7 = Type.INT; + private static final Type t8 = Type.LONG; + @Test public void normalMatchedDiffedFieldValues() { - FieldValue normal1 = new FieldValue("name", "type", Value.pack(1)); - FieldValue normal2 = new FieldValue("name", "type", Value.pack(2)); + FieldValue normal1 = new FieldValue("name", t0, Value.pack(1)); + FieldValue normal2 = new FieldValue("name", t0, Value.pack(2)); DiffedFieldValue x = DiffedFieldValue.matched(normal1, normal2); assertEquals("name", x.name); - assertEquals("type", x.type); + assertEquals(t0, x.type); assertEquals(Value.pack(1), x.current); assertEquals(Value.pack(2), x.baseline); assertEquals(DiffedFieldValue.Status.MATCHED, x.status); @@ -43,19 +55,19 @@ public class DiffFieldsTest { @Test public void nulledMatchedDiffedFieldValues() { - FieldValue normal = new FieldValue("name", "type", Value.pack(1)); - FieldValue nulled = new FieldValue("name", "type", null); + FieldValue normal = new FieldValue("name", t0, Value.pack(1)); + FieldValue nulled = new FieldValue("name", t0, null); DiffedFieldValue x = DiffedFieldValue.matched(normal, nulled); assertEquals("name", x.name); - assertEquals("type", x.type); + assertEquals(t0, x.type); assertEquals(Value.pack(1), x.current); assertNull(x.baseline); assertEquals(DiffedFieldValue.Status.MATCHED, x.status); DiffedFieldValue y = DiffedFieldValue.matched(nulled, normal); assertEquals("name", y.name); - assertEquals("type", y.type); + assertEquals(t0, y.type); assertNull(y.current); assertEquals(Value.pack(1), y.baseline); assertEquals(DiffedFieldValue.Status.MATCHED, y.status); @@ -63,44 +75,44 @@ public class DiffFieldsTest { @Test public void normalAddedDiffedFieldValues() { - FieldValue normal = new FieldValue("name", "type", Value.pack(1)); + FieldValue normal = new FieldValue("name", t0, Value.pack(1)); DiffedFieldValue x = DiffedFieldValue.added(normal); assertEquals("name", x.name); - assertEquals("type", x.type); + assertEquals(t0, x.type); assertEquals(Value.pack(1), x.current); assertEquals(DiffedFieldValue.Status.ADDED, x.status); } @Test public void nulledAddedDiffedFieldValues() { - FieldValue nulled = new FieldValue("name", "type", null); + FieldValue nulled = new FieldValue("name", t0, null); DiffedFieldValue x = DiffedFieldValue.added(nulled); assertEquals("name", x.name); - assertEquals("type", x.type); + assertEquals(t0, x.type); assertNull(x.current); assertEquals(DiffedFieldValue.Status.ADDED, x.status); } @Test public void normalDeletedDiffedFieldValues() { - FieldValue normal = new FieldValue("name", "type", Value.pack(1)); + FieldValue normal = new FieldValue("name", t0, Value.pack(1)); DiffedFieldValue x = DiffedFieldValue.deleted(normal); assertEquals("name", x.name); - assertEquals("type", x.type); + assertEquals(t0, x.type); assertEquals(Value.pack(1), x.baseline); assertEquals(DiffedFieldValue.Status.DELETED, x.status); } @Test public void nulledDeletedDiffedFieldValues() { - FieldValue nulled = new FieldValue("name", "type", null); + FieldValue nulled = new FieldValue("name", t0, null); DiffedFieldValue x = DiffedFieldValue.deleted(nulled); assertEquals("name", x.name); - assertEquals("type", x.type); + assertEquals(t0, x.type); assertNull(x.baseline); assertEquals(DiffedFieldValue.Status.DELETED, x.status); } @@ -108,21 +120,21 @@ public class DiffFieldsTest { @Test public void basicDiff() { List<FieldValue> a = new ArrayList<FieldValue>(); - a.add(new FieldValue("n0", "t0", null)); - a.add(new FieldValue("n2", "t2", null)); - a.add(new FieldValue("n3", "t3", null)); - a.add(new FieldValue("n4", "t4", null)); - a.add(new FieldValue("n5", "t5", null)); - a.add(new FieldValue("n6", "t6", null)); + a.add(new FieldValue("n0", t0, null)); + a.add(new FieldValue("n2", t2, null)); + a.add(new FieldValue("n3", t3, null)); + a.add(new FieldValue("n4", t4, null)); + a.add(new FieldValue("n5", t5, null)); + a.add(new FieldValue("n6", t6, null)); List<FieldValue> b = new ArrayList<FieldValue>(); - b.add(new FieldValue("n0", "t0", null)); - b.add(new FieldValue("n1", "t1", null)); - b.add(new FieldValue("n2", "t2", null)); - b.add(new FieldValue("n3", "t3", null)); - b.add(new FieldValue("n5", "t5", null)); - b.add(new FieldValue("n6", "t6", null)); - b.add(new FieldValue("n7", "t7", null)); + b.add(new FieldValue("n0", t0, null)); + b.add(new FieldValue("n1", t1, null)); + b.add(new FieldValue("n2", t2, null)); + b.add(new FieldValue("n3", t3, null)); + b.add(new FieldValue("n5", t5, null)); + b.add(new FieldValue("n6", t6, null)); + b.add(new FieldValue("n7", t7, null)); // Note: The expected result makes assumptions about the implementation of // field diff to match the order of the returned fields. If the @@ -145,22 +157,22 @@ public class DiffFieldsTest { @Test public void reorderedDiff() { List<FieldValue> a = new ArrayList<FieldValue>(); - a.add(new FieldValue("n0", "t0", null)); - a.add(new FieldValue("n1", "t1", null)); - a.add(new FieldValue("n2", "t2", null)); - a.add(new FieldValue("n3", "t3", null)); - a.add(new FieldValue("n4", "t4", null)); - a.add(new FieldValue("n5", "t5", null)); - a.add(new FieldValue("n6", "t6", null)); + a.add(new FieldValue("n0", t0, null)); + a.add(new FieldValue("n1", t1, null)); + a.add(new FieldValue("n2", t2, null)); + a.add(new FieldValue("n3", t3, null)); + a.add(new FieldValue("n4", t4, null)); + a.add(new FieldValue("n5", t5, null)); + a.add(new FieldValue("n6", t6, null)); List<FieldValue> b = new ArrayList<FieldValue>(); - b.add(new FieldValue("n4", "t4", null)); - b.add(new FieldValue("n1", "t1", null)); - b.add(new FieldValue("n3", "t3", null)); - b.add(new FieldValue("n0", "t0", null)); - b.add(new FieldValue("n5", "t5", null)); - b.add(new FieldValue("n2", "t2", null)); - b.add(new FieldValue("n6", "t6", null)); + b.add(new FieldValue("n4", t4, null)); + b.add(new FieldValue("n1", t1, null)); + b.add(new FieldValue("n3", t3, null)); + b.add(new FieldValue("n0", t0, null)); + b.add(new FieldValue("n5", t5, null)); + b.add(new FieldValue("n2", t2, null)); + b.add(new FieldValue("n6", t6, null)); // Note: The expected result makes assumptions about the implementation of // field diff to match the order of the returned fields. If the diff --git a/tools/ahat/test/DiffTest.java b/tools/ahat/test/DiffTest.java index d0349fd178..585f29ae61 100644 --- a/tools/ahat/test/DiffTest.java +++ b/tools/ahat/test/DiffTest.java @@ -18,26 +18,7 @@ package com.android.ahat; import com.android.ahat.heapdump.AhatHeap; import com.android.ahat.heapdump.AhatInstance; -import com.android.ahat.heapdump.AhatSnapshot; -import com.android.ahat.heapdump.Diff; -import com.android.tools.perflib.heap.hprof.HprofClassDump; -import com.android.tools.perflib.heap.hprof.HprofConstant; -import com.android.tools.perflib.heap.hprof.HprofDumpRecord; -import com.android.tools.perflib.heap.hprof.HprofHeapDump; -import com.android.tools.perflib.heap.hprof.HprofInstanceDump; -import com.android.tools.perflib.heap.hprof.HprofInstanceField; -import com.android.tools.perflib.heap.hprof.HprofLoadClass; -import com.android.tools.perflib.heap.hprof.HprofPrimitiveArrayDump; -import com.android.tools.perflib.heap.hprof.HprofRecord; -import com.android.tools.perflib.heap.hprof.HprofRootDebugger; -import com.android.tools.perflib.heap.hprof.HprofStaticField; -import com.android.tools.perflib.heap.hprof.HprofStringBuilder; -import com.android.tools.perflib.heap.hprof.HprofType; -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -93,39 +74,9 @@ public class DiffTest { } @Test - public void nullClassObj() throws IOException { - // Set up a heap dump that has a null classObj. - // The heap dump is derived from the InstanceTest.asStringEmbedded test. - HprofStringBuilder strings = new HprofStringBuilder(0); - List<HprofRecord> records = new ArrayList<HprofRecord>(); - List<HprofDumpRecord> dump = new ArrayList<HprofDumpRecord>(); - - final int stringClassObjectId = 1; - records.add(new HprofLoadClass(0, 0, stringClassObjectId, 0, strings.get("java.lang.String"))); - dump.add(new HprofClassDump(stringClassObjectId, 0, 0, 0, 0, 0, 0, 0, 0, - new HprofConstant[0], new HprofStaticField[0], - new HprofInstanceField[]{ - new HprofInstanceField(strings.get("count"), HprofType.TYPE_INT), - new HprofInstanceField(strings.get("hashCode"), HprofType.TYPE_INT), - new HprofInstanceField(strings.get("offset"), HprofType.TYPE_INT), - new HprofInstanceField(strings.get("value"), HprofType.TYPE_OBJECT)})); - - dump.add(new HprofPrimitiveArrayDump(0x41, 0, HprofType.TYPE_CHAR, - new long[]{'n', 'o', 't', ' ', 'h', 'e', 'l', 'l', 'o', 'o', 'p'})); - - ByteArrayDataOutput values = ByteStreams.newDataOutput(); - values.writeInt(5); // count - values.writeInt(0); // hashCode - values.writeInt(4); // offset - values.writeInt(0x41); // value - dump.add(new HprofInstanceDump(0x42, 0, stringClassObjectId, values.toByteArray())); - dump.add(new HprofRootDebugger(stringClassObjectId)); - dump.add(new HprofRootDebugger(0x42)); - - records.add(new HprofHeapDump(0, dump.toArray(new HprofDumpRecord[0]))); - AhatSnapshot snapshot = SnapshotBuilder.makeSnapshot(strings, records); - - // Diffing should not crash. - Diff.snapshots(snapshot, snapshot); + public void diffClassRemoved() throws IOException { + TestDump dump = TestDump.getTestDump("O.hprof", "L.hprof", null); + AhatHandler handler = new ObjectsHandler(dump.getAhatSnapshot()); + TestHandler.testNoCrash(handler, "http://localhost:7100/objects?class=java.lang.Class"); } } diff --git a/tools/ahat/test/HtmlEscaperTest.java b/tools/ahat/test/HtmlEscaperTest.java new file mode 100644 index 0000000000..a36db356f5 --- /dev/null +++ b/tools/ahat/test/HtmlEscaperTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2017 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. + */ + +package com.android.ahat; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class HtmlEscaperTest { + @Test + public void tests() { + assertEquals("nothing to escape", HtmlEscaper.escape("nothing to escape")); + assertEquals("a<b> & "c'd"e", HtmlEscaper.escape("a<b> & \"c\'d\"e")); + assertEquals("adjacent <<>> x", HtmlEscaper.escape("adjacent <<>> x")); + assertEquals("< initial", HtmlEscaper.escape("< initial")); + assertEquals("ending >", HtmlEscaper.escape("ending >")); + } +} diff --git a/tools/ahat/test/InstanceTest.java b/tools/ahat/test/InstanceTest.java index 63055db93d..49a21e2d70 100644 --- a/tools/ahat/test/InstanceTest.java +++ b/tools/ahat/test/InstanceTest.java @@ -23,23 +23,7 @@ import com.android.ahat.heapdump.AhatSnapshot; import com.android.ahat.heapdump.PathElement; import com.android.ahat.heapdump.Size; import com.android.ahat.heapdump.Value; -import com.android.tools.perflib.heap.hprof.HprofClassDump; -import com.android.tools.perflib.heap.hprof.HprofConstant; -import com.android.tools.perflib.heap.hprof.HprofDumpRecord; -import com.android.tools.perflib.heap.hprof.HprofHeapDump; -import com.android.tools.perflib.heap.hprof.HprofInstanceDump; -import com.android.tools.perflib.heap.hprof.HprofInstanceField; -import com.android.tools.perflib.heap.hprof.HprofLoadClass; -import com.android.tools.perflib.heap.hprof.HprofPrimitiveArrayDump; -import com.android.tools.perflib.heap.hprof.HprofRecord; -import com.android.tools.perflib.heap.hprof.HprofRootDebugger; -import com.android.tools.perflib.heap.hprof.HprofStaticField; -import com.android.tools.perflib.heap.hprof.HprofStringBuilder; -import com.android.tools.perflib.heap.hprof.HprofType; -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; import java.io.IOException; -import java.util.ArrayList; import java.util.List; import org.junit.Test; @@ -395,44 +379,63 @@ public class InstanceTest { @Test public void asStringEmbedded() throws IOException { - // Set up a heap dump with an instance of java.lang.String of - // "hello" with instance id 0x42 that is backed by a char array that is - // bigger. This is how ART used to represent strings, and we should still - // support it in case the heap dump is from a previous platform version. - HprofStringBuilder strings = new HprofStringBuilder(0); - List<HprofRecord> records = new ArrayList<HprofRecord>(); - List<HprofDumpRecord> dump = new ArrayList<HprofDumpRecord>(); - - final int stringClassObjectId = 1; - records.add(new HprofLoadClass(0, 0, stringClassObjectId, 0, strings.get("java.lang.String"))); - dump.add(new HprofClassDump(stringClassObjectId, 0, 0, 0, 0, 0, 0, 0, 0, - new HprofConstant[0], new HprofStaticField[0], - new HprofInstanceField[]{ - new HprofInstanceField(strings.get("count"), HprofType.TYPE_INT), - new HprofInstanceField(strings.get("hashCode"), HprofType.TYPE_INT), - new HprofInstanceField(strings.get("offset"), HprofType.TYPE_INT), - new HprofInstanceField(strings.get("value"), HprofType.TYPE_OBJECT)})); - - dump.add(new HprofPrimitiveArrayDump(0x41, 0, HprofType.TYPE_CHAR, - new long[]{'n', 'o', 't', ' ', 'h', 'e', 'l', 'l', 'o', 'o', 'p'})); - - ByteArrayDataOutput values = ByteStreams.newDataOutput(); - values.writeInt(5); // count - values.writeInt(0); // hashCode - values.writeInt(4); // offset - values.writeInt(0x41); // value - dump.add(new HprofInstanceDump(0x42, 0, stringClassObjectId, values.toByteArray())); - dump.add(new HprofRootDebugger(stringClassObjectId)); - dump.add(new HprofRootDebugger(0x42)); - - records.add(new HprofHeapDump(0, dump.toArray(new HprofDumpRecord[0]))); - AhatSnapshot snapshot = SnapshotBuilder.makeSnapshot(strings, records); - AhatInstance chars = snapshot.findInstance(0x41); - assertNotNull(chars); - assertEquals("not helloop", chars.asString()); - - AhatInstance stringInstance = snapshot.findInstance(0x42); - assertNotNull(stringInstance); - assertEquals("hello", stringInstance.asString()); + // On Android L, image strings were backed by a single big char array. + // Verify we show just the relative part of the string, not the entire + // char array. + TestDump dump = TestDump.getTestDump("L.hprof", null, null); + AhatSnapshot snapshot = dump.getAhatSnapshot(); + + // java.lang.String@0x6fe17050 is an image string "char" backed by a + // shared char array. + AhatInstance str = snapshot.findInstance(0x6fe17050); + assertEquals("char", str.asString()); + } + + @Test + public void nonDefaultHeapRoot() throws IOException { + TestDump dump = TestDump.getTestDump("O.hprof", null, null); + AhatSnapshot snapshot = dump.getAhatSnapshot(); + + // java.util.HashMap@6004fdb8 is marked as a VM INTERNAL root. + // Previously we had a bug where roots not on the default heap were not + // properly treated as roots (b/65356532). + AhatInstance map = snapshot.findInstance(0x6004fdb8); + assertEquals("java.util.HashMap", map.getClassName()); + assertTrue(map.isRoot()); + } + + @Test + public void threadRoot() throws IOException { + TestDump dump = TestDump.getTestDump("O.hprof", null, null); + AhatSnapshot snapshot = dump.getAhatSnapshot(); + + // java.lang.Thread@12c03470 is marked as a thread root. + // Previously we had a bug where thread roots were not properly treated as + // roots (b/65356532). + AhatInstance thread = snapshot.findInstance(0x12c03470); + assertEquals("java.lang.Thread", thread.getClassName()); + assertTrue(thread.isRoot()); + } + + @Test + public void classOfClass() throws IOException { + TestDump dump = TestDump.getTestDump(); + AhatInstance obj = dump.getDumpedAhatInstance("anObject"); + AhatClassObj cls = obj.getClassObj(); + AhatClassObj clscls = cls.getClassObj(); + assertNotNull(clscls); + assertEquals("java.lang.Class", clscls.getName()); + } + + @Test + public void nullValueString() throws IOException { + TestDump dump = TestDump.getTestDump("RI.hprof", null, null); + AhatSnapshot snapshot = dump.getAhatSnapshot(); + + // java.lang.String@500001a8 has a null 'value' field, which should not + // cause ahat to crash. + AhatInstance str = snapshot.findInstance(0x500001a8); + assertEquals("java.lang.String", str.getClassName()); + assertNull(str.asString()); } } diff --git a/tools/ahat/test/ProguardMapTest.java b/tools/ahat/test/ProguardMapTest.java new file mode 100644 index 0000000000..ad40f45665 --- /dev/null +++ b/tools/ahat/test/ProguardMapTest.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.android.ahat; + +import com.android.ahat.proguard.ProguardMap; +import java.io.IOException; +import java.io.StringReader; +import java.text.ParseException; +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +public class ProguardMapTest { + private static final String TEST_MAP = + "class.that.is.Empty -> a:\n" + + "class.that.is.Empty$subclass -> b:\n" + + "class.with.only.Fields -> c:\n" + + " int prim_type_field -> a\n" + + " int[] prim_array_type_field -> b\n" + + " class.that.is.Empty class_type_field -> c\n" + + " class.that.is.Empty[] array_type_field -> d\n" + + " int longObfuscatedNameField -> abc\n" + + "class.with.Methods -> d:\n" + + " int some_field -> a\n" + + " 12:23:void <clinit>() -> <clinit>\n" + + " 42:43:void boringMethod() -> m\n" + + " 45:48:void methodWithPrimArgs(int,float) -> m\n" + + " 49:50:void methodWithPrimArrArgs(int[],float) -> m\n" + + " 52:55:void methodWithClearObjArg(class.not.in.Map) -> m\n" + + " 57:58:void methodWithClearObjArrArg(class.not.in.Map[]) -> m\n" + + " 59:61:void methodWithObfObjArg(class.with.only.Fields) -> m\n" + + " 64:66:class.with.only.Fields methodWithObfRes() -> n\n" + + " 80:80:void lineObfuscatedMethod():8:8 -> o\n" + + " 90:90:void lineObfuscatedMethod2():9 -> p\n" + + " 120:121:void method.from.a.Superclass.supermethod() -> q\n" + ; + + @Test + public void proguardMap() throws IOException, ParseException { + ProguardMap map = new ProguardMap(); + + // An empty proguard map should not deobfuscate anything. + assertEquals("foo.bar.Sludge", map.getClassName("foo.bar.Sludge")); + assertEquals("fooBarSludge", map.getClassName("fooBarSludge")); + assertEquals("myfield", map.getFieldName("foo.bar.Sludge", "myfield")); + assertEquals("myfield", map.getFieldName("fooBarSludge", "myfield")); + ProguardMap.Frame frame = map.getFrame( + "foo.bar.Sludge", "mymethod", "(Lfoo/bar/Sludge;)V", "SourceFile.java", 123); + assertEquals("mymethod", frame.method); + assertEquals("(Lfoo/bar/Sludge;)V", frame.signature); + assertEquals("SourceFile.java", frame.filename); + assertEquals(123, frame.line); + + // Read in the proguard map. + map.readFromReader(new StringReader(TEST_MAP)); + + // It should still not deobfuscate things that aren't in the map + assertEquals("foo.bar.Sludge", map.getClassName("foo.bar.Sludge")); + assertEquals("fooBarSludge", map.getClassName("fooBarSludge")); + assertEquals("myfield", map.getFieldName("foo.bar.Sludge", "myfield")); + assertEquals("myfield", map.getFieldName("fooBarSludge", "myfield")); + frame = map.getFrame("foo.bar.Sludge", "mymethod", "(Lfoo/bar/Sludge;)V", + "SourceFile.java", 123); + assertEquals("mymethod", frame.method); + assertEquals("(Lfoo/bar/Sludge;)V", frame.signature); + assertEquals("SourceFile.java", frame.filename); + assertEquals(123, frame.line); + + // Test deobfuscation of class names + assertEquals("class.that.is.Empty", map.getClassName("a")); + assertEquals("class.that.is.Empty$subclass", map.getClassName("b")); + assertEquals("class.with.only.Fields", map.getClassName("c")); + assertEquals("class.with.Methods", map.getClassName("d")); + + // Test deobfuscation of array classes. + assertEquals("class.with.Methods[]", map.getClassName("d[]")); + assertEquals("class.with.Methods[][]", map.getClassName("d[][]")); + + // Test deobfuscation of methods + assertEquals("prim_type_field", map.getFieldName("class.with.only.Fields", "a")); + assertEquals("prim_array_type_field", map.getFieldName("class.with.only.Fields", "b")); + assertEquals("class_type_field", map.getFieldName("class.with.only.Fields", "c")); + assertEquals("array_type_field", map.getFieldName("class.with.only.Fields", "d")); + assertEquals("longObfuscatedNameField", map.getFieldName("class.with.only.Fields", "abc")); + assertEquals("some_field", map.getFieldName("class.with.Methods", "a")); + + // Test deobfuscation of frames + frame = map.getFrame("class.with.Methods", "<clinit>", "()V", "SourceFile.java", 13); + assertEquals("<clinit>", frame.method); + assertEquals("()V", frame.signature); + assertEquals("Methods.java", frame.filename); + assertEquals(13, frame.line); + + frame = map.getFrame("class.with.Methods", "m", "()V", "SourceFile.java", 42); + assertEquals("boringMethod", frame.method); + assertEquals("()V", frame.signature); + assertEquals("Methods.java", frame.filename); + assertEquals(42, frame.line); + + frame = map.getFrame("class.with.Methods", "m", "(IF)V", "SourceFile.java", 45); + assertEquals("methodWithPrimArgs", frame.method); + assertEquals("(IF)V", frame.signature); + assertEquals("Methods.java", frame.filename); + assertEquals(45, frame.line); + + frame = map.getFrame("class.with.Methods", "m", "([IF)V", "SourceFile.java", 49); + assertEquals("methodWithPrimArrArgs", frame.method); + assertEquals("([IF)V", frame.signature); + assertEquals("Methods.java", frame.filename); + assertEquals(49, frame.line); + + frame = map.getFrame("class.with.Methods", "m", "(Lclass/not/in/Map;)V", + "SourceFile.java", 52); + assertEquals("methodWithClearObjArg", frame.method); + assertEquals("(Lclass/not/in/Map;)V", frame.signature); + assertEquals("Methods.java", frame.filename); + assertEquals(52, frame.line); + + frame = map.getFrame("class.with.Methods", "m", "([Lclass/not/in/Map;)V", + "SourceFile.java", 57); + assertEquals("methodWithClearObjArrArg", frame.method); + assertEquals("([Lclass/not/in/Map;)V", frame.signature); + assertEquals("Methods.java", frame.filename); + assertEquals(57, frame.line); + + frame = map.getFrame("class.with.Methods", "m", "(Lc;)V", "SourceFile.java", 59); + assertEquals("methodWithObfObjArg", frame.method); + assertEquals("(Lclass/with/only/Fields;)V", frame.signature); + assertEquals("Methods.java", frame.filename); + assertEquals(59, frame.line); + + frame = map.getFrame("class.with.Methods", "n", "()Lc;", "SourceFile.java", 64); + assertEquals("methodWithObfRes", frame.method); + assertEquals("()Lclass/with/only/Fields;", frame.signature); + assertEquals("Methods.java", frame.filename); + assertEquals(64, frame.line); + + frame = map.getFrame("class.with.Methods", "o", "()V", "SourceFile.java", 80); + assertEquals("lineObfuscatedMethod", frame.method); + assertEquals("()V", frame.signature); + assertEquals("Methods.java", frame.filename); + assertEquals(8, frame.line); + + frame = map.getFrame("class.with.Methods", "p", "()V", "SourceFile.java", 94); + assertEquals("lineObfuscatedMethod2", frame.method); + assertEquals("()V", frame.signature); + assertEquals("Methods.java", frame.filename); + assertEquals(13, frame.line); + + frame = map.getFrame("class.with.Methods", "q", "()V", "SourceFile.java", 120); + // TODO: Should this be "supermethod", instead of + // "method.from.a.Superclass.supermethod"? + assertEquals("method.from.a.Superclass.supermethod", frame.method); + assertEquals("()V", frame.signature); + assertEquals("Superclass.java", frame.filename); + assertEquals(120, frame.line); + } +} diff --git a/tools/ahat/test/SnapshotBuilder.java b/tools/ahat/test/SnapshotBuilder.java deleted file mode 100644 index 0eea6357fd..0000000000 --- a/tools/ahat/test/SnapshotBuilder.java +++ /dev/null @@ -1,53 +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. - */ - -package com.android.ahat; - -import com.android.ahat.heapdump.AhatSnapshot; -import com.android.tools.perflib.heap.ProguardMap; -import com.android.tools.perflib.heap.hprof.Hprof; -import com.android.tools.perflib.heap.hprof.HprofRecord; -import com.android.tools.perflib.heap.hprof.HprofStringBuilder; -import com.android.tools.perflib.heap.io.InMemoryBuffer; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * Class with utilities to help constructing snapshots for tests. - */ -public class SnapshotBuilder { - - // Helper function to make a snapshot with id size 4 given an - // HprofStringBuilder and list of HprofRecords - public static AhatSnapshot makeSnapshot(HprofStringBuilder strings, List<HprofRecord> records) - throws IOException { - // TODO: When perflib can handle the case where strings are referred to - // before they are defined, just add the string records to the records - // list. - List<HprofRecord> actualRecords = new ArrayList<HprofRecord>(); - actualRecords.addAll(strings.getStringRecords()); - actualRecords.addAll(records); - - Hprof hprof = new Hprof("JAVA PROFILE 1.0.3", 4, new Date(), actualRecords); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - hprof.write(os); - InMemoryBuffer buffer = new InMemoryBuffer(os.toByteArray()); - return AhatSnapshot.fromDataBuffer(buffer, new ProguardMap()); - } -} diff --git a/tools/ahat/test/TestDump.java b/tools/ahat/test/TestDump.java index db9b25646a..a0d1021ef1 100644 --- a/tools/ahat/test/TestDump.java +++ b/tools/ahat/test/TestDump.java @@ -21,75 +21,124 @@ import com.android.ahat.heapdump.AhatInstance; import com.android.ahat.heapdump.AhatSnapshot; import com.android.ahat.heapdump.Diff; import com.android.ahat.heapdump.FieldValue; +import com.android.ahat.heapdump.HprofFormatException; +import com.android.ahat.heapdump.Parser; import com.android.ahat.heapdump.Site; import com.android.ahat.heapdump.Value; -import com.android.tools.perflib.heap.ProguardMap; -import java.io.File; +import com.android.ahat.proguard.ProguardMap; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.ByteBuffer; import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; +import java.util.List; +import java.util.Objects; /** - * The TestDump class is used to get an AhatSnapshot for the test-dump - * program. + * The TestDump class is used to get the current and baseline AhatSnapshots + * for heap dumps generated by the test-dump program that are stored as + * resources in this jar file. */ public class TestDump { - // It can take on the order of a second to parse and process the test-dump - // hprof. To avoid repeating this overhead for each test case, we cache the - // loaded instance of TestDump and reuse it when possible. In theory the - // test cases should not be able to modify the cached snapshot in a way that - // is visible to other test cases. - private static TestDump mCachedTestDump = null; + // It can take on the order of a second to parse and process test dumps. + // To avoid repeating this overhead for each test case, we provide a way to + // cache loaded instance of TestDump and reuse it when possible. In theory + // the test cases should not be able to modify the cached snapshot in a way + // that is visible to other test cases. + private static List<TestDump> mCachedTestDumps = new ArrayList<TestDump>(); + + // The name of the resources this test dump is loaded from. + private String mHprofResource; + private String mHprofBaseResource; + private String mMapResource; // If the test dump fails to load the first time, it will likely fail every // other test we try. Rather than having to wait a potentially very long // time for test dump loading to fail over and over again, record when it // fails and don't try to load it again. - private static boolean mTestDumpFailed = false; + private boolean mTestDumpFailed = true; + // The loaded heap dumps. private AhatSnapshot mSnapshot; private AhatSnapshot mBaseline; + + // Cached reference to the 'Main' class object in the snapshot and baseline + // heap dumps. private AhatClassObj mMain; private AhatClassObj mBaselineMain; /** - * Load the test-dump.hprof and test-dump-base.hprof files. - * The location of the files are read from the system properties - * "ahat.test.dump.hprof" and "ahat.test.dump.base.hprof", which is expected - * to be set on the command line. - * The location of the proguard map for both hprof files is read from the - * system property "ahat.test.dump.map". For example: - * java -Dahat.test.dump.hprof=test-dump.hprof \ - * -Dahat.test.dump.base.hprof=test-dump-base.hprof \ - * -Dahat.test.dump.map=proguard.map \ - * -jar ahat-tests.jar + * Read the named resource into a ByteBuffer. + */ + private static ByteBuffer dataBufferFromResource(String name) throws IOException { + ClassLoader loader = TestDump.class.getClassLoader(); + InputStream is = loader.getResourceAsStream(name); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buf = new byte[4096]; + int read; + while ((read = is.read(buf)) != -1) { + baos.write(buf, 0, read); + } + return ByteBuffer.wrap(baos.toByteArray()); + } + + /** + * Create a TestDump instance. + * The load() method should be called to load and process the heap dumps. + * The files are specified as names of resources compiled into the jar file. + * The baseline resouce may be null to indicate that no diffing should be + * performed. + * The map resource may be null to indicate no proguard map will be used. * + */ + private TestDump(String hprofResource, String hprofBaseResource, String mapResource) { + mHprofResource = hprofResource; + mHprofBaseResource = hprofBaseResource; + mMapResource = mapResource; + } + + /** + * Load the heap dumps for this TestDump. * An IOException is thrown if there is a failure reading the hprof files or * the proguard map. */ - private TestDump() throws IOException { - // TODO: Make use of the baseline hprof for tests. - String hprof = System.getProperty("ahat.test.dump.hprof"); - String hprofBase = System.getProperty("ahat.test.dump.base.hprof"); - - String mapfile = System.getProperty("ahat.test.dump.map"); + private void load() throws IOException { ProguardMap map = new ProguardMap(); - try { - map.readFromFile(new File(mapfile)); - } catch (ParseException e) { - throw new IOException("Unable to load proguard map", e); + if (mMapResource != null) { + try { + ClassLoader loader = TestDump.class.getClassLoader(); + InputStream is = loader.getResourceAsStream(mMapResource); + map.readFromReader(new InputStreamReader(is)); + } catch (ParseException e) { + throw new IOException("Unable to load proguard map", e); + } } - mSnapshot = AhatSnapshot.fromHprof(new File(hprof), map); - mBaseline = AhatSnapshot.fromHprof(new File(hprofBase), map); - Diff.snapshots(mSnapshot, mBaseline); + try { + ByteBuffer hprof = dataBufferFromResource(mHprofResource); + mSnapshot = Parser.parseHeapDump(hprof, map); + mMain = findClass(mSnapshot, "Main"); + assert(mMain != null); + } catch (HprofFormatException e) { + throw new IOException("Unable to parse heap dump", e); + } - mMain = findClass(mSnapshot, "Main"); - assert(mMain != null); + if (mHprofBaseResource != null) { + try { + ByteBuffer hprofBase = dataBufferFromResource(mHprofBaseResource); + mBaseline = Parser.parseHeapDump(hprofBase, map); + mBaselineMain = findClass(mBaseline, "Main"); + assert(mBaselineMain != null); + } catch (HprofFormatException e) { + throw new IOException("Unable to parse base heap dump", e); + } + Diff.snapshots(mSnapshot, mBaseline); + } - mBaselineMain = findClass(mBaseline, "Main"); - assert(mBaselineMain != null); + mTestDumpFailed = false; } /** @@ -182,22 +231,42 @@ public class TestDump { } /** - * Get the test dump. + * Get the default (cached) test dump. * An IOException is thrown if there is an error reading the test dump hprof * file. * To improve performance, this returns a cached instance of the TestDump * when possible. */ public static synchronized TestDump getTestDump() throws IOException { - if (mTestDumpFailed) { - throw new RuntimeException("Test dump failed before, assuming it will again"); - } + return getTestDump("test-dump.hprof", "test-dump-base.hprof", "test-dump.map"); + } - if (mCachedTestDump == null) { - mTestDumpFailed = true; - mCachedTestDump = new TestDump(); - mTestDumpFailed = false; + /** + * Get a (cached) test dump. + * @param hprof - The string resouce name of the hprof file. + * @param base - The string resouce name of the baseline hprof, may be null. + * @param map - The string resouce name of the proguard map, may be null. + * An IOException is thrown if there is an error reading the test dump hprof + * file. + * To improve performance, this returns a cached instance of the TestDump + * when possible. + */ + public static synchronized TestDump getTestDump(String hprof, String base, String map) + throws IOException { + for (TestDump loaded : mCachedTestDumps) { + if (Objects.equals(loaded.mHprofResource, hprof) + && Objects.equals(loaded.mHprofBaseResource, base) + && Objects.equals(loaded.mMapResource, map)) { + if (loaded.mTestDumpFailed) { + throw new IOException("Test dump failed before, assuming it will again"); + } + return loaded; + } } - return mCachedTestDump; + + TestDump dump = new TestDump(hprof, base, map); + mCachedTestDumps.add(dump); + dump.load(); + return dump; } } diff --git a/tools/ahat/test/Tests.java b/tools/ahat/test/Tests.java index cd33a9059b..0e7043291d 100644 --- a/tools/ahat/test/Tests.java +++ b/tools/ahat/test/Tests.java @@ -25,11 +25,13 @@ public class Tests { "com.android.ahat.DiffFieldsTest", "com.android.ahat.DiffTest", "com.android.ahat.DominatorsTest", + "com.android.ahat.HtmlEscaperTest", "com.android.ahat.InstanceTest", "com.android.ahat.NativeAllocationTest", "com.android.ahat.ObjectHandlerTest", "com.android.ahat.OverviewHandlerTest", "com.android.ahat.PerformanceTest", + "com.android.ahat.ProguardMapTest", "com.android.ahat.RootedHandlerTest", "com.android.ahat.QueryTest", "com.android.ahat.SiteHandlerTest", diff --git a/tools/cpp-define-generator/Android.bp b/tools/cpp-define-generator/Android.bp index 59c52117eb..57c9c095f8 100644 --- a/tools/cpp-define-generator/Android.bp +++ b/tools/cpp-define-generator/Android.bp @@ -20,7 +20,7 @@ // // In the future we may wish to parameterize this on (32,64)x(read_barrier,no_read_barrier). -cc_binary { // Do not use art_cc_binary because HOST_PREFER_32_BIT is incompatible with genrule. +cc_binary { // Do not use art_cc_binary because HOST_PREFER_32_BIT is incompatible with genrule. name: "cpp-define-generator-data", host_supported: true, device_supported: false, @@ -39,9 +39,9 @@ cc_binary { // Do not use art_cc_binary because HOST_PREFER_32_BIT is incompati // For the exact filename that this generates to run make command on just // this rule later. genrule { - name: "cpp-define-generator-asm-support", - out: ["asm_support_gen.h"], - tools: ["cpp-define-generator-data"], - tool_files: ["verify-asm-support"], - cmd: "$(location verify-asm-support) --quiet \"$(location cpp-define-generator-data)\" \"$(out)\"" + name: "cpp-define-generator-asm-support", + out: ["asm_support_gen.h"], + tools: ["cpp-define-generator-data"], + tool_files: ["verify-asm-support"], + cmd: "$(location verify-asm-support) --quiet \"$(location cpp-define-generator-data)\" \"$(out)\"", } diff --git a/tools/libjdwp_art_failures.txt b/tools/libjdwp_art_failures.txt new file mode 100644 index 0000000000..6b5daec5a7 --- /dev/null +++ b/tools/libjdwp_art_failures.txt @@ -0,0 +1,102 @@ +/* + * This file contains expectations for ART's buildbot. The purpose of this file is + * to temporarily list failing tests and not break the bots. + */ +[ +{ + description: "Test fails due to unexpectedly getting the thread-groups of zombie threads", + result: EXEC_FAILED, + bug: 66906414, + name: "org.apache.harmony.jpda.tests.jdwp.ThreadReference.ThreadGroup002Test#testThreadGroup002" +}, +{ + description: "Test fails due to modifiers not including ACC_SUPER", + result: EXEC_FAILED, + bug: 66906055, + name: "org.apache.harmony.jpda.tests.jdwp.ReferenceType.ModifiersTest#testModifiers001" +}, +{ + description: "Test fails due to static values not being set correctly.", + result: EXEC_FAILED, + bug: 66905894, + name: "org.apache.harmony.jpda.tests.jdwp.ReferenceType.GetValues006Test#testGetValues006" +}, +{ + description: "Tests fail due to using the not yet supported interrupt thread functions", + result: EXEC_FAILED, + bug: 34415266, + names: [ "org.apache.harmony.jpda.tests.jdwp.ThreadReference.CurrentContendedMonitorTest#testCurrentContendedMonitor001", + "org.apache.harmony.jpda.tests.jdwp.ThreadReference.InterruptTest#testInterrupt001" ] +}, +{ + description: "Tests fail with assertion error on slot number", + result: EXEC_FAILED, + bug: 66905468, + names: [ "org.apache.harmony.jpda.tests.jdwp.Method.VariableTableTest#testVariableTableTest001", + "org.apache.harmony.jpda.tests.jdwp.Method.VariableTableWithGenericTest#testVariableTableWithGenericTest001" ] +}, +{ + description: "Test fails with assertion error 'Invalid Path' for class path.", + result: EXEC_FAILED, + bug: 66904994, + name: "org.apache.harmony.jpda.tests.jdwp.VirtualMachine.ClassPathsTest#testClassPaths001" +}, +{ + description: "Test fails with Error VM_DEAD when trying to resume during VM_DEATH event", + result: EXEC_FAILED, + bug: 66904725, + name: "org.apache.harmony.jpda.tests.jdwp.Events.VMDeath002Test#testVMDeathRequest" +}, +{ + description: "Test fails with INTERNAL error due to proxy frame!", + result: EXEC_FAILED, + bug: 66903662, + name: "org.apache.harmony.jpda.tests.jdwp.StackFrame.ProxyThisObjectTest#testThisObject" +}, +{ + description: "Test fails with unexpected TYPE_MISMATCH error", + result: EXEC_FAILED, + bug: 66904008, + name: "org.apache.harmony.jpda.tests.jdwp.StackFrame.ThisObjectTest#testThisObjectTest001" +}, +{ + description: "Tests that fail only on ART with INVALID_SLOT error", + result: EXEC_FAILED, + bug: 66903181, + names: [ "org.apache.harmony.jpda.tests.jdwp.EventModifiers.InstanceOnlyModifierTest#testBreakpoint", + "org.apache.harmony.jpda.tests.jdwp.EventModifiers.InstanceOnlyModifierTest#testException", + "org.apache.harmony.jpda.tests.jdwp.EventModifiers.InstanceOnlyModifierTest#testFieldAccess", + "org.apache.harmony.jpda.tests.jdwp.EventModifiers.InstanceOnlyModifierTest#testFieldModification", + "org.apache.harmony.jpda.tests.jdwp.EventModifiers.InstanceOnlyModifierTest#testMethodEntry", + "org.apache.harmony.jpda.tests.jdwp.EventModifiers.InstanceOnlyModifierTest#testMethodExit", + "org.apache.harmony.jpda.tests.jdwp.EventModifiers.InstanceOnlyModifierTest#testMethodExitWithReturnValue" ] +}, +/* TODO Categorize these failures more. */ +{ + description: "Tests that fail on both ART and RI. These tests are likely incorrect", + result: EXEC_FAILED, + bug: 66906734, + names: [ "org.apache.harmony.jpda.tests.jdwp.ArrayReference.SetValues003Test#testSetValues003_InvalidIndex", + "org.apache.harmony.jpda.tests.jdwp.ClassType.InvokeMethod002Test#testInvokeMethod_wrong_argument_types", + "org.apache.harmony.jpda.tests.jdwp.ClassType.InvokeMethodTest#testInvokeMethod002", + "org.apache.harmony.jpda.tests.jdwp.ClassType.InvokeMethodTest#testInvokeMethod003", + "org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceTest#testNewInstance002", + "org.apache.harmony.jpda.tests.jdwp.ClassType.SetValues002Test#testSetValues002", + "org.apache.harmony.jpda.tests.jdwp.Events.ClassPrepare002Test#testClassPrepareCausedByDebugger", + "org.apache.harmony.jpda.tests.jdwp.Events.ExceptionCaughtTest#testExceptionEvent_ThrowLocation_FromNative", + "org.apache.harmony.jpda.tests.jdwp.ObjectReference.DisableCollectionTest#testDisableCollection_null", + "org.apache.harmony.jpda.tests.jdwp.ObjectReference.EnableCollectionTest#testEnableCollection_invalid", + "org.apache.harmony.jpda.tests.jdwp.ObjectReference.EnableCollectionTest#testEnableCollection_null", + "org.apache.harmony.jpda.tests.jdwp.ObjectReference.GetValues002Test#testGetValues002", + "org.apache.harmony.jpda.tests.jdwp.ObjectReference.SetValues003Test#testSetValues003", + "org.apache.harmony.jpda.tests.jdwp.ObjectReference.SetValuesTest#testSetValues001", + "org.apache.harmony.jpda.tests.jdwp.ReferenceType.FieldsWithGenericTest#testFieldsWithGeneric001", + "org.apache.harmony.jpda.tests.jdwp.ReferenceType.GetValues002Test#testGetValues002", + "org.apache.harmony.jpda.tests.jdwp.ReferenceType.GetValues004Test#testGetValues004", + "org.apache.harmony.jpda.tests.jdwp.StringReference.ValueTest#testStringReferenceValueTest001_NullString", + "org.apache.harmony.jpda.tests.jdwp.ThreadGroupReference.ChildrenTest#testChildren_NullObject", + "org.apache.harmony.jpda.tests.jdwp.ThreadGroupReference.NameTest#testName001_NullObject", + "org.apache.harmony.jpda.tests.jdwp.ThreadGroupReference.ParentTest#testParent_NullObject", + "org.apache.harmony.jpda.tests.jdwp.VirtualMachine.CapabilitiesNewTest#testCapabilitiesNew001" ] +} +] diff --git a/tools/titrace/Android.bp b/tools/titrace/Android.bp index b95ec9db25..097622e756 100644 --- a/tools/titrace/Android.bp +++ b/tools/titrace/Android.bp @@ -19,7 +19,10 @@ cc_defaults { name: "titrace-defaults", host_supported: true, - srcs: ["titrace.cc", "instruction_decoder.cc"], + srcs: [ + "titrace.cc", + "instruction_decoder.cc", + ], defaults: ["art_defaults"], // Note that this tool needs to be built for both 32-bit and 64-bit since it requires @@ -27,7 +30,7 @@ cc_defaults { compile_multilib: "both", shared_libs: [ - "libbase" + "libbase", ], target: { android: { @@ -37,7 +40,7 @@ cc_defaults { }, header_libs: [ "libopenjdkjvmti_headers", - "libart_runtime_headers" // for dex_instruction_list.h only + "libart_runtime_headers", // for dex_instruction_list.h only // "libbase_headers", ], multilib: { diff --git a/tools/wrapagentproperties/Android.bp b/tools/wrapagentproperties/Android.bp index c39b81a279..8dec847c9e 100644 --- a/tools/wrapagentproperties/Android.bp +++ b/tools/wrapagentproperties/Android.bp @@ -27,7 +27,7 @@ cc_defaults { compile_multilib: "both", shared_libs: [ - "libbase" + "libbase", ], target: { android: { @@ -62,5 +62,5 @@ art_cc_library { "art_debug_defaults", "wrapagentproperties-defaults", ], - shared_libs: [ ], + shared_libs: [], } |