ART: Add unstarted-runtime functions
Add more functions to allow compile-time initialization of
code.
Bug: 27248115
(cherry picked from commit 0866f4ed6338faa4a193b7e819fc7cd72bd7b0ae)
Change-Id: Iaf8d92deb73547ccd31c0d6dde68da3bc14c3985
diff --git a/runtime/mirror/abstract_method.cc b/runtime/mirror/abstract_method.cc
index 91a9870..5a07dee 100644
--- a/runtime/mirror/abstract_method.cc
+++ b/runtime/mirror/abstract_method.cc
@@ -21,25 +21,36 @@
namespace art {
namespace mirror {
+template <bool kTransactionActive>
bool AbstractMethod::CreateFromArtMethod(ArtMethod* method) {
- auto* interface_method = method->GetInterfaceMethodIfProxy(sizeof(void*));
- SetArtMethod(method);
- SetFieldObject<false>(DeclaringClassOffset(), method->GetDeclaringClass());
- SetFieldObject<false>(
+ auto* interface_method = method->GetInterfaceMethodIfProxy(
+ kTransactionActive
+ ? Runtime::Current()->GetClassLinker()->GetImagePointerSize()
+ : sizeof(void*));
+ SetArtMethod<kTransactionActive>(method);
+ SetFieldObject<kTransactionActive>(DeclaringClassOffset(), method->GetDeclaringClass());
+ SetFieldObject<kTransactionActive>(
DeclaringClassOfOverriddenMethodOffset(), interface_method->GetDeclaringClass());
- SetField32<false>(AccessFlagsOffset(), method->GetAccessFlags());
- SetField32<false>(DexMethodIndexOffset(), method->GetDexMethodIndex());
+ SetField32<kTransactionActive>(AccessFlagsOffset(), method->GetAccessFlags());
+ SetField32<kTransactionActive>(DexMethodIndexOffset(), method->GetDexMethodIndex());
return true;
}
+template bool AbstractMethod::CreateFromArtMethod<false>(ArtMethod* method);
+template bool AbstractMethod::CreateFromArtMethod<true>(ArtMethod* method);
+
ArtMethod* AbstractMethod::GetArtMethod() {
return reinterpret_cast<ArtMethod*>(GetField64(ArtMethodOffset()));
}
+template <bool kTransactionActive>
void AbstractMethod::SetArtMethod(ArtMethod* method) {
- SetField64<false>(ArtMethodOffset(), reinterpret_cast<uint64_t>(method));
+ SetField64<kTransactionActive>(ArtMethodOffset(), reinterpret_cast<uint64_t>(method));
}
+template void AbstractMethod::SetArtMethod<false>(ArtMethod* method);
+template void AbstractMethod::SetArtMethod<true>(ArtMethod* method);
+
mirror::Class* AbstractMethod::GetDeclaringClass() {
return GetFieldObject<mirror::Class>(DeclaringClassOffset());
}
diff --git a/runtime/mirror/abstract_method.h b/runtime/mirror/abstract_method.h
index dc084be..a39f94d 100644
--- a/runtime/mirror/abstract_method.h
+++ b/runtime/mirror/abstract_method.h
@@ -34,11 +34,13 @@
class MANAGED AbstractMethod : public AccessibleObject {
public:
// Called from Constructor::CreateFromArtMethod, Method::CreateFromArtMethod.
+ template <bool kTransactionActive = false>
bool CreateFromArtMethod(ArtMethod* method) SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
ArtMethod* GetArtMethod() SHARED_REQUIRES(Locks::mutator_lock_);
// Only used by the image writer.
+ template <bool kTransactionActive = false>
void SetArtMethod(ArtMethod* method) SHARED_REQUIRES(Locks::mutator_lock_);
mirror::Class* GetDeclaringClass() SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 9190e44..7900eac 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -1054,5 +1054,89 @@
return (type_id == nullptr) ? DexFile::kDexNoIndex : dex_file.GetIndexForTypeId(*type_id);
}
+template <bool kTransactionActive>
+mirror::Method* Class::GetDeclaredMethodInternal(Thread* self,
+ mirror::Class* klass,
+ mirror::String* name,
+ mirror::ObjectArray<mirror::Class>* args) {
+ // Covariant return types permit the class to define multiple
+ // methods with the same name and parameter types. Prefer to
+ // return a non-synthetic method in such situations. We may
+ // still return a synthetic method to handle situations like
+ // escalated visibility. We never return miranda methods that
+ // were synthesized by the runtime.
+ constexpr uint32_t kSkipModifiers = kAccMiranda | kAccSynthetic;
+ StackHandleScope<3> hs(self);
+ auto h_method_name = hs.NewHandle(name);
+ if (UNLIKELY(h_method_name.Get() == nullptr)) {
+ ThrowNullPointerException("name == null");
+ return nullptr;
+ }
+ auto h_args = hs.NewHandle(args);
+ Handle<mirror::Class> h_klass = hs.NewHandle(klass);
+ ArtMethod* result = nullptr;
+ const size_t pointer_size = kTransactionActive
+ ? Runtime::Current()->GetClassLinker()->GetImagePointerSize()
+ : sizeof(void*);
+ for (auto& m : h_klass->GetDeclaredVirtualMethods(pointer_size)) {
+ auto* np_method = m.GetInterfaceMethodIfProxy(pointer_size);
+ // May cause thread suspension.
+ mirror::String* np_name = np_method->GetNameAsString(self);
+ if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
+ if (UNLIKELY(self->IsExceptionPending())) {
+ return nullptr;
+ }
+ continue;
+ }
+ auto modifiers = m.GetAccessFlags();
+ if ((modifiers & kSkipModifiers) == 0) {
+ return mirror::Method::CreateFromArtMethod<kTransactionActive>(self, &m);
+ }
+ if ((modifiers & kAccMiranda) == 0) {
+ result = &m; // Remember as potential result if it's not a miranda method.
+ }
+ }
+ if (result == nullptr) {
+ for (auto& m : h_klass->GetDirectMethods(pointer_size)) {
+ auto modifiers = m.GetAccessFlags();
+ if ((modifiers & kAccConstructor) != 0) {
+ continue;
+ }
+ auto* np_method = m.GetInterfaceMethodIfProxy(pointer_size);
+ // May cause thread suspension.
+ mirror::String* np_name = np_method->GetNameAsString(self);
+ if (np_name == nullptr) {
+ self->AssertPendingException();
+ return nullptr;
+ }
+ if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
+ if (UNLIKELY(self->IsExceptionPending())) {
+ return nullptr;
+ }
+ continue;
+ }
+ if ((modifiers & kSkipModifiers) == 0) {
+ return mirror::Method::CreateFromArtMethod<kTransactionActive>(self, &m);
+ }
+ // Direct methods cannot be miranda methods, so this potential result must be synthetic.
+ result = &m;
+ }
+ }
+ return result != nullptr
+ ? mirror::Method::CreateFromArtMethod<kTransactionActive>(self, result)
+ : nullptr;
+}
+
+template
+mirror::Method* Class::GetDeclaredMethodInternal<false>(Thread* self,
+ mirror::Class* klass,
+ mirror::String* name,
+ mirror::ObjectArray<mirror::Class>* args);
+template
+mirror::Method* Class::GetDeclaredMethodInternal<true>(Thread* self,
+ mirror::Class* klass,
+ mirror::String* name,
+ mirror::ObjectArray<mirror::Class>* args);
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 6e3463c..7082c88 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -55,6 +55,7 @@
class Constructor;
class DexCache;
class IfTable;
+class Method;
// C++ mirror of java.lang.Class
class MANAGED Class FINAL : public Object {
@@ -759,6 +760,13 @@
size_t pointer_size)
SHARED_REQUIRES(Locks::mutator_lock_);
+ template <bool kTransactionActive = false>
+ static Method* GetDeclaredMethodInternal(Thread* self,
+ mirror::Class* klass,
+ mirror::String* name,
+ mirror::ObjectArray<mirror::Class>* args)
+ SHARED_REQUIRES(Locks::mutator_lock_);
+
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE ArraySlice<ArtMethod> GetDeclaredVirtualMethodsSlice(size_t pointer_size)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
index 85c52e9..97973e6 100644
--- a/runtime/mirror/method.cc
+++ b/runtime/mirror/method.cc
@@ -51,15 +51,19 @@
array_class_ = GcRoot<Class>(nullptr);
}
+template <bool kTransactionActive>
Method* Method::CreateFromArtMethod(Thread* self, ArtMethod* method) {
DCHECK(!method->IsConstructor()) << PrettyMethod(method);
auto* ret = down_cast<Method*>(StaticClass()->AllocObject(self));
if (LIKELY(ret != nullptr)) {
- static_cast<AbstractMethod*>(ret)->CreateFromArtMethod(method);
+ static_cast<AbstractMethod*>(ret)->CreateFromArtMethod<kTransactionActive>(method);
}
return ret;
}
+template Method* Method::CreateFromArtMethod<false>(Thread* self, ArtMethod* method);
+template Method* Method::CreateFromArtMethod<true>(Thread* self, ArtMethod* method);
+
void Method::VisitRoots(RootVisitor* visitor) {
static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
diff --git a/runtime/mirror/method.h b/runtime/mirror/method.h
index 0c28e4f..12a72fe 100644
--- a/runtime/mirror/method.h
+++ b/runtime/mirror/method.h
@@ -28,6 +28,7 @@
// C++ mirror of java.lang.reflect.Method.
class MANAGED Method : public AbstractMethod {
public:
+ template <bool kTransactionActive = false>
static Method* CreateFromArtMethod(Thread* self, ArtMethod* method)
SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);