diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/inliner.cc | 50 | ||||
| -rw-r--r-- | compiler/optimizing/inliner.h | 3 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_mips.cc | 89 |
3 files changed, 126 insertions, 16 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index d84787984d..3b83e95071 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -344,6 +344,7 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) { if (actual_method != nullptr) { bool result = TryInlineAndReplace(invoke_instruction, actual_method, + ReferenceTypeInfo::CreateInvalid(), /* do_rtp */ true, cha_devirtualize); if (result && !invoke_instruction->IsInvokeStaticOrDirect()) { @@ -471,9 +472,10 @@ bool HInliner::TryInlineMonomorphicCall(HInvoke* invoke_instruction, HInstruction* receiver = invoke_instruction->InputAt(0); HInstruction* cursor = invoke_instruction->GetPrevious(); HBasicBlock* bb_cursor = invoke_instruction->GetBlock(); - + Handle<mirror::Class> handle = handles_->NewHandle(GetMonomorphicType(classes)); if (!TryInlineAndReplace(invoke_instruction, resolved_method, + ReferenceTypeInfo::Create(handle, /* is_exact */ true), /* do_rtp */ false, /* cha_devirtualize */ false)) { return false; @@ -591,13 +593,13 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, break; } ArtMethod* method = nullptr; + + Handle<mirror::Class> handle = handles_->NewHandle(classes->Get(i)); if (invoke_instruction->IsInvokeInterface()) { - method = classes->Get(i)->FindVirtualMethodForInterface( - resolved_method, pointer_size); + method = handle->FindVirtualMethodForInterface(resolved_method, pointer_size); } else { DCHECK(invoke_instruction->IsInvokeVirtual()); - method = classes->Get(i)->FindVirtualMethodForVirtual( - resolved_method, pointer_size); + method = handle->FindVirtualMethodForVirtual(resolved_method, pointer_size); } HInstruction* receiver = invoke_instruction->InputAt(0); @@ -605,10 +607,13 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, HBasicBlock* bb_cursor = invoke_instruction->GetBlock(); dex::TypeIndex class_index = FindClassIndexIn( - classes->Get(i), caller_dex_file, caller_compilation_unit_.GetDexCache()); + handle.Get(), caller_dex_file, caller_compilation_unit_.GetDexCache()); HInstruction* return_replacement = nullptr; if (!class_index.IsValid() || - !TryBuildAndInline(invoke_instruction, method, &return_replacement)) { + !TryBuildAndInline(invoke_instruction, + method, + ReferenceTypeInfo::Create(handle, /* is_exact */ true), + &return_replacement)) { all_targets_inlined = false; } else { one_target_inlined = true; @@ -627,7 +632,7 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, cursor, bb_cursor, class_index, - classes->Get(i), + handle.Get(), invoke_instruction, deoptimize); if (deoptimize) { @@ -792,7 +797,10 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget( HBasicBlock* bb_cursor = invoke_instruction->GetBlock(); HInstruction* return_replacement = nullptr; - if (!TryBuildAndInline(invoke_instruction, actual_method, &return_replacement)) { + if (!TryBuildAndInline(invoke_instruction, + actual_method, + ReferenceTypeInfo::CreateInvalid(), + &return_replacement)) { return false; } @@ -857,13 +865,14 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget( bool HInliner::TryInlineAndReplace(HInvoke* invoke_instruction, ArtMethod* method, + ReferenceTypeInfo receiver_type, bool do_rtp, bool cha_devirtualize) { HInstruction* return_replacement = nullptr; uint32_t dex_pc = invoke_instruction->GetDexPc(); HInstruction* cursor = invoke_instruction->GetPrevious(); HBasicBlock* bb_cursor = invoke_instruction->GetBlock(); - if (!TryBuildAndInline(invoke_instruction, method, &return_replacement)) { + if (!TryBuildAndInline(invoke_instruction, method, receiver_type, &return_replacement)) { if (invoke_instruction->IsInvokeInterface()) { // Turn an invoke-interface into an invoke-virtual. An invoke-virtual is always // better than an invoke-interface because: @@ -921,6 +930,7 @@ bool HInliner::TryInlineAndReplace(HInvoke* invoke_instruction, bool HInliner::TryBuildAndInline(HInvoke* invoke_instruction, ArtMethod* method, + ReferenceTypeInfo receiver_type, HInstruction** return_replacement) { if (method->IsProxyMethod()) { VLOG(compiler) << "Method " << method->PrettyMethod() @@ -997,7 +1007,8 @@ bool HInliner::TryBuildAndInline(HInvoke* invoke_instruction, return false; } - if (!TryBuildAndInlineHelper(invoke_instruction, method, same_dex_file, return_replacement)) { + if (!TryBuildAndInlineHelper( + invoke_instruction, method, receiver_type, same_dex_file, return_replacement)) { return false; } @@ -1194,8 +1205,10 @@ HInstanceFieldSet* HInliner::CreateInstanceFieldSet(Handle<mirror::DexCache> dex bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, ArtMethod* resolved_method, + ReferenceTypeInfo receiver_type, bool same_dex_file, HInstruction** return_replacement) { + DCHECK(!(resolved_method->IsStatic() && receiver_type.IsValid())); ScopedObjectAccess soa(Thread::Current()); const DexFile::CodeItem* code_item = resolved_method->GetCodeItem(); const DexFile& callee_dex_file = *resolved_method->GetDexFile(); @@ -1286,12 +1299,13 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, } size_t parameter_index = 0; + bool run_rtp = false; for (HInstructionIterator instructions(callee_graph->GetEntryBlock()->GetInstructions()); !instructions.Done(); instructions.Advance()) { HInstruction* current = instructions.Current(); if (current->IsParameterValue()) { - HInstruction* argument = invoke_instruction->InputAt(parameter_index++); + HInstruction* argument = invoke_instruction->InputAt(parameter_index); if (argument->IsNullConstant()) { current->ReplaceWith(callee_graph->GetNullConstant()); } else if (argument->IsIntConstant()) { @@ -1305,15 +1319,21 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, current->ReplaceWith( callee_graph->GetDoubleConstant(argument->AsDoubleConstant()->GetValue())); } else if (argument->GetType() == Primitive::kPrimNot) { - current->SetReferenceTypeInfo(argument->GetReferenceTypeInfo()); + if (!resolved_method->IsStatic() && parameter_index == 0 && receiver_type.IsValid()) { + run_rtp = true; + current->SetReferenceTypeInfo(receiver_type); + } else { + current->SetReferenceTypeInfo(argument->GetReferenceTypeInfo()); + } current->AsParameterValue()->SetCanBeNull(argument->CanBeNull()); } + ++parameter_index; } } // We have replaced formal arguments with actual arguments. If actual types // are more specific than the declared ones, run RTP again on the inner graph. - if (ArgumentTypesMoreSpecific(invoke_instruction, resolved_method)) { + if (run_rtp || ArgumentTypesMoreSpecific(invoke_instruction, resolved_method)) { ReferenceTypePropagation(callee_graph, dex_compilation_unit.GetDexCache(), handles_, @@ -1502,7 +1522,7 @@ static bool IsReferenceTypeRefinement(ReferenceTypeInfo declared_rti, ReferenceTypeInfo actual_rti = actual_obj->GetReferenceTypeInfo(); return (actual_rti.IsExact() && !declared_rti.IsExact()) || - declared_rti.IsStrictSupertypeOf(actual_rti); + declared_rti.IsStrictSupertypeOf(actual_rti); } ReferenceTypeInfo HInliner::GetClassRTI(mirror::Class* klass) { diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h index 0c6436235f..4c0b990f26 100644 --- a/compiler/optimizing/inliner.h +++ b/compiler/optimizing/inliner.h @@ -66,17 +66,20 @@ class HInliner : public HOptimization { // a CHA guard needs to be added for the inlining. bool TryInlineAndReplace(HInvoke* invoke_instruction, ArtMethod* resolved_method, + ReferenceTypeInfo receiver_type, bool do_rtp, bool cha_devirtualize) REQUIRES_SHARED(Locks::mutator_lock_); bool TryBuildAndInline(HInvoke* invoke_instruction, ArtMethod* resolved_method, + ReferenceTypeInfo receiver_type, HInstruction** return_replacement) REQUIRES_SHARED(Locks::mutator_lock_); bool TryBuildAndInlineHelper(HInvoke* invoke_instruction, ArtMethod* resolved_method, + ReferenceTypeInfo receiver_type, bool same_dex_file, HInstruction** return_replacement); diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 1fb90e5113..e9c6615870 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -2466,6 +2466,94 @@ void IntrinsicCodeGeneratorMIPS::VisitMathRoundFloat(HInvoke* invoke) { __ Bind(&done); } +// void java.lang.String.getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) +void IntrinsicLocationsBuilderMIPS::VisitStringGetCharsNoCheck(HInvoke* invoke) { + LocationSummary* locations = new (arena_) LocationSummary(invoke, + LocationSummary::kCallOnMainOnly, + kIntrinsified); + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetInAt(1, Location::RequiresRegister()); + locations->SetInAt(2, Location::RequiresRegister()); + locations->SetInAt(3, Location::RequiresRegister()); + locations->SetInAt(4, Location::RequiresRegister()); + + // We will call memcpy() to do the actual work. Allocate the temporary + // registers to use the correct input registers, and output register. + // memcpy() uses the normal MIPS calling convention. + InvokeRuntimeCallingConvention calling_convention; + + locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0))); + locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(1))); + locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2))); + + Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt); + locations->AddTemp(Location::RegisterLocation(outLocation.AsRegister<Register>())); +} + +void IntrinsicCodeGeneratorMIPS::VisitStringGetCharsNoCheck(HInvoke* invoke) { + MipsAssembler* assembler = GetAssembler(); + LocationSummary* locations = invoke->GetLocations(); + + // Check assumption that sizeof(Char) is 2 (used in scaling below). + const size_t char_size = Primitive::ComponentSize(Primitive::kPrimChar); + DCHECK_EQ(char_size, 2u); + const size_t char_shift = Primitive::ComponentSizeShift(Primitive::kPrimChar); + + Register srcObj = locations->InAt(0).AsRegister<Register>(); + Register srcBegin = locations->InAt(1).AsRegister<Register>(); + Register srcEnd = locations->InAt(2).AsRegister<Register>(); + Register dstObj = locations->InAt(3).AsRegister<Register>(); + Register dstBegin = locations->InAt(4).AsRegister<Register>(); + + Register dstPtr = locations->GetTemp(0).AsRegister<Register>(); + DCHECK_EQ(dstPtr, A0); + Register srcPtr = locations->GetTemp(1).AsRegister<Register>(); + DCHECK_EQ(srcPtr, A1); + Register numChrs = locations->GetTemp(2).AsRegister<Register>(); + DCHECK_EQ(numChrs, A2); + + Register dstReturn = locations->GetTemp(3).AsRegister<Register>(); + DCHECK_EQ(dstReturn, V0); + + MipsLabel done; + + // Location of data in char array buffer. + const uint32_t data_offset = mirror::Array::DataOffset(char_size).Uint32Value(); + + // Get offset of value field within a string object. + const int32_t value_offset = mirror::String::ValueOffset().Int32Value(); + + __ Beq(srcEnd, srcBegin, &done); // No characters to move. + + // Calculate number of characters to be copied. + __ Subu(numChrs, srcEnd, srcBegin); + + // Calculate destination address. + __ Addiu(dstPtr, dstObj, data_offset); + if (IsR6()) { + __ Lsa(dstPtr, dstBegin, dstPtr, char_shift); + } else { + __ Sll(AT, dstBegin, char_shift); + __ Addu(dstPtr, dstPtr, AT); + } + + // Calculate source address. + __ Addiu(srcPtr, srcObj, value_offset); + if (IsR6()) { + __ Lsa(srcPtr, srcBegin, srcPtr, char_shift); + } else { + __ Sll(AT, srcBegin, char_shift); + __ Addu(srcPtr, srcPtr, AT); + } + + // Calculate number of bytes to copy from number of characters. + __ Sll(numChrs, numChrs, char_shift); + + codegen_->InvokeRuntime(kQuickMemcpy, invoke, invoke->GetDexPc(), nullptr); + + __ Bind(&done); +} + // Unimplemented intrinsics. UNIMPLEMENTED_INTRINSIC(MIPS, MathCeil) @@ -2475,7 +2563,6 @@ UNIMPLEMENTED_INTRINSIC(MIPS, MathRoundDouble) UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeCASLong) UNIMPLEMENTED_INTRINSIC(MIPS, ReferenceGetReferent) -UNIMPLEMENTED_INTRINSIC(MIPS, StringGetCharsNoCheck) UNIMPLEMENTED_INTRINSIC(MIPS, SystemArrayCopyChar) UNIMPLEMENTED_INTRINSIC(MIPS, SystemArrayCopy) |