summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/Android.bp9
-rw-r--r--compiler/compiler.cc10
-rw-r--r--compiler/compiler.h2
-rw-r--r--compiler/debug/elf_debug_info_writer.h22
-rw-r--r--compiler/debug/elf_debug_line_writer.h4
-rw-r--r--compiler/debug/elf_debug_loc_writer.h5
-rw-r--r--compiler/debug/method_debug_info.h2
-rw-r--r--compiler/dex/dex_to_dex_compiler.cc11
-rw-r--r--compiler/dex/dex_to_dex_compiler.h2
-rw-r--r--compiler/dex/dex_to_dex_decompiler_test.cc8
-rw-r--r--compiler/dex/inline_method_analyser.cc21
-rw-r--r--compiler/dex/inline_method_analyser.h4
-rw-r--r--compiler/dex/quick_compiler_callbacks.cc2
-rw-r--r--compiler/dex/verified_method.cc6
-rw-r--r--compiler/dex/verified_method.h2
-rw-r--r--compiler/driver/compiler_driver.cc79
-rw-r--r--compiler/driver/compiler_driver.h26
-rw-r--r--compiler/driver/compiler_driver_test.cc30
-rw-r--r--compiler/driver/compiler_options.cc20
-rw-r--r--compiler/driver/dex_compilation_unit.cc5
-rw-r--r--compiler/driver/dex_compilation_unit.h9
-rw-r--r--compiler/exception_test.cc27
-rw-r--r--compiler/jni/jni_compiler_test.cc8
-rw-r--r--compiler/jni/quick/jni_compiler.cc2
-rw-r--r--compiler/linker/arm/relative_patcher_arm_base.cc2
-rw-r--r--compiler/linker/elf_builder.h21
-rw-r--r--compiler/optimizing/block_builder.cc72
-rw-r--r--compiler/optimizing/block_builder.h23
-rw-r--r--compiler/optimizing/builder.cc54
-rw-r--r--compiler/optimizing/builder.h24
-rw-r--r--compiler/optimizing/code_generator.cc4
-rw-r--r--compiler/optimizing/code_generator_arm64.cc13
-rw-r--r--compiler/optimizing/code_generator_arm64.h2
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.cc124
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.h1
-rw-r--r--compiler/optimizing/code_generator_mips.cc20
-rw-r--r--compiler/optimizing/code_generator_mips.h2
-rw-r--r--compiler/optimizing/code_generator_mips64.cc31
-rw-r--r--compiler/optimizing/code_generator_x86.cc11
-rw-r--r--compiler/optimizing/code_generator_x86.h2
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc11
-rw-r--r--compiler/optimizing/codegen_test.cc4
-rw-r--r--compiler/optimizing/dominator_test.cc2
-rw-r--r--compiler/optimizing/find_loops_test.cc4
-rw-r--r--compiler/optimizing/inliner.cc16
-rw-r--r--compiler/optimizing/inliner.h2
-rw-r--r--compiler/optimizing/instruction_builder.cc60
-rw-r--r--compiler/optimizing/instruction_builder.h34
-rw-r--r--compiler/optimizing/intrinsics_arm_vixl.cc76
-rw-r--r--compiler/optimizing/linearize_test.cc4
-rw-r--r--compiler/optimizing/live_ranges_test.cc4
-rw-r--r--compiler/optimizing/liveness_test.cc4
-rw-r--r--compiler/optimizing/nodes.h4
-rw-r--r--compiler/optimizing/optimization.cc6
-rw-r--r--compiler/optimizing/optimizing_cfi_test.cc4
-rw-r--r--compiler/optimizing/optimizing_compiler.cc10
-rw-r--r--compiler/optimizing/optimizing_unit_test.h8
-rw-r--r--compiler/optimizing/prepare_for_register_allocation.cc2
-rw-r--r--compiler/optimizing/pretty_printer_test.cc4
-rw-r--r--compiler/optimizing/register_allocator_test.cc6
-rw-r--r--compiler/optimizing/scheduler_arm.cc6
-rw-r--r--compiler/optimizing/ssa_test.cc4
-rw-r--r--compiler/optimizing/stack_map_stream.cc2
-rw-r--r--compiler/optimizing/superblock_cloner_test.cc (renamed from compiler/optimizing/cloner_test.cc)6
-rw-r--r--compiler/optimizing/suspend_check_test.cc2
-rw-r--r--compiler/trampolines/trampoline_compiler.h1
-rw-r--r--compiler/utils/arm/assembler_arm_shared.h7
-rw-r--r--compiler/utils/arm/assembler_arm_test.h555
-rw-r--r--compiler/utils/arm/assembler_arm_vixl.cc25
-rw-r--r--compiler/utils/arm/assembler_arm_vixl.h4
-rw-r--r--compiler/utils/arm/jni_macro_assembler_arm_vixl.cc14
-rw-r--r--compiler/utils/atomic_dex_ref_map-inl.h4
-rw-r--r--compiler/utils/atomic_dex_ref_map.h2
-rw-r--r--compiler/utils/atomic_dex_ref_map_test.cc2
-rw-r--r--compiler/utils/mips64/assembler_mips64.cc31
-rw-r--r--compiler/utils/mips64/assembler_mips64.h4
-rw-r--r--compiler/utils/mips64/assembler_mips64_test.cc31
-rw-r--r--compiler/utils/string_reference_test.cc2
-rw-r--r--compiler/utils/test_dex_file_builder.h8
-rw-r--r--compiler/utils/test_dex_file_builder_test.cc2
-rw-r--r--compiler/verifier_deps_test.cc8
81 files changed, 656 insertions, 1051 deletions
diff --git a/compiler/Android.bp b/compiler/Android.bp
index fc19b54131..d4d72f380b 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -249,6 +249,13 @@ art_cc_library {
shared_libs: [
"libart",
],
+
+ pgo: {
+ instrumentation: true,
+ profile_file: "dex2oat.profdata",
+ benchmarks: ["dex2oat"],
+ enable_profile_use: false,
+ }
}
art_cc_library {
@@ -318,7 +325,7 @@ art_cc_test {
"linker/linker_patch_test.cc",
"linker/output_stream_test.cc",
"optimizing/bounds_check_elimination_test.cc",
- "optimizing/cloner_test.cc",
+ "optimizing/superblock_cloner_test.cc",
"optimizing/data_type_test.cc",
"optimizing/dominator_test.cc",
"optimizing/find_loops_test.cc",
diff --git a/compiler/compiler.cc b/compiler/compiler.cc
index bb614ae7b2..7c7ae71d77 100644
--- a/compiler/compiler.cc
+++ b/compiler/compiler.cc
@@ -19,6 +19,7 @@
#include <android-base/logging.h>
#include "base/macros.h"
+#include "dex/code_item_accessors-inl.h"
#include "driver/compiler_driver.h"
#include "optimizing/optimizing_compiler.h"
#include "utils.h"
@@ -46,15 +47,16 @@ bool Compiler::IsPathologicalCase(const DexFile::CodeItem& code_item,
* Dalvik uses 16-bit uints for instruction and register counts. We'll limit to a quarter
* of that, which also guarantees we cannot overflow our 16-bit internal Quick SSA name space.
*/
- if (code_item.insns_size_in_code_units_ >= UINT16_MAX / 4) {
+ CodeItemDataAccessor accessor(dex_file, &code_item);
+ if (accessor.InsnsSizeInCodeUnits() >= UINT16_MAX / 4) {
LOG(INFO) << "Method exceeds compiler instruction limit: "
- << code_item.insns_size_in_code_units_
+ << accessor.InsnsSizeInCodeUnits()
<< " in " << dex_file.PrettyMethod(method_idx);
return true;
}
- if (code_item.registers_size_ >= UINT16_MAX / 4) {
+ if (accessor.RegistersSize() >= UINT16_MAX / 4) {
LOG(INFO) << "Method exceeds compiler virtual register limit: "
- << code_item.registers_size_ << " in " << dex_file.PrettyMethod(method_idx);
+ << accessor.RegistersSize() << " in " << dex_file.PrettyMethod(method_idx);
return true;
}
return false;
diff --git a/compiler/compiler.h b/compiler/compiler.h
index 85abd6654c..b92bff61a9 100644
--- a/compiler/compiler.h
+++ b/compiler/compiler.h
@@ -18,7 +18,7 @@
#define ART_COMPILER_COMPILER_H_
#include "base/mutex.h"
-#include "dex_file.h"
+#include "dex/dex_file.h"
#include "os.h"
namespace art {
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h
index 107ed488cd..713f8eb05d 100644
--- a/compiler/debug/elf_debug_info_writer.h
+++ b/compiler/debug/elf_debug_info_writer.h
@@ -22,14 +22,14 @@
#include <vector>
#include "art_field-inl.h"
-#include "code_item_accessors-inl.h"
#include "debug/dwarf/debug_abbrev_writer.h"
#include "debug/dwarf/debug_info_entry_writer.h"
#include "debug/elf_compilation_unit.h"
#include "debug/elf_debug_loc_writer.h"
#include "debug/method_debug_info.h"
-#include "dex_file-inl.h"
-#include "dex_file.h"
+#include "dex/code_item_accessors-inl.h"
+#include "dex/dex_file-inl.h"
+#include "dex/dex_file.h"
#include "heap_poisoning.h"
#include "linear_alloc.h"
#include "linker/elf_builder.h"
@@ -49,7 +49,7 @@ static void LocalInfoCallback(void* ctx, const DexFile::LocalInfo& entry) {
static std::vector<const char*> GetParamNames(const MethodDebugInfo* mi) {
std::vector<const char*> names;
- CodeItemDebugInfoAccessor accessor(mi->dex_file, mi->code_item);
+ CodeItemDebugInfoAccessor accessor(*mi->dex_file, mi->code_item);
if (accessor.HasCodeItem()) {
DCHECK(mi->dex_file != nullptr);
const uint8_t* stream = mi->dex_file->GetDebugInfoStream(accessor.DebugInfoOffset());
@@ -163,7 +163,7 @@ class ElfCompilationUnitWriter {
for (auto mi : compilation_unit.methods) {
DCHECK(mi->dex_file != nullptr);
const DexFile* dex = mi->dex_file;
- CodeItemDebugInfoAccessor accessor(dex, mi->code_item);
+ CodeItemDebugInfoAccessor accessor(*dex, mi->code_item);
const DexFile::MethodId& dex_method = dex->GetMethodId(mi->dex_method_index);
const DexFile::ProtoId& dex_proto = dex->GetMethodPrototype(dex_method);
const DexFile::TypeList* dex_params = dex->GetProtoParameters(dex_proto);
@@ -260,14 +260,10 @@ class ElfCompilationUnitWriter {
// Write local variables.
LocalInfos local_infos;
- if (dex->DecodeDebugLocalInfo(accessor.RegistersSize(),
- accessor.InsSize(),
- accessor.InsnsSizeInCodeUnits(),
- accessor.DebugInfoOffset(),
- is_static,
- mi->dex_method_index,
- LocalInfoCallback,
- &local_infos)) {
+ if (accessor.DecodeDebugLocalInfo(is_static,
+ mi->dex_method_index,
+ LocalInfoCallback,
+ &local_infos)) {
for (const DexFile::LocalInfo& var : local_infos) {
if (var.reg_ < accessor.RegistersSize() - accessor.InsSize()) {
info_.StartTag(DW_TAG_variable);
diff --git a/compiler/debug/elf_debug_line_writer.h b/compiler/debug/elf_debug_line_writer.h
index d7fd52448c..4e37f4e4ba 100644
--- a/compiler/debug/elf_debug_line_writer.h
+++ b/compiler/debug/elf_debug_line_writer.h
@@ -24,7 +24,7 @@
#include "debug/dwarf/headers.h"
#include "debug/elf_compilation_unit.h"
#include "debug/src_map_elem.h"
-#include "dex_file-inl.h"
+#include "dex/dex_file-inl.h"
#include "linker/elf_builder.h"
#include "oat_file.h"
#include "stack_map.h"
@@ -159,7 +159,7 @@ class ElfDebugLineWriter {
PositionInfos dex2line_map;
DCHECK(mi->dex_file != nullptr);
const DexFile* dex = mi->dex_file;
- CodeItemDebugInfoAccessor accessor(dex, mi->code_item);
+ CodeItemDebugInfoAccessor accessor(*dex, mi->code_item);
const uint32_t debug_info_offset = accessor.DebugInfoOffset();
if (!dex->DecodeDebugPositionInfo(debug_info_offset, PositionInfoCallback, &dex2line_map)) {
continue;
diff --git a/compiler/debug/elf_debug_loc_writer.h b/compiler/debug/elf_debug_loc_writer.h
index 1d609af4e6..9ea9f01cd9 100644
--- a/compiler/debug/elf_debug_loc_writer.h
+++ b/compiler/debug/elf_debug_loc_writer.h
@@ -149,11 +149,12 @@ static std::vector<VariableLocation> GetVariableLocations(
DCHECK_LT(stack_map_index, dex_register_maps.size());
DexRegisterMap dex_register_map = dex_register_maps[stack_map_index];
DCHECK(dex_register_map.IsValid());
+ CodeItemDataAccessor accessor(*method_info->dex_file, method_info->code_item);
reg_lo = dex_register_map.GetDexRegisterLocation(
- vreg, method_info->code_item->registers_size_, code_info, encoding);
+ vreg, accessor.RegistersSize(), code_info, encoding);
if (is64bitValue) {
reg_hi = dex_register_map.GetDexRegisterLocation(
- vreg + 1, method_info->code_item->registers_size_, code_info, encoding);
+ vreg + 1, accessor.RegistersSize(), code_info, encoding);
}
// Add location entry for this address range.
diff --git a/compiler/debug/method_debug_info.h b/compiler/debug/method_debug_info.h
index a8225fa2b4..43c8de26aa 100644
--- a/compiler/debug/method_debug_info.h
+++ b/compiler/debug/method_debug_info.h
@@ -21,7 +21,7 @@
#include "arch/instruction_set.h"
#include "base/array_ref.h"
-#include "dex_file.h"
+#include "dex/dex_file.h"
namespace art {
namespace debug {
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index ead909af9a..52cb217980 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -26,8 +26,8 @@
#include "base/mutex.h"
#include "bytecode_utils.h"
#include "compiled_method.h"
-#include "dex_file-inl.h"
-#include "dex_instruction-inl.h"
+#include "dex/dex_file-inl.h"
+#include "dex/dex_instruction-inl.h"
#include "driver/compiler_driver.h"
#include "driver/dex_compilation_unit.h"
#include "mirror/dex_cache.h"
@@ -114,7 +114,8 @@ class DexCompiler {
void DexCompiler::Compile() {
DCHECK_EQ(dex_to_dex_compilation_level_, DexToDexCompilationLevel::kOptimize);
- IterationRange<DexInstructionIterator> instructions = unit_.GetCodeItem()->Instructions();
+ IterationRange<DexInstructionIterator> instructions(unit_.GetCodeItemAccessor().begin(),
+ unit_.GetCodeItemAccessor().end());
for (DexInstructionIterator it = instructions.begin(); it != instructions.end(); ++it) {
const uint32_t dex_pc = it.DexPc();
Instruction* inst = const_cast<Instruction*>(&it.Inst());
@@ -364,7 +365,7 @@ CompiledMethod* ArtCompileDEX(
if (kIsDebugBuild) {
// Double check that the counts line up with the size of the quicken info.
size_t quicken_count = 0;
- for (const DexInstructionPcPair& pair : code_item->Instructions()) {
+ for (const DexInstructionPcPair& pair : unit.GetCodeItemAccessor()) {
if (QuickenInfoTable::NeedsIndexForInstruction(&pair.Inst())) {
++quicken_count;
}
@@ -376,7 +377,7 @@ CompiledMethod* ArtCompileDEX(
// Dex pc is not serialized, only used for checking the instructions. Since we access the
// array based on the index of the quickened instruction, the indexes must line up perfectly.
// The reader side uses the NeedsIndexForInstruction function too.
- const Instruction& inst = code_item->InstructionAt(info.dex_pc);
+ const Instruction& inst = unit.GetCodeItemAccessor().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));
diff --git a/compiler/dex/dex_to_dex_compiler.h b/compiler/dex/dex_to_dex_compiler.h
index 87ddb395ad..80b94d2dc3 100644
--- a/compiler/dex/dex_to_dex_compiler.h
+++ b/compiler/dex/dex_to_dex_compiler.h
@@ -17,7 +17,7 @@
#ifndef ART_COMPILER_DEX_DEX_TO_DEX_COMPILER_H_
#define ART_COMPILER_DEX_DEX_TO_DEX_COMPILER_H_
-#include "dex_file.h"
+#include "dex/dex_file.h"
#include "handle.h"
#include "invoke_type.h"
diff --git a/compiler/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc
index 979c4c4ce2..19b190093f 100644
--- a/compiler/dex/dex_to_dex_decompiler_test.cc
+++ b/compiler/dex/dex_to_dex_decompiler_test.cc
@@ -20,7 +20,7 @@
#include "common_compiler_test.h"
#include "compiled_method-inl.h"
#include "compiler_callbacks.h"
-#include "dex_file.h"
+#include "dex/dex_file.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
#include "handle_scope-inl.h"
@@ -99,8 +99,10 @@ class DexToDexDecompilerTest : public CommonCompilerTest {
if (compiled_method != nullptr) {
table = compiled_method->GetVmapTable();
}
- optimizer::ArtDecompileDEX(
- *it.GetMethodCodeItem(), table, /* decompile_return_instruction */ true);
+ optimizer::ArtDecompileDEX(*updated_dex_file,
+ *it.GetMethodCodeItem(),
+ table,
+ /* decompile_return_instruction */ true);
it.Next();
}
DCHECK(!it.HasNext());
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc
index b409eb2dbb..ce67b85b99 100644
--- a/compiler/dex/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -20,11 +20,11 @@
#include "art_method-inl.h"
#include "base/enums.h"
#include "class_linker-inl.h"
-#include "code_item_accessors-inl.h"
-#include "dex_file-inl.h"
-#include "dex_instruction-inl.h"
-#include "dex_instruction.h"
-#include "dex_instruction_utils.h"
+#include "dex/code_item_accessors-inl.h"
+#include "dex/dex_file-inl.h"
+#include "dex/dex_instruction-inl.h"
+#include "dex/dex_instruction.h"
+#include "dex/dex_instruction_utils.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
@@ -141,8 +141,11 @@ bool Matcher::DoMatch(const CodeItemDataAccessor* code_item, MatchFn* const* pat
ArtMethod* GetTargetConstructor(ArtMethod* method, const Instruction* invoke_direct)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK_EQ(invoke_direct->Opcode(), Instruction::INVOKE_DIRECT);
- DCHECK_EQ(invoke_direct->VRegC_35c(),
- method->GetCodeItem()->registers_size_ - method->GetCodeItem()->ins_size_);
+ if (kIsDebugBuild) {
+ CodeItemDataAccessor accessor(method);
+ DCHECK_EQ(invoke_direct->VRegC_35c(),
+ accessor.RegistersSize() - accessor.InsSize());
+ }
uint32_t method_index = invoke_direct->VRegB_35c();
ArtMethod* target_method = Runtime::Current()->GetClassLinker()->LookupResolvedMethod(
method_index, method->GetDexCache(), method->GetClassLoader());
@@ -323,7 +326,7 @@ bool DoAnalyseConstructor(const CodeItemDataAccessor* code_item,
if (target_method->GetDeclaringClass()->IsObjectClass()) {
DCHECK_EQ(CodeItemDataAccessor(target_method).begin()->Opcode(), Instruction::RETURN_VOID);
} else {
- CodeItemDataAccessor target_code_item = CodeItemDataAccessor::CreateNullable(target_method);
+ CodeItemDataAccessor target_code_item(target_method);
if (!target_code_item.HasCodeItem()) {
return false; // Native constructor?
}
@@ -427,7 +430,7 @@ static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_SHORT) ==
InlineMethodAnalyser::IPutVariant(Instruction::IPUT_SHORT), "iget/iput_short variant");
bool InlineMethodAnalyser::AnalyseMethodCode(ArtMethod* method, InlineMethod* result) {
- CodeItemDataAccessor code_item = CodeItemDataAccessor::CreateNullable(method);
+ CodeItemDataAccessor code_item(method);
if (!code_item.HasCodeItem()) {
// Native or abstract.
return false;
diff --git a/compiler/dex/inline_method_analyser.h b/compiler/dex/inline_method_analyser.h
index cde2147995..837cc85456 100644
--- a/compiler/dex/inline_method_analyser.h
+++ b/compiler/dex/inline_method_analyser.h
@@ -19,8 +19,8 @@
#include "base/macros.h"
#include "base/mutex.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
+#include "dex/dex_file.h"
+#include "dex/dex_instruction.h"
#include "method_reference.h"
/*
diff --git a/compiler/dex/quick_compiler_callbacks.cc b/compiler/dex/quick_compiler_callbacks.cc
index 92b123013d..540bd0ce45 100644
--- a/compiler/dex/quick_compiler_callbacks.cc
+++ b/compiler/dex/quick_compiler_callbacks.cc
@@ -38,7 +38,7 @@ ClassStatus QuickCompilerCallbacks::GetPreviousClassState(ClassReference ref) {
// If we don't have class unloading enabled in the compiler, we will never see class that were
// previously verified. Return false to avoid overhead from the lookup in the compiler driver.
if (!does_class_unloading_) {
- return ClassStatus::kStatusNotReady;
+ return ClassStatus::kNotReady;
}
DCHECK(compiler_driver_ != nullptr);
// In the case of the quicken filter: avoiding verification of quickened instructions, which the
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index 8934201b10..f2da3ffc2f 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -21,9 +21,9 @@
#include <android-base/logging.h>
-#include "code_item_accessors-inl.h"
-#include "dex_file.h"
-#include "dex_instruction-inl.h"
+#include "dex/code_item_accessors-inl.h"
+#include "dex/dex_file.h"
+#include "dex/dex_instruction-inl.h"
#include "runtime.h"
#include "verifier/method_verifier-inl.h"
#include "verifier/reg_type-inl.h"
diff --git a/compiler/dex/verified_method.h b/compiler/dex/verified_method.h
index 64b3f448e6..2ed17f1dfd 100644
--- a/compiler/dex/verified_method.h
+++ b/compiler/dex/verified_method.h
@@ -20,7 +20,7 @@
#include <vector>
#include "base/mutex.h"
-#include "dex_file.h"
+#include "dex/dex_file.h"
#include "method_reference.h"
#include "safe_map.h"
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 1c65df8bb5..c0886d0185 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -42,13 +42,13 @@
#include "compiler.h"
#include "compiler_callbacks.h"
#include "compiler_driver-inl.h"
+#include "dex/dex_file-inl.h"
+#include "dex/dex_file_annotations.h"
+#include "dex/dex_instruction-inl.h"
#include "dex/dex_to_dex_compiler.h"
#include "dex/verification_results.h"
#include "dex/verified_method.h"
#include "dex_compilation_unit.h"
-#include "dex_file-inl.h"
-#include "dex_file_annotations.h"
-#include "dex_instruction-inl.h"
#include "driver/compiler_options.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/accounting/heap_bitmap.h"
@@ -402,12 +402,6 @@ static optimizer::DexToDexCompilationLevel GetDexToDexCompilationLevel(
Thread* self, const CompilerDriver& driver, Handle<mirror::ClassLoader> class_loader,
const DexFile& dex_file, const DexFile::ClassDef& class_def)
REQUIRES_SHARED(Locks::mutator_lock_) {
- // When the dex file is uncompressed in the APK, we do not generate a copy in the .vdex
- // file. As a result, dex2oat will map the dex file read-only, and we only need to check
- // that to know if we can do quickening.
- if (dex_file.GetContainer() != nullptr && dex_file.GetContainer()->IsReadOnly()) {
- return optimizer::DexToDexCompilationLevel::kDontDexToDexCompile;
- }
auto* const runtime = Runtime::Current();
DCHECK(driver.GetCompilerOptions().IsQuickeningCompilationEnabled());
const char* descriptor = dex_file.GetClassDescriptor(class_def);
@@ -708,6 +702,7 @@ void CompilerDriver::Resolve(jobject class_loader,
// stable order.
static void ResolveConstStrings(Handle<mirror::DexCache> dex_cache,
+ const DexFile& dex_file,
const DexFile::CodeItem* code_item)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (code_item == nullptr) {
@@ -716,7 +711,7 @@ static void ResolveConstStrings(Handle<mirror::DexCache> dex_cache,
}
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
- for (const DexInstructionPcPair& inst : code_item->Instructions()) {
+ for (const DexInstructionPcPair& inst : CodeItemInstructionAccessor(dex_file, code_item)) {
switch (inst->Opcode()) {
case Instruction::CONST_STRING:
case Instruction::CONST_STRING_JUMBO: {
@@ -778,7 +773,7 @@ static void ResolveConstStrings(CompilerDriver* driver,
continue;
}
previous_method_idx = method_idx;
- ResolveConstStrings(dex_cache, it.GetMethodCodeItem());
+ ResolveConstStrings(dex_cache, *dex_file, it.GetMethodCodeItem());
it.Next();
}
DCHECK(!it.HasNext());
@@ -955,14 +950,14 @@ class ResolveCatchBlockExceptionsClassVisitor : public ClassVisitor {
ArtMethod* method,
std::set<std::pair<dex::TypeIndex, const DexFile*>>* exceptions_to_resolve)
REQUIRES_SHARED(Locks::mutator_lock_) {
- const DexFile::CodeItem* code_item = method->GetCodeItem();
- if (code_item == nullptr) {
+ if (method->GetCodeItem() == nullptr) {
return; // native or abstract method
}
- if (code_item->tries_size_ == 0) {
+ CodeItemDataAccessor accessor(method);
+ if (accessor.TriesSize() == 0) {
return; // nothing to process
}
- const uint8_t* encoded_catch_handler_list = DexFile::GetCatchHandlerData(*code_item, 0);
+ const uint8_t* encoded_catch_handler_list = accessor.GetCatchHandlerData();
size_t num_encoded_catch_handlers = DecodeUnsignedLeb128(&encoded_catch_handler_list);
for (size_t i = 0; i < num_encoded_catch_handlers; i++) {
int32_t encoded_catch_handler_size = DecodeSignedLeb128(&encoded_catch_handler_list);
@@ -1814,7 +1809,7 @@ static void PopulateVerifiedMethods(const DexFile& dex_file,
static void LoadAndUpdateStatus(const DexFile& dex_file,
const DexFile::ClassDef& class_def,
- mirror::Class::Status status,
+ ClassStatus status,
Handle<mirror::ClassLoader> class_loader,
Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -1873,16 +1868,16 @@ bool CompilerDriver::FastVerify(jobject jclass_loader,
// Just update the compiled_classes_ map. The compiler doesn't need to resolve
// the type.
ClassReference ref(dex_file, i);
- mirror::Class::Status existing = mirror::Class::kStatusNotReady;
+ ClassStatus existing = ClassStatus::kNotReady;
DCHECK(compiled_classes_.Get(ref, &existing)) << ref.dex_file->GetLocation();
ClassStateTable::InsertResult result =
- compiled_classes_.Insert(ref, existing, mirror::Class::kStatusVerified);
+ compiled_classes_.Insert(ref, existing, ClassStatus::kVerified);
CHECK_EQ(result, ClassStateTable::kInsertResultSuccess);
} else {
// Update the class status, so later compilation stages know they don't need to verify
// the class.
LoadAndUpdateStatus(
- *dex_file, class_def, mirror::Class::kStatusVerified, class_loader, soa.Self());
+ *dex_file, class_def, ClassStatus::kVerified, class_loader, soa.Self());
// Create `VerifiedMethod`s for each methods, the compiler expects one for
// quickening or compiling.
// Note that this means:
@@ -1896,7 +1891,7 @@ bool CompilerDriver::FastVerify(jobject jclass_loader,
// this class again.
LoadAndUpdateStatus(*dex_file,
class_def,
- mirror::Class::kStatusRetryVerificationAtRuntime,
+ ClassStatus::kRetryVerificationAtRuntime,
class_loader,
soa.Self());
}
@@ -2110,10 +2105,10 @@ class SetVerifiedClassVisitor : public CompilationVisitor {
// Only do this if the class is resolved. If even resolution fails, quickening will go very,
// very wrong.
if (klass->IsResolved() && !klass->IsErroneousResolved()) {
- if (klass->GetStatus() < mirror::Class::kStatusVerified) {
+ if (klass->GetStatus() < ClassStatus::kVerified) {
ObjectLock<mirror::Class> lock(soa.Self(), klass);
// Set class status to verified.
- mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, soa.Self());
+ mirror::Class::SetStatus(klass, ClassStatus::kVerified, soa.Self());
// Mark methods as pre-verified. If we don't do this, the interpreter will run with
// access checks.
klass->SetSkipAccessChecksFlagOnAllMethods(
@@ -2190,7 +2185,7 @@ class InitializeClassVisitor : public CompilationVisitor {
const bool is_boot_image = manager_->GetCompiler()->GetCompilerOptions().IsBootImage();
const bool is_app_image = manager_->GetCompiler()->GetCompilerOptions().IsAppImage();
- mirror::Class::Status old_status = klass->GetStatus();
+ ClassStatus old_status = klass->GetStatus();
// Don't initialize classes in boot space when compiling app image
if (is_app_image && klass->IsBootStrapClassLoaded()) {
// Also return early and don't store the class status in the recorded class status.
@@ -2315,7 +2310,7 @@ class InitializeClassVisitor : public CompilationVisitor {
// would do so they can be skipped at runtime.
if (!klass->IsInitialized() &&
manager_->GetClassLinker()->ValidateSuperClassDescriptors(klass)) {
- old_status = mirror::Class::kStatusSuperclassValidated;
+ old_status = ClassStatus::kSuperclassValidated;
} else {
soa.Self()->ClearException();
}
@@ -2358,9 +2353,7 @@ class InitializeClassVisitor : public CompilationVisitor {
// Intern strings seen in <clinit>.
ArtMethod* clinit = klass->FindClassInitializer(class_linker->GetImagePointerSize());
if (clinit != nullptr) {
- const DexFile::CodeItem* code_item = clinit->GetCodeItem();
- DCHECK(code_item != nullptr);
- for (const DexInstructionPcPair& inst : code_item->Instructions()) {
+ for (const DexInstructionPcPair& inst : clinit->DexInstructions()) {
if (inst->Opcode() == Instruction::CONST_STRING) {
ObjPtr<mirror::String> s = class_linker->ResolveString(
dex::StringIndex(inst->VRegB_21c()), dex_cache);
@@ -2778,36 +2771,36 @@ void CompilerDriver::AddCompiledMethod(const MethodReference& method_ref,
DCHECK(GetCompiledMethod(method_ref) != nullptr) << method_ref.PrettyMethod();
}
-bool CompilerDriver::GetCompiledClass(const ClassReference& ref,
- mirror::Class::Status* status) const {
+bool CompilerDriver::GetCompiledClass(const ClassReference& ref, ClassStatus* status) const {
DCHECK(status != nullptr);
// The table doesn't know if something wasn't inserted. For this case it will return
- // kStatusNotReady. To handle this, just assume anything we didn't try to verify is not compiled.
+ // ClassStatus::kNotReady. To handle this, just assume anything we didn't try to verify
+ // is not compiled.
if (!compiled_classes_.Get(ref, status) ||
- *status < mirror::Class::kStatusRetryVerificationAtRuntime) {
+ *status < ClassStatus::kRetryVerificationAtRuntime) {
return false;
}
return true;
}
-mirror::Class::Status CompilerDriver::GetClassStatus(const ClassReference& ref) const {
- mirror::Class::Status status = ClassStatus::kStatusNotReady;
+ClassStatus CompilerDriver::GetClassStatus(const ClassReference& ref) const {
+ ClassStatus status = ClassStatus::kNotReady;
if (!GetCompiledClass(ref, &status)) {
classpath_classes_.Get(ref, &status);
}
return status;
}
-void CompilerDriver::RecordClassStatus(const ClassReference& ref, mirror::Class::Status status) {
+void CompilerDriver::RecordClassStatus(const ClassReference& ref, ClassStatus status) {
switch (status) {
- case mirror::Class::kStatusErrorResolved:
- case mirror::Class::kStatusErrorUnresolved:
- case mirror::Class::kStatusNotReady:
- case mirror::Class::kStatusResolved:
- case mirror::Class::kStatusRetryVerificationAtRuntime:
- case mirror::Class::kStatusVerified:
- case mirror::Class::kStatusSuperclassValidated:
- case mirror::Class::kStatusInitialized:
+ case ClassStatus::kErrorResolved:
+ case ClassStatus::kErrorUnresolved:
+ case ClassStatus::kNotReady:
+ case ClassStatus::kResolved:
+ case ClassStatus::kRetryVerificationAtRuntime:
+ case ClassStatus::kVerified:
+ case ClassStatus::kSuperclassValidated:
+ case ClassStatus::kInitialized:
break; // Expected states.
default:
LOG(FATAL) << "Unexpected class status for class "
@@ -2819,7 +2812,7 @@ void CompilerDriver::RecordClassStatus(const ClassReference& ref, mirror::Class:
ClassStateTable::InsertResult result;
ClassStateTable* table = &compiled_classes_;
do {
- mirror::Class::Status existing = mirror::Class::kStatusNotReady;
+ ClassStatus existing = ClassStatus::kNotReady;
if (!table->Get(ref, &existing)) {
// A classpath class.
if (kIsDebugBuild) {
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 07b65438b0..ef16212fb7 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -31,13 +31,13 @@
#include "base/mutex.h"
#include "base/timing_logger.h"
#include "class_reference.h"
+#include "class_status.h"
#include "compiler.h"
-#include "dex_file.h"
-#include "dex_file_types.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_types.h"
#include "driver/compiled_method_storage.h"
#include "jit/profile_compilation_info.h"
#include "method_reference.h"
-#include "mirror/class.h" // For mirror::Class::Status.
#include "os.h"
#include "safe_map.h"
#include "thread_pool.h"
@@ -47,6 +47,7 @@
namespace art {
namespace mirror {
+class Class;
class DexCache;
} // namespace mirror
@@ -55,18 +56,21 @@ class MethodVerifier;
class VerifierDepsTest;
} // namespace verifier
+class ArtField;
class BitVector;
class CompiledMethod;
class CompilerOptions;
class DexCompilationUnit;
+template<class T> class Handle;
struct InlineIGetIPutData;
class InstructionSetFeatures;
class InternTable;
enum InvokeType : uint32_t;
+class MemberOffset;
+template<class MirrorType> class ObjPtr;
class ParallelCompilationManager;
class ScopedObjectAccess;
template <class Allocator> class SrcMap;
-template<class T> class Handle;
class TimingLogger;
class VdexFile;
class VerificationResults;
@@ -102,13 +106,13 @@ class CompilerDriver {
~CompilerDriver();
- // Set dex files associated with the oat file being compiled.
+ // Set dex files that will be stored in the oat file after being compiled.
void SetDexFilesForOatFile(const std::vector<const DexFile*>& dex_files);
// Set dex files classpath.
void SetClasspathDexFiles(const std::vector<const DexFile*>& dex_files);
- // Get dex files associated with the the oat file being compiled.
+ // Get dex file that will be stored in the oat file after being compiled.
ArrayRef<const DexFile* const> GetDexFilesForOatFile() const {
return ArrayRef<const DexFile* const>(dex_files_for_oat_file_);
}
@@ -152,8 +156,8 @@ class CompilerDriver {
std::unique_ptr<const std::vector<uint8_t>> CreateQuickResolutionTrampoline() const;
std::unique_ptr<const std::vector<uint8_t>> CreateQuickToInterpreterBridge() const;
- mirror::Class::Status GetClassStatus(const ClassReference& ref) const;
- bool GetCompiledClass(const ClassReference& ref, mirror::Class::Status* status) const;
+ ClassStatus GetClassStatus(const ClassReference& ref) const;
+ bool GetCompiledClass(const ClassReference& ref, ClassStatus* status) const;
CompiledMethod* GetCompiledMethod(MethodReference ref) const;
size_t GetNonRelativeLinkerPatchCount() const;
@@ -321,7 +325,7 @@ class CompilerDriver {
// according to the profile file.
bool ShouldVerifyClassBasedOnProfile(const DexFile& dex_file, uint16_t class_idx) const;
- void RecordClassStatus(const ClassReference& ref, mirror::Class::Status status);
+ void RecordClassStatus(const ClassReference& ref, ClassStatus status);
// Checks if the specified method has been verified without failures. Returns
// false if the method is not in the verification results (GetVerificationResults).
@@ -476,7 +480,7 @@ class CompilerDriver {
GUARDED_BY(requires_constructor_barrier_lock_);
// All class references that this compiler has compiled. Indexed by class defs.
- using ClassStateTable = AtomicDexRefMap<ClassReference, mirror::Class::Status>;
+ using ClassStateTable = AtomicDexRefMap<ClassReference, ClassStatus>;
ClassStateTable compiled_classes_;
// All class references that are in the classpath. Indexed by class defs.
ClassStateTable classpath_classes_;
@@ -525,7 +529,7 @@ class CompilerDriver {
bool support_boot_image_fixup_;
- // List of dex files associates with the oat file.
+ // List of dex files that will be stored in the oat file.
std::vector<const DexFile*> dex_files_for_oat_file_;
CompiledMethodStorage compiled_method_storage_;
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 278358b250..162904c0e7 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -16,16 +16,18 @@
#include "driver/compiler_driver.h"
+#include <limits>
#include <stdint.h>
#include <stdio.h>
#include <memory>
#include "art_method-inl.h"
+#include "base/casts.h"
#include "class_linker-inl.h"
#include "common_compiler_test.h"
#include "compiler_callbacks.h"
-#include "dex_file.h"
-#include "dex_file_types.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_types.h"
#include "gc/heap.h"
#include "handle_scope-inl.h"
#include "jit/profile_compilation_info.h"
@@ -344,11 +346,11 @@ class CompilerDriverVerifyTest : public CompilerDriverTest {
ASSERT_NE(klass, nullptr);
EXPECT_TRUE(klass->IsVerified());
- mirror::Class::Status status;
+ ClassStatus status;
bool found = compiler_driver_->GetCompiledClass(
ClassReference(&klass->GetDexFile(), klass->GetDexTypeIndex().index_), &status);
ASSERT_TRUE(found);
- EXPECT_EQ(status, mirror::Class::kStatusVerified);
+ EXPECT_EQ(status, ClassStatus::kVerified);
}
};
@@ -367,8 +369,8 @@ TEST_F(CompilerDriverVerifyTest, VerifyCompilation) {
CheckVerifiedClass(class_loader, "LSecond;");
}
-// Test that a class of status kStatusRetryVerificationAtRuntime is indeed recorded that way in the
-// driver.
+// Test that a class of status ClassStatus::kRetryVerificationAtRuntime is indeed
+// recorded that way in the driver.
TEST_F(CompilerDriverVerifyTest, RetryVerifcationStatusCheckVerified) {
Thread* const self = Thread::Current();
jobject class_loader;
@@ -386,17 +388,19 @@ TEST_F(CompilerDriverVerifyTest, RetryVerifcationStatusCheckVerified) {
callbacks_->SetDoesClassUnloading(true, compiler_driver_.get());
ClassReference ref(dex_file, 0u);
// Test that the status is read from the compiler driver as expected.
- for (size_t i = mirror::Class::kStatusRetryVerificationAtRuntime;
- i < mirror::Class::kStatusMax;
- ++i) {
- const mirror::Class::Status expected_status = static_cast<mirror::Class::Status>(i);
+ static_assert(enum_cast<size_t>(ClassStatus::kLast) < std::numeric_limits<size_t>::max(),
+ "Make sure incrementing the class status does not overflow.");
+ for (size_t i = enum_cast<size_t>(ClassStatus::kRetryVerificationAtRuntime);
+ i <= enum_cast<size_t>(ClassStatus::kLast);
+ ++i) {
+ const ClassStatus expected_status = enum_cast<ClassStatus>(i);
// Skip unsupported status that are not supposed to be ever recorded.
- if (expected_status == mirror::Class::kStatusVerifyingAtRuntime ||
- expected_status == mirror::Class::kStatusInitializing) {
+ if (expected_status == ClassStatus::kVerifyingAtRuntime ||
+ expected_status == ClassStatus::kInitializing) {
continue;
}
compiler_driver_->RecordClassStatus(ref, expected_status);
- mirror::Class::Status status = {};
+ ClassStatus status = {};
ASSERT_TRUE(compiler_driver_->GetCompiledClass(ref, &status));
EXPECT_EQ(status, expected_status);
}
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index c0a9a05aa6..1780b1d7ed 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -20,6 +20,7 @@
#include "android-base/stringprintf.h"
+#include "base/runtime_debug.h"
#include "base/variant_map.h"
#include "cmdline_parser.h"
#include "compiler_options_map-inl.h"
@@ -68,17 +69,16 @@ CompilerOptions::~CompilerOptions() {
// because we don't want to include the PassManagerOptions definition from the header file.
}
+namespace {
+
+bool kEmitRuntimeReadBarrierChecks = kIsDebugBuild &&
+ RegisterRuntimeDebugFlag(&kEmitRuntimeReadBarrierChecks);
+
+} // namespace
+
bool CompilerOptions::EmitRunTimeChecksInDebugMode() const {
- // Run-time checks (e.g. Marking Register checks) are only emitted
- // in debug mode, and
- // - when running on device; or
- // - when running on host, but only
- // - when compiling the core image (which is used only for testing); or
- // - when JIT compiling (only relevant for non-native methods).
- // This is to prevent these checks from being emitted into pre-opted
- // boot image or apps, as these are compiled with dex2oatd.
- return kIsDebugBuild &&
- (kIsTargetBuild || IsCoreImage() || Runtime::Current()->UseJitCompilation());
+ // Run-time checks (e.g. Marking Register checks) are only emitted in slow-debug mode.
+ return kEmitRuntimeReadBarrierChecks;
}
bool CompilerOptions::ParseDumpInitFailures(const std::string& option, std::string* error_msg) {
diff --git a/compiler/driver/dex_compilation_unit.cc b/compiler/driver/dex_compilation_unit.cc
index 7e8e812c4a..28e68c94df 100644
--- a/compiler/driver/dex_compilation_unit.cc
+++ b/compiler/driver/dex_compilation_unit.cc
@@ -16,6 +16,7 @@
#include "dex_compilation_unit.h"
+#include "dex/code_item_accessors-inl.h"
#include "mirror/dex_cache.h"
#include "utils.h"
@@ -38,8 +39,8 @@ DexCompilationUnit::DexCompilationUnit(Handle<mirror::ClassLoader> class_loader,
dex_method_idx_(method_idx),
access_flags_(access_flags),
verified_method_(verified_method),
- dex_cache_(dex_cache) {
-}
+ dex_cache_(dex_cache),
+ code_item_accessor_(dex_file, code_item) {}
const std::string& DexCompilationUnit::GetSymbol() {
if (symbol_.empty()) {
diff --git a/compiler/driver/dex_compilation_unit.h b/compiler/driver/dex_compilation_unit.h
index 24a9a5b653..c1ae3c938b 100644
--- a/compiler/driver/dex_compilation_unit.h
+++ b/compiler/driver/dex_compilation_unit.h
@@ -20,7 +20,8 @@
#include <stdint.h>
#include "base/arena_object.h"
-#include "dex_file.h"
+#include "dex/code_item_accessors.h"
+#include "dex/dex_file.h"
#include "handle.h"
#include "jni.h"
@@ -112,6 +113,10 @@ class DexCompilationUnit : public DeletableArenaObject<kArenaAllocMisc> {
return dex_cache_;
}
+ const CodeItemDataAccessor& GetCodeItemAccessor() const {
+ return code_item_accessor_;
+ }
+
private:
const Handle<mirror::ClassLoader> class_loader_;
@@ -127,6 +132,8 @@ class DexCompilationUnit : public DeletableArenaObject<kArenaAllocMisc> {
const Handle<mirror::DexCache> dex_cache_;
+ const CodeItemDataAccessor code_item_accessor_;
+
std::string symbol_;
};
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
index 897b50bdac..7bacacf91d 100644
--- a/compiler/exception_test.cc
+++ b/compiler/exception_test.cc
@@ -21,8 +21,10 @@
#include "base/enums.h"
#include "class_linker.h"
#include "common_runtime_test.h"
-#include "dex_file-inl.h"
-#include "dex_file.h"
+#include "dex/code_item_accessors-inl.h"
+#include "dex/dex_file-inl.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_exception_helpers.h"
#include "gtest/gtest.h"
#include "handle_scope-inl.h"
#include "leb128.h"
@@ -128,19 +130,18 @@ class ExceptionTest : public CommonRuntimeTest {
TEST_F(ExceptionTest, FindCatchHandler) {
ScopedObjectAccess soa(Thread::Current());
- const DexFile::CodeItem* code_item = dex_->GetCodeItem(method_f_->GetCodeItemOffset());
+ CodeItemDataAccessor accessor(*dex_, dex_->GetCodeItem(method_f_->GetCodeItemOffset()));
- ASSERT_TRUE(code_item != nullptr);
+ ASSERT_TRUE(accessor.HasCodeItem());
- ASSERT_EQ(2u, code_item->tries_size_);
- ASSERT_NE(0u, code_item->insns_size_in_code_units_);
+ ASSERT_EQ(2u, accessor.TriesSize());
+ ASSERT_NE(0u, accessor.InsnsSizeInCodeUnits());
- const DexFile::TryItem *t0, *t1;
- t0 = dex_->GetTryItems(*code_item, 0);
- t1 = dex_->GetTryItems(*code_item, 1);
- EXPECT_LE(t0->start_addr_, t1->start_addr_);
+ const DexFile::TryItem& t0 = accessor.TryItems().begin()[0];
+ const DexFile::TryItem& t1 = accessor.TryItems().begin()[1];
+ EXPECT_LE(t0.start_addr_, t1.start_addr_);
{
- CatchHandlerIterator iter(*code_item, 4 /* Dex PC in the first try block */);
+ CatchHandlerIterator iter(accessor, 4 /* Dex PC in the first try block */);
EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
ASSERT_TRUE(iter.HasNext());
iter.Next();
@@ -150,14 +151,14 @@ TEST_F(ExceptionTest, FindCatchHandler) {
EXPECT_FALSE(iter.HasNext());
}
{
- CatchHandlerIterator iter(*code_item, 8 /* Dex PC in the second try block */);
+ CatchHandlerIterator iter(accessor, 8 /* Dex PC in the second try block */);
EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
ASSERT_TRUE(iter.HasNext());
iter.Next();
EXPECT_FALSE(iter.HasNext());
}
{
- CatchHandlerIterator iter(*code_item, 11 /* Dex PC not in any try block */);
+ CatchHandlerIterator iter(accessor, 11 /* Dex PC not in any try block */);
EXPECT_FALSE(iter.HasNext());
}
}
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index daf64d1298..f34e9b844b 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -24,7 +24,7 @@
#include "class_linker.h"
#include "common_compiler_test.h"
#include "compiler.h"
-#include "dex_file.h"
+#include "dex/dex_file.h"
#include "gtest/gtest.h"
#include "indirect_reference_table.h"
#include "java_vm_ext.h"
@@ -299,7 +299,6 @@ class JniCompilerTest : public CommonCompilerTest {
}
// JNI operations after runtime start.
env_ = Thread::Current()->GetJniEnv();
- library_search_path_ = env_->NewStringUTF("");
jklass_ = env_->FindClass("MyClassNatives");
ASSERT_TRUE(jklass_ != nullptr) << method_name << " " << method_sig;
@@ -380,7 +379,6 @@ class JniCompilerTest : public CommonCompilerTest {
void CriticalNativeImpl();
JNIEnv* env_;
- jstring library_search_path_;
jmethodID jmethod_;
private:
@@ -660,7 +658,7 @@ void JniCompilerTest::CompileAndRunIntMethodThroughStubImpl() {
std::string reason;
ASSERT_TRUE(Runtime::Current()->GetJavaVM()->
- LoadNativeLibrary(env_, "", class_loader_, library_search_path_, &reason))
+ LoadNativeLibrary(env_, "", class_loader_, &reason))
<< reason;
jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
@@ -676,7 +674,7 @@ void JniCompilerTest::CompileAndRunStaticIntMethodThroughStubImpl() {
std::string reason;
ASSERT_TRUE(Runtime::Current()->GetJavaVM()->
- LoadNativeLibrary(env_, "", class_loader_, library_search_path_, &reason))
+ LoadNativeLibrary(env_, "", class_loader_, &reason))
<< reason;
jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42);
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 136e3db062..fc44927231 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -30,7 +30,7 @@
#include "calling_convention.h"
#include "class_linker.h"
#include "debug/dwarf/debug_frame_opcode_writer.h"
-#include "dex_file-inl.h"
+#include "dex/dex_file-inl.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
#include "entrypoints/quick/quick_entrypoints.h"
diff --git a/compiler/linker/arm/relative_patcher_arm_base.cc b/compiler/linker/arm/relative_patcher_arm_base.cc
index 2cb23d1710..cedbe5d97f 100644
--- a/compiler/linker/arm/relative_patcher_arm_base.cc
+++ b/compiler/linker/arm/relative_patcher_arm_base.cc
@@ -19,7 +19,7 @@
#include "base/stl_util.h"
#include "compiled_method-inl.h"
#include "debug/method_debug_info.h"
-#include "dex_file_types.h"
+#include "dex/dex_file_types.h"
#include "linker/linker_patch.h"
#include "linker/output_stream.h"
#include "oat.h"
diff --git a/compiler/linker/elf_builder.h b/compiler/linker/elf_builder.h
index aa3cd98595..5262ab6f3b 100644
--- a/compiler/linker/elf_builder.h
+++ b/compiler/linker/elf_builder.h
@@ -38,9 +38,10 @@ namespace linker {
// Elf_Ehdr - The ELF header.
// Elf_Phdr[] - Program headers for the linker.
// .note.gnu.build-id - Optional build ID section (SHA-1 digest).
-// .rodata - DEX files and oat metadata.
+// .rodata - Oat metadata.
// .text - Compiled code.
// .bss - Zero-initialized writeable section.
+// .dex - Reserved NOBITS space for dex-related data.
// .MIPS.abiflags - MIPS specific section.
// .dynstr - Names for .dynsym.
// .dynsym - A few oat-specific dynamic symbols.
@@ -503,6 +504,7 @@ class ElfBuilder FINAL {
rodata_(this, ".rodata", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
text_(this, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, nullptr, 0, kPageSize, 0),
bss_(this, ".bss", SHT_NOBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
+ dex_(this, ".dex", SHT_NOBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
dynstr_(this, ".dynstr", SHF_ALLOC, kPageSize),
dynsym_(this, ".dynsym", SHT_DYNSYM, SHF_ALLOC, &dynstr_),
hash_(this, ".hash", SHT_HASH, SHF_ALLOC, &dynsym_, 0, sizeof(Elf_Word), sizeof(Elf_Word)),
@@ -525,6 +527,7 @@ class ElfBuilder FINAL {
virtual_address_(0) {
text_.phdr_flags_ = PF_R | PF_X;
bss_.phdr_flags_ = PF_R | PF_W;
+ dex_.phdr_flags_ = PF_R;
dynamic_.phdr_flags_ = PF_R | PF_W;
dynamic_.phdr_type_ = PT_DYNAMIC;
eh_frame_hdr_.phdr_type_ = PT_GNU_EH_FRAME;
@@ -538,6 +541,7 @@ class ElfBuilder FINAL {
Section* GetRoData() { return &rodata_; }
Section* GetText() { return &text_; }
Section* GetBss() { return &bss_; }
+ Section* GetDex() { return &dex_; }
StringSection* GetStrTab() { return &strtab_; }
SymbolSection* GetSymTab() { return &symtab_; }
Section* GetEhFrame() { return &eh_frame_; }
@@ -666,7 +670,8 @@ class ElfBuilder FINAL {
Elf_Word text_size,
Elf_Word bss_size,
Elf_Word bss_methods_offset,
- Elf_Word bss_roots_offset) {
+ Elf_Word bss_roots_offset,
+ Elf_Word dex_size) {
std::string soname(elf_file_path);
size_t directory_separator_pos = soname.rfind('/');
if (directory_separator_pos != std::string::npos) {
@@ -679,6 +684,9 @@ class ElfBuilder FINAL {
if (bss_size != 0) {
bss_.AllocateVirtualMemory(bss_size);
}
+ if (dex_size != 0) {
+ dex_.AllocateVirtualMemory(dex_size);
+ }
if (isa_ == InstructionSet::kMips || isa_ == InstructionSet::kMips64) {
abiflags_.AllocateVirtualMemory(abiflags_.GetSize());
}
@@ -725,6 +733,14 @@ class ElfBuilder FINAL {
Elf_Word bsslastword_address = bss_.GetAddress() + bss_size - 4;
dynsym_.Add(oatbsslastword, &bss_, bsslastword_address, 4, STB_GLOBAL, STT_OBJECT);
}
+ if (dex_size != 0u) {
+ Elf_Word oatdex = dynstr_.Add("oatdex");
+ dynsym_.Add(oatdex, &dex_, dex_.GetAddress(), dex_size, STB_GLOBAL, STT_OBJECT);
+ Elf_Word oatdexlastword = dynstr_.Add("oatdexlastword");
+ Elf_Word oatdexlastword_address = dex_.GetAddress() + dex_size - 4;
+ dynsym_.Add(oatdexlastword, &dex_, oatdexlastword_address, 4, STB_GLOBAL, STT_OBJECT);
+ }
+
Elf_Word soname_offset = dynstr_.Add(soname);
// We do not really need a hash-table since there is so few entries.
@@ -967,6 +983,7 @@ class ElfBuilder FINAL {
Section rodata_;
Section text_;
Section bss_;
+ Section dex_;
CachedStringSection dynstr_;
SymbolSection dynsym_;
CachedSection hash_;
diff --git a/compiler/optimizing/block_builder.cc b/compiler/optimizing/block_builder.cc
index 58f591bd1e..2b568bcffd 100644
--- a/compiler/optimizing/block_builder.cc
+++ b/compiler/optimizing/block_builder.cc
@@ -18,10 +18,32 @@
#include "base/logging.h" // FOR VLOG.
#include "bytecode_utils.h"
+#include "dex/code_item_accessors-inl.h"
+#include "dex/dex_file_exception_helpers.h"
#include "quicken_info.h"
namespace art {
+HBasicBlockBuilder::HBasicBlockBuilder(HGraph* graph,
+ const DexFile* const dex_file,
+ const CodeItemDebugInfoAccessor& accessor,
+ ScopedArenaAllocator* local_allocator)
+ : allocator_(graph->GetAllocator()),
+ graph_(graph),
+ dex_file_(dex_file),
+ code_item_accessor_(accessor),
+ local_allocator_(local_allocator),
+ branch_targets_(code_item_accessor_.HasCodeItem()
+ ? code_item_accessor_.InsnsSizeInCodeUnits()
+ : /* fake dex_pc=0 for intrinsic graph */ 1u,
+ nullptr,
+ local_allocator->Adapter(kArenaAllocGraphBuilder)),
+ throwing_blocks_(kDefaultNumberOfThrowingBlocks,
+ local_allocator->Adapter(kArenaAllocGraphBuilder)),
+ number_of_branches_(0u),
+ quicken_index_for_dex_pc_(std::less<uint32_t>(),
+ local_allocator->Adapter(kArenaAllocGraphBuilder)) {}
+
HBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t dex_pc) {
return MaybeCreateBlockAt(dex_pc, dex_pc);
}
@@ -41,20 +63,19 @@ bool HBasicBlockBuilder::CreateBranchTargets() {
// Create the first block for the dex instructions, single successor of the entry block.
MaybeCreateBlockAt(0u);
- if (code_item_->tries_size_ != 0) {
+ if (code_item_accessor_.TriesSize() != 0) {
// Create branch targets at the start/end of the TryItem range. These are
// places where the program might fall through into/out of the a block and
// where TryBoundary instructions will be inserted later. Other edges which
// enter/exit the try blocks are a result of branches/switches.
- for (size_t idx = 0; idx < code_item_->tries_size_; ++idx) {
- const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item_, idx);
- uint32_t dex_pc_start = try_item->start_addr_;
- uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_;
+ for (const DexFile::TryItem& try_item : code_item_accessor_.TryItems()) {
+ uint32_t dex_pc_start = try_item.start_addr_;
+ uint32_t dex_pc_end = dex_pc_start + try_item.insn_count_;
MaybeCreateBlockAt(dex_pc_start);
- if (dex_pc_end < code_item_->insns_size_in_code_units_) {
+ if (dex_pc_end < code_item_accessor_.InsnsSizeInCodeUnits()) {
// TODO: Do not create block if the last instruction cannot fall through.
MaybeCreateBlockAt(dex_pc_end);
- } else if (dex_pc_end == code_item_->insns_size_in_code_units_) {
+ } else if (dex_pc_end == code_item_accessor_.InsnsSizeInCodeUnits()) {
// The TryItem spans until the very end of the CodeItem and therefore
// cannot have any code afterwards.
} else {
@@ -65,7 +86,7 @@ bool HBasicBlockBuilder::CreateBranchTargets() {
}
// Create branch targets for exception handlers.
- const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
+ const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData();
uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
for (uint32_t idx = 0; idx < handlers_size; ++idx) {
CatchHandlerIterator iterator(handlers_ptr);
@@ -78,8 +99,7 @@ bool HBasicBlockBuilder::CreateBranchTargets() {
// Iterate over all instructions and find branching instructions. Create blocks for
// the locations these instructions branch to.
- IterationRange<DexInstructionIterator> instructions = code_item_->Instructions();
- for (const DexInstructionPcPair& pair : instructions) {
+ for (const DexInstructionPcPair& pair : code_item_accessor_) {
const uint32_t dex_pc = pair.DexPc();
const Instruction& instruction = pair.Inst();
@@ -109,7 +129,7 @@ bool HBasicBlockBuilder::CreateBranchTargets() {
if (instruction.CanFlowThrough()) {
DexInstructionIterator next(std::next(DexInstructionIterator(pair)));
- if (next == instructions.end()) {
+ if (next == code_item_accessor_.end()) {
// In the normal case we should never hit this but someone can artificially forge a dex
// file to fall-through out the method code. In this case we bail out compilation.
VLOG(compiler) << "Not compiled: Fall-through beyond the CodeItem";
@@ -130,7 +150,7 @@ void HBasicBlockBuilder::ConnectBasicBlocks() {
bool is_throwing_block = false;
// Calculate the qucikening index here instead of CreateBranchTargets since it's easier to
// calculate in dex_pc order.
- for (const DexInstructionPcPair& pair : code_item_->Instructions()) {
+ for (const DexInstructionPcPair& pair : code_item_accessor_) {
const uint32_t dex_pc = pair.DexPc();
const Instruction& instruction = pair.Inst();
@@ -213,10 +233,12 @@ static const DexFile::TryItem* GetTryItem(
// successors matches the order in which runtime exception delivery searches
// for a handler.
static void LinkToCatchBlocks(HTryBoundary* try_boundary,
- const DexFile::CodeItem& code_item,
+ const CodeItemDataAccessor& accessor,
const DexFile::TryItem* try_item,
const ScopedArenaSafeMap<uint32_t, HBasicBlock*>& catch_blocks) {
- for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) {
+ for (CatchHandlerIterator it(accessor.GetCatchHandlerData(try_item->handler_off_));
+ it.HasNext();
+ it.Next()) {
try_boundary->AddExceptionHandler(catch_blocks.Get(it.GetHandlerAddress()));
}
}
@@ -232,7 +254,7 @@ bool HBasicBlockBuilder::MightHaveLiveNormalPredecessors(HBasicBlock* catch_bloc
}
}
- const Instruction& first = code_item_->InstructionAt(catch_block->GetDexPc());
+ const Instruction& first = code_item_accessor_.InstructionAt(catch_block->GetDexPc());
if (first.Opcode() == Instruction::MOVE_EXCEPTION) {
// Verifier guarantees that if a catch block begins with MOVE_EXCEPTION then
// it has no live normal predecessors.
@@ -250,7 +272,7 @@ bool HBasicBlockBuilder::MightHaveLiveNormalPredecessors(HBasicBlock* catch_bloc
}
void HBasicBlockBuilder::InsertTryBoundaryBlocks() {
- if (code_item_->tries_size_ == 0) {
+ if (code_item_accessor_.TriesSize() == 0) {
return;
}
@@ -272,12 +294,10 @@ void HBasicBlockBuilder::InsertTryBoundaryBlocks() {
// loop for synchronized blocks.
if (ContainsElement(throwing_blocks_, block)) {
// Try to find a TryItem covering the block.
- const int32_t try_item_idx = DexFile::FindTryItem(DexFile::GetTryItems(*code_item_, 0u),
- code_item_->tries_size_,
- block->GetDexPc());
- if (try_item_idx != -1) {
+ const DexFile::TryItem* try_item = code_item_accessor_.FindTryItem(block->GetDexPc());
+ if (try_item != nullptr) {
// Block throwing and in a TryItem. Store the try block information.
- try_block_info.Put(block->GetBlockId(), DexFile::GetTryItems(*code_item_, try_item_idx));
+ try_block_info.Put(block->GetBlockId(), try_item);
}
}
}
@@ -288,7 +308,7 @@ void HBasicBlockBuilder::InsertTryBoundaryBlocks() {
// Iterate over catch blocks, create artifical landing pads if necessary to
// simplify the CFG, and set metadata.
- const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
+ const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData();
uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
for (uint32_t idx = 0; idx < handlers_size; ++idx) {
CatchHandlerIterator iterator(handlers_ptr);
@@ -336,7 +356,7 @@ void HBasicBlockBuilder::InsertTryBoundaryBlocks() {
HTryBoundary* try_entry = new (allocator_) HTryBoundary(
HTryBoundary::BoundaryKind::kEntry, try_block->GetDexPc());
try_block->CreateImmediateDominator()->AddInstruction(try_entry);
- LinkToCatchBlocks(try_entry, *code_item_, try_item, catch_blocks);
+ LinkToCatchBlocks(try_entry, code_item_accessor_, try_item, catch_blocks);
break;
}
}
@@ -364,13 +384,13 @@ void HBasicBlockBuilder::InsertTryBoundaryBlocks() {
HTryBoundary* try_exit =
new (allocator_) HTryBoundary(HTryBoundary::BoundaryKind::kExit, successor->GetDexPc());
graph_->SplitEdge(try_block, successor)->AddInstruction(try_exit);
- LinkToCatchBlocks(try_exit, *code_item_, try_item, catch_blocks);
+ LinkToCatchBlocks(try_exit, code_item_accessor_, try_item, catch_blocks);
}
}
}
bool HBasicBlockBuilder::Build() {
- DCHECK(code_item_ != nullptr);
+ DCHECK(code_item_accessor_.HasCodeItem());
DCHECK(graph_->GetBlocks().empty());
graph_->SetEntryBlock(new (allocator_) HBasicBlock(graph_, kNoDexPc));
@@ -388,7 +408,7 @@ bool HBasicBlockBuilder::Build() {
}
void HBasicBlockBuilder::BuildIntrinsic() {
- DCHECK(code_item_ == nullptr);
+ DCHECK(!code_item_accessor_.HasCodeItem());
DCHECK(graph_->GetBlocks().empty());
// Create blocks.
diff --git a/compiler/optimizing/block_builder.h b/compiler/optimizing/block_builder.h
index 7d0f56db34..2c1f034d80 100644
--- a/compiler/optimizing/block_builder.h
+++ b/compiler/optimizing/block_builder.h
@@ -19,7 +19,8 @@
#include "base/scoped_arena_allocator.h"
#include "base/scoped_arena_containers.h"
-#include "dex_file.h"
+#include "dex/code_item_accessors.h"
+#include "dex/dex_file.h"
#include "nodes.h"
namespace art {
@@ -28,22 +29,8 @@ class HBasicBlockBuilder : public ValueObject {
public:
HBasicBlockBuilder(HGraph* graph,
const DexFile* const dex_file,
- const DexFile::CodeItem* code_item,
- ScopedArenaAllocator* local_allocator)
- : allocator_(graph->GetAllocator()),
- graph_(graph),
- dex_file_(dex_file),
- code_item_(code_item),
- local_allocator_(local_allocator),
- branch_targets_(code_item != nullptr ? code_item->insns_size_in_code_units_
- : /* fake dex_pc=0 for intrinsic graph */ 1u,
- nullptr,
- local_allocator->Adapter(kArenaAllocGraphBuilder)),
- throwing_blocks_(kDefaultNumberOfThrowingBlocks,
- local_allocator->Adapter(kArenaAllocGraphBuilder)),
- number_of_branches_(0u),
- quicken_index_for_dex_pc_(std::less<uint32_t>(),
- local_allocator->Adapter(kArenaAllocGraphBuilder)) {}
+ const CodeItemDebugInfoAccessor& accessor,
+ ScopedArenaAllocator* local_allocator);
// Creates basic blocks in `graph_` at branch target dex_pc positions of the
// `code_item_`. Blocks are connected but left unpopulated with instructions.
@@ -83,7 +70,7 @@ class HBasicBlockBuilder : public ValueObject {
HGraph* const graph_;
const DexFile* const dex_file_;
- const DexFile::CodeItem* const code_item_; // null for intrinsic graph.
+ CodeItemDataAccessor code_item_accessor_; // null code item for intrinsic graph.
ScopedArenaAllocator* const local_allocator_;
ScopedArenaVector<HBasicBlock*> branch_targets_;
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index d73ef1f3a1..af537dd653 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -37,7 +37,7 @@
namespace art {
HGraphBuilder::HGraphBuilder(HGraph* graph,
- const DexFile::CodeItem* code_item,
+ const CodeItemDebugInfoAccessor& accessor,
const DexCompilationUnit* dex_compilation_unit,
const DexCompilationUnit* outer_compilation_unit,
CompilerDriver* driver,
@@ -47,7 +47,7 @@ HGraphBuilder::HGraphBuilder(HGraph* graph,
VariableSizedHandleScope* handles)
: graph_(graph),
dex_file_(&graph->GetDexFile()),
- code_item_(code_item),
+ code_item_accessor_(accessor),
dex_compilation_unit_(dex_compilation_unit),
outer_compilation_unit_(outer_compilation_unit),
compiler_driver_(driver),
@@ -57,6 +57,23 @@ HGraphBuilder::HGraphBuilder(HGraph* graph,
handles_(handles),
return_type_(DataType::FromShorty(dex_compilation_unit_->GetShorty()[0])) {}
+HGraphBuilder::HGraphBuilder(HGraph* graph,
+ const DexCompilationUnit* dex_compilation_unit,
+ const CodeItemDebugInfoAccessor& accessor,
+ VariableSizedHandleScope* handles,
+ DataType::Type return_type)
+ : graph_(graph),
+ dex_file_(&graph->GetDexFile()),
+ code_item_accessor_(accessor),
+ dex_compilation_unit_(dex_compilation_unit),
+ outer_compilation_unit_(nullptr),
+ compiler_driver_(nullptr),
+ code_generator_(nullptr),
+ compilation_stats_(nullptr),
+ interpreter_metadata_(nullptr),
+ handles_(handles),
+ return_type_(return_type) {}
+
bool HGraphBuilder::SkipCompilation(size_t number_of_branches) {
if (compiler_driver_ == nullptr) {
// Note that the compiler driver is null when unit testing.
@@ -69,20 +86,20 @@ bool HGraphBuilder::SkipCompilation(size_t number_of_branches) {
return false;
}
- if (compiler_options.IsHugeMethod(code_item_->insns_size_in_code_units_)) {
+ const uint32_t code_units = code_item_accessor_.InsnsSizeInCodeUnits();
+ if (compiler_options.IsHugeMethod(code_units)) {
VLOG(compiler) << "Skip compilation of huge method "
<< dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
- << ": " << code_item_->insns_size_in_code_units_ << " code units";
+ << ": " << code_units << " code units";
MaybeRecordStat(compilation_stats_, MethodCompilationStat::kNotCompiledHugeMethod);
return true;
}
// If it's large and contains no branches, it's likely to be machine generated initialization.
- if (compiler_options.IsLargeMethod(code_item_->insns_size_in_code_units_)
- && (number_of_branches == 0)) {
+ if (compiler_options.IsLargeMethod(code_units) && (number_of_branches == 0)) {
VLOG(compiler) << "Skip compilation of large method with no branch "
<< dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
- << ": " << code_item_->insns_size_in_code_units_ << " code units";
+ << ": " << code_units << " code units";
MaybeRecordStat(compilation_stats_, MethodCompilationStat::kNotCompiledLargeMethodNoBranches);
return true;
}
@@ -91,17 +108,17 @@ bool HGraphBuilder::SkipCompilation(size_t number_of_branches) {
}
GraphAnalysisResult HGraphBuilder::BuildGraph() {
- DCHECK(code_item_ != nullptr);
+ DCHECK(code_item_accessor_.HasCodeItem());
DCHECK(graph_->GetBlocks().empty());
- graph_->SetNumberOfVRegs(code_item_->registers_size_);
- graph_->SetNumberOfInVRegs(code_item_->ins_size_);
- graph_->SetMaximumNumberOfOutVRegs(code_item_->outs_size_);
- graph_->SetHasTryCatch(code_item_->tries_size_ != 0);
+ graph_->SetNumberOfVRegs(code_item_accessor_.RegistersSize());
+ graph_->SetNumberOfInVRegs(code_item_accessor_.InsSize());
+ graph_->SetMaximumNumberOfOutVRegs(code_item_accessor_.OutsSize());
+ graph_->SetHasTryCatch(code_item_accessor_.TriesSize() != 0);
// Use ScopedArenaAllocator for all local allocations.
ScopedArenaAllocator local_allocator(graph_->GetArenaStack());
- HBasicBlockBuilder block_builder(graph_, dex_file_, code_item_, &local_allocator);
+ HBasicBlockBuilder block_builder(graph_, dex_file_, code_item_accessor_, &local_allocator);
SsaBuilder ssa_builder(graph_,
dex_compilation_unit_->GetClassLoader(),
dex_compilation_unit_->GetDexCache(),
@@ -111,7 +128,7 @@ GraphAnalysisResult HGraphBuilder::BuildGraph() {
&block_builder,
&ssa_builder,
dex_file_,
- code_item_,
+ code_item_accessor_,
return_type_,
dex_compilation_unit_,
outer_compilation_unit_,
@@ -150,7 +167,7 @@ GraphAnalysisResult HGraphBuilder::BuildGraph() {
}
void HGraphBuilder::BuildIntrinsicGraph(ArtMethod* method) {
- DCHECK(code_item_ == nullptr);
+ DCHECK(!code_item_accessor_.HasCodeItem());
DCHECK(graph_->GetBlocks().empty());
// Determine the number of arguments and associated vregs.
@@ -170,7 +187,10 @@ void HGraphBuilder::BuildIntrinsicGraph(ArtMethod* method) {
// Use ScopedArenaAllocator for all local allocations.
ScopedArenaAllocator local_allocator(graph_->GetArenaStack());
- HBasicBlockBuilder block_builder(graph_, dex_file_, /* code_item */ nullptr, &local_allocator);
+ HBasicBlockBuilder block_builder(graph_,
+ dex_file_,
+ CodeItemDebugInfoAccessor(),
+ &local_allocator);
SsaBuilder ssa_builder(graph_,
dex_compilation_unit_->GetClassLoader(),
dex_compilation_unit_->GetDexCache(),
@@ -180,7 +200,7 @@ void HGraphBuilder::BuildIntrinsicGraph(ArtMethod* method) {
&block_builder,
&ssa_builder,
dex_file_,
- /* code_item */ nullptr,
+ CodeItemDebugInfoAccessor(),
return_type_,
dex_compilation_unit_,
outer_compilation_unit_,
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index 0bb3a051f7..c16a3a928d 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -18,8 +18,9 @@
#define ART_COMPILER_OPTIMIZING_BUILDER_H_
#include "base/arena_object.h"
-#include "dex_file-inl.h"
-#include "dex_file.h"
+#include "dex/code_item_accessors.h"
+#include "dex/dex_file-inl.h"
+#include "dex/dex_file.h"
#include "driver/compiler_driver.h"
#include "nodes.h"
@@ -33,7 +34,7 @@ class OptimizingCompilerStats;
class HGraphBuilder : public ValueObject {
public:
HGraphBuilder(HGraph* graph,
- const DexFile::CodeItem* code_item,
+ const CodeItemDebugInfoAccessor& accessor,
const DexCompilationUnit* dex_compilation_unit,
const DexCompilationUnit* outer_compilation_unit,
CompilerDriver* driver,
@@ -45,20 +46,9 @@ class HGraphBuilder : public ValueObject {
// Only for unit testing.
HGraphBuilder(HGraph* graph,
const DexCompilationUnit* dex_compilation_unit,
- const DexFile::CodeItem& code_item,
+ const CodeItemDebugInfoAccessor& accessor,
VariableSizedHandleScope* handles,
- DataType::Type return_type = DataType::Type::kInt32)
- : graph_(graph),
- dex_file_(&graph->GetDexFile()),
- code_item_(&code_item),
- dex_compilation_unit_(dex_compilation_unit),
- outer_compilation_unit_(nullptr),
- compiler_driver_(nullptr),
- code_generator_(nullptr),
- compilation_stats_(nullptr),
- interpreter_metadata_(nullptr),
- handles_(handles),
- return_type_(return_type) {}
+ DataType::Type return_type = DataType::Type::kInt32);
GraphAnalysisResult BuildGraph();
void BuildIntrinsicGraph(ArtMethod* method);
@@ -70,7 +60,7 @@ class HGraphBuilder : public ValueObject {
HGraph* const graph_;
const DexFile* const dex_file_;
- const DexFile::CodeItem* const code_item_; // null for intrinsic graph.
+ const CodeItemDebugInfoAccessor code_item_accessor_; // null for intrinsic graph.
// The compilation unit of the current method being compiled. Note that
// it can be an inlined method.
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index dee74e96dc..01155dcd37 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -46,6 +46,7 @@
#include "bytecode_utils.h"
#include "class_linker.h"
#include "compiled_method.h"
+#include "dex/code_item_accessors-inl.h"
#include "dex/verified_method.h"
#include "driver/compiler_driver.h"
#include "graph_visualizer.h"
@@ -910,7 +911,8 @@ static void CheckLoopEntriesCanBeUsedForOsr(const HGraph& graph,
}
ArenaVector<size_t> covered(
loop_headers.size(), 0, graph.GetAllocator()->Adapter(kArenaAllocMisc));
- for (const DexInstructionPcPair& pair : code_item.Instructions()) {
+ for (const DexInstructionPcPair& pair : CodeItemInstructionAccessor(graph.GetDexFile(),
+ &code_item)) {
const uint32_t dex_pc = pair.DexPc();
const Instruction& instruction = pair.Inst();
if (instruction.IsBranch()) {
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index f9dcb5d6ef..28f481670c 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -2097,15 +2097,18 @@ void InstructionCodeGeneratorARM64::GenerateClassInitializationCheck(SlowPathCod
Register class_reg) {
UseScratchRegisterScope temps(GetVIXLAssembler());
Register temp = temps.AcquireW();
- size_t status_offset = mirror::Class::StatusOffset().SizeValue();
+ constexpr size_t status_lsb_position = SubtypeCheckBits::BitStructSizeOf();
+ const size_t status_byte_offset =
+ mirror::Class::StatusOffset().SizeValue() + (status_lsb_position / kBitsPerByte);
+ constexpr uint32_t shifted_initialized_value =
+ enum_cast<uint32_t>(ClassStatus::kInitialized) << (status_lsb_position % kBitsPerByte);
// Even if the initialized flag is set, we need to ensure consistent memory ordering.
// TODO(vixl): Let the MacroAssembler handle MemOperand.
- __ Add(temp, class_reg, status_offset);
+ __ Add(temp, class_reg, status_byte_offset);
__ Ldarb(temp, HeapOperand(temp));
- __ Cmp(temp, mirror::Class::kStatusInitialized);
- __ B(ne, slow_path->GetEntryLabel());
- // Use Bne instead of Blt because ARM64 doesn't have Ldarsb.
+ __ Cmp(temp, shifted_initialized_value);
+ __ B(lo, slow_path->GetEntryLabel());
__ Bind(slow_path->GetExitLabel());
}
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index e53773c73d..f92c94fda7 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -20,7 +20,7 @@
#include "arch/arm64/quick_method_frame_info_arm64.h"
#include "code_generator.h"
#include "common_arm64.h"
-#include "dex_file_types.h"
+#include "dex/dex_file_types.h"
#include "driver/compiler_options.h"
#include "nodes.h"
#include "parallel_move_resolver.h"
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 017598d484..f1ad4e187e 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -1128,7 +1128,7 @@ class LoadReferenceWithBakerReadBarrierAndUpdateFieldSlowPathARMVIXL
//
// Note that this field could also hold a different object, if
// another thread had concurrently changed it. In that case, the
- // LDREX/SUBS/ITNE sequence of instructions in the compare-and-set
+ // LDREX/CMP/BNE sequence of instructions in the compare-and-set
// (CAS) operation below would abort the CAS, leaving the field
// as-is.
__ Cmp(temp1_, ref_reg);
@@ -1168,28 +1168,16 @@ class LoadReferenceWithBakerReadBarrierAndUpdateFieldSlowPathARMVIXL
// tmp = [r_ptr] - expected;
// } while (tmp == 0 && failure([r_ptr] <- r_new_value));
- vixl32::Label loop_head, exit_loop;
+ vixl32::Label loop_head, comparison_failed, exit_loop;
__ Bind(&loop_head);
-
__ Ldrex(tmp, MemOperand(tmp_ptr));
-
- __ Subs(tmp, tmp, expected);
-
- {
- ExactAssemblyScope aas(arm_codegen->GetVIXLAssembler(),
- 2 * kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
-
- __ it(ne);
- __ clrex(ne);
- }
-
- __ B(ne, &exit_loop, /* far_target */ false);
-
+ __ Cmp(tmp, expected);
+ __ B(ne, &comparison_failed, /* far_target */ false);
__ Strex(tmp, value, MemOperand(tmp_ptr));
- __ Cmp(tmp, 1);
- __ B(eq, &loop_head, /* far_target */ false);
-
+ __ CompareAndBranchIfZero(tmp, &exit_loop, /* far_target */ false);
+ __ B(&loop_head);
+ __ Bind(&comparison_failed);
+ __ Clrex();
__ Bind(&exit_loop);
if (kPoisonHeapReferences) {
@@ -5609,42 +5597,13 @@ Location LocationsBuilderARMVIXL::ArmEncodableConstantOrRegister(HInstruction* c
return Location::RequiresRegister();
}
-bool LocationsBuilderARMVIXL::CanEncodeConstantAsImmediate(HConstant* input_cst,
- Opcode opcode) {
- uint64_t value = static_cast<uint64_t>(Int64FromConstant(input_cst));
- if (DataType::Is64BitType(input_cst->GetType())) {
- Opcode high_opcode = opcode;
- SetCc low_set_cc = kCcDontCare;
- switch (opcode) {
- case SUB:
- // Flip the operation to an ADD.
- value = -value;
- opcode = ADD;
- FALLTHROUGH_INTENDED;
- case ADD:
- if (Low32Bits(value) == 0u) {
- return CanEncodeConstantAsImmediate(High32Bits(value), opcode, kCcDontCare);
- }
- high_opcode = ADC;
- low_set_cc = kCcSet;
- break;
- default:
- break;
- }
- return CanEncodeConstantAsImmediate(Low32Bits(value), opcode, low_set_cc) &&
- CanEncodeConstantAsImmediate(High32Bits(value), high_opcode, kCcDontCare);
- } else {
- return CanEncodeConstantAsImmediate(Low32Bits(value), opcode);
- }
-}
-
-// TODO(VIXL): Replace art::arm::SetCc` with `vixl32::FlagsUpdate after flags set optimization
-// enabled.
-bool LocationsBuilderARMVIXL::CanEncodeConstantAsImmediate(uint32_t value,
- Opcode opcode,
- SetCc set_cc) {
- ArmVIXLAssembler* assembler = codegen_->GetAssembler();
- if (assembler->ShifterOperandCanHold(opcode, value, set_cc)) {
+static bool CanEncode32BitConstantAsImmediate(
+ CodeGeneratorARMVIXL* codegen,
+ uint32_t value,
+ Opcode opcode,
+ vixl32::FlagsUpdate flags_update = vixl32::FlagsUpdate::DontCare) {
+ ArmVIXLAssembler* assembler = codegen->GetAssembler();
+ if (assembler->ShifterOperandCanHold(opcode, value, flags_update)) {
return true;
}
Opcode neg_opcode = kNoOperand;
@@ -5661,13 +5620,41 @@ bool LocationsBuilderARMVIXL::CanEncodeConstantAsImmediate(uint32_t value,
return false;
}
- if (assembler->ShifterOperandCanHold(neg_opcode, neg_value, set_cc)) {
+ if (assembler->ShifterOperandCanHold(neg_opcode, neg_value, flags_update)) {
return true;
}
return opcode == AND && IsPowerOfTwo(value + 1);
}
+bool LocationsBuilderARMVIXL::CanEncodeConstantAsImmediate(HConstant* input_cst, Opcode opcode) {
+ uint64_t value = static_cast<uint64_t>(Int64FromConstant(input_cst));
+ if (DataType::Is64BitType(input_cst->GetType())) {
+ Opcode high_opcode = opcode;
+ vixl32::FlagsUpdate low_flags_update = vixl32::FlagsUpdate::DontCare;
+ switch (opcode) {
+ case SUB:
+ // Flip the operation to an ADD.
+ value = -value;
+ opcode = ADD;
+ FALLTHROUGH_INTENDED;
+ case ADD:
+ if (Low32Bits(value) == 0u) {
+ return CanEncode32BitConstantAsImmediate(codegen_, High32Bits(value), opcode);
+ }
+ high_opcode = ADC;
+ low_flags_update = vixl32::FlagsUpdate::SetFlags;
+ break;
+ default:
+ break;
+ }
+ return CanEncode32BitConstantAsImmediate(codegen_, High32Bits(value), high_opcode) &&
+ CanEncode32BitConstantAsImmediate(codegen_, Low32Bits(value), opcode, low_flags_update);
+ } else {
+ return CanEncode32BitConstantAsImmediate(codegen_, Low32Bits(value), opcode);
+ }
+}
+
void InstructionCodeGeneratorARMVIXL::HandleFieldGet(HInstruction* instruction,
const FieldInfo& field_info) {
DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
@@ -7185,12 +7172,15 @@ void InstructionCodeGeneratorARMVIXL::GenerateClassInitializationCheck(
LoadClassSlowPathARMVIXL* slow_path, vixl32::Register class_reg) {
UseScratchRegisterScope temps(GetVIXLAssembler());
vixl32::Register temp = temps.Acquire();
- GetAssembler()->LoadFromOffset(kLoadSignedByte,
- temp,
- class_reg,
- mirror::Class::StatusOffset().Int32Value());
- __ Cmp(temp, mirror::Class::kStatusInitialized);
- __ B(lt, slow_path->GetEntryLabel());
+ constexpr size_t status_lsb_position = SubtypeCheckBits::BitStructSizeOf();
+ const size_t status_byte_offset =
+ mirror::Class::StatusOffset().SizeValue() + (status_lsb_position / kBitsPerByte);
+ constexpr uint32_t shifted_initialized_value =
+ enum_cast<uint32_t>(ClassStatus::kInitialized) << (status_lsb_position % kBitsPerByte);
+
+ GetAssembler()->LoadFromOffset(kLoadUnsignedByte, temp, class_reg, status_byte_offset);
+ __ Cmp(temp, shifted_initialized_value);
+ __ B(lo, slow_path->GetEntryLabel());
// Even if the initialized flag is set, we may be in a situation where caches are not synced
// properly. Therefore, we do a memory fence.
__ Dmb(ISH);
@@ -8143,13 +8133,11 @@ void InstructionCodeGeneratorARMVIXL::GenerateAddLongConst(Location out,
return;
}
__ Adds(out_low, first_low, value_low);
- if (GetAssembler()->ShifterOperandCanHold(ADC, value_high, kCcDontCare)) {
+ if (GetAssembler()->ShifterOperandCanHold(ADC, value_high)) {
__ Adc(out_high, first_high, value_high);
- } else if (GetAssembler()->ShifterOperandCanHold(SBC, ~value_high, kCcDontCare)) {
- __ Sbc(out_high, first_high, ~value_high);
} else {
- LOG(FATAL) << "Unexpected constant " << value_high;
- UNREACHABLE();
+ DCHECK(GetAssembler()->ShifterOperandCanHold(SBC, ~value_high));
+ __ Sbc(out_high, first_high, ~value_high);
}
}
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index c46d17ccec..38570bb0fe 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -287,7 +287,6 @@ class LocationsBuilderARMVIXL : public HGraphVisitor {
Location ArithmeticZeroOrFpuRegister(HInstruction* input);
Location ArmEncodableConstantOrRegister(HInstruction* constant, Opcode opcode);
bool CanEncodeConstantAsImmediate(HConstant* input_cst, Opcode opcode);
- bool CanEncodeConstantAsImmediate(uint32_t value, Opcode opcode, SetCc set_cc = kCcDontCare);
CodeGeneratorARMVIXL* const codegen_;
InvokeDexCallingConventionVisitorARMVIXL parameter_visitor_;
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 9f4c2349e7..c8bd5d4fc8 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1915,9 +1915,15 @@ void CodeGeneratorMIPS::GenerateInvokeRuntime(int32_t entry_point_offset, bool d
void InstructionCodeGeneratorMIPS::GenerateClassInitializationCheck(SlowPathCodeMIPS* slow_path,
Register class_reg) {
- __ LoadFromOffset(kLoadSignedByte, TMP, class_reg, mirror::Class::StatusOffset().Int32Value());
- __ LoadConst32(AT, mirror::Class::kStatusInitialized);
- __ Blt(TMP, AT, slow_path->GetEntryLabel());
+ constexpr size_t status_lsb_position = SubtypeCheckBits::BitStructSizeOf();
+ const size_t status_byte_offset =
+ mirror::Class::StatusOffset().SizeValue() + (status_lsb_position / kBitsPerByte);
+ constexpr uint32_t shifted_initialized_value =
+ enum_cast<uint32_t>(ClassStatus::kInitialized) << (status_lsb_position % kBitsPerByte);
+
+ __ LoadFromOffset(kLoadUnsignedByte, TMP, class_reg, status_byte_offset);
+ __ LoadConst32(AT, shifted_initialized_value);
+ __ Bltu(TMP, AT, slow_path->GetEntryLabel());
// Even if the initialized flag is set, we need to ensure consistent memory ordering.
__ Sync(0);
__ Bind(slow_path->GetExitLabel());
@@ -3774,8 +3780,12 @@ void InstructionCodeGeneratorMIPS::DivRemByPowerOfTwo(HBinaryOperation* instruct
if (IsUint<16>(abs_imm - 1)) {
__ Andi(out, out, abs_imm - 1);
} else {
- __ Sll(out, out, 32 - ctz_imm);
- __ Srl(out, out, 32 - ctz_imm);
+ if (codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2()) {
+ __ Ins(out, ZERO, ctz_imm, 32 - ctz_imm);
+ } else {
+ __ Sll(out, out, 32 - ctz_imm);
+ __ Srl(out, out, 32 - ctz_imm);
+ }
}
__ Subu(out, out, TMP);
}
diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h
index cf8e7a373a..32b3e4221f 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -18,7 +18,7 @@
#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS_H_
#include "code_generator.h"
-#include "dex_file_types.h"
+#include "dex/dex_file_types.h"
#include "driver/compiler_options.h"
#include "nodes.h"
#include "parallel_move_resolver.h"
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index eb64f1be23..bbdc3be5c1 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -1761,9 +1761,15 @@ void CodeGeneratorMIPS64::GenerateInvokeRuntime(int32_t entry_point_offset) {
void InstructionCodeGeneratorMIPS64::GenerateClassInitializationCheck(SlowPathCodeMIPS64* slow_path,
GpuRegister class_reg) {
- __ LoadFromOffset(kLoadSignedByte, TMP, class_reg, mirror::Class::StatusOffset().Int32Value());
- __ LoadConst32(AT, mirror::Class::kStatusInitialized);
- __ Bltc(TMP, AT, slow_path->GetEntryLabel());
+ constexpr size_t status_lsb_position = SubtypeCheckBits::BitStructSizeOf();
+ const size_t status_byte_offset =
+ mirror::Class::StatusOffset().SizeValue() + (status_lsb_position / kBitsPerByte);
+ constexpr uint32_t shifted_initialized_value =
+ enum_cast<uint32_t>(ClassStatus::kInitialized) << (status_lsb_position % kBitsPerByte);
+
+ __ LoadFromOffset(kLoadUnsignedByte, TMP, class_reg, status_byte_offset);
+ __ LoadConst32(AT, shifted_initialized_value);
+ __ Bltuc(TMP, AT, slow_path->GetEntryLabel());
// Even if the initialized flag is set, we need to ensure consistent memory ordering.
__ Sync(0);
__ Bind(slow_path->GetExitLabel());
@@ -3311,12 +3317,7 @@ void InstructionCodeGeneratorMIPS64::DivRemByPowerOfTwo(HBinaryOperation* instru
__ Sra(TMP, dividend, 31);
__ Srl(TMP, TMP, 32 - ctz_imm);
__ Addu(out, dividend, TMP);
- if (IsUint<16>(abs_imm - 1)) {
- __ Andi(out, out, abs_imm - 1);
- } else {
- __ Sll(out, out, 32 - ctz_imm);
- __ Srl(out, out, 32 - ctz_imm);
- }
+ __ Ins(out, ZERO, ctz_imm, 32 - ctz_imm);
__ Subu(out, out, TMP);
}
} else {
@@ -3335,17 +3336,7 @@ void InstructionCodeGeneratorMIPS64::DivRemByPowerOfTwo(HBinaryOperation* instru
__ Dsrl32(TMP, TMP, 32 - ctz_imm);
}
__ Daddu(out, dividend, TMP);
- if (IsUint<16>(abs_imm - 1)) {
- __ Andi(out, out, abs_imm - 1);
- } else {
- if (ctz_imm > 32) {
- __ Dsll(out, out, 64 - ctz_imm);
- __ Dsrl(out, out, 64 - ctz_imm);
- } else {
- __ Dsll32(out, out, 32 - ctz_imm);
- __ Dsrl32(out, out, 32 - ctz_imm);
- }
- }
+ __ DblIns(out, ZERO, ctz_imm, 64 - ctz_imm);
__ Dsubu(out, out, TMP);
}
}
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index ba222fe532..537e97aacf 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -6219,9 +6219,14 @@ void InstructionCodeGeneratorX86::VisitClinitCheck(HClinitCheck* check) {
void InstructionCodeGeneratorX86::GenerateClassInitializationCheck(
SlowPathCode* slow_path, Register class_reg) {
- __ cmpb(Address(class_reg, mirror::Class::StatusOffset().Int32Value()),
- Immediate(mirror::Class::kStatusInitialized));
- __ j(kLess, slow_path->GetEntryLabel());
+ constexpr size_t status_lsb_position = SubtypeCheckBits::BitStructSizeOf();
+ const size_t status_byte_offset =
+ mirror::Class::StatusOffset().SizeValue() + (status_lsb_position / kBitsPerByte);
+ constexpr uint32_t shifted_initialized_value =
+ enum_cast<uint32_t>(ClassStatus::kInitialized) << (status_lsb_position % kBitsPerByte);
+
+ __ cmpb(Address(class_reg, status_byte_offset), Immediate(shifted_initialized_value));
+ __ j(kBelow, slow_path->GetEntryLabel());
__ Bind(slow_path->GetExitLabel());
// No need for memory fence, thanks to the X86 memory model.
}
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 40b7e3c54f..0082853184 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -20,7 +20,7 @@
#include "arch/x86/instruction_set_features_x86.h"
#include "base/enums.h"
#include "code_generator.h"
-#include "dex_file_types.h"
+#include "dex/dex_file_types.h"
#include "driver/compiler_options.h"
#include "nodes.h"
#include "parallel_move_resolver.h"
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index caad7885bd..4a6428592e 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -5425,9 +5425,14 @@ void ParallelMoveResolverX86_64::RestoreScratch(int reg) {
void InstructionCodeGeneratorX86_64::GenerateClassInitializationCheck(
SlowPathCode* slow_path, CpuRegister class_reg) {
- __ cmpb(Address(class_reg, mirror::Class::StatusOffset().Int32Value()),
- Immediate(mirror::Class::kStatusInitialized));
- __ j(kLess, slow_path->GetEntryLabel());
+ constexpr size_t status_lsb_position = SubtypeCheckBits::BitStructSizeOf();
+ const size_t status_byte_offset =
+ mirror::Class::StatusOffset().SizeValue() + (status_lsb_position / kBitsPerByte);
+ constexpr uint32_t shifted_initialized_value =
+ enum_cast<uint32_t>(ClassStatus::kInitialized) << (status_lsb_position % kBitsPerByte);
+
+ __ cmpb(Address(class_reg, status_byte_offset), Immediate(shifted_initialized_value));
+ __ j(kBelow, slow_path->GetEntryLabel());
__ Bind(slow_path->GetExitLabel());
// No need for memory fence, thanks to the x86-64 memory model.
}
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index ba431a5b08..6eda289861 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -20,8 +20,8 @@
#include "base/macros.h"
#include "builder.h"
#include "codegen_test_utils.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
+#include "dex/dex_file.h"
+#include "dex/dex_instruction.h"
#include "driver/compiler_options.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
diff --git a/compiler/optimizing/dominator_test.cc b/compiler/optimizing/dominator_test.cc
index 6bf3a5943f..572466eec8 100644
--- a/compiler/optimizing/dominator_test.cc
+++ b/compiler/optimizing/dominator_test.cc
@@ -16,7 +16,7 @@
#include "base/arena_allocator.h"
#include "builder.h"
-#include "dex_instruction.h"
+#include "dex/dex_instruction.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
diff --git a/compiler/optimizing/find_loops_test.cc b/compiler/optimizing/find_loops_test.cc
index c91752855b..b799fb4688 100644
--- a/compiler/optimizing/find_loops_test.cc
+++ b/compiler/optimizing/find_loops_test.cc
@@ -16,8 +16,8 @@
#include "base/arena_allocator.h"
#include "builder.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
+#include "dex/dex_file.h"
+#include "dex/dex_instruction.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "pretty_printer.h"
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 8750910fe1..b2ad8ec400 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -1381,26 +1381,26 @@ bool HInliner::TryBuildAndInline(HInvoke* invoke_instruction,
bool same_dex_file = IsSameDexFile(*outer_compilation_unit_.GetDexFile(), *method->GetDexFile());
- const DexFile::CodeItem* code_item = method->GetCodeItem();
+ CodeItemDataAccessor accessor(method);
- if (code_item == nullptr) {
+ if (!accessor.HasCodeItem()) {
LOG_FAIL_NO_STAT()
<< "Method " << method->PrettyMethod() << " is not inlined because it is native";
return false;
}
size_t inline_max_code_units = compiler_driver_->GetCompilerOptions().GetInlineMaxCodeUnits();
- if (code_item->insns_size_in_code_units_ > inline_max_code_units) {
+ if (accessor.InsnsSizeInCodeUnits() > inline_max_code_units) {
LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedCodeItem)
<< "Method " << method->PrettyMethod()
<< " is not inlined because its code item is too big: "
- << code_item->insns_size_in_code_units_
+ << accessor.InsnsSizeInCodeUnits()
<< " > "
<< inline_max_code_units;
return false;
}
- if (code_item->tries_size_ != 0) {
+ if (accessor.TriesSize() != 0) {
LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedTryCatch)
<< "Method " << method->PrettyMethod() << " is not inlined because of try block";
return false;
@@ -1660,6 +1660,7 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction,
const DexFile::CodeItem* code_item = resolved_method->GetCodeItem();
const DexFile& callee_dex_file = *resolved_method->GetDexFile();
uint32_t method_index = resolved_method->GetDexMethodIndex();
+ CodeItemDebugInfoAccessor code_item_accessor(callee_dex_file, code_item);
ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
Handle<mirror::DexCache> dex_cache = NewHandleIfDifferent(resolved_method->GetDexCache(),
caller_compilation_unit_.GetDexCache(),
@@ -1714,7 +1715,7 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction,
}
}
HGraphBuilder builder(callee_graph,
- code_item,
+ code_item_accessor,
&dex_compilation_unit,
&outer_compilation_unit_,
compiler_driver_,
@@ -1967,6 +1968,7 @@ void HInliner::RunOptimizations(HGraph* callee_graph,
return;
}
+ CodeItemDataAccessor accessor(callee_graph->GetDexFile(), code_item);
HInliner inliner(callee_graph,
outermost_graph_,
codegen_,
@@ -1975,7 +1977,7 @@ void HInliner::RunOptimizations(HGraph* callee_graph,
compiler_driver_,
handles_,
inline_stats_,
- total_number_of_dex_registers_ + code_item->registers_size_,
+ total_number_of_dex_registers_ + accessor.RegistersSize(),
total_number_of_instructions_ + number_of_instructions,
this,
depth_ + 1);
diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h
index 042eee3204..e81d97b0a8 100644
--- a/compiler/optimizing/inliner.h
+++ b/compiler/optimizing/inliner.h
@@ -17,7 +17,7 @@
#ifndef ART_COMPILER_OPTIMIZING_INLINER_H_
#define ART_COMPILER_OPTIMIZING_INLINER_H_
-#include "dex_file_types.h"
+#include "dex/dex_file_types.h"
#include "invoke_type.h"
#include "jit/profile_compilation_info.h"
#include "optimization.h"
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index e36d91fb05..72a93c1f77 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -23,7 +23,7 @@
#include "bytecode_utils.h"
#include "class_linker.h"
#include "data_type-inl.h"
-#include "dex_instruction-inl.h"
+#include "dex/dex_instruction-inl.h"
#include "driver/compiler_driver-inl.h"
#include "driver/dex_compilation_unit.h"
#include "driver/compiler_options.h"
@@ -39,6 +39,44 @@
namespace art {
+HInstructionBuilder::HInstructionBuilder(HGraph* graph,
+ HBasicBlockBuilder* block_builder,
+ SsaBuilder* ssa_builder,
+ const DexFile* dex_file,
+ const CodeItemDebugInfoAccessor& accessor,
+ DataType::Type return_type,
+ const DexCompilationUnit* dex_compilation_unit,
+ const DexCompilationUnit* outer_compilation_unit,
+ CompilerDriver* compiler_driver,
+ CodeGenerator* code_generator,
+ const uint8_t* interpreter_metadata,
+ OptimizingCompilerStats* compiler_stats,
+ VariableSizedHandleScope* handles,
+ ScopedArenaAllocator* local_allocator)
+ : allocator_(graph->GetAllocator()),
+ graph_(graph),
+ handles_(handles),
+ dex_file_(dex_file),
+ code_item_accessor_(accessor),
+ return_type_(return_type),
+ block_builder_(block_builder),
+ ssa_builder_(ssa_builder),
+ compiler_driver_(compiler_driver),
+ code_generator_(code_generator),
+ dex_compilation_unit_(dex_compilation_unit),
+ outer_compilation_unit_(outer_compilation_unit),
+ quicken_info_(interpreter_metadata),
+ compilation_stats_(compiler_stats),
+ local_allocator_(local_allocator),
+ locals_for_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
+ current_block_(nullptr),
+ current_locals_(nullptr),
+ latest_result_(nullptr),
+ current_this_parameter_(nullptr),
+ loop_headers_(local_allocator->Adapter(kArenaAllocGraphBuilder)) {
+ loop_headers_.reserve(kDefaultNumberOfLoops);
+}
+
HBasicBlock* HInstructionBuilder::FindBlockStartingAt(uint32_t dex_pc) const {
return block_builder_->GetBlockAt(dex_pc);
}
@@ -273,7 +311,7 @@ static bool IsBlockPopulated(HBasicBlock* block) {
}
bool HInstructionBuilder::Build() {
- DCHECK(code_item_ != nullptr);
+ DCHECK(code_item_accessor_.HasCodeItem());
locals_for_.resize(
graph_->GetBlocks().size(),
ScopedArenaVector<HInstruction*>(local_allocator_->Adapter(kArenaAllocGraphBuilder)));
@@ -323,7 +361,7 @@ bool HInstructionBuilder::Build() {
quicken_index = block_builder_->GetQuickenIndex(block_dex_pc);
}
- for (const DexInstructionPcPair& pair : code_item_->Instructions(block_dex_pc)) {
+ for (const DexInstructionPcPair& pair : code_item_accessor_.InstructionsFrom(block_dex_pc)) {
if (current_block_ == nullptr) {
// The previous instruction ended this block.
break;
@@ -367,7 +405,7 @@ bool HInstructionBuilder::Build() {
}
void HInstructionBuilder::BuildIntrinsic(ArtMethod* method) {
- DCHECK(code_item_ == nullptr);
+ DCHECK(!code_item_accessor_.HasCodeItem());
DCHECK(method->IsIntrinsic());
locals_for_.resize(
@@ -442,15 +480,16 @@ ArenaBitVector* HInstructionBuilder::FindNativeDebugInfoLocations() {
return false;
}
};
- CodeItemDebugInfoAccessor accessor(dex_file_, code_item_);
ArenaBitVector* locations = ArenaBitVector::Create(local_allocator_,
- accessor.InsnsSizeInCodeUnits(),
+ code_item_accessor_.InsnsSizeInCodeUnits(),
/* expandable */ false,
kArenaAllocGraphBuilder);
locations->ClearAllBits();
- dex_file_->DecodeDebugPositionInfo(accessor.DebugInfoOffset(), Callback::Position, locations);
+ dex_file_->DecodeDebugPositionInfo(code_item_accessor_.DebugInfoOffset(),
+ Callback::Position,
+ locations);
// Instruction-specific tweaks.
- for (const DexInstructionPcPair& inst : accessor) {
+ for (const DexInstructionPcPair& inst : code_item_accessor_) {
switch (inst->Opcode()) {
case Instruction::MOVE_EXCEPTION: {
// Stop in native debugger after the exception has been moved.
@@ -459,7 +498,7 @@ ArenaBitVector* HInstructionBuilder::FindNativeDebugInfoLocations() {
locations->ClearBit(inst.DexPc());
DexInstructionIterator next = std::next(DexInstructionIterator(inst));
DCHECK(next.DexPc() != inst.DexPc());
- if (next != accessor.end()) {
+ if (next != code_item_accessor_.end()) {
locations->SetBit(next.DexPc());
}
break;
@@ -1706,7 +1745,8 @@ void HInstructionBuilder::BuildFillArrayData(const Instruction& instruction, uin
int32_t payload_offset = instruction.VRegB_31t() + dex_pc;
const Instruction::ArrayDataPayload* payload =
- reinterpret_cast<const Instruction::ArrayDataPayload*>(code_item_->insns_ + payload_offset);
+ reinterpret_cast<const Instruction::ArrayDataPayload*>(
+ code_item_accessor_.Insns() + payload_offset);
const uint8_t* data = payload->data;
uint32_t element_count = payload->element_count;
diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h
index 0500d40cd3..708a09711a 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -20,8 +20,9 @@
#include "base/scoped_arena_allocator.h"
#include "base/scoped_arena_containers.h"
#include "data_type.h"
-#include "dex_file.h"
-#include "dex_file_types.h"
+#include "dex/code_item_accessors.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_types.h"
#include "handle.h"
#include "nodes.h"
#include "quicken_info.h"
@@ -50,7 +51,7 @@ class HInstructionBuilder : public ValueObject {
HBasicBlockBuilder* block_builder,
SsaBuilder* ssa_builder,
const DexFile* dex_file,
- const DexFile::CodeItem* code_item,
+ const CodeItemDebugInfoAccessor& accessor,
DataType::Type return_type,
const DexCompilationUnit* dex_compilation_unit,
const DexCompilationUnit* outer_compilation_unit,
@@ -59,30 +60,7 @@ class HInstructionBuilder : public ValueObject {
const uint8_t* interpreter_metadata,
OptimizingCompilerStats* compiler_stats,
VariableSizedHandleScope* handles,
- ScopedArenaAllocator* local_allocator)
- : allocator_(graph->GetAllocator()),
- graph_(graph),
- handles_(handles),
- dex_file_(dex_file),
- code_item_(code_item),
- return_type_(return_type),
- block_builder_(block_builder),
- ssa_builder_(ssa_builder),
- compiler_driver_(compiler_driver),
- code_generator_(code_generator),
- dex_compilation_unit_(dex_compilation_unit),
- outer_compilation_unit_(outer_compilation_unit),
- quicken_info_(interpreter_metadata),
- compilation_stats_(compiler_stats),
- local_allocator_(local_allocator),
- locals_for_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
- current_block_(nullptr),
- current_locals_(nullptr),
- latest_result_(nullptr),
- current_this_parameter_(nullptr),
- loop_headers_(local_allocator->Adapter(kArenaAllocGraphBuilder)) {
- loop_headers_.reserve(kDefaultNumberOfLoops);
- }
+ ScopedArenaAllocator* local_allocator);
bool Build();
void BuildIntrinsic(ArtMethod* method);
@@ -329,7 +307,7 @@ class HInstructionBuilder : public ValueObject {
// The dex file where the method being compiled is, and the bytecode data.
const DexFile* const dex_file_;
- const DexFile::CodeItem* const code_item_; // null for intrinsic graph.
+ const CodeItemDebugInfoAccessor code_item_accessor_; // null for intrinsic graph.
// The return type of the method being compiled.
const DataType::Type return_type_;
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 1d8ea092a4..99b8b5df74 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -1458,30 +1458,38 @@ void IntrinsicLocationsBuilderARMVIXL::VisitStringCompareTo(HInvoke* invoke) {
locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
}
+// Forward declaration.
+//
+// ART build system imposes a size limit (deviceFrameSizeLimit) on the stack frames generated
+// by the compiler for every C++ function, and if this function gets inlined in
+// IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo, the limit will be exceeded, resulting in a
+// build failure. That is the reason why NO_INLINE attribute is used.
+static void NO_INLINE GenerateStringCompareToLoop(ArmVIXLAssembler* assembler,
+ HInvoke* invoke,
+ vixl32::Label* end,
+ vixl32::Label* different_compression);
+
void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) {
ArmVIXLAssembler* assembler = GetAssembler();
LocationSummary* locations = invoke->GetLocations();
- vixl32::Register str = InputRegisterAt(invoke, 0);
- vixl32::Register arg = InputRegisterAt(invoke, 1);
- vixl32::Register out = OutputRegister(invoke);
+ const vixl32::Register str = InputRegisterAt(invoke, 0);
+ const vixl32::Register arg = InputRegisterAt(invoke, 1);
+ const vixl32::Register out = OutputRegister(invoke);
- vixl32::Register temp0 = RegisterFrom(locations->GetTemp(0));
- vixl32::Register temp1 = RegisterFrom(locations->GetTemp(1));
- vixl32::Register temp2 = RegisterFrom(locations->GetTemp(2));
+ const vixl32::Register temp0 = RegisterFrom(locations->GetTemp(0));
+ const vixl32::Register temp1 = RegisterFrom(locations->GetTemp(1));
+ const vixl32::Register temp2 = RegisterFrom(locations->GetTemp(2));
vixl32::Register temp3;
if (mirror::kUseStringCompression) {
temp3 = RegisterFrom(locations->GetTemp(3));
}
- vixl32::Label loop;
- vixl32::Label find_char_diff;
vixl32::Label end;
vixl32::Label different_compression;
// Get offsets of count and value fields within a string object.
const int32_t count_offset = mirror::String::CountOffset().Int32Value();
- const int32_t value_offset = mirror::String::ValueOffset().Int32Value();
// Note that the null check must have been done earlier.
DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0)));
@@ -1546,6 +1554,38 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) {
__ add(ne, temp0, temp0, temp0);
}
+
+ GenerateStringCompareToLoop(assembler, invoke, &end, &different_compression);
+
+ __ Bind(&end);
+
+ if (can_slow_path) {
+ __ Bind(slow_path->GetExitLabel());
+ }
+}
+
+static void GenerateStringCompareToLoop(ArmVIXLAssembler* assembler,
+ HInvoke* invoke,
+ vixl32::Label* end,
+ vixl32::Label* different_compression) {
+ LocationSummary* locations = invoke->GetLocations();
+
+ const vixl32::Register str = InputRegisterAt(invoke, 0);
+ const vixl32::Register arg = InputRegisterAt(invoke, 1);
+ const vixl32::Register out = OutputRegister(invoke);
+
+ const vixl32::Register temp0 = RegisterFrom(locations->GetTemp(0));
+ const vixl32::Register temp1 = RegisterFrom(locations->GetTemp(1));
+ const vixl32::Register temp2 = RegisterFrom(locations->GetTemp(2));
+ vixl32::Register temp3;
+ if (mirror::kUseStringCompression) {
+ temp3 = RegisterFrom(locations->GetTemp(3));
+ }
+
+ vixl32::Label loop;
+ vixl32::Label find_char_diff;
+
+ const int32_t value_offset = mirror::String::ValueOffset().Int32Value();
// Store offset of string value in preparation for comparison loop.
__ Mov(temp1, value_offset);
@@ -1577,12 +1617,12 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) {
// With string compression, we have compared 8 bytes, otherwise 4 chars.
__ Subs(temp0, temp0, (mirror::kUseStringCompression ? 8 : 4));
__ B(hi, &loop, /* far_target */ false);
- __ B(&end);
+ __ B(end);
__ Bind(&find_char_diff_2nd_cmp);
if (mirror::kUseStringCompression) {
__ Subs(temp0, temp0, 4); // 4 bytes previously compared.
- __ B(ls, &end, /* far_target */ false); // Was the second comparison fully beyond the end?
+ __ B(ls, end, /* far_target */ false); // Was the second comparison fully beyond the end?
} else {
// Without string compression, we can start treating temp0 as signed
// and rely on the signed comparison below.
@@ -1610,7 +1650,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) {
// the remaining string data, so just return length diff (out).
// The comparison is unsigned for string compression, otherwise signed.
__ Cmp(temp0, Operand(temp1, vixl32::LSR, (mirror::kUseStringCompression ? 3 : 4)));
- __ B((mirror::kUseStringCompression ? ls : le), &end, /* far_target */ false);
+ __ B((mirror::kUseStringCompression ? ls : le), end, /* far_target */ false);
// Extract the characters and calculate the difference.
if (mirror::kUseStringCompression) {
@@ -1637,8 +1677,8 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) {
temps.Release(temp_reg);
if (mirror::kUseStringCompression) {
- __ B(&end);
- __ Bind(&different_compression);
+ __ B(end);
+ __ Bind(different_compression);
// Comparison for different compression style.
const size_t c_char_size = DataType::Size(DataType::Type::kInt8);
@@ -1680,7 +1720,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) {
__ B(ne, &different_compression_diff, /* far_target */ false);
__ Subs(temp0, temp0, 2);
__ B(hi, &different_compression_loop, /* far_target */ false);
- __ B(&end);
+ __ B(end);
// Calculate the difference.
__ Bind(&different_compression_diff);
@@ -1698,12 +1738,6 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) {
__ it(cc);
__ rsb(cc, out, out, 0);
}
-
- __ Bind(&end);
-
- if (can_slow_path) {
- __ Bind(slow_path->GetExitLabel());
- }
}
// The cut off for unrolling the loop in String.equals() intrinsic for const strings.
diff --git a/compiler/optimizing/linearize_test.cc b/compiler/optimizing/linearize_test.cc
index b2a9c0a8e7..43b63a73ef 100644
--- a/compiler/optimizing/linearize_test.cc
+++ b/compiler/optimizing/linearize_test.cc
@@ -21,8 +21,8 @@
#include "builder.h"
#include "code_generator.h"
#include "code_generator_x86.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
+#include "dex/dex_file.h"
+#include "dex/dex_instruction.h"
#include "driver/compiler_options.h"
#include "graph_visualizer.h"
#include "nodes.h"
diff --git a/compiler/optimizing/live_ranges_test.cc b/compiler/optimizing/live_ranges_test.cc
index ddcad5aed8..e45d7c820c 100644
--- a/compiler/optimizing/live_ranges_test.cc
+++ b/compiler/optimizing/live_ranges_test.cc
@@ -19,8 +19,8 @@
#include "builder.h"
#include "code_generator.h"
#include "code_generator_x86.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
+#include "dex/dex_file.h"
+#include "dex/dex_instruction.h"
#include "driver/compiler_options.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
diff --git a/compiler/optimizing/liveness_test.cc b/compiler/optimizing/liveness_test.cc
index 3eadc8f8fc..35bc4ff8b3 100644
--- a/compiler/optimizing/liveness_test.cc
+++ b/compiler/optimizing/liveness_test.cc
@@ -19,8 +19,8 @@
#include "builder.h"
#include "code_generator.h"
#include "code_generator_x86.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
+#include "dex/dex_file.h"
+#include "dex/dex_instruction.h"
#include "driver/compiler_options.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index d13f5b42bf..d4382c6b4c 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -30,8 +30,8 @@
#include "base/transform_array_ref.h"
#include "data_type.h"
#include "deoptimization_kind.h"
-#include "dex_file.h"
-#include "dex_file_types.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_types.h"
#include "entrypoints/quick/quick_entrypoints_enum.h"
#include "handle.h"
#include "handle_scope.h"
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index 7149d93d07..57db7a634c 100644
--- a/compiler/optimizing/optimization.cc
+++ b/compiler/optimizing/optimization.cc
@@ -39,6 +39,7 @@
#include "constant_folding.h"
#include "constructor_fence_redundancy_elimination.h"
#include "dead_code_elimination.h"
+#include "dex/code_item_accessors-inl.h"
#include "driver/dex_compilation_unit.h"
#include "gvn.h"
#include "induction_var_analysis.h"
@@ -241,7 +242,8 @@ ArenaVector<HOptimization*> ConstructOptimizations(
opt = new (allocator) HDeadCodeElimination(graph, stats, name);
break;
case OptimizationPass::kInliner: {
- size_t number_of_dex_registers = dex_compilation_unit.GetCodeItem()->registers_size_;
+ CodeItemDataAccessor accessor(*dex_compilation_unit.GetDexFile(),
+ dex_compilation_unit.GetCodeItem());
opt = new (allocator) HInliner(graph, // outer_graph
graph, // outermost_graph
codegen,
@@ -250,7 +252,7 @@ ArenaVector<HOptimization*> ConstructOptimizations(
driver,
handles,
stats,
- number_of_dex_registers,
+ accessor.RegistersSize(),
/* total_number_of_instructions */ 0,
/* parent */ nullptr,
/* depth */ 0,
diff --git a/compiler/optimizing/optimizing_cfi_test.cc b/compiler/optimizing/optimizing_cfi_test.cc
index 4ad29961be..e2b2106f65 100644
--- a/compiler/optimizing/optimizing_cfi_test.cc
+++ b/compiler/optimizing/optimizing_cfi_test.cc
@@ -18,6 +18,7 @@
#include <vector>
#include "arch/instruction_set.h"
+#include "base/runtime_debug.h"
#include "cfi_test.h"
#include "driver/compiler_options.h"
#include "gtest/gtest.h"
@@ -56,6 +57,9 @@ class OptimizingCFITest : public CFITest {
ArenaAllocator* GetAllocator() { return pool_and_allocator_.GetAllocator(); }
void SetUpFrame(InstructionSet isa) {
+ // Ensure that slow-debug is off, so that there is no unexpected read-barrier check emitted.
+ SetRuntimeDebugFlagsEnabled(false);
+
// Setup simple context.
std::string error;
isa_features_ = InstructionSetFeatures::FromVariant(isa, "default", &error);
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 24b1a123ee..f4115f7e7b 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -36,9 +36,9 @@
#include "compiler.h"
#include "debug/elf_debug_writer.h"
#include "debug/method_debug_info.h"
+#include "dex/dex_file_types.h"
#include "dex/verification_results.h"
#include "dex/verified_method.h"
-#include "dex_file_types.h"
#include "driver/compiler_driver-inl.h"
#include "driver/compiler_options.h"
#include "driver/dex_compilation_unit.h"
@@ -766,11 +766,13 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* allocator,
static constexpr size_t kSpaceFilterOptimizingThreshold = 128;
const CompilerOptions& compiler_options = compiler_driver->GetCompilerOptions();
if ((compiler_options.GetCompilerFilter() == CompilerFilter::kSpace)
- && (code_item->insns_size_in_code_units_ > kSpaceFilterOptimizingThreshold)) {
+ && (CodeItemInstructionAccessor(dex_file, code_item).InsnsSizeInCodeUnits() >
+ kSpaceFilterOptimizingThreshold)) {
MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kNotCompiledSpaceFilter);
return nullptr;
}
+ CodeItemDebugInfoAccessor code_item_accessor(dex_file, code_item);
HGraph* graph = new (allocator) HGraph(
allocator,
arena_stack,
@@ -814,7 +816,7 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* allocator,
VLOG(compiler) << "Building " << pass_observer.GetMethodName();
PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
HGraphBuilder builder(graph,
- code_item,
+ code_item_accessor,
&dex_compilation_unit,
&dex_compilation_unit,
compiler_driver,
@@ -932,7 +934,7 @@ CodeGenerator* OptimizingCompiler::TryCompileIntrinsic(
VLOG(compiler) << "Building intrinsic graph " << pass_observer.GetMethodName();
PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
HGraphBuilder builder(graph,
- /* code_item */ nullptr,
+ CodeItemDebugInfoAccessor(), // Null code item.
&dex_compilation_unit,
&dex_compilation_unit,
compiler_driver,
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index 158c252f45..8c97d57f4a 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -20,8 +20,9 @@
#include "base/scoped_arena_allocator.h"
#include "builder.h"
#include "common_compiler_test.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
+#include "dex/code_item_accessors-inl.h"
+#include "dex/dex_file.h"
+#include "dex/dex_instruction.h"
#include "driver/dex_compilation_unit.h"
#include "handle_scope-inl.h"
#include "mirror/class_loader.h"
@@ -145,7 +146,8 @@ class OptimizingUnitTest : public CommonCompilerTest {
/* access_flags */ 0u,
/* verified_method */ nullptr,
handles_->NewHandle<mirror::DexCache>(nullptr));
- HGraphBuilder builder(graph, dex_compilation_unit, *code_item, handles_.get(), return_type);
+ CodeItemDebugInfoAccessor accessor(graph->GetDexFile(), code_item);
+ HGraphBuilder builder(graph, dex_compilation_unit, accessor, handles_.get(), return_type);
bool graph_built = (builder.BuildGraph() == kAnalysisSuccess);
return graph_built ? graph : nullptr;
}
diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc
index 1ed190d328..f843c008d8 100644
--- a/compiler/optimizing/prepare_for_register_allocation.cc
+++ b/compiler/optimizing/prepare_for_register_allocation.cc
@@ -16,7 +16,7 @@
#include "prepare_for_register_allocation.h"
-#include "dex_file_types.h"
+#include "dex/dex_file_types.h"
#include "jni_internal.h"
#include "optimizing_compiler_stats.h"
#include "well_known_classes.h"
diff --git a/compiler/optimizing/pretty_printer_test.cc b/compiler/optimizing/pretty_printer_test.cc
index 4aec6d3999..4fc7fe9427 100644
--- a/compiler/optimizing/pretty_printer_test.cc
+++ b/compiler/optimizing/pretty_printer_test.cc
@@ -18,8 +18,8 @@
#include "base/arena_allocator.h"
#include "builder.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
+#include "dex/dex_file.h"
+#include "dex/dex_instruction.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index 69ed8c7fcc..3748d599a3 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -21,9 +21,9 @@
#include "builder.h"
#include "code_generator.h"
#include "code_generator_x86.h"
-#include "dex_file.h"
-#include "dex_file_types.h"
-#include "dex_instruction.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_types.h"
+#include "dex/dex_instruction.h"
#include "driver/compiler_options.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
diff --git a/compiler/optimizing/scheduler_arm.cc b/compiler/optimizing/scheduler_arm.cc
index b3c8f105d1..8dcadaad2e 100644
--- a/compiler/optimizing/scheduler_arm.cc
+++ b/compiler/optimizing/scheduler_arm.cc
@@ -330,10 +330,12 @@ bool SchedulingLatencyVisitorARM::CanGenerateTest(HCondition* condition) {
}
} else if (c == kCondLE || c == kCondGT) {
if (value < std::numeric_limits<int64_t>::max() &&
- !codegen_->GetAssembler()->ShifterOperandCanHold(SBC, High32Bits(value + 1), kCcSet)) {
+ !codegen_->GetAssembler()->ShifterOperandCanHold(
+ SBC, High32Bits(value + 1), vixl32::FlagsUpdate::SetFlags)) {
return false;
}
- } else if (!codegen_->GetAssembler()->ShifterOperandCanHold(SBC, High32Bits(value), kCcSet)) {
+ } else if (!codegen_->GetAssembler()->ShifterOperandCanHold(
+ SBC, High32Bits(value), vixl32::FlagsUpdate::SetFlags)) {
return false;
}
}
diff --git a/compiler/optimizing/ssa_test.cc b/compiler/optimizing/ssa_test.cc
index e08904e84b..77e70d733e 100644
--- a/compiler/optimizing/ssa_test.cc
+++ b/compiler/optimizing/ssa_test.cc
@@ -18,8 +18,8 @@
#include "base/arena_allocator.h"
#include "builder.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
+#include "dex/dex_file.h"
+#include "dex/dex_instruction.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "pretty_printer.h"
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index 4f43eb374c..7010e3f380 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -18,7 +18,7 @@
#include "art_method-inl.h"
#include "base/stl_util.h"
-#include "dex_file_types.h"
+#include "dex/dex_file_types.h"
#include "optimizing/optimizing_compiler.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
diff --git a/compiler/optimizing/cloner_test.cc b/compiler/optimizing/superblock_cloner_test.cc
index d34dd81767..fd77eb81fc 100644
--- a/compiler/optimizing/cloner_test.cc
+++ b/compiler/optimizing/superblock_cloner_test.cc
@@ -24,9 +24,9 @@ namespace art {
// This class provides methods and helpers for testing various cloning and copying routines:
// individual instruction cloning and cloning of the more coarse-grain structures.
-class ClonerTest : public OptimizingUnitTest {
+class SuperblockClonerTest : public OptimizingUnitTest {
public:
- ClonerTest()
+ SuperblockClonerTest()
: graph_(CreateGraph()), entry_block_(nullptr), exit_block_(nullptr), parameter_(nullptr) {}
void CreateBasicLoopControlFlow(/* out */ HBasicBlock** header_p,
@@ -154,7 +154,7 @@ class ClonerTest : public OptimizingUnitTest {
HInstruction* parameter_;
};
-TEST_F(ClonerTest, IndividualInstrCloner) {
+TEST_F(SuperblockClonerTest, IndividualInstrCloner) {
HBasicBlock* header = nullptr;
HBasicBlock* loop_body = nullptr;
diff --git a/compiler/optimizing/suspend_check_test.cc b/compiler/optimizing/suspend_check_test.cc
index 88336b0009..7e83f8ce5f 100644
--- a/compiler/optimizing/suspend_check_test.cc
+++ b/compiler/optimizing/suspend_check_test.cc
@@ -15,7 +15,7 @@
*/
#include "builder.h"
-#include "dex_instruction.h"
+#include "dex/dex_instruction.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "pretty_printer.h"
diff --git a/compiler/trampolines/trampoline_compiler.h b/compiler/trampolines/trampoline_compiler.h
index 1a10e4c799..64c1eb5022 100644
--- a/compiler/trampolines/trampoline_compiler.h
+++ b/compiler/trampolines/trampoline_compiler.h
@@ -21,6 +21,7 @@
#include <vector>
#include "driver/compiler_driver.h"
+#include "offsets.h"
namespace art {
diff --git a/compiler/utils/arm/assembler_arm_shared.h b/compiler/utils/arm/assembler_arm_shared.h
index 21f13eeab7..7464052d93 100644
--- a/compiler/utils/arm/assembler_arm_shared.h
+++ b/compiler/utils/arm/assembler_arm_shared.h
@@ -40,13 +40,6 @@ enum StoreOperandType {
kStoreDWord
};
-// Set condition codes request.
-enum SetCc {
- kCcDontCare, // Allows prioritizing 16-bit instructions on Thumb2 whether they set CCs or not.
- kCcSet,
- kCcKeep,
-};
-
} // namespace arm
} // namespace art
diff --git a/compiler/utils/arm/assembler_arm_test.h b/compiler/utils/arm/assembler_arm_test.h
deleted file mode 100644
index 8c3a11f2cf..0000000000
--- a/compiler/utils/arm/assembler_arm_test.h
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_
-#define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_
-
-#include "utils/assembler_test.h"
-
-namespace art {
-
-template<typename Ass,
- typename Reg,
- typename FPReg,
- typename Imm,
- typename SOp,
- typename Cond,
- typename SetCc>
-class AssemblerArmTest : public AssemblerTest<Ass, Reg, FPReg, Imm> {
- public:
- typedef AssemblerTest<Ass, Reg, FPReg, Imm> Base;
-
- using Base::GetRegisters;
- using Base::GetRegName;
- using Base::CreateImmediate;
- using Base::WarnOnCombinations;
-
- static constexpr int64_t kFullImmRangeThreshold = 32;
-
- virtual void FillImmediates(std::vector<Imm>& immediates, int64_t imm_min, int64_t imm_max) {
- // Small range: do completely.
- if (imm_max - imm_min <= kFullImmRangeThreshold) {
- for (int64_t i = imm_min; i <= imm_max; ++i) {
- immediates.push_back(CreateImmediate(i));
- }
- } else {
- immediates.push_back(CreateImmediate(imm_min));
- immediates.push_back(CreateImmediate(imm_max));
- if (imm_min < imm_max - 1) {
- immediates.push_back(CreateImmediate(imm_min + 1));
- }
- if (imm_min < imm_max - 2) {
- immediates.push_back(CreateImmediate(imm_min + 2));
- }
- if (imm_min < imm_max - 3) {
- immediates.push_back(CreateImmediate(imm_max - 1));
- }
- if (imm_min < imm_max - 4) {
- immediates.push_back(CreateImmediate((imm_min + imm_max) / 2));
- }
- }
- }
-
- std::string RepeatRRIIC(void (Ass::*f)(Reg, Reg, Imm, Imm, Cond),
- int64_t imm1_min, int64_t imm1_max,
- int64_t imm2_min, int64_t imm2_max,
- std::string fmt) {
- return RepeatTemplatedRRIIC(f, GetRegisters(), GetRegisters(),
- &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
- &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
- imm1_min, imm1_max, imm2_min, imm2_max,
- fmt);
- }
-
- template <typename Reg1, typename Reg2>
- std::string RepeatTemplatedRRIIC(void (Ass::*f)(Reg1, Reg2, Imm, Imm, Cond),
- const std::vector<Reg1*> reg1_registers,
- const std::vector<Reg2*> reg2_registers,
- std::string (AssemblerArmTest::*GetName1)(const Reg1&),
- std::string (AssemblerArmTest::*GetName2)(const Reg2&),
- int64_t imm1_min, int64_t imm1_max,
- int64_t imm2_min, int64_t imm2_max,
- std::string fmt) {
- std::vector<Imm> immediates1;
- FillImmediates(immediates1, imm1_min, imm1_max);
- std::vector<Imm> immediates2;
- FillImmediates(immediates2, imm2_min, imm2_max);
-
- std::vector<Cond>& cond = GetConditions();
-
- WarnOnCombinations(cond.size() * immediates1.size() * immediates2.size() *
- reg1_registers.size() * reg2_registers.size());
-
- std::ostringstream oss;
- bool first = true;
- for (Cond& c : cond) {
- std::string after_cond = fmt;
-
- size_t cond_index = after_cond.find(COND_TOKEN);
- if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
- }
-
- for (Imm i : immediates1) {
- std::string base = after_cond;
-
- size_t imm1_index = base.find(IMM1_TOKEN);
- if (imm1_index != std::string::npos) {
- std::ostringstream sreg;
- sreg << i;
- std::string imm_string = sreg.str();
- base.replace(imm1_index, ConstexprStrLen(IMM1_TOKEN), imm_string);
- }
-
- for (Imm j : immediates2) {
- std::string base2 = base;
-
- size_t imm2_index = base2.find(IMM2_TOKEN);
- if (imm2_index != std::string::npos) {
- std::ostringstream sreg;
- sreg << j;
- std::string imm_string = sreg.str();
- base2.replace(imm2_index, ConstexprStrLen(IMM2_TOKEN), imm_string);
- }
-
- for (auto reg1 : reg1_registers) {
- std::string base3 = base2;
-
- std::string reg1_string = (this->*GetName1)(*reg1);
- size_t reg1_index;
- while ((reg1_index = base3.find(Base::REG1_TOKEN)) != std::string::npos) {
- base3.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
- }
-
- for (auto reg2 : reg2_registers) {
- std::string base4 = base3;
-
- std::string reg2_string = (this->*GetName2)(*reg2);
- size_t reg2_index;
- while ((reg2_index = base4.find(Base::REG2_TOKEN)) != std::string::npos) {
- base4.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
- }
-
- if (first) {
- first = false;
- } else {
- oss << "\n";
- }
- oss << base4;
-
- (Base::GetAssembler()->*f)(*reg1, *reg2, i, j, c);
- }
- }
- }
- }
- }
- // Add a newline at the end.
- oss << "\n";
-
- return oss.str();
- }
-
- std::string RepeatRRiiC(void (Ass::*f)(Reg, Reg, Imm, Imm, Cond),
- std::vector<std::pair<Imm, Imm>>& immediates,
- std::string fmt) {
- return RepeatTemplatedRRiiC<Reg, Reg>(f, GetRegisters(), GetRegisters(),
- &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
- &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
- immediates, fmt);
- }
-
- template <typename Reg1, typename Reg2>
- std::string RepeatTemplatedRRiiC(void (Ass::*f)(Reg1, Reg2, Imm, Imm, Cond),
- const std::vector<Reg1*> reg1_registers,
- const std::vector<Reg2*> reg2_registers,
- std::string (AssemblerArmTest::*GetName1)(const Reg1&),
- std::string (AssemblerArmTest::*GetName2)(const Reg2&),
- std::vector<std::pair<Imm, Imm>>& immediates,
- std::string fmt) {
- std::vector<Cond>& cond = GetConditions();
-
- WarnOnCombinations(cond.size() * immediates.size() * reg1_registers.size() *
- reg2_registers.size());
-
- std::ostringstream oss;
- bool first = true;
- for (Cond& c : cond) {
- std::string after_cond = fmt;
-
- size_t cond_index = after_cond.find(COND_TOKEN);
- if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
- }
-
- for (std::pair<Imm, Imm>& pair : immediates) {
- Imm i = pair.first;
- Imm j = pair.second;
- std::string after_imm1 = after_cond;
-
- size_t imm1_index = after_imm1.find(IMM1_TOKEN);
- if (imm1_index != std::string::npos) {
- std::ostringstream sreg;
- sreg << i;
- std::string imm_string = sreg.str();
- after_imm1.replace(imm1_index, ConstexprStrLen(IMM1_TOKEN), imm_string);
- }
-
- std::string after_imm2 = after_imm1;
-
- size_t imm2_index = after_imm2.find(IMM2_TOKEN);
- if (imm2_index != std::string::npos) {
- std::ostringstream sreg;
- sreg << j;
- std::string imm_string = sreg.str();
- after_imm2.replace(imm2_index, ConstexprStrLen(IMM2_TOKEN), imm_string);
- }
-
- for (auto reg1 : reg1_registers) {
- std::string after_reg1 = after_imm2;
-
- std::string reg1_string = (this->*GetName1)(*reg1);
- size_t reg1_index;
- while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
- after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
- }
-
- for (auto reg2 : reg2_registers) {
- std::string after_reg2 = after_reg1;
-
- std::string reg2_string = (this->*GetName2)(*reg2);
- size_t reg2_index;
- while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
- after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
- }
-
- if (first) {
- first = false;
- } else {
- oss << "\n";
- }
- oss << after_reg2;
-
- (Base::GetAssembler()->*f)(*reg1, *reg2, i, j, c);
- }
- }
- }
- }
- // Add a newline at the end.
- oss << "\n";
-
- return oss.str();
- }
-
- std::string RepeatRRC(void (Ass::*f)(Reg, Reg, Cond), std::string fmt) {
- return RepeatTemplatedRRC(f, GetRegisters(), GetRegisters(), GetConditions(),
- &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
- &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
- fmt);
- }
-
- template <typename Reg1, typename Reg2>
- std::string RepeatTemplatedRRC(void (Ass::*f)(Reg1, Reg2, Cond),
- const std::vector<Reg1*>& reg1_registers,
- const std::vector<Reg2*>& reg2_registers,
- const std::vector<Cond>& cond,
- std::string (AssemblerArmTest::*GetName1)(const Reg1&),
- std::string (AssemblerArmTest::*GetName2)(const Reg2&),
- std::string fmt) {
- WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size());
-
- std::ostringstream oss;
- bool first = true;
- for (const Cond& c : cond) {
- std::string after_cond = fmt;
-
- size_t cond_index = after_cond.find(COND_TOKEN);
- if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
- }
-
- for (auto reg1 : reg1_registers) {
- std::string after_reg1 = after_cond;
-
- std::string reg1_string = (this->*GetName1)(*reg1);
- size_t reg1_index;
- while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
- after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
- }
-
- for (auto reg2 : reg2_registers) {
- std::string after_reg2 = after_reg1;
-
- std::string reg2_string = (this->*GetName2)(*reg2);
- size_t reg2_index;
- while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
- after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
- }
-
- if (first) {
- first = false;
- } else {
- oss << "\n";
- }
- oss << after_reg2;
-
- (Base::GetAssembler()->*f)(*reg1, *reg2, c);
- }
- }
- }
- // Add a newline at the end.
- oss << "\n";
-
- return oss.str();
- }
-
- std::string RepeatRRRC(void (Ass::*f)(Reg, Reg, Reg, Cond), std::string fmt) {
- return RepeatTemplatedRRRC(f, GetRegisters(), GetRegisters(), GetRegisters(), GetConditions(),
- &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
- &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
- &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
- fmt);
- }
-
- template <typename Reg1, typename Reg2, typename Reg3>
- std::string RepeatTemplatedRRRC(void (Ass::*f)(Reg1, Reg2, Reg3, Cond),
- const std::vector<Reg1*>& reg1_registers,
- const std::vector<Reg2*>& reg2_registers,
- const std::vector<Reg3*>& reg3_registers,
- const std::vector<Cond>& cond,
- std::string (AssemblerArmTest::*GetName1)(const Reg1&),
- std::string (AssemblerArmTest::*GetName2)(const Reg2&),
- std::string (AssemblerArmTest::*GetName3)(const Reg3&),
- std::string fmt) {
- WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size() *
- reg3_registers.size());
-
- std::ostringstream oss;
- bool first = true;
- for (const Cond& c : cond) {
- std::string after_cond = fmt;
-
- size_t cond_index = after_cond.find(COND_TOKEN);
- if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
- }
-
- for (auto reg1 : reg1_registers) {
- std::string after_reg1 = after_cond;
-
- std::string reg1_string = (this->*GetName1)(*reg1);
- size_t reg1_index;
- while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
- after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
- }
-
- for (auto reg2 : reg2_registers) {
- std::string after_reg2 = after_reg1;
-
- std::string reg2_string = (this->*GetName2)(*reg2);
- size_t reg2_index;
- while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
- after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
- }
-
- for (auto reg3 : reg3_registers) {
- std::string after_reg3 = after_reg2;
-
- std::string reg3_string = (this->*GetName3)(*reg3);
- size_t reg3_index;
- while ((reg3_index = after_reg3.find(REG3_TOKEN)) != std::string::npos) {
- after_reg3.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
- }
-
- if (first) {
- first = false;
- } else {
- oss << "\n";
- }
- oss << after_reg3;
-
- (Base::GetAssembler()->*f)(*reg1, *reg2, *reg3, c);
- }
- }
- }
- }
- // Add a newline at the end.
- oss << "\n";
-
- return oss.str();
- }
-
- template <typename RegT>
- std::string RepeatTemplatedRSC(void (Ass::*f)(RegT, SOp, Cond),
- const std::vector<RegT*>& registers,
- const std::vector<SOp>& shifts,
- const std::vector<Cond>& cond,
- std::string (AssemblerArmTest::*GetName)(const RegT&),
- std::string fmt) {
- WarnOnCombinations(cond.size() * registers.size() * shifts.size());
-
- std::ostringstream oss;
- bool first = true;
- for (const Cond& c : cond) {
- std::string after_cond = fmt;
-
- size_t cond_index = after_cond.find(COND_TOKEN);
- if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
- }
-
- for (const SOp& shift : shifts) {
- std::string after_shift = after_cond;
-
- std::string shift_string = GetShiftString(shift);
- size_t shift_index;
- while ((shift_index = after_shift.find(Base::SHIFT_TOKEN)) != std::string::npos) {
- after_shift.replace(shift_index, ConstexprStrLen(Base::SHIFT_TOKEN), shift_string);
- }
-
- for (auto reg : registers) {
- std::string after_reg = after_shift;
-
- std::string reg_string = (this->*GetName)(*reg);
- size_t reg_index;
- while ((reg_index = after_reg.find(Base::REG_TOKEN)) != std::string::npos) {
- after_reg.replace(reg_index, ConstexprStrLen(Base::REG_TOKEN), reg_string);
- }
-
- if (first) {
- first = false;
- } else {
- oss << "\n";
- }
- oss << after_reg;
-
- (Base::GetAssembler()->*f)(*reg, shift, c);
- }
- }
- }
- // Add a newline at the end.
- oss << "\n";
-
- return oss.str();
- }
-
- template <typename Reg1, typename Reg2>
- std::string RepeatTemplatedRRSC(void (Ass::*f)(Reg1, Reg2, const SOp&, Cond),
- const std::vector<Reg1*>& reg1_registers,
- const std::vector<Reg2*>& reg2_registers,
- const std::vector<SOp>& shifts,
- const std::vector<Cond>& cond,
- std::string (AssemblerArmTest::*GetName1)(const Reg1&),
- std::string (AssemblerArmTest::*GetName2)(const Reg2&),
- std::string fmt) {
- WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size() * shifts.size());
-
- std::ostringstream oss;
- bool first = true;
- for (const Cond& c : cond) {
- std::string after_cond = fmt;
-
- size_t cond_index = after_cond.find(COND_TOKEN);
- if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
- }
-
- for (const SOp& shift : shifts) {
- std::string after_shift = after_cond;
-
- std::string shift_string = GetShiftString(shift);
- size_t shift_index;
- while ((shift_index = after_shift.find(SHIFT_TOKEN)) != std::string::npos) {
- after_shift.replace(shift_index, ConstexprStrLen(SHIFT_TOKEN), shift_string);
- }
-
- for (auto reg1 : reg1_registers) {
- std::string after_reg1 = after_shift;
-
- std::string reg1_string = (this->*GetName1)(*reg1);
- size_t reg1_index;
- while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
- after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
- }
-
- for (auto reg2 : reg2_registers) {
- std::string after_reg2 = after_reg1;
-
- std::string reg2_string = (this->*GetName2)(*reg2);
- size_t reg2_index;
- while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
- after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
- }
-
- if (first) {
- first = false;
- } else {
- oss << "\n";
- }
- oss << after_reg2;
-
- (Base::GetAssembler()->*f)(*reg1, *reg2, shift, c);
- }
- }
- }
- }
- // Add a newline at the end.
- oss << "\n";
-
- return oss.str();
- }
-
- protected:
- AssemblerArmTest() {}
-
- virtual std::vector<Cond>& GetConditions() = 0;
- virtual std::string GetConditionString(Cond c) = 0;
-
- virtual std::vector<SetCc>& GetSetCcs() = 0;
- virtual std::string GetSetCcString(SetCc s) = 0;
-
- virtual std::vector<SOp>& GetShiftOperands() = 0;
- virtual std::string GetShiftString(SOp sop) = 0;
-
- virtual Reg GetPCRegister() = 0;
- virtual std::vector<Reg*> GetRegistersWithoutPC() {
- std::vector<Reg*> without_pc = GetRegisters();
- Reg pc_reg = GetPCRegister();
-
- for (auto it = without_pc.begin(); it != without_pc.end(); ++it) {
- if (**it == pc_reg) {
- without_pc.erase(it);
- break;
- }
- }
-
- return without_pc;
- }
-
- static constexpr const char* IMM1_TOKEN = "{imm1}";
- static constexpr const char* IMM2_TOKEN = "{imm2}";
- static constexpr const char* REG3_TOKEN = "{reg3}";
- static constexpr const char* REG4_TOKEN = "{reg4}";
- static constexpr const char* COND_TOKEN = "{cond}";
- static constexpr const char* SET_CC_TOKEN = "{s}";
- static constexpr const char* SHIFT_TOKEN = "{shift}";
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AssemblerArmTest);
-};
-
-} // namespace art
-
-#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_
diff --git a/compiler/utils/arm/assembler_arm_vixl.cc b/compiler/utils/arm/assembler_arm_vixl.cc
index 34849cd58d..05250a4157 100644
--- a/compiler/utils/arm/assembler_arm_vixl.cc
+++ b/compiler/utils/arm/assembler_arm_vixl.cc
@@ -112,12 +112,14 @@ bool ArmVIXLAssembler::ShifterOperandCanAlwaysHold(uint32_t immediate) {
return vixl_masm_.IsModifiedImmediate(immediate);
}
-bool ArmVIXLAssembler::ShifterOperandCanHold(Opcode opcode, uint32_t immediate, SetCc set_cc) {
+bool ArmVIXLAssembler::ShifterOperandCanHold(Opcode opcode,
+ uint32_t immediate,
+ vixl::aarch32::FlagsUpdate update_flags) {
switch (opcode) {
case ADD:
case SUB:
// Less than (or equal to) 12 bits can be done if we don't need to set condition codes.
- if (IsUint<12>(immediate) && set_cc != kCcSet) {
+ if (IsUint<12>(immediate) && update_flags != vixl::aarch32::SetFlags) {
return true;
}
return ShifterOperandCanAlwaysHold(immediate);
@@ -483,13 +485,9 @@ void ArmVIXLMacroAssembler::CompareAndBranchIfNonZero(vixl32::Register rn,
void ArmVIXLMacroAssembler::B(vixl32::Label* label) {
if (!label->IsBound()) {
- // Try to use 16-bit T2 encoding of B instruction.
+ // Try to use a 16-bit encoding of the B instruction.
DCHECK(OutsideITBlock());
- ExactAssemblyScope guard(this,
- k16BitT32InstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
- b(al, Narrow, label);
- AddBranchLabel(label);
+ BPreferNear(label);
return;
}
MacroAssembler::B(label);
@@ -497,18 +495,11 @@ void ArmVIXLMacroAssembler::B(vixl32::Label* label) {
void ArmVIXLMacroAssembler::B(vixl32::Condition cond, vixl32::Label* label, bool is_far_target) {
if (!label->IsBound() && !is_far_target) {
- // Try to use 16-bit T2 encoding of B instruction.
+ // Try to use a 16-bit encoding of the B instruction.
DCHECK(OutsideITBlock());
- ExactAssemblyScope guard(this,
- k16BitT32InstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
- b(cond, Narrow, label);
- AddBranchLabel(label);
+ BPreferNear(cond, label);
return;
}
- // To further reduce the Bcc encoding size and use 16-bit T1 encoding,
- // we can provide a hint to this function: i.e. far_target=false.
- // By default this function uses 'EncodingSizeType::Best' which generates 32-bit T3 encoding.
MacroAssembler::B(cond, label);
}
diff --git a/compiler/utils/arm/assembler_arm_vixl.h b/compiler/utils/arm/assembler_arm_vixl.h
index 1377e64073..b0310f2fb6 100644
--- a/compiler/utils/arm/assembler_arm_vixl.h
+++ b/compiler/utils/arm/assembler_arm_vixl.h
@@ -218,7 +218,9 @@ class ArmVIXLAssembler FINAL : public Assembler {
void StoreRegisterList(RegList regs, size_t stack_offset);
bool ShifterOperandCanAlwaysHold(uint32_t immediate);
- bool ShifterOperandCanHold(Opcode opcode, uint32_t immediate, SetCc set_cc = kCcDontCare);
+ bool ShifterOperandCanHold(Opcode opcode,
+ uint32_t immediate,
+ vixl::aarch32::FlagsUpdate update_flags = vixl::aarch32::DontCare);
bool CanSplitLoadStoreOffset(int32_t allowed_offset_bits,
int32_t offset,
/*out*/ int32_t* add_to_base,
diff --git a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
index 0bae4d4b69..065c3de23c 100644
--- a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
+++ b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
@@ -492,7 +492,7 @@ void ArmVIXLJNIMacroAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
temps.Exclude(in_reg.AsVIXLRegister());
___ Cmp(in_reg.AsVIXLRegister(), 0);
- if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value(), kCcDontCare)) {
+ if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value())) {
if (!out_reg.Equals(in_reg)) {
ExactAssemblyScope guard(asm_.GetVIXLAssembler(),
3 * vixl32::kMaxInstructionSizeInBytes,
@@ -531,7 +531,7 @@ void ArmVIXLJNIMacroAssembler::CreateHandleScopeEntry(FrameOffset out_off,
// e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset)
___ Cmp(scratch.AsVIXLRegister(), 0);
- if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value(), kCcDontCare)) {
+ if (asm_.ShifterOperandCanHold(ADD, handle_scope_offset.Int32Value())) {
ExactAssemblyScope guard(asm_.GetVIXLAssembler(),
2 * vixl32::kMaxInstructionSizeInBytes,
CodeBufferCheckScope::kMaximumSize);
@@ -624,14 +624,8 @@ void ArmVIXLJNIMacroAssembler::ExceptionPoll(ManagedRegister m_scratch, size_t s
Thread::ExceptionOffset<kArmPointerSize>().Int32Value());
___ Cmp(scratch.AsVIXLRegister(), 0);
- {
- ExactAssemblyScope guard(asm_.GetVIXLAssembler(),
- vixl32::kMaxInstructionSizeInBytes,
- CodeBufferCheckScope::kMaximumSize);
- vixl32::Label* label = exception_blocks_.back()->Entry();
- ___ b(ne, Narrow, label);
- ___ AddBranchLabel(label);
- }
+ vixl32::Label* label = exception_blocks_.back()->Entry();
+ ___ BPreferNear(ne, label);
// TODO: think about using CBNZ here.
}
diff --git a/compiler/utils/atomic_dex_ref_map-inl.h b/compiler/utils/atomic_dex_ref_map-inl.h
index 33d59f9d42..203e484fb7 100644
--- a/compiler/utils/atomic_dex_ref_map-inl.h
+++ b/compiler/utils/atomic_dex_ref_map-inl.h
@@ -21,8 +21,8 @@
#include <type_traits>
-#include "dex_file-inl.h"
#include "class_reference.h"
+#include "dex/dex_file-inl.h"
#include "method_reference.h"
#include "type_reference.h"
@@ -58,7 +58,7 @@ inline typename AtomicDexRefMap<DexFileReferenceType, Value>::InsertResult
return kInsertResultInvalidDexFile;
}
DCHECK_LT(ref.index, array->size());
- return (*array)[ref.index].CompareExchangeStrongSequentiallyConsistent(expected, desired)
+ return (*array)[ref.index].CompareAndSetStrongSequentiallyConsistent(expected, desired)
? kInsertResultSuccess
: kInsertResultCASFailure;
}
diff --git a/compiler/utils/atomic_dex_ref_map.h b/compiler/utils/atomic_dex_ref_map.h
index 205543f31d..9ff506d6a4 100644
--- a/compiler/utils/atomic_dex_ref_map.h
+++ b/compiler/utils/atomic_dex_ref_map.h
@@ -18,7 +18,7 @@
#define ART_COMPILER_UTILS_ATOMIC_DEX_REF_MAP_H_
#include "base/dchecked_vector.h"
-#include "dex_file_reference.h"
+#include "dex/dex_file_reference.h"
#include "safe_map.h"
namespace art {
diff --git a/compiler/utils/atomic_dex_ref_map_test.cc b/compiler/utils/atomic_dex_ref_map_test.cc
index 8fce36f021..d58d60b4f3 100644
--- a/compiler/utils/atomic_dex_ref_map_test.cc
+++ b/compiler/utils/atomic_dex_ref_map_test.cc
@@ -19,7 +19,7 @@
#include <memory>
#include "common_runtime_test.h"
-#include "dex_file-inl.h"
+#include "dex/dex_file-inl.h"
#include "method_reference.h"
#include "scoped_thread_state_change-inl.h"
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc
index bf56877499..e1b0e75108 100644
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ b/compiler/utils/mips64/assembler_mips64.cc
@@ -430,6 +430,20 @@ void Mips64Assembler::Dext(GpuRegister rt, GpuRegister rs, int pos, int size) {
EmitR(0x1f, rs, rt, static_cast<GpuRegister>(size - 1), pos, 0x3);
}
+void Mips64Assembler::Ins(GpuRegister rd, GpuRegister rt, int pos, int size) {
+ CHECK(IsUint<5>(pos)) << pos;
+ CHECK(IsUint<5>(size - 1)) << size;
+ CHECK(IsUint<5>(pos + size - 1)) << pos << " + " << size;
+ EmitR(0x1f, rt, rd, static_cast<GpuRegister>(pos + size - 1), pos, 0x04);
+}
+
+void Mips64Assembler::Dinsm(GpuRegister rt, GpuRegister rs, int pos, int size) {
+ CHECK(IsUint<5>(pos)) << pos;
+ CHECK(2 <= size && size <= 64) << size;
+ CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size;
+ EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos, 0x5);
+}
+
void Mips64Assembler::Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size) {
CHECK(IsUint<5>(pos - 32)) << pos;
CHECK(IsUint<5>(size - 1)) << size;
@@ -437,6 +451,23 @@ void Mips64Assembler::Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size) {
EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos - 32, 0x6);
}
+void Mips64Assembler::Dins(GpuRegister rt, GpuRegister rs, int pos, int size) {
+ CHECK(IsUint<5>(pos)) << pos;
+ CHECK(IsUint<5>(size - 1)) << size;
+ CHECK(IsUint<5>(pos + size - 1)) << pos << " + " << size;
+ EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 1), pos, 0x7);
+}
+
+void Mips64Assembler::DblIns(GpuRegister rt, GpuRegister rs, int pos, int size) {
+ if (pos >= 32) {
+ Dinsu(rt, rs, pos, size);
+ } else if ((static_cast<int64_t>(pos) + size - 1) >= 32) {
+ Dinsm(rt, rs, pos, size);
+ } else {
+ Dins(rt, rs, pos, size);
+ }
+}
+
void Mips64Assembler::Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) {
CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
int sa = saPlusOne - 1;
diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h
index 9f5e6aaa88..7a61f39e64 100644
--- a/compiler/utils/mips64/assembler_mips64.h
+++ b/compiler/utils/mips64/assembler_mips64.h
@@ -478,7 +478,11 @@ class Mips64Assembler FINAL : public Assembler, public JNIMacroAssembler<Pointer
void Dsbh(GpuRegister rd, GpuRegister rt); // MIPS64
void Dshd(GpuRegister rd, GpuRegister rt); // MIPS64
void Dext(GpuRegister rs, GpuRegister rt, int pos, int size); // MIPS64
+ void Ins(GpuRegister rt, GpuRegister rs, int pos, int size);
+ void Dins(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
+ void Dinsm(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
void Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
+ void DblIns(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
void Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne);
void Dlsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne); // MIPS64
void Wsbh(GpuRegister rd, GpuRegister rt);
diff --git a/compiler/utils/mips64/assembler_mips64_test.cc b/compiler/utils/mips64/assembler_mips64_test.cc
index d89ca3d6ea..b0e1d91c3f 100644
--- a/compiler/utils/mips64/assembler_mips64_test.cc
+++ b/compiler/utils/mips64/assembler_mips64_test.cc
@@ -1353,23 +1353,42 @@ TEST_F(AssemblerMIPS64Test, Dext) {
DriverStr(expected.str(), "Dext");
}
-TEST_F(AssemblerMIPS64Test, Dinsu) {
+TEST_F(AssemblerMIPS64Test, Ins) {
+ std::vector<mips64::GpuRegister*> regs = GetRegisters();
+ WarnOnCombinations(regs.size() * regs.size() * 33 * 16);
+ std::string expected;
+ for (mips64::GpuRegister* reg1 : regs) {
+ for (mips64::GpuRegister* reg2 : regs) {
+ for (int32_t pos = 0; pos < 32; pos++) {
+ for (int32_t size = 1; pos + size <= 32; size++) {
+ __ Ins(*reg1, *reg2, pos, size);
+ std::ostringstream instr;
+ instr << "ins $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
+ expected += instr.str();
+ }
+ }
+ }
+ }
+ DriverStr(expected, "Ins");
+}
+
+TEST_F(AssemblerMIPS64Test, DblIns) {
std::vector<mips64::GpuRegister*> reg1_registers = GetRegisters();
std::vector<mips64::GpuRegister*> reg2_registers = GetRegisters();
- WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * 33 * 16);
+ WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * 65 * 32);
std::ostringstream expected;
for (mips64::GpuRegister* reg1 : reg1_registers) {
for (mips64::GpuRegister* reg2 : reg2_registers) {
- for (int32_t pos = 32; pos < 64; pos++) {
+ for (int32_t pos = 0; pos < 64; pos++) {
for (int32_t size = 1; pos + size <= 64; size++) {
- __ Dinsu(*reg1, *reg2, pos, size);
- expected << "dinsu $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
+ __ DblIns(*reg1, *reg2, pos, size);
+ expected << "dins $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
}
}
}
}
- DriverStr(expected.str(), "Dinsu");
+ DriverStr(expected.str(), "DblIns");
}
TEST_F(AssemblerMIPS64Test, Lsa) {
diff --git a/compiler/utils/string_reference_test.cc b/compiler/utils/string_reference_test.cc
index 90335eb048..4b07e65771 100644
--- a/compiler/utils/string_reference_test.cc
+++ b/compiler/utils/string_reference_test.cc
@@ -18,7 +18,7 @@
#include <memory>
-#include "dex_file_types.h"
+#include "dex/dex_file_types.h"
#include "gtest/gtest.h"
#include "utils/test_dex_file_builder.h"
diff --git a/compiler/utils/test_dex_file_builder.h b/compiler/utils/test_dex_file_builder.h
index 441ef8e117..58f1ec7b08 100644
--- a/compiler/utils/test_dex_file_builder.h
+++ b/compiler/utils/test_dex_file_builder.h
@@ -27,8 +27,9 @@
#include <android-base/logging.h>
#include "base/bit_utils.h"
-#include "dex_file_loader.h"
-#include "standard_dex_file.h"
+#include "dex/art_dex_file_loader.h"
+#include "dex/dex_file_loader.h"
+#include "dex/standard_dex_file.h"
namespace art {
@@ -233,7 +234,8 @@ class TestDexFileBuilder {
static constexpr bool kVerify = false;
static constexpr bool kVerifyChecksum = false;
std::string error_msg;
- std::unique_ptr<const DexFile> dex_file(DexFileLoader::Open(
+ const ArtDexFileLoader dex_file_loader;
+ std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(
&dex_file_data_[0],
dex_file_data_.size(),
dex_location,
diff --git a/compiler/utils/test_dex_file_builder_test.cc b/compiler/utils/test_dex_file_builder_test.cc
index c76739b3b1..736a17edac 100644
--- a/compiler/utils/test_dex_file_builder_test.cc
+++ b/compiler/utils/test_dex_file_builder_test.cc
@@ -16,7 +16,7 @@
#include "test_dex_file_builder.h"
-#include "dex_file-inl.h"
+#include "dex/dex_file-inl.h"
#include "gtest/gtest.h"
#include "utils.h"
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index ee1d7c69bc..76448d819c 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -21,10 +21,10 @@
#include "class_linker.h"
#include "common_compiler_test.h"
#include "compiler_callbacks.h"
+#include "dex/dex_file-inl.h"
+#include "dex/dex_file_types.h"
#include "dex/verification_results.h"
#include "dex/verified_method.h"
-#include "dex_file-inl.h"
-#include "dex_file_types.h"
#include "driver/compiler_driver-inl.h"
#include "driver/compiler_options.h"
#include "handle_scope-inl.h"
@@ -237,9 +237,9 @@ class VerifierDepsTest : public CommonCompilerTest {
CHECK(soa.Self()->IsExceptionPending());
soa.Self()->ClearException();
} else if (unverified_classes.find(class_def.class_idx_) == unverified_classes.end()) {
- ASSERT_EQ(cls->GetStatus(), mirror::Class::kStatusVerified);
+ ASSERT_EQ(cls->GetStatus(), ClassStatus::kVerified);
} else {
- ASSERT_LT(cls->GetStatus(), mirror::Class::kStatusVerified);
+ ASSERT_LT(cls->GetStatus(), ClassStatus::kVerified);
}
}
}