ART: Refactor Thread::Init
This refactor allows the parent thread to allocate the JNIEnvExt
for the child (with a fallback in place in Init). This allows to
throw an OOME in CreateNativeThread instead of aborting in the
child.
Bug: 21291279
(cherry picked from commit 520abbd0edcf333f07164539620ce65258c72383)
Change-Id: Iccc1a5c202999f5bfacec706d9833e53135ba2fa
diff --git a/runtime/thread.h b/runtime/thread.h
index 8c2e215..3f0d0a5 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -975,7 +975,15 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void RemoveFromThreadGroup(ScopedObjectAccess& soa) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool Init(ThreadList*, JavaVMExt*) EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_);
+ // Initialize a thread.
+ //
+ // The third parameter is not mandatory. If given, the thread will use this JNIEnvExt. In case
+ // Init succeeds, this means the thread takes ownership of it. If Init fails, it is the caller's
+ // responsibility to destroy the given JNIEnvExt. If the parameter is null, Init will try to
+ // create a JNIEnvExt on its own (and potentially fail at that stage, indicated by a return value
+ // of false).
+ bool Init(ThreadList*, JavaVMExt*, JNIEnvExt* jni_env_ext = nullptr)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_);
void InitCardTable();
void InitCpu();
void CleanupCpu();
@@ -1111,8 +1119,8 @@
struct PACKED(4) tls_ptr_sized_values {
tls_ptr_sized_values() : card_table(nullptr), exception(nullptr), stack_end(nullptr),
- managed_stack(), suspend_trigger(nullptr), jni_env(nullptr), self(nullptr), opeer(nullptr),
- jpeer(nullptr), stack_begin(nullptr), stack_size(0),
+ managed_stack(), suspend_trigger(nullptr), jni_env(nullptr), tmp_jni_env(nullptr),
+ self(nullptr), opeer(nullptr), jpeer(nullptr), stack_begin(nullptr), stack_size(0),
stack_trace_sample(nullptr), wait_next(nullptr), monitor_enter_object(nullptr),
top_handle_scope(nullptr), class_loader_override(nullptr), long_jump_context(nullptr),
instrumentation_stack(nullptr), debug_invoke_req(nullptr), single_step_control(nullptr),
@@ -1144,6 +1152,10 @@
// Every thread may have an associated JNI environment
JNIEnvExt* jni_env;
+ // Temporary storage to transfer a pre-allocated JNIEnvExt from the creating thread to the
+ // created thread.
+ JNIEnvExt* tmp_jni_env;
+
// Initialized to "this". On certain architectures (such as x86) reading off of Thread::Current
// is easy but getting the address of Thread::Current is hard. This field can be read off of
// Thread::Current to give the address.