}
DCHECK_EQ(argument_index, number_of_arguments);
- if (invoke->IsInvokeStaticOrDirect()) {
- invoke->SetArgumentAt(argument_index, graph_->GetCurrentMethod());
- argument_index++;
- }
-
if (clinit_check_requirement == HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit) {
// Add the class initialization check as last input of `invoke`.
DCHECK(clinit_check != nullptr);
HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor) {
ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetArena();
LocationSummary* locations = new (allocator) LocationSummary(invoke, LocationSummary::kCall);
+ locations->AddTemp(visitor->GetMethodLocation());
for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) {
HInstruction* input = invoke->InputAt(i);
}
locations->SetOut(visitor->GetReturnLocation(invoke->GetType()));
-
- if (invoke->IsInvokeStaticOrDirect()) {
- HInvokeStaticOrDirect* call = invoke->AsInvokeStaticOrDirect();
- if (call->IsStringInit()) {
- locations->AddTemp(visitor->GetMethodLocation());
- } else if (call->IsRecursive()) {
- locations->SetInAt(call->GetCurrentMethodInputIndex(), visitor->GetMethodLocation());
- } else {
- locations->AddTemp(visitor->GetMethodLocation());
- locations->SetInAt(call->GetCurrentMethodInputIndex(), Location::RequiresRegister());
- }
- } else {
- locations->AddTemp(visitor->GetMethodLocation());
- }
}
void CodeGenerator::BlockIfInRegister(Location location, bool is_out) const {
IntrinsicLocationsBuilderARM intrinsic(GetGraph()->GetArena(),
codegen_->GetInstructionSetFeatures());
if (intrinsic.TryDispatch(invoke)) {
- LocationSummary* locations = invoke->GetLocations();
- if (locations->CanCall()) {
- locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister());
- }
return;
}
return;
}
- LocationSummary* locations = invoke->GetLocations();
- codegen_->GenerateStaticOrDirectCall(
- invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
+ Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
+
+ codegen_->GenerateStaticOrDirectCall(invoke, temp);
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
Location receiver = locations->InAt(0);
uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
// temp = object->GetClass();
- DCHECK(receiver.IsRegister());
- __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
+ if (receiver.IsStackSlot()) {
+ __ LoadFromOffset(kLoadWord, temp, SP, receiver.GetStackIndex());
+ __ LoadFromOffset(kLoadWord, temp, temp, class_offset);
+ } else {
+ __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
+ }
codegen_->MaybeRecordImplicitNullCheck(invoke);
// temp = temp->GetMethodAt(method_offset);
uint32_t entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(
}
}
-void CodeGeneratorARM::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
+void CodeGeneratorARM::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp) {
+ DCHECK_EQ(temp, kArtMethodRegister);
+
// TODO: Implement all kinds of calls:
// 1) boot -> boot
// 2) app -> boot
// Currently we implement the app -> app logic, which looks up in the resolve cache.
if (invoke->IsStringInit()) {
- Register reg = temp.AsRegister<Register>();
// temp = thread->string_init_entrypoint
- __ LoadFromOffset(kLoadWord, reg, TR, invoke->GetStringInitOffset());
+ __ LoadFromOffset(kLoadWord, temp, TR, invoke->GetStringInitOffset());
// LR = temp[offset_of_quick_compiled_code]
- __ LoadFromOffset(kLoadWord, LR, reg,
+ __ LoadFromOffset(kLoadWord, LR, temp,
ArtMethod::EntryPointFromQuickCompiledCodeOffset(
kArmWordSize).Int32Value());
// LR()
__ blx(LR);
- } else if (invoke->IsRecursive()) {
- __ bl(GetFrameEntryLabel());
} else {
- Register current_method =
- invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex()).AsRegister<Register>();
- Register reg = temp.AsRegister<Register>();
- // reg = current_method->dex_cache_resolved_methods_;
- __ LoadFromOffset(
- kLoadWord, reg, current_method, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value());
- // reg = reg[index_in_cache]
- __ LoadFromOffset(
- kLoadWord, reg, reg, CodeGenerator::GetCacheOffset(invoke->GetDexMethodIndex()));
- // LR = reg[offset_of_quick_compiled_code]
- __ LoadFromOffset(kLoadWord, LR, reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
- kArmWordSize).Int32Value());
- // LR()
- __ blx(LR);
+ // temp = method;
+ LoadCurrentMethod(temp);
+ if (!invoke->IsRecursive()) {
+ // temp = temp->dex_cache_resolved_methods_;
+ __ LoadFromOffset(
+ kLoadWord, temp, temp, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value());
+ // temp = temp[index_in_cache]
+ __ LoadFromOffset(
+ kLoadWord, temp, temp, CodeGenerator::GetCacheOffset(invoke->GetDexMethodIndex()));
+ // LR = temp[offset_of_quick_compiled_code]
+ __ LoadFromOffset(kLoadWord, LR, temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+ kArmWordSize).Int32Value());
+ // LR()
+ __ blx(LR);
+ } else {
+ __ bl(GetFrameEntryLabel());
+ }
}
DCHECK(!IsLeafMethod());
Label* GetFrameEntryLabel() { return &frame_entry_label_; }
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
+ void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp);
private:
// Labels for each block that will be compiled.
}
Location InvokeDexCallingConventionVisitorARM64::GetMethodLocation() const {
- return LocationFrom(kArtMethodRegister);
+ return LocationFrom(x0);
}
CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph,
IntrinsicLocationsBuilderARM64 intrinsic(GetGraph()->GetArena());
if (intrinsic.TryDispatch(invoke)) {
- LocationSummary* locations = invoke->GetLocations();
- if (locations->CanCall()) {
- locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister());
- }
return;
}
return false;
}
-void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
+void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp) {
// Make sure that ArtMethod* is passed in kArtMethodRegister as per the calling convention.
+ DCHECK(temp.Is(kArtMethodRegister));
size_t index_in_cache = GetCachePointerOffset(invoke->GetDexMethodIndex());
// TODO: Implement all kinds of calls:
// Currently we implement the app -> app logic, which looks up in the resolve cache.
if (invoke->IsStringInit()) {
- Register reg = XRegisterFrom(temp);
// temp = thread->string_init_entrypoint
- __ Ldr(reg.X(), MemOperand(tr, invoke->GetStringInitOffset()));
+ __ Ldr(temp.X(), MemOperand(tr, invoke->GetStringInitOffset()));
// LR = temp->entry_point_from_quick_compiled_code_;
__ Ldr(lr, MemOperand(
- reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize).Int32Value()));
+ temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize).Int32Value()));
// lr()
__ Blr(lr);
- } else if (invoke->IsRecursive()) {
- __ Bl(&frame_entry_label_);
} else {
- Register current_method =
- XRegisterFrom(invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex()));
- Register reg = XRegisterFrom(temp);
- // temp = current_method->dex_cache_resolved_methods_;
- __ Ldr(reg.W(), MemOperand(current_method.X(),
- ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
- // temp = temp[index_in_cache];
- __ Ldr(reg.X(), MemOperand(reg, index_in_cache));
- // lr = temp->entry_point_from_quick_compiled_code_;
- __ Ldr(lr, MemOperand(reg.X(), ArtMethod::EntryPointFromQuickCompiledCodeOffset(
- kArm64WordSize).Int32Value()));
- // lr();
- __ Blr(lr);
+ // temp = method;
+ LoadCurrentMethod(temp.X());
+ if (!invoke->IsRecursive()) {
+ // temp = temp->dex_cache_resolved_methods_;
+ __ Ldr(temp.W(), MemOperand(temp.X(),
+ ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
+ // temp = temp[index_in_cache];
+ __ Ldr(temp.X(), MemOperand(temp, index_in_cache));
+ // lr = temp->entry_point_from_quick_compiled_code_;
+ __ Ldr(lr, MemOperand(temp.X(), ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+ kArm64WordSize).Int32Value()));
+ // lr();
+ __ Blr(lr);
+ } else {
+ __ Bl(&frame_entry_label_);
+ }
}
DCHECK(!IsLeafMethod());
}
BlockPoolsScope block_pools(GetVIXLAssembler());
- LocationSummary* locations = invoke->GetLocations();
- codegen_->GenerateStaticOrDirectCall(
- invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
+ Register temp = XRegisterFrom(invoke->GetLocations()->GetTemp(0));
+ codegen_->GenerateStaticOrDirectCall(invoke, temp);
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
BlockPoolsScope block_pools(GetVIXLAssembler());
- DCHECK(receiver.IsRegister());
- __ Ldr(temp.W(), HeapOperandFrom(receiver, class_offset));
+ // temp = object->GetClass();
+ if (receiver.IsStackSlot()) {
+ __ Ldr(temp.W(), MemOperand(sp, receiver.GetStackIndex()));
+ __ Ldr(temp.W(), HeapOperand(temp.W(), class_offset));
+ } else {
+ DCHECK(receiver.IsRegister());
+ __ Ldr(temp.W(), HeapOperandFrom(receiver, class_offset));
+ }
codegen_->MaybeRecordImplicitNullCheck(invoke);
// temp = temp->GetMethodAt(method_offset);
__ Ldr(temp, MemOperand(temp, method_offset));
void LocationsBuilderARM64::VisitCurrentMethod(HCurrentMethod* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
- locations->SetOut(LocationFrom(kArtMethodRegister));
+ locations->SetOut(LocationFrom(x0));
}
void InstructionCodeGeneratorARM64::VisitCurrentMethod(
return false;
}
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
+ void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, vixl::Register temp);
private:
// Labels for each block that will be compiled.
IntrinsicLocationsBuilderX86 intrinsic(codegen_);
if (intrinsic.TryDispatch(invoke)) {
- LocationSummary* locations = invoke->GetLocations();
- if (locations->CanCall()) {
- locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister());
- }
return;
}
return;
}
- LocationSummary* locations = invoke->GetLocations();
codegen_->GenerateStaticOrDirectCall(
- invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
+ invoke, invoke->GetLocations()->GetTemp(0).AsRegister<Register>());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
LocationSummary* locations = invoke->GetLocations();
Location receiver = locations->InAt(0);
uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
- DCHECK(receiver.IsRegister());
- __ movl(temp, Address(receiver.AsRegister<Register>(), class_offset));
+ // temp = object->GetClass();
+ if (receiver.IsStackSlot()) {
+ __ movl(temp, Address(ESP, receiver.GetStackIndex()));
+ __ movl(temp, Address(temp, class_offset));
+ } else {
+ __ movl(temp, Address(receiver.AsRegister<Register>(), class_offset));
+ }
codegen_->MaybeRecordImplicitNullCheck(invoke);
// temp = temp->GetMethodAt(method_offset);
__ movl(temp, Address(temp, method_offset));
void CodeGeneratorX86::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
- Location temp) {
+ Register temp) {
// TODO: Implement all kinds of calls:
// 1) boot -> boot
// 2) app -> boot
if (invoke->IsStringInit()) {
// temp = thread->string_init_entrypoint
- Register reg = temp.AsRegister<Register>();
- __ fs()->movl(reg, Address::Absolute(invoke->GetStringInitOffset()));
+ __ fs()->movl(temp, Address::Absolute(invoke->GetStringInitOffset()));
// (temp + offset_of_quick_compiled_code)()
__ call(Address(
- reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
- } else if (invoke->IsRecursive()) {
- __ call(GetFrameEntryLabel());
+ temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
} else {
- Register current_method =
- invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex()).AsRegister<Register>();
- Register reg = temp.AsRegister<Register>();
- // temp = temp->dex_cache_resolved_methods_;
- __ movl(reg, Address(
- current_method, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
- // temp = temp[index_in_cache]
- __ movl(reg, Address(reg,
- CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
- // (temp + offset_of_quick_compiled_code)()
- __ call(Address(reg,
- ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
+ // temp = method;
+ LoadCurrentMethod(temp);
+ if (!invoke->IsRecursive()) {
+ // temp = temp->dex_cache_resolved_methods_;
+ __ movl(temp, Address(temp, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
+ // temp = temp[index_in_cache]
+ __ movl(temp, Address(temp,
+ CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
+ // (temp + offset_of_quick_compiled_code)()
+ __ call(Address(temp,
+ ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
+ } else {
+ __ call(GetFrameEntryLabel());
+ }
}
DCHECK(!IsLeafMethod());
void Move64(Location destination, Location source);
// Generate a call to a static or direct method.
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
+ void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp);
// Emit a write barrier.
void MarkGCCard(Register temp,
}
void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
- Location temp) {
+ CpuRegister temp) {
// All registers are assumed to be correctly set up.
// TODO: Implement all kinds of calls:
// Currently we implement the app -> app logic, which looks up in the resolve cache.
if (invoke->IsStringInit()) {
- CpuRegister reg = temp.AsRegister<CpuRegister>();
// temp = thread->string_init_entrypoint
- __ gs()->movl(reg, Address::Absolute(invoke->GetStringInitOffset()));
+ __ gs()->movl(temp, Address::Absolute(invoke->GetStringInitOffset()));
// (temp + offset_of_quick_compiled_code)()
- __ call(Address(reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+ __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
kX86_64WordSize).SizeValue()));
- } else if (invoke->IsRecursive()) {
- __ call(&frame_entry_label_);
} else {
- LocationSummary* locations = invoke->GetLocations();
- CpuRegister reg = temp.AsRegister<CpuRegister>();
- CpuRegister current_method =
- locations->InAt(invoke->GetCurrentMethodInputIndex()).AsRegister<CpuRegister>();
- // temp = temp->dex_cache_resolved_methods_;
- __ movl(reg, Address(
- current_method, ArtMethod::DexCacheResolvedMethodsOffset().SizeValue()));
- // temp = temp[index_in_cache]
- __ movq(reg, Address(
- reg, CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
- // (temp + offset_of_quick_compiled_code)()
- __ call(Address(reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
- kX86_64WordSize).SizeValue()));
+ // temp = method;
+ LoadCurrentMethod(temp);
+ if (!invoke->IsRecursive()) {
+ // temp = temp->dex_cache_resolved_methods_;
+ __ movl(temp, Address(temp, ArtMethod::DexCacheResolvedMethodsOffset().SizeValue()));
+ // temp = temp[index_in_cache]
+ __ movq(temp, Address(
+ temp, CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
+ // (temp + offset_of_quick_compiled_code)()
+ __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+ kX86_64WordSize).SizeValue()));
+ } else {
+ __ call(&frame_entry_label_);
+ }
}
DCHECK(!IsLeafMethod());
IntrinsicLocationsBuilderX86_64 intrinsic(codegen_);
if (intrinsic.TryDispatch(invoke)) {
- LocationSummary* locations = invoke->GetLocations();
- if (locations->CanCall()) {
- locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister());
- }
return;
}
return;
}
- LocationSummary* locations = invoke->GetLocations();
codegen_->GenerateStaticOrDirectCall(
- invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
+ invoke,
+ invoke->GetLocations()->GetTemp(0).AsRegister<CpuRegister>());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
Location receiver = locations->InAt(0);
size_t class_offset = mirror::Object::ClassOffset().SizeValue();
// temp = object->GetClass();
- DCHECK(receiver.IsRegister());
- __ movl(temp, Address(receiver.AsRegister<CpuRegister>(), class_offset));
+ if (receiver.IsStackSlot()) {
+ __ movl(temp, Address(CpuRegister(RSP), receiver.GetStackIndex()));
+ __ movl(temp, Address(temp, class_offset));
+ } else {
+ __ movl(temp, Address(receiver.AsRegister<CpuRegister>(), class_offset));
+ }
codegen_->MaybeRecordImplicitNullCheck(invoke);
// temp = temp->GetMethodAt(method_offset);
__ movq(temp, Address(temp, method_offset));
return false;
}
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
+ void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, CpuRegister temp);
const X86_64InstructionSetFeatures& GetInstructionSetFeatures() const {
return isa_features_;
MoveArguments(invoke_, codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
- Location::RegisterLocation(kArtMethodRegister));
+ codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), kArtMethodRegister);
RecordPcInfo(codegen, invoke_, invoke_->GetDexPc());
} else {
UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
MoveArguments(invoke_, codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
- LocationFrom(kArtMethodRegister));
+ codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), kArtMethodRegister);
RecordPcInfo(codegen, invoke_, invoke_->GetDexPc());
} else {
UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
MoveArguments(invoke_, codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
- Location::RegisterLocation(EAX));
+ codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), EAX);
RecordPcInfo(codegen, invoke_, invoke_->GetDexPc());
} else {
UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
MoveArguments(invoke, codegen);
DCHECK(invoke->IsInvokeStaticOrDirect());
- codegen->GenerateStaticOrDirectCall(invoke->AsInvokeStaticOrDirect(),
- Location::RegisterLocation(EAX));
+ codegen->GenerateStaticOrDirectCall(invoke->AsInvokeStaticOrDirect(), EAX);
codegen->RecordPcInfo(invoke, invoke->GetDexPc());
// Copy the result back to the expected output.
MoveArguments(invoke_, codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(
- invoke_->AsInvokeStaticOrDirect(), Location::RegisterLocation(RDI));
+ codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), CpuRegister(RDI));
RecordPcInfo(codegen, invoke_, invoke_->GetDexPc());
} else {
UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
MoveArguments(invoke, codegen);
DCHECK(invoke->IsInvokeStaticOrDirect());
- codegen->GenerateStaticOrDirectCall(
- invoke->AsInvokeStaticOrDirect(), Location::RegisterLocation(RDI));
+ codegen->GenerateStaticOrDirectCall(invoke->AsInvokeStaticOrDirect(), CpuRegister(RDI));
codegen->RecordPcInfo(invoke, invoke->GetDexPc());
// Copy the result back to the expected output.
return temps_.Size();
}
- bool HasTemps() const { return !temps_.IsEmpty(); }
-
Location Out() const { return output_; }
bool CanCall() const { return call_kind_ != kNoCall; }
ClinitCheckRequirement clinit_check_requirement)
: HInvoke(arena,
number_of_arguments,
- // There is one extra argument for the HCurrentMethod node, and
- // potentially one other if the clinit check is explicit.
- clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 2u : 1u,
+ clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u,
return_type,
dex_pc,
dex_method_index,
bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); }
bool IsStringInit() const { return string_init_offset_ != 0; }
int32_t GetStringInitOffset() const { return string_init_offset_; }
- uint32_t GetCurrentMethodInputIndex() const { return GetNumberOfArguments(); }
// Is this instruction a call to a static method?
bool IsStatic() const {
if (defined_by != nullptr && !current->IsSplit()) {
LocationSummary* locations = defined_by->GetLocations();
if (!locations->OutputCanOverlapWithInputs() && locations->Out().IsUnallocated()) {
- for (size_t i = 0, e = defined_by->InputCount(); i < e; ++i) {
+ for (HInputIterator it(defined_by); !it.Done(); it.Advance()) {
// Take the last interval of the input. It is the location of that interval
// that will be used at `defined_by`.
- LiveInterval* interval = defined_by->InputAt(i)->GetLiveInterval()->GetLastSibling();
+ LiveInterval* interval = it.Current()->GetLiveInterval()->GetLastSibling();
// Note that interval may have not been processed yet.
// TODO: Handle non-split intervals last in the work list.
- if (locations->InAt(i).IsValid()
- && interval->HasRegister()
- && interval->SameRegisterKind(*current)) {
+ if (interval->HasRegister() && interval->SameRegisterKind(*current)) {
// The input must be live until the end of `defined_by`, to comply to
// the linear scan algorithm. So we use `defined_by`'s end lifetime
// position to check whether the input is dead or is inactive after
HInstruction* input = current->InputAt(i);
// Some instructions 'inline' their inputs, that is they do not need
// to be materialized.
- if (input->HasSsaIndex() && current->GetLocations()->InAt(i).IsValid()) {
+ if (input->HasSsaIndex()) {
live_in->SetBit(input->GetSsaIndex());
input->GetLiveInterval()->AddUse(current, /* environment */ nullptr, i);
}
first_range_->start_ = from;
} else {
// Instruction without uses.
- DCHECK(first_use_ == nullptr);
+ DCHECK(!defined_by_->HasNonEnvironmentUses());
DCHECK(from == defined_by_->GetLifetimePosition());
first_range_ = last_range_ = range_search_start_ =
new (allocator_) LiveRange(from, from + 2, nullptr);
/// CHECK-START: void Main.InlineVoid() inliner (before)
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
/// CHECK-DAG: InvokeStaticOrDirect
- /// CHECK-DAG: InvokeStaticOrDirect [<<Const42>>,{{[ij]\d+}}]
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Const42>>]
/// CHECK-START: void Main.InlineVoid() inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
/// CHECK-START: int Main.InlineParameter(int) inliner (before)
/// CHECK-DAG: <<Param:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Param>>,{{[ij]\d+}}]
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Param>>]
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.InlineParameter(int) inliner (after)
/// CHECK-START: long Main.InlineWideParameter(long) inliner (before)
/// CHECK-DAG: <<Param:j\d+>> ParameterValue
- /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<Param>>,{{[ij]\d+}}]
+ /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<Param>>]
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: long Main.InlineWideParameter(long) inliner (after)
/// CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (before)
/// CHECK-DAG: <<Param:l\d+>> ParameterValue
- /// CHECK-DAG: <<Result:l\d+>> InvokeStaticOrDirect [<<Param>>,{{[ij]\d+}}]
+ /// CHECK-DAG: <<Result:l\d+>> InvokeStaticOrDirect [<<Param>>]
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (after)
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Add:i\d+>> InvokeStaticOrDirect [<<Const1>>,<<Const3>>,{{[ij]\d+}}]
- /// CHECK-DAG: <<Sub:i\d+>> InvokeStaticOrDirect [<<Const5>>,<<Const3>>,{{[ij]\d+}}]
+ /// CHECK-DAG: <<Add:i\d+>> InvokeStaticOrDirect [<<Const1>>,<<Const3>>]
+ /// CHECK-DAG: <<Sub:i\d+>> InvokeStaticOrDirect [<<Const5>>,<<Const3>>]
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Add>>,<<Sub>>]
/// CHECK-DAG: Return [<<Phi>>]
/// CHECK-START: void Main.invokeStaticInlined() builder (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [<<ClinitCheck>>]
/// CHECK-START: void Main.invokeStaticInlined() inliner (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-START: void Main.invokeStaticNotInlined() builder (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [<<ClinitCheck>>]
/// CHECK-START: void Main.invokeStaticNotInlined() inliner (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [<<ClinitCheck>>]
// The following checks ensure the clinit check and load class
// instructions added by the builder are pruned by the