From d2fe10a3a34af171bf1631219cd2d6ff6b7778b5 Mon Sep 17 00:00:00 2001 From: Sebastien Hertz Date: Wed, 15 Jan 2014 10:20:56 +0100 Subject: Remove blacklist Removes the class initialization blacklist and use transaction to detect and revert class initialization attempting to invoke native method. This only concerns class initialization happening at compilation time when generating an image (like boot.art for the system). In transactional mode, we log every object's field assignment and array update. Therefore we're able to abort a transaction to restore values of fields and array as they were before the transaction starts. We also log changes to the intern string table so we can restore its state prior to transaction start. Since transactional mode only happens at compilation time, we don't need to log all these changes at runtime. In order to reduce the overhead of testing if transactional mode is on/off, we templatize interfaces of mirror::Object and mirror::Array, respectively responsible for setting a field and setting an array element. For various reasons, we skip some specific fields from transaction: - Object's class and array's length must remain unchanged so garbage collector can compute object's size. - Immutable fields only set during class loading: list of fields, method, dex caches, vtables, ... as all classes have been loaded and verified before a transaction occurs. - Object's monitor for performance reason. Before generating the image, we browse the heap to collect objects that need to be written into it. Since the heap may still holds references to unreachable objects due to aborted transactions, we trigger one collection at the end of the class preinitialization phase. Since the transaction is held by the runtime and all compilation threads share the same runtime, we need to ensure only one compilation thread has exclusive access to the runtime. To workaround this issue, we force class initialization phase to run with only one thread. Note this is only done when generating image so application compilation is not impacted. This issue will be addressed in a separate CL. Bug: 9676614 Change-Id: I221910a9183a5ba6c2b99a277f5a5a68bc69b5f9 --- runtime/intern_table.h | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'runtime/intern_table.h') diff --git a/runtime/intern_table.h b/runtime/intern_table.h index 9f09fb9..cc48480 100644 --- a/runtime/intern_table.h +++ b/runtime/intern_table.h @@ -18,6 +18,7 @@ #define ART_RUNTIME_INTERN_TABLE_H_ #include "base/mutex.h" +#include "locks.h" #include "object_callbacks.h" #include @@ -26,6 +27,7 @@ namespace art { namespace mirror { class String; } // namespace mirror +class Transaction; /** * Used to intern strings. @@ -72,19 +74,38 @@ class InternTable { typedef std::multimap Table; mirror::String* Insert(mirror::String* s, bool is_strong) + LOCKS_EXCLUDED(Locks::intern_table_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::String* Lookup(Table& table, mirror::String* s, uint32_t hash_code) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::String* Insert(Table& table, mirror::String* s, uint32_t hash_code); - void Remove(Table& table, const mirror::String* s, uint32_t hash_code); - - mutable Mutex intern_table_lock_; - bool is_dirty_ GUARDED_BY(intern_table_lock_); - bool allow_new_interns_ GUARDED_BY(intern_table_lock_); - ConditionVariable new_intern_condition_ GUARDED_BY(intern_table_lock_); - Table strong_interns_ GUARDED_BY(intern_table_lock_); - Table weak_interns_ GUARDED_BY(intern_table_lock_); + mirror::String* InsertStrong(mirror::String* s, uint32_t hash_code) + EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_); + mirror::String* InsertWeak(mirror::String* s, uint32_t hash_code) + EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_); + mirror::String* Insert(Table& table, mirror::String* s, uint32_t hash_code) + EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_); + void RemoveWeak(mirror::String* s, uint32_t hash_code) + EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_); + void Remove(Table& table, mirror::String* s, uint32_t hash_code) + EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_); + + // Transaction rollback access. + mirror::String* InsertStrongFromTransaction(mirror::String* s, uint32_t hash_code) + EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_); + mirror::String* InsertWeakFromTransaction(mirror::String* s, uint32_t hash_code) + EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_); + void RemoveStrongFromTransaction(mirror::String* s, uint32_t hash_code) + EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_); + void RemoveWeakFromTransaction(mirror::String* s, uint32_t hash_code) + EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_); + friend class Transaction; + + bool is_dirty_ GUARDED_BY(Locks::intern_table_lock_); + bool allow_new_interns_ GUARDED_BY(Locks::intern_table_lock_); + ConditionVariable new_intern_condition_ GUARDED_BY(Locks::intern_table_lock_); + Table strong_interns_ GUARDED_BY(Locks::intern_table_lock_); + Table weak_interns_ GUARDED_BY(Locks::intern_table_lock_); }; } // namespace art -- cgit v1.1