summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/driver/compiler_driver.cc325
-rw-r--r--compiler/jit/jit_compiler.cc10
-rw-r--r--compiler/optimizing/code_generator.cc30
-rw-r--r--compiler/optimizing/code_generator.h8
-rw-r--r--compiler/optimizing/code_generator_arm.cc36
-rw-r--r--compiler/optimizing/code_generator_arm.h6
-rw-r--r--compiler/optimizing/code_generator_arm64.cc53
-rw-r--r--compiler/optimizing/code_generator_arm64.h6
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.cc65
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.h6
-rw-r--r--compiler/optimizing/code_generator_mips.cc43
-rw-r--r--compiler/optimizing/code_generator_mips.h6
-rw-r--r--compiler/optimizing/code_generator_mips64.cc41
-rw-r--r--compiler/optimizing/code_generator_mips64.h6
-rw-r--r--compiler/optimizing/code_generator_x86.cc33
-rw-r--r--compiler/optimizing/code_generator_x86.h6
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc35
-rw-r--r--compiler/optimizing/code_generator_x86_64.h6
-rw-r--r--compiler/optimizing/inliner.cc2
-rw-r--r--compiler/optimizing/instruction_builder.cc2
-rw-r--r--compiler/optimizing/intrinsics_arm64.cc8
-rw-r--r--compiler/optimizing/intrinsics_arm_vixl.cc5
-rw-r--r--compiler/optimizing/intrinsics_mips.cc8
-rw-r--r--compiler/optimizing/intrinsics_mips64.cc8
-rw-r--r--compiler/optimizing/intrinsics_utils.h5
-rw-r--r--compiler/optimizing/intrinsics_x86.cc1
-rw-r--r--compiler/optimizing/intrinsics_x86_64.cc1
-rw-r--r--compiler/optimizing/nodes.cc6
-rw-r--r--compiler/optimizing/nodes.h10
29 files changed, 258 insertions, 519 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 93f678c64a..29413d9a0a 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1000,8 +1000,9 @@ bool CompilerDriver::ShouldCompileBasedOnProfile(const MethodReference& method_r
if (profile_compilation_info_ == nullptr) {
return false;
}
- // TODO: Revisit compiling all startup methods. b/36457259
- bool result = profile_compilation_info_->IsStartupOrHotMethod(method_ref);
+ // Compile only hot methods, it is the profile saver's job to decide what startup methods to mark
+ // as hot.
+ bool result = profile_compilation_info_->ContainsHotMethod(method_ref);
if (kDebugProfileGuidedCompilation) {
LOG(INFO) << "[ProfileGuidedCompilation] "
@@ -2240,7 +2241,7 @@ class InitializeClassVisitor : public CompilationVisitor {
public:
explicit InitializeClassVisitor(const ParallelCompilationManager* manager) : manager_(manager) {}
- void Visit(size_t class_def_index) OVERRIDE {
+ void Visit(size_t class_def_index) REQUIRES(!Locks::mutator_lock_) OVERRIDE {
ATRACE_CALL();
jobject jclass_loader = manager_->GetClassLoader();
const DexFile& dex_file = *manager_->GetDexFile();
@@ -2255,132 +2256,89 @@ class InitializeClassVisitor : public CompilationVisitor {
Handle<mirror::Class> klass(
hs.NewHandle(manager_->GetClassLinker()->FindClass(soa.Self(), descriptor, class_loader)));
- if (klass != nullptr && !SkipClass(manager_->GetClassLoader(), dex_file, klass.Get())) {
- TryInitializeClass(klass, class_loader);
- }
- // Clear any class not found or verification exceptions.
- soa.Self()->ClearException();
- }
-
- // A helper function for initializing klass.
- void TryInitializeClass(Handle<mirror::Class> klass, Handle<mirror::ClassLoader>& class_loader)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- const DexFile& dex_file = klass->GetDexFile();
- const DexFile::ClassDef* class_def = klass->GetClassDef();
- const DexFile::TypeId& class_type_id = dex_file.GetTypeId(class_def->class_idx_);
- const char* descriptor = dex_file.StringDataByIdx(class_type_id.descriptor_idx_);
- ScopedObjectAccessUnchecked soa(Thread::Current());
- StackHandleScope<3> hs(soa.Self());
-
- mirror::Class::Status old_status = klass->GetStatus();;
- // Only try to initialize classes that were successfully verified.
- if (klass->IsVerified()) {
- // Attempt to initialize the class but bail if we either need to initialize the super-class
- // or static fields.
- manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, false);
- old_status = klass->GetStatus();
- if (!klass->IsInitialized()) {
- // We don't want non-trivial class initialization occurring on multiple threads due to
- // deadlock problems. For example, a parent class is initialized (holding its lock) that
- // refers to a sub-class in its static/class initializer causing it to try to acquire the
- // sub-class' lock. While on a second thread the sub-class is initialized (holding its lock)
- // after first initializing its parents, whose locks are acquired. This leads to a
- // parent-to-child and a child-to-parent lock ordering and consequent potential deadlock.
- // We need to use an ObjectLock due to potential suspension in the interpreting code. Rather
- // than use a special Object for the purpose we use the Class of java.lang.Class.
- Handle<mirror::Class> h_klass(hs.NewHandle(klass->GetClass()));
- ObjectLock<mirror::Class> lock(soa.Self(), h_klass);
- // Attempt to initialize allowing initialization of parent classes but still not static
- // fields.
- bool is_superclass_initialized = true;
- if (!manager_->GetCompiler()->GetCompilerOptions().IsAppImage()) {
- // If not an app image case, the compiler won't initialize too much things and do a fast
- // fail, don't check dependencies.
+ if (klass != nullptr && !SkipClass(jclass_loader, dex_file, klass.Get())) {
+ // Only try to initialize classes that were successfully verified.
+ if (klass->IsVerified()) {
+ // Attempt to initialize the class but bail if we either need to initialize the super-class
+ // or static fields.
+ manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, false);
+ if (!klass->IsInitialized()) {
+ // We don't want non-trivial class initialization occurring on multiple threads due to
+ // deadlock problems. For example, a parent class is initialized (holding its lock) that
+ // refers to a sub-class in its static/class initializer causing it to try to acquire the
+ // sub-class' lock. While on a second thread the sub-class is initialized (holding its lock)
+ // after first initializing its parents, whose locks are acquired. This leads to a
+ // parent-to-child and a child-to-parent lock ordering and consequent potential deadlock.
+ // We need to use an ObjectLock due to potential suspension in the interpreting code. Rather
+ // than use a special Object for the purpose we use the Class of java.lang.Class.
+ Handle<mirror::Class> h_klass(hs.NewHandle(klass->GetClass()));
+ ObjectLock<mirror::Class> lock(soa.Self(), h_klass);
+ // Attempt to initialize allowing initialization of parent classes but still not static
+ // fields.
manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, true);
- } else {
- // For app images, do the initialization recursively and resolve types encountered to make
- // sure the compiler runs without error.
- is_superclass_initialized = InitializeDependencies(klass, class_loader, soa.Self());
- if (is_superclass_initialized) {
- manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, true);
- }
- }
- old_status = klass->GetStatus();
- // If superclass cannot be initialized, no need to proceed.
- if (!klass->IsInitialized() &&
- is_superclass_initialized &&
- manager_->GetCompiler()->IsImageClass(descriptor)) {
- bool can_init_static_fields = false;
- if (manager_->GetCompiler()->GetCompilerOptions().IsBootImage()) {
+ if (!klass->IsInitialized()) {
// We need to initialize static fields, we only do this for image classes that aren't
// marked with the $NoPreloadHolder (which implies this should not be initialized early).
- can_init_static_fields = !StringPiece(descriptor).ends_with("$NoPreloadHolder;");
- } else {
- can_init_static_fields = manager_->GetCompiler()->GetCompilerOptions().IsAppImage() &&
- !soa.Self()->IsExceptionPending() &&
- NoClinitInDependency(klass, soa.Self(), &class_loader);
- // TODO The checking for clinit can be removed since it's already
- // checked when init superclass. Currently keep it because it contains
- // processing of intern strings. Will be removed later when intern strings
- // and clinit are both initialized.
- }
-
- if (can_init_static_fields) {
- VLOG(compiler) << "Initializing: " << descriptor;
- // TODO multithreading support. We should ensure the current compilation thread has
- // exclusive access to the runtime and the transaction. To achieve this, we could use
- // a ReaderWriterMutex but we're holding the mutator lock so we fail mutex sanity
- // checks in Thread::AssertThreadSuspensionIsAllowable.
- Runtime* const runtime = Runtime::Current();
- Transaction transaction;
-
- // Run the class initializer in transaction mode.
- runtime->EnterTransactionMode(&transaction);
- bool success = manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, true,
- true);
- // TODO we detach transaction from runtime to indicate we quit the transactional
- // mode which prevents the GC from visiting objects modified during the transaction.
- // Ensure GC is not run so don't access freed objects when aborting transaction.
-
- {
- ScopedAssertNoThreadSuspension ants("Transaction end");
- runtime->ExitTransactionMode();
-
- if (!success) {
- CHECK(soa.Self()->IsExceptionPending());
- mirror::Throwable* exception = soa.Self()->GetException();
- VLOG(compiler) << "Initialization of " << descriptor << " aborted because of "
- << exception->Dump();
- std::ostream* file_log = manager_->GetCompiler()->
- GetCompilerOptions().GetInitFailureOutput();
- if (file_log != nullptr) {
- *file_log << descriptor << "\n";
- *file_log << exception->Dump() << "\n";
+ bool can_init_static_fields =
+ manager_->GetCompiler()->GetCompilerOptions().IsBootImage() &&
+ manager_->GetCompiler()->IsImageClass(descriptor) &&
+ !StringPiece(descriptor).ends_with("$NoPreloadHolder;");
+ if (can_init_static_fields) {
+ VLOG(compiler) << "Initializing: " << descriptor;
+ // TODO multithreading support. We should ensure the current compilation thread has
+ // exclusive access to the runtime and the transaction. To achieve this, we could use
+ // a ReaderWriterMutex but we're holding the mutator lock so we fail mutex sanity
+ // checks in Thread::AssertThreadSuspensionIsAllowable.
+ Runtime* const runtime = Runtime::Current();
+ Transaction transaction;
+
+ // Run the class initializer in transaction mode.
+ runtime->EnterTransactionMode(&transaction);
+ const mirror::Class::Status old_status = klass->GetStatus();
+ bool success = manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, true,
+ true);
+ // TODO we detach transaction from runtime to indicate we quit the transactional
+ // mode which prevents the GC from visiting objects modified during the transaction.
+ // Ensure GC is not run so don't access freed objects when aborting transaction.
+
+ {
+ ScopedAssertNoThreadSuspension ants("Transaction end");
+ runtime->ExitTransactionMode();
+
+ if (!success) {
+ CHECK(soa.Self()->IsExceptionPending());
+ mirror::Throwable* exception = soa.Self()->GetException();
+ VLOG(compiler) << "Initialization of " << descriptor << " aborted because of "
+ << exception->Dump();
+ std::ostream* file_log = manager_->GetCompiler()->
+ GetCompilerOptions().GetInitFailureOutput();
+ if (file_log != nullptr) {
+ *file_log << descriptor << "\n";
+ *file_log << exception->Dump() << "\n";
+ }
+ soa.Self()->ClearException();
+ transaction.Rollback();
+ CHECK_EQ(old_status, klass->GetStatus()) << "Previous class status not restored";
}
- soa.Self()->ClearException();
- transaction.Rollback();
- CHECK_EQ(old_status, klass->GetStatus()) << "Previous class status not restored";
}
- }
- if (!success) {
- // On failure, still intern strings of static fields and seen in <clinit>, as these
- // will be created in the zygote. This is separated from the transaction code just
- // above as we will allocate strings, so must be allowed to suspend.
- if (&klass->GetDexFile() == manager_->GetDexFile()) {
+ if (!success) {
+ // On failure, still intern strings of static fields and seen in <clinit>, as these
+ // will be created in the zygote. This is separated from the transaction code just
+ // above as we will allocate strings, so must be allowed to suspend.
InternStrings(klass, class_loader);
}
}
}
+ soa.Self()->AssertNoPendingException();
}
- soa.Self()->AssertNoPendingException();
}
+ // Record the final class status if necessary.
+ ClassReference ref(manager_->GetDexFile(), class_def_index);
+ manager_->GetCompiler()->RecordClassStatus(ref, klass->GetStatus());
}
- // Record the final class status if necessary.
- ClassReference ref(&dex_file, klass->GetDexClassDefIndex());
- // Back up the status before doing initialization for static encoded fields,
- // because the static encoded branch wants to keep the status to uninitialized.
- manager_->GetCompiler()->RecordClassStatus(ref, old_status);
+ // Clear any class not found or verification exceptions.
+ soa.Self()->ClearException();
}
private:
@@ -2435,136 +2393,6 @@ class InitializeClassVisitor : public CompilationVisitor {
}
}
- bool ResolveTypesOfMethods(Thread* self, ArtMethod* m)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- auto rtn_type = m->GetReturnType(true);
- if (rtn_type == nullptr) {
- self->ClearException();
- return false;
- }
- const DexFile::TypeList* types = m->GetParameterTypeList();
- if (types != nullptr) {
- for (uint32_t i = 0; i < types->Size(); ++i) {
- dex::TypeIndex param_type_idx = types->GetTypeItem(i).type_idx_;
- auto param_type = m->GetClassFromTypeIndex(param_type_idx, true);
- if (param_type == nullptr) {
- self->ClearException();
- return false;
- }
- }
- }
- return true;
- }
-
- // Pre resolve types mentioned in all method signatures before start a transaction
- // since ResolveType doesn't work in transaction mode.
- bool PreResolveTypes(Thread* self, const Handle<mirror::Class>& klass)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- PointerSize pointer_size = manager_->GetClassLinker()->GetImagePointerSize();
- for (ArtMethod& m : klass->GetMethods(pointer_size)) {
- if (!ResolveTypesOfMethods(self, &m)) {
- return false;
- }
- }
- if (klass->IsInterface()) {
- return true;
- } else if (klass->HasSuperClass()) {
- StackHandleScope<1> hs(self);
- MutableHandle<mirror::Class> super_klass(hs.NewHandle<mirror::Class>(klass->GetSuperClass()));
- for (int i = super_klass->GetVTableLength() - 1; i >= 0; --i) {
- ArtMethod* m = klass->GetVTableEntry(i, pointer_size);
- ArtMethod* super_m = super_klass->GetVTableEntry(i, pointer_size);
- if (!ResolveTypesOfMethods(self, m) || !ResolveTypesOfMethods(self, super_m)) {
- return false;
- }
- }
- for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
- super_klass.Assign(klass->GetIfTable()->GetInterface(i));
- if (klass->GetClassLoader() != super_klass->GetClassLoader()) {
- uint32_t num_methods = super_klass->NumVirtualMethods();
- for (uint32_t j = 0; j < num_methods; ++j) {
- ArtMethod* m = klass->GetIfTable()->GetMethodArray(i)->GetElementPtrSize<ArtMethod*>(
- j, pointer_size);
- ArtMethod* super_m = super_klass->GetVirtualMethod(j, pointer_size);
- if (!ResolveTypesOfMethods(self, m) || !ResolveTypesOfMethods(self, super_m)) {
- return false;
- }
- }
- }
- }
- }
- return true;
- }
-
- // Initialize the klass's dependencies recursively before initializing itself.
- // Checking for interfaces is also necessary since interfaces can contain
- // both default methods and static encoded fields.
- bool InitializeDependencies(const Handle<mirror::Class>& klass,
- Handle<mirror::ClassLoader> class_loader,
- Thread* self)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- if (klass->HasSuperClass()) {
- ObjPtr<mirror::Class> super_class = klass->GetSuperClass();
- StackHandleScope<1> hs(self);
- Handle<mirror::Class> handle_scope_super(hs.NewHandle(super_class));
- if (!handle_scope_super->IsInitialized()) {
- this->TryInitializeClass(handle_scope_super, class_loader);
- if (!handle_scope_super->IsInitialized()) {
- return false;
- }
- }
- }
-
- uint32_t num_if = klass->NumDirectInterfaces();
- for (size_t i = 0; i < num_if; i++) {
- ObjPtr<mirror::Class>
- interface = mirror::Class::GetDirectInterface(self, klass.Get(), i);
- StackHandleScope<1> hs(self);
- Handle<mirror::Class> handle_interface(hs.NewHandle(interface));
-
- TryInitializeClass(handle_interface, class_loader);
-
- if (!handle_interface->IsInitialized()) {
- return false;
- }
- }
-
- return PreResolveTypes(self, klass);
- }
-
- // In this phase the classes containing class initializers are ignored. Make sure no
- // clinit appears in kalss's super class chain and interfaces.
- bool NoClinitInDependency(const Handle<mirror::Class>& klass,
- Thread* self,
- Handle<mirror::ClassLoader>* class_loader)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- ArtMethod* clinit =
- klass->FindClassInitializer(manager_->GetClassLinker()->GetImagePointerSize());
- if (clinit != nullptr) {
- VLOG(compiler) << klass->PrettyClass() << ' ' << clinit->PrettyMethod(true);
- return false;
- }
- if (klass->HasSuperClass()) {
- ObjPtr<mirror::Class> super_class = klass->GetSuperClass();
- StackHandleScope<1> hs(self);
- Handle<mirror::Class> handle_scope_super(hs.NewHandle(super_class));
- if (!NoClinitInDependency(handle_scope_super, self, class_loader))
- return false;
- }
-
- uint32_t num_if = klass->NumDirectInterfaces();
- for (size_t i = 0; i < num_if; i++) {
- ObjPtr<mirror::Class>
- interface = mirror::Class::GetDirectInterface(self, klass.Get(), i);
- StackHandleScope<1> hs(self);
- Handle<mirror::Class> handle_interface(hs.NewHandle(interface));
- if (!NoClinitInDependency(handle_interface, self, class_loader))
- return false;
- }
-
- return true;
- }
-
const ParallelCompilationManager* const manager_;
};
@@ -2584,10 +2412,7 @@ void CompilerDriver::InitializeClasses(jobject jni_class_loader,
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
ParallelCompilationManager context(class_linker, jni_class_loader, this, &dex_file, dex_files,
init_thread_pool);
-
- if (GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsAppImage()) {
- // Set the concurrency thread to 1 to support initialization for App Images since transaction
- // doesn't support multithreading now.
+ if (GetCompilerOptions().IsBootImage()) {
// TODO: remove this when transactional mode supports multithreading.
init_thread_count = 1U;
}
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index fed1f48d65..66135414f7 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -189,18 +189,12 @@ JitCompiler::~JitCompiler() {
bool JitCompiler::CompileMethod(Thread* self, ArtMethod* method, bool osr) {
DCHECK(!method->IsProxyMethod());
+ DCHECK(method->GetDeclaringClass()->IsResolved());
+
TimingLogger logger("JIT compiler timing logger", true, VLOG_IS_ON(jit));
- StackHandleScope<2> hs(self);
self->AssertNoPendingException();
Runtime* runtime = Runtime::Current();
- // Ensure the class is initialized.
- Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
- if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
- VLOG(jit) << "JIT failed to initialize " << method->PrettyMethod();
- return false;
- }
-
// Do the compilation.
bool success = false;
{
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index c918ee6687..136401898c 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -337,7 +337,7 @@ void CodeGenerator::CreateCommonInvokeLocationSummary(
case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
locations->SetInAt(call->GetSpecialInputIndex(), visitor->GetMethodLocation());
break;
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod:
+ case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall:
locations->AddTemp(visitor->GetMethodLocation());
locations->SetInAt(call->GetSpecialInputIndex(), Location::RequiresRegister());
break;
@@ -350,6 +350,34 @@ void CodeGenerator::CreateCommonInvokeLocationSummary(
}
}
+void CodeGenerator::GenerateInvokeStaticOrDirectRuntimeCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
+ MoveConstant(temp, invoke->GetDexMethodIndex());
+
+ // The access check is unnecessary but we do not want to introduce
+ // extra entrypoints for the codegens that do not support some
+ // invoke type and fall back to the runtime call.
+
+ // Initialize to anything to silent compiler warnings.
+ QuickEntrypointEnum entrypoint = kQuickInvokeStaticTrampolineWithAccessCheck;
+ switch (invoke->GetInvokeType()) {
+ case kStatic:
+ entrypoint = kQuickInvokeStaticTrampolineWithAccessCheck;
+ break;
+ case kDirect:
+ entrypoint = kQuickInvokeDirectTrampolineWithAccessCheck;
+ break;
+ case kSuper:
+ entrypoint = kQuickInvokeSuperTrampolineWithAccessCheck;
+ break;
+ case kVirtual:
+ case kInterface:
+ LOG(FATAL) << "Unexpected invoke type: " << invoke->GetInvokeType();
+ UNREACHABLE();
+ }
+
+ InvokeRuntime(entrypoint, invoke, invoke->GetDexPc(), slow_path);
+}
void CodeGenerator::GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke) {
MoveConstant(invoke->GetLocations()->GetTemp(0), invoke->GetDexMethodIndex());
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index c9ba5c3357..7bf43f7971 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -496,6 +496,8 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> {
static void CreateCommonInvokeLocationSummary(
HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor);
+ void GenerateInvokeStaticOrDirectRuntimeCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path);
void GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke);
void GenerateInvokePolymorphicCall(HInvokePolymorphic* invoke);
@@ -564,9 +566,11 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> {
HInvokeStaticOrDirect* invoke) = 0;
// Generate a call to a static or direct method.
- virtual void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) = 0;
+ virtual void GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) = 0;
// Generate a call to a virtual method.
- virtual void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) = 0;
+ virtual void GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) = 0;
// Copy the result of a call into the given target.
virtual void MoveFromReturnRegister(Location trg, Primitive::Type type) = 0;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 097e4833d0..8300f8186e 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -47,7 +47,6 @@ static bool ExpectedPairLayout(Location location) {
return ((location.low() & 1) == 0) && (location.low() + 1 == location.high());
}
-static constexpr int kCurrentMethodStackOffset = 0;
static constexpr Register kMethodRegisterArgument = R0;
static constexpr Register kCoreAlwaysSpillRegister = R5;
@@ -3589,7 +3588,6 @@ void InstructionCodeGeneratorARM::VisitInvokeStaticOrDirect(HInvokeStaticOrDirec
LocationSummary* locations = invoke->GetLocations();
codegen_->GenerateStaticOrDirectCall(
invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderARM::HandleInvoke(HInvoke* invoke) {
@@ -3613,7 +3611,6 @@ void InstructionCodeGeneratorARM::VisitInvokeVirtual(HInvokeVirtual* invoke) {
codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
DCHECK(!codegen_->IsLeafMethod());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderARM::VisitInvokeInterface(HInvokeInterface* invoke) {
@@ -8955,7 +8952,8 @@ Register CodeGeneratorARM::GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOr
return location.AsRegister<Register>();
}
-void CodeGeneratorARM::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
+void CodeGeneratorARM::GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
Location callee_method = temp; // For all kinds except kRecursive, callee will be in temp.
switch (invoke->GetMethodLoadKind()) {
case HInvokeStaticOrDirect::MethodLoadKind::kStringInit: {
@@ -8992,28 +8990,9 @@ void CodeGeneratorARM::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
__ LoadFromOffset(kLoadWord, temp.AsRegister<Register>(), base_reg, offset);
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod: {
- Location current_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
- Register method_reg;
- Register reg = temp.AsRegister<Register>();
- if (current_method.IsRegister()) {
- method_reg = current_method.AsRegister<Register>();
- } else {
- DCHECK(invoke->GetLocations()->Intrinsified());
- DCHECK(!current_method.IsValid());
- method_reg = reg;
- __ LoadFromOffset(kLoadWord, reg, SP, kCurrentMethodStackOffset);
- }
- // /* ArtMethod*[] */ temp = temp.ptr_sized_fields_->dex_cache_resolved_methods_;
- __ LoadFromOffset(kLoadWord,
- reg,
- method_reg,
- ArtMethod::DexCacheResolvedMethodsOffset(kArmPointerSize).Int32Value());
- // temp = temp[index_in_cache];
- // Note: Don't use invoke->GetTargetMethod() as it may point to a different dex file.
- uint32_t index_in_cache = invoke->GetDexMethodIndex();
- __ LoadFromOffset(kLoadWord, reg, reg, CodeGenerator::GetCachePointerOffset(index_in_cache));
- break;
+ case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+ GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
+ return; // No code pointer retrieval; the runtime performs the call directly.
}
}
@@ -9030,11 +9009,13 @@ void CodeGeneratorARM::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
__ blx(LR);
break;
}
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
DCHECK(!IsLeafMethod());
}
-void CodeGeneratorARM::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_location) {
+void CodeGeneratorARM::GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp_location, SlowPathCode* slow_path) {
Register temp = temp_location.AsRegister<Register>();
uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
invoke->GetVTableIndex(), kArmPointerSize).Uint32Value();
@@ -9065,6 +9046,7 @@ void CodeGeneratorARM::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp
__ LoadFromOffset(kLoadWord, LR, temp, entry_point);
// LR();
__ blx(LR);
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
}
CodeGeneratorARM::PcRelativePatchInfo* CodeGeneratorARM::NewPcRelativeMethodPatch(
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 5f37d3bff1..398b6ed7d8 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -455,8 +455,10 @@ class CodeGeneratorARM : public CodeGenerator {
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
HInvokeStaticOrDirect* invoke) OVERRIDE;
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
- void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
+ void GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
+ void GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE;
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index d8e709c7a9..a84f8f3308 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -78,7 +78,6 @@ using helpers::VIXLRegCodeFromART;
using helpers::WRegisterFrom;
using helpers::XRegisterFrom;
-static constexpr int kCurrentMethodStackOffset = 0;
// The compare/jump sequence will generate about (1.5 * num_entries + 3) instructions. While jump
// table version generates 7 instructions and num_entries literals. Compare/jump sequence will
// generates less code/data with a small num_entries.
@@ -4497,7 +4496,8 @@ HInvokeStaticOrDirect::DispatchInfo CodeGeneratorARM64::GetSupportedInvokeStatic
return desired_dispatch_info;
}
-void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
+void CodeGeneratorARM64::GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
// Make sure that ArtMethod* is passed in kArtMethodRegister as per the calling convention.
Location callee_method = temp; // For all kinds except kRecursive, callee will be in temp.
switch (invoke->GetMethodLoadKind()) {
@@ -4538,34 +4538,22 @@ void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invok
EmitLdrOffsetPlaceholder(ldr_label, XRegisterFrom(temp), XRegisterFrom(temp));
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod: {
- Location current_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
- Register reg = XRegisterFrom(temp);
- Register method_reg;
- if (current_method.IsRegister()) {
- method_reg = XRegisterFrom(current_method);
- } else {
- DCHECK(invoke->GetLocations()->Intrinsified());
- DCHECK(!current_method.IsValid());
- method_reg = reg;
- __ Ldr(reg.X(), MemOperand(sp, kCurrentMethodStackOffset));
- }
-
- // /* ArtMethod*[] */ temp = temp.ptr_sized_fields_->dex_cache_resolved_methods_;
- __ Ldr(reg.X(),
- MemOperand(method_reg.X(),
- ArtMethod::DexCacheResolvedMethodsOffset(kArm64PointerSize).Int32Value()));
- // temp = temp[index_in_cache];
- // Note: Don't use invoke->GetTargetMethod() as it may point to a different dex file.
- uint32_t index_in_cache = invoke->GetDexMethodIndex();
- __ Ldr(reg.X(), MemOperand(reg.X(), GetCachePointerOffset(index_in_cache)));
- break;
+ case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+ GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
+ return; // No code pointer retrieval; the runtime performs the call directly.
}
}
switch (invoke->GetCodePtrLocation()) {
case HInvokeStaticOrDirect::CodePtrLocation::kCallSelf:
- __ Bl(&frame_entry_label_);
+ {
+ // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
+ ExactAssemblyScope eas(GetVIXLAssembler(),
+ kInstructionSize,
+ CodeBufferCheckScope::kExactSize);
+ __ bl(&frame_entry_label_);
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+ }
break;
case HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod:
// LR = callee_method->entry_point_from_quick_compiled_code_;
@@ -4573,14 +4561,13 @@ void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invok
XRegisterFrom(callee_method),
ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64PointerSize).Int32Value()));
{
- // To ensure that the pc position is recorded immediately after the `blr` instruction
- // BLR must be the last instruction emitted in this function.
- // Recording the pc will occur right after returning from this function.
+ // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
ExactAssemblyScope eas(GetVIXLAssembler(),
kInstructionSize,
CodeBufferCheckScope::kExactSize);
// lr()
__ blr(lr);
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
}
break;
}
@@ -4588,7 +4575,8 @@ void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invok
DCHECK(!IsLeafMethod());
}
-void CodeGeneratorARM64::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_in) {
+void CodeGeneratorARM64::GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp_in, SlowPathCode* slow_path) {
// Use the calling convention instead of the location of the receiver, as
// intrinsics may have put the receiver in a different register. In the intrinsics
// slow path, the arguments have been moved to the right place, so here we are
@@ -4622,12 +4610,11 @@ void CodeGeneratorARM64::GenerateVirtualCall(HInvokeVirtual* invoke, Location te
// lr = temp->GetEntryPoint();
__ Ldr(lr, MemOperand(temp, entry_point.SizeValue()));
{
- // To ensure that the pc position is recorded immediately after the `blr` instruction
- // BLR should be the last instruction emitted in this function.
- // Recording the pc will occur right after returning from this function.
+ // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
ExactAssemblyScope eas(GetVIXLAssembler(), kInstructionSize, CodeBufferCheckScope::kExactSize);
// lr();
__ blr(lr);
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
}
}
@@ -4824,7 +4811,6 @@ void InstructionCodeGeneratorARM64::VisitInvokeStaticOrDirect(HInvokeStaticOrDir
LocationSummary* locations = invoke->GetLocations();
codegen_->GenerateStaticOrDirectCall(
invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void InstructionCodeGeneratorARM64::VisitInvokeVirtual(HInvokeVirtual* invoke) {
@@ -4837,7 +4823,6 @@ void InstructionCodeGeneratorARM64::VisitInvokeVirtual(HInvokeVirtual* invoke) {
EmissionCheckScope guard(GetVIXLAssembler(), kInvokeCodeMarginSizeInBytes);
codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
DCHECK(!codegen_->IsLeafMethod());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
HLoadClass::LoadKind CodeGeneratorARM64::GetSupportedLoadClassKind(
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 747fc9f0b1..5bb2ab57df 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -540,8 +540,10 @@ class CodeGeneratorARM64 : public CodeGenerator {
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
HInvokeStaticOrDirect* invoke) OVERRIDE;
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
- void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
+ void GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
+ void GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED,
Primitive::Type type ATTRIBUTE_UNUSED) OVERRIDE {
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 4d5f88e14a..d5e3723e68 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -76,7 +76,6 @@ static bool ExpectedPairLayout(Location location) {
// Use a local definition to prevent copying mistakes.
static constexpr size_t kArmWordSize = static_cast<size_t>(kArmPointerSize);
static constexpr size_t kArmBitsPerWord = kArmWordSize * kBitsPerByte;
-static constexpr int kCurrentMethodStackOffset = 0;
static constexpr uint32_t kPackedSwitchCompareJumpThreshold = 7;
// Reference load (except object array loads) is using LDR Rt, [Rn, #offset] which can handle
@@ -3678,7 +3677,6 @@ void InstructionCodeGeneratorARMVIXL::VisitInvokeStaticOrDirect(HInvokeStaticOrD
LocationSummary* locations = invoke->GetLocations();
codegen_->GenerateStaticOrDirectCall(
invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderARMVIXL::HandleInvoke(HInvoke* invoke) {
@@ -3701,7 +3699,6 @@ void InstructionCodeGeneratorARMVIXL::VisitInvokeVirtual(HInvokeVirtual* invoke)
}
codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
DCHECK(!codegen_->IsLeafMethod());
}
@@ -9120,7 +9117,7 @@ vixl32::Register CodeGeneratorARMVIXL::GetInvokeStaticOrDirectExtraParameter(
}
void CodeGeneratorARMVIXL::GenerateStaticOrDirectCall(
- HInvokeStaticOrDirect* invoke, Location temp) {
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
Location callee_method = temp; // For all kinds except kRecursive, callee will be in temp.
switch (invoke->GetMethodLoadKind()) {
case HInvokeStaticOrDirect::MethodLoadKind::kStringInit: {
@@ -9151,36 +9148,22 @@ void CodeGeneratorARMVIXL::GenerateStaticOrDirectCall(
GetAssembler()->LoadFromOffset(kLoadWord, RegisterFrom(temp), base_reg, offset);
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod: {
- Location current_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
- vixl32::Register method_reg;
- vixl32::Register reg = RegisterFrom(temp);
- if (current_method.IsRegister()) {
- method_reg = RegisterFrom(current_method);
- } else {
- DCHECK(invoke->GetLocations()->Intrinsified());
- DCHECK(!current_method.IsValid());
- method_reg = reg;
- GetAssembler()->LoadFromOffset(kLoadWord, reg, sp, kCurrentMethodStackOffset);
- }
- // /* ArtMethod*[] */ temp = temp.ptr_sized_fields_->dex_cache_resolved_methods_;
- GetAssembler()->LoadFromOffset(
- kLoadWord,
- reg,
- method_reg,
- ArtMethod::DexCacheResolvedMethodsOffset(kArmPointerSize).Int32Value());
- // temp = temp[index_in_cache];
- // Note: Don't use invoke->GetTargetMethod() as it may point to a different dex file.
- uint32_t index_in_cache = invoke->GetDexMethodIndex();
- GetAssembler()->LoadFromOffset(
- kLoadWord, reg, reg, CodeGenerator::GetCachePointerOffset(index_in_cache));
- break;
+ case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+ GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
+ return; // No code pointer retrieval; the runtime performs the call directly.
}
}
switch (invoke->GetCodePtrLocation()) {
case HInvokeStaticOrDirect::CodePtrLocation::kCallSelf:
- __ Bl(GetFrameEntryLabel());
+ {
+ // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::k32BitT32InstructionSizeInBytes,
+ CodeBufferCheckScope::kMaximumSize);
+ __ bl(GetFrameEntryLabel());
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+ }
break;
case HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod:
// LR = callee_method->entry_point_from_quick_compiled_code_
@@ -9190,12 +9173,14 @@ void CodeGeneratorARMVIXL::GenerateStaticOrDirectCall(
RegisterFrom(callee_method),
ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArmPointerSize).Int32Value());
{
+ // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
// blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
ExactAssemblyScope aas(GetVIXLAssembler(),
vixl32::k16BitT32InstructionSizeInBytes,
CodeBufferCheckScope::kExactSize);
// LR()
__ blx(lr);
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
}
break;
}
@@ -9203,7 +9188,8 @@ void CodeGeneratorARMVIXL::GenerateStaticOrDirectCall(
DCHECK(!IsLeafMethod());
}
-void CodeGeneratorARMVIXL::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_location) {
+void CodeGeneratorARMVIXL::GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp_location, SlowPathCode* slow_path) {
vixl32::Register temp = RegisterFrom(temp_location);
uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
invoke->GetVTableIndex(), kArmPointerSize).Uint32Value();
@@ -9239,15 +9225,16 @@ void CodeGeneratorARMVIXL::GenerateVirtualCall(HInvokeVirtual* invoke, Location
GetAssembler()->LoadFromOffset(kLoadWord, temp, temp, method_offset);
// LR = temp->GetEntryPoint();
GetAssembler()->LoadFromOffset(kLoadWord, lr, temp, entry_point);
- // LR();
- // This `blx` *must* be the *last* instruction generated by this stub, so that calls to
- // `RecordPcInfo()` immediately following record the correct pc. Use a scope to help guarantee
- // that.
- // blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
- ExactAssemblyScope aas(GetVIXLAssembler(),
- vixl32::k16BitT32InstructionSizeInBytes,
- CodeBufferCheckScope::kExactSize);
- __ blx(lr);
+ {
+ // Use a scope to help guarantee that `RecordPcInfo()` records the correct pc.
+ // blx in T32 has only 16bit encoding that's why a stricter check for the scope is used.
+ ExactAssemblyScope aas(GetVIXLAssembler(),
+ vixl32::k16BitT32InstructionSizeInBytes,
+ CodeBufferCheckScope::kExactSize);
+ // LR();
+ __ blx(lr);
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+ }
}
CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewPcRelativeMethodPatch(
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index f6e4de33a8..5320f71290 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -538,8 +538,10 @@ class CodeGeneratorARMVIXL : public CodeGenerator {
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
HInvokeStaticOrDirect* invoke) OVERRIDE;
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
- void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
+ void GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
+ void GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE;
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 951d75a708..8560e3e5f6 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -7105,13 +7105,14 @@ HInvokeStaticOrDirect::DispatchInfo CodeGeneratorMIPS::GetSupportedInvokeStaticO
break;
}
if (fallback_load) {
- dispatch_info.method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod;
+ dispatch_info.method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall;
dispatch_info.method_load_data = 0;
}
return dispatch_info;
}
-void CodeGeneratorMIPS::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
+void CodeGeneratorMIPS::GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
// All registers are assumed to be correctly set up per the calling convention.
Location callee_method = temp; // For all kinds except kRecursive, callee will be in temp.
HInvokeStaticOrDirect::MethodLoadKind method_load_kind = invoke->GetMethodLoadKind();
@@ -7165,33 +7166,9 @@ void CodeGeneratorMIPS::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke
__ LoadFromOffset(kLoadWord, temp.AsRegister<Register>(), base_reg, offset);
}
break;
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod: {
- Location current_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
- Register reg = temp.AsRegister<Register>();
- Register method_reg;
- if (current_method.IsRegister()) {
- method_reg = current_method.AsRegister<Register>();
- } else {
- // TODO: use the appropriate DCHECK() here if possible.
- // DCHECK(invoke->GetLocations()->Intrinsified());
- DCHECK(!current_method.IsValid());
- method_reg = reg;
- __ Lw(reg, SP, kCurrentMethodStackOffset);
- }
-
- // temp = temp->dex_cache_resolved_methods_;
- __ LoadFromOffset(kLoadWord,
- reg,
- method_reg,
- ArtMethod::DexCacheResolvedMethodsOffset(kMipsPointerSize).Int32Value());
- // temp = temp[index_in_cache];
- // Note: Don't use invoke->GetTargetMethod() as it may point to a different dex file.
- uint32_t index_in_cache = invoke->GetDexMethodIndex();
- __ LoadFromOffset(kLoadWord,
- reg,
- reg,
- CodeGenerator::GetCachePointerOffset(index_in_cache));
- break;
+ case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+ GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
+ return; // No code pointer retrieval; the runtime performs the call directly.
}
}
@@ -7211,6 +7188,8 @@ void CodeGeneratorMIPS::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke
__ NopIfNoReordering();
break;
}
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+
DCHECK(!IsLeafMethod());
}
@@ -7228,10 +7207,10 @@ void InstructionCodeGeneratorMIPS::VisitInvokeStaticOrDirect(HInvokeStaticOrDire
locations->HasTemps()
? locations->GetTemp(0)
: Location::NoLocation());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
-void CodeGeneratorMIPS::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_location) {
+void CodeGeneratorMIPS::GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp_location, SlowPathCode* slow_path) {
// Use the calling convention instead of the location of the receiver, as
// intrinsics may have put the receiver in a different register. In the intrinsics
// slow path, the arguments have been moved to the right place, so here we are
@@ -7263,6 +7242,7 @@ void CodeGeneratorMIPS::GenerateVirtualCall(HInvokeVirtual* invoke, Location tem
// T9();
__ Jalr(T9);
__ NopIfNoReordering();
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
}
void InstructionCodeGeneratorMIPS::VisitInvokeVirtual(HInvokeVirtual* invoke) {
@@ -7272,7 +7252,6 @@ void InstructionCodeGeneratorMIPS::VisitInvokeVirtual(HInvokeVirtual* invoke) {
codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
DCHECK(!codegen_->IsLeafMethod());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderMIPS::VisitLoadClass(HLoadClass* cls) {
diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h
index 736b5070d9..d774219ba9 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -552,8 +552,10 @@ class CodeGeneratorMIPS : public CodeGenerator {
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
HInvokeStaticOrDirect* invoke) OVERRIDE;
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
- void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
+ void GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
+ void GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED,
Primitive::Type type ATTRIBUTE_UNUSED) OVERRIDE {
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 6026814f04..da43c4e757 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -4915,7 +4915,8 @@ HInvokeStaticOrDirect::DispatchInfo CodeGeneratorMIPS64::GetSupportedInvokeStati
return desired_dispatch_info;
}
-void CodeGeneratorMIPS64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
+void CodeGeneratorMIPS64::GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
// All registers are assumed to be correctly set up per the calling convention.
Location callee_method = temp; // For all kinds except kRecursive, callee will be in temp.
HInvokeStaticOrDirect::MethodLoadKind method_load_kind = invoke->GetMethodLoadKind();
@@ -4956,33 +4957,9 @@ void CodeGeneratorMIPS64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invo
__ Ld(temp.AsRegister<GpuRegister>(), AT, /* placeholder */ 0x5678);
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod: {
- Location current_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
- GpuRegister reg = temp.AsRegister<GpuRegister>();
- GpuRegister method_reg;
- if (current_method.IsRegister()) {
- method_reg = current_method.AsRegister<GpuRegister>();
- } else {
- // TODO: use the appropriate DCHECK() here if possible.
- // DCHECK(invoke->GetLocations()->Intrinsified());
- DCHECK(!current_method.IsValid());
- method_reg = reg;
- __ Ld(reg, SP, kCurrentMethodStackOffset);
- }
-
- // temp = temp->dex_cache_resolved_methods_;
- __ LoadFromOffset(kLoadDoubleword,
- reg,
- method_reg,
- ArtMethod::DexCacheResolvedMethodsOffset(kMips64PointerSize).Int32Value());
- // temp = temp[index_in_cache];
- // Note: Don't use invoke->GetTargetMethod() as it may point to a different dex file.
- uint32_t index_in_cache = invoke->GetDexMethodIndex();
- __ LoadFromOffset(kLoadDoubleword,
- reg,
- reg,
- CodeGenerator::GetCachePointerOffset(index_in_cache));
- break;
+ case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+ GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
+ return; // No code pointer retrieval; the runtime performs the call directly.
}
}
@@ -5002,6 +4979,8 @@ void CodeGeneratorMIPS64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invo
__ Nop();
break;
}
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
+
DCHECK(!IsLeafMethod());
}
@@ -5019,10 +4998,10 @@ void InstructionCodeGeneratorMIPS64::VisitInvokeStaticOrDirect(HInvokeStaticOrDi
locations->HasTemps()
? locations->GetTemp(0)
: Location::NoLocation());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
-void CodeGeneratorMIPS64::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_location) {
+void CodeGeneratorMIPS64::GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp_location, SlowPathCode* slow_path) {
// Use the calling convention instead of the location of the receiver, as
// intrinsics may have put the receiver in a different register. In the intrinsics
// slow path, the arguments have been moved to the right place, so here we are
@@ -5054,6 +5033,7 @@ void CodeGeneratorMIPS64::GenerateVirtualCall(HInvokeVirtual* invoke, Location t
// T9();
__ Jalr(T9);
__ Nop();
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
}
void InstructionCodeGeneratorMIPS64::VisitInvokeVirtual(HInvokeVirtual* invoke) {
@@ -5063,7 +5043,6 @@ void InstructionCodeGeneratorMIPS64::VisitInvokeVirtual(HInvokeVirtual* invoke)
codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
DCHECK(!codegen_->IsLeafMethod());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderMIPS64::VisitLoadClass(HLoadClass* cls) {
diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h
index 9c6b6f62cb..2e8af2185a 100644
--- a/compiler/optimizing/code_generator_mips64.h
+++ b/compiler/optimizing/code_generator_mips64.h
@@ -521,8 +521,10 @@ class CodeGeneratorMIPS64 : public CodeGenerator {
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
HInvokeStaticOrDirect* invoke) OVERRIDE;
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
- void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
+ void GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
+ void GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED,
Primitive::Type type ATTRIBUTE_UNUSED) OVERRIDE {
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index b8465cd9d5..ca921b843e 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -2204,7 +2204,6 @@ void InstructionCodeGeneratorX86::VisitInvokeStaticOrDirect(HInvokeStaticOrDirec
LocationSummary* locations = invoke->GetLocations();
codegen_->GenerateStaticOrDirectCall(
invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderX86::VisitInvokeVirtual(HInvokeVirtual* invoke) {
@@ -2228,7 +2227,6 @@ void InstructionCodeGeneratorX86::VisitInvokeVirtual(HInvokeVirtual* invoke) {
codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
DCHECK(!codegen_->IsLeafMethod());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderX86::VisitInvokeInterface(HInvokeInterface* invoke) {
@@ -4530,7 +4528,8 @@ Register CodeGeneratorX86::GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOr
return location.AsRegister<Register>();
}
-void CodeGeneratorX86::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
+void CodeGeneratorX86::GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
Location callee_method = temp; // For all kinds except kRecursive, callee will be in temp.
switch (invoke->GetMethodLoadKind()) {
case HInvokeStaticOrDirect::MethodLoadKind::kStringInit: {
@@ -4566,26 +4565,9 @@ void CodeGeneratorX86::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
offset));
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod: {
- Location current_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
- Register method_reg;
- Register reg = temp.AsRegister<Register>();
- if (current_method.IsRegister()) {
- method_reg = current_method.AsRegister<Register>();
- } else {
- DCHECK(invoke->GetLocations()->Intrinsified());
- DCHECK(!current_method.IsValid());
- method_reg = reg;
- __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
- }
- // /* ArtMethod*[] */ temp = temp.ptr_sized_fields_->dex_cache_resolved_methods_;
- __ movl(reg, Address(method_reg,
- ArtMethod::DexCacheResolvedMethodsOffset(kX86PointerSize).Int32Value()));
- // temp = temp[index_in_cache];
- // Note: Don't use invoke->GetTargetMethod() as it may point to a different dex file.
- uint32_t index_in_cache = invoke->GetDexMethodIndex();
- __ movl(reg, Address(reg, CodeGenerator::GetCachePointerOffset(index_in_cache)));
- break;
+ case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+ GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
+ return; // No code pointer retrieval; the runtime performs the call directly.
}
}
@@ -4600,11 +4582,13 @@ void CodeGeneratorX86::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
kX86PointerSize).Int32Value()));
break;
}
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
DCHECK(!IsLeafMethod());
}
-void CodeGeneratorX86::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_in) {
+void CodeGeneratorX86::GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp_in, SlowPathCode* slow_path) {
Register temp = temp_in.AsRegister<Register>();
uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
invoke->GetVTableIndex(), kX86PointerSize).Uint32Value();
@@ -4632,6 +4616,7 @@ void CodeGeneratorX86::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp
// call temp->GetEntryPoint();
__ call(Address(
temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86PointerSize).Int32Value()));
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
}
void CodeGeneratorX86::RecordBootMethodPatch(HInvokeStaticOrDirect* invoke) {
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 8130bd9d25..689f93e31a 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -408,9 +408,11 @@ class CodeGeneratorX86 : public CodeGenerator {
HInvokeStaticOrDirect* invoke) OVERRIDE;
// Generate a call to a static or direct method.
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
+ void GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
// Generate a call to a virtual method.
- void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
+ void GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
void RecordBootMethodPatch(HInvokeStaticOrDirect* invoke);
void RecordBootTypePatch(HLoadClass* load_class);
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 8dde298267..148f55139e 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -977,8 +977,8 @@ HInvokeStaticOrDirect::DispatchInfo CodeGeneratorX86_64::GetSupportedInvokeStati
return desired_dispatch_info;
}
-void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
- Location temp) {
+void CodeGeneratorX86_64::GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path) {
// All registers are assumed to be correctly set up.
Location callee_method = temp; // For all kinds except kRecursive, callee will be in temp.
@@ -1010,27 +1010,9 @@ void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invo
__ Bind(NewPcRelativeDexCacheArrayPatch(invoke->GetDexFileForPcRelativeDexCache(), offset));
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod: {
- Location current_method = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
- Register method_reg;
- CpuRegister reg = temp.AsRegister<CpuRegister>();
- if (current_method.IsRegister()) {
- method_reg = current_method.AsRegister<Register>();
- } else {
- DCHECK(invoke->GetLocations()->Intrinsified());
- DCHECK(!current_method.IsValid());
- method_reg = reg.AsRegister();
- __ movq(reg, Address(CpuRegister(RSP), kCurrentMethodStackOffset));
- }
- // /* ArtMethod*[] */ temp = temp.ptr_sized_fields_->dex_cache_resolved_methods_;
- __ movq(reg,
- Address(CpuRegister(method_reg),
- ArtMethod::DexCacheResolvedMethodsOffset(kX86_64PointerSize).SizeValue()));
- // temp = temp[index_in_cache];
- // Note: Don't use invoke->GetTargetMethod() as it may point to a different dex file.
- uint32_t index_in_cache = invoke->GetDexMethodIndex();
- __ movq(reg, Address(reg, CodeGenerator::GetCachePointerOffset(index_in_cache)));
- break;
+ case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
+ GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
+ return; // No code pointer retrieval; the runtime performs the call directly.
}
}
@@ -1045,11 +1027,13 @@ void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invo
kX86_64PointerSize).SizeValue()));
break;
}
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
DCHECK(!IsLeafMethod());
}
-void CodeGeneratorX86_64::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_in) {
+void CodeGeneratorX86_64::GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp_in, SlowPathCode* slow_path) {
CpuRegister temp = temp_in.AsRegister<CpuRegister>();
size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
invoke->GetVTableIndex(), kX86_64PointerSize).SizeValue();
@@ -1078,6 +1062,7 @@ void CodeGeneratorX86_64::GenerateVirtualCall(HInvokeVirtual* invoke, Location t
// call temp->GetEntryPoint();
__ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
kX86_64PointerSize).SizeValue()));
+ RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
}
void CodeGeneratorX86_64::RecordBootMethodPatch(HInvokeStaticOrDirect* invoke) {
@@ -2387,7 +2372,6 @@ void InstructionCodeGeneratorX86_64::VisitInvokeStaticOrDirect(HInvokeStaticOrDi
LocationSummary* locations = invoke->GetLocations();
codegen_->GenerateStaticOrDirectCall(
invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderX86_64::HandleInvoke(HInvoke* invoke) {
@@ -2411,7 +2395,6 @@ void InstructionCodeGeneratorX86_64::VisitInvokeVirtual(HInvokeVirtual* invoke)
codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
DCHECK(!codegen_->IsLeafMethod());
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
void LocationsBuilderX86_64::VisitInvokeInterface(HInvokeInterface* invoke) {
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 25479814d0..31debde0ce 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -404,8 +404,10 @@ class CodeGeneratorX86_64 : public CodeGenerator {
const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
HInvokeStaticOrDirect* invoke) OVERRIDE;
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
- void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
+ void GenerateStaticOrDirectCall(
+ HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
+ void GenerateVirtualCall(
+ HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
void RecordBootMethodPatch(HInvokeStaticOrDirect* invoke);
void RecordBootTypePatch(HLoadClass* load_class);
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 9be6a512f5..142c95780e 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -56,7 +56,7 @@ static constexpr size_t kMaximumNumberOfInstructionsForSmallMethod = 3;
// Limit the number of dex registers that we accumulate while inlining
// to avoid creating large amount of nested environments.
-static constexpr size_t kMaximumNumberOfCumulatedDexRegisters = 64;
+static constexpr size_t kMaximumNumberOfCumulatedDexRegisters = 32;
// Limit recursive call inlining, which do not benefit from too
// much inlining compared to code locality.
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index df9e7164ed..a73b1246d8 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -888,7 +888,7 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
}
HInvokeStaticOrDirect::DispatchInfo dispatch_info = {
- HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod,
+ HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall,
HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod,
0u
};
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 990a773a95..37d79814be 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -124,12 +124,12 @@ class IntrinsicSlowPathARM64 : public SlowPathCodeARM64 {
// are no pools emitted.
vixl::EmissionCheckScope guard(codegen->GetVIXLAssembler(), kInvokeCodeMarginSizeInBytes);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
- LocationFrom(kArtMethodRegister));
+ codegen->GenerateStaticOrDirectCall(
+ invoke_->AsInvokeStaticOrDirect(), LocationFrom(kArtMethodRegister), this);
} else {
- codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), LocationFrom(kArtMethodRegister));
+ codegen->GenerateVirtualCall(
+ invoke_->AsInvokeVirtual(), LocationFrom(kArtMethodRegister), this);
}
- codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
}
// Copy the result back to the expected output.
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 0e04b9a950..3c9b613803 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -97,11 +97,10 @@ class IntrinsicSlowPathARMVIXL : public SlowPathCodeARMVIXL {
Location method_loc = MoveArguments(codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), method_loc);
+ codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), method_loc, this);
} else {
- codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), method_loc);
+ codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), method_loc, this);
}
- codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
// Copy the result back to the expected output.
Location out = invoke_->GetLocations()->Out();
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc
index ea3e9e5ec9..4cea6dfdfb 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -112,12 +112,12 @@ class IntrinsicSlowPathMIPS : public SlowPathCodeMIPS {
MoveArguments(invoke_, codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
- Location::RegisterLocation(A0));
+ codegen->GenerateStaticOrDirectCall(
+ invoke_->AsInvokeStaticOrDirect(), Location::RegisterLocation(A0), this);
} else {
- codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), Location::RegisterLocation(A0));
+ codegen->GenerateVirtualCall(
+ invoke_->AsInvokeVirtual(), Location::RegisterLocation(A0), this);
}
- codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
// Copy the result back to the expected output.
Location out = invoke_->GetLocations()->Out();
diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc
index 2ecb1a3b02..d785567e0f 100644
--- a/compiler/optimizing/intrinsics_mips64.cc
+++ b/compiler/optimizing/intrinsics_mips64.cc
@@ -101,12 +101,12 @@ class IntrinsicSlowPathMIPS64 : public SlowPathCodeMIPS64 {
MoveArguments(invoke_, codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
- Location::RegisterLocation(A0));
+ codegen->GenerateStaticOrDirectCall(
+ invoke_->AsInvokeStaticOrDirect(), Location::RegisterLocation(A0), this);
} else {
- codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), Location::RegisterLocation(A0));
+ codegen->GenerateVirtualCall(
+ invoke_->AsInvokeVirtual(), Location::RegisterLocation(A0), this);
}
- codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
// Copy the result back to the expected output.
Location out = invoke_->GetLocations()->Out();
diff --git a/compiler/optimizing/intrinsics_utils.h b/compiler/optimizing/intrinsics_utils.h
index c1f9ae6425..8c69d9b643 100644
--- a/compiler/optimizing/intrinsics_utils.h
+++ b/compiler/optimizing/intrinsics_utils.h
@@ -56,11 +56,10 @@ class IntrinsicSlowPath : public SlowPathCode {
Location method_loc = MoveArguments(codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), method_loc);
+ codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), method_loc, this);
} else {
- codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), method_loc);
+ codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), method_loc, this);
}
- codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
// Copy the result back to the expected output.
Location out = invoke_->GetLocations()->Out();
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index a9da15d2ce..6b4851d541 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -796,7 +796,6 @@ static void InvokeOutOfLineIntrinsic(CodeGeneratorX86* codegen, HInvoke* invoke)
DCHECK(invoke->IsInvokeStaticOrDirect());
codegen->GenerateStaticOrDirectCall(invoke->AsInvokeStaticOrDirect(),
Location::RegisterLocation(EAX));
- codegen->RecordPcInfo(invoke, invoke->GetDexPc());
// Copy the result back to the expected output.
Location out = invoke->GetLocations()->Out();
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 8100645e54..ef98b7be30 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -567,7 +567,6 @@ static void InvokeOutOfLineIntrinsic(CodeGeneratorX86_64* codegen, HInvoke* invo
DCHECK(invoke->IsInvokeStaticOrDirect());
codegen->GenerateStaticOrDirectCall(
invoke->AsInvokeStaticOrDirect(), Location::RegisterLocation(RDI));
- codegen->RecordPcInfo(invoke, invoke->GetDexPc());
// Copy the result back to the expected output.
Location out = invoke->GetLocations()->Out();
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 9a91287670..e53209f941 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2623,7 +2623,7 @@ const DexFile& HInvokeStaticOrDirect::GetDexFileForPcRelativeDexCache() const {
}
bool HInvokeStaticOrDirect::NeedsDexCacheOfDeclaringClass() const {
- if (GetMethodLoadKind() != MethodLoadKind::kDexCacheViaMethod) {
+ if (GetMethodLoadKind() != MethodLoadKind::kRuntimeCall) {
return false;
}
if (!IsIntrinsic()) {
@@ -2645,8 +2645,8 @@ std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind
return os << "DirectAddress";
case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative:
return os << "DexCachePcRelative";
- case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod:
- return os << "DexCacheViaMethod";
+ case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall:
+ return os << "RuntimeCall";
default:
LOG(FATAL) << "Unknown MethodLoadKind: " << static_cast<int>(rhs);
UNREACHABLE();
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index befd0ff97b..74bb2ab3c4 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4172,11 +4172,9 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
// and we know that we can access the dex cache arrays using a PC-relative load.
kDexCachePcRelative,
- // Use ArtMethod* from the resolved methods of the compiled method's own ArtMethod*.
- // Used for JIT when we need to use the dex cache. This is also the last-resort-kind
- // used when other kinds are unavailable (say, dex cache arrays are not PC-relative)
- // or unimplemented or impractical (i.e. slow) on a particular architecture.
- kDexCacheViaMethod,
+ // Make a runtime call to resolve and call the method. This is the last-resort-kind
+ // used when other kinds are unimplemented on a particular architecture.
+ kRuntimeCall,
};
// Determines the location of the code pointer.
@@ -4376,7 +4374,7 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
// Does this method load kind need the current method as an input?
static bool NeedsCurrentMethodInput(MethodLoadKind kind) {
- return kind == MethodLoadKind::kRecursive || kind == MethodLoadKind::kDexCacheViaMethod;
+ return kind == MethodLoadKind::kRecursive || kind == MethodLoadKind::kRuntimeCall;
}
DECLARE_INSTRUCTION(InvokeStaticOrDirect);