summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Andreas Gampe <agampe@google.com> 2018-05-17 11:47:09 -0700
committer Andreas Gampe <agampe@google.com> 2018-05-17 12:57:49 -0700
commit9abc31e41d0983b3d0a111ea7752bd392f1c309e (patch)
tree29438ec505e1f16f5c7ea26ecd546fbcf0c54bf9
parent1e7b825ffb4c19e1f046eb254ab8e491919c7a69 (diff)
ART: Refactor String.init binding
Do not use JNI infrastructure, and move the initialization to the classlinker's FinishInit. This means the binding is available after the minimal set of initializations. We could consider moving the functionality even earlier, as soon as String methods are known and StringFactory can be loaded, but this placement works well enough and is nicely isolated. Bug: 79902155 Test: m test-art-host Change-Id: If4e9f1424668eb200ff5544bc21f5cea6151e4b3
-rw-r--r--runtime/class_linker.cc15
-rw-r--r--runtime/well_known_classes.cc38
-rw-r--r--runtime/well_known_classes.h6
3 files changed, 43 insertions, 16 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index be9e08fbec..b88aa5e07a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -828,9 +828,24 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
return true;
}
+static void CreateStringInitBindings(Thread* self, ClassLinker* class_linker)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Find String.<init> -> StringFactory bindings.
+ ObjPtr<mirror::Class> string_factory_class =
+ class_linker->FindSystemClass(self, "Ljava/lang/StringFactory;");
+ CHECK(string_factory_class != nullptr);
+ ObjPtr<mirror::Class> string_class =
+ class_linker->GetClassRoot(ClassLinker::ClassRoot::kJavaLangString);
+ WellKnownClasses::InitStringInit(string_class, string_factory_class);
+ // Update the primordial thread.
+ self->InitStringEntryPoints();
+}
+
void ClassLinker::FinishInit(Thread* self) {
VLOG(startup) << "ClassLinker::FinishInit entering";
+ CreateStringInitBindings(self, this);
+
// Let the heap know some key offsets into java.lang.ref instances
// Note: we hard code the field indexes here rather than using FindInstanceField
// as the types of the field can't be resolved prior to the runtime being
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 4843061be6..f7cdf3920a 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -23,6 +23,8 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
+#include "base/enums.h"
+#include "class_linker.h"
#include "entrypoints/quick/quick_entrypoints_enum.h"
#include "hidden_api.h"
#include "jni/jni_internal.h"
@@ -30,6 +32,7 @@
#include "mirror/throwable.h"
#include "nativehelper/scoped_local_ref.h"
#include "obj_ptr-inl.h"
+#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
@@ -231,19 +234,28 @@ static jmethodID CachePrimitiveBoxingMethod(JNIEnv* env, char prim_name, const c
V(java_lang_String_init_StringBuilder, "(Ljava/lang/StringBuilder;)V", newStringFromStringBuilder, "newStringFromStringBuilder", "(Ljava/lang/StringBuilder;)Ljava/lang/String;", NewStringFromStringBuilder) \
#define STATIC_STRING_INIT(init_runtime_name, init_signature, new_runtime_name, ...) \
- static ArtMethod* init_runtime_name; \
- static ArtMethod* new_runtime_name;
+ static ArtMethod* init_runtime_name = nullptr; \
+ static ArtMethod* new_runtime_name = nullptr;
STRING_INIT_LIST(STATIC_STRING_INIT)
#undef STATIC_STRING_INIT
-void WellKnownClasses::InitStringInit(JNIEnv* env) {
- ScopedObjectAccess soa(Thread::Current());
- #define LOAD_STRING_INIT(init_runtime_name, init_signature, new_runtime_name, \
- new_java_name, new_signature, ...) \
- init_runtime_name = jni::DecodeArtMethod( \
- CacheMethod(env, java_lang_String, false, "<init>", init_signature)); \
- new_runtime_name = jni::DecodeArtMethod( \
- CacheMethod(env, java_lang_StringFactory, true, new_java_name, new_signature));
+void WellKnownClasses::InitStringInit(ObjPtr<mirror::Class> string_class,
+ ObjPtr<mirror::Class> string_builder_class) {
+ PointerSize p_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+ auto find_method = [p_size](ObjPtr<mirror::Class> klass,
+ const char* name,
+ const char* sig,
+ bool expext_static) REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtMethod* ret = klass->FindClassMethod(name, sig, p_size);
+ CHECK(ret != nullptr);
+ CHECK_EQ(expext_static, ret->IsStatic());
+ return ret;
+ };
+
+ #define LOAD_STRING_INIT(init_runtime_name, init_signature, new_runtime_name, \
+ new_java_name, new_signature, ...) \
+ init_runtime_name = find_method(string_class, "<init>", init_signature, false); \
+ new_runtime_name = find_method(string_builder_class, new_java_name, new_signature, true);
STRING_INIT_LIST(LOAD_STRING_INIT)
#undef LOAD_STRING_INIT
}
@@ -252,6 +264,7 @@ void Thread::InitStringEntryPoints() {
QuickEntryPoints* qpoints = &tlsPtr_.quick_entrypoints;
#define SET_ENTRY_POINT(init_runtime_name, init_signature, new_runtime_name, \
new_java_name, new_signature, entry_point_name) \
+ DCHECK(!Runtime::Current()->IsStarted() || (new_runtime_name) != nullptr); \
qpoints->p ## entry_point_name = reinterpret_cast<void(*)()>(new_runtime_name);
STRING_INIT_LIST(SET_ENTRY_POINT)
#undef SET_ENTRY_POINT
@@ -260,7 +273,9 @@ void Thread::InitStringEntryPoints() {
ArtMethod* WellKnownClasses::StringInitToStringFactory(ArtMethod* string_init) {
#define TO_STRING_FACTORY(init_runtime_name, init_signature, new_runtime_name, \
new_java_name, new_signature, entry_point_name) \
+ DCHECK((init_runtime_name) != nullptr); \
if (string_init == (init_runtime_name)) { \
+ DCHECK((new_runtime_name) != nullptr); \
return (new_runtime_name); \
}
STRING_INIT_LIST(TO_STRING_FACTORY)
@@ -410,9 +425,6 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_Integer_valueOf = CachePrimitiveBoxingMethod(env, 'I', "java/lang/Integer");
java_lang_Long_valueOf = CachePrimitiveBoxingMethod(env, 'J', "java/lang/Long");
java_lang_Short_valueOf = CachePrimitiveBoxingMethod(env, 'S', "java/lang/Short");
-
- InitStringInit(env);
- Thread::Current()->InitStringEntryPoints();
}
void WellKnownClasses::LateInit(JNIEnv* env) {
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 25c07b27de..c06e4a71ce 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -40,6 +40,9 @@ struct WellKnownClasses {
static void Clear();
+ static void InitStringInit(ObjPtr<mirror::Class> string_class,
+ ObjPtr<mirror::Class> string_builder_class)
+ REQUIRES_SHARED(Locks::mutator_lock_);
static ArtMethod* StringInitToStringFactory(ArtMethod* method);
static uint32_t StringInitToEntryPoint(ArtMethod* method);
@@ -168,9 +171,6 @@ struct WellKnownClasses {
static jfieldID org_apache_harmony_dalvik_ddmc_Chunk_length;
static jfieldID org_apache_harmony_dalvik_ddmc_Chunk_offset;
static jfieldID org_apache_harmony_dalvik_ddmc_Chunk_type;
-
- private:
- static void InitStringInit(JNIEnv* env);
};
} // namespace art