Global lock levels.
Introduce the notion of the mutators/GC being a shared-exclusive (aka
reader-writer) lock. Introduce globally ordered locks, analysable by
annotalysis, statically at compile time. Add locking attributes to
methods.
More subtly, remove the heap_lock_ and split between various locks that
are held for smaller periods (where work doesn't get blocked). Remove
buggy Dalvik style thread transitions. Make GC use CMS in all cases when
concurrent is enabled. Fix bug where suspend counts rather than debug
suspend counts were sent to JDWP. Move the PathClassLoader to
WellKnownClasses. In debugger refactor calls to send request and
possibly suspend. Break apart different VmWait thread states. Move
identity hash code to a shared method.
Change-Id: Icdbfc3ce3fcccd14341860ac7305d8e97b51f5c6
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index b2a88b7..a67366f 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -162,10 +162,12 @@
};
/* Verify a class. Returns "kNoFailure" on success. */
- static FailureKind VerifyClass(const Class* klass, std::string& error);
+ static FailureKind VerifyClass(const Class* klass, std::string& error)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
static FailureKind VerifyClass(const DexFile* dex_file, DexCache* dex_cache,
ClassLoader* class_loader, uint32_t class_def_idx,
- std::string& error);
+ std::string& error)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
uint8_t EncodePcToReferenceMapData() const;
@@ -191,13 +193,16 @@
// Dump the state of the verifier, namely each instruction, what flags are set on it, register
// information
- void Dump(std::ostream& os);
+ void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
- static const std::vector<uint8_t>* GetGcMap(Compiler::MethodReference ref);
+ static const std::vector<uint8_t>* GetGcMap(Compiler::MethodReference ref)
+ LOCKS_EXCLUDED(gc_maps_lock_);
// Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding
// to the locks held at 'dex_pc' in 'm'.
- static void FindLocksAtDexPc(Method* m, uint32_t dex_pc, std::vector<uint32_t>& monitor_enter_dex_pcs);
+ static void FindLocksAtDexPc(Method* m, uint32_t dex_pc,
+ std::vector<uint32_t>& monitor_enter_dex_pcs)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
static void Init();
static void Shutdown();
@@ -206,12 +211,14 @@
static const InferredRegCategoryMap* GetInferredRegCategoryMap(Compiler::MethodReference ref);
#endif
- static bool IsClassRejected(Compiler::ClassReference ref);
+ static bool IsClassRejected(Compiler::ClassReference ref)
+ LOCKS_EXCLUDED(rejected_classes_lock_);
private:
explicit MethodVerifier(const DexFile* dex_file, DexCache* dex_cache,
ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item,
- uint32_t method_idx, Method* method, uint32_t access_flags);
+ uint32_t method_idx, Method* method, uint32_t access_flags)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Adds the given string to the beginning of the last failure message.
void PrependToLastFailMessage(std::string);
@@ -232,14 +239,16 @@
*/
static FailureKind VerifyMethod(uint32_t method_idx, const DexFile* dex_file, DexCache* dex_cache,
ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item,
- Method* method, uint32_t method_access_flags);
- static void VerifyMethodAndDump(Method* method);
+ Method* method, uint32_t method_access_flags)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+ static void VerifyMethodAndDump(Method* method)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Run verification on the method. Returns true if verification completes and false if the input
// has an irrecoverable corruption.
- bool Verify();
+ bool Verify() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
- void FindLocksAtDexPc();
+ void FindLocksAtDexPc() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
/*
* Compute the width of the instruction at each address in the instruction stream, and store it in
@@ -267,7 +276,7 @@
* Returns "false" if something in the exception table looks fishy, but we're expecting the
* exception table to be somewhat sane.
*/
- bool ScanTryCatchBlocks();
+ bool ScanTryCatchBlocks() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
/*
* Perform static verification on all instructions in a method.
@@ -373,11 +382,11 @@
bool* selfOkay);
/* Perform detailed code-flow analysis on a single method. */
- bool VerifyCodeFlow();
+ bool VerifyCodeFlow() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Set the register types for the first instruction in the method based on the method signature.
// This has the side-effect of validating the signature.
- bool SetTypesFromSignature();
+ bool SetTypesFromSignature() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
/*
* Perform code flow on a method.
@@ -425,7 +434,7 @@
* reordering by specifying that you can't execute the new-instance instruction if a register
* contains an uninitialized instance created by that same instruction.
*/
- bool CodeFlowVerifyMethod();
+ bool CodeFlowVerifyMethod() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
/*
* Perform verification for a single instruction.
@@ -436,54 +445,62 @@
* point needs to be (re-)evaluated. Register changes are merged into "reg_types_" at the target
* addresses. Does not set or clear any other flags in "insn_flags_".
*/
- bool CodeFlowVerifyInstruction(uint32_t* start_guess);
+ bool CodeFlowVerifyInstruction(uint32_t* start_guess)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Perform verification of a new array instruction
void VerifyNewArray(const DecodedInstruction& dec_insn, bool is_filled,
- bool is_range);
+ bool is_range)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Perform verification of an aget instruction. The destination register's type will be set to
// be that of component type of the array unless the array type is unknown, in which case a
// bottom type inferred from the type of instruction is used. is_primitive is false for an
// aget-object.
void VerifyAGet(const DecodedInstruction& insn, const RegType& insn_type,
- bool is_primitive);
+ bool is_primitive) SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Perform verification of an aput instruction.
void VerifyAPut(const DecodedInstruction& insn, const RegType& insn_type,
- bool is_primitive);
+ bool is_primitive) SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Lookup instance field and fail for resolution violations
- Field* GetInstanceField(const RegType& obj_type, int field_idx);
+ Field* GetInstanceField(const RegType& obj_type, int field_idx)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Lookup static field and fail for resolution violations
- Field* GetStaticField(int field_idx);
+ Field* GetStaticField(int field_idx) SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Perform verification of an iget or sget instruction.
void VerifyISGet(const DecodedInstruction& insn, const RegType& insn_type,
- bool is_primitive, bool is_static);
+ bool is_primitive, bool is_static)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Perform verification of an iput or sput instruction.
void VerifyISPut(const DecodedInstruction& insn, const RegType& insn_type,
- bool is_primitive, bool is_static);
+ bool is_primitive, bool is_static)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Resolves a class based on an index and performs access checks to ensure the referrer can
// access the resolved class.
- const RegType& ResolveClassAndCheckAccess(uint32_t class_idx);
+ const RegType& ResolveClassAndCheckAccess(uint32_t class_idx)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
/*
* For the "move-exception" instruction at "work_insn_idx_", which must be at an exception handler
* address, determine the Join of all exceptions that can land here. Fails if no matching
* exception handler can be found or if the Join of exception types fails.
*/
- const RegType& GetCaughtExceptionType();
+ const RegType& GetCaughtExceptionType()
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
/*
* Resolves a method based on an index and performs access checks to ensure
* the referrer can access the resolved method.
* Does not throw exceptions.
*/
- Method* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type);
+ Method* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
/*
* Verify the arguments to a method. We're executing in "method", making
@@ -508,7 +525,8 @@
* set appropriately).
*/
Method* VerifyInvocationArgs(const DecodedInstruction& dec_insn,
- MethodType method_type, bool is_range, bool is_super);
+ MethodType method_type, bool is_range, bool is_super)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
/*
* Verify that the target instruction is not "move-exception". It's important that the only way
@@ -528,7 +546,8 @@
* next_insn, and set the changed flag on the target address if any of the registers were changed.
* Returns "false" if an error is encountered.
*/
- bool UpdateRegisters(uint32_t next_insn, const RegisterLine* merge_line);
+ bool UpdateRegisters(uint32_t next_insn, const RegisterLine* merge_line)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Is the method being verified a constructor?
bool IsConstructor() const {
@@ -541,10 +560,10 @@
}
// Return the register type for the method.
- const RegType& GetMethodReturnType();
+ const RegType& GetMethodReturnType() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
// Get a type representing the declaring class of the method.
- const RegType& GetDeclaringClass();
+ const RegType& GetDeclaringClass() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
#if defined(ART_USE_LLVM_COMPILER) || defined(ART_USE_GREENLAND_COMPILER)
/*
@@ -572,25 +591,27 @@
// All the GC maps that the verifier has created
typedef SafeMap<const Compiler::MethodReference, const std::vector<uint8_t>*> GcMapTable;
- static Mutex* gc_maps_lock_;
- static GcMapTable* gc_maps_;
- static void SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map);
+ static Mutex* gc_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+ static GcMapTable* gc_maps_ GUARDED_BY(gc_maps_lock_);
+ static void SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map)
+ LOCKS_EXCLUDED(gc_maps_lock_);
typedef std::set<Compiler::ClassReference> RejectedClassesTable;
- static Mutex* rejected_classes_lock_;
+ static Mutex* rejected_classes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
static RejectedClassesTable* rejected_classes_;
#if defined(ART_USE_LLVM_COMPILER) || defined(ART_USE_GREENLAND_COMPILER)
// All the inferred register category maps that the verifier has created.
typedef SafeMap<const Compiler::MethodReference,
const InferredRegCategoryMap*> InferredRegCategoryMapTable;
- static Mutex* inferred_reg_category_maps_lock_;
+ static Mutex* inferred_reg_category_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
static InferredRegCategoryMapTable* inferred_reg_category_maps_;
static void SetInferredRegCategoryMap(Compiler::MethodReference ref,
const InferredRegCategoryMap& m);
#endif
- static void AddRejectedClass(Compiler::ClassReference ref);
+ static void AddRejectedClass(Compiler::ClassReference ref)
+ LOCKS_EXCLUDED(rejected_classes_lock_);
RegTypeCache reg_types_;
@@ -607,11 +628,14 @@
UniquePtr<RegisterLine> saved_line_;
uint32_t method_idx_; // The method we're working on.
- Method* foo_method_; // Its object representation if known.
+ // Its object representation if known.
+ Method* foo_method_ GUARDED_BY(GlobalSynchronization::mutator_lock_);
uint32_t method_access_flags_; // Method's access flags.
const DexFile* dex_file_; // The dex file containing the method.
- DexCache* dex_cache_; // The dex_cache for the declaring class of the method.
- ClassLoader* class_loader_; // The class loader for the declaring class of the method.
+ // The dex_cache for the declaring class of the method.
+ DexCache* dex_cache_ GUARDED_BY(GlobalSynchronization::mutator_lock_);
+ // The class loader for the declaring class of the method.
+ ClassLoader* class_loader_ GUARDED_BY(GlobalSynchronization::mutator_lock_);
uint32_t class_def_idx_; // The class def index of the declaring class of the method.
const DexFile::CodeItem* code_item_; // The code item containing the code for the method.
UniquePtr<InsnFlags[]> insn_flags_; // Instruction widths and flags, one entry per code unit.