diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2014-11-07 17:47:25 +0000 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2014-11-10 10:33:37 +0000 |
commit | 52839d17c06175e19ca4a093fb878450d1c4310d (patch) | |
tree | 552ea632ad4d1f688bdfd04b66102e25312bd237 /compiler/optimizing/code_generator_arm.cc | |
parent | a453307957afdc3ef0a7988025539ab8919464bc (diff) | |
download | art-52839d17c06175e19ca4a093fb878450d1c4310d.tar.gz art-52839d17c06175e19ca4a093fb878450d1c4310d.tar.bz2 art-52839d17c06175e19ca4a093fb878450d1c4310d.zip |
Support invoke-interface in optimizing.
Change-Id: Ic18d7c3d2810557231caf0571956e0c431f5d384
Diffstat (limited to 'compiler/optimizing/code_generator_arm.cc')
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index fef7f0e80f..8c54cdfcf3 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1131,10 +1131,6 @@ void InstructionCodeGeneratorARM::VisitInvokeStatic(HInvokeStatic* invoke) { DCHECK(!codegen_->IsLeafMethod()); } -void LocationsBuilderARM::VisitInvokeVirtual(HInvokeVirtual* invoke) { - HandleInvoke(invoke); -} - void LocationsBuilderARM::HandleInvoke(HInvoke* invoke) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke, LocationSummary::kCall); @@ -1149,6 +1145,9 @@ void LocationsBuilderARM::HandleInvoke(HInvoke* invoke) { locations->SetOut(calling_convention_visitor.GetReturnLocation(invoke->GetType())); } +void LocationsBuilderARM::VisitInvokeVirtual(HInvokeVirtual* invoke) { + HandleInvoke(invoke); +} void InstructionCodeGeneratorARM::VisitInvokeVirtual(HInvokeVirtual* invoke) { Register temp = invoke->GetLocations()->GetTemp(0).As<Register>(); @@ -1175,6 +1174,42 @@ void InstructionCodeGeneratorARM::VisitInvokeVirtual(HInvokeVirtual* invoke) { codegen_->RecordPcInfo(invoke, invoke->GetDexPc()); } +void LocationsBuilderARM::VisitInvokeInterface(HInvokeInterface* invoke) { + HandleInvoke(invoke); + // Add the hidden argument. + invoke->GetLocations()->AddTemp(Location::RegisterLocation(R12)); +} + +void InstructionCodeGeneratorARM::VisitInvokeInterface(HInvokeInterface* invoke) { + // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError. + Register temp = invoke->GetLocations()->GetTemp(0).As<Register>(); + uint32_t method_offset = mirror::Class::EmbeddedImTableOffset().Uint32Value() + + (invoke->GetImtIndex() % mirror::Class::kImtSize) * sizeof(mirror::Class::ImTableEntry); + LocationSummary* locations = invoke->GetLocations(); + Location receiver = locations->InAt(0); + uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); + + // Set the hidden argument. + __ LoadImmediate(invoke->GetLocations()->GetTemp(1).As<Register>(), invoke->GetDexMethodIndex()); + + // temp = object->GetClass(); + if (receiver.IsStackSlot()) { + __ LoadFromOffset(kLoadWord, temp, SP, receiver.GetStackIndex()); + __ LoadFromOffset(kLoadWord, temp, temp, class_offset); + } else { + __ LoadFromOffset(kLoadWord, temp, receiver.As<Register>(), class_offset); + } + // temp = temp->GetImtEntryAt(method_offset); + uint32_t entry_point = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value(); + __ LoadFromOffset(kLoadWord, temp, temp, method_offset); + // LR = temp->GetEntryPoint(); + __ LoadFromOffset(kLoadWord, LR, temp, entry_point); + // LR(); + __ blx(LR); + DCHECK(!codegen_->IsLeafMethod()); + codegen_->RecordPcInfo(invoke, invoke->GetDexPc()); +} + void LocationsBuilderARM::VisitNeg(HNeg* neg) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); |