diff options
author | 2018-01-08 12:37:05 +0000 | |
---|---|---|
committer | 2018-01-08 12:37:05 +0000 | |
commit | 30f54cc45bd338f9d9079786dae96ea13ab9f163 (patch) | |
tree | 542b2e8afa185ee3fdeb17fa1637579c110cc2c6 | |
parent | 4cb6347613e37c98bf40d8bb5e6583ac81f4d856 (diff) | |
parent | 672b9c1e95beed861a63d4a4c273114387f035a6 (diff) |
Merge "ARM: Fix breaking changes from recent VIXL update."
-rw-r--r-- | compiler/optimizing/intrinsics_arm_vixl.cc | 76 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm_vixl.cc | 19 | ||||
-rw-r--r-- | compiler/utils/arm/jni_macro_assembler_arm_vixl.cc | 10 | ||||
-rw-r--r-- | disassembler/disassembler_arm.cc | 26 |
4 files changed, 81 insertions, 50 deletions
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc index 1d8ea092a4..99b8b5df74 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.cc +++ b/compiler/optimizing/intrinsics_arm_vixl.cc @@ -1458,30 +1458,38 @@ void IntrinsicLocationsBuilderARMVIXL::VisitStringCompareTo(HInvoke* invoke) { locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap); } +// Forward declaration. +// +// ART build system imposes a size limit (deviceFrameSizeLimit) on the stack frames generated +// by the compiler for every C++ function, and if this function gets inlined in +// IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo, the limit will be exceeded, resulting in a +// build failure. That is the reason why NO_INLINE attribute is used. +static void NO_INLINE GenerateStringCompareToLoop(ArmVIXLAssembler* assembler, + HInvoke* invoke, + vixl32::Label* end, + vixl32::Label* different_compression); + void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) { ArmVIXLAssembler* assembler = GetAssembler(); LocationSummary* locations = invoke->GetLocations(); - vixl32::Register str = InputRegisterAt(invoke, 0); - vixl32::Register arg = InputRegisterAt(invoke, 1); - vixl32::Register out = OutputRegister(invoke); + const vixl32::Register str = InputRegisterAt(invoke, 0); + const vixl32::Register arg = InputRegisterAt(invoke, 1); + const vixl32::Register out = OutputRegister(invoke); - vixl32::Register temp0 = RegisterFrom(locations->GetTemp(0)); - vixl32::Register temp1 = RegisterFrom(locations->GetTemp(1)); - vixl32::Register temp2 = RegisterFrom(locations->GetTemp(2)); + const vixl32::Register temp0 = RegisterFrom(locations->GetTemp(0)); + const vixl32::Register temp1 = RegisterFrom(locations->GetTemp(1)); + const vixl32::Register temp2 = RegisterFrom(locations->GetTemp(2)); vixl32::Register temp3; if (mirror::kUseStringCompression) { temp3 = RegisterFrom(locations->GetTemp(3)); } - vixl32::Label loop; - vixl32::Label find_char_diff; vixl32::Label end; vixl32::Label different_compression; // Get offsets of count and value fields within a string object. const int32_t count_offset = mirror::String::CountOffset().Int32Value(); - const int32_t value_offset = mirror::String::ValueOffset().Int32Value(); // Note that the null check must have been done earlier. DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0))); @@ -1546,6 +1554,38 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) { __ add(ne, temp0, temp0, temp0); } + + GenerateStringCompareToLoop(assembler, invoke, &end, &different_compression); + + __ Bind(&end); + + if (can_slow_path) { + __ Bind(slow_path->GetExitLabel()); + } +} + +static void GenerateStringCompareToLoop(ArmVIXLAssembler* assembler, + HInvoke* invoke, + vixl32::Label* end, + vixl32::Label* different_compression) { + LocationSummary* locations = invoke->GetLocations(); + + const vixl32::Register str = InputRegisterAt(invoke, 0); + const vixl32::Register arg = InputRegisterAt(invoke, 1); + const vixl32::Register out = OutputRegister(invoke); + + const vixl32::Register temp0 = RegisterFrom(locations->GetTemp(0)); + const vixl32::Register temp1 = RegisterFrom(locations->GetTemp(1)); + const vixl32::Register temp2 = RegisterFrom(locations->GetTemp(2)); + vixl32::Register temp3; + if (mirror::kUseStringCompression) { + temp3 = RegisterFrom(locations->GetTemp(3)); + } + + vixl32::Label loop; + vixl32::Label find_char_diff; + + const int32_t value_offset = mirror::String::ValueOffset().Int32Value(); // Store offset of string value in preparation for comparison loop. __ Mov(temp1, value_offset); @@ -1577,12 +1617,12 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) { // With string compression, we have compared 8 bytes, otherwise 4 chars. __ Subs(temp0, temp0, (mirror::kUseStringCompression ? 8 : 4)); __ B(hi, &loop, /* far_target */ false); - __ B(&end); + __ B(end); __ Bind(&find_char_diff_2nd_cmp); if (mirror::kUseStringCompression) { __ Subs(temp0, temp0, 4); // 4 bytes previously compared. - __ B(ls, &end, /* far_target */ false); // Was the second comparison fully beyond the end? + __ B(ls, end, /* far_target */ false); // Was the second comparison fully beyond the end? } else { // Without string compression, we can start treating temp0 as signed // and rely on the signed comparison below. @@ -1610,7 +1650,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) { // the remaining string data, so just return length diff (out). // The comparison is unsigned for string compression, otherwise signed. __ Cmp(temp0, Operand(temp1, vixl32::LSR, (mirror::kUseStringCompression ? 3 : 4))); - __ B((mirror::kUseStringCompression ? ls : le), &end, /* far_target */ false); + __ B((mirror::kUseStringCompression ? ls : le), end, /* far_target */ false); // Extract the characters and calculate the difference. if (mirror::kUseStringCompression) { @@ -1637,8 +1677,8 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) { temps.Release(temp_reg); if (mirror::kUseStringCompression) { - __ B(&end); - __ Bind(&different_compression); + __ B(end); + __ Bind(different_compression); // Comparison for different compression style. const size_t c_char_size = DataType::Size(DataType::Type::kInt8); @@ -1680,7 +1720,7 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) { __ B(ne, &different_compression_diff, /* far_target */ false); __ Subs(temp0, temp0, 2); __ B(hi, &different_compression_loop, /* far_target */ false); - __ B(&end); + __ B(end); // Calculate the difference. __ Bind(&different_compression_diff); @@ -1698,12 +1738,6 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringCompareTo(HInvoke* invoke) { __ it(cc); __ rsb(cc, out, out, 0); } - - __ Bind(&end); - - if (can_slow_path) { - __ Bind(slow_path->GetExitLabel()); - } } // The cut off for unrolling the loop in String.equals() intrinsic for const strings. diff --git a/compiler/utils/arm/assembler_arm_vixl.cc b/compiler/utils/arm/assembler_arm_vixl.cc index 34849cd58d..d6b24da407 100644 --- a/compiler/utils/arm/assembler_arm_vixl.cc +++ b/compiler/utils/arm/assembler_arm_vixl.cc @@ -483,13 +483,9 @@ void ArmVIXLMacroAssembler::CompareAndBranchIfNonZero(vixl32::Register rn, void ArmVIXLMacroAssembler::B(vixl32::Label* label) { if (!label->IsBound()) { - // Try to use 16-bit T2 encoding of B instruction. + // Try to use a 16-bit encoding of the B instruction. DCHECK(OutsideITBlock()); - ExactAssemblyScope guard(this, - k16BitT32InstructionSizeInBytes, - CodeBufferCheckScope::kMaximumSize); - b(al, Narrow, label); - AddBranchLabel(label); + BPreferNear(label); return; } MacroAssembler::B(label); @@ -497,18 +493,11 @@ void ArmVIXLMacroAssembler::B(vixl32::Label* label) { void ArmVIXLMacroAssembler::B(vixl32::Condition cond, vixl32::Label* label, bool is_far_target) { if (!label->IsBound() && !is_far_target) { - // Try to use 16-bit T2 encoding of B instruction. + // Try to use a 16-bit encoding of the B instruction. DCHECK(OutsideITBlock()); - ExactAssemblyScope guard(this, - k16BitT32InstructionSizeInBytes, - CodeBufferCheckScope::kMaximumSize); - b(cond, Narrow, label); - AddBranchLabel(label); + BPreferNear(cond, label); return; } - // To further reduce the Bcc encoding size and use 16-bit T1 encoding, - // we can provide a hint to this function: i.e. far_target=false. - // By default this function uses 'EncodingSizeType::Best' which generates 32-bit T3 encoding. MacroAssembler::B(cond, label); } diff --git a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc index 0bae4d4b69..2b3e979606 100644 --- a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc +++ b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc @@ -624,14 +624,8 @@ void ArmVIXLJNIMacroAssembler::ExceptionPoll(ManagedRegister m_scratch, size_t s Thread::ExceptionOffset<kArmPointerSize>().Int32Value()); ___ Cmp(scratch.AsVIXLRegister(), 0); - { - ExactAssemblyScope guard(asm_.GetVIXLAssembler(), - vixl32::kMaxInstructionSizeInBytes, - CodeBufferCheckScope::kMaximumSize); - vixl32::Label* label = exception_blocks_.back()->Entry(); - ___ b(ne, Narrow, label); - ___ AddBranchLabel(label); - } + vixl32::Label* label = exception_blocks_.back()->Entry(); + ___ BPreferNear(ne, label); // TODO: think about using CBNZ here. } diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc index 66419e3649..49f92499e3 100644 --- a/disassembler/disassembler_arm.cc +++ b/disassembler/disassembler_arm.cc @@ -63,10 +63,8 @@ class DisassemblerArm::CustomDisassembler FINAL : public PrintDisassembler { case kVld2Location: case kVld3Location: case kVld4Location: { - const uintptr_t pc_delta = label.GetLabel()->GetPcOffset(); - const int32_t offset = label.GetLabel()->GetLocation(); - - os() << "[pc, #" << offset - pc_delta << "]"; + const int32_t offset = label.GetImmediate(); + os() << "[pc, #" << offset << "]"; PrintLiteral(type, offset); return *this; } @@ -114,14 +112,26 @@ class DisassemblerArm::CustomDisassembler FINAL : public PrintDisassembler { public: CustomDisassembler(std::ostream& os, const DisassemblerOptions* options) - : PrintDisassembler(&disassembler_stream_), disassembler_stream_(os, this, options) {} + : PrintDisassembler(&disassembler_stream_), + disassembler_stream_(os, this, options), + is_t32_(true) {} void PrintCodeAddress(uint32_t prog_ctr) OVERRIDE { os() << "0x" << std::hex << std::setw(8) << std::setfill('0') << prog_ctr << ": "; } + void SetIsT32(bool is_t32) { + is_t32_ = is_t32; + } + + bool GetIsT32() const { + return is_t32_; + } + private: CustomDisassemblerStream disassembler_stream_; + // Whether T32 stream is decoded. + bool is_t32_; }; void DisassemblerArm::CustomDisassembler::CustomDisassemblerStream::PrintLiteral(LocationType type, @@ -141,7 +151,9 @@ void DisassemblerArm::CustomDisassembler::CustomDisassemblerStream::PrintLiteral sizeof(unaligned_float), sizeof(unaligned_double)}; const uintptr_t begin = reinterpret_cast<uintptr_t>(options_->base_address_); const uintptr_t end = reinterpret_cast<uintptr_t>(options_->end_address_); - uintptr_t literal_addr = RoundDown(disasm_->GetCodeAddress(), vixl::aarch32::kRegSizeInBytes) + offset; + uintptr_t literal_addr = + RoundDown(disasm_->GetCodeAddress(), vixl::aarch32::kRegSizeInBytes) + offset; + literal_addr += disasm_->GetIsT32() ? vixl::aarch32::kT32PcDelta : vixl::aarch32::kA32PcDelta; if (!options_->absolute_addresses_) { literal_addr += begin; @@ -199,6 +211,7 @@ size_t DisassemblerArm::Dump(std::ostream& os, const uint8_t* begin) { const bool is_t32 = (reinterpret_cast<uintptr_t>(begin) & 1) != 0; disasm_->SetCodeAddress(GetPc(instr_ptr)); + disasm_->SetIsT32(is_t32); if (is_t32) { const uint16_t* const ip = reinterpret_cast<const uint16_t*>(instr_ptr); @@ -223,6 +236,7 @@ void DisassemblerArm::Dump(std::ostream& os, const uint8_t* begin, const uint8_t const bool is_t32 = (reinterpret_cast<uintptr_t>(begin) & 1) != 0; disasm_->SetCodeAddress(GetPc(base)); + disasm_->SetIsT32(is_t32); if (is_t32) { // The Thumb specifier bits cancel each other. |