Merge "Add D8 verification for 910-methods."
diff --git a/benchmark/Android.bp b/benchmark/Android.bp
index 606734b..3995ca2 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 @@
"libbase",
"libnativehelper",
],
- clang: true,
- target: {
- android: {
- shared_libs: ["libdl"],
- },
- host: {
- host_ldlibs: ["-ldl", "-lpthread"],
- },
- },
cflags: [
"-Wno-frame-larger-than=",
],
@@ -49,7 +40,10 @@
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 @@
],
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 65df933..8e8a2f6 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -20,7 +20,6 @@
// 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 @@
// Apple, it's a pain.
"-Wmissing-noreturn",
],
- host_ldlibs: [
- "-lrt",
- ],
},
host: {
cflags: [
@@ -109,10 +105,6 @@
"-msse4.2",
"-mpopcnt",
],
- host_ldlibs: [
- "-ldl",
- "-lpthread",
- ],
},
},
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 1475679..3044890 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -23,7 +23,6 @@
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 @@
"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 @@
},
},
target: {
- host: {
- // For compiler driver TLS.
- host_ldlibs: ["-lpthread"],
- },
android: {
// For atrace.
shared_libs: ["libcutils"],
@@ -204,10 +200,10 @@
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_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 0d38620..500fc4a 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 0000000..c432747
--- /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 0d9021f..111469f 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 @@
}
}
-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 @@
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 @@
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 5ef6cbf..892bc59 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 cf5d65e..49d52c4 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 5678910..a8225fa 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 0000000..5286b8c
--- /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 0000000..ceaa53f
--- /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 9d57b96..7581962 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -374,8 +374,8 @@
// 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 @@
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 e36d416..6637be2 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 c8e3d5e..925863e 100644
--- a/compiler/dex/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -64,14 +64,14 @@
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 @@
return false;
}
matcher->pos_ += 1u;
- matcher->instruction_ = matcher->instruction_->Next();
+ ++matcher->instruction_;
return true;
}
@@ -105,7 +105,7 @@
return true;
}
matcher->pos_ = matcher->mark_;
- matcher->instruction_ = matcher->instruction_->Next();
+ ++matcher->instruction_;
return true;
}
@@ -301,26 +301,27 @@
// 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 @@
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 @@
// 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::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::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 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 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 e46dc59..9c5b632 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -64,24 +64,21 @@
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 528b0a2..c739333 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 @@
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 @@
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 27011e8..249f06c 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 @@
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 @@
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 2ec2af5..e1ea630 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 @@
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 678f090..7573367 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 @@
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 @@
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 @@
default:
break;
}
-
- code_ptr += inst->SizeInCodeUnits();
}
}
@@ -2438,21 +2433,16 @@
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 5fdf9ff..511a44a 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -175,7 +175,8 @@
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 e7e4647..c66a2a6 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -665,7 +665,7 @@
/* 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 cb6522c..2cb23d1 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 704feeb..f84fea3 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 82f502a..828c99b 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 0000000..0ac1490
--- /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
similarity index 90%
rename from compiler/compiled_method_test.cc
rename to compiler/linker/linker_patch_test.cc
index f4a72cf..e87dc8d 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 @@
}
}
+} // namespace linker
} // namespace art
diff --git a/compiler/linker/mips/relative_patcher_mips.cc b/compiler/linker/mips/relative_patcher_mips.cc
index 408ac22..69e0846 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 2bcd98a..aae5746 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 e079946..548e128 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 @@
namespace linker {
+class LinkerPatch;
class OutputStream;
/**
diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h
index f7dbc1e..6297dd0 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 6967b0b..cdd2cef 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 156ece9..9633564 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 a170734..a7f7bce 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -927,7 +927,7 @@
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 @@
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 @@
// 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 @@
*/
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 2aaf058..851838c 100644
--- a/compiler/optimizing/bounds_check_elimination_test.cc
+++ b/compiler/optimizing/bounds_check_elimination_test.cc
@@ -70,10 +70,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
//////////////////////////////////////////////////////////////////////////////////
// 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 @@
// 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 @@
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 @@
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 @@
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 0d9d3d4..0e708ed 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 2c9a9ef..9524fe2 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 @@
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 1e5f1ec..3cb3792 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -68,35 +68,35 @@
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 @@
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::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 @@
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::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 @@
// 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 @@
}
} 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::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 @@
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 @@
}
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 @@
}
}
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 @@
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 @@
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 @@
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 @@
}
} 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 @@
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 @@
}
} 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 @@
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::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 30c2b52..ac3c839 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -61,9 +61,12 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 8814cfc..42e9f68 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 @@
}
}
-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 @@
// 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 @@
// 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 @@
{
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 @@
__ 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 @@
{
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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
// 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 @@
#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::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::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 @@
}
-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 @@
void CodeGeneratorARM64::MoveLocation(Location destination,
Location source,
- Primitive::Type dst_type) {
+ DataType::Type dst_type) {
if (source.Equals(destination)) {
return;
}
@@ -1779,7 +1783,7 @@
// 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 @@
|| 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 @@
__ 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 @@
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::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 @@
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 @@
// 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 @@
}
}
break;
- case Primitive::kPrimByte:
+ case DataType::Type::kInt8:
{
ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize);
__ ldarb(Register(dst), base);
@@ -1983,9 +1988,9 @@
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 @@
}
}
break;
- case Primitive::kPrimShort:
+ case DataType::Type::kInt16:
{
ExactAssemblyScope eas(masm, kInstructionSize, CodeBufferCheckScope::kExactSize);
__ ldarh(Register(dst), base);
@@ -2002,12 +2007,12 @@
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 @@
}
}
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 @@
__ 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 @@
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 @@
}
}
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 @@
}
}
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 @@
}
}
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 @@
}
break;
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unreachable type " << type;
}
}
@@ -2268,17 +2273,17 @@
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 @@
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 @@
}
}
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 @@
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 @@
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 @@
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 @@
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::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 @@
}
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 @@
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 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 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 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 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 @@
// 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 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 @@
// 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 @@
}
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 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 @@
// 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 @@
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 @@
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 @@
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 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 @@
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 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 @@
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 @@
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 @@
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 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 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 @@
__ 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 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 @@
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 @@
__ 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 @@
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 @@
}
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::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 @@
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 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
__ 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 @@
}
}
-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 @@
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<linker::LinkerPatch::TypeClassTablePatch>(
+ pc_relative_type_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::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::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 @@
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 @@
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 @@
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 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 @@
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 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 @@
} 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 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 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 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 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 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 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 69c5119..21da955 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -100,7 +100,7 @@
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 @@
kRuntimeParameterFpuRegistersLength,
kArm64PointerSize) {}
- Location GetReturnLocation(Primitive::Type return_type);
+ Location GetReturnLocation(DataType::Type return_type);
private:
DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
@@ -187,7 +187,7 @@
kParameterFPRegistersLength,
kArm64PointerSize) {}
- Location GetReturnLocation(Primitive::Type return_type) const {
+ Location GetReturnLocation(DataType::Type return_type) const {
return ARM64ReturnLocation(return_type);
}
@@ -201,8 +201,8 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 baf68c4..2b9e0fe 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 @@
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 @@
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 @@
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 @@
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 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 @@
// 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 @@
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 @@
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> 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 @@
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 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 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 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 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 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 @@
__ 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 @@
}
}
- 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 @@
}
}
- 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 @@
}
}
- 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 @@
}
}
- 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 @@
__ 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 @@
// 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 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 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 @@
return;
}
- if (!Primitive::IsFloatingPointType(type)) {
+ if (!DataType::IsFloatingPointType(type)) {
bool invert = false;
if (out.Equals(second)) {
@@ -3260,7 +3261,7 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
__ 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 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 @@
// 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 @@
}
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 @@
}
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 @@
}
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 @@
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 @@
}
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 @@
}
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 @@
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 @@
};
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
}
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 @@
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 @@
}
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 @@
__ 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 @@
}
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 @@
}
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 @@
};
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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::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::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::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::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 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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
if (value.IsRegisterPair()) {
UseScratchRegisterScope temps(GetVIXLAssembler());
vixl32::Register temp = temps.Acquire();
@@ -4890,13 +4891,13 @@
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 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 @@
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 @@
}
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 @@
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 @@
}
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
vixl32::Register o_h = HighRegisterFrom(out);
vixl32::Register o_l = LowRegisterFrom(out);
@@ -5257,11 +5258,11 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
if (is_volatile && !atomic_ldrd_strd) {
GenerateWideAtomicStore(base,
offset,
@@ -5556,12 +5557,12 @@
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 @@
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 @@
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 @@
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 @@
}
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::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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 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 @@
}
}
-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 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 @@
}
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 @@
// 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 @@
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 @@
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 @@
__ 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 @@
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 @@
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 @@
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
if (index.IsConstant()) {
size_t offset =
(Int32ConstantFrom(index) << TIMES_8) + data_offset;
@@ -6347,7 +6349,7 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
// 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 @@
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
Location value = locations->InAt(2);
if (index.IsConstant()) {
size_t offset =
@@ -6632,7 +6634,7 @@
break;
}
- case Primitive::kPrimFloat: {
+ case DataType::Type::kFloat32: {
Location value = locations->InAt(2);
DCHECK(value.IsFpuRegister());
if (index.IsConstant()) {
@@ -6647,7 +6649,7 @@
break;
}
- case Primitive::kPrimDouble: {
+ case DataType::Type::kFloat64: {
Location value = locations->InAt(2);
DCHECK(value.IsFpuRegisterPair());
if (index.IsConstant()) {
@@ -6662,13 +6664,13 @@
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 @@
// 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::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 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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
__ 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 @@
// 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 @@
// 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 @@
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 @@
});
}
-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 @@
}
}
-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 @@
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<linker::LinkerPatch::TypeClassTablePatch>(
+ pc_relative_type_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::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::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 @@
}
// 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 @@
// 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 e78bc15..58b8525 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -173,8 +173,8 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 6256722..a7c8557 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 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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
&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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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::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 @@
} 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 @@
} 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 @@
} 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 @@
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 @@
void CodeGeneratorMIPS::MoveLocation(Location destination,
Location source,
- Primitive::Type dst_type) {
+ DataType::Type dst_type) {
if (source.Equals(destination)) {
return;
}
@@ -1493,10 +1498,10 @@
}
} 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 @@
__ 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 @@
}
}
-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 @@
}
}
-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 @@
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<linker::LinkerPatch::TypeClassTablePatch>(
+ pc_relative_type_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::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::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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
}
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 @@
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 @@
break;
}
- case Primitive::kPrimByte: {
+ case DataType::Type::kInt8: {
Register out = out_loc.AsRegister<Register>();
if (index.IsConstant()) {
size_t offset =
@@ -2613,7 +2618,7 @@
break;
}
- case Primitive::kPrimShort: {
+ case DataType::Type::kInt16: {
Register out = out_loc.AsRegister<Register>();
if (index.IsConstant()) {
size_t offset =
@@ -2626,7 +2631,7 @@
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 @@
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 @@
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 @@
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
Register out = out_loc.AsRegisterPairLow<Register>();
if (index.IsConstant()) {
size_t offset =
@@ -2765,7 +2770,7 @@
break;
}
- case Primitive::kPrimFloat: {
+ case DataType::Type::kFloat32: {
FRegister out = out_loc.AsFpuRegister<FRegister>();
if (index.IsConstant()) {
size_t offset =
@@ -2778,7 +2783,7 @@
break;
}
- case Primitive::kPrimDouble: {
+ case DataType::Type::kFloat64: {
FRegister out = out_loc.AsFpuRegister<FRegister>();
if (index.IsConstant()) {
size_t offset =
@@ -2791,7 +2796,7 @@
break;
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
}
@@ -2836,7 +2841,7 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
break;
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
}
@@ -3378,31 +3383,31 @@
}
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 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 @@
__ 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 @@
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 @@
__ 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 @@
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 @@
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 @@
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::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::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::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::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 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 @@
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 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 @@
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 @@
}
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::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 @@
}
}
} else {
- DCHECK_EQ(type, Primitive::kPrimDouble);
+ DCHECK_EQ(type, DataType::Type::kFloat64);
if (isR6) {
switch (cond) {
case kCondEQ:
@@ -5005,13 +5010,13 @@
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 @@
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::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 @@
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 @@
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 @@
}
}
} else {
- DCHECK_EQ(type, Primitive::kPrimDouble);
+ DCHECK_EQ(type, DataType::Type::kFloat64);
if (isR6) {
switch (cond) {
case kCondEQ:
@@ -5432,7 +5437,7 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
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 @@
__ 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 @@
}
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 @@
}
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 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 @@
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 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 @@
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 @@
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 @@
}
}
} 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 @@
// 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 @@
} 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
}
} 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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
}
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 @@
}
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 @@
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 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 @@
__ 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 @@
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 @@
} 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 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 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 @@
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 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 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 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 @@
} 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 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 @@
__ 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 @@
__ Sra(dst, dst, 24);
}
break;
- case Primitive::kPrimShort:
+ case DataType::Type::kInt16:
if (has_sign_extension) {
__ Seh(dst, src);
} else {
@@ -8703,7 +8689,7 @@
__ Sra(dst, dst, 16);
}
break;
- case Primitive::kPrimInt:
+ case DataType::Type::kInt32:
if (dst != src) {
__ Move(dst, src);
}
@@ -8713,8 +8699,8 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
__ 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 @@
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 @@
__ 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 @@
__ Bind(&truncate);
}
- if (input_type == Primitive::kPrimFloat) {
+ if (input_type == DataType::Type::kFloat32) {
__ TruncWS(FTMP, src);
} else {
__ TruncWD(FTMP, src);
@@ -8841,11 +8827,11 @@
__ 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 f15f8c6..5f2f900 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -81,8 +81,8 @@
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 @@
kRuntimeParameterFpuRegistersLength,
kMipsPointerSize) {}
- Location GetReturnLocation(Primitive::Type return_type);
+ Location GetReturnLocation(DataType::Type return_type);
private:
DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
@@ -116,17 +116,17 @@
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 @@
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 @@
// `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 @@
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 @@
// 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 @@
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 @@
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 @@
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 e8ae2db..7051cce 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 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 @@
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 @@
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 @@
// 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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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::MoveLocation(Location destination,
Location source,
- Primitive::Type dst_type) {
+ DataType::Type dst_type) {
if (source.Equals(destination)) {
return;
}
@@ -1261,7 +1262,7 @@
// 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 @@
|| 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 @@
} 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 @@
__ 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 @@
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 @@
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::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 @@
// 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 @@
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 @@
}
}
-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 @@
}
}
-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 @@
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<linker::LinkerPatch::TypeClassTablePatch>(
+ pc_relative_type_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::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::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 @@
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 @@
}
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 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 @@
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 @@
}
} 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 @@
}
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 @@
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 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 @@
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 @@
}
}
} 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 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 @@
}
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 @@
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 @@
break;
}
- case Primitive::kPrimByte: {
+ case DataType::Type::kInt8: {
GpuRegister out = out_loc.AsRegister<GpuRegister>();
if (index.IsConstant()) {
size_t offset =
@@ -2194,7 +2196,7 @@
break;
}
- case Primitive::kPrimShort: {
+ case DataType::Type::kInt16: {
GpuRegister out = out_loc.AsRegister<GpuRegister>();
if (index.IsConstant()) {
size_t offset =
@@ -2207,7 +2209,7 @@
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 @@
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 @@
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 @@
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
GpuRegister out = out_loc.AsRegister<GpuRegister>();
if (index.IsConstant()) {
size_t offset =
@@ -2347,7 +2350,7 @@
break;
}
- case Primitive::kPrimFloat: {
+ case DataType::Type::kFloat32: {
FpuRegister out = out_loc.AsFpuRegister<FpuRegister>();
if (index.IsConstant()) {
size_t offset =
@@ -2360,7 +2363,7 @@
break;
}
- case Primitive::kPrimDouble: {
+ case DataType::Type::kFloat64: {
FpuRegister out = out_loc.AsFpuRegister<FpuRegister>();
if (index.IsConstant()) {
size_t offset =
@@ -2373,7 +2376,7 @@
break;
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
}
@@ -2418,7 +2421,7 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
break;
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
}
@@ -2960,24 +2963,24 @@
}
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 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 @@
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 @@
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 @@
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 @@
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::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 @@
__ 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::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 @@
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 @@
__ 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 @@
}
}
} 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 @@
__ 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 @@
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::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 @@
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 @@
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 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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
}
}
} 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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
__ 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 @@
}
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 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 @@
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 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 @@
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 @@
// 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 @@
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 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 @@
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 @@
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 @@
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 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 @@
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 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 @@
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 @@
} 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 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 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 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 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 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 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 @@
__ 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 @@
__ 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 @@
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 3035621..2a95b37 100644
--- a/compiler/optimizing/code_generator_mips64.h
+++ b/compiler/optimizing/code_generator_mips64.h
@@ -79,8 +79,8 @@
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 @@
kRuntimeParameterFpuRegistersLength,
kMips64PointerSize) {}
- Location GetReturnLocation(Primitive::Type return_type);
+ Location GetReturnLocation(DataType::Type return_type);
private:
DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
@@ -114,16 +114,16 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 18a55c8..5d5623b 100644
--- a/compiler/optimizing/code_generator_vector_arm64.cc
+++ b/compiler/optimizing/code_generator_vector_arm64.cc
@@ -41,17 +41,17 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 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 @@
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 @@
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 @@
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 @@
break;
}
break;
- case Primitive::kPrimLong:
+ case DataType::Type::kInt64:
DCHECK_EQ(2u, instruction->GetVectorLength());
switch (instruction->GetKind()) {
case HVecReduce::kSum:
@@ -249,9 +249,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
: __ 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 @@
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 @@
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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 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* 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 @@
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 @@
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 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 @@
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 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 7a11dff..333d108 100644
--- a/compiler/optimizing/code_generator_vector_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_vector_arm_vixl.cc
@@ -35,11 +35,11 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
: __ 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 @@
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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 c2fbf7f..c25f5ac 100644
--- a/compiler/optimizing/code_generator_vector_mips.cc
+++ b/compiler/optimizing/code_generator_vector_mips.cc
@@ -26,17 +26,17 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
: __ 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 @@
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 @@
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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 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 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 @@
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 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 9d3a777..f60f708 100644
--- a/compiler/optimizing/code_generator_vector_mips64.cc
+++ b/compiler/optimizing/code_generator_vector_mips64.cc
@@ -31,17 +31,17 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
: __ 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 @@
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 @@
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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 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 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 @@
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 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 37190f8..6515dbe 100644
--- a/compiler/optimizing/code_generator_vector_x86.cc
+++ b/compiler/optimizing/code_generator_vector_x86.cc
@@ -30,28 +30,27 @@
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 @@
}
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 @@
__ 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 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 @@
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 @@
__ 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 @@
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 @@
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 @@
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 @@
}
}
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 @@
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 @@
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 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 @@
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 @@
__ 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 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 @@
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 @@
__ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
}
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 @@
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 @@
__ 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 @@
__ 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
__ 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 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 InstructionCodeGeneratorX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
- LOG(FATAL) << "No SIMD for " << instr->GetId();
+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::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 @@
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 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 @@
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 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 edd0209..4241042 100644
--- a/compiler/optimizing/code_generator_vector_x86_64.cc
+++ b/compiler/optimizing/code_generator_vector_x86_64.cc
@@ -30,18 +30,18 @@
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 @@
}
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 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 @@
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 @@
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 @@
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 @@
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 @@
}
}
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 @@
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 @@
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 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 @@
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 @@
__ 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 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 @@
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 @@
__ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
}
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 @@
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 @@
__ 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 @@
__ 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
}
+// 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 @@
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 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 @@
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 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 0b9130f..70e270e 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 @@
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 @@
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 @@
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 @@
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 @@
__ 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 @@
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 @@
}
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
uint32_t index = gp_index_;
gp_index_ += 2;
stack_index_ += 2;
@@ -1186,7 +1187,7 @@
}
}
- case Primitive::kPrimFloat: {
+ case DataType::Type::kFloat32: {
uint32_t index = float_index_++;
stack_index_++;
if (index < calling_convention.GetNumberOfFpuRegisters()) {
@@ -1196,7 +1197,7 @@
}
}
- case Primitive::kPrimDouble: {
+ case DataType::Type::kFloat64: {
uint32_t index = float_index_++;
stack_index_ += 2;
if (index < calling_convention.GetNumberOfFpuRegisters()) {
@@ -1206,7 +1207,7 @@
}
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unexpected parameter type " << type;
break;
}
@@ -1262,10 +1263,10 @@
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 @@
} 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 @@
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 @@
__ 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 @@
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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
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 @@
}
} 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 @@
// 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 @@
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 @@
}
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 @@
__ 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 @@
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 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 @@
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 @@
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 @@
__ 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 @@
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 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 @@
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 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 @@
// 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 @@
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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
};
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 @@
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 @@
__ 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 @@
}
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 @@
__ 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 @@
}
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 @@
}
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 @@
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 @@
}
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 @@
__ 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 @@
}
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 @@
__ 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 @@
}
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 @@
// 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 @@
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 @@
};
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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::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 @@
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 @@
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 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 @@
}
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 @@
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 @@
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 @@
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 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 @@
}
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 @@
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 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 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 @@
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 @@
}
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
}
-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 @@
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<linker::LinkerPatch::TypeClassTablePatch>(
+ boot_image_type_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::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::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 @@
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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
break;
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unreachable type " << field_type;
UNREACHABLE();
}
@@ -5203,7 +5205,7 @@
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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
break;
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
}
@@ -5801,7 +5803,7 @@
__ 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::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 @@
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 @@
}
}
} 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 @@
}
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 @@
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 @@
}
// 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 @@
// 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 b32d57a..fb61e75 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -83,8 +83,8 @@
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 @@
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 @@
? 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 @@
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 @@
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 @@
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 @@
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 39a6580..42704e9 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 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 @@
}
} else {
- DCHECK_EQ(Primitive::kPrimLong, type_);
+ DCHECK_EQ(DataType::Type::kInt64, type_);
if (is_div_) {
__ negq(cpu_reg_);
} else {
@@ -132,7 +133,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
}
-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 @@
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<linker::LinkerPatch::TypeClassTablePatch>(
+ boot_image_type_patches_, linker_patches);
+ EmitPcRelativeLinkerPatches<linker::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::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::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 @@
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 @@
}
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
}
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
uint32_t index = gp_index_;
stack_index_ += 2;
if (index < calling_convention.GetNumberOfRegisters()) {
@@ -2306,7 +2308,7 @@
}
}
- case Primitive::kPrimFloat: {
+ case DataType::Type::kFloat32: {
uint32_t index = float_index_++;
stack_index_++;
if (index < calling_convention.GetNumberOfFpuRegisters()) {
@@ -2316,7 +2318,7 @@
}
}
- case Primitive::kPrimDouble: {
+ case DataType::Type::kFloat64: {
uint32_t index = float_index_++;
stack_index_ += 2;
if (index < calling_convention.GetNumberOfFpuRegisters()) {
@@ -2326,7 +2328,7 @@
}
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unexpected parameter type " << type;
break;
}
@@ -2467,14 +2469,14 @@
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 @@
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 @@
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 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 @@
}
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 @@
}
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 @@
}
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 @@
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 @@
}
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 @@
}
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 @@
};
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 @@
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 @@
}
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 @@
}
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
};
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
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::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 @@
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 @@
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
if (instruction->IsRem()) {
__ xorl(output_register, output_register);
} else {
@@ -3533,7 +3535,7 @@
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 @@
__ 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 @@
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 @@
} 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::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 @@
// 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 @@
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 @@
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 @@
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 @@
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 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 @@
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 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 @@
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 @@
}
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 @@
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 @@
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 @@
}
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
if (second.IsRegister()) {
CpuRegister second_reg = second.AsRegister<CpuRegister>();
if (op->IsShl()) {
@@ -4002,8 +4004,8 @@
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 @@
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 @@
__ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
break;
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unreachable type " << field_type;
UNREACHABLE();
}
@@ -4679,7 +4681,7 @@
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 @@
}
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
break;
}
- case Primitive::kPrimVoid:
+ case DataType::Type::kVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
}
@@ -6359,8 +6361,8 @@
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 @@
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 @@
}
}
} 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 @@
}
// 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 f5fa86b..6f67a45 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -89,16 +89,16 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 0a8e97c..896fcfa 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -91,7 +91,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 e354654..356ff9f 100644
--- a/compiler/optimizing/common_arm.h
+++ b/compiler/optimizing/common_arm.h
@@ -76,8 +76,8 @@
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 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::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 @@
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 e73fd7d..102acb3 100644
--- a/compiler/optimizing/common_arm64.h
+++ b/compiler/optimizing/common_arm64.h
@@ -73,9 +73,9 @@
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 @@
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 @@
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 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 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 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 5f39a49..bb586bf 100644
--- a/compiler/optimizing/constant_folding.cc
+++ b/compiler/optimizing/constant_folding.cc
@@ -150,7 +150,7 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
// 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::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::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::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 @@
// 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 7ef28ed..c85a2e3 100644
--- a/compiler/optimizing/constant_folding_test.cc
+++ b/compiler/optimizing/constant_folding_test.cc
@@ -43,7 +43,7 @@
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 @@
expected_after_cf,
expected_after_dce,
check_after_cf,
- Primitive::kPrimLong);
+ DataType::Type::kInt64);
}
/**
@@ -483,7 +483,7 @@
expected_after_cf,
expected_after_dce,
check_after_cf,
- Primitive::kPrimLong);
+ DataType::Type::kInt64);
}
/**
@@ -547,7 +547,7 @@
expected_after_cf,
expected_after_dce,
check_after_cf,
- Primitive::kPrimLong);
+ DataType::Type::kInt64);
}
/**
@@ -756,7 +756,7 @@
// 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 0000000..fbc0c12
--- /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 0000000..6890617
--- /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 0000000..08f9263
--- /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 0000000..927291a
--- /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 787296d..9b094e9 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -118,7 +118,7 @@
}
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 fa3c4df..0e9c81d 100644
--- a/compiler/optimizing/emit_swap_mips_test.cc
+++ b/compiler/optimizing/emit_swap_mips_test.cc
@@ -118,12 +118,12 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 327e11f..1c7d1a0 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -456,7 +456,7 @@
}
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
instruction->DebugName(),
instruction->GetId(),
static_cast<int>(input_index),
- Primitive::PrettyDescriptor(input->GetType())));
+ DataType::PrettyDescriptor(input->GetType())));
}
}
@@ -904,27 +904,27 @@
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::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::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 3035e46..194f063 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 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
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 @@
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 e1ed7f6..ac0dbee 100644
--- a/compiler/optimizing/gvn_test.cc
+++ b/compiler/optimizing/gvn_test.cc
@@ -37,7 +37,7 @@
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 @@
block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimNot,
+ DataType::Type::kReference,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -55,7 +55,7 @@
0));
block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimNot,
+ DataType::Type::kReference,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -65,7 +65,7 @@
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 @@
block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
parameter,
nullptr,
- Primitive::kPrimNot,
+ DataType::Type::kReference,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -86,7 +86,7 @@
0));
block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimNot,
+ DataType::Type::kReference,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -121,7 +121,7 @@
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 @@
entry->AddSuccessor(block);
block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimBoolean,
+ DataType::Type::kBool,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -152,7 +152,7 @@
then->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimBoolean,
+ DataType::Type::kBool,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -162,7 +162,7 @@
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 @@
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 @@
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 @@
entry->AddSuccessor(block);
block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimBoolean,
+ DataType::Type::kBool,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -235,7 +235,7 @@
loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimBoolean,
+ DataType::Type::kBool,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -250,7 +250,7 @@
loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
parameter,
nullptr,
- Primitive::kPrimBoolean,
+ DataType::Type::kBool,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -260,7 +260,7 @@
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 @@
exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimBoolean,
+ DataType::Type::kBool,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -351,7 +351,7 @@
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 @@
entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
parameter,
nullptr,
- Primitive::kPrimNot,
+ DataType::Type::kReference,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -399,7 +399,7 @@
new (&allocator) HInstanceFieldSet(parameter,
parameter,
nullptr,
- Primitive::kPrimNot,
+ DataType::Type::kReference,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -425,7 +425,7 @@
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 84b20f6..fe286ab 100644
--- a/compiler/optimizing/induction_var_analysis.cc
+++ b/compiler/optimizing/induction_var_analysis.cc
@@ -56,17 +56,17 @@
/**
* 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 @@
/**
* 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 @@
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::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 @@
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 @@
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::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 @@
}
// 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 @@
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::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::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::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 @@
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::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 @@
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 @@
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 39b39cd..421b3ab 100644
--- a/compiler/optimizing/induction_var_analysis.h
+++ b/compiler/optimizing/induction_var_analysis.h
@@ -103,7 +103,7 @@
InductionInfo* a,
InductionInfo* b,
HInstruction* f,
- Primitive::Type t)
+ DataType::Type t)
: induction_class(ic),
operation(op),
op_a(a),
@@ -115,7 +115,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 9516ccb..53c8044 100644
--- a/compiler/optimizing/induction_var_analysis_test.cc
+++ b/compiler/optimizing/induction_var_analysis_test.cc
@@ -94,7 +94,7 @@
// 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 @@
// 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 @@
*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 @@
// 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 @@
// 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 @@
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 @@
// }
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
// 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 @@
} 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 @@
// }
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 @@
// }
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 191d3d1..92b584c 100644
--- a/compiler/optimizing/induction_var_range.cc
+++ b/compiler/optimizing/induction_var_range.cc
@@ -157,15 +157,15 @@
}
/** 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 @@
// 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 @@
} 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 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 9437014..1c84269 100644
--- a/compiler/optimizing/induction_var_range_test.cc
+++ b/compiler/optimizing/induction_var_range_test.cc
@@ -71,12 +71,12 @@
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 @@
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 @@
}
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 @@
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 @@
CreateConst(a),
CreateConst(b),
nullptr,
- Primitive::kPrimInt);
+ DataType::Type::kInt32);
}
/** Constructs a polynomial sum(a * i + b) + c induction. */
@@ -193,7 +194,7 @@
CreateLinear(a, b),
CreateConst(c),
nullptr,
- Primitive::kPrimInt);
+ DataType::Type::kInt32);
}
/** Constructs a geometric a * f^i + b induction. */
@@ -204,7 +205,7 @@
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 @@
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 @@
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, 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 793e781..90e3d2a 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* result = new (graph_->GetArena()) HInstanceFieldGet(
receiver,
field,
- Primitive::kPrimNot,
+ DataType::Type::kReference,
field->GetOffset(),
field->IsVolatile(),
field->GetDexFieldIndex(),
@@ -1143,9 +1144,9 @@
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 @@
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 @@
}
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 @@
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 @@
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* 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 @@
// 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 @@
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 @@
HGraphBuilder builder(callee_graph,
&dex_compilation_unit,
&outer_compilation_unit_,
- resolved_method->GetDexFile(),
- *code_item,
compiler_driver_,
codegen_,
inline_stats_,
@@ -1711,7 +1710,7 @@
} 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 @@
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 @@
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 @@
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 6532ec1..6ad8036 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 @@
}
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 @@
};
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 @@
}
}
-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 @@
}
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 @@
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 @@
}
(*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 @@
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 @@
*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 @@
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 @@
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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
}
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::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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
}
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::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 @@
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 @@
|| 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
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 b7fa394..a684bf4 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -42,7 +42,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 337177f..cf1cbd5 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 @@
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 @@
// 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::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::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 @@
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 @@
// 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;
@@ -359,18 +360,36 @@
}
// Shift operations implicitly mask the shift amount according to the type width. Get rid of
- // unnecessary explicit masking operations on the shift amount.
+ // unnecessary And/Or/Xor/Add/Sub/TypeConversion operations on the shift amount that do not
+ // affect the relevant bits.
// Replace code looking like
- // AND masked_shift, shift, <superset of implicit mask>
- // SHL dst, value, masked_shift
+ // AND adjusted_shift, shift, <superset of implicit mask>
+ // [OR/XOR/ADD/SUB adjusted_shift, shift, <value not overlapping with implicit mask>]
+ // [<conversion-from-integral-non-64-bit-type> adjusted_shift, shift]
+ // SHL dst, value, adjusted_shift
// with
// SHL dst, value, shift
- if (shift_amount->IsAnd()) {
- HAnd* and_insn = shift_amount->AsAnd();
- HConstant* mask = and_insn->GetConstantRight();
- if ((mask != nullptr) && ((Int64FromConstant(mask) & implicit_mask) == implicit_mask)) {
- instruction->ReplaceInput(and_insn->GetLeastConstantLeft(), 1);
+ if (shift_amount->IsAnd() ||
+ shift_amount->IsOr() ||
+ shift_amount->IsXor() ||
+ shift_amount->IsAdd() ||
+ shift_amount->IsSub()) {
+ int64_t required_result = shift_amount->IsAnd() ? implicit_mask : 0;
+ HBinaryOperation* bin_op = shift_amount->AsBinaryOperation();
+ HConstant* mask = bin_op->GetConstantRight();
+ if (mask != nullptr && (Int64FromConstant(mask) & implicit_mask) == required_result) {
+ instruction->ReplaceInput(bin_op->GetLeastConstantLeft(), 1);
RecordSimplification();
+ return;
+ }
+ } else if (shift_amount->IsTypeConversion()) {
+ DCHECK_NE(shift_amount->GetType(), DataType::Type::kBool); // We never convert to bool.
+ DataType::Type source_type = shift_amount->InputAt(0)->GetType();
+ // Non-integral and 64-bit source types require an explicit type conversion.
+ if (DataType::IsIntegralType(source_type) && !DataType::Is64BitType(source_type)) {
+ instruction->ReplaceInput(shift_amount->AsTypeConversion()->GetInput(), 1);
+ RecordSimplification();
+ return;
}
}
}
@@ -412,7 +431,7 @@
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 +464,7 @@
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 +525,7 @@
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 +683,14 @@
}
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 +727,7 @@
}
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 +820,7 @@
} 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 +834,8 @@
// 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 +856,8 @@
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 +867,20 @@
// 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 +923,12 @@
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 +994,9 @@
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 +1036,39 @@
}
}
-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 +1080,7 @@
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 +1091,10 @@
// 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 +1116,15 @@
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 +1146,7 @@
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 +1248,7 @@
// 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 +1469,7 @@
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 +1493,19 @@
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 +1524,7 @@
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 +1544,7 @@
}
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 +1555,7 @@
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 +1569,7 @@
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 +1652,7 @@
}
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 +1748,8 @@
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 +1840,7 @@
// 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 +1875,7 @@
}
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 +1952,7 @@
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 +1962,7 @@
// 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 +2015,8 @@
{
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 +2026,8 @@
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 +2040,14 @@
}
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 +2055,28 @@
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 +2097,14 @@
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 +2128,17 @@
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 +2168,7 @@
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 +2271,28 @@
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 +2360,7 @@
HBinaryOperation* instruction) {
DCHECK(instruction->IsCommutative());
- if (!Primitive::IsIntegralType(instruction->GetType())) {
+ if (!DataType::IsIntegralType(instruction->GetType())) {
return false;
}
@@ -2387,12 +2410,12 @@
}
// 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 +2437,8 @@
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 a32d0ce..7439893 100644
--- a/compiler/optimizing/instruction_simplifier_arm.cc
+++ b/compiler/optimizing/instruction_simplifier_arm.cc
@@ -30,6 +30,57 @@
namespace arm {
+class InstructionSimplifierArmVisitor : public HGraphVisitor {
+ public:
+ InstructionSimplifierArmVisitor(HGraph* graph, OptimizingCompilerStats* stats)
+ : HGraphVisitor(graph), stats_(stats) {}
+
+ private:
+ void RecordSimplification() {
+ if (stats_ != nullptr) {
+ stats_->RecordStat(kInstructionSimplificationsArch);
+ }
+ }
+
+ bool TryMergeIntoUsersShifterOperand(HInstruction* instruction);
+ bool TryMergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op, bool do_merge);
+ bool CanMergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op) {
+ return TryMergeIntoShifterOperand(use, bitfield_op, /* do_merge */ false);
+ }
+ bool MergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op) {
+ DCHECK(CanMergeIntoShifterOperand(use, bitfield_op));
+ return TryMergeIntoShifterOperand(use, bitfield_op, /* do_merge */ true);
+ }
+
+ /**
+ * This simplifier uses a special-purpose BB visitor.
+ * (1) No need to visit Phi nodes.
+ * (2) Since statements can be removed in a "forward" fashion,
+ * the visitor should test if each statement is still there.
+ */
+ void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
+ // TODO: fragile iteration, provide more robust iterators?
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
+ HInstruction* instruction = it.Current();
+ if (instruction->IsInBlock()) {
+ instruction->Accept(this);
+ }
+ }
+ }
+
+ void VisitAnd(HAnd* instruction) OVERRIDE;
+ void VisitArrayGet(HArrayGet* instruction) OVERRIDE;
+ void VisitArraySet(HArraySet* instruction) OVERRIDE;
+ void VisitMul(HMul* instruction) OVERRIDE;
+ void VisitOr(HOr* instruction) OVERRIDE;
+ void VisitShl(HShl* instruction) OVERRIDE;
+ void VisitShr(HShr* instruction) OVERRIDE;
+ void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE;
+ void VisitUShr(HUShr* instruction) OVERRIDE;
+
+ OptimizingCompilerStats* stats_;
+};
+
bool InstructionSimplifierArmVisitor::TryMergeIntoShifterOperand(HInstruction* use,
HInstruction* bitfield_op,
bool do_merge) {
@@ -38,8 +89,8 @@
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 +121,17 @@
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 +194,7 @@
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 +204,9 @@
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 +221,13 @@
}
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 +266,15 @@
}
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);
}
}
@@ -234,5 +285,10 @@
}
}
+void InstructionSimplifierArm::Run() {
+ InstructionSimplifierArmVisitor visitor(graph_, stats_);
+ visitor.VisitReversePostOrder();
+}
+
} // namespace arm
} // namespace art
diff --git a/compiler/optimizing/instruction_simplifier_arm.h b/compiler/optimizing/instruction_simplifier_arm.h
index e2ed257..2f65729 100644
--- a/compiler/optimizing/instruction_simplifier_arm.h
+++ b/compiler/optimizing/instruction_simplifier_arm.h
@@ -23,58 +23,6 @@
namespace art {
namespace arm {
-class InstructionSimplifierArmVisitor : public HGraphVisitor {
- public:
- InstructionSimplifierArmVisitor(HGraph* graph, OptimizingCompilerStats* stats)
- : HGraphVisitor(graph), stats_(stats) {}
-
- private:
- void RecordSimplification() {
- if (stats_ != nullptr) {
- stats_->RecordStat(kInstructionSimplificationsArch);
- }
- }
-
- bool TryMergeIntoUsersShifterOperand(HInstruction* instruction);
- bool TryMergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op, bool do_merge);
- bool CanMergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op) {
- return TryMergeIntoShifterOperand(use, bitfield_op, /* do_merge */ false);
- }
- bool MergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op) {
- DCHECK(CanMergeIntoShifterOperand(use, bitfield_op));
- return TryMergeIntoShifterOperand(use, bitfield_op, /* do_merge */ true);
- }
-
- /**
- * This simplifier uses a special-purpose BB visitor.
- * (1) No need to visit Phi nodes.
- * (2) Since statements can be removed in a "forward" fashion,
- * the visitor should test if each statement is still there.
- */
- void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
- // TODO: fragile iteration, provide more robust iterators?
- for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
- HInstruction* instruction = it.Current();
- if (instruction->IsInBlock()) {
- instruction->Accept(this);
- }
- }
- }
-
- void VisitAnd(HAnd* instruction) OVERRIDE;
- void VisitArrayGet(HArrayGet* instruction) OVERRIDE;
- void VisitArraySet(HArraySet* instruction) OVERRIDE;
- void VisitMul(HMul* instruction) OVERRIDE;
- void VisitOr(HOr* instruction) OVERRIDE;
- void VisitShl(HShl* instruction) OVERRIDE;
- void VisitShr(HShr* instruction) OVERRIDE;
- void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE;
- void VisitUShr(HUShr* instruction) OVERRIDE;
-
- OptimizingCompilerStats* stats_;
-};
-
-
class InstructionSimplifierArm : public HOptimization {
public:
InstructionSimplifierArm(HGraph* graph, OptimizingCompilerStats* stats)
@@ -82,10 +30,7 @@
static constexpr const char* kInstructionSimplifierArmPassName = "instruction_simplifier_arm";
- void Run() OVERRIDE {
- InstructionSimplifierArmVisitor visitor(graph_, stats_);
- visitor.VisitReversePostOrder();
- }
+ void Run() OVERRIDE;
};
} // namespace arm
diff --git a/compiler/optimizing/instruction_simplifier_arm64.cc b/compiler/optimizing/instruction_simplifier_arm64.cc
index 7c9bfb1..c639953 100644
--- a/compiler/optimizing/instruction_simplifier_arm64.cc
+++ b/compiler/optimizing/instruction_simplifier_arm64.cc
@@ -30,6 +30,63 @@
using helpers::ShifterOperandSupportsExtension;
+class InstructionSimplifierArm64Visitor : public HGraphVisitor {
+ public:
+ InstructionSimplifierArm64Visitor(HGraph* graph, OptimizingCompilerStats* stats)
+ : HGraphVisitor(graph), stats_(stats) {}
+
+ private:
+ void RecordSimplification() {
+ if (stats_ != nullptr) {
+ stats_->RecordStat(kInstructionSimplificationsArch);
+ }
+ }
+
+ bool TryMergeIntoUsersShifterOperand(HInstruction* instruction);
+ bool TryMergeIntoShifterOperand(HInstruction* use,
+ HInstruction* bitfield_op,
+ bool do_merge);
+ bool CanMergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op) {
+ return TryMergeIntoShifterOperand(use, bitfield_op, /* do_merge */ false);
+ }
+ bool MergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op) {
+ DCHECK(CanMergeIntoShifterOperand(use, bitfield_op));
+ return TryMergeIntoShifterOperand(use, bitfield_op, /* do_merge */ true);
+ }
+
+ /**
+ * This simplifier uses a special-purpose BB visitor.
+ * (1) No need to visit Phi nodes.
+ * (2) Since statements can be removed in a "forward" fashion,
+ * the visitor should test if each statement is still there.
+ */
+ void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
+ // TODO: fragile iteration, provide more robust iterators?
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
+ HInstruction* instruction = it.Current();
+ if (instruction->IsInBlock()) {
+ instruction->Accept(this);
+ }
+ }
+ }
+
+ // HInstruction visitors, sorted alphabetically.
+ void VisitAnd(HAnd* instruction) OVERRIDE;
+ void VisitArrayGet(HArrayGet* instruction) OVERRIDE;
+ void VisitArraySet(HArraySet* instruction) OVERRIDE;
+ void VisitMul(HMul* instruction) OVERRIDE;
+ void VisitOr(HOr* instruction) OVERRIDE;
+ void VisitShl(HShl* instruction) OVERRIDE;
+ void VisitShr(HShr* instruction) OVERRIDE;
+ void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE;
+ void VisitUShr(HUShr* instruction) OVERRIDE;
+ void VisitXor(HXor* instruction) OVERRIDE;
+ void VisitVecLoad(HVecLoad* instruction) OVERRIDE;
+ void VisitVecStore(HVecStore* instruction) OVERRIDE;
+
+ OptimizingCompilerStats* stats_;
+};
+
bool InstructionSimplifierArm64Visitor::TryMergeIntoShifterOperand(HInstruction* use,
HInstruction* bitfield_op,
bool do_merge) {
@@ -38,8 +95,8 @@
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 +207,7 @@
}
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 +242,15 @@
}
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);
}
}
@@ -223,5 +280,10 @@
}
}
+void InstructionSimplifierArm64::Run() {
+ InstructionSimplifierArm64Visitor visitor(graph_, stats_);
+ visitor.VisitReversePostOrder();
+}
+
} // namespace arm64
} // namespace art
diff --git a/compiler/optimizing/instruction_simplifier_arm64.h b/compiler/optimizing/instruction_simplifier_arm64.h
index 4f16fc3..d180a8d 100644
--- a/compiler/optimizing/instruction_simplifier_arm64.h
+++ b/compiler/optimizing/instruction_simplifier_arm64.h
@@ -23,64 +23,6 @@
namespace art {
namespace arm64 {
-class InstructionSimplifierArm64Visitor : public HGraphVisitor {
- public:
- InstructionSimplifierArm64Visitor(HGraph* graph, OptimizingCompilerStats* stats)
- : HGraphVisitor(graph), stats_(stats) {}
-
- private:
- void RecordSimplification() {
- if (stats_ != nullptr) {
- stats_->RecordStat(kInstructionSimplificationsArch);
- }
- }
-
- bool TryMergeIntoUsersShifterOperand(HInstruction* instruction);
- bool TryMergeIntoShifterOperand(HInstruction* use,
- HInstruction* bitfield_op,
- bool do_merge);
- bool CanMergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op) {
- return TryMergeIntoShifterOperand(use, bitfield_op, /* do_merge */ false);
- }
- bool MergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op) {
- DCHECK(CanMergeIntoShifterOperand(use, bitfield_op));
- return TryMergeIntoShifterOperand(use, bitfield_op, /* do_merge */ true);
- }
-
- /**
- * This simplifier uses a special-purpose BB visitor.
- * (1) No need to visit Phi nodes.
- * (2) Since statements can be removed in a "forward" fashion,
- * the visitor should test if each statement is still there.
- */
- void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
- // TODO: fragile iteration, provide more robust iterators?
- for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
- HInstruction* instruction = it.Current();
- if (instruction->IsInBlock()) {
- instruction->Accept(this);
- }
- }
- }
-
- // HInstruction visitors, sorted alphabetically.
- void VisitAnd(HAnd* instruction) OVERRIDE;
- void VisitArrayGet(HArrayGet* instruction) OVERRIDE;
- void VisitArraySet(HArraySet* instruction) OVERRIDE;
- void VisitMul(HMul* instruction) OVERRIDE;
- void VisitOr(HOr* instruction) OVERRIDE;
- void VisitShl(HShl* instruction) OVERRIDE;
- void VisitShr(HShr* instruction) OVERRIDE;
- void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE;
- void VisitUShr(HUShr* instruction) OVERRIDE;
- void VisitXor(HXor* instruction) OVERRIDE;
- void VisitVecLoad(HVecLoad* instruction) OVERRIDE;
- void VisitVecStore(HVecStore* instruction) OVERRIDE;
-
- OptimizingCompilerStats* stats_;
-};
-
-
class InstructionSimplifierArm64 : public HOptimization {
public:
InstructionSimplifierArm64(HGraph* graph, OptimizingCompilerStats* stats)
@@ -88,10 +30,7 @@
static constexpr const char* kInstructionSimplifierArm64PassName = "instruction_simplifier_arm64";
- void Run() OVERRIDE {
- InstructionSimplifierArm64Visitor visitor(graph_, stats_);
- visitor.VisitReversePostOrder();
- }
+ void Run() OVERRIDE;
};
} // namespace arm64
diff --git a/compiler/optimizing/instruction_simplifier_shared.cc b/compiler/optimizing/instruction_simplifier_shared.cc
index 7a759b9..73d866f 100644
--- a/compiler/optimizing/instruction_simplifier_shared.cc
+++ b/compiler/optimizing/instruction_simplifier_shared.cc
@@ -25,7 +25,7 @@
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 @@
} // 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 @@
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 @@
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 @@
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 31e2383..b016a87 100644
--- a/compiler/optimizing/instruction_simplifier_shared.h
+++ b/compiler/optimizing/instruction_simplifier_shared.h
@@ -26,10 +26,10 @@
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.cc b/compiler/optimizing/intrinsics.cc
index 11725f4..daec634 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -30,6 +30,16 @@
namespace art {
+// Check that intrinsic enum values fit within space set aside in ArtMethod modifier flags.
+#define CHECK_INTRINSICS_ENUM_VALUES(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
+ static_assert( \
+ static_cast<uint32_t>(Intrinsics::k ## Name) <= (kAccIntrinsicBits >> CTZ(kAccIntrinsicBits)), \
+ "Instrinsics enumeration space overflow: ");
+#include "intrinsics_list.h"
+ INTRINSICS_LIST(CHECK_INTRINSICS_ENUM_VALUES)
+#undef INTRINSICS_LIST
+#undef CHECK_INTRINSICS_ENUM_VALUES
+
// Function that returns whether an intrinsic is static/direct or virtual.
static inline InvokeType GetIntrinsicInvokeType(Intrinsics i) {
switch (i) {
@@ -109,6 +119,7 @@
// InvokeStaticOrDirect.
InvokeType intrinsic_type = GetIntrinsicInvokeType(intrinsic);
InvokeType invoke_type = invoke->GetInvokeType();
+
switch (intrinsic_type) {
case kStatic:
return (invoke_type == kStatic);
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 96efe7f..75a1ce7 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -76,16 +76,16 @@
#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 @@
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 @@
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 @@
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 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 @@
}
static void GenUnsafePut(HInvoke* invoke,
- Primitive::Type type,
+ DataType::Type type,
bool is_volatile,
bool is_ordered,
CodeGeneratorARM64* codegen) {
@@ -1066,7 +1066,7 @@
// 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 @@
}
}
- 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 @@
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 @@
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 @@
// 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 @@
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 @@
__ 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 @@
__ 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 @@
}
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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
__ 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 @@
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 @@
__ 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 @@
__ 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 @@
// 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 @@
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 @@
src_stop_addr = src_stop_addr.X();
GenSystemArrayCopyAddresses(masm,
- Primitive::kPrimChar,
+ DataType::Type::kUint16,
src,
src_pos,
dst,
@@ -2364,7 +2364,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 e2494f0..7ce576c 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -126,16 +126,16 @@
// 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 @@
// 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 @@
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 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 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 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 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 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 @@
}
static void GenUnsafeGet(HInvoke* invoke,
- Primitive::Type type,
+ DataType::Type type,
bool is_volatile,
CodeGeneratorARMVIXL* codegen) {
LocationSummary* locations = invoke->GetLocations();
@@ -975,7 +975,7 @@
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 @@
break;
}
- case Primitive::kPrimNot: {
+ case DataType::Type::kReference: {
vixl32::Register trg = RegisterFrom(trg_loc);
if (kEmitCompilerReadBarrier) {
if (kUseBakerReadBarrier) {
@@ -1011,7 +1011,7 @@
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 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 @@
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 @@
}
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 @@
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 @@
}
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 @@
__ 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 @@
} 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 @@
__ 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
}
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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
// 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 @@
}
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 @@
}
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 @@
__ 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 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 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 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 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 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 IntrinsicCodeGeneratorARMVIXL::VisitLongLowestOneBit(HInvoke* invoke) {
- GenLowestOneBit(invoke, Primitive::kPrimLong, codegen_);
+ GenLowestOneBit(invoke, DataType::Type::kInt64, codegen_);
}
void IntrinsicLocationsBuilderARMVIXL::VisitStringGetCharsNoCheck(HInvoke* invoke) {
@@ -3056,7 +3062,7 @@
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 @@
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 @@
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 fe5579c..8847256 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -61,16 +61,16 @@
#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 @@
} 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 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 @@
__ 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 @@
__ 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 IntrinsicCodeGeneratorMIPS::VisitIntegerReverseBytes(HInvoke* invoke) {
GenReverse(invoke->GetLocations(),
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
IsR2OrNewer(),
IsR6(),
/* reverseBits */ false,
@@ -421,7 +421,7 @@
void IntrinsicCodeGeneratorMIPS::VisitLongReverseBytes(HInvoke* invoke) {
GenReverse(invoke->GetLocations(),
- Primitive::kPrimLong,
+ DataType::Type::kInt64,
IsR2OrNewer(),
IsR6(),
/* reverseBits */ false,
@@ -435,7 +435,7 @@
void IntrinsicCodeGeneratorMIPS::VisitShortReverseBytes(HInvoke* invoke) {
GenReverse(invoke->GetLocations(),
- Primitive::kPrimShort,
+ DataType::Type::kInt16,
IsR2OrNewer(),
IsR6(),
/* reverseBits */ false,
@@ -584,7 +584,7 @@
void IntrinsicCodeGeneratorMIPS::VisitIntegerReverse(HInvoke* invoke) {
GenReverse(invoke->GetLocations(),
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
IsR2OrNewer(),
IsR6(),
/* reverseBits */ true,
@@ -598,7 +598,7 @@
void IntrinsicCodeGeneratorMIPS::VisitLongReverse(HInvoke* invoke) {
GenReverse(invoke->GetLocations(),
- Primitive::kPrimLong,
+ DataType::Type::kInt64,
IsR2OrNewer(),
IsR6(),
/* reverseBits */ true,
@@ -614,7 +614,7 @@
}
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 @@
// 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 @@
}
__ 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 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 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 @@
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 @@
// 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 @@
__ 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 @@
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 @@
// 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ Bind(&select);
- if (type == Primitive::kPrimDouble) {
+ if (type == DataType::Type::kFloat64) {
__ MovtD(out, a);
__ MovfD(out, b);
} else {
@@ -1043,7 +1043,7 @@
void IntrinsicCodeGeneratorMIPS::VisitMathMinDoubleDouble(HInvoke* invoke) {
GenMinMaxFP(invoke->GetLocations(),
/* is_min */ true,
- Primitive::kPrimDouble,
+ DataType::Type::kFloat64,
IsR6(),
GetAssembler());
}
@@ -1056,7 +1056,7 @@
void IntrinsicCodeGeneratorMIPS::VisitMathMinFloatFloat(HInvoke* invoke) {
GenMinMaxFP(invoke->GetLocations(),
/* is_min */ true,
- Primitive::kPrimFloat,
+ DataType::Type::kFloat32,
IsR6(),
GetAssembler());
}
@@ -1069,7 +1069,7 @@
void IntrinsicCodeGeneratorMIPS::VisitMathMaxDoubleDouble(HInvoke* invoke) {
GenMinMaxFP(invoke->GetLocations(),
/* is_min */ false,
- Primitive::kPrimDouble,
+ DataType::Type::kFloat64,
IsR6(),
GetAssembler());
}
@@ -1082,7 +1082,7 @@
void IntrinsicCodeGeneratorMIPS::VisitMathMaxFloatFloat(HInvoke* invoke) {
GenMinMaxFP(invoke->GetLocations(),
/* is_min */ false,
- Primitive::kPrimFloat,
+ DataType::Type::kFloat32,
IsR6(),
GetAssembler());
}
@@ -1098,7 +1098,7 @@
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 @@
// 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 @@
__ 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 @@
}
}
} 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 @@
}
}
} 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 IntrinsicCodeGeneratorMIPS::VisitMathMinIntInt(HInvoke* invoke) {
GenMinMax(invoke->GetLocations(),
/* is_min */ true,
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
IsR6(),
GetAssembler());
}
@@ -1286,7 +1286,7 @@
void IntrinsicCodeGeneratorMIPS::VisitMathMinLongLong(HInvoke* invoke) {
GenMinMax(invoke->GetLocations(),
/* is_min */ true,
- Primitive::kPrimLong,
+ DataType::Type::kInt64,
IsR6(),
GetAssembler());
}
@@ -1299,7 +1299,7 @@
void IntrinsicCodeGeneratorMIPS::VisitMathMaxIntInt(HInvoke* invoke) {
GenMinMax(invoke->GetLocations(),
/* is_min */ false,
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
IsR6(),
GetAssembler());
}
@@ -1312,7 +1312,7 @@
void IntrinsicCodeGeneratorMIPS::VisitMathMaxLongLong(HInvoke* invoke) {
GenMinMax(invoke->GetLocations(),
/* is_min */ false,
- Primitive::kPrimLong,
+ DataType::Type::kInt64,
IsR6(),
GetAssembler());
}
@@ -1519,7 +1519,7 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
break;
}
- case Primitive::kPrimNot: {
+ case DataType::Type::kReference: {
Register trg = trg_loc.AsRegister<Register>();
if (kEmitCompilerReadBarrier) {
if (kUseBakerReadBarrier) {
@@ -1657,47 +1657,47 @@
// 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 @@
// 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 @@
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 @@
__ 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 IntrinsicCodeGeneratorMIPS::VisitUnsafePut(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(),
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
/* is_volatile */ false,
/* is_ordered */ false,
IsR6(),
@@ -1793,7 +1793,7 @@
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 IntrinsicCodeGeneratorMIPS::VisitUnsafePutVolatile(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(),
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
/* is_volatile */ true,
/* is_ordered */ false,
IsR6(),
@@ -1821,7 +1821,7 @@
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 IntrinsicCodeGeneratorMIPS::VisitUnsafePutObjectOrdered(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(),
- Primitive::kPrimNot,
+ DataType::Type::kReference,
/* is_volatile */ false,
/* is_ordered */ true,
IsR6(),
@@ -1849,7 +1849,7 @@
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 IntrinsicCodeGeneratorMIPS::VisitUnsafePutLong(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(),
- Primitive::kPrimLong,
+ DataType::Type::kInt64,
/* is_volatile */ false,
/* is_ordered */ false,
IsR6(),
@@ -1877,7 +1877,7 @@
void IntrinsicCodeGeneratorMIPS::VisitUnsafePutLongOrdered(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(),
- Primitive::kPrimLong,
+ DataType::Type::kInt64,
/* is_volatile */ false,
/* is_ordered */ true,
IsR6(),
@@ -1908,7 +1908,7 @@
// 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 @@
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 @@
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 @@
__ 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 @@
// 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 @@
__ 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 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 @@
// 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 @@
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 @@
__ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
__ 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 @@
__ 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 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 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 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 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 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 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 @@
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 @@
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 @@
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 @@
// 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 @@
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 80448f1..d0234d8 100644
--- a/compiler/optimizing/intrinsics_mips64.cc
+++ b/compiler/optimizing/intrinsics_mips64.cc
@@ -49,16 +49,16 @@
#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 @@
} 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 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 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 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 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 @@
}
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 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 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 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 @@
// 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 @@
__ 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 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 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 @@
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 @@
// 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 @@
__ 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 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 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 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 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 @@
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 @@
// 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 @@
}
// 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 @@
}
// 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 @@
}
// 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 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 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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
__ 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 @@
}
break;
- case Primitive::kPrimLong:
+ case DataType::Type::kInt64:
__ Sd(value, TMP, 0);
break;
@@ -1333,7 +1333,7 @@
__ 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 IntrinsicCodeGeneratorMIPS64::VisitUnsafePut(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(),
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
/* is_volatile */ false,
/* is_ordered */ false,
codegen_);
@@ -1359,7 +1359,7 @@
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 IntrinsicCodeGeneratorMIPS64::VisitUnsafePutVolatile(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(),
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
/* is_volatile */ true,
/* is_ordered */ false,
codegen_);
@@ -1385,7 +1385,7 @@
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 IntrinsicCodeGeneratorMIPS64::VisitUnsafePutObjectOrdered(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(),
- Primitive::kPrimNot,
+ DataType::Type::kReference,
/* is_volatile */ false,
/* is_ordered */ true,
codegen_);
@@ -1411,7 +1411,7 @@
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 IntrinsicCodeGeneratorMIPS64::VisitUnsafePutLong(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(),
- Primitive::kPrimLong,
+ DataType::Type::kInt64,
/* is_volatile */ false,
/* is_ordered */ false,
codegen_);
@@ -1437,7 +1437,7 @@
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 IntrinsicCodeGeneratorMIPS64::VisitUnsafePutLongVolatile(HInvoke* invoke) {
GenUnsafePut(invoke->GetLocations(),
- Primitive::kPrimLong,
+ DataType::Type::kInt64,
/* is_volatile */ true,
/* is_ordered */ false,
codegen_);
@@ -1480,7 +1480,7 @@
// 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 @@
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 @@
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 @@
__ 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 @@
// 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 @@
__ 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 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 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 @@
// 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 @@
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 @@
__ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
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 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 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 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 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 @@
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 @@
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 @@
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 abd9014..a591622 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -97,7 +97,7 @@
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 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 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 IntrinsicCodeGeneratorX86::VisitShortReverseBytes(HInvoke* invoke) {
- GenReverseBytes(invoke->GetLocations(), Primitive::kPrimShort, GetAssembler());
+ GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt16, GetAssembler());
}
@@ -1307,7 +1307,7 @@
// 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 @@
__ 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 @@
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 @@
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 @@
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 @@
__ 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 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 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 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 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
}
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 @@
}
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 @@
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 @@
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 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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
__ 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 @@
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 @@
}
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 @@
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 @@
// 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 @@
}
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 @@
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 @@
// 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 @@
// `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 @@
}
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 @@
// 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 @@
// 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 @@
// 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 @@
__ 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 7798c0d..a2545ee 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -90,7 +90,7 @@
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 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 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 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 IntrinsicCodeGeneratorX86_64::VisitShortReverseBytes(HInvoke* invoke) {
- GenReverseBytes(invoke->GetLocations(), Primitive::kPrimShort, GetAssembler());
+ GenReverseBytes(invoke->GetLocations(), DataType::Type::kInt16, GetAssembler());
}
@@ -1084,7 +1084,7 @@
// 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 @@
// 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 @@
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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
}
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 @@
__ 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 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 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 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 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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 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 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 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 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 @@
}
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 @@
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 @@
break;
}
- case Primitive::kPrimLong:
+ case DataType::Type::kInt64:
__ movq(output, Address(base, offset, ScaleFactor::TIMES_1, 0));
break;
@@ -2234,27 +2234,27 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
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 @@
__ 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 @@
}
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 @@
// 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 8967d7c..0617e60 100644
--- a/compiler/optimizing/licm_test.cc
+++ b/compiler/optimizing/licm_test.cc
@@ -78,7 +78,7 @@
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 @@
// 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 @@
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 @@
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 @@
HInstruction* set_field = new (&allocator_) HInstanceFieldSet(parameter_,
get_field,
nullptr,
- Primitive::kPrimLong,
+ DataType::Type::kInt64,
MemberOffset(10),
false,
kUnknownFieldIndex,
@@ -184,10 +184,10 @@
// 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 @@
// 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 02bc254..d46b904 100644
--- a/compiler/optimizing/load_store_analysis.h
+++ b/compiler/optimizing/load_store_analysis.h
@@ -369,7 +369,7 @@
}
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 81344b5..0df2f27 100644
--- a/compiler/optimizing/load_store_analysis_test.cc
+++ b/compiler/optimizing/load_store_analysis_test.cc
@@ -49,16 +49,17 @@
// 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 @@
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 @@
0);
HInstanceFieldGet* get_field10 = new (&allocator_) HInstanceFieldGet(object,
nullptr,
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
MemberOffset(10),
false,
kUnknownFieldIndex,
@@ -143,7 +144,7 @@
0);
HInstanceFieldGet* get_field20 = new (&allocator_) HInstanceFieldGet(object,
nullptr,
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
MemberOffset(20),
false,
kUnknownFieldIndex,
@@ -191,26 +192,28 @@
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 @@
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 @@
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 8a9acf1..bd14f2b 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -271,21 +271,21 @@
}
}
- 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 @@
// 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 baa0453..fec64e2 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -71,27 +71,31 @@
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);
+
+// Detect a sign extension in instruction from the given type.
+// Returns the promoted operand on success.
static bool IsSignExtensionAndGet(HInstruction* instruction,
- Primitive::Type type,
+ DataType::Type type,
/*out*/ HInstruction** operand) {
// 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).
+ // (the fact that Uint16 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;
}
@@ -100,46 +104,62 @@
return false;
}
}
- // An implicit widening conversion of a signed integer to an integral type sign-extends
- // the two's-complement representation of the integer value to fill the wider format.
- if (instruction->GetType() == type && (instruction->IsArrayGet() ||
- instruction->IsStaticFieldGet() ||
- instruction->IsInstanceFieldGet())) {
+ // An implicit widening conversion of any signed expression sign-extends.
+ if (instruction->GetType() == type) {
switch (type) {
- case Primitive::kPrimByte:
- case Primitive::kPrimShort:
+ case DataType::Type::kInt8:
+ case DataType::Type::kInt16:
*operand = instruction;
return true;
default:
return false;
}
}
- // TODO: perhaps explicit conversions later too?
- // (this may return something different from instruction)
+ // An explicit widening conversion of a signed expression sign-extends.
+ if (instruction->IsTypeConversion()) {
+ HInstruction* conv = instruction->InputAt(0);
+ DataType::Type from = conv->GetType();
+ switch (instruction->GetType()) {
+ case DataType::Type::kInt32:
+ case DataType::Type::kInt64:
+ if (type == from && (from == DataType::Type::kInt8 ||
+ from == DataType::Type::kInt16 ||
+ from == DataType::Type::kInt32)) {
+ *operand = conv;
+ return true;
+ }
+ return false;
+ case DataType::Type::kInt16:
+ return type == DataType::Type::kUint16 &&
+ from == DataType::Type::kUint16 &&
+ IsZeroExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand);
+ default:
+ return false;
+ }
+ }
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.
+// Returns the promoted operand on success.
static bool IsZeroExtensionAndGet(HInstruction* instruction,
- Primitive::Type type,
+ DataType::Type type,
/*out*/ HInstruction** operand) {
// 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 Int8/Int16 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;
}
@@ -148,18 +168,18 @@
return false;
}
}
- // An implicit widening conversion of a char to an integral type zero-extends
- // the representation of the char value to fill the wider format.
- if (instruction->GetType() == type && (instruction->IsArrayGet() ||
- instruction->IsStaticFieldGet() ||
- instruction->IsInstanceFieldGet())) {
- if (type == Primitive::kPrimChar) {
+ // An implicit widening conversion of any unsigned expression zero-extends.
+ if (instruction->GetType() == type) {
+ if (type == DataType::Type::kUint16) {
*operand = instruction;
return true;
}
}
// A sign (or zero) extension followed by an explicit removal of just the
// higher sign bits is equivalent to a zero extension of the underlying operand.
+ //
+ // TODO: move this into simplifier and use new type system instead.
+ //
if (instruction->IsAnd()) {
int64_t mask = 0;
HInstruction* a = instruction->InputAt(0);
@@ -170,14 +190,35 @@
(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();
default: return false;
}
}
}
- // TODO: perhaps explicit conversions later too?
+ // An explicit widening conversion of an unsigned expression zero-extends.
+ if (instruction->IsTypeConversion()) {
+ HInstruction* conv = instruction->InputAt(0);
+ DataType::Type from = conv->GetType();
+ switch (instruction->GetType()) {
+ case DataType::Type::kInt32:
+ case DataType::Type::kInt64:
+ if (type == from && from == DataType::Type::kUint16) {
+ *operand = conv;
+ return true;
+ }
+ return false;
+ case DataType::Type::kUint16:
+ return type == DataType::Type::kInt16 &&
+ from == DataType::Type::kInt16 &&
+ IsSignExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand);
+ default:
+ return false;
+ }
+ }
return false;
}
@@ -185,7 +226,7 @@
// 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 +242,7 @@
// 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 +255,55 @@
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,
@@ -259,17 +349,33 @@
return false;
}
+// Detect a + c for constant c.
+static bool IsAddConst(HInstruction* instruction,
+ /*out*/ HInstruction** a,
+ /*out*/ int64_t* c) {
+ if (instruction->IsAdd()) {
+ if (IsInt64AndGet(instruction->InputAt(0), c)) {
+ *a = instruction->InputAt(1);
+ return true;
+ } else if (IsInt64AndGet(instruction->InputAt(1), c)) {
+ *a = instruction->InputAt(0);
+ return true;
+ }
+ }
+ return false;
+}
+
// 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 +386,8 @@
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 +395,9 @@
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 +827,6 @@
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 +845,11 @@
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 +878,10 @@
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 +890,8 @@
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 +905,7 @@
graph_->TransformLoopForVectorization(vector_header_, vector_body_, exit),
vector_index_,
ptc,
- graph_->GetIntConstant(1),
+ graph_->GetConstant(induc_type, 1),
kNoUnrollingFactor);
}
@@ -806,7 +918,7 @@
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 +932,20 @@
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 +971,7 @@
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 +1035,7 @@
// (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 +1059,11 @@
// (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 +1086,7 @@
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 +1147,23 @@
// 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);
+ DataType::Type ctype = size_from == size_vec ? from : type;
+ // 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, ctype, restrictions))) {
if (generate_code) {
if (vector_mode_ == kVector) {
vector_map_->Put(instruction, vector_map_->Get(opa)); // operand pass-through
@@ -1046,7 +1173,7 @@
}
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 +1215,7 @@
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 +1248,7 @@
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 +1308,8 @@
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 +1331,7 @@
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 +1339,15 @@
// 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 +1358,24 @@
// 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 +1386,25 @@
// 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 +1415,24 @@
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 +1443,24 @@
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 +1485,7 @@
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 +1499,16 @@
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 +1520,7 @@
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 +1533,7 @@
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 +1601,15 @@
// 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 +1625,20 @@
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 +1657,21 @@
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 +1681,47 @@
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 +1802,8 @@
//
// 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 +1812,7 @@
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 +1847,8 @@
}
// 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 +1877,100 @@
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->GetType() == reduction_type) {
+ int64_t c = 0;
+ if (x->IsSub()) {
+ a = x->InputAt(0);
+ b = x->InputAt(1);
+ } else if (IsAddConst(x, /*out*/ &a, /*out*/ &c)) {
+ b = graph_->GetConstant(reduction_type, -c); // hidden SUB!
+ }
+ }
+ }
+ 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).
+ // We inspect the operands carefully to pick the most suited type.
+ HInstruction* r = a;
+ HInstruction* s = b;
+ bool is_unsigned = false;
+ DataType::Type sub_type = a->GetType();
+ if (DataType::Size(b->GetType()) < DataType::Size(sub_type)) {
+ sub_type = b->GetType();
+ }
+ if (a->IsTypeConversion() &&
+ DataType::Size(a->InputAt(0)->GetType()) < DataType::Size(sub_type)) {
+ sub_type = a->InputAt(0)->GetType();
+ }
+ if (b->IsTypeConversion() &&
+ DataType::Size(b->InputAt(0)->GetType()) < DataType::Size(sub_type)) {
+ sub_type = b->InputAt(0)->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 f347518..6e6e387 100644
--- a/compiler/optimizing/loop_optimization.h
+++ b/compiler/optimizing/loop_optimization.h
@@ -75,6 +75,7 @@
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 @@
* 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 @@
}
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 @@
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 1c5603d..95718ae 100644
--- a/compiler/optimizing/loop_optimization_test.cc
+++ b/compiler/optimizing/loop_optimization_test.cc
@@ -51,7 +51,7 @@
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 @@
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 9cff6b0..41ea998 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -564,7 +564,7 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
} 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 @@
} 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 @@
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 @@
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 @@
} 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 @@
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 @@
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 @@
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 @@
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 a6d0da1..c49cee3 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 @@
// 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 @@
M(VecUShr, VecBinaryOperation) \
M(VecSetScalars, VecOperation) \
M(VecMultiplyAccumulate, VecOperation) \
+ M(VecSADAccumulate, VecOperation) \
M(VecLoad, VecMemoryOperation) \
M(VecStore, VecMemoryOperation) \
@@ -1566,7 +1567,7 @@
* 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 @@
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 @@
((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 @@
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 @@
// 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 @@
}
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
: 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 @@
// 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 @@
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 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 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 @@
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 @@
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 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 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 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 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 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 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 @@
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 @@
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 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 @@
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 @@
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 @@
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 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 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 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 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 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 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 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 @@
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 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 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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
&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 @@
&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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 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 @@
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 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 @@
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 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 @@
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 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 @@
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 @@
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 @@
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 @@
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 8e439d9..80e652e 100644
--- a/compiler/optimizing/nodes_mips.h
+++ b/compiler/optimizing/nodes_mips.h
@@ -24,7 +24,7 @@
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 f6d33f0..f982523 100644
--- a/compiler/optimizing/nodes_shared.cc
+++ b/compiler/optimizing/nodes_shared.cc
@@ -42,20 +42,20 @@
*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 075a816..14cbf85 100644
--- a/compiler/optimizing/nodes_shared.h
+++ b/compiler/optimizing/nodes_shared.h
@@ -26,7 +26,7 @@
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 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 @@
// 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 @@
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 @@
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 f3a78a0..ada6177 100644
--- a/compiler/optimizing/nodes_test.cc
+++ b/compiler/optimizing/nodes_test.cc
@@ -36,7 +36,7 @@
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 @@
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 @@
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 @@
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 886d75e..0aac260 100644
--- a/compiler/optimizing/nodes_vector.h
+++ b/compiler/optimizing/nodes_vector.h
@@ -65,10 +65,10 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 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 @@
};
// 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 @@
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 @@
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 @@
}
// Yields a single component in the vector.
- Primitive::Type GetType() const OVERRIDE {
+ DataType::Type GetType() const OVERRIDE {
return GetPackedType();
}
@@ -317,7 +317,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
};
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
//
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 5a56a2c..3acdb20 100644
--- a/compiler/optimizing/nodes_vector_test.cc
+++ b/compiler/optimizing/nodes_vector_test.cc
@@ -45,7 +45,7 @@
parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(),
dex::TypeIndex(0),
0,
- Primitive::kPrimInt);
+ DataType::Type::kInt32);
entry_block_->AddInstruction(parameter_);
}
@@ -119,15 +119,15 @@
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 @@
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, 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, 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, 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, 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, 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, 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 75893c3..22e92ea 100644
--- a/compiler/optimizing/nodes_x86.h
+++ b/compiler/optimizing/nodes_x86.h
@@ -24,7 +24,7 @@
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 @@
// 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 8dd2762..1218586 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"
@@ -668,22 +669,42 @@
#endif
#ifdef ART_ENABLE_CODEGEN_mips
case kMips: {
+ SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph);
+ GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects, "GVN$after_arch");
mips::PcRelativeFixups* pc_relative_fixups =
new (arena) mips::PcRelativeFixups(graph, codegen, stats);
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: {
+ SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph);
+ GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects, "GVN$after_arch");
x86::PcRelativeFixups* pc_relative_fixups =
new (arena) x86::PcRelativeFixups(graph, codegen, stats);
x86::X86MemoryOperandGeneration* memory_gen =
new (arena) x86::X86MemoryOperandGeneration(graph, codegen, stats);
HOptimization* x86_optimizations[] = {
+ side_effects,
+ gvn,
pc_relative_fixups,
memory_gen
};
@@ -693,9 +714,13 @@
#endif
#ifdef ART_ENABLE_CODEGEN_x86_64
case kX86_64: {
+ SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph);
+ GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects, "GVN$after_arch");
x86::X86MemoryOperandGeneration* memory_gen =
new (arena) x86::X86MemoryOperandGeneration(graph, codegen, stats);
HOptimization* x86_64_optimizations[] = {
+ side_effects,
+ gvn,
memory_gen
};
RunOptimizations(x86_64_optimizations, arraysize(x86_64_optimizations), pass_observer);
@@ -833,13 +858,13 @@
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 +876,7 @@
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 +901,7 @@
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 +1014,6 @@
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 08493fa..33f1a4a 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -50,7 +50,8 @@
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 @@
// 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 be470cc..2036b4a 100644
--- a/compiler/optimizing/parallel_move_resolver.cc
+++ b/compiler/optimizing/parallel_move_resolver.cc
@@ -457,7 +457,7 @@
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::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 4278861..e6e069f 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 @@
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 50620f0..cb87cab 100644
--- a/compiler/optimizing/parallel_move_test.cc
+++ b/compiler/optimizing/parallel_move_test.cc
@@ -158,7 +158,7 @@
moves->AddMove(
Location::RegisterLocation(operands[i][0]),
Location::RegisterLocation(operands[i][1]),
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
nullptr);
}
return moves;
@@ -264,12 +264,12 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 9877e10..a114e78 100644
--- a/compiler/optimizing/pc_relative_fixups_x86.cc
+++ b/compiler/optimizing/pc_relative_fixups_x86.cc
@@ -63,7 +63,7 @@
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 @@
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 @@
}
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 @@
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 2c856cd..b52de36 100644
--- a/compiler/optimizing/prepare_for_register_allocation.cc
+++ b/compiler/optimizing/prepare_for_register_allocation.cc
@@ -77,7 +77,7 @@
// 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 93613a5..f5064c3 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -133,7 +133,7 @@
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 @@
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::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::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::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::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::VisitPhi(HPhi* phi) {
- if (phi->IsDead() || phi->GetType() != Primitive::kPrimNot) {
+ if (phi->IsDead() || phi->GetType() != DataType::Type::kReference) {
return;
}
@@ -813,7 +813,7 @@
}
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 @@
}
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::VisitArrayGet(HArrayGet* instr) {
- if (instr->GetType() != Primitive::kPrimNot) {
+ if (instr->GetType() != DataType::Type::kReference) {
return;
}
@@ -989,7 +989,7 @@
}
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 @@
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 ce3a496..f0057c3 100644
--- a/compiler/optimizing/register_allocation_resolver.cc
+++ b/compiler/optimizing/register_allocation_resolver.cc
@@ -100,24 +100,24 @@
// [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 @@
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 @@
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 @@
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 d48b1a0..4a148e0 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 @@
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 7e1fff8..4375d68 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 5e22772..4ff7315 100644
--- a/compiler/optimizing/register_allocator_graph_color.cc
+++ b/compiler/optimizing/register_allocator_graph_color.cc
@@ -540,7 +540,7 @@
};
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
// 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 548687f..3f6d674 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 ab8d540..2012cd5 100644
--- a/compiler/optimizing/register_allocator_linear_scan.cc
+++ b/compiler/optimizing/register_allocator_linear_scan.cc
@@ -83,8 +83,8 @@
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 @@
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 @@
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 @@
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 @@
}
}
- 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 @@
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 b3834f4..9c650a4 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 bcdd7f9..59987e2 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -461,15 +461,15 @@
// 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 @@
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 @@
HInstruction* test = new (allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimBoolean,
+ DataType::Type::kBool,
MemberOffset(22),
false,
kUnknownFieldIndex,
@@ -528,11 +528,11 @@
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 @@
0);
*input2 = new (allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -658,7 +658,7 @@
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 @@
*field = new (allocator) HInstanceFieldGet(parameter,
nullptr,
- Primitive::kPrimInt,
+ DataType::Type::kInt32,
MemberOffset(42),
false,
kUnknownFieldIndex,
@@ -742,7 +742,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 38cd51b..5212e86 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 @@
}
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 66756a5..110db47 100644
--- a/compiler/optimizing/scheduler_arm.cc
+++ b/compiler/optimizing/scheduler_arm.cc
@@ -31,15 +31,15 @@
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::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::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::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::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::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::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 @@
// 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 @@
}
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::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::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::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 @@
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::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::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::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::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::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 @@
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 @@
break;
}
- case Primitive::kPrimNot: {
+ case DataType::Type::kReference: {
if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
last_visited_latency_ = kArmLoadWithBakerReadBarrierLatency;
} else {
@@ -681,7 +681,7 @@
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
if (index->IsConstant()) {
last_visited_latency_ = kArmMemoryLoadLatency;
} else {
@@ -691,7 +691,7 @@
break;
}
- case Primitive::kPrimFloat: {
+ case DataType::Type::kFloat32: {
if (index->IsConstant()) {
last_visited_latency_ = kArmMemoryLoadLatency;
} else {
@@ -701,7 +701,7 @@
break;
}
- case Primitive::kPrimDouble: {
+ case DataType::Type::kFloat64: {
if (index->IsConstant()) {
last_visited_latency_ = kArmMemoryLoadLatency;
} else {
@@ -727,16 +727,16 @@
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 @@
break;
}
- case Primitive::kPrimNot: {
+ case DataType::Type::kReference: {
if (instruction->InputAt(2)->IsNullConstant()) {
if (index->IsConstant()) {
last_visited_latency_ = kArmMemoryStoreLatency;
@@ -765,7 +765,7 @@
break;
}
- case Primitive::kPrimLong: {
+ case DataType::Type::kInt64: {
if (index->IsConstant()) {
last_visited_latency_ = kArmMemoryLoadLatency;
} else {
@@ -775,7 +775,7 @@
break;
}
- case Primitive::kPrimFloat: {
+ case DataType::Type::kFloat32: {
if (index->IsConstant()) {
last_visited_latency_ = kArmMemoryLoadLatency;
} else {
@@ -785,7 +785,7 @@
break;
}
- case Primitive::kPrimDouble: {
+ case DataType::Type::kFloat64: {
if (index->IsConstant()) {
last_visited_latency_ = kArmMemoryLoadLatency;
} else {
@@ -823,9 +823,9 @@
}
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 @@
}
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::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 @@
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 @@
}
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 @@
}
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 @@
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 @@
}
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 @@
}
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::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 @@
}
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 @@
}
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 @@
}
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 1d9d28a..7bcf4e7 100644
--- a/compiler/optimizing/scheduler_arm64.cc
+++ b/compiler/optimizing/scheduler_arm64.cc
@@ -24,7 +24,7 @@
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::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::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::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::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::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::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::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::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::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::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 cdb6666..0e6e0c5 100644
--- a/compiler/optimizing/scheduler_test.cc
+++ b/compiler/optimizing/scheduler_test.cc
@@ -103,18 +103,20 @@
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 @@
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 e220d32..827b591 100644
--- a/compiler/optimizing/select_generator.cc
+++ b/compiler/optimizing/select_generator.cc
@@ -140,11 +140,11 @@
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 b01bc1c..ac5eb15 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, 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, 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, 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 @@
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 50ab11b..77b7a22 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
}
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* 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 @@
}
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 @@
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 @@
}
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 @@
} 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 @@
* 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 @@
}
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 @@
// 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 @@
}
}
-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 @@
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 978f113..1819ee5 100644
--- a/compiler/optimizing/ssa_builder.h
+++ b/compiler/optimizing/ssa_builder.h
@@ -64,20 +64,20 @@
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 @@
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 185303b..f1f1be2 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -474,11 +474,13 @@
// 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 a668157..ec4ab31 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -262,16 +262,16 @@
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 @@
return parent_->env_uses_;
}
- Primitive::Type GetType() const {
+ DataType::Type GetType() const {
return type_;
}
@@ -783,7 +783,7 @@
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 @@
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 @@
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 @@
// 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 b46060a..e89bf6d 100644
--- a/compiler/optimizing/ssa_liveness_analysis_test.cc
+++ b/compiler/optimizing/ssa_liveness_analysis_test.cc
@@ -70,7 +70,7 @@
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, 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 @@
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, 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 @@
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 f69f417..ac998db 100644
--- a/compiler/optimizing/ssa_test.cc
+++ b/compiler/optimizing/ssa_test.cc
@@ -89,7 +89,7 @@
// 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 4e25683..0271850 100644
--- a/compiler/optimizing/x86_memory_gen.cc
+++ b/compiler/optimizing/x86_memory_gen.cc
@@ -41,7 +41,7 @@
}
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 12954a4..227954e 100644
--- a/compiler/utils/assembler_test.h
+++ b/compiler/utils/assembler_test.h
@@ -114,6 +114,24 @@
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 @@
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 @@
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 @@
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/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index e51b622..4dbe71b 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -126,15 +126,8 @@
int cmd_result = system(cmd);
ASSERT_EQ(cmd_result, 0) << strerror(errno);
- // Remove the $d symbols to prevent the disassembler dumping the instructions
- // as .word
- snprintf(cmd, sizeof(cmd), "%sobjcopy -N '$d' %s.o %s.oo", toolsdir.c_str(), filename, filename);
- int cmd_result2 = system(cmd);
- ASSERT_EQ(cmd_result2, 0) << strerror(errno);
-
// Disassemble.
-
- snprintf(cmd, sizeof(cmd), "%sobjdump -d %s.oo | grep '^ *[0-9a-f][0-9a-f]*:'",
+ snprintf(cmd, sizeof(cmd), "%sobjdump -D -M force-thumb --section=.text %s.o | grep '^ *[0-9a-f][0-9a-f]*:'",
toolsdir.c_str(), filename);
if (kPrintResults) {
// Print the results only, don't check. This is used to generate new output for inserting
@@ -169,9 +162,6 @@
char buf[FILENAME_MAX];
snprintf(buf, sizeof(buf), "%s.o", filename);
unlink(buf);
-
- snprintf(buf, sizeof(buf), "%s.oo", filename);
- unlink(buf);
#endif // ART_TARGET_ANDROID
}
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index 3162a32..9fcede5 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 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 c28ed3b..cccde37 100644
--- a/compiler/utils/x86/assembler_x86_test.cc
+++ b/compiler/utils/x86/assembler_x86_test.cc
@@ -148,21 +148,14 @@
};
//
-// 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, 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 @@
// 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, 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, 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, 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, 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 3bff67d..51f61ca 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -36,6 +36,34 @@
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..1130444 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -80,6 +80,21 @@
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 @@
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 3e6110d..aff8871 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 @@
}
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 @@
}
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 @@
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 @@
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, 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, 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 @@
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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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");
+ DriverStr(RepeatAR(&x86_64::X86_64Assembler::LockCmpxchgq,
+ "lock cmpxchg %{reg}, {mem}"), "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, MovqStore) {
+ DriverStr(RepeatAR(&x86_64::X86_64Assembler::movq, "movq %{reg}, {mem}"), "movq_s");
}
-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");
+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, MovlAddrImm) {
+ DriverStr(RepeatAI(&x86_64::X86_64Assembler::movl,
+ /*imm_bytes*/ 4U, "movl ${imm}, {mem}"), "movl");
+}
+
+TEST_F(AssemblerX86_64Test, MovwAddrImm) {
+ DriverStr(RepeatAI(&x86_64::X86_64Assembler::movw,
+ /*imm_bytes*/ 2U, "movw ${imm}, {mem}"), "movw");
+}
+
+TEST_F(AssemblerX86_64Test, MovbAddrImm) {
+ DriverStr(RepeatAI(&x86_64::X86_64Assembler::movb,
+ /*imm_bytes*/ 1U, "movb ${imm}, {mem}"), "movb");
}
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";
-
- DriverStr(expected, "movntl");
+ DriverStr(RepeatAr(&x86_64::X86_64Assembler::movntl, "movntil %{reg}, {mem}"), "movntl");
}
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";
-
- DriverStr(expected, "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, 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 @@
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 @@
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, 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, 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, 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 @@
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 @@
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, 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, 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, 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, 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, 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, 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, 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 @@
"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 @@
"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, 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 @@
// 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 @@
// 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 09bbbda..0405fe1 100644
--- a/dalvikvm/Android.bp
+++ b/dalvikvm/Android.bp
@@ -30,15 +30,8 @@
],
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 bdb8ff1..c9125df 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -18,7 +18,6 @@
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 @@
"linker/oat_writer.cc",
],
target: {
- host: {
- // For compiler driver TLS.
- host_ldlibs: ["-lpthread"],
- },
android: {
// For atrace.
shared_libs: ["libcutils"],
@@ -70,7 +65,7 @@
defaults: ["libart-dex2oat-defaults"],
shared_libs: [
"libart-compiler",
- "libart"
+ "libart",
],
}
@@ -82,7 +77,7 @@
],
shared_libs: [
"libartd-compiler",
- "libartd"
+ "libartd",
],
}
@@ -126,7 +121,7 @@
],
static_libs: [
"libart-dex2oat",
- ]
+ ],
}
art_cc_binary {
@@ -145,7 +140,7 @@
],
static_libs: [
"libartd-dex2oat",
- ]
+ ],
}
art_cc_binary {
@@ -231,5 +226,5 @@
],
static_libs: [
"libartd-dex2oat",
- ]
+ ],
}
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 21d3895..7b46531 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -712,6 +712,10 @@
}
}
+ 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 @@
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 @@
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 @@
}
} 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 @@
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 @@
} else {
if (vdex_file->SetLength(0) != 0) {
PLOG(ERROR) << "Truncating vdex file " << vdex_location << " failed.";
+ vdex_file->Erase();
return false;
}
}
@@ -2305,6 +2312,10 @@
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 @@
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 @@
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/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index 7ddf1c1..1f644c1 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -311,7 +311,11 @@
{
ProfileCompilationInfo profile;
VisitLibcoreDexes([&profile](MethodReference ref) {
- EXPECT_TRUE(profile.AddMethodIndex(ProfileCompilationInfo::MethodHotness::kFlagHot, ref));
+ uint32_t flags = ProfileCompilationInfo::MethodHotness::kFlagHot |
+ ProfileCompilationInfo::MethodHotness::kFlagStartup;
+ EXPECT_TRUE(profile.AddMethodIndex(
+ static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
+ ref));
}, [&profile](TypeReference ref) {
EXPECT_TRUE(profile.AddClassForDex(ref));
}, kMethodFrequency, kTypeFrequency);
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index 71f1fa6..492c76b 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -302,8 +302,8 @@
}
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 1b2d43e..ca9c5f1 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 51c2a03..dfbe31a 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 @@
// 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 @@
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(FATAL) << "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)) {
+ }
+
+ 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();
- 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()));
- }
- }
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;
+ size_t debug_info_idx = OrderedMethodData::kDebugInfoIdxInvalid;
- 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();
+ {
+ 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);
- // 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;
+ // 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;
}
+ }
+
+ MethodReference method_ref(dex_file_, it.GetMemberIndex());
+
+ // 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);
}
}
+ } 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);
+ });
+ }
- // 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);
- }
+ 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 (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());
- }
+ 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 @@
};
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 @@
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 @@
}
}
- ~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 @@
DCHECK(dex_cache_ != nullptr);
}
}
+ }
+
+ 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 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;
- }
- }
- return result;
- }
-
- 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);
+ 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;
}
- 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);
- 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;
}
- DCHECK_OFFSET_();
- ++method_offsets_index_;
+
+ if (!out->WriteFully(quick_code.data(), code_size)) {
+ ReportWriteFailure("method code", method_ref);
+ return false;
+ }
+ 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 @@
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 @@
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::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 @@
"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::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)
+ 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";
+ }
- VISIT(WriteCodeMethodVisitor);
-
- #undef VISIT
+ 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 a93dd23..c742fd4 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 OatDexMethodVisitor;
class InitBssLayoutMethodVisitor;
class InitOatClassesMethodVisitor;
+ class LayoutCodeMethodVisitor;
+ class LayoutReserveOffsetCodeMethodVisitor;
+ struct OrderedMethodData;
+ class OrderedMethodVisitor;
class InitCodeMethodVisitor;
class InitMapMethodVisitor;
class InitMethodInfoVisitor;
@@ -486,6 +491,13 @@
// 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 33d1491..d89d9f0 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 588a3ae..29c9e92 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -74,9 +74,9 @@
android: {
shared_libs: [
"libpagemap",
- ]
+ ],
},
- }
+ },
}
art_cc_test {
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index 5913832..0c944ce 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -185,21 +185,14 @@
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 362c08b..5dcc87d 100644
--- a/dexlayout/dex_ir.h
+++ b/dexlayout/dex_ir.h
@@ -947,6 +947,11 @@
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 92a1366..095c960 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1079,16 +1079,15 @@
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 715c209..33366ad 100644
--- a/dexoptanalyzer/Android.bp
+++ b/dexoptanalyzer/Android.bp
@@ -58,7 +58,7 @@
"art_gtest_defaults",
],
shared_libs: [
- "libbacktrace"
+ "libbacktrace",
],
srcs: ["dexoptanalyzer_test.cc"],
}
diff --git a/disassembler/Android.bp b/disassembler/Android.bp
index 086b8c7..8849309 100644
--- a/disassembler/Android.bp
+++ b/disassembler/Android.bp
@@ -18,7 +18,6 @@
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 36bd4bc..bcf007b 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 @@
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 @@
default:
break;
}
-
- code_ptr += inst->SizeInCodeUnits();
}
}
@@ -1519,12 +1515,11 @@
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 071b434..761df02 100644
--- a/openjdkjvm/Android.bp
+++ b/openjdkjvm/Android.bp
@@ -20,7 +20,7 @@
srcs: ["OpenjdkJvm.cc"],
shared_libs: [
"libbase",
- "libnativehelper"
+ "libnativehelper",
],
}
diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp
index b6b1b56..84a90d6 100644
--- a/openjdkjvmti/Android.bp
+++ b/openjdkjvmti/Android.bp
@@ -23,31 +23,33 @@
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 4339b2b..bac57f9 100644
--- a/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/openjdkjvmti/OpenjdkJvmTi.cc
@@ -1034,14 +1034,13 @@
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 62603aa..f05977a 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -86,20 +86,38 @@
TiMethodCallback gMethodCallback;
+// TODO We should make this much more selective in the future so we only return true when we
+// actually care about the method (i.e. had locals changed, have breakpoints, etc.). For now though
+// we can just assume that we care we are loaded at all.
+//
+// Even if we don't keep track of this at the method level we might want to keep track of it at the
+// level of enabled capabilities.
+struct TiMethodInspectionCallback : public art::MethodInspectionCallback {
+ bool IsMethodBeingInspected(art::ArtMethod* method ATTRIBUTE_UNUSED)
+ OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ return true;
+ }
+};
+
+TiMethodInspectionCallback gMethodInspectionCallback;
+
void MethodUtil::Register(EventHandler* handler) {
gMethodCallback.event_handler = handler;
art::ScopedThreadStateChange stsc(art::Thread::Current(),
art::ThreadState::kWaitingForDebuggerToAttach);
art::ScopedSuspendAll ssa("Add method callback");
- art::Runtime::Current()->GetRuntimeCallbacks()->AddMethodCallback(&gMethodCallback);
+ art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks();
+ callbacks->AddMethodCallback(&gMethodCallback);
+ callbacks->AddMethodInspectionCallback(&gMethodInspectionCallback);
}
void MethodUtil::Unregister() {
art::ScopedThreadStateChange stsc(art::Thread::Current(),
art::ThreadState::kWaitingForDebuggerToAttach);
art::ScopedSuspendAll ssa("Remove method callback");
- art::Runtime* runtime = art::Runtime::Current();
- runtime->GetRuntimeCallbacks()->RemoveMethodCallback(&gMethodCallback);
+ art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks();
+ callbacks->RemoveMethodCallback(&gMethodCallback);
+ callbacks->AddMethodInspectionCallback(&gMethodInspectionCallback);
}
jvmtiError MethodUtil::GetBytecodes(jvmtiEnv* env,
@@ -761,12 +779,10 @@
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 +906,10 @@
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 +937,6 @@
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 +963,10 @@
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 f92d81e..5a38f46 100644
--- a/openjdkjvmti/ti_monitor.cc
+++ b/openjdkjvmti/ti_monitor.cc
@@ -335,12 +335,10 @@
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 @@
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_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 1b4e910..5d9bf2c 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -1396,7 +1396,7 @@
linker->SetEntryPointsToInterpreter(&method);
method.SetCodeItemOffset(dex_file_->FindCodeItemOffset(class_def, dex_method_idx));
// Clear all the intrinsics related flags.
- method.ClearAccessFlags(art::kAccIntrinsic | (~art::kAccFlagsNotUsedByIntrinsic));
+ method.SetNotIntrinsic();
// Notify the jit that this method is redefined.
art::jit::Jit* jit = driver_->runtime_->GetJit();
if (jit != nullptr) {
diff --git a/openjdkjvmti/ti_stack.cc b/openjdkjvmti/ti_stack.cc
index 699f695..d4cc42a 100644
--- a/openjdkjvmti/ti_stack.cc
+++ b/openjdkjvmti/ti_stack.cc
@@ -211,34 +211,6 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 d437e52..907b515 100644
--- a/openjdkjvmti/ti_thread.cc
+++ b/openjdkjvmti/ti_thread.cc
@@ -161,13 +161,34 @@
}
// 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 @@
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 @@
};
// 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 @@
}
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 @@
}
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 @@
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 @@
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 @@
{
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 @@
{
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 @@
// 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 @@
} 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 @@
// 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 57b1943..ceebff6 100644
--- a/openjdkjvmti/ti_thread.h
+++ b/openjdkjvmti/ti_thread.h
@@ -93,8 +93,24 @@
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/profman/profile_assistant.cc b/profman/profile_assistant.cc
index c238f0d..ff02b5d 100644
--- a/profman/profile_assistant.cc
+++ b/profman/profile_assistant.cc
@@ -23,8 +23,11 @@
// Minimum number of new methods/classes that profiles
// must contain to enable recompilation.
-static constexpr const uint32_t kMinNewMethodsForCompilation = 10;
-static constexpr const uint32_t kMinNewClassesForCompilation = 10;
+static constexpr const uint32_t kMinNewMethodsForCompilation = 100;
+static constexpr const uint32_t kMinNewMethodsPercentChangeForCompilation = 2;
+static constexpr const uint32_t kMinNewClassesForCompilation = 50;
+static constexpr const uint32_t kMinNewClassesPercentChangeForCompilation = 2;
+
ProfileAssistant::ProcessingResult ProfileAssistant::ProcessProfilesInternal(
const std::vector<ScopedFlock>& profile_files,
@@ -55,9 +58,16 @@
}
}
+ uint32_t min_change_in_methods_for_compilation = std::max(
+ (kMinNewMethodsPercentChangeForCompilation * number_of_methods) / 100,
+ kMinNewMethodsForCompilation);
+ uint32_t min_change_in_classes_for_compilation = std::max(
+ (kMinNewClassesPercentChangeForCompilation * number_of_classes) / 100,
+ kMinNewClassesForCompilation);
// Check if there is enough new information added by the current profiles.
- if (((info.GetNumberOfMethods() - number_of_methods) < kMinNewMethodsForCompilation) &&
- ((info.GetNumberOfResolvedClasses() - number_of_classes) < kMinNewClassesForCompilation)) {
+ if (((info.GetNumberOfMethods() - number_of_methods) < min_change_in_methods_for_compilation) &&
+ ((info.GetNumberOfResolvedClasses() - number_of_classes)
+ < min_change_in_classes_for_compilation)) {
return kSkipCompilation;
}
diff --git a/profman/profile_assistant_test.cc b/profman/profile_assistant_test.cc
index 8cbf8c3..73724b2 100644
--- a/profman/profile_assistant_test.cc
+++ b/profman/profile_assistant_test.cc
@@ -335,6 +335,46 @@
ASSERT_EQ(expected_clases.size(), found);
}
+ int CheckCompilationMethodPercentChange(uint16_t methods_in_cur_profile,
+ uint16_t methods_in_ref_profile) {
+ ScratchFile profile;
+ ScratchFile reference_profile;
+ std::vector<int> profile_fds({ GetFd(profile)});
+ int reference_profile_fd = GetFd(reference_profile);
+ std::vector<uint32_t> hot_methods_cur;
+ std::vector<uint32_t> hot_methods_ref;
+ std::vector<uint32_t> empty_vector;
+ for (size_t i = 0; i < methods_in_cur_profile; ++i) {
+ hot_methods_cur.push_back(i);
+ }
+ for (size_t i = 0; i < methods_in_ref_profile; ++i) {
+ hot_methods_ref.push_back(i);
+ }
+ ProfileCompilationInfo info1;
+ uint16_t methods_in_profile = std::max(methods_in_cur_profile, methods_in_ref_profile);
+ SetupBasicProfile("p1", 1, methods_in_profile, hot_methods_cur, empty_vector, empty_vector,
+ profile, &info1);
+ ProfileCompilationInfo info2;
+ SetupBasicProfile("p1", 1, methods_in_profile, hot_methods_ref, empty_vector, empty_vector,
+ reference_profile, &info2);
+ return ProcessProfiles(profile_fds, reference_profile_fd);
+ }
+
+ int CheckCompilationClassPercentChange(uint16_t classes_in_cur_profile,
+ uint16_t classes_in_ref_profile) {
+ ScratchFile profile;
+ ScratchFile reference_profile;
+
+ std::vector<int> profile_fds({ GetFd(profile)});
+ int reference_profile_fd = GetFd(reference_profile);
+
+ ProfileCompilationInfo info1;
+ SetupProfile("p1", 1, 0, classes_in_cur_profile, profile, &info1);
+ ProfileCompilationInfo info2;
+ SetupProfile("p1", 1, 0, classes_in_ref_profile, reference_profile, &info2);
+ return ProcessProfiles(profile_fds, reference_profile_fd);
+ }
+
std::unique_ptr<ArenaAllocator> arena_;
// Cache of inline caches generated during tests.
@@ -460,7 +500,7 @@
GetFd(profile2)});
int reference_profile_fd = GetFd(reference_profile);
- const uint16_t kNumberOfMethodsToSkipCompilation = 1;
+ const uint16_t kNumberOfMethodsToSkipCompilation = 24; // Threshold is 100.
ProfileCompilationInfo info1;
SetupProfile("p1", 1, kNumberOfMethodsToSkipCompilation, 0, profile1, &info1);
ProfileCompilationInfo info2;
@@ -489,6 +529,42 @@
CheckProfileInfo(profile2, info2);
}
+TEST_F(ProfileAssistantTest, DoNotAdviseCompilationMethodPercentage) {
+ const uint16_t kNumberOfMethodsInRefProfile = 6000;
+ const uint16_t kNumberOfMethodsInCurProfile = 6100; // Threshold is 2%.
+ // We should not advise compilation.
+ ASSERT_EQ(ProfileAssistant::kSkipCompilation,
+ CheckCompilationMethodPercentChange(kNumberOfMethodsInCurProfile,
+ kNumberOfMethodsInRefProfile));
+}
+
+TEST_F(ProfileAssistantTest, ShouldAdviseCompilationMethodPercentage) {
+ const uint16_t kNumberOfMethodsInRefProfile = 6000;
+ const uint16_t kNumberOfMethodsInCurProfile = 6200; // Threshold is 2%.
+ // We should advise compilation.
+ ASSERT_EQ(ProfileAssistant::kCompile,
+ CheckCompilationMethodPercentChange(kNumberOfMethodsInCurProfile,
+ kNumberOfMethodsInRefProfile));
+}
+
+TEST_F(ProfileAssistantTest, DoNotdviseCompilationClassPercentage) {
+ const uint16_t kNumberOfClassesInRefProfile = 6000;
+ const uint16_t kNumberOfClassesInCurProfile = 6110; // Threshold is 2%.
+ // We should not advise compilation.
+ ASSERT_EQ(ProfileAssistant::kSkipCompilation,
+ CheckCompilationClassPercentChange(kNumberOfClassesInCurProfile,
+ kNumberOfClassesInRefProfile));
+}
+
+TEST_F(ProfileAssistantTest, ShouldAdviseCompilationClassPercentage) {
+ const uint16_t kNumberOfClassesInRefProfile = 6000;
+ const uint16_t kNumberOfClassesInCurProfile = 6120; // Threshold is 2%.
+ // We should advise compilation.
+ ASSERT_EQ(ProfileAssistant::kCompile,
+ CheckCompilationClassPercentChange(kNumberOfClassesInCurProfile,
+ kNumberOfClassesInRefProfile));
+}
+
TEST_F(ProfileAssistantTest, FailProcessingBecauseOfProfiles) {
ScratchFile profile1;
ScratchFile profile2;
diff --git a/runtime/Android.bp b/runtime/Android.bp
index db9707f..711bc65 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -356,10 +356,9 @@
"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.
@@ -388,7 +387,7 @@
],
shared_libs: [
"libziparchive",
- "libz-host",
+ "libz",
],
},
},
@@ -398,7 +397,6 @@
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 {
name: "libartd",
defaults: [
- "art_debug_defaults",
- "libart_defaults",
+ "art_debug_defaults",
+ "libart_defaults",
],
}
@@ -503,12 +501,12 @@
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 @@
"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 @@
"libbacktrace",
],
header_libs: [
- "art_cmdlineparser_headers", // For parsed_options_test.
+ "art_cmdlineparser_headers", // For parsed_options_test.
],
}
@@ -636,7 +633,7 @@
}
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-inl.h b/runtime/art_method-inl.h
index 7ff35ac..4181169 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -377,14 +377,14 @@
}
inline void ArtMethod::SetIntrinsic(uint32_t intrinsic) {
- DCHECK(IsUint<8>(intrinsic));
// Currently we only do intrinsics for static/final methods or methods of final
// classes. We don't set kHasSingleImplementation for those methods.
DCHECK(IsStatic() || IsFinal() || GetDeclaringClass()->IsFinal()) <<
"Potential conflict with kAccSingleImplementation";
- uint32_t new_value = (GetAccessFlags() & kAccFlagsNotUsedByIntrinsic) |
- kAccIntrinsic |
- (intrinsic << POPCOUNT(kAccFlagsNotUsedByIntrinsic));
+ static const int kAccFlagsShift = CTZ(kAccIntrinsicBits);
+ DCHECK_LE(intrinsic, kAccIntrinsicBits >> kAccFlagsShift);
+ uint32_t intrinsic_bits = intrinsic << kAccFlagsShift;
+ uint32_t new_value = (GetAccessFlags() & ~kAccIntrinsicBits) | kAccIntrinsic | intrinsic_bits;
if (kIsDebugBuild) {
uint32_t java_flags = (GetAccessFlags() & kAccJavaFlagsMask);
bool is_constructor = IsConstructor();
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index ece853f..d4297df 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -777,26 +777,16 @@
}
std::string ArtMethod::PrettyMethod(bool with_signature) {
- ArtMethod* m = this;
- if (!m->IsRuntimeMethod()) {
- m = m->GetInterfaceMethodIfProxy(Runtime::Current()->GetClassLinker()->GetImagePointerSize());
+ if (UNLIKELY(IsRuntimeMethod())) {
+ std::string result = GetDeclaringClassDescriptor();
+ result += '.';
+ result += GetName();
+ // Do not add "<no signature>" even if `with_signature` is true.
+ return result;
}
- 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;
+ ArtMethod* m =
+ GetInterfaceMethodIfProxy(Runtime::Current()->GetClassLinker()->GetImagePointerSize());
+ return m->GetDexFile()->PrettyMethod(m->GetDexMethodIndex(), with_signature);
}
std::string ArtMethod::JniShortName() {
diff --git a/runtime/art_method.h b/runtime/art_method.h
index fbdc32d..caef81c 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -117,26 +117,6 @@
access_flags_.store(new_access_flags, std::memory_order_relaxed);
}
- // This setter guarantees atomicity.
- void AddAccessFlags(uint32_t flag) {
- uint32_t old_access_flags;
- uint32_t new_access_flags;
- do {
- old_access_flags = access_flags_.load(std::memory_order_relaxed);
- new_access_flags = old_access_flags | flag;
- } while (!access_flags_.compare_exchange_weak(old_access_flags, new_access_flags));
- }
-
- // This setter guarantees atomicity.
- void ClearAccessFlags(uint32_t flag) {
- uint32_t old_access_flags;
- uint32_t new_access_flags;
- do {
- old_access_flags = access_flags_.load(std::memory_order_relaxed);
- new_access_flags = old_access_flags & ~flag;
- } while (!access_flags_.compare_exchange_weak(old_access_flags, new_access_flags));
- }
-
static MemberOffset AccessFlagsOffset() {
return MemberOffset(OFFSETOF_MEMBER(ArtMethod, access_flags_));
}
@@ -196,12 +176,21 @@
ALWAYS_INLINE void SetIntrinsic(uint32_t intrinsic) REQUIRES_SHARED(Locks::mutator_lock_);
uint32_t GetIntrinsic() {
+ static const int kAccFlagsShift = CTZ(kAccIntrinsicBits);
+ static_assert(IsPowerOfTwo((kAccIntrinsicBits >> kAccFlagsShift) + 1),
+ "kAccIntrinsicBits are not continuous");
+ static_assert((kAccIntrinsic & kAccIntrinsicBits) == 0,
+ "kAccIntrinsic overlaps kAccIntrinsicBits");
DCHECK(IsIntrinsic());
- return (GetAccessFlags() >> POPCOUNT(kAccFlagsNotUsedByIntrinsic)) & kAccMaxIntrinsic;
+ return (GetAccessFlags() & kAccIntrinsicBits) >> kAccFlagsShift;
+ }
+
+ void SetNotIntrinsic() REQUIRES_SHARED(Locks::mutator_lock_) {
+ ClearAccessFlags(kAccIntrinsic | kAccIntrinsicBits);
}
bool IsCopied() {
- static_assert((kAccCopied & kAccFlagsNotUsedByIntrinsic) == kAccCopied,
+ static_assert((kAccCopied & (kAccIntrinsic | kAccIntrinsicBits)) == 0,
"kAccCopied conflicts with intrinsic modifier");
const bool copied = (GetAccessFlags() & kAccCopied) != 0;
// (IsMiranda() || IsDefaultConflicting()) implies copied
@@ -211,7 +200,7 @@
}
bool IsMiranda() {
- static_assert((kAccMiranda & kAccFlagsNotUsedByIntrinsic) == kAccMiranda,
+ static_assert((kAccMiranda & (kAccIntrinsic | kAccIntrinsicBits)) == 0,
"kAccMiranda conflicts with intrinsic modifier");
return (GetAccessFlags() & kAccMiranda) != 0;
}
@@ -245,7 +234,7 @@
// This is set by the class linker.
bool IsDefault() {
- static_assert((kAccDefault & kAccFlagsNotUsedByIntrinsic) == kAccDefault,
+ static_assert((kAccDefault & (kAccIntrinsic | kAccIntrinsicBits)) == 0,
"kAccDefault conflicts with intrinsic modifier");
return (GetAccessFlags() & kAccDefault) != 0;
}
@@ -290,6 +279,22 @@
AddAccessFlags(kAccSkipAccessChecks);
}
+ bool PreviouslyWarm() {
+ if (IsIntrinsic()) {
+ // kAccPreviouslyWarm overlaps with kAccIntrinsicBits.
+ return true;
+ }
+ return (GetAccessFlags() & kAccPreviouslyWarm) != 0;
+ }
+
+ void SetPreviouslyWarm() {
+ if (IsIntrinsic()) {
+ // kAccPreviouslyWarm overlaps with kAccIntrinsicBits.
+ return;
+ }
+ AddAccessFlags(kAccPreviouslyWarm);
+ }
+
// Should this method be run in the interpreter and count locks (e.g., failed structured-
// locking verification)?
bool MustCountLocks() {
@@ -299,6 +304,10 @@
return (GetAccessFlags() & kAccMustCountLocks) != 0;
}
+ void SetMustCountLocks() {
+ AddAccessFlags(kAccMustCountLocks);
+ }
+
// Checks to see if the method was annotated with @dalvik.annotation.optimization.FastNative
// -- Independent of kAccFastNative access flags.
bool IsAnnotatedWithFastNative();
@@ -782,6 +791,37 @@
template <ReadBarrierOption kReadBarrierOption> void GetAccessFlagsDCheck();
+ static inline bool IsValidIntrinsicUpdate(uint32_t modifier) {
+ return (((modifier & kAccIntrinsic) == kAccIntrinsic) &&
+ (((modifier & ~(kAccIntrinsic | kAccIntrinsicBits)) == 0)));
+ }
+
+ static inline bool OverlapsIntrinsicBits(uint32_t modifier) {
+ return (modifier & kAccIntrinsicBits) != 0;
+ }
+
+ // This setter guarantees atomicity.
+ void AddAccessFlags(uint32_t flag) {
+ DCHECK(!IsIntrinsic() || !OverlapsIntrinsicBits(flag) || IsValidIntrinsicUpdate(flag));
+ uint32_t old_access_flags;
+ uint32_t new_access_flags;
+ do {
+ old_access_flags = access_flags_.load(std::memory_order_relaxed);
+ new_access_flags = old_access_flags | flag;
+ } while (!access_flags_.compare_exchange_weak(old_access_flags, new_access_flags));
+ }
+
+ // This setter guarantees atomicity.
+ void ClearAccessFlags(uint32_t flag) {
+ DCHECK(!IsIntrinsic() || !OverlapsIntrinsicBits(flag) || IsValidIntrinsicUpdate(flag));
+ uint32_t old_access_flags;
+ uint32_t new_access_flags;
+ do {
+ old_access_flags = access_flags_.load(std::memory_order_relaxed);
+ new_access_flags = old_access_flags & ~flag;
+ } while (!access_flags_.compare_exchange_weak(old_access_flags, new_access_flags));
+ }
+
DISALLOW_COPY_AND_ASSIGN(ArtMethod); // Need to use CopyFrom to deal with 32 vs 64 bits.
};
diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc
index b2e5251..b8d6931 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -128,8 +128,11 @@
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::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 a5344db..a8a6701 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 @@
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 @@
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 @@
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 35a73d0..770d2c0 100644
--- a/runtime/base/timing_logger_test.cc
+++ b/runtime/base/timing_logger_test.cc
@@ -158,4 +158,21 @@
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 eb8ced0..6d1de00 100644
--- a/runtime/base/unix_file/fd_file.cc
+++ b/runtime/base/unix_file/fd_file.cc
@@ -70,7 +70,7 @@
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, 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 @@
// 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 3bd4596..2282da0 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -220,7 +220,7 @@
// 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/debugger.cc b/runtime/debugger.cc
index 6daec72..b021ff1 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -324,6 +324,7 @@
bool Dbg::gDebuggerActive = false;
bool Dbg::gDisposed = false;
ObjectRegistry* Dbg::gRegistry = nullptr;
+DebuggerActiveMethodInspectionCallback Dbg::gDebugActiveCallback;
// Deoptimization support.
std::vector<DeoptimizationRequest> Dbg::deoptimization_requests_;
@@ -341,6 +342,10 @@
Dbg::DbgThreadLifecycleCallback Dbg::thread_lifecycle_callback_;
Dbg::DbgClassLoadCallback Dbg::class_load_callback_;
+bool DebuggerActiveMethodInspectionCallback::IsMethodBeingInspected(ArtMethod* m ATTRIBUTE_UNUSED) {
+ return Dbg::IsDebuggerActive();
+}
+
// Breakpoints.
static std::vector<Breakpoint> gBreakpoints GUARDED_BY(Locks::breakpoint_lock_);
@@ -652,6 +657,7 @@
}
instrumentation_events_ = 0;
gDebuggerActive = true;
+ Runtime::Current()->GetRuntimeCallbacks()->AddMethodInspectionCallback(&gDebugActiveCallback);
LOG(INFO) << "Debugger is active";
}
@@ -689,6 +695,8 @@
runtime->GetInstrumentation()->DisableDeoptimization(kDbgInstrumentationKey);
}
gDebuggerActive = false;
+ Runtime::Current()->GetRuntimeCallbacks()->RemoveMethodInspectionCallback(
+ &gDebugActiveCallback);
}
}
diff --git a/runtime/debugger.h b/runtime/debugger.h
index 0be46d6..18126b1 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -34,6 +34,7 @@
#include "jni.h"
#include "jvalue.h"
#include "obj_ptr.h"
+#include "runtime_callbacks.h"
#include "thread.h"
#include "thread_state.h"
@@ -51,6 +52,12 @@
class StackVisitor;
class Thread;
+struct DebuggerActiveMethodInspectionCallback : public MethodInspectionCallback {
+ bool IsMethodBeingInspected(ArtMethod* m ATTRIBUTE_UNUSED)
+ OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
+};
+
+
/*
* Invoke-during-breakpoint support.
*/
@@ -773,6 +780,8 @@
// Indicates whether the debugger is making requests.
static bool gDebuggerActive;
+ static DebuggerActiveMethodInspectionCallback gDebugActiveCallback;
+
// Indicates whether we should drop the JDWP connection because the runtime stops or the
// debugger called VirtualMachine.Dispose.
static bool gDisposed;
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index f70846b..be157a3 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -1302,17 +1302,27 @@
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 @@
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 4807427..ac91d52 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 @@
// 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 1a73062..a7bf59e 100644
--- a/runtime/dex_file_test.cc
+++ b/runtime/dex_file_test.cc
@@ -423,28 +423,83 @@
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 0000000..280746e
--- /dev/null
+++ b/runtime/dex_instruction_iterator.h
@@ -0,0 +1,108 @@
+/*
+ * 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 value_type = std::iterator<std::forward_iterator_tag, Instruction>::value_type;
+ using difference_type = std::iterator<std::forward_iterator_tag, value_type>::difference_type;
+
+ DexInstructionIterator() = default;
+ DexInstructionIterator(const DexInstructionIterator&) = default;
+ DexInstructionIterator(DexInstructionIterator&&) = default;
+ DexInstructionIterator& operator=(const DexInstructionIterator&) = default;
+ DexInstructionIterator& operator=(DexInstructionIterator&&) = default;
+
+ explicit DexInstructionIterator(const value_type* inst) : inst_(inst) {}
+ explicit DexInstructionIterator(const uint16_t* inst) : inst_(value_type::At(inst)) {}
+
+ // Value after modification.
+ DexInstructionIterator& operator++() {
+ inst_ = inst_->Next();
+ return *this;
+ }
+
+ // Value before modification.
+ DexInstructionIterator operator++(int) {
+ DexInstructionIterator temp = *this;
+ ++*this;
+ return temp;
+ }
+
+ const value_type& operator*() const {
+ return *inst_;
+ }
+
+ const value_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 value_type* Inst() const {
+ return inst_;
+ }
+
+ private:
+ const value_type* inst_ = nullptr;
+};
+
+static ALWAYS_INLINE 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 !(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 3f7ac57..48ed027 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 @@
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 @@
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 @@
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 a44bc16..0000000
--- 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 e83829b..0000000
--- 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 211381c..813a264 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1119,8 +1119,8 @@
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]);
- Instruction::Code instr_code = instr->Opcode();
+ const Instruction& instr = code->InstructionAt(dex_pc);
+ Instruction::Code instr_code = instr.Opcode();
bool is_range;
switch (instr_code) {
case Instruction::INVOKE_DIRECT:
@@ -1164,10 +1164,10 @@
is_range = true;
break;
default:
- LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(nullptr);
+ LOG(FATAL) << "Unexpected call into trampoline: " << instr.DumpString(nullptr);
UNREACHABLE();
}
- called_method.index = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
+ called_method.index = (is_range) ? instr.VRegB_3rc() : instr.VRegB_35c();
// Check that the invoke matches what we expected, note that this path only happens for debug
// builds.
if (found_stack_map) {
@@ -2484,16 +2484,16 @@
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]);
- Instruction::Code instr_code = instr->Opcode();
+ 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)
- << "Unexpected call into interface trampoline: " << instr->DumpString(nullptr);
+ << "Unexpected call into interface trampoline: " << instr.DumpString(nullptr);
if (instr_code == Instruction::INVOKE_INTERFACE) {
- dex_method_idx = instr->VRegB_35c();
+ dex_method_idx = instr.VRegB_35c();
} else {
DCHECK_EQ(instr_code, Instruction::INVOKE_INTERFACE_RANGE);
- dex_method_idx = instr->VRegB_3rc();
+ dex_method_idx = instr.VRegB_3rc();
}
const DexFile& dex_file = caller_method->GetDeclaringClass()->GetDexFile();
@@ -2600,11 +2600,11 @@
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]);
- DCHECK(inst->Opcode() == Instruction::INVOKE_POLYMORPHIC ||
- inst->Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE);
+ 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();
- const uint32_t proto_idx = inst->VRegH();
+ const uint32_t proto_idx = inst.VRegH();
const char* shorty = dex_file->GetShorty(proto_idx);
const size_t shorty_length = strlen(shorty);
static const bool kMethodIsStatic = false; // invoke() and invokeExact() are not static.
@@ -2621,7 +2621,7 @@
// Resolve method - it's either MethodHandle.invoke() or MethodHandle.invokeExact().
ClassLinker* linker = Runtime::Current()->GetClassLinker();
ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
- self, inst->VRegB(), caller_method, kVirtual);
+ self, inst.VRegB(), caller_method, kVirtual);
DCHECK((resolved_method ==
jni::DecodeArtMethod(WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact)) ||
(resolved_method ==
@@ -2642,15 +2642,15 @@
return static_cast<uintptr_t>('V');
}
- DCHECK_EQ(ArtMethod::NumArgRegisters(shorty) + 1u, (uint32_t)inst->VRegA());
+ DCHECK_EQ(ArtMethod::NumArgRegisters(shorty) + 1u, (uint32_t)inst.VRegA());
DCHECK_EQ(resolved_method->IsStatic(), kMethodIsStatic);
// Fix references before constructing the shadow frame.
gc_visitor.FixupReferences();
// Construct shadow frame placing arguments consecutively from |first_arg|.
- const bool is_range = (inst->Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE);
- const size_t num_vregs = is_range ? inst->VRegA_4rcc() : inst->VRegA_45cc();
+ const bool is_range = (inst.Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE);
+ const size_t num_vregs = is_range ? inst.VRegA_4rcc() : inst.VRegA_45cc();
const size_t first_arg = 0;
ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
CREATE_SHADOW_FRAME(num_vregs, /* link */ nullptr, resolved_method, dex_pc);
diff --git a/runtime/image.cc b/runtime/image.cc
index 0236f47..4c6529b 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -26,7 +26,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '4', '8', '\0' }; // Map boot image tables.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '4', '9', '\0' }; // 256 intrinsics
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc
index cff3ea7..2dd4db3 100644
--- a/runtime/indirect_reference_table.cc
+++ b/runtime/indirect_reference_table.cc
@@ -237,7 +237,8 @@
}
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 @@
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 6d52d95..bf287b1 100644
--- a/runtime/indirect_reference_table.h
+++ b/runtime/indirect_reference_table.h
@@ -244,8 +244,10 @@
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 6aefe23..9278509 100644
--- a/runtime/indirect_reference_table_test.cc
+++ b/runtime/indirect_reference_table_test.cc
@@ -80,13 +80,13 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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/shadow_frame.h b/runtime/interpreter/shadow_frame.h
index 6903af2..80fdadb 100644
--- a/runtime/interpreter/shadow_frame.h
+++ b/runtime/interpreter/shadow_frame.h
@@ -188,9 +188,7 @@
const uint32_t* vreg_ptr = &vregs_[i];
ref = reinterpret_cast<const StackReference<mirror::Object>*>(vreg_ptr)->AsMirrorPtr();
}
- if (kUseReadBarrier) {
- ReadBarrier::AssertToSpaceInvariant(ref);
- }
+ ReadBarrier::MaybeAssertToSpaceInvariant(ref);
if (kVerifyFlags & kVerifyReads) {
VerifyObject(ref);
}
@@ -256,9 +254,7 @@
if (kVerifyFlags & kVerifyWrites) {
VerifyObject(val);
}
- if (kUseReadBarrier) {
- ReadBarrier::AssertToSpaceInvariant(val);
- }
+ ReadBarrier::MaybeAssertToSpaceInvariant(val);
uint32_t* vreg = &vregs_[i];
reinterpret_cast<StackReference<mirror::Object>*>(vreg)->Assign(val);
if (HasReferenceArray()) {
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 71ab01e..fb37825 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -393,7 +393,7 @@
// 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 @@
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 @@
// 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 @@
// 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 1593577..5a16053 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 @@
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 @@
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 @@
// 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/jit.cc b/runtime/jit/jit.cc
index 8c27bfe..97a3b71 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -490,10 +490,10 @@
return false;
}
- // Before allowing the jump, make sure the debugger is not active to avoid jumping from
- // interpreter to OSR while e.g. single stepping. Note that we could selectively disable
- // OSR when single stepping, but that's currently hard to know at this point.
- if (Dbg::IsDebuggerActive()) {
+ // Before allowing the jump, make sure no code is actively inspecting the method to avoid
+ // jumping from interpreter to OSR while e.g. single stepping. Note that we could selectively
+ // disable OSR when single stepping, but that's currently hard to know at this point.
+ if (Runtime::Current()->GetRuntimeCallbacks()->IsMethodBeingInspected(method)) {
return false;
}
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 40a5212..ae08fe2 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -534,7 +534,7 @@
static void ClearMethodCounter(ArtMethod* method, bool was_warm) {
if (was_warm) {
- method->AddAccessFlags(kAccPreviouslyWarm);
+ method->SetPreviouslyWarm();
}
// We reset the counter to 1 so that the profile knows that the method was executed at least once.
// This is required for layout purposes.
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index 12fa49e..5601317 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -1053,6 +1053,98 @@
}
}
+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) {
@@ -1612,7 +1704,10 @@
if (m < (number_of_methods / kFavorSplit)) {
method_idx %= kFavorFirstN;
}
- info.AddMethodIndex(MethodHotness::kFlagHot,
+ // Alternate between startup and post startup.
+ uint32_t flags = MethodHotness::kFlagHot;
+ flags |= ((m & 1) != 0) ? MethodHotness::kFlagPostStartup : MethodHotness::kFlagStartup;
+ info.AddMethodIndex(static_cast<MethodHotness::Flag>(flags),
profile_key,
/*method_idx*/ 0,
method_idx,
@@ -1669,8 +1764,13 @@
if (number_of_methods - i == methods_required_in_profile ||
std::rand() % (number_of_methods - i - methods_required_in_profile) == 0) {
uint32_t method_index = (method_start_index + i) % number_of_methods;
- info.AddMethodIndex(MethodHotness::kFlagHot, MethodReference(dex_file.get(),
- method_index));
+ // Alternate between startup and post startup.
+ uint32_t flags = MethodHotness::kFlagHot;
+ flags |= ((method_index & 1) != 0)
+ ? MethodHotness::kFlagPostStartup
+ : MethodHotness::kFlagStartup;
+ info.AddMethodIndex(static_cast<MethodHotness::Flag>(flags),
+ MethodReference(dex_file.get(), method_index));
methods_required_in_profile--;
}
}
diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h
index 009554c..09de29e 100644
--- a/runtime/jit/profile_compilation_info.h
+++ b/runtime/jit/profile_compilation_info.h
@@ -305,6 +305,15 @@
// 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/profile_saver.cc b/runtime/jit/profile_saver.cc
index af6a45f..2bf8d8b 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -349,7 +349,7 @@
// Mark startup methods as hot if they have more than hot_method_sample_threshold
// samples. This means they will get compiled by the compiler driver.
if (method.GetProfilingInfo(kRuntimePointerSize) != nullptr ||
- (method.GetAccessFlags() & kAccPreviouslyWarm) != 0 ||
+ method.PreviouslyWarm() ||
counter >= hot_method_sample_threshold) {
hot_methods->AddReference(method.GetDexFile(), method.GetDexMethodIndex());
} else if (counter != 0) {
diff --git a/runtime/jit/profiling_info.cc b/runtime/jit/profiling_info.cc
index 1bd095a..ad01324 100644
--- a/runtime/jit/profiling_info.cc
+++ b/runtime/jit/profiling_info.cc
@@ -43,15 +43,12 @@
// 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 @@
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 25893b7..d66df08 100644
--- a/runtime/jni_env_ext-inl.h
+++ b/runtime/jni_env_ext-inl.h
@@ -25,7 +25,13 @@
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 3ff94f9..8352657 100644
--- a/runtime/jni_env_ext.cc
+++ b/runtime/jni_env_ext.cc
@@ -99,7 +99,14 @@
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 77a5b55..78f6b25 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -128,7 +128,8 @@
}
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::GetDeclaredMethodsSliceUnchecked(PointerSize pointer_size) {
- return GetMethodsSliceRangeUnchecked(pointer_size,
+ return GetMethodsSliceRangeUnchecked(GetMethodsPtr(),
+ pointer_size,
GetDirectMethodsStartOffset(),
GetCopiedMethodsStartOffset());
}
@@ -152,7 +154,8 @@
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::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::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 @@
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 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::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 c44b616..148273b 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -773,6 +773,8 @@
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 @@
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/modifiers.h b/runtime/modifiers.h
index 68ab4a4..4b790a0 100644
--- a/runtime/modifiers.h
+++ b/runtime/modifiers.h
@@ -79,6 +79,11 @@
// virtual call.
static constexpr uint32_t kAccSingleImplementation = 0x08000000; // method (runtime)
+// Not currently used, except for intrinsic methods where these bits
+// are part of the intrinsic ordinal.
+static constexpr uint32_t kAccMayBeUnusedBits = 0x70000000;
+
+// Set by the compiler driver when compiling boot classes with instrinsic methods.
static constexpr uint32_t kAccIntrinsic = 0x80000000; // method (runtime)
// Special runtime-only flags.
@@ -89,8 +94,10 @@
// class/ancestor overrides finalize()
static constexpr uint32_t kAccClassIsFinalizable = 0x80000000;
-static constexpr uint32_t kAccFlagsNotUsedByIntrinsic = 0x00FFFFFF;
-static constexpr uint32_t kAccMaxIntrinsic = 0x7F;
+// Continuous sequence of bits used to hold the ordinal of an intrinsic method. Flags
+// which overlap are not valid when kAccIntrinsic is set.
+static constexpr uint32_t kAccIntrinsicBits = kAccMayBeUnusedBits | kAccSingleImplementation |
+ kAccMustCountLocks | kAccCompileDontBother | kAccDefaultConflict | kAccPreviouslyWarm;
// Valid (meaningful) bits for a field.
static constexpr uint32_t kAccValidFieldFlags = kAccPublic | kAccPrivate | kAccProtected |
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index b2f6c03..9a42c29 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -635,29 +635,35 @@
}
if (boot_image_tables != nullptr) {
- // Map boot image tables into the .bss. The reserved size must match size of the tables.
- size_t reserved_size = static_cast<size_t>(boot_image_tables_end - boot_image_tables);
- size_t tables_size = 0u;
- for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
- tables_size += space->GetImageHeader().GetBootImageConstantTablesSize();
- DCHECK_ALIGNED(tables_size, kPageSize);
- }
- if (tables_size != reserved_size) {
- *error_msg = StringPrintf("In oat file '%s' found unexpected boot image table sizes, "
- " %zu bytes, should be %zu.",
- GetLocation().c_str(),
- reserved_size,
- tables_size);
- return false;
- }
- for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
- uint32_t current_tables_size = space->GetImageHeader().GetBootImageConstantTablesSize();
- if (current_tables_size != 0u && !MapConstantTables(space, boot_image_tables)) {
+ Runtime* runtime = Runtime::Current();
+ if (UNLIKELY(runtime == nullptr)) {
+ // This must be oatdump without boot image. Make sure the .bss is inaccessible.
+ mprotect(const_cast<uint8_t*>(BssBegin()), BssSize(), PROT_NONE);
+ } else {
+ // Map boot image tables into the .bss. The reserved size must match size of the tables.
+ size_t reserved_size = static_cast<size_t>(boot_image_tables_end - boot_image_tables);
+ size_t tables_size = 0u;
+ for (gc::space::ImageSpace* space : runtime->GetHeap()->GetBootImageSpaces()) {
+ tables_size += space->GetImageHeader().GetBootImageConstantTablesSize();
+ DCHECK_ALIGNED(tables_size, kPageSize);
+ }
+ if (tables_size != reserved_size) {
+ *error_msg = StringPrintf("In oat file '%s' found unexpected boot image table sizes, "
+ " %zu bytes, should be %zu.",
+ GetLocation().c_str(),
+ reserved_size,
+ tables_size);
return false;
}
- boot_image_tables += current_tables_size;
+ for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
+ uint32_t current_tables_size = space->GetImageHeader().GetBootImageConstantTablesSize();
+ if (current_tables_size != 0u && !MapConstantTables(space, boot_image_tables)) {
+ return false;
+ }
+ boot_image_tables += current_tables_size;
+ }
+ DCHECK(boot_image_tables == boot_image_tables_end);
}
- DCHECK(boot_image_tables == boot_image_tables_end);
}
return true;
}
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 83a8e09..f3a0725 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -645,6 +645,30 @@
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 @@
(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 @@
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 @@
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 @@
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 05b63d2..7cabae5 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -54,7 +54,8 @@
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 1ec345a..6f3571c 100644
--- a/runtime/primitive.cc
+++ b/runtime/primitive.cc
@@ -60,9 +60,9 @@
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 a0edaee..a429914 100644
--- a/runtime/primitive.h
+++ b/runtime/primitive.h
@@ -49,7 +49,7 @@
kPrimLast = kPrimVoid
};
- static Type GetType(char type) {
+ static constexpr Type GetType(char type) {
switch (type) {
case 'B':
return kPrimByte;
@@ -74,7 +74,7 @@
}
}
- static size_t ComponentSizeShift(Type type) {
+ static constexpr size_t ComponentSizeShift(Type type) {
switch (type) {
case kPrimVoid:
case kPrimBoolean:
@@ -86,13 +86,12 @@
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 @@
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 @@
// 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 @@
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 @@
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/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index d8b6237..f94923e 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -166,10 +166,9 @@
<< line_number << ")";
}
}
- if (clear_exception_) {
- // Exception was cleared as part of delivery.
- DCHECK(!self_->IsExceptionPending());
- } else {
+ // Exception was cleared as part of delivery.
+ DCHECK(!self_->IsExceptionPending());
+ if (!clear_exception_) {
// Put exception back in root set with clear throw location.
self_->SetException(exception_ref.Get());
}
diff --git a/runtime/quick_exception_handler.h b/runtime/quick_exception_handler.h
index 8090f9b..12b63c9 100644
--- a/runtime/quick_exception_handler.h
+++ b/runtime/quick_exception_handler.h
@@ -112,6 +112,10 @@
handler_dex_pc_ = dex_pc;
}
+ bool GetClearException() const {
+ return clear_exception_;
+ }
+
void SetClearException(bool clear_exception) {
clear_exception_ = clear_exception;
}
diff --git a/runtime/read_barrier.h b/runtime/read_barrier.h
index 45e78bc..00674b2 100644
--- a/runtime/read_barrier.h
+++ b/runtime/read_barrier.h
@@ -89,6 +89,14 @@
static void AssertToSpaceInvariant(GcRootSource* gc_root_source, mirror::Object* ref)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Without the holder object, and only with the read barrier configuration (no-op otherwise).
+ static void MaybeAssertToSpaceInvariant(mirror::Object* ref)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (kUseReadBarrier) {
+ AssertToSpaceInvariant(ref);
+ }
+ }
+
// ALWAYS_INLINE on this caused a performance regression b/26744236.
static mirror::Object* Mark(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/runtime_callbacks.cc b/runtime/runtime_callbacks.cc
index 88d3f28..f164f7c 100644
--- a/runtime/runtime_callbacks.cc
+++ b/runtime/runtime_callbacks.cc
@@ -26,10 +26,6 @@
namespace art {
-void RuntimeCallbacks::AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
- thread_callbacks_.push_back(cb);
-}
-
template <typename T>
ALWAYS_INLINE
static inline void Remove(T* cb, std::vector<T*>* data) {
@@ -39,6 +35,27 @@
}
}
+void RuntimeCallbacks::AddMethodInspectionCallback(MethodInspectionCallback* cb) {
+ method_inspection_callbacks_.push_back(cb);
+}
+
+void RuntimeCallbacks::RemoveMethodInspectionCallback(MethodInspectionCallback* cb) {
+ Remove(cb, &method_inspection_callbacks_);
+}
+
+bool RuntimeCallbacks::IsMethodBeingInspected(ArtMethod* m) {
+ for (MethodInspectionCallback* cb : method_inspection_callbacks_) {
+ if (cb->IsMethodBeingInspected(m)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void RuntimeCallbacks::AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
+ thread_callbacks_.push_back(cb);
+}
+
void RuntimeCallbacks::MonitorContendedLocking(Monitor* m) {
for (MonitorCallback* cb : monitor_callbacks_) {
cb->MonitorContendedLocking(m);
diff --git a/runtime/runtime_callbacks.h b/runtime/runtime_callbacks.h
index fa686d3..c936049 100644
--- a/runtime/runtime_callbacks.h
+++ b/runtime/runtime_callbacks.h
@@ -94,6 +94,18 @@
virtual ~MonitorCallback() {}
};
+// A callback to let parts of the runtime note that they are currently relying on a particular
+// method remaining in it's current state. Users should not rely on always being called. If multiple
+// callbacks are added the runtime will short-circuit when the first one returns 'true'.
+class MethodInspectionCallback {
+ public:
+ virtual ~MethodInspectionCallback() {}
+
+ // Returns true if the method is being inspected currently and the runtime should not modify it in
+ // potentially dangerous ways (i.e. replace with compiled version, JIT it, etc).
+ virtual bool IsMethodBeingInspected(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) = 0;
+};
+
class RuntimeCallbacks {
public:
void AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) REQUIRES(Locks::mutator_lock_);
@@ -151,6 +163,15 @@
void AddMonitorCallback(MonitorCallback* cb) REQUIRES_SHARED(Locks::mutator_lock_);
void RemoveMonitorCallback(MonitorCallback* cb) REQUIRES_SHARED(Locks::mutator_lock_);
+ // Returns true if some MethodInspectionCallback indicates the method is being inspected/depended
+ // on by some code.
+ bool IsMethodBeingInspected(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
+
+ void AddMethodInspectionCallback(MethodInspectionCallback* cb)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ void RemoveMethodInspectionCallback(MethodInspectionCallback* cb)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
private:
std::vector<ThreadLifecycleCallback*> thread_callbacks_
GUARDED_BY(Locks::mutator_lock_);
@@ -164,6 +185,8 @@
GUARDED_BY(Locks::mutator_lock_);
std::vector<MonitorCallback*> monitor_callbacks_
GUARDED_BY(Locks::mutator_lock_);
+ std::vector<MethodInspectionCallback*> method_inspection_callbacks_
+ GUARDED_BY(Locks::mutator_lock_);
};
} // namespace art
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 968a23b..524e73d 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2159,11 +2159,11 @@
ScopedObjectAccess soa(self);
// We may need to call user-supplied managed code, do this before final clean-up.
HandleUncaughtExceptions(soa);
+ RemoveFromThreadGroup(soa);
Runtime* runtime = Runtime::Current();
if (runtime != nullptr) {
runtime->GetRuntimeCallbacks()->ThreadDeath(self);
}
- RemoveFromThreadGroup(soa);
// this.nativePeer = 0;
if (Runtime::Current()->IsActiveTransaction()) {
@@ -3080,6 +3080,8 @@
UNREACHABLE();
}
+ ReadBarrier::MaybeAssertToSpaceInvariant(exception.Ptr());
+
// This is a real exception: let the instrumentation know about it.
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
if (instrumentation->HasExceptionThrownListeners() &&
@@ -3121,6 +3123,15 @@
QuickExceptionHandler exception_handler(this, false);
exception_handler.FindCatch(exception);
exception_handler.UpdateInstrumentationStack();
+ if (exception_handler.GetClearException()) {
+ // Exception was cleared as part of delivery.
+ DCHECK(!IsExceptionPending());
+ } else {
+ // Exception was put back with a throw location.
+ DCHECK(IsExceptionPending());
+ // Check the to-space invariant on the re-installed exception (if applicable).
+ ReadBarrier::MaybeAssertToSpaceInvariant(GetException());
+ }
exception_handler.DoLongJump();
}
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 3fe18c7..b72dec6 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 @@
}
}
-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 @@
// 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 @@
*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 @@
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* 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 @@
}
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 739681d..4cb06c1 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -81,13 +81,10 @@
// 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 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 ee8eb36..e846c98 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 @@
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 @@
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 e4ad55d..ee428ed 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -431,7 +431,7 @@
}
}
if ((verifier.encountered_failure_types_ & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
- method->AddAccessFlags(kAccMustCountLocks);
+ method->SetMustCountLocks();
}
}
} else {
@@ -616,18 +616,11 @@
}
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 @@
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 @@
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 @@
// 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 @@
}
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 @@
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 @@
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 @@
} else if (inst->IsReturn()) {
GetInstructionFlags(dex_pc).SetCompileTimeInfoPointAndReturn();
}
- dex_pc += inst->SizeInCodeUnits();
- inst = inst->Next();
}
return true;
}
@@ -1671,9 +1656,10 @@
}
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 @@
* 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 @@
}
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 @@
}
}
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()) - 1);
}
// To dump the state of the verify after a method, do something like:
// if (dex_file_->PrettyMethod(dex_method_idx_) ==
@@ -2340,17 +2329,17 @@
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 @@
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:
* ...;
@@ -2663,9 +2652,9 @@
* - when vX == vY.
*/
if (!CurrentInsnFlags()->IsBranchTarget() &&
- (Instruction::INSTANCE_OF == instance_of_inst->Opcode()) &&
- (inst->VRegA_21t() == instance_of_inst->VRegA_22c()) &&
- (instance_of_inst->VRegA_22c() != instance_of_inst->VRegB_22c())) {
+ (Instruction::INSTANCE_OF == instance_of_inst.Opcode()) &&
+ (inst->VRegA_21t() == instance_of_inst.VRegA_22c()) &&
+ (instance_of_inst.VRegA_22c() != instance_of_inst.VRegB_22c())) {
// Check the type of the instance-of is different than that of registers type, as if they
// are the same there is no work to be done here. Check that the conversion is not to or
// from an unresolved type as type information is imprecise. If the instance-of is to an
@@ -2676,9 +2665,9 @@
// type is assignable to the original then allow optimization. This check is performed to
// ensure that subsequent merges don't lose type information - such as becoming an
// interface from a class that would lose information relevant to field checks.
- const RegType& orig_type = work_line_->GetRegisterType(this, instance_of_inst->VRegB_22c());
+ const RegType& orig_type = work_line_->GetRegisterType(this, instance_of_inst.VRegB_22c());
const RegType& cast_type = ResolveClass<CheckAccess::kYes>(
- dex::TypeIndex(instance_of_inst->VRegC_22c()));
+ dex::TypeIndex(instance_of_inst.VRegC_22c()));
if (!orig_type.Equals(cast_type) &&
!cast_type.IsUnresolvedTypes() && !orig_type.IsUnresolvedTypes() &&
@@ -2695,7 +2684,7 @@
}
update_line->CopyFromLine(work_line_.get());
update_line->SetRegisterType<LockOp::kKeep>(this,
- instance_of_inst->VRegB_22c(),
+ instance_of_inst.VRegB_22c(),
cast_type);
if (!GetInstructionFlags(instance_of_idx).IsBranchTarget() && 0 != instance_of_idx) {
// See if instance-of was preceded by a move-object operation, common due to the small
@@ -2710,26 +2699,26 @@
work_insn_idx_)) {
break;
}
- const Instruction* move_inst = Instruction::At(code_item_->insns_ + move_idx);
- switch (move_inst->Opcode()) {
+ 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()) {
+ if (move_inst.VRegA_12x() == instance_of_inst.VRegB_22c()) {
update_line->SetRegisterType<LockOp::kKeep>(this,
- move_inst->VRegB_12x(),
+ move_inst.VRegB_12x(),
cast_type);
}
break;
case Instruction::MOVE_OBJECT_FROM16:
- if (move_inst->VRegA_22x() == instance_of_inst->VRegB_22c()) {
+ if (move_inst.VRegA_22x() == instance_of_inst.VRegB_22c()) {
update_line->SetRegisterType<LockOp::kKeep>(this,
- move_inst->VRegB_22x(),
+ move_inst.VRegB_22x(),
cast_type);
}
break;
case Instruction::MOVE_OBJECT_16:
- if (move_inst->VRegA_32x() == instance_of_inst->VRegB_22c()) {
+ if (move_inst.VRegA_32x() == instance_of_inst.VRegB_22c()) {
update_line->SetRegisterType<LockOp::kKeep>(this,
- move_inst->VRegB_32x(),
+ move_inst.VRegB_32x(),
cast_type);
}
break;
@@ -3648,7 +3637,7 @@
* 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 0c64b7d..7aab726 100644
--- a/sigchainlib/Android.bp
+++ b/sigchainlib/Android.bp
@@ -25,9 +25,6 @@
srcs: ["sigchain.cc"],
},
target: {
- host: {
- host_ldlibs: ["-ldl"],
- },
android: {
shared_libs: ["liblog"],
},
@@ -49,9 +46,6 @@
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 a399289..74b5a90 100644
--- a/simulator/Android.bp
+++ b/simulator/Android.bp
@@ -73,7 +73,7 @@
],
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 7e85ab1..1d05160 100644
--- a/test/004-JniTest/expected.txt
+++ b/test/004-JniTest/expected.txt
@@ -60,3 +60,4 @@
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 0000000..8fe0e0a
--- /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 fe5f4e3..871107c 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 @@
testCriticalNativeMethods();
testClinitMethodLookup();
+
+ testDoubleLoad(args[0]);
}
private static native boolean registerNativesJniTest();
@@ -346,6 +351,57 @@
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 1005b77..2cfc0d7 100644
--- a/test/063-process-manager/src/Main.java
+++ b/test/063-process-manager/src/Main.java
@@ -10,7 +10,7 @@
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 @@
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 @@
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 @@
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 f5cbc2a..3f7bb56 100644
--- a/test/088-monitor-verification/src/Main.java
+++ b/test/088-monitor-verification/src/Main.java
@@ -25,7 +25,7 @@
/**
* 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 @@
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/1923-frame-pop/src/art/Trace.java b/test/1923-frame-pop/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/1923-frame-pop/src/art/Trace.java
+++ b/test/1923-frame-pop/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/1924-frame-pop-toggle/src/art/Trace.java b/test/1924-frame-pop-toggle/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/1924-frame-pop-toggle/src/art/Trace.java
+++ b/test/1924-frame-pop-toggle/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/1925-self-frame-pop/src/art/Trace.java b/test/1925-self-frame-pop/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/1925-self-frame-pop/src/art/Trace.java
+++ b/test/1925-self-frame-pop/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/1926-missed-frame-pop/src/art/Trace.java b/test/1926-missed-frame-pop/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/1926-missed-frame-pop/src/art/Trace.java
+++ b/test/1926-missed-frame-pop/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/1930-monitor-info/src/art/Monitors.java b/test/1930-monitor-info/src/art/Monitors.java
index b28a3ee..7fe2b60 100644
--- a/test/1930-monitor-info/src/art/Monitors.java
+++ b/test/1930-monitor-info/src/art/Monitors.java
@@ -36,12 +36,40 @@
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 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 @@
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 @@
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 a7fa1c7..ee03d73 100644
--- a/test/1930-monitor-info/src/art/Test1930.java
+++ b/test/1930-monitor-info/src/art/Test1930.java
@@ -96,7 +96,7 @@
printMonitorUsage(lk);
sem.release();
try {
- lk.wait();
+ lk.DoWait();
} catch (Exception e) {
throw new Error("Error waiting!", e);
}
@@ -107,7 +107,7 @@
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 b28a3ee..7fe2b60 100644
--- a/test/1931-monitor-events/src/art/Monitors.java
+++ b/test/1931-monitor-events/src/art/Monitors.java
@@ -36,12 +36,40 @@
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 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 @@
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 @@
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 b28a3ee..7fe2b60 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 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 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 @@
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 @@
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 b28a3ee..7fe2b60 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 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 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 @@
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 @@
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 e21c395..194a043 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 @@
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/1935-get-set-current-frame-jit/expected.txt b/test/1935-get-set-current-frame-jit/expected.txt
new file mode 100644
index 0000000..fed993c
--- /dev/null
+++ b/test/1935-get-set-current-frame-jit/expected.txt
@@ -0,0 +1,7 @@
+JNI_OnLoad called
+From GetLocalInt(), value is 42
+isInterpreted? true
+ Value is '42'
+Setting TARGET to 1337
+isInterpreted? true
+ Value is '1337'
diff --git a/test/1935-get-set-current-frame-jit/info.txt b/test/1935-get-set-current-frame-jit/info.txt
new file mode 100644
index 0000000..7342af7
--- /dev/null
+++ b/test/1935-get-set-current-frame-jit/info.txt
@@ -0,0 +1,2 @@
+Tests for jvmti get/set Local variable in the currently executing method frame.
+
diff --git a/test/1935-get-set-current-frame-jit/run b/test/1935-get-set-current-frame-jit/run
new file mode 100755
index 0000000..51875a7
--- /dev/null
+++ b/test/1935-get-set-current-frame-jit/run
@@ -0,0 +1,18 @@
+#!/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.
+
+# Ask for stack traces to be dumped to a file rather than to stdout.
+./default-run "$@" --jvmti
diff --git a/test/1935-get-set-current-frame-jit/src/Main.java b/test/1935-get-set-current-frame-jit/src/Main.java
new file mode 100644
index 0000000..eb0a637
--- /dev/null
+++ b/test/1935-get-set-current-frame-jit/src/Main.java
@@ -0,0 +1,162 @@
+/*
+ * 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 art.Locals;
+import art.StackTrace;
+import art.Suspension;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.util.concurrent.Semaphore;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.function.Consumer;
+
+public class Main {
+ public static final int SET_VALUE = 1337;
+ public static final String TARGET_VAR = "TARGET";
+
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+ Locals.EnableLocalVariableAccess();
+ runGet();
+ runSet();
+ }
+
+ public static void reportValue(Object val) {
+ System.out.println("\tValue is '" + val + "'");
+ }
+
+ public static class IntRunner implements Runnable {
+ private volatile boolean continueBusyLoop;
+ private volatile boolean inBusyLoop;
+ public IntRunner() {
+ this.continueBusyLoop = true;
+ this.inBusyLoop = false;
+ }
+ public void run() {
+ int TARGET = 42;
+ // We will suspend the thread during this loop.
+ while (continueBusyLoop) {
+ inBusyLoop = true;
+ }
+ int i = 0;
+ while (Main.isInterpreted() && i < 10000) {
+ Main.ensureJitCompiled(IntRunner.class, "run");
+ i++;
+ }
+ // We shouldn't be doing OSR since we are using JVMTI and the get/set local will push us to
+ // interpreter.
+ System.out.println("isInterpreted? " + Main.isInterpreted());
+ reportValue(TARGET);
+ }
+ public void waitForBusyLoopStart() { while (!inBusyLoop) {} }
+ public void finish() {
+ continueBusyLoop = false;
+ }
+ }
+
+ public static void runGet() throws Exception {
+ Method target = IntRunner.class.getDeclaredMethod("run");
+ // Get Int
+ IntRunner int_runner = new IntRunner();
+ Thread target_get = new Thread(int_runner, "GetLocalInt - Target");
+ target_get.start();
+ int_runner.waitForBusyLoopStart();
+ try {
+ Suspension.suspend(target_get);
+ } catch (Exception e) {
+ System.out.println("FAIL: got " + e);
+ e.printStackTrace();
+ int_runner.finish();
+ target_get.join();
+ return;
+ }
+ try {
+ StackTrace.StackFrameData frame = FindStackFrame(target_get, target);
+ int depth = frame.depth;
+ if (depth != 0) { throw new Error("Expected depth 0 but got " + depth); }
+ int slot = FindSlot(frame);
+ int value = Locals.GetLocalVariableInt(target_get, depth, slot);
+ System.out.println("From GetLocalInt(), value is " + value);
+ } finally {
+ Suspension.resume(target_get);
+ int_runner.finish();
+ target_get.join();
+ }
+ }
+
+ public static void runSet() throws Exception {
+ Method target = IntRunner.class.getDeclaredMethod("run");
+ // Set Int
+ IntRunner int_runner = new IntRunner();
+ Thread target_set = new Thread(int_runner, "SetLocalInt - Target");
+ target_set.start();
+ int_runner.waitForBusyLoopStart();
+ try {
+ Suspension.suspend(target_set);
+ } catch (Exception e) {
+ System.out.println("FAIL: got " + e);
+ e.printStackTrace();
+ int_runner.finish();
+ target_set.join();
+ return;
+ }
+ try {
+ StackTrace.StackFrameData frame = FindStackFrame(target_set, target);
+ int depth = frame.depth;
+ if (depth != 0) { throw new Error("Expected depth 0 but got " + depth); }
+ int slot = FindSlot(frame);
+ System.out.println("Setting TARGET to " + SET_VALUE);
+ Locals.SetLocalVariableInt(target_set, depth, slot, SET_VALUE);
+ } finally {
+ Suspension.resume(target_set);
+ int_runner.finish();
+ target_set.join();
+ }
+ }
+
+ public static int FindSlot(StackTrace.StackFrameData frame) throws Exception {
+ long loc = frame.current_location;
+ for (Locals.VariableDescription var : Locals.GetLocalVariableTable(frame.method)) {
+ if (var.start_location <= loc &&
+ var.length + var.start_location > loc &&
+ var.name.equals(TARGET_VAR)) {
+ return var.slot;
+ }
+ }
+ throw new Error(
+ "Unable to find variable " + TARGET_VAR + " in " + frame.method + " at loc " + loc);
+ }
+
+ private static StackTrace.StackFrameData FindStackFrame(Thread thr, Method target) {
+ for (StackTrace.StackFrameData frame : StackTrace.GetStackTrace(thr)) {
+ if (frame.method.equals(target)) {
+ return frame;
+ }
+ }
+ throw new Error("Unable to find stack frame in method " + target + " on thread " + thr);
+ }
+
+ public static native void ensureJitCompiled(Class k, String f);
+ public static native boolean isInterpreted();
+}
diff --git a/test/1935-get-set-current-frame-jit/src/art/Breakpoint.java b/test/1935-get-set-current-frame-jit/src/art/Breakpoint.java
new file mode 100644
index 0000000..bbb89f7
--- /dev/null
+++ b/test/1935-get-set-current-frame-jit/src/art/Breakpoint.java
@@ -0,0 +1,202 @@
+/*
+ * 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 art;
+
+import java.lang.reflect.Executable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Objects;
+
+public class Breakpoint {
+ public static class Manager {
+ public static class BP {
+ public final Executable method;
+ public final long location;
+
+ public BP(Executable method) {
+ this(method, getStartLocation(method));
+ }
+
+ public BP(Executable method, long location) {
+ this.method = method;
+ this.location = location;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return (other instanceof BP) &&
+ method.equals(((BP)other).method) &&
+ location == ((BP)other).location;
+ }
+
+ @Override
+ public String toString() {
+ return method.toString() + " @ " + getLine();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(method, location);
+ }
+
+ public int getLine() {
+ try {
+ LineNumber[] lines = getLineNumberTable(method);
+ int best = -1;
+ for (LineNumber l : lines) {
+ if (l.location > location) {
+ break;
+ } else {
+ best = l.line;
+ }
+ }
+ return best;
+ } catch (Exception e) {
+ return -1;
+ }
+ }
+ }
+
+ private Set<BP> breaks = new HashSet<>();
+
+ public void setBreakpoints(BP... bs) {
+ for (BP b : bs) {
+ if (breaks.add(b)) {
+ Breakpoint.setBreakpoint(b.method, b.location);
+ }
+ }
+ }
+ public void setBreakpoint(Executable method, long location) {
+ setBreakpoints(new BP(method, location));
+ }
+
+ public void clearBreakpoints(BP... bs) {
+ for (BP b : bs) {
+ if (breaks.remove(b)) {
+ Breakpoint.clearBreakpoint(b.method, b.location);
+ }
+ }
+ }
+ public void clearBreakpoint(Executable method, long location) {
+ clearBreakpoints(new BP(method, location));
+ }
+
+ public void clearAllBreakpoints() {
+ clearBreakpoints(breaks.toArray(new BP[0]));
+ }
+ }
+
+ public static void startBreakpointWatch(Class<?> methodClass,
+ Executable breakpointReached,
+ Thread thr) {
+ startBreakpointWatch(methodClass, breakpointReached, false, thr);
+ }
+
+ /**
+ * Enables the trapping of breakpoint events.
+ *
+ * If allowRecursive == true then breakpoints will be sent even if one is currently being handled.
+ */
+ public static native void startBreakpointWatch(Class<?> methodClass,
+ Executable breakpointReached,
+ boolean allowRecursive,
+ Thread thr);
+ public static native void stopBreakpointWatch(Thread thr);
+
+ public static final class LineNumber implements Comparable<LineNumber> {
+ public final long location;
+ public final int line;
+
+ private LineNumber(long loc, int line) {
+ this.location = loc;
+ this.line = line;
+ }
+
+ public boolean equals(Object other) {
+ return other instanceof LineNumber && ((LineNumber)other).line == line &&
+ ((LineNumber)other).location == location;
+ }
+
+ public int compareTo(LineNumber other) {
+ int v = Integer.valueOf(line).compareTo(Integer.valueOf(other.line));
+ if (v != 0) {
+ return v;
+ } else {
+ return Long.valueOf(location).compareTo(Long.valueOf(other.location));
+ }
+ }
+ }
+
+ public static native void setBreakpoint(Executable m, long loc);
+ public static void setBreakpoint(Executable m, LineNumber l) {
+ setBreakpoint(m, l.location);
+ }
+
+ public static native void clearBreakpoint(Executable m, long loc);
+ public static void clearBreakpoint(Executable m, LineNumber l) {
+ clearBreakpoint(m, l.location);
+ }
+
+ private static native Object[] getLineNumberTableNative(Executable m);
+ public static LineNumber[] getLineNumberTable(Executable m) {
+ Object[] nativeTable = getLineNumberTableNative(m);
+ long[] location = (long[])(nativeTable[0]);
+ int[] lines = (int[])(nativeTable[1]);
+ if (lines.length != location.length) {
+ throw new Error("Lines and locations have different lengths!");
+ }
+ LineNumber[] out = new LineNumber[lines.length];
+ for (int i = 0; i < lines.length; i++) {
+ out[i] = new LineNumber(location[i], lines[i]);
+ }
+ return out;
+ }
+
+ public static native long getStartLocation(Executable m);
+
+ public static int locationToLine(Executable m, long location) {
+ try {
+ Breakpoint.LineNumber[] lines = Breakpoint.getLineNumberTable(m);
+ int best = -1;
+ for (Breakpoint.LineNumber l : lines) {
+ if (l.location > location) {
+ break;
+ } else {
+ best = l.line;
+ }
+ }
+ return best;
+ } catch (Exception e) {
+ return -1;
+ }
+ }
+
+ public static long lineToLocation(Executable m, int line) throws Exception {
+ try {
+ Breakpoint.LineNumber[] lines = Breakpoint.getLineNumberTable(m);
+ for (Breakpoint.LineNumber l : lines) {
+ if (l.line == line) {
+ return l.location;
+ }
+ }
+ throw new Exception("Unable to find line " + line + " in " + m);
+ } catch (Exception e) {
+ throw new Exception("Unable to get line number info for " + m, e);
+ }
+ }
+}
+
diff --git a/test/1935-get-set-current-frame-jit/src/art/Locals.java b/test/1935-get-set-current-frame-jit/src/art/Locals.java
new file mode 100644
index 0000000..22e21be
--- /dev/null
+++ b/test/1935-get-set-current-frame-jit/src/art/Locals.java
@@ -0,0 +1,121 @@
+/*
+ * 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 art;
+
+import java.lang.reflect.Executable;
+import java.util.Objects;
+
+public class Locals {
+ public static native void EnableLocalVariableAccess();
+
+ public static class VariableDescription {
+ public final long start_location;
+ public final int length;
+ public final String name;
+ public final String signature;
+ public final String generic_signature;
+ public final int slot;
+
+ public VariableDescription(
+ long start, int length, String name, String sig, String gen_sig, int slot) {
+ this.start_location = start;
+ this.length = length;
+ this.name = name;
+ this.signature = sig;
+ this.generic_signature = gen_sig;
+ this.slot = slot;
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "VariableDescription { " +
+ "Sig: '%s', Name: '%s', Gen_sig: '%s', slot: %d, start: %d, len: %d" +
+ "}",
+ this.signature,
+ this.name,
+ this.generic_signature,
+ this.slot,
+ this.start_location,
+ this.length);
+ }
+ public boolean equals(Object other) {
+ if (!(other instanceof VariableDescription)) {
+ return false;
+ } else {
+ VariableDescription v = (VariableDescription)other;
+ return Objects.equals(v.signature, signature) &&
+ Objects.equals(v.name, name) &&
+ Objects.equals(v.generic_signature, generic_signature) &&
+ v.slot == slot &&
+ v.start_location == start_location &&
+ v.length == length;
+ }
+ }
+ public int hashCode() {
+ return Objects.hash(this.signature, this.name, this.generic_signature, this.slot,
+ this.start_location, this.length);
+ }
+ }
+
+ public static native VariableDescription[] GetLocalVariableTable(Executable e);
+
+ public static VariableDescription GetVariableAtLine(
+ Executable e, String name, String sig, int line) throws Exception {
+ return GetVariableAtLocation(e, name, sig, Breakpoint.lineToLocation(e, line));
+ }
+
+ public static VariableDescription GetVariableAtLocation(
+ Executable e, String name, String sig, long loc) {
+ VariableDescription[] vars = GetLocalVariableTable(e);
+ for (VariableDescription var : vars) {
+ if (var.start_location <= loc &&
+ var.length + var.start_location > loc &&
+ var.name.equals(name) &&
+ var.signature.equals(sig)) {
+ return var;
+ }
+ }
+ throw new Error(
+ "Unable to find variable " + name + " (sig: " + sig + ") in " + e + " at loc " + loc);
+ }
+
+ public static native int GetLocalVariableInt(Thread thr, int depth, int slot);
+ public static native long GetLocalVariableLong(Thread thr, int depth, int slot);
+ public static native float GetLocalVariableFloat(Thread thr, int depth, int slot);
+ public static native double GetLocalVariableDouble(Thread thr, int depth, int slot);
+ public static native Object GetLocalVariableObject(Thread thr, int depth, int slot);
+ public static native Object GetLocalInstance(Thread thr, int depth);
+
+ public static void SetLocalVariableInt(Thread thr, int depth, int slot, Object val) {
+ SetLocalVariableInt(thr, depth, slot, ((Number)val).intValue());
+ }
+ public static void SetLocalVariableLong(Thread thr, int depth, int slot, Object val) {
+ SetLocalVariableLong(thr, depth, slot, ((Number)val).longValue());
+ }
+ public static void SetLocalVariableFloat(Thread thr, int depth, int slot, Object val) {
+ SetLocalVariableFloat(thr, depth, slot, ((Number)val).floatValue());
+ }
+ public static void SetLocalVariableDouble(Thread thr, int depth, int slot, Object val) {
+ SetLocalVariableDouble(thr, depth, slot, ((Number)val).doubleValue());
+ }
+ public static native void SetLocalVariableInt(Thread thr, int depth, int slot, int val);
+ public static native void SetLocalVariableLong(Thread thr, int depth, int slot, long val);
+ public static native void SetLocalVariableFloat(Thread thr, int depth, int slot, float val);
+ public static native void SetLocalVariableDouble(Thread thr, int depth, int slot, double val);
+ public static native void SetLocalVariableObject(Thread thr, int depth, int slot, Object val);
+}
diff --git a/test/1935-get-set-current-frame-jit/src/art/StackTrace.java b/test/1935-get-set-current-frame-jit/src/art/StackTrace.java
new file mode 100644
index 0000000..2ea2f20
--- /dev/null
+++ b/test/1935-get-set-current-frame-jit/src/art/StackTrace.java
@@ -0,0 +1,68 @@
+/*
+ * 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 art;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
+
+public class StackTrace {
+ public static class StackFrameData {
+ public final Thread thr;
+ public final Executable method;
+ public final long current_location;
+ public final int depth;
+
+ public StackFrameData(Thread thr, Executable e, long loc, int depth) {
+ this.thr = thr;
+ this.method = e;
+ this.current_location = loc;
+ this.depth = depth;
+ }
+ @Override
+ public String toString() {
+ return String.format(
+ "StackFrameData { thr: '%s', method: '%s', loc: %d, depth: %d }",
+ this.thr,
+ this.method,
+ this.current_location,
+ this.depth);
+ }
+ }
+
+ public static native int GetStackDepth(Thread thr);
+
+ private static native StackFrameData[] nativeGetStackTrace(Thread thr);
+
+ public static StackFrameData[] GetStackTrace(Thread thr) {
+ // The RI seems to give inconsistent (and sometimes nonsensical) results if the thread is not
+ // suspended. The spec says that not being suspended is fine but since we want this to be
+ // consistent we will suspend for the RI.
+ boolean suspend_thread =
+ !System.getProperty("java.vm.name").equals("Dalvik") &&
+ !thr.equals(Thread.currentThread()) &&
+ !Suspension.isSuspended(thr);
+ if (suspend_thread) {
+ Suspension.suspend(thr);
+ }
+ StackFrameData[] out = nativeGetStackTrace(thr);
+ if (suspend_thread) {
+ Suspension.resume(thr);
+ }
+ return out;
+ }
+}
+
diff --git a/test/1935-get-set-current-frame-jit/src/art/Suspension.java b/test/1935-get-set-current-frame-jit/src/art/Suspension.java
new file mode 100644
index 0000000..16e62cc
--- /dev/null
+++ b/test/1935-get-set-current-frame-jit/src/art/Suspension.java
@@ -0,0 +1,30 @@
+/*
+ * 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 art;
+
+public class Suspension {
+ // Suspends a thread using jvmti.
+ public native static void suspend(Thread thr);
+
+ // Resumes a thread using jvmti.
+ public native static void resume(Thread thr);
+
+ public native static boolean isSuspended(Thread thr);
+
+ public native static int[] suspendList(Thread... threads);
+ public native static int[] resumeList(Thread... threads);
+}
diff --git a/test/1936-thread-end-events/check b/test/1936-thread-end-events/check
new file mode 100644
index 0000000..8a84388
--- /dev/null
+++ b/test/1936-thread-end-events/check
@@ -0,0 +1,22 @@
+#!/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.
+
+# The RI sends an extra event that art doesn't. Add it to the expected output.
+if [[ "$TEST_RUNTIME" == "jvm" ]]; then
+ patch -p0 expected.txt < jvm-expected.patch >/dev/null
+fi
+
+./default-check "$@"
diff --git a/test/1936-thread-end-events/expected.txt b/test/1936-thread-end-events/expected.txt
new file mode 100644
index 0000000..6b71c5e
--- /dev/null
+++ b/test/1936-thread-end-events/expected.txt
@@ -0,0 +1,42 @@
+Entered public static void art.Test1936.foo()
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
+Entered void java.lang.ThreadGroup.threadTerminated(java.lang.Thread)
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
+Entered private void java.lang.ThreadGroup.remove(java.lang.Thread)
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
+Entered public static native void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
+Entered public static void art.Test1936.NotifyThreadEnd(java.lang.Thread)
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
+Entered public static void art.Test1936.foo()
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
diff --git a/test/1936-thread-end-events/info.txt b/test/1936-thread-end-events/info.txt
new file mode 100644
index 0000000..51986c4
--- /dev/null
+++ b/test/1936-thread-end-events/info.txt
@@ -0,0 +1,6 @@
+Tests JVMTI ThreadEnd bug
+
+We had a bug where we were still sending events after JVMTI_EVENT_THREAD_END due
+to where we sent the event. This test ensures that the placement of the
+THREAD_END event is correct.
+
diff --git a/test/1936-thread-end-events/jvm-expected.patch b/test/1936-thread-end-events/jvm-expected.patch
new file mode 100644
index 0000000..ddb30a3
--- /dev/null
+++ b/test/1936-thread-end-events/jvm-expected.patch
@@ -0,0 +1,16 @@
+7a8,14
+> Entered private void java.lang.Thread.exit()
+> Thread: test-thread
+> | alive: true
+> | interrupted: false
+> | daemon: false
+> | group: java.lang.ThreadGroup[name=main,maxpri=10]
+>
+34c41
+< | group: java.lang.ThreadGroup[name=main,maxpri=10]
+---
+> | group: null
+41c48
+< | group: java.lang.ThreadGroup[name=main,maxpri=10]
+---
+> | group: null
diff --git a/test/1936-thread-end-events/method_trace.cc b/test/1936-thread-end-events/method_trace.cc
new file mode 100644
index 0000000..019b6a9
--- /dev/null
+++ b/test/1936-thread-end-events/method_trace.cc
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 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 <inttypes.h>
+
+#include <cstdio>
+#include <memory>
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+
+#include "jni.h"
+#include "jvmti.h"
+#include "scoped_local_ref.h"
+
+// Test infrastructure
+#include "jni_binder.h"
+#include "jni_helper.h"
+#include "jvmti_helper.h"
+#include "test_env.h"
+#include "ti_macros.h"
+
+namespace art {
+namespace Test989StackTraceThrow {
+
+extern "C" JNIEXPORT
+jfloat JNICALL Java_art_Test989_returnFloatNative(JNIEnv* env, jclass klass) {
+ jmethodID targetMethod = env->GetStaticMethodID(klass, "doGetFloat", "()F");
+ return env->CallStaticFloatMethod(klass, targetMethod);
+}
+extern "C" JNIEXPORT
+jdouble JNICALL Java_art_Test989_returnDoubleNative(JNIEnv* env, jclass klass) {
+ jmethodID targetMethod = env->GetStaticMethodID(klass, "doGetDouble", "()D");
+ return env->CallStaticDoubleMethod(klass, targetMethod);
+}
+
+extern "C" JNIEXPORT jobject JNICALL Java_art_Test989_returnValueNative(JNIEnv* env, jclass klass) {
+ jmethodID targetMethod = env->GetStaticMethodID(klass, "mkTestObject", "()Ljava/lang/Object;");
+ return env->CallStaticObjectMethod(klass, targetMethod);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test989_doNothingNative(JNIEnv* env ATTRIBUTE_UNUSED,
+ jclass klass ATTRIBUTE_UNUSED) {
+ return;
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test989_throwANative(JNIEnv* env,
+ jclass klass) {
+ jmethodID targetMethod = env->GetStaticMethodID(klass, "doThrowA", "()V");
+ env->CallStaticVoidMethod(klass, targetMethod);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test989_acceptValueNative(JNIEnv* env,
+ jclass klass,
+ jobject arg) {
+ jmethodID targetMethod = env->GetStaticMethodID(klass, "printObject", "(Ljava/lang/Object;)V");
+ env->CallStaticVoidMethod(klass, targetMethod, arg);
+}
+
+} // namespace Test989StackTraceThrow
+} // namespace art
+
diff --git a/test/1936-thread-end-events/run b/test/1936-thread-end-events/run
new file mode 100755
index 0000000..51875a7
--- /dev/null
+++ b/test/1936-thread-end-events/run
@@ -0,0 +1,18 @@
+#!/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.
+
+# Ask for stack traces to be dumped to a file rather than to stdout.
+./default-run "$@" --jvmti
diff --git a/test/1936-thread-end-events/src/Main.java b/test/1936-thread-end-events/src/Main.java
new file mode 100644
index 0000000..da66fc3
--- /dev/null
+++ b/test/1936-thread-end-events/src/Main.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 Main {
+ public static void main(String[] args) throws Exception {
+ art.Test1936.run();
+ }
+}
diff --git a/test/1936-thread-end-events/src/art/Test1936.java b/test/1936-thread-end-events/src/art/Test1936.java
new file mode 100644
index 0000000..868deca
--- /dev/null
+++ b/test/1936-thread-end-events/src/art/Test1936.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package art;
+
+public class Test1936 {
+ public static void foo() {}
+
+ public static void NotifyThreadEnd(Thread me) {
+ // Don't actually do anything.
+ foo();
+ }
+
+ public static void NotifyMethodEntry(Object o) {
+ System.out.println("Entered " + o.toString());
+ Thread me = Thread.currentThread();
+ System.out.println(String.format(
+ "Thread: %s\n" +
+ " | alive: %b\n" +
+ " | interrupted: %b\n" +
+ " | daemon: %b\n" +
+ " | group: %s\n",
+ me.getName(), me.isAlive(), me.isInterrupted(), me.isDaemon(), me.getThreadGroup()));
+ }
+
+ public static native void waitForever();
+ private static void setupTracing(Thread target) throws Exception {
+ Trace.disableTracing(target);
+ Trace.enableTracing2(
+ Test1936.class,
+ Test1936.class.getDeclaredMethod("NotifyMethodEntry", Object.class),
+ /*exit*/null,
+ /*field_access*/null,
+ /*field_modify*/null,
+ /*single_step*/null,
+ /*thread_start*/null,
+ Test1936.class.getDeclaredMethod("NotifyThreadEnd", Thread.class),
+ target);
+ }
+
+
+ public static void run() throws Exception {
+ Thread t = new Thread(() -> {
+ try {
+ setupTracing(Thread.currentThread());
+ foo();
+ } catch (Exception e) {
+ System.out.println("Caught exception " + e + "!");
+ e.printStackTrace();
+ }
+ }, "test-thread");
+ t.start();
+ t.join();
+ }
+}
diff --git a/test/1936-thread-end-events/src/art/Trace.java b/test/1936-thread-end-events/src/art/Trace.java
new file mode 100644
index 0000000..8999bb1
--- /dev/null
+++ b/test/1936-thread-end-events/src/art/Trace.java
@@ -0,0 +1,68 @@
+/*
+ * 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 art;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class Trace {
+ public static native void enableTracing(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Thread thr);
+ public static native void disableTracing(Thread thr);
+
+ public static void enableFieldTracing(Class<?> methodClass,
+ Method fieldAccess,
+ Method fieldModify,
+ Thread thr) {
+ enableTracing(methodClass, null, null, fieldAccess, fieldModify, null, thr);
+ }
+
+ public static void enableMethodTracing(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Thread thr) {
+ enableTracing(methodClass, entryMethod, exitMethod, null, null, null, thr);
+ }
+
+ public static void enableSingleStepTracing(Class<?> methodClass,
+ Method singleStep,
+ Thread thr) {
+ enableTracing(methodClass, null, null, null, null, singleStep, thr);
+ }
+
+ public static native void watchFieldAccess(Field f);
+ public static native void watchFieldModification(Field f);
+ public static native void watchAllFieldAccesses();
+ public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
+}
diff --git a/test/442-checker-constant-folding/smali/TestCmp.smali b/test/442-checker-constant-folding/smali/TestCmp.smali
index df631bc..f55c837 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 eba5137..95c19ea 100644
--- a/test/442-checker-constant-folding/src/Main.java
+++ b/test/442-checker-constant-folding/src/Main.java
@@ -113,6 +113,19 @@
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 @@
/// 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 @@
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 @@
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/458-checker-instruct-simplification/src/Main.java b/test/458-checker-instruct-simplification/src/Main.java
index 5c36ce9..f36c261 100644
--- a/test/458-checker-instruct-simplification/src/Main.java
+++ b/test/458-checker-instruct-simplification/src/Main.java
@@ -2038,6 +2038,84 @@
return (value >> temp) + temp;
}
+ /// CHECK-START: int Main.$noinline$intUnnecessaryShiftModifications(int, int) instruction_simplifier (before)
+ /// CHECK: <<Value:i\d+>> ParameterValue
+ /// CHECK: <<Shift:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const32:i\d+>> IntConstant 32
+ /// CHECK-DAG: <<Const64:i\d+>> IntConstant 64
+ /// CHECK-DAG: <<Const96:i\d+>> IntConstant 96
+ /// CHECK-DAG: <<Const128:i\d+>> IntConstant 128
+ /// CHECK-DAG: <<Or:i\d+>> Or [<<Shift>>,<<Const32>>]
+ /// CHECK-DAG: <<Xor:i\d+>> Xor [<<Shift>>,<<Const64>>]
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Shift>>,<<Const96>>]
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Shift>>,<<Const128>>]
+ /// CHECK-DAG: <<Conv:b\d+>> TypeConversion [<<Shift>>]
+ /// CHECK-DAG: Shl [<<Value>>,<<Or>>]
+ /// CHECK-DAG: Shr [<<Value>>,<<Xor>>]
+ /// CHECK-DAG: UShr [<<Value>>,<<Add>>]
+ /// CHECK-DAG: Shl [<<Value>>,<<Sub>>]
+ /// CHECK-DAG: Shr [<<Value>>,<<Conv>>]
+
+ /// CHECK-START: int Main.$noinline$intUnnecessaryShiftModifications(int, int) instruction_simplifier (after)
+ /// CHECK: <<Value:i\d+>> ParameterValue
+ /// CHECK: <<Shift:i\d+>> ParameterValue
+ /// CHECK-DAG: Shl [<<Value>>,<<Shift>>]
+ /// CHECK-DAG: Shr [<<Value>>,<<Shift>>]
+ /// CHECK-DAG: UShr [<<Value>>,<<Shift>>]
+ /// CHECK-DAG: Shl [<<Value>>,<<Shift>>]
+ /// CHECK-DAG: Shr [<<Value>>,<<Shift>>]
+
+ public static int $noinline$intUnnecessaryShiftModifications(int value, int shift) {
+ if (doThrow) { throw new Error(); }
+ int c128 = 128;
+ return (value << (shift | 32)) +
+ (value >> (shift ^ 64)) +
+ (value >>> (shift + 96)) +
+ (value << (shift - c128)) + // Needs a named constant to generate Sub.
+ (value >> ((byte) shift));
+ }
+
+ /// CHECK-START: int Main.$noinline$intNecessaryShiftModifications(int, int) instruction_simplifier (before)
+ /// CHECK: <<Value:i\d+>> ParameterValue
+ /// CHECK: <<Shift:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const33:i\d+>> IntConstant 33
+ /// CHECK-DAG: <<Const65:i\d+>> IntConstant 65
+ /// CHECK-DAG: <<Const97:i\d+>> IntConstant 97
+ /// CHECK-DAG: <<Const129:i\d+>> IntConstant 129
+ /// CHECK-DAG: <<Or:i\d+>> Or [<<Shift>>,<<Const33>>]
+ /// CHECK-DAG: <<Xor:i\d+>> Xor [<<Shift>>,<<Const65>>]
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Shift>>,<<Const97>>]
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Shift>>,<<Const129>>]
+ /// CHECK-DAG: Shl [<<Value>>,<<Or>>]
+ /// CHECK-DAG: Shr [<<Value>>,<<Xor>>]
+ /// CHECK-DAG: UShr [<<Value>>,<<Add>>]
+ /// CHECK-DAG: Shl [<<Value>>,<<Sub>>]
+
+ /// CHECK-START: int Main.$noinline$intNecessaryShiftModifications(int, int) instruction_simplifier (after)
+ /// CHECK: <<Value:i\d+>> ParameterValue
+ /// CHECK: <<Shift:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const33:i\d+>> IntConstant 33
+ /// CHECK-DAG: <<Const65:i\d+>> IntConstant 65
+ /// CHECK-DAG: <<Const97:i\d+>> IntConstant 97
+ /// CHECK-DAG: <<Const129:i\d+>> IntConstant 129
+ /// CHECK-DAG: <<Or:i\d+>> Or [<<Shift>>,<<Const33>>]
+ /// CHECK-DAG: <<Xor:i\d+>> Xor [<<Shift>>,<<Const65>>]
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Shift>>,<<Const97>>]
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Shift>>,<<Const129>>]
+ /// CHECK-DAG: Shl [<<Value>>,<<Or>>]
+ /// CHECK-DAG: Shr [<<Value>>,<<Xor>>]
+ /// CHECK-DAG: UShr [<<Value>>,<<Add>>]
+ /// CHECK-DAG: Shl [<<Value>>,<<Sub>>]
+
+ public static int $noinline$intNecessaryShiftModifications(int value, int shift) {
+ if (doThrow) { throw new Error(); }
+ int c129 = 129;
+ return (value << (shift | 33)) +
+ (value >> (shift ^ 65)) +
+ (value >>> (shift + 97)) +
+ (value << (shift - c129)); // Needs a named constant to generate Sub.
+ }
+
/// CHECK-START: int Main.$noinline$intAddSubSimplifyArg1(int, int) instruction_simplifier (before)
/// CHECK: <<X:i\d+>> ParameterValue
/// CHECK: <<Y:i\d+>> ParameterValue
@@ -2363,14 +2441,22 @@
assertIntEquals(26, $noinline$runSmaliTestInt("SubSubConst3", 5));
assertIntEquals(0x5e6f7808, $noinline$intUnnecessaryShiftMasking(0xabcdef01, 3));
assertIntEquals(0x5e6f7808, $noinline$intUnnecessaryShiftMasking(0xabcdef01, 3 + 32));
- assertLongEquals(0xffffffffffffeaf3L, $noinline$longUnnecessaryShiftMasking(0xabcdef0123456789L, 50));
- assertLongEquals(0xffffffffffffeaf3L, $noinline$longUnnecessaryShiftMasking(0xabcdef0123456789L, 50 + 64));
+ assertLongEquals(0xffffffffffffeaf3L,
+ $noinline$longUnnecessaryShiftMasking(0xabcdef0123456789L, 50));
+ assertLongEquals(0xffffffffffffeaf3L,
+ $noinline$longUnnecessaryShiftMasking(0xabcdef0123456789L, 50 + 64));
assertIntEquals(0x2af37b, $noinline$intUnnecessaryWiderShiftMasking(0xabcdef01, 10));
assertIntEquals(0x2af37b, $noinline$intUnnecessaryWiderShiftMasking(0xabcdef01, 10 + 128));
- assertLongEquals(0xaf37bc048d159e24L, $noinline$longSmallerShiftMasking(0xabcdef0123456789L, 2));
- assertLongEquals(0xaf37bc048d159e24L, $noinline$longSmallerShiftMasking(0xabcdef0123456789L, 2 + 256));
+ assertLongEquals(0xaf37bc048d159e24L,
+ $noinline$longSmallerShiftMasking(0xabcdef0123456789L, 2));
+ assertLongEquals(0xaf37bc048d159e24L,
+ $noinline$longSmallerShiftMasking(0xabcdef0123456789L, 2 + 256));
assertIntEquals(0xfffd5e7c, $noinline$otherUseOfUnnecessaryShiftMasking(0xabcdef01, 13));
assertIntEquals(0xfffd5e7c, $noinline$otherUseOfUnnecessaryShiftMasking(0xabcdef01, 13 + 512));
+ assertIntEquals(0x5f49eb48, $noinline$intUnnecessaryShiftModifications(0xabcdef01, 2));
+ assertIntEquals(0xbd4c29b0, $noinline$intUnnecessaryShiftModifications(0xabcdef01, 3));
+ assertIntEquals(0xc0fed1ca, $noinline$intNecessaryShiftModifications(0xabcdef01, 2));
+ assertIntEquals(0x03578ebc, $noinline$intNecessaryShiftModifications(0xabcdef01, 3));
assertIntEquals(654321, $noinline$intAddSubSimplifyArg1(arg, 654321));
assertIntEquals(arg, $noinline$intAddSubSimplifyArg2(arg, 654321));
diff --git a/test/529-checker-unresolved/src/Main.java b/test/529-checker-unresolved/src/Main.java
index c2683ac..255ce78 100644
--- a/test/529-checker-unresolved/src/Main.java
+++ b/test/529-checker-unresolved/src/Main.java
@@ -45,21 +45,21 @@
}
/// 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: 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: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: 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 @@
}
/// 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: 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: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: 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 1f1920c..55873ea 100644
--- a/test/552-checker-sharpening/src/Main.java
+++ b/test/552-checker-sharpening/src/Main.java
@@ -63,16 +63,12 @@
/// 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 @@
/// 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 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 @@
}
}
- /// 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 @@
/// 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 @@
/// 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 0000000..2919f46
--- /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 0751783..8c6f069 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 @@
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 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/623-checker-loop-regressions/src/Main.java b/test/623-checker-loop-regressions/src/Main.java
index 418be30..f6d3bba 100644
--- a/test/623-checker-loop-regressions/src/Main.java
+++ b/test/623-checker-loop-regressions/src/Main.java
@@ -497,6 +497,13 @@
}
}
+ // Mixed of 16-bit and 8-bit array references.
+ static void castAndNarrow(byte[] x, char[] y) {
+ for (int i = 0; i < x.length; i++) {
+ x[i] = (byte) ((short) y[i] + 1);
+ }
+ }
+
public static void main(String[] args) {
expectEquals(10, earlyExitFirst(-1));
for (int i = 0; i <= 10; i++) {
@@ -650,6 +657,15 @@
expectEquals(2805, f[i]);
}
+ char[] cx = new char[259];
+ for (int i = 0; i < 259; i++) {
+ cx[i] = (char) (i - 100);
+ }
+ castAndNarrow(b1, cx);
+ for (int i = 0; i < 259; i++) {
+ expectEquals((byte)((short) cx[i] + 1), b1[i]);
+ }
+
System.out.println("passed");
}
diff --git a/test/638-checker-inline-caches/profile b/test/638-checker-inline-caches/profile
index 1ca6d7b..7756a16 100644
--- a/test/638-checker-inline-caches/profile
+++ b/test/638-checker-inline-caches/profile
@@ -1,6 +1,6 @@
-LMain;->inlineMonomorphicSubA(LSuper;)I+LSubA;
-LMain;->inlinePolymophicSubASubB(LSuper;)I+LSubA;,LSubB;
-LMain;->inlinePolymophicCrossDexSubASubC(LSuper;)I+LSubA;,LSubC;
-LMain;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;
-LMain;->inlineMissingTypes(LSuper;)I+missing_types
-LMain;->noInlineCache(LSuper;)I
+HSLMain;->inlineMonomorphicSubA(LSuper;)I+LSubA;
+HSLMain;->inlinePolymophicSubASubB(LSuper;)I+LSubA;,LSubB;
+HSLMain;->inlinePolymophicCrossDexSubASubC(LSuper;)I+LSubA;,LSubC;
+HSLMain;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;
+HSLMain;->inlineMissingTypes(LSuper;)I+missing_types
+HSLMain;->noInlineCache(LSuper;)I
diff --git a/test/643-checker-bogus-ic/profile b/test/643-checker-bogus-ic/profile
index cbf7796..540a935 100644
--- a/test/643-checker-bogus-ic/profile
+++ b/test/643-checker-bogus-ic/profile
@@ -1,2 +1,2 @@
-LMain;->inlineMonomorphic(LMain;)I+LUnrelated;
-LMain;->inlinePolymorphic(LMain;)I+LUnrelated;,LMain;
+SHLMain;->inlineMonomorphic(LMain;)I+LUnrelated;
+SHLMain;->inlinePolymorphic(LMain;)I+LUnrelated;,LMain;
diff --git a/test/645-checker-abs-simd/src/Main.java b/test/645-checker-abs-simd/src/Main.java
index c49d85d..57c51a6 100644
--- a/test/645-checker-abs-simd/src/Main.java
+++ b/test/645-checker-abs-simd/src/Main.java
@@ -131,6 +131,28 @@
}
}
+ /// CHECK-START: void Main.doitCastedChar(char[]) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START-ARM64: void Main.doitCastedChar(char[]) loop_optimization (after)
+ /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none
+ /// CHECK-DAG: VecLoad loop:<<Loop1>> outer_loop:none
+ /// CHECK-DAG: VecAbs loop:<<Loop1>> outer_loop:none
+ /// CHECK-DAG: VecStore loop:<<Loop1>> outer_loop:none
+ /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:none
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:none
+ //
+ /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
+ //
+ private static void doitCastedChar(char[] x) {
+ for (int i = 0; i < x.length; i++) {
+ x[i] = (char) Math.abs((short) x[i]);
+ }
+ }
+
/// CHECK-START: void Main.doitInt(int[]) loop_optimization (before)
/// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
@@ -298,7 +320,7 @@
xc[i] = (char) i;
}
doitChar(xc);
- for (int i = 0; i < 1024 *64; i++) {
+ for (int i = 0; i < 1024 * 64; i++) {
expectEquals32((char) Math.abs((char) i), xc[i]);
}
short[] xs = new short[1024 * 64];
@@ -309,6 +331,13 @@
for (int i = 0; i < 1024 * 64; i++) {
expectEquals32((short) Math.abs((short) i), xs[i]);
}
+ for (int i = 0; i < 1024 * 64; i++) {
+ xc[i] = (char) i;
+ }
+ doitCastedChar(xc);
+ for (int i = 0; i < 1024 * 64; i++) {
+ expectEquals32((char) Math.abs((short) i), xc[i]);
+ }
// Set up minint32, maxint32 and some others.
int[] xi = new int[8];
xi[0] = 0x80000000;
diff --git a/test/648-inline-caches-unresolved/profile b/test/648-inline-caches-unresolved/profile
index 92c0a41..06bc8ad 100644
--- a/test/648-inline-caches-unresolved/profile
+++ b/test/648-inline-caches-unresolved/profile
@@ -1 +1 @@
-LMain;->inlineMonomorphicUnresolvedSuper(Ljava/lang/Object;)Ljava/lang/String;+LSubclass;
+SHLMain;->inlineMonomorphicUnresolvedSuper(Ljava/lang/Object;)Ljava/lang/String;+LSubclass;
diff --git a/test/651-checker-byte-simd-minmax/src/Main.java b/test/651-checker-byte-simd-minmax/src/Main.java
index e018b56..9643b90 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 @@
}
}
+ /// 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 @@
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 57cad9b..8a0262c 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 @@
}
}
+ /// 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 @@
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 4f2a7a4..ffbf73b 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 @@
}
}
+ /// 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 @@
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 091633f..39a126f 100644
--- a/test/656-checker-simd-opt/src/Main.java
+++ b/test/656-checker-simd-opt/src/Main.java
@@ -92,7 +92,91 @@
}
}
- 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 @@
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]);
- }
+ }
+
+ 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;
}
- {
- 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]);
- }
+ 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;
- }
- 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 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 0000000..b0aad4d
--- /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 0000000..b56c119
--- /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 0000000..72d1c24
--- /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 0000000..b0aad4d
--- /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 0000000..b56c119
--- /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 0000000..2535d49
--- /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 0000000..b0aad4d
--- /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 0000000..b56c119
--- /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 0000000..0daeedd
--- /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 0000000..b0aad4d
--- /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 0000000..b56c119
--- /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 0000000..06f62bd
--- /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 0000000..b0aad4d
--- /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 0000000..b56c119
--- /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 0000000..d94308e
--- /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 0000000..b0aad4d
--- /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 0000000..b56c119
--- /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 0000000..7acc490
--- /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/660-checker-simd-sad-short3/expected.txt b/test/660-checker-simd-sad-short3/expected.txt
new file mode 100644
index 0000000..b0aad4d
--- /dev/null
+++ b/test/660-checker-simd-sad-short3/expected.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/660-checker-simd-sad-short3/info.txt b/test/660-checker-simd-sad-short3/info.txt
new file mode 100644
index 0000000..b56c119
--- /dev/null
+++ b/test/660-checker-simd-sad-short3/info.txt
@@ -0,0 +1 @@
+Functional tests on SAD vectorization.
diff --git a/test/660-checker-simd-sad-short3/src/Main.java b/test/660-checker-simd-sad-short3/src/Main.java
new file mode 100644
index 0000000..c8850b4
--- /dev/null
+++ b/test/660-checker-simd-sad-short3/src/Main.java
@@ -0,0 +1,351 @@
+/*
+ * 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).
+ *
+ * Some special cases: parameters, constants, invariants, casted computations.
+ */
+public class Main {
+
+ /// CHECK-START: int Main.sadShort2IntParamRight(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: <<Param:s\d+>> ParameterValue 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: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get>>,<<Param>>] 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.sadShort2IntParamRight(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: <<Param:s\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<Param>>] 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: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
+ private static int sadShort2IntParamRight(short[] s, short param) {
+ int sad = 0;
+ for (int i = 0; i < s.length; i++) {
+ sad += Math.abs(s[i] - param);
+ }
+ return sad;
+ }
+
+ /// CHECK-START: int Main.sadShort2IntParamLeft(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: <<Param:s\d+>> ParameterValue 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: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Param>>,<<Get>>] 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.sadShort2IntParamLeft(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: <<Param:s\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<Param>>] 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: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Rep>>,<<Load>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
+ private static int sadShort2IntParamLeft(short[] s, short param) {
+ int sad = 0;
+ for (int i = 0; i < s.length; i++) {
+ sad += Math.abs(param - s[i]);
+ }
+ return sad;
+ }
+
+ /// CHECK-START: int Main.sadShort2IntConstRight(short[]) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<ConsI:i\d+>> IntConstant -32767 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: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<ConsI>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Add>>] 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.sadShort2IntConstRight(short[]) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<ConsI:i\d+>> IntConstant 32767 loop:none
+ /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<ConsI>>] 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: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
+ private static int sadShort2IntConstRight(short[] s) {
+ int sad = 0;
+ for (int i = 0; i < s.length; i++) {
+ sad += Math.abs(s[i] - 32767);
+ }
+ return sad;
+ }
+
+ /// CHECK-START: int Main.sadShort2IntConstLeft(short[]) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<ConsI:i\d+>> IntConstant 32767 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: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<ConsI>>,<<Get>>] 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.sadShort2IntConstLeft(short[]) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<ConsI:i\d+>> IntConstant 32767 loop:none
+ /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<ConsI>>] 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: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Rep>>,<<Load>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
+ private static int sadShort2IntConstLeft(short[] s) {
+ int sad = 0;
+ for (int i = 0; i < s.length; i++) {
+ sad += Math.abs(32767 - s[i]);
+ }
+ return sad;
+ }
+
+ /// CHECK-START: int Main.sadShort2IntInvariantRight(short[], int) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Conv:s\d+>> TypeConversion [{{i\d+}}] 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: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get>>,<<Conv>>] 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.sadShort2IntInvariantRight(short[], int) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<Conv:s\d+>> TypeConversion [{{i\d+}}] loop:none
+ /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<Conv>>] 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: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
+ private static int sadShort2IntInvariantRight(short[] s, int val) {
+ int sad = 0;
+ short x = (short) (val + 1);
+ for (int i = 0; i < s.length; i++) {
+ sad += Math.abs(s[i] - x);
+ }
+ return sad;
+ }
+
+ /// CHECK-START: int Main.sadShort2IntInvariantLeft(short[], int) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Conv:s\d+>> TypeConversion [{{i\d+}}] 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: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Conv>>,<<Get>>] 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.sadShort2IntInvariantLeft(short[], int) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<Conv:s\d+>> TypeConversion [{{i\d+}}] loop:none
+ /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<Conv>>] 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: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Rep>>,<<Load>>] loop:<<Loop>> outer_loop:none
+ private static int sadShort2IntInvariantLeft(short[] s, int val) {
+ int sad = 0;
+ short x = (short) (val + 1);
+ for (int i = 0; i < s.length; i++) {
+ sad += Math.abs(x - s[i]);
+ }
+ return sad;
+ }
+
+ /// CHECK-START: int Main.sadShort2IntCastedExprRight(short[]) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<ConsI:i\d+>> IntConstant 110 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: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Add:i\d+>> [<<Get>>,<<ConsI>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Conv:s\d+>> TypeConversion [<<Add>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get>>,<<Conv>>] 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.sadShort2IntCastedExprRight(short[]) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<ConsI:i\d+>> IntConstant 110 loop:none
+ /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<ConsI>>] 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: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Add:d\d+>> VecAdd [<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load>>,<<Add>>] loop:<<Loop>> outer_loop:none
+ private static int sadShort2IntCastedExprRight(short[] s) {
+ int sad = 0;
+ for (int i = 0; i < s.length; i++) {
+ short x = (short) (s[i] + 110); // narrower part sign extends
+ sad += Math.abs(s[i] - x);
+ }
+ return sad;
+ }
+
+ /// CHECK-START: int Main.sadShort2IntCastedExprLeft(short[]) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<ConsI:i\d+>> IntConstant 110 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: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Add:i\d+>> [<<Get>>,<<ConsI>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Conv:s\d+>> TypeConversion [<<Add>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Conv>>,<<Get>>] 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.sadShort2IntCastedExprLeft(short[]) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<ConsI:i\d+>> IntConstant 110 loop:none
+ /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<ConsI>>] 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: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Add:d\d+>> VecAdd [<<Load>>,<<Rep>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Add>>,<<Load>>] loop:<<Loop>> outer_loop:none
+ private static int sadShort2IntCastedExprLeft(short[] s) {
+ int sad = 0;
+ for (int i = 0; i < s.length; i++) {
+ short x = (short) (s[i] + 110); // narrower part sign extends
+ sad += Math.abs(x - s[i]);
+ }
+ return sad;
+ }
+
+ public static void main(String[] args) {
+ short[] interesting = {
+ (short) 0x0000,
+ (short) 0x0001,
+ (short) 0x0002,
+ (short) 0x0003,
+ (short) 0x0004,
+ (short) 0x1234,
+ (short) 0x8000,
+ (short) 0x8001,
+ (short) 0x8002,
+ (short) 0x8003,
+ (short) 0x8004,
+ (short) 0x8004,
+ (short) 0x7000,
+ (short) 0x7fff,
+ (short) 0xf000,
+ (short) 0xffff
+ };
+ short[] s = new short[64];
+ for (int i = 0; i < 64; i++) {
+ s[i] = interesting[i % interesting.length];
+ }
+
+ expectEquals(1067200, sadShort2IntParamRight(s, (short)-1));
+ expectEquals(1067200, sadShort2IntParamRight(s, (short) 0));
+ expectEquals(1067208, sadShort2IntParamRight(s, (short) 1));
+ expectEquals(1067224, sadShort2IntParamRight(s, (short) 2));
+ expectEquals(2635416, sadShort2IntParamRight(s, (short) 0x7fff));
+ expectEquals(1558824, sadShort2IntParamRight(s, (short) 0x8000));
+
+ expectEquals(1067200, sadShort2IntParamLeft(s, (short)-1));
+ expectEquals(1067200, sadShort2IntParamLeft(s, (short) 0));
+ expectEquals(1067208, sadShort2IntParamLeft(s, (short) 1));
+ expectEquals(1067224, sadShort2IntParamLeft(s, (short) 2));
+ expectEquals(2635416, sadShort2IntParamLeft(s, (short) 0x7fff));
+ expectEquals(1558824, sadShort2IntParamLeft(s, (short) 0x8000));
+
+ expectEquals(2635416, sadShort2IntConstRight(s));
+ expectEquals(2635416, sadShort2IntConstLeft(s));
+
+ expectEquals(1067200, sadShort2IntInvariantRight(s, -2));
+ expectEquals(1067200, sadShort2IntInvariantRight(s, -1));
+ expectEquals(1067208, sadShort2IntInvariantRight(s, 0));
+ expectEquals(1067224, sadShort2IntInvariantRight(s, 1));
+ expectEquals(2635416, sadShort2IntInvariantRight(s, 0x7ffe));
+ expectEquals(1558824, sadShort2IntInvariantRight(s, 0x7fff));
+
+ expectEquals(1067200, sadShort2IntInvariantLeft(s, -2));
+ expectEquals(1067200, sadShort2IntInvariantLeft(s, -1));
+ expectEquals(1067208, sadShort2IntInvariantLeft(s, 0));
+ expectEquals(1067224, sadShort2IntInvariantLeft(s, 1));
+ expectEquals(2635416, sadShort2IntInvariantLeft(s, 0x7ffe));
+ expectEquals(1558824, sadShort2IntInvariantLeft(s, 0x7fff));
+
+ expectEquals(268304, sadShort2IntCastedExprLeft(s));
+ expectEquals(268304, sadShort2IntCastedExprRight(s));
+
+ 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 71eb3cd..bcfa968 100644
--- a/test/661-checker-simd-reduc/src/Main.java
+++ b/test/661-checker-simd-reduc/src/Main.java
@@ -80,6 +80,101 @@
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 @@
}
// 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 0000000..4ed7577
--- /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 0000000..b7ad70a
--- /dev/null
+++ b/test/661-oat-writer-layout/expected.txt
@@ -0,0 +1,64 @@
+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$$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 0000000..897b85c
--- /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 0000000..61996b2
--- /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 0000000..ab9b9a9
--- /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 0000000..cf307c2
--- /dev/null
+++ b/test/661-oat-writer-layout/profile
@@ -0,0 +1,54 @@
+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
+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
+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
+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
+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
+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
+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
+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
+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 0000000..f93d7b7
--- /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 0000000..09f4e88
--- /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 0000000..940798d
--- /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 0000000..f862e37
--- /dev/null
+++ b/test/661-oat-writer-layout/src/Test.java
@@ -0,0 +1,90 @@
+// 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;
+
+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 {
+ ArrayList<Method> all_methods = new ArrayList<Method>();
+ all_methods.add(A.class.getDeclaredMethod("m_a$$$"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$Hot$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$Hot$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$$Startup$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$$$"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$Hot$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$Hot$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$$Startup$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$$$"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$Hot$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$Hot$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$$Startup$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$$$"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$Hot$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$Hot$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$$$"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$Hot$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$Hot$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$$$"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$Hot$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$Hot$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$$$"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$Hot$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$Hot$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$$$"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$Hot$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$Hot$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$$$"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$Hot$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$Hot$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup"));
+ return all_methods.toArray(new Method[all_methods.size()]);
+ }
+}
+
diff --git a/test/707-checker-invalid-profile/check b/test/707-checker-invalid-profile/check
new file mode 100755
index 0000000..976afc4
--- /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 e69de29..4d84c96 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/707-checker-invalid-profile/profile b/test/707-checker-invalid-profile/profile
index 5979dd2..f142c40 100644
--- a/test/707-checker-invalid-profile/profile
+++ b/test/707-checker-invalid-profile/profile
@@ -1,4 +1,4 @@
-LMain;->attemptInlineMonomorphic(LMain;)I+invalid_class
-LMain;->attemptInlinePolymorphic(LMain;)I+LMain;,invalid_class
-LMain;->invalid_method
+SHLMain;->attemptInlineMonomorphic(LMain;)I+invalid_class
+SHLMain;->attemptInlinePolymorphic(LMain;)I+LMain;,invalid_class
+SHLMain;->invalid_method
invalid_class
\ No newline at end of file
diff --git a/test/911-get-stack-trace/src/art/PrintThread.java b/test/911-get-stack-trace/src/art/PrintThread.java
index fee5ba0..d8b3cbc 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 @@
// 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 9dcc5f9..7ad5d60 100644
--- a/test/912-classes/expected.txt
+++ b/test/912-classes/expected.txt
@@ -56,7 +56,7 @@
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 2e41c26..ddfadf3 100644
--- a/test/912-classes/src-art/art/Test912.java
+++ b/test/912-classes/src-art/art/Test912.java
@@ -19,8 +19,10 @@
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 @@
}
}
- 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 1eb2e1b..e529559 100644
--- a/test/924-threads/expected.txt
+++ b/test/924-threads/expected.txt
@@ -26,6 +26,15 @@
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 b73eb30..1ff2c3f 100644
--- a/test/924-threads/src/art/Test924.java
+++ b/test/924-threads/src/art/Test924.java
@@ -21,6 +21,7 @@
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 @@
};
printThreadInfo(t4);
- doStateTests();
+ doCurrentThreadStateTests();
+ doStateTests(Thread::new);
+ doStateTests(ExtThread::new);
doAllThreadsTests();
@@ -85,14 +88,20 @@
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 @@
}
};
- 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 0000000..fdcd2a8
--- /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 07b21b3..6f1e709 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/988-method-trace/src/art/Trace.java b/test/988-method-trace/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/988-method-trace/src/art/Trace.java
+++ b/test/988-method-trace/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/989-method-trace-throw/src/art/Trace.java b/test/989-method-trace-throw/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/989-method-trace-throw/src/art/Trace.java
+++ b/test/989-method-trace-throw/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/990-field-trace/src/art/Trace.java b/test/990-field-trace/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/990-field-trace/src/art/Trace.java
+++ b/test/990-field-trace/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/991-field-trace-2/src/art/Trace.java b/test/991-field-trace-2/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/991-field-trace-2/src/art/Trace.java
+++ b/test/991-field-trace-2/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/997-single-step/src/art/Trace.java b/test/997-single-step/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/997-single-step/src/art/Trace.java
+++ b/test/997-single-step/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/Android.bp b/test/Android.bp
index d56c0b5..2af03e3 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -67,6 +67,7 @@
"libicuuc",
"libicui18n",
"libnativehelper",
+ "libz",
],
whole_static_libs: [
"libsigchain",
@@ -84,11 +85,6 @@
],
shared_libs: [
"libziparchive",
- "libz-host",
- ],
- host_ldlibs: [
- "-ldl",
- "-lpthread",
],
cflags: [
// gtest issue
@@ -107,8 +103,6 @@
],
shared_libs: [
"liblog",
- "libdl",
- "libz",
],
cflags: [
// gtest issue
@@ -169,26 +163,15 @@
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 +189,6 @@
"libbase",
"libnativehelper",
],
- target: {
- android: {
- shared_libs: ["libdl"],
- },
- host: {
- host_ldlibs: [
- "-ldl",
- "-lpthread",
- ],
- },
- },
}
art_cc_test_library {
@@ -237,7 +209,7 @@
}
art_cc_defaults {
- name: "libtiagent-base-defaults",
+ name: "libtiagent-base-defaults",
defaults: ["libartagent-defaults"],
srcs: [
// These are the ART-independent parts.
@@ -302,7 +274,7 @@
"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 +331,7 @@
art_cc_test_library {
name: "libtistress",
- defaults: [ "libtistress-defaults"],
+ defaults: ["libtistress-defaults"],
shared_libs: ["libart"],
}
@@ -420,25 +392,15 @@
"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 +428,4 @@
],
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 c2ba948..d2f96bb 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 c16c487..d37e6bc 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -70,6 +70,10 @@
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 @@
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 @@
# 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 252d13a..df24c7d 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 d45d009..cc19afc 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -115,82 +115,9 @@
# 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 @@
# 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 f425097..2a772ff 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -45,6 +45,7 @@
"""
import argparse
+import collections
import fnmatch
import itertools
import json
@@ -60,21 +61,6 @@
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_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 @@
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 @@
# Bisection search writes to standard output.
env.ART_TEST_QUIET = False
- if not TARGET_TYPES:
- TARGET_TYPES.add('host')
- TARGET_TYPES.add('target')
+ 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 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 not _user_input_variants['target']:
+ _user_input_variants['target'].add('host')
+ _user_input_variants['target'].add('target')
- 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')
+ 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 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 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 not _user_input_variants['relocate']: # Default
+ _user_input_variants['relocate'].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 not _user_input_variants['trace']: # Default
+ _user_input_variants['trace'].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 not _user_input_variants['gc']: # Default
+ _user_input_variants['gc'].add('cms')
- if env.ART_TEST_JNI_FORCECOPY:
- JNI_TYPES.add('forcecopy')
- if not JNI_TYPES: # Default
- JNI_TYPES.add('checkjni')
+ if not _user_input_variants['jni']: # Default
+ _user_input_variants['jni'].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 not _user_input_variants['image']: # Default
+ _user_input_variants['image'].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 not _user_input_variants['pictest']: # Default
+ _user_input_variants['pictest'].add('npictest')
- if env.ART_TEST_RUN_TEST_DEBUGGABLE:
- DEBUGGABLE_TYPES.add('debuggable')
- if not DEBUGGABLE_TYPES: # Default
- DEBUGGABLE_TYPES.add('ndebuggable')
+ if not _user_input_variants['debuggable']: # Default
+ _user_input_variants['debuggable'].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['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 @@
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 @@
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 @@
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 verify_knownfailure_entry(entry):
supported_field = {
'tests' : (list, str),
+ 'test_patterns' : (list,),
'description' : (list, str),
'bug' : (str,),
'variant' : (str,),
@@ -650,6 +605,11 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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/test/ti-agent/trace_helper.cc b/test/ti-agent/trace_helper.cc
index 1f8ceff..8b74c7c 100644
--- a/test/ti-agent/trace_helper.cc
+++ b/test/ti-agent/trace_helper.cc
@@ -34,11 +34,36 @@
jmethodID field_access;
jmethodID field_modify;
jmethodID single_step;
+ jmethodID thread_start;
+ jmethodID thread_end;
bool in_callback;
bool access_watch_on_load;
bool modify_watch_on_load;
};
+static void threadStartCB(jvmtiEnv* jvmti,
+ JNIEnv* jnienv,
+ jthread thread) {
+ TraceData* data = nullptr;
+ if (JvmtiErrorToException(jnienv, jvmti,
+ jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) {
+ return;
+ }
+ CHECK(data->thread_start != nullptr);
+ jnienv->CallStaticVoidMethod(data->test_klass, data->thread_start, thread);
+}
+static void threadEndCB(jvmtiEnv* jvmti,
+ JNIEnv* jnienv,
+ jthread thread) {
+ TraceData* data = nullptr;
+ if (JvmtiErrorToException(jnienv, jvmti,
+ jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) {
+ return;
+ }
+ CHECK(data->thread_end != nullptr);
+ jnienv->CallStaticVoidMethod(data->test_klass, data->thread_end, thread);
+}
+
static void singleStepCB(jvmtiEnv* jvmti,
JNIEnv* jnienv,
jthread thread,
@@ -362,7 +387,7 @@
env->DeleteLocalRef(klass);
}
-extern "C" JNIEXPORT void JNICALL Java_art_Trace_enableTracing(
+extern "C" JNIEXPORT void JNICALL Java_art_Trace_enableTracing2(
JNIEnv* env,
jclass trace ATTRIBUTE_UNUSED,
jclass klass,
@@ -371,6 +396,8 @@
jobject field_access,
jobject field_modify,
jobject single_step,
+ jobject thread_start,
+ jobject thread_end,
jthread thr) {
TraceData* data = nullptr;
if (JvmtiErrorToException(env,
@@ -386,6 +413,8 @@
data->field_access = field_access != nullptr ? env->FromReflectedMethod(field_access) : nullptr;
data->field_modify = field_modify != nullptr ? env->FromReflectedMethod(field_modify) : nullptr;
data->single_step = single_step != nullptr ? env->FromReflectedMethod(single_step) : nullptr;
+ data->thread_start = thread_start != nullptr ? env->FromReflectedMethod(thread_start) : nullptr;
+ data->thread_end = thread_end != nullptr ? env->FromReflectedMethod(thread_end) : nullptr;
data->in_callback = false;
TraceData* old_data = nullptr;
@@ -410,6 +439,8 @@
cb.FieldModification = fieldModificationCB;
cb.ClassPrepare = classPrepareCB;
cb.SingleStep = singleStepCB;
+ cb.ThreadStart = threadStartCB;
+ cb.ThreadEnd = threadEndCB;
if (JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb)))) {
return;
}
@@ -453,6 +484,46 @@
thr))) {
return;
}
+ if (thread_start != nullptr &&
+ JvmtiErrorToException(env,
+ jvmti_env,
+ jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
+ JVMTI_EVENT_THREAD_START,
+ thr))) {
+ return;
+ }
+ if (thread_end != nullptr &&
+ JvmtiErrorToException(env,
+ jvmti_env,
+ jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
+ JVMTI_EVENT_THREAD_END,
+ thr))) {
+ return;
+ }
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Trace_enableTracing(
+ JNIEnv* env,
+ jclass trace,
+ jclass klass,
+ jobject enter,
+ jobject exit,
+ jobject field_access,
+ jobject field_modify,
+ jobject single_step,
+ jthread thr) {
+ Java_art_Trace_enableTracing2(env,
+ trace,
+ klass,
+ enter,
+ exit,
+ field_access,
+ field_modify,
+ single_step,
+ /* thread_start */ nullptr,
+ /* thread_end */ nullptr,
+ thr);
+ return;
}
extern "C" JNIEXPORT void JNICALL Java_art_Trace_disableTracing(
diff --git a/tools/ahat/Android.mk b/tools/ahat/Android.mk
index 2ce61cf..cf31e2e 100644
--- a/tools/ahat/Android.mk
+++ b/tools/ahat/Android.mk
@@ -22,10 +22,7 @@
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_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 @@
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_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 4471c0a..a765b17 100644
--- a/tools/ahat/README.txt
+++ b/tools/ahat/README.txt
@@ -48,34 +48,22 @@
time.
* That we don't show the 'extra' column in the DominatedList if we are
showing all the instances.
- * That Instance.asString properly takes into account "offset" and
- "count" fields, if they are present.
* Instance.getDexCacheLocation
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
+ 1.5 Pending
+
+ 1.4 October 03, 2017
+ Give better error messages on failure to launch ahat.
+ Properly mark thread and non-default root objects as roots.
+ Improve startup performance, in some cases significantly.
+ Other miscellaneous bug fixes.
+
+ 1.3.1 August 22, 2017
+ Don't include weak references in sample paths.
1.3 July 25, 2017
Improve diffing of static and instance fields.
diff --git a/tools/ahat/src/DocString.java b/tools/ahat/src/DocString.java
index 7970bf8..76e9e80 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 @@
* 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 @@
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 @@
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 0000000..75a6827
--- /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 7cda035..31c485d 100644
--- a/tools/ahat/src/Main.java
+++ b/tools/ahat/src/Main.java
@@ -18,7 +18,9 @@
import com.android.ahat.heapdump.AhatSnapshot;
import com.android.ahat.heapdump.Diff;
-import com.android.tools.perflib.heap.ProguardMap;
+import com.android.ahat.heapdump.HprofFormatException;
+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 +48,7 @@
out.println("");
}
- public static void main(String[] args) throws IOException {
+ public static void main(String[] args) {
int port = 7100;
for (String arg : args) {
if (arg.equals("--help")) {
@@ -103,34 +105,40 @@
return;
}
- // Launch the server before parsing the hprof file so we get
- // BindExceptions quickly.
- InetAddress loopback = InetAddress.getLoopbackAddress();
- InetSocketAddress addr = new InetSocketAddress(loopback, port);
- HttpServer server = HttpServer.create(addr, 0);
+ try {
+ // Launch the server before parsing the hprof file so we get
+ // BindExceptions quickly.
+ InetAddress loopback = InetAddress.getLoopbackAddress();
+ InetSocketAddress addr = new InetSocketAddress(loopback, port);
+ System.out.println("Preparing " + addr + " ...");
+ HttpServer server = HttpServer.create(addr, 0);
- System.out.println("Processing hprof file...");
- AhatSnapshot ahat = AhatSnapshot.fromHprof(hprof, map);
+ System.out.println("Processing '" + hprof + "' ...");
+ AhatSnapshot ahat = Parser.parseHeapDump(hprof, map);
- if (hprofbase != null) {
- System.out.println("Processing baseline hprof file...");
- AhatSnapshot base = AhatSnapshot.fromHprof(hprofbase, mapbase);
+ if (hprofbase != null) {
+ System.out.println("Processing '" + hprofbase + "' ...");
+ AhatSnapshot base = Parser.parseHeapDump(hprofbase, mapbase);
- System.out.println("Diffing hprof files...");
- Diff.snapshots(ahat, base);
+ System.out.println("Diffing heap dumps ...");
+ Diff.snapshots(ahat, base);
+ }
+
+ server.createContext("/", new AhatHttpHandler(new OverviewHandler(ahat, hprof, hprofbase)));
+ server.createContext("/rooted", new AhatHttpHandler(new RootedHandler(ahat)));
+ server.createContext("/object", new AhatHttpHandler(new ObjectHandler(ahat)));
+ server.createContext("/objects", new AhatHttpHandler(new ObjectsHandler(ahat)));
+ server.createContext("/site", new AhatHttpHandler(new SiteHandler(ahat)));
+ server.createContext("/bitmap", new BitmapHandler(ahat));
+ server.createContext("/style.css", new StaticHandler("style.css", "text/css"));
+ server.setExecutor(Executors.newFixedThreadPool(1));
+ System.out.println("Server started on localhost:" + port);
+
+ server.start();
+ } catch (HprofFormatException|IOException e) {
+ System.err.println("Unable to launch ahat:");
+ e.printStackTrace();
}
-
- server.createContext("/", new AhatHttpHandler(new OverviewHandler(ahat, hprof, hprofbase)));
- server.createContext("/rooted", new AhatHttpHandler(new RootedHandler(ahat)));
- server.createContext("/object", new AhatHttpHandler(new ObjectHandler(ahat)));
- server.createContext("/objects", new AhatHttpHandler(new ObjectsHandler(ahat)));
- server.createContext("/site", new AhatHttpHandler(new SiteHandler(ahat)));
- server.createContext("/bitmap", new BitmapHandler(ahat));
- server.createContext("/style.css", new StaticHandler("style.css", "text/css"));
- server.setExecutor(Executors.newFixedThreadPool(1));
- System.out.println("Server started on localhost:" + port);
-
- server.start();
}
}
diff --git a/tools/ahat/src/ObjectHandler.java b/tools/ahat/src/ObjectHandler.java
index f4926aa..79f8b76 100644
--- a/tools/ahat/src/ObjectHandler.java
+++ b/tools/ahat/src/ObjectHandler.java
@@ -25,6 +25,7 @@
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 @@
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 @@
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 b2805d6..4a68f1c 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 @@
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 8d23276..50a4805 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 @@
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;
+ /**
+ * 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;
+ }
- case CHAR:
- final char[] chars = array.asCharArray(0, array.getLength());
- mCharArray = chars;
- mValues = new AbstractList<Value>() {
- @Override public int size() {
- return chars.length;
- }
+ @Override public Value get(int index) {
+ return Value.pack(chars[index]);
+ }
+ };
+ }
- @Override public Value get(int index) {
- return Value.pack(chars[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;
+ }
- 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(floats[index]);
+ }
+ };
+ }
- @Override public Value get(int index) {
- return Value.pack(bytes[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;
+ }
- 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(doubles[index]);
+ }
+ };
+ }
- @Override public Value get(int index) {
- return Value.pack(values[index]);
- }
- };
- break;
+ /**
+ * 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 f7d8431..94efa50 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 @@
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 @@
}
Value value = getField("value");
- if (!value.isAhatInstance()) {
+ if (value == null || !value.isAhatInstance()) {
return null;
}
@@ -248,6 +243,49 @@
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 08c7097..be0f713 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 @@
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);
+ void initialize(AhatClassObj superClass,
+ long instanceSize,
+ Field[] instanceFields,
+ long staticFieldsSize) {
+ mSuperClassObj = superClass;
+ mInstanceSize = instanceSize;
+ mInstanceFields = instanceFields;
+ mStaticFieldsSize = staticFieldsSize;
+ }
- ClassObj classObj = (ClassObj)inst;
- mClassName = classObj.getClassName();
+ void initialize(AhatInstance classLoader, FieldValue[] staticFields) {
+ mClassLoader = classLoader;
+ mStaticFieldValues = staticFields;
+ }
- 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());
- }
+ @Override
+ protected long getExtraJavaSize() {
+ return mStaticFieldsSize;
}
/**
@@ -91,6 +76,14 @@
}
/**
+ * 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 0e78558..c044487 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 @@
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 @@
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 @@
* 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 @@
* 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 @@
* 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 @@
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 @@
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 @@
}
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 @@
@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 8b4c679..07f5b50 100644
--- a/tools/ahat/src/heapdump/AhatPlaceHolderClassObj.java
+++ b/tools/ahat/src/heapdump/AhatPlaceHolderClassObj.java
@@ -24,11 +24,15 @@
*/
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 9abc952..8849403 100644
--- a/tools/ahat/src/heapdump/AhatPlaceHolderInstance.java
+++ b/tools/ahat/src/heapdump/AhatPlaceHolderInstance.java
@@ -36,6 +36,10 @@
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 1b2cf3c..945966c 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);
- }
+ AhatSnapshot(SuperRoot root,
+ Instances<AhatInstance> instances,
+ List<AhatHeap> heaps,
+ Site rootSite) {
+ mSuperRoot = root;
+ mInstances = instances;
+ mHeaps = heaps;
+ mRootSite = rootSite;
- /**
- * 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());
- }
- }
+ // Update registered native allocation size.
+ for (AhatInstance cleaner : mInstances) {
+ AhatInstance.RegisteredNativeAllocation nra = cleaner.asRegisteredNativeAllocation();
+ if (nra != null) {
+ nra.referent.addRegisteredNativeSize(nra.size);
}
}
- // 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);
- }
+ AhatInstance.computeReverseReferences(mSuperRoot);
+ DominatorsComputation.computeDominators(mSuperRoot);
+ AhatInstance.computeRetainedSize(mSuperRoot, mHeaps.size());
- // 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);
- }
- }
-
- // 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());
-
- 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 @@
* 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 @@
* SENTINEL_ROOT.
*/
public List<AhatInstance> getRooted() {
- return mRooted;
+ return mSuperRoot.getDominated();
}
/**
@@ -252,14 +122,6 @@
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 e2dcf3e..3cd273e 100644
--- a/tools/ahat/src/heapdump/DiffedFieldValue.java
+++ b/tools/ahat/src/heapdump/DiffedFieldValue.java
@@ -23,7 +23,7 @@
*/
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 @@
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 01f87c7..dff4017 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 @@
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 6d72595..20e6da7 100644
--- a/tools/ahat/src/heapdump/FieldValue.java
+++ b/tools/ahat/src/heapdump/FieldValue.java
@@ -18,10 +18,10 @@
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 0000000..0e128cd
--- /dev/null
+++ b/tools/ahat/src/heapdump/HprofFormatException.java
@@ -0,0 +1,27 @@
+/*
+ * 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);
+ }
+
+ public HprofFormatException(String msg, Exception cause) {
+ super(msg, cause);
+ }
+}
diff --git a/tools/ahat/src/heapdump/Instances.java b/tools/ahat/src/heapdump/Instances.java
new file mode 100644
index 0000000..0851446
--- /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 0000000..756b7d2
--- /dev/null
+++ b/tools/ahat/src/heapdump/Parser.java
@@ -0,0 +1,957 @@
+/*
+ * 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.BufferUnderflowException;
+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 {
+ try {
+ return parseHeapDump(new HprofBuffer(hprof), map);
+ } catch (BufferUnderflowException e) {
+ throw new HprofFormatException("Unexpected end of file", e);
+ }
+ }
+
+ /**
+ * Parse a heap dump from a byte buffer.
+ */
+ public static AhatSnapshot parseHeapDump(ByteBuffer hprof, ProguardMap map)
+ throws IOException, HprofFormatException {
+ try {
+ return parseHeapDump(new HprofBuffer(hprof), map);
+ } catch (BufferUnderflowException e) {
+ throw new HprofFormatException("Unexpected end of file", e);
+ }
+ }
+
+ private static AhatSnapshot parseHeapDump(HprofBuffer hprof, ProguardMap map)
+ throws IOException, HprofFormatException, BufferUnderflowException {
+ // 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 0x8a: { // ROOT FINALIZING (ANDROID)
+ long objectId = hprof.getId();
+ roots.add(new RootData(objectId, RootType.FINALIZING));
+ 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 d0264a3..0000000
--- 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 0000000..af552ea
--- /dev/null
+++ b/tools/ahat/src/heapdump/RootType.java
@@ -0,0 +1,40 @@
+/*
+ * 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),
+ FINALIZING (1 << 13);
+
+ 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 82931f0..821493f 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 @@
* 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 d377113..a2adbd2 100644
--- a/tools/ahat/src/heapdump/SuperRoot.java
+++ b/tools/ahat/src/heapdump/SuperRoot.java
@@ -34,6 +34,11 @@
}
@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 0000000..726bc47
--- /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 7f86c01..01fd250 100644
--- a/tools/ahat/src/heapdump/Value.java
+++ b/tools/ahat/src/heapdump/Value.java
@@ -25,37 +25,6 @@
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 @@
}
/**
+ * 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 @@
}
@Override
+ protected Type getType() {
+ return Type.BOOLEAN;
+ }
+
+ @Override
public String toString() {
return Boolean.toString(mBool);
}
@@ -198,6 +184,11 @@
}
@Override
+ protected Type getType() {
+ return Type.BYTE;
+ }
+
+ @Override
public String toString() {
return Byte.toString(mByte);
}
@@ -224,6 +215,11 @@
}
@Override
+ protected Type getType() {
+ return Type.CHAR;
+ }
+
+ @Override
public String toString() {
return Character.toString(mChar);
}
@@ -245,6 +241,11 @@
}
@Override
+ protected Type getType() {
+ return Type.DOUBLE;
+ }
+
+ @Override
public String toString() {
return Double.toString(mDouble);
}
@@ -266,6 +267,11 @@
}
@Override
+ protected Type getType() {
+ return Type.FLOAT;
+ }
+
+ @Override
public String toString() {
return Float.toString(mFloat);
}
@@ -298,6 +304,11 @@
}
@Override
+ protected Type getType() {
+ return Type.OBJECT;
+ }
+
+ @Override
public String toString() {
return mInstance.toString();
}
@@ -334,6 +345,11 @@
}
@Override
+ protected Type getType() {
+ return Type.INT;
+ }
+
+ @Override
public String toString() {
return Integer.toString(mInt);
}
@@ -365,6 +381,11 @@
}
@Override
+ protected Type getType() {
+ return Type.LONG;
+ }
+
+ @Override
public String toString() {
return Long.toString(mLong);
}
@@ -386,6 +407,11 @@
}
@Override
+ protected Type getType() {
+ return Type.SHORT;
+ }
+
+ @Override
public String toString() {
return Short.toString(mShort);
}
diff --git a/tools/ahat/src/manifest.txt b/tools/ahat/src/manifest.txt
index d893c5e..1753406 100644
--- a/tools/ahat/src/manifest.txt
+++ b/tools/ahat/src/manifest.txt
@@ -1,4 +1,4 @@
Name: ahat/
Implementation-Title: ahat
-Implementation-Version: 1.3
+Implementation-Version: 1.4
Main-Class: com.android.ahat.Main
diff --git a/tools/ahat/src/proguard/ProguardMap.java b/tools/ahat/src/proguard/ProguardMap.java
new file mode 100644
index 0000000..50c110a
--- /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
new file mode 100644
index 0000000..1acdf79
--- /dev/null
+++ b/tools/ahat/test-dump/L.hprof
Binary files differ
diff --git a/tools/ahat/test-dump/O.hprof b/tools/ahat/test-dump/O.hprof
new file mode 100644
index 0000000..d474c6c
--- /dev/null
+++ b/tools/ahat/test-dump/O.hprof
Binary files differ
diff --git a/tools/ahat/test-dump/README.txt b/tools/ahat/test-dump/README.txt
new file mode 100644
index 0000000..e7ea584
--- /dev/null
+++ b/tools/ahat/test-dump/README.txt
@@ -0,0 +1,7 @@
+
+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,
+ with one of the ROOT_DEBUGGER records manually changed to a
+ ROOT_FINALIZING record.
+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
new file mode 100644
index 0000000..9482542
--- /dev/null
+++ b/tools/ahat/test-dump/RI.hprof
Binary files differ
diff --git a/tools/ahat/test/DiffFieldsTest.java b/tools/ahat/test/DiffFieldsTest.java
index 7dc519d..1939975 100644
--- a/tools/ahat/test/DiffFieldsTest.java
+++ b/tools/ahat/test/DiffFieldsTest.java
@@ -19,6 +19,7 @@
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.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 @@
@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 @@
@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 @@
@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 @@
@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 d0349fd..585f29a 100644
--- a/tools/ahat/test/DiffTest.java
+++ b/tools/ahat/test/DiffTest.java
@@ -18,26 +18,7 @@
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 @@
}
@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 0000000..a36db35
--- /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 63055db..49a21e2 100644
--- a/tools/ahat/test/InstanceTest.java
+++ b/tools/ahat/test/InstanceTest.java
@@ -23,23 +23,7 @@
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 @@
@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>();
+ // 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();
- 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)}));
+ // java.lang.String@0x6fe17050 is an image string "char" backed by a
+ // shared char array.
+ AhatInstance str = snapshot.findInstance(0x6fe17050);
+ assertEquals("char", str.asString());
+ }
- dump.add(new HprofPrimitiveArrayDump(0x41, 0, HprofType.TYPE_CHAR,
- new long[]{'n', 'o', 't', ' ', 'h', 'e', 'l', 'l', 'o', 'o', 'p'}));
+ @Test
+ public void nonDefaultHeapRoot() throws IOException {
+ TestDump dump = TestDump.getTestDump("O.hprof", null, null);
+ AhatSnapshot snapshot = dump.getAhatSnapshot();
- 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));
+ // 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());
+ }
- 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());
+ @Test
+ public void threadRoot() throws IOException {
+ TestDump dump = TestDump.getTestDump("O.hprof", null, null);
+ AhatSnapshot snapshot = dump.getAhatSnapshot();
- AhatInstance stringInstance = snapshot.findInstance(0x42);
- assertNotNull(stringInstance);
- assertEquals("hello", stringInstance.asString());
+ // 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 0000000..ad40f45
--- /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 0eea635..0000000
--- 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 db9b256..a0d1021 100644
--- a/tools/ahat/test/TestDump.java
+++ b/tools/ahat/test/TestDump.java
@@ -21,75 +21,124 @@
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 @@
}
/**
- * 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");
+ }
+
+ /**
+ * 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;
+ }
}
- if (mCachedTestDump == null) {
- mTestDumpFailed = true;
- mCachedTestDump = new TestDump();
- mTestDumpFailed = false;
- }
- 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 cd33a90..0e70432 100644
--- a/tools/ahat/test/Tests.java
+++ b/tools/ahat/test/Tests.java
@@ -25,11 +25,13 @@
"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 59c5211..57c9c09 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 @@
// 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 0000000..6b5daec
--- /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 b95ec9d..097622e 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 @@
compile_multilib: "both",
shared_libs: [
- "libbase"
+ "libbase",
],
target: {
android: {
@@ -37,7 +40,7 @@
},
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 c39b81a..8dec847 100644
--- a/tools/wrapagentproperties/Android.bp
+++ b/tools/wrapagentproperties/Android.bp
@@ -27,7 +27,7 @@
compile_multilib: "both",
shared_libs: [
- "libbase"
+ "libbase",
],
target: {
android: {
@@ -62,5 +62,5 @@
"art_debug_defaults",
"wrapagentproperties-defaults",
],
- shared_libs: [ ],
+ shared_libs: [],
}