summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/debug/elf_debug_loc_writer.h4
-rw-r--r--compiler/optimizing/code_generator.cc129
-rw-r--r--compiler/optimizing/code_generator.h5
-rw-r--r--compiler/optimizing/code_generator_arm64.cc106
-rw-r--r--compiler/optimizing/code_generator_arm64.h4
-rw-r--r--compiler/optimizing/common_arm64.h26
-rw-r--r--compiler/optimizing/gvn.cc5
-rw-r--r--compiler/optimizing/nodes.cc8
-rw-r--r--compiler/optimizing/nodes.h1
-rw-r--r--compiler/optimizing/stack_map_stream.cc103
-rw-r--r--compiler/optimizing/stack_map_stream.h71
-rw-r--r--compiler/optimizing/stack_map_test.cc138
-rw-r--r--dexlayout/compact_dex_writer.cc12
-rw-r--r--dexlayout/dex_ir.cc180
-rw-r--r--dexlayout/dex_ir.h193
-rw-r--r--dexlayout/dex_ir_builder.cc9
-rw-r--r--dexlayout/dex_verify.cc8
-rw-r--r--dexlayout/dex_visualize.cc8
-rw-r--r--dexlayout/dex_writer.cc14
-rw-r--r--dexlayout/dexlayout.cc36
-rw-r--r--libartbase/base/bit_table.h69
-rw-r--r--libartbase/base/bit_table_test.cc64
-rw-r--r--libartbase/base/indenter.h4
-rw-r--r--libartbase/base/mem_map.cc20
-rw-r--r--libartbase/base/mem_map_test.cc5
-rw-r--r--libartbase/base/stats.h60
-rw-r--r--oatdump/oatdump.cc317
-rw-r--r--oatdump/oatdump_test.h2
-rw-r--r--runtime/Android.bp1
-rw-r--r--runtime/check_reference_map_visitor.h4
-rw-r--r--runtime/class_linker.cc4
-rw-r--r--runtime/dex_register_location.cc50
-rw-r--r--runtime/dex_register_location.h26
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc5
-rw-r--r--runtime/exec_utils_test.cc42
-rw-r--r--runtime/instrumentation.cc24
-rw-r--r--runtime/jit/jit.cc4
-rw-r--r--runtime/native_stack_dump.cc5
-rw-r--r--runtime/oat.h4
-rw-r--r--runtime/proxy_test.cc15
-rw-r--r--runtime/quick_exception_handler.cc18
-rw-r--r--runtime/stack.cc15
-rw-r--r--runtime/stack_map.cc91
-rw-r--r--runtime/stack_map.h157
-rw-r--r--runtime/thread.cc2
-rw-r--r--runtime/well_known_classes.cc11
-rw-r--r--runtime/well_known_classes.h1
-rw-r--r--test/004-ReferenceMap/build3
-rw-r--r--test/004-StackWalk/build3
-rwxr-xr-xtest/004-ThreadStress/run24
-rw-r--r--test/004-ThreadStress/src-art/Main.java8
-rw-r--r--test/022-interface/build2
-rwxr-xr-xtest/091-override-package-private-method/build4
-rw-r--r--test/111-unresolvable-exception/build2
-rw-r--r--test/113-multidex/build4
-rw-r--r--test/126-miranda-multidex/build4
-rwxr-xr-xtest/127-checker-secondarydex/build4
-rwxr-xr-xtest/138-duplicate-classes-check2/build4
-rw-r--r--test/477-checker-bound-type/src/Main.java76
-rw-r--r--test/530-checker-lse2/build20
-rw-r--r--test/565-checker-rotate/build20
-rw-r--r--test/565-checker-rotate/smali/Main2.smali165
-rw-r--r--test/565-checker-rotate/src-art/Main.java546
-rw-r--r--test/565-checker-rotate/src/Main.java620
-rw-r--r--test/569-checker-pattern-replacement/build20
-rw-r--r--test/583-checker-zero/build20
-rw-r--r--test/626-checker-arm64-scratch-register/build20
-rw-r--r--test/626-checker-arm64-scratch-register/smali/Main2.smali1768
-rw-r--r--test/626-checker-arm64-scratch-register/src-art/Main.java23
-rw-r--r--test/626-checker-arm64-scratch-register/src/Main.java279
-rw-r--r--test/646-checker-hadd-alt-char/build20
-rw-r--r--test/646-checker-hadd-alt-char/src/Main.java4
-rw-r--r--test/646-checker-hadd-alt-short/build20
-rw-r--r--test/646-checker-hadd-alt-short/src/Main.java12
-rw-r--r--test/646-checker-hadd-char/build20
-rw-r--r--test/646-checker-hadd-char/src/Main.java4
-rw-r--r--test/646-checker-hadd-short/build20
-rw-r--r--test/646-checker-hadd-short/src/Main.java20
-rw-r--r--test/660-checker-simd-sad-byte/build20
-rw-r--r--test/660-checker-simd-sad-byte/src/Main.java12
-rw-r--r--test/660-checker-simd-sad-char/build20
-rw-r--r--test/660-checker-simd-sad-char/src/Main.java12
-rw-r--r--test/660-checker-simd-sad-int/build20
-rw-r--r--test/660-checker-simd-sad-int/src/Main.java12
-rw-r--r--test/660-checker-simd-sad-short/build20
-rw-r--r--test/660-checker-simd-sad-short/src/Main.java24
-rw-r--r--test/660-checker-simd-sad-short2/build20
-rw-r--r--test/660-checker-simd-sad-short2/src/Main.java36
-rw-r--r--test/660-checker-simd-sad-short3/build20
-rw-r--r--test/660-checker-simd-sad-short3/src/Main.java32
-rw-r--r--test/679-checker-minmax/src/Main.java204
-rwxr-xr-xtest/952-invoke-custom/build7
-rwxr-xr-xtest/979-const-method-handle/build7
-rwxr-xr-xtest/etc/default-build2
-rwxr-xr-xtest/run-test25
-rwxr-xr-xtools/teardown-buildbot-device.sh130
96 files changed, 4045 insertions, 2417 deletions
diff --git a/compiler/debug/elf_debug_loc_writer.h b/compiler/debug/elf_debug_loc_writer.h
index 4009acb992..b663291b4d 100644
--- a/compiler/debug/elf_debug_loc_writer.h
+++ b/compiler/debug/elf_debug_loc_writer.h
@@ -149,9 +149,9 @@ static std::vector<VariableLocation> GetVariableLocations(
DexRegisterMap dex_register_map = dex_register_maps[stack_map_index];
DCHECK(!dex_register_map.empty());
CodeItemDataAccessor accessor(*method_info->dex_file, method_info->code_item);
- reg_lo = dex_register_map.GetDexRegisterLocation(vreg);
+ reg_lo = dex_register_map[vreg];
if (is64bitValue) {
- reg_hi = dex_register_map.GetDexRegisterLocation(vreg + 1);
+ reg_hi = dex_register_map[vreg + 1];
}
// Add location entry for this address range.
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index b3feb787a9..2589869859 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -1055,7 +1055,8 @@ void CodeGenerator::BuildStackMaps(MemoryRegion stack_map_region,
void CodeGenerator::RecordPcInfo(HInstruction* instruction,
uint32_t dex_pc,
- SlowPathCode* slow_path) {
+ SlowPathCode* slow_path,
+ bool native_debug_info) {
if (instruction != nullptr) {
// The code generated for some type conversions
// may call the runtime, thus normally requiring a subsequent
@@ -1120,12 +1121,23 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction,
outer_dex_pc = outer_environment->GetDexPc();
outer_environment_size = outer_environment->Size();
}
+
+ HLoopInformation* info = instruction->GetBlock()->GetLoopInformation();
+ bool osr =
+ instruction->IsSuspendCheck() &&
+ (info != nullptr) &&
+ graph_->IsCompilingOsr() &&
+ (inlining_depth == 0);
+ StackMap::Kind kind = native_debug_info
+ ? StackMap::Kind::Debug
+ : (osr ? StackMap::Kind::OSR : StackMap::Kind::Default);
stack_map_stream->BeginStackMapEntry(outer_dex_pc,
native_pc,
register_mask,
locations->GetStackMask(),
outer_environment_size,
- inlining_depth);
+ inlining_depth,
+ kind);
EmitEnvironment(environment, slow_path);
// Record invoke info, the common case for the trampoline is super and static invokes. Only
// record these to reduce oat file size.
@@ -1138,19 +1150,9 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction,
}
stack_map_stream->EndStackMapEntry();
- HLoopInformation* info = instruction->GetBlock()->GetLoopInformation();
- if (instruction->IsSuspendCheck() &&
- (info != nullptr) &&
- graph_->IsCompilingOsr() &&
- (inlining_depth == 0)) {
+ if (osr) {
DCHECK_EQ(info->GetSuspendCheck(), instruction);
- // We duplicate the stack map as a marker that this stack map can be an OSR entry.
- // Duplicating it avoids having the runtime recognize and skip an OSR stack map.
DCHECK(info->IsIrreducible());
- stack_map_stream->BeginStackMapEntry(
- dex_pc, native_pc, register_mask, locations->GetStackMask(), outer_environment_size, 0);
- EmitEnvironment(instruction->GetEnvironment(), slow_path);
- stack_map_stream->EndStackMapEntry();
if (kIsDebugBuild) {
for (size_t i = 0, environment_size = environment->Size(); i < environment_size; ++i) {
HInstruction* in_environment = environment->GetInstructionAt(i);
@@ -1167,14 +1169,6 @@ void CodeGenerator::RecordPcInfo(HInstruction* instruction,
}
}
}
- } else if (kIsDebugBuild) {
- // Ensure stack maps are unique, by checking that the native pc in the stack map
- // last emitted is different than the native pc of the stack map just emitted.
- size_t number_of_stack_maps = stack_map_stream->GetNumberOfStackMaps();
- if (number_of_stack_maps > 1) {
- DCHECK_NE(stack_map_stream->GetStackMapNativePcOffset(number_of_stack_maps - 1),
- stack_map_stream->GetStackMapNativePcOffset(number_of_stack_maps - 2));
- }
}
}
@@ -1196,12 +1190,11 @@ void CodeGenerator::MaybeRecordNativeDebugInfo(HInstruction* instruction,
// Ensure that we do not collide with the stack map of the previous instruction.
GenerateNop();
}
- RecordPcInfo(instruction, dex_pc, slow_path);
+ RecordPcInfo(instruction, dex_pc, slow_path, /* native_debug_info */ true);
}
}
void CodeGenerator::RecordCatchBlockInfo() {
- ArenaAllocator* allocator = graph_->GetAllocator();
StackMapStream* stack_map_stream = GetStackMapStream();
for (HBasicBlock* block : *block_order_) {
@@ -1213,28 +1206,24 @@ void CodeGenerator::RecordCatchBlockInfo() {
uint32_t num_vregs = graph_->GetNumberOfVRegs();
uint32_t inlining_depth = 0; // Inlining of catch blocks is not supported at the moment.
uint32_t native_pc = GetAddressOf(block);
- uint32_t register_mask = 0; // Not used.
-
- // The stack mask is not used, so we leave it empty.
- ArenaBitVector* stack_mask =
- ArenaBitVector::Create(allocator, 0, /* expandable */ true, kArenaAllocCodeGenerator);
stack_map_stream->BeginStackMapEntry(dex_pc,
native_pc,
- register_mask,
- stack_mask,
+ /* register_mask */ 0,
+ /* stack_mask */ nullptr,
num_vregs,
- inlining_depth);
+ inlining_depth,
+ StackMap::Kind::Catch);
HInstruction* current_phi = block->GetFirstPhi();
for (size_t vreg = 0; vreg < num_vregs; ++vreg) {
- while (current_phi != nullptr && current_phi->AsPhi()->GetRegNumber() < vreg) {
- HInstruction* next_phi = current_phi->GetNext();
- DCHECK(next_phi == nullptr ||
- current_phi->AsPhi()->GetRegNumber() <= next_phi->AsPhi()->GetRegNumber())
- << "Phis need to be sorted by vreg number to keep this a linear-time loop.";
- current_phi = next_phi;
- }
+ while (current_phi != nullptr && current_phi->AsPhi()->GetRegNumber() < vreg) {
+ HInstruction* next_phi = current_phi->GetNext();
+ DCHECK(next_phi == nullptr ||
+ current_phi->AsPhi()->GetRegNumber() <= next_phi->AsPhi()->GetRegNumber())
+ << "Phis need to be sorted by vreg number to keep this a linear-time loop.";
+ current_phi = next_phi;
+ }
if (current_phi == nullptr || current_phi->AsPhi()->GetRegNumber() != vreg) {
stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kNone, 0);
@@ -1294,50 +1283,45 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo
continue;
}
+ using Kind = DexRegisterLocation::Kind;
Location location = environment->GetLocationAt(i);
switch (location.GetKind()) {
case Location::kConstant: {
DCHECK_EQ(current, location.GetConstant());
if (current->IsLongConstant()) {
int64_t value = current->AsLongConstant()->GetValue();
- stack_map_stream->AddDexRegisterEntry(
- DexRegisterLocation::Kind::kConstant, Low32Bits(value));
- stack_map_stream->AddDexRegisterEntry(
- DexRegisterLocation::Kind::kConstant, High32Bits(value));
+ stack_map_stream->AddDexRegisterEntry(Kind::kConstant, Low32Bits(value));
+ stack_map_stream->AddDexRegisterEntry(Kind::kConstant, High32Bits(value));
++i;
DCHECK_LT(i, environment_size);
} else if (current->IsDoubleConstant()) {
int64_t value = bit_cast<int64_t, double>(current->AsDoubleConstant()->GetValue());
- stack_map_stream->AddDexRegisterEntry(
- DexRegisterLocation::Kind::kConstant, Low32Bits(value));
- stack_map_stream->AddDexRegisterEntry(
- DexRegisterLocation::Kind::kConstant, High32Bits(value));
+ stack_map_stream->AddDexRegisterEntry(Kind::kConstant, Low32Bits(value));
+ stack_map_stream->AddDexRegisterEntry(Kind::kConstant, High32Bits(value));
++i;
DCHECK_LT(i, environment_size);
} else if (current->IsIntConstant()) {
int32_t value = current->AsIntConstant()->GetValue();
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant, value);
+ stack_map_stream->AddDexRegisterEntry(Kind::kConstant, value);
} else if (current->IsNullConstant()) {
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant, 0);
+ stack_map_stream->AddDexRegisterEntry(Kind::kConstant, 0);
} else {
DCHECK(current->IsFloatConstant()) << current->DebugName();
int32_t value = bit_cast<int32_t, float>(current->AsFloatConstant()->GetValue());
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant, value);
+ stack_map_stream->AddDexRegisterEntry(Kind::kConstant, value);
}
break;
}
case Location::kStackSlot: {
- stack_map_stream->AddDexRegisterEntry(
- DexRegisterLocation::Kind::kInStack, location.GetStackIndex());
+ stack_map_stream->AddDexRegisterEntry(Kind::kInStack, location.GetStackIndex());
break;
}
case Location::kDoubleStackSlot: {
+ stack_map_stream->AddDexRegisterEntry(Kind::kInStack, location.GetStackIndex());
stack_map_stream->AddDexRegisterEntry(
- DexRegisterLocation::Kind::kInStack, location.GetStackIndex());
- stack_map_stream->AddDexRegisterEntry(
- DexRegisterLocation::Kind::kInStack, location.GetHighStackIndex(kVRegSize));
+ Kind::kInStack, location.GetHighStackIndex(kVRegSize));
++i;
DCHECK_LT(i, environment_size);
break;
@@ -1347,17 +1331,16 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo
int id = location.reg();
if (slow_path != nullptr && slow_path->IsCoreRegisterSaved(id)) {
uint32_t offset = slow_path->GetStackOffsetOfCoreRegister(id);
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInStack, offset);
if (current->GetType() == DataType::Type::kInt64) {
- stack_map_stream->AddDexRegisterEntry(
- DexRegisterLocation::Kind::kInStack, offset + kVRegSize);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInStack, offset + kVRegSize);
++i;
DCHECK_LT(i, environment_size);
}
} else {
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister, id);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInRegister, id);
if (current->GetType() == DataType::Type::kInt64) {
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegisterHigh, id);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInRegisterHigh, id);
++i;
DCHECK_LT(i, environment_size);
}
@@ -1369,18 +1352,16 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo
int id = location.reg();
if (slow_path != nullptr && slow_path->IsFpuRegisterSaved(id)) {
uint32_t offset = slow_path->GetStackOffsetOfFpuRegister(id);
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInStack, offset);
if (current->GetType() == DataType::Type::kFloat64) {
- stack_map_stream->AddDexRegisterEntry(
- DexRegisterLocation::Kind::kInStack, offset + kVRegSize);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInStack, offset + kVRegSize);
++i;
DCHECK_LT(i, environment_size);
}
} else {
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister, id);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInFpuRegister, id);
if (current->GetType() == DataType::Type::kFloat64) {
- stack_map_stream->AddDexRegisterEntry(
- DexRegisterLocation::Kind::kInFpuRegisterHigh, id);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInFpuRegisterHigh, id);
++i;
DCHECK_LT(i, environment_size);
}
@@ -1393,16 +1374,16 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo
int high = location.high();
if (slow_path != nullptr && slow_path->IsFpuRegisterSaved(low)) {
uint32_t offset = slow_path->GetStackOffsetOfFpuRegister(low);
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInStack, offset);
} else {
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister, low);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInFpuRegister, low);
}
if (slow_path != nullptr && slow_path->IsFpuRegisterSaved(high)) {
uint32_t offset = slow_path->GetStackOffsetOfFpuRegister(high);
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInStack, offset);
++i;
} else {
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister, high);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInFpuRegister, high);
++i;
}
DCHECK_LT(i, environment_size);
@@ -1414,15 +1395,15 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo
int high = location.high();
if (slow_path != nullptr && slow_path->IsCoreRegisterSaved(low)) {
uint32_t offset = slow_path->GetStackOffsetOfCoreRegister(low);
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInStack, offset);
} else {
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister, low);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInRegister, low);
}
if (slow_path != nullptr && slow_path->IsCoreRegisterSaved(high)) {
uint32_t offset = slow_path->GetStackOffsetOfCoreRegister(high);
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInStack, offset);
} else {
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister, high);
+ stack_map_stream->AddDexRegisterEntry(Kind::kInRegister, high);
}
++i;
DCHECK_LT(i, environment_size);
@@ -1430,7 +1411,7 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo
}
case Location::kInvalid: {
- stack_map_stream->AddDexRegisterEntry(DexRegisterLocation::Kind::kNone, 0);
+ stack_map_stream->AddDexRegisterEntry(Kind::kNone, 0);
break;
}
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index b3c29aa804..03ae4983d4 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -323,7 +323,10 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> {
}
// Record native to dex mapping for a suspend point. Required by runtime.
- void RecordPcInfo(HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path = nullptr);
+ void RecordPcInfo(HInstruction* instruction,
+ uint32_t dex_pc,
+ SlowPathCode* slow_path = nullptr,
+ bool native_debug_info = false);
// Check whether we have already recorded mapping at this PC.
bool HasStackMapAtCurrentPc();
// Record extra stack maps if we support native debugging.
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 5f0533cbe9..8aa790db34 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -2459,6 +2459,9 @@ void InstructionCodeGeneratorARM64::HandleBinaryOp(HBinaryOperation* instr) {
// all & reg_bits - 1.
__ Ror(dst, lhs, RegisterFrom(instr->GetLocations()->InAt(1), type));
}
+ } else if (instr->IsMin() || instr->IsMax()) {
+ __ Cmp(lhs, rhs);
+ __ Csel(dst, lhs, rhs, instr->IsMin() ? lt : gt);
} else {
DCHECK(instr->IsXor());
__ Eor(dst, lhs, rhs);
@@ -2474,6 +2477,10 @@ void InstructionCodeGeneratorARM64::HandleBinaryOp(HBinaryOperation* instr) {
__ Fadd(dst, lhs, rhs);
} else if (instr->IsSub()) {
__ Fsub(dst, lhs, rhs);
+ } else if (instr->IsMin()) {
+ __ Fmin(dst, lhs, rhs);
+ } else if (instr->IsMax()) {
+ __ Fmax(dst, lhs, rhs);
} else {
LOG(FATAL) << "Unexpected floating-point binary operation";
}
@@ -5671,111 +5678,20 @@ void InstructionCodeGeneratorARM64::VisitRem(HRem* rem) {
}
}
-// TODO: integrate with HandleBinaryOp?
-static void CreateMinMaxLocations(ArenaAllocator* allocator, HBinaryOperation* minmax) {
- LocationSummary* locations = new (allocator) LocationSummary(minmax);
- switch (minmax->GetResultType()) {
- case DataType::Type::kInt32:
- case DataType::Type::kInt64:
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RequiresRegister());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
- break;
- case DataType::Type::kFloat32:
- case DataType::Type::kFloat64:
- locations->SetInAt(0, Location::RequiresFpuRegister());
- locations->SetInAt(1, Location::RequiresFpuRegister());
- locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
- break;
- default:
- LOG(FATAL) << "Unexpected type for HMinMax " << minmax->GetResultType();
- }
-}
-
-void InstructionCodeGeneratorARM64::GenerateMinMaxInt(LocationSummary* locations,
- bool is_min,
- DataType::Type type) {
- Location op1 = locations->InAt(0);
- Location op2 = locations->InAt(1);
- Location out = locations->Out();
-
- Register op1_reg;
- Register op2_reg;
- Register out_reg;
- if (type == DataType::Type::kInt64) {
- op1_reg = XRegisterFrom(op1);
- op2_reg = XRegisterFrom(op2);
- out_reg = XRegisterFrom(out);
- } else {
- DCHECK_EQ(type, DataType::Type::kInt32);
- op1_reg = WRegisterFrom(op1);
- op2_reg = WRegisterFrom(op2);
- out_reg = WRegisterFrom(out);
- }
-
- __ Cmp(op1_reg, op2_reg);
- __ Csel(out_reg, op1_reg, op2_reg, is_min ? lt : gt);
-}
-
-void InstructionCodeGeneratorARM64::GenerateMinMaxFP(LocationSummary* locations,
- bool is_min,
- DataType::Type type) {
- Location op1 = locations->InAt(0);
- Location op2 = locations->InAt(1);
- Location out = locations->Out();
-
- FPRegister op1_reg;
- FPRegister op2_reg;
- FPRegister out_reg;
- if (type == DataType::Type::kFloat64) {
- op1_reg = DRegisterFrom(op1);
- op2_reg = DRegisterFrom(op2);
- out_reg = DRegisterFrom(out);
- } else {
- DCHECK_EQ(type, DataType::Type::kFloat32);
- op1_reg = SRegisterFrom(op1);
- op2_reg = SRegisterFrom(op2);
- out_reg = SRegisterFrom(out);
- }
-
- if (is_min) {
- __ Fmin(out_reg, op1_reg, op2_reg);
- } else {
- __ Fmax(out_reg, op1_reg, op2_reg);
- }
-}
-
-// TODO: integrate with HandleBinaryOp?
-void InstructionCodeGeneratorARM64::GenerateMinMax(HBinaryOperation* minmax, bool is_min) {
- DataType::Type type = minmax->GetResultType();
- switch (type) {
- case DataType::Type::kInt32:
- case DataType::Type::kInt64:
- GenerateMinMaxInt(minmax->GetLocations(), is_min, type);
- break;
- case DataType::Type::kFloat32:
- case DataType::Type::kFloat64:
- GenerateMinMaxFP(minmax->GetLocations(), is_min, type);
- break;
- default:
- LOG(FATAL) << "Unexpected type for HMinMax " << type;
- }
-}
-
void LocationsBuilderARM64::VisitMin(HMin* min) {
- CreateMinMaxLocations(GetGraph()->GetAllocator(), min);
+ HandleBinaryOp(min);
}
void InstructionCodeGeneratorARM64::VisitMin(HMin* min) {
- GenerateMinMax(min, /*is_min*/ true);
+ HandleBinaryOp(min);
}
void LocationsBuilderARM64::VisitMax(HMax* max) {
- CreateMinMaxLocations(GetGraph()->GetAllocator(), max);
+ HandleBinaryOp(max);
}
void InstructionCodeGeneratorARM64::VisitMax(HMax* max) {
- GenerateMinMax(max, /*is_min*/ false);
+ HandleBinaryOp(max);
}
void LocationsBuilderARM64::VisitAbs(HAbs* abs) {
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index e7fe5b71b7..5afb712d17 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -280,10 +280,6 @@ class InstructionCodeGeneratorARM64 : public InstructionCodeGenerator {
void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
void HandleCondition(HCondition* instruction);
- void GenerateMinMaxInt(LocationSummary* locations, bool is_min, DataType::Type type);
- void GenerateMinMaxFP(LocationSummary* locations, bool is_min, DataType::Type type);
- void GenerateMinMax(HBinaryOperation* minmax, bool is_min);
-
// Generate a heap reference load using one register `out`:
//
// out <- *(out + offset)
diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h
index ed2f8e995d..5191ee2b1e 100644
--- a/compiler/optimizing/common_arm64.h
+++ b/compiler/optimizing/common_arm64.h
@@ -234,6 +234,13 @@ inline vixl::aarch64::Operand OperandFromMemOperand(
}
}
+inline bool AddSubCanEncodeAsImmediate(int64_t value) {
+ // If `value` does not fit but `-value` does, VIXL will automatically use
+ // the 'opposite' instruction.
+ return vixl::aarch64::Assembler::IsImmAddSub(value)
+ || vixl::aarch64::Assembler::IsImmAddSub(-value);
+}
+
inline bool Arm64CanEncodeConstantAsImmediate(HConstant* constant, HInstruction* instr) {
int64_t value = CodeGenerator::GetInt64ValueOf(constant);
@@ -249,6 +256,20 @@ inline bool Arm64CanEncodeConstantAsImmediate(HConstant* constant, HInstruction*
return IsUint<8>(value);
}
+ // Code generation for Min/Max:
+ // Cmp left_op, right_op
+ // Csel dst, left_op, right_op, cond
+ if (instr->IsMin() || instr->IsMax()) {
+ if (constant->GetUses().HasExactlyOneElement()) {
+ // If value can be encoded as immediate for the Cmp, then let VIXL handle
+ // the constant generation for the Csel.
+ return AddSubCanEncodeAsImmediate(value);
+ }
+ // These values are encodable as immediates for Cmp and VIXL will use csinc and csinv
+ // with the zr register as right_op, hence no constant generation is required.
+ return constant->IsZeroBitPattern() || constant->IsOne() || constant->IsMinusOne();
+ }
+
// For single uses we let VIXL handle the constant generation since it will
// use registers that are not managed by the register allocator (wip0, wip1).
if (constant->GetUses().HasExactlyOneElement()) {
@@ -275,10 +296,7 @@ inline bool Arm64CanEncodeConstantAsImmediate(HConstant* constant, HInstruction*
instr->IsSub())
<< instr->DebugName();
// Uses aliases of ADD/SUB instructions.
- // If `value` does not fit but `-value` does, VIXL will automatically use
- // the 'opposite' instruction.
- return vixl::aarch64::Assembler::IsImmAddSub(value)
- || vixl::aarch64::Assembler::IsImmAddSub(-value);
+ return AddSubCanEncodeAsImmediate(value);
}
}
diff --git a/compiler/optimizing/gvn.cc b/compiler/optimizing/gvn.cc
index 4863718518..e6b6326726 100644
--- a/compiler/optimizing/gvn.cc
+++ b/compiler/optimizing/gvn.cc
@@ -479,7 +479,10 @@ void GlobalValueNumberer::VisitBasicBlock(HBasicBlock* block) {
HInstruction* next = current->GetNext();
// Do not kill the set with the side effects of the instruction just now: if
// the instruction is GVN'ed, we don't need to kill.
- if (current->CanBeMoved()) {
+ //
+ // BoundType is a special case example of an instruction which shouldn't be moved but can be
+ // GVN'ed.
+ if (current->CanBeMoved() || current->IsBoundType()) {
if (current->IsBinaryOperation() && current->AsBinaryOperation()->IsCommutative()) {
// For commutative ops, (x op y) will be treated the same as (y op x)
// after fixed ordering.
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index ef8a757ad0..661f66a34c 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2786,6 +2786,14 @@ void HInstruction::SetReferenceTypeInfo(ReferenceTypeInfo rti) {
SetPackedFlag<kFlagReferenceTypeIsExact>(rti.IsExact());
}
+bool HBoundType::InstructionDataEquals(const HInstruction* other) const {
+ const HBoundType* other_bt = other->AsBoundType();
+ ScopedObjectAccess soa(Thread::Current());
+ return GetUpperBound().IsEqual(other_bt->GetUpperBound()) &&
+ GetUpperCanBeNull() == other_bt->GetUpperCanBeNull() &&
+ CanBeNull() == other_bt->CanBeNull();
+}
+
void HBoundType::SetUpperBound(const ReferenceTypeInfo& upper_bound, bool can_be_null) {
if (kIsDebugBuild) {
ScopedObjectAccess soa(Thread::Current());
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 2037879726..975ad1c324 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -7142,6 +7142,7 @@ class HBoundType FINAL : public HExpression<1> {
SetRawInputAt(0, input);
}
+ bool InstructionDataEquals(const HInstruction* other) const OVERRIDE;
bool IsClonable() const OVERRIDE { return true; }
// {Get,Set}Upper* should only be used in reference type propagation.
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index 094b75de69..58a35dde8e 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -31,11 +31,12 @@ namespace art {
constexpr static bool kVerifyStackMaps = kIsDebugBuild;
uint32_t StackMapStream::GetStackMapNativePcOffset(size_t i) {
- return StackMap::UnpackNativePc(stack_maps_[i].packed_native_pc, instruction_set_);
+ return StackMap::UnpackNativePc(stack_maps_[i][StackMap::kPackedNativePc], instruction_set_);
}
void StackMapStream::SetStackMapNativePcOffset(size_t i, uint32_t native_pc_offset) {
- stack_maps_[i].packed_native_pc = StackMap::PackNativePc(native_pc_offset, instruction_set_);
+ stack_maps_[i][StackMap::kPackedNativePc] =
+ StackMap::PackNativePc(native_pc_offset, instruction_set_);
}
void StackMapStream::BeginStackMapEntry(uint32_t dex_pc,
@@ -43,7 +44,8 @@ void StackMapStream::BeginStackMapEntry(uint32_t dex_pc,
uint32_t register_mask,
BitVector* stack_mask,
uint32_t num_dex_registers,
- uint8_t inlining_depth) {
+ uint8_t inlining_depth,
+ StackMap::Kind kind) {
DCHECK(!in_stack_map_) << "Mismatched Begin/End calls";
in_stack_map_ = true;
// num_dex_registers_ is the constant per-method number of registers.
@@ -54,19 +56,17 @@ void StackMapStream::BeginStackMapEntry(uint32_t dex_pc,
DCHECK_EQ(num_dex_registers_, num_dex_registers) << "Inconsistent register count";
}
- current_stack_map_ = StackMapEntry {
- .packed_native_pc = StackMap::PackNativePc(native_pc_offset, instruction_set_),
- .dex_pc = dex_pc,
- .register_mask_index = kNoValue,
- .stack_mask_index = kNoValue,
- .inline_info_index = kNoValue,
- .dex_register_mask_index = kNoValue,
- .dex_register_map_index = kNoValue,
- };
+ current_stack_map_ = BitTableBuilder<StackMap::kCount>::Entry();
+ current_stack_map_[StackMap::kKind] = static_cast<uint32_t>(kind);
+ current_stack_map_[StackMap::kPackedNativePc] =
+ StackMap::PackNativePc(native_pc_offset, instruction_set_);
+ current_stack_map_[StackMap::kDexPc] = dex_pc;
if (register_mask != 0) {
uint32_t shift = LeastSignificantBit(register_mask);
- RegisterMaskEntry entry = { register_mask >> shift, shift };
- current_stack_map_.register_mask_index = register_masks_.Dedup(&entry);
+ BitTableBuilder<RegisterMask::kCount>::Entry entry;
+ entry[RegisterMask::kValue] = register_mask >> shift;
+ entry[RegisterMask::kShift] = shift;
+ current_stack_map_[StackMap::kRegisterMaskIndex] = register_masks_.Dedup(&entry);
}
// The compiler assumes the bit vector will be read during PrepareForFillIn(),
// and it might modify the data before that. Therefore, just store the pointer.
@@ -81,8 +81,17 @@ void StackMapStream::BeginStackMapEntry(uint32_t dex_pc,
// Create lambda method, which will be executed at the very end to verify data.
// Parameters and local variables will be captured(stored) by the lambda "[=]".
dchecks_.emplace_back([=](const CodeInfo& code_info) {
+ if (kind == StackMap::Kind::Default || kind == StackMap::Kind::OSR) {
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset,
+ instruction_set_);
+ CHECK_EQ(stack_map.Row(), stack_map_index);
+ } else if (kind == StackMap::Kind::Catch) {
+ StackMap stack_map = code_info.GetCatchStackMapForDexPc(dex_pc);
+ CHECK_EQ(stack_map.Row(), stack_map_index);
+ }
StackMap stack_map = code_info.GetStackMapAt(stack_map_index);
CHECK_EQ(stack_map.GetNativePcOffset(instruction_set_), native_pc_offset);
+ CHECK_EQ(stack_map.GetKind(), static_cast<uint32_t>(kind));
CHECK_EQ(stack_map.GetDexPc(), dex_pc);
CHECK_EQ(code_info.GetRegisterMaskOf(stack_map), register_mask);
BitMemoryRegion seen_stack_mask = code_info.GetStackMaskOf(stack_map);
@@ -103,8 +112,8 @@ void StackMapStream::EndStackMapEntry() {
// Generate index into the InlineInfo table.
if (!current_inline_infos_.empty()) {
- current_inline_infos_.back().is_last = InlineInfo::kLast;
- current_stack_map_.inline_info_index =
+ current_inline_infos_.back()[InlineInfo::kIsLast] = InlineInfo::kLast;
+ current_stack_map_[StackMap::kInlineInfoIndex] =
inline_infos_.Dedup(current_inline_infos_.data(), current_inline_infos_.size());
}
@@ -114,18 +123,14 @@ void StackMapStream::EndStackMapEntry() {
stack_maps_.Add(current_stack_map_);
}
-void StackMapStream::AddDexRegisterEntry(DexRegisterLocation::Kind kind, int32_t value) {
- current_dex_registers_.push_back(DexRegisterLocation(kind, value));
-}
-
void StackMapStream::AddInvoke(InvokeType invoke_type, uint32_t dex_method_index) {
- uint32_t packed_native_pc = current_stack_map_.packed_native_pc;
+ uint32_t packed_native_pc = current_stack_map_[StackMap::kPackedNativePc];
size_t invoke_info_index = invoke_infos_.size();
- invoke_infos_.Add(InvokeInfoEntry {
- .packed_native_pc = packed_native_pc,
- .invoke_type = invoke_type,
- .method_info_index = method_infos_.Dedup(&dex_method_index),
- });
+ BitTableBuilder<InvokeInfo::kCount>::Entry entry;
+ entry[InvokeInfo::kPackedNativePc] = packed_native_pc;
+ entry[InvokeInfo::kInvokeType] = invoke_type;
+ entry[InvokeInfo::kMethodInfoIndex] = method_infos_.Dedup({dex_method_index});
+ invoke_infos_.Add(entry);
if (kVerifyStackMaps) {
dchecks_.emplace_back([=](const CodeInfo& code_info) {
@@ -133,7 +138,7 @@ void StackMapStream::AddInvoke(InvokeType invoke_type, uint32_t dex_method_index
CHECK_EQ(invoke_info.GetNativePcOffset(instruction_set_),
StackMap::UnpackNativePc(packed_native_pc, instruction_set_));
CHECK_EQ(invoke_info.GetInvokeType(), invoke_type);
- CHECK_EQ(method_infos_[invoke_info.GetMethodInfoIndex()], dex_method_index);
+ CHECK_EQ(method_infos_[invoke_info.GetMethodInfoIndex()][0], dex_method_index);
});
}
}
@@ -148,24 +153,20 @@ void StackMapStream::BeginInlineInfoEntry(ArtMethod* method,
expected_num_dex_registers_ += num_dex_registers;
- InlineInfoEntry entry = {
- .is_last = InlineInfo::kMore,
- .dex_pc = dex_pc,
- .method_info_index = kNoValue,
- .art_method_hi = kNoValue,
- .art_method_lo = kNoValue,
- .num_dex_registers = static_cast<uint32_t>(expected_num_dex_registers_),
- };
+ BitTableBuilder<InlineInfo::kCount>::Entry entry;
+ entry[InlineInfo::kIsLast] = InlineInfo::kMore;
+ entry[InlineInfo::kDexPc] = dex_pc;
+ entry[InlineInfo::kNumberOfDexRegisters] = static_cast<uint32_t>(expected_num_dex_registers_);
if (EncodeArtMethodInInlineInfo(method)) {
- entry.art_method_hi = High32Bits(reinterpret_cast<uintptr_t>(method));
- entry.art_method_lo = Low32Bits(reinterpret_cast<uintptr_t>(method));
+ entry[InlineInfo::kArtMethodHi] = High32Bits(reinterpret_cast<uintptr_t>(method));
+ entry[InlineInfo::kArtMethodLo] = Low32Bits(reinterpret_cast<uintptr_t>(method));
} else {
if (dex_pc != static_cast<uint32_t>(-1) && kIsDebugBuild) {
ScopedObjectAccess soa(Thread::Current());
DCHECK(IsSameDexFile(*outer_dex_file, *method->GetDexFile()));
}
uint32_t dex_method_index = method->GetDexMethodIndexUnchecked();
- entry.method_info_index = method_infos_.Dedup(&dex_method_index);
+ entry[InlineInfo::kMethodInfoIndex] = method_infos_.Dedup({dex_method_index});
}
current_inline_infos_.push_back(entry);
@@ -181,7 +182,7 @@ void StackMapStream::BeginInlineInfoEntry(ArtMethod* method,
if (encode_art_method) {
CHECK_EQ(inline_info.GetArtMethod(), method);
} else {
- CHECK_EQ(method_infos_[inline_info.GetMethodInfoIndex()],
+ CHECK_EQ(method_infos_[inline_info.GetMethodInfoIndex()][0],
method->GetDexMethodIndexUnchecked());
}
});
@@ -214,13 +215,13 @@ void StackMapStream::CreateDexRegisterMap() {
// Distance is difference between this index and the index of last modification.
uint32_t distance = stack_maps_.size() - dex_register_timestamp_[i];
if (previous_dex_registers_[i] != reg || distance > kMaxDexRegisterMapSearchDistance) {
- DexRegisterEntry entry = DexRegisterEntry{
- .kind = static_cast<uint32_t>(reg.GetKind()),
- .packed_value = DexRegisterInfo::PackValue(reg.GetKind(), reg.GetValue()),
- };
+ BitTableBuilder<DexRegisterInfo::kCount>::Entry entry;
+ entry[DexRegisterInfo::kKind] = static_cast<uint32_t>(reg.GetKind());
+ entry[DexRegisterInfo::kPackedValue] =
+ DexRegisterInfo::PackValue(reg.GetKind(), reg.GetValue());
uint32_t index = reg.IsLive() ? dex_register_catalog_.Dedup(&entry) : kNoValue;
temp_dex_register_mask_.SetBit(i);
- temp_dex_register_map_.push_back(index);
+ temp_dex_register_map_.push_back({index});
previous_dex_registers_[i] = reg;
dex_register_timestamp_[i] = stack_maps_.size();
}
@@ -228,12 +229,12 @@ void StackMapStream::CreateDexRegisterMap() {
// Set the mask and map for the current StackMap (which includes inlined registers).
if (temp_dex_register_mask_.GetNumberOfBits() != 0) {
- current_stack_map_.dex_register_mask_index =
+ current_stack_map_[StackMap::kDexRegisterMaskIndex] =
dex_register_masks_.Dedup(temp_dex_register_mask_.GetRawStorage(),
temp_dex_register_mask_.GetNumberOfBits());
}
if (!current_dex_registers_.empty()) {
- current_stack_map_.dex_register_map_index =
+ current_stack_map_[StackMap::kDexRegisterMapIndex] =
dex_register_maps_.Dedup(temp_dex_register_map_.data(),
temp_dex_register_map_.size());
}
@@ -264,7 +265,7 @@ void StackMapStream::FillInMethodInfo(MemoryRegion region) {
{
MethodInfo info(region.begin(), method_infos_.size());
for (size_t i = 0; i < method_infos_.size(); ++i) {
- info.SetMethodIndex(i, method_infos_[i]);
+ info.SetMethodIndex(i, method_infos_[i][0]);
}
}
if (kVerifyStackMaps) {
@@ -273,23 +274,19 @@ void StackMapStream::FillInMethodInfo(MemoryRegion region) {
const size_t count = info.NumMethodIndices();
DCHECK_EQ(count, method_infos_.size());
for (size_t i = 0; i < count; ++i) {
- DCHECK_EQ(info.GetMethodIndex(i), method_infos_[i]);
+ DCHECK_EQ(info.GetMethodIndex(i), method_infos_[i][0]);
}
}
}
size_t StackMapStream::PrepareForFillIn() {
- static_assert(sizeof(StackMapEntry) == StackMap::kCount * sizeof(uint32_t), "Layout");
- static_assert(sizeof(InvokeInfoEntry) == InvokeInfo::kCount * sizeof(uint32_t), "Layout");
- static_assert(sizeof(InlineInfoEntry) == InlineInfo::kCount * sizeof(uint32_t), "Layout");
- static_assert(sizeof(DexRegisterEntry) == DexRegisterInfo::kCount * sizeof(uint32_t), "Layout");
DCHECK_EQ(out_.size(), 0u);
// Read the stack masks now. The compiler might have updated them.
for (size_t i = 0; i < lazy_stack_masks_.size(); i++) {
BitVector* stack_mask = lazy_stack_masks_[i];
if (stack_mask != nullptr && stack_mask->GetNumberOfBits() != 0) {
- stack_maps_[i].stack_mask_index =
+ stack_maps_[i][StackMap::kStackMaskIndex] =
stack_masks_.Dedup(stack_mask->GetRawStorage(), stack_mask->GetNumberOfBits());
}
}
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index 02fb6cb434..6842d9fd7e 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -27,11 +27,10 @@
#include "dex_register_location.h"
#include "method_info.h"
#include "nodes.h"
+#include "stack_map.h"
namespace art {
-class CodeInfo;
-
/**
* Collects and builds stack maps for a method. All the stack maps
* for a method are placed in a CodeInfo object.
@@ -53,6 +52,7 @@ class StackMapStream : public ValueObject {
lazy_stack_masks_(allocator->Adapter(kArenaAllocStackMapStream)),
in_stack_map_(false),
in_inline_info_(false),
+ current_stack_map_(),
current_inline_infos_(allocator->Adapter(kArenaAllocStackMapStream)),
current_dex_registers_(allocator->Adapter(kArenaAllocStackMapStream)),
previous_dex_registers_(allocator->Adapter(kArenaAllocStackMapStream)),
@@ -66,10 +66,13 @@ class StackMapStream : public ValueObject {
uint32_t register_mask,
BitVector* sp_mask,
uint32_t num_dex_registers,
- uint8_t inlining_depth);
+ uint8_t inlining_depth,
+ StackMap::Kind kind = StackMap::Kind::Default);
void EndStackMapEntry();
- void AddDexRegisterEntry(DexRegisterLocation::Kind kind, int32_t value);
+ void AddDexRegisterEntry(DexRegisterLocation::Kind kind, int32_t value) {
+ current_dex_registers_.push_back(DexRegisterLocation(kind, value));
+ }
void AddInvoke(InvokeType type, uint32_t dex_method_index);
@@ -97,69 +100,29 @@ class StackMapStream : public ValueObject {
private:
static constexpr uint32_t kNoValue = -1;
- // The fields must be uint32_t and mirror the StackMap accessor in stack_map.h!
- struct StackMapEntry {
- uint32_t packed_native_pc;
- uint32_t dex_pc;
- uint32_t register_mask_index;
- uint32_t stack_mask_index;
- uint32_t inline_info_index;
- uint32_t dex_register_mask_index;
- uint32_t dex_register_map_index;
- };
-
- // The fields must be uint32_t and mirror the InlineInfo accessor in stack_map.h!
- struct InlineInfoEntry {
- uint32_t is_last;
- uint32_t dex_pc;
- uint32_t method_info_index;
- uint32_t art_method_hi;
- uint32_t art_method_lo;
- uint32_t num_dex_registers;
- };
-
- // The fields must be uint32_t and mirror the InvokeInfo accessor in stack_map.h!
- struct InvokeInfoEntry {
- uint32_t packed_native_pc;
- uint32_t invoke_type;
- uint32_t method_info_index;
- };
-
- // The fields must be uint32_t and mirror the DexRegisterInfo accessor in stack_map.h!
- struct DexRegisterEntry {
- uint32_t kind;
- uint32_t packed_value;
- };
-
- // The fields must be uint32_t and mirror the RegisterMask accessor in stack_map.h!
- struct RegisterMaskEntry {
- uint32_t value;
- uint32_t shift;
- };
-
void CreateDexRegisterMap();
const InstructionSet instruction_set_;
- BitTableBuilder<StackMapEntry> stack_maps_;
- BitTableBuilder<RegisterMaskEntry> register_masks_;
+ BitTableBuilder<StackMap::kCount> stack_maps_;
+ BitTableBuilder<RegisterMask::kCount> register_masks_;
BitmapTableBuilder stack_masks_;
- BitTableBuilder<InvokeInfoEntry> invoke_infos_;
- BitTableBuilder<InlineInfoEntry> inline_infos_;
+ BitTableBuilder<InvokeInfo::kCount> invoke_infos_;
+ BitTableBuilder<InlineInfo::kCount> inline_infos_;
BitmapTableBuilder dex_register_masks_;
- BitTableBuilder<uint32_t> dex_register_maps_;
- BitTableBuilder<DexRegisterEntry> dex_register_catalog_;
+ BitTableBuilder<MaskInfo::kCount> dex_register_maps_;
+ BitTableBuilder<DexRegisterInfo::kCount> dex_register_catalog_;
uint32_t num_dex_registers_ = 0; // TODO: Make this const and get the value in constructor.
ScopedArenaVector<uint8_t> out_;
- BitTableBuilder<uint32_t> method_infos_;
+ BitTableBuilder<1> method_infos_;
ScopedArenaVector<BitVector*> lazy_stack_masks_;
// Variables which track the current state between Begin/End calls;
bool in_stack_map_;
bool in_inline_info_;
- StackMapEntry current_stack_map_;
- ScopedArenaVector<InlineInfoEntry> current_inline_infos_;
+ BitTableBuilder<StackMap::kCount>::Entry current_stack_map_;
+ ScopedArenaVector<BitTableBuilder<InlineInfo::kCount>::Entry> current_inline_infos_;
ScopedArenaVector<DexRegisterLocation> current_dex_registers_;
ScopedArenaVector<DexRegisterLocation> previous_dex_registers_;
ScopedArenaVector<uint32_t> dex_register_timestamp_; // Stack map index of last change.
@@ -168,7 +131,7 @@ class StackMapStream : public ValueObject {
// Temporary variables used in CreateDexRegisterMap.
// They are here so that we can reuse the reserved memory.
ArenaBitVector temp_dex_register_mask_;
- ScopedArenaVector<uint32_t> temp_dex_register_map_;
+ ScopedArenaVector<BitTableBuilder<DexRegisterMapInfo::kCount>::Entry> temp_dex_register_map_;
// A set of lambda functions to be executed at the end to verify
// the encoded data. It is generally only used in debug builds.
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index 9adc4c5ba6..fd856671ba 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -83,14 +83,14 @@ TEST(StackMapTest, Test1) {
ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(stack_map);
ASSERT_EQ(number_of_dex_registers, dex_register_map.size());
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
+ ASSERT_TRUE(dex_register_map[0].IsLive());
+ ASSERT_TRUE(dex_register_map[1].IsLive());
ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters());
- ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(0));
- ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(1));
- ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(0));
- ASSERT_EQ(-2, dex_register_map.GetConstant(1));
+ ASSERT_EQ(Kind::kInStack, dex_register_map[0].GetKind());
+ ASSERT_EQ(Kind::kConstant, dex_register_map[1].GetKind());
+ ASSERT_EQ(0, dex_register_map[0].GetStackOffsetInBytes());
+ ASSERT_EQ(-2, dex_register_map[1].GetConstant());
DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(0);
DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(1);
@@ -172,14 +172,14 @@ TEST(StackMapTest, Test2) {
ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(stack_map);
ASSERT_EQ(number_of_dex_registers, dex_register_map.size());
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
+ ASSERT_TRUE(dex_register_map[0].IsLive());
+ ASSERT_TRUE(dex_register_map[1].IsLive());
ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters());
- ASSERT_EQ(Kind::kInStack, dex_register_map.GetLocationKind(0));
- ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(1));
- ASSERT_EQ(0, dex_register_map.GetStackOffsetInBytes(0));
- ASSERT_EQ(-2, dex_register_map.GetConstant(1));
+ ASSERT_EQ(Kind::kInStack, dex_register_map[0].GetKind());
+ ASSERT_EQ(Kind::kConstant, dex_register_map[1].GetKind());
+ ASSERT_EQ(0, dex_register_map[0].GetStackOffsetInBytes());
+ ASSERT_EQ(-2, dex_register_map[1].GetConstant());
DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(0);
DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(1);
@@ -212,14 +212,14 @@ TEST(StackMapTest, Test2) {
ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(stack_map);
ASSERT_EQ(number_of_dex_registers, dex_register_map.size());
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
+ ASSERT_TRUE(dex_register_map[0].IsLive());
+ ASSERT_TRUE(dex_register_map[1].IsLive());
ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters());
- ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(0));
- ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(1));
- ASSERT_EQ(18, dex_register_map.GetMachineRegister(0));
- ASSERT_EQ(3, dex_register_map.GetMachineRegister(1));
+ ASSERT_EQ(Kind::kInRegister, dex_register_map[0].GetKind());
+ ASSERT_EQ(Kind::kInFpuRegister, dex_register_map[1].GetKind());
+ ASSERT_EQ(18, dex_register_map[0].GetMachineRegister());
+ ASSERT_EQ(3, dex_register_map[1].GetMachineRegister());
DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(2);
DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(3);
@@ -245,14 +245,14 @@ TEST(StackMapTest, Test2) {
ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(stack_map);
ASSERT_EQ(number_of_dex_registers, dex_register_map.size());
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
+ ASSERT_TRUE(dex_register_map[0].IsLive());
+ ASSERT_TRUE(dex_register_map[1].IsLive());
ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters());
- ASSERT_EQ(Kind::kInRegister, dex_register_map.GetLocationKind(0));
- ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map.GetLocationKind(1));
- ASSERT_EQ(6, dex_register_map.GetMachineRegister(0));
- ASSERT_EQ(8, dex_register_map.GetMachineRegister(1));
+ ASSERT_EQ(Kind::kInRegister, dex_register_map[0].GetKind());
+ ASSERT_EQ(Kind::kInRegisterHigh, dex_register_map[1].GetKind());
+ ASSERT_EQ(6, dex_register_map[0].GetMachineRegister());
+ ASSERT_EQ(8, dex_register_map[1].GetMachineRegister());
DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(4);
DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(5);
@@ -278,14 +278,14 @@ TEST(StackMapTest, Test2) {
ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(stack_map);
ASSERT_EQ(number_of_dex_registers, dex_register_map.size());
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(0));
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
+ ASSERT_TRUE(dex_register_map[0].IsLive());
+ ASSERT_TRUE(dex_register_map[1].IsLive());
ASSERT_EQ(2u, dex_register_map.GetNumberOfLiveDexRegisters());
- ASSERT_EQ(Kind::kInFpuRegister, dex_register_map.GetLocationKind(0));
- ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map.GetLocationKind(1));
- ASSERT_EQ(3, dex_register_map.GetMachineRegister(0));
- ASSERT_EQ(1, dex_register_map.GetMachineRegister(1));
+ ASSERT_EQ(Kind::kInFpuRegister, dex_register_map[0].GetKind());
+ ASSERT_EQ(Kind::kInFpuRegisterHigh, dex_register_map[1].GetKind());
+ ASSERT_EQ(3, dex_register_map[0].GetMachineRegister());
+ ASSERT_EQ(1, dex_register_map[1].GetMachineRegister());
DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(3);
DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(6);
@@ -344,14 +344,14 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) {
ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap map(code_info.GetDexRegisterMapOf(stack_map));
ASSERT_EQ(number_of_dex_registers, map.size());
- ASSERT_TRUE(map.IsDexRegisterLive(0));
- ASSERT_TRUE(map.IsDexRegisterLive(1));
+ ASSERT_TRUE(map[0].IsLive());
+ ASSERT_TRUE(map[1].IsLive());
ASSERT_EQ(2u, map.GetNumberOfLiveDexRegisters());
- ASSERT_EQ(Kind::kInStack, map.GetLocationKind(0));
- ASSERT_EQ(Kind::kConstant, map.GetLocationKind(1));
- ASSERT_EQ(0, map.GetStackOffsetInBytes(0));
- ASSERT_EQ(-2, map.GetConstant(1));
+ ASSERT_EQ(Kind::kInStack, map[0].GetKind());
+ ASSERT_EQ(Kind::kConstant, map[1].GetKind());
+ ASSERT_EQ(0, map[0].GetStackOffsetInBytes());
+ ASSERT_EQ(-2, map[1].GetConstant());
DexRegisterLocation location0 = code_info.GetDexRegisterCatalogEntry(0);
DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(1);
@@ -396,13 +396,13 @@ TEST(StackMapTest, TestNonLiveDexRegisters) {
ASSERT_TRUE(stack_map.HasDexRegisterMap());
DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(stack_map);
ASSERT_EQ(number_of_dex_registers, dex_register_map.size());
- ASSERT_FALSE(dex_register_map.IsDexRegisterLive(0));
- ASSERT_TRUE(dex_register_map.IsDexRegisterLive(1));
+ ASSERT_FALSE(dex_register_map[0].IsLive());
+ ASSERT_TRUE(dex_register_map[1].IsLive());
ASSERT_EQ(1u, dex_register_map.GetNumberOfLiveDexRegisters());
- ASSERT_EQ(Kind::kNone, dex_register_map.GetLocationKind(0));
- ASSERT_EQ(Kind::kConstant, dex_register_map.GetLocationKind(1));
- ASSERT_EQ(-2, dex_register_map.GetConstant(1));
+ ASSERT_EQ(Kind::kNone, dex_register_map[0].GetKind());
+ ASSERT_EQ(Kind::kConstant, dex_register_map[1].GetKind());
+ ASSERT_EQ(-2, dex_register_map[1].GetConstant());
DexRegisterLocation location1 = code_info.GetDexRegisterCatalogEntry(0);
ASSERT_EQ(Kind::kConstant, location1.GetKind());
@@ -425,12 +425,12 @@ TEST(StackMapTest, TestShareDexRegisterMap) {
stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
stream.EndStackMapEntry();
// Second stack map, which should share the same dex register map.
- stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(0, 65 * kPcAlign, 0x3, &sp_mask, number_of_dex_registers, 0);
stream.AddDexRegisterEntry(Kind::kInRegister, 0); // Short location.
stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
stream.EndStackMapEntry();
// Third stack map (doesn't share the dex register map).
- stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask, number_of_dex_registers, 0);
+ stream.BeginStackMapEntry(0, 66 * kPcAlign, 0x3, &sp_mask, number_of_dex_registers, 0);
stream.AddDexRegisterEntry(Kind::kInRegister, 2); // Short location.
stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location.
stream.EndStackMapEntry();
@@ -446,22 +446,22 @@ TEST(StackMapTest, TestShareDexRegisterMap) {
StackMap sm0 = ci.GetStackMapAt(0);
DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0);
ASSERT_EQ(number_of_dex_registers, dex_registers0.size());
- ASSERT_EQ(0, dex_registers0.GetMachineRegister(0));
- ASSERT_EQ(-2, dex_registers0.GetConstant(1));
+ ASSERT_EQ(0, dex_registers0[0].GetMachineRegister());
+ ASSERT_EQ(-2, dex_registers0[1].GetConstant());
// Verify second stack map.
StackMap sm1 = ci.GetStackMapAt(1);
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapOf(sm1);
ASSERT_EQ(number_of_dex_registers, dex_registers1.size());
- ASSERT_EQ(0, dex_registers1.GetMachineRegister(0));
- ASSERT_EQ(-2, dex_registers1.GetConstant(1));
+ ASSERT_EQ(0, dex_registers1[0].GetMachineRegister());
+ ASSERT_EQ(-2, dex_registers1[1].GetConstant());
// Verify third stack map.
StackMap sm2 = ci.GetStackMapAt(2);
DexRegisterMap dex_registers2 = ci.GetDexRegisterMapOf(sm2);
ASSERT_EQ(number_of_dex_registers, dex_registers2.size());
- ASSERT_EQ(2, dex_registers2.GetMachineRegister(0));
- ASSERT_EQ(-2, dex_registers2.GetConstant(1));
+ ASSERT_EQ(2, dex_registers2[0].GetMachineRegister());
+ ASSERT_EQ(-2, dex_registers2[1].GetConstant());
// Verify dex register mask offsets.
ASSERT_FALSE(sm1.HasDexRegisterMaskIndex()); // No delta.
@@ -528,7 +528,7 @@ TEST(StackMapTest, InlineTest) {
sp_mask1.SetBit(4);
// First stack map.
- stream.BeginStackMapEntry(0, 64 * kPcAlign, 0x3, &sp_mask1, 2, 2);
+ stream.BeginStackMapEntry(0, 10 * kPcAlign, 0x3, &sp_mask1, 2, 2);
stream.AddDexRegisterEntry(Kind::kInStack, 0);
stream.AddDexRegisterEntry(Kind::kConstant, 4);
@@ -597,8 +597,8 @@ TEST(StackMapTest, InlineTest) {
DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0);
ASSERT_EQ(2u, dex_registers0.size());
- ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0));
- ASSERT_EQ(4, dex_registers0.GetConstant(1));
+ ASSERT_EQ(0, dex_registers0[0].GetStackOffsetInBytes());
+ ASSERT_EQ(4, dex_registers0[1].GetConstant());
InlineInfo if0_0 = ci.GetInlineInfoAtDepth(sm0, 0);
InlineInfo if0_1 = ci.GetInlineInfoAtDepth(sm0, 1);
@@ -610,13 +610,13 @@ TEST(StackMapTest, InlineTest) {
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, sm0);
ASSERT_EQ(1u, dex_registers1.size());
- ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0));
+ ASSERT_EQ(8, dex_registers1[0].GetStackOffsetInBytes());
DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, sm0);
ASSERT_EQ(3u, dex_registers2.size());
- ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0));
- ASSERT_EQ(20, dex_registers2.GetConstant(1));
- ASSERT_EQ(15, dex_registers2.GetMachineRegister(2));
+ ASSERT_EQ(16, dex_registers2[0].GetStackOffsetInBytes());
+ ASSERT_EQ(20, dex_registers2[1].GetConstant());
+ ASSERT_EQ(15, dex_registers2[2].GetMachineRegister());
}
{
@@ -625,8 +625,8 @@ TEST(StackMapTest, InlineTest) {
DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm1);
ASSERT_EQ(2u, dex_registers0.size());
- ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0));
- ASSERT_EQ(0, dex_registers0.GetConstant(1));
+ ASSERT_EQ(56, dex_registers0[0].GetStackOffsetInBytes());
+ ASSERT_EQ(0, dex_registers0[1].GetConstant());
InlineInfo if1_0 = ci.GetInlineInfoAtDepth(sm1, 0);
InlineInfo if1_1 = ci.GetInlineInfoAtDepth(sm1, 1);
@@ -641,13 +641,13 @@ TEST(StackMapTest, InlineTest) {
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, sm1);
ASSERT_EQ(1u, dex_registers1.size());
- ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0));
+ ASSERT_EQ(12, dex_registers1[0].GetStackOffsetInBytes());
DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, sm1);
ASSERT_EQ(3u, dex_registers2.size());
- ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0));
- ASSERT_EQ(10, dex_registers2.GetConstant(1));
- ASSERT_EQ(5, dex_registers2.GetMachineRegister(2));
+ ASSERT_EQ(80, dex_registers2[0].GetStackOffsetInBytes());
+ ASSERT_EQ(10, dex_registers2[1].GetConstant());
+ ASSERT_EQ(5, dex_registers2[2].GetMachineRegister());
}
{
@@ -656,8 +656,8 @@ TEST(StackMapTest, InlineTest) {
DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2);
ASSERT_EQ(2u, dex_registers0.size());
- ASSERT_FALSE(dex_registers0.IsDexRegisterLive(0));
- ASSERT_EQ(4, dex_registers0.GetConstant(1));
+ ASSERT_FALSE(dex_registers0[0].IsLive());
+ ASSERT_EQ(4, dex_registers0[1].GetConstant());
ASSERT_FALSE(sm2.HasInlineInfo());
}
@@ -667,8 +667,8 @@ TEST(StackMapTest, InlineTest) {
DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm3);
ASSERT_EQ(2u, dex_registers0.size());
- ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0));
- ASSERT_EQ(0, dex_registers0.GetConstant(1));
+ ASSERT_EQ(56, dex_registers0[0].GetStackOffsetInBytes());
+ ASSERT_EQ(0, dex_registers0[1].GetConstant());
InlineInfo if2_0 = ci.GetInlineInfoAtDepth(sm3, 0);
InlineInfo if2_1 = ci.GetInlineInfoAtDepth(sm3, 1);
@@ -683,12 +683,12 @@ TEST(StackMapTest, InlineTest) {
DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, sm3);
ASSERT_EQ(1u, dex_registers1.size());
- ASSERT_EQ(2, dex_registers1.GetMachineRegister(0));
+ ASSERT_EQ(2, dex_registers1[0].GetMachineRegister());
DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, sm3);
ASSERT_EQ(2u, dex_registers2.size());
- ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0));
- ASSERT_EQ(3, dex_registers2.GetMachineRegister(1));
+ ASSERT_FALSE(dex_registers2[0].IsLive());
+ ASSERT_EQ(3, dex_registers2[1].GetMachineRegister());
}
}
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc
index 2b4144c611..3f5dbcfce5 100644
--- a/dexlayout/compact_dex_writer.cc
+++ b/dexlayout/compact_dex_writer.cc
@@ -59,8 +59,8 @@ uint32_t CompactDexWriter::WriteDebugInfoOffsetTable(Stream* stream) {
for (auto& method : *(invoke_type == InvokeType::kDirect
? class_data->DirectMethods()
: class_data->VirtualMethods())) {
- const dex_ir::MethodId* method_id = method->GetMethodId();
- dex_ir::CodeItem* code_item = method->GetCodeItem();
+ const dex_ir::MethodId* method_id = method.GetMethodId();
+ dex_ir::CodeItem* code_item = method.GetCodeItem();
if (code_item != nullptr && code_item->DebugInfo() != nullptr) {
const uint32_t debug_info_offset = code_item->DebugInfo()->GetOffset();
const uint32_t method_idx = method_id->GetIndex();
@@ -248,8 +248,8 @@ void CompactDexWriter::SortDebugInfosByMethodIndex() {
for (auto& method : *(invoke_type == InvokeType::kDirect
? class_data->DirectMethods()
: class_data->VirtualMethods())) {
- const dex_ir::MethodId* method_id = method->GetMethodId();
- dex_ir::CodeItem* code_item = method->GetCodeItem();
+ const dex_ir::MethodId* method_id = method.GetMethodId();
+ dex_ir::CodeItem* code_item = method.GetCodeItem();
if (code_item != nullptr && code_item->DebugInfo() != nullptr) {
const dex_ir::DebugInfoItem* debug_item = code_item->DebugInfo();
method_idx_map.insert(std::make_pair(debug_item, method_id->GetIndex()));
@@ -350,8 +350,8 @@ bool CompactDexWriter::CanGenerateCompactDex(std::string* error_msg) {
for (auto& method : *(invoke_type == InvokeType::kDirect
? class_data->DirectMethods()
: class_data->VirtualMethods())) {
- const uint32_t idx = method->GetMethodId()->GetIndex();
- dex_ir::CodeItem* code_item = method->GetCodeItem();
+ const uint32_t idx = method.GetMethodId()->GetIndex();
+ dex_ir::CodeItem* code_item = method.GetCodeItem();
dex_ir:: DebugInfoItem* debug_info_item = nullptr;
if (code_item != nullptr) {
debug_info_item = code_item->DebugInfo();
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index b7d9db6da5..15e3baf18a 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -318,17 +318,22 @@ void Collections::ReadEncodedValue(const DexFile& dex_file,
void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) {
const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i));
- StringData* string_data = new StringData(dex_file.GetStringData(disk_string_id));
- AddItem(string_datas_map_, string_datas_, string_data, disk_string_id.string_data_off_);
-
- StringId* string_id = new StringId(string_data);
- AddIndexedItem(string_ids_, string_id, StringIdsOffset() + i * StringId::ItemSize(), i);
+ StringData* string_data = CreateAndAddItem(string_datas_map_,
+ string_datas_,
+ disk_string_id.string_data_off_,
+ dex_file.GetStringData(disk_string_id));
+ CreateAndAddIndexedItem(string_ids_,
+ StringIdsOffset() + i * StringId::ItemSize(),
+ i,
+ string_data);
}
void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) {
const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i));
- TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_.index_));
- AddIndexedItem(type_ids_, type_id, TypeIdsOffset() + i * TypeId::ItemSize(), i);
+ CreateAndAddIndexedItem(type_ids_,
+ TypeIdsOffset() + i * TypeId::ItemSize(),
+ i,
+ GetStringId(disk_type_id.descriptor_idx_.index_));
}
void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
@@ -336,26 +341,32 @@ void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
- ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_.index_),
- GetTypeId(disk_proto_id.return_type_idx_.index_),
- parameter_type_list);
- AddIndexedItem(proto_ids_, proto_id, ProtoIdsOffset() + i * ProtoId::ItemSize(), i);
+ CreateAndAddIndexedItem(proto_ids_,
+ ProtoIdsOffset() + i * ProtoId::ItemSize(),
+ i,
+ GetStringId(disk_proto_id.shorty_idx_.index_),
+ GetTypeId(disk_proto_id.return_type_idx_.index_),
+ parameter_type_list);
}
void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) {
const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
- FieldId* field_id = new FieldId(GetTypeId(disk_field_id.class_idx_.index_),
- GetTypeId(disk_field_id.type_idx_.index_),
- GetStringId(disk_field_id.name_idx_.index_));
- AddIndexedItem(field_ids_, field_id, FieldIdsOffset() + i * FieldId::ItemSize(), i);
+ CreateAndAddIndexedItem(field_ids_,
+ FieldIdsOffset() + i * FieldId::ItemSize(),
+ i,
+ GetTypeId(disk_field_id.class_idx_.index_),
+ GetTypeId(disk_field_id.type_idx_.index_),
+ GetStringId(disk_field_id.name_idx_.index_));
}
void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) {
const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
- MethodId* method_id = new MethodId(GetTypeId(disk_method_id.class_idx_.index_),
- GetProtoId(disk_method_id.proto_idx_.index_),
- GetStringId(disk_method_id.name_idx_.index_));
- AddIndexedItem(method_ids_, method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i);
+ CreateAndAddIndexedItem(method_ids_,
+ MethodIdsOffset() + i * MethodId::ItemSize(),
+ i,
+ GetTypeId(disk_method_id.class_idx_.index_),
+ GetProtoId(disk_method_id.proto_idx_.index_),
+ GetStringId(disk_method_id.name_idx_.index_));
}
void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) {
@@ -382,9 +393,17 @@ void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) {
CreateEncodedArrayItem(dex_file, static_data, disk_class_def.static_values_off_);
ClassData* class_data = CreateClassData(
dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_);
- ClassDef* class_def = new ClassDef(class_type, access_flags, superclass, interfaces_type_list,
- source_file, annotations, static_values, class_data);
- AddIndexedItem(class_defs_, class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i);
+ CreateAndAddIndexedItem(class_defs_,
+ ClassDefsOffset() + i * ClassDef::ItemSize(),
+ i,
+ class_type,
+ access_flags,
+ superclass,
+ interfaces_type_list,
+ source_file,
+ annotations,
+ static_values,
+ class_data);
}
TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) {
@@ -398,8 +417,7 @@ TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, ui
for (uint32_t index = 0; index < size; ++index) {
type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_.index_));
}
- type_list = new TypeList(type_vector);
- AddItem(type_lists_map_, type_lists_, type_list, offset);
+ type_list = CreateAndAddItem(type_lists_map_, type_lists_, offset, type_vector);
}
return type_list;
}
@@ -418,8 +436,10 @@ EncodedArrayItem* Collections::CreateEncodedArrayItem(const DexFile& dex_file,
values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, &static_data)));
}
// TODO: Calculate the size of the encoded array.
- encoded_array_item = new EncodedArrayItem(values);
- AddItem(encoded_array_items_map_, encoded_array_items_, encoded_array_item, offset);
+ encoded_array_item = CreateAndAddItem(encoded_array_items_map_,
+ encoded_array_items_,
+ offset,
+ values);
}
return encoded_array_item;
}
@@ -447,9 +467,12 @@ AnnotationItem* Collections::CreateAnnotationItem(const DexFile& dex_file,
const uint8_t* annotation_data = annotation->annotation_;
std::unique_ptr<EncodedValue> encoded_value(
ReadEncodedValue(dex_file, &annotation_data, DexFile::kDexAnnotationAnnotation, 0));
- annotation_item = new AnnotationItem(visibility, encoded_value->ReleaseEncodedAnnotation());
+ annotation_item = CreateAndAddItem(annotation_items_map_,
+ annotation_items_,
+ offset,
+ visibility,
+ encoded_value->ReleaseEncodedAnnotation());
annotation_item->SetSize(annotation_data - start_data);
- AddItem(annotation_items_map_, annotation_items_, annotation_item, offset);
}
return annotation_item;
}
@@ -472,8 +495,10 @@ AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file,
AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
items->push_back(annotation_item);
}
- annotation_set_item = new AnnotationSetItem(items);
- AddItem(annotation_set_items_map_, annotation_set_items_, annotation_set_item, offset);
+ annotation_set_item = CreateAndAddItem(annotation_set_items_map_,
+ annotation_set_items_,
+ offset,
+ items);
}
return annotation_set_item;
}
@@ -538,13 +563,13 @@ AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexF
}
}
// TODO: Calculate the size of the annotations directory.
-annotations_directory_item = new AnnotationsDirectoryItem(
- class_annotation, field_annotations, method_annotations, parameter_annotations);
- AddItem(annotations_directory_items_map_,
- annotations_directory_items_,
- annotations_directory_item,
- offset);
- return annotations_directory_item;
+ return CreateAndAddItem(annotations_directory_items_map_,
+ annotations_directory_items_,
+ offset,
+ class_annotation,
+ field_annotations,
+ method_annotations,
+ parameter_annotations);
}
ParameterAnnotation* Collections::GenerateParameterAnnotation(
@@ -559,8 +584,10 @@ ParameterAnnotation* Collections::GenerateParameterAnnotation(
uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
annotations->push_back(CreateAnnotationSetItem(dex_file, annotation_set_item, set_offset));
}
- set_ref_list = new AnnotationSetRefList(annotations);
- AddItem(annotation_set_ref_lists_map_, annotation_set_ref_lists_, set_ref_list, offset);
+ set_ref_list = CreateAndAddItem(annotation_set_ref_lists_map_,
+ annotation_set_ref_lists_,
+ offset,
+ annotations);
}
return new ParameterAnnotation(method_id, set_ref_list);
}
@@ -590,8 +617,11 @@ CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file,
uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
- debug_info = new DebugInfoItem(debug_info_size, debug_info_buffer);
- AddItem(debug_info_items_map_, debug_info_items_, debug_info, debug_info_offset);
+ debug_info = CreateAndAddItem(debug_info_items_map_,
+ debug_info_items_,
+ debug_info_offset,
+ debug_info_size,
+ debug_info_buffer);
}
}
@@ -677,14 +707,14 @@ CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file,
}
uint32_t size = dex_file.GetCodeItemSize(*disk_code_item);
- CodeItem* code_item = new CodeItem(accessor.RegistersSize(),
- accessor.InsSize(),
- accessor.OutsSize(),
- debug_info,
- insns_size,
- insns,
- tries,
- handler_list);
+ CodeItem* code_item = code_items_.CreateAndAddItem(accessor.RegistersSize(),
+ accessor.InsSize(),
+ accessor.OutsSize(),
+ debug_info,
+ insns_size,
+ insns,
+ tries,
+ handler_list);
code_item->SetSize(size);
// Add the code item to the map.
@@ -693,7 +723,6 @@ CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file,
code_item->SetOffset(offset);
}
code_items_map_.emplace(offsets_pair, code_item);
- code_items_.AddItem(code_item);
// Add "fixup" references to types, strings, methods, and fields.
// This is temporary, as we will probably want more detailed parsing of the
@@ -718,7 +747,7 @@ CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file,
return code_item;
}
-MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
+MethodItem Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
MethodId* method_id = GetMethodId(cdii.GetMemberIndex());
uint32_t access_flags = cdii.GetRawMemberAccessFlags();
const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
@@ -728,7 +757,7 @@ MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataIt
disk_code_item,
cdii.GetMethodCodeItemOffset(),
cdii.GetMemberIndex());
- return new MethodItem(access_flags, method_id, code_item);
+ return MethodItem(access_flags, method_id, code_item);
}
ClassData* Collections::CreateClassData(
@@ -743,29 +772,33 @@ ClassData* Collections::CreateClassData(
for (; cdii.HasNextStaticField(); cdii.Next()) {
FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
uint32_t access_flags = cdii.GetRawMemberAccessFlags();
- static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
+ static_fields->emplace_back(access_flags, field_item);
}
// Instance fields.
FieldItemVector* instance_fields = new FieldItemVector();
for (; cdii.HasNextInstanceField(); cdii.Next()) {
FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
uint32_t access_flags = cdii.GetRawMemberAccessFlags();
- instance_fields->push_back(
- std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
+ instance_fields->emplace_back(access_flags, field_item);
}
// Direct methods.
MethodItemVector* direct_methods = new MethodItemVector();
for (; cdii.HasNextDirectMethod(); cdii.Next()) {
- direct_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
+ direct_methods->push_back(GenerateMethodItem(dex_file, cdii));
}
// Virtual methods.
MethodItemVector* virtual_methods = new MethodItemVector();
for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
- virtual_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
+ virtual_methods->push_back(GenerateMethodItem(dex_file, cdii));
}
- class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
+ class_data = CreateAndAddItem(class_datas_map_,
+ class_datas_,
+ offset,
+ static_fields,
+ instance_fields,
+ direct_methods,
+ virtual_methods);
class_data->SetSize(cdii.EndDataPointer() - encoded_data);
- AddItem(class_datas_map_, class_datas_, class_data, offset);
}
return class_data;
}
@@ -802,8 +835,10 @@ void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
EncodedArrayItem* call_site_item =
CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_);
- CallSiteId* call_site_id = new CallSiteId(call_site_item);
- AddIndexedItem(call_site_ids_, call_site_id, CallSiteIdsOffset() + i * CallSiteId::ItemSize(), i);
+ CreateAndAddIndexedItem(call_site_ids_,
+ CallSiteIdsOffset() + i * CallSiteId::ItemSize(),
+ i,
+ call_site_item);
}
void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
@@ -824,11 +859,11 @@ void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
} else {
field_or_method_id = GetFieldId(index);
}
- MethodHandleItem* method_handle = new MethodHandleItem(type, field_or_method_id);
- AddIndexedItem(method_handle_items_,
- method_handle,
- MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(),
- i);
+ CreateAndAddIndexedItem(method_handle_items_,
+ MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(),
+ i,
+ type,
+ field_or_method_id);
}
void Collections::SortVectorsByMapOrder() {
@@ -844,6 +879,19 @@ void Collections::SortVectorsByMapOrder() {
class_datas_.SortByMapOrder(class_datas_map_.Collection());
}
+void Collections::ClearMaps() {
+ string_datas_map_.Collection().clear();
+ type_lists_map_.Collection().clear();
+ encoded_array_items_map_.Collection().clear();
+ annotation_items_map_.Collection().clear();
+ annotation_set_items_map_.Collection().clear();
+ annotation_set_ref_lists_map_.Collection().clear();
+ annotations_directory_items_map_.Collection().clear();
+ debug_info_items_map_.Collection().clear();
+ code_items_map_.clear();
+ class_datas_map_.Collection().clear();
+}
+
static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
return 0;
}
diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h
index 5ecad2bf87..54ff105820 100644
--- a/dexlayout/dex_ir.h
+++ b/dexlayout/dex_ir.h
@@ -129,7 +129,11 @@ template<class T> class CollectionBase {
template<class T> class CollectionVector : public CollectionBase<T> {
public:
using Vector = std::vector<std::unique_ptr<T>>;
- CollectionVector() = default;
+ CollectionVector() { }
+ explicit CollectionVector(size_t size) {
+ // Preallocate so that assignment does not invalidate pointers into the vector.
+ collection_.reserve(size);
+ }
uint32_t Size() const { return collection_.size(); }
Vector& Collection() { return collection_; }
@@ -152,8 +156,11 @@ template<class T> class CollectionVector : public CollectionBase<T> {
protected:
Vector collection_;
- void AddItem(T* object) {
+ template<class... Args>
+ T* CreateAndAddItem(Args&&... args) {
+ T* object = new T(std::forward<Args>(args)...);
collection_.push_back(std::unique_ptr<T>(object));
+ return object;
}
private:
@@ -165,11 +172,20 @@ template<class T> class IndexedCollectionVector : public CollectionVector<T> {
public:
using Vector = std::vector<std::unique_ptr<T>>;
IndexedCollectionVector() = default;
+ explicit IndexedCollectionVector(size_t size) : CollectionVector<T>(size) { }
private:
- void AddIndexedItem(T* object, uint32_t index) {
+ template <class... Args>
+ T* CreateAndAddIndexedItem(uint32_t index, Args&&... args) {
+ T* object = CollectionVector<T>::CreateAndAddItem(std::forward<Args>(args)...);
object->SetIndex(index);
- CollectionVector<T>::collection_.push_back(std::unique_ptr<T>(object));
+ return object;
+ }
+
+ T* GetElement(uint32_t index) {
+ DCHECK_LT(index, CollectionVector<T>::Size());
+ DCHECK_NE(CollectionVector<T>::collection_[index].get(), static_cast<T*>(nullptr));
+ return CollectionVector<T>::collection_[index].get();
}
friend class Collections;
@@ -193,6 +209,8 @@ template<class T> class CollectionMap : public CollectionBase<T> {
private:
std::map<uint32_t, T*> collection_;
+ // CollectionMaps do not own the objects they contain, therefore AddItem is supported
+ // rather than CreateAndAddItem.
void AddItem(T* object, uint32_t offset) {
auto it = collection_.emplace(offset, object);
CHECK(it.second) << "CollectionMap already has an object with offset " << offset << " "
@@ -206,13 +224,25 @@ template<class T> class CollectionMap : public CollectionBase<T> {
class Collections {
public:
Collections() = default;
-
- CollectionVector<StringId>::Vector& StringIds() { return string_ids_.Collection(); }
- CollectionVector<TypeId>::Vector& TypeIds() { return type_ids_.Collection(); }
- CollectionVector<ProtoId>::Vector& ProtoIds() { return proto_ids_.Collection(); }
- CollectionVector<FieldId>::Vector& FieldIds() { return field_ids_.Collection(); }
- CollectionVector<MethodId>::Vector& MethodIds() { return method_ids_.Collection(); }
- CollectionVector<ClassDef>::Vector& ClassDefs() { return class_defs_.Collection(); }
+ Collections(uint32_t num_string_ids,
+ uint32_t num_type_ids,
+ uint32_t num_proto_ids,
+ uint32_t num_field_ids,
+ uint32_t num_method_ids,
+ uint32_t num_class_defs)
+ : string_ids_(num_string_ids),
+ type_ids_(num_type_ids),
+ proto_ids_(num_proto_ids),
+ field_ids_(num_field_ids),
+ method_ids_(num_method_ids),
+ class_defs_(num_class_defs) { }
+
+ IndexedCollectionVector<StringId>::Vector& StringIds() { return string_ids_.Collection(); }
+ IndexedCollectionVector<TypeId>::Vector& TypeIds() { return type_ids_.Collection(); }
+ IndexedCollectionVector<ProtoId>::Vector& ProtoIds() { return proto_ids_.Collection(); }
+ IndexedCollectionVector<FieldId>::Vector& FieldIds() { return field_ids_.Collection(); }
+ IndexedCollectionVector<MethodId>::Vector& MethodIds() { return method_ids_.Collection(); }
+ IndexedCollectionVector<ClassDef>::Vector& ClassDefs() { return class_defs_.Collection(); }
CollectionVector<CallSiteId>::Vector& CallSiteIds() { return call_site_ids_.Collection(); }
CollectionVector<MethodHandleItem>::Vector& MethodHandleItems()
{ return method_handle_items_.Collection(); }
@@ -266,28 +296,22 @@ class Collections {
uint32_t count);
StringId* GetStringId(uint32_t index) {
- CHECK_LT(index, StringIdsSize());
- return StringIds()[index].get();
+ return string_ids_.GetElement(index);
}
TypeId* GetTypeId(uint32_t index) {
- CHECK_LT(index, TypeIdsSize());
- return TypeIds()[index].get();
+ return type_ids_.GetElement(index);
}
ProtoId* GetProtoId(uint32_t index) {
- CHECK_LT(index, ProtoIdsSize());
- return ProtoIds()[index].get();
+ return proto_ids_.GetElement(index);
}
FieldId* GetFieldId(uint32_t index) {
- CHECK_LT(index, FieldIdsSize());
- return FieldIds()[index].get();
+ return field_ids_.GetElement(index);
}
MethodId* GetMethodId(uint32_t index) {
- CHECK_LT(index, MethodIdsSize());
- return MethodIds()[index].get();
+ return method_ids_.GetElement(index);
}
ClassDef* GetClassDef(uint32_t index) {
- CHECK_LT(index, ClassDefsSize());
- return ClassDefs()[index].get();
+ return class_defs_.GetElement(index);
}
CallSiteId* GetCallSiteId(uint32_t index) {
CHECK_LT(index, CallSiteIdsSize());
@@ -372,31 +396,35 @@ class Collections {
// Sort the vectors buy map order (same order that was used in the input file).
void SortVectorsByMapOrder();
-
- template <typename Type>
- void AddItem(CollectionMap<Type>& map,
- CollectionVector<Type>& vector,
- Type* item,
- uint32_t offset) {
+ // Empty the maps, which are only used for IR construction.
+ void ClearMaps();
+
+ template <typename Type, class... Args>
+ Type* CreateAndAddItem(CollectionMap<Type>& map,
+ CollectionVector<Type>& vector,
+ uint32_t offset,
+ Args&&... args) {
+ Type* item = vector.CreateAndAddItem(std::forward<Args>(args)...);
DCHECK(!map.GetExistingObject(offset));
DCHECK(!item->OffsetAssigned());
if (eagerly_assign_offsets_) {
item->SetOffset(offset);
}
map.AddItem(item, offset);
- vector.AddItem(item);
+ return item;
}
- template <typename Type>
- void AddIndexedItem(IndexedCollectionVector<Type>& vector,
- Type* item,
- uint32_t offset,
- uint32_t index) {
+ template <typename Type, class... Args>
+ Type* CreateAndAddIndexedItem(IndexedCollectionVector<Type>& vector,
+ uint32_t offset,
+ uint32_t index,
+ Args&&... args) {
+ Type* item = vector.CreateAndAddIndexedItem(index, std::forward<Args>(args)...);
DCHECK(!item->OffsetAssigned());
if (eagerly_assign_offsets_) {
item->SetOffset(offset);
}
- vector.AddIndexedItem(item, index);
+ return item;
}
void SetEagerlyAssignOffsets(bool eagerly_assign_offsets) {
@@ -425,7 +453,7 @@ class Collections {
ParameterAnnotation* GenerateParameterAnnotation(const DexFile& dex_file, MethodId* method_id,
const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset);
- MethodItem* GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii);
+ MethodItem GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii);
// Collection vectors own the IR data.
IndexedCollectionVector<StringId> string_ids_;
@@ -433,6 +461,7 @@ class Collections {
IndexedCollectionVector<ProtoId> proto_ids_;
IndexedCollectionVector<FieldId> field_ids_;
IndexedCollectionVector<MethodId> method_ids_;
+ IndexedCollectionVector<ClassDef> class_defs_;
IndexedCollectionVector<CallSiteId> call_site_ids_;
IndexedCollectionVector<MethodHandleItem> method_handle_items_;
IndexedCollectionVector<StringData> string_datas_;
@@ -442,7 +471,6 @@ class Collections {
IndexedCollectionVector<AnnotationSetItem> annotation_set_items_;
IndexedCollectionVector<AnnotationSetRefList> annotation_set_ref_lists_;
IndexedCollectionVector<AnnotationsDirectoryItem> annotations_directory_items_;
- IndexedCollectionVector<ClassDef> class_defs_;
// The order of the vectors controls the layout of the output file by index order, to change the
// layout just sort the vector. Note that you may only change the order of the non indexed vectors
// below. Indexed vectors are accessed by indices in other places, changing the sorting order will
@@ -485,6 +513,8 @@ class Item {
Item() { }
virtual ~Item() { }
+ Item(Item&&) = default;
+
// Return the assigned offset.
uint32_t GetOffset() const WARN_UNUSED {
CHECK(OffsetAssigned());
@@ -536,18 +566,54 @@ class Header : public Item {
uint32_t data_size,
uint32_t data_offset,
bool support_default_methods)
+ : Item(0, kHeaderItemSize), support_default_methods_(support_default_methods) {
+ ConstructorHelper(magic,
+ checksum,
+ signature,
+ endian_tag,
+ file_size,
+ header_size,
+ link_size,
+ link_offset,
+ data_size,
+ data_offset);
+ }
+
+ Header(const uint8_t* magic,
+ uint32_t checksum,
+ const uint8_t* signature,
+ uint32_t endian_tag,
+ uint32_t file_size,
+ uint32_t header_size,
+ uint32_t link_size,
+ uint32_t link_offset,
+ uint32_t data_size,
+ uint32_t data_offset,
+ bool support_default_methods,
+ uint32_t num_string_ids,
+ uint32_t num_type_ids,
+ uint32_t num_proto_ids,
+ uint32_t num_field_ids,
+ uint32_t num_method_ids,
+ uint32_t num_class_defs)
: Item(0, kHeaderItemSize),
- checksum_(checksum),
- endian_tag_(endian_tag),
- file_size_(file_size),
- header_size_(header_size),
- link_size_(link_size),
- link_offset_(link_offset),
- data_size_(data_size),
- data_offset_(data_offset),
- support_default_methods_(support_default_methods) {
- memcpy(magic_, magic, sizeof(magic_));
- memcpy(signature_, signature, sizeof(signature_));
+ support_default_methods_(support_default_methods),
+ collections_(num_string_ids,
+ num_type_ids,
+ num_proto_ids,
+ num_field_ids,
+ num_method_ids,
+ num_class_defs) {
+ ConstructorHelper(magic,
+ checksum,
+ signature,
+ endian_tag,
+ file_size,
+ header_size,
+ link_size,
+ link_offset,
+ data_size,
+ data_offset);
}
~Header() OVERRIDE { }
@@ -596,6 +662,27 @@ class Header : public Item {
uint32_t data_offset_;
const bool support_default_methods_;
+ void ConstructorHelper(const uint8_t* magic,
+ uint32_t checksum,
+ const uint8_t* signature,
+ uint32_t endian_tag,
+ uint32_t file_size,
+ uint32_t header_size,
+ uint32_t link_size,
+ uint32_t link_offset,
+ uint32_t data_size,
+ uint32_t data_offset) {
+ checksum_ = checksum;
+ endian_tag_ = endian_tag;
+ file_size_ = file_size;
+ header_size_ = header_size;
+ link_size_ = link_size;
+ link_offset_ = link_offset;
+ data_size_ = data_size;
+ data_offset_ = data_offset;
+ memcpy(magic_, magic, sizeof(magic_));
+ memcpy(signature_, signature, sizeof(signature_));
+ }
Collections collections_;
DISALLOW_COPY_AND_ASSIGN(Header);
@@ -744,6 +831,8 @@ class FieldItem : public Item {
: access_flags_(access_flags), field_id_(field_id) { }
~FieldItem() OVERRIDE { }
+ FieldItem(FieldItem&&) = default;
+
uint32_t GetAccessFlags() const { return access_flags_; }
const FieldId* GetFieldId() const { return field_id_; }
@@ -756,7 +845,7 @@ class FieldItem : public Item {
DISALLOW_COPY_AND_ASSIGN(FieldItem);
};
-using FieldItemVector = std::vector<std::unique_ptr<FieldItem>>;
+using FieldItemVector = std::vector<FieldItem>;
class MethodItem : public Item {
public:
@@ -764,6 +853,8 @@ class MethodItem : public Item {
: access_flags_(access_flags), method_id_(method_id), code_(code) { }
~MethodItem() OVERRIDE { }
+ MethodItem(MethodItem&&) = default;
+
uint32_t GetAccessFlags() const { return access_flags_; }
const MethodId* GetMethodId() const { return method_id_; }
CodeItem* GetCodeItem() { return code_; }
@@ -778,7 +869,7 @@ class MethodItem : public Item {
DISALLOW_COPY_AND_ASSIGN(MethodItem);
};
-using MethodItemVector = std::vector<std::unique_ptr<MethodItem>>;
+using MethodItemVector = std::vector<MethodItem>;
class EncodedValue {
public:
diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc
index 4f9bcdd742..9468f763d6 100644
--- a/dexlayout/dex_ir_builder.cc
+++ b/dexlayout/dex_ir_builder.cc
@@ -43,7 +43,13 @@ Header* DexIrBuilder(const DexFile& dex_file,
disk_header.link_off_,
disk_header.data_size_,
disk_header.data_off_,
- dex_file.SupportsDefaultMethods());
+ dex_file.SupportsDefaultMethods(),
+ dex_file.NumStringIds(),
+ dex_file.NumTypeIds(),
+ dex_file.NumProtoIds(),
+ dex_file.NumFieldIds(),
+ dex_file.NumMethodIds(),
+ dex_file.NumClassDefs());
Collections& collections = header->GetCollections();
collections.SetEagerlyAssignOffsets(eagerly_assign_offsets);
// Walk the rest of the header fields.
@@ -94,6 +100,7 @@ Header* DexIrBuilder(const DexFile& dex_file,
// Sort the vectors by the map order (same order as the file).
collections.SortVectorsByMapOrder();
+ collections.ClearMaps();
// Load the link data if it exists.
collections.SetLinkData(std::vector<uint8_t>(
diff --git a/dexlayout/dex_verify.cc b/dexlayout/dex_verify.cc
index 18ddc86e0c..2e4756b482 100644
--- a/dexlayout/dex_verify.cc
+++ b/dexlayout/dex_verify.cc
@@ -769,8 +769,8 @@ bool VerifyFields(dex_ir::FieldItemVector* orig,
return false;
}
for (size_t i = 0; i < orig->size(); ++i) {
- dex_ir::FieldItem* orig_field = (*orig)[i].get();
- dex_ir::FieldItem* output_field = (*output)[i].get();
+ dex_ir::FieldItem* orig_field = &(*orig)[i];
+ dex_ir::FieldItem* output_field = &(*output)[i];
if (orig_field->GetFieldId()->GetIndex() != output_field->GetFieldId()->GetIndex()) {
*error_msg = StringPrintf("Mismatched field index for class data at offset %x: %u vs %u.",
orig_offset,
@@ -802,8 +802,8 @@ bool VerifyMethods(dex_ir::MethodItemVector* orig,
return false;
}
for (size_t i = 0; i < orig->size(); ++i) {
- dex_ir::MethodItem* orig_method = (*orig)[i].get();
- dex_ir::MethodItem* output_method = (*output)[i].get();
+ dex_ir::MethodItem* orig_method = &(*orig)[i];
+ dex_ir::MethodItem* output_method = &(*output)[i];
if (orig_method->GetMethodId()->GetIndex() != output_method->GetMethodId()->GetIndex()) {
*error_msg = StringPrintf("Mismatched method index for class data at offset %x: %u vs %u.",
orig_offset,
diff --git a/dexlayout/dex_visualize.cc b/dexlayout/dex_visualize.cc
index c8aac941ff..0e04c587e7 100644
--- a/dexlayout/dex_visualize.cc
+++ b/dexlayout/dex_visualize.cc
@@ -279,22 +279,22 @@ void VisualizeDexLayout(dex_ir::Header* header,
dumper->DumpAddressRange(class_data, class_index);
if (class_data->StaticFields()) {
for (auto& field_item : *class_data->StaticFields()) {
- dumper->DumpFieldItem(field_item.get(), class_index);
+ dumper->DumpFieldItem(&field_item, class_index);
}
}
if (class_data->InstanceFields()) {
for (auto& field_item : *class_data->InstanceFields()) {
- dumper->DumpFieldItem(field_item.get(), class_index);
+ dumper->DumpFieldItem(&field_item, class_index);
}
}
if (class_data->DirectMethods()) {
for (auto& method_item : *class_data->DirectMethods()) {
- dumper->DumpMethodItem(method_item.get(), dex_file, class_index, profile_info);
+ dumper->DumpMethodItem(&method_item, dex_file, class_index, profile_info);
}
}
if (class_data->VirtualMethods()) {
for (auto& method_item : *class_data->VirtualMethods()) {
- dumper->DumpMethodItem(method_item.get(), dex_file, class_index, profile_info);
+ dumper->DumpMethodItem(&method_item, dex_file, class_index, profile_info);
}
}
}
diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc
index eead13f69a..9ed1312983 100644
--- a/dexlayout/dex_writer.cc
+++ b/dexlayout/dex_writer.cc
@@ -207,21 +207,21 @@ void DexWriter::WriteEncodedAnnotation(Stream* stream, dex_ir::EncodedAnnotation
void DexWriter::WriteEncodedFields(Stream* stream, dex_ir::FieldItemVector* fields) {
uint32_t prev_index = 0;
- for (std::unique_ptr<dex_ir::FieldItem>& field : *fields) {
- uint32_t index = field->GetFieldId()->GetIndex();
+ for (auto& field : *fields) {
+ uint32_t index = field.GetFieldId()->GetIndex();
stream->WriteUleb128(index - prev_index);
- stream->WriteUleb128(field->GetAccessFlags());
+ stream->WriteUleb128(field.GetAccessFlags());
prev_index = index;
}
}
void DexWriter::WriteEncodedMethods(Stream* stream, dex_ir::MethodItemVector* methods) {
uint32_t prev_index = 0;
- for (std::unique_ptr<dex_ir::MethodItem>& method : *methods) {
- uint32_t index = method->GetMethodId()->GetIndex();
- uint32_t code_off = method->GetCodeItem() == nullptr ? 0 : method->GetCodeItem()->GetOffset();
+ for (auto& method : *methods) {
+ uint32_t index = method.GetMethodId()->GetIndex();
+ uint32_t code_off = method.GetCodeItem() == nullptr ? 0 : method.GetCodeItem()->GetOffset();
stream->WriteUleb128(index - prev_index);
- stream->WriteUleb128(method->GetAccessFlags());
+ stream->WriteUleb128(method.GetAccessFlags());
stream->WriteUleb128(code_off);
prev_index = index;
}
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 62dd1a9554..39d93bfc77 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1459,8 +1459,8 @@ void DexLayout::DumpClass(int idx, char** last_package) {
dex_ir::FieldItemVector* static_fields = class_data->StaticFields();
if (static_fields != nullptr) {
for (uint32_t i = 0; i < static_fields->size(); i++) {
- DumpSField((*static_fields)[i]->GetFieldId()->GetIndex(),
- (*static_fields)[i]->GetAccessFlags(),
+ DumpSField((*static_fields)[i].GetFieldId()->GetIndex(),
+ (*static_fields)[i].GetAccessFlags(),
i,
i < encoded_values_size ? (*encoded_values)[i].get() : nullptr);
} // for
@@ -1475,8 +1475,8 @@ void DexLayout::DumpClass(int idx, char** last_package) {
dex_ir::FieldItemVector* instance_fields = class_data->InstanceFields();
if (instance_fields != nullptr) {
for (uint32_t i = 0; i < instance_fields->size(); i++) {
- DumpIField((*instance_fields)[i]->GetFieldId()->GetIndex(),
- (*instance_fields)[i]->GetAccessFlags(),
+ DumpIField((*instance_fields)[i].GetFieldId()->GetIndex(),
+ (*instance_fields)[i].GetAccessFlags(),
i);
} // for
}
@@ -1490,9 +1490,9 @@ void DexLayout::DumpClass(int idx, char** last_package) {
dex_ir::MethodItemVector* direct_methods = class_data->DirectMethods();
if (direct_methods != nullptr) {
for (uint32_t i = 0; i < direct_methods->size(); i++) {
- DumpMethod((*direct_methods)[i]->GetMethodId()->GetIndex(),
- (*direct_methods)[i]->GetAccessFlags(),
- (*direct_methods)[i]->GetCodeItem(),
+ DumpMethod((*direct_methods)[i].GetMethodId()->GetIndex(),
+ (*direct_methods)[i].GetAccessFlags(),
+ (*direct_methods)[i].GetCodeItem(),
i);
} // for
}
@@ -1506,9 +1506,9 @@ void DexLayout::DumpClass(int idx, char** last_package) {
dex_ir::MethodItemVector* virtual_methods = class_data->VirtualMethods();
if (virtual_methods != nullptr) {
for (uint32_t i = 0; i < virtual_methods->size(); i++) {
- DumpMethod((*virtual_methods)[i]->GetMethodId()->GetIndex(),
- (*virtual_methods)[i]->GetAccessFlags(),
- (*virtual_methods)[i]->GetCodeItem(),
+ DumpMethod((*virtual_methods)[i].GetMethodId()->GetIndex(),
+ (*virtual_methods)[i].GetAccessFlags(),
+ (*virtual_methods)[i].GetCodeItem(),
i);
} // for
}
@@ -1636,14 +1636,14 @@ void DexLayout::LayoutStringData(const DexFile* dex_file) {
}
for (size_t i = 0; i < 2; ++i) {
for (auto& method : *(i == 0 ? data->DirectMethods() : data->VirtualMethods())) {
- const dex_ir::MethodId* method_id = method->GetMethodId();
- dex_ir::CodeItem* code_item = method->GetCodeItem();
+ const dex_ir::MethodId* method_id = method.GetMethodId();
+ dex_ir::CodeItem* code_item = method.GetCodeItem();
if (code_item == nullptr) {
continue;
}
const bool is_clinit = is_profile_class &&
- (method->GetAccessFlags() & kAccConstructor) != 0 &&
- (method->GetAccessFlags() & kAccStatic) != 0;
+ (method.GetAccessFlags() & kAccConstructor) != 0 &&
+ (method.GetAccessFlags() & kAccStatic) != 0;
const bool method_executed = is_clinit ||
info_->GetMethodHotness(MethodReference(dex_file, method_id->GetIndex())).IsInProfile();
if (!method_executed) {
@@ -1744,14 +1744,14 @@ void DexLayout::LayoutCodeItems(const DexFile* dex_file) {
for (auto& method : *(invoke_type == InvokeType::kDirect
? class_data->DirectMethods()
: class_data->VirtualMethods())) {
- const dex_ir::MethodId *method_id = method->GetMethodId();
- dex_ir::CodeItem *code_item = method->GetCodeItem();
+ const dex_ir::MethodId *method_id = method.GetMethodId();
+ dex_ir::CodeItem *code_item = method.GetCodeItem();
if (code_item == nullptr) {
continue;
}
// Separate executed methods (clinits and profiled methods) from unexecuted methods.
- const bool is_clinit = (method->GetAccessFlags() & kAccConstructor) != 0 &&
- (method->GetAccessFlags() & kAccStatic) != 0;
+ const bool is_clinit = (method.GetAccessFlags() & kAccConstructor) != 0 &&
+ (method.GetAccessFlags() & kAccStatic) != 0;
const bool is_startup_clinit = is_profile_class && is_clinit;
using Hotness = ProfileCompilationInfo::MethodHotness;
Hotness hotness = info_->GetMethodHotness(MethodReference(dex_file, method_id->GetIndex()));
diff --git a/libartbase/base/bit_table.h b/libartbase/base/bit_table.h
index 0ae60b9070..2cc1a31ade 100644
--- a/libartbase/base/bit_table.h
+++ b/libartbase/base/bit_table.h
@@ -18,6 +18,7 @@
#define ART_LIBARTBASE_BASE_BIT_TABLE_H_
#include <array>
+#include <initializer_list>
#include <numeric>
#include <string.h>
#include <type_traits>
@@ -120,6 +121,7 @@ class BitTable {
ALWAYS_INLINE void Decode(BitMemoryRegion region, size_t* bit_offset) {
// Decode row count and column sizes from the table header.
+ size_t initial_bit_offset = *bit_offset;
num_rows_ = DecodeVarintBits(region, bit_offset);
if (num_rows_ != 0) {
column_offset_[0] = 0;
@@ -128,6 +130,7 @@ class BitTable {
column_offset_[i + 1] = dchecked_integral_cast<uint16_t>(column_end);
}
}
+ header_bit_size_ = *bit_offset - initial_bit_offset;
// Record the region which contains the table data and skip past it.
table_data_ = region.Subregion(*bit_offset, num_rows_ * NumRowBits());
@@ -158,55 +161,78 @@ class BitTable {
return column_offset_[column + 1] - column_offset_[column];
}
- size_t DataBitSize() const { return num_rows_ * column_offset_[kNumColumns]; }
+ size_t HeaderBitSize() const { return header_bit_size_; }
+ size_t BitSize() const { return header_bit_size_ + table_data_.size_in_bits(); }
protected:
BitMemoryRegion table_data_;
size_t num_rows_ = 0;
uint16_t column_offset_[kNumColumns + 1] = {};
+ uint16_t header_bit_size_ = 0;
};
// Template meta-programming helper.
template<typename Accessor, size_t... Columns>
-static const char** GetBitTableColumnNamesImpl(std::index_sequence<Columns...>) {
+static const char* const* GetBitTableColumnNamesImpl(std::index_sequence<Columns...>) {
static const char* names[] = { Accessor::template ColumnName<Columns, 0>::Value... };
return names;
}
template<typename Accessor>
-static const char** GetBitTableColumnNames() {
+static const char* const* GetBitTableColumnNames() {
return GetBitTableColumnNamesImpl<Accessor>(std::make_index_sequence<Accessor::kCount>());
}
// Helper class for encoding BitTable. It can optionally de-duplicate the inputs.
-// Type 'T' must be POD type consisting of uint32_t fields (one for each column).
-template<typename T>
+template<uint32_t kNumColumns>
class BitTableBuilder {
public:
- static_assert(std::is_pod<T>::value, "Type 'T' must be POD");
- static constexpr size_t kNumColumns = sizeof(T) / sizeof(uint32_t);
+ class Entry {
+ public:
+ Entry() {
+ std::fill_n(data_, kNumColumns, BitTable<kNumColumns>::Accessor::kNoValue);
+ }
+
+ Entry(std::initializer_list<uint32_t> values) {
+ DCHECK_EQ(values.size(), kNumColumns);
+ std::copy(values.begin(), values.end(), data_);
+ }
+
+ uint32_t& operator[](size_t column) {
+ DCHECK_LT(column, kNumColumns);
+ return data_[column];
+ }
+
+ uint32_t operator[](size_t column) const {
+ DCHECK_LT(column, kNumColumns);
+ return data_[column];
+ }
+
+ private:
+ uint32_t data_[kNumColumns];
+ };
explicit BitTableBuilder(ScopedArenaAllocator* allocator)
: rows_(allocator->Adapter(kArenaAllocBitTableBuilder)),
dedup_(8, allocator->Adapter(kArenaAllocBitTableBuilder)) {
}
- T& operator[](size_t row) { return rows_[row]; }
- const T& operator[](size_t row) const { return rows_[row]; }
+ Entry& operator[](size_t row) { return rows_[row]; }
+ const Entry& operator[](size_t row) const { return rows_[row]; }
size_t size() const { return rows_.size(); }
// Append given value to the vector without de-duplication.
// This will not add the element to the dedup map to avoid its associated costs.
- void Add(T value) {
+ void Add(Entry value) {
rows_.push_back(value);
}
// Append given list of values and return the index of the first value.
// If the exact same set of values was already added, return the old index.
- uint32_t Dedup(T* values, size_t count = 1) {
+ uint32_t Dedup(Entry* values, size_t count = 1) {
FNVHash<MemoryRegion> hasher;
- uint32_t hash = hasher(MemoryRegion(values, sizeof(T) * count));
+ uint32_t hash = hasher(MemoryRegion(values, sizeof(Entry) * count));
// Check if we have already added identical set of values.
auto range = dedup_.equal_range(hash);
@@ -216,8 +242,8 @@ class BitTableBuilder {
std::equal(values,
values + count,
rows_.begin() + index,
- [](const T& lhs, const T& rhs) {
- return memcmp(&lhs, &rhs, sizeof(T)) == 0;
+ [](const Entry& lhs, const Entry& rhs) {
+ return memcmp(&lhs, &rhs, sizeof(Entry)) == 0;
})) {
return index;
}
@@ -230,11 +256,8 @@ class BitTableBuilder {
return index;
}
- ALWAYS_INLINE uint32_t Get(uint32_t row, uint32_t column) const {
- DCHECK_LT(row, size());
- DCHECK_LT(column, kNumColumns);
- const uint32_t* data = reinterpret_cast<const uint32_t*>(&rows_[row]);
- return data[column];
+ uint32_t Dedup(Entry value) {
+ return Dedup(&value, /* count */ 1);
}
// Calculate the column bit widths based on the current data.
@@ -243,7 +266,7 @@ class BitTableBuilder {
std::fill_n(max_column_value, kNumColumns, 0);
for (uint32_t r = 0; r < size(); r++) {
for (uint32_t c = 0; c < kNumColumns; c++) {
- max_column_value[c] |= Get(r, c) - BitTable<kNumColumns>::kValueBias;
+ max_column_value[c] |= rows_[r][c] - BitTable<kNumColumns>::kValueBias;
}
}
for (uint32_t c = 0; c < kNumColumns; c++) {
@@ -272,7 +295,7 @@ class BitTableBuilder {
BitMemoryRegion region(MemoryRegion(out->data(), out->size()));
for (uint32_t r = 0; r < size(); r++) {
for (uint32_t c = 0; c < kNumColumns; c++) {
- region.StoreBitsAndAdvance(bit_offset, Get(r, c) - bias, column_bits[c]);
+ region.StoreBitsAndAdvance(bit_offset, rows_[r][c] - bias, column_bits[c]);
}
}
}
@@ -288,14 +311,14 @@ class BitTableBuilder {
}
for (uint32_t r = 0; r < size(); r++) {
for (uint32_t c = 0; c < kNumColumns; c++) {
- DCHECK_EQ(Get(r, c), table.Get(r, c)) << " (" << r << ", " << c << ")";
+ DCHECK_EQ(rows_[r][c], table.Get(r, c)) << " (" << r << ", " << c << ")";
}
}
}
}
protected:
- ScopedArenaDeque<T> rows_;
+ ScopedArenaDeque<Entry> rows_;
ScopedArenaUnorderedMultimap<uint32_t, uint32_t> dedup_; // Hash -> row index.
};
diff --git a/libartbase/base/bit_table_test.cc b/libartbase/base/bit_table_test.cc
index 8abf0da9d9..969940fe39 100644
--- a/libartbase/base/bit_table_test.cc
+++ b/libartbase/base/bit_table_test.cc
@@ -50,7 +50,7 @@ TEST(BitTableTest, TestEmptyTable) {
std::vector<uint8_t> buffer;
size_t encode_bit_offset = 0;
- BitTableBuilder<uint32_t> builder(&allocator);
+ BitTableBuilder<1> builder(&allocator);
builder.Encode(&buffer, &encode_bit_offset);
size_t decode_bit_offset = 0;
@@ -67,11 +67,11 @@ TEST(BitTableTest, TestSingleColumnTable) {
constexpr uint32_t kNoValue = -1;
std::vector<uint8_t> buffer;
size_t encode_bit_offset = 0;
- BitTableBuilder<uint32_t> builder(&allocator);
- builder.Add(42u);
- builder.Add(kNoValue);
- builder.Add(1000u);
- builder.Add(kNoValue);
+ BitTableBuilder<1> builder(&allocator);
+ builder.Add({42u});
+ builder.Add({kNoValue});
+ builder.Add({1000u});
+ builder.Add({kNoValue});
builder.Encode(&buffer, &encode_bit_offset);
size_t decode_bit_offset = 0;
@@ -93,8 +93,8 @@ TEST(BitTableTest, TestUnalignedTable) {
for (size_t start_bit_offset = 0; start_bit_offset <= 32; start_bit_offset++) {
std::vector<uint8_t> buffer;
size_t encode_bit_offset = start_bit_offset;
- BitTableBuilder<uint32_t> builder(&allocator);
- builder.Add(42u);
+ BitTableBuilder<1> builder(&allocator);
+ builder.Add({42u});
builder.Encode(&buffer, &encode_bit_offset);
size_t decode_bit_offset = start_bit_offset;
@@ -113,15 +113,9 @@ TEST(BitTableTest, TestBigTable) {
constexpr uint32_t kNoValue = -1;
std::vector<uint8_t> buffer;
size_t encode_bit_offset = 0;
- struct RowData {
- uint32_t a;
- uint32_t b;
- uint32_t c;
- uint32_t d;
- };
- BitTableBuilder<RowData> builder(&allocator);
- builder.Add(RowData{42u, kNoValue, 0u, static_cast<uint32_t>(-2)});
- builder.Add(RowData{62u, kNoValue, 63u, static_cast<uint32_t>(-3)});
+ BitTableBuilder<4> builder(&allocator);
+ builder.Add({42u, kNoValue, 0u, static_cast<uint32_t>(-2)});
+ builder.Add({62u, kNoValue, 63u, static_cast<uint32_t>(-3)});
builder.Encode(&buffer, &encode_bit_offset);
size_t decode_bit_offset = 0;
@@ -147,13 +141,9 @@ TEST(BitTableTest, TestDedup) {
ArenaStack arena_stack(&pool);
ScopedArenaAllocator allocator(&arena_stack);
- struct RowData {
- uint32_t a;
- uint32_t b;
- };
- BitTableBuilder<RowData> builder(&allocator);
- RowData value0{1, 2};
- RowData value1{3, 4};
+ BitTableBuilder<2> builder(&allocator);
+ BitTableBuilder<2>::Entry value0{1, 2};
+ BitTableBuilder<2>::Entry value1{3, 4};
EXPECT_EQ(0u, builder.Dedup(&value0));
EXPECT_EQ(1u, builder.Dedup(&value1));
EXPECT_EQ(0u, builder.Dedup(&value0));
@@ -197,16 +187,12 @@ TEST(BitTableTest, TestCollisions) {
ScopedArenaAllocator allocator(&arena_stack);
FNVHash<MemoryRegion> hasher;
- struct RowData {
- uint32_t a;
- uint32_t b;
- };
- RowData value0{56948505, 0};
- RowData value1{67108869, 0};
+ BitTableBuilder<2>::Entry value0{56948505, 0};
+ BitTableBuilder<2>::Entry value1{67108869, 0};
- BitTableBuilder<RowData> builder(&allocator);
- EXPECT_EQ(hasher(MemoryRegion(&value0, sizeof(RowData))),
- hasher(MemoryRegion(&value1, sizeof(RowData))));
+ BitTableBuilder<2> builder(&allocator);
+ EXPECT_EQ(hasher(MemoryRegion(&value0, sizeof(value0))),
+ hasher(MemoryRegion(&value1, sizeof(value1))));
EXPECT_EQ(0u, builder.Dedup(&value0));
EXPECT_EQ(1u, builder.Dedup(&value1));
EXPECT_EQ(0u, builder.Dedup(&value0));
@@ -214,12 +200,12 @@ TEST(BitTableTest, TestCollisions) {
EXPECT_EQ(2u, builder.size());
BitmapTableBuilder builder2(&allocator);
- EXPECT_EQ(hasher(MemoryRegion(&value0, BitsToBytesRoundUp(MinimumBitsToStore(value0.a)))),
- hasher(MemoryRegion(&value1, BitsToBytesRoundUp(MinimumBitsToStore(value1.a)))));
- EXPECT_EQ(0u, builder2.Dedup(&value0.a, MinimumBitsToStore(value0.a)));
- EXPECT_EQ(1u, builder2.Dedup(&value1.a, MinimumBitsToStore(value1.a)));
- EXPECT_EQ(0u, builder2.Dedup(&value0.a, MinimumBitsToStore(value0.a)));
- EXPECT_EQ(1u, builder2.Dedup(&value1.a, MinimumBitsToStore(value1.a)));
+ EXPECT_EQ(hasher(MemoryRegion(&value0, BitsToBytesRoundUp(MinimumBitsToStore(value0[0])))),
+ hasher(MemoryRegion(&value1, BitsToBytesRoundUp(MinimumBitsToStore(value1[0])))));
+ EXPECT_EQ(0u, builder2.Dedup(&value0[0], MinimumBitsToStore(value0[0])));
+ EXPECT_EQ(1u, builder2.Dedup(&value1[0], MinimumBitsToStore(value1[0])));
+ EXPECT_EQ(0u, builder2.Dedup(&value0[0], MinimumBitsToStore(value0[0])));
+ EXPECT_EQ(1u, builder2.Dedup(&value1[0], MinimumBitsToStore(value1[0])));
EXPECT_EQ(2u, builder2.size());
}
diff --git a/libartbase/base/indenter.h b/libartbase/base/indenter.h
index 06e7340d36..a479b7d650 100644
--- a/libartbase/base/indenter.h
+++ b/libartbase/base/indenter.h
@@ -122,6 +122,10 @@ class VariableIndentationOutputStream {
return indented_os_;
}
+ size_t GetIndentation() const {
+ return indenter_.count_;
+ }
+
void IncreaseIndentation(size_t adjustment) {
indenter_.count_ += adjustment;
}
diff --git a/libartbase/base/mem_map.cc b/libartbase/base/mem_map.cc
index 9ba1d6c139..d53480d4ca 100644
--- a/libartbase/base/mem_map.cc
+++ b/libartbase/base/mem_map.cc
@@ -647,21 +647,11 @@ void MemMap::MadviseDontNeedAndZero() {
}
bool MemMap::Sync() {
- bool result;
- if (redzone_size_ != 0) {
- // To avoid errors when running on a memory tool, temporarily lift the lower-end noaccess
- // protection before passing it to msync() as it only accepts page-aligned base address,
- // and exclude the higher-end noaccess protection from the msync range. b/27552451.
- // TODO: Valgrind is no longer supported, but Address Sanitizer is:
- // check whether this special case is needed for ASan.
- uint8_t* base_begin = reinterpret_cast<uint8_t*>(base_begin_);
- MEMORY_TOOL_MAKE_DEFINED(base_begin, begin_ - base_begin);
- result = msync(BaseBegin(), End() - base_begin, MS_SYNC) == 0;
- MEMORY_TOOL_MAKE_NOACCESS(base_begin, begin_ - base_begin);
- } else {
- result = msync(BaseBegin(), BaseSize(), MS_SYNC) == 0;
- }
- return result;
+ // Historical note: To avoid Valgrind errors, we temporarily lifted the lower-end noaccess
+ // protection before passing it to msync() when `redzone_size_` was non-null, as Valgrind
+ // only accepts page-aligned base address, and excludes the higher-end noaccess protection
+ // from the msync range. b/27552451.
+ return msync(BaseBegin(), BaseSize(), MS_SYNC) == 0;
}
bool MemMap::Protect(int prot) {
diff --git a/libartbase/base/mem_map_test.cc b/libartbase/base/mem_map_test.cc
index 4a78bdcabe..c575c7a31f 100644
--- a/libartbase/base/mem_map_test.cc
+++ b/libartbase/base/mem_map_test.cc
@@ -471,9 +471,8 @@ TEST_F(MemMapTest, MapAnonymousExactAddr32bitHighAddr) {
// cannot allocate in the 2GB-4GB region.
TEST_DISABLED_FOR_MIPS();
- // This test may not work under Valgrind.
- // TODO: Valgrind is no longer supported, but Address Sanitizer is:
- // check whether this test works with ASan.
+ // This test does not work under AddressSanitizer.
+ // Historical note: This test did not work under Valgrind either.
TEST_DISABLED_FOR_MEMORY_TOOL();
CommonInit();
diff --git a/libartbase/base/stats.h b/libartbase/base/stats.h
new file mode 100644
index 0000000000..4dcbfe81c6
--- /dev/null
+++ b/libartbase/base/stats.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 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_LIBARTBASE_BASE_STATS_H_
+#define ART_LIBARTBASE_BASE_STATS_H_
+
+#include <unordered_map>
+
+#include "globals.h"
+
+namespace art {
+
+// Simple structure to record tree of statistical values.
+class Stats {
+ public:
+ double Value() const { return value_; }
+ size_t Count() const { return count_; }
+ Stats* Child(const char* name) { return &children_[name]; }
+ const std::unordered_map<const char*, Stats>& Children() const { return children_; }
+
+ void AddBytes(double bytes, size_t count = 1) { Add(bytes, count); }
+ void AddBits(double bits, size_t count = 1) { Add(bits / kBitsPerByte, count); }
+ void AddSeconds(double s, size_t count = 1) { Add(s, count); }
+ void AddNanoSeconds(double ns, size_t count = 1) { Add(ns / 1000000000.0, count); }
+
+ double SumChildrenValues() const {
+ double sum = 0.0;
+ for (auto it : children_) {
+ sum += it.second.Value();
+ }
+ return sum;
+ }
+
+ private:
+ void Add(double value, size_t count = 1) {
+ value_ += value;
+ count_ += count;
+ }
+
+ double value_ = 0.0; // Commutative sum of the collected statistic in basic units.
+ size_t count_ = 0; // The number of samples for this node.
+ std::unordered_map<const char*, Stats> children_;
+};
+
+} // namespace art
+
+#endif // ART_LIBARTBASE_BASE_STATS_H_
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 453e9da106..2b0095ce27 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <fstream>
+#include <iomanip>
#include <iostream>
#include <map>
#include <set>
@@ -37,6 +38,7 @@
#include "base/indenter.h"
#include "base/os.h"
#include "base/safe_map.h"
+#include "base/stats.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "class_linker-inl.h"
@@ -544,28 +546,30 @@ class OatDumper {
os << "\n";
}
- // Dump .bss entries.
- DumpBssEntries(
- os,
- "ArtMethod",
- oat_dex_file->GetMethodBssMapping(),
- dex_file->NumMethodIds(),
- static_cast<size_t>(GetInstructionSetPointerSize(instruction_set_)),
- [=](uint32_t index) { return dex_file->PrettyMethod(index); });
- DumpBssEntries(
- os,
- "Class",
- oat_dex_file->GetTypeBssMapping(),
- dex_file->NumTypeIds(),
- sizeof(GcRoot<mirror::Class>),
- [=](uint32_t index) { return dex_file->PrettyType(dex::TypeIndex(index)); });
- DumpBssEntries(
- os,
- "String",
- oat_dex_file->GetStringBssMapping(),
- dex_file->NumStringIds(),
- sizeof(GcRoot<mirror::Class>),
- [=](uint32_t index) { return dex_file->StringDataByIdx(dex::StringIndex(index)); });
+ if (!options_.dump_header_only_) {
+ // Dump .bss entries.
+ DumpBssEntries(
+ os,
+ "ArtMethod",
+ oat_dex_file->GetMethodBssMapping(),
+ dex_file->NumMethodIds(),
+ static_cast<size_t>(GetInstructionSetPointerSize(instruction_set_)),
+ [=](uint32_t index) { return dex_file->PrettyMethod(index); });
+ DumpBssEntries(
+ os,
+ "Class",
+ oat_dex_file->GetTypeBssMapping(),
+ dex_file->NumTypeIds(),
+ sizeof(GcRoot<mirror::Class>),
+ [=](uint32_t index) { return dex_file->PrettyType(dex::TypeIndex(index)); });
+ DumpBssEntries(
+ os,
+ "String",
+ oat_dex_file->GetStringBssMapping(),
+ dex_file->NumStringIds(),
+ sizeof(GcRoot<mirror::Class>),
+ [=](uint32_t index) { return dex_file->StringDataByIdx(dex::StringIndex(index)); });
+ }
}
if (!options_.dump_header_only_) {
@@ -639,7 +643,8 @@ class OatDumper {
{
os << "OAT FILE STATS:\n";
VariableIndentationOutputStream vios(&os);
- stats_.Dump(vios);
+ stats_.AddBytes(oat_file_.Size());
+ DumpStats(vios, "OatFile", stats_, stats_.Value());
}
os << std::flush;
@@ -737,156 +742,42 @@ class OatDumper {
return vdex_file;
}
- struct Stats {
- enum ByteKind {
- kByteKindCode,
- kByteKindQuickMethodHeader,
- kByteKindCodeInfoLocationCatalog,
- kByteKindCodeInfoDexRegisterMask,
- kByteKindCodeInfoDexRegisterMap,
- kByteKindCodeInfo,
- kByteKindCodeInfoInvokeInfo,
- kByteKindCodeInfoStackMasks,
- kByteKindCodeInfoRegisterMasks,
- kByteKindStackMapNativePc,
- kByteKindStackMapDexPc,
- kByteKindStackMapDexRegisterMap,
- kByteKindStackMapInlineInfoIndex,
- kByteKindStackMapRegisterMaskIndex,
- kByteKindStackMapStackMaskIndex,
- kByteKindInlineInfoMethodIndexIdx,
- kByteKindInlineInfoDexPc,
- kByteKindInlineInfoArtMethod,
- kByteKindInlineInfoNumDexRegisters,
- kByteKindInlineInfoIsLast,
- kByteKindCount,
- // Special ranges for std::accumulate convenience.
- kByteKindStackMapFirst = kByteKindStackMapNativePc,
- kByteKindStackMapLast = kByteKindStackMapStackMaskIndex,
- kByteKindInlineInfoFirst = kByteKindInlineInfoMethodIndexIdx,
- kByteKindInlineInfoLast = kByteKindInlineInfoIsLast,
- };
- int64_t bits[kByteKindCount] = {};
- // Since code has deduplication, seen tracks already seen pointers to avoid double counting
- // deduplicated code and tables.
- std::unordered_set<const void*> seen;
-
- // Returns true if it was newly added.
- bool AddBitsIfUnique(ByteKind kind, int64_t count, const void* address) {
- if (seen.insert(address).second == true) {
- // True means the address was not already in the set.
- AddBits(kind, count);
- return true;
+ bool AddStatsObject(const void* address) {
+ return seen_stats_objects_.insert(address).second; // Inserted new entry.
+ }
+
+ void DumpStats(VariableIndentationOutputStream& os,
+ const std::string& name,
+ const Stats& stats,
+ double total) {
+ if (std::fabs(stats.Value()) > 0 || !stats.Children().empty()) {
+ double percent = 100.0 * stats.Value() / total;
+ os.Stream()
+ << std::setw(40 - os.GetIndentation()) << std::left << name << std::right << " "
+ << std::setw(8) << stats.Count() << " "
+ << std::setw(12) << std::fixed << std::setprecision(3) << stats.Value() / KB << "KB "
+ << std::setw(8) << std::fixed << std::setprecision(1) << percent << "%\n";
+
+ // Sort all children by largest value first, than by name.
+ std::map<std::pair<double, std::string>, const Stats&> sorted_children;
+ for (const auto& it : stats.Children()) {
+ sorted_children.emplace(std::make_pair(-it.second.Value(), it.first), it.second);
}
- return false;
- }
- void AddBits(ByteKind kind, int64_t count) {
- bits[kind] += count;
- }
-
- void Dump(VariableIndentationOutputStream& os) {
- const int64_t sum = std::accumulate(bits, bits + kByteKindCount, 0u);
- os.Stream() << "Dumping cumulative use of " << sum / kBitsPerByte << " accounted bytes\n";
- if (sum > 0) {
- Dump(os, "Code ", bits[kByteKindCode], sum);
- Dump(os, "QuickMethodHeader ", bits[kByteKindQuickMethodHeader], sum);
- Dump(os, "CodeInfo ", bits[kByteKindCodeInfo], sum);
- Dump(os, "CodeInfoLocationCatalog ", bits[kByteKindCodeInfoLocationCatalog], sum);
- Dump(os, "CodeInfoDexRegisterMask ", bits[kByteKindCodeInfoDexRegisterMask], sum);
- Dump(os, "CodeInfoDexRegisterMap ", bits[kByteKindCodeInfoDexRegisterMap], sum);
- Dump(os, "CodeInfoStackMasks ", bits[kByteKindCodeInfoStackMasks], sum);
- Dump(os, "CodeInfoRegisterMasks ", bits[kByteKindCodeInfoRegisterMasks], sum);
- Dump(os, "CodeInfoInvokeInfo ", bits[kByteKindCodeInfoInvokeInfo], sum);
- // Stack map section.
- const int64_t stack_map_bits = std::accumulate(bits + kByteKindStackMapFirst,
- bits + kByteKindStackMapLast + 1,
- 0u);
- Dump(os, "CodeInfoStackMap ", stack_map_bits, sum);
- {
- ScopedIndentation indent1(&os);
- Dump(os,
- "StackMapNativePc ",
- bits[kByteKindStackMapNativePc],
- stack_map_bits,
- "stack map");
- Dump(os,
- "StackMapDexPc ",
- bits[kByteKindStackMapDexPc],
- stack_map_bits,
- "stack map");
- Dump(os,
- "StackMapDexRegisterMap ",
- bits[kByteKindStackMapDexRegisterMap],
- stack_map_bits,
- "stack map");
- Dump(os,
- "StackMapInlineInfoIndex ",
- bits[kByteKindStackMapInlineInfoIndex],
- stack_map_bits,
- "stack map");
- Dump(os,
- "StackMapRegisterMaskIndex ",
- bits[kByteKindStackMapRegisterMaskIndex],
- stack_map_bits,
- "stack map");
- Dump(os,
- "StackMapStackMaskIndex ",
- bits[kByteKindStackMapStackMaskIndex],
- stack_map_bits,
- "stack map");
- }
- // Inline info section.
- const int64_t inline_info_bits = std::accumulate(bits + kByteKindInlineInfoFirst,
- bits + kByteKindInlineInfoLast + 1,
- 0u);
- Dump(os, "CodeInfoInlineInfo ", inline_info_bits, sum);
- {
- ScopedIndentation indent1(&os);
- Dump(os,
- "InlineInfoMethodIndexIdx ",
- bits[kByteKindInlineInfoMethodIndexIdx],
- inline_info_bits,
- "inline info");
- Dump(os,
- "InlineInfoDexPc ",
- bits[kByteKindStackMapDexPc],
- inline_info_bits,
- "inline info");
- Dump(os,
- "InlineInfoArtMethod ",
- bits[kByteKindInlineInfoArtMethod],
- inline_info_bits,
- "inline info");
- Dump(os,
- "InlineInfoNumDexRegisters ",
- bits[kByteKindInlineInfoNumDexRegisters],
- inline_info_bits,
- "inline info");
- Dump(os,
- "InlineInfoIsLast ",
- bits[kByteKindInlineInfoIsLast],
- inline_info_bits,
- "inline info");
- }
+ // Add "other" row to represent any amount not account for by the children.
+ Stats other;
+ other.AddBytes(stats.Value() - stats.SumChildrenValues(), stats.Count());
+ if (std::fabs(other.Value()) > 0 && !stats.Children().empty()) {
+ sorted_children.emplace(std::make_pair(-other.Value(), "(other)"), other);
}
- os.Stream() << "\n" << std::flush;
- }
- private:
- void Dump(VariableIndentationOutputStream& os,
- const char* name,
- int64_t size,
- int64_t total,
- const char* sum_of = "total") {
- const double percent = (static_cast<double>(size) / static_cast<double>(total)) * 100;
- os.Stream() << StringPrintf("%s = %8" PRId64 " (%2.0f%% of %s)\n",
- name,
- size / kBitsPerByte,
- percent,
- sum_of);
+ // Print the data.
+ ScopedIndentation indent1(&os);
+ for (const auto& it : sorted_children) {
+ DumpStats(os, it.first.second, it.second, total);
+ }
}
- };
+ }
private:
void AddAllOffsets() {
@@ -1266,9 +1157,9 @@ class OatDumper {
vios->Stream() << "OatQuickMethodHeader ";
uint32_t method_header_offset = oat_method.GetOatQuickMethodHeaderOffset();
const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader();
- stats_.AddBitsIfUnique(Stats::kByteKindQuickMethodHeader,
- sizeof(*method_header) * kBitsPerByte,
- method_header);
+ if (AddStatsObject(method_header)) {
+ stats_.Child("QuickMethodHeader")->AddBytes(sizeof(*method_header));
+ }
if (options_.absolute_addresses_) {
vios->Stream() << StringPrintf("%p ", method_header);
}
@@ -1340,7 +1231,9 @@ class OatDumper {
const void* code = oat_method.GetQuickCode();
uint32_t aligned_code_begin = AlignCodeOffset(code_offset);
uint64_t aligned_code_end = aligned_code_begin + code_size;
- stats_.AddBitsIfUnique(Stats::kByteKindCode, code_size * kBitsPerByte, code);
+ if (AddStatsObject(code)) {
+ stats_.Child("Code")->AddBytes(code_size);
+ }
if (options_.absolute_addresses_) {
vios->Stream() << StringPrintf("%p ", code);
@@ -1690,78 +1583,15 @@ class OatDumper {
} else if (!bad_input && IsMethodGeneratedByOptimizingCompiler(oat_method,
code_item_accessor)) {
// The optimizing compiler outputs its CodeInfo data in the vmap table.
+ const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader();
StackMapsHelper helper(oat_method.GetVmapTable(), instruction_set_);
- MethodInfo method_info(oat_method.GetOatQuickMethodHeader()->GetOptimizedMethodInfo());
- {
- const CodeInfo code_info = helper.GetCodeInfo();
- const BitTable<StackMap::kCount>& stack_maps = code_info.stack_maps_;
- const size_t num_stack_maps = stack_maps.NumRows();
- if (stats_.AddBitsIfUnique(Stats::kByteKindCodeInfo,
- code_info.size_ * kBitsPerByte,
- oat_method.GetVmapTable())) {
- // Stack maps
- stats_.AddBits(
- Stats::kByteKindStackMapNativePc,
- stack_maps.NumColumnBits(StackMap::kPackedNativePc) * num_stack_maps);
- stats_.AddBits(
- Stats::kByteKindStackMapDexPc,
- stack_maps.NumColumnBits(StackMap::kDexPc) * num_stack_maps);
- stats_.AddBits(
- Stats::kByteKindStackMapDexRegisterMap,
- stack_maps.NumColumnBits(StackMap::kDexRegisterMapIndex) * num_stack_maps);
- stats_.AddBits(
- Stats::kByteKindStackMapInlineInfoIndex,
- stack_maps.NumColumnBits(StackMap::kInlineInfoIndex) * num_stack_maps);
- stats_.AddBits(
- Stats::kByteKindStackMapRegisterMaskIndex,
- stack_maps.NumColumnBits(StackMap::kRegisterMaskIndex) * num_stack_maps);
- stats_.AddBits(
- Stats::kByteKindStackMapStackMaskIndex,
- stack_maps.NumColumnBits(StackMap::kStackMaskIndex) * num_stack_maps);
-
- // Stack masks
- stats_.AddBits(
- Stats::kByteKindCodeInfoStackMasks,
- code_info.stack_masks_.DataBitSize());
-
- // Register masks
- stats_.AddBits(
- Stats::kByteKindCodeInfoRegisterMasks,
- code_info.register_masks_.DataBitSize());
-
- // Invoke infos
- stats_.AddBits(
- Stats::kByteKindCodeInfoInvokeInfo,
- code_info.invoke_infos_.DataBitSize());
-
- // Location catalog
- stats_.AddBits(Stats::kByteKindCodeInfoLocationCatalog,
- code_info.dex_register_catalog_.DataBitSize());
- stats_.AddBits(Stats::kByteKindCodeInfoDexRegisterMask,
- code_info.dex_register_masks_.DataBitSize());
- stats_.AddBits(Stats::kByteKindCodeInfoDexRegisterMap,
- code_info.dex_register_maps_.DataBitSize());
-
- // Inline infos.
- const BitTable<InlineInfo::kCount>& inline_infos = code_info.inline_infos_;
- const size_t num_inline_infos = inline_infos.NumRows();
- if (num_inline_infos > 0u) {
- stats_.AddBits(
- Stats::kByteKindInlineInfoMethodIndexIdx,
- inline_infos.NumColumnBits(InlineInfo::kMethodInfoIndex) * num_inline_infos);
- stats_.AddBits(
- Stats::kByteKindInlineInfoDexPc,
- inline_infos.NumColumnBits(InlineInfo::kDexPc) * num_inline_infos);
- stats_.AddBits(
- Stats::kByteKindInlineInfoArtMethod,
- inline_infos.NumColumnBits(InlineInfo::kArtMethodHi) * num_inline_infos +
- inline_infos.NumColumnBits(InlineInfo::kArtMethodLo) * num_inline_infos);
- stats_.AddBits(
- Stats::kByteKindInlineInfoNumDexRegisters,
- inline_infos.NumColumnBits(InlineInfo::kNumberOfDexRegisters) * num_inline_infos);
- stats_.AddBits(Stats::kByteKindInlineInfoIsLast, num_inline_infos);
- }
- }
+ if (AddStatsObject(oat_method.GetVmapTable())) {
+ helper.GetCodeInfo().AddSizeStats(&stats_);
+ }
+ MethodInfo method_info(method_header->GetOptimizedMethodInfo());
+ if (AddStatsObject(method_header->GetOptimizedMethodInfoPtr())) {
+ size_t method_info_size = MethodInfo::ComputeSize(method_info.NumMethodIndices());
+ stats_.Child("MethodInfo")->AddBytes(method_info_size);
}
const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
size_t offset = 0;
@@ -1894,6 +1724,7 @@ class OatDumper {
std::set<uintptr_t> offsets_;
Disassembler* disassembler_;
Stats stats_;
+ std::unordered_set<const void*> seen_stats_objects_;
};
class ImageDumper {
diff --git a/oatdump/oatdump_test.h b/oatdump/oatdump_test.h
index 293acdc3a6..231163b674 100644
--- a/oatdump/oatdump_test.h
+++ b/oatdump/oatdump_test.h
@@ -158,7 +158,7 @@ class OatDumpTest : public CommonRuntimeTest {
// Code and dex code do not show up if list only.
expected_prefixes.push_back("DEX CODE:");
expected_prefixes.push_back("CODE:");
- expected_prefixes.push_back("CodeInfoInlineInfo");
+ expected_prefixes.push_back("InlineInfos");
}
if (mode == kModeArt) {
exec_argv.push_back("--image=" + core_art_location_);
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 777a1fc5ee..1168798f38 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -47,6 +47,7 @@ libart_cc_defaults {
"debug_print.cc",
"debugger.cc",
"dex/dex_file_annotations.cc",
+ "dex_register_location.cc",
"dex_to_dex_decompiler.cc",
"elf_file.cc",
"exec_utils.cc",
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index 8a2a70e7ab..8f9f45c30b 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -75,7 +75,7 @@ class CheckReferenceMapVisitor : public StackVisitor {
for (int i = 0; i < number_of_references; ++i) {
int reg = registers[i];
CHECK_LT(reg, accessor.RegistersSize());
- DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(reg);
+ DexRegisterLocation location = dex_register_map[reg];
switch (location.GetKind()) {
case DexRegisterLocation::Kind::kNone:
// Not set, should not be a reference.
@@ -98,7 +98,7 @@ class CheckReferenceMapVisitor : public StackVisitor {
CHECK_EQ(location.GetValue(), 0);
break;
default:
- LOG(FATAL) << "Unexpected location kind " << location.GetInternalKind();
+ LOG(FATAL) << "Unexpected location kind " << location.GetKind();
}
}
}
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 1710e788ef..c374e03ed7 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4440,8 +4440,8 @@ void ClassLinker::CreateProxyConstructor(Handle<mirror::Class> klass, ArtMethod*
// Find the <init>(InvocationHandler)V method. The exact method offset varies depending
// on which front-end compiler was used to build the libcore DEX files.
- ArtMethod* proxy_constructor = proxy_class->FindConstructor(
- "(Ljava/lang/reflect/InvocationHandler;)V", image_pointer_size_);
+ ArtMethod* proxy_constructor =
+ jni::DecodeArtMethod(WellKnownClasses::java_lang_reflect_Proxy_init);
DCHECK(proxy_constructor != nullptr)
<< "Could not find <init> method in java.lang.reflect.Proxy";
diff --git a/runtime/dex_register_location.cc b/runtime/dex_register_location.cc
new file mode 100644
index 0000000000..f3b09733b9
--- /dev/null
+++ b/runtime/dex_register_location.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dex_register_location.h"
+
+namespace art {
+
+std::ostream& operator<<(std::ostream& stream, DexRegisterLocation::Kind kind) {
+ return stream << "Kind<" << static_cast<int32_t>(kind) << ">";
+}
+
+std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg) {
+ using Kind = DexRegisterLocation::Kind;
+ switch (reg.GetKind()) {
+ case Kind::kInvalid:
+ return stream << "Invalid";
+ case Kind::kNone:
+ return stream << "None";
+ case Kind::kInStack:
+ return stream << "sp+" << reg.GetValue();
+ case Kind::kInRegister:
+ return stream << "r" << reg.GetValue();
+ case Kind::kInRegisterHigh:
+ return stream << "r" << reg.GetValue() << "/hi";
+ case Kind::kInFpuRegister:
+ return stream << "f" << reg.GetValue();
+ case Kind::kInFpuRegisterHigh:
+ return stream << "f" << reg.GetValue() << "/hi";
+ case Kind::kConstant:
+ return stream << "#" << reg.GetValue();
+ default:
+ return stream << "DexRegisterLocation(" << static_cast<uint32_t>(reg.GetKind())
+ << "," << reg.GetValue() << ")";
+ }
+}
+
+} // namespace art
diff --git a/runtime/dex_register_location.h b/runtime/dex_register_location.h
index a20dccbc12..98b4d41e2d 100644
--- a/runtime/dex_register_location.h
+++ b/runtime/dex_register_location.h
@@ -48,9 +48,6 @@ class DexRegisterLocation {
Kind GetKind() const { return kind_; }
- // TODO: Remove.
- Kind GetInternalKind() const { return kind_; }
-
int32_t GetValue() const { return value_; }
bool operator==(DexRegisterLocation other) const {
@@ -61,6 +58,24 @@ class DexRegisterLocation {
return !(*this == other);
}
+ int32_t GetStackOffsetInBytes() const {
+ DCHECK(kind_ == Kind::kInStack);
+ return value_;
+ }
+
+ int32_t GetConstant() const {
+ DCHECK(kind_ == Kind::kConstant);
+ return value_;
+ }
+
+ int32_t GetMachineRegister() const {
+ DCHECK(kind_ == Kind::kInRegister ||
+ kind_ == Kind::kInRegisterHigh ||
+ kind_ == Kind::kInFpuRegister ||
+ kind_ == Kind::kInFpuRegisterHigh);
+ return value_;
+ }
+
private:
DexRegisterLocation() {}
@@ -70,9 +85,8 @@ class DexRegisterLocation {
friend class DexRegisterMap; // Allow creation of uninitialized array of locations.
};
-static inline std::ostream& operator<<(std::ostream& stream, DexRegisterLocation::Kind kind) {
- return stream << "Kind<" << static_cast<int32_t>(kind) << ">";
-}
+std::ostream& operator<<(std::ostream& stream, DexRegisterLocation::Kind kind);
+std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg);
} // namespace art
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 2b1623ac5a..3ccfa556f1 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1101,11 +1101,14 @@ extern "C" const void* artInstrumentationMethodEntryFromCode(ArtMethod* method,
// that part.
ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+ DCHECK(!method->IsProxyMethod())
+ << "Proxy method " << method->PrettyMethod()
+ << " (declaring class: " << method->GetDeclaringClass()->PrettyClass() << ")"
+ << " should not hit instrumentation entrypoint.";
if (instrumentation->IsDeoptimized(method)) {
result = GetQuickToInterpreterBridge();
} else {
result = instrumentation->GetQuickCodeFor(method, kRuntimePointerSize);
- DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(result));
}
bool interpreter_entry = (result == GetQuickToInterpreterBridge());
diff --git a/runtime/exec_utils_test.cc b/runtime/exec_utils_test.cc
index a9c1ea2ae0..c138ce3f9e 100644
--- a/runtime/exec_utils_test.cc
+++ b/runtime/exec_utils_test.cc
@@ -36,12 +36,9 @@ TEST_F(ExecUtilsTest, ExecSuccess) {
command.push_back("/usr/bin/id");
}
std::string error_msg;
- if (!(kRunningOnMemoryTool && kMemoryToolDetectsLeaks)) {
- // Running on Valgrind fails due to some memory that leaks in thread alternate signal stacks.
- // TODO: Valgrind is no longer supported, but Address Sanitizer is:
- // check whether the following code works with ASan.
- EXPECT_TRUE(Exec(command, &error_msg));
- }
+ // Historical note: Running on Valgrind failed due to some memory
+ // that leaks in thread alternate signal stacks.
+ EXPECT_TRUE(Exec(command, &error_msg));
EXPECT_EQ(0U, error_msg.size()) << error_msg;
}
@@ -52,13 +49,10 @@ TEST_F(ExecUtilsTest, ExecError) {
std::vector<std::string> command;
command.push_back("bogus");
std::string error_msg;
- if (!(kRunningOnMemoryTool && kMemoryToolDetectsLeaks)) {
- // Running on Valgrind fails due to some memory that leaks in thread alternate signal stacks.
- // TODO: Valgrind is no longer supported, but Address Sanitizer is:
- // check whether the following code works with ASan.
- EXPECT_FALSE(Exec(command, &error_msg));
- EXPECT_FALSE(error_msg.empty());
- }
+ // Historical note: Running on Valgrind failed due to some memory
+ // that leaks in thread alternate signal stacks.
+ EXPECT_FALSE(Exec(command, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
}
TEST_F(ExecUtilsTest, EnvSnapshotAdditionsAreNotVisible) {
@@ -76,13 +70,10 @@ TEST_F(ExecUtilsTest, EnvSnapshotAdditionsAreNotVisible) {
}
command.push_back(kModifiedVariable);
std::string error_msg;
- if (!(kRunningOnMemoryTool && kMemoryToolDetectsLeaks)) {
- // Running on Valgrind fails due to some memory that leaks in thread alternate signal stacks.
- // TODO: Valgrind is no longer supported, but Address Sanitizer is:
- // check whether the following code works with ASan.
- EXPECT_FALSE(Exec(command, &error_msg));
- EXPECT_NE(0U, error_msg.size()) << error_msg;
- }
+ // Historical note: Running on Valgrind failed due to some memory
+ // that leaks in thread alternate signal stacks.
+ EXPECT_FALSE(Exec(command, &error_msg));
+ EXPECT_NE(0U, error_msg.size()) << error_msg;
}
TEST_F(ExecUtilsTest, EnvSnapshotDeletionsAreNotVisible) {
@@ -103,13 +94,10 @@ TEST_F(ExecUtilsTest, EnvSnapshotDeletionsAreNotVisible) {
}
command.push_back(kDeletedVariable);
std::string error_msg;
- if (!(kRunningOnMemoryTool && kMemoryToolDetectsLeaks)) {
- // Running on Valgrind fails due to some memory that leaks in thread alternate signal stacks.
- // TODO: Valgrind is no longer supported, but Address Sanitizer is:
- // check whether the following code works with ASan.
- EXPECT_TRUE(Exec(command, &error_msg));
- EXPECT_EQ(0U, error_msg.size()) << error_msg;
- }
+ // Historical note: Running on Valgrind failed due to some memory
+ // that leaks in thread alternate signal stacks.
+ EXPECT_TRUE(Exec(command, &error_msg));
+ EXPECT_EQ(0U, error_msg.size()) << error_msg;
// Restore the variable's value.
EXPECT_EQ(setenv(kDeletedVariable, save_value, kOverwrite), 0);
}
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index d7f33d5e43..d752805d02 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -154,8 +154,16 @@ void Instrumentation::InstallStubsForMethod(ArtMethod* method) {
return;
}
// Don't stub Proxy.<init>. Note that the Proxy class itself is not a proxy class.
- if (method->IsConstructor() &&
- method->GetDeclaringClass()->DescriptorEquals("Ljava/lang/reflect/Proxy;")) {
+ // TODO We should remove the need for this since it means we cannot always correctly detect calls
+ // to Proxy.<init>
+ // Annoyingly this can be called before we have actually initialized WellKnownClasses so therefore
+ // we also need to check this based on the declaring-class descriptor. The check is valid because
+ // Proxy only has a single constructor.
+ ArtMethod* well_known_proxy_init = jni::DecodeArtMethod(
+ WellKnownClasses::java_lang_reflect_Proxy_init);
+ if ((LIKELY(well_known_proxy_init != nullptr) && UNLIKELY(method == well_known_proxy_init)) ||
+ UNLIKELY(method->IsConstructor() &&
+ method->GetDeclaringClass()->DescriptorEquals("Ljava/lang/reflect/Proxy;"))) {
return;
}
const void* new_quick_code;
@@ -354,7 +362,7 @@ static void InstrumentationInstallStack(Thread* thread, void* arg)
}
uint32_t dex_pc = visitor.dex_pcs_.back();
visitor.dex_pcs_.pop_back();
- if (!isi->interpreter_entry_) {
+ if (!isi->interpreter_entry_ && !isi->method_->IsRuntimeMethod()) {
instrumentation->MethodEnterEvent(thread, (*isi).this_object_, (*isi).method_, dex_pc);
}
}
@@ -785,7 +793,13 @@ void Instrumentation::UpdateMethodsCodeImpl(ArtMethod* method, const void* quick
if (class_linker->IsQuickResolutionStub(quick_code) ||
class_linker->IsQuickToInterpreterBridge(quick_code)) {
new_quick_code = quick_code;
- } else if (entry_exit_stubs_installed_) {
+ } else if (entry_exit_stubs_installed_ &&
+ // We need to make sure not to replace anything that InstallStubsForMethod
+ // wouldn't. Specifically we cannot stub out Proxy.<init> since subtypes copy the
+ // implementation directly and this will confuse the instrumentation trampolines.
+ // TODO We should remove the need for this since it makes it impossible to profile
+ // Proxy.<init> correctly in all cases.
+ method != jni::DecodeArtMethod(WellKnownClasses::java_lang_reflect_Proxy_init)) {
new_quick_code = GetQuickInstrumentationEntryPoint();
} else {
new_quick_code = quick_code;
@@ -912,7 +926,7 @@ void Instrumentation::Undeoptimize(ArtMethod* method) {
}
// If there is no deoptimized method left, we can restore the stack of each thread.
- if (empty) {
+ if (empty && !entry_exit_stubs_installed_) {
MutexLock mu(self, *Locks::thread_list_lock_);
Runtime::Current()->GetThreadList()->ForEach(InstrumentationRestoreStack, this);
instrumentation_stubs_installed_ = false;
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 0a8e0cd64f..5e736035f8 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -515,7 +515,7 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
} else {
DCHECK_EQ(vreg_map.size(), number_of_vregs);
for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
- DexRegisterLocation::Kind location = vreg_map.GetLocationKind(vreg);
+ DexRegisterLocation::Kind location = vreg_map[vreg].GetKind();
if (location == DexRegisterLocation::Kind::kNone) {
// Dex register is dead or uninitialized.
continue;
@@ -529,7 +529,7 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
DCHECK_EQ(location, DexRegisterLocation::Kind::kInStack);
int32_t vreg_value = shadow_frame->GetVReg(vreg);
- int32_t slot_offset = vreg_map.GetStackOffsetInBytes(vreg);
+ int32_t slot_offset = vreg_map[vreg].GetStackOffsetInBytes();
DCHECK_LT(slot_offset, static_cast<int32_t>(frame_size));
DCHECK_GT(slot_offset, 0);
(reinterpret_cast<int32_t*>(memory))[slot_offset / sizeof(int32_t)] = vreg_value;
diff --git a/runtime/native_stack_dump.cc b/runtime/native_stack_dump.cc
index b3a47c3053..ce295aacde 100644
--- a/runtime/native_stack_dump.cc
+++ b/runtime/native_stack_dump.cc
@@ -290,11 +290,6 @@ void DumpNativeStack(std::ostream& os,
void* ucontext_ptr,
bool skip_frames) {
// Historical note: This was disabled when running under Valgrind (b/18119146).
- // TODO: Valgrind is no longer supported, but Address Sanitizer is:
- // check whether this test works with ASan.
- if (kRunningOnMemoryTool) {
- return;
- }
BacktraceMap* map = existing_map;
std::unique_ptr<BacktraceMap> tmp_map;
diff --git a/runtime/oat.h b/runtime/oat.h
index 40f4edd8bb..22c6a39e09 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@ class InstructionSetFeatures;
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- // Last oat version changed reason: compiler support invoke-custom
- static constexpr uint8_t kOatVersion[] = { '1', '4', '8', '\0' };
+ // Last oat version changed reason: Add Kind column to stack maps.
+ static constexpr uint8_t kOatVersion[] = { '1', '4', '9', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 946ea018f3..36dea60367 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -23,11 +23,24 @@
#include "mirror/field-inl.h"
#include "proxy_test.h"
#include "scoped_thread_state_change-inl.h"
+#include "well_known_classes.h"
namespace art {
namespace proxy_test {
-class ProxyTest : public CommonRuntimeTest {};
+class ProxyTest : public CommonRuntimeTest {
+ protected:
+ void SetUp() OVERRIDE {
+ CommonRuntimeTest::SetUp();
+ // The creation of a Proxy class uses WellKnownClasses. These are not normally initialized by
+ // CommonRuntimeTest so we need to do that now.
+ WellKnownClasses::Clear();
+ WellKnownClasses::Init(art::Thread::Current()->GetJniEnv());
+ // Since we aren't actually calling any of the native functions we can just immediately call
+ // LateInit after calling Init.
+ WellKnownClasses::LateInit(art::Thread::Current()->GetJniEnv());
+ }
+};
// Creates a proxy class and check ClassHelper works correctly.
TEST_F(ProxyTest, ProxyClassHelper) {
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index cf1cbe7f7b..8b99b9f9c8 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -245,7 +245,7 @@ void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor*
// Copy values between them.
for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
- DexRegisterLocation::Kind catch_location = catch_vreg_map.GetLocationKind(vreg);
+ DexRegisterLocation::Kind catch_location = catch_vreg_map[vreg].GetKind();
if (catch_location == DexRegisterLocation::Kind::kNone) {
continue;
}
@@ -253,7 +253,7 @@ void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor*
// Get vreg value from its current location.
uint32_t vreg_value;
- VRegKind vreg_kind = ToVRegKind(throw_vreg_map.GetLocationKind(vreg));
+ VRegKind vreg_kind = ToVRegKind(throw_vreg_map[vreg].GetKind());
bool get_vreg_success = stack_visitor->GetVReg(stack_visitor->GetMethod(),
vreg,
vreg_kind,
@@ -264,7 +264,7 @@ void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor*
<< "native_pc_offset=" << stack_visitor->GetNativePcOffset() << ")";
// Copy value to the catch phi's stack slot.
- int32_t slot_offset = catch_vreg_map.GetStackOffsetInBytes(vreg);
+ int32_t slot_offset = catch_vreg_map[vreg].GetStackOffsetInBytes();
ArtMethod** frame_top = stack_visitor->GetCurrentQuickFrame();
uint8_t* slot_address = reinterpret_cast<uint8_t*>(frame_top) + slot_offset;
uint32_t* slot_ptr = reinterpret_cast<uint32_t*>(slot_address);
@@ -417,14 +417,14 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
continue;
}
- DexRegisterLocation::Kind location = vreg_map.GetLocationKind(vreg);
+ DexRegisterLocation::Kind location = vreg_map[vreg].GetKind();
static constexpr uint32_t kDeadValue = 0xEBADDE09;
uint32_t value = kDeadValue;
bool is_reference = false;
switch (location) {
case DexRegisterLocation::Kind::kInStack: {
- const int32_t offset = vreg_map.GetStackOffsetInBytes(vreg);
+ const int32_t offset = vreg_map[vreg].GetStackOffsetInBytes();
const uint8_t* addr = reinterpret_cast<const uint8_t*>(GetCurrentQuickFrame()) + offset;
value = *reinterpret_cast<const uint32_t*>(addr);
uint32_t bit = (offset >> 2);
@@ -437,7 +437,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
case DexRegisterLocation::Kind::kInRegisterHigh:
case DexRegisterLocation::Kind::kInFpuRegister:
case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
- uint32_t reg = vreg_map.GetMachineRegister(vreg);
+ uint32_t reg = vreg_map[vreg].GetMachineRegister();
bool result = GetRegisterIfAccessible(reg, ToVRegKind(location), &value);
CHECK(result);
if (location == DexRegisterLocation::Kind::kInRegister) {
@@ -448,7 +448,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
break;
}
case DexRegisterLocation::Kind::kConstant: {
- value = vreg_map.GetConstant(vreg);
+ value = vreg_map[vreg].GetConstant();
if (value == 0) {
// Make it a reference for extra safety.
is_reference = true;
@@ -459,9 +459,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
break;
}
default: {
- LOG(FATAL)
- << "Unexpected location kind "
- << vreg_map.GetLocationInternalKind(vreg);
+ LOG(FATAL) << "Unexpected location kind " << vreg_map[vreg].GetKind();
UNREACHABLE();
}
}
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 56e47b9c77..a181bfe091 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -242,10 +242,10 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin
return false;
}
DCHECK_EQ(dex_register_map.size(), number_of_dex_registers);
- DexRegisterLocation::Kind location_kind = dex_register_map.GetLocationKind(vreg);
+ DexRegisterLocation::Kind location_kind = dex_register_map[vreg].GetKind();
switch (location_kind) {
case DexRegisterLocation::Kind::kInStack: {
- const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg);
+ const int32_t offset = dex_register_map[vreg].GetStackOffsetInBytes();
const uint8_t* addr = reinterpret_cast<const uint8_t*>(cur_quick_frame_) + offset;
*val = *reinterpret_cast<const uint32_t*>(addr);
return true;
@@ -254,18 +254,16 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin
case DexRegisterLocation::Kind::kInRegisterHigh:
case DexRegisterLocation::Kind::kInFpuRegister:
case DexRegisterLocation::Kind::kInFpuRegisterHigh: {
- uint32_t reg = dex_register_map.GetMachineRegister(vreg);
+ uint32_t reg = dex_register_map[vreg].GetMachineRegister();
return GetRegisterIfAccessible(reg, kind, val);
}
case DexRegisterLocation::Kind::kConstant:
- *val = dex_register_map.GetConstant(vreg);
+ *val = dex_register_map[vreg].GetConstant();
return true;
case DexRegisterLocation::Kind::kNone:
return false;
default:
- LOG(FATAL)
- << "Unexpected location kind "
- << dex_register_map.GetLocationInternalKind(vreg);
+ LOG(FATAL) << "Unexpected location kind " << dex_register_map[vreg].GetKind();
UNREACHABLE();
}
}
@@ -851,7 +849,8 @@ void StackVisitor::WalkStack(bool include_transitions) {
uint8_t* return_pc_addr = reinterpret_cast<uint8_t*>(cur_quick_frame_) + return_pc_offset;
uintptr_t return_pc = *reinterpret_cast<uintptr_t*>(return_pc_addr);
- if (UNLIKELY(exit_stubs_installed)) {
+ if (UNLIKELY(exit_stubs_installed ||
+ reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc()) == return_pc)) {
// While profiling, the return pc is restored from the side stack, except when walking
// the stack for an exception where the side stack will be unwound in VisitFrame.
if (reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc()) == return_pc) {
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index a25c9fdee0..43609e80bd 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -21,6 +21,7 @@
#include "art_method.h"
#include "base/indenter.h"
+#include "base/stats.h"
#include "scoped_thread_state_change-inl.h"
namespace art {
@@ -88,56 +89,62 @@ void CodeInfo::DecodeDexRegisterMap(uint32_t stack_map_index,
}
}
-std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg) {
- using Kind = DexRegisterLocation::Kind;
- switch (reg.GetKind()) {
- case Kind::kNone:
- return stream << "None";
- case Kind::kInStack:
- return stream << "sp+" << reg.GetValue();
- case Kind::kInRegister:
- return stream << "r" << reg.GetValue();
- case Kind::kInRegisterHigh:
- return stream << "r" << reg.GetValue() << "/hi";
- case Kind::kInFpuRegister:
- return stream << "f" << reg.GetValue();
- case Kind::kInFpuRegisterHigh:
- return stream << "f" << reg.GetValue() << "/hi";
- case Kind::kConstant:
- return stream << "#" << reg.GetValue();
- case Kind::kInvalid:
- return stream << "Invalid";
- default:
- return stream << "DexRegisterLocation(" << static_cast<uint32_t>(reg.GetKind())
- << "," << reg.GetValue() << ")";
+template<typename Accessor>
+static void AddTableSizeStats(const char* table_name,
+ const BitTable<Accessor::kCount>& table,
+ /*out*/ Stats* parent) {
+ Stats* table_stats = parent->Child(table_name);
+ table_stats->AddBits(table.BitSize());
+ table_stats->Child("Header")->AddBits(table.HeaderBitSize());
+ const char* const* column_names = GetBitTableColumnNames<Accessor>();
+ for (size_t c = 0; c < table.NumColumns(); c++) {
+ if (table.NumColumnBits(c) > 0) {
+ Stats* column_stats = table_stats->Child(column_names[c]);
+ column_stats->AddBits(table.NumRows() * table.NumColumnBits(c), table.NumRows());
+ }
}
}
-static void DumpDexRegisterMap(VariableIndentationOutputStream* vios,
- const DexRegisterMap& map) {
- if (!map.empty()) {
+void CodeInfo::AddSizeStats(/*out*/ Stats* parent) const {
+ Stats* stats = parent->Child("CodeInfo");
+ stats->AddBytes(size_);
+ stats->Child("Header")->AddBytes(UnsignedLeb128Size(size_));
+ AddTableSizeStats<StackMap>("StackMaps", stack_maps_, stats);
+ AddTableSizeStats<RegisterMask>("RegisterMasks", register_masks_, stats);
+ AddTableSizeStats<MaskInfo>("StackMasks", stack_masks_, stats);
+ AddTableSizeStats<InvokeInfo>("InvokeInfos", invoke_infos_, stats);
+ AddTableSizeStats<InlineInfo>("InlineInfos", inline_infos_, stats);
+ AddTableSizeStats<MaskInfo>("DexRegisterMasks", dex_register_masks_, stats);
+ AddTableSizeStats<DexRegisterMapInfo>("DexRegisterMaps", dex_register_maps_, stats);
+ AddTableSizeStats<DexRegisterInfo>("DexRegisterCatalog", dex_register_catalog_, stats);
+}
+
+void DexRegisterMap::Dump(VariableIndentationOutputStream* vios) const {
+ if (HasAnyLiveDexRegisters()) {
ScopedIndentation indent1(vios);
- for (size_t i = 0; i < map.size(); ++i) {
- if (map.IsDexRegisterLive(i)) {
- vios->Stream() << "v" << i << ":" << map.Get(i) << " ";
+ for (size_t i = 0; i < size(); ++i) {
+ DexRegisterLocation reg = (*this)[i];
+ if (reg.IsLive()) {
+ vios->Stream() << "v" << i << ":" << reg << " ";
}
}
vios->Stream() << "\n";
}
}
-template<uint32_t kNumColumns>
+template<typename Accessor>
static void DumpTable(VariableIndentationOutputStream* vios,
const char* table_name,
- const BitTable<kNumColumns>& table,
+ const BitTable<Accessor::kCount>& table,
bool verbose,
bool is_mask = false) {
if (table.NumRows() != 0) {
- vios->Stream() << table_name << " BitSize=" << table.NumRows() * table.NumRowBits();
+ vios->Stream() << table_name << " BitSize=" << table.BitSize();
vios->Stream() << " Rows=" << table.NumRows() << " Bits={";
+ const char* const* column_names = GetBitTableColumnNames<Accessor>();
for (size_t c = 0; c < table.NumColumns(); c++) {
vios->Stream() << (c != 0 ? " " : "");
- vios->Stream() << table.NumColumnBits(c);
+ vios->Stream() << column_names[c] << "=" << table.NumColumnBits(c);
}
vios->Stream() << "}\n";
if (verbose) {
@@ -171,14 +178,14 @@ void CodeInfo::Dump(VariableIndentationOutputStream* vios,
<< " BitSize=" << size_ * kBitsPerByte
<< "\n";
ScopedIndentation indent1(vios);
- DumpTable(vios, "StackMaps", stack_maps_, verbose);
- DumpTable(vios, "RegisterMasks", register_masks_, verbose);
- DumpTable(vios, "StackMasks", stack_masks_, verbose, true /* is_mask */);
- DumpTable(vios, "InvokeInfos", invoke_infos_, verbose);
- DumpTable(vios, "InlineInfos", inline_infos_, verbose);
- DumpTable(vios, "DexRegisterMasks", dex_register_masks_, verbose, true /* is_mask */);
- DumpTable(vios, "DexRegisterMaps", dex_register_maps_, verbose);
- DumpTable(vios, "DexRegisterCatalog", dex_register_catalog_, verbose);
+ DumpTable<StackMap>(vios, "StackMaps", stack_maps_, verbose);
+ DumpTable<RegisterMask>(vios, "RegisterMasks", register_masks_, verbose);
+ DumpTable<MaskInfo>(vios, "StackMasks", stack_masks_, verbose, true /* is_mask */);
+ DumpTable<InvokeInfo>(vios, "InvokeInfos", invoke_infos_, verbose);
+ DumpTable<InlineInfo>(vios, "InlineInfos", inline_infos_, verbose);
+ DumpTable<MaskInfo>(vios, "DexRegisterMasks", dex_register_masks_, verbose, true /* is_mask */);
+ DumpTable<DexRegisterMapInfo>(vios, "DexRegisterMaps", dex_register_maps_, verbose);
+ DumpTable<DexRegisterInfo>(vios, "DexRegisterCatalog", dex_register_catalog_, verbose);
// Display stack maps along with (live) Dex register maps.
if (verbose) {
@@ -208,7 +215,7 @@ void StackMap::Dump(VariableIndentationOutputStream* vios,
vios->Stream() << stack_mask.LoadBit(e - i - 1);
}
vios->Stream() << ")\n";
- DumpDexRegisterMap(vios, code_info.GetDexRegisterMapOf(*this));
+ code_info.GetDexRegisterMapOf(*this).Dump(vios);
uint32_t depth = code_info.GetInlineDepthOf(*this);
for (size_t d = 0; d < depth; d++) {
InlineInfo inline_info = code_info.GetInlineInfoAtDepth(*this, d);
@@ -235,7 +242,7 @@ void InlineInfo::Dump(VariableIndentationOutputStream* vios,
<< ", method_index=" << GetMethodIndex(method_info);
}
vios->Stream() << ")\n";
- DumpDexRegisterMap(vios, code_info.GetDexRegisterMapAtDepth(depth, stack_map));
+ code_info.GetDexRegisterMapAtDepth(depth, stack_map).Dump(vios);
}
} // namespace art
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 53f80e5203..8af73e9e10 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -47,15 +47,18 @@ static constexpr size_t kMaxDexRegisterMapSearchDistance = 32;
class ArtMethod;
class CodeInfo;
+class Stats;
std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg);
// Information on Dex register locations for a specific PC.
// Effectively just a convenience wrapper for DexRegisterLocation vector.
// If the size is small enough, it keeps the data on the stack.
+// TODO: Replace this with generic purpose "small-vector" implementation.
class DexRegisterMap {
public:
using iterator = DexRegisterLocation*;
+ using const_iterator = const DexRegisterLocation*;
// Create map for given number of registers and initialize them to the given value.
DexRegisterMap(size_t count, DexRegisterLocation value) : count_(count), regs_small_{} {
@@ -69,76 +72,36 @@ class DexRegisterMap {
DexRegisterLocation* data() {
return count_ <= kSmallCount ? regs_small_.data() : regs_large_.data();
}
+ const DexRegisterLocation* data() const {
+ return count_ <= kSmallCount ? regs_small_.data() : regs_large_.data();
+ }
iterator begin() { return data(); }
iterator end() { return data() + count_; }
-
+ const_iterator begin() const { return data(); }
+ const_iterator end() const { return data() + count_; }
size_t size() const { return count_; }
-
bool empty() const { return count_ == 0; }
- DexRegisterLocation Get(size_t index) const {
+ DexRegisterLocation& operator[](size_t index) {
DCHECK_LT(index, count_);
- return count_ <= kSmallCount ? regs_small_[index] : regs_large_[index];
- }
-
- DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number) const {
- return Get(dex_register_number).GetKind();
- }
-
- // TODO: Remove.
- DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number) const {
- return Get(dex_register_number).GetKind();
- }
-
- DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number) const {
- return Get(dex_register_number);
- }
-
- int32_t GetStackOffsetInBytes(uint16_t dex_register_number) const {
- DexRegisterLocation location = Get(dex_register_number);
- DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack);
- return location.GetValue();
+ return data()[index];
}
-
- int32_t GetConstant(uint16_t dex_register_number) const {
- DexRegisterLocation location = Get(dex_register_number);
- DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant);
- return location.GetValue();
- }
-
- int32_t GetMachineRegister(uint16_t dex_register_number) const {
- DexRegisterLocation location = Get(dex_register_number);
- DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInRegister ||
- location.GetKind() == DexRegisterLocation::Kind::kInRegisterHigh ||
- location.GetKind() == DexRegisterLocation::Kind::kInFpuRegister ||
- location.GetKind() == DexRegisterLocation::Kind::kInFpuRegisterHigh);
- return location.GetValue();
- }
-
- ALWAYS_INLINE bool IsDexRegisterLive(uint16_t dex_register_number) const {
- return Get(dex_register_number).IsLive();
+ const DexRegisterLocation& operator[](size_t index) const {
+ DCHECK_LT(index, count_);
+ return data()[index];
}
size_t GetNumberOfLiveDexRegisters() const {
- size_t number_of_live_dex_registers = 0;
- for (size_t i = 0; i < count_; ++i) {
- if (IsDexRegisterLive(i)) {
- ++number_of_live_dex_registers;
- }
- }
- return number_of_live_dex_registers;
+ return std::count_if(begin(), end(), [](auto& loc) { return loc.IsLive(); });
}
bool HasAnyLiveDexRegisters() const {
- for (size_t i = 0; i < count_; ++i) {
- if (IsDexRegisterLive(i)) {
- return true;
- }
- }
- return false;
+ return std::any_of(begin(), end(), [](auto& loc) { return loc.IsLive(); });
}
+ void Dump(VariableIndentationOutputStream* vios) const;
+
private:
// Store the data inline if the number of registers is small to avoid memory allocations.
// If count_ <= kSmallCount, we use the regs_small_ array, and regs_large_ otherwise.
@@ -156,16 +119,23 @@ class DexRegisterMap {
* - Knowing the inlining information,
* - Knowing the values of dex registers.
*/
-class StackMap : public BitTable<7>::Accessor {
+class StackMap : public BitTable<8>::Accessor {
public:
+ enum Kind {
+ Default = -1,
+ Catch = 0,
+ OSR = 1,
+ Debug = 2,
+ };
BIT_TABLE_HEADER()
- BIT_TABLE_COLUMN(0, PackedNativePc)
- BIT_TABLE_COLUMN(1, DexPc)
- BIT_TABLE_COLUMN(2, RegisterMaskIndex)
- BIT_TABLE_COLUMN(3, StackMaskIndex)
- BIT_TABLE_COLUMN(4, InlineInfoIndex)
- BIT_TABLE_COLUMN(5, DexRegisterMaskIndex)
- BIT_TABLE_COLUMN(6, DexRegisterMapIndex)
+ BIT_TABLE_COLUMN(0, Kind)
+ BIT_TABLE_COLUMN(1, PackedNativePc)
+ BIT_TABLE_COLUMN(2, DexPc)
+ BIT_TABLE_COLUMN(3, RegisterMaskIndex)
+ BIT_TABLE_COLUMN(4, StackMaskIndex)
+ BIT_TABLE_COLUMN(5, InlineInfoIndex)
+ BIT_TABLE_COLUMN(6, DexRegisterMaskIndex)
+ BIT_TABLE_COLUMN(7, DexRegisterMapIndex)
ALWAYS_INLINE uint32_t GetNativePcOffset(InstructionSet instruction_set) const {
return UnpackNativePc(Get<kPackedNativePc>(), instruction_set);
@@ -252,6 +222,18 @@ class InvokeInfo : public BitTable<3>::Accessor {
}
};
+class MaskInfo : public BitTable<1>::Accessor {
+ public:
+ BIT_TABLE_HEADER()
+ BIT_TABLE_COLUMN(0, Mask)
+};
+
+class DexRegisterMapInfo : public BitTable<1>::Accessor {
+ public:
+ BIT_TABLE_HEADER()
+ BIT_TABLE_COLUMN(0, CatalogueIndex)
+};
+
class DexRegisterInfo : public BitTable<2>::Accessor {
public:
BIT_TABLE_HEADER()
@@ -402,19 +384,18 @@ class CodeInfo {
StackMap GetStackMapForDexPc(uint32_t dex_pc) const {
for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
StackMap stack_map = GetStackMapAt(i);
- if (stack_map.GetDexPc() == dex_pc) {
+ if (stack_map.GetDexPc() == dex_pc && stack_map.GetKind() != StackMap::Kind::Debug) {
return stack_map;
}
}
return StackMap();
}
- // Searches the stack map list backwards because catch stack maps are stored
- // at the end.
+ // Searches the stack map list backwards because catch stack maps are stored at the end.
StackMap GetCatchStackMapForDexPc(uint32_t dex_pc) const {
for (size_t i = GetNumberOfStackMaps(); i > 0; --i) {
StackMap stack_map = GetStackMapAt(i - 1);
- if (stack_map.GetDexPc() == dex_pc) {
+ if (stack_map.GetDexPc() == dex_pc && stack_map.GetKind() == StackMap::Kind::Catch) {
return stack_map;
}
}
@@ -422,41 +403,26 @@ class CodeInfo {
}
StackMap GetOsrStackMapForDexPc(uint32_t dex_pc) const {
- size_t e = GetNumberOfStackMaps();
- if (e == 0) {
- // There cannot be OSR stack map if there is no stack map.
- return StackMap();
- }
- // Walk over all stack maps. If two consecutive stack maps are identical, then we
- // have found a stack map suitable for OSR.
- for (size_t i = 0; i < e - 1; ++i) {
+ for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
StackMap stack_map = GetStackMapAt(i);
- if (stack_map.GetDexPc() == dex_pc) {
- StackMap other = GetStackMapAt(i + 1);
- if (other.GetDexPc() == dex_pc &&
- other.GetNativePcOffset(kRuntimeISA) ==
- stack_map.GetNativePcOffset(kRuntimeISA)) {
- if (i < e - 2) {
- // Make sure there are not three identical stack maps following each other.
- DCHECK_NE(
- stack_map.GetNativePcOffset(kRuntimeISA),
- GetStackMapAt(i + 2).GetNativePcOffset(kRuntimeISA));
- }
- return stack_map;
- }
+ if (stack_map.GetDexPc() == dex_pc && stack_map.GetKind() == StackMap::Kind::OSR) {
+ return stack_map;
}
}
return StackMap();
}
- StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const {
+ StackMap GetStackMapForNativePcOffset(uint32_t pc, InstructionSet isa = kRuntimeISA) const {
// TODO: Safepoint stack maps are sorted by native_pc_offset but catch stack
// maps are not. If we knew that the method does not have try/catch,
// we could do binary search.
for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
StackMap stack_map = GetStackMapAt(i);
- if (stack_map.GetNativePcOffset(kRuntimeISA) == native_pc_offset) {
- return stack_map;
+ if (stack_map.GetNativePcOffset(isa) == pc) {
+ StackMap::Kind kind = static_cast<StackMap::Kind>(stack_map.GetKind());
+ if (kind == StackMap::Kind::Default || kind == StackMap::Kind::OSR) {
+ return stack_map;
+ }
}
}
return StackMap();
@@ -480,6 +446,9 @@ class CodeInfo {
InstructionSet instruction_set,
const MethodInfo& method_info) const;
+ // Accumulate code info size statistics into the given Stats tree.
+ void AddSizeStats(/*out*/ Stats* parent) const;
+
private:
// Scan backward to determine dex register locations at given stack map.
void DecodeDexRegisterMap(uint32_t stack_map_index,
@@ -506,15 +475,13 @@ class CodeInfo {
size_t size_;
BitTable<StackMap::kCount> stack_maps_;
BitTable<RegisterMask::kCount> register_masks_;
- BitTable<1> stack_masks_;
+ BitTable<MaskInfo::kCount> stack_masks_;
BitTable<InvokeInfo::kCount> invoke_infos_;
BitTable<InlineInfo::kCount> inline_infos_;
- BitTable<1> dex_register_masks_;
- BitTable<1> dex_register_maps_;
+ BitTable<MaskInfo::kCount> dex_register_masks_;
+ BitTable<DexRegisterMapInfo::kCount> dex_register_maps_;
BitTable<DexRegisterInfo::kCount> dex_register_catalog_;
uint32_t number_of_dex_registers_; // Excludes any inlined methods.
-
- friend class OatDumper;
};
#undef ELEMENT_BYTE_OFFSET_AFTER
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 4a53425477..7a7a80e4b6 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3658,7 +3658,7 @@ class ReferenceMapVisitor : public StackVisitor {
REQUIRES_SHARED(Locks::mutator_lock_) {
bool found = false;
for (size_t dex_reg = 0; dex_reg != number_of_dex_registers; ++dex_reg) {
- DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(dex_reg);
+ DexRegisterLocation location = dex_register_map[dex_reg];
if (location.GetKind() == kind && static_cast<size_t>(location.GetValue()) == index) {
visitor(ref, dex_reg, stack_visitor);
found = true;
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index c64e7bbca1..206418fbc6 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -26,6 +26,7 @@
#include "base/enums.h"
#include "class_linker.h"
#include "entrypoints/quick/quick_entrypoints_enum.h"
+#include "entrypoints/runtime_asm_entrypoints.h"
#include "hidden_api.h"
#include "jni/jni_internal.h"
#include "mirror/class.h"
@@ -98,6 +99,7 @@ jmethodID WellKnownClasses::java_lang_Long_valueOf;
jmethodID WellKnownClasses::java_lang_ref_FinalizerReference_add;
jmethodID WellKnownClasses::java_lang_ref_ReferenceQueue_add;
jmethodID WellKnownClasses::java_lang_reflect_Parameter_init;
+jmethodID WellKnownClasses::java_lang_reflect_Proxy_init;
jmethodID WellKnownClasses::java_lang_reflect_Proxy_invoke;
jmethodID WellKnownClasses::java_lang_Runtime_nativeLoad;
jmethodID WellKnownClasses::java_lang_Short_valueOf;
@@ -418,6 +420,14 @@ void WellKnownClasses::LateInit(JNIEnv* env) {
CacheMethod(env, java_lang_Runtime.get(), true, "nativeLoad",
"(Ljava/lang/String;Ljava/lang/ClassLoader;)"
"Ljava/lang/String;");
+ java_lang_reflect_Proxy_init =
+ CacheMethod(env, java_lang_reflect_Proxy, false, "<init>",
+ "(Ljava/lang/reflect/InvocationHandler;)V");
+ // This invariant is important since otherwise we will have the entire proxy invoke system
+ // confused.
+ DCHECK_NE(
+ jni::DecodeArtMethod(java_lang_reflect_Proxy_init)->GetEntryPointFromQuickCompiledCode(),
+ GetQuickInstrumentationEntryPoint());
java_lang_reflect_Proxy_invoke =
CacheMethod(env, java_lang_reflect_Proxy, true, "invoke",
"(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/Method;"
@@ -484,6 +494,7 @@ void WellKnownClasses::Clear() {
java_lang_ref_FinalizerReference_add = nullptr;
java_lang_ref_ReferenceQueue_add = nullptr;
java_lang_reflect_Parameter_init = nullptr;
+ java_lang_reflect_Proxy_init = nullptr;
java_lang_reflect_Proxy_invoke = nullptr;
java_lang_Runtime_nativeLoad = nullptr;
java_lang_Short_valueOf = nullptr;
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index c81062f594..ce5ab1df84 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -108,6 +108,7 @@ struct WellKnownClasses {
static jmethodID java_lang_ref_FinalizerReference_add;
static jmethodID java_lang_ref_ReferenceQueue_add;
static jmethodID java_lang_reflect_Parameter_init;
+ static jmethodID java_lang_reflect_Proxy_init;
static jmethodID java_lang_reflect_Proxy_invoke;
static jmethodID java_lang_Runtime_nativeLoad;
static jmethodID java_lang_Short_valueOf;
diff --git a/test/004-ReferenceMap/build b/test/004-ReferenceMap/build
index 08987b556c..3bb63ca624 100644
--- a/test/004-ReferenceMap/build
+++ b/test/004-ReferenceMap/build
@@ -21,6 +21,5 @@ set -e
# (see b/19467889)
mkdir classes
${JAVAC} -d classes `find src -name '*.java'`
-${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
- --dump-width=1000 ${DX_FLAGS} classes
+${DX} -JXmx256m --debug --dex --output=classes.dex ${DX_FLAGS} classes
zip $TEST_NAME.jar classes.dex
diff --git a/test/004-StackWalk/build b/test/004-StackWalk/build
index 08987b556c..3bb63ca624 100644
--- a/test/004-StackWalk/build
+++ b/test/004-StackWalk/build
@@ -21,6 +21,5 @@ set -e
# (see b/19467889)
mkdir classes
${JAVAC} -d classes `find src -name '*.java'`
-${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
- --dump-width=1000 ${DX_FLAGS} classes
+${DX} -JXmx256m --debug --dex --output=classes.dex ${DX_FLAGS} classes
zip $TEST_NAME.jar classes.dex
diff --git a/test/004-ThreadStress/run b/test/004-ThreadStress/run
index 8004036868..067e0d0407 100755
--- a/test/004-ThreadStress/run
+++ b/test/004-ThreadStress/run
@@ -15,7 +15,29 @@
# limitations under the License.
# Enable lock contention logging.
-${RUN} --runtime-option -Xlockprofthreshold:10 "${@}"
+if [[ "x$ART_DEFAULT_GC_TYPE" = xGSS ]]; then
+ # NonMovingAlloc operations fail an assertion with the Generational
+ # Semi-Space (GSS) collector (see b/72738921); disable them for now
+ # by explicitly assigning frequencies to operations when the GSS
+ # collector is used.
+ #
+ # Note: The trick to use command substitution to have comments within
+ # a multi-line command is from https://stackoverflow.com/a/12797512.
+ ${RUN} --runtime-option -Xlockprofthreshold:10 "${@}" Main \
+ -oom:0.005 `# 1/200` \
+ -sigquit:0.095 `# 19/200` \
+ -alloc:0.225 `# 45/200` \
+ -largealloc:0.05 `# 10/200` \
+ -nonmovingalloc:0.0 `# 0/200` \
+ -stacktrace:0.1 `# 20/200` \
+ -exit:0.225 `# 45/200` \
+ -sleep:0.125 `# 25/200` \
+ -timedwait:0.05 `# 10/200` \
+ -wait:0.075 `# 15/200` \
+ -queuedwait:0.05 `# 10/200`
+else
+ ${RUN} --runtime-option -Xlockprofthreshold:10 "${@}"
+fi
return_status1=$?
# Run locks-only mode with stack-dump lock profiling. Reduce the number of total operations from
diff --git a/test/004-ThreadStress/src-art/Main.java b/test/004-ThreadStress/src-art/Main.java
index a142934638..3a89f4f166 100644
--- a/test/004-ThreadStress/src-art/Main.java
+++ b/test/004-ThreadStress/src-art/Main.java
@@ -315,11 +315,9 @@ public class Main implements Runnable {
Map<Operation, Double> frequencyMap = new HashMap<Operation, Double>();
frequencyMap.put(new OOM(), 0.005); // 1/200
frequencyMap.put(new SigQuit(), 0.095); // 19/200
- frequencyMap.put(new Alloc(), 0.225); // 45/200
+ frequencyMap.put(new Alloc(), 0.2); // 40/200
frequencyMap.put(new LargeAlloc(), 0.05); // 10/200
- // TODO: NonMovingAlloc operations fail an assertion with the
- // GSS collector (see b/72738921); disable them for now.
- frequencyMap.put(new NonMovingAlloc(), 0.0); // 0/200
+ frequencyMap.put(new NonMovingAlloc(), 0.025); // 5/200
frequencyMap.put(new StackTrace(), 0.1); // 20/200
frequencyMap.put(new Exit(), 0.225); // 45/200
frequencyMap.put(new Sleep(), 0.125); // 25/200
@@ -379,6 +377,8 @@ public class Main implements Runnable {
op = new Alloc();
} else if (split[0].equals("-largealloc")) {
op = new LargeAlloc();
+ } else if (split[0].equals("-nonmovingalloc")) {
+ op = new NonMovingAlloc();
} else if (split[0].equals("-stacktrace")) {
op = new StackTrace();
} else if (split[0].equals("-exit")) {
diff --git a/test/022-interface/build b/test/022-interface/build
index f6aad91e97..ab1c822ebf 100644
--- a/test/022-interface/build
+++ b/test/022-interface/build
@@ -17,6 +17,6 @@
# Stop if something fails.
set -e
-${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
+${DX} --debug --dex --output=classes.dex classes
zip $TEST_NAME.jar classes.dex
diff --git a/test/091-override-package-private-method/build b/test/091-override-package-private-method/build
index ea12b3a540..e5fa6693a3 100755
--- a/test/091-override-package-private-method/build
+++ b/test/091-override-package-private-method/build
@@ -24,8 +24,8 @@ mkdir classes-ex
mv classes/OverridePackagePrivateMethodSuper.class classes-ex
if [ ${NEED_DEX} = "true" ]; then
- ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes
zip $TEST_NAME.jar classes.dex
- ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes-ex
zip ${TEST_NAME}-ex.jar classes.dex
fi
diff --git a/test/111-unresolvable-exception/build b/test/111-unresolvable-exception/build
index 6fe73af8d8..f24c5b2004 100644
--- a/test/111-unresolvable-exception/build
+++ b/test/111-unresolvable-exception/build
@@ -22,6 +22,6 @@ ${JAVAC} -d classes `find src -name '*.java'`
rm classes/TestException.class
if [ ${NEED_DEX} = "true" ]; then
- ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes
zip $TEST_NAME.jar classes.dex
fi
diff --git a/test/113-multidex/build b/test/113-multidex/build
index f945563939..4ad7cb9134 100644
--- a/test/113-multidex/build
+++ b/test/113-multidex/build
@@ -29,9 +29,9 @@ rm classes2/Second.class classes2/FillerA.class classes2/FillerB.class classes2/
if [ ${NEED_DEX} = "true" ]; then
# All except Main
- ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes
# Only Main
- ${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex classes2
+ ${DX} -JXmx256m --debug --dex --output=classes2.dex classes2
zip $TEST_NAME.jar classes.dex classes2.dex
fi
diff --git a/test/126-miranda-multidex/build b/test/126-miranda-multidex/build
index cf19855316..b4bb88d644 100644
--- a/test/126-miranda-multidex/build
+++ b/test/126-miranda-multidex/build
@@ -29,9 +29,9 @@ rm classes2/Main.class classes2/MirandaAbstract.class classes2/MirandaClass*.cla
if [ ${NEED_DEX} = "true" ]; then
# All except Main
- ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes
# Only Main
- ${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex classes2
+ ${DX} -JXmx256m --debug --dex --output=classes2.dex classes2
zip $TEST_NAME.jar classes.dex classes2.dex
fi
diff --git a/test/127-checker-secondarydex/build b/test/127-checker-secondarydex/build
index 712774f7ef..c23b7613b9 100755
--- a/test/127-checker-secondarydex/build
+++ b/test/127-checker-secondarydex/build
@@ -24,8 +24,8 @@ mkdir classes-ex
mv classes/Super.class classes-ex
if [ ${NEED_DEX} = "true" ]; then
- ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes
zip $TEST_NAME.jar classes.dex
- ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes-ex
zip ${TEST_NAME}-ex.jar classes.dex
fi
diff --git a/test/138-duplicate-classes-check2/build b/test/138-duplicate-classes-check2/build
index 76d535abf1..3ff15aae38 100755
--- a/test/138-duplicate-classes-check2/build
+++ b/test/138-duplicate-classes-check2/build
@@ -25,8 +25,8 @@ ${JAVAC} -d classes-ex `find src-ex -name '*.java'`
rm classes-ex/A.class
if [ ${NEED_DEX} = "true" ]; then
- ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes
zip ${TEST_NAME}.jar classes.dex
- ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex
+ ${DX} -JXmx256m --debug --dex --output=classes.dex classes-ex
zip ${TEST_NAME}-ex.jar classes.dex
fi
diff --git a/test/477-checker-bound-type/src/Main.java b/test/477-checker-bound-type/src/Main.java
index 2504ab2839..237e4dafb6 100644
--- a/test/477-checker-bound-type/src/Main.java
+++ b/test/477-checker-bound-type/src/Main.java
@@ -57,5 +57,79 @@ public class Main {
}
}
- public static void main(String[] args) { }
+ /// CHECK-START: void Main.boundTypeInLoop(int[]) licm (before)
+ /// CHECK-DAG: <<Param:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<BoundT:l\d+>> BoundType [<<Param>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArrayLength [<<BoundT>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.boundTypeInLoop(int[]) licm (after)
+ /// CHECK-DAG: <<Param:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<BoundT:l\d+>> BoundType [<<Param>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArrayLength [<<BoundT>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-NOT: BoundType
+
+ /// CHECK-START: void Main.boundTypeInLoop(int[]) loop_optimization (after)
+ /// CHECK-DAG: <<Param:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<BoundTA:l\d+>> BoundType [<<Param>>] loop:none
+ /// CHECK-DAG: ArrayLength [<<BoundTA>>] loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<BoundT:l\d+>> BoundType [<<Param>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArrayLength [<<BoundT>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.boundTypeInLoop(int[]) GVN$after_arch (after)
+ /// CHECK-DAG: <<Param:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<BoundTA:l\d+>> BoundType [<<Param>>] loop:none
+ /// CHECK-DAG: ArrayLength [<<BoundTA>>] loop:none
+ /// CHECK-DAG: ArrayGet loop:none
+ /// CHECK-DAG: ArraySet loop:none
+ /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-NOT: BoundType
+ /// CHECK-NOT: ArrayLength
+ private static void boundTypeInLoop(int[] a) {
+ for (int i = 0; a != null && i < a.length; i++) {
+ a[i] += 1;
+ }
+ }
+
+ // BoundType must not be hoisted by LICM, in this example it leads to ArrayLength being
+ // hoisted as well which is invalid.
+ //
+ /// CHECK-START: void Main.BoundTypeNoLICM(java.lang.Object) licm (before)
+ /// CHECK-DAG: <<Param:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: SuspendCheck loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Bound1:l\d+>> BoundType [<<Param>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Bound2:l\d+>> BoundType [<<Bound1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArrayLength [<<Bound2>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START: void Main.BoundTypeNoLICM(java.lang.Object) licm (after)
+ /// CHECK-DAG: <<Param:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: SuspendCheck loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Bound1:l\d+>> BoundType [<<Param>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Bound2:l\d+>> BoundType [<<Bound1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArrayLength [<<Bound2>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-NOT: BoundType loop:none
+ private static void BoundTypeNoLICM(Object obj) {
+ int i = 0;
+ while (obj instanceof int[]) {
+ int[] a = (int[])obj;
+ a[0] = 1;
+ }
+ }
+
+ public static void main(String[] args) { }
}
diff --git a/test/530-checker-lse2/build b/test/530-checker-lse2/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/530-checker-lse2/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/565-checker-rotate/build b/test/565-checker-rotate/build
deleted file mode 100644
index 10ffcc537d..0000000000
--- a/test/565-checker-rotate/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/565-checker-rotate/smali/Main2.smali b/test/565-checker-rotate/smali/Main2.smali
new file mode 100644
index 0000000000..ca5027e971
--- /dev/null
+++ b/test/565-checker-rotate/smali/Main2.smali
@@ -0,0 +1,165 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LMain2;
+.super Ljava/lang/Object;
+
+## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) intrinsics_recognition (after)
+## CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+## CHECK: <<ArgVal:z\d+>> ParameterValue
+## CHECK: <<ArgDist:i\d+>> ParameterValue
+## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+## CHECK-DAG: <<One:i\d+>> IntConstant 1
+## CHECK-DAG: <<Val:i\d+>> Phi [<<One>>,<<Zero>>]
+## CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Val>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+## CHECK-DAG: Return [<<Result>>]
+
+## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) instruction_simplifier (after)
+## CHECK: <<ArgVal:z\d+>> ParameterValue
+## CHECK: <<ArgDist:i\d+>> ParameterValue
+## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+## CHECK-DAG: <<One:i\d+>> IntConstant 1
+## CHECK-DAG: <<Val:i\d+>> Phi [<<One>>,<<Zero>>]
+## CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
+## CHECK-DAG: <<Result:i\d+>> Ror [<<Val>>,<<NegDist>>]
+## CHECK-DAG: Return [<<Result>>]
+
+## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) instruction_simplifier (after)
+## CHECK-NOT: InvokeStaticOrDirect
+
+## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) select_generator (after)
+## CHECK: <<ArgVal:z\d+>> ParameterValue
+## CHECK: <<ArgDist:i\d+>> ParameterValue
+## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+## CHECK-DAG: <<One:i\d+>> IntConstant 1
+## CHECK-DAG: <<SelVal:i\d+>> Select [<<Zero>>,<<One>>,<<ArgVal>>]
+## CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
+## CHECK-DAG: <<Result:i\d+>> Ror [<<SelVal>>,<<NegDist>>]
+## CHECK-DAG: Return [<<Result>>]
+
+## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) select_generator (after)
+## CHECK-NOT: Phi
+
+## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) instruction_simplifier$after_bce (after)
+## CHECK: <<ArgVal:z\d+>> ParameterValue
+## CHECK: <<ArgDist:i\d+>> ParameterValue
+## CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
+## CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
+## CHECK-DAG: Return [<<Result>>]
+
+## CHECK-START: int Main2.rotateLeftBoolean(boolean, int) instruction_simplifier$after_bce (after)
+## CHECK-NOT: Select
+
+# Original java source
+#
+# private static int rotateLeftBoolean(boolean value, int distance) {
+# return Integer.rotateLeft(value ? 1 : 0, distance);
+# }
+
+.method public static rotateLeftBoolean(ZI)I
+ .registers 3
+ .param p0, "value" # Z
+ .param p1, "distance" # I
+
+ .prologue
+ .line 66
+ if-eqz p0, :cond_8
+
+ const/4 v0, 0x1
+
+ :goto_3
+ invoke-static {v0, p1}, Ljava/lang/Integer;->rotateLeft(II)I
+
+ move-result v0
+
+ return v0
+
+ :cond_8
+ const/4 v0, 0x0
+
+ goto :goto_3
+.end method
+
+## CHECK-START: int Main2.rotateRightBoolean(boolean, int) intrinsics_recognition (after)
+## CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+## CHECK: <<ArgVal:z\d+>> ParameterValue
+## CHECK: <<ArgDist:i\d+>> ParameterValue
+## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+## CHECK-DAG: <<One:i\d+>> IntConstant 1
+## CHECK-DAG: <<Val:i\d+>> Phi [<<One>>,<<Zero>>]
+## CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Val>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+## CHECK-DAG: Return [<<Result>>]
+
+## CHECK-START: int Main2.rotateRightBoolean(boolean, int) instruction_simplifier (after)
+## CHECK: <<ArgVal:z\d+>> ParameterValue
+## CHECK: <<ArgDist:i\d+>> ParameterValue
+## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+## CHECK-DAG: <<One:i\d+>> IntConstant 1
+## CHECK-DAG: <<Val:i\d+>> Phi [<<One>>,<<Zero>>]
+## CHECK-DAG: <<Result:i\d+>> Ror [<<Val>>,<<ArgDist>>]
+## CHECK-DAG: Return [<<Result>>]
+
+## CHECK-START: int Main2.rotateRightBoolean(boolean, int) instruction_simplifier (after)
+## CHECK-NOT: InvokeStaticOrDirect
+
+## CHECK-START: int Main2.rotateRightBoolean(boolean, int) select_generator (after)
+## CHECK: <<ArgVal:z\d+>> ParameterValue
+## CHECK: <<ArgDist:i\d+>> ParameterValue
+## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
+## CHECK-DAG: <<One:i\d+>> IntConstant 1
+## CHECK-DAG: <<SelVal:i\d+>> Select [<<Zero>>,<<One>>,<<ArgVal>>]
+## CHECK-DAG: <<Result:i\d+>> Ror [<<SelVal>>,<<ArgDist>>]
+## CHECK-DAG: Return [<<Result>>]
+
+## CHECK-START: int Main2.rotateRightBoolean(boolean, int) select_generator (after)
+## CHECK-NOT: Phi
+
+## CHECK-START: int Main2.rotateRightBoolean(boolean, int) instruction_simplifier$after_bce (after)
+## CHECK: <<ArgVal:z\d+>> ParameterValue
+## CHECK: <<ArgDist:i\d+>> ParameterValue
+## CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
+## CHECK-DAG: Return [<<Result>>]
+
+## CHECK-START: int Main2.rotateRightBoolean(boolean, int) instruction_simplifier$after_bce (after)
+## CHECK-NOT: Select
+
+# Original java source:
+#
+# private static int rotateRightBoolean(boolean value, int distance) {
+# return Integer.rotateRight(value ? 1 : 0, distance);
+# }
+
+.method public static rotateRightBoolean(ZI)I
+ .registers 3
+ .param p0, "value" # Z
+ .param p1, "distance" # I
+
+ .prologue
+ .line 219
+ if-eqz p0, :cond_8
+
+ const/4 v0, 0x1
+
+ :goto_3
+ invoke-static {v0, p1}, Ljava/lang/Integer;->rotateRight(II)I
+
+ move-result v0
+
+ return v0
+
+ :cond_8
+ const/4 v0, 0x0
+
+ goto :goto_3
+.end method
diff --git a/test/565-checker-rotate/src-art/Main.java b/test/565-checker-rotate/src-art/Main.java
new file mode 100644
index 0000000000..b9e1315bd4
--- /dev/null
+++ b/test/565-checker-rotate/src-art/Main.java
@@ -0,0 +1,546 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+
+public class Main {
+
+ private static Class main2;
+
+ /// CHECK-START: int Main.rotateLeftByte(byte, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:b\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateLeftByte(byte, int) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:b\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
+ /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateLeftByte(byte, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int rotateLeftByte(byte value, int distance) {
+ return Integer.rotateLeft(value, distance);
+ }
+
+ /// CHECK-START: int Main.rotateLeftShort(short, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:s\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateLeftShort(short, int) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:s\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
+ /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateLeftShort(short, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int rotateLeftShort(short value, int distance) {
+ return Integer.rotateLeft(value, distance);
+ }
+
+ /// CHECK-START: int Main.rotateLeftChar(char, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:c\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateLeftChar(char, int) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:c\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
+ /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateLeftChar(char, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int rotateLeftChar(char value, int distance) {
+ return Integer.rotateLeft(value, distance);
+ }
+
+ /// CHECK-START: int Main.rotateLeftInt(int, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:i\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateLeftInt(int, int) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:i\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
+ /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateLeftInt(int, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int rotateLeftInt(int value, int distance) {
+ return Integer.rotateLeft(value, distance);
+ }
+
+ /// CHECK-START: long Main.rotateLeftLong(long, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:j\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:LongRotateLeft
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: long Main.rotateLeftLong(long, int) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:j\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
+ /// CHECK-DAG: <<Result:j\d+>> Ror [<<ArgVal>>,<<NegDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: long Main.rotateLeftLong(long, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static long rotateLeftLong(long value, int distance) {
+ return Long.rotateLeft(value, distance);
+ }
+
+ /// CHECK-START: int Main.rotateRightByte(byte, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:b\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateRightByte(byte, int) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:b\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateRightByte(byte, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int rotateRightByte(byte value, int distance) {
+ return Integer.rotateRight(value, distance);
+ }
+
+ /// CHECK-START: int Main.rotateRightShort(short, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:s\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateRightShort(short, int) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:s\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateRightShort(short, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int rotateRightShort(short value, int distance) {
+ return Integer.rotateRight(value, distance);
+ }
+
+ /// CHECK-START: int Main.rotateRightChar(char, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:c\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateRightChar(char, int) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:c\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateRightChar(char, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int rotateRightChar(char value, int distance) {
+ return Integer.rotateRight(value, distance);
+ }
+
+ /// CHECK-START: int Main.rotateRightInt(int, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:i\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateRightInt(int, int) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:i\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateRightInt(int, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int rotateRightInt(int value, int distance) {
+ return Integer.rotateRight(value, distance);
+ }
+
+ /// CHECK-START: long Main.rotateRightLong(long, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:j\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:LongRotateRight
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: long Main.rotateRightLong(long, int) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:j\d+>> ParameterValue
+ /// CHECK: <<ArgDist:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:j\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: long Main.rotateRightLong(long, int) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static long rotateRightLong(long value, int distance) {
+ return Long.rotateRight(value, distance);
+ }
+
+
+ /// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:i\d+>> ParameterValue
+ /// CHECK: <<ArgDist:b\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:i\d+>> ParameterValue
+ /// CHECK: <<ArgDist:b\d+>> ParameterValue
+ /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
+ /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int rotateLeftIntWithByteDistance(int value, byte distance) {
+ return Integer.rotateLeft(value, distance);
+ }
+
+ /// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
+ /// CHECK: <<ArgVal:i\d+>> ParameterValue
+ /// CHECK: <<ArgDist:b\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) instruction_simplifier (after)
+ /// CHECK: <<ArgVal:i\d+>> ParameterValue
+ /// CHECK: <<ArgDist:b\d+>> ParameterValue
+ /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
+ /// CHECK-DAG: Return [<<Result>>]
+
+ /// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) instruction_simplifier (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ private static int rotateRightIntWithByteDistance(int value, byte distance) {
+ return Integer.rotateRight(value, distance);
+ }
+
+
+ public static void testRotateLeftBoolean() throws Exception {
+ Method rotateLeftBoolean = main2.getMethod("rotateLeftBoolean", boolean.class, int.class);
+ for (int i = 0; i < 40; i++) { // overshoot a bit
+ int j = i & 31;
+ expectEqualsInt(0, (int)rotateLeftBoolean.invoke(null, false, i));
+ expectEqualsInt(1 << i, (int)rotateLeftBoolean.invoke(null, true, i));
+ }
+ }
+
+ public static void testRotateLeftByte() {
+ expectEqualsInt(0x00000001, rotateLeftByte((byte)0x01, 0));
+ expectEqualsInt(0x00000002, rotateLeftByte((byte)0x01, 1));
+ expectEqualsInt(0x80000000, rotateLeftByte((byte)0x01, 31));
+ expectEqualsInt(0x00000001, rotateLeftByte((byte)0x01, 32)); // overshoot
+ expectEqualsInt(0xFFFFFF03, rotateLeftByte((byte)0x81, 1));
+ expectEqualsInt(0xFFFFFE07, rotateLeftByte((byte)0x81, 2));
+ expectEqualsInt(0x00000120, rotateLeftByte((byte)0x12, 4));
+ expectEqualsInt(0xFFFF9AFF, rotateLeftByte((byte)0x9A, 8));
+ for (int i = 0; i < 40; i++) { // overshoot a bit
+ int j = i & 31;
+ expectEqualsInt(0x00000000, rotateLeftByte((byte)0x0000, i));
+ expectEqualsInt(0xFFFFFFFF, rotateLeftByte((byte)0xFFFF, i));
+ expectEqualsInt((1 << j), rotateLeftByte((byte)0x0001, i));
+ expectEqualsInt((0x12 << j) | (0x12 >>> -j), rotateLeftByte((byte)0x12, i));
+ }
+ }
+
+ public static void testRotateLeftShort() {
+ expectEqualsInt(0x00000001, rotateLeftShort((short)0x0001, 0));
+ expectEqualsInt(0x00000002, rotateLeftShort((short)0x0001, 1));
+ expectEqualsInt(0x80000000, rotateLeftShort((short)0x0001, 31));
+ expectEqualsInt(0x00000001, rotateLeftShort((short)0x0001, 32)); // overshoot
+ expectEqualsInt(0xFFFF0003, rotateLeftShort((short)0x8001, 1));
+ expectEqualsInt(0xFFFE0007, rotateLeftShort((short)0x8001, 2));
+ expectEqualsInt(0x00012340, rotateLeftShort((short)0x1234, 4));
+ expectEqualsInt(0xFF9ABCFF, rotateLeftShort((short)0x9ABC, 8));
+ for (int i = 0; i < 40; i++) { // overshoot a bit
+ int j = i & 31;
+ expectEqualsInt(0x00000000, rotateLeftShort((short)0x0000, i));
+ expectEqualsInt(0xFFFFFFFF, rotateLeftShort((short)0xFFFF, i));
+ expectEqualsInt((1 << j), rotateLeftShort((short)0x0001, i));
+ expectEqualsInt((0x1234 << j) | (0x1234 >>> -j), rotateLeftShort((short)0x1234, i));
+ }
+ }
+
+ public static void testRotateLeftChar() {
+ expectEqualsInt(0x00000001, rotateLeftChar((char)0x0001, 0));
+ expectEqualsInt(0x00000002, rotateLeftChar((char)0x0001, 1));
+ expectEqualsInt(0x80000000, rotateLeftChar((char)0x0001, 31));
+ expectEqualsInt(0x00000001, rotateLeftChar((char)0x0001, 32)); // overshoot
+ expectEqualsInt(0x00010002, rotateLeftChar((char)0x8001, 1));
+ expectEqualsInt(0x00020004, rotateLeftChar((char)0x8001, 2));
+ expectEqualsInt(0x00012340, rotateLeftChar((char)0x1234, 4));
+ expectEqualsInt(0x009ABC00, rotateLeftChar((char)0x9ABC, 8));
+ expectEqualsInt(0x00FF0000, rotateLeftChar((char)0xFF00, 8));
+ for (int i = 0; i < 40; i++) { // overshoot a bit
+ int j = i & 31;
+ expectEqualsInt(0x00000000, rotateLeftChar((char)0x0000, i));
+ expectEqualsInt((1 << j), rotateLeftChar((char)0x0001, i));
+ expectEqualsInt((0x1234 << j) | (0x1234 >>> -j), rotateLeftChar((char)0x1234, i));
+ }
+ }
+
+ public static void testRotateLeftInt() {
+ expectEqualsInt(0x00000001, rotateLeftInt(0x00000001, 0));
+ expectEqualsInt(0x00000002, rotateLeftInt(0x00000001, 1));
+ expectEqualsInt(0x80000000, rotateLeftInt(0x00000001, 31));
+ expectEqualsInt(0x00000001, rotateLeftInt(0x00000001, 32)); // overshoot
+ expectEqualsInt(0x00000003, rotateLeftInt(0x80000001, 1));
+ expectEqualsInt(0x00000006, rotateLeftInt(0x80000001, 2));
+ expectEqualsInt(0x23456781, rotateLeftInt(0x12345678, 4));
+ expectEqualsInt(0xBCDEF09A, rotateLeftInt(0x9ABCDEF0, 8));
+ for (int i = 0; i < 40; i++) { // overshoot a bit
+ int j = i & 31;
+ expectEqualsInt(0x00000000, rotateLeftInt(0x00000000, i));
+ expectEqualsInt(0xFFFFFFFF, rotateLeftInt(0xFFFFFFFF, i));
+ expectEqualsInt(1 << j, rotateLeftInt(0x00000001, i));
+ expectEqualsInt((0x12345678 << j) | (0x12345678 >>> -j), rotateLeftInt(0x12345678, i));
+ }
+ }
+
+ public static void testRotateLeftLong() {
+ expectEqualsLong(0x0000000000000001L, rotateLeftLong(0x0000000000000001L, 0));
+ expectEqualsLong(0x0000000000000002L, rotateLeftLong(0x0000000000000001L, 1));
+ expectEqualsLong(0x8000000000000000L, rotateLeftLong(0x0000000000000001L, 63));
+ expectEqualsLong(0x0000000000000001L, rotateLeftLong(0x0000000000000001L, 64)); // overshoot
+ expectEqualsLong(0x0000000000000003L, rotateLeftLong(0x8000000000000001L, 1));
+ expectEqualsLong(0x0000000000000006L, rotateLeftLong(0x8000000000000001L, 2));
+ expectEqualsLong(0x23456789ABCDEF01L, rotateLeftLong(0x123456789ABCDEF0L, 4));
+ expectEqualsLong(0x3456789ABCDEF012L, rotateLeftLong(0x123456789ABCDEF0L, 8));
+ for (int i = 0; i < 70; i++) { // overshoot a bit
+ int j = i & 63;
+ expectEqualsLong(0x0000000000000000L, rotateLeftLong(0x0000000000000000L, i));
+ expectEqualsLong(0xFFFFFFFFFFFFFFFFL, rotateLeftLong(0xFFFFFFFFFFFFFFFFL, i));
+ expectEqualsLong(1L << j, rotateLeftLong(0x0000000000000001, i));
+ expectEqualsLong((0x123456789ABCDEF0L << j) | (0x123456789ABCDEF0L >>> -j),
+ rotateLeftLong(0x123456789ABCDEF0L, i));
+ }
+ }
+
+ public static void testRotateRightBoolean() throws Exception {
+ Method rotateRightBoolean = main2.getMethod("rotateRightBoolean", boolean.class, int.class);
+ for (int i = 0; i < 40; i++) { // overshoot a bit
+ int j = i & 31;
+ expectEqualsInt(0, (int)rotateRightBoolean.invoke(null, false, i));
+ expectEqualsInt(1 << (32 - i), (int)rotateRightBoolean.invoke(null, true, i));
+ }
+ }
+
+ public static void testRotateRightByte() {
+ expectEqualsInt(0xFFFFFF80, rotateRightByte((byte)0x80, 0));
+ expectEqualsInt(0x7FFFFFC0, rotateRightByte((byte)0x80, 1));
+ expectEqualsInt(0xFFFFFF01, rotateRightByte((byte)0x80, 31));
+ expectEqualsInt(0xFFFFFF80, rotateRightByte((byte)0x80, 32)); // overshoot
+ expectEqualsInt(0xFFFFFFC0, rotateRightByte((byte)0x81, 1));
+ expectEqualsInt(0x7FFFFFE0, rotateRightByte((byte)0x81, 2));
+ expectEqualsInt(0x20000001, rotateRightByte((byte)0x12, 4));
+ expectEqualsInt(0x9AFFFFFF, rotateRightByte((byte)0x9A, 8));
+ for (int i = 0; i < 40; i++) { // overshoot a bit
+ int j = i & 31;
+ expectEqualsInt(0x00000000, rotateRightByte((byte)0x00, i));
+ expectEqualsInt(0xFFFFFFFF, rotateRightByte((byte)0xFF, i));
+ expectEqualsInt(1 << (32 - j), rotateRightByte((byte)0x01, i));
+ expectEqualsInt((0x12 >>> j) | (0x12 << -j), rotateRightByte((byte)0x12, i));
+ }
+ }
+
+ public static void testRotateRightShort() {
+ expectEqualsInt(0xFFFF8000, rotateRightShort((short)0x8000, 0));
+ expectEqualsInt(0x7FFFC000, rotateRightShort((short)0x8000, 1));
+ expectEqualsInt(0xFFFF0001, rotateRightShort((short)0x8000, 31));
+ expectEqualsInt(0xFFFF8000, rotateRightShort((short)0x8000, 32)); // overshoot
+ expectEqualsInt(0xFFFFC000, rotateRightShort((short)0x8001, 1));
+ expectEqualsInt(0x7FFFE000, rotateRightShort((short)0x8001, 2));
+ expectEqualsInt(0x40000123, rotateRightShort((short)0x1234, 4));
+ expectEqualsInt(0xBCFFFF9A, rotateRightShort((short)0x9ABC, 8));
+ for (int i = 0; i < 40; i++) { // overshoot a bit
+ int j = i & 31;
+ expectEqualsInt(0x00000000, rotateRightShort((short)0x0000, i));
+ expectEqualsInt(0xFFFFFFFF, rotateRightShort((short)0xFFFF, i));
+ expectEqualsInt(1 << (32 - j), rotateRightShort((short)0x0001, i));
+ expectEqualsInt((0x1234 >>> j) | (0x1234 << -j), rotateRightShort((short)0x1234, i));
+ }
+ }
+
+ public static void testRotateRightChar() {
+ expectEqualsInt(0x00008000, rotateRightChar((char)0x8000, 0));
+ expectEqualsInt(0x00004000, rotateRightChar((char)0x8000, 1));
+ expectEqualsInt(0x00010000, rotateRightChar((char)0x8000, 31));
+ expectEqualsInt(0x00008000, rotateRightChar((char)0x8000, 32)); // overshoot
+ expectEqualsInt(0x80004000, rotateRightChar((char)0x8001, 1));
+ expectEqualsInt(0x40002000, rotateRightChar((char)0x8001, 2));
+ expectEqualsInt(0x40000123, rotateRightChar((char)0x1234, 4));
+ expectEqualsInt(0xBC00009A, rotateRightChar((char)0x9ABC, 8));
+ for (int i = 0; i < 40; i++) { // overshoot a bit
+ int j = i & 31;
+ expectEqualsInt(0x00000000, rotateRightChar((char)0x0000, i));
+ expectEqualsInt(1 << (32 - j), rotateRightChar((char)0x0001, i));
+ expectEqualsInt((0x1234 >>> j) | (0x1234 << -j), rotateRightChar((char)0x1234, i));
+ }
+ }
+
+ public static void testRotateRightInt() {
+ expectEqualsInt(0x80000000, rotateRightInt(0x80000000, 0));
+ expectEqualsInt(0x40000000, rotateRightInt(0x80000000, 1));
+ expectEqualsInt(0x00000001, rotateRightInt(0x80000000, 31));
+ expectEqualsInt(0x80000000, rotateRightInt(0x80000000, 32)); // overshoot
+ expectEqualsInt(0xC0000000, rotateRightInt(0x80000001, 1));
+ expectEqualsInt(0x60000000, rotateRightInt(0x80000001, 2));
+ expectEqualsInt(0x81234567, rotateRightInt(0x12345678, 4));
+ expectEqualsInt(0xF09ABCDE, rotateRightInt(0x9ABCDEF0, 8));
+ for (int i = 0; i < 40; i++) { // overshoot a bit
+ int j = i & 31;
+ expectEqualsInt(0x00000000, rotateRightInt(0x00000000, i));
+ expectEqualsInt(0xFFFFFFFF, rotateRightInt(0xFFFFFFFF, i));
+ expectEqualsInt(0x80000000 >>> j, rotateRightInt(0x80000000, i));
+ expectEqualsInt((0x12345678 >>> j) | (0x12345678 << -j), rotateRightInt(0x12345678, i));
+ }
+ }
+
+ public static void testRotateRightLong() {
+ expectEqualsLong(0x8000000000000000L, rotateRightLong(0x8000000000000000L, 0));
+ expectEqualsLong(0x4000000000000000L, rotateRightLong(0x8000000000000000L, 1));
+ expectEqualsLong(0x0000000000000001L, rotateRightLong(0x8000000000000000L, 63));
+ expectEqualsLong(0x8000000000000000L, rotateRightLong(0x8000000000000000L, 64)); // overshoot
+ expectEqualsLong(0xC000000000000000L, rotateRightLong(0x8000000000000001L, 1));
+ expectEqualsLong(0x6000000000000000L, rotateRightLong(0x8000000000000001L, 2));
+ expectEqualsLong(0x0123456789ABCDEFL, rotateRightLong(0x123456789ABCDEF0L, 4));
+ expectEqualsLong(0xF0123456789ABCDEL, rotateRightLong(0x123456789ABCDEF0L, 8));
+ for (int i = 0; i < 70; i++) { // overshoot a bit
+ int j = i & 63;
+ expectEqualsLong(0x0000000000000000L, rotateRightLong(0x0000000000000000L, i));
+ expectEqualsLong(0xFFFFFFFFFFFFFFFFL, rotateRightLong(0xFFFFFFFFFFFFFFFFL, i));
+ expectEqualsLong(0x8000000000000000L >>> j, rotateRightLong(0x8000000000000000L, i));
+ expectEqualsLong((0x123456789ABCDEF0L >>> j) | (0x123456789ABCDEF0L << -j),
+ rotateRightLong(0x123456789ABCDEF0L, i));
+ }
+ }
+
+
+ public static void testRotateLeftIntWithByteDistance() {
+ expectEqualsInt(0x00000001, rotateLeftIntWithByteDistance(0x00000001, (byte)0));
+ expectEqualsInt(0x00000002, rotateLeftIntWithByteDistance(0x00000001, (byte)1));
+ expectEqualsInt(0x80000000, rotateLeftIntWithByteDistance(0x00000001, (byte)31));
+ expectEqualsInt(0x00000001, rotateLeftIntWithByteDistance(0x00000001, (byte)32)); // overshoot
+ expectEqualsInt(0x00000003, rotateLeftIntWithByteDistance(0x80000001, (byte)1));
+ expectEqualsInt(0x00000006, rotateLeftIntWithByteDistance(0x80000001, (byte)2));
+ expectEqualsInt(0x23456781, rotateLeftIntWithByteDistance(0x12345678, (byte)4));
+ expectEqualsInt(0xBCDEF09A, rotateLeftIntWithByteDistance(0x9ABCDEF0, (byte)8));
+ for (byte i = 0; i < 40; i++) { // overshoot a bit
+ byte j = (byte)(i & 31);
+ expectEqualsInt(0x00000000, rotateLeftIntWithByteDistance(0x00000000, i));
+ expectEqualsInt(0xFFFFFFFF, rotateLeftIntWithByteDistance(0xFFFFFFFF, i));
+ expectEqualsInt(1 << j, rotateLeftIntWithByteDistance(0x00000001, i));
+ expectEqualsInt((0x12345678 << j) | (0x12345678 >>> -j),
+ rotateLeftIntWithByteDistance(0x12345678, i));
+ }
+ }
+
+ public static void testRotateRightIntWithByteDistance() {
+ expectEqualsInt(0x80000000, rotateRightIntWithByteDistance(0x80000000, (byte)0));
+ expectEqualsInt(0x40000000, rotateRightIntWithByteDistance(0x80000000, (byte)1));
+ expectEqualsInt(0x00000001, rotateRightIntWithByteDistance(0x80000000, (byte)31));
+ expectEqualsInt(0x80000000, rotateRightIntWithByteDistance(0x80000000, (byte)32)); // overshoot
+ expectEqualsInt(0xC0000000, rotateRightIntWithByteDistance(0x80000001, (byte)1));
+ expectEqualsInt(0x60000000, rotateRightIntWithByteDistance(0x80000001, (byte)2));
+ expectEqualsInt(0x81234567, rotateRightIntWithByteDistance(0x12345678, (byte)4));
+ expectEqualsInt(0xF09ABCDE, rotateRightIntWithByteDistance(0x9ABCDEF0, (byte)8));
+ for (byte i = 0; i < 40; i++) { // overshoot a bit
+ byte j = (byte)(i & 31);
+ expectEqualsInt(0x00000000, rotateRightIntWithByteDistance(0x00000000, i));
+ expectEqualsInt(0xFFFFFFFF, rotateRightIntWithByteDistance(0xFFFFFFFF, i));
+ expectEqualsInt(0x80000000 >>> j, rotateRightIntWithByteDistance(0x80000000, i));
+ expectEqualsInt((0x12345678 >>> j) | (0x12345678 << -j),
+ rotateRightIntWithByteDistance(0x12345678, i));
+ }
+ }
+
+
+ public static void main(String args[]) throws Exception {
+ main2 = Class.forName("Main2");
+
+ testRotateLeftBoolean();
+ testRotateLeftByte();
+ testRotateLeftShort();
+ testRotateLeftChar();
+ testRotateLeftInt();
+ testRotateLeftLong();
+
+ testRotateRightBoolean();
+ testRotateRightByte();
+ testRotateRightShort();
+ testRotateRightChar();
+ testRotateRightInt();
+ testRotateRightLong();
+
+ // Also exercise distance values with types other than int.
+ testRotateLeftIntWithByteDistance();
+ testRotateRightIntWithByteDistance();
+
+ System.out.println("passed");
+ }
+
+
+ private static void expectEqualsInt(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEqualsLong(long expected, long result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+}
diff --git a/test/565-checker-rotate/src/Main.java b/test/565-checker-rotate/src/Main.java
index eb0e8688c0..79b8555878 100644
--- a/test/565-checker-rotate/src/Main.java
+++ b/test/565-checker-rotate/src/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -14,623 +14,9 @@
* limitations under the License.
*/
+// This file is just for running on the RI as the test is ART specific.
public class Main {
-
- /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:z\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
- /// CHECK-DAG: <<One:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Val:i\d+>> Phi [<<One>>,<<Zero>>]
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Val>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:z\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
- /// CHECK-DAG: <<One:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Val:i\d+>> Phi [<<One>>,<<Zero>>]
- /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<Val>>,<<NegDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) select_generator (after)
- /// CHECK: <<ArgVal:z\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
- /// CHECK-DAG: <<One:i\d+>> IntConstant 1
- /// CHECK-DAG: <<SelVal:i\d+>> Select [<<Zero>>,<<One>>,<<ArgVal>>]
- /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<SelVal>>,<<NegDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) select_generator (after)
- /// CHECK-NOT: Phi
-
- /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) instruction_simplifier$after_bce (after)
- /// CHECK: <<ArgVal:z\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) instruction_simplifier$after_bce (after)
- /// CHECK-NOT: Select
-
- private static int rotateLeftBoolean(boolean value, int distance) {
- return Integer.rotateLeft(value ? 1 : 0, distance);
- }
-
- /// CHECK-START: int Main.rotateLeftByte(byte, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:b\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftByte(byte, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:b\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftByte(byte, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static int rotateLeftByte(byte value, int distance) {
- return Integer.rotateLeft(value, distance);
- }
-
- /// CHECK-START: int Main.rotateLeftShort(short, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:s\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftShort(short, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:s\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftShort(short, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static int rotateLeftShort(short value, int distance) {
- return Integer.rotateLeft(value, distance);
- }
-
- /// CHECK-START: int Main.rotateLeftChar(char, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:c\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftChar(char, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:c\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftChar(char, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static int rotateLeftChar(char value, int distance) {
- return Integer.rotateLeft(value, distance);
- }
-
- /// CHECK-START: int Main.rotateLeftInt(int, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:i\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftInt(int, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:i\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftInt(int, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static int rotateLeftInt(int value, int distance) {
- return Integer.rotateLeft(value, distance);
- }
-
- /// CHECK-START: long Main.rotateLeftLong(long, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:j\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:LongRotateLeft
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: long Main.rotateLeftLong(long, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:j\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
- /// CHECK-DAG: <<Result:j\d+>> Ror [<<ArgVal>>,<<NegDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: long Main.rotateLeftLong(long, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static long rotateLeftLong(long value, int distance) {
- return Long.rotateLeft(value, distance);
- }
-
-
- /// CHECK-START: int Main.rotateRightBoolean(boolean, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:z\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
- /// CHECK-DAG: <<One:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Val:i\d+>> Phi [<<One>>,<<Zero>>]
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Val>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightBoolean(boolean, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:z\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
- /// CHECK-DAG: <<One:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Val:i\d+>> Phi [<<One>>,<<Zero>>]
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<Val>>,<<ArgDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightBoolean(boolean, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- /// CHECK-START: int Main.rotateRightBoolean(boolean, int) select_generator (after)
- /// CHECK: <<ArgVal:z\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
- /// CHECK-DAG: <<One:i\d+>> IntConstant 1
- /// CHECK-DAG: <<SelVal:i\d+>> Select [<<Zero>>,<<One>>,<<ArgVal>>]
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<SelVal>>,<<ArgDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightBoolean(boolean, int) select_generator (after)
- /// CHECK-NOT: Phi
-
- /// CHECK-START: int Main.rotateRightBoolean(boolean, int) instruction_simplifier$after_bce (after)
- /// CHECK: <<ArgVal:z\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightBoolean(boolean, int) instruction_simplifier$after_bce (after)
- /// CHECK-NOT: Select
-
- private static int rotateRightBoolean(boolean value, int distance) {
- return Integer.rotateRight(value ? 1 : 0, distance);
- }
-
- /// CHECK-START: int Main.rotateRightByte(byte, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:b\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightByte(byte, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:b\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightByte(byte, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static int rotateRightByte(byte value, int distance) {
- return Integer.rotateRight(value, distance);
- }
-
- /// CHECK-START: int Main.rotateRightShort(short, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:s\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightShort(short, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:s\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightShort(short, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static int rotateRightShort(short value, int distance) {
- return Integer.rotateRight(value, distance);
- }
-
- /// CHECK-START: int Main.rotateRightChar(char, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:c\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightChar(char, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:c\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightChar(char, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static int rotateRightChar(char value, int distance) {
- return Integer.rotateRight(value, distance);
- }
-
- /// CHECK-START: int Main.rotateRightInt(int, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:i\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightInt(int, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:i\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightInt(int, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static int rotateRightInt(int value, int distance) {
- return Integer.rotateRight(value, distance);
- }
-
- /// CHECK-START: long Main.rotateRightLong(long, int) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:j\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:LongRotateRight
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: long Main.rotateRightLong(long, int) instruction_simplifier (after)
- /// CHECK: <<ArgVal:j\d+>> ParameterValue
- /// CHECK: <<ArgDist:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:j\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: long Main.rotateRightLong(long, int) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static long rotateRightLong(long value, int distance) {
- return Long.rotateRight(value, distance);
- }
-
-
- /// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:i\d+>> ParameterValue
- /// CHECK: <<ArgDist:b\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) instruction_simplifier (after)
- /// CHECK: <<ArgVal:i\d+>> ParameterValue
- /// CHECK: <<ArgDist:b\d+>> ParameterValue
- /// CHECK-DAG: <<NegDist:i\d+>> Neg [<<ArgDist>>]
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<NegDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateLeftIntWithByteDistance(int, byte) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static int rotateLeftIntWithByteDistance(int value, byte distance) {
- return Integer.rotateLeft(value, distance);
- }
-
- /// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) intrinsics_recognition (after)
- /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod
- /// CHECK: <<ArgVal:i\d+>> ParameterValue
- /// CHECK: <<ArgDist:b\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) instruction_simplifier (after)
- /// CHECK: <<ArgVal:i\d+>> ParameterValue
- /// CHECK: <<ArgDist:b\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> Ror [<<ArgVal>>,<<ArgDist>>]
- /// CHECK-DAG: Return [<<Result>>]
-
- /// CHECK-START: int Main.rotateRightIntWithByteDistance(int, byte) instruction_simplifier (after)
- /// CHECK-NOT: InvokeStaticOrDirect
-
- private static int rotateRightIntWithByteDistance(int value, byte distance) {
- return Integer.rotateRight(value, distance);
- }
-
-
- public static void testRotateLeftBoolean() {
- for (int i = 0; i < 40; i++) { // overshoot a bit
- int j = i & 31;
- expectEqualsInt(0, rotateLeftBoolean(false, i));
- expectEqualsInt(1 << i, rotateLeftBoolean(true, i));
- }
- }
-
- public static void testRotateLeftByte() {
- expectEqualsInt(0x00000001, rotateLeftByte((byte)0x01, 0));
- expectEqualsInt(0x00000002, rotateLeftByte((byte)0x01, 1));
- expectEqualsInt(0x80000000, rotateLeftByte((byte)0x01, 31));
- expectEqualsInt(0x00000001, rotateLeftByte((byte)0x01, 32)); // overshoot
- expectEqualsInt(0xFFFFFF03, rotateLeftByte((byte)0x81, 1));
- expectEqualsInt(0xFFFFFE07, rotateLeftByte((byte)0x81, 2));
- expectEqualsInt(0x00000120, rotateLeftByte((byte)0x12, 4));
- expectEqualsInt(0xFFFF9AFF, rotateLeftByte((byte)0x9A, 8));
- for (int i = 0; i < 40; i++) { // overshoot a bit
- int j = i & 31;
- expectEqualsInt(0x00000000, rotateLeftByte((byte)0x0000, i));
- expectEqualsInt(0xFFFFFFFF, rotateLeftByte((byte)0xFFFF, i));
- expectEqualsInt((1 << j), rotateLeftByte((byte)0x0001, i));
- expectEqualsInt((0x12 << j) | (0x12 >>> -j), rotateLeftByte((byte)0x12, i));
- }
- }
-
- public static void testRotateLeftShort() {
- expectEqualsInt(0x00000001, rotateLeftShort((short)0x0001, 0));
- expectEqualsInt(0x00000002, rotateLeftShort((short)0x0001, 1));
- expectEqualsInt(0x80000000, rotateLeftShort((short)0x0001, 31));
- expectEqualsInt(0x00000001, rotateLeftShort((short)0x0001, 32)); // overshoot
- expectEqualsInt(0xFFFF0003, rotateLeftShort((short)0x8001, 1));
- expectEqualsInt(0xFFFE0007, rotateLeftShort((short)0x8001, 2));
- expectEqualsInt(0x00012340, rotateLeftShort((short)0x1234, 4));
- expectEqualsInt(0xFF9ABCFF, rotateLeftShort((short)0x9ABC, 8));
- for (int i = 0; i < 40; i++) { // overshoot a bit
- int j = i & 31;
- expectEqualsInt(0x00000000, rotateLeftShort((short)0x0000, i));
- expectEqualsInt(0xFFFFFFFF, rotateLeftShort((short)0xFFFF, i));
- expectEqualsInt((1 << j), rotateLeftShort((short)0x0001, i));
- expectEqualsInt((0x1234 << j) | (0x1234 >>> -j), rotateLeftShort((short)0x1234, i));
- }
- }
-
- public static void testRotateLeftChar() {
- expectEqualsInt(0x00000001, rotateLeftChar((char)0x0001, 0));
- expectEqualsInt(0x00000002, rotateLeftChar((char)0x0001, 1));
- expectEqualsInt(0x80000000, rotateLeftChar((char)0x0001, 31));
- expectEqualsInt(0x00000001, rotateLeftChar((char)0x0001, 32)); // overshoot
- expectEqualsInt(0x00010002, rotateLeftChar((char)0x8001, 1));
- expectEqualsInt(0x00020004, rotateLeftChar((char)0x8001, 2));
- expectEqualsInt(0x00012340, rotateLeftChar((char)0x1234, 4));
- expectEqualsInt(0x009ABC00, rotateLeftChar((char)0x9ABC, 8));
- expectEqualsInt(0x00FF0000, rotateLeftChar((char)0xFF00, 8));
- for (int i = 0; i < 40; i++) { // overshoot a bit
- int j = i & 31;
- expectEqualsInt(0x00000000, rotateLeftChar((char)0x0000, i));
- expectEqualsInt((1 << j), rotateLeftChar((char)0x0001, i));
- expectEqualsInt((0x1234 << j) | (0x1234 >>> -j), rotateLeftChar((char)0x1234, i));
- }
- }
-
- public static void testRotateLeftInt() {
- expectEqualsInt(0x00000001, rotateLeftInt(0x00000001, 0));
- expectEqualsInt(0x00000002, rotateLeftInt(0x00000001, 1));
- expectEqualsInt(0x80000000, rotateLeftInt(0x00000001, 31));
- expectEqualsInt(0x00000001, rotateLeftInt(0x00000001, 32)); // overshoot
- expectEqualsInt(0x00000003, rotateLeftInt(0x80000001, 1));
- expectEqualsInt(0x00000006, rotateLeftInt(0x80000001, 2));
- expectEqualsInt(0x23456781, rotateLeftInt(0x12345678, 4));
- expectEqualsInt(0xBCDEF09A, rotateLeftInt(0x9ABCDEF0, 8));
- for (int i = 0; i < 40; i++) { // overshoot a bit
- int j = i & 31;
- expectEqualsInt(0x00000000, rotateLeftInt(0x00000000, i));
- expectEqualsInt(0xFFFFFFFF, rotateLeftInt(0xFFFFFFFF, i));
- expectEqualsInt(1 << j, rotateLeftInt(0x00000001, i));
- expectEqualsInt((0x12345678 << j) | (0x12345678 >>> -j), rotateLeftInt(0x12345678, i));
- }
- }
-
- public static void testRotateLeftLong() {
- expectEqualsLong(0x0000000000000001L, rotateLeftLong(0x0000000000000001L, 0));
- expectEqualsLong(0x0000000000000002L, rotateLeftLong(0x0000000000000001L, 1));
- expectEqualsLong(0x8000000000000000L, rotateLeftLong(0x0000000000000001L, 63));
- expectEqualsLong(0x0000000000000001L, rotateLeftLong(0x0000000000000001L, 64)); // overshoot
- expectEqualsLong(0x0000000000000003L, rotateLeftLong(0x8000000000000001L, 1));
- expectEqualsLong(0x0000000000000006L, rotateLeftLong(0x8000000000000001L, 2));
- expectEqualsLong(0x23456789ABCDEF01L, rotateLeftLong(0x123456789ABCDEF0L, 4));
- expectEqualsLong(0x3456789ABCDEF012L, rotateLeftLong(0x123456789ABCDEF0L, 8));
- for (int i = 0; i < 70; i++) { // overshoot a bit
- int j = i & 63;
- expectEqualsLong(0x0000000000000000L, rotateLeftLong(0x0000000000000000L, i));
- expectEqualsLong(0xFFFFFFFFFFFFFFFFL, rotateLeftLong(0xFFFFFFFFFFFFFFFFL, i));
- expectEqualsLong(1L << j, rotateLeftLong(0x0000000000000001, i));
- expectEqualsLong((0x123456789ABCDEF0L << j) | (0x123456789ABCDEF0L >>> -j),
- rotateLeftLong(0x123456789ABCDEF0L, i));
- }
- }
-
- public static void testRotateRightBoolean() {
- for (int i = 0; i < 40; i++) { // overshoot a bit
- int j = i & 31;
- expectEqualsInt(0, rotateRightBoolean(false, i));
- expectEqualsInt(1 << (32 - i), rotateRightBoolean(true, i));
- }
- }
-
- public static void testRotateRightByte() {
- expectEqualsInt(0xFFFFFF80, rotateRightByte((byte)0x80, 0));
- expectEqualsInt(0x7FFFFFC0, rotateRightByte((byte)0x80, 1));
- expectEqualsInt(0xFFFFFF01, rotateRightByte((byte)0x80, 31));
- expectEqualsInt(0xFFFFFF80, rotateRightByte((byte)0x80, 32)); // overshoot
- expectEqualsInt(0xFFFFFFC0, rotateRightByte((byte)0x81, 1));
- expectEqualsInt(0x7FFFFFE0, rotateRightByte((byte)0x81, 2));
- expectEqualsInt(0x20000001, rotateRightByte((byte)0x12, 4));
- expectEqualsInt(0x9AFFFFFF, rotateRightByte((byte)0x9A, 8));
- for (int i = 0; i < 40; i++) { // overshoot a bit
- int j = i & 31;
- expectEqualsInt(0x00000000, rotateRightByte((byte)0x00, i));
- expectEqualsInt(0xFFFFFFFF, rotateRightByte((byte)0xFF, i));
- expectEqualsInt(1 << (32 - j), rotateRightByte((byte)0x01, i));
- expectEqualsInt((0x12 >>> j) | (0x12 << -j), rotateRightByte((byte)0x12, i));
- }
- }
-
- public static void testRotateRightShort() {
- expectEqualsInt(0xFFFF8000, rotateRightShort((short)0x8000, 0));
- expectEqualsInt(0x7FFFC000, rotateRightShort((short)0x8000, 1));
- expectEqualsInt(0xFFFF0001, rotateRightShort((short)0x8000, 31));
- expectEqualsInt(0xFFFF8000, rotateRightShort((short)0x8000, 32)); // overshoot
- expectEqualsInt(0xFFFFC000, rotateRightShort((short)0x8001, 1));
- expectEqualsInt(0x7FFFE000, rotateRightShort((short)0x8001, 2));
- expectEqualsInt(0x40000123, rotateRightShort((short)0x1234, 4));
- expectEqualsInt(0xBCFFFF9A, rotateRightShort((short)0x9ABC, 8));
- for (int i = 0; i < 40; i++) { // overshoot a bit
- int j = i & 31;
- expectEqualsInt(0x00000000, rotateRightShort((short)0x0000, i));
- expectEqualsInt(0xFFFFFFFF, rotateRightShort((short)0xFFFF, i));
- expectEqualsInt(1 << (32 - j), rotateRightShort((short)0x0001, i));
- expectEqualsInt((0x1234 >>> j) | (0x1234 << -j), rotateRightShort((short)0x1234, i));
- }
- }
-
- public static void testRotateRightChar() {
- expectEqualsInt(0x00008000, rotateRightChar((char)0x8000, 0));
- expectEqualsInt(0x00004000, rotateRightChar((char)0x8000, 1));
- expectEqualsInt(0x00010000, rotateRightChar((char)0x8000, 31));
- expectEqualsInt(0x00008000, rotateRightChar((char)0x8000, 32)); // overshoot
- expectEqualsInt(0x80004000, rotateRightChar((char)0x8001, 1));
- expectEqualsInt(0x40002000, rotateRightChar((char)0x8001, 2));
- expectEqualsInt(0x40000123, rotateRightChar((char)0x1234, 4));
- expectEqualsInt(0xBC00009A, rotateRightChar((char)0x9ABC, 8));
- for (int i = 0; i < 40; i++) { // overshoot a bit
- int j = i & 31;
- expectEqualsInt(0x00000000, rotateRightChar((char)0x0000, i));
- expectEqualsInt(1 << (32 - j), rotateRightChar((char)0x0001, i));
- expectEqualsInt((0x1234 >>> j) | (0x1234 << -j), rotateRightChar((char)0x1234, i));
- }
- }
-
- public static void testRotateRightInt() {
- expectEqualsInt(0x80000000, rotateRightInt(0x80000000, 0));
- expectEqualsInt(0x40000000, rotateRightInt(0x80000000, 1));
- expectEqualsInt(0x00000001, rotateRightInt(0x80000000, 31));
- expectEqualsInt(0x80000000, rotateRightInt(0x80000000, 32)); // overshoot
- expectEqualsInt(0xC0000000, rotateRightInt(0x80000001, 1));
- expectEqualsInt(0x60000000, rotateRightInt(0x80000001, 2));
- expectEqualsInt(0x81234567, rotateRightInt(0x12345678, 4));
- expectEqualsInt(0xF09ABCDE, rotateRightInt(0x9ABCDEF0, 8));
- for (int i = 0; i < 40; i++) { // overshoot a bit
- int j = i & 31;
- expectEqualsInt(0x00000000, rotateRightInt(0x00000000, i));
- expectEqualsInt(0xFFFFFFFF, rotateRightInt(0xFFFFFFFF, i));
- expectEqualsInt(0x80000000 >>> j, rotateRightInt(0x80000000, i));
- expectEqualsInt((0x12345678 >>> j) | (0x12345678 << -j), rotateRightInt(0x12345678, i));
- }
- }
-
- public static void testRotateRightLong() {
- expectEqualsLong(0x8000000000000000L, rotateRightLong(0x8000000000000000L, 0));
- expectEqualsLong(0x4000000000000000L, rotateRightLong(0x8000000000000000L, 1));
- expectEqualsLong(0x0000000000000001L, rotateRightLong(0x8000000000000000L, 63));
- expectEqualsLong(0x8000000000000000L, rotateRightLong(0x8000000000000000L, 64)); // overshoot
- expectEqualsLong(0xC000000000000000L, rotateRightLong(0x8000000000000001L, 1));
- expectEqualsLong(0x6000000000000000L, rotateRightLong(0x8000000000000001L, 2));
- expectEqualsLong(0x0123456789ABCDEFL, rotateRightLong(0x123456789ABCDEF0L, 4));
- expectEqualsLong(0xF0123456789ABCDEL, rotateRightLong(0x123456789ABCDEF0L, 8));
- for (int i = 0; i < 70; i++) { // overshoot a bit
- int j = i & 63;
- expectEqualsLong(0x0000000000000000L, rotateRightLong(0x0000000000000000L, i));
- expectEqualsLong(0xFFFFFFFFFFFFFFFFL, rotateRightLong(0xFFFFFFFFFFFFFFFFL, i));
- expectEqualsLong(0x8000000000000000L >>> j, rotateRightLong(0x8000000000000000L, i));
- expectEqualsLong((0x123456789ABCDEF0L >>> j) | (0x123456789ABCDEF0L << -j),
- rotateRightLong(0x123456789ABCDEF0L, i));
- }
- }
-
-
- public static void testRotateLeftIntWithByteDistance() {
- expectEqualsInt(0x00000001, rotateLeftIntWithByteDistance(0x00000001, (byte)0));
- expectEqualsInt(0x00000002, rotateLeftIntWithByteDistance(0x00000001, (byte)1));
- expectEqualsInt(0x80000000, rotateLeftIntWithByteDistance(0x00000001, (byte)31));
- expectEqualsInt(0x00000001, rotateLeftIntWithByteDistance(0x00000001, (byte)32)); // overshoot
- expectEqualsInt(0x00000003, rotateLeftIntWithByteDistance(0x80000001, (byte)1));
- expectEqualsInt(0x00000006, rotateLeftIntWithByteDistance(0x80000001, (byte)2));
- expectEqualsInt(0x23456781, rotateLeftIntWithByteDistance(0x12345678, (byte)4));
- expectEqualsInt(0xBCDEF09A, rotateLeftIntWithByteDistance(0x9ABCDEF0, (byte)8));
- for (byte i = 0; i < 40; i++) { // overshoot a bit
- byte j = (byte)(i & 31);
- expectEqualsInt(0x00000000, rotateLeftIntWithByteDistance(0x00000000, i));
- expectEqualsInt(0xFFFFFFFF, rotateLeftIntWithByteDistance(0xFFFFFFFF, i));
- expectEqualsInt(1 << j, rotateLeftIntWithByteDistance(0x00000001, i));
- expectEqualsInt((0x12345678 << j) | (0x12345678 >>> -j),
- rotateLeftIntWithByteDistance(0x12345678, i));
- }
- }
-
- public static void testRotateRightIntWithByteDistance() {
- expectEqualsInt(0x80000000, rotateRightIntWithByteDistance(0x80000000, (byte)0));
- expectEqualsInt(0x40000000, rotateRightIntWithByteDistance(0x80000000, (byte)1));
- expectEqualsInt(0x00000001, rotateRightIntWithByteDistance(0x80000000, (byte)31));
- expectEqualsInt(0x80000000, rotateRightIntWithByteDistance(0x80000000, (byte)32)); // overshoot
- expectEqualsInt(0xC0000000, rotateRightIntWithByteDistance(0x80000001, (byte)1));
- expectEqualsInt(0x60000000, rotateRightIntWithByteDistance(0x80000001, (byte)2));
- expectEqualsInt(0x81234567, rotateRightIntWithByteDistance(0x12345678, (byte)4));
- expectEqualsInt(0xF09ABCDE, rotateRightIntWithByteDistance(0x9ABCDEF0, (byte)8));
- for (byte i = 0; i < 40; i++) { // overshoot a bit
- byte j = (byte)(i & 31);
- expectEqualsInt(0x00000000, rotateRightIntWithByteDistance(0x00000000, i));
- expectEqualsInt(0xFFFFFFFF, rotateRightIntWithByteDistance(0xFFFFFFFF, i));
- expectEqualsInt(0x80000000 >>> j, rotateRightIntWithByteDistance(0x80000000, i));
- expectEqualsInt((0x12345678 >>> j) | (0x12345678 << -j),
- rotateRightIntWithByteDistance(0x12345678, i));
- }
- }
-
-
public static void main(String args[]) {
- testRotateLeftBoolean();
- testRotateLeftByte();
- testRotateLeftShort();
- testRotateLeftChar();
- testRotateLeftInt();
- testRotateLeftLong();
-
- testRotateRightBoolean();
- testRotateRightByte();
- testRotateRightShort();
- testRotateRightChar();
- testRotateRightInt();
- testRotateRightLong();
-
- // Also exercise distance values with types other than int.
- testRotateLeftIntWithByteDistance();
- testRotateRightIntWithByteDistance();
-
System.out.println("passed");
}
-
-
- private static void expectEqualsInt(int expected, int result) {
- if (expected != result) {
- throw new Error("Expected: " + expected + ", found: " + result);
- }
- }
-
- private static void expectEqualsLong(long expected, long result) {
- if (expected != result) {
- throw new Error("Expected: " + expected + ", found: " + result);
- }
- }
-}
+} \ No newline at end of file
diff --git a/test/569-checker-pattern-replacement/build b/test/569-checker-pattern-replacement/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/569-checker-pattern-replacement/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/583-checker-zero/build b/test/583-checker-zero/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/583-checker-zero/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/626-checker-arm64-scratch-register/build b/test/626-checker-arm64-scratch-register/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/626-checker-arm64-scratch-register/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/626-checker-arm64-scratch-register/smali/Main2.smali b/test/626-checker-arm64-scratch-register/smali/Main2.smali
new file mode 100644
index 0000000000..914ae6eeaf
--- /dev/null
+++ b/test/626-checker-arm64-scratch-register/smali/Main2.smali
@@ -0,0 +1,1768 @@
+# Copyright (C) 2018 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.
+
+.class public LMain2;
+.super Ljava/lang/Object;
+
+
+# instance fields
+.field b00:Z
+
+.field b01:Z
+
+.field b02:Z
+
+.field b03:Z
+
+.field b04:Z
+
+.field b05:Z
+
+.field b06:Z
+
+.field b07:Z
+
+.field b08:Z
+
+.field b09:Z
+
+.field b10:Z
+
+.field b11:Z
+
+.field b12:Z
+
+.field b13:Z
+
+.field b14:Z
+
+.field b15:Z
+
+.field b16:Z
+
+.field b17:Z
+
+.field b18:Z
+
+.field b19:Z
+
+.field b20:Z
+
+.field b21:Z
+
+.field b22:Z
+
+.field b23:Z
+
+.field b24:Z
+
+.field b25:Z
+
+.field b26:Z
+
+.field b27:Z
+
+.field b28:Z
+
+.field b29:Z
+
+.field b30:Z
+
+.field b31:Z
+
+.field b32:Z
+
+.field b33:Z
+
+.field b34:Z
+
+.field b35:Z
+
+.field b36:Z
+
+.field conditionA:Z
+
+.field conditionB:Z
+
+.field conditionC:Z
+
+
+# direct methods
+.method public constructor <init>()V
+ .registers 1
+
+ .prologue
+ .line 17
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+ return-void
+.end method
+
+## CHECK-START-ARM64: void Main2.test() register (after)
+## CHECK: begin_block
+## CHECK: name "B0"
+## CHECK: <<This:l\d+>> ParameterValue
+## CHECK: end_block
+## CHECK: begin_block
+## CHECK: successors "<<ThenBlock:B\d+>>" "<<ElseBlock:B\d+>>"
+## CHECK: <<CondB:z\d+>> InstanceFieldGet [<<This>>] field_name:Main2.conditionB
+## CHECK: If [<<CondB>>]
+## CHECK: end_block
+## CHECK: begin_block
+## CHECK: name "<<ElseBlock>>"
+## CHECK: ParallelMove moves:[40(sp)->d0,24(sp)->32(sp),28(sp)->36(sp),d0->d3,d3->d4,d2->d5,d4->d6,d5->d7,d6->d18,d7->d19,d18->d20,d19->d21,d20->d22,d21->d23,d22->d10,d23->d11,16(sp)->24(sp),20(sp)->28(sp),d10->d14,d11->d12,d12->d13,d13->d1,d14->d2,32(sp)->16(sp),36(sp)->20(sp)]
+## CHECK: end_block
+
+## CHECK-START-ARM64: void Main2.test() disassembly (after)
+## CHECK: begin_block
+## CHECK: name "B0"
+## CHECK: <<This:l\d+>> ParameterValue
+## CHECK: end_block
+## CHECK: begin_block
+## CHECK: successors "<<ThenBlock:B\d+>>" "<<ElseBlock:B\d+>>"
+## CHECK: <<CondB:z\d+>> InstanceFieldGet [<<This>>] field_name:Main2.conditionB
+## CHECK: If [<<CondB>>]
+## CHECK: end_block
+## CHECK: begin_block
+## CHECK: name "<<ElseBlock>>"
+## CHECK: ParallelMove moves:[invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid]
+## CHECK: fmov d31, d2
+## CHECK: ldr s2, [sp, #36]
+## CHECK: ldr w16, [sp, #16]
+## CHECK: str w16, [sp, #36]
+## CHECK: str s14, [sp, #16]
+## CHECK: ldr s14, [sp, #28]
+## CHECK: str s1, [sp, #28]
+## CHECK: ldr s1, [sp, #32]
+## CHECK: str s31, [sp, #32]
+## CHECK: ldr s31, [sp, #20]
+## CHECK: str s31, [sp, #40]
+## CHECK: str s12, [sp, #20]
+## CHECK: fmov d12, d11
+## CHECK: fmov d11, d10
+## CHECK: fmov d10, d23
+## CHECK: fmov d23, d22
+## CHECK: fmov d22, d21
+## CHECK: fmov d21, d20
+## CHECK: fmov d20, d19
+## CHECK: fmov d19, d18
+## CHECK: fmov d18, d7
+## CHECK: fmov d7, d6
+## CHECK: fmov d6, d5
+## CHECK: fmov d5, d4
+## CHECK: fmov d4, d3
+## CHECK: fmov d3, d13
+## CHECK: ldr s13, [sp, #24]
+## CHECK: str s3, [sp, #24]
+## CHECK: ldr s3, pc+{{\d+}} (addr {{0x[0-9a-f]+}}) (100)
+## CHECK: end_block
+
+# Original java source:
+#
+# public void test() {
+# String r = "";
+#
+# // For the purpose of this regression test, the order of
+# // definition of these float variable matters. Likewise with the
+# // order of the instructions where these variables are used below.
+# // Reordering these lines make make the original (b/32545705)
+# // issue vanish.
+# float f17 = b17 ? 0.0f : 1.0f;
+# float f16 = b16 ? 0.0f : 1.0f;
+# float f18 = b18 ? 0.0f : 1.0f;
+# float f19 = b19 ? 0.0f : 1.0f;
+# float f20 = b20 ? 0.0f : 1.0f;
+# float f21 = b21 ? 0.0f : 1.0f;
+# float f15 = b15 ? 0.0f : 1.0f;
+# float f00 = b00 ? 0.0f : 1.0f;
+# float f22 = b22 ? 0.0f : 1.0f;
+# float f23 = b23 ? 0.0f : 1.0f;
+# float f24 = b24 ? 0.0f : 1.0f;
+# float f25 = b25 ? 0.0f : 1.0f;
+# float f26 = b26 ? 0.0f : 1.0f;
+# float f27 = b27 ? 0.0f : 1.0f;
+# float f29 = b29 ? 0.0f : 1.0f;
+# float f28 = b28 ? 0.0f : 1.0f;
+# float f01 = b01 ? 0.0f : 1.0f;
+# float f02 = b02 ? 0.0f : 1.0f;
+# float f03 = b03 ? 0.0f : 1.0f;
+# float f04 = b04 ? 0.0f : 1.0f;
+# float f05 = b05 ? 0.0f : 1.0f;
+# float f07 = b07 ? 0.0f : 1.0f;
+# float f06 = b06 ? 0.0f : 1.0f;
+# float f30 = b30 ? 0.0f : 1.0f;
+# float f31 = b31 ? 0.0f : 1.0f;
+# float f32 = b32 ? 0.0f : 1.0f;
+# float f33 = b33 ? 0.0f : 1.0f;
+# float f34 = b34 ? 0.0f : 1.0f;
+# float f36 = b36 ? 0.0f : 1.0f;
+# float f35 = b35 ? 0.0f : 1.0f;
+# float f08 = b08 ? 0.0f : 1.0f;
+# float f09 = b09 ? 0.0f : 1.0f;
+# float f10 = b10 ? 0.0f : 1.0f;
+# float f11 = b11 ? 0.0f : 1.0f;
+# float f12 = b12 ? 0.0f : 1.0f;
+# float f14 = b14 ? 0.0f : 1.0f;
+# float f13 = b13 ? 0.0f : 1.0f;
+#
+# if (conditionA) {
+# f16 /= 1000.0f;
+# f17 /= 1000.0f;
+# f18 /= 1000.0f;
+# f19 /= 1000.0f;
+# f20 /= 1000.0f;
+# f21 /= 1000.0f;
+# f15 /= 1000.0f;
+# f08 /= 1000.0f;
+# f09 /= 1000.0f;
+# f10 /= 1000.0f;
+# f11 /= 1000.0f;
+# f12 /= 1000.0f;
+# f30 /= 1000.0f;
+# f31 /= 1000.0f;
+# f32 /= 1000.0f;
+# f33 /= 1000.0f;
+# f34 /= 1000.0f;
+# f01 /= 1000.0f;
+# f02 /= 1000.0f;
+# f03 /= 1000.0f;
+# f04 /= 1000.0f;
+# f05 /= 1000.0f;
+# f23 /= 1000.0f;
+# f24 /= 1000.0f;
+# f25 /= 1000.0f;
+# f26 /= 1000.0f;
+# f27 /= 1000.0f;
+# f22 /= 1000.0f;
+# f00 /= 1000.0f;
+# f14 /= 1000.0f;
+# f13 /= 1000.0f;
+# f36 /= 1000.0f;
+# f35 /= 1000.0f;
+# f07 /= 1000.0f;
+# f06 /= 1000.0f;
+# f29 /= 1000.0f;
+# f28 /= 1000.0f;
+# }
+# // The parallel move that used to exhaust the ARM64 parallel move
+# // resolver's scratch register pool (provided by VIXL) was in the
+# // "else" branch of the following condition generated by ART's
+# // compiler.
+# if (conditionB) {
+# f16 /= 100.0f;
+# f17 /= 100.0f;
+# f18 /= 100.0f;
+# f19 /= 100.0f;
+# f20 /= 100.0f;
+# f21 /= 100.0f;
+# f15 /= 100.0f;
+# f08 /= 100.0f;
+# f09 /= 100.0f;
+# f10 /= 100.0f;
+# f11 /= 100.0f;
+# f12 /= 100.0f;
+# f30 /= 100.0f;
+# f31 /= 100.0f;
+# f32 /= 100.0f;
+# f33 /= 100.0f;
+# f34 /= 100.0f;
+# f01 /= 100.0f;
+# f02 /= 100.0f;
+# f03 /= 100.0f;
+# f04 /= 100.0f;
+# f05 /= 100.0f;
+# f23 /= 100.0f;
+# f24 /= 100.0f;
+# f25 /= 100.0f;
+# f26 /= 100.0f;
+# f27 /= 100.0f;
+# f22 /= 100.0f;
+# f00 /= 100.0f;
+# f14 /= 100.0f;
+# f13 /= 100.0f;
+# f36 /= 100.0f;
+# f35 /= 100.0f;
+# f07 /= 100.0f;
+# f06 /= 100.0f;
+# f29 /= 100.0f;
+# f28 /= 100.0f;
+# }
+# if (conditionC) {
+# f16 /= 12.0f;
+# f17 /= 12.0f;
+# f18 /= 12.0f;
+# f19 /= 12.0f;
+# f20 /= 12.0f;
+# f21 /= 12.0f;
+# f15 /= 12.0f;
+# f08 /= 12.0f;
+# f09 /= 12.0f;
+# f10 /= 12.0f;
+# f11 /= 12.0f;
+# f12 /= 12.0f;
+# f30 /= 12.0f;
+# f31 /= 12.0f;
+# f32 /= 12.0f;
+# f33 /= 12.0f;
+# f34 /= 12.0f;
+# f01 /= 12.0f;
+# f02 /= 12.0f;
+# f03 /= 12.0f;
+# f04 /= 12.0f;
+# f05 /= 12.0f;
+# f23 /= 12.0f;
+# f24 /= 12.0f;
+# f25 /= 12.0f;
+# f26 /= 12.0f;
+# f27 /= 12.0f;
+# f22 /= 12.0f;
+# f00 /= 12.0f;
+# f14 /= 12.0f;
+# f13 /= 12.0f;
+# f36 /= 12.0f;
+# f35 /= 12.0f;
+# f07 /= 12.0f;
+# f06 /= 12.0f;
+# f29 /= 12.0f;
+# f28 /= 12.0f;
+# }
+# float s = 0.0f;
+# s = ((float) Math.round(100.0f * s)) / 100.0f;
+# String res = s + r;
+# }
+
+# virtual methods
+.method public test()V
+ .registers 45
+
+ .prologue
+ .line 121
+ const-string v39, ""
+
+ .line 128
+ .local v39, "r":Ljava/lang/String;
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b17:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_367
+
+ const/16 v19, 0x0
+
+ .line 129
+ .local v19, "f17":F
+ :goto_c
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b16:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_36b
+
+ const/16 v18, 0x0
+
+ .line 130
+ .local v18, "f16":F
+ :goto_16
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b18:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_36f
+
+ const/16 v20, 0x0
+
+ .line 131
+ .local v20, "f18":F
+ :goto_20
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b19:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_373
+
+ const/16 v21, 0x0
+
+ .line 132
+ .local v21, "f19":F
+ :goto_2a
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b20:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_377
+
+ const/16 v22, 0x0
+
+ .line 133
+ .local v22, "f20":F
+ :goto_34
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b21:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_37b
+
+ const/16 v23, 0x0
+
+ .line 134
+ .local v23, "f21":F
+ :goto_3e
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b15:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_37f
+
+ const/16 v17, 0x0
+
+ .line 135
+ .local v17, "f15":F
+ :goto_48
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b00:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_383
+
+ const/4 v2, 0x0
+
+ .line 136
+ .local v2, "f00":F
+ :goto_51
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b22:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_387
+
+ const/16 v24, 0x0
+
+ .line 137
+ .local v24, "f22":F
+ :goto_5b
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b23:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_38b
+
+ const/16 v25, 0x0
+
+ .line 138
+ .local v25, "f23":F
+ :goto_65
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b24:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_38f
+
+ const/16 v26, 0x0
+
+ .line 139
+ .local v26, "f24":F
+ :goto_6f
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b25:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_393
+
+ const/16 v27, 0x0
+
+ .line 140
+ .local v27, "f25":F
+ :goto_79
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b26:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_397
+
+ const/16 v28, 0x0
+
+ .line 141
+ .local v28, "f26":F
+ :goto_83
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b27:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_39b
+
+ const/16 v29, 0x0
+
+ .line 142
+ .local v29, "f27":F
+ :goto_8d
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b29:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_39f
+
+ const/16 v31, 0x0
+
+ .line 143
+ .local v31, "f29":F
+ :goto_97
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b28:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3a3
+
+ const/16 v30, 0x0
+
+ .line 144
+ .local v30, "f28":F
+ :goto_a1
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b01:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3a7
+
+ const/4 v3, 0x0
+
+ .line 145
+ .local v3, "f01":F
+ :goto_aa
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b02:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3ab
+
+ const/4 v4, 0x0
+
+ .line 146
+ .local v4, "f02":F
+ :goto_b3
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b03:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3af
+
+ const/4 v5, 0x0
+
+ .line 147
+ .local v5, "f03":F
+ :goto_bc
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b04:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3b3
+
+ const/4 v6, 0x0
+
+ .line 148
+ .local v6, "f04":F
+ :goto_c5
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b05:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3b7
+
+ const/4 v7, 0x0
+
+ .line 149
+ .local v7, "f05":F
+ :goto_ce
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b07:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3bb
+
+ const/4 v9, 0x0
+
+ .line 150
+ .local v9, "f07":F
+ :goto_d7
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b06:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3bf
+
+ const/4 v8, 0x0
+
+ .line 151
+ .local v8, "f06":F
+ :goto_e0
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b30:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3c3
+
+ const/16 v32, 0x0
+
+ .line 152
+ .local v32, "f30":F
+ :goto_ea
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b31:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3c7
+
+ const/16 v33, 0x0
+
+ .line 153
+ .local v33, "f31":F
+ :goto_f4
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b32:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3cb
+
+ const/16 v34, 0x0
+
+ .line 154
+ .local v34, "f32":F
+ :goto_fe
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b33:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3cf
+
+ const/16 v35, 0x0
+
+ .line 155
+ .local v35, "f33":F
+ :goto_108
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b34:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3d3
+
+ const/16 v36, 0x0
+
+ .line 156
+ .local v36, "f34":F
+ :goto_112
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b36:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3d7
+
+ const/16 v38, 0x0
+
+ .line 157
+ .local v38, "f36":F
+ :goto_11c
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b35:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3db
+
+ const/16 v37, 0x0
+
+ .line 158
+ .local v37, "f35":F
+ :goto_126
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b08:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3df
+
+ const/4 v10, 0x0
+
+ .line 159
+ .local v10, "f08":F
+ :goto_12f
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b09:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3e3
+
+ const/4 v11, 0x0
+
+ .line 160
+ .local v11, "f09":F
+ :goto_138
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b10:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3e7
+
+ const/4 v12, 0x0
+
+ .line 161
+ .local v12, "f10":F
+ :goto_141
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b11:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3eb
+
+ const/4 v13, 0x0
+
+ .line 162
+ .local v13, "f11":F
+ :goto_14a
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b12:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3ef
+
+ const/4 v14, 0x0
+
+ .line 163
+ .local v14, "f12":F
+ :goto_153
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b14:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3f3
+
+ const/16 v16, 0x0
+
+ .line 164
+ .local v16, "f14":F
+ :goto_15d
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->b13:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_3f7
+
+ const/4 v15, 0x0
+
+ .line 166
+ .local v15, "f13":F
+ :goto_166
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->conditionA:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_202
+
+ .line 167
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v18, v18, v42
+
+ .line 168
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v19, v19, v42
+
+ .line 169
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v20, v20, v42
+
+ .line 170
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v21, v21, v42
+
+ .line 171
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v22, v22, v42
+
+ .line 172
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v23, v23, v42
+
+ .line 173
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v17, v17, v42
+
+ .line 174
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v10, v10, v42
+
+ .line 175
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v11, v11, v42
+
+ .line 176
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v12, v12, v42
+
+ .line 177
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v13, v13, v42
+
+ .line 178
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v14, v14, v42
+
+ .line 179
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v32, v32, v42
+
+ .line 180
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v33, v33, v42
+
+ .line 181
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v34, v34, v42
+
+ .line 182
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v35, v35, v42
+
+ .line 183
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v36, v36, v42
+
+ .line 184
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v3, v3, v42
+
+ .line 185
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v4, v4, v42
+
+ .line 186
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v5, v5, v42
+
+ .line 187
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v6, v6, v42
+
+ .line 188
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v7, v7, v42
+
+ .line 189
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v25, v25, v42
+
+ .line 190
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v26, v26, v42
+
+ .line 191
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v27, v27, v42
+
+ .line 192
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v28, v28, v42
+
+ .line 193
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v29, v29, v42
+
+ .line 194
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v24, v24, v42
+
+ .line 195
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v2, v2, v42
+
+ .line 196
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v16, v16, v42
+
+ .line 197
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v15, v15, v42
+
+ .line 198
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v38, v38, v42
+
+ .line 199
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v37, v37, v42
+
+ .line 200
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v9, v9, v42
+
+ .line 201
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v8, v8, v42
+
+ .line 202
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v31, v31, v42
+
+ .line 203
+ const/high16 v42, 0x447a0000 # 1000.0f
+
+ div-float v30, v30, v42
+
+ .line 209
+ :cond_202
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->conditionB:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_29e
+
+ .line 210
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v18, v18, v42
+
+ .line 211
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v19, v19, v42
+
+ .line 212
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v20, v20, v42
+
+ .line 213
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v21, v21, v42
+
+ .line 214
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v22, v22, v42
+
+ .line 215
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v23, v23, v42
+
+ .line 216
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v17, v17, v42
+
+ .line 217
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v10, v10, v42
+
+ .line 218
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v11, v11, v42
+
+ .line 219
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v12, v12, v42
+
+ .line 220
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v13, v13, v42
+
+ .line 221
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v14, v14, v42
+
+ .line 222
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v32, v32, v42
+
+ .line 223
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v33, v33, v42
+
+ .line 224
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v34, v34, v42
+
+ .line 225
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v35, v35, v42
+
+ .line 226
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v36, v36, v42
+
+ .line 227
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v3, v3, v42
+
+ .line 228
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v4, v4, v42
+
+ .line 229
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v5, v5, v42
+
+ .line 230
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v6, v6, v42
+
+ .line 231
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v7, v7, v42
+
+ .line 232
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v25, v25, v42
+
+ .line 233
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v26, v26, v42
+
+ .line 234
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v27, v27, v42
+
+ .line 235
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v28, v28, v42
+
+ .line 236
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v29, v29, v42
+
+ .line 237
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v24, v24, v42
+
+ .line 238
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v2, v2, v42
+
+ .line 239
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v16, v16, v42
+
+ .line 240
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v15, v15, v42
+
+ .line 241
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v38, v38, v42
+
+ .line 242
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v37, v37, v42
+
+ .line 243
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v9, v9, v42
+
+ .line 244
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v8, v8, v42
+
+ .line 245
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v31, v31, v42
+
+ .line 246
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ div-float v30, v30, v42
+
+ .line 248
+ :cond_29e
+ move-object/from16 v0, p0
+
+ iget-boolean v0, v0, LMain2;->conditionC:Z
+
+ move/from16 v42, v0
+
+ if-eqz v42, :cond_33a
+
+ .line 249
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v18, v18, v42
+
+ .line 250
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v19, v19, v42
+
+ .line 251
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v20, v20, v42
+
+ .line 252
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v21, v21, v42
+
+ .line 253
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v22, v22, v42
+
+ .line 254
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v23, v23, v42
+
+ .line 255
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v17, v17, v42
+
+ .line 256
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v10, v10, v42
+
+ .line 257
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v11, v11, v42
+
+ .line 258
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v12, v12, v42
+
+ .line 259
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v13, v13, v42
+
+ .line 260
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v14, v14, v42
+
+ .line 261
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v32, v32, v42
+
+ .line 262
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v33, v33, v42
+
+ .line 263
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v34, v34, v42
+
+ .line 264
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v35, v35, v42
+
+ .line 265
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v36, v36, v42
+
+ .line 266
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v3, v3, v42
+
+ .line 267
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v4, v4, v42
+
+ .line 268
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v5, v5, v42
+
+ .line 269
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v6, v6, v42
+
+ .line 270
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v7, v7, v42
+
+ .line 271
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v25, v25, v42
+
+ .line 272
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v26, v26, v42
+
+ .line 273
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v27, v27, v42
+
+ .line 274
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v28, v28, v42
+
+ .line 275
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v29, v29, v42
+
+ .line 276
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v24, v24, v42
+
+ .line 277
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v2, v2, v42
+
+ .line 278
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v16, v16, v42
+
+ .line 279
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v15, v15, v42
+
+ .line 280
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v38, v38, v42
+
+ .line 281
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v37, v37, v42
+
+ .line 282
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v9, v9, v42
+
+ .line 283
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v8, v8, v42
+
+ .line 284
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v31, v31, v42
+
+ .line 285
+ const/high16 v42, 0x41400000 # 12.0f
+
+ div-float v30, v30, v42
+
+ .line 287
+ :cond_33a
+ const/16 v41, 0x0
+
+ .line 288
+ .local v41, "s":F
+ const/high16 v42, 0x42c80000 # 100.0f
+
+ mul-float v42, v42, v41
+
+ invoke-static/range {v42 .. v42}, Ljava/lang/Math;->round(F)I
+
+ move-result v42
+
+ move/from16 v0, v42
+
+ int-to-float v0, v0
+
+ move/from16 v42, v0
+
+ const/high16 v43, 0x42c80000 # 100.0f
+
+ div-float v41, v42, v43
+
+ .line 289
+ new-instance v42, Ljava/lang/StringBuilder;
+
+ invoke-direct/range {v42 .. v42}, Ljava/lang/StringBuilder;-><init>()V
+
+ move-object/from16 v0, v42
+
+ move/from16 v1, v41
+
+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(F)Ljava/lang/StringBuilder;
+
+ move-result-object v42
+
+ move-object/from16 v0, v42
+
+ move-object/from16 v1, v39
+
+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+ move-result-object v42
+
+ invoke-virtual/range {v42 .. v42}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
+
+ move-result-object v40
+
+ .line 290
+ .local v40, "res":Ljava/lang/String;
+ return-void
+
+ .line 128
+ .end local v2 # "f00":F
+ .end local v3 # "f01":F
+ .end local v4 # "f02":F
+ .end local v5 # "f03":F
+ .end local v6 # "f04":F
+ .end local v7 # "f05":F
+ .end local v8 # "f06":F
+ .end local v9 # "f07":F
+ .end local v10 # "f08":F
+ .end local v11 # "f09":F
+ .end local v12 # "f10":F
+ .end local v13 # "f11":F
+ .end local v14 # "f12":F
+ .end local v15 # "f13":F
+ .end local v16 # "f14":F
+ .end local v17 # "f15":F
+ .end local v18 # "f16":F
+ .end local v19 # "f17":F
+ .end local v20 # "f18":F
+ .end local v21 # "f19":F
+ .end local v22 # "f20":F
+ .end local v23 # "f21":F
+ .end local v24 # "f22":F
+ .end local v25 # "f23":F
+ .end local v26 # "f24":F
+ .end local v27 # "f25":F
+ .end local v28 # "f26":F
+ .end local v29 # "f27":F
+ .end local v30 # "f28":F
+ .end local v31 # "f29":F
+ .end local v32 # "f30":F
+ .end local v33 # "f31":F
+ .end local v34 # "f32":F
+ .end local v35 # "f33":F
+ .end local v36 # "f34":F
+ .end local v37 # "f35":F
+ .end local v38 # "f36":F
+ .end local v40 # "res":Ljava/lang/String;
+ .end local v41 # "s":F
+ :cond_367
+ const/high16 v19, 0x3f800000 # 1.0f
+
+ goto/16 :goto_c
+
+ .line 129
+ .restart local v19 # "f17":F
+ :cond_36b
+ const/high16 v18, 0x3f800000 # 1.0f
+
+ goto/16 :goto_16
+
+ .line 130
+ .restart local v18 # "f16":F
+ :cond_36f
+ const/high16 v20, 0x3f800000 # 1.0f
+
+ goto/16 :goto_20
+
+ .line 131
+ .restart local v20 # "f18":F
+ :cond_373
+ const/high16 v21, 0x3f800000 # 1.0f
+
+ goto/16 :goto_2a
+
+ .line 132
+ .restart local v21 # "f19":F
+ :cond_377
+ const/high16 v22, 0x3f800000 # 1.0f
+
+ goto/16 :goto_34
+
+ .line 133
+ .restart local v22 # "f20":F
+ :cond_37b
+ const/high16 v23, 0x3f800000 # 1.0f
+
+ goto/16 :goto_3e
+
+ .line 134
+ .restart local v23 # "f21":F
+ :cond_37f
+ const/high16 v17, 0x3f800000 # 1.0f
+
+ goto/16 :goto_48
+
+ .line 135
+ .restart local v17 # "f15":F
+ :cond_383
+ const/high16 v2, 0x3f800000 # 1.0f
+
+ goto/16 :goto_51
+
+ .line 136
+ .restart local v2 # "f00":F
+ :cond_387
+ const/high16 v24, 0x3f800000 # 1.0f
+
+ goto/16 :goto_5b
+
+ .line 137
+ .restart local v24 # "f22":F
+ :cond_38b
+ const/high16 v25, 0x3f800000 # 1.0f
+
+ goto/16 :goto_65
+
+ .line 138
+ .restart local v25 # "f23":F
+ :cond_38f
+ const/high16 v26, 0x3f800000 # 1.0f
+
+ goto/16 :goto_6f
+
+ .line 139
+ .restart local v26 # "f24":F
+ :cond_393
+ const/high16 v27, 0x3f800000 # 1.0f
+
+ goto/16 :goto_79
+
+ .line 140
+ .restart local v27 # "f25":F
+ :cond_397
+ const/high16 v28, 0x3f800000 # 1.0f
+
+ goto/16 :goto_83
+
+ .line 141
+ .restart local v28 # "f26":F
+ :cond_39b
+ const/high16 v29, 0x3f800000 # 1.0f
+
+ goto/16 :goto_8d
+
+ .line 142
+ .restart local v29 # "f27":F
+ :cond_39f
+ const/high16 v31, 0x3f800000 # 1.0f
+
+ goto/16 :goto_97
+
+ .line 143
+ .restart local v31 # "f29":F
+ :cond_3a3
+ const/high16 v30, 0x3f800000 # 1.0f
+
+ goto/16 :goto_a1
+
+ .line 144
+ .restart local v30 # "f28":F
+ :cond_3a7
+ const/high16 v3, 0x3f800000 # 1.0f
+
+ goto/16 :goto_aa
+
+ .line 145
+ .restart local v3 # "f01":F
+ :cond_3ab
+ const/high16 v4, 0x3f800000 # 1.0f
+
+ goto/16 :goto_b3
+
+ .line 146
+ .restart local v4 # "f02":F
+ :cond_3af
+ const/high16 v5, 0x3f800000 # 1.0f
+
+ goto/16 :goto_bc
+
+ .line 147
+ .restart local v5 # "f03":F
+ :cond_3b3
+ const/high16 v6, 0x3f800000 # 1.0f
+
+ goto/16 :goto_c5
+
+ .line 148
+ .restart local v6 # "f04":F
+ :cond_3b7
+ const/high16 v7, 0x3f800000 # 1.0f
+
+ goto/16 :goto_ce
+
+ .line 149
+ .restart local v7 # "f05":F
+ :cond_3bb
+ const/high16 v9, 0x3f800000 # 1.0f
+
+ goto/16 :goto_d7
+
+ .line 150
+ .restart local v9 # "f07":F
+ :cond_3bf
+ const/high16 v8, 0x3f800000 # 1.0f
+
+ goto/16 :goto_e0
+
+ .line 151
+ .restart local v8 # "f06":F
+ :cond_3c3
+ const/high16 v32, 0x3f800000 # 1.0f
+
+ goto/16 :goto_ea
+
+ .line 152
+ .restart local v32 # "f30":F
+ :cond_3c7
+ const/high16 v33, 0x3f800000 # 1.0f
+
+ goto/16 :goto_f4
+
+ .line 153
+ .restart local v33 # "f31":F
+ :cond_3cb
+ const/high16 v34, 0x3f800000 # 1.0f
+
+ goto/16 :goto_fe
+
+ .line 154
+ .restart local v34 # "f32":F
+ :cond_3cf
+ const/high16 v35, 0x3f800000 # 1.0f
+
+ goto/16 :goto_108
+
+ .line 155
+ .restart local v35 # "f33":F
+ :cond_3d3
+ const/high16 v36, 0x3f800000 # 1.0f
+
+ goto/16 :goto_112
+
+ .line 156
+ .restart local v36 # "f34":F
+ :cond_3d7
+ const/high16 v38, 0x3f800000 # 1.0f
+
+ goto/16 :goto_11c
+
+ .line 157
+ .restart local v38 # "f36":F
+ :cond_3db
+ const/high16 v37, 0x3f800000 # 1.0f
+
+ goto/16 :goto_126
+
+ .line 158
+ .restart local v37 # "f35":F
+ :cond_3df
+ const/high16 v10, 0x3f800000 # 1.0f
+
+ goto/16 :goto_12f
+
+ .line 159
+ .restart local v10 # "f08":F
+ :cond_3e3
+ const/high16 v11, 0x3f800000 # 1.0f
+
+ goto/16 :goto_138
+
+ .line 160
+ .restart local v11 # "f09":F
+ :cond_3e7
+ const/high16 v12, 0x3f800000 # 1.0f
+
+ goto/16 :goto_141
+
+ .line 161
+ .restart local v12 # "f10":F
+ :cond_3eb
+ const/high16 v13, 0x3f800000 # 1.0f
+
+ goto/16 :goto_14a
+
+ .line 162
+ .restart local v13 # "f11":F
+ :cond_3ef
+ const/high16 v14, 0x3f800000 # 1.0f
+
+ goto/16 :goto_153
+
+ .line 163
+ .restart local v14 # "f12":F
+ :cond_3f3
+ const/high16 v16, 0x3f800000 # 1.0f
+
+ goto/16 :goto_15d
+
+ .line 164
+ .restart local v16 # "f14":F
+ :cond_3f7
+ const/high16 v15, 0x3f800000 # 1.0f
+
+ goto/16 :goto_166
+.end method
diff --git a/test/626-checker-arm64-scratch-register/src-art/Main.java b/test/626-checker-arm64-scratch-register/src-art/Main.java
new file mode 100644
index 0000000000..b816586c84
--- /dev/null
+++ b/test/626-checker-arm64-scratch-register/src-art/Main.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ Class main2 = Class.forName("Main2");
+ main2.getMethod("test").invoke(main2.newInstance());
+ System.out.println("passed");
+ }
+}
diff --git a/test/626-checker-arm64-scratch-register/src/Main.java b/test/626-checker-arm64-scratch-register/src/Main.java
index 139491769e..fa8e5cd1fe 100644
--- a/test/626-checker-arm64-scratch-register/src/Main.java
+++ b/test/626-checker-arm64-scratch-register/src/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -14,284 +14,9 @@
* limitations under the License.
*/
+// This file is just for running on the RI as the test is ART specific.
public class Main {
-
- boolean b00;
- boolean b01;
- boolean b02;
- boolean b03;
- boolean b04;
- boolean b05;
- boolean b06;
- boolean b07;
- boolean b08;
- boolean b09;
- boolean b10;
- boolean b11;
- boolean b12;
- boolean b13;
- boolean b14;
- boolean b15;
- boolean b16;
- boolean b17;
- boolean b18;
- boolean b19;
- boolean b20;
- boolean b21;
- boolean b22;
- boolean b23;
- boolean b24;
- boolean b25;
- boolean b26;
- boolean b27;
- boolean b28;
- boolean b29;
- boolean b30;
- boolean b31;
- boolean b32;
- boolean b33;
- boolean b34;
- boolean b35;
- boolean b36;
-
- boolean conditionA;
- boolean conditionB;
- boolean conditionC;
-
- /// CHECK-START-ARM64: void Main.test() register (after)
- /// CHECK: begin_block
- /// CHECK: name "B0"
- /// CHECK: <<This:l\d+>> ParameterValue
- /// CHECK: end_block
- /// CHECK: begin_block
- /// CHECK: successors "<<ThenBlock:B\d+>>" "<<ElseBlock:B\d+>>"
- /// CHECK: <<CondB:z\d+>> InstanceFieldGet [<<This>>] field_name:Main.conditionB
- /// CHECK: If [<<CondB>>]
- /// CHECK: end_block
- /// CHECK: begin_block
- /// CHECK: name "<<ElseBlock>>"
- /// CHECK: ParallelMove moves:[40(sp)->d0,24(sp)->32(sp),28(sp)->36(sp),d0->d3,d3->d4,d2->d5,d4->d6,d5->d7,d6->d18,d7->d19,d18->d20,d19->d21,d20->d22,d21->d23,d22->d10,d23->d11,16(sp)->24(sp),20(sp)->28(sp),d10->d14,d11->d12,d12->d13,d13->d1,d14->d2,32(sp)->16(sp),36(sp)->20(sp)]
- /// CHECK: end_block
-
- /// CHECK-START-ARM64: void Main.test() disassembly (after)
- /// CHECK: begin_block
- /// CHECK: name "B0"
- /// CHECK: <<This:l\d+>> ParameterValue
- /// CHECK: end_block
- /// CHECK: begin_block
- /// CHECK: successors "<<ThenBlock:B\d+>>" "<<ElseBlock:B\d+>>"
- /// CHECK: <<CondB:z\d+>> InstanceFieldGet [<<This>>] field_name:Main.conditionB
- /// CHECK: If [<<CondB>>]
- /// CHECK: end_block
- /// CHECK: begin_block
- /// CHECK: name "<<ElseBlock>>"
- /// CHECK: ParallelMove moves:[invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid,invalid->invalid]
- /// CHECK: fmov d31, d2
- /// CHECK: ldr s2, [sp, #36]
- /// CHECK: ldr w16, [sp, #16]
- /// CHECK: str w16, [sp, #36]
- /// CHECK: str s14, [sp, #16]
- /// CHECK: ldr s14, [sp, #28]
- /// CHECK: str s1, [sp, #28]
- /// CHECK: ldr s1, [sp, #32]
- /// CHECK: str s31, [sp, #32]
- /// CHECK: ldr s31, [sp, #20]
- /// CHECK: str s31, [sp, #40]
- /// CHECK: str s12, [sp, #20]
- /// CHECK: fmov d12, d11
- /// CHECK: fmov d11, d10
- /// CHECK: fmov d10, d23
- /// CHECK: fmov d23, d22
- /// CHECK: fmov d22, d21
- /// CHECK: fmov d21, d20
- /// CHECK: fmov d20, d19
- /// CHECK: fmov d19, d18
- /// CHECK: fmov d18, d7
- /// CHECK: fmov d7, d6
- /// CHECK: fmov d6, d5
- /// CHECK: fmov d5, d4
- /// CHECK: fmov d4, d3
- /// CHECK: fmov d3, d13
- /// CHECK: ldr s13, [sp, #24]
- /// CHECK: str s3, [sp, #24]
- /// CHECK: ldr s3, pc+{{\d+}} (addr {{0x[0-9a-f]+}}) (100)
- /// CHECK: end_block
-
- public void test() {
- String r = "";
-
- // For the purpose of this regression test, the order of
- // definition of these float variable matters. Likewise with the
- // order of the instructions where these variables are used below.
- // Reordering these lines make make the original (b/32545705)
- // issue vanish.
- float f17 = b17 ? 0.0f : 1.0f;
- float f16 = b16 ? 0.0f : 1.0f;
- float f18 = b18 ? 0.0f : 1.0f;
- float f19 = b19 ? 0.0f : 1.0f;
- float f20 = b20 ? 0.0f : 1.0f;
- float f21 = b21 ? 0.0f : 1.0f;
- float f15 = b15 ? 0.0f : 1.0f;
- float f00 = b00 ? 0.0f : 1.0f;
- float f22 = b22 ? 0.0f : 1.0f;
- float f23 = b23 ? 0.0f : 1.0f;
- float f24 = b24 ? 0.0f : 1.0f;
- float f25 = b25 ? 0.0f : 1.0f;
- float f26 = b26 ? 0.0f : 1.0f;
- float f27 = b27 ? 0.0f : 1.0f;
- float f29 = b29 ? 0.0f : 1.0f;
- float f28 = b28 ? 0.0f : 1.0f;
- float f01 = b01 ? 0.0f : 1.0f;
- float f02 = b02 ? 0.0f : 1.0f;
- float f03 = b03 ? 0.0f : 1.0f;
- float f04 = b04 ? 0.0f : 1.0f;
- float f05 = b05 ? 0.0f : 1.0f;
- float f07 = b07 ? 0.0f : 1.0f;
- float f06 = b06 ? 0.0f : 1.0f;
- float f30 = b30 ? 0.0f : 1.0f;
- float f31 = b31 ? 0.0f : 1.0f;
- float f32 = b32 ? 0.0f : 1.0f;
- float f33 = b33 ? 0.0f : 1.0f;
- float f34 = b34 ? 0.0f : 1.0f;
- float f36 = b36 ? 0.0f : 1.0f;
- float f35 = b35 ? 0.0f : 1.0f;
- float f08 = b08 ? 0.0f : 1.0f;
- float f09 = b09 ? 0.0f : 1.0f;
- float f10 = b10 ? 0.0f : 1.0f;
- float f11 = b11 ? 0.0f : 1.0f;
- float f12 = b12 ? 0.0f : 1.0f;
- float f14 = b14 ? 0.0f : 1.0f;
- float f13 = b13 ? 0.0f : 1.0f;
-
- if (conditionA) {
- f16 /= 1000.0f;
- f17 /= 1000.0f;
- f18 /= 1000.0f;
- f19 /= 1000.0f;
- f20 /= 1000.0f;
- f21 /= 1000.0f;
- f15 /= 1000.0f;
- f08 /= 1000.0f;
- f09 /= 1000.0f;
- f10 /= 1000.0f;
- f11 /= 1000.0f;
- f12 /= 1000.0f;
- f30 /= 1000.0f;
- f31 /= 1000.0f;
- f32 /= 1000.0f;
- f33 /= 1000.0f;
- f34 /= 1000.0f;
- f01 /= 1000.0f;
- f02 /= 1000.0f;
- f03 /= 1000.0f;
- f04 /= 1000.0f;
- f05 /= 1000.0f;
- f23 /= 1000.0f;
- f24 /= 1000.0f;
- f25 /= 1000.0f;
- f26 /= 1000.0f;
- f27 /= 1000.0f;
- f22 /= 1000.0f;
- f00 /= 1000.0f;
- f14 /= 1000.0f;
- f13 /= 1000.0f;
- f36 /= 1000.0f;
- f35 /= 1000.0f;
- f07 /= 1000.0f;
- f06 /= 1000.0f;
- f29 /= 1000.0f;
- f28 /= 1000.0f;
- }
- // The parallel move that used to exhaust the ARM64 parallel move
- // resolver's scratch register pool (provided by VIXL) was in the
- // "else" branch of the following condition generated by ART's
- // compiler.
- if (conditionB) {
- f16 /= 100.0f;
- f17 /= 100.0f;
- f18 /= 100.0f;
- f19 /= 100.0f;
- f20 /= 100.0f;
- f21 /= 100.0f;
- f15 /= 100.0f;
- f08 /= 100.0f;
- f09 /= 100.0f;
- f10 /= 100.0f;
- f11 /= 100.0f;
- f12 /= 100.0f;
- f30 /= 100.0f;
- f31 /= 100.0f;
- f32 /= 100.0f;
- f33 /= 100.0f;
- f34 /= 100.0f;
- f01 /= 100.0f;
- f02 /= 100.0f;
- f03 /= 100.0f;
- f04 /= 100.0f;
- f05 /= 100.0f;
- f23 /= 100.0f;
- f24 /= 100.0f;
- f25 /= 100.0f;
- f26 /= 100.0f;
- f27 /= 100.0f;
- f22 /= 100.0f;
- f00 /= 100.0f;
- f14 /= 100.0f;
- f13 /= 100.0f;
- f36 /= 100.0f;
- f35 /= 100.0f;
- f07 /= 100.0f;
- f06 /= 100.0f;
- f29 /= 100.0f;
- f28 /= 100.0f;
- }
- if (conditionC) {
- f16 /= 12.0f;
- f17 /= 12.0f;
- f18 /= 12.0f;
- f19 /= 12.0f;
- f20 /= 12.0f;
- f21 /= 12.0f;
- f15 /= 12.0f;
- f08 /= 12.0f;
- f09 /= 12.0f;
- f10 /= 12.0f;
- f11 /= 12.0f;
- f12 /= 12.0f;
- f30 /= 12.0f;
- f31 /= 12.0f;
- f32 /= 12.0f;
- f33 /= 12.0f;
- f34 /= 12.0f;
- f01 /= 12.0f;
- f02 /= 12.0f;
- f03 /= 12.0f;
- f04 /= 12.0f;
- f05 /= 12.0f;
- f23 /= 12.0f;
- f24 /= 12.0f;
- f25 /= 12.0f;
- f26 /= 12.0f;
- f27 /= 12.0f;
- f22 /= 12.0f;
- f00 /= 12.0f;
- f14 /= 12.0f;
- f13 /= 12.0f;
- f36 /= 12.0f;
- f35 /= 12.0f;
- f07 /= 12.0f;
- f06 /= 12.0f;
- f29 /= 12.0f;
- f28 /= 12.0f;
- }
- float s = 0.0f;
- s = ((float) Math.round(100.0f * s)) / 100.0f;
- String res = s + r;
- }
-
public static void main(String[] args) {
- Main main = new Main();
- main.test();
System.out.println("passed");
}
}
diff --git a/test/646-checker-hadd-alt-char/build b/test/646-checker-hadd-alt-char/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/646-checker-hadd-alt-char/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/646-checker-hadd-alt-char/src/Main.java b/test/646-checker-hadd-alt-char/src/Main.java
index 2a1382dfde..79904ce74f 100644
--- a/test/646-checker-hadd-alt-char/src/Main.java
+++ b/test/646-checker-hadd-alt-char/src/Main.java
@@ -58,7 +58,7 @@ public class Main {
/// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<And2:i\d+>> And [<<IMAX>>,<<Get2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> Add [<<And1>>,<<And2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add>>,<<I1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none
@@ -120,7 +120,7 @@ public class Main {
/// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<And2:i\d+>> And [<<IMAX>>,<<Get2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add1:i\d+>> Add [<<And1>>,<<And2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add2>>,<<I1>>] loop:<<Loop>> outer_loop:none
diff --git a/test/646-checker-hadd-alt-short/build b/test/646-checker-hadd-alt-short/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/646-checker-hadd-alt-short/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/646-checker-hadd-alt-short/src/Main.java b/test/646-checker-hadd-alt-short/src/Main.java
index 4035b97209..1ecb1d8273 100644
--- a/test/646-checker-hadd-alt-short/src/Main.java
+++ b/test/646-checker-hadd-alt-short/src/Main.java
@@ -58,7 +58,7 @@ public class Main {
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<And2:i\d+>> And [<<UMAX>>,<<Get2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> Add [<<And1>>,<<And2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add>>,<<I1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none
@@ -82,7 +82,9 @@ public class Main {
private static void halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
for (int i = 0; i < min_length; i++) {
- bo[i] = (short) (((b1[i] & 0xffff) + (b2[i] & 0xffff)) >>> 1);
+ int v1 = b1[i] & 0xffff;
+ int v2 = b2[i] & 0xffff;
+ bo[i] = (short) ((v1 + v2) >>> 1);
}
}
@@ -116,7 +118,7 @@ public class Main {
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<And2:i\d+>> And [<<UMAX>>,<<Get2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add1:i\d+>> Add [<<And1>>,<<And2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add2>>,<<I1>>] loop:<<Loop>> outer_loop:none
@@ -142,7 +144,9 @@ public class Main {
private static void rounding_halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
for (int i = 0; i < min_length; i++) {
- bo[i] = (short) (((b1[i] & 0xffff) + (b2[i] & 0xffff) + 1) >>> 1);
+ int v1 = b1[i] & 0xffff;
+ int v2 = b2[i] & 0xffff;
+ bo[i] = (short) ((v1 + v2 + 1) >>> 1);
}
}
diff --git a/test/646-checker-hadd-char/build b/test/646-checker-hadd-char/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/646-checker-hadd-char/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/646-checker-hadd-char/src/Main.java b/test/646-checker-hadd-char/src/Main.java
index 6549dab9ff..cbe629711f 100644
--- a/test/646-checker-hadd-char/src/Main.java
+++ b/test/646-checker-hadd-char/src/Main.java
@@ -67,7 +67,7 @@ public class Main {
/// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<And2:i\d+>> And [<<IMAX>>,<<Get2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> Add [<<And1>>,<<And2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Shr:i\d+>> Shr [<<Add>>,<<I1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<Shr>>] loop:<<Loop>> outer_loop:none
@@ -152,7 +152,7 @@ public class Main {
/// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<IMAX>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<And2:i\d+>> And [<<IMAX>>,<<Get2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add1:i\d+>> Add [<<And1>>,<<And2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Shr:i\d+>> Shr [<<Add2>>,<<I1>>] loop:<<Loop>> outer_loop:none
diff --git a/test/646-checker-hadd-short/build b/test/646-checker-hadd-short/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/646-checker-hadd-short/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/646-checker-hadd-short/src/Main.java b/test/646-checker-hadd-short/src/Main.java
index c09da8125b..d78a678dc8 100644
--- a/test/646-checker-hadd-short/src/Main.java
+++ b/test/646-checker-hadd-short/src/Main.java
@@ -86,7 +86,7 @@ public class Main {
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<And2:i\d+>> And [<<UMAX>>,<<Get2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> Add [<<And1>>,<<And2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Shr:i\d+>> Shr [<<Add>>,<<I1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Shr>>] loop:<<Loop>> outer_loop:none
@@ -110,7 +110,9 @@ public class Main {
private static void halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
for (int i = 0; i < min_length; i++) {
- bo[i] = (short) (((b1[i] & 0xffff) + (b2[i] & 0xffff)) >> 1);
+ int v1 = b1[i] & 0xffff;
+ int v2 = b2[i] & 0xffff;
+ bo[i] = (short) ((v1 + v2) >> 1);
}
}
@@ -224,7 +226,7 @@ public class Main {
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<And2:i\d+>> And [<<UMAX>>,<<Get2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add1:i\d+>> Add [<<And1>>,<<And2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Shr:i\d+>> Shr [<<Add2>>,<<I1>>] loop:<<Loop>> outer_loop:none
@@ -250,7 +252,9 @@ public class Main {
private static void rounding_halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
for (int i = 0; i < min_length; i++) {
- bo[i] = (short) (((b1[i] & 0xffff) + (b2[i] & 0xffff) + 1) >> 1);
+ int v1 = b1[i] & 0xffff;
+ int v2 = b2[i] & 0xffff;
+ bo[i] = (short) ((v1 + v2 + 1) >> 1);
}
}
@@ -261,9 +265,9 @@ public class Main {
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<And2:i\d+>> And [<<UMAX>>,<<Get2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add1:i\d+>> Add [<<And2>>,<<I1>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<Add2:i\d+>> Add [<<And1>>,<<Add1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<And1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Shr:i\d+>> Shr [<<Add2>>,<<I1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Shr>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>> outer_loop:none
@@ -288,7 +292,9 @@ public class Main {
int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
for (int i = 0; i < min_length; i++) {
// Slightly different order in idiom does not confuse recognition.
- bo[i] = (short) ((b1[i] & 0xffff) + ((b2[i] & 0xffff) + 1) >> 1);
+ int v1 = b1[i] & 0xffff;
+ int v2 = b2[i] & 0xffff;
+ bo[i] = (short) (v1 + (v2 + 1) >> 1);
}
}
diff --git a/test/660-checker-simd-sad-byte/build b/test/660-checker-simd-sad-byte/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/660-checker-simd-sad-byte/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/660-checker-simd-sad-byte/src/Main.java b/test/660-checker-simd-sad-byte/src/Main.java
index 778d55c3ce..38003d18c6 100644
--- a/test/660-checker-simd-sad-byte/src/Main.java
+++ b/test/660-checker-simd-sad-byte/src/Main.java
@@ -90,8 +90,8 @@ public class Main {
/// CHECK-START: int Main.sadByte2Int(byte[], byte[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
@@ -121,8 +121,8 @@ public class Main {
/// CHECK-START: int Main.sadByte2IntAlt(byte[], byte[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none
@@ -154,8 +154,8 @@ public class Main {
/// CHECK-START: int Main.sadByte2IntAlt2(byte[], byte[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:b\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
diff --git a/test/660-checker-simd-sad-char/build b/test/660-checker-simd-sad-char/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/660-checker-simd-sad-char/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/660-checker-simd-sad-char/src/Main.java b/test/660-checker-simd-sad-char/src/Main.java
index 91c92f1179..18ae024231 100644
--- a/test/660-checker-simd-sad-char/src/Main.java
+++ b/test/660-checker-simd-sad-char/src/Main.java
@@ -59,8 +59,8 @@ public class Main {
/// CHECK-START: int Main.sadChar2Int(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
@@ -82,8 +82,8 @@ public class Main {
/// CHECK-START: int Main.sadChar2IntAlt(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none
@@ -107,8 +107,8 @@ public class Main {
/// CHECK-START: int Main.sadChar2IntAlt2(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
diff --git a/test/660-checker-simd-sad-int/build b/test/660-checker-simd-sad-int/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/660-checker-simd-sad-int/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/660-checker-simd-sad-int/src/Main.java b/test/660-checker-simd-sad-int/src/Main.java
index 29415fd2cf..5952c41c2d 100644
--- a/test/660-checker-simd-sad-int/src/Main.java
+++ b/test/660-checker-simd-sad-int/src/Main.java
@@ -22,8 +22,8 @@ public class Main {
/// CHECK-START: int Main.sadInt2Int(int[], int[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
@@ -51,8 +51,8 @@ public class Main {
/// CHECK-START: int Main.sadInt2IntAlt(int[], int[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub1:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none
@@ -79,8 +79,8 @@ public class Main {
/// CHECK-START: int Main.sadInt2IntAlt2(int[], int[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:i\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
diff --git a/test/660-checker-simd-sad-short/build b/test/660-checker-simd-sad-short/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/660-checker-simd-sad-short/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/660-checker-simd-sad-short/src/Main.java b/test/660-checker-simd-sad-short/src/Main.java
index 77c9e53e0c..ff74559292 100644
--- a/test/660-checker-simd-sad-short/src/Main.java
+++ b/test/660-checker-simd-sad-short/src/Main.java
@@ -61,8 +61,8 @@ public class Main {
/// CHECK-START: int Main.sadShort2Int(short[], short[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
@@ -92,8 +92,8 @@ public class Main {
/// CHECK-START: int Main.sadShort2IntAlt(short[], short[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none
@@ -125,8 +125,8 @@ public class Main {
/// CHECK-START: int Main.sadShort2IntAlt2(short[], short[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
@@ -161,8 +161,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<Cons:i\d+>> IntConstant -7 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> Add [<<Get1>>,<<Cons>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Add>>] loop:<<Loop>> outer_loop:none
@@ -193,8 +193,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<Cons:i\d+>> IntConstant 7 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Cons>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
@@ -225,8 +225,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<Cons:i\d+>> IntConstant 7 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> Add [<<Get1>>,<<Cons>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Add>>] loop:<<Loop>> outer_loop:none
diff --git a/test/660-checker-simd-sad-short2/build b/test/660-checker-simd-sad-short2/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/660-checker-simd-sad-short2/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/660-checker-simd-sad-short2/src/Main.java b/test/660-checker-simd-sad-short2/src/Main.java
index a1f98297c5..1ce0e2a266 100644
--- a/test/660-checker-simd-sad-short2/src/Main.java
+++ b/test/660-checker-simd-sad-short2/src/Main.java
@@ -59,8 +59,8 @@ public class Main {
/// CHECK-START: int Main.sadCastedChar2Int(char[], char[]) instruction_simplifier (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<BC1:i\d+>> BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<BC2:i\d+>> BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<BC1>>] loop:<<Loop>> outer_loop:none
@@ -75,8 +75,8 @@ public class Main {
/// CHECK-START: int Main.sadCastedChar2Int(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
@@ -106,8 +106,8 @@ public class Main {
/// CHECK-START: int Main.sadCastedChar2IntAlt(char[], char[]) instruction_simplifier (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<BC1:i\d+>> BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<BC2:i\d+>> BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<BC1>>] loop:<<Loop>> outer_loop:none
@@ -123,13 +123,11 @@ public class Main {
/// CHECK-START: int Main.sadCastedChar2IntAlt(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
- // Note: Get1+Cnv1 not simplified yet due to env use of Get1 in NullCheck for s2[i].
- /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get2>>,<<Cnv1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get2>>,<<Get1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
@@ -158,8 +156,8 @@ public class Main {
/// CHECK-START: int Main.sadCastedChar2IntAlt2(char[], char[]) instruction_simplifier (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<BC1:\i\d+>> BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<BC2:\i\d+>> BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<BC1>>] loop:<<Loop>> outer_loop:none
@@ -175,13 +173,11 @@ public class Main {
/// CHECK-START: int Main.sadCastedChar2IntAlt2(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
- // Note: Get1+Cnv1 not simplified yet due to env use of Get1 in NullCheck for s2[i].
- /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get2:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
- /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Cnv1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
diff --git a/test/660-checker-simd-sad-short3/build b/test/660-checker-simd-sad-short3/build
deleted file mode 100644
index d85147f17b..0000000000
--- a/test/660-checker-simd-sad-short3/build
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 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.
-
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
diff --git a/test/660-checker-simd-sad-short3/src/Main.java b/test/660-checker-simd-sad-short3/src/Main.java
index 877a5362ce..d0892c37c8 100644
--- a/test/660-checker-simd-sad-short3/src/Main.java
+++ b/test/660-checker-simd-sad-short3/src/Main.java
@@ -25,8 +25,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<Param:s\d+>> ParameterValue loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get>>,<<Param>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
@@ -56,8 +56,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<Param:s\d+>> ParameterValue loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Param>>,<<Get>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
@@ -87,8 +87,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<ConsI:i\d+>> IntConstant -32767 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<ConsI>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Add>>] loop:<<Loop>> outer_loop:none
@@ -118,8 +118,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<ConsI:i\d+>> IntConstant 32767 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<ConsI>>,<<Get>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
@@ -149,8 +149,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<Conv:s\d+>> TypeConversion [{{i\d+}}] loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Get>>,<<Conv>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
@@ -181,8 +181,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<Conv:s\d+>> TypeConversion [{{i\d+}}] loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Conv>>,<<Get>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Intrin:i\d+>> Abs [<<Sub>>] loop:<<Loop>> outer_loop:none
@@ -213,8 +213,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<ConsI:i\d+>> IntConstant 110 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> [<<Get>>,<<ConsI>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Conv:s\d+>> TypeConversion [<<Add>>] loop:<<Loop>> outer_loop:none
@@ -248,8 +248,8 @@ public class Main {
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<ConsI:i\d+>> IntConstant 110 loop:none
- /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
- /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Get:s\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> [<<Get>>,<<ConsI>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Conv:s\d+>> TypeConversion [<<Add>>] loop:<<Loop>> outer_loop:none
diff --git a/test/679-checker-minmax/src/Main.java b/test/679-checker-minmax/src/Main.java
index abf8c279da..4b7265642a 100644
--- a/test/679-checker-minmax/src/Main.java
+++ b/test/679-checker-minmax/src/Main.java
@@ -37,6 +37,13 @@ public class Main {
//
/// CHECK-START: int Main.minI(int) instruction_simplifier (after)
/// CHECK-NOT: InvokeStaticOrDirect
+ //
+ /// CHECK-START-ARM64: int Main.minI(int) disassembly (after)
+ /// CHECK-NOT: mov {{w\d+}}, #0x14
+ /// CHECK: cmp {{w\d+}}, #0x14
+ // Check that the constant generation was handled by VIXL.
+ /// CHECK: mov w16, #0x14
+ /// CHECK: csel {{w\d+}}, {{w\d+}}, w16, lt
public static int minI(int a) {
return Math.min(a, 20);
}
@@ -55,6 +62,13 @@ public class Main {
//
/// CHECK-START: long Main.minL(long) instruction_simplifier (after)
/// CHECK-NOT: InvokeStaticOrDirect
+ //
+ /// CHECK-START-ARM64: long Main.minL(long) disassembly (after)
+ /// CHECK-NOT: mov {{x\d+}}, #0x14
+ /// CHECK: cmp {{x\d+}}, #0x14
+ // Check that the constant generation was handled by VIXL.
+ /// CHECK: mov x16, #0x14
+ /// CHECK: csel {{x\d+}}, {{x\d+}}, x16, lt
public static long minL(long a) {
return Math.min(a, 20L);
}
@@ -73,6 +87,13 @@ public class Main {
//
/// CHECK-START: int Main.maxI(int) instruction_simplifier (after)
/// CHECK-NOT: InvokeStaticOrDirect
+ //
+ /// CHECK-START-ARM64: int Main.maxI(int) disassembly (after)
+ /// CHECK-NOT: mov {{w\d+}}, #0x14
+ /// CHECK: cmp {{w\d+}}, #0x14
+ // Check that the constant generation was handled by VIXL.
+ /// CHECK: mov w16, #0x14
+ /// CHECK: csel {{w\d+}}, {{w\d+}}, w16, gt
public static int maxI(int a) {
return Math.max(a, 20);
}
@@ -91,11 +112,166 @@ public class Main {
//
/// CHECK-START: long Main.maxL(long) instruction_simplifier (after)
/// CHECK-NOT: InvokeStaticOrDirect
+ //
+ /// CHECK-START-ARM64: long Main.maxL(long) disassembly (after)
+ /// CHECK-NOT: mov {{x\d+}}, #0x14
+ /// CHECK: cmp {{x\d+}}, #0x14
+ // Check that the constant generation was handled by VIXL.
+ /// CHECK: mov x16, #0x14
+ /// CHECK: csel {{x\d+}}, {{x\d+}}, x16, gt
public static long maxL(long a) {
return Math.max(a, 20L);
}
//
+ // Special Cases
+ //
+
+ /// CHECK-START-ARM64: int Main.minIntConstantZero(int) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{w\d+}}, #0x0
+ /// CHECK: cmp {{w\d+}}, #0x0 (0)
+ /// CHECK: csel {{w\d+}}, {{w\d+}}, wzr, lt
+ /// CHECK: ret
+ public static int minIntConstantZero(int a) {
+ return Math.min(a, 0);
+ }
+
+ /// CHECK-START-ARM64: int Main.minIntConstantOne(int) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{w\d+}}, #0x1
+ /// CHECK: cmp {{w\d+}}, #0x1 (1)
+ /// CHECK: csinc {{w\d+}}, {{w\d+}}, wzr, lt
+ /// CHECK: ret
+ public static int minIntConstantOne(int a) {
+ return Math.min(a, 1);
+ }
+
+ /// CHECK-START-ARM64: int Main.minIntConstantMinusOne(int) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{w\d+}}, #0xffffffff
+ /// CHECK: cmn {{w\d+}}, #0x1 (1)
+ /// CHECK: csinv {{w\d+}}, {{w\d+}}, wzr, lt
+ /// CHECK: ret
+ public static int minIntConstantMinusOne(int a) {
+ return Math.min(a, -1);
+ }
+
+ /// CHECK-START-ARM64: long Main.minLongConstantZero(long) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{x\d+}}, #0x0
+ /// CHECK: cmp {{x\d+}}, #0x0 (0)
+ /// CHECK: csel {{x\d+}}, {{x\d+}}, xzr, lt
+ /// CHECK: ret
+ public static long minLongConstantZero(long a) {
+ return Math.min(a, 0L);
+ }
+
+ /// CHECK-START-ARM64: long Main.minLongConstantOne(long) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{x\d+}}, #0x1
+ /// CHECK: cmp {{x\d+}}, #0x1 (1)
+ /// CHECK: csinc {{x\d+}}, {{x\d+}}, xzr, lt
+ /// CHECK: ret
+ public static long minLongConstantOne(long a) {
+ return Math.min(a, 1L);
+ }
+
+ /// CHECK-START-ARM64: long Main.minLongConstantMinusOne(long) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{x\d+}}, #0xffffffffffffffff
+ /// CHECK: cmn {{x\d+}}, #0x1 (1)
+ /// CHECK: csinv {{x\d+}}, {{x\d+}}, xzr, lt
+ /// CHECK: ret
+ public static long minLongConstantMinusOne(long a) {
+ return Math.min(a, -1L);
+ }
+
+ /// CHECK-START-ARM64: int Main.maxIntConstantZero(int) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{w\d+}}, #0x0
+ /// CHECK: cmp {{w\d+}}, #0x0 (0)
+ /// CHECK: csel {{w\d+}}, {{w\d+}}, wzr, gt
+ /// CHECK: ret
+ public static int maxIntConstantZero(int a) {
+ return Math.max(a, 0);
+ }
+
+ /// CHECK-START-ARM64: int Main.maxIntConstantOne(int) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{w\d+}}, #0x1
+ /// CHECK: cmp {{w\d+}}, #0x1 (1)
+ /// CHECK: csinc {{w\d+}}, {{w\d+}}, wzr, gt
+ /// CHECK: ret
+ public static int maxIntConstantOne(int a) {
+ return Math.max(a, 1);
+ }
+
+ /// CHECK-START-ARM64: int Main.maxIntConstantMinusOne(int) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{w\d+}}, #0xffffffff
+ /// CHECK: cmn {{w\d+}}, #0x1 (1)
+ /// CHECK: csinv {{w\d+}}, {{w\d+}}, wzr, gt
+ /// CHECK: ret
+ public static int maxIntConstantMinusOne(int a) {
+ return Math.max(a, -1);
+ }
+
+ /// CHECK-START-ARM64: int Main.maxIntLargeConstant(int) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK: mov {{w\d+}}, #0x2001
+ /// CHECK: cmp {{w\d+}}, {{w\d+}}
+ // Check that constant generation was not handled by VIXL.
+ /// CHECK-NOT: mov {{w\d+}}, #0x2001
+ /// CHECK: csel {{w\d+}}, {{w\d+}}, {{w\d+}}, gt
+ /// CHECK: ret
+ public static int maxIntLargeConstant(int a) {
+ return Math.max(a, 8193);
+ }
+
+ /// CHECK-START-ARM64: long Main.maxLongConstantZero(long) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{x\d+}}, #0x0
+ /// CHECK: cmp {{x\d+}}, #0x0 (0)
+ /// CHECK: csel {{x\d+}}, {{x\d+}}, xzr, gt
+ /// CHECK: ret
+ public static long maxLongConstantZero(long a) {
+ return Math.max(a, 0L);
+ }
+
+ /// CHECK-START-ARM64: long Main.maxLongConstantOne(long) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{x\d+}}, #0x1
+ /// CHECK: cmp {{x\d+}}, #0x1 (1)
+ /// CHECK: csinc {{x\d+}}, {{x\d+}}, xzr, gt
+ /// CHECK: ret
+ public static long maxLongConstantOne(long a) {
+ return Math.max(a, 1L);
+ }
+
+ /// CHECK-START-ARM64: long Main.maxLongConstantMinusOne(long) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK-NOT: mov {{x\d+}}, #0xffffffffffffffff
+ /// CHECK: cmn {{x\d+}}, #0x1 (1)
+ /// CHECK: csinv {{x\d+}}, {{x\d+}}, xzr, gt
+ /// CHECK: ret
+ public static long maxLongConstantMinusOne(long a) {
+ return Math.max(a, -1L);
+ }
+
+ /// CHECK-START-ARM64: long Main.maxLongLargeConstant(long) disassembly (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ /// CHECK: mov {{x\d+}}, #0x2001
+ /// CHECK: cmp {{x\d+}}, {{x\d+}}
+ // Check that constant generation was not handled by VIXL.
+ /// CHECK-NOT: mov {{x\d+}}, #0x2001
+ /// CHECK: csel {{x\d+}}, {{x\d+}}, {{x\d+}}, gt
+ /// CHECK: ret
+ public static long maxLongLargeConstant(long a) {
+ return Math.max(a, 8193L);
+ }
+
+ //
// Different types.
//
@@ -538,12 +714,40 @@ public class Main {
// Intrinsics.
expectEquals(10, minI(10));
expectEquals(20, minI(25));
+ expectEquals(-1, minIntConstantZero(-1));
+ expectEquals(0, minIntConstantZero(1));
+ expectEquals(0, minIntConstantOne(0));
+ expectEquals(1, minIntConstantOne(2));
+ expectEquals(-2, minIntConstantMinusOne(-2));
+ expectEquals(-1, minIntConstantMinusOne(0));
expectEquals(10L, minL(10L));
expectEquals(20L, minL(25L));
+ expectEquals(-1L, minLongConstantZero(-1L));
+ expectEquals(0L, minLongConstantZero(1L));
+ expectEquals(0L, minLongConstantOne(0L));
+ expectEquals(1L, minLongConstantOne(2L));
+ expectEquals(-2L, minLongConstantMinusOne(-2L));
+ expectEquals(-1L, minLongConstantMinusOne(0L));
expectEquals(20, maxI(10));
expectEquals(25, maxI(25));
+ expectEquals(0, maxIntConstantZero(-1));
+ expectEquals(1, maxIntConstantZero(1));
+ expectEquals(1, maxIntConstantOne(0));
+ expectEquals(2, maxIntConstantOne(2));
+ expectEquals(-1, maxIntConstantMinusOne(-2));
+ expectEquals(0, maxIntConstantMinusOne(0));
+ expectEquals(8193, maxIntLargeConstant(8192));
+ expectEquals(9000, maxIntLargeConstant(9000));
expectEquals(20L, maxL(10L));
expectEquals(25L, maxL(25L));
+ expectEquals(0L, maxLongConstantZero(-1L));
+ expectEquals(1L, maxLongConstantZero(1L));
+ expectEquals(1L, maxLongConstantOne(0L));
+ expectEquals(2L, maxLongConstantOne(2L));
+ expectEquals(-1L, maxLongConstantMinusOne(-2L));
+ expectEquals(0L, maxLongConstantMinusOne(0L));
+ expectEquals(8193L, maxLongLargeConstant(8192L));
+ expectEquals(9000L, maxLongLargeConstant(9000L));
// Types.
expectEquals(10, min1(10, 20));
expectEquals(10, min2(10, 20));
diff --git a/test/952-invoke-custom/build b/test/952-invoke-custom/build
index 2caca94d7f..53d8228808 100755
--- a/test/952-invoke-custom/build
+++ b/test/952-invoke-custom/build
@@ -21,11 +21,6 @@ ASM_JAR="${ANDROID_BUILD_TOP}/prebuilts/misc/common/asm/asm-6.0.jar"
INTERMEDIATE_CLASSES=classes-intermediate
CLASSES=classes
-DEXER="${DX:-dx}"
-if [ "${USE_D8=false}" = "true" ]; then
- DEXER="${ANDROID_HOST_OUT}/bin/d8-compat-dx"
-fi
-
# Create directory for intermediate classes
rm -rf "${INTERMEDIATE_CLASSES}"
mkdir "${INTERMEDIATE_CLASSES}"
@@ -46,7 +41,7 @@ done
# Create DEX
DX_FLAGS="${DX_FLAGS} --min-sdk-version=26 --debug --dump-width=1000"
-${DEXER} -JXmx256m --dex ${DX_FLAGS} --dump-to=${CLASSES}.lst --output=classes.dex ${CLASSES}
+${DX} -JXmx256m --dex ${DX_FLAGS} --output=classes.dex ${CLASSES}
# Zip DEX to file name expected by test runner
zip ${TEST_NAME:-classes-dex}.jar classes.dex
diff --git a/test/979-const-method-handle/build b/test/979-const-method-handle/build
index ce931a96d1..67fc2a6339 100755
--- a/test/979-const-method-handle/build
+++ b/test/979-const-method-handle/build
@@ -22,11 +22,6 @@ INTERMEDIATE_CLASSES=classes-intermediate
TRANSFORMER_CLASSES=classes-transformer
CLASSES=classes
-DEXER="${DX:-dx}"
-if [ "${USE_D8=false}" = "true" ]; then
- DEXER="${ANDROID_HOST_OUT}/bin/d8-compat-dx"
-fi
-
# Create directories for classes
for class_dir in "${INTERMEDIATE_CLASSES}" "${TRANSFORMER_CLASSES}" "${CLASSES}"; do
rm -rf "${class_dir}"
@@ -49,7 +44,7 @@ done
# Create DEX
DX_FLAGS="${DX_FLAGS} --min-sdk-version=28 --debug --dump-width=1000"
-${DEXER} -JXmx256m --dex ${DX_FLAGS} --dump-to=${CLASSES}.lst --output=classes.dex ${CLASSES} ${TRANSFORMER_CLASSES}
+${DX} -JXmx256m --dex ${DX_FLAGS} --output=classes.dex ${CLASSES} ${TRANSFORMER_CLASSES}
# Zip DEX to file name expected by test runner
zip ${TEST_NAME:-classes-dex}.jar classes.dex
diff --git a/test/etc/default-build b/test/etc/default-build
index 9dbc73c6b4..c8993c6611 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -307,7 +307,7 @@ function make_dex() {
fi
# Make dex file from desugared JAR.
- ${dexer} -JXmx256m ${DX_VM_FLAGS} --debug --dex --dump-to=${name}.lst --output=${name}.dex --dump-width=1000 ${DX_FLAGS} "${dx_input}"
+ ${dexer} -JXmx256m ${DX_VM_FLAGS} --debug --dex --output=${name}.dex ${DX_FLAGS} "${dx_input}"
}
# Merge all the dex files in $1..$N into $1. Skip non-existing files, but at least 1 file must exist.
diff --git a/test/run-test b/test/run-test
index 5bd8b3b348..b5b42854e5 100755
--- a/test/run-test
+++ b/test/run-test
@@ -529,12 +529,27 @@ fi
# Most interesting target architecture variables are Makefile variables, not environment variables.
# Try to map the suffix64 flag and what we find in ${ANDROID_PRODUCT_OUT}/data/art-test to an architecture name.
function guess_target_arch_name() {
- grep32bit=`ls ${ANDROID_PRODUCT_OUT}/data/art-test | grep -E '^(arm|x86|mips)$'`
- grep64bit=`ls ${ANDROID_PRODUCT_OUT}/data/art-test | grep -E '^(arm64|x86_64|mips64)$'`
- if [ "x${suffix64}" = "x64" ]; then
- target_arch_name=${grep64bit}
+ # Check whether this is a device with native bridge. Currently this is hardcoded
+ # to x86 + arm.
+ x86_arm=`ls ${ANDROID_PRODUCT_OUT}/data/art-test | sort | grep -E '^(arm|x86)$'`
+ # Collapse line-breaks into spaces
+ x86_arm=$(echo $x86_arm)
+ if [ "x$x86_arm" = "xarm x86" ] ; then
+ err_echo "Native-bridge configuration detected."
+ # We only support the main arch for tests.
+ if [ "x${suffix64}" = "x64" ]; then
+ target_arch_name=""
+ else
+ target_arch_name=x86
+ fi
else
- target_arch_name=${grep32bit}
+ grep32bit=`ls ${ANDROID_PRODUCT_OUT}/data/art-test | grep -E '^(arm|x86|mips)$'`
+ grep64bit=`ls ${ANDROID_PRODUCT_OUT}/data/art-test | grep -E '^(arm64|x86_64|mips64)$'`
+ if [ "x${suffix64}" = "x64" ]; then
+ target_arch_name=${grep64bit}
+ else
+ target_arch_name=${grep32bit}
+ fi
fi
}
diff --git a/tools/teardown-buildbot-device.sh b/tools/teardown-buildbot-device.sh
index bf14ca4f9f..d25dd2b15f 100755
--- a/tools/teardown-buildbot-device.sh
+++ b/tools/teardown-buildbot-device.sh
@@ -25,62 +25,82 @@ adb root
adb wait-for-device
if [[ -n "$ART_TEST_CHROOT" ]]; then
-
- # remove_filesystem_from_chroot DIR-IN-CHROOT FSTYPE REMOVE-DIR-IN-CHROOT
- # -----------------------------------------------------------------------
- # Unmount filesystem with type FSTYPE mounted in directory DIR-IN-CHROOT
- # under the chroot directory.
- # Remove DIR-IN-CHROOT under the chroot if REMOVE-DIR-IN-CHROOT is
- # true.
- remove_filesystem_from_chroot() {
- local dir_in_chroot=$1
- local fstype=$2
- local remove_dir=$3
- local dir="$ART_TEST_CHROOT/$dir_in_chroot"
- adb shell test -d "$dir" \
- && adb shell mount | grep -q "^$fstype on $dir type $fstype " \
- && if adb shell umount "$dir"; then
- $remove_dir && adb shell rmdir "$dir"
- else
- adb shell lsof "$dir"
- fi
- }
-
- # Tear down the chroot dir.
- echo -e "${green}Tear down the chroot dir in $ART_TEST_CHROOT${nc}"
-
# Check that ART_TEST_CHROOT is correctly defined.
[[ "x$ART_TEST_CHROOT" = x/* ]] || { echo "$ART_TEST_CHROOT is not an absolute path"; exit 1; }
- # Remove /dev from chroot.
- remove_filesystem_from_chroot dev tmpfs true
-
- # Remove /sys/kernel/debug from chroot.
- # The /sys/kernel/debug directory under the chroot dir cannot be
- # deleted, as it is part of the host device's /sys filesystem.
- remove_filesystem_from_chroot sys/kernel/debug debugfs false
- # Remove /sys from chroot.
- remove_filesystem_from_chroot sys sysfs true
-
- # Remove /proc from chroot.
- remove_filesystem_from_chroot proc proc true
-
- # Remove /etc from chroot.
- adb shell rm -f "$ART_TEST_CHROOT/etc"
- adb shell rm -rf "$ART_TEST_CHROOT/system/etc"
-
- # Remove directories used for ART testing in chroot.
- adb shell rm -rf "$ART_TEST_CHROOT/data/local/tmp"
- adb shell rm -rf "$ART_TEST_CHROOT/data/dalvik-cache"
- adb shell rm -rf "$ART_TEST_CHROOT/tmp"
-
- # Remove property_contexts file(s) from chroot.
- property_context_files="/property_contexts \
- /system/etc/selinux/plat_property_contexts \
- /vendor/etc/selinux/nonplat_property_context \
- /plat_property_contexts \
- /nonplat_property_contexts"
- for f in $property_context_files; do
- adb shell rm -f "$ART_TEST_CHROOT$f"
- done
+ if adb shell test -d "$ART_TEST_CHROOT"; then
+ # Display users of the chroot dir.
+
+ echo -e "${green}List open files under chroot dir $ART_TEST_CHROOT${nc}"
+ adb shell lsof | grep "$ART_TEST_CHROOT"
+
+ echo -e "${green}List processes running from binaries under chroot dir $ART_TEST_CHROOT${nc}"
+ for link in $(adb shell ls -d "/proc/*/root"); do
+ root=$(adb shell readlink "$link")
+ if [[ "x$root" = "x$ART_TEST_CHROOT" ]]; then
+ dir=$(dirname "$link")
+ pid=$(basename "$dir")
+ cmdline=$(adb shell cat "$dir"/cmdline | tr -d '\000')
+ echo "$cmdline (PID: $pid)"
+ fi
+ done
+
+
+ # Tear down the chroot dir.
+
+ echo -e "${green}Tear down the chroot set up in $ART_TEST_CHROOT${nc}"
+
+ # remove_filesystem_from_chroot DIR-IN-CHROOT FSTYPE REMOVE-DIR-IN-CHROOT
+ # -----------------------------------------------------------------------
+ # Unmount filesystem with type FSTYPE mounted in directory DIR-IN-CHROOT
+ # under the chroot directory.
+ # Remove DIR-IN-CHROOT under the chroot if REMOVE-DIR-IN-CHROOT is
+ # true.
+ remove_filesystem_from_chroot() {
+ local dir_in_chroot=$1
+ local fstype=$2
+ local remove_dir=$3
+ local dir="$ART_TEST_CHROOT/$dir_in_chroot"
+ adb shell test -d "$dir" \
+ && adb shell mount | grep -q "^$fstype on $dir type $fstype " \
+ && if adb shell umount "$dir"; then
+ $remove_dir && adb shell rmdir "$dir"
+ else
+ echo "Files still open in $dir:"
+ adb shell lsof | grep "$dir"
+ fi
+ }
+
+ # Remove /dev from chroot.
+ remove_filesystem_from_chroot dev tmpfs true
+
+ # Remove /sys/kernel/debug from chroot.
+ # The /sys/kernel/debug directory under the chroot dir cannot be
+ # deleted, as it is part of the host device's /sys filesystem.
+ remove_filesystem_from_chroot sys/kernel/debug debugfs false
+ # Remove /sys from chroot.
+ remove_filesystem_from_chroot sys sysfs true
+
+ # Remove /proc from chroot.
+ remove_filesystem_from_chroot proc proc true
+
+ # Remove /etc from chroot.
+ adb shell rm -f "$ART_TEST_CHROOT/etc"
+ adb shell rm -rf "$ART_TEST_CHROOT/system/etc"
+
+ # Remove directories used for ART testing in chroot.
+ adb shell rm -rf "$ART_TEST_CHROOT/data/local/tmp"
+ adb shell rm -rf "$ART_TEST_CHROOT/data/dalvik-cache"
+ adb shell rm -rf "$ART_TEST_CHROOT/tmp"
+
+ # Remove property_contexts file(s) from chroot.
+ property_context_files="/property_contexts \
+ /system/etc/selinux/plat_property_contexts \
+ /vendor/etc/selinux/nonplat_property_context \
+ /plat_property_contexts \
+ /nonplat_property_contexts"
+ for f in $property_context_files; do
+ adb shell rm -f "$ART_TEST_CHROOT$f"
+ done
+ fi
fi